@one-million-lines/email-builder 0.2.0 → 0.2.2
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 +9 -12
- package/README.md +0 -23
- package/dist/ai/catalog.d.ts +2 -4
- package/dist/email-builder.cjs +4 -4
- package/dist/email-builder.cjs.map +1 -1
- package/dist/email-builder.js +1107 -1137
- package/dist/email-builder.js.map +1 -1
- package/dist/index.d.ts +0 -5
- package/dist/styles.css +1 -1
- package/package.json +6 -2
- package/dist/gallery/index.d.ts +0 -14
- package/dist/gallery/registry.d.ts +0 -54
- package/dist/gallery/sampleGallery.d.ts +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"email-builder.cjs","names":["useLayoutEffect","useEffect","React","React","ID_PREFIX","ID_PREFIX$1","React"],"sources":["../src/core/validation.ts","../src/core/theme.ts","../src/core/utils.ts","../src/core/renderer.ts","../src/themes/defaultThemes.ts","../src/store/emailStore.ts","../src/templates/registry.ts","../src/modules/helpers.ts","../src/templates/weeklyNewsletter.ts","../src/templates/flashSale.ts","../src/templates/abandonedCart.ts","../src/templates/productLaunch.ts","../src/templates/welcomeOnboarding.ts","../src/templates/eventInvite.ts","../src/templates/orderReceipt.ts","../src/templates/blogDigest.ts","../src/editor/TemplatesModal.tsx","../src/editor/TopBar.tsx","../src/modules/registry.ts","../src/gallery/registry.ts","../src/ai/state.ts","../src/ai/catalog.ts","../src/core/aiActions.ts","../src/ai/applyResponse.ts","../src/ai/AIChatPanel.tsx","../src/editor/LeftSidebar.tsx","../node_modules/@dnd-kit/utilities/dist/utilities.esm.js","../node_modules/@dnd-kit/accessibility/dist/accessibility.esm.js","../node_modules/@dnd-kit/core/dist/core.esm.js","../node_modules/@dnd-kit/sortable/dist/sortable.esm.js","../src/editor/Canvas.tsx","../src/core/plugins.ts","../src/recommendations/logic.ts","../src/editor/RecommendationsPanel.tsx","../src/editor/RightSidebar.tsx","../src/modules/basic.ts","../src/modules/header.ts","../src/modules/menu.ts","../src/modules/content.ts","../src/modules/feature.ts","../src/modules/cta.ts","../src/modules/ecommerce.ts","../src/modules/transactional.ts","../src/modules/social.ts","../src/modules/footer.ts","../src/modules/defaultModules.ts","../src/App.tsx","../src/gallery/sampleGallery.ts","../src/gallery/index.ts","../src/ai/provider.ts","../src/ai/index.ts","../src/plugins/imageUploader/index.ts","../src/index.ts"],"sourcesContent":["import { z } from \"zod\";\n\nconst styleValue = z.union([z.string(), z.number(), z.boolean(), z.record(z.string(), z.any())]);\nconst styleSchema = z.record(z.string(), styleValue).optional();\n\nconst elementSchema = z.discriminatedUnion(\"type\", [\n z.object({\n id: z.string(),\n type: z.literal(\"text\"),\n role: z.string().optional(),\n content: z.string(),\n style: styleSchema,\n }),\n z.object({\n id: z.string(),\n type: z.literal(\"image\"),\n src: z.string(),\n alt: z.string().optional(),\n link: z.string().optional(),\n style: styleSchema,\n }),\n z.object({\n id: z.string(),\n type: z.literal(\"button\"),\n label: z.string(),\n link: z.string(),\n style: styleSchema,\n }),\n z.object({\n id: z.string(),\n type: z.literal(\"spacer\"),\n height: z.number(),\n }),\n z.object({\n id: z.string(),\n type: z.literal(\"divider\"),\n style: styleSchema,\n }),\n z.object({\n id: z.string(),\n type: z.literal(\"productGrid\"),\n products: z.array(\n z.object({\n id: z.string(),\n image: z.string(),\n imageAlt: z.string().optional(),\n name: z.string(),\n oldPrice: z.string().optional(),\n finalPrice: z.string(),\n description: z.string().optional(),\n link: z.string().optional(),\n buttonLabel: z.string().optional(),\n })\n ),\n columns: z.union([z.literal(1), z.literal(2), z.literal(3)]),\n showOldPrice: z.boolean(),\n showButton: z.boolean(),\n showDescription: z.boolean(),\n buttonLabel: z.string().optional(),\n style: styleSchema,\n }),\n]);\n\nexport const moduleSchema = z.object({\n id: z.string(),\n type: z.string(),\n name: z.string(),\n style: styleSchema,\n children: z.array(elementSchema),\n data: z.record(z.string(), z.any()).optional(),\n});\n\nexport const themeSchema = z.object({\n id: z.string(),\n name: z.string(),\n tokens: z.object({\n colors: z.record(z.string(), z.string()),\n fonts: z.record(z.string(), z.string()),\n spacing: z.record(z.string(), z.number()),\n radius: z.record(z.string(), z.number()),\n }),\n});\n\nexport const documentSchema = z.object({\n version: z.string(),\n meta: z.object({ name: z.string(), previewText: z.string() }),\n theme: themeSchema,\n settings: z.object({\n width: z.number(),\n backgroundColor: z.string(),\n contentBackgroundColor: z.string(),\n }),\n modules: z.array(moduleSchema),\n});\n\nexport type ValidatedDocument = z.infer<typeof documentSchema>;\n","// Theme token resolution. Tokens use {colors.primary} or {spacing.md} syntax.\nimport type { Theme } from \"./types\";\n\nexport function resolveToken(value: unknown, theme: Theme): unknown {\n if (typeof value !== \"string\") return value;\n const m = value.match(/^\\{([\\w.]+)\\}$/);\n if (!m) return value;\n const path = m[1].split(\".\");\n let cur: unknown = theme.tokens;\n for (const p of path) {\n if (cur && typeof cur === \"object\" && p in (cur as Record<string, unknown>)) {\n cur = (cur as Record<string, unknown>)[p];\n } else {\n return value;\n }\n }\n return cur;\n}\n\nexport function resolveStyle(\n style: Record<string, unknown> | undefined | null,\n theme: Theme\n): Record<string, unknown> {\n if (!style) return {};\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(style)) {\n out[k] = resolveToken(v, theme);\n }\n return out;\n}\n","export function uid(prefix = \"id\"): string {\n return `${prefix}_${Math.random().toString(36).slice(2, 9)}${Date.now().toString(36).slice(-3)}`;\n}\n\nexport function escapeHtml(s: string): string {\n return s\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\");\n}\n\nexport function safeUrl(url: string | undefined): string {\n if (!url) return \"#\";\n try {\n const u = new URL(url, \"https://example.com\");\n if (![\"http:\", \"https:\", \"mailto:\"].includes(u.protocol)) return \"#\";\n return url;\n } catch {\n return \"#\";\n }\n}\n","// Table-based HTML email renderer. Inline CSS, ESP-friendly.\n// Responsive via @media (max-width:600px) class overrides + Outlook (MSO) fallbacks.\nimport type {\n EmailDocument,\n EmailModule,\n EmailElement,\n TextElement,\n ImageElement,\n ButtonElement,\n SpacerElement,\n DividerElement,\n ProductGridElement,\n Product,\n Theme,\n} from \"./types\";\nimport { resolveStyle, resolveToken } from \"./theme\";\nimport { escapeHtml, safeUrl } from \"./utils\";\n\nfunction px(n: number | undefined, fallback = 0): string {\n return `${n ?? fallback}px`;\n}\n\nfunction styleString(style: Record<string, unknown>): string {\n const parts: string[] = [];\n for (const [k, v] of Object.entries(style)) {\n if (v === undefined || v === null || v === \"\") continue;\n parts.push(`${k}:${v}`);\n }\n return parts.join(\";\");\n}\n\nfunction mobileCssBlock(mobileStyle: Record<string, unknown>, theme: Theme): string {\n const resolved = resolveStyle(mobileStyle, theme);\n const map: Record<string, string> = {};\n const set = (cssKey: string, val: unknown, suffix = \"\") => {\n if (val === undefined || val === null || val === \"\") return;\n map[cssKey] = `${val}${suffix} !important`;\n };\n set(\"font-family\", resolved.fontFamily);\n if (resolved.fontSize !== undefined) set(\"font-size\", resolved.fontSize, \"px\");\n set(\"line-height\", resolved.lineHeight);\n if (resolved.letterSpacing !== undefined) set(\"letter-spacing\", resolved.letterSpacing, \"px\");\n set(\"font-weight\", resolved.fontWeight);\n set(\"color\", resolved.color);\n set(\"text-align\", resolved.align);\n set(\"background-color\", resolved.backgroundColor);\n if (resolved.paddingTop !== undefined) set(\"padding-top\", resolved.paddingTop, \"px\");\n if (resolved.paddingBottom !== undefined) set(\"padding-bottom\", resolved.paddingBottom, \"px\");\n if (resolved.paddingLeft !== undefined) set(\"padding-left\", resolved.paddingLeft, \"px\");\n if (resolved.paddingRight !== undefined) set(\"padding-right\", resolved.paddingRight, \"px\");\n if (resolved.borderRadius !== undefined) set(\"border-radius\", resolved.borderRadius, \"px\");\n if (resolved.width !== undefined) set(\"width\", resolved.width, \"px\");\n if (resolved.height !== undefined) set(\"height\", resolved.height, \"px\");\n return Object.entries(map)\n .map(([k, v]) => `${k}:${v}`)\n .join(\";\");\n}\n\ninterface RenderCtx {\n theme: Theme;\n mobileRules: string[];\n classCounter: { n: number };\n}\n\nfunction nextClass(ctx: RenderCtx): string {\n ctx.classCounter.n += 1;\n return `r${ctx.classCounter.n}`;\n}\n\nfunction collectMobile(\n ctx: RenderCtx,\n style: Record<string, unknown> | undefined\n): string | null {\n const mobile = style?.mobile as Record<string, unknown> | undefined;\n const hideOn = style?.hideOn as \"mobile\" | \"desktop\" | undefined;\n if (!mobile && !hideOn) return null;\n const cls = nextClass(ctx);\n if (mobile && Object.keys(mobile).length > 0) {\n const css = mobileCssBlock(mobile, ctx.theme);\n if (css) {\n ctx.mobileRules.push(`@media only screen and (max-width:600px){.${cls}{${css}}}`);\n if (mobile.width !== undefined) {\n ctx.mobileRules.push(\n `@media only screen and (max-width:600px){.${cls} img{max-width:${mobile.width}px !important;width:100% !important;height:auto !important;}}`\n );\n }\n }\n }\n if (hideOn === \"mobile\") {\n ctx.mobileRules.push(\n `@media only screen and (max-width:600px){.${cls}{display:none !important;mso-hide:all;max-height:0;overflow:hidden;}}`\n );\n }\n if (hideOn === \"desktop\") {\n ctx.mobileRules.push(\n `@media only screen and (min-width:601px){.${cls}{display:none !important;}}`\n );\n }\n return cls;\n}\n\nfunction renderText(el: TextElement, ctx: RenderCtx): string {\n const s = resolveStyle((el.style ?? {}) as Record<string, unknown>, ctx.theme);\n const css = styleString({\n \"font-family\": s.fontFamily ?? \"Arial, Helvetica, sans-serif\",\n \"font-size\": s.fontSize ? `${s.fontSize}px` : \"16px\",\n \"line-height\": s.lineHeight ?? 1.5,\n \"letter-spacing\": s.letterSpacing ? `${s.letterSpacing}px` : undefined,\n \"font-weight\": s.fontWeight ?? \"normal\",\n color: s.color ?? \"#111827\",\n \"text-align\": s.align ?? \"left\",\n \"padding-top\": px(s.paddingTop as number, 8),\n \"padding-bottom\": px(s.paddingBottom as number, 8),\n \"padding-left\": px(s.paddingLeft as number, 16),\n \"padding-right\": px(s.paddingRight as number, 16),\n \"mso-line-height-rule\": \"exactly\",\n \"-webkit-text-size-adjust\": \"100%\",\n \"-ms-text-size-adjust\": \"100%\",\n margin: 0,\n });\n const link = s.link as string | undefined;\n const inner = link\n ? `<a href=\"${safeUrl(link)}\" style=\"color:inherit;text-decoration:underline\">${el.content}</a>`\n : el.content;\n const cls = collectMobile(ctx, el.style as Record<string, unknown>);\n return `<div${cls ? ` class=\"${cls}\"` : \"\"} style=\"${css}\">${inner}</div>`;\n}\n\nfunction renderImage(el: ImageElement, ctx: RenderCtx): string {\n const s = resolveStyle((el.style ?? {}) as Record<string, unknown>, ctx.theme);\n const wrapCss = styleString({\n \"text-align\": s.align ?? \"center\",\n \"padding-top\": px(s.paddingTop as number, 0),\n \"padding-bottom\": px(s.paddingBottom as number, 0),\n \"padding-left\": px(s.paddingLeft as number, 0),\n \"padding-right\": px(s.paddingRight as number, 0),\n \"font-size\": \"0\",\n \"line-height\": \"0\",\n });\n const imgCss = styleString({\n display: \"block\",\n \"max-width\": \"100%\",\n width: s.width ? `${s.width}px` : \"100%\",\n height: s.height ? `${s.height}px` : \"auto\",\n \"border-radius\": s.borderRadius ? `${s.borderRadius}px` : undefined,\n border: 0,\n outline: \"none\",\n \"text-decoration\": \"none\",\n \"-ms-interpolation-mode\": \"bicubic\",\n margin: s.align === \"center\" || !s.align ? \"0 auto\" : undefined,\n });\n const widthAttr = s.width ? ` width=\"${s.width}\"` : \"\";\n const img = `<img src=\"${escapeHtml(el.src)}\" alt=\"${escapeHtml(el.alt ?? \"\")}\"${widthAttr} style=\"${imgCss}\" />`;\n const wrapped = el.link ? `<a href=\"${safeUrl(el.link)}\">${img}</a>` : img;\n const cls = collectMobile(ctx, el.style as Record<string, unknown>);\n return `<div${cls ? ` class=\"${cls}\"` : \"\"} style=\"${wrapCss}\">${wrapped}</div>`;\n}\n\nfunction renderButton(el: ButtonElement, ctx: RenderCtx): string {\n const s = resolveStyle((el.style ?? {}) as Record<string, unknown>, ctx.theme);\n const align = (s.align as string) ?? \"center\";\n const wrapCss = styleString({\n \"text-align\": align,\n \"padding-top\": px(s.paddingTop as number, 12),\n \"padding-bottom\": px(s.paddingBottom as number, 12),\n \"padding-left\": px(s.paddingLeft as number, 16),\n \"padding-right\": px(s.paddingRight as number, 16),\n });\n const bg = (s.backgroundColor as string) ?? \"#3A7D52\";\n const color = (s.color as string) ?? \"#FFFFFF\";\n const radius = (s.borderRadius as number) ?? 6;\n const fontSize = (s.fontSize as number) ?? 16;\n const fontFamily = (s.fontFamily as string) ?? \"Arial, Helvetica, sans-serif\";\n const fontWeight = (s.fontWeight as string) ?? \"bold\";\n\n const btnCss = styleString({\n display: \"inline-block\",\n \"background-color\": bg,\n color,\n \"font-family\": fontFamily,\n \"font-size\": `${fontSize}px`,\n \"font-weight\": fontWeight,\n \"text-decoration\": \"none\",\n \"border-radius\": `${radius}px`,\n padding: \"14px 28px\",\n \"mso-padding-alt\": \"0\",\n \"line-height\": \"100%\",\n \"-webkit-text-size-adjust\": \"none\",\n });\n const label = escapeHtml(el.label);\n const href = safeUrl(el.link);\n const arcsize = Math.min(50, Math.round((radius / 22) * 100));\n const vml = `<!--[if mso]>\n<v:roundrect xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:w=\"urn:schemas-microsoft-com:office:word\" href=\"${href}\" style=\"height:44px;v-text-anchor:middle;width:200px;\" arcsize=\"${arcsize}%\" stroke=\"f\" fillcolor=\"${bg}\">\n<w:anchorlock/>\n<center style=\"color:${color};font-family:${fontFamily};font-size:${fontSize}px;font-weight:${fontWeight};\">${label}</center>\n</v:roundrect>\n<![endif]-->`;\n const html = `<!--[if !mso]><!-- --><a href=\"${href}\" style=\"${btnCss}\">${label}</a><!--<![endif]-->`;\n const cls = collectMobile(ctx, el.style as Record<string, unknown>);\n return `<div${cls ? ` class=\"${cls}\"` : \"\"} style=\"${wrapCss}\">${vml}${html}</div>`;\n}\n\nfunction renderSpacer(el: SpacerElement): string {\n return `<div style=\"height:${el.height}px;line-height:${el.height}px;font-size:1px;mso-line-height-rule:exactly;\"> </div>`;\n}\n\nfunction renderDivider(el: DividerElement, ctx: RenderCtx): string {\n const s = resolveStyle((el.style ?? {}) as Record<string, unknown>, ctx.theme);\n const padTop = px(s.paddingTop as number, 8);\n const padBot = px(s.paddingBottom as number, 8);\n const color = (s.color as string) ?? \"#E5E7EB\";\n const thickness = (s.thickness as number) ?? 1;\n return `<div style=\"padding-top:${padTop};padding-bottom:${padBot};\"><hr style=\"border:0;border-top:${thickness}px solid ${color};margin:0;height:0;\" /></div>`;\n}\n\nfunction renderElement(el: EmailElement, ctx: RenderCtx): string {\n switch (el.type) {\n case \"text\":\n return renderText(el, ctx);\n case \"image\":\n return renderImage(el, ctx);\n case \"button\":\n return renderButton(el, ctx);\n case \"spacer\":\n return renderSpacer(el);\n case \"divider\":\n return renderDivider(el, ctx);\n case \"productGrid\":\n return renderProductGrid(el, ctx);\n }\n}\n\nfunction renderProductGrid(el: ProductGridElement, ctx: RenderCtx): string {\n const s = resolveStyle((el.style ?? {}) as Record<string, unknown>, ctx.theme);\n const cols = el.columns;\n const products = el.products.slice(0, cols * 6); // sane upper bound\n const cardBg =\n (s.cardBackgroundColor as string) ?? (s.backgroundColor as string) ?? \"transparent\";\n const nameColor = (s.nameColor as string) ?? \"{colors.text}\";\n const finalColor = (s.finalPriceColor as string) ?? \"{colors.primary}\";\n const oldColor = (s.oldPriceColor as string) ?? \"#9CA3AF\";\n const btnBg = (s.buttonBackgroundColor as string) ?? \"{colors.buttonBackground}\";\n const btnColor = (s.buttonColor as string) ?? \"{colors.buttonText}\";\n const radius = (s.borderRadius as number) ?? 0;\n const padTop = px(s.paddingTop as number, 16);\n const padBot = px(s.paddingBottom as number, 16);\n const padL = px(s.paddingLeft as number, 16);\n const padR = px(s.paddingRight as number, 16);\n\n const colWidthPct = `${Math.floor(100 / cols)}%`;\n\n // Build product card HTML.\n const card = (p: Product, last: boolean): string => {\n const finalPrice = `<span class=\"final_price\" style=\"color:${resolveTokenSafe(finalColor, ctx.theme)};font-weight:bold;font-size:18px;\">${escapeHtml(\n p.finalPrice\n )}</span>`;\n const oldPrice = el.showOldPrice && p.oldPrice\n ? `<span class=\"old_price\" style=\"color:${resolveTokenSafe(oldColor, ctx.theme)};text-decoration:line-through;font-size:14px;margin-right:8px;\">${escapeHtml(\n p.oldPrice\n )}</span>`\n : \"\";\n const desc = el.showDescription && p.description\n ? `<div style=\"font-family:Arial,Helvetica,sans-serif;font-size:13px;line-height:1.5;color:#6B7280;padding:0 0 12px 0;\">${escapeHtml(p.description)}</div>`\n : \"\";\n const btnLabel = p.buttonLabel ?? el.buttonLabel ?? \"Shop now\";\n const link = p.link ?? \"#\";\n const btn = el.showButton\n ? `<table role=\"presentation\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"margin:0 auto;\"><tr><td align=\"center\" bgcolor=\"${resolveTokenSafe(\n btnBg,\n ctx.theme\n )}\" style=\"border-radius:6px;\"><!--[if mso]>\n<v:roundrect xmlns:v=\"urn:schemas-microsoft-com:vml\" href=\"${safeUrl(link)}\" style=\"height:36px;v-text-anchor:middle;width:140px;\" arcsize=\"15%\" stroke=\"f\" fillcolor=\"${resolveTokenSafe(btnBg, ctx.theme)}\"><w:anchorlock/><center style=\"color:${resolveTokenSafe(btnColor, ctx.theme)};font-family:Arial,sans-serif;font-size:13px;font-weight:bold;\">${escapeHtml(btnLabel)}</center></v:roundrect>\n<![endif]--><!--[if !mso]><!-- --><a href=\"${safeUrl(link)}\" style=\"display:inline-block;padding:10px 18px;font-family:Arial,Helvetica,sans-serif;font-size:13px;font-weight:bold;color:${resolveTokenSafe(btnColor, ctx.theme)};background-color:${resolveTokenSafe(btnBg, ctx.theme)};border-radius:6px;text-decoration:none;\">${escapeHtml(btnLabel)}</a><!--<![endif]--></td></tr></table>`\n : \"\";\n const img = `<img src=\"${escapeHtml(p.image)}\" alt=\"${escapeHtml(p.imageAlt ?? p.name)}\" width=\"100%\" style=\"display:block;width:100%;max-width:100%;height:auto;border:0;outline:none;text-decoration:none;border-radius:${radius}px;\" />`;\n const imgWrapped = p.link\n ? `<a href=\"${safeUrl(p.link)}\" style=\"text-decoration:none;color:inherit;\">${img}</a>`\n : img;\n\n // Each cell: stack on mobile via class. Vertical-align top.\n return `<td class=\"stack\" valign=\"top\" style=\"padding:0 ${last ? 0 : 8}px 16px ${last ? 0 : 0}px;width:${colWidthPct};vertical-align:top;\">\n <table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"background-color:${resolveTokenSafe(cardBg, ctx.theme)};border-radius:${radius}px;\">\n <tr><td style=\"padding:0;font-size:0;line-height:0;\">${imgWrapped}</td></tr>\n <tr><td style=\"padding:12px 12px 4px 12px;font-family:Arial,Helvetica,sans-serif;font-size:15px;font-weight:bold;color:${resolveTokenSafe(nameColor, ctx.theme)};line-height:1.3;\">${escapeHtml(p.name)}</td></tr>\n <tr><td style=\"padding:0 12px 8px 12px;font-family:Arial,Helvetica,sans-serif;\">${oldPrice}${finalPrice}</td></tr>\n ${desc ? `<tr><td style=\"padding:0 12px 4px 12px;\">${desc}</td></tr>` : \"\"}\n ${btn ? `<tr><td align=\"center\" style=\"padding:4px 12px 12px 12px;\">${btn}</td></tr>` : \"\"}\n </table>\n</td>`;\n };\n\n // Group products into rows of `cols`.\n const rows: string[] = [];\n for (let i = 0; i < products.length; i += cols) {\n const slice = products.slice(i, i + cols);\n const tds = slice\n .map((p, idx) => card(p, idx === slice.length - 1))\n .join(\"\\n\");\n // Pad with empty cells if last row is short to keep widths even on desktop.\n const pads = cols - slice.length;\n let padTds = \"\";\n for (let j = 0; j < pads; j++) {\n padTds += `<td class=\"stack\" style=\"width:${colWidthPct};\"> </td>`;\n }\n rows.push(`<tr>${tds}${padTds}</tr>`);\n }\n\n // Mobile: each .stack td becomes block, full-width.\n const cls = collectMobile(ctx, el.style as Record<string, unknown>);\n return `<div${cls ? ` class=\"${cls}\"` : \"\"} style=\"padding:${padTop} ${padR} ${padBot} ${padL};\">\n<!--[if mso | IE]><table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\"><tr><td><![endif]-->\n<table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"width:100%;border-collapse:separate;border-spacing:0;\">\n${rows.join(\"\\n\")}\n</table>\n<!--[if mso | IE]></td></tr></table><![endif]-->\n</div>`;\n}\n\nfunction resolveTokenSafe(value: string | undefined, theme: Theme): string {\n if (!value) return \"\";\n const r = resolveToken(value, theme);\n return typeof r === \"string\" ? r : String(r);\n}\n\nfunction renderModule(m: EmailModule, ctx: RenderCtx): string {\n const s = resolveStyle((m.style ?? {}) as Record<string, unknown>, ctx.theme);\n const css = styleString({\n \"background-color\": s.backgroundColor,\n \"padding-top\": px(s.paddingTop as number, 0),\n \"padding-bottom\": px(s.paddingBottom as number, 0),\n \"padding-left\": px(s.paddingLeft as number, 0),\n \"padding-right\": px(s.paddingRight as number, 0),\n \"border-radius\": s.borderRadius ? `${s.borderRadius}px` : undefined,\n });\n const inner = m.children.map((c) => renderElement(c, ctx)).join(\"\\n\");\n const cls = collectMobile(ctx, m.style as Record<string, unknown>);\n return `<tr><td${cls ? ` class=\"${cls}\"` : \"\"} style=\"${css}\">${inner}</td></tr>`;\n}\n\nexport function renderEmailHtml(doc: EmailDocument): string {\n const bg = resolveToken(doc.settings.backgroundColor, doc.theme) as string;\n const cbg = resolveToken(doc.settings.contentBackgroundColor, doc.theme) as string;\n const width = doc.settings.width;\n const ctx: RenderCtx = { theme: doc.theme, mobileRules: [], classCounter: { n: 0 } };\n const body = doc.modules.map((m) => renderModule(m, ctx)).join(\"\\n\");\n const previewText = escapeHtml(doc.meta.previewText ?? \"\");\n const mobileCss = ctx.mobileRules.join(\"\\n\");\n\n return `<!doctype html>\n<html lang=\"en\" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:o=\"urn:schemas-microsoft-com:office:office\">\n<head>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\" />\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n<meta name=\"x-apple-disable-message-reformatting\" />\n<meta name=\"format-detection\" content=\"telephone=no,address=no,email=no,date=no\" />\n<meta name=\"color-scheme\" content=\"light dark\" />\n<meta name=\"supported-color-schemes\" content=\"light dark\" />\n<title>${escapeHtml(doc.meta.name)}</title>\n<!--[if gte mso 9]><xml><o:OfficeDocumentSettings><o:AllowPNG/><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings></xml><![endif]-->\n<style>\n html,body{margin:0 !important;padding:0 !important;height:100% !important;width:100% !important;}\n *{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;}\n table,td{mso-table-lspace:0pt !important;mso-table-rspace:0pt !important;border-collapse:collapse;}\n table{border-spacing:0 !important;border-collapse:collapse !important;table-layout:fixed !important;margin:0 auto !important;}\n img{-ms-interpolation-mode:bicubic;border:0;height:auto;line-height:100%;outline:none;text-decoration:none;}\n a{text-decoration:none;}\n a[x-apple-data-detectors]{color:inherit !important;text-decoration:none !important;font-size:inherit !important;font-family:inherit !important;font-weight:inherit !important;line-height:inherit !important;}\n u + #body a{color:inherit;text-decoration:none;}\n #MessageViewBody a{color:inherit;text-decoration:none;}\n @media only screen and (max-width:600px){\n .email-container{width:100% !important;max-width:100% !important;}\n .email-content{width:100% !important;max-width:100% !important;}\n .stack{display:block !important;width:100% !important;max-width:100% !important;box-sizing:border-box;padding:0 0 16px 0 !important;}\n .center-on-mobile{text-align:center !important;}\n .full-on-mobile{width:100% !important;height:auto !important;max-width:100% !important;}\n }\n /* Price classes — override these to restyle prices project-wide. */\n .final_price{font-weight:bold;}\n .old_price{text-decoration:line-through;color:#9CA3AF;margin-right:8px;}\n${mobileCss}\n</style>\n</head>\n<body id=\"body\" style=\"margin:0;padding:0;background-color:${bg};\">\n<div style=\"display:none;max-height:0;overflow:hidden;opacity:0;mso-hide:all;\">${previewText}</div>\n<table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"background-color:${bg};\">\n <tr><td align=\"center\" style=\"padding:0;\">\n <!--[if mso | IE]><table role=\"presentation\" width=\"${width}\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" align=\"center\"><tr><td><![endif]-->\n <table role=\"presentation\" class=\"email-container\" width=\"${width}\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"width:${width}px;max-width:${width}px;background-color:${cbg};margin:0 auto;\">\n${body}\n </table>\n <!--[if mso | IE]></td></tr></table><![endif]-->\n </td></tr>\n</table>\n</body>\n</html>`;\n}\n","import type { Theme } from \"../core/types\";\n\nexport const minimalSaaS: Theme = {\n id: \"minimal-saas\",\n name: \"Minimal SaaS\",\n tokens: {\n colors: {\n background: \"#F4F5F7\",\n surface: \"#FFFFFF\",\n primary: \"#2563EB\",\n text: \"#0F172A\",\n muted: \"#64748B\",\n buttonBackground: \"#2563EB\",\n buttonText: \"#FFFFFF\",\n },\n fonts: {\n heading: \"Helvetica, Arial, sans-serif\",\n body: \"Helvetica, Arial, sans-serif\",\n button: \"Helvetica, Arial, sans-serif\",\n },\n spacing: { xs: 4, sm: 8, md: 16, lg: 24, xl: 40 },\n radius: { sm: 4, md: 8, lg: 16 },\n },\n};\n\nexport const ecommercePromo: Theme = {\n id: \"ecommerce-promo\",\n name: \"Ecommerce Promo\",\n tokens: {\n colors: {\n background: \"#FFF7ED\",\n surface: \"#FFFFFF\",\n primary: \"#EA580C\",\n text: \"#1C1917\",\n muted: \"#78716C\",\n buttonBackground: \"#EA580C\",\n buttonText: \"#FFFFFF\",\n },\n fonts: {\n heading: \"Georgia, serif\",\n body: \"Arial, Helvetica, sans-serif\",\n button: \"Arial, Helvetica, sans-serif\",\n },\n spacing: { xs: 4, sm: 8, md: 16, lg: 24, xl: 40 },\n radius: { sm: 4, md: 8, lg: 24 },\n },\n};\n\nexport const luxuryBlack: Theme = {\n id: \"luxury-black\",\n name: \"Luxury Black\",\n tokens: {\n colors: {\n background: \"#000000\",\n surface: \"#0A0A0A\",\n primary: \"#D4AF37\",\n text: \"#F5F5F5\",\n muted: \"#9CA3AF\",\n buttonBackground: \"#D4AF37\",\n buttonText: \"#000000\",\n },\n fonts: {\n heading: \"Georgia, serif\",\n body: \"Georgia, serif\",\n button: \"Helvetica, Arial, sans-serif\",\n },\n spacing: { xs: 4, sm: 8, md: 16, lg: 24, xl: 48 },\n radius: { sm: 0, md: 0, lg: 0 },\n },\n};\n\nexport const greenEco: Theme = {\n id: \"green-eco\",\n name: \"Green Eco\",\n tokens: {\n colors: {\n background: \"#BEC0B6\",\n surface: \"#FFFFFF\",\n primary: \"#3A7D52\",\n text: \"#2C2928\",\n muted: \"#6B6B6B\",\n buttonBackground: \"#3A7D52\",\n buttonText: \"#FFFFFF\",\n },\n fonts: {\n heading: \"Georgia, serif\",\n body: \"Arial, Helvetica, sans-serif\",\n button: \"Arial, Helvetica, sans-serif\",\n },\n spacing: { xs: 4, sm: 8, md: 16, lg: 24, xl: 40 },\n radius: { sm: 4, md: 8, lg: 16 },\n },\n};\n\nexport const newsletterEditorial: Theme = {\n id: \"newsletter-editorial\",\n name: \"Newsletter Editorial\",\n tokens: {\n colors: {\n background: \"#FAFAF9\",\n surface: \"#FFFFFF\",\n primary: \"#111827\",\n text: \"#111827\",\n muted: \"#6B7280\",\n buttonBackground: \"#111827\",\n buttonText: \"#FFFFFF\",\n },\n fonts: {\n heading: \"Georgia, 'Times New Roman', serif\",\n body: \"Georgia, 'Times New Roman', serif\",\n button: \"Helvetica, Arial, sans-serif\",\n },\n spacing: { xs: 4, sm: 8, md: 16, lg: 32, xl: 48 },\n radius: { sm: 2, md: 4, lg: 8 },\n },\n};\n\nexport const defaultThemes: Theme[] = [\n minimalSaaS,\n ecommercePromo,\n luxuryBlack,\n greenEco,\n newsletterEditorial,\n];\n","import { create } from \"zustand\";\nimport type {\n EmailDocument,\n EmailModule,\n EmailElement,\n Theme,\n Selection,\n} from \"../core/types\";\nimport { uid } from \"../core/utils\";\nimport { documentSchema } from \"../core/validation\";\nimport { renderEmailHtml } from \"../core/renderer\";\nimport { defaultThemes } from \"../themes/defaultThemes\";\nimport type { TemplateDefinition } from \"../templates/registry\";\n\nconst HISTORY_LIMIT = 50;\n\nexport type ViewMode = \"desktop\" | \"mobile\";\n\ninterface State {\n doc: EmailDocument;\n selection: Selection;\n past: EmailDocument[];\n future: EmailDocument[];\n themes: Theme[];\n viewMode: ViewMode;\n\n // Mutations\n setSelection: (sel: Selection) => void;\n setViewMode: (mode: ViewMode) => void;\n applyDoc: (next: EmailDocument, push?: boolean) => void;\n undo: () => void;\n redo: () => void;\n\n addModule: (mod: EmailModule, index?: number) => void;\n deleteModule: (moduleId: string) => void;\n duplicateModule: (moduleId: string) => void;\n reorderModules: (fromIndex: number, toIndex: number) => void;\n\n updateModule: (moduleId: string, patch: Partial<EmailModule>) => void;\n updateElement: (\n moduleId: string,\n elementId: string,\n patch: Partial<EmailElement>\n ) => void;\n deleteElement: (moduleId: string, elementId: string) => void;\n reorderElement: (moduleId: string, fromIndex: number, toIndex: number) => void;\n moveElement: (moduleId: string, elementId: string, dir: -1 | 1) => void;\n\n applyTheme: (theme: Theme) => void;\n updateMeta: (patch: Partial<EmailDocument[\"meta\"]>) => void;\n updateSettings: (patch: Partial<EmailDocument[\"settings\"]>) => void;\n\n // Templates\n loadTemplate: (def: TemplateDefinition) => void;\n resetDocument: () => void;\n\n // I/O\n exportJson: () => string;\n importJson: (json: string) => { ok: true } | { ok: false; error: string };\n exportHtml: () => string;\n loadFromLocalStorage: () => void;\n saveToLocalStorage: () => void;\n}\n\nconst STORAGE_KEY = \"openpostcards.draft\";\n\nfunction emptyDoc(theme: Theme): EmailDocument {\n return {\n version: \"1.0\",\n meta: { name: \"Untitled email\", previewText: \"\" },\n theme,\n settings: {\n width: 600,\n backgroundColor: \"{colors.background}\",\n contentBackgroundColor: \"{colors.surface}\",\n },\n modules: [],\n };\n}\n\nexport const useEmailStore = create<State>((set, get) => ({\n doc: emptyDoc(defaultThemes[0]),\n selection: { kind: \"email\" },\n past: [],\n future: [],\n themes: defaultThemes,\n viewMode: \"desktop\",\n\n setSelection: (sel) => set({ selection: sel }),\n setViewMode: (mode) => set({ viewMode: mode }),\n\n applyDoc: (next, push = true) =>\n set((s) => {\n if (!push) return { doc: next };\n const past = [...s.past, s.doc].slice(-HISTORY_LIMIT);\n return { doc: next, past, future: [] };\n }),\n\n undo: () =>\n set((s) => {\n if (s.past.length === 0) return s;\n const prev = s.past[s.past.length - 1];\n return {\n doc: prev,\n past: s.past.slice(0, -1),\n future: [s.doc, ...s.future],\n };\n }),\n\n redo: () =>\n set((s) => {\n if (s.future.length === 0) return s;\n const [next, ...rest] = s.future;\n return { doc: next, past: [...s.past, s.doc], future: rest };\n }),\n\n addModule: (mod, index) => {\n const { doc, applyDoc } = get();\n const idx = index ?? doc.modules.length;\n const modules = [...doc.modules];\n modules.splice(idx, 0, mod);\n applyDoc({ ...doc, modules });\n set({ selection: { kind: \"module\", moduleId: mod.id } });\n },\n\n deleteModule: (moduleId) => {\n const { doc, applyDoc } = get();\n const modules = doc.modules.filter((m) => m.id !== moduleId);\n applyDoc({ ...doc, modules });\n set({ selection: { kind: \"email\" } });\n },\n\n duplicateModule: (moduleId) => {\n const { doc, applyDoc } = get();\n const idx = doc.modules.findIndex((m) => m.id === moduleId);\n if (idx === -1) return;\n const original = doc.modules[idx];\n const clone: EmailModule = {\n ...original,\n id: uid(\"module\"),\n children: original.children.map((c) => ({ ...c, id: uid(\"el\") })),\n };\n const modules = [...doc.modules];\n modules.splice(idx + 1, 0, clone);\n applyDoc({ ...doc, modules });\n set({ selection: { kind: \"module\", moduleId: clone.id } });\n },\n\n reorderModules: (fromIndex, toIndex) => {\n const { doc, applyDoc } = get();\n if (fromIndex === toIndex) return;\n const modules = [...doc.modules];\n const [moved] = modules.splice(fromIndex, 1);\n modules.splice(toIndex, 0, moved);\n applyDoc({ ...doc, modules });\n },\n\n updateModule: (moduleId, patch) => {\n const { doc, applyDoc } = get();\n const modules = doc.modules.map((m) =>\n m.id === moduleId ? { ...m, ...patch, style: { ...m.style, ...patch.style } } : m\n );\n applyDoc({ ...doc, modules });\n },\n\n updateElement: (moduleId, elementId, patch) => {\n const { doc, applyDoc } = get();\n const modules = doc.modules.map((m) => {\n if (m.id !== moduleId) return m;\n const children = m.children.map((c) => {\n if (c.id !== elementId) return c;\n const next = { ...c, ...patch } as EmailElement;\n if (\"style\" in c && \"style\" in patch) {\n (next as { style?: Record<string, unknown> }).style = {\n ...(c as { style?: Record<string, unknown> }).style,\n ...(patch as { style?: Record<string, unknown> }).style,\n };\n }\n return next;\n });\n return { ...m, children };\n });\n applyDoc({ ...doc, modules });\n },\n\n deleteElement: (moduleId, elementId) => {\n const { doc, applyDoc } = get();\n const modules = doc.modules.map((m) =>\n m.id === moduleId\n ? { ...m, children: m.children.filter((c) => c.id !== elementId) }\n : m\n );\n applyDoc({ ...doc, modules });\n set({ selection: { kind: \"module\", moduleId } });\n },\n\n reorderElement: (moduleId, fromIndex, toIndex) => {\n const { doc, applyDoc } = get();\n const modules = doc.modules.map((m) => {\n if (m.id !== moduleId) return m;\n if (fromIndex < 0 || fromIndex >= m.children.length) return m;\n if (toIndex < 0 || toIndex >= m.children.length) return m;\n if (fromIndex === toIndex) return m;\n const children = [...m.children];\n const [moved] = children.splice(fromIndex, 1);\n children.splice(toIndex, 0, moved);\n return { ...m, children };\n });\n applyDoc({ ...doc, modules });\n },\n\n moveElement: (moduleId, elementId, dir) => {\n const { doc, reorderElement } = get();\n const m = doc.modules.find((x) => x.id === moduleId);\n if (!m) return;\n const idx = m.children.findIndex((c) => c.id === elementId);\n if (idx === -1) return;\n reorderElement(moduleId, idx, idx + dir);\n },\n\n applyTheme: (theme) => {\n const { doc, applyDoc } = get();\n applyDoc({ ...doc, theme });\n },\n\n updateMeta: (patch) => {\n const { doc, applyDoc } = get();\n applyDoc({ ...doc, meta: { ...doc.meta, ...patch } });\n },\n\n updateSettings: (patch) => {\n const { doc, applyDoc } = get();\n applyDoc({ ...doc, settings: { ...doc.settings, ...patch } });\n },\n\n loadTemplate: (def) => {\n const next = def.build();\n get().applyDoc(next);\n set({ selection: { kind: \"email\" }, past: [], future: [] });\n },\n\n resetDocument: () => {\n const { doc, applyDoc } = get();\n applyDoc(emptyDoc(doc.theme));\n set({ selection: { kind: \"email\" }, past: [], future: [] });\n },\n\n exportJson: () => JSON.stringify(get().doc, null, 2),\n\n importJson: (json) => {\n try {\n const parsed = JSON.parse(json);\n const result = documentSchema.safeParse(parsed);\n if (!result.success) {\n return { ok: false, error: result.error.message };\n }\n get().applyDoc(result.data as EmailDocument);\n return { ok: true };\n } catch (e) {\n return { ok: false, error: (e as Error).message };\n }\n },\n\n exportHtml: () => renderEmailHtml(get().doc),\n\n loadFromLocalStorage: () => {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return;\n const result = documentSchema.safeParse(JSON.parse(raw));\n if (result.success) {\n set({ doc: result.data as EmailDocument, past: [], future: [] });\n }\n } catch {\n // ignore corrupt drafts\n }\n },\n\n saveToLocalStorage: () => {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(get().doc));\n },\n}));\n","// Template = a complete EmailDocument factory. Templates are JSON-shaped\n// (their `build()` returns the same `EmailDocument` JSON used by the editor),\n// but they are written as TypeScript factories so they can:\n// - reuse element helpers (text, image, productGrid, ...)\n// - generate fresh ids on every load (avoiding id collisions)\n// - reference theme tokens like {colors.primary}.\n//\n// Each template file exports a `TemplateDefinition` and self-registers with\n// `templateRegistry.register(def)` via the aggregator in ./index.ts.\n\nimport type { EmailDocument } from \"../core/types\";\n\nexport type TemplateCategory =\n | \"newsletter\"\n | \"ecommerce\"\n | \"abandoned_cart\"\n | \"product_launch\"\n | \"onboarding\"\n | \"event\"\n | \"transactional\"\n | \"publishing\";\n\nexport interface TemplateDefinition {\n id: string;\n name: string;\n category: TemplateCategory;\n /** Human + AI readable description. */\n description: string;\n /** Free-form tags for search. */\n tags?: string[];\n /** Optional preview image URL (https or data: URI). */\n thumbnail?: string;\n /** Returns a fresh `EmailDocument` JSON with new ids every call. */\n build: () => EmailDocument;\n}\n\nclass TemplateRegistry {\n private templates = new Map<string, TemplateDefinition>();\n\n register(def: TemplateDefinition) {\n this.templates.set(def.id, def);\n }\n\n get(id: string): TemplateDefinition | undefined {\n return this.templates.get(id);\n }\n\n list(): TemplateDefinition[] {\n return Array.from(this.templates.values());\n }\n\n byCategory(cat: TemplateCategory): TemplateDefinition[] {\n return this.list().filter((t) => t.category === cat);\n }\n}\n\nexport const templateRegistry = new TemplateRegistry();\n\nexport const TEMPLATE_CATEGORY_LABELS: Record<TemplateCategory, string> = {\n newsletter: \"Newsletter\",\n ecommerce: \"Ecommerce\",\n abandoned_cart: \"Abandoned Cart\",\n product_launch: \"Product Launch\",\n onboarding: \"Onboarding\",\n event: \"Event\",\n transactional: \"Transactional\",\n publishing: \"Publishing\",\n};\n","// Shared element builders for module definitions.\n// Keeps individual module files terse and consistent.\nimport type { EmailElement, EmailModule, Product, ProductGridElement } from \"../core/types\";\nimport { uid } from \"../core/utils\";\n\nexport const text = (\n content: string,\n opts: Partial<{\n role: \"headline\" | \"subheadline\" | \"body\" | \"caption\";\n fontSize: number;\n fontFamily: string;\n fontWeight: number | string;\n color: string;\n align: \"left\" | \"center\" | \"right\";\n paddingTop: number;\n paddingBottom: number;\n paddingLeft: number;\n paddingRight: number;\n lineHeight: number;\n letterSpacing: number;\n link: string;\n mobile: Record<string, unknown>;\n }> = {}\n): EmailElement => {\n // Sensible mobile defaults: tighter side padding, slightly smaller large headings.\n const baseFontSize = opts.fontSize ?? 16;\n const mobileDefaults: Record<string, unknown> = {\n paddingLeft: 16,\n paddingRight: 16,\n };\n if (baseFontSize >= 28) mobileDefaults.fontSize = Math.max(22, Math.round(baseFontSize * 0.78));\n else if (baseFontSize >= 22) mobileDefaults.fontSize = Math.max(20, Math.round(baseFontSize * 0.85));\n return {\n id: uid(\"el\"),\n type: \"text\",\n role: opts.role,\n content,\n style: {\n fontFamily: opts.fontFamily ?? \"{fonts.body}\",\n fontSize: baseFontSize,\n fontWeight: opts.fontWeight,\n color: opts.color ?? \"{colors.text}\",\n align: opts.align ?? \"left\",\n paddingTop: opts.paddingTop ?? 8,\n paddingBottom: opts.paddingBottom ?? 8,\n paddingLeft: opts.paddingLeft ?? 24,\n paddingRight: opts.paddingRight ?? 24,\n lineHeight: opts.lineHeight ?? 1.5,\n letterSpacing: opts.letterSpacing,\n link: opts.link,\n mobile: { ...mobileDefaults, ...(opts.mobile ?? {}) },\n },\n };\n};\n\nexport const image = (\n src: string,\n alt: string,\n opts: Partial<{\n width: number;\n height: number;\n align: \"left\" | \"center\" | \"right\";\n link: string;\n paddingTop: number;\n paddingBottom: number;\n borderRadius: number;\n mobile: Record<string, unknown>;\n }> = {}\n): EmailElement => {\n const w = opts.width ?? 552;\n // Mobile: cap to viewport width (account for outer 16px padding).\n const mobileDefaults: Record<string, unknown> = w > 343 ? { width: 343, align: \"center\" } : {};\n return {\n id: uid(\"el\"),\n type: \"image\",\n src,\n alt,\n link: opts.link,\n style: {\n width: w,\n height: opts.height,\n align: opts.align ?? \"center\",\n paddingTop: opts.paddingTop ?? 8,\n paddingBottom: opts.paddingBottom ?? 8,\n borderRadius: opts.borderRadius,\n mobile: { ...mobileDefaults, ...(opts.mobile ?? {}) },\n },\n };\n};\n\nexport const button = (\n label: string,\n link = \"#\",\n opts: Partial<{\n align: \"left\" | \"center\" | \"right\";\n backgroundColor: string;\n color: string;\n fontSize: number;\n borderRadius: number;\n paddingTop: number;\n paddingBottom: number;\n mobile: Record<string, unknown>;\n }> = {}\n): EmailElement => ({\n id: uid(\"el\"),\n type: \"button\",\n label,\n link,\n style: {\n backgroundColor: opts.backgroundColor ?? \"{colors.buttonBackground}\",\n color: opts.color ?? \"{colors.buttonText}\",\n fontFamily: \"{fonts.button}\",\n fontSize: opts.fontSize ?? 16,\n borderRadius: opts.borderRadius ?? 8,\n align: opts.align ?? \"center\",\n paddingTop: opts.paddingTop ?? 16,\n paddingBottom: opts.paddingBottom ?? 16,\n // On mobile, full-width touch-friendly button.\n mobile: { align: \"center\", ...(opts.mobile ?? {}) },\n },\n});\n\nexport const spacer = (height = 16): EmailElement => ({\n id: uid(\"el\"),\n type: \"spacer\",\n height,\n});\n\nexport const divider = (\n opts: Partial<{ color: string; thickness: number; paddingTop: number; paddingBottom: number }> = {}\n): EmailElement => ({\n id: uid(\"el\"),\n type: \"divider\",\n style: {\n color: opts.color ?? \"#E5E7EB\",\n thickness: opts.thickness ?? 1,\n paddingTop: opts.paddingTop ?? 8,\n paddingBottom: opts.paddingBottom ?? 8,\n },\n});\n\nexport const mod = (\n type: string,\n name: string,\n children: EmailElement[],\n style?: EmailModule[\"style\"]\n): EmailModule => ({\n id: uid(\"module\"),\n type,\n name,\n style: style ?? {\n backgroundColor: \"{colors.surface}\",\n paddingTop: 16,\n paddingBottom: 16,\n mobile: { paddingLeft: 0, paddingRight: 0 },\n },\n children,\n});\n\n// Heading shortcut for newsletter article titles.\nexport const heading = (\n content: string,\n opts: {\n level?: 1 | 2 | 3;\n align?: \"left\" | \"center\" | \"right\";\n paddingTop?: number;\n paddingBottom?: number;\n fontSize?: number;\n } = {}\n) => {\n const sizes = { 1: 32, 2: 24, 3: 18 } as const;\n return text(content, {\n role: \"headline\",\n fontFamily: \"{fonts.heading}\",\n fontSize: opts.fontSize ?? sizes[opts.level ?? 2],\n fontWeight: \"bold\",\n align: opts.align,\n paddingTop: opts.paddingTop ?? 16,\n paddingBottom: opts.paddingBottom ?? 8,\n lineHeight: 1.25,\n });\n};\n\nexport const eyebrow = (\n content: string,\n opts: { align?: \"left\" | \"center\" | \"right\"; paddingTop?: number; paddingBottom?: number } = {}\n) =>\n text(content.toUpperCase(), {\n fontSize: 12,\n fontWeight: \"bold\",\n color: \"{colors.primary}\",\n letterSpacing: 2,\n align: opts.align,\n paddingTop: opts.paddingTop ?? 16,\n paddingBottom: opts.paddingBottom ?? 4,\n });\n\nexport const muted = (\n content: string,\n opts: {\n align?: \"left\" | \"center\" | \"right\";\n fontSize?: number;\n paddingTop?: number;\n paddingBottom?: number;\n lineHeight?: number;\n link?: string;\n letterSpacing?: number;\n } = {}\n) =>\n text(content, {\n color: \"{colors.muted}\",\n align: opts.align,\n fontSize: opts.fontSize ?? 14,\n paddingTop: opts.paddingTop,\n paddingBottom: opts.paddingBottom,\n lineHeight: opts.lineHeight,\n link: opts.link,\n letterSpacing: opts.letterSpacing,\n });\n\nexport const PLACEHOLDER = (w: number, h: number, label = \"Image\") =>\n `https://placehold.co/${w}x${h}?text=${encodeURIComponent(label)}`;\n\nlet productSeed = 0;\nexport const product = (p: Partial<Product> & { name: string; finalPrice: string }): Product => {\n productSeed += 1;\n return {\n id: uid(\"prod\"),\n image: p.image ?? PLACEHOLDER(400, 400, p.name),\n imageAlt: p.imageAlt ?? p.name,\n name: p.name,\n finalPrice: p.finalPrice,\n oldPrice: p.oldPrice,\n description: p.description,\n link: p.link ?? \"#\",\n buttonLabel: p.buttonLabel,\n };\n};\n\nexport const productGrid = (\n products: Product[],\n opts: Partial<{\n columns: 1 | 2 | 3;\n showOldPrice: boolean;\n showButton: boolean;\n showDescription: boolean;\n buttonLabel: string;\n cardBackgroundColor: string;\n nameColor: string;\n finalPriceColor: string;\n oldPriceColor: string;\n buttonBackgroundColor: string;\n buttonColor: string;\n borderRadius: number;\n paddingTop: number;\n paddingBottom: number;\n paddingLeft: number;\n paddingRight: number;\n }> = {}\n): ProductGridElement => ({\n id: uid(\"el\"),\n type: \"productGrid\",\n products,\n columns: opts.columns ?? (products.length >= 3 ? 3 : 2),\n showOldPrice: opts.showOldPrice ?? products.some((p) => !!p.oldPrice),\n showButton: opts.showButton ?? true,\n showDescription: opts.showDescription ?? false,\n buttonLabel: opts.buttonLabel ?? \"Shop now\",\n style: {\n cardBackgroundColor: opts.cardBackgroundColor ?? \"{colors.surface}\",\n nameColor: opts.nameColor ?? \"{colors.text}\",\n finalPriceColor: opts.finalPriceColor ?? \"{colors.primary}\",\n oldPriceColor: opts.oldPriceColor ?? \"#9CA3AF\",\n buttonBackgroundColor: opts.buttonBackgroundColor ?? \"{colors.buttonBackground}\",\n buttonColor: opts.buttonColor ?? \"{colors.buttonText}\",\n borderRadius: opts.borderRadius ?? 8,\n paddingTop: opts.paddingTop ?? 8,\n paddingBottom: opts.paddingBottom ?? 8,\n paddingLeft: opts.paddingLeft ?? 16,\n paddingRight: opts.paddingRight ?? 16,\n },\n});\n","import type { EmailDocument } from \"../core/types\";\nimport { templateRegistry, type TemplateDefinition } from \"./registry\";\nimport { newsletterEditorial } from \"../themes/defaultThemes\";\nimport {\n mod,\n text,\n image,\n button,\n spacer,\n divider,\n heading,\n muted,\n eyebrow,\n PLACEHOLDER,\n} from \"../modules/helpers\";\n\nconst def: TemplateDefinition = {\n id: \"weekly-newsletter\",\n name: \"The Weekly Digest\",\n category: \"newsletter\",\n description:\n \"Editorial weekly newsletter with masthead, in-this-issue table of contents, three article summaries, and a footer.\",\n tags: [\"newsletter\", \"editorial\", \"weekly\", \"publishing\"],\n thumbnail: \"https://placehold.co/600x800/F5F1EA/1F2937?text=The+Weekly\",\n build: (): EmailDocument => ({\n version: \"1.0\",\n meta: {\n name: \"The Weekly Digest — Issue 42\",\n previewText: \"This week: AI in the newsroom, three reads, and a recipe.\",\n },\n theme: newsletterEditorial,\n settings: {\n width: 600,\n backgroundColor: \"{colors.background}\",\n contentBackgroundColor: \"{colors.surface}\",\n },\n modules: [\n mod(\"header.masthead\", \"Masthead\", [\n text(\"THE WEEKLY\", {\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 32,\n fontWeight: \"bold\",\n letterSpacing: 6,\n paddingTop: 32,\n paddingBottom: 4,\n }),\n muted(\"Issue 42 · April 30, 2026\", { align: \"center\", paddingBottom: 24 }),\n divider({ paddingTop: 0, paddingBottom: 0 }),\n ]),\n mod(\"content.article\", \"Lead Story\", [\n eyebrow(\"LEAD STORY\", { paddingTop: 24 }),\n heading(\"AI Comes to the Newsroom — and It's Helping\", {\n fontSize: 28,\n paddingTop: 4,\n paddingBottom: 12,\n }),\n image(PLACEHOLDER(560, 320, \"Lead+Story\"), \"Newsroom\", { width: 560 }),\n text(\n \"A new generation of editorial assistants is changing how stories get written, fact-checked and published. Here's what we found in three newsrooms.\",\n { paddingTop: 16, paddingBottom: 12 }\n ),\n text(\"Read the full piece →\", {\n color: \"{colors.primary}\",\n fontWeight: \"bold\",\n link: \"#\",\n paddingBottom: 8,\n }),\n ]),\n mod(\"content.three_reads\", \"Three More Reads\", [\n eyebrow(\"ALSO THIS WEEK\", { paddingTop: 16 }),\n heading(\"Three more reads\", { paddingBottom: 12 }),\n text(\"01 · The hidden cost of free tier APIs\", {\n fontWeight: \"bold\",\n link: \"#\",\n paddingTop: 4,\n paddingBottom: 4,\n }),\n muted(\"How startups are quietly burning runway on metered cloud calls.\", {\n paddingBottom: 12,\n }),\n divider({ paddingTop: 4, paddingBottom: 4 }),\n text(\"02 · A field guide to product-led onboarding\", {\n fontWeight: \"bold\",\n link: \"#\",\n paddingBottom: 4,\n }),\n muted(\"Stop sending welcome emails. Start designing the first 5 minutes.\", {\n paddingBottom: 12,\n }),\n divider({ paddingTop: 4, paddingBottom: 4 }),\n text(\"03 · Inside the new Madrid co-working scene\", {\n fontWeight: \"bold\",\n link: \"#\",\n paddingBottom: 4,\n }),\n muted(\"Why founders are leaving Lisbon for Spain's quiet capital.\", {\n paddingBottom: 16,\n }),\n ]),\n mod(\"cta.subscribe_share\", \"Forward to a friend\", [\n divider({ paddingTop: 8, paddingBottom: 8 }),\n text(\"Liked this? Forward it to a friend.\", {\n align: \"center\",\n paddingTop: 16,\n paddingBottom: 12,\n }),\n button(\"Share The Weekly\", \"#\"),\n spacer(16),\n ]),\n mod(\n \"footer.simple\",\n \"Footer\",\n [\n muted(\"© 2026 The Weekly · 350 Madison Ave · NY 10017\", {\n align: \"center\",\n paddingTop: 16,\n }),\n muted(\"Manage preferences · Unsubscribe\", {\n align: \"center\",\n paddingTop: 4,\n paddingBottom: 24,\n link: \"#\",\n }),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n ],\n }),\n};\n\ntemplateRegistry.register(def);\nexport default def;\n","import type { EmailDocument } from \"../core/types\";\nimport { templateRegistry, type TemplateDefinition } from \"./registry\";\nimport { ecommercePromo } from \"../themes/defaultThemes\";\nimport {\n mod,\n text,\n spacer,\n button,\n productGrid,\n product,\n PLACEHOLDER,\n muted,\n} from \"../modules/helpers\";\n\nconst def: TemplateDefinition = {\n id: \"flash-sale\",\n name: \"Flash Sale — 24h\",\n category: \"ecommerce\",\n description:\n \"Urgency-driven 24-hour flash sale with countdown headline, three featured products with old/final prices, and a closing CTA.\",\n tags: [\"ecommerce\", \"sale\", \"promo\", \"discount\", \"urgency\"],\n thumbnail: \"https://placehold.co/600x800/EA580C/FFFFFF?text=FLASH+SALE\",\n build: (): EmailDocument => ({\n version: \"1.0\",\n meta: {\n name: \"Flash Sale — 24h only\",\n previewText: \"Up to 50% off — ends midnight tonight.\",\n },\n theme: ecommercePromo,\n settings: {\n width: 600,\n backgroundColor: \"{colors.background}\",\n contentBackgroundColor: \"{colors.surface}\",\n },\n modules: [\n mod(\n \"hero.flash\",\n \"Flash hero\",\n [\n text(\"⏰ FLASH SALE — ENDS IN 24H\", {\n color: \"{colors.buttonText}\",\n align: \"center\",\n fontWeight: \"bold\",\n letterSpacing: 3,\n paddingTop: 24,\n paddingBottom: 8,\n }),\n text(\"Up to 50% off everything\", {\n color: \"{colors.buttonText}\",\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 32,\n fontWeight: \"bold\",\n paddingBottom: 16,\n }),\n button(\"Shop the sale\", \"#\", {\n backgroundColor: \"{colors.surface}\",\n color: \"{colors.primary}\",\n }),\n spacer(24),\n ],\n { backgroundColor: \"{colors.primary}\", paddingTop: 0, paddingBottom: 0 }\n ),\n mod(\"ecom.featured_grid\", \"Featured products\", [\n text(\"Today's picks\", {\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 24,\n fontWeight: \"bold\",\n paddingTop: 24,\n paddingBottom: 16,\n }),\n productGrid(\n [\n product({\n name: \"Linen Tote Bag\",\n image: PLACEHOLDER(400, 400, \"Tote\"),\n oldPrice: \"$59\",\n finalPrice: \"$29\",\n }),\n product({\n name: \"Ceramic Mug Set\",\n image: PLACEHOLDER(400, 400, \"Mug+Set\"),\n oldPrice: \"$48\",\n finalPrice: \"$24\",\n }),\n product({\n name: \"Brass Desk Lamp\",\n image: PLACEHOLDER(400, 400, \"Lamp\"),\n oldPrice: \"$159\",\n finalPrice: \"$79\",\n }),\n ],\n { columns: 3, showOldPrice: true, buttonLabel: \"Add to bag\" }\n ),\n ]),\n mod(\"cta.urgency\", \"Final CTA\", [\n text(\"Don't sleep on it — this ends at midnight.\", {\n align: \"center\",\n fontWeight: \"bold\",\n paddingTop: 16,\n paddingBottom: 12,\n }),\n button(\"Shop now\", \"#\"),\n spacer(24),\n ]),\n mod(\n \"footer.simple\",\n \"Footer\",\n [\n muted(\"© 2026 Acme Co · Unsubscribe · Manage preferences\", {\n align: \"center\",\n paddingTop: 16,\n paddingBottom: 24,\n link: \"#\",\n }),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n ],\n }),\n};\n\ntemplateRegistry.register(def);\nexport default def;\n","import type { EmailDocument } from \"../core/types\";\nimport { templateRegistry, type TemplateDefinition } from \"./registry\";\nimport { greenEco } from \"../themes/defaultThemes\";\nimport {\n mod,\n text,\n spacer,\n button,\n productGrid,\n product,\n PLACEHOLDER,\n heading,\n muted,\n divider,\n} from \"../modules/helpers\";\n\nconst def: TemplateDefinition = {\n id: \"abandoned-cart\",\n name: \"Abandoned Cart Recovery\",\n category: \"abandoned_cart\",\n description:\n \"Friendly reminder showing items left in the cart, a discount nudge, and a return-to-cart button. For automated cart-recovery flows.\",\n tags: [\"abandoned-cart\", \"recovery\", \"automation\", \"ecommerce\"],\n thumbnail: \"https://placehold.co/600x800/F5F1EA/2C2928?text=Cart+Reminder\",\n build: (): EmailDocument => ({\n version: \"1.0\",\n meta: {\n name: \"You left something behind\",\n previewText: \"Your cart is waiting — and we saved your spot.\",\n },\n theme: greenEco,\n settings: {\n width: 600,\n backgroundColor: \"{colors.background}\",\n contentBackgroundColor: \"{colors.surface}\",\n },\n modules: [\n mod(\"header.logo\", \"Logo\", [\n text(\"ACME\", {\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 22,\n fontWeight: \"bold\",\n letterSpacing: 4,\n paddingTop: 24,\n paddingBottom: 24,\n }),\n ]),\n mod(\"hero.text\", \"Headline\", [\n heading(\"You left something behind\", {\n align: \"center\",\n fontSize: 28,\n paddingTop: 16,\n paddingBottom: 8,\n }),\n muted(\"We saved your bag. Pick up right where you left off.\", {\n align: \"center\",\n paddingBottom: 16,\n }),\n ]),\n mod(\"ecom.cart_items\", \"Cart items\", [\n productGrid(\n [\n product({\n name: \"Linen Tote Bag\",\n image: PLACEHOLDER(400, 400, \"Tote\"),\n oldPrice: \"$59\",\n finalPrice: \"$39\",\n description: \"Heavyweight natural linen, made in Portugal.\",\n }),\n product({\n name: \"Cast Iron Skillet\",\n image: PLACEHOLDER(400, 400, \"Skillet\"),\n finalPrice: \"$89\",\n description: \"Pre-seasoned, lifetime guarantee.\",\n }),\n ],\n { columns: 1, showOldPrice: true, showDescription: true, buttonLabel: \"Return to cart\" }\n ),\n ]),\n mod(\"cta.discount\", \"Discount nudge\", [\n divider({ paddingTop: 8, paddingBottom: 16 }),\n text(\"Here's 10% off to seal the deal\", {\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 22,\n fontWeight: \"bold\",\n paddingBottom: 4,\n }),\n text(\"COMEBACK10\", {\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 28,\n fontWeight: \"bold\",\n color: \"{colors.primary}\",\n letterSpacing: 4,\n paddingBottom: 16,\n }),\n button(\"Complete your order\"),\n spacer(24),\n ]),\n mod(\n \"footer.simple\",\n \"Footer\",\n [\n muted(\"Questions? hello@acme.shop\", {\n align: \"center\",\n paddingTop: 16,\n }),\n muted(\"© 2026 Acme · Unsubscribe\", {\n align: \"center\",\n paddingTop: 4,\n paddingBottom: 24,\n link: \"#\",\n }),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n ],\n }),\n};\n\ntemplateRegistry.register(def);\nexport default def;\n","import type { EmailDocument } from \"../core/types\";\nimport { templateRegistry, type TemplateDefinition } from \"./registry\";\nimport { luxuryBlack } from \"../themes/defaultThemes\";\nimport {\n mod,\n text,\n spacer,\n button,\n image,\n productGrid,\n product,\n PLACEHOLDER,\n heading,\n muted,\n} from \"../modules/helpers\";\n\nconst def: TemplateDefinition = {\n id: \"product-launch\",\n name: \"Product Launch — Drop\",\n category: \"product_launch\",\n description:\n \"Bold full-bleed product launch announcement: hero image, big headline, three new products, and an early-access CTA.\",\n tags: [\"launch\", \"drop\", \"new-arrivals\", \"ecommerce\"],\n thumbnail: \"https://placehold.co/600x800/000000/D4AF37?text=NEW+DROP\",\n build: (): EmailDocument => ({\n version: \"1.0\",\n meta: {\n name: \"AUREX 02 — New Drop\",\n previewText: \"The new collection lands today. Limited stock.\",\n },\n theme: luxuryBlack,\n settings: {\n width: 600,\n backgroundColor: \"{colors.background}\",\n contentBackgroundColor: \"{colors.surface}\",\n },\n modules: [\n mod(\n \"hero.full_bleed\",\n \"Full-bleed hero\",\n [\n image(PLACEHOLDER(600, 700, \"AUREX+02\"), \"AUREX 02 hero\", {\n width: 600,\n paddingTop: 0,\n paddingBottom: 0,\n }),\n text(\"AUREX 02\", {\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 40,\n fontWeight: \"bold\",\n color: \"{colors.primary}\",\n letterSpacing: 6,\n paddingTop: 32,\n paddingBottom: 8,\n }),\n text(\"Pure performance. Limited release.\", {\n align: \"center\",\n color: \"{colors.text}\",\n paddingBottom: 24,\n }),\n button(\"Shop the drop\", \"#\"),\n spacer(40),\n ],\n { backgroundColor: \"{colors.surface}\", paddingTop: 0, paddingBottom: 0 }\n ),\n mod(\"ecom.collection\", \"The Collection\", [\n muted(\"THE COLLECTION\", {\n align: \"center\",\n letterSpacing: 4,\n paddingTop: 24,\n paddingBottom: 4,\n }),\n heading(\"Meet the line-up\", {\n align: \"center\",\n fontSize: 26,\n paddingBottom: 16,\n }),\n productGrid(\n [\n product({\n name: \"AUREX 02 — Carbon\",\n image: PLACEHOLDER(400, 400, \"Carbon\"),\n finalPrice: \"$329\",\n }),\n product({\n name: \"AUREX 02 — Sand\",\n image: PLACEHOLDER(400, 400, \"Sand\"),\n finalPrice: \"$329\",\n }),\n product({\n name: \"AUREX 02 — Sage\",\n image: PLACEHOLDER(400, 400, \"Sage\"),\n finalPrice: \"$329\",\n }),\n ],\n { columns: 3, showOldPrice: false, buttonLabel: \"View\" }\n ),\n ]),\n mod(\n \"cta.early_access\",\n \"Early access\",\n [\n text(\"Members get 24h early access\", {\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 22,\n fontWeight: \"bold\",\n color: \"{colors.text}\",\n paddingTop: 32,\n paddingBottom: 16,\n }),\n button(\"Become a member\", \"#\"),\n spacer(40),\n ],\n { backgroundColor: \"{colors.surface}\", paddingTop: 0, paddingBottom: 0 }\n ),\n mod(\n \"footer.brand\",\n \"Footer\",\n [\n muted(\"AUREX · Designed in Berlin · Made in Italy\", {\n align: \"center\",\n paddingTop: 16,\n }),\n muted(\"Manage preferences · Unsubscribe\", {\n align: \"center\",\n paddingTop: 4,\n paddingBottom: 24,\n link: \"#\",\n }),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n ],\n }),\n};\n\ntemplateRegistry.register(def);\nexport default def;\n","import type { EmailDocument } from \"../core/types\";\nimport { templateRegistry, type TemplateDefinition } from \"./registry\";\nimport { minimalSaaS } from \"../themes/defaultThemes\";\nimport {\n mod,\n text,\n spacer,\n button,\n divider,\n heading,\n muted,\n PLACEHOLDER,\n image,\n} from \"../modules/helpers\";\n\nconst def: TemplateDefinition = {\n id: \"welcome-onboarding\",\n name: \"SaaS Welcome & Onboarding\",\n category: \"onboarding\",\n description:\n \"First-touch SaaS welcome with a personal note, a 3-step getting-started checklist, and a CTA to the app.\",\n tags: [\"welcome\", \"onboarding\", \"saas\", \"checklist\"],\n thumbnail: \"https://placehold.co/600x800/F4F5F7/2563EB?text=Welcome\",\n build: (): EmailDocument => ({\n version: \"1.0\",\n meta: {\n name: \"Welcome to Acme\",\n previewText: \"Three quick steps to get the most out of Acme.\",\n },\n theme: minimalSaaS,\n settings: {\n width: 600,\n backgroundColor: \"{colors.background}\",\n contentBackgroundColor: \"{colors.surface}\",\n },\n modules: [\n mod(\"header.logo\", \"Logo\", [\n image(PLACEHOLDER(120, 40, \"ACME\"), \"Acme\", { width: 120, paddingTop: 24 }),\n ]),\n mod(\"hero.welcome\", \"Welcome\", [\n heading(\"Welcome aboard, friend 👋\", {\n align: \"center\",\n fontSize: 28,\n paddingTop: 8,\n paddingBottom: 8,\n }),\n text(\n \"I'm Maya, the founder of Acme. Thanks for signing up — I wanted to send you a quick note (and a 3-step checklist) so you get value fast.\",\n { align: \"center\", paddingBottom: 24 }\n ),\n ]),\n mod(\"content.checklist\", \"Checklist\", [\n text(\"✅ 1. Connect your data\", { fontWeight: \"bold\", paddingTop: 8, paddingBottom: 4 }),\n muted(\"Hook up Stripe, HubSpot or Salesforce in 30 seconds.\", { paddingBottom: 12 }),\n divider({ paddingTop: 4, paddingBottom: 4 }),\n text(\"⚡ 2. Run your first report\", { fontWeight: \"bold\", paddingTop: 4, paddingBottom: 4 }),\n muted(\"Pick a template, click Run, watch the magic.\", { paddingBottom: 12 }),\n divider({ paddingTop: 4, paddingBottom: 4 }),\n text(\"👯 3. Invite a teammate\", { fontWeight: \"bold\", paddingTop: 4, paddingBottom: 4 }),\n muted(\"Acme is more fun (and useful) with your team.\", { paddingBottom: 16 }),\n ]),\n mod(\"cta.app\", \"Open the app\", [\n button(\"Open Acme\", \"#\"),\n spacer(8),\n muted(\"Or reply to this email — a real human will read it.\", { align: \"center\", paddingBottom: 24 }),\n ]),\n mod(\n \"footer.simple\",\n \"Footer\",\n [\n muted(\"Acme, Inc · 100 Market St · San Francisco, CA\", {\n align: \"center\",\n paddingTop: 16,\n }),\n muted(\"Manage notifications · Unsubscribe\", {\n align: \"center\",\n paddingTop: 4,\n paddingBottom: 24,\n link: \"#\",\n }),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n ],\n }),\n};\n\ntemplateRegistry.register(def);\nexport default def;\n","import type { EmailDocument } from \"../core/types\";\nimport { templateRegistry, type TemplateDefinition } from \"./registry\";\nimport { newsletterEditorial } from \"../themes/defaultThemes\";\nimport {\n mod,\n text,\n spacer,\n button,\n image,\n divider,\n heading,\n muted,\n PLACEHOLDER,\n} from \"../modules/helpers\";\n\nconst def: TemplateDefinition = {\n id: \"event-invite\",\n name: \"Event Invite\",\n category: \"event\",\n description:\n \"Invite to a live event with a header image, date / time / location card, agenda highlights, and an RSVP button.\",\n tags: [\"event\", \"invite\", \"rsvp\", \"conference\", \"meetup\"],\n thumbnail: \"https://placehold.co/600x800/111827/FAFAF9?text=You're+Invited\",\n build: (): EmailDocument => ({\n version: \"1.0\",\n meta: {\n name: \"You're invited: Acme Summit 2026\",\n previewText: \"Join us June 12 in Brooklyn for talks, food and a rooftop after-party.\",\n },\n theme: newsletterEditorial,\n settings: {\n width: 600,\n backgroundColor: \"{colors.background}\",\n contentBackgroundColor: \"{colors.surface}\",\n },\n modules: [\n mod(\"header.logo\", \"Logo\", [\n text(\"ACME SUMMIT\", {\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 18,\n fontWeight: \"bold\",\n letterSpacing: 6,\n paddingTop: 24,\n paddingBottom: 16,\n }),\n ]),\n mod(\"hero.event\", \"Event hero\", [\n image(PLACEHOLDER(600, 320, \"Acme+Summit\"), \"Acme Summit\", {\n width: 600,\n paddingTop: 0,\n paddingBottom: 16,\n }),\n heading(\"You're invited.\", {\n align: \"center\",\n fontSize: 32,\n paddingTop: 8,\n paddingBottom: 4,\n }),\n muted(\"A one-day gathering for builders. Brooklyn, NY.\", {\n align: \"center\",\n paddingBottom: 24,\n }),\n ]),\n mod(\n \"content.event_card\",\n \"Event details\",\n [\n text(\"📅 Friday, June 12, 2026\", {\n align: \"center\",\n fontWeight: \"bold\",\n paddingTop: 24,\n paddingBottom: 4,\n }),\n text(\"⏰ 9:00 AM — 6:00 PM\", { align: \"center\", paddingBottom: 4 }),\n text(\"📍 The Invisible Dog · 51 Bergen St, Brooklyn\", {\n align: \"center\",\n paddingBottom: 16,\n }),\n button(\"RSVP — free\", \"#\"),\n spacer(24),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n mod(\"content.agenda\", \"Agenda\", [\n divider({ paddingTop: 16, paddingBottom: 16 }),\n eyebrowText(\"AGENDA HIGHLIGHTS\"),\n agendaRow(\"9:30\", \"Opening keynote — Maya Chen, Acme\"),\n agendaRow(\"11:00\", \"Workshop: shipping AI features users actually want\"),\n agendaRow(\"13:00\", \"Lunch + open conversations\"),\n agendaRow(\"15:30\", \"Panel: building durable companies\"),\n agendaRow(\"18:00\", \"Rooftop after-party\"),\n spacer(16),\n ]),\n mod(\n \"footer.simple\",\n \"Footer\",\n [\n muted(\"Acme, Inc · 100 Market St · San Francisco, CA\", {\n align: \"center\",\n paddingTop: 16,\n }),\n muted(\"Update preferences · Unsubscribe\", {\n align: \"center\",\n paddingTop: 4,\n paddingBottom: 24,\n link: \"#\",\n }),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n ],\n }),\n};\n\nfunction eyebrowText(s: string) {\n return text(s, {\n fontFamily: \"{fonts.button}\",\n color: \"{colors.muted}\",\n fontSize: 11,\n fontWeight: \"bold\",\n letterSpacing: 3,\n paddingBottom: 12,\n });\n}\n\nfunction agendaRow(time: string, label: string) {\n return text(`<b>${time}</b> · ${label}`, {\n paddingTop: 6,\n paddingBottom: 6,\n });\n}\n\ntemplateRegistry.register(def);\nexport default def;\n","import type { EmailDocument } from \"../core/types\";\nimport { templateRegistry, type TemplateDefinition } from \"./registry\";\nimport { minimalSaaS } from \"../themes/defaultThemes\";\nimport {\n mod,\n text,\n spacer,\n button,\n divider,\n heading,\n muted,\n} from \"../modules/helpers\";\n\nconst def: TemplateDefinition = {\n id: \"order-receipt\",\n name: \"Order Receipt\",\n category: \"transactional\",\n description:\n \"Transactional order confirmation with order number, an itemized table, totals, shipping address and a help footer.\",\n tags: [\"transactional\", \"receipt\", \"order\", \"confirmation\"],\n thumbnail: \"https://placehold.co/600x800/F4F5F7/0F172A?text=Order+%23A12345\",\n build: (): EmailDocument => ({\n version: \"1.0\",\n meta: {\n name: \"Your order #A12345 is confirmed\",\n previewText: \"Thanks for your order! Here's your receipt.\",\n },\n theme: minimalSaaS,\n settings: {\n width: 600,\n backgroundColor: \"{colors.background}\",\n contentBackgroundColor: \"{colors.surface}\",\n },\n modules: [\n mod(\"header.logo\", \"Logo\", [\n text(\"ACME\", {\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 22,\n fontWeight: \"bold\",\n letterSpacing: 4,\n paddingTop: 24,\n paddingBottom: 24,\n }),\n ]),\n mod(\"hero.confirmation\", \"Confirmation\", [\n heading(\"Thanks, your order is confirmed\", {\n align: \"center\",\n fontSize: 26,\n paddingTop: 8,\n paddingBottom: 4,\n }),\n muted(\"Order #A12345 · placed April 30, 2026\", {\n align: \"center\",\n paddingBottom: 24,\n }),\n ]),\n mod(\"tx.items\", \"Items\", [\n text(\"ITEMS\", {\n fontSize: 11,\n letterSpacing: 3,\n fontWeight: \"bold\",\n color: \"{colors.muted}\",\n paddingTop: 8,\n paddingBottom: 12,\n }),\n text(\"Linen Tote Bag · Natural · Qty 1\", {\n fontWeight: \"bold\",\n paddingBottom: 4,\n }),\n muted(\"$39.00\", { paddingBottom: 12 }),\n divider({ paddingTop: 4, paddingBottom: 4 }),\n text(\"Ceramic Mug · Sand · Qty 2\", { fontWeight: \"bold\", paddingBottom: 4 }),\n muted(\"$48.00\", { paddingBottom: 16 }),\n divider({ paddingTop: 8, paddingBottom: 12 }),\n text(\"Subtotal · $87.00\", { align: \"right\", paddingBottom: 4 }),\n text(\"Shipping · $9.00\", { align: \"right\", paddingBottom: 4 }),\n text(\"<b>Total · $96.00</b>\", {\n align: \"right\",\n fontSize: 18,\n paddingBottom: 16,\n }),\n ]),\n mod(\n \"tx.shipping\",\n \"Shipping address\",\n [\n text(\"SHIPPING TO\", {\n fontSize: 11,\n letterSpacing: 3,\n fontWeight: \"bold\",\n color: \"{colors.muted}\",\n paddingTop: 16,\n paddingBottom: 8,\n }),\n text(\"Alex Rada<br/>350 Madison Ave<br/>New York, NY 10017\", {\n paddingBottom: 16,\n }),\n button(\"Track shipment\", \"#\"),\n spacer(16),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n mod(\n \"footer.help\",\n \"Help\",\n [\n muted(\"Questions about your order? help@acme.shop\", {\n align: \"center\",\n paddingTop: 16,\n }),\n muted(\"© 2026 Acme · Privacy\", {\n align: \"center\",\n paddingTop: 4,\n paddingBottom: 24,\n link: \"#\",\n }),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n ],\n }),\n};\n\ntemplateRegistry.register(def);\nexport default def;\n","import type { EmailDocument } from \"../core/types\";\nimport { templateRegistry, type TemplateDefinition } from \"./registry\";\nimport { newsletterEditorial } from \"../themes/defaultThemes\";\nimport {\n mod,\n text,\n spacer,\n image,\n divider,\n heading,\n muted,\n PLACEHOLDER,\n} from \"../modules/helpers\";\n\nconst def: TemplateDefinition = {\n id: \"blog-digest\",\n name: \"Blog / Publishing Digest\",\n category: \"publishing\",\n description:\n \"Editorial digest of three blog posts: each with a thumbnail, title, dek and read-link. Best for media and creators.\",\n tags: [\"blog\", \"digest\", \"publishing\", \"media\"],\n thumbnail: \"https://placehold.co/600x800/FAFAF9/111827?text=Blog+Digest\",\n build: (): EmailDocument => ({\n version: \"1.0\",\n meta: {\n name: \"This week on the blog\",\n previewText: \"Three new pieces — including our deep dive on micro-SaaS in 2026.\",\n },\n theme: newsletterEditorial,\n settings: {\n width: 600,\n backgroundColor: \"{colors.background}\",\n contentBackgroundColor: \"{colors.surface}\",\n },\n modules: [\n mod(\"header.publication\", \"Publication header\", [\n text(\"THE LEDGER\", {\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 22,\n fontWeight: \"bold\",\n letterSpacing: 6,\n paddingTop: 32,\n paddingBottom: 4,\n }),\n muted(\"Notes on building, weekly\", { align: \"center\", paddingBottom: 24 }),\n divider({ paddingTop: 0, paddingBottom: 0 }),\n ]),\n post(\n \"Micro-SaaS in 2026: smaller, sharper, more profitable\",\n \"Why the next wave of indie founders is winning by going narrower than you think.\",\n \"Maya Chen · 8 min read\",\n PLACEHOLDER(560, 280, \"Post+1\")\n ),\n post(\n \"Stop A/B testing your homepage\",\n \"An evidence-based case for spending that energy on your activation flow instead.\",\n \"Jordan Lee · 6 min read\",\n PLACEHOLDER(560, 280, \"Post+2\")\n ),\n post(\n \"The five-line founder check-in\",\n \"A weekly journaling pattern that keeps the team aligned and the founder sane.\",\n \"Sam Park · 4 min read\",\n PLACEHOLDER(560, 280, \"Post+3\")\n ),\n mod(\n \"footer.simple\",\n \"Footer\",\n [\n muted(\"The Ledger · Published Tuesdays\", {\n align: \"center\",\n paddingTop: 16,\n }),\n muted(\"© 2026 · Manage subscription · Unsubscribe\", {\n align: \"center\",\n paddingTop: 4,\n paddingBottom: 24,\n link: \"#\",\n }),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n ],\n }),\n};\n\nfunction post(title: string, dek: string, byline: string, img: string) {\n return mod(\"content.post\", \"Post\", [\n image(img, title, { width: 560, paddingTop: 24, paddingBottom: 16 }),\n heading(title, { fontSize: 24, paddingBottom: 8 }),\n text(dek, { paddingBottom: 8 }),\n muted(byline, { paddingBottom: 4 }),\n text(\"Read the full post →\", {\n color: \"{colors.primary}\",\n fontWeight: \"bold\",\n link: \"#\",\n paddingTop: 4,\n paddingBottom: 8,\n }),\n spacer(8),\n ]);\n}\n\ntemplateRegistry.register(def);\nexport default def;\n","import { useEffect, useMemo, useState } from \"react\";\nimport { X, Search } from \"lucide-react\";\nimport { useEmailStore } from \"../store/emailStore\";\nimport {\n templateRegistry,\n TEMPLATE_CATEGORY_LABELS,\n type TemplateCategory,\n type TemplateDefinition,\n} from \"../templates\";\n\ninterface Props {\n open: boolean;\n onClose: () => void;\n}\n\nexport function TemplatesModal({ open, onClose }: Props) {\n const loadTemplate = useEmailStore((s) => s.loadTemplate);\n const hasContent = useEmailStore((s) => s.doc.modules.length > 0);\n\n const [category, setCategory] = useState<TemplateCategory | \"all\">(\"all\");\n const [query, setQuery] = useState(\"\");\n\n useEffect(() => {\n if (!open) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [open, onClose]);\n\n const all = useMemo(() => templateRegistry.list(), [open]);\n\n const filtered = useMemo(() => {\n let list = all;\n if (category !== \"all\") list = list.filter((t) => t.category === category);\n if (query.trim()) {\n const q = query.toLowerCase();\n list = list.filter(\n (t) =>\n t.name.toLowerCase().includes(q) ||\n t.description.toLowerCase().includes(q) ||\n (t.tags ?? []).some((tag) => tag.toLowerCase().includes(q))\n );\n }\n return list;\n }, [all, category, query]);\n\n if (!open) return null;\n\n const handlePick = (def: TemplateDefinition) => {\n if (\n hasContent &&\n !window.confirm(\n `Loading \"${def.name}\" will replace your current email. Continue?`\n )\n ) {\n return;\n }\n loadTemplate(def);\n onClose();\n };\n\n const categories: Array<{ key: TemplateCategory | \"all\"; label: string }> = [\n { key: \"all\", label: \"All templates\" },\n ...(Object.entries(TEMPLATE_CATEGORY_LABELS) as Array<\n [TemplateCategory, string]\n >).map(([key, label]) => ({ key, label })),\n ];\n\n return (\n <div className=\"fixed inset-0 z-50 flex bg-black/60 backdrop-blur-sm\">\n <div className=\"m-auto flex h-[92vh] w-[96vw] max-w-350 flex-col overflow-hidden rounded-2xl bg-white shadow-2xl\">\n {/* Header */}\n <div className=\"flex items-center justify-between border-b border-neutral-200 px-6 py-4\">\n <div>\n <h2 className=\"text-lg font-semibold text-neutral-900\">\n Start from a template\n </h2>\n <p className=\"text-sm text-neutral-500\">\n Pick a fully-built email and tweak from there.\n </p>\n </div>\n <button\n onClick={onClose}\n className=\"rounded-lg p-2 text-neutral-500 hover:bg-neutral-100 hover:text-neutral-900\"\n aria-label=\"Close\"\n >\n <X size={20} />\n </button>\n </div>\n\n <div className=\"flex flex-1 overflow-hidden\">\n {/* Sidebar */}\n <aside className=\"w-56 shrink-0 overflow-y-auto border-r border-neutral-200 bg-neutral-50 p-3\">\n <div className=\"relative mb-3\">\n <Search\n size={14}\n className=\"pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-neutral-400\"\n />\n <input\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder=\"Search…\"\n className=\"w-full rounded-md border border-neutral-200 bg-white py-1.5 pl-7 pr-2 text-sm outline-none focus:border-neutral-400\"\n />\n </div>\n <ul className=\"space-y-0.5\">\n {categories.map((c) => {\n const active = c.key === category;\n return (\n <li key={c.key}>\n <button\n onClick={() => setCategory(c.key)}\n className={\n \"block w-full rounded-md px-2.5 py-1.5 text-left text-sm transition \" +\n (active\n ? \"bg-neutral-900 text-white\"\n : \"text-neutral-700 hover:bg-neutral-200\")\n }\n >\n {c.label}\n </button>\n </li>\n );\n })}\n </ul>\n </aside>\n\n {/* Grid */}\n <main className=\"flex-1 overflow-y-auto p-6\">\n {filtered.length === 0 ? (\n <div className=\"grid h-full place-items-center text-sm text-neutral-500\">\n No templates match.\n </div>\n ) : (\n <div className=\"grid grid-cols-2 gap-5 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5\">\n {filtered.map((t) => (\n <TemplateCard\n key={t.id}\n def={t}\n onPick={() => handlePick(t)}\n />\n ))}\n </div>\n )}\n </main>\n </div>\n </div>\n </div>\n );\n}\n\nfunction TemplateCard({\n def,\n onPick,\n}: {\n def: TemplateDefinition;\n onPick: () => void;\n}) {\n return (\n <button\n onClick={onPick}\n className=\"group flex flex-col overflow-hidden rounded-xl border border-neutral-200 bg-white text-left transition hover:-translate-y-0.5 hover:border-neutral-400 hover:shadow-lg\"\n >\n <div className=\"aspect-3/4 w-full overflow-hidden bg-neutral-100\">\n {def.thumbnail ? (\n <img\n src={def.thumbnail}\n alt={def.name}\n className=\"h-full w-full object-cover transition group-hover:scale-[1.02]\"\n />\n ) : (\n <div className=\"grid h-full place-items-center text-xs text-neutral-400\">\n No preview\n </div>\n )}\n </div>\n <div className=\"flex flex-col gap-1 p-3\">\n <div className=\"text-xs uppercase tracking-wider text-neutral-500\">\n {TEMPLATE_CATEGORY_LABELS[def.category]}\n </div>\n <div className=\"line-clamp-1 text-sm font-semibold text-neutral-900\">\n {def.name}\n </div>\n <div className=\"line-clamp-2 text-xs text-neutral-500\">\n {def.description}\n </div>\n </div>\n </button>\n );\n}\n","import { useEmailStore } from \"../store/emailStore\";\nimport { Undo2, Redo2, Save, Download, Upload, Eye, FileCode, Monitor, Smartphone, LayoutTemplate, RotateCcw } from \"lucide-react\";\nimport { useRef, useState } from \"react\";\nimport { TemplatesModal } from \"./TemplatesModal\";\n\nexport function TopBar() {\n const { doc, updateMeta, undo, redo, past, future, exportJson, importJson, exportHtml, saveToLocalStorage, viewMode, setViewMode, resetDocument } =\n useEmailStore();\n const fileRef = useRef<HTMLInputElement>(null);\n const [previewing, setPreviewing] = useState(false);\n const [templatesOpen, setTemplatesOpen] = useState(false);\n\n const handleReset = () => {\n if (doc.modules.length === 0) return;\n if (window.confirm(\"Reset the editor? Your current email will be cleared.\")) {\n resetDocument();\n }\n };\n\n const downloadFile = (filename: string, content: string, type: string) => {\n const blob = new Blob([content], { type });\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = filename;\n a.click();\n URL.revokeObjectURL(url);\n };\n\n const handleExportHtml = () => {\n const html = exportHtml();\n downloadFile(`${doc.meta.name || \"email\"}.html`, html, \"text/html\");\n };\n\n const handleExportJson = () => {\n downloadFile(`${doc.meta.name || \"email\"}.json`, exportJson(), \"application/json\");\n };\n\n const handleImport = (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n file.text().then((text) => {\n const r = importJson(text);\n if (!r.ok) alert(`Import failed: ${r.error}`);\n });\n e.target.value = \"\";\n };\n\n const handlePreview = () => {\n const html = exportHtml();\n const w = window.open(\"\", \"_blank\");\n if (w) {\n w.document.write(html);\n w.document.close();\n }\n setPreviewing(true);\n setTimeout(() => setPreviewing(false), 600);\n };\n\n return (\n <div className=\"flex items-center gap-2 h-12 px-4 bg-white border-b border-gray-200 shrink-0\">\n <input\n className=\"font-medium text-sm px-2 py-1 rounded hover:bg-gray-50 focus:bg-gray-50 outline-none w-64\"\n value={doc.meta.name}\n onChange={(e) => updateMeta({ name: e.target.value })}\n />\n <div className=\"ml-auto flex items-center gap-1\">\n <div className=\"inline-flex items-center bg-gray-100 rounded p-0.5 mr-2\">\n <button\n title=\"Desktop preview\"\n onClick={() => setViewMode(\"desktop\")}\n className={`flex items-center gap-1 px-2 py-1 rounded text-xs transition-colors ${\n viewMode === \"desktop\" ? \"bg-white shadow text-gray-900\" : \"text-gray-500 hover:text-gray-700\"\n }`}\n >\n <Monitor size={14} /> Desktop\n </button>\n <button\n title=\"Mobile preview\"\n onClick={() => setViewMode(\"mobile\")}\n className={`flex items-center gap-1 px-2 py-1 rounded text-xs transition-colors ${\n viewMode === \"mobile\" ? \"bg-white shadow text-gray-900\" : \"text-gray-500 hover:text-gray-700\"\n }`}\n >\n <Smartphone size={14} /> Mobile\n </button>\n </div>\n <ToolButton title=\"Browse templates\" onClick={() => setTemplatesOpen(true)}>\n <LayoutTemplate size={16} /> Templates\n </ToolButton>\n <ToolButton title=\"Reset editor\" onClick={handleReset} disabled={doc.modules.length === 0}>\n <RotateCcw size={16} /> Reset\n </ToolButton>\n <Divider />\n <ToolButton title=\"Undo\" onClick={undo} disabled={past.length === 0}>\n <Undo2 size={16} />\n </ToolButton>\n <ToolButton title=\"Redo\" onClick={redo} disabled={future.length === 0}>\n <Redo2 size={16} />\n </ToolButton>\n <Divider />\n <ToolButton title=\"Save draft (local)\" onClick={saveToLocalStorage}>\n <Save size={16} />\n </ToolButton>\n <ToolButton title=\"Preview\" onClick={handlePreview}>\n <Eye size={16} /> {previewing ? \"Opened\" : \"Preview\"}\n </ToolButton>\n <Divider />\n <ToolButton title=\"Import JSON\" onClick={() => fileRef.current?.click()}>\n <Upload size={16} /> Import\n </ToolButton>\n <input ref={fileRef} type=\"file\" accept=\".json\" hidden onChange={handleImport} />\n <ToolButton title=\"Export JSON\" onClick={handleExportJson}>\n <Download size={16} /> JSON\n </ToolButton>\n <ToolButton title=\"Export HTML\" onClick={handleExportHtml} primary>\n <FileCode size={16} /> Export HTML\n </ToolButton>\n </div>\n <TemplatesModal open={templatesOpen} onClose={() => setTemplatesOpen(false)} />\n </div>\n );\n}\n\nfunction ToolButton({\n children,\n onClick,\n disabled,\n title,\n primary,\n}: {\n children: React.ReactNode;\n onClick?: () => void;\n disabled?: boolean;\n title?: string;\n primary?: boolean;\n}) {\n return (\n <button\n title={title}\n disabled={disabled}\n onClick={onClick}\n className={`flex items-center gap-1.5 px-2.5 py-1.5 rounded text-sm transition-colors ${\n primary\n ? \"bg-blue-600 text-white hover:bg-blue-700 disabled:bg-gray-300\"\n : \"text-gray-700 hover:bg-gray-100 disabled:text-gray-300 disabled:hover:bg-transparent\"\n }`}\n >\n {children}\n </button>\n );\n}\n\nfunction Divider() {\n return <div className=\"w-px h-5 bg-gray-200 mx-1\" />;\n}\n","import type { EmailModule } from \"../core/types\";\n\nexport type ModuleCategory =\n | \"basic\"\n | \"menu\"\n | \"header\"\n | \"content\"\n | \"feature\"\n | \"call_to_action\"\n | \"ecommerce\"\n | \"transactional\"\n | \"social\"\n | \"footer\";\n\nexport interface ModuleDefinition {\n type: string;\n category: ModuleCategory;\n name: string;\n /** Human + AI readable summary of the module's structure, intent and content slots. Used by AI to choose modules when assembling templates. */\n description: string;\n /** Free-form tags to help AI semantic search: e.g. [\"product\", \"grid\", \"ecommerce\", \"3-column\"]. */\n tags?: string[];\n thumbnail?: string;\n /** Returns a fresh module JSON with new ids. */\n create: () => EmailModule;\n}\n\nclass ModuleRegistry {\n private modules = new Map<string, ModuleDefinition>();\n\n register(def: ModuleDefinition) {\n this.modules.set(def.type, def);\n }\n\n get(type: string): ModuleDefinition | undefined {\n return this.modules.get(type);\n }\n\n list(): ModuleDefinition[] {\n return Array.from(this.modules.values());\n }\n\n byCategory(category: ModuleCategory): ModuleDefinition[] {\n return this.list().filter((m) => m.category === category);\n }\n}\n\nexport const moduleRegistry = new ModuleRegistry();\n\nexport const CATEGORY_LABELS: Record<ModuleCategory, string> = {\n basic: \"Basic\",\n menu: \"Menu\",\n header: \"Header\",\n content: \"Content\",\n feature: \"Feature\",\n call_to_action: \"Call to Action\",\n ecommerce: \"Ecommerce\",\n transactional: \"Transactional\",\n social: \"Social\",\n footer: \"Footer\",\n};\n","// Gallery registry.\n//\n// A \"gallery\" is a named collection of extra, ready-to-drop modules (\"styles\"\n// or new elements) that embedders can add on top of the built-in modules.\n// Gallery items are grouped by the same `ModuleCategory` as regular modules\n// and are surfaced at the TOP of each category panel in the left sidebar, so\n// freshly loaded elements are always the first thing a user sees.\n//\n// Unlike `moduleRegistry`, this registry is reactive: the sidebar subscribes to\n// it so galleries can be loaded dynamically at runtime (e.g. fetched from a\n// backend) and appear without a manual refresh.\n\nimport type { ModuleDefinition, ModuleCategory } from \"../modules/registry\";\n\n/**\n * A single gallery entry. It is a normal {@link ModuleDefinition} (so it can be\n * dropped into the canvas exactly like a built-in module) plus bookkeeping that\n * ties it back to the gallery it came from.\n */\nexport interface GalleryItem extends ModuleDefinition {\n /** Id of the {@link GalleryDefinition} this item belongs to. */\n galleryId: string;\n /** Optional short label shown as a badge (defaults to \"New\"). */\n badge?: string;\n}\n\n/**\n * A gallery: a themed pack of modules spanning one or more categories.\n * Register whole galleries via {@link galleryRegistry.registerGallery} or the\n * `galleryPlugin()` factory.\n */\nexport interface GalleryDefinition {\n id: string;\n name: string;\n description?: string;\n /** Modules provided by this gallery (any category). */\n items: ModuleDefinition[];\n /** Badge shown on every item of this gallery (defaults to \"New\"). */\n badge?: string;\n}\n\ntype Listener = () => void;\n\nclass GalleryRegistry {\n private galleries = new Map<string, GalleryDefinition>();\n /** Insertion-ordered items so \"newest on top\" is deterministic. */\n private items: GalleryItem[] = [];\n private listeners = new Set<Listener>();\n private version = 0;\n\n /** Register (or replace) a whole gallery. Safe to call at runtime. */\n registerGallery(def: GalleryDefinition) {\n // Replacing an existing gallery id first removes its previous items.\n if (this.galleries.has(def.id)) this.removeGallery(def.id, false);\n this.galleries.set(def.id, def);\n for (const item of def.items) {\n this.items.push({ ...item, galleryId: def.id, badge: def.badge });\n }\n this.emit();\n }\n\n /** Register a single item into a gallery (creating the gallery if needed). */\n registerItem(galleryId: string, item: ModuleDefinition, badge?: string) {\n if (!this.galleries.has(galleryId)) {\n this.galleries.set(galleryId, { id: galleryId, name: galleryId, items: [] });\n }\n const gallery = this.galleries.get(galleryId)!;\n gallery.items.push(item);\n this.items.push({ ...item, galleryId, badge: badge ?? gallery.badge });\n this.emit();\n }\n\n /** Remove a gallery and all of its items. */\n removeGallery(galleryId: string, emit = true) {\n this.galleries.delete(galleryId);\n this.items = this.items.filter((i) => i.galleryId !== galleryId);\n if (emit) this.emit();\n }\n\n /** Every gallery item, newest galleries last (kept in insertion order). */\n list(): GalleryItem[] {\n return this.items;\n }\n\n /** Gallery items for a single category (top-of-list candidates). */\n byCategory(category: ModuleCategory): GalleryItem[] {\n return this.items.filter((i) => i.category === category);\n }\n\n /** Registered galleries (metadata only). */\n listGalleries(): GalleryDefinition[] {\n return Array.from(this.galleries.values());\n }\n\n /** Look up a gallery item by module type. */\n get(type: string): GalleryItem | undefined {\n return this.items.find((i) => i.type === type);\n }\n\n // ---- Reactive subscription (for React `useSyncExternalStore`) ----\n\n subscribe = (listener: Listener): (() => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n /** Monotonic version; changes whenever the gallery set changes. */\n getSnapshot = (): number => this.version;\n\n private emit() {\n this.version += 1;\n for (const l of this.listeners) l();\n }\n}\n\nexport const galleryRegistry = new GalleryRegistry();\n","// Reactive holder for the configured AI provider.\n//\n// The editor's AI chat panel only appears when a provider has been wired up\n// (via the `aiProvider` prop, the `aiAssistantPlugin`, or `builder.setAIProvider`).\n// Because providers are configured imperatively, this small reactive store lets\n// React components show/hide the panel the moment a provider is (un)set.\n\nimport type { AIProvider } from \"../core/aiActions\";\n\ntype Listener = () => void;\n\nlet provider: AIProvider | null = null;\nconst listeners = new Set<Listener>();\nlet version = 0;\n\nfunction emit() {\n version += 1;\n for (const l of listeners) l();\n}\n\n/** Set (or clear) the active AI provider. Notifies subscribers. */\nexport function setAIProvider(next: AIProvider | null) {\n if (provider === next) return;\n provider = next;\n emit();\n}\n\n/** The active AI provider, or null when AI is not configured. */\nexport function getAIProvider(): AIProvider | null {\n return provider;\n}\n\n/** Subscribe to provider changes (for `useSyncExternalStore`). */\nexport const subscribeAIProvider = (listener: Listener): (() => void) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n};\n\n/** Monotonic version; changes whenever the provider is set or cleared. */\nexport const getAIProviderVersion = (): number => version;\n","// Module catalog for the AI backend.\n//\n// The backend must only ever produce modules the editor can actually render.\n// To guarantee that, the client sends a *catalog* of every available module —\n// built-in modules AND gallery items — including one concrete `sample` of each\n// module's JSON. The model picks module `type`s from this catalog and the\n// backend assembles the email from the real samples, so the output is always\n// valid and visible.\n\nimport type { EmailModule } from \"../core/types\";\nimport { moduleRegistry } from \"../modules/registry\";\nimport { galleryRegistry } from \"../gallery/registry\";\n\nexport interface CatalogEntry {\n type: string;\n category: string;\n name: string;\n description: string;\n tags: string[];\n /** Whether the module comes from a gallery (vs a built-in pack). */\n source: \"module\" | \"gallery\";\n /** A concrete, renderable instance of the module (ids included). */\n sample: EmailModule;\n}\n\n/**\n * Build the catalog sent to the AI backend. Gallery items are listed first so\n * the model is nudged to prefer freshly added styles, mirroring the sidebar.\n */\nexport function buildCatalog(): CatalogEntry[] {\n const galleryEntries: CatalogEntry[] = galleryRegistry.list().map((def) => ({\n type: def.type,\n category: def.category,\n name: def.name,\n description: def.description,\n tags: def.tags ?? [],\n source: \"gallery\",\n sample: def.create(),\n }));\n\n const galleryTypes = new Set(galleryEntries.map((e) => e.type));\n\n const moduleEntries: CatalogEntry[] = moduleRegistry\n .list()\n .filter((def) => !galleryTypes.has(def.type))\n .map((def) => ({\n type: def.type,\n category: def.category,\n name: def.name,\n description: def.description,\n tags: def.tags ?? [],\n source: \"module\",\n sample: def.create(),\n }));\n\n return [...galleryEntries, ...moduleEntries];\n}\n","// AI action interface. AI must edit JSON, not HTML.\nimport type { EmailDocument, EmailModule, Theme } from \"../core/types\";\nimport { documentSchema } from \"../core/validation\";\n\nexport type AIAction =\n | { type: \"update_meta\"; patch: Partial<EmailDocument[\"meta\"]> }\n | { type: \"update_settings\"; patch: Partial<EmailDocument[\"settings\"]> }\n | { type: \"apply_theme\"; theme: Theme }\n | { type: \"insert_module\"; index?: number; module: EmailModule }\n | { type: \"delete_module\"; moduleId: string }\n | { type: \"update_module\"; moduleId: string; patch: Partial<EmailModule> }\n | {\n type: \"update_element\";\n moduleId: string;\n elementId: string;\n patch: Record<string, unknown>;\n };\n\nexport interface AIRequest {\n task:\n | \"create_email\"\n | \"rewrite_text\"\n | \"generate_subject\"\n | \"generate_preview\"\n | \"translate\"\n | \"adapt_tone\"\n | \"apply_theme\";\n document?: EmailDocument;\n instruction?: string;\n context?: Record<string, unknown>;\n}\n\nexport interface AIResponse {\n actions?: AIAction[];\n document?: EmailDocument;\n text?: string;\n}\n\nexport interface AIProvider {\n generate(req: AIRequest): Promise<AIResponse>;\n}\n\nexport function applyAIActions(\n doc: EmailDocument,\n actions: AIAction[]\n): EmailDocument {\n let next = doc;\n for (const a of actions) {\n next = applyAIAction(next, a);\n }\n return next;\n}\n\nfunction applyAIAction(doc: EmailDocument, action: AIAction): EmailDocument {\n switch (action.type) {\n case \"update_meta\":\n return { ...doc, meta: { ...doc.meta, ...action.patch } };\n case \"update_settings\":\n return { ...doc, settings: { ...doc.settings, ...action.patch } };\n case \"apply_theme\":\n return { ...doc, theme: action.theme };\n case \"insert_module\": {\n const idx = action.index ?? doc.modules.length;\n const modules = [...doc.modules];\n modules.splice(idx, 0, action.module);\n return { ...doc, modules };\n }\n case \"delete_module\":\n return { ...doc, modules: doc.modules.filter((m) => m.id !== action.moduleId) };\n case \"update_module\":\n return {\n ...doc,\n modules: doc.modules.map((m) =>\n m.id === action.moduleId ? { ...m, ...action.patch } : m\n ),\n };\n case \"update_element\":\n return {\n ...doc,\n modules: doc.modules.map((m) => {\n if (m.id !== action.moduleId) return m;\n return {\n ...m,\n children: m.children.map((c) =>\n c.id === action.elementId ? ({ ...c, ...action.patch } as typeof c) : c\n ),\n };\n }),\n };\n }\n}\n\n/** Validate an AI-returned document before applying. */\nexport function validateAIDocument(doc: unknown):\n | { ok: true; document: EmailDocument }\n | { ok: false; error: string } {\n const result = documentSchema.safeParse(doc);\n if (result.success) return { ok: true, document: result.data as EmailDocument };\n return { ok: false, error: result.error.message };\n}\n\n/** Mock AI provider for demos and tests. Returns deterministic patches. */\nexport const mockAIProvider: AIProvider = {\n async generate(req) {\n if (req.task === \"rewrite_text\" && req.instruction) {\n return { text: `[AI rewrite] ${req.instruction}` };\n }\n if (req.task === \"generate_subject\") {\n return { text: \"Your weekly insight is here ✨\" };\n }\n if (req.task === \"generate_preview\") {\n return { text: \"A short summary that nudges readers to open.\" };\n }\n return { actions: [] };\n },\n};\n","// Safely apply an AI response to the current document.\n//\n// Every AI-produced change is funnelled through here so the editor never trusts\n// raw model output: ids are regenerated to avoid collisions, actions are applied\n// with the existing `applyAIActions` reducer, and the final document is validated\n// with the Zod `documentSchema` before it is handed back to the store.\n\nimport type { EmailDocument, EmailModule } from \"../core/types\";\nimport type { AIAction, AIResponse } from \"../core/aiActions\";\nimport { applyAIActions, validateAIDocument } from \"../core/aiActions\";\nimport { uid } from \"../core/utils\";\n\n/** Drop `undefined`-valued keys anywhere in the document via a JSON round-trip.\n *\n * Module helpers leave optional style fields as `undefined`; those keys survive\n * in-memory but fail Zod validation. Serializing removes them so validation is\n * meaningful and the stored document stays clean. */\nfunction sanitize<T>(value: T): T {\n return JSON.parse(JSON.stringify(value)) as T;\n}\n\n/** Deep-clone a module with fresh ids for the module and all its children. */\nfunction withFreshIds(mod: EmailModule): EmailModule {\n const clone = sanitize(mod);\n return {\n ...clone,\n id: uid(\"module\"),\n children: (clone.children ?? []).map((c) => ({ ...c, id: uid(\"el\") })),\n };\n}\n\n/**\n * Regenerate ids on any module the AI wants to insert. This keeps ids unique\n * even when the backend reuses a catalog `sample` (which ships with stable ids).\n */\nfunction normalizeActions(actions: AIAction[]): AIAction[] {\n return actions.map((a) =>\n a.type === \"insert_module\" ? { ...a, module: withFreshIds(a.module) } : a\n );\n}\n\nexport interface ApplyResult {\n document: EmailDocument;\n /** Assistant chat text, if any. */\n text?: string;\n /** Short human summary of what changed, for the chat log. */\n summary: string;\n}\n\n/**\n * Apply an {@link AIResponse} to `doc`. Returns the next document plus a summary,\n * or an error string when the result fails validation.\n */\nexport function applyAIResponse(\n doc: EmailDocument,\n res: AIResponse\n): { ok: true; result: ApplyResult } | { ok: false; error: string } {\n // 1) A full replacement document takes precedence when present.\n if (res.document) {\n const validated = validateAIDocument(sanitize(res.document));\n if (!validated.ok) return { ok: false, error: validated.error };\n return {\n ok: true,\n result: {\n document: validated.document,\n text: res.text,\n summary: \"Replaced the email with a freshly generated document.\",\n },\n };\n }\n\n // 2) Otherwise apply structured actions.\n if (res.actions && res.actions.length > 0) {\n const next = applyAIActions(doc, normalizeActions(res.actions));\n const validated = validateAIDocument(sanitize(next));\n if (!validated.ok) return { ok: false, error: validated.error };\n return {\n ok: true,\n result: {\n document: validated.document,\n text: res.text,\n summary: summarizeActions(res.actions),\n },\n };\n }\n\n // 3) Text-only response (e.g. rewrite suggestions, subject lines).\n return {\n ok: true,\n result: {\n document: doc,\n text: res.text,\n summary: res.text ? \"\" : \"No changes were suggested.\",\n },\n };\n}\n\nfunction summarizeActions(actions: AIAction[]): string {\n const counts: Record<string, number> = {};\n for (const a of actions) counts[a.type] = (counts[a.type] ?? 0) + 1;\n const label: Record<string, string> = {\n insert_module: \"added block\",\n delete_module: \"removed block\",\n update_module: \"updated block\",\n update_element: \"edited content\",\n update_meta: \"updated meta\",\n update_settings: \"updated settings\",\n apply_theme: \"applied theme\",\n };\n const parts = Object.entries(counts).map(([type, n]) => {\n const base = label[type] ?? type;\n return n > 1 ? `${n} ${base}s` : base;\n });\n return parts.length ? `Applied: ${parts.join(\", \")}.` : \"No changes applied.\";\n}\n","import { useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport { Sparkles, Send, Loader2, AlertTriangle } from \"lucide-react\";\nimport { useEmailStore } from \"../store/emailStore\";\nimport type { AIRequest } from \"../core/aiActions\";\nimport { getAIProvider, subscribeAIProvider, getAIProviderVersion } from \"./state\";\nimport { buildCatalog } from \"./catalog\";\nimport { applyAIResponse } from \"./applyResponse\";\n\ninterface ChatMessage {\n id: string;\n role: \"user\" | \"assistant\";\n text: string;\n error?: boolean;\n}\n\nconst SUGGESTIONS = [\n \"Create a welcome email for new subscribers\",\n \"Build a flash sale announcement with a product grid\",\n \"Write a weekly newsletter with a lead story and footer\",\n];\n\n/** Hook: is an AI provider currently configured? Reactive. */\nexport function useAIAvailable(): boolean {\n // Re-render whenever the provider version changes, then read current state.\n useSyncExternalStore(subscribeAIProvider, getAIProviderVersion, getAIProviderVersion);\n return getAIProvider() !== null;\n}\n\nexport function AIChatPanel() {\n const { doc, applyDoc } = useEmailStore();\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [input, setInput] = useState(\"\");\n const [busy, setBusy] = useState(false);\n const listRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n listRef.current?.scrollTo({ top: listRef.current.scrollHeight });\n }, [messages, busy]);\n\n const send = async (prompt: string) => {\n const provider = getAIProvider();\n if (!provider || !prompt.trim() || busy) return;\n const userMsg: ChatMessage = { id: crypto.randomUUID(), role: \"user\", text: prompt };\n setMessages((m) => [...m, userMsg]);\n setInput(\"\");\n setBusy(true);\n\n const req: AIRequest = {\n task: \"create_email\",\n document: doc,\n instruction: prompt,\n context: { catalog: buildCatalog() },\n };\n\n try {\n const res = await provider.generate(req);\n const applied = applyAIResponse(doc, res);\n if (!applied.ok) {\n pushAssistant(`I produced an invalid document and stopped. (${applied.error})`, true);\n } else {\n const { document, text, summary } = applied.result;\n if (document !== doc) applyDoc(document);\n pushAssistant([text, summary].filter(Boolean).join(\"\\n\\n\") || \"Done.\");\n }\n } catch (err) {\n pushAssistant((err as Error).message || \"The AI request failed.\", true);\n } finally {\n setBusy(false);\n }\n };\n\n const pushAssistant = (text: string, error = false) =>\n setMessages((m) => [...m, { id: crypto.randomUUID(), role: \"assistant\", text, error }]);\n\n return (\n <div className=\"flex flex-col h-full\">\n <div className=\"flex items-center gap-2 mb-2\">\n <Sparkles size={16} className=\"text-blue-600\" />\n <h3 className=\"text-xs font-semibold uppercase tracking-wide text-gray-500\">\n AI Assistant\n </h3>\n </div>\n\n <div ref={listRef} className=\"flex-1 overflow-y-auto pr-1 flex flex-col gap-2\">\n {messages.length === 0 && (\n <div className=\"text-xs text-gray-500\">\n <p className=\"mb-2\">\n Describe the email you want and I'll assemble it from the available blocks.\n </p>\n <div className=\"flex flex-col gap-1.5\">\n {SUGGESTIONS.map((s) => (\n <button\n key={s}\n onClick={() => send(s)}\n className=\"text-left text-xs px-2.5 py-2 rounded border border-gray-200 bg-white hover:border-blue-400 hover:bg-blue-50 transition-colors\"\n >\n {s}\n </button>\n ))}\n </div>\n </div>\n )}\n {messages.map((m) => (\n <div\n key={m.id}\n className={`text-xs rounded-lg px-3 py-2 whitespace-pre-wrap ${\n m.role === \"user\"\n ? \"bg-blue-600 text-white self-end max-w-[85%]\"\n : m.error\n ? \"bg-red-50 text-red-700 border border-red-200 self-start max-w-[95%]\"\n : \"bg-gray-100 text-gray-800 self-start max-w-[95%]\"\n }`}\n >\n {m.error && (\n <AlertTriangle size={12} className=\"inline mr-1 -mt-0.5\" aria-hidden />\n )}\n {m.text}\n </div>\n ))}\n {busy && (\n <div className=\"text-xs text-gray-500 flex items-center gap-1.5 self-start\">\n <Loader2 size={12} className=\"animate-spin\" /> Thinking…\n </div>\n )}\n </div>\n\n <form\n className=\"mt-2 flex items-end gap-1.5\"\n onSubmit={(e) => {\n e.preventDefault();\n send(input);\n }}\n >\n <textarea\n value={input}\n onChange={(e) => setInput(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n send(input);\n }\n }}\n rows={2}\n placeholder=\"Ask the AI to build or edit your email…\"\n className=\"flex-1 resize-none text-xs rounded border border-gray-300 px-2 py-1.5 outline-none focus:border-blue-500\"\n />\n <button\n type=\"submit\"\n disabled={busy || !input.trim()}\n title=\"Send\"\n className=\"p-2 rounded bg-blue-600 text-white hover:bg-blue-700 disabled:bg-gray-300\"\n >\n {busy ? <Loader2 size={14} className=\"animate-spin\" /> : <Send size={14} />}\n </button>\n </form>\n </div>\n );\n}\n","import { useState, useSyncExternalStore } from \"react\";\nimport { useEmailStore } from \"../store/emailStore\";\nimport { moduleRegistry, CATEGORY_LABELS, type ModuleCategory } from \"../modules/registry\";\nimport { galleryRegistry, type GalleryItem } from \"../gallery/registry\";\nimport type { EmailModule } from \"../core/types\";\nimport { AIChatPanel, useAIAvailable } from \"../ai/AIChatPanel\";\nimport {\n Square,\n Menu,\n LayoutTemplate,\n Type,\n Star,\n MousePointerClick,\n ShoppingCart,\n Receipt,\n Share2,\n AlignVerticalJustifyEnd,\n Palette,\n Layers,\n Images,\n Sparkles,\n ArrowUp,\n ArrowDown,\n Trash2,\n Copy,\n} from \"lucide-react\";\n\nconst CATEGORIES: { id: ModuleCategory; icon: React.ComponentType<{ size?: number }> }[] = [\n { id: \"basic\", icon: Square },\n { id: \"menu\", icon: Menu },\n { id: \"header\", icon: LayoutTemplate },\n { id: \"content\", icon: Type },\n { id: \"feature\", icon: Star },\n { id: \"call_to_action\", icon: MousePointerClick },\n { id: \"ecommerce\", icon: ShoppingCart },\n { id: \"transactional\", icon: Receipt },\n { id: \"social\", icon: Share2 },\n { id: \"footer\", icon: AlignVerticalJustifyEnd },\n];\n\nexport function LeftSidebar() {\n const [active, setActive] = useState<\n ModuleCategory | \"themes\" | \"layers\" | \"gallery\" | \"ai\"\n >(\"layers\");\n const { addModule, themes, applyTheme, doc } = useEmailStore();\n const aiAvailable = useAIAvailable();\n\n // Re-render when galleries are (un)registered at runtime.\n useSyncExternalStore(\n galleryRegistry.subscribe,\n galleryRegistry.getSnapshot,\n galleryRegistry.getSnapshot\n );\n\n const hasGallery = galleryRegistry.list().length > 0;\n\n return (\n <div className=\"flex h-full bg-white border-r border-gray-200 shrink-0\">\n {/* Category rail */}\n <div className=\"w-16 border-r border-gray-200 flex flex-col items-center py-2 gap-1 overflow-y-auto\">\n {aiAvailable && (\n <>\n <RailButton\n id=\"ai\"\n label=\"AI\"\n icon={Sparkles}\n active={active === \"ai\"}\n onClick={() => setActive(\"ai\")}\n accent\n />\n <div className=\"h-px w-10 bg-gray-200 my-1\" />\n </>\n )}\n <RailButton\n id=\"layers\"\n label=\"Layers\"\n icon={Layers}\n active={active === \"layers\"}\n onClick={() => setActive(\"layers\")}\n />\n {hasGallery && (\n <RailButton\n id=\"gallery\"\n label=\"Gallery\"\n icon={Images}\n active={active === \"gallery\"}\n onClick={() => setActive(\"gallery\")}\n />\n )}\n <div className=\"h-px w-10 bg-gray-200 my-1\" />\n {CATEGORIES.map((c) => (\n <RailButton\n key={c.id}\n id={c.id}\n label={CATEGORY_LABELS[c.id]}\n icon={c.icon}\n active={active === c.id}\n onClick={() => setActive(c.id)}\n />\n ))}\n <div className=\"mt-auto\">\n <RailButton\n id=\"themes\"\n label=\"Themes\"\n icon={Palette}\n active={active === \"themes\"}\n onClick={() => setActive(\"themes\")}\n />\n </div>\n </div>\n\n {/* Module list panel */}\n <div className=\"w-64 overflow-y-auto p-3\">\n {active === \"layers\" ? (\n <LayersPanel />\n ) : active === \"ai\" ? (\n <AIChatPanel />\n ) : active === \"gallery\" ? (\n <GalleryPanel onAdd={(item) => addModule(item.create())} />\n ) : active === \"themes\" ? (\n <>\n <h3 className=\"text-xs font-semibold uppercase tracking-wide text-gray-500 mb-3\">\n Themes\n </h3>\n <div className=\"flex flex-col gap-2\">\n {themes.map((t) => {\n const isActive = doc.theme.id === t.id;\n return (\n <button\n key={t.id}\n onClick={() => applyTheme(t)}\n className={`text-left p-3 rounded border transition-colors ${\n isActive\n ? \"border-blue-500 bg-blue-50\"\n : \"border-gray-200 hover:border-gray-300 bg-white\"\n }`}\n >\n <div className=\"flex items-center gap-2 mb-2\">\n <div\n className=\"w-4 h-4 rounded\"\n style={{ background: t.tokens.colors.primary }}\n />\n <div\n className=\"w-4 h-4 rounded border border-gray-200\"\n style={{ background: t.tokens.colors.surface }}\n />\n <div\n className=\"w-4 h-4 rounded\"\n style={{ background: t.tokens.colors.text }}\n />\n </div>\n <div className=\"text-sm font-medium\">{t.name}</div>\n </button>\n );\n })}\n </div>\n </>\n ) : (\n <CategoryPanel category={active} onAdd={(create) => addModule(create())} />\n )}\n </div>\n </div>\n );\n}\n\n// ---------- Category rail button ----------\n\nfunction RailButton({\n label,\n icon: Icon,\n active,\n onClick,\n accent,\n}: {\n id: string;\n label: string;\n icon: React.ComponentType<{ size?: number }>;\n active: boolean;\n onClick: () => void;\n accent?: boolean;\n}) {\n return (\n <button\n onClick={onClick}\n title={label}\n className={`flex flex-col items-center gap-0.5 w-14 py-2 rounded text-[10px] transition-colors ${\n active\n ? \"bg-blue-50 text-blue-700\"\n : accent\n ? \"text-blue-600 hover:bg-blue-50\"\n : \"text-gray-600 hover:bg-gray-50\"\n }`}\n >\n <Icon size={20} />\n <span className=\"leading-tight text-center\">{label}</span>\n </button>\n );\n}\n\n// ---------- Category panel (gallery items on top, then built-ins) ----------\n\nfunction CategoryPanel({\n category,\n onAdd,\n}: {\n category: ModuleCategory;\n onAdd: (create: () => EmailModule) => void;\n}) {\n const galleryItems = galleryRegistry.byCategory(category);\n const modules = moduleRegistry.byCategory(category);\n\n return (\n <>\n <h3 className=\"text-xs font-semibold uppercase tracking-wide text-gray-500 mb-3\">\n {CATEGORY_LABELS[category]}\n </h3>\n <div className=\"grid grid-cols-1 gap-2\">\n {galleryItems.map((item) => (\n <ModuleCard\n key={item.type}\n name={item.name}\n badge={item.badge ?? \"New\"}\n onClick={() => onAdd(item.create)}\n />\n ))}\n {modules.map((def) => (\n <ModuleCard key={def.type} name={def.name} onClick={() => onAdd(def.create)} />\n ))}\n {galleryItems.length === 0 && modules.length === 0 && (\n <div className=\"text-xs text-gray-400 italic py-4 text-center\">\n No modules in this category yet.\n </div>\n )}\n </div>\n </>\n );\n}\n\n// ---------- Gallery panel (all gallery items grouped by category) ----------\n\nfunction GalleryPanel({ onAdd }: { onAdd: (item: GalleryItem) => void }) {\n const galleries = galleryRegistry.listGalleries();\n const items = galleryRegistry.list();\n\n if (items.length === 0) {\n return (\n <>\n <h3 className=\"text-xs font-semibold uppercase tracking-wide text-gray-500 mb-3\">\n Gallery\n </h3>\n <p className=\"text-xs text-gray-400 italic\">No galleries loaded.</p>\n </>\n );\n }\n\n return (\n <>\n <h3 className=\"text-xs font-semibold uppercase tracking-wide text-gray-500 mb-1\">\n Gallery\n </h3>\n <p className=\"text-[10px] text-gray-400 mb-3\">\n {items.length} element{items.length === 1 ? \"\" : \"s\"} across {galleries.length}{\" \"}\n {galleries.length === 1 ? \"gallery\" : \"galleries\"}\n </p>\n <div className=\"flex flex-col gap-4\">\n {galleries.map((g) => {\n const gItems = items.filter((i) => i.galleryId === g.id);\n if (gItems.length === 0) return null;\n return (\n <div key={g.id}>\n <div className=\"text-[11px] font-medium text-gray-600 mb-1.5\">{g.name}</div>\n <div className=\"grid grid-cols-1 gap-2\">\n {gItems.map((item) => (\n <ModuleCard\n key={item.type}\n name={item.name}\n badge={item.badge ?? \"New\"}\n sub={CATEGORY_LABELS[item.category]}\n onClick={() => onAdd(item)}\n />\n ))}\n </div>\n </div>\n );\n })}\n </div>\n </>\n );\n}\n\n// ---------- Shared module card ----------\n\nfunction ModuleCard({\n name,\n onClick,\n badge,\n sub,\n}: {\n name: string;\n onClick: () => void;\n badge?: string;\n sub?: string;\n}) {\n return (\n <button\n onClick={onClick}\n className=\"relative text-left p-3 rounded border border-gray-200 bg-white hover:border-blue-400 hover:shadow-sm transition-all\"\n >\n {badge && (\n <span className=\"absolute top-1.5 right-1.5 text-[9px] font-semibold uppercase tracking-wide bg-blue-100 text-blue-700 px-1.5 py-0.5 rounded\">\n {badge}\n </span>\n )}\n <div className=\"h-12 bg-gray-50 rounded mb-2 flex items-center justify-center text-xs text-gray-400 px-2 text-center\">\n {name}\n </div>\n <div className=\"text-xs font-medium text-gray-700\">{name}</div>\n {sub && <div className=\"text-[10px] text-gray-400\">{sub}</div>}\n </button>\n );\n}\n\n// ---------- Layers (layout overview) panel ----------\n\nfunction LayersPanel() {\n const { doc, selection, setSelection, reorderModules, deleteModule, duplicateModule } =\n useEmailStore();\n\n if (doc.modules.length === 0) {\n return (\n <>\n <h3 className=\"text-xs font-semibold uppercase tracking-wide text-gray-500 mb-3\">\n Layout\n </h3>\n <p className=\"text-xs text-gray-400 italic\">\n No blocks yet. Pick a category from the rail to add modules.\n </p>\n </>\n );\n }\n\n return (\n <>\n <h3 className=\"text-xs font-semibold uppercase tracking-wide text-gray-500 mb-1\">\n Layout\n </h3>\n <p className=\"text-[10px] text-gray-400 mb-3\">\n {doc.modules.length} block{doc.modules.length === 1 ? \"\" : \"s\"} · click to select\n </p>\n <ul className=\"flex flex-col gap-1\">\n {doc.modules.map((m, i) => {\n const active = selection?.kind !== \"email\" && selection?.moduleId === m.id;\n return (\n <li\n key={m.id}\n className={`flex items-center gap-1 rounded border px-2 py-1.5 text-xs cursor-pointer transition-colors ${\n active\n ? \"border-blue-500 bg-blue-50 text-blue-900\"\n : \"border-gray-200 bg-white hover:border-gray-300\"\n }`}\n onClick={() => setSelection({ kind: \"module\", moduleId: m.id })}\n >\n <span className=\"text-[10px] text-gray-400 w-4 shrink-0\">{i + 1}</span>\n <span className=\"flex-1 truncate\">\n {m.name}\n <span className=\"text-[10px] text-gray-400 ml-1\">\n ({m.children.length})\n </span>\n </span>\n <button\n disabled={i === 0}\n onClick={(e) => {\n e.stopPropagation();\n reorderModules(i, i - 1);\n }}\n className=\"p-0.5 text-gray-500 hover:text-blue-600 disabled:opacity-30\"\n title=\"Move up\"\n >\n <ArrowUp size={12} />\n </button>\n <button\n disabled={i === doc.modules.length - 1}\n onClick={(e) => {\n e.stopPropagation();\n reorderModules(i, i + 1);\n }}\n className=\"p-0.5 text-gray-500 hover:text-blue-600 disabled:opacity-30\"\n title=\"Move down\"\n >\n <ArrowDown size={12} />\n </button>\n <button\n onClick={(e) => {\n e.stopPropagation();\n duplicateModule(m.id);\n }}\n className=\"p-0.5 text-gray-500 hover:text-blue-600\"\n title=\"Duplicate\"\n >\n <Copy size={12} />\n </button>\n <button\n onClick={(e) => {\n e.stopPropagation();\n deleteModule(m.id);\n }}\n className=\"p-0.5 text-gray-500 hover:text-red-600\"\n title=\"Delete\"\n >\n <Trash2 size={12} />\n </button>\n </li>\n );\n })}\n </ul>\n </>\n );\n}\n","import { useMemo, useLayoutEffect, useEffect, useRef, useCallback } from 'react';\n\nfunction useCombinedRefs() {\n for (var _len = arguments.length, refs = new Array(_len), _key = 0; _key < _len; _key++) {\n refs[_key] = arguments[_key];\n }\n\n return useMemo(() => node => {\n refs.forEach(ref => ref(node));\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n refs);\n}\n\n// https://github.com/facebook/react/blob/master/packages/shared/ExecutionEnvironment.js\nconst canUseDOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';\n\nfunction isWindow(element) {\n const elementString = Object.prototype.toString.call(element);\n return elementString === '[object Window]' || // In Electron context the Window object serializes to [object global]\n elementString === '[object global]';\n}\n\nfunction isNode(node) {\n return 'nodeType' in node;\n}\n\nfunction getWindow(target) {\n var _target$ownerDocument, _target$ownerDocument2;\n\n if (!target) {\n return window;\n }\n\n if (isWindow(target)) {\n return target;\n }\n\n if (!isNode(target)) {\n return window;\n }\n\n return (_target$ownerDocument = (_target$ownerDocument2 = target.ownerDocument) == null ? void 0 : _target$ownerDocument2.defaultView) != null ? _target$ownerDocument : window;\n}\n\nfunction isDocument(node) {\n const {\n Document\n } = getWindow(node);\n return node instanceof Document;\n}\n\nfunction isHTMLElement(node) {\n if (isWindow(node)) {\n return false;\n }\n\n return node instanceof getWindow(node).HTMLElement;\n}\n\nfunction isSVGElement(node) {\n return node instanceof getWindow(node).SVGElement;\n}\n\nfunction getOwnerDocument(target) {\n if (!target) {\n return document;\n }\n\n if (isWindow(target)) {\n return target.document;\n }\n\n if (!isNode(target)) {\n return document;\n }\n\n if (isDocument(target)) {\n return target;\n }\n\n if (isHTMLElement(target) || isSVGElement(target)) {\n return target.ownerDocument;\n }\n\n return document;\n}\n\n/**\r\n * A hook that resolves to useEffect on the server and useLayoutEffect on the client\r\n * @param callback {function} Callback function that is invoked when the dependencies of the hook change\r\n */\n\nconst useIsomorphicLayoutEffect = canUseDOM ? useLayoutEffect : useEffect;\n\nfunction useEvent(handler) {\n const handlerRef = useRef(handler);\n useIsomorphicLayoutEffect(() => {\n handlerRef.current = handler;\n });\n return useCallback(function () {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n return handlerRef.current == null ? void 0 : handlerRef.current(...args);\n }, []);\n}\n\nfunction useInterval() {\n const intervalRef = useRef(null);\n const set = useCallback((listener, duration) => {\n intervalRef.current = setInterval(listener, duration);\n }, []);\n const clear = useCallback(() => {\n if (intervalRef.current !== null) {\n clearInterval(intervalRef.current);\n intervalRef.current = null;\n }\n }, []);\n return [set, clear];\n}\n\nfunction useLatestValue(value, dependencies) {\n if (dependencies === void 0) {\n dependencies = [value];\n }\n\n const valueRef = useRef(value);\n useIsomorphicLayoutEffect(() => {\n if (valueRef.current !== value) {\n valueRef.current = value;\n }\n }, dependencies);\n return valueRef;\n}\n\nfunction useLazyMemo(callback, dependencies) {\n const valueRef = useRef();\n return useMemo(() => {\n const newValue = callback(valueRef.current);\n valueRef.current = newValue;\n return newValue;\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [...dependencies]);\n}\n\nfunction useNodeRef(onChange) {\n const onChangeHandler = useEvent(onChange);\n const node = useRef(null);\n const setNodeRef = useCallback(element => {\n if (element !== node.current) {\n onChangeHandler == null ? void 0 : onChangeHandler(element, node.current);\n }\n\n node.current = element;\n }, //eslint-disable-next-line\n []);\n return [node, setNodeRef];\n}\n\nfunction usePrevious(value) {\n const ref = useRef();\n useEffect(() => {\n ref.current = value;\n }, [value]);\n return ref.current;\n}\n\nlet ids = {};\nfunction useUniqueId(prefix, value) {\n return useMemo(() => {\n if (value) {\n return value;\n }\n\n const id = ids[prefix] == null ? 0 : ids[prefix] + 1;\n ids[prefix] = id;\n return prefix + \"-\" + id;\n }, [prefix, value]);\n}\n\nfunction createAdjustmentFn(modifier) {\n return function (object) {\n for (var _len = arguments.length, adjustments = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n adjustments[_key - 1] = arguments[_key];\n }\n\n return adjustments.reduce((accumulator, adjustment) => {\n const entries = Object.entries(adjustment);\n\n for (const [key, valueAdjustment] of entries) {\n const value = accumulator[key];\n\n if (value != null) {\n accumulator[key] = value + modifier * valueAdjustment;\n }\n }\n\n return accumulator;\n }, { ...object\n });\n };\n}\n\nconst add = /*#__PURE__*/createAdjustmentFn(1);\nconst subtract = /*#__PURE__*/createAdjustmentFn(-1);\n\nfunction hasViewportRelativeCoordinates(event) {\n return 'clientX' in event && 'clientY' in event;\n}\n\nfunction isKeyboardEvent(event) {\n if (!event) {\n return false;\n }\n\n const {\n KeyboardEvent\n } = getWindow(event.target);\n return KeyboardEvent && event instanceof KeyboardEvent;\n}\n\nfunction isTouchEvent(event) {\n if (!event) {\n return false;\n }\n\n const {\n TouchEvent\n } = getWindow(event.target);\n return TouchEvent && event instanceof TouchEvent;\n}\n\n/**\r\n * Returns the normalized x and y coordinates for mouse and touch events.\r\n */\n\nfunction getEventCoordinates(event) {\n if (isTouchEvent(event)) {\n if (event.touches && event.touches.length) {\n const {\n clientX: x,\n clientY: y\n } = event.touches[0];\n return {\n x,\n y\n };\n } else if (event.changedTouches && event.changedTouches.length) {\n const {\n clientX: x,\n clientY: y\n } = event.changedTouches[0];\n return {\n x,\n y\n };\n }\n }\n\n if (hasViewportRelativeCoordinates(event)) {\n return {\n x: event.clientX,\n y: event.clientY\n };\n }\n\n return null;\n}\n\nconst CSS = /*#__PURE__*/Object.freeze({\n Translate: {\n toString(transform) {\n if (!transform) {\n return;\n }\n\n const {\n x,\n y\n } = transform;\n return \"translate3d(\" + (x ? Math.round(x) : 0) + \"px, \" + (y ? Math.round(y) : 0) + \"px, 0)\";\n }\n\n },\n Scale: {\n toString(transform) {\n if (!transform) {\n return;\n }\n\n const {\n scaleX,\n scaleY\n } = transform;\n return \"scaleX(\" + scaleX + \") scaleY(\" + scaleY + \")\";\n }\n\n },\n Transform: {\n toString(transform) {\n if (!transform) {\n return;\n }\n\n return [CSS.Translate.toString(transform), CSS.Scale.toString(transform)].join(' ');\n }\n\n },\n Transition: {\n toString(_ref) {\n let {\n property,\n duration,\n easing\n } = _ref;\n return property + \" \" + duration + \"ms \" + easing;\n }\n\n }\n});\n\nconst SELECTOR = 'a,frame,iframe,input:not([type=hidden]):not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),*[tabindex]';\nfunction findFirstFocusableNode(element) {\n if (element.matches(SELECTOR)) {\n return element;\n }\n\n return element.querySelector(SELECTOR);\n}\n\nexport { CSS, add, canUseDOM, findFirstFocusableNode, getEventCoordinates, getOwnerDocument, getWindow, hasViewportRelativeCoordinates, isDocument, isHTMLElement, isKeyboardEvent, isNode, isSVGElement, isTouchEvent, isWindow, subtract, useCombinedRefs, useEvent, useInterval, useIsomorphicLayoutEffect, useLatestValue, useLazyMemo, useNodeRef, usePrevious, useUniqueId };\n//# sourceMappingURL=utilities.esm.js.map\n","import React, { useState, useCallback } from 'react';\n\nconst hiddenStyles = {\n display: 'none'\n};\nfunction HiddenText(_ref) {\n let {\n id,\n value\n } = _ref;\n return React.createElement(\"div\", {\n id: id,\n style: hiddenStyles\n }, value);\n}\n\nfunction LiveRegion(_ref) {\n let {\n id,\n announcement,\n ariaLiveType = \"assertive\"\n } = _ref;\n // Hide element visually but keep it readable by screen readers\n const visuallyHidden = {\n position: 'fixed',\n top: 0,\n left: 0,\n width: 1,\n height: 1,\n margin: -1,\n border: 0,\n padding: 0,\n overflow: 'hidden',\n clip: 'rect(0 0 0 0)',\n clipPath: 'inset(100%)',\n whiteSpace: 'nowrap'\n };\n return React.createElement(\"div\", {\n id: id,\n style: visuallyHidden,\n role: \"status\",\n \"aria-live\": ariaLiveType,\n \"aria-atomic\": true\n }, announcement);\n}\n\nfunction useAnnouncement() {\n const [announcement, setAnnouncement] = useState('');\n const announce = useCallback(value => {\n if (value != null) {\n setAnnouncement(value);\n }\n }, []);\n return {\n announce,\n announcement\n };\n}\n\nexport { HiddenText, LiveRegion, useAnnouncement };\n//# sourceMappingURL=accessibility.esm.js.map\n","import React, { createContext, useContext, useEffect, useState, useCallback, useMemo, useRef, memo, useReducer, cloneElement, forwardRef } from 'react';\nimport { createPortal, unstable_batchedUpdates } from 'react-dom';\nimport { useUniqueId, getEventCoordinates, getWindow, isDocument, isHTMLElement, isSVGElement, canUseDOM, isWindow, isNode, getOwnerDocument, add, isKeyboardEvent, subtract, useLazyMemo, useInterval, usePrevious, useLatestValue, useEvent, useIsomorphicLayoutEffect, useNodeRef, findFirstFocusableNode, CSS } from '@dnd-kit/utilities';\nimport { useAnnouncement, HiddenText, LiveRegion } from '@dnd-kit/accessibility';\n\nconst DndMonitorContext = /*#__PURE__*/createContext(null);\n\nfunction useDndMonitor(listener) {\n const registerListener = useContext(DndMonitorContext);\n useEffect(() => {\n if (!registerListener) {\n throw new Error('useDndMonitor must be used within a children of <DndContext>');\n }\n\n const unsubscribe = registerListener(listener);\n return unsubscribe;\n }, [listener, registerListener]);\n}\n\nfunction useDndMonitorProvider() {\n const [listeners] = useState(() => new Set());\n const registerListener = useCallback(listener => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n }, [listeners]);\n const dispatch = useCallback(_ref => {\n let {\n type,\n event\n } = _ref;\n listeners.forEach(listener => {\n var _listener$type;\n\n return (_listener$type = listener[type]) == null ? void 0 : _listener$type.call(listener, event);\n });\n }, [listeners]);\n return [dispatch, registerListener];\n}\n\nconst defaultScreenReaderInstructions = {\n draggable: \"\\n To pick up a draggable item, press the space bar.\\n While dragging, use the arrow keys to move the item.\\n Press space again to drop the item in its new position, or press escape to cancel.\\n \"\n};\nconst defaultAnnouncements = {\n onDragStart(_ref) {\n let {\n active\n } = _ref;\n return \"Picked up draggable item \" + active.id + \".\";\n },\n\n onDragOver(_ref2) {\n let {\n active,\n over\n } = _ref2;\n\n if (over) {\n return \"Draggable item \" + active.id + \" was moved over droppable area \" + over.id + \".\";\n }\n\n return \"Draggable item \" + active.id + \" is no longer over a droppable area.\";\n },\n\n onDragEnd(_ref3) {\n let {\n active,\n over\n } = _ref3;\n\n if (over) {\n return \"Draggable item \" + active.id + \" was dropped over droppable area \" + over.id;\n }\n\n return \"Draggable item \" + active.id + \" was dropped.\";\n },\n\n onDragCancel(_ref4) {\n let {\n active\n } = _ref4;\n return \"Dragging was cancelled. Draggable item \" + active.id + \" was dropped.\";\n }\n\n};\n\nfunction Accessibility(_ref) {\n let {\n announcements = defaultAnnouncements,\n container,\n hiddenTextDescribedById,\n screenReaderInstructions = defaultScreenReaderInstructions\n } = _ref;\n const {\n announce,\n announcement\n } = useAnnouncement();\n const liveRegionId = useUniqueId(\"DndLiveRegion\");\n const [mounted, setMounted] = useState(false);\n useEffect(() => {\n setMounted(true);\n }, []);\n useDndMonitor(useMemo(() => ({\n onDragStart(_ref2) {\n let {\n active\n } = _ref2;\n announce(announcements.onDragStart({\n active\n }));\n },\n\n onDragMove(_ref3) {\n let {\n active,\n over\n } = _ref3;\n\n if (announcements.onDragMove) {\n announce(announcements.onDragMove({\n active,\n over\n }));\n }\n },\n\n onDragOver(_ref4) {\n let {\n active,\n over\n } = _ref4;\n announce(announcements.onDragOver({\n active,\n over\n }));\n },\n\n onDragEnd(_ref5) {\n let {\n active,\n over\n } = _ref5;\n announce(announcements.onDragEnd({\n active,\n over\n }));\n },\n\n onDragCancel(_ref6) {\n let {\n active,\n over\n } = _ref6;\n announce(announcements.onDragCancel({\n active,\n over\n }));\n }\n\n }), [announce, announcements]));\n\n if (!mounted) {\n return null;\n }\n\n const markup = React.createElement(React.Fragment, null, React.createElement(HiddenText, {\n id: hiddenTextDescribedById,\n value: screenReaderInstructions.draggable\n }), React.createElement(LiveRegion, {\n id: liveRegionId,\n announcement: announcement\n }));\n return container ? createPortal(markup, container) : markup;\n}\n\nvar Action;\n\n(function (Action) {\n Action[\"DragStart\"] = \"dragStart\";\n Action[\"DragMove\"] = \"dragMove\";\n Action[\"DragEnd\"] = \"dragEnd\";\n Action[\"DragCancel\"] = \"dragCancel\";\n Action[\"DragOver\"] = \"dragOver\";\n Action[\"RegisterDroppable\"] = \"registerDroppable\";\n Action[\"SetDroppableDisabled\"] = \"setDroppableDisabled\";\n Action[\"UnregisterDroppable\"] = \"unregisterDroppable\";\n})(Action || (Action = {}));\n\nfunction noop() {}\n\nfunction useSensor(sensor, options) {\n return useMemo(() => ({\n sensor,\n options: options != null ? options : {}\n }), // eslint-disable-next-line react-hooks/exhaustive-deps\n [sensor, options]);\n}\n\nfunction useSensors() {\n for (var _len = arguments.length, sensors = new Array(_len), _key = 0; _key < _len; _key++) {\n sensors[_key] = arguments[_key];\n }\n\n return useMemo(() => [...sensors].filter(sensor => sensor != null), // eslint-disable-next-line react-hooks/exhaustive-deps\n [...sensors]);\n}\n\nconst defaultCoordinates = /*#__PURE__*/Object.freeze({\n x: 0,\n y: 0\n});\n\n/**\r\n * Returns the distance between two points\r\n */\nfunction distanceBetween(p1, p2) {\n return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));\n}\n\nfunction getRelativeTransformOrigin(event, rect) {\n const eventCoordinates = getEventCoordinates(event);\n\n if (!eventCoordinates) {\n return '0 0';\n }\n\n const transformOrigin = {\n x: (eventCoordinates.x - rect.left) / rect.width * 100,\n y: (eventCoordinates.y - rect.top) / rect.height * 100\n };\n return transformOrigin.x + \"% \" + transformOrigin.y + \"%\";\n}\n\n/**\r\n * Sort collisions from smallest to greatest value\r\n */\nfunction sortCollisionsAsc(_ref, _ref2) {\n let {\n data: {\n value: a\n }\n } = _ref;\n let {\n data: {\n value: b\n }\n } = _ref2;\n return a - b;\n}\n/**\r\n * Sort collisions from greatest to smallest value\r\n */\n\nfunction sortCollisionsDesc(_ref3, _ref4) {\n let {\n data: {\n value: a\n }\n } = _ref3;\n let {\n data: {\n value: b\n }\n } = _ref4;\n return b - a;\n}\n/**\r\n * Returns the coordinates of the corners of a given rectangle:\r\n * [TopLeft {x, y}, TopRight {x, y}, BottomLeft {x, y}, BottomRight {x, y}]\r\n */\n\nfunction cornersOfRectangle(_ref5) {\n let {\n left,\n top,\n height,\n width\n } = _ref5;\n return [{\n x: left,\n y: top\n }, {\n x: left + width,\n y: top\n }, {\n x: left,\n y: top + height\n }, {\n x: left + width,\n y: top + height\n }];\n}\nfunction getFirstCollision(collisions, property) {\n if (!collisions || collisions.length === 0) {\n return null;\n }\n\n const [firstCollision] = collisions;\n return property ? firstCollision[property] : firstCollision;\n}\n\n/**\r\n * Returns the coordinates of the center of a given ClientRect\r\n */\n\nfunction centerOfRectangle(rect, left, top) {\n if (left === void 0) {\n left = rect.left;\n }\n\n if (top === void 0) {\n top = rect.top;\n }\n\n return {\n x: left + rect.width * 0.5,\n y: top + rect.height * 0.5\n };\n}\n/**\r\n * Returns the closest rectangles from an array of rectangles to the center of a given\r\n * rectangle.\r\n */\n\n\nconst closestCenter = _ref => {\n let {\n collisionRect,\n droppableRects,\n droppableContainers\n } = _ref;\n const centerRect = centerOfRectangle(collisionRect, collisionRect.left, collisionRect.top);\n const collisions = [];\n\n for (const droppableContainer of droppableContainers) {\n const {\n id\n } = droppableContainer;\n const rect = droppableRects.get(id);\n\n if (rect) {\n const distBetween = distanceBetween(centerOfRectangle(rect), centerRect);\n collisions.push({\n id,\n data: {\n droppableContainer,\n value: distBetween\n }\n });\n }\n }\n\n return collisions.sort(sortCollisionsAsc);\n};\n\n/**\r\n * Returns the closest rectangles from an array of rectangles to the corners of\r\n * another rectangle.\r\n */\n\nconst closestCorners = _ref => {\n let {\n collisionRect,\n droppableRects,\n droppableContainers\n } = _ref;\n const corners = cornersOfRectangle(collisionRect);\n const collisions = [];\n\n for (const droppableContainer of droppableContainers) {\n const {\n id\n } = droppableContainer;\n const rect = droppableRects.get(id);\n\n if (rect) {\n const rectCorners = cornersOfRectangle(rect);\n const distances = corners.reduce((accumulator, corner, index) => {\n return accumulator + distanceBetween(rectCorners[index], corner);\n }, 0);\n const effectiveDistance = Number((distances / 4).toFixed(4));\n collisions.push({\n id,\n data: {\n droppableContainer,\n value: effectiveDistance\n }\n });\n }\n }\n\n return collisions.sort(sortCollisionsAsc);\n};\n\n/**\r\n * Returns the intersecting rectangle area between two rectangles\r\n */\n\nfunction getIntersectionRatio(entry, target) {\n const top = Math.max(target.top, entry.top);\n const left = Math.max(target.left, entry.left);\n const right = Math.min(target.left + target.width, entry.left + entry.width);\n const bottom = Math.min(target.top + target.height, entry.top + entry.height);\n const width = right - left;\n const height = bottom - top;\n\n if (left < right && top < bottom) {\n const targetArea = target.width * target.height;\n const entryArea = entry.width * entry.height;\n const intersectionArea = width * height;\n const intersectionRatio = intersectionArea / (targetArea + entryArea - intersectionArea);\n return Number(intersectionRatio.toFixed(4));\n } // Rectangles do not overlap, or overlap has an area of zero (edge/corner overlap)\n\n\n return 0;\n}\n/**\r\n * Returns the rectangles that has the greatest intersection area with a given\r\n * rectangle in an array of rectangles.\r\n */\n\nconst rectIntersection = _ref => {\n let {\n collisionRect,\n droppableRects,\n droppableContainers\n } = _ref;\n const collisions = [];\n\n for (const droppableContainer of droppableContainers) {\n const {\n id\n } = droppableContainer;\n const rect = droppableRects.get(id);\n\n if (rect) {\n const intersectionRatio = getIntersectionRatio(rect, collisionRect);\n\n if (intersectionRatio > 0) {\n collisions.push({\n id,\n data: {\n droppableContainer,\n value: intersectionRatio\n }\n });\n }\n }\n }\n\n return collisions.sort(sortCollisionsDesc);\n};\n\n/**\r\n * Check if a given point is contained within a bounding rectangle\r\n */\n\nfunction isPointWithinRect(point, rect) {\n const {\n top,\n left,\n bottom,\n right\n } = rect;\n return top <= point.y && point.y <= bottom && left <= point.x && point.x <= right;\n}\n/**\r\n * Returns the rectangles that the pointer is hovering over\r\n */\n\n\nconst pointerWithin = _ref => {\n let {\n droppableContainers,\n droppableRects,\n pointerCoordinates\n } = _ref;\n\n if (!pointerCoordinates) {\n return [];\n }\n\n const collisions = [];\n\n for (const droppableContainer of droppableContainers) {\n const {\n id\n } = droppableContainer;\n const rect = droppableRects.get(id);\n\n if (rect && isPointWithinRect(pointerCoordinates, rect)) {\n /* There may be more than a single rectangle intersecting\r\n * with the pointer coordinates. In order to sort the\r\n * colliding rectangles, we measure the distance between\r\n * the pointer and the corners of the intersecting rectangle\r\n */\n const corners = cornersOfRectangle(rect);\n const distances = corners.reduce((accumulator, corner) => {\n return accumulator + distanceBetween(pointerCoordinates, corner);\n }, 0);\n const effectiveDistance = Number((distances / 4).toFixed(4));\n collisions.push({\n id,\n data: {\n droppableContainer,\n value: effectiveDistance\n }\n });\n }\n }\n\n return collisions.sort(sortCollisionsAsc);\n};\n\nfunction adjustScale(transform, rect1, rect2) {\n return { ...transform,\n scaleX: rect1 && rect2 ? rect1.width / rect2.width : 1,\n scaleY: rect1 && rect2 ? rect1.height / rect2.height : 1\n };\n}\n\nfunction getRectDelta(rect1, rect2) {\n return rect1 && rect2 ? {\n x: rect1.left - rect2.left,\n y: rect1.top - rect2.top\n } : defaultCoordinates;\n}\n\nfunction createRectAdjustmentFn(modifier) {\n return function adjustClientRect(rect) {\n for (var _len = arguments.length, adjustments = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n adjustments[_key - 1] = arguments[_key];\n }\n\n return adjustments.reduce((acc, adjustment) => ({ ...acc,\n top: acc.top + modifier * adjustment.y,\n bottom: acc.bottom + modifier * adjustment.y,\n left: acc.left + modifier * adjustment.x,\n right: acc.right + modifier * adjustment.x\n }), { ...rect\n });\n };\n}\nconst getAdjustedRect = /*#__PURE__*/createRectAdjustmentFn(1);\n\nfunction parseTransform(transform) {\n if (transform.startsWith('matrix3d(')) {\n const transformArray = transform.slice(9, -1).split(/, /);\n return {\n x: +transformArray[12],\n y: +transformArray[13],\n scaleX: +transformArray[0],\n scaleY: +transformArray[5]\n };\n } else if (transform.startsWith('matrix(')) {\n const transformArray = transform.slice(7, -1).split(/, /);\n return {\n x: +transformArray[4],\n y: +transformArray[5],\n scaleX: +transformArray[0],\n scaleY: +transformArray[3]\n };\n }\n\n return null;\n}\n\nfunction inverseTransform(rect, transform, transformOrigin) {\n const parsedTransform = parseTransform(transform);\n\n if (!parsedTransform) {\n return rect;\n }\n\n const {\n scaleX,\n scaleY,\n x: translateX,\n y: translateY\n } = parsedTransform;\n const x = rect.left - translateX - (1 - scaleX) * parseFloat(transformOrigin);\n const y = rect.top - translateY - (1 - scaleY) * parseFloat(transformOrigin.slice(transformOrigin.indexOf(' ') + 1));\n const w = scaleX ? rect.width / scaleX : rect.width;\n const h = scaleY ? rect.height / scaleY : rect.height;\n return {\n width: w,\n height: h,\n top: y,\n right: x + w,\n bottom: y + h,\n left: x\n };\n}\n\nconst defaultOptions = {\n ignoreTransform: false\n};\n/**\r\n * Returns the bounding client rect of an element relative to the viewport.\r\n */\n\nfunction getClientRect(element, options) {\n if (options === void 0) {\n options = defaultOptions;\n }\n\n let rect = element.getBoundingClientRect();\n\n if (options.ignoreTransform) {\n const {\n transform,\n transformOrigin\n } = getWindow(element).getComputedStyle(element);\n\n if (transform) {\n rect = inverseTransform(rect, transform, transformOrigin);\n }\n }\n\n const {\n top,\n left,\n width,\n height,\n bottom,\n right\n } = rect;\n return {\n top,\n left,\n width,\n height,\n bottom,\n right\n };\n}\n/**\r\n * Returns the bounding client rect of an element relative to the viewport.\r\n *\r\n * @remarks\r\n * The ClientRect returned by this method does not take into account transforms\r\n * applied to the element it measures.\r\n *\r\n */\n\nfunction getTransformAgnosticClientRect(element) {\n return getClientRect(element, {\n ignoreTransform: true\n });\n}\n\nfunction getWindowClientRect(element) {\n const width = element.innerWidth;\n const height = element.innerHeight;\n return {\n top: 0,\n left: 0,\n right: width,\n bottom: height,\n width,\n height\n };\n}\n\nfunction isFixed(node, computedStyle) {\n if (computedStyle === void 0) {\n computedStyle = getWindow(node).getComputedStyle(node);\n }\n\n return computedStyle.position === 'fixed';\n}\n\nfunction isScrollable(element, computedStyle) {\n if (computedStyle === void 0) {\n computedStyle = getWindow(element).getComputedStyle(element);\n }\n\n const overflowRegex = /(auto|scroll|overlay)/;\n const properties = ['overflow', 'overflowX', 'overflowY'];\n return properties.some(property => {\n const value = computedStyle[property];\n return typeof value === 'string' ? overflowRegex.test(value) : false;\n });\n}\n\nfunction getScrollableAncestors(element, limit) {\n const scrollParents = [];\n\n function findScrollableAncestors(node) {\n if (limit != null && scrollParents.length >= limit) {\n return scrollParents;\n }\n\n if (!node) {\n return scrollParents;\n }\n\n if (isDocument(node) && node.scrollingElement != null && !scrollParents.includes(node.scrollingElement)) {\n scrollParents.push(node.scrollingElement);\n return scrollParents;\n }\n\n if (!isHTMLElement(node) || isSVGElement(node)) {\n return scrollParents;\n }\n\n if (scrollParents.includes(node)) {\n return scrollParents;\n }\n\n const computedStyle = getWindow(element).getComputedStyle(node);\n\n if (node !== element) {\n if (isScrollable(node, computedStyle)) {\n scrollParents.push(node);\n }\n }\n\n if (isFixed(node, computedStyle)) {\n return scrollParents;\n }\n\n return findScrollableAncestors(node.parentNode);\n }\n\n if (!element) {\n return scrollParents;\n }\n\n return findScrollableAncestors(element);\n}\nfunction getFirstScrollableAncestor(node) {\n const [firstScrollableAncestor] = getScrollableAncestors(node, 1);\n return firstScrollableAncestor != null ? firstScrollableAncestor : null;\n}\n\nfunction getScrollableElement(element) {\n if (!canUseDOM || !element) {\n return null;\n }\n\n if (isWindow(element)) {\n return element;\n }\n\n if (!isNode(element)) {\n return null;\n }\n\n if (isDocument(element) || element === getOwnerDocument(element).scrollingElement) {\n return window;\n }\n\n if (isHTMLElement(element)) {\n return element;\n }\n\n return null;\n}\n\nfunction getScrollXCoordinate(element) {\n if (isWindow(element)) {\n return element.scrollX;\n }\n\n return element.scrollLeft;\n}\nfunction getScrollYCoordinate(element) {\n if (isWindow(element)) {\n return element.scrollY;\n }\n\n return element.scrollTop;\n}\nfunction getScrollCoordinates(element) {\n return {\n x: getScrollXCoordinate(element),\n y: getScrollYCoordinate(element)\n };\n}\n\nvar Direction;\n\n(function (Direction) {\n Direction[Direction[\"Forward\"] = 1] = \"Forward\";\n Direction[Direction[\"Backward\"] = -1] = \"Backward\";\n})(Direction || (Direction = {}));\n\nfunction isDocumentScrollingElement(element) {\n if (!canUseDOM || !element) {\n return false;\n }\n\n return element === document.scrollingElement;\n}\n\nfunction getScrollPosition(scrollingContainer) {\n const minScroll = {\n x: 0,\n y: 0\n };\n const dimensions = isDocumentScrollingElement(scrollingContainer) ? {\n height: window.innerHeight,\n width: window.innerWidth\n } : {\n height: scrollingContainer.clientHeight,\n width: scrollingContainer.clientWidth\n };\n const maxScroll = {\n x: scrollingContainer.scrollWidth - dimensions.width,\n y: scrollingContainer.scrollHeight - dimensions.height\n };\n const isTop = scrollingContainer.scrollTop <= minScroll.y;\n const isLeft = scrollingContainer.scrollLeft <= minScroll.x;\n const isBottom = scrollingContainer.scrollTop >= maxScroll.y;\n const isRight = scrollingContainer.scrollLeft >= maxScroll.x;\n return {\n isTop,\n isLeft,\n isBottom,\n isRight,\n maxScroll,\n minScroll\n };\n}\n\nconst defaultThreshold = {\n x: 0.2,\n y: 0.2\n};\nfunction getScrollDirectionAndSpeed(scrollContainer, scrollContainerRect, _ref, acceleration, thresholdPercentage) {\n let {\n top,\n left,\n right,\n bottom\n } = _ref;\n\n if (acceleration === void 0) {\n acceleration = 10;\n }\n\n if (thresholdPercentage === void 0) {\n thresholdPercentage = defaultThreshold;\n }\n\n const {\n isTop,\n isBottom,\n isLeft,\n isRight\n } = getScrollPosition(scrollContainer);\n const direction = {\n x: 0,\n y: 0\n };\n const speed = {\n x: 0,\n y: 0\n };\n const threshold = {\n height: scrollContainerRect.height * thresholdPercentage.y,\n width: scrollContainerRect.width * thresholdPercentage.x\n };\n\n if (!isTop && top <= scrollContainerRect.top + threshold.height) {\n // Scroll Up\n direction.y = Direction.Backward;\n speed.y = acceleration * Math.abs((scrollContainerRect.top + threshold.height - top) / threshold.height);\n } else if (!isBottom && bottom >= scrollContainerRect.bottom - threshold.height) {\n // Scroll Down\n direction.y = Direction.Forward;\n speed.y = acceleration * Math.abs((scrollContainerRect.bottom - threshold.height - bottom) / threshold.height);\n }\n\n if (!isRight && right >= scrollContainerRect.right - threshold.width) {\n // Scroll Right\n direction.x = Direction.Forward;\n speed.x = acceleration * Math.abs((scrollContainerRect.right - threshold.width - right) / threshold.width);\n } else if (!isLeft && left <= scrollContainerRect.left + threshold.width) {\n // Scroll Left\n direction.x = Direction.Backward;\n speed.x = acceleration * Math.abs((scrollContainerRect.left + threshold.width - left) / threshold.width);\n }\n\n return {\n direction,\n speed\n };\n}\n\nfunction getScrollElementRect(element) {\n if (element === document.scrollingElement) {\n const {\n innerWidth,\n innerHeight\n } = window;\n return {\n top: 0,\n left: 0,\n right: innerWidth,\n bottom: innerHeight,\n width: innerWidth,\n height: innerHeight\n };\n }\n\n const {\n top,\n left,\n right,\n bottom\n } = element.getBoundingClientRect();\n return {\n top,\n left,\n right,\n bottom,\n width: element.clientWidth,\n height: element.clientHeight\n };\n}\n\nfunction getScrollOffsets(scrollableAncestors) {\n return scrollableAncestors.reduce((acc, node) => {\n return add(acc, getScrollCoordinates(node));\n }, defaultCoordinates);\n}\nfunction getScrollXOffset(scrollableAncestors) {\n return scrollableAncestors.reduce((acc, node) => {\n return acc + getScrollXCoordinate(node);\n }, 0);\n}\nfunction getScrollYOffset(scrollableAncestors) {\n return scrollableAncestors.reduce((acc, node) => {\n return acc + getScrollYCoordinate(node);\n }, 0);\n}\n\nfunction scrollIntoViewIfNeeded(element, measure) {\n if (measure === void 0) {\n measure = getClientRect;\n }\n\n if (!element) {\n return;\n }\n\n const {\n top,\n left,\n bottom,\n right\n } = measure(element);\n const firstScrollableAncestor = getFirstScrollableAncestor(element);\n\n if (!firstScrollableAncestor) {\n return;\n }\n\n if (bottom <= 0 || right <= 0 || top >= window.innerHeight || left >= window.innerWidth) {\n element.scrollIntoView({\n block: 'center',\n inline: 'center'\n });\n }\n}\n\nconst properties = [['x', ['left', 'right'], getScrollXOffset], ['y', ['top', 'bottom'], getScrollYOffset]];\nclass Rect {\n constructor(rect, element) {\n this.rect = void 0;\n this.width = void 0;\n this.height = void 0;\n this.top = void 0;\n this.bottom = void 0;\n this.right = void 0;\n this.left = void 0;\n const scrollableAncestors = getScrollableAncestors(element);\n const scrollOffsets = getScrollOffsets(scrollableAncestors);\n this.rect = { ...rect\n };\n this.width = rect.width;\n this.height = rect.height;\n\n for (const [axis, keys, getScrollOffset] of properties) {\n for (const key of keys) {\n Object.defineProperty(this, key, {\n get: () => {\n const currentOffsets = getScrollOffset(scrollableAncestors);\n const scrollOffsetsDeltla = scrollOffsets[axis] - currentOffsets;\n return this.rect[key] + scrollOffsetsDeltla;\n },\n enumerable: true\n });\n }\n }\n\n Object.defineProperty(this, 'rect', {\n enumerable: false\n });\n }\n\n}\n\nclass Listeners {\n constructor(target) {\n this.target = void 0;\n this.listeners = [];\n\n this.removeAll = () => {\n this.listeners.forEach(listener => {\n var _this$target;\n\n return (_this$target = this.target) == null ? void 0 : _this$target.removeEventListener(...listener);\n });\n };\n\n this.target = target;\n }\n\n add(eventName, handler, options) {\n var _this$target2;\n\n (_this$target2 = this.target) == null ? void 0 : _this$target2.addEventListener(eventName, handler, options);\n this.listeners.push([eventName, handler, options]);\n }\n\n}\n\nfunction getEventListenerTarget(target) {\n // If the `event.target` element is removed from the document events will still be targeted\n // at it, and hence won't always bubble up to the window or document anymore.\n // If there is any risk of an element being removed while it is being dragged,\n // the best practice is to attach the event listeners directly to the target.\n // https://developer.mozilla.org/en-US/docs/Web/API/EventTarget\n const {\n EventTarget\n } = getWindow(target);\n return target instanceof EventTarget ? target : getOwnerDocument(target);\n}\n\nfunction hasExceededDistance(delta, measurement) {\n const dx = Math.abs(delta.x);\n const dy = Math.abs(delta.y);\n\n if (typeof measurement === 'number') {\n return Math.sqrt(dx ** 2 + dy ** 2) > measurement;\n }\n\n if ('x' in measurement && 'y' in measurement) {\n return dx > measurement.x && dy > measurement.y;\n }\n\n if ('x' in measurement) {\n return dx > measurement.x;\n }\n\n if ('y' in measurement) {\n return dy > measurement.y;\n }\n\n return false;\n}\n\nvar EventName;\n\n(function (EventName) {\n EventName[\"Click\"] = \"click\";\n EventName[\"DragStart\"] = \"dragstart\";\n EventName[\"Keydown\"] = \"keydown\";\n EventName[\"ContextMenu\"] = \"contextmenu\";\n EventName[\"Resize\"] = \"resize\";\n EventName[\"SelectionChange\"] = \"selectionchange\";\n EventName[\"VisibilityChange\"] = \"visibilitychange\";\n})(EventName || (EventName = {}));\n\nfunction preventDefault(event) {\n event.preventDefault();\n}\nfunction stopPropagation(event) {\n event.stopPropagation();\n}\n\nvar KeyboardCode;\n\n(function (KeyboardCode) {\n KeyboardCode[\"Space\"] = \"Space\";\n KeyboardCode[\"Down\"] = \"ArrowDown\";\n KeyboardCode[\"Right\"] = \"ArrowRight\";\n KeyboardCode[\"Left\"] = \"ArrowLeft\";\n KeyboardCode[\"Up\"] = \"ArrowUp\";\n KeyboardCode[\"Esc\"] = \"Escape\";\n KeyboardCode[\"Enter\"] = \"Enter\";\n KeyboardCode[\"Tab\"] = \"Tab\";\n})(KeyboardCode || (KeyboardCode = {}));\n\nconst defaultKeyboardCodes = {\n start: [KeyboardCode.Space, KeyboardCode.Enter],\n cancel: [KeyboardCode.Esc],\n end: [KeyboardCode.Space, KeyboardCode.Enter, KeyboardCode.Tab]\n};\nconst defaultKeyboardCoordinateGetter = (event, _ref) => {\n let {\n currentCoordinates\n } = _ref;\n\n switch (event.code) {\n case KeyboardCode.Right:\n return { ...currentCoordinates,\n x: currentCoordinates.x + 25\n };\n\n case KeyboardCode.Left:\n return { ...currentCoordinates,\n x: currentCoordinates.x - 25\n };\n\n case KeyboardCode.Down:\n return { ...currentCoordinates,\n y: currentCoordinates.y + 25\n };\n\n case KeyboardCode.Up:\n return { ...currentCoordinates,\n y: currentCoordinates.y - 25\n };\n }\n\n return undefined;\n};\n\nclass KeyboardSensor {\n constructor(props) {\n this.props = void 0;\n this.autoScrollEnabled = false;\n this.referenceCoordinates = void 0;\n this.listeners = void 0;\n this.windowListeners = void 0;\n this.props = props;\n const {\n event: {\n target\n }\n } = props;\n this.props = props;\n this.listeners = new Listeners(getOwnerDocument(target));\n this.windowListeners = new Listeners(getWindow(target));\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n this.attach();\n }\n\n attach() {\n this.handleStart();\n this.windowListeners.add(EventName.Resize, this.handleCancel);\n this.windowListeners.add(EventName.VisibilityChange, this.handleCancel);\n setTimeout(() => this.listeners.add(EventName.Keydown, this.handleKeyDown));\n }\n\n handleStart() {\n const {\n activeNode,\n onStart\n } = this.props;\n const node = activeNode.node.current;\n\n if (node) {\n scrollIntoViewIfNeeded(node);\n }\n\n onStart(defaultCoordinates);\n }\n\n handleKeyDown(event) {\n if (isKeyboardEvent(event)) {\n const {\n active,\n context,\n options\n } = this.props;\n const {\n keyboardCodes = defaultKeyboardCodes,\n coordinateGetter = defaultKeyboardCoordinateGetter,\n scrollBehavior = 'smooth'\n } = options;\n const {\n code\n } = event;\n\n if (keyboardCodes.end.includes(code)) {\n this.handleEnd(event);\n return;\n }\n\n if (keyboardCodes.cancel.includes(code)) {\n this.handleCancel(event);\n return;\n }\n\n const {\n collisionRect\n } = context.current;\n const currentCoordinates = collisionRect ? {\n x: collisionRect.left,\n y: collisionRect.top\n } : defaultCoordinates;\n\n if (!this.referenceCoordinates) {\n this.referenceCoordinates = currentCoordinates;\n }\n\n const newCoordinates = coordinateGetter(event, {\n active,\n context: context.current,\n currentCoordinates\n });\n\n if (newCoordinates) {\n const coordinatesDelta = subtract(newCoordinates, currentCoordinates);\n const scrollDelta = {\n x: 0,\n y: 0\n };\n const {\n scrollableAncestors\n } = context.current;\n\n for (const scrollContainer of scrollableAncestors) {\n const direction = event.code;\n const {\n isTop,\n isRight,\n isLeft,\n isBottom,\n maxScroll,\n minScroll\n } = getScrollPosition(scrollContainer);\n const scrollElementRect = getScrollElementRect(scrollContainer);\n const clampedCoordinates = {\n x: Math.min(direction === KeyboardCode.Right ? scrollElementRect.right - scrollElementRect.width / 2 : scrollElementRect.right, Math.max(direction === KeyboardCode.Right ? scrollElementRect.left : scrollElementRect.left + scrollElementRect.width / 2, newCoordinates.x)),\n y: Math.min(direction === KeyboardCode.Down ? scrollElementRect.bottom - scrollElementRect.height / 2 : scrollElementRect.bottom, Math.max(direction === KeyboardCode.Down ? scrollElementRect.top : scrollElementRect.top + scrollElementRect.height / 2, newCoordinates.y))\n };\n const canScrollX = direction === KeyboardCode.Right && !isRight || direction === KeyboardCode.Left && !isLeft;\n const canScrollY = direction === KeyboardCode.Down && !isBottom || direction === KeyboardCode.Up && !isTop;\n\n if (canScrollX && clampedCoordinates.x !== newCoordinates.x) {\n const newScrollCoordinates = scrollContainer.scrollLeft + coordinatesDelta.x;\n const canScrollToNewCoordinates = direction === KeyboardCode.Right && newScrollCoordinates <= maxScroll.x || direction === KeyboardCode.Left && newScrollCoordinates >= minScroll.x;\n\n if (canScrollToNewCoordinates && !coordinatesDelta.y) {\n // We don't need to update coordinates, the scroll adjustment alone will trigger\n // logic to auto-detect the new container we are over\n scrollContainer.scrollTo({\n left: newScrollCoordinates,\n behavior: scrollBehavior\n });\n return;\n }\n\n if (canScrollToNewCoordinates) {\n scrollDelta.x = scrollContainer.scrollLeft - newScrollCoordinates;\n } else {\n scrollDelta.x = direction === KeyboardCode.Right ? scrollContainer.scrollLeft - maxScroll.x : scrollContainer.scrollLeft - minScroll.x;\n }\n\n if (scrollDelta.x) {\n scrollContainer.scrollBy({\n left: -scrollDelta.x,\n behavior: scrollBehavior\n });\n }\n\n break;\n } else if (canScrollY && clampedCoordinates.y !== newCoordinates.y) {\n const newScrollCoordinates = scrollContainer.scrollTop + coordinatesDelta.y;\n const canScrollToNewCoordinates = direction === KeyboardCode.Down && newScrollCoordinates <= maxScroll.y || direction === KeyboardCode.Up && newScrollCoordinates >= minScroll.y;\n\n if (canScrollToNewCoordinates && !coordinatesDelta.x) {\n // We don't need to update coordinates, the scroll adjustment alone will trigger\n // logic to auto-detect the new container we are over\n scrollContainer.scrollTo({\n top: newScrollCoordinates,\n behavior: scrollBehavior\n });\n return;\n }\n\n if (canScrollToNewCoordinates) {\n scrollDelta.y = scrollContainer.scrollTop - newScrollCoordinates;\n } else {\n scrollDelta.y = direction === KeyboardCode.Down ? scrollContainer.scrollTop - maxScroll.y : scrollContainer.scrollTop - minScroll.y;\n }\n\n if (scrollDelta.y) {\n scrollContainer.scrollBy({\n top: -scrollDelta.y,\n behavior: scrollBehavior\n });\n }\n\n break;\n }\n }\n\n this.handleMove(event, add(subtract(newCoordinates, this.referenceCoordinates), scrollDelta));\n }\n }\n }\n\n handleMove(event, coordinates) {\n const {\n onMove\n } = this.props;\n event.preventDefault();\n onMove(coordinates);\n }\n\n handleEnd(event) {\n const {\n onEnd\n } = this.props;\n event.preventDefault();\n this.detach();\n onEnd();\n }\n\n handleCancel(event) {\n const {\n onCancel\n } = this.props;\n event.preventDefault();\n this.detach();\n onCancel();\n }\n\n detach() {\n this.listeners.removeAll();\n this.windowListeners.removeAll();\n }\n\n}\nKeyboardSensor.activators = [{\n eventName: 'onKeyDown',\n handler: (event, _ref, _ref2) => {\n let {\n keyboardCodes = defaultKeyboardCodes,\n onActivation\n } = _ref;\n let {\n active\n } = _ref2;\n const {\n code\n } = event.nativeEvent;\n\n if (keyboardCodes.start.includes(code)) {\n const activator = active.activatorNode.current;\n\n if (activator && event.target !== activator) {\n return false;\n }\n\n event.preventDefault();\n onActivation == null ? void 0 : onActivation({\n event: event.nativeEvent\n });\n return true;\n }\n\n return false;\n }\n}];\n\nfunction isDistanceConstraint(constraint) {\n return Boolean(constraint && 'distance' in constraint);\n}\n\nfunction isDelayConstraint(constraint) {\n return Boolean(constraint && 'delay' in constraint);\n}\n\nclass AbstractPointerSensor {\n constructor(props, events, listenerTarget) {\n var _getEventCoordinates;\n\n if (listenerTarget === void 0) {\n listenerTarget = getEventListenerTarget(props.event.target);\n }\n\n this.props = void 0;\n this.events = void 0;\n this.autoScrollEnabled = true;\n this.document = void 0;\n this.activated = false;\n this.initialCoordinates = void 0;\n this.timeoutId = null;\n this.listeners = void 0;\n this.documentListeners = void 0;\n this.windowListeners = void 0;\n this.props = props;\n this.events = events;\n const {\n event\n } = props;\n const {\n target\n } = event;\n this.props = props;\n this.events = events;\n this.document = getOwnerDocument(target);\n this.documentListeners = new Listeners(this.document);\n this.listeners = new Listeners(listenerTarget);\n this.windowListeners = new Listeners(getWindow(target));\n this.initialCoordinates = (_getEventCoordinates = getEventCoordinates(event)) != null ? _getEventCoordinates : defaultCoordinates;\n this.handleStart = this.handleStart.bind(this);\n this.handleMove = this.handleMove.bind(this);\n this.handleEnd = this.handleEnd.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n this.handleKeydown = this.handleKeydown.bind(this);\n this.removeTextSelection = this.removeTextSelection.bind(this);\n this.attach();\n }\n\n attach() {\n const {\n events,\n props: {\n options: {\n activationConstraint,\n bypassActivationConstraint\n }\n }\n } = this;\n this.listeners.add(events.move.name, this.handleMove, {\n passive: false\n });\n this.listeners.add(events.end.name, this.handleEnd);\n\n if (events.cancel) {\n this.listeners.add(events.cancel.name, this.handleCancel);\n }\n\n this.windowListeners.add(EventName.Resize, this.handleCancel);\n this.windowListeners.add(EventName.DragStart, preventDefault);\n this.windowListeners.add(EventName.VisibilityChange, this.handleCancel);\n this.windowListeners.add(EventName.ContextMenu, preventDefault);\n this.documentListeners.add(EventName.Keydown, this.handleKeydown);\n\n if (activationConstraint) {\n if (bypassActivationConstraint != null && bypassActivationConstraint({\n event: this.props.event,\n activeNode: this.props.activeNode,\n options: this.props.options\n })) {\n return this.handleStart();\n }\n\n if (isDelayConstraint(activationConstraint)) {\n this.timeoutId = setTimeout(this.handleStart, activationConstraint.delay);\n this.handlePending(activationConstraint);\n return;\n }\n\n if (isDistanceConstraint(activationConstraint)) {\n this.handlePending(activationConstraint);\n return;\n }\n }\n\n this.handleStart();\n }\n\n detach() {\n this.listeners.removeAll();\n this.windowListeners.removeAll(); // Wait until the next event loop before removing document listeners\n // This is necessary because we listen for `click` and `selection` events on the document\n\n setTimeout(this.documentListeners.removeAll, 50);\n\n if (this.timeoutId !== null) {\n clearTimeout(this.timeoutId);\n this.timeoutId = null;\n }\n }\n\n handlePending(constraint, offset) {\n const {\n active,\n onPending\n } = this.props;\n onPending(active, constraint, this.initialCoordinates, offset);\n }\n\n handleStart() {\n const {\n initialCoordinates\n } = this;\n const {\n onStart\n } = this.props;\n\n if (initialCoordinates) {\n this.activated = true; // Stop propagation of click events once activation constraints are met\n\n this.documentListeners.add(EventName.Click, stopPropagation, {\n capture: true\n }); // Remove any text selection from the document\n\n this.removeTextSelection(); // Prevent further text selection while dragging\n\n this.documentListeners.add(EventName.SelectionChange, this.removeTextSelection);\n onStart(initialCoordinates);\n }\n }\n\n handleMove(event) {\n var _getEventCoordinates2;\n\n const {\n activated,\n initialCoordinates,\n props\n } = this;\n const {\n onMove,\n options: {\n activationConstraint\n }\n } = props;\n\n if (!initialCoordinates) {\n return;\n }\n\n const coordinates = (_getEventCoordinates2 = getEventCoordinates(event)) != null ? _getEventCoordinates2 : defaultCoordinates;\n const delta = subtract(initialCoordinates, coordinates); // Constraint validation\n\n if (!activated && activationConstraint) {\n if (isDistanceConstraint(activationConstraint)) {\n if (activationConstraint.tolerance != null && hasExceededDistance(delta, activationConstraint.tolerance)) {\n return this.handleCancel();\n }\n\n if (hasExceededDistance(delta, activationConstraint.distance)) {\n return this.handleStart();\n }\n }\n\n if (isDelayConstraint(activationConstraint)) {\n if (hasExceededDistance(delta, activationConstraint.tolerance)) {\n return this.handleCancel();\n }\n }\n\n this.handlePending(activationConstraint, delta);\n return;\n }\n\n if (event.cancelable) {\n event.preventDefault();\n }\n\n onMove(coordinates);\n }\n\n handleEnd() {\n const {\n onAbort,\n onEnd\n } = this.props;\n this.detach();\n\n if (!this.activated) {\n onAbort(this.props.active);\n }\n\n onEnd();\n }\n\n handleCancel() {\n const {\n onAbort,\n onCancel\n } = this.props;\n this.detach();\n\n if (!this.activated) {\n onAbort(this.props.active);\n }\n\n onCancel();\n }\n\n handleKeydown(event) {\n if (event.code === KeyboardCode.Esc) {\n this.handleCancel();\n }\n }\n\n removeTextSelection() {\n var _this$document$getSel;\n\n (_this$document$getSel = this.document.getSelection()) == null ? void 0 : _this$document$getSel.removeAllRanges();\n }\n\n}\n\nconst events = {\n cancel: {\n name: 'pointercancel'\n },\n move: {\n name: 'pointermove'\n },\n end: {\n name: 'pointerup'\n }\n};\nclass PointerSensor extends AbstractPointerSensor {\n constructor(props) {\n const {\n event\n } = props; // Pointer events stop firing if the target is unmounted while dragging\n // Therefore we attach listeners to the owner document instead\n\n const listenerTarget = getOwnerDocument(event.target);\n super(props, events, listenerTarget);\n }\n\n}\nPointerSensor.activators = [{\n eventName: 'onPointerDown',\n handler: (_ref, _ref2) => {\n let {\n nativeEvent: event\n } = _ref;\n let {\n onActivation\n } = _ref2;\n\n if (!event.isPrimary || event.button !== 0) {\n return false;\n }\n\n onActivation == null ? void 0 : onActivation({\n event\n });\n return true;\n }\n}];\n\nconst events$1 = {\n move: {\n name: 'mousemove'\n },\n end: {\n name: 'mouseup'\n }\n};\nvar MouseButton;\n\n(function (MouseButton) {\n MouseButton[MouseButton[\"RightClick\"] = 2] = \"RightClick\";\n})(MouseButton || (MouseButton = {}));\n\nclass MouseSensor extends AbstractPointerSensor {\n constructor(props) {\n super(props, events$1, getOwnerDocument(props.event.target));\n }\n\n}\nMouseSensor.activators = [{\n eventName: 'onMouseDown',\n handler: (_ref, _ref2) => {\n let {\n nativeEvent: event\n } = _ref;\n let {\n onActivation\n } = _ref2;\n\n if (event.button === MouseButton.RightClick) {\n return false;\n }\n\n onActivation == null ? void 0 : onActivation({\n event\n });\n return true;\n }\n}];\n\nconst events$2 = {\n cancel: {\n name: 'touchcancel'\n },\n move: {\n name: 'touchmove'\n },\n end: {\n name: 'touchend'\n }\n};\nclass TouchSensor extends AbstractPointerSensor {\n constructor(props) {\n super(props, events$2);\n }\n\n static setup() {\n // Adding a non-capture and non-passive `touchmove` listener in order\n // to force `event.preventDefault()` calls to work in dynamically added\n // touchmove event handlers. This is required for iOS Safari.\n window.addEventListener(events$2.move.name, noop, {\n capture: false,\n passive: false\n });\n return function teardown() {\n window.removeEventListener(events$2.move.name, noop);\n }; // We create a new handler because the teardown function of another sensor\n // could remove our event listener if we use a referentially equal listener.\n\n function noop() {}\n }\n\n}\nTouchSensor.activators = [{\n eventName: 'onTouchStart',\n handler: (_ref, _ref2) => {\n let {\n nativeEvent: event\n } = _ref;\n let {\n onActivation\n } = _ref2;\n const {\n touches\n } = event;\n\n if (touches.length > 1) {\n return false;\n }\n\n onActivation == null ? void 0 : onActivation({\n event\n });\n return true;\n }\n}];\n\nvar AutoScrollActivator;\n\n(function (AutoScrollActivator) {\n AutoScrollActivator[AutoScrollActivator[\"Pointer\"] = 0] = \"Pointer\";\n AutoScrollActivator[AutoScrollActivator[\"DraggableRect\"] = 1] = \"DraggableRect\";\n})(AutoScrollActivator || (AutoScrollActivator = {}));\n\nvar TraversalOrder;\n\n(function (TraversalOrder) {\n TraversalOrder[TraversalOrder[\"TreeOrder\"] = 0] = \"TreeOrder\";\n TraversalOrder[TraversalOrder[\"ReversedTreeOrder\"] = 1] = \"ReversedTreeOrder\";\n})(TraversalOrder || (TraversalOrder = {}));\n\nfunction useAutoScroller(_ref) {\n let {\n acceleration,\n activator = AutoScrollActivator.Pointer,\n canScroll,\n draggingRect,\n enabled,\n interval = 5,\n order = TraversalOrder.TreeOrder,\n pointerCoordinates,\n scrollableAncestors,\n scrollableAncestorRects,\n delta,\n threshold\n } = _ref;\n const scrollIntent = useScrollIntent({\n delta,\n disabled: !enabled\n });\n const [setAutoScrollInterval, clearAutoScrollInterval] = useInterval();\n const scrollSpeed = useRef({\n x: 0,\n y: 0\n });\n const scrollDirection = useRef({\n x: 0,\n y: 0\n });\n const rect = useMemo(() => {\n switch (activator) {\n case AutoScrollActivator.Pointer:\n return pointerCoordinates ? {\n top: pointerCoordinates.y,\n bottom: pointerCoordinates.y,\n left: pointerCoordinates.x,\n right: pointerCoordinates.x\n } : null;\n\n case AutoScrollActivator.DraggableRect:\n return draggingRect;\n }\n }, [activator, draggingRect, pointerCoordinates]);\n const scrollContainerRef = useRef(null);\n const autoScroll = useCallback(() => {\n const scrollContainer = scrollContainerRef.current;\n\n if (!scrollContainer) {\n return;\n }\n\n const scrollLeft = scrollSpeed.current.x * scrollDirection.current.x;\n const scrollTop = scrollSpeed.current.y * scrollDirection.current.y;\n scrollContainer.scrollBy(scrollLeft, scrollTop);\n }, []);\n const sortedScrollableAncestors = useMemo(() => order === TraversalOrder.TreeOrder ? [...scrollableAncestors].reverse() : scrollableAncestors, [order, scrollableAncestors]);\n useEffect(() => {\n if (!enabled || !scrollableAncestors.length || !rect) {\n clearAutoScrollInterval();\n return;\n }\n\n for (const scrollContainer of sortedScrollableAncestors) {\n if ((canScroll == null ? void 0 : canScroll(scrollContainer)) === false) {\n continue;\n }\n\n const index = scrollableAncestors.indexOf(scrollContainer);\n const scrollContainerRect = scrollableAncestorRects[index];\n\n if (!scrollContainerRect) {\n continue;\n }\n\n const {\n direction,\n speed\n } = getScrollDirectionAndSpeed(scrollContainer, scrollContainerRect, rect, acceleration, threshold);\n\n for (const axis of ['x', 'y']) {\n if (!scrollIntent[axis][direction[axis]]) {\n speed[axis] = 0;\n direction[axis] = 0;\n }\n }\n\n if (speed.x > 0 || speed.y > 0) {\n clearAutoScrollInterval();\n scrollContainerRef.current = scrollContainer;\n setAutoScrollInterval(autoScroll, interval);\n scrollSpeed.current = speed;\n scrollDirection.current = direction;\n return;\n }\n }\n\n scrollSpeed.current = {\n x: 0,\n y: 0\n };\n scrollDirection.current = {\n x: 0,\n y: 0\n };\n clearAutoScrollInterval();\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [acceleration, autoScroll, canScroll, clearAutoScrollInterval, enabled, interval, // eslint-disable-next-line react-hooks/exhaustive-deps\n JSON.stringify(rect), // eslint-disable-next-line react-hooks/exhaustive-deps\n JSON.stringify(scrollIntent), setAutoScrollInterval, scrollableAncestors, sortedScrollableAncestors, scrollableAncestorRects, // eslint-disable-next-line react-hooks/exhaustive-deps\n JSON.stringify(threshold)]);\n}\nconst defaultScrollIntent = {\n x: {\n [Direction.Backward]: false,\n [Direction.Forward]: false\n },\n y: {\n [Direction.Backward]: false,\n [Direction.Forward]: false\n }\n};\n\nfunction useScrollIntent(_ref2) {\n let {\n delta,\n disabled\n } = _ref2;\n const previousDelta = usePrevious(delta);\n return useLazyMemo(previousIntent => {\n if (disabled || !previousDelta || !previousIntent) {\n // Reset scroll intent tracking when auto-scrolling is disabled\n return defaultScrollIntent;\n }\n\n const direction = {\n x: Math.sign(delta.x - previousDelta.x),\n y: Math.sign(delta.y - previousDelta.y)\n }; // Keep track of the user intent to scroll in each direction for both axis\n\n return {\n x: {\n [Direction.Backward]: previousIntent.x[Direction.Backward] || direction.x === -1,\n [Direction.Forward]: previousIntent.x[Direction.Forward] || direction.x === 1\n },\n y: {\n [Direction.Backward]: previousIntent.y[Direction.Backward] || direction.y === -1,\n [Direction.Forward]: previousIntent.y[Direction.Forward] || direction.y === 1\n }\n };\n }, [disabled, delta, previousDelta]);\n}\n\nfunction useCachedNode(draggableNodes, id) {\n const draggableNode = id != null ? draggableNodes.get(id) : undefined;\n const node = draggableNode ? draggableNode.node.current : null;\n return useLazyMemo(cachedNode => {\n var _ref;\n\n if (id == null) {\n return null;\n } // In some cases, the draggable node can unmount while dragging\n // This is the case for virtualized lists. In those situations,\n // we fall back to the last known value for that node.\n\n\n return (_ref = node != null ? node : cachedNode) != null ? _ref : null;\n }, [node, id]);\n}\n\nfunction useCombineActivators(sensors, getSyntheticHandler) {\n return useMemo(() => sensors.reduce((accumulator, sensor) => {\n const {\n sensor: Sensor\n } = sensor;\n const sensorActivators = Sensor.activators.map(activator => ({\n eventName: activator.eventName,\n handler: getSyntheticHandler(activator.handler, sensor)\n }));\n return [...accumulator, ...sensorActivators];\n }, []), [sensors, getSyntheticHandler]);\n}\n\nvar MeasuringStrategy;\n\n(function (MeasuringStrategy) {\n MeasuringStrategy[MeasuringStrategy[\"Always\"] = 0] = \"Always\";\n MeasuringStrategy[MeasuringStrategy[\"BeforeDragging\"] = 1] = \"BeforeDragging\";\n MeasuringStrategy[MeasuringStrategy[\"WhileDragging\"] = 2] = \"WhileDragging\";\n})(MeasuringStrategy || (MeasuringStrategy = {}));\n\nvar MeasuringFrequency;\n\n(function (MeasuringFrequency) {\n MeasuringFrequency[\"Optimized\"] = \"optimized\";\n})(MeasuringFrequency || (MeasuringFrequency = {}));\n\nconst defaultValue = /*#__PURE__*/new Map();\nfunction useDroppableMeasuring(containers, _ref) {\n let {\n dragging,\n dependencies,\n config\n } = _ref;\n const [queue, setQueue] = useState(null);\n const {\n frequency,\n measure,\n strategy\n } = config;\n const containersRef = useRef(containers);\n const disabled = isDisabled();\n const disabledRef = useLatestValue(disabled);\n const measureDroppableContainers = useCallback(function (ids) {\n if (ids === void 0) {\n ids = [];\n }\n\n if (disabledRef.current) {\n return;\n }\n\n setQueue(value => {\n if (value === null) {\n return ids;\n }\n\n return value.concat(ids.filter(id => !value.includes(id)));\n });\n }, [disabledRef]);\n const timeoutId = useRef(null);\n const droppableRects = useLazyMemo(previousValue => {\n if (disabled && !dragging) {\n return defaultValue;\n }\n\n if (!previousValue || previousValue === defaultValue || containersRef.current !== containers || queue != null) {\n const map = new Map();\n\n for (let container of containers) {\n if (!container) {\n continue;\n }\n\n if (queue && queue.length > 0 && !queue.includes(container.id) && container.rect.current) {\n // This container does not need to be re-measured\n map.set(container.id, container.rect.current);\n continue;\n }\n\n const node = container.node.current;\n const rect = node ? new Rect(measure(node), node) : null;\n container.rect.current = rect;\n\n if (rect) {\n map.set(container.id, rect);\n }\n }\n\n return map;\n }\n\n return previousValue;\n }, [containers, queue, dragging, disabled, measure]);\n useEffect(() => {\n containersRef.current = containers;\n }, [containers]);\n useEffect(() => {\n if (disabled) {\n return;\n }\n\n measureDroppableContainers();\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [dragging, disabled]);\n useEffect(() => {\n if (queue && queue.length > 0) {\n setQueue(null);\n }\n }, //eslint-disable-next-line react-hooks/exhaustive-deps\n [JSON.stringify(queue)]);\n useEffect(() => {\n if (disabled || typeof frequency !== 'number' || timeoutId.current !== null) {\n return;\n }\n\n timeoutId.current = setTimeout(() => {\n measureDroppableContainers();\n timeoutId.current = null;\n }, frequency);\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [frequency, disabled, measureDroppableContainers, ...dependencies]);\n return {\n droppableRects,\n measureDroppableContainers,\n measuringScheduled: queue != null\n };\n\n function isDisabled() {\n switch (strategy) {\n case MeasuringStrategy.Always:\n return false;\n\n case MeasuringStrategy.BeforeDragging:\n return dragging;\n\n default:\n return !dragging;\n }\n }\n}\n\nfunction useInitialValue(value, computeFn) {\n return useLazyMemo(previousValue => {\n if (!value) {\n return null;\n }\n\n if (previousValue) {\n return previousValue;\n }\n\n return typeof computeFn === 'function' ? computeFn(value) : value;\n }, [computeFn, value]);\n}\n\nfunction useInitialRect(node, measure) {\n return useInitialValue(node, measure);\n}\n\n/**\r\n * Returns a new MutationObserver instance.\r\n * If `MutationObserver` is undefined in the execution environment, returns `undefined`.\r\n */\n\nfunction useMutationObserver(_ref) {\n let {\n callback,\n disabled\n } = _ref;\n const handleMutations = useEvent(callback);\n const mutationObserver = useMemo(() => {\n if (disabled || typeof window === 'undefined' || typeof window.MutationObserver === 'undefined') {\n return undefined;\n }\n\n const {\n MutationObserver\n } = window;\n return new MutationObserver(handleMutations);\n }, [handleMutations, disabled]);\n useEffect(() => {\n return () => mutationObserver == null ? void 0 : mutationObserver.disconnect();\n }, [mutationObserver]);\n return mutationObserver;\n}\n\n/**\r\n * Returns a new ResizeObserver instance bound to the `onResize` callback.\r\n * If `ResizeObserver` is undefined in the execution environment, returns `undefined`.\r\n */\n\nfunction useResizeObserver(_ref) {\n let {\n callback,\n disabled\n } = _ref;\n const handleResize = useEvent(callback);\n const resizeObserver = useMemo(() => {\n if (disabled || typeof window === 'undefined' || typeof window.ResizeObserver === 'undefined') {\n return undefined;\n }\n\n const {\n ResizeObserver\n } = window;\n return new ResizeObserver(handleResize);\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [disabled]);\n useEffect(() => {\n return () => resizeObserver == null ? void 0 : resizeObserver.disconnect();\n }, [resizeObserver]);\n return resizeObserver;\n}\n\nfunction defaultMeasure(element) {\n return new Rect(getClientRect(element), element);\n}\n\nfunction useRect(element, measure, fallbackRect) {\n if (measure === void 0) {\n measure = defaultMeasure;\n }\n\n const [rect, setRect] = useState(null);\n\n function measureRect() {\n setRect(currentRect => {\n if (!element) {\n return null;\n }\n\n if (element.isConnected === false) {\n var _ref;\n\n // Fall back to last rect we measured if the element is\n // no longer connected to the DOM.\n return (_ref = currentRect != null ? currentRect : fallbackRect) != null ? _ref : null;\n }\n\n const newRect = measure(element);\n\n if (JSON.stringify(currentRect) === JSON.stringify(newRect)) {\n return currentRect;\n }\n\n return newRect;\n });\n }\n\n const mutationObserver = useMutationObserver({\n callback(records) {\n if (!element) {\n return;\n }\n\n for (const record of records) {\n const {\n type,\n target\n } = record;\n\n if (type === 'childList' && target instanceof HTMLElement && target.contains(element)) {\n measureRect();\n break;\n }\n }\n }\n\n });\n const resizeObserver = useResizeObserver({\n callback: measureRect\n });\n useIsomorphicLayoutEffect(() => {\n measureRect();\n\n if (element) {\n resizeObserver == null ? void 0 : resizeObserver.observe(element);\n mutationObserver == null ? void 0 : mutationObserver.observe(document.body, {\n childList: true,\n subtree: true\n });\n } else {\n resizeObserver == null ? void 0 : resizeObserver.disconnect();\n mutationObserver == null ? void 0 : mutationObserver.disconnect();\n }\n }, [element]);\n return rect;\n}\n\nfunction useRectDelta(rect) {\n const initialRect = useInitialValue(rect);\n return getRectDelta(rect, initialRect);\n}\n\nconst defaultValue$1 = [];\nfunction useScrollableAncestors(node) {\n const previousNode = useRef(node);\n const ancestors = useLazyMemo(previousValue => {\n if (!node) {\n return defaultValue$1;\n }\n\n if (previousValue && previousValue !== defaultValue$1 && node && previousNode.current && node.parentNode === previousNode.current.parentNode) {\n return previousValue;\n }\n\n return getScrollableAncestors(node);\n }, [node]);\n useEffect(() => {\n previousNode.current = node;\n }, [node]);\n return ancestors;\n}\n\nfunction useScrollOffsets(elements) {\n const [scrollCoordinates, setScrollCoordinates] = useState(null);\n const prevElements = useRef(elements); // To-do: Throttle the handleScroll callback\n\n const handleScroll = useCallback(event => {\n const scrollingElement = getScrollableElement(event.target);\n\n if (!scrollingElement) {\n return;\n }\n\n setScrollCoordinates(scrollCoordinates => {\n if (!scrollCoordinates) {\n return null;\n }\n\n scrollCoordinates.set(scrollingElement, getScrollCoordinates(scrollingElement));\n return new Map(scrollCoordinates);\n });\n }, []);\n useEffect(() => {\n const previousElements = prevElements.current;\n\n if (elements !== previousElements) {\n cleanup(previousElements);\n const entries = elements.map(element => {\n const scrollableElement = getScrollableElement(element);\n\n if (scrollableElement) {\n scrollableElement.addEventListener('scroll', handleScroll, {\n passive: true\n });\n return [scrollableElement, getScrollCoordinates(scrollableElement)];\n }\n\n return null;\n }).filter(entry => entry != null);\n setScrollCoordinates(entries.length ? new Map(entries) : null);\n prevElements.current = elements;\n }\n\n return () => {\n cleanup(elements);\n cleanup(previousElements);\n };\n\n function cleanup(elements) {\n elements.forEach(element => {\n const scrollableElement = getScrollableElement(element);\n scrollableElement == null ? void 0 : scrollableElement.removeEventListener('scroll', handleScroll);\n });\n }\n }, [handleScroll, elements]);\n return useMemo(() => {\n if (elements.length) {\n return scrollCoordinates ? Array.from(scrollCoordinates.values()).reduce((acc, coordinates) => add(acc, coordinates), defaultCoordinates) : getScrollOffsets(elements);\n }\n\n return defaultCoordinates;\n }, [elements, scrollCoordinates]);\n}\n\nfunction useScrollOffsetsDelta(scrollOffsets, dependencies) {\n if (dependencies === void 0) {\n dependencies = [];\n }\n\n const initialScrollOffsets = useRef(null);\n useEffect(() => {\n initialScrollOffsets.current = null;\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n dependencies);\n useEffect(() => {\n const hasScrollOffsets = scrollOffsets !== defaultCoordinates;\n\n if (hasScrollOffsets && !initialScrollOffsets.current) {\n initialScrollOffsets.current = scrollOffsets;\n }\n\n if (!hasScrollOffsets && initialScrollOffsets.current) {\n initialScrollOffsets.current = null;\n }\n }, [scrollOffsets]);\n return initialScrollOffsets.current ? subtract(scrollOffsets, initialScrollOffsets.current) : defaultCoordinates;\n}\n\nfunction useSensorSetup(sensors) {\n useEffect(() => {\n if (!canUseDOM) {\n return;\n }\n\n const teardownFns = sensors.map(_ref => {\n let {\n sensor\n } = _ref;\n return sensor.setup == null ? void 0 : sensor.setup();\n });\n return () => {\n for (const teardown of teardownFns) {\n teardown == null ? void 0 : teardown();\n }\n };\n }, // TO-DO: Sensors length could theoretically change which would not be a valid dependency\n // eslint-disable-next-line react-hooks/exhaustive-deps\n sensors.map(_ref2 => {\n let {\n sensor\n } = _ref2;\n return sensor;\n }));\n}\n\nfunction useSyntheticListeners(listeners, id) {\n return useMemo(() => {\n return listeners.reduce((acc, _ref) => {\n let {\n eventName,\n handler\n } = _ref;\n\n acc[eventName] = event => {\n handler(event, id);\n };\n\n return acc;\n }, {});\n }, [listeners, id]);\n}\n\nfunction useWindowRect(element) {\n return useMemo(() => element ? getWindowClientRect(element) : null, [element]);\n}\n\nconst defaultValue$2 = [];\nfunction useRects(elements, measure) {\n if (measure === void 0) {\n measure = getClientRect;\n }\n\n const [firstElement] = elements;\n const windowRect = useWindowRect(firstElement ? getWindow(firstElement) : null);\n const [rects, setRects] = useState(defaultValue$2);\n\n function measureRects() {\n setRects(() => {\n if (!elements.length) {\n return defaultValue$2;\n }\n\n return elements.map(element => isDocumentScrollingElement(element) ? windowRect : new Rect(measure(element), element));\n });\n }\n\n const resizeObserver = useResizeObserver({\n callback: measureRects\n });\n useIsomorphicLayoutEffect(() => {\n resizeObserver == null ? void 0 : resizeObserver.disconnect();\n measureRects();\n elements.forEach(element => resizeObserver == null ? void 0 : resizeObserver.observe(element));\n }, [elements]);\n return rects;\n}\n\nfunction getMeasurableNode(node) {\n if (!node) {\n return null;\n }\n\n if (node.children.length > 1) {\n return node;\n }\n\n const firstChild = node.children[0];\n return isHTMLElement(firstChild) ? firstChild : node;\n}\n\nfunction useDragOverlayMeasuring(_ref) {\n let {\n measure\n } = _ref;\n const [rect, setRect] = useState(null);\n const handleResize = useCallback(entries => {\n for (const {\n target\n } of entries) {\n if (isHTMLElement(target)) {\n setRect(rect => {\n const newRect = measure(target);\n return rect ? { ...rect,\n width: newRect.width,\n height: newRect.height\n } : newRect;\n });\n break;\n }\n }\n }, [measure]);\n const resizeObserver = useResizeObserver({\n callback: handleResize\n });\n const handleNodeChange = useCallback(element => {\n const node = getMeasurableNode(element);\n resizeObserver == null ? void 0 : resizeObserver.disconnect();\n\n if (node) {\n resizeObserver == null ? void 0 : resizeObserver.observe(node);\n }\n\n setRect(node ? measure(node) : null);\n }, [measure, resizeObserver]);\n const [nodeRef, setRef] = useNodeRef(handleNodeChange);\n return useMemo(() => ({\n nodeRef,\n rect,\n setRef\n }), [rect, nodeRef, setRef]);\n}\n\nconst defaultSensors = [{\n sensor: PointerSensor,\n options: {}\n}, {\n sensor: KeyboardSensor,\n options: {}\n}];\nconst defaultData = {\n current: {}\n};\nconst defaultMeasuringConfiguration = {\n draggable: {\n measure: getTransformAgnosticClientRect\n },\n droppable: {\n measure: getTransformAgnosticClientRect,\n strategy: MeasuringStrategy.WhileDragging,\n frequency: MeasuringFrequency.Optimized\n },\n dragOverlay: {\n measure: getClientRect\n }\n};\n\nclass DroppableContainersMap extends Map {\n get(id) {\n var _super$get;\n\n return id != null ? (_super$get = super.get(id)) != null ? _super$get : undefined : undefined;\n }\n\n toArray() {\n return Array.from(this.values());\n }\n\n getEnabled() {\n return this.toArray().filter(_ref => {\n let {\n disabled\n } = _ref;\n return !disabled;\n });\n }\n\n getNodeFor(id) {\n var _this$get$node$curren, _this$get;\n\n return (_this$get$node$curren = (_this$get = this.get(id)) == null ? void 0 : _this$get.node.current) != null ? _this$get$node$curren : undefined;\n }\n\n}\n\nconst defaultPublicContext = {\n activatorEvent: null,\n active: null,\n activeNode: null,\n activeNodeRect: null,\n collisions: null,\n containerNodeRect: null,\n draggableNodes: /*#__PURE__*/new Map(),\n droppableRects: /*#__PURE__*/new Map(),\n droppableContainers: /*#__PURE__*/new DroppableContainersMap(),\n over: null,\n dragOverlay: {\n nodeRef: {\n current: null\n },\n rect: null,\n setRef: noop\n },\n scrollableAncestors: [],\n scrollableAncestorRects: [],\n measuringConfiguration: defaultMeasuringConfiguration,\n measureDroppableContainers: noop,\n windowRect: null,\n measuringScheduled: false\n};\nconst defaultInternalContext = {\n activatorEvent: null,\n activators: [],\n active: null,\n activeNodeRect: null,\n ariaDescribedById: {\n draggable: ''\n },\n dispatch: noop,\n draggableNodes: /*#__PURE__*/new Map(),\n over: null,\n measureDroppableContainers: noop\n};\nconst InternalContext = /*#__PURE__*/createContext(defaultInternalContext);\nconst PublicContext = /*#__PURE__*/createContext(defaultPublicContext);\n\nfunction getInitialState() {\n return {\n draggable: {\n active: null,\n initialCoordinates: {\n x: 0,\n y: 0\n },\n nodes: new Map(),\n translate: {\n x: 0,\n y: 0\n }\n },\n droppable: {\n containers: new DroppableContainersMap()\n }\n };\n}\nfunction reducer(state, action) {\n switch (action.type) {\n case Action.DragStart:\n return { ...state,\n draggable: { ...state.draggable,\n initialCoordinates: action.initialCoordinates,\n active: action.active\n }\n };\n\n case Action.DragMove:\n if (state.draggable.active == null) {\n return state;\n }\n\n return { ...state,\n draggable: { ...state.draggable,\n translate: {\n x: action.coordinates.x - state.draggable.initialCoordinates.x,\n y: action.coordinates.y - state.draggable.initialCoordinates.y\n }\n }\n };\n\n case Action.DragEnd:\n case Action.DragCancel:\n return { ...state,\n draggable: { ...state.draggable,\n active: null,\n initialCoordinates: {\n x: 0,\n y: 0\n },\n translate: {\n x: 0,\n y: 0\n }\n }\n };\n\n case Action.RegisterDroppable:\n {\n const {\n element\n } = action;\n const {\n id\n } = element;\n const containers = new DroppableContainersMap(state.droppable.containers);\n containers.set(id, element);\n return { ...state,\n droppable: { ...state.droppable,\n containers\n }\n };\n }\n\n case Action.SetDroppableDisabled:\n {\n const {\n id,\n key,\n disabled\n } = action;\n const element = state.droppable.containers.get(id);\n\n if (!element || key !== element.key) {\n return state;\n }\n\n const containers = new DroppableContainersMap(state.droppable.containers);\n containers.set(id, { ...element,\n disabled\n });\n return { ...state,\n droppable: { ...state.droppable,\n containers\n }\n };\n }\n\n case Action.UnregisterDroppable:\n {\n const {\n id,\n key\n } = action;\n const element = state.droppable.containers.get(id);\n\n if (!element || key !== element.key) {\n return state;\n }\n\n const containers = new DroppableContainersMap(state.droppable.containers);\n containers.delete(id);\n return { ...state,\n droppable: { ...state.droppable,\n containers\n }\n };\n }\n\n default:\n {\n return state;\n }\n }\n}\n\nfunction RestoreFocus(_ref) {\n let {\n disabled\n } = _ref;\n const {\n active,\n activatorEvent,\n draggableNodes\n } = useContext(InternalContext);\n const previousActivatorEvent = usePrevious(activatorEvent);\n const previousActiveId = usePrevious(active == null ? void 0 : active.id); // Restore keyboard focus on the activator node\n\n useEffect(() => {\n if (disabled) {\n return;\n }\n\n if (!activatorEvent && previousActivatorEvent && previousActiveId != null) {\n if (!isKeyboardEvent(previousActivatorEvent)) {\n return;\n }\n\n if (document.activeElement === previousActivatorEvent.target) {\n // No need to restore focus\n return;\n }\n\n const draggableNode = draggableNodes.get(previousActiveId);\n\n if (!draggableNode) {\n return;\n }\n\n const {\n activatorNode,\n node\n } = draggableNode;\n\n if (!activatorNode.current && !node.current) {\n return;\n }\n\n requestAnimationFrame(() => {\n for (const element of [activatorNode.current, node.current]) {\n if (!element) {\n continue;\n }\n\n const focusableNode = findFirstFocusableNode(element);\n\n if (focusableNode) {\n focusableNode.focus();\n break;\n }\n }\n });\n }\n }, [activatorEvent, disabled, draggableNodes, previousActiveId, previousActivatorEvent]);\n return null;\n}\n\nfunction applyModifiers(modifiers, _ref) {\n let {\n transform,\n ...args\n } = _ref;\n return modifiers != null && modifiers.length ? modifiers.reduce((accumulator, modifier) => {\n return modifier({\n transform: accumulator,\n ...args\n });\n }, transform) : transform;\n}\n\nfunction useMeasuringConfiguration(config) {\n return useMemo(() => ({\n draggable: { ...defaultMeasuringConfiguration.draggable,\n ...(config == null ? void 0 : config.draggable)\n },\n droppable: { ...defaultMeasuringConfiguration.droppable,\n ...(config == null ? void 0 : config.droppable)\n },\n dragOverlay: { ...defaultMeasuringConfiguration.dragOverlay,\n ...(config == null ? void 0 : config.dragOverlay)\n }\n }), // eslint-disable-next-line react-hooks/exhaustive-deps\n [config == null ? void 0 : config.draggable, config == null ? void 0 : config.droppable, config == null ? void 0 : config.dragOverlay]);\n}\n\nfunction useLayoutShiftScrollCompensation(_ref) {\n let {\n activeNode,\n measure,\n initialRect,\n config = true\n } = _ref;\n const initialized = useRef(false);\n const {\n x,\n y\n } = typeof config === 'boolean' ? {\n x: config,\n y: config\n } : config;\n useIsomorphicLayoutEffect(() => {\n const disabled = !x && !y;\n\n if (disabled || !activeNode) {\n initialized.current = false;\n return;\n }\n\n if (initialized.current || !initialRect) {\n // Return early if layout shift scroll compensation was already attempted\n // or if there is no initialRect to compare to.\n return;\n } // Get the most up to date node ref for the active draggable\n\n\n const node = activeNode == null ? void 0 : activeNode.node.current;\n\n if (!node || node.isConnected === false) {\n // Return early if there is no attached node ref or if the node is\n // disconnected from the document.\n return;\n }\n\n const rect = measure(node);\n const rectDelta = getRectDelta(rect, initialRect);\n\n if (!x) {\n rectDelta.x = 0;\n }\n\n if (!y) {\n rectDelta.y = 0;\n } // Only perform layout shift scroll compensation once\n\n\n initialized.current = true;\n\n if (Math.abs(rectDelta.x) > 0 || Math.abs(rectDelta.y) > 0) {\n const firstScrollableAncestor = getFirstScrollableAncestor(node);\n\n if (firstScrollableAncestor) {\n firstScrollableAncestor.scrollBy({\n top: rectDelta.y,\n left: rectDelta.x\n });\n }\n }\n }, [activeNode, x, y, initialRect, measure]);\n}\n\nconst ActiveDraggableContext = /*#__PURE__*/createContext({ ...defaultCoordinates,\n scaleX: 1,\n scaleY: 1\n});\nvar Status;\n\n(function (Status) {\n Status[Status[\"Uninitialized\"] = 0] = \"Uninitialized\";\n Status[Status[\"Initializing\"] = 1] = \"Initializing\";\n Status[Status[\"Initialized\"] = 2] = \"Initialized\";\n})(Status || (Status = {}));\n\nconst DndContext = /*#__PURE__*/memo(function DndContext(_ref) {\n var _sensorContext$curren, _dragOverlay$nodeRef$, _dragOverlay$rect, _over$rect;\n\n let {\n id,\n accessibility,\n autoScroll = true,\n children,\n sensors = defaultSensors,\n collisionDetection = rectIntersection,\n measuring,\n modifiers,\n ...props\n } = _ref;\n const store = useReducer(reducer, undefined, getInitialState);\n const [state, dispatch] = store;\n const [dispatchMonitorEvent, registerMonitorListener] = useDndMonitorProvider();\n const [status, setStatus] = useState(Status.Uninitialized);\n const isInitialized = status === Status.Initialized;\n const {\n draggable: {\n active: activeId,\n nodes: draggableNodes,\n translate\n },\n droppable: {\n containers: droppableContainers\n }\n } = state;\n const node = activeId != null ? draggableNodes.get(activeId) : null;\n const activeRects = useRef({\n initial: null,\n translated: null\n });\n const active = useMemo(() => {\n var _node$data;\n\n return activeId != null ? {\n id: activeId,\n // It's possible for the active node to unmount while dragging\n data: (_node$data = node == null ? void 0 : node.data) != null ? _node$data : defaultData,\n rect: activeRects\n } : null;\n }, [activeId, node]);\n const activeRef = useRef(null);\n const [activeSensor, setActiveSensor] = useState(null);\n const [activatorEvent, setActivatorEvent] = useState(null);\n const latestProps = useLatestValue(props, Object.values(props));\n const draggableDescribedById = useUniqueId(\"DndDescribedBy\", id);\n const enabledDroppableContainers = useMemo(() => droppableContainers.getEnabled(), [droppableContainers]);\n const measuringConfiguration = useMeasuringConfiguration(measuring);\n const {\n droppableRects,\n measureDroppableContainers,\n measuringScheduled\n } = useDroppableMeasuring(enabledDroppableContainers, {\n dragging: isInitialized,\n dependencies: [translate.x, translate.y],\n config: measuringConfiguration.droppable\n });\n const activeNode = useCachedNode(draggableNodes, activeId);\n const activationCoordinates = useMemo(() => activatorEvent ? getEventCoordinates(activatorEvent) : null, [activatorEvent]);\n const autoScrollOptions = getAutoScrollerOptions();\n const initialActiveNodeRect = useInitialRect(activeNode, measuringConfiguration.draggable.measure);\n useLayoutShiftScrollCompensation({\n activeNode: activeId != null ? draggableNodes.get(activeId) : null,\n config: autoScrollOptions.layoutShiftCompensation,\n initialRect: initialActiveNodeRect,\n measure: measuringConfiguration.draggable.measure\n });\n const activeNodeRect = useRect(activeNode, measuringConfiguration.draggable.measure, initialActiveNodeRect);\n const containerNodeRect = useRect(activeNode ? activeNode.parentElement : null);\n const sensorContext = useRef({\n activatorEvent: null,\n active: null,\n activeNode,\n collisionRect: null,\n collisions: null,\n droppableRects,\n draggableNodes,\n draggingNode: null,\n draggingNodeRect: null,\n droppableContainers,\n over: null,\n scrollableAncestors: [],\n scrollAdjustedTranslate: null\n });\n const overNode = droppableContainers.getNodeFor((_sensorContext$curren = sensorContext.current.over) == null ? void 0 : _sensorContext$curren.id);\n const dragOverlay = useDragOverlayMeasuring({\n measure: measuringConfiguration.dragOverlay.measure\n }); // Use the rect of the drag overlay if it is mounted\n\n const draggingNode = (_dragOverlay$nodeRef$ = dragOverlay.nodeRef.current) != null ? _dragOverlay$nodeRef$ : activeNode;\n const draggingNodeRect = isInitialized ? (_dragOverlay$rect = dragOverlay.rect) != null ? _dragOverlay$rect : activeNodeRect : null;\n const usesDragOverlay = Boolean(dragOverlay.nodeRef.current && dragOverlay.rect); // The delta between the previous and new position of the draggable node\n // is only relevant when there is no drag overlay\n\n const nodeRectDelta = useRectDelta(usesDragOverlay ? null : activeNodeRect); // Get the window rect of the dragging node\n\n const windowRect = useWindowRect(draggingNode ? getWindow(draggingNode) : null); // Get scrollable ancestors of the dragging node\n\n const scrollableAncestors = useScrollableAncestors(isInitialized ? overNode != null ? overNode : activeNode : null);\n const scrollableAncestorRects = useRects(scrollableAncestors); // Apply modifiers\n\n const modifiedTranslate = applyModifiers(modifiers, {\n transform: {\n x: translate.x - nodeRectDelta.x,\n y: translate.y - nodeRectDelta.y,\n scaleX: 1,\n scaleY: 1\n },\n activatorEvent,\n active,\n activeNodeRect,\n containerNodeRect,\n draggingNodeRect,\n over: sensorContext.current.over,\n overlayNodeRect: dragOverlay.rect,\n scrollableAncestors,\n scrollableAncestorRects,\n windowRect\n });\n const pointerCoordinates = activationCoordinates ? add(activationCoordinates, translate) : null;\n const scrollOffsets = useScrollOffsets(scrollableAncestors); // Represents the scroll delta since dragging was initiated\n\n const scrollAdjustment = useScrollOffsetsDelta(scrollOffsets); // Represents the scroll delta since the last time the active node rect was measured\n\n const activeNodeScrollDelta = useScrollOffsetsDelta(scrollOffsets, [activeNodeRect]);\n const scrollAdjustedTranslate = add(modifiedTranslate, scrollAdjustment);\n const collisionRect = draggingNodeRect ? getAdjustedRect(draggingNodeRect, modifiedTranslate) : null;\n const collisions = active && collisionRect ? collisionDetection({\n active,\n collisionRect,\n droppableRects,\n droppableContainers: enabledDroppableContainers,\n pointerCoordinates\n }) : null;\n const overId = getFirstCollision(collisions, 'id');\n const [over, setOver] = useState(null); // When there is no drag overlay used, we need to account for the\n // window scroll delta\n\n const appliedTranslate = usesDragOverlay ? modifiedTranslate : add(modifiedTranslate, activeNodeScrollDelta);\n const transform = adjustScale(appliedTranslate, (_over$rect = over == null ? void 0 : over.rect) != null ? _over$rect : null, activeNodeRect);\n const activeSensorRef = useRef(null);\n const instantiateSensor = useCallback((event, _ref2) => {\n let {\n sensor: Sensor,\n options\n } = _ref2;\n\n if (activeRef.current == null) {\n return;\n }\n\n const activeNode = draggableNodes.get(activeRef.current);\n\n if (!activeNode) {\n return;\n }\n\n const activatorEvent = event.nativeEvent;\n const sensorInstance = new Sensor({\n active: activeRef.current,\n activeNode,\n event: activatorEvent,\n options,\n // Sensors need to be instantiated with refs for arguments that change over time\n // otherwise they are frozen in time with the stale arguments\n context: sensorContext,\n\n onAbort(id) {\n const draggableNode = draggableNodes.get(id);\n\n if (!draggableNode) {\n return;\n }\n\n const {\n onDragAbort\n } = latestProps.current;\n const event = {\n id\n };\n onDragAbort == null ? void 0 : onDragAbort(event);\n dispatchMonitorEvent({\n type: 'onDragAbort',\n event\n });\n },\n\n onPending(id, constraint, initialCoordinates, offset) {\n const draggableNode = draggableNodes.get(id);\n\n if (!draggableNode) {\n return;\n }\n\n const {\n onDragPending\n } = latestProps.current;\n const event = {\n id,\n constraint,\n initialCoordinates,\n offset\n };\n onDragPending == null ? void 0 : onDragPending(event);\n dispatchMonitorEvent({\n type: 'onDragPending',\n event\n });\n },\n\n onStart(initialCoordinates) {\n const id = activeRef.current;\n\n if (id == null) {\n return;\n }\n\n const draggableNode = draggableNodes.get(id);\n\n if (!draggableNode) {\n return;\n }\n\n const {\n onDragStart\n } = latestProps.current;\n const event = {\n activatorEvent,\n active: {\n id,\n data: draggableNode.data,\n rect: activeRects\n }\n };\n unstable_batchedUpdates(() => {\n onDragStart == null ? void 0 : onDragStart(event);\n setStatus(Status.Initializing);\n dispatch({\n type: Action.DragStart,\n initialCoordinates,\n active: id\n });\n dispatchMonitorEvent({\n type: 'onDragStart',\n event\n });\n setActiveSensor(activeSensorRef.current);\n setActivatorEvent(activatorEvent);\n });\n },\n\n onMove(coordinates) {\n dispatch({\n type: Action.DragMove,\n coordinates\n });\n },\n\n onEnd: createHandler(Action.DragEnd),\n onCancel: createHandler(Action.DragCancel)\n });\n activeSensorRef.current = sensorInstance;\n\n function createHandler(type) {\n return async function handler() {\n const {\n active,\n collisions,\n over,\n scrollAdjustedTranslate\n } = sensorContext.current;\n let event = null;\n\n if (active && scrollAdjustedTranslate) {\n const {\n cancelDrop\n } = latestProps.current;\n event = {\n activatorEvent,\n active: active,\n collisions,\n delta: scrollAdjustedTranslate,\n over\n };\n\n if (type === Action.DragEnd && typeof cancelDrop === 'function') {\n const shouldCancel = await Promise.resolve(cancelDrop(event));\n\n if (shouldCancel) {\n type = Action.DragCancel;\n }\n }\n }\n\n activeRef.current = null;\n unstable_batchedUpdates(() => {\n dispatch({\n type\n });\n setStatus(Status.Uninitialized);\n setOver(null);\n setActiveSensor(null);\n setActivatorEvent(null);\n activeSensorRef.current = null;\n const eventName = type === Action.DragEnd ? 'onDragEnd' : 'onDragCancel';\n\n if (event) {\n const handler = latestProps.current[eventName];\n handler == null ? void 0 : handler(event);\n dispatchMonitorEvent({\n type: eventName,\n event\n });\n }\n });\n };\n }\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [draggableNodes]);\n const bindActivatorToSensorInstantiator = useCallback((handler, sensor) => {\n return (event, active) => {\n const nativeEvent = event.nativeEvent;\n const activeDraggableNode = draggableNodes.get(active);\n\n if ( // Another sensor is already instantiating\n activeRef.current !== null || // No active draggable\n !activeDraggableNode || // Event has already been captured\n nativeEvent.dndKit || nativeEvent.defaultPrevented) {\n return;\n }\n\n const activationContext = {\n active: activeDraggableNode\n };\n const shouldActivate = handler(event, sensor.options, activationContext);\n\n if (shouldActivate === true) {\n nativeEvent.dndKit = {\n capturedBy: sensor.sensor\n };\n activeRef.current = active;\n instantiateSensor(event, sensor);\n }\n };\n }, [draggableNodes, instantiateSensor]);\n const activators = useCombineActivators(sensors, bindActivatorToSensorInstantiator);\n useSensorSetup(sensors);\n useIsomorphicLayoutEffect(() => {\n if (activeNodeRect && status === Status.Initializing) {\n setStatus(Status.Initialized);\n }\n }, [activeNodeRect, status]);\n useEffect(() => {\n const {\n onDragMove\n } = latestProps.current;\n const {\n active,\n activatorEvent,\n collisions,\n over\n } = sensorContext.current;\n\n if (!active || !activatorEvent) {\n return;\n }\n\n const event = {\n active,\n activatorEvent,\n collisions,\n delta: {\n x: scrollAdjustedTranslate.x,\n y: scrollAdjustedTranslate.y\n },\n over\n };\n unstable_batchedUpdates(() => {\n onDragMove == null ? void 0 : onDragMove(event);\n dispatchMonitorEvent({\n type: 'onDragMove',\n event\n });\n });\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [scrollAdjustedTranslate.x, scrollAdjustedTranslate.y]);\n useEffect(() => {\n const {\n active,\n activatorEvent,\n collisions,\n droppableContainers,\n scrollAdjustedTranslate\n } = sensorContext.current;\n\n if (!active || activeRef.current == null || !activatorEvent || !scrollAdjustedTranslate) {\n return;\n }\n\n const {\n onDragOver\n } = latestProps.current;\n const overContainer = droppableContainers.get(overId);\n const over = overContainer && overContainer.rect.current ? {\n id: overContainer.id,\n rect: overContainer.rect.current,\n data: overContainer.data,\n disabled: overContainer.disabled\n } : null;\n const event = {\n active,\n activatorEvent,\n collisions,\n delta: {\n x: scrollAdjustedTranslate.x,\n y: scrollAdjustedTranslate.y\n },\n over\n };\n unstable_batchedUpdates(() => {\n setOver(over);\n onDragOver == null ? void 0 : onDragOver(event);\n dispatchMonitorEvent({\n type: 'onDragOver',\n event\n });\n });\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [overId]);\n useIsomorphicLayoutEffect(() => {\n sensorContext.current = {\n activatorEvent,\n active,\n activeNode,\n collisionRect,\n collisions,\n droppableRects,\n draggableNodes,\n draggingNode,\n draggingNodeRect,\n droppableContainers,\n over,\n scrollableAncestors,\n scrollAdjustedTranslate\n };\n activeRects.current = {\n initial: draggingNodeRect,\n translated: collisionRect\n };\n }, [active, activeNode, collisions, collisionRect, draggableNodes, draggingNode, draggingNodeRect, droppableRects, droppableContainers, over, scrollableAncestors, scrollAdjustedTranslate]);\n useAutoScroller({ ...autoScrollOptions,\n delta: translate,\n draggingRect: collisionRect,\n pointerCoordinates,\n scrollableAncestors,\n scrollableAncestorRects\n });\n const publicContext = useMemo(() => {\n const context = {\n active,\n activeNode,\n activeNodeRect,\n activatorEvent,\n collisions,\n containerNodeRect,\n dragOverlay,\n draggableNodes,\n droppableContainers,\n droppableRects,\n over,\n measureDroppableContainers,\n scrollableAncestors,\n scrollableAncestorRects,\n measuringConfiguration,\n measuringScheduled,\n windowRect\n };\n return context;\n }, [active, activeNode, activeNodeRect, activatorEvent, collisions, containerNodeRect, dragOverlay, draggableNodes, droppableContainers, droppableRects, over, measureDroppableContainers, scrollableAncestors, scrollableAncestorRects, measuringConfiguration, measuringScheduled, windowRect]);\n const internalContext = useMemo(() => {\n const context = {\n activatorEvent,\n activators,\n active,\n activeNodeRect,\n ariaDescribedById: {\n draggable: draggableDescribedById\n },\n dispatch,\n draggableNodes,\n over,\n measureDroppableContainers\n };\n return context;\n }, [activatorEvent, activators, active, activeNodeRect, dispatch, draggableDescribedById, draggableNodes, over, measureDroppableContainers]);\n return React.createElement(DndMonitorContext.Provider, {\n value: registerMonitorListener\n }, React.createElement(InternalContext.Provider, {\n value: internalContext\n }, React.createElement(PublicContext.Provider, {\n value: publicContext\n }, React.createElement(ActiveDraggableContext.Provider, {\n value: transform\n }, children)), React.createElement(RestoreFocus, {\n disabled: (accessibility == null ? void 0 : accessibility.restoreFocus) === false\n })), React.createElement(Accessibility, { ...accessibility,\n hiddenTextDescribedById: draggableDescribedById\n }));\n\n function getAutoScrollerOptions() {\n const activeSensorDisablesAutoscroll = (activeSensor == null ? void 0 : activeSensor.autoScrollEnabled) === false;\n const autoScrollGloballyDisabled = typeof autoScroll === 'object' ? autoScroll.enabled === false : autoScroll === false;\n const enabled = isInitialized && !activeSensorDisablesAutoscroll && !autoScrollGloballyDisabled;\n\n if (typeof autoScroll === 'object') {\n return { ...autoScroll,\n enabled\n };\n }\n\n return {\n enabled\n };\n }\n});\n\nconst NullContext = /*#__PURE__*/createContext(null);\nconst defaultRole = 'button';\nconst ID_PREFIX = 'Draggable';\nfunction useDraggable(_ref) {\n let {\n id,\n data,\n disabled = false,\n attributes\n } = _ref;\n const key = useUniqueId(ID_PREFIX);\n const {\n activators,\n activatorEvent,\n active,\n activeNodeRect,\n ariaDescribedById,\n draggableNodes,\n over\n } = useContext(InternalContext);\n const {\n role = defaultRole,\n roleDescription = 'draggable',\n tabIndex = 0\n } = attributes != null ? attributes : {};\n const isDragging = (active == null ? void 0 : active.id) === id;\n const transform = useContext(isDragging ? ActiveDraggableContext : NullContext);\n const [node, setNodeRef] = useNodeRef();\n const [activatorNode, setActivatorNodeRef] = useNodeRef();\n const listeners = useSyntheticListeners(activators, id);\n const dataRef = useLatestValue(data);\n useIsomorphicLayoutEffect(() => {\n draggableNodes.set(id, {\n id,\n key,\n node,\n activatorNode,\n data: dataRef\n });\n return () => {\n const node = draggableNodes.get(id);\n\n if (node && node.key === key) {\n draggableNodes.delete(id);\n }\n };\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [draggableNodes, id]);\n const memoizedAttributes = useMemo(() => ({\n role,\n tabIndex,\n 'aria-disabled': disabled,\n 'aria-pressed': isDragging && role === defaultRole ? true : undefined,\n 'aria-roledescription': roleDescription,\n 'aria-describedby': ariaDescribedById.draggable\n }), [disabled, role, tabIndex, isDragging, roleDescription, ariaDescribedById.draggable]);\n return {\n active,\n activatorEvent,\n activeNodeRect,\n attributes: memoizedAttributes,\n isDragging,\n listeners: disabled ? undefined : listeners,\n node,\n over,\n setNodeRef,\n setActivatorNodeRef,\n transform\n };\n}\n\nfunction useDndContext() {\n return useContext(PublicContext);\n}\n\nconst ID_PREFIX$1 = 'Droppable';\nconst defaultResizeObserverConfig = {\n timeout: 25\n};\nfunction useDroppable(_ref) {\n let {\n data,\n disabled = false,\n id,\n resizeObserverConfig\n } = _ref;\n const key = useUniqueId(ID_PREFIX$1);\n const {\n active,\n dispatch,\n over,\n measureDroppableContainers\n } = useContext(InternalContext);\n const previous = useRef({\n disabled\n });\n const resizeObserverConnected = useRef(false);\n const rect = useRef(null);\n const callbackId = useRef(null);\n const {\n disabled: resizeObserverDisabled,\n updateMeasurementsFor,\n timeout: resizeObserverTimeout\n } = { ...defaultResizeObserverConfig,\n ...resizeObserverConfig\n };\n const ids = useLatestValue(updateMeasurementsFor != null ? updateMeasurementsFor : id);\n const handleResize = useCallback(() => {\n if (!resizeObserverConnected.current) {\n // ResizeObserver invokes the `handleResize` callback as soon as `observe` is called,\n // assuming the element is rendered and displayed.\n resizeObserverConnected.current = true;\n return;\n }\n\n if (callbackId.current != null) {\n clearTimeout(callbackId.current);\n }\n\n callbackId.current = setTimeout(() => {\n measureDroppableContainers(Array.isArray(ids.current) ? ids.current : [ids.current]);\n callbackId.current = null;\n }, resizeObserverTimeout);\n }, //eslint-disable-next-line react-hooks/exhaustive-deps\n [resizeObserverTimeout]);\n const resizeObserver = useResizeObserver({\n callback: handleResize,\n disabled: resizeObserverDisabled || !active\n });\n const handleNodeChange = useCallback((newElement, previousElement) => {\n if (!resizeObserver) {\n return;\n }\n\n if (previousElement) {\n resizeObserver.unobserve(previousElement);\n resizeObserverConnected.current = false;\n }\n\n if (newElement) {\n resizeObserver.observe(newElement);\n }\n }, [resizeObserver]);\n const [nodeRef, setNodeRef] = useNodeRef(handleNodeChange);\n const dataRef = useLatestValue(data);\n useEffect(() => {\n if (!resizeObserver || !nodeRef.current) {\n return;\n }\n\n resizeObserver.disconnect();\n resizeObserverConnected.current = false;\n resizeObserver.observe(nodeRef.current);\n }, [nodeRef, resizeObserver]);\n useEffect(() => {\n dispatch({\n type: Action.RegisterDroppable,\n element: {\n id,\n key,\n disabled,\n node: nodeRef,\n rect,\n data: dataRef\n }\n });\n return () => dispatch({\n type: Action.UnregisterDroppable,\n key,\n id\n });\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [id]);\n useEffect(() => {\n if (disabled !== previous.current.disabled) {\n dispatch({\n type: Action.SetDroppableDisabled,\n id,\n key,\n disabled\n });\n previous.current.disabled = disabled;\n }\n }, [id, key, disabled, dispatch]);\n return {\n active,\n rect,\n isOver: (over == null ? void 0 : over.id) === id,\n node: nodeRef,\n over,\n setNodeRef\n };\n}\n\nfunction AnimationManager(_ref) {\n let {\n animation,\n children\n } = _ref;\n const [clonedChildren, setClonedChildren] = useState(null);\n const [element, setElement] = useState(null);\n const previousChildren = usePrevious(children);\n\n if (!children && !clonedChildren && previousChildren) {\n setClonedChildren(previousChildren);\n }\n\n useIsomorphicLayoutEffect(() => {\n if (!element) {\n return;\n }\n\n const key = clonedChildren == null ? void 0 : clonedChildren.key;\n const id = clonedChildren == null ? void 0 : clonedChildren.props.id;\n\n if (key == null || id == null) {\n setClonedChildren(null);\n return;\n }\n\n Promise.resolve(animation(id, element)).then(() => {\n setClonedChildren(null);\n });\n }, [animation, clonedChildren, element]);\n return React.createElement(React.Fragment, null, children, clonedChildren ? cloneElement(clonedChildren, {\n ref: setElement\n }) : null);\n}\n\nconst defaultTransform = {\n x: 0,\n y: 0,\n scaleX: 1,\n scaleY: 1\n};\nfunction NullifiedContextProvider(_ref) {\n let {\n children\n } = _ref;\n return React.createElement(InternalContext.Provider, {\n value: defaultInternalContext\n }, React.createElement(ActiveDraggableContext.Provider, {\n value: defaultTransform\n }, children));\n}\n\nconst baseStyles = {\n position: 'fixed',\n touchAction: 'none'\n};\n\nconst defaultTransition = activatorEvent => {\n const isKeyboardActivator = isKeyboardEvent(activatorEvent);\n return isKeyboardActivator ? 'transform 250ms ease' : undefined;\n};\n\nconst PositionedOverlay = /*#__PURE__*/forwardRef((_ref, ref) => {\n let {\n as,\n activatorEvent,\n adjustScale,\n children,\n className,\n rect,\n style,\n transform,\n transition = defaultTransition\n } = _ref;\n\n if (!rect) {\n return null;\n }\n\n const scaleAdjustedTransform = adjustScale ? transform : { ...transform,\n scaleX: 1,\n scaleY: 1\n };\n const styles = { ...baseStyles,\n width: rect.width,\n height: rect.height,\n top: rect.top,\n left: rect.left,\n transform: CSS.Transform.toString(scaleAdjustedTransform),\n transformOrigin: adjustScale && activatorEvent ? getRelativeTransformOrigin(activatorEvent, rect) : undefined,\n transition: typeof transition === 'function' ? transition(activatorEvent) : transition,\n ...style\n };\n return React.createElement(as, {\n className,\n style: styles,\n ref\n }, children);\n});\n\nconst defaultDropAnimationSideEffects = options => _ref => {\n let {\n active,\n dragOverlay\n } = _ref;\n const originalStyles = {};\n const {\n styles,\n className\n } = options;\n\n if (styles != null && styles.active) {\n for (const [key, value] of Object.entries(styles.active)) {\n if (value === undefined) {\n continue;\n }\n\n originalStyles[key] = active.node.style.getPropertyValue(key);\n active.node.style.setProperty(key, value);\n }\n }\n\n if (styles != null && styles.dragOverlay) {\n for (const [key, value] of Object.entries(styles.dragOverlay)) {\n if (value === undefined) {\n continue;\n }\n\n dragOverlay.node.style.setProperty(key, value);\n }\n }\n\n if (className != null && className.active) {\n active.node.classList.add(className.active);\n }\n\n if (className != null && className.dragOverlay) {\n dragOverlay.node.classList.add(className.dragOverlay);\n }\n\n return function cleanup() {\n for (const [key, value] of Object.entries(originalStyles)) {\n active.node.style.setProperty(key, value);\n }\n\n if (className != null && className.active) {\n active.node.classList.remove(className.active);\n }\n };\n};\n\nconst defaultKeyframeResolver = _ref2 => {\n let {\n transform: {\n initial,\n final\n }\n } = _ref2;\n return [{\n transform: CSS.Transform.toString(initial)\n }, {\n transform: CSS.Transform.toString(final)\n }];\n};\n\nconst defaultDropAnimationConfiguration = {\n duration: 250,\n easing: 'ease',\n keyframes: defaultKeyframeResolver,\n sideEffects: /*#__PURE__*/defaultDropAnimationSideEffects({\n styles: {\n active: {\n opacity: '0'\n }\n }\n })\n};\nfunction useDropAnimation(_ref3) {\n let {\n config,\n draggableNodes,\n droppableContainers,\n measuringConfiguration\n } = _ref3;\n return useEvent((id, node) => {\n if (config === null) {\n return;\n }\n\n const activeDraggable = draggableNodes.get(id);\n\n if (!activeDraggable) {\n return;\n }\n\n const activeNode = activeDraggable.node.current;\n\n if (!activeNode) {\n return;\n }\n\n const measurableNode = getMeasurableNode(node);\n\n if (!measurableNode) {\n return;\n }\n\n const {\n transform\n } = getWindow(node).getComputedStyle(node);\n const parsedTransform = parseTransform(transform);\n\n if (!parsedTransform) {\n return;\n }\n\n const animation = typeof config === 'function' ? config : createDefaultDropAnimation(config);\n scrollIntoViewIfNeeded(activeNode, measuringConfiguration.draggable.measure);\n return animation({\n active: {\n id,\n data: activeDraggable.data,\n node: activeNode,\n rect: measuringConfiguration.draggable.measure(activeNode)\n },\n draggableNodes,\n dragOverlay: {\n node,\n rect: measuringConfiguration.dragOverlay.measure(measurableNode)\n },\n droppableContainers,\n measuringConfiguration,\n transform: parsedTransform\n });\n });\n}\n\nfunction createDefaultDropAnimation(options) {\n const {\n duration,\n easing,\n sideEffects,\n keyframes\n } = { ...defaultDropAnimationConfiguration,\n ...options\n };\n return _ref4 => {\n let {\n active,\n dragOverlay,\n transform,\n ...rest\n } = _ref4;\n\n if (!duration) {\n // Do not animate if animation duration is zero.\n return;\n }\n\n const delta = {\n x: dragOverlay.rect.left - active.rect.left,\n y: dragOverlay.rect.top - active.rect.top\n };\n const scale = {\n scaleX: transform.scaleX !== 1 ? active.rect.width * transform.scaleX / dragOverlay.rect.width : 1,\n scaleY: transform.scaleY !== 1 ? active.rect.height * transform.scaleY / dragOverlay.rect.height : 1\n };\n const finalTransform = {\n x: transform.x - delta.x,\n y: transform.y - delta.y,\n ...scale\n };\n const animationKeyframes = keyframes({ ...rest,\n active,\n dragOverlay,\n transform: {\n initial: transform,\n final: finalTransform\n }\n });\n const [firstKeyframe] = animationKeyframes;\n const lastKeyframe = animationKeyframes[animationKeyframes.length - 1];\n\n if (JSON.stringify(firstKeyframe) === JSON.stringify(lastKeyframe)) {\n // The start and end keyframes are the same, infer that there is no animation needed.\n return;\n }\n\n const cleanup = sideEffects == null ? void 0 : sideEffects({\n active,\n dragOverlay,\n ...rest\n });\n const animation = dragOverlay.node.animate(animationKeyframes, {\n duration,\n easing,\n fill: 'forwards'\n });\n return new Promise(resolve => {\n animation.onfinish = () => {\n cleanup == null ? void 0 : cleanup();\n resolve();\n };\n });\n };\n}\n\nlet key = 0;\nfunction useKey(id) {\n return useMemo(() => {\n if (id == null) {\n return;\n }\n\n key++;\n return key;\n }, [id]);\n}\n\nconst DragOverlay = /*#__PURE__*/React.memo(_ref => {\n let {\n adjustScale = false,\n children,\n dropAnimation: dropAnimationConfig,\n style,\n transition,\n modifiers,\n wrapperElement = 'div',\n className,\n zIndex = 999\n } = _ref;\n const {\n activatorEvent,\n active,\n activeNodeRect,\n containerNodeRect,\n draggableNodes,\n droppableContainers,\n dragOverlay,\n over,\n measuringConfiguration,\n scrollableAncestors,\n scrollableAncestorRects,\n windowRect\n } = useDndContext();\n const transform = useContext(ActiveDraggableContext);\n const key = useKey(active == null ? void 0 : active.id);\n const modifiedTransform = applyModifiers(modifiers, {\n activatorEvent,\n active,\n activeNodeRect,\n containerNodeRect,\n draggingNodeRect: dragOverlay.rect,\n over,\n overlayNodeRect: dragOverlay.rect,\n scrollableAncestors,\n scrollableAncestorRects,\n transform,\n windowRect\n });\n const initialRect = useInitialValue(activeNodeRect);\n const dropAnimation = useDropAnimation({\n config: dropAnimationConfig,\n draggableNodes,\n droppableContainers,\n measuringConfiguration\n }); // We need to wait for the active node to be measured before connecting the drag overlay ref\n // otherwise collisions can be computed against a mispositioned drag overlay\n\n const ref = initialRect ? dragOverlay.setRef : undefined;\n return React.createElement(NullifiedContextProvider, null, React.createElement(AnimationManager, {\n animation: dropAnimation\n }, active && key ? React.createElement(PositionedOverlay, {\n key: key,\n id: active.id,\n ref: ref,\n as: wrapperElement,\n activatorEvent: activatorEvent,\n adjustScale: adjustScale,\n className: className,\n transition: transition,\n rect: initialRect,\n style: {\n zIndex,\n ...style\n },\n transform: modifiedTransform\n }, children) : null));\n});\n\nexport { AutoScrollActivator, DndContext, DragOverlay, KeyboardCode, KeyboardSensor, MeasuringFrequency, MeasuringStrategy, MouseSensor, PointerSensor, TouchSensor, TraversalOrder, applyModifiers, closestCenter, closestCorners, defaultAnnouncements, defaultCoordinates, defaultDropAnimationConfiguration as defaultDropAnimation, defaultDropAnimationSideEffects, defaultKeyboardCoordinateGetter, defaultScreenReaderInstructions, getClientRect, getFirstCollision, getScrollableAncestors, pointerWithin, rectIntersection, useDndContext, useDndMonitor, useDraggable, useDroppable, useSensor, useSensors };\n//# sourceMappingURL=core.esm.js.map\n","import React, { useMemo, useRef, useEffect, useState, useContext } from 'react';\nimport { useDndContext, getClientRect, useDroppable, useDraggable, closestCorners, getFirstCollision, getScrollableAncestors, KeyboardCode } from '@dnd-kit/core';\nimport { useUniqueId, useIsomorphicLayoutEffect, CSS, useCombinedRefs, isKeyboardEvent, subtract } from '@dnd-kit/utilities';\n\n/**\r\n * Move an array item to a different position. Returns a new array with the item moved to the new position.\r\n */\nfunction arrayMove(array, from, to) {\n const newArray = array.slice();\n newArray.splice(to < 0 ? newArray.length + to : to, 0, newArray.splice(from, 1)[0]);\n return newArray;\n}\n\n/**\r\n * Swap an array item to a different position. Returns a new array with the item swapped to the new position.\r\n */\nfunction arraySwap(array, from, to) {\n const newArray = array.slice();\n newArray[from] = array[to];\n newArray[to] = array[from];\n return newArray;\n}\n\nfunction getSortedRects(items, rects) {\n return items.reduce((accumulator, id, index) => {\n const rect = rects.get(id);\n\n if (rect) {\n accumulator[index] = rect;\n }\n\n return accumulator;\n }, Array(items.length));\n}\n\nfunction isValidIndex(index) {\n return index !== null && index >= 0;\n}\n\nfunction itemsEqual(a, b) {\n if (a === b) {\n return true;\n }\n\n if (a.length !== b.length) {\n return false;\n }\n\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) {\n return false;\n }\n }\n\n return true;\n}\n\nfunction normalizeDisabled(disabled) {\n if (typeof disabled === 'boolean') {\n return {\n draggable: disabled,\n droppable: disabled\n };\n }\n\n return disabled;\n}\n\n// To-do: We should be calculating scale transformation\nconst defaultScale = {\n scaleX: 1,\n scaleY: 1\n};\nconst horizontalListSortingStrategy = _ref => {\n var _rects$activeIndex;\n\n let {\n rects,\n activeNodeRect: fallbackActiveRect,\n activeIndex,\n overIndex,\n index\n } = _ref;\n const activeNodeRect = (_rects$activeIndex = rects[activeIndex]) != null ? _rects$activeIndex : fallbackActiveRect;\n\n if (!activeNodeRect) {\n return null;\n }\n\n const itemGap = getItemGap(rects, index, activeIndex);\n\n if (index === activeIndex) {\n const newIndexRect = rects[overIndex];\n\n if (!newIndexRect) {\n return null;\n }\n\n return {\n x: activeIndex < overIndex ? newIndexRect.left + newIndexRect.width - (activeNodeRect.left + activeNodeRect.width) : newIndexRect.left - activeNodeRect.left,\n y: 0,\n ...defaultScale\n };\n }\n\n if (index > activeIndex && index <= overIndex) {\n return {\n x: -activeNodeRect.width - itemGap,\n y: 0,\n ...defaultScale\n };\n }\n\n if (index < activeIndex && index >= overIndex) {\n return {\n x: activeNodeRect.width + itemGap,\n y: 0,\n ...defaultScale\n };\n }\n\n return {\n x: 0,\n y: 0,\n ...defaultScale\n };\n};\n\nfunction getItemGap(rects, index, activeIndex) {\n const currentRect = rects[index];\n const previousRect = rects[index - 1];\n const nextRect = rects[index + 1];\n\n if (!currentRect || !previousRect && !nextRect) {\n return 0;\n }\n\n if (activeIndex < index) {\n return previousRect ? currentRect.left - (previousRect.left + previousRect.width) : nextRect.left - (currentRect.left + currentRect.width);\n }\n\n return nextRect ? nextRect.left - (currentRect.left + currentRect.width) : currentRect.left - (previousRect.left + previousRect.width);\n}\n\nconst rectSortingStrategy = _ref => {\n let {\n rects,\n activeIndex,\n overIndex,\n index\n } = _ref;\n const newRects = arrayMove(rects, overIndex, activeIndex);\n const oldRect = rects[index];\n const newRect = newRects[index];\n\n if (!newRect || !oldRect) {\n return null;\n }\n\n return {\n x: newRect.left - oldRect.left,\n y: newRect.top - oldRect.top,\n scaleX: newRect.width / oldRect.width,\n scaleY: newRect.height / oldRect.height\n };\n};\n\nconst rectSwappingStrategy = _ref => {\n let {\n activeIndex,\n index,\n rects,\n overIndex\n } = _ref;\n let oldRect;\n let newRect;\n\n if (index === activeIndex) {\n oldRect = rects[index];\n newRect = rects[overIndex];\n }\n\n if (index === overIndex) {\n oldRect = rects[index];\n newRect = rects[activeIndex];\n }\n\n if (!newRect || !oldRect) {\n return null;\n }\n\n return {\n x: newRect.left - oldRect.left,\n y: newRect.top - oldRect.top,\n scaleX: newRect.width / oldRect.width,\n scaleY: newRect.height / oldRect.height\n };\n};\n\n// To-do: We should be calculating scale transformation\nconst defaultScale$1 = {\n scaleX: 1,\n scaleY: 1\n};\nconst verticalListSortingStrategy = _ref => {\n var _rects$activeIndex;\n\n let {\n activeIndex,\n activeNodeRect: fallbackActiveRect,\n index,\n rects,\n overIndex\n } = _ref;\n const activeNodeRect = (_rects$activeIndex = rects[activeIndex]) != null ? _rects$activeIndex : fallbackActiveRect;\n\n if (!activeNodeRect) {\n return null;\n }\n\n if (index === activeIndex) {\n const overIndexRect = rects[overIndex];\n\n if (!overIndexRect) {\n return null;\n }\n\n return {\n x: 0,\n y: activeIndex < overIndex ? overIndexRect.top + overIndexRect.height - (activeNodeRect.top + activeNodeRect.height) : overIndexRect.top - activeNodeRect.top,\n ...defaultScale$1\n };\n }\n\n const itemGap = getItemGap$1(rects, index, activeIndex);\n\n if (index > activeIndex && index <= overIndex) {\n return {\n x: 0,\n y: -activeNodeRect.height - itemGap,\n ...defaultScale$1\n };\n }\n\n if (index < activeIndex && index >= overIndex) {\n return {\n x: 0,\n y: activeNodeRect.height + itemGap,\n ...defaultScale$1\n };\n }\n\n return {\n x: 0,\n y: 0,\n ...defaultScale$1\n };\n};\n\nfunction getItemGap$1(clientRects, index, activeIndex) {\n const currentRect = clientRects[index];\n const previousRect = clientRects[index - 1];\n const nextRect = clientRects[index + 1];\n\n if (!currentRect) {\n return 0;\n }\n\n if (activeIndex < index) {\n return previousRect ? currentRect.top - (previousRect.top + previousRect.height) : nextRect ? nextRect.top - (currentRect.top + currentRect.height) : 0;\n }\n\n return nextRect ? nextRect.top - (currentRect.top + currentRect.height) : previousRect ? currentRect.top - (previousRect.top + previousRect.height) : 0;\n}\n\nconst ID_PREFIX = 'Sortable';\nconst Context = /*#__PURE__*/React.createContext({\n activeIndex: -1,\n containerId: ID_PREFIX,\n disableTransforms: false,\n items: [],\n overIndex: -1,\n useDragOverlay: false,\n sortedRects: [],\n strategy: rectSortingStrategy,\n disabled: {\n draggable: false,\n droppable: false\n }\n});\nfunction SortableContext(_ref) {\n let {\n children,\n id,\n items: userDefinedItems,\n strategy = rectSortingStrategy,\n disabled: disabledProp = false\n } = _ref;\n const {\n active,\n dragOverlay,\n droppableRects,\n over,\n measureDroppableContainers\n } = useDndContext();\n const containerId = useUniqueId(ID_PREFIX, id);\n const useDragOverlay = Boolean(dragOverlay.rect !== null);\n const items = useMemo(() => userDefinedItems.map(item => typeof item === 'object' && 'id' in item ? item.id : item), [userDefinedItems]);\n const isDragging = active != null;\n const activeIndex = active ? items.indexOf(active.id) : -1;\n const overIndex = over ? items.indexOf(over.id) : -1;\n const previousItemsRef = useRef(items);\n const itemsHaveChanged = !itemsEqual(items, previousItemsRef.current);\n const disableTransforms = overIndex !== -1 && activeIndex === -1 || itemsHaveChanged;\n const disabled = normalizeDisabled(disabledProp);\n useIsomorphicLayoutEffect(() => {\n if (itemsHaveChanged && isDragging) {\n measureDroppableContainers(items);\n }\n }, [itemsHaveChanged, items, isDragging, measureDroppableContainers]);\n useEffect(() => {\n previousItemsRef.current = items;\n }, [items]);\n const contextValue = useMemo(() => ({\n activeIndex,\n containerId,\n disabled,\n disableTransforms,\n items,\n overIndex,\n useDragOverlay,\n sortedRects: getSortedRects(items, droppableRects),\n strategy\n }), // eslint-disable-next-line react-hooks/exhaustive-deps\n [activeIndex, containerId, disabled.draggable, disabled.droppable, disableTransforms, items, overIndex, droppableRects, useDragOverlay, strategy]);\n return React.createElement(Context.Provider, {\n value: contextValue\n }, children);\n}\n\nconst defaultNewIndexGetter = _ref => {\n let {\n id,\n items,\n activeIndex,\n overIndex\n } = _ref;\n return arrayMove(items, activeIndex, overIndex).indexOf(id);\n};\nconst defaultAnimateLayoutChanges = _ref2 => {\n let {\n containerId,\n isSorting,\n wasDragging,\n index,\n items,\n newIndex,\n previousItems,\n previousContainerId,\n transition\n } = _ref2;\n\n if (!transition || !wasDragging) {\n return false;\n }\n\n if (previousItems !== items && index === newIndex) {\n return false;\n }\n\n if (isSorting) {\n return true;\n }\n\n return newIndex !== index && containerId === previousContainerId;\n};\nconst defaultTransition = {\n duration: 200,\n easing: 'ease'\n};\nconst transitionProperty = 'transform';\nconst disabledTransition = /*#__PURE__*/CSS.Transition.toString({\n property: transitionProperty,\n duration: 0,\n easing: 'linear'\n});\nconst defaultAttributes = {\n roleDescription: 'sortable'\n};\n\n/*\r\n * When the index of an item changes while sorting,\r\n * we need to temporarily disable the transforms\r\n */\n\nfunction useDerivedTransform(_ref) {\n let {\n disabled,\n index,\n node,\n rect\n } = _ref;\n const [derivedTransform, setDerivedtransform] = useState(null);\n const previousIndex = useRef(index);\n useIsomorphicLayoutEffect(() => {\n if (!disabled && index !== previousIndex.current && node.current) {\n const initial = rect.current;\n\n if (initial) {\n const current = getClientRect(node.current, {\n ignoreTransform: true\n });\n const delta = {\n x: initial.left - current.left,\n y: initial.top - current.top,\n scaleX: initial.width / current.width,\n scaleY: initial.height / current.height\n };\n\n if (delta.x || delta.y) {\n setDerivedtransform(delta);\n }\n }\n }\n\n if (index !== previousIndex.current) {\n previousIndex.current = index;\n }\n }, [disabled, index, node, rect]);\n useEffect(() => {\n if (derivedTransform) {\n setDerivedtransform(null);\n }\n }, [derivedTransform]);\n return derivedTransform;\n}\n\nfunction useSortable(_ref) {\n let {\n animateLayoutChanges = defaultAnimateLayoutChanges,\n attributes: userDefinedAttributes,\n disabled: localDisabled,\n data: customData,\n getNewIndex = defaultNewIndexGetter,\n id,\n strategy: localStrategy,\n resizeObserverConfig,\n transition = defaultTransition\n } = _ref;\n const {\n items,\n containerId,\n activeIndex,\n disabled: globalDisabled,\n disableTransforms,\n sortedRects,\n overIndex,\n useDragOverlay,\n strategy: globalStrategy\n } = useContext(Context);\n const disabled = normalizeLocalDisabled(localDisabled, globalDisabled);\n const index = items.indexOf(id);\n const data = useMemo(() => ({\n sortable: {\n containerId,\n index,\n items\n },\n ...customData\n }), [containerId, customData, index, items]);\n const itemsAfterCurrentSortable = useMemo(() => items.slice(items.indexOf(id)), [items, id]);\n const {\n rect,\n node,\n isOver,\n setNodeRef: setDroppableNodeRef\n } = useDroppable({\n id,\n data,\n disabled: disabled.droppable,\n resizeObserverConfig: {\n updateMeasurementsFor: itemsAfterCurrentSortable,\n ...resizeObserverConfig\n }\n });\n const {\n active,\n activatorEvent,\n activeNodeRect,\n attributes,\n setNodeRef: setDraggableNodeRef,\n listeners,\n isDragging,\n over,\n setActivatorNodeRef,\n transform\n } = useDraggable({\n id,\n data,\n attributes: { ...defaultAttributes,\n ...userDefinedAttributes\n },\n disabled: disabled.draggable\n });\n const setNodeRef = useCombinedRefs(setDroppableNodeRef, setDraggableNodeRef);\n const isSorting = Boolean(active);\n const displaceItem = isSorting && !disableTransforms && isValidIndex(activeIndex) && isValidIndex(overIndex);\n const shouldDisplaceDragSource = !useDragOverlay && isDragging;\n const dragSourceDisplacement = shouldDisplaceDragSource && displaceItem ? transform : null;\n const strategy = localStrategy != null ? localStrategy : globalStrategy;\n const finalTransform = displaceItem ? dragSourceDisplacement != null ? dragSourceDisplacement : strategy({\n rects: sortedRects,\n activeNodeRect,\n activeIndex,\n overIndex,\n index\n }) : null;\n const newIndex = isValidIndex(activeIndex) && isValidIndex(overIndex) ? getNewIndex({\n id,\n items,\n activeIndex,\n overIndex\n }) : index;\n const activeId = active == null ? void 0 : active.id;\n const previous = useRef({\n activeId,\n items,\n newIndex,\n containerId\n });\n const itemsHaveChanged = items !== previous.current.items;\n const shouldAnimateLayoutChanges = animateLayoutChanges({\n active,\n containerId,\n isDragging,\n isSorting,\n id,\n index,\n items,\n newIndex: previous.current.newIndex,\n previousItems: previous.current.items,\n previousContainerId: previous.current.containerId,\n transition,\n wasDragging: previous.current.activeId != null\n });\n const derivedTransform = useDerivedTransform({\n disabled: !shouldAnimateLayoutChanges,\n index,\n node,\n rect\n });\n useEffect(() => {\n if (isSorting && previous.current.newIndex !== newIndex) {\n previous.current.newIndex = newIndex;\n }\n\n if (containerId !== previous.current.containerId) {\n previous.current.containerId = containerId;\n }\n\n if (items !== previous.current.items) {\n previous.current.items = items;\n }\n }, [isSorting, newIndex, containerId, items]);\n useEffect(() => {\n if (activeId === previous.current.activeId) {\n return;\n }\n\n if (activeId != null && previous.current.activeId == null) {\n previous.current.activeId = activeId;\n return;\n }\n\n const timeoutId = setTimeout(() => {\n previous.current.activeId = activeId;\n }, 50);\n return () => clearTimeout(timeoutId);\n }, [activeId]);\n return {\n active,\n activeIndex,\n attributes,\n data,\n rect,\n index,\n newIndex,\n items,\n isOver,\n isSorting,\n isDragging,\n listeners,\n node,\n overIndex,\n over,\n setNodeRef,\n setActivatorNodeRef,\n setDroppableNodeRef,\n setDraggableNodeRef,\n transform: derivedTransform != null ? derivedTransform : finalTransform,\n transition: getTransition()\n };\n\n function getTransition() {\n if ( // Temporarily disable transitions for a single frame to set up derived transforms\n derivedTransform || // Or to prevent items jumping to back to their \"new\" position when items change\n itemsHaveChanged && previous.current.newIndex === index) {\n return disabledTransition;\n }\n\n if (shouldDisplaceDragSource && !isKeyboardEvent(activatorEvent) || !transition) {\n return undefined;\n }\n\n if (isSorting || shouldAnimateLayoutChanges) {\n return CSS.Transition.toString({ ...transition,\n property: transitionProperty\n });\n }\n\n return undefined;\n }\n}\n\nfunction normalizeLocalDisabled(localDisabled, globalDisabled) {\n var _localDisabled$dragga, _localDisabled$droppa;\n\n if (typeof localDisabled === 'boolean') {\n return {\n draggable: localDisabled,\n // Backwards compatibility\n droppable: false\n };\n }\n\n return {\n draggable: (_localDisabled$dragga = localDisabled == null ? void 0 : localDisabled.draggable) != null ? _localDisabled$dragga : globalDisabled.draggable,\n droppable: (_localDisabled$droppa = localDisabled == null ? void 0 : localDisabled.droppable) != null ? _localDisabled$droppa : globalDisabled.droppable\n };\n}\n\nfunction hasSortableData(entry) {\n if (!entry) {\n return false;\n }\n\n const data = entry.data.current;\n\n if (data && 'sortable' in data && typeof data.sortable === 'object' && 'containerId' in data.sortable && 'items' in data.sortable && 'index' in data.sortable) {\n return true;\n }\n\n return false;\n}\n\nconst directions = [KeyboardCode.Down, KeyboardCode.Right, KeyboardCode.Up, KeyboardCode.Left];\nconst sortableKeyboardCoordinates = (event, _ref) => {\n let {\n context: {\n active,\n collisionRect,\n droppableRects,\n droppableContainers,\n over,\n scrollableAncestors\n }\n } = _ref;\n\n if (directions.includes(event.code)) {\n event.preventDefault();\n\n if (!active || !collisionRect) {\n return;\n }\n\n const filteredContainers = [];\n droppableContainers.getEnabled().forEach(entry => {\n if (!entry || entry != null && entry.disabled) {\n return;\n }\n\n const rect = droppableRects.get(entry.id);\n\n if (!rect) {\n return;\n }\n\n switch (event.code) {\n case KeyboardCode.Down:\n if (collisionRect.top < rect.top) {\n filteredContainers.push(entry);\n }\n\n break;\n\n case KeyboardCode.Up:\n if (collisionRect.top > rect.top) {\n filteredContainers.push(entry);\n }\n\n break;\n\n case KeyboardCode.Left:\n if (collisionRect.left > rect.left) {\n filteredContainers.push(entry);\n }\n\n break;\n\n case KeyboardCode.Right:\n if (collisionRect.left < rect.left) {\n filteredContainers.push(entry);\n }\n\n break;\n }\n });\n const collisions = closestCorners({\n active,\n collisionRect: collisionRect,\n droppableRects,\n droppableContainers: filteredContainers,\n pointerCoordinates: null\n });\n let closestId = getFirstCollision(collisions, 'id');\n\n if (closestId === (over == null ? void 0 : over.id) && collisions.length > 1) {\n closestId = collisions[1].id;\n }\n\n if (closestId != null) {\n const activeDroppable = droppableContainers.get(active.id);\n const newDroppable = droppableContainers.get(closestId);\n const newRect = newDroppable ? droppableRects.get(newDroppable.id) : null;\n const newNode = newDroppable == null ? void 0 : newDroppable.node.current;\n\n if (newNode && newRect && activeDroppable && newDroppable) {\n const newScrollAncestors = getScrollableAncestors(newNode);\n const hasDifferentScrollAncestors = newScrollAncestors.some((element, index) => scrollableAncestors[index] !== element);\n const hasSameContainer = isSameContainer(activeDroppable, newDroppable);\n const isAfterActive = isAfter(activeDroppable, newDroppable);\n const offset = hasDifferentScrollAncestors || !hasSameContainer ? {\n x: 0,\n y: 0\n } : {\n x: isAfterActive ? collisionRect.width - newRect.width : 0,\n y: isAfterActive ? collisionRect.height - newRect.height : 0\n };\n const rectCoordinates = {\n x: newRect.left,\n y: newRect.top\n };\n const newCoordinates = offset.x && offset.y ? rectCoordinates : subtract(rectCoordinates, offset);\n return newCoordinates;\n }\n }\n }\n\n return undefined;\n};\n\nfunction isSameContainer(a, b) {\n if (!hasSortableData(a) || !hasSortableData(b)) {\n return false;\n }\n\n return a.data.current.sortable.containerId === b.data.current.sortable.containerId;\n}\n\nfunction isAfter(a, b) {\n if (!hasSortableData(a) || !hasSortableData(b)) {\n return false;\n }\n\n if (!isSameContainer(a, b)) {\n return false;\n }\n\n return a.data.current.sortable.index < b.data.current.sortable.index;\n}\n\nexport { SortableContext, arrayMove, arraySwap, defaultAnimateLayoutChanges, defaultNewIndexGetter, hasSortableData, horizontalListSortingStrategy, rectSortingStrategy, rectSwappingStrategy, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy };\n//# sourceMappingURL=sortable.esm.js.map\n","import { useEmailStore } from \"../store/emailStore\";\nimport type {\n EmailModule,\n EmailElement,\n TextElement,\n ImageElement,\n ButtonElement,\n SpacerElement,\n DividerElement,\n ProductGridElement,\n Theme,\n} from \"../core/types\";\nimport { resolveStyle, resolveToken } from \"../core/theme\";\nimport { Copy, Trash2, GripVertical, ArrowUp, ArrowDown, MousePointer2 } from \"lucide-react\";\nimport {\n DndContext,\n closestCenter,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n type DragEndEvent,\n} from \"@dnd-kit/core\";\nimport {\n SortableContext,\n sortableKeyboardCoordinates,\n useSortable,\n verticalListSortingStrategy,\n arrayMove,\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { useEffect, useState } from \"react\";\n\nconst MOBILE_WIDTH = 375;\n\n/**\n * Returns true when `color` is white or very light (luminance > 0.82).\n * Used by TextRender to add a canvas-only text-shadow so white text remains\n * readable while editing, without affecting the exported HTML.\n */\nfunction isColorLight(color: string): boolean {\n const hex = color.replace(\"#\", \"\");\n if (hex.length !== 3 && hex.length !== 6) {\n // Named colours: handle the most common ones.\n if (color === \"white\" || color === \"#fff\" || color === \"#ffffff\") return true;\n return false;\n }\n const full = hex.length === 3 ? hex.split(\"\").map((c) => c + c).join(\"\") : hex;\n const r = parseInt(full.slice(0, 2), 16) / 255;\n const g = parseInt(full.slice(2, 4), 16) / 255;\n const b = parseInt(full.slice(4, 6), 16) / 255;\n // sRGB relative luminance (approximate)\n const lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;\n return lum > 0.82;\n}\n\nfunction mergeMobile(\n style: Record<string, unknown> | undefined,\n viewMode: \"desktop\" | \"mobile\"\n): Record<string, unknown> {\n const base = (style ?? {}) as Record<string, unknown>;\n if (viewMode !== \"mobile\") return base;\n const mobile = (base.mobile as Record<string, unknown> | undefined) ?? {};\n return { ...base, ...mobile };\n}\n\nexport function Canvas() {\n const {\n doc,\n selection,\n setSelection,\n reorderModules,\n deleteModule,\n duplicateModule,\n deleteElement,\n moveElement,\n viewMode,\n } = useEmailStore();\n\n const sensors = useSensors(\n useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),\n useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })\n );\n\n const handleDragEnd = (e: DragEndEvent) => {\n const { active, over } = e;\n if (!over || active.id === over.id) return;\n const from = doc.modules.findIndex((m) => m.id === active.id);\n const to = doc.modules.findIndex((m) => m.id === over.id);\n if (from === -1 || to === -1) return;\n reorderModules(from, to);\n };\n\n // Keyboard delete (modules and elements)\n useEffect(() => {\n const handler = (e: KeyboardEvent) => {\n if (e.key !== \"Delete\" && e.key !== \"Backspace\") return;\n const target = e.target as HTMLElement;\n if (target.tagName === \"INPUT\" || target.tagName === \"TEXTAREA\" || target.isContentEditable)\n return;\n if (selection?.kind === \"module\") deleteModule(selection.moduleId);\n else if (selection?.kind === \"element\")\n deleteElement(selection.moduleId, selection.elementId);\n };\n window.addEventListener(\"keydown\", handler);\n return () => window.removeEventListener(\"keydown\", handler);\n }, [selection, deleteModule, deleteElement]);\n\n const bg = resolveToken(doc.settings.backgroundColor, doc.theme) as string;\n const cbg = resolveToken(doc.settings.contentBackgroundColor, doc.theme) as string;\n\n const reorderedIds = doc.modules.map((m) => m.id);\n const canvasWidth = viewMode === \"mobile\" ? MOBILE_WIDTH : doc.settings.width;\n\n return (\n <div\n className=\"flex-1 overflow-y-auto\"\n style={{ background: bg }}\n onClick={() => setSelection({ kind: \"email\" })}\n >\n <div className=\"py-8 flex justify-center\">\n <div\n className={`shadow-lg transition-all duration-200 ${viewMode === \"mobile\" ? \"rounded-[28px] border-[10px] border-gray-800\" : \"\"}`}\n style={{ width: canvasWidth, background: cbg, minHeight: 300 }}\n onClick={(e) => e.stopPropagation()}\n >\n {doc.modules.length === 0 && (\n <div className=\"p-12 text-center text-gray-400 text-sm\">\n Add modules from the left sidebar to start building your email.\n </div>\n )}\n <DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>\n <SortableContext items={reorderedIds} strategy={verticalListSortingStrategy}>\n {doc.modules.map((m, i) => (\n <SortableModule\n key={m.id}\n mod={m}\n index={i}\n viewMode={viewMode}\n selected={selection?.kind === \"module\" && selection.moduleId === m.id}\n selectionEl={\n selection?.kind === \"element\" && selection.moduleId === m.id\n ? selection.elementId\n : null\n }\n theme={doc.theme}\n onSelectModule={() => setSelection({ kind: \"module\", moduleId: m.id })}\n onSelectElement={(elId) =>\n setSelection({ kind: \"element\", moduleId: m.id, elementId: elId })\n }\n onDuplicate={() => duplicateModule(m.id)}\n onDelete={() => deleteModule(m.id)}\n />\n ))}\n </SortableContext>\n </DndContext>\n </div>\n </div>\n </div>\n );\n}\n\nfunction SortableModule(props: {\n mod: EmailModule;\n index: number;\n viewMode: \"desktop\" | \"mobile\";\n selected: boolean;\n selectionEl: string | null;\n theme: Theme;\n onSelectModule: () => void;\n onSelectElement: (id: string) => void;\n onDuplicate: () => void;\n onDelete: () => void;\n}) {\n const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({\n id: props.mod.id,\n });\n const style: React.CSSProperties = {\n transform: CSS.Transform.toString(transform),\n transition,\n opacity: isDragging ? 0.5 : 1,\n position: \"relative\",\n // Lift the selected module above its siblings so the selection toolbar\n // (which overflows outside the block bounds) is never obscured.\n zIndex: props.selected ? 10 : \"auto\",\n };\n return (\n <div ref={setNodeRef} style={style}>\n <ModuleView\n mod={props.mod}\n viewMode={props.viewMode}\n selected={props.selected}\n selectionEl={props.selectionEl}\n theme={props.theme}\n onSelectModule={props.onSelectModule}\n onSelectElement={props.onSelectElement}\n onDuplicate={props.onDuplicate}\n onDelete={props.onDelete}\n dragHandle={\n <button\n {...attributes}\n {...listeners}\n className=\"bg-blue-600 text-white p-1 rounded cursor-grab active:cursor-grabbing\"\n title=\"Drag to reorder\"\n onClick={(e) => e.stopPropagation()}\n >\n <GripVertical size={14} />\n </button>\n }\n />\n </div>\n );\n}\n\nfunction ModuleView({\n mod,\n viewMode,\n selected,\n selectionEl,\n theme,\n onSelectModule,\n onSelectElement,\n onDuplicate,\n onDelete,\n dragHandle,\n}: {\n mod: EmailModule;\n viewMode: \"desktop\" | \"mobile\";\n selected: boolean;\n selectionEl: string | null;\n theme: Theme;\n onSelectModule: () => void;\n onSelectElement: (id: string) => void;\n onDuplicate: () => void;\n onDelete: () => void;\n dragHandle: React.ReactNode;\n}) {\n const rawStyle = (mod.style ?? {}) as Record<string, unknown>;\n const hideOn = rawStyle.hideOn as \"mobile\" | \"desktop\" | undefined;\n if (hideOn === viewMode) return null;\n const merged = mergeMobile(rawStyle, viewMode);\n const s = resolveStyle(merged, theme);\n const [hovered, setHovered] = useState(false);\n const moduleStyle: React.CSSProperties = {\n backgroundColor: s.backgroundColor as string,\n paddingTop: (s.paddingTop as number) ?? 0,\n paddingBottom: (s.paddingBottom as number) ?? 0,\n paddingLeft: (s.paddingLeft as number) ?? 0,\n paddingRight: (s.paddingRight as number) ?? 0,\n borderRadius: s.borderRadius as number,\n position: \"relative\",\n outline: selected\n ? \"2px solid #2563eb\"\n : hovered\n ? \"1px dashed #93c5fd\"\n : \"1px dashed transparent\",\n outlineOffset: -2,\n cursor: \"pointer\",\n };\n\n return (\n <div\n style={moduleStyle}\n onClick={(e) => {\n e.stopPropagation();\n onSelectModule();\n }}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n >\n {/* Hover label (when not selected) makes it obvious what block you're targeting */}\n {!selected && hovered && (\n <div className=\"absolute top-0 right-0 z-10 bg-blue-600 text-white text-[10px] px-1.5 py-0.5 rounded-bl pointer-events-none\">\n Click to select: {mod.name}\n </div>\n )}\n {selected && (\n // Toolbar sits INSIDE the block at the top-left so it is never clipped\n // by the scroll container or hidden above the first block in the canvas.\n <div\n className=\"absolute top-0 left-0 z-20 flex items-center gap-1 p-1 rounded-br bg-blue-600 shadow-md\"\n onClick={(e) => e.stopPropagation()}\n >\n {dragHandle}\n <button\n onClick={(e) => {\n e.stopPropagation();\n onDuplicate();\n }}\n className=\"text-white p-1 rounded hover:bg-blue-700\"\n title=\"Duplicate\"\n >\n <Copy size={14} />\n </button>\n <button\n onClick={(e) => {\n e.stopPropagation();\n onDelete();\n }}\n className=\"text-white p-1 rounded hover:bg-red-600\"\n title=\"Delete\"\n >\n <Trash2 size={14} />\n </button>\n <span className=\"text-white text-[10px] font-medium px-1.5 py-0.5\">\n {mod.name}\n </span>\n </div>\n )}\n {mod.children.map((c, i) => (\n <ElementView\n key={c.id}\n el={c}\n index={i}\n totalElements={mod.children.length}\n viewMode={viewMode}\n theme={theme}\n moduleId={mod.id}\n moduleSelected={selected}\n selected={selectionEl === c.id}\n onSelect={() => onSelectElement(c.id)}\n onSelectModule={onSelectModule}\n />\n ))}\n </div>\n );\n}\n\nfunction ElementView({\n el,\n index,\n totalElements,\n viewMode,\n theme,\n moduleId,\n moduleSelected,\n selected,\n onSelect,\n onSelectModule,\n}: {\n el: EmailElement;\n index: number;\n totalElements: number;\n viewMode: \"desktop\" | \"mobile\";\n theme: Theme;\n moduleId: string;\n moduleSelected: boolean;\n selected: boolean;\n onSelect: () => void;\n onSelectModule: () => void;\n}) {\n const moveElement = useEmailStore((s) => s.moveElement);\n const deleteElement = useEmailStore((s) => s.deleteElement);\n const elStyle = (el as { style?: Record<string, unknown> }).style;\n const hideOn = elStyle?.hideOn as \"mobile\" | \"desktop\" | undefined;\n if (hideOn === viewMode) return null;\n const wrapStyle: React.CSSProperties = {\n // Amber outline when selected; a faint border otherwise so element\n // boundaries stay visible even when text colour is white or near-white.\n outline: selected ? \"2px solid #f59e0b\" : \"1px dashed rgba(0,0,0,0.08)\",\n outlineOffset: -1,\n position: \"relative\",\n };\n // Two-click drilldown: clicking an element when its module is not selected\n // selects the MODULE first; a second click then drills into the element.\n // This makes module selection intuitive (you don't keep landing on a child).\n const handle = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (!moduleSelected && !selected) {\n onSelectModule();\n return;\n }\n onSelect();\n };\n\n const toolbar = selected && (\n <div\n className=\"absolute top-0 right-0 z-20 flex items-center gap-1 p-1 rounded-bl bg-amber-500 shadow-md\"\n onClick={(e) => e.stopPropagation()}\n >\n <button\n onClick={() => onSelectModule()}\n className=\"text-white p-1 rounded hover:bg-amber-600\"\n title=\"Select parent block\"\n >\n <MousePointer2 size={12} />\n </button>\n <button\n disabled={index === 0}\n onClick={() => moveElement(moduleId, el.id, -1)}\n className=\"text-white p-1 rounded disabled:opacity-40 hover:bg-amber-600\"\n title=\"Move up\"\n >\n <ArrowUp size={12} />\n </button>\n <button\n disabled={index === totalElements - 1}\n onClick={() => moveElement(moduleId, el.id, 1)}\n className=\"text-white p-1 rounded disabled:opacity-40 hover:bg-amber-600\"\n title=\"Move down\"\n >\n <ArrowDown size={12} />\n </button>\n <button\n onClick={() => deleteElement(moduleId, el.id)}\n className=\"text-white p-1 rounded hover:bg-red-600\"\n title=\"Delete element\"\n >\n <Trash2 size={12} />\n </button>\n <span className=\"text-white text-[10px] font-medium px-1 py-0.5\">\n {el.type}\n </span>\n </div>\n );\n\n const wrapWith = (inner: React.ReactNode) => (\n <div style={wrapStyle} onClick={handle}>\n {toolbar}\n {inner}\n </div>\n );\n\n switch (el.type) {\n case \"text\":\n return wrapWith(<TextRender el={el} viewMode={viewMode} theme={theme} moduleId={moduleId} />);\n case \"image\":\n return wrapWith(<ImageRender el={el} viewMode={viewMode} theme={theme} />);\n case \"button\":\n return wrapWith(<ButtonRender el={el} viewMode={viewMode} theme={theme} />);\n case \"spacer\":\n return wrapWith(<SpacerRender el={el} />);\n case \"divider\":\n return wrapWith(<DividerRender el={el} viewMode={viewMode} theme={theme} />);\n case \"productGrid\":\n return wrapWith(<ProductGridRender el={el} viewMode={viewMode} theme={theme} />);\n }\n}\n\nfunction TextRender({\n el,\n viewMode,\n theme,\n moduleId,\n}: {\n el: TextElement;\n viewMode: \"desktop\" | \"mobile\";\n theme: Theme;\n moduleId: string;\n}) {\n const updateElement = useEmailStore((s) => s.updateElement);\n const merged = mergeMobile(el.style as Record<string, unknown>, viewMode);\n const s = resolveStyle(merged, theme);\n const color = (s.color as string) ?? \"#000000\";\n\n // Canvas-only: add a subtle text-shadow when the text colour is very light\n // (white or near-white) so content is readable against any module background\n // while editing. This shadow is NOT present in the exported HTML.\n const isLightColor = isColorLight(color);\n\n const style: React.CSSProperties = {\n fontFamily: s.fontFamily as string,\n fontSize: s.fontSize as number,\n lineHeight: s.lineHeight as number,\n letterSpacing: s.letterSpacing as number,\n fontWeight: s.fontWeight as React.CSSProperties[\"fontWeight\"],\n color,\n textAlign: s.align as React.CSSProperties[\"textAlign\"],\n paddingTop: (s.paddingTop as number) ?? 8,\n paddingBottom: (s.paddingBottom as number) ?? 8,\n paddingLeft: (s.paddingLeft as number) ?? 16,\n paddingRight: (s.paddingRight as number) ?? 16,\n margin: 0,\n minHeight: \"1.5em\",\n ...(isLightColor\n ? { textShadow: \"0 0 8px rgba(0,0,0,0.55), 0 1px 2px rgba(0,0,0,0.45)\" }\n : undefined),\n };\n return (\n <div\n style={style}\n contentEditable\n suppressContentEditableWarning\n onBlur={(e) => {\n const next = e.currentTarget.innerHTML;\n if (next !== el.content) {\n updateElement(moduleId, el.id, { content: next } as Partial<TextElement>);\n }\n }}\n dangerouslySetInnerHTML={{ __html: el.content }}\n />\n );\n}\n\nfunction ImageRender({ el, viewMode, theme }: { el: ImageElement; viewMode: \"desktop\" | \"mobile\"; theme: Theme }) {\n const merged = mergeMobile(el.style as Record<string, unknown>, viewMode);\n const s = resolveStyle(merged, theme);\n const wrap: React.CSSProperties = {\n textAlign: (s.align as React.CSSProperties[\"textAlign\"]) ?? \"center\",\n paddingTop: (s.paddingTop as number) ?? 0,\n paddingBottom: (s.paddingBottom as number) ?? 0,\n paddingLeft: (s.paddingLeft as number) ?? 0,\n paddingRight: (s.paddingRight as number) ?? 0,\n };\n const img: React.CSSProperties = {\n display: \"inline-block\",\n maxWidth: \"100%\",\n width: s.width as number,\n height: (s.height as number) || \"auto\",\n borderRadius: s.borderRadius as number,\n };\n return (\n <div style={wrap}>\n <img src={el.src} alt={el.alt ?? \"\"} style={img} />\n </div>\n );\n}\n\nfunction ButtonRender({ el, viewMode, theme }: { el: ButtonElement; viewMode: \"desktop\" | \"mobile\"; theme: Theme }) {\n const merged = mergeMobile(el.style as Record<string, unknown>, viewMode);\n const s = resolveStyle(merged, theme);\n const wrap: React.CSSProperties = {\n textAlign: (s.align as React.CSSProperties[\"textAlign\"]) ?? \"center\",\n paddingTop: (s.paddingTop as number) ?? 12,\n paddingBottom: (s.paddingBottom as number) ?? 12,\n paddingLeft: (s.paddingLeft as number) ?? 16,\n paddingRight: (s.paddingRight as number) ?? 16,\n };\n const btn: React.CSSProperties = {\n display: \"inline-block\",\n backgroundColor: (s.backgroundColor as string) ?? \"#3A7D52\",\n color: (s.color as string) ?? \"#fff\",\n fontFamily: s.fontFamily as string,\n fontSize: (s.fontSize as number) ?? 16,\n fontWeight: (s.fontWeight as React.CSSProperties[\"fontWeight\"]) ?? \"bold\",\n borderRadius: (s.borderRadius as number) ?? 6,\n padding: \"12px 24px\",\n textDecoration: \"none\",\n };\n return (\n <div style={wrap}>\n <span style={btn}>{el.label}</span>\n </div>\n );\n}\n\nfunction SpacerRender({ el }: { el: SpacerElement }) {\n return <div style={{ height: el.height, background: \"rgba(0,0,0,0.02)\" }} />;\n}\n\nfunction DividerRender({ el, viewMode, theme }: { el: DividerElement; viewMode: \"desktop\" | \"mobile\"; theme: Theme }) {\n const merged = mergeMobile(el.style as Record<string, unknown>, viewMode);\n const s = resolveStyle(merged, theme);\n return (\n <div\n style={{\n paddingTop: (s.paddingTop as number) ?? 8,\n paddingBottom: (s.paddingBottom as number) ?? 8,\n }}\n >\n <hr\n style={{\n border: 0,\n borderTop: `${(s.thickness as number) ?? 1}px solid ${(s.color as string) ?? \"#E5E7EB\"}`,\n margin: 0,\n }}\n />\n </div>\n );\n}\n\nfunction ProductGridRender({\n el,\n viewMode,\n theme,\n}: {\n el: ProductGridElement;\n viewMode: \"desktop\" | \"mobile\";\n theme: Theme;\n}) {\n const merged = mergeMobile(el.style as Record<string, unknown>, viewMode);\n const s = resolveStyle(merged, theme);\n const isMobile = viewMode === \"mobile\";\n const cols = el.columns;\n const cardBg =\n (s.cardBackgroundColor as string) ?? (s.backgroundColor as string) ?? \"transparent\";\n const nameColor = (s.nameColor as string) ?? \"#111827\";\n const finalColor = (s.finalPriceColor as string) ?? \"#3A7D52\";\n const oldColor = (s.oldPriceColor as string) ?? \"#9CA3AF\";\n const btnBg = (s.buttonBackgroundColor as string) ?? \"#3A7D52\";\n const btnColor = (s.buttonColor as string) ?? \"#FFFFFF\";\n const radius = (s.borderRadius as number) ?? 0;\n\n const wrapStyle: React.CSSProperties = {\n paddingTop: (s.paddingTop as number) ?? 16,\n paddingBottom: (s.paddingBottom as number) ?? 16,\n paddingLeft: (s.paddingLeft as number) ?? 16,\n paddingRight: (s.paddingRight as number) ?? 16,\n display: \"flex\",\n flexWrap: \"wrap\",\n gap: 8,\n };\n\n return (\n <div style={wrapStyle}>\n {el.products.map((p) => {\n const cellStyle: React.CSSProperties = {\n width: isMobile ? \"100%\" : `calc(${100 / cols}% - 8px)`,\n background: cardBg,\n borderRadius: radius,\n overflow: \"hidden\",\n display: \"flex\",\n flexDirection: \"column\",\n };\n return (\n <div key={p.id} style={cellStyle}>\n <img\n src={p.image}\n alt={p.imageAlt ?? p.name}\n style={{ display: \"block\", width: \"100%\", height: \"auto\", borderRadius: radius }}\n />\n <div\n style={{\n padding: \"12px 12px 4px 12px\",\n fontFamily: \"Arial, Helvetica, sans-serif\",\n fontSize: 15,\n fontWeight: \"bold\",\n color: nameColor,\n lineHeight: 1.3,\n }}\n >\n {p.name}\n </div>\n <div style={{ padding: \"0 12px 8px 12px\", fontFamily: \"Arial, Helvetica, sans-serif\" }}>\n {el.showOldPrice && p.oldPrice && (\n <span\n className=\"old_price\"\n style={{\n color: oldColor,\n textDecoration: \"line-through\",\n fontSize: 14,\n marginRight: 8,\n }}\n >\n {p.oldPrice}\n </span>\n )}\n <span\n className=\"final_price\"\n style={{ color: finalColor, fontWeight: \"bold\", fontSize: 18 }}\n >\n {p.finalPrice}\n </span>\n </div>\n {el.showDescription && p.description && (\n <div\n style={{\n padding: \"0 12px 8px 12px\",\n fontFamily: \"Arial, Helvetica, sans-serif\",\n fontSize: 13,\n color: \"#6B7280\",\n lineHeight: 1.5,\n }}\n >\n {p.description}\n </div>\n )}\n {el.showButton && (\n <div style={{ padding: \"4px 12px 12px 12px\", textAlign: \"center\", marginTop: \"auto\" }}>\n <span\n style={{\n display: \"inline-block\",\n padding: \"10px 18px\",\n fontFamily: \"Arial, Helvetica, sans-serif\",\n fontSize: 13,\n fontWeight: \"bold\",\n color: btnColor,\n backgroundColor: btnBg,\n borderRadius: 6,\n }}\n >\n {p.buttonLabel ?? el.buttonLabel ?? \"Shop now\"}\n </span>\n </div>\n )}\n </div>\n );\n })}\n </div>\n );\n}\n","// Plugin API. Plugins can add modules, themes, AI providers, asset providers.\nimport type { ModuleDefinition } from \"../modules/registry\";\nimport { moduleRegistry } from \"../modules/registry\";\nimport type { Theme } from \"./types\";\nimport type { AIProvider } from \"./aiActions\";\nimport { setAIProvider as setReactiveAIProvider } from \"../ai/state\";\n\nexport interface AssetProvider {\n upload: (file: File) => Promise<{ url: string; alt?: string }>;\n}\n\nexport interface BuilderHandle {\n registerModule: (def: ModuleDefinition) => void;\n registerTheme: (theme: Theme) => void;\n registerAssetProvider: (provider: AssetProvider) => void;\n setAIProvider: (provider: AIProvider) => void;\n}\n\nexport type PluginType = \"modules\" | \"themes\" | \"asset-provider\" | \"ai-provider\";\n\nexport interface Plugin {\n name: string;\n type: PluginType;\n setup: (builder: BuilderHandle) => void;\n}\n\nconst themes: Theme[] = [];\nlet assetProvider: AssetProvider | null = null;\nlet aiProvider: AIProvider | null = null;\n\nexport const builder: BuilderHandle = {\n registerModule: (def) => moduleRegistry.register(def),\n registerTheme: (t) => themes.push(t),\n registerAssetProvider: (p) => {\n assetProvider = p;\n },\n setAIProvider: (p) => {\n aiProvider = p;\n // Notify the reactive store so the AI chat panel appears/updates.\n setReactiveAIProvider(p);\n },\n};\n\nexport function registerPlugin(plugin: Plugin) {\n plugin.setup(builder);\n}\n\nexport function getRegisteredThemes(): Theme[] {\n return themes;\n}\n\nexport function getAssetProvider(): AssetProvider | null {\n return assetProvider;\n}\n\nexport function getAIProvider(): AIProvider | null {\n return aiProvider;\n}\n","// Recommendation logic — ports the legacy Vibetrace logic-builder concept.\n// The full logic JSON is stored on the module under `module.data.recommendations`.\n// Any module that contains a `productGrid` child becomes \"product-aware\" and the\n// Recommendations panel auto-appears in the right sidebar when the module is selected.\n\nimport type { EmailModule } from \"../core/types\";\n\nexport type RecommendationMode = \"manual\" | \"recommender\";\n\nexport type FallbackId = \"smart-reccs\" | \"random\" | \"ignore\" | \"stop\";\n\nexport interface AlgorithmParamSpec {\n key: string;\n label: string;\n type: \"select\" | \"text\" | \"number\";\n options?: Array<{ value: string | number; label: string }>;\n default?: string | number;\n}\n\nexport interface AlgorithmDefinition {\n id: string;\n label: string;\n group?: \"behavioral\" | \"catalog\" | \"personal\" | \"contextual\";\n params?: AlgorithmParamSpec[];\n}\n\nexport interface StackEntry {\n algorithm: string;\n params?: Record<string, string | number | boolean>;\n}\n\nexport interface RecommendationFilters {\n /** Product IDs / SKUs to include (manual or boost). */\n includeProducts: string[];\n /** Product IDs / SKUs to exclude. */\n excludeProducts: string[];\n /** Categories to include. */\n includeCategories: string[];\n /** Categories to exclude. */\n excludeCategories: string[];\n minStock?: number;\n minPrice?: number;\n mainOnly?: boolean;\n higherPrice?: boolean;\n salesPrice?: boolean;\n sameCategory?: boolean;\n matchTitle?: boolean;\n /** Comma-separated property keys to match on, e.g. \"brand,color\". */\n sameField?: string;\n /** Free-form advanced JSON overrides. */\n advanced?: Record<string, unknown>;\n}\n\nexport interface RecommendationsLogic {\n mode: RecommendationMode;\n noProducts: number;\n /** Source feed id (for manual mode). */\n sourceFeed?: string;\n /** Manually-picked product ids (manual mode). */\n manualProducts: string[];\n /** Algorithm stack — tried in order. Max 3. */\n stack: StackEntry[];\n /** Last-resort algorithm. */\n fallback: FallbackId;\n filters: RecommendationFilters;\n}\n\n// ---------------------------------------------------------------------------\n// Algorithm catalog — ported from Vibetrace CONSTANTS.algorithms\n// ---------------------------------------------------------------------------\n\nconst daysParam: AlgorithmParamSpec = {\n key: \"days\",\n label: \"Time window\",\n type: \"select\",\n default: 7,\n options: [\n { value: 7, label: \"Last 7 days\" },\n { value: 14, label: \"Last 14 days\" },\n { value: 30, label: \"Last 30 days\" },\n ],\n};\n\nexport const ALGORITHMS: AlgorithmDefinition[] = [\n { id: \"abandoned-cart\", label: \"Abandoned basket products\", group: \"behavioral\" },\n { id: \"bestseller-conversion\", label: \"Best seller by Conversion\", group: \"catalog\", params: [daysParam] },\n { id: \"bestseller-units\", label: \"Best seller by Units\", group: \"catalog\", params: [daysParam] },\n { id: \"new-products\", label: \"New items added\", group: \"catalog\", params: [daysParam] },\n { id: \"cross-sell\", label: \"Products Cross-Sell\", group: \"contextual\" },\n { id: \"upsell\", label: \"Products Upsell\", group: \"contextual\" },\n { id: \"viewed-categories\", label: \"Items from viewed categories\", group: \"behavioral\" },\n { id: \"viewed-items\", label: \"Items viewed\", group: \"behavioral\" },\n { id: \"similar-basket\", label: \"Similar to basket items\", group: \"behavioral\" },\n { id: \"bought-together\", label: \"Items bought together\", group: \"contextual\" },\n { id: \"best-discount\", label: \"Items with the best discount\", group: \"catalog\" },\n { id: \"match-data\", label: \"Items matching specific attributes\", group: \"catalog\" },\n { id: \"last-purchased\", label: \"Last purchased items\", group: \"personal\" },\n { id: \"similar-to-purchased\", label: \"Similar to last purchase\", group: \"personal\" },\n { id: \"cross-sell-purchased\", label: \"Cross-sell to last purchase\", group: \"personal\" },\n { id: \"similar-items\", label: \"Similar items\", group: \"contextual\" },\n];\n\nexport const ALGORITHM_BY_ID: Record<string, AlgorithmDefinition> = Object.fromEntries(\n ALGORITHMS.map((a) => [a.id, a])\n);\n\nexport const FALLBACK_OPTIONS: Array<{ value: FallbackId; label: string; description: string }> = [\n { value: \"smart-reccs\", label: \"Smart Recommendations\", description: \"Best generic algorithm — recommended default.\" },\n { value: \"random\", label: \"Random items (strict filters)\", description: \"Random items that still pass include/exclude filters.\" },\n { value: \"ignore\", label: \"Ignore position\", description: \"Skip the slot if no items found.\" },\n { value: \"stop\", label: \"Don't display\", description: \"Don't render the email if the slot can't be filled.\" },\n];\n\nexport const MAX_STACK = 3;\n\nexport function defaultLogic(noProducts = 2): RecommendationsLogic {\n return {\n mode: \"recommender\",\n noProducts,\n sourceFeed: \"\",\n manualProducts: [],\n stack: [{ algorithm: \"abandoned-cart\" }],\n fallback: \"smart-reccs\",\n filters: {\n includeProducts: [],\n excludeProducts: [],\n includeCategories: [],\n excludeCategories: [],\n minStock: 0,\n minPrice: 0,\n mainOnly: false,\n higherPrice: false,\n salesPrice: false,\n sameCategory: false,\n matchTitle: false,\n sameField: \"\",\n },\n };\n}\n\n/** Read recommendations logic from a module, returning defaults if absent. */\nexport function readLogic(data: Record<string, unknown> | undefined): RecommendationsLogic | null {\n if (!data) return null;\n const raw = data[\"recommendations\"];\n if (!raw || typeof raw !== \"object\") return null;\n return raw as RecommendationsLogic;\n}\n\n/** A module is \"product-aware\" if any of its children renders products. */\nexport function isProductAware(m: EmailModule): boolean {\n if (!m?.children) return false;\n return m.children.some((c) => c.type === \"productGrid\");\n}\n\n/** Count of product slots the module currently shows (used as default noProducts). */\nexport function productSlotCount(m: EmailModule): number {\n if (!m?.children) return 0;\n let n = 0;\n for (const c of m.children) {\n if (c.type === \"productGrid\") n += c.products.length;\n }\n return n;\n}\n\n/** Serialize back to legacy Vibetrace-shaped JSON for backend interop. */\nexport function toLegacyShape(l: RecommendationsLogic) {\n return {\n params: {\n selection: l.mode === \"manual\" ? \"manual\" : \"recommender\",\n include: {\n item: l.filters.includeProducts,\n category: l.filters.includeCategories,\n },\n exclude: {\n item: l.filters.excludeProducts,\n category: l.filters.excludeCategories,\n },\n higherPrice: l.filters.higherPrice ?? false,\n salesPrice: l.filters.salesPrice ?? false,\n sameCategory: l.filters.sameCategory ?? false,\n matchTitle: l.filters.matchTitle ?? false,\n sameField: l.filters.sameField ?? \"\",\n mainOnly: l.filters.mainOnly ?? false,\n },\n noProducts: String(l.noProducts),\n fallback: l.fallback,\n stack: l.mode === \"manual\" ? [] : l.stack,\n minStock: String(l.filters.minStock ?? 0),\n minPrice: String(l.filters.minPrice ?? 0),\n sourceFeed: l.sourceFeed ?? \"\",\n manualProducts: l.manualProducts,\n };\n}\n","import { useState } from \"react\";\nimport { ChevronUp, ChevronDown, Trash2, Plus, X, Sparkles, Hand } from \"lucide-react\";\nimport { useEmailStore } from \"../store/emailStore\";\nimport type { EmailModule } from \"../core/types\";\nimport {\n ALGORITHMS,\n ALGORITHM_BY_ID,\n FALLBACK_OPTIONS,\n MAX_STACK,\n defaultLogic,\n readLogic,\n productSlotCount,\n type RecommendationsLogic,\n type StackEntry,\n} from \"../recommendations/logic\";\n\ninterface Props {\n mod: EmailModule;\n}\n\nexport function RecommendationsPanel({ mod }: Props) {\n const updateModule = useEmailStore((s) => s.updateModule);\n const slots = productSlotCount(mod) || 2;\n const logic = readLogic(mod.data) ?? defaultLogic(slots);\n\n const update = (patch: Partial<RecommendationsLogic>) => {\n const next = { ...logic, ...patch };\n updateModule(mod.id, { data: { ...(mod.data ?? {}), recommendations: next } });\n };\n\n const updateFilters = (patch: Partial<RecommendationsLogic[\"filters\"]>) =>\n update({ filters: { ...logic.filters, ...patch } });\n\n return (\n <div className=\"border border-blue-200 rounded-lg bg-blue-50/40 mt-4 overflow-hidden\">\n <div className=\"px-3 py-2 flex items-center gap-2 border-b border-blue-200 bg-blue-50\">\n <Sparkles size={14} className=\"text-blue-700\" />\n <div className=\"text-xs font-semibold text-blue-900 uppercase tracking-wide\">\n Products Source\n </div>\n </div>\n\n {/* Step 1 — choose how products are sourced */}\n <div className=\"p-3 bg-white border-b border-blue-100\">\n <div className=\"grid grid-cols-2 gap-2\">\n <ModeCard\n active={logic.mode === \"manual\"}\n \n title=\"Select Items\"\n subtitle=\"Hand-pick from a feed\"\n onClick={() => update({ mode: \"manual\" })}\n />\n <ModeCard\n active={logic.mode === \"recommender\"}\n \n title=\"Recommender\"\n subtitle=\"Algorithms + filters\"\n onClick={() => update({ mode: \"recommender\" })}\n />\n </div>\n </div>\n\n {/* Step 2 — per-mode body */}\n <div className=\"p-3 bg-white space-y-3\">\n <Field label=\"Number of products\">\n <input\n type=\"number\"\n min={1}\n max={20}\n value={logic.noProducts}\n onChange={(e) => update({ noProducts: Number(e.target.value) || 1 })}\n className={inputCls}\n />\n <div className=\"text-[11px] text-gray-500 mt-1\">\n Block has {slots} slot{slots === 1 ? \"\" : \"s\"} in the design.\n </div>\n </Field>\n\n {logic.mode === \"manual\" ? (\n <ManualSection logic={logic} update={update} />\n ) : (\n <RecommenderSection\n logic={logic}\n update={update}\n updateFilters={updateFilters}\n />\n )}\n\n <details className=\"border border-gray-200 rounded\">\n <summary className=\"px-2 py-1.5 text-[11px] font-medium text-gray-600 cursor-pointer select-none\">\n View saved JSON\n </summary>\n <pre className=\"text-[10px] bg-gray-900 text-gray-100 p-2 overflow-auto max-h-60 leading-tight\">\n {JSON.stringify(logic, null, 2)}\n </pre>\n </details>\n </div>\n </div>\n );\n}\n\n// ---------- Sections ----------\n\nfunction ManualSection({\n logic,\n update,\n}: {\n logic: RecommendationsLogic;\n update: (p: Partial<RecommendationsLogic>) => void;\n}) {\n return (\n <>\n <Field label=\"Source feed\">\n <input\n type=\"text\"\n placeholder=\"e.g. main-catalog\"\n value={logic.sourceFeed ?? \"\"}\n onChange={(e) => update({ sourceFeed: e.target.value })}\n className={inputCls}\n />\n </Field>\n <Field label=\"Items to include (product IDs / SKUs)\">\n <TokenInput\n value={logic.manualProducts}\n onChange={(v) => update({ manualProducts: v })}\n placeholder=\"Add product id\"\n />\n </Field>\n <div className=\"text-[11px] text-gray-500\">\n Items are sent to the renderer as-is in the order shown.\n </div>\n </>\n );\n}\n\nfunction RecommenderSection({\n logic,\n update,\n updateFilters,\n}: {\n logic: RecommendationsLogic;\n update: (p: Partial<RecommendationsLogic>) => void;\n updateFilters: (p: Partial<RecommendationsLogic[\"filters\"]>) => void;\n}) {\n const [advanced, setAdvanced] = useState(false);\n return (\n <>\n <div>\n <div className=\"flex items-center justify-between mb-1.5\">\n <label className=\"text-xs font-medium text-gray-700\">\n Algorithms (max {MAX_STACK})\n </label>\n <AddAlgorithmDropdown\n disabled={logic.stack.length >= MAX_STACK}\n existing={logic.stack.map((s) => s.algorithm)}\n onPick={(id) => update({ stack: [...logic.stack, { algorithm: id }] })}\n />\n </div>\n <StackList stack={logic.stack} onChange={(stack) => update({ stack })} />\n </div>\n\n <Field label=\"Fallback\">\n <select\n value={logic.fallback}\n onChange={(e) =>\n update({ fallback: e.target.value as RecommendationsLogic[\"fallback\"] })\n }\n className={inputCls}\n >\n {FALLBACK_OPTIONS.map((f) => (\n <option key={f.value} value={f.value}>\n {f.label}\n </option>\n ))}\n </select>\n <div className=\"text-[11px] text-gray-500 mt-1\">\n {FALLBACK_OPTIONS.find((f) => f.value === logic.fallback)?.description}\n </div>\n </Field>\n\n <SectionHeader\n title=\"Include & Exclude filters\"\n right={\n <div className=\"flex items-center gap-1\">\n <Pill active={!advanced} onClick={() => setAdvanced(false)}>\n Basic\n </Pill>\n <Pill active={advanced} onClick={() => setAdvanced(true)}>\n Advanced\n </Pill>\n </div>\n }\n />\n\n <Field label=\"Exclude products\">\n <TokenInput\n value={logic.filters.excludeProducts}\n onChange={(v) => updateFilters({ excludeProducts: v })}\n placeholder=\"Add product id\"\n />\n </Field>\n <Field label=\"Include products\">\n <TokenInput\n value={logic.filters.includeProducts}\n onChange={(v) => updateFilters({ includeProducts: v })}\n placeholder=\"Add product id\"\n />\n </Field>\n <Field label=\"Exclude categories\">\n <TokenInput\n value={logic.filters.excludeCategories}\n onChange={(v) => updateFilters({ excludeCategories: v })}\n placeholder=\"Add category\"\n />\n </Field>\n <Field label=\"Include categories\">\n <TokenInput\n value={logic.filters.includeCategories}\n onChange={(v) => updateFilters({ includeCategories: v })}\n placeholder=\"Add category\"\n />\n </Field>\n\n <div className=\"grid grid-cols-2 gap-2\">\n <Field label=\"Minimum stock\">\n <input\n type=\"number\"\n min={0}\n value={logic.filters.minStock ?? 0}\n onChange={(e) => updateFilters({ minStock: Number(e.target.value) || 0 })}\n className={inputCls}\n />\n </Field>\n <Field label=\"Minimum price\">\n <input\n type=\"number\"\n min={0}\n value={logic.filters.minPrice ?? 0}\n onChange={(e) => updateFilters({ minPrice: Number(e.target.value) || 0 })}\n className={inputCls}\n />\n </Field>\n </div>\n\n <ToggleRow\n label=\"Only main items\"\n checked={!!logic.filters.mainOnly}\n onChange={(v) => updateFilters({ mainOnly: v })}\n />\n <ToggleRow\n label=\"Higher price than current item (upsell)\"\n checked={!!logic.filters.higherPrice}\n onChange={(v) => updateFilters({ higherPrice: v })}\n />\n <ToggleRow\n label=\"On sale only\"\n checked={!!logic.filters.salesPrice}\n onChange={(v) => updateFilters({ salesPrice: v })}\n />\n <ToggleRow\n label=\"Same category as current\"\n checked={!!logic.filters.sameCategory}\n onChange={(v) => updateFilters({ sameCategory: v })}\n />\n <ToggleRow\n label=\"Match title keywords\"\n checked={!!logic.filters.matchTitle}\n onChange={(v) => updateFilters({ matchTitle: v })}\n />\n <Field label=\"Match same fields (comma-separated)\">\n <input\n type=\"text\"\n placeholder=\"brand, color\"\n value={logic.filters.sameField ?? \"\"}\n onChange={(e) => updateFilters({ sameField: e.target.value })}\n className={inputCls}\n />\n </Field>\n\n {advanced && (\n <Field label=\"Advanced JSON overrides\">\n <JsonEdit\n value={logic.filters.advanced ?? {}}\n onChange={(v) => updateFilters({ advanced: v })}\n />\n </Field>\n )}\n </>\n );\n}\n\n// ---------- Subcomponents ----------\n\nconst inputCls =\n \"w-full px-2 py-1.5 text-sm border border-gray-200 rounded focus:border-blue-500 focus:outline-none bg-white\";\n\nfunction ModeCard({\n active,\n icon,\n title,\n subtitle,\n onClick,\n}: {\n active: boolean;\n icon?: React.ReactNode;\n title: string;\n subtitle: string;\n onClick: () => void;\n}) {\n return (\n <button\n onClick={onClick}\n className={\n \"flex flex-col items-start gap-0.5 p-2.5 rounded border text-left transition \" +\n (active\n ? \"border-teal-600 bg-teal-50 ring-1 ring-teal-600\"\n : \"border-gray-200 bg-white hover:border-gray-300\")\n }\n >\n <div className={\"flex items-center gap-1.5 \" + (active ? \"text-teal-700\" : \"text-gray-700\")}>\n {icon}\n <span className=\"text-xs font-semibold\">{title}</span>\n </div>\n <span className=\"text-[10px] text-gray-500\">{subtitle}</span>\n </button>\n );\n}\n\nfunction SectionHeader({ title, right }: { title: string; right?: React.ReactNode }) {\n return (\n <div className=\"flex items-center justify-between border-t border-gray-200 pt-3 mt-3\">\n <div className=\"text-[11px] font-semibold uppercase tracking-wide text-gray-600\">\n {title}\n </div>\n {right}\n </div>\n );\n}\n\nfunction Field({ label, children }: { label: React.ReactNode; children: React.ReactNode }) {\n return (\n <div>\n <label className=\"block text-xs font-medium text-gray-700 mb-1\">{label}</label>\n {children}\n </div>\n );\n}\n\nfunction Pill({\n active,\n onClick,\n children,\n}: {\n active: boolean;\n onClick: () => void;\n children: React.ReactNode;\n}) {\n return (\n <button\n onClick={onClick}\n className={\n \"px-2 py-0.5 rounded text-[10px] font-semibold uppercase tracking-wide \" +\n (active ? \"bg-teal-600 text-white\" : \"bg-gray-100 text-gray-600 hover:bg-gray-200\")\n }\n >\n {children}\n </button>\n );\n}\n\nfunction ToggleRow({\n label,\n checked,\n onChange,\n}: {\n label: string;\n checked: boolean;\n onChange: (v: boolean) => void;\n}) {\n return (\n <label className=\"flex items-center justify-between gap-2 text-xs text-gray-700 py-1\">\n <span>{label}</span>\n <input\n type=\"checkbox\"\n checked={checked}\n onChange={(e) => onChange(e.target.checked)}\n className=\"h-4 w-4 accent-teal-600\"\n />\n </label>\n );\n}\n\nfunction StackList({\n stack,\n onChange,\n}: {\n stack: StackEntry[];\n onChange: (s: StackEntry[]) => void;\n}) {\n if (stack.length === 0) {\n return (\n <div className=\"text-[11px] text-gray-500 italic border border-dashed border-gray-300 rounded px-2 py-3 text-center\">\n No algorithms yet. Click <b>Add algorithm</b> to start.\n </div>\n );\n }\n const move = (i: number, dir: -1 | 1) => {\n const j = i + dir;\n if (j < 0 || j >= stack.length) return;\n const next = stack.slice();\n [next[i], next[j]] = [next[j], next[i]];\n onChange(next);\n };\n const remove = (i: number) => onChange(stack.filter((_, k) => k !== i));\n const setParam = (i: number, key: string, value: string | number) => {\n const next = stack.slice();\n next[i] = { ...next[i], params: { ...(next[i].params ?? {}), [key]: value } };\n onChange(next);\n };\n return (\n <div className=\"space-y-1.5\">\n {stack.map((s, i) => {\n const def = ALGORITHM_BY_ID[s.algorithm];\n return (\n <div\n key={i}\n className=\"border border-gray-200 rounded px-2 py-1.5 bg-white flex flex-col gap-1\"\n >\n <div className=\"flex items-center gap-1\">\n <span className=\"flex-1 text-xs text-gray-800 truncate\">\n {def?.label ?? s.algorithm}\n </span>\n <button\n title=\"Move up\"\n onClick={() => move(i, -1)}\n disabled={i === 0}\n className=\"p-1 text-gray-400 hover:text-gray-700 disabled:opacity-30\"\n >\n <ChevronUp size={13} />\n </button>\n <button\n title=\"Move down\"\n onClick={() => move(i, 1)}\n disabled={i === stack.length - 1}\n className=\"p-1 text-gray-400 hover:text-gray-700 disabled:opacity-30\"\n >\n <ChevronDown size={13} />\n </button>\n <button\n title=\"Remove\"\n onClick={() => remove(i)}\n className=\"p-1 text-gray-400 hover:text-red-600\"\n >\n <Trash2 size={13} />\n </button>\n </div>\n {def?.params?.map((p) => (\n <div key={p.key} className=\"flex items-center gap-2\">\n <span className=\"text-[10px] text-gray-500 w-20 shrink-0\">{p.label}</span>\n {p.type === \"select\" ? (\n <select\n value={String(s.params?.[p.key] ?? p.default ?? \"\")}\n onChange={(e) => setParam(i, p.key, e.target.value)}\n className=\"flex-1 text-xs border border-gray-200 rounded px-1.5 py-1 bg-white\"\n >\n {p.options?.map((o) => (\n <option key={String(o.value)} value={String(o.value)}>\n {o.label}\n </option>\n ))}\n </select>\n ) : (\n <input\n type={p.type === \"number\" ? \"number\" : \"text\"}\n value={String(s.params?.[p.key] ?? p.default ?? \"\")}\n onChange={(e) =>\n setParam(\n i,\n p.key,\n p.type === \"number\" ? Number(e.target.value) : e.target.value\n )\n }\n className=\"flex-1 text-xs border border-gray-200 rounded px-1.5 py-1\"\n />\n )}\n </div>\n ))}\n </div>\n );\n })}\n </div>\n );\n}\n\nfunction AddAlgorithmDropdown({\n disabled,\n existing,\n onPick,\n}: {\n disabled: boolean;\n existing: string[];\n onPick: (id: string) => void;\n}) {\n const [open, setOpen] = useState(false);\n return (\n <div className=\"relative\">\n <button\n disabled={disabled}\n onClick={() => setOpen((o) => !o)}\n className={\n \"flex items-center gap-1 px-2 py-1 rounded text-[11px] font-semibold uppercase \" +\n (disabled\n ? \"bg-gray-200 text-gray-400 cursor-not-allowed\"\n : \"bg-teal-600 text-white hover:bg-teal-700\")\n }\n >\n <Plus size={12} /> Add\n </button>\n {open && !disabled && (\n <>\n <div className=\"fixed inset-0 z-10\" onClick={() => setOpen(false)} />\n <div className=\"absolute right-0 top-full mt-1 w-64 max-h-80 overflow-auto bg-white border border-gray-200 rounded shadow-lg z-20\">\n {ALGORITHMS.map((a) => {\n const used = existing.includes(a.id);\n return (\n <button\n key={a.id}\n disabled={used}\n onClick={() => {\n onPick(a.id);\n setOpen(false);\n }}\n className={\n \"block w-full text-left px-2.5 py-1.5 text-xs \" +\n (used\n ? \"text-gray-400 cursor-not-allowed\"\n : \"text-gray-700 hover:bg-teal-50 hover:text-teal-700\")\n }\n >\n {a.label}\n {used && <span className=\"ml-1 text-[10px]\">· added</span>}\n </button>\n );\n })}\n </div>\n </>\n )}\n </div>\n );\n}\n\nfunction TokenInput({\n value,\n onChange,\n placeholder,\n}: {\n value: string[];\n onChange: (v: string[]) => void;\n placeholder?: string;\n}) {\n const [draft, setDraft] = useState(\"\");\n const add = () => {\n const v = draft.trim();\n if (!v) return;\n if (value.includes(v)) return;\n onChange([...value, v]);\n setDraft(\"\");\n };\n return (\n <div className=\"border border-gray-200 rounded bg-white p-1 flex flex-wrap items-center gap-1 focus-within:border-blue-500\">\n {value.map((tok) => (\n <span\n key={tok}\n className=\"inline-flex items-center gap-1 bg-gray-100 text-gray-800 text-[11px] rounded px-1.5 py-0.5\"\n >\n {tok}\n <button\n onClick={() => onChange(value.filter((x) => x !== tok))}\n className=\"text-gray-500 hover:text-red-600\"\n >\n <X size={10} />\n </button>\n </span>\n ))}\n <input\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \",\") {\n e.preventDefault();\n add();\n } else if (e.key === \"Backspace\" && !draft && value.length) {\n onChange(value.slice(0, -1));\n }\n }}\n onBlur={add}\n placeholder={value.length === 0 ? placeholder : \"\"}\n className=\"flex-1 min-w-20 outline-none text-xs bg-transparent px-1 py-0.5\"\n />\n </div>\n );\n}\n\nfunction JsonEdit({\n value,\n onChange,\n}: {\n value: Record<string, unknown>;\n onChange: (v: Record<string, unknown>) => void;\n}) {\n const [text, setText] = useState(() => JSON.stringify(value, null, 2));\n const [error, setError] = useState<string | null>(null);\n return (\n <div>\n <textarea\n value={text}\n onChange={(e) => {\n const t = e.target.value;\n setText(t);\n try {\n const parsed = JSON.parse(t || \"{}\");\n setError(null);\n onChange(parsed);\n } catch (err) {\n setError(String((err as Error).message));\n }\n }}\n rows={6}\n spellCheck={false}\n className=\"w-full font-mono text-[11px] border border-gray-200 rounded p-2 bg-gray-50 focus:border-blue-500 focus:outline-none\"\n />\n {error && <div className=\"text-[10px] text-red-600 mt-1\">{error}</div>}\n </div>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { useEmailStore } from \"../store/emailStore\";\nimport { resolveToken } from \"../core/theme\";\nimport { getAssetProvider } from \"../core/plugins\";\nimport { RecommendationsPanel } from \"./RecommendationsPanel\";\nimport { isProductAware } from \"../recommendations/logic\";\nimport type {\n EmailElement,\n EmailModule,\n TextElement,\n ImageElement,\n ButtonElement,\n SpacerElement,\n DividerElement,\n ProductGridElement,\n Product,\n} from \"../core/types\";\nimport { Smartphone, Monitor, Trash2, Plus, RotateCcw, Upload, Loader2 } from \"lucide-react\";\n\nexport function RightSidebar() {\n const { selection, doc, viewMode } = useEmailStore();\n\n return (\n <div className=\"w-72 bg-white border-l border-gray-200 shrink-0 overflow-y-auto\">\n <div className={`px-4 py-2 text-[11px] flex items-center gap-1.5 border-b ${viewMode === \"mobile\" ? \"bg-amber-50 text-amber-800 border-amber-200\" : \"bg-blue-50 text-blue-800 border-blue-100\"}`}>\n {viewMode === \"mobile\" ? <Smartphone size={12} /> : <Monitor size={12} />}\n Editing {viewMode} styles\n </div>\n <div className=\"p-4\">\n {!selection || selection.kind === \"email\" ? (\n <EmailSettingsPanel />\n ) : selection.kind === \"module\" ? (\n (() => {\n const m = doc.modules.find((x) => x.id === selection.moduleId);\n return m ? <ModulePanel mod={m} /> : <Empty />;\n })()\n ) : (\n (() => {\n const m = doc.modules.find((x) => x.id === selection.moduleId);\n const el = m?.children.find((c) => c.id === selection.elementId);\n return m && el ? <ElementPanel mod={m} el={el} /> : <Empty />;\n })()\n )}\n </div>\n </div>\n );\n}\n\nfunction Empty() {\n return <div className=\"text-xs text-gray-400\">Nothing selected.</div>;\n}\n\n// ---------- Mobile-aware style helpers ----------\n\n// Read merged style: in mobile view, base + mobile override; in desktop, just base.\nfunction readStyle(rawStyle: Record<string, unknown>, viewMode: \"desktop\" | \"mobile\") {\n if (viewMode !== \"mobile\") return rawStyle;\n const mobile = (rawStyle.mobile as Record<string, unknown> | undefined) ?? {};\n return { ...rawStyle, ...mobile };\n}\n\n// Write a patch into the right slot depending on view mode.\nfunction writeStylePatch(\n rawStyle: Record<string, unknown>,\n patch: Record<string, unknown>,\n viewMode: \"desktop\" | \"mobile\"\n): Record<string, unknown> {\n if (viewMode !== \"mobile\") return { ...rawStyle, ...patch };\n const mobile = (rawStyle.mobile as Record<string, unknown> | undefined) ?? {};\n return { ...rawStyle, mobile: { ...mobile, ...patch } };\n}\n\nfunction MobileBadge({ overridden }: { overridden: boolean }) {\n if (!overridden) return null;\n return (\n <span className=\"ml-1 text-[9px] uppercase tracking-wide bg-amber-100 text-amber-800 px-1 rounded\">\n mobile\n </span>\n );\n}\n\nfunction VisibilityField({\n hideOn,\n onChange,\n}: {\n hideOn: \"mobile\" | \"desktop\" | undefined;\n onChange: (v: \"mobile\" | \"desktop\" | undefined) => void;\n}) {\n return (\n <Field label=\"Visibility\">\n <Select\n value={hideOn ?? \"\"}\n onChange={(e) => {\n const v = e.target.value;\n onChange(v === \"\" ? undefined : (v as \"mobile\" | \"desktop\"));\n }}\n >\n <option value=\"\">Show on all</option>\n <option value=\"mobile\">Hide on mobile</option>\n <option value=\"desktop\">Hide on desktop</option>\n </Select>\n </Field>\n );\n}\n\nfunction PanelTitle({ children }: { children: React.ReactNode }) {\n return (\n <h3 className=\"text-xs font-semibold uppercase tracking-wide text-gray-500 mb-3\">\n {children}\n </h3>\n );\n}\n\nfunction Field({ label, children }: { label: React.ReactNode; children: React.ReactNode }) {\n return (\n <label className=\"block mb-3\">\n <span className=\"flex items-center text-xs text-gray-600 mb-1\">{label}</span>\n {children}\n </label>\n );\n}\n\nfunction TextInput(props: React.InputHTMLAttributes<HTMLInputElement>) {\n return (\n <input\n {...props}\n className=\"w-full px-2 py-1.5 text-sm border border-gray-200 rounded focus:border-blue-500 focus:outline-none\"\n />\n );\n}\n\nfunction NumberInput(props: React.InputHTMLAttributes<HTMLInputElement>) {\n return <TextInput type=\"number\" {...props} />;\n}\n\nfunction ImageUrlInput({\n value,\n onChange,\n onAlt,\n}: {\n value: string;\n onChange: (url: string) => void;\n onAlt?: (alt: string) => void;\n}) {\n const provider = getAssetProvider();\n const fileRef = useRef<HTMLInputElement | null>(null);\n const [busy, setBusy] = useState(false);\n const [err, setErr] = useState<string | null>(null);\n\n const handleFile = async (file: File) => {\n if (!provider) return;\n setBusy(true);\n setErr(null);\n try {\n const res = await provider.upload(file);\n onChange(res.url);\n if (res.alt && onAlt) onAlt(res.alt);\n } catch (e) {\n setErr(e instanceof Error ? e.message : String(e));\n } finally {\n setBusy(false);\n if (fileRef.current) fileRef.current.value = \"\";\n }\n };\n\n return (\n <div>\n <div className=\"flex gap-1\">\n <TextInput value={value ?? \"\"} onChange={(e) => onChange(e.target.value)} />\n {provider && (\n <>\n <input\n ref={fileRef}\n type=\"file\"\n accept=\"image/*\"\n className=\"hidden\"\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) void handleFile(f);\n }}\n />\n <button\n type=\"button\"\n disabled={busy}\n onClick={() => fileRef.current?.click()}\n className=\"shrink-0 px-2 py-1.5 text-xs border border-gray-200 rounded hover:bg-gray-50 disabled:opacity-50 flex items-center gap-1\"\n title=\"Upload image\"\n >\n {busy ? <Loader2 size={12} className=\"animate-spin\" /> : <Upload size={12} />}\n </button>\n </>\n )}\n </div>\n {err && <p className=\"text-[10px] text-red-600 mt-1\">{err}</p>}\n {!provider && (\n <p className=\"text-[10px] text-gray-400 mt-1\">\n Tip: register an image uploader plugin to enable file uploads.\n </p>\n )}\n </div>\n );\n}\n\nfunction ColorInput({\n value,\n onChange,\n defaultValue,\n}: {\n value: string;\n onChange: (v: string) => void;\n defaultValue?: string;\n}) {\n const theme = useEmailStore((s) => s.doc.theme);\n const isToken = typeof value === \"string\" && value.startsWith(\"{\");\n\n // Remember the most recent token seen so the user can reset back to it\n // even after picking a custom hex color.\n const lastTokenRef = useRef<string | undefined>(\n defaultValue && defaultValue.startsWith(\"{\") ? defaultValue : isToken ? value : undefined\n );\n useEffect(() => {\n if (isToken) lastTokenRef.current = value;\n else if (defaultValue && defaultValue.startsWith(\"{\")) lastTokenRef.current = defaultValue;\n }, [value, isToken, defaultValue]);\n\n // Hex shown in the native picker swatch (resolves tokens against theme).\n const swatchHex = (() => {\n const resolved = resolveToken(value, theme);\n if (typeof resolved === \"string\" && /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(resolved)) {\n return resolved.length === 4\n ? \"#\" + resolved.slice(1).split(\"\").map((c) => c + c).join(\"\")\n : resolved;\n }\n return \"#000000\";\n })();\n\n const resetTarget = defaultValue ?? lastTokenRef.current;\n const canReset = !!resetTarget && resetTarget !== value;\n\n // Local text mirrors prop but lets user type freely (commits on blur/Enter).\n const [text, setText] = useState(value ?? \"\");\n useEffect(() => setText(value ?? \"\"), [value]);\n\n return (\n <div className=\"flex gap-1 items-center\">\n <label\n className=\"relative w-9 h-8 border border-gray-200 rounded cursor-pointer overflow-hidden shrink-0\"\n title={isToken ? `Token → ${swatchHex} (click to override)` : \"Pick color\"}\n style={{ background: swatchHex }}\n >\n <input\n type=\"color\"\n value={swatchHex}\n onChange={(e) => onChange(e.target.value)}\n className=\"absolute inset-0 opacity-0 cursor-pointer\"\n />\n {isToken && (\n <span\n className=\"absolute inset-0 pointer-events-none border-2 border-dashed rounded\"\n style={{ borderColor: \"rgba(255,255,255,0.6)\" }}\n />\n )}\n </label>\n <input\n value={text}\n onChange={(e) => setText(e.target.value)}\n onBlur={() => text !== value && onChange(text)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") (e.target as HTMLInputElement).blur();\n }}\n className=\"w-full px-2 py-1.5 text-sm border border-gray-200 rounded focus:border-blue-500 focus:outline-none font-mono\"\n />\n {canReset && (\n <button\n type=\"button\"\n onClick={() => onChange(resetTarget!)}\n className=\"shrink-0 p-1.5 text-gray-400 hover:text-blue-600 hover:bg-blue-50 rounded\"\n title={`Reset to ${resetTarget}`}\n >\n <RotateCcw size={12} />\n </button>\n )}\n </div>\n );\n}\n\nfunction Select(props: React.SelectHTMLAttributes<HTMLSelectElement>) {\n return (\n <select\n {...props}\n className=\"w-full px-2 py-1.5 text-sm border border-gray-200 rounded focus:border-blue-500 focus:outline-none bg-white\"\n />\n );\n}\n\n// ---------- Email-level panel ----------\n\nfunction EmailSettingsPanel() {\n const { doc, updateMeta, updateSettings } = useEmailStore();\n return (\n <>\n <PanelTitle>Email</PanelTitle>\n <Field label=\"Name\">\n <TextInput\n value={doc.meta.name}\n onChange={(e) => updateMeta({ name: e.target.value })}\n />\n </Field>\n <Field label=\"Preview text\">\n <TextInput\n value={doc.meta.previewText}\n onChange={(e) => updateMeta({ previewText: e.target.value })}\n />\n </Field>\n <Field label=\"Width (px)\">\n <NumberInput\n value={doc.settings.width}\n onChange={(e) => updateSettings({ width: Number(e.target.value) || 600 })}\n />\n </Field>\n <Field label=\"Background color\">\n <ColorInput\n value={doc.settings.backgroundColor}\n onChange={(v) => updateSettings({ backgroundColor: v })}\n />\n </Field>\n <Field label=\"Content background color\">\n <ColorInput\n value={doc.settings.contentBackgroundColor}\n onChange={(v) => updateSettings({ contentBackgroundColor: v })}\n />\n </Field>\n\n <div className=\"mt-6 pt-4 border-t border-gray-100\">\n <PanelTitle>Theme tokens (read-only preview)</PanelTitle>\n <div className=\"text-xs space-y-1\">\n <div className=\"font-medium\">{doc.theme.name}</div>\n <div className=\"grid grid-cols-2 gap-1 text-gray-500\">\n {Object.entries(doc.theme.tokens.colors).map(([k, v]) => (\n <div key={k} className=\"flex items-center gap-1\">\n <span className=\"w-3 h-3 rounded\" style={{ background: v }} />\n <span className=\"truncate\">{k}</span>\n </div>\n ))}\n </div>\n </div>\n </div>\n </>\n );\n}\n\n// ---------- Module panel ----------\n\nfunction ModulePanel({ mod }: { mod: EmailModule }) {\n const updateModule = useEmailStore((s) => s.updateModule);\n const viewMode = useEmailStore((s) => s.viewMode);\n const rawStyle = (mod.style ?? {}) as Record<string, unknown>;\n const style = readStyle(rawStyle, viewMode);\n const mobileKeys = new Set(Object.keys((rawStyle.mobile as Record<string, unknown>) ?? {}));\n const set = (patch: Record<string, unknown>) =>\n updateModule(mod.id, { style: writeStylePatch(rawStyle, patch, viewMode) });\n return (\n <>\n <PanelTitle>{mod.name}</PanelTitle>\n <Field label={<>Background color<MobileBadge overridden={mobileKeys.has(\"backgroundColor\")} /></>}>\n <ColorInput\n value={(style.backgroundColor as string) ?? \"\"}\n onChange={(v) => set({ backgroundColor: v })}\n />\n </Field>\n <PaddingFields style={style} mobileKeys={mobileKeys} onSet={set} />\n <Field label={<>Border radius<MobileBadge overridden={mobileKeys.has(\"borderRadius\")} /></>}>\n <NumberInput\n value={(style.borderRadius as number) ?? 0}\n onChange={(e) => set({ borderRadius: Number(e.target.value) })}\n />\n </Field>\n <VisibilityField\n hideOn={rawStyle.hideOn as \"mobile\" | \"desktop\" | undefined}\n onChange={(v) => updateModule(mod.id, { style: { ...rawStyle, hideOn: v } })}\n />\n {isProductAware(mod) && <RecommendationsPanel mod={mod} />}\n </>\n );\n}\n\n// ---------- Element panel ----------\n\nfunction ElementPanel({ mod, el }: { mod: EmailModule; el: EmailElement }) {\n switch (el.type) {\n case \"text\":\n return <TextElementPanel mod={mod} el={el} />;\n case \"image\":\n return <ImageElementPanel mod={mod} el={el} />;\n case \"button\":\n return <ButtonElementPanel mod={mod} el={el} />;\n case \"spacer\":\n return <SpacerElementPanel mod={mod} el={el} />;\n case \"divider\":\n return <DividerElementPanel mod={mod} el={el} />;\n case \"productGrid\":\n return <ProductGridElementPanel mod={mod} el={el} />;\n }\n}\n\nfunction PaddingFields({\n style,\n mobileKeys,\n onSet,\n}: {\n style: Record<string, unknown>;\n mobileKeys?: Set<string>;\n onSet: (p: Record<string, unknown>) => void;\n}) {\n return (\n <div className=\"grid grid-cols-2 gap-2 mb-3\">\n {([\"paddingTop\", \"paddingBottom\", \"paddingLeft\", \"paddingRight\"] as const).map((k) => (\n <Field key={k} label={<>{k.replace(\"padding\", \"Pad \")}<MobileBadge overridden={!!mobileKeys?.has(k)} /></>}>\n <NumberInput\n value={(style[k] as number) ?? 0}\n onChange={(e) => onSet({ [k]: Number(e.target.value) })}\n />\n </Field>\n ))}\n </div>\n );\n}\n\nfunction useElPatch<T extends EmailElement>(mod: EmailModule, el: T) {\n const updateElement = useEmailStore((s) => s.updateElement);\n return (patch: Partial<T>) => updateElement(mod.id, el.id, patch as Partial<EmailElement>);\n}\n\nfunction TextElementPanel({ mod, el }: { mod: EmailModule; el: TextElement }) {\n const patch = useElPatch(mod, el);\n const viewMode = useEmailStore((s) => s.viewMode);\n const rawStyle = (el.style ?? {}) as Record<string, unknown>;\n const style = readStyle(rawStyle, viewMode);\n const mobileKeys = new Set(Object.keys((rawStyle.mobile as Record<string, unknown>) ?? {}));\n const setStyle = (p: Record<string, unknown>) =>\n patch({ style: writeStylePatch(rawStyle, p, viewMode) } as Partial<TextElement>);\n return (\n <>\n <PanelTitle>Text</PanelTitle>\n <Field label=\"Content\">\n <textarea\n value={el.content.replace(/<br\\s*\\/?>/g, \"\\n\")}\n onChange={(e) =>\n patch({ content: e.target.value.replace(/\\n/g, \"<br/>\") } as Partial<TextElement>)\n }\n rows={3}\n className=\"w-full px-2 py-1.5 text-sm border border-gray-200 rounded focus:border-blue-500 focus:outline-none\"\n />\n </Field>\n <Field label=\"Font family\">\n <TextInput\n value={(style.fontFamily as string) ?? \"\"}\n onChange={(e) => setStyle({ fontFamily: e.target.value })}\n />\n </Field>\n <div className=\"grid grid-cols-2 gap-2\">\n <Field label=\"Font size\">\n <NumberInput\n value={(style.fontSize as number) ?? 16}\n onChange={(e) => setStyle({ fontSize: Number(e.target.value) })}\n />\n </Field>\n <Field label=\"Weight\">\n <TextInput\n value={String(style.fontWeight ?? \"\")}\n onChange={(e) => setStyle({ fontWeight: e.target.value || undefined })}\n />\n </Field>\n <Field label=\"Line height\">\n <NumberInput\n step={0.1}\n value={(style.lineHeight as number) ?? 1.5}\n onChange={(e) => setStyle({ lineHeight: Number(e.target.value) })}\n />\n </Field>\n <Field label=\"Letter spacing\">\n <NumberInput\n value={(style.letterSpacing as number) ?? 0}\n onChange={(e) => setStyle({ letterSpacing: Number(e.target.value) })}\n />\n </Field>\n </div>\n <Field label=\"Color\">\n <ColorInput\n value={(style.color as string) ?? \"#000000\"}\n onChange={(v) => setStyle({ color: v })}\n />\n </Field>\n <Field label=\"Align\">\n <Select\n value={(style.align as string) ?? \"left\"}\n onChange={(e) => setStyle({ align: e.target.value })}\n >\n <option value=\"left\">Left</option>\n <option value=\"center\">Center</option>\n <option value=\"right\">Right</option>\n </Select>\n </Field>\n <Field label=\"Link URL\">\n <TextInput\n value={(style.link as string) ?? \"\"}\n onChange={(e) => setStyle({ link: e.target.value })}\n />\n </Field>\n <PaddingFields style={style} mobileKeys={mobileKeys} onSet={setStyle} />\n <VisibilityField\n hideOn={rawStyle.hideOn as \"mobile\" | \"desktop\" | undefined}\n onChange={(v) => patch({ style: { ...rawStyle, hideOn: v } } as Partial<TextElement>)}\n />\n <button\n onClick={() =>\n patch({ content: `${el.content} ✨` } as Partial<TextElement>)\n }\n className=\"w-full mt-2 px-3 py-2 text-xs bg-purple-50 text-purple-700 border border-purple-200 rounded hover:bg-purple-100\"\n >\n ✨ AI rewrite (mock)\n </button>\n </>\n );\n}\n\nfunction ImageElementPanel({ mod, el }: { mod: EmailModule; el: ImageElement }) {\n const patch = useElPatch(mod, el);\n const viewMode = useEmailStore((s) => s.viewMode);\n const rawStyle = (el.style ?? {}) as Record<string, unknown>;\n const style = readStyle(rawStyle, viewMode);\n const mobileKeys = new Set(Object.keys((rawStyle.mobile as Record<string, unknown>) ?? {}));\n const setStyle = (p: Record<string, unknown>) =>\n patch({ style: writeStylePatch(rawStyle, p, viewMode) } as Partial<ImageElement>);\n return (\n <>\n <PanelTitle>Image</PanelTitle>\n <Field label=\"Image URL\">\n <ImageUrlInput\n value={el.src}\n onChange={(url) => patch({ src: url } as Partial<ImageElement>)}\n onAlt={(alt) => patch({ alt } as Partial<ImageElement>)}\n />\n </Field>\n <Field label=\"Alt text\">\n <TextInput\n value={el.alt ?? \"\"}\n onChange={(e) => patch({ alt: e.target.value } as Partial<ImageElement>)}\n />\n </Field>\n <Field label=\"Link\">\n <TextInput\n value={el.link ?? \"\"}\n onChange={(e) => patch({ link: e.target.value } as Partial<ImageElement>)}\n />\n </Field>\n <div className=\"grid grid-cols-2 gap-2\">\n <Field label={<>Width<MobileBadge overridden={mobileKeys.has(\"width\")} /></>}>\n <NumberInput\n value={(style.width as number) ?? 0}\n onChange={(e) => setStyle({ width: Number(e.target.value) })}\n />\n </Field>\n <Field label={<>Height<MobileBadge overridden={mobileKeys.has(\"height\")} /></>}>\n <NumberInput\n value={(style.height as number) ?? 0}\n onChange={(e) => setStyle({ height: Number(e.target.value) || undefined })}\n />\n </Field>\n </div>\n <Field label=\"Border radius\">\n <NumberInput\n value={(style.borderRadius as number) ?? 0}\n onChange={(e) => setStyle({ borderRadius: Number(e.target.value) })}\n />\n </Field>\n <Field label=\"Align\">\n <Select\n value={(style.align as string) ?? \"center\"}\n onChange={(e) => setStyle({ align: e.target.value })}\n >\n <option value=\"left\">Left</option>\n <option value=\"center\">Center</option>\n <option value=\"right\">Right</option>\n </Select>\n </Field>\n <PaddingFields style={style} mobileKeys={mobileKeys} onSet={setStyle} />\n <VisibilityField\n hideOn={rawStyle.hideOn as \"mobile\" | \"desktop\" | undefined}\n onChange={(v) => patch({ style: { ...rawStyle, hideOn: v } } as Partial<ImageElement>)}\n />\n </>\n );\n}\n\nfunction ButtonElementPanel({ mod, el }: { mod: EmailModule; el: ButtonElement }) {\n const patch = useElPatch(mod, el);\n const viewMode = useEmailStore((s) => s.viewMode);\n const rawStyle = (el.style ?? {}) as Record<string, unknown>;\n const style = readStyle(rawStyle, viewMode);\n const mobileKeys = new Set(Object.keys((rawStyle.mobile as Record<string, unknown>) ?? {}));\n const setStyle = (p: Record<string, unknown>) =>\n patch({ style: writeStylePatch(rawStyle, p, viewMode) } as Partial<ButtonElement>);\n return (\n <>\n <PanelTitle>Button</PanelTitle>\n <Field label=\"Label\">\n <TextInput value={el.label} onChange={(e) => patch({ label: e.target.value } as Partial<ButtonElement>)} />\n </Field>\n <Field label=\"Link\">\n <TextInput value={el.link} onChange={(e) => patch({ link: e.target.value } as Partial<ButtonElement>)} />\n </Field>\n <Field label=\"Background color\">\n <ColorInput\n value={(style.backgroundColor as string) ?? \"\"}\n onChange={(v) => setStyle({ backgroundColor: v })}\n />\n </Field>\n <Field label=\"Text color\">\n <ColorInput\n value={(style.color as string) ?? \"#FFFFFF\"}\n onChange={(v) => setStyle({ color: v })}\n />\n </Field>\n <div className=\"grid grid-cols-2 gap-2\">\n <Field label=\"Font size\">\n <NumberInput\n value={(style.fontSize as number) ?? 16}\n onChange={(e) => setStyle({ fontSize: Number(e.target.value) })}\n />\n </Field>\n <Field label=\"Border radius\">\n <NumberInput\n value={(style.borderRadius as number) ?? 6}\n onChange={(e) => setStyle({ borderRadius: Number(e.target.value) })}\n />\n </Field>\n </div>\n <Field label=\"Align\">\n <Select\n value={(style.align as string) ?? \"center\"}\n onChange={(e) => setStyle({ align: e.target.value })}\n >\n <option value=\"left\">Left</option>\n <option value=\"center\">Center</option>\n <option value=\"right\">Right</option>\n </Select>\n </Field>\n <PaddingFields style={style} mobileKeys={mobileKeys} onSet={setStyle} />\n <VisibilityField\n hideOn={rawStyle.hideOn as \"mobile\" | \"desktop\" | undefined}\n onChange={(v) => patch({ style: { ...rawStyle, hideOn: v } } as Partial<ButtonElement>)}\n />\n </>\n );\n}\n\nfunction SpacerElementPanel({ mod, el }: { mod: EmailModule; el: SpacerElement }) {\n const patch = useElPatch(mod, el);\n return (\n <>\n <PanelTitle>Spacer</PanelTitle>\n <Field label=\"Height (px)\">\n <NumberInput\n value={el.height}\n onChange={(e) => patch({ height: Number(e.target.value) || 0 } as Partial<SpacerElement>)}\n />\n </Field>\n </>\n );\n}\n\nfunction DividerElementPanel({ mod, el }: { mod: EmailModule; el: DividerElement }) {\n const patch = useElPatch(mod, el);\n const viewMode = useEmailStore((s) => s.viewMode);\n const rawStyle = (el.style ?? {}) as Record<string, unknown>;\n const style = readStyle(rawStyle, viewMode);\n const mobileKeys = new Set(Object.keys((rawStyle.mobile as Record<string, unknown>) ?? {}));\n const setStyle = (p: Record<string, unknown>) =>\n patch({ style: writeStylePatch(rawStyle, p, viewMode) } as Partial<DividerElement>);\n return (\n <>\n <PanelTitle>Divider</PanelTitle>\n <Field label=\"Color\">\n <ColorInput\n value={(style.color as string) ?? \"#E5E7EB\"}\n onChange={(v) => setStyle({ color: v })}\n />\n </Field>\n <Field label=\"Thickness\">\n <NumberInput\n value={(style.thickness as number) ?? 1}\n onChange={(e) => setStyle({ thickness: Number(e.target.value) })}\n />\n </Field>\n <PaddingFields style={style} mobileKeys={mobileKeys} onSet={setStyle} />\n <VisibilityField\n hideOn={rawStyle.hideOn as \"mobile\" | \"desktop\" | undefined}\n onChange={(v) => patch({ style: { ...rawStyle, hideOn: v } } as Partial<DividerElement>)}\n />\n </>\n );\n}\n\n// ---------- Product Grid panel ----------\n\nfunction newProduct(seed = 0): Product {\n const i = seed + 1;\n return {\n id: `p_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`,\n image: `https://placehold.co/400x400?text=Product+${i}`,\n imageAlt: `Product ${i}`,\n name: `Product ${i}`,\n oldPrice: \"$59\",\n finalPrice: \"$39\",\n description: \"Short product description.\",\n link: \"#\",\n };\n}\n\nfunction ProductGridElementPanel({ mod, el }: { mod: EmailModule; el: ProductGridElement }) {\n const patch = useElPatch(mod, el);\n const viewMode = useEmailStore((s) => s.viewMode);\n const rawStyle = (el.style ?? {}) as Record<string, unknown>;\n const style = readStyle(rawStyle, viewMode);\n const setStyle = (p: Record<string, unknown>) =>\n patch({ style: writeStylePatch(rawStyle, p, viewMode) } as Partial<ProductGridElement>);\n\n const setProducts = (products: Product[]) =>\n patch({ products } as Partial<ProductGridElement>);\n\n const setColumns = (columns: 1 | 2 | 3) => {\n // Resize products array to a sensible default for the new column count.\n const target = columns;\n let products = el.products.slice();\n if (products.length < target) {\n while (products.length < target) products.push(newProduct(products.length));\n }\n patch({ columns, products } as Partial<ProductGridElement>);\n };\n\n return (\n <>\n <PanelTitle>Product Grid</PanelTitle>\n\n <Field label=\"Columns (desktop)\">\n <div className=\"inline-flex bg-gray-100 rounded p-0.5 w-full\">\n {[1, 2, 3].map((n) => (\n <button\n key={n}\n onClick={() => setColumns(n as 1 | 2 | 3)}\n className={`flex-1 px-2 py-1 text-xs rounded ${\n el.columns === n ? \"bg-white shadow text-gray-900\" : \"text-gray-500 hover:text-gray-700\"\n }`}\n >\n {n} {n === 1 ? \"col\" : \"cols\"}\n </button>\n ))}\n </div>\n <p className=\"text-[10px] text-gray-400 mt-1\">Always stacks to 1 column on mobile.</p>\n </Field>\n\n <Field label=\"Show old price\">\n <Toggle\n checked={el.showOldPrice}\n onChange={(v) => patch({ showOldPrice: v } as Partial<ProductGridElement>)}\n />\n </Field>\n <Field label=\"Show description\">\n <Toggle\n checked={el.showDescription}\n onChange={(v) => patch({ showDescription: v } as Partial<ProductGridElement>)}\n />\n </Field>\n <Field label=\"Show button\">\n <Toggle\n checked={el.showButton}\n onChange={(v) => patch({ showButton: v } as Partial<ProductGridElement>)}\n />\n </Field>\n {el.showButton && (\n <Field label=\"Default button label\">\n <TextInput\n value={el.buttonLabel ?? \"\"}\n placeholder=\"Shop now\"\n onChange={(e) => patch({ buttonLabel: e.target.value } as Partial<ProductGridElement>)}\n />\n </Field>\n )}\n\n <div className=\"mt-4 pt-3 border-t border-gray-100\">\n <div className=\"flex items-center justify-between mb-2\">\n <PanelTitle>Products ({el.products.length})</PanelTitle>\n <button\n onClick={() => setProducts([...el.products, newProduct(el.products.length)])}\n className=\"flex items-center gap-1 px-1.5 py-0.5 text-[11px] text-blue-600 hover:bg-blue-50 rounded\"\n title=\"Add product\"\n >\n <Plus size={12} /> Add\n </button>\n </div>\n {el.products.map((p, idx) => (\n <ProductRow\n key={p.id}\n index={idx}\n product={p}\n showOldPrice={el.showOldPrice}\n showDescription={el.showDescription}\n showButton={el.showButton}\n onChange={(np) => {\n const next = [...el.products];\n next[idx] = np;\n setProducts(next);\n }}\n onDelete={() => setProducts(el.products.filter((_, i) => i !== idx))}\n />\n ))}\n </div>\n\n <div className=\"mt-4 pt-3 border-t border-gray-100\">\n <PanelTitle>Style</PanelTitle>\n <Field label=\"Card background\">\n <ColorInput\n value={(style.cardBackgroundColor as string) ?? \"\"}\n onChange={(v) => setStyle({ cardBackgroundColor: v })}\n />\n </Field>\n <Field label=\"Name color\">\n <ColorInput\n value={(style.nameColor as string) ?? \"\"}\n onChange={(v) => setStyle({ nameColor: v })}\n />\n </Field>\n <Field label=\"Final price color\">\n <ColorInput\n value={(style.finalPriceColor as string) ?? \"\"}\n onChange={(v) => setStyle({ finalPriceColor: v })}\n />\n </Field>\n <Field label=\"Old price color\">\n <ColorInput\n value={(style.oldPriceColor as string) ?? \"\"}\n onChange={(v) => setStyle({ oldPriceColor: v })}\n />\n </Field>\n <Field label=\"Button background\">\n <ColorInput\n value={(style.buttonBackgroundColor as string) ?? \"\"}\n onChange={(v) => setStyle({ buttonBackgroundColor: v })}\n />\n </Field>\n <Field label=\"Button text color\">\n <ColorInput\n value={(style.buttonColor as string) ?? \"\"}\n onChange={(v) => setStyle({ buttonColor: v })}\n />\n </Field>\n <Field label=\"Card radius\">\n <NumberInput\n value={(style.borderRadius as number) ?? 0}\n onChange={(e) => setStyle({ borderRadius: Number(e.target.value) })}\n />\n </Field>\n <PaddingFields style={style} onSet={setStyle} />\n </div>\n </>\n );\n}\n\nfunction Toggle({ checked, onChange }: { checked: boolean; onChange: (v: boolean) => void }) {\n return (\n <button\n onClick={() => onChange(!checked)}\n className={`relative inline-flex h-5 w-9 items-center rounded-full transition-colors ${\n checked ? \"bg-blue-600\" : \"bg-gray-300\"\n }`}\n >\n <span\n className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${\n checked ? \"translate-x-4\" : \"translate-x-0.5\"\n }`}\n />\n </button>\n );\n}\n\nfunction ProductRow({\n index,\n product,\n showOldPrice,\n showDescription,\n showButton,\n onChange,\n onDelete,\n}: {\n index: number;\n product: Product;\n showOldPrice: boolean;\n showDescription: boolean;\n showButton: boolean;\n onChange: (p: Product) => void;\n onDelete: () => void;\n}) {\n const set = (p: Partial<Product>) => onChange({ ...product, ...p });\n return (\n <div className=\"border border-gray-200 rounded p-2 mb-2 bg-gray-50\">\n <div className=\"flex items-center justify-between mb-2\">\n <span className=\"text-[11px] font-semibold text-gray-600\">#{index + 1}</span>\n <button\n onClick={onDelete}\n className=\"text-gray-400 hover:text-red-600\"\n title=\"Remove product\"\n >\n <Trash2 size={12} />\n </button>\n </div>\n <Field label=\"Name\">\n <TextInput value={product.name} onChange={(e) => set({ name: e.target.value })} />\n </Field>\n <Field label=\"Image URL\">\n <ImageUrlInput\n value={product.image}\n onChange={(url) => set({ image: url })}\n onAlt={(alt) => set({ imageAlt: alt })}\n />\n </Field>\n <Field label=\"Link\">\n <TextInput\n value={product.link ?? \"\"}\n onChange={(e) => set({ link: e.target.value })}\n />\n </Field>\n <div className=\"grid grid-cols-2 gap-2\">\n <Field label=\"Final price\">\n <TextInput\n value={product.finalPrice}\n onChange={(e) => set({ finalPrice: e.target.value })}\n />\n </Field>\n {showOldPrice && (\n <Field label=\"Old price\">\n <TextInput\n value={product.oldPrice ?? \"\"}\n onChange={(e) => set({ oldPrice: e.target.value })}\n />\n </Field>\n )}\n </div>\n {showDescription && (\n <Field label=\"Description\">\n <TextInput\n value={product.description ?? \"\"}\n onChange={(e) => set({ description: e.target.value })}\n />\n </Field>\n )}\n {showButton && (\n <Field label=\"Button label (override)\">\n <TextInput\n value={product.buttonLabel ?? \"\"}\n placeholder=\"Inherit default\"\n onChange={(e) => set({ buttonLabel: e.target.value || undefined })}\n />\n </Field>\n )}\n </div>\n );\n}\n","import type { ModuleDefinition } from \"./registry\";\nimport { text, image, spacer, divider, mod, PLACEHOLDER } from \"./helpers\";\n\nexport const basicModules: ModuleDefinition[] = [\n {\n type: \"basic.text\",\n category: \"basic\",\n name: \"Text Block\",\n description: \"Single editable paragraph of body copy. Use for short notes, intros, or filler text between sections.\",\n tags: [\"text\", \"paragraph\", \"body\"],\n create: () =>\n mod(\"basic.text\", \"Text Block\", [text(\"Write your text here.\", { role: \"body\" })]),\n },\n {\n type: \"basic.heading\",\n category: \"basic\",\n name: \"Heading\",\n description: \"Bold standalone heading using the theme heading font. Use to introduce a section without other elements.\",\n tags: [\"heading\", \"title\", \"section\"],\n create: () =>\n mod(\"basic.heading\", \"Heading\", [\n text(\"A clear section heading\", {\n role: \"headline\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 28,\n fontWeight: \"bold\",\n paddingTop: 16,\n paddingBottom: 8,\n lineHeight: 1.25,\n }),\n ]),\n },\n {\n type: \"basic.image\",\n category: \"basic\",\n name: \"Image\",\n description: \"Single full-width image, centered. Use for hero photography, illustrations, or screenshots.\",\n tags: [\"image\", \"media\", \"photo\"],\n create: () => mod(\"basic.image\", \"Image\", [image(PLACEHOLDER(600, 300), \"Placeholder\")]),\n },\n {\n type: \"basic.image_caption\",\n category: \"basic\",\n name: \"Image with Caption\",\n description: \"Image followed by a small italicized caption underneath. Editorial style for newsletters.\",\n tags: [\"image\", \"caption\", \"editorial\"],\n create: () =>\n mod(\"basic.image_caption\", \"Image + Caption\", [\n image(PLACEHOLDER(600, 360), \"Photo\"),\n text(\"Photo: caption goes here.\", {\n color: \"{colors.muted}\",\n fontSize: 13,\n align: \"center\",\n paddingTop: 4,\n paddingBottom: 16,\n }),\n ]),\n },\n {\n type: \"basic.spacer\",\n category: \"basic\",\n name: \"Spacer\",\n description: \"Empty vertical space. Use to separate modules with breathing room.\",\n tags: [\"spacer\", \"spacing\", \"gap\"],\n create: () => mod(\"basic.spacer\", \"Spacer\", [spacer(32)]),\n },\n {\n type: \"basic.divider\",\n category: \"basic\",\n name: \"Divider\",\n description: \"Thin horizontal rule across the email. Use to visually separate sections.\",\n tags: [\"divider\", \"separator\", \"rule\"],\n create: () => mod(\"basic.divider\", \"Divider\", [divider()]),\n },\n];\n","import type { ModuleDefinition } from \"./registry\";\nimport { text, image, mod, divider, PLACEHOLDER } from \"./helpers\";\n\nexport const headerModules: ModuleDefinition[] = [\n {\n type: \"header.logo\",\n category: \"header\",\n name: \"Logo Centered\",\n description: \"Centered brand logo. The simplest header used at the top of almost every newsletter.\",\n tags: [\"logo\", \"brand\", \"centered\"],\n create: () =>\n mod(\"header.logo\", \"Logo Header\", [\n image(PLACEHOLDER(180, 56, \"LOGO\"), \"Logo\", { width: 180, paddingTop: 24, paddingBottom: 24 }),\n ]),\n },\n {\n type: \"header.logo_left_date_right\",\n category: \"header\",\n name: \"Logo Left + Date Right\",\n description: \"Two-column header with logo on the left and a date or issue label on the right. Common for periodical newsletters and digests.\",\n tags: [\"logo\", \"date\", \"issue\", \"publication\", \"newsletter\"],\n create: () =>\n mod(\"header.logo_left_date_right\", \"Logo + Date\", [\n image(PLACEHOLDER(140, 36, \"LOGO\"), \"Logo\", { width: 140, align: \"left\", paddingTop: 16, paddingBottom: 16 }),\n text(\"Issue #128 · April 29, 2026\", {\n color: \"{colors.muted}\",\n fontSize: 13,\n align: \"right\",\n paddingTop: 0,\n paddingBottom: 16,\n }),\n divider({ paddingTop: 0, paddingBottom: 0 }),\n ]),\n },\n {\n type: \"header.publication\",\n category: \"header\",\n name: \"Publication Masthead\",\n description: \"Editorial masthead with publication name in serif type, tagline, and a divider. Mimics print magazine and newspaper newsletters.\",\n tags: [\"masthead\", \"publication\", \"editorial\", \"serif\", \"newspaper\", \"magazine\"],\n create: () =>\n mod(\n \"header.publication\",\n \"Masthead\",\n [\n text(\"THE WEEKLY\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 36,\n fontWeight: \"bold\",\n align: \"center\",\n letterSpacing: 6,\n paddingTop: 32,\n paddingBottom: 4,\n }),\n text(\"Curated reading for thoughtful people\", {\n color: \"{colors.muted}\",\n align: \"center\",\n fontSize: 13,\n paddingBottom: 16,\n }),\n divider({ paddingTop: 0, paddingBottom: 0 }),\n ]\n ),\n },\n {\n type: \"header.hero\",\n category: \"header\",\n name: \"Hero with Headline & Image\",\n description: \"Big headline, subtitle and a wide hero image. Use for the lead story or campaign announcement.\",\n tags: [\"hero\", \"headline\", \"image\", \"lead\", \"feature\"],\n create: () =>\n mod(\"header.hero\", \"Hero\", [\n text(\"Steps Towards a Greener World\", {\n role: \"headline\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 36,\n fontWeight: \"bold\",\n align: \"center\",\n paddingTop: 32,\n lineHeight: 1.2,\n }),\n text(\"Small actions, big impact.\", {\n color: \"{colors.muted}\",\n align: \"center\",\n paddingBottom: 16,\n }),\n image(PLACEHOLDER(560, 280, \"Hero\"), \"Hero\", { width: 560 }),\n ]),\n },\n {\n type: \"header.hero_text_only\",\n category: \"header\",\n name: \"Hero Text Only\",\n description: \"Centered eyebrow + large headline + supporting paragraph, no image. Editorial intro for opinion or essay newsletters.\",\n tags: [\"hero\", \"text\", \"essay\", \"editorial\", \"minimal\"],\n create: () =>\n mod(\"header.hero_text_only\", \"Hero Text\", [\n text(\"ESSAY · ISSUE 42\", {\n fontSize: 12,\n fontWeight: \"bold\",\n color: \"{colors.primary}\",\n letterSpacing: 3,\n align: \"center\",\n paddingTop: 32,\n paddingBottom: 8,\n }),\n text(\"On building things slowly\", {\n role: \"headline\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 40,\n fontWeight: \"bold\",\n align: \"center\",\n lineHeight: 1.15,\n paddingBottom: 8,\n }),\n text(\"Why patience and craft still win in a world of shortcuts.\", {\n color: \"{colors.muted}\",\n align: \"center\",\n fontSize: 16,\n paddingBottom: 32,\n }),\n ]),\n },\n {\n type: \"header.announcement\",\n category: \"header\",\n name: \"Announcement Bar\",\n description: \"Thin colored top bar with a single line of promotional text. Use for free shipping, sales, or alerts.\",\n tags: [\"announcement\", \"bar\", \"promo\", \"alert\"],\n create: () =>\n mod(\n \"header.announcement\",\n \"Announcement\",\n [\n text(\"✨ Free shipping on orders over $50\", {\n color: \"{colors.buttonText}\",\n align: \"center\",\n fontSize: 14,\n paddingTop: 12,\n paddingBottom: 12,\n }),\n ],\n { backgroundColor: \"{colors.primary}\", paddingTop: 0, paddingBottom: 0 }\n ),\n },\n {\n type: \"header.logo_with_view_browser\",\n category: \"header\",\n name: \"Logo + View in Browser\",\n description: \"Logo with a small 'View in browser' link above it. Standard for marketing newsletters that may render poorly.\",\n tags: [\"logo\", \"view-in-browser\", \"marketing\", \"preheader\"],\n create: () =>\n mod(\"header.logo_with_view_browser\", \"Logo + Browser Link\", [\n text(\"View in browser\", {\n color: \"{colors.muted}\",\n fontSize: 11,\n align: \"right\",\n paddingTop: 8,\n paddingBottom: 0,\n link: \"#\",\n }),\n image(PLACEHOLDER(160, 48, \"LOGO\"), \"Logo\", { width: 160, paddingTop: 8, paddingBottom: 16 }),\n ]),\n },\n {\n type: \"header.welcome\",\n category: \"header\",\n name: \"Welcome Header\",\n description: \"Friendly greeting with first name placeholder, used at the top of welcome and onboarding emails.\",\n tags: [\"welcome\", \"onboarding\", \"greeting\", \"personalized\"],\n create: () =>\n mod(\"header.welcome\", \"Welcome\", [\n text(\"👋 Welcome aboard, {{first_name}}\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 28,\n fontWeight: \"bold\",\n align: \"center\",\n paddingTop: 32,\n paddingBottom: 8,\n }),\n text(\"We're glad you're here. Here's what to do next.\", {\n color: \"{colors.muted}\",\n align: \"center\",\n paddingBottom: 16,\n }),\n ]),\n },\n {\n type: \"header.logo_with_tagline\",\n category: \"header\",\n name: \"Logo + Tagline\",\n description: \"Centered logo above a one-line tagline. Friendly brand-forward header.\",\n tags: [\"logo\", \"tagline\", \"brand\"],\n create: () =>\n mod(\"header.logo_with_tagline\", \"Logo + Tagline\", [\n image(PLACEHOLDER(160, 48, \"LOGO\"), \"Logo\", { width: 160, paddingTop: 24, paddingBottom: 4 }),\n text(\"Newsletters that respect your time.\", {\n align: \"center\",\n color: \"{colors.muted}\",\n fontSize: 14,\n paddingBottom: 24,\n }),\n ]),\n },\n {\n type: \"header.story_label\",\n category: \"header\",\n name: \"Story Label Header\",\n description: \"Small category label (e.g. 'Top story', 'Deep dive') above the masthead. Used by The Hustle, Morning Brew style newsletters.\",\n tags: [\"label\", \"category\", \"story\", \"newsletter\", \"topic\"],\n create: () =>\n mod(\"header.story_label\", \"Story Label\", [\n text(\"TODAY'S TOP STORY\", {\n color: \"{colors.primary}\",\n fontSize: 12,\n fontWeight: \"bold\",\n letterSpacing: 3,\n align: \"center\",\n paddingTop: 24,\n paddingBottom: 4,\n }),\n text(\"AI editing tools come for the inbox\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 28,\n fontWeight: \"bold\",\n align: \"center\",\n paddingBottom: 16,\n lineHeight: 1.2,\n }),\n ]),\n },\n];\n","import type { ModuleDefinition } from \"./registry\";\nimport { text, mod, divider } from \"./helpers\";\n\nexport const menuModules: ModuleDefinition[] = [\n {\n type: \"menu.horizontal\",\n category: \"menu\",\n name: \"Horizontal Nav\",\n description: \"Horizontal menu with 3-5 inline links separated by dots. Common publication navigation under the masthead.\",\n tags: [\"menu\", \"nav\", \"horizontal\", \"publication\"],\n create: () =>\n mod(\"menu.horizontal\", \"Horizontal Menu\", [\n text(\"Home · Articles · Podcast · About · Subscribe\", {\n align: \"center\",\n color: \"{colors.text}\",\n fontSize: 13,\n paddingTop: 12,\n paddingBottom: 12,\n }),\n ]),\n },\n {\n type: \"menu.sections\",\n category: \"menu\",\n name: \"Section Tabs\",\n description: \"Linked section labels representing the contents of today's issue (e.g. News · Markets · Tech · Culture). Used by daily digests.\",\n tags: [\"menu\", \"sections\", \"tabs\", \"digest\", \"daily\"],\n create: () =>\n mod(\"menu.sections\", \"Section Tabs\", [\n divider({ paddingTop: 0, paddingBottom: 8 }),\n text(\"NEWS · MARKETS · TECH · CULTURE · WEEKEND\", {\n align: \"center\",\n color: \"{colors.primary}\",\n fontSize: 11,\n fontWeight: \"bold\",\n letterSpacing: 2,\n paddingTop: 0,\n paddingBottom: 8,\n }),\n divider({ paddingTop: 0, paddingBottom: 8 }),\n ]),\n },\n {\n type: \"menu.in_this_issue\",\n category: \"menu\",\n name: \"In This Issue\",\n description: \"Table-of-contents box listing the items in this newsletter issue with anchor links. Helps readers scan long emails.\",\n tags: [\"toc\", \"menu\", \"issue\", \"summary\", \"table of contents\"],\n create: () =>\n mod(\n \"menu.in_this_issue\",\n \"In This Issue\",\n [\n text(\"IN THIS ISSUE\", {\n fontSize: 11,\n fontWeight: \"bold\",\n color: \"{colors.muted}\",\n letterSpacing: 2,\n paddingTop: 16,\n paddingBottom: 8,\n }),\n text(\"→ Lead story: AI in the inbox\", { fontSize: 14, paddingTop: 2, paddingBottom: 2, link: \"#lead\" }),\n text(\"→ 3 things worth your time\", { fontSize: 14, paddingTop: 2, paddingBottom: 2, link: \"#picks\" }),\n text(\"→ Reader question of the week\", { fontSize: 14, paddingTop: 2, paddingBottom: 2, link: \"#qa\" }),\n text(\"→ Upcoming events\", { fontSize: 14, paddingTop: 2, paddingBottom: 16, link: \"#events\" }),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 8, paddingBottom: 8, paddingLeft: 16, paddingRight: 16 }\n ),\n },\n {\n type: \"menu.cta_strip\",\n category: \"menu\",\n name: \"Linked Action Strip\",\n description: \"Three short text actions in a row (e.g. 'Read · Share · Reply'). Light alternative to a button bar.\",\n tags: [\"menu\", \"actions\", \"links\", \"strip\"],\n create: () =>\n mod(\"menu.cta_strip\", \"Action Strip\", [\n text(\"Read online · Share · Reply with feedback\", {\n align: \"center\",\n color: \"{colors.primary}\",\n fontSize: 13,\n paddingTop: 12,\n paddingBottom: 12,\n }),\n ]),\n },\n];\n","import type { ModuleDefinition } from \"./registry\";\nimport { text, image, mod, divider, spacer, button, eyebrow, heading, muted, PLACEHOLDER } from \"./helpers\";\n\nexport const contentModules: ModuleDefinition[] = [\n {\n type: \"content.headline_body\",\n category: \"content\",\n name: \"Headline + Body\",\n description: \"Section title with one paragraph of body text. The most generic written content block.\",\n tags: [\"headline\", \"body\", \"paragraph\", \"article\"],\n create: () =>\n mod(\"content.headline_body\", \"Headline + Body\", [\n heading(\"A compelling headline\", { paddingTop: 24 }),\n text(\n \"Tell your story with a clear, concise paragraph. Keep readers engaged with short sentences and meaningful detail.\",\n { paddingBottom: 24 }\n ),\n ]),\n },\n {\n type: \"content.lead_story\",\n category: \"content\",\n name: \"Lead Story\",\n description: \"Top story of the issue: eyebrow label, big headline, hero image, lead paragraph and a 'Continue reading' link. Used by news and editorial newsletters.\",\n tags: [\"lead\", \"story\", \"feature\", \"news\", \"editorial\", \"long-form\"],\n create: () =>\n mod(\"content.lead_story\", \"Lead Story\", [\n eyebrow(\"Lead story\"),\n heading(\"Inside the new wave of indie publishers\", { level: 1, paddingBottom: 4 }),\n muted(\"By Jane Doe · 6 min read\", { fontSize: 13 }),\n image(PLACEHOLDER(560, 320, \"Lead\"), \"Lead\", { width: 560, paddingTop: 12 }),\n text(\n \"A growing group of writers are leaving big media to build their own readerships, betting that quality and a direct relationship beat scale.\",\n { paddingTop: 16 }\n ),\n text(\"Continue reading →\", {\n color: \"{colors.primary}\",\n fontWeight: \"bold\",\n paddingTop: 4,\n paddingBottom: 24,\n link: \"#\",\n }),\n ]),\n },\n {\n type: \"content.article_summary\",\n category: \"content\",\n name: \"Article Summary Card\",\n description: \"Compact link-out card: image on top, category label, title, one-line summary, and 'Read more'. Use repeatedly to list secondary articles.\",\n tags: [\"article\", \"summary\", \"card\", \"link-out\", \"newsletter\"],\n create: () =>\n mod(\"content.article_summary\", \"Article Card\", [\n image(PLACEHOLDER(560, 280, \"Article\"), \"Article\", { width: 560 }),\n text(\"CULTURE\", {\n color: \"{colors.primary}\",\n fontSize: 11,\n fontWeight: \"bold\",\n letterSpacing: 2,\n paddingTop: 12,\n paddingBottom: 4,\n }),\n heading(\"How long-form writing made a comeback\", { paddingTop: 0, paddingBottom: 4 }),\n text(\"Why subscribers are paying for slower, deeper coverage — and what it means for publishers.\", {\n paddingBottom: 8,\n }),\n text(\"Read more →\", { color: \"{colors.primary}\", fontWeight: \"bold\", paddingBottom: 24, link: \"#\" }),\n ]),\n },\n {\n type: \"content.image_text\",\n category: \"content\",\n name: \"Image + Text Beside\",\n description: \"Image with article title and short summary stacked below. Standard editorial card.\",\n tags: [\"image\", \"text\", \"article\", \"stacked\"],\n create: () =>\n mod(\"content.image_text\", \"Image + Text\", [\n image(PLACEHOLDER(560, 300, \"Article\"), \"Article\", { width: 560 }),\n heading(\"Article title\", { paddingTop: 16, paddingBottom: 4 }),\n text(\"A short summary of the article goes here, two or three lines is plenty.\"),\n ]),\n },\n {\n type: \"content.two_column_articles\",\n category: \"content\",\n name: \"Two Column Stories\",\n description: \"Two short article previews shown side-by-side as stacked blocks (renders as full-width on mobile). Use to tease two related stories.\",\n tags: [\"two-column\", \"articles\", \"side-by-side\", \"preview\"],\n create: () =>\n mod(\"content.two_column_articles\", \"Two Stories\", [\n eyebrow(\"More to read\"),\n image(PLACEHOLDER(272, 180, \"Story A\"), \"Story A\", { width: 272 }),\n text(\"Story A title\", { fontWeight: \"bold\", paddingTop: 4, paddingBottom: 2 }),\n text(\"One sentence about story A.\", { fontSize: 14, paddingBottom: 16 }),\n image(PLACEHOLDER(272, 180, \"Story B\"), \"Story B\", { width: 272 }),\n text(\"Story B title\", { fontWeight: \"bold\", paddingTop: 4, paddingBottom: 2 }),\n text(\"One sentence about story B.\", { fontSize: 14, paddingBottom: 16 }),\n ]),\n },\n {\n type: \"content.three_picks\",\n category: \"content\",\n name: \"Three Picks (Numbered)\",\n description: \"Numbered list of three short recommendations or links. Used by curators ('3 things to read this week').\",\n tags: [\"list\", \"picks\", \"curated\", \"links\", \"recommendations\"],\n create: () =>\n mod(\"content.three_picks\", \"Three Picks\", [\n eyebrow(\"Three picks\"),\n text(\"01 / How to stay focused in 2026\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 18,\n fontWeight: \"bold\",\n paddingTop: 8,\n paddingBottom: 4,\n link: \"#\",\n }),\n muted(\"Notes on attention, deep work, and the slow internet.\", { fontSize: 14 }),\n divider({ paddingTop: 12, paddingBottom: 8 }),\n text(\"02 / The case for boring software\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 18,\n fontWeight: \"bold\",\n paddingTop: 8,\n paddingBottom: 4,\n link: \"#\",\n }),\n muted(\"Why teams are returning to simpler, predictable tools.\", { fontSize: 14 }),\n divider({ paddingTop: 12, paddingBottom: 8 }),\n text(\"03 / A short history of the inbox\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 18,\n fontWeight: \"bold\",\n paddingTop: 8,\n paddingBottom: 4,\n link: \"#\",\n }),\n muted(\"From memos to MIME, and what comes next.\", { fontSize: 14, paddingBottom: 24 }),\n ]),\n },\n {\n type: \"content.quote\",\n category: \"content\",\n name: \"Pull Quote\",\n description: \"Centered serif pull quote with attribution. Adds rhythm to long editorial newsletters.\",\n tags: [\"quote\", \"pull-quote\", \"editorial\", \"attribution\"],\n create: () =>\n mod(\"content.quote\", \"Pull Quote\", [\n text(\"“The best way to predict the future is to create it.”\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 22,\n align: \"center\",\n paddingTop: 24,\n lineHeight: 1.4,\n }),\n text(\"— Peter Drucker\", { color: \"{colors.muted}\", align: \"center\", paddingBottom: 24 }),\n ]),\n },\n {\n type: \"content.author_byline\",\n category: \"content\",\n name: \"Author Byline\",\n description: \"Round avatar + author name + role on one line. Drop above or below an article body for personal newsletters.\",\n tags: [\"author\", \"byline\", \"avatar\", \"personal\"],\n create: () =>\n mod(\"content.author_byline\", \"Byline\", [\n image(PLACEHOLDER(64, 64, \"👤\"), \"Author\", { width: 64, borderRadius: 32, paddingTop: 16, paddingBottom: 0 }),\n text(\"Jane Doe\", { align: \"center\", fontWeight: \"bold\", paddingTop: 8, paddingBottom: 0 }),\n muted(\"Editor, The Weekly\", { align: \"center\", fontSize: 13 }),\n spacer(16),\n ]),\n },\n {\n type: \"content.editor_note\",\n category: \"content\",\n name: \"Editor's Note\",\n description: \"Personal letter-style block: 'Hi {{first_name}}', a few paragraphs and a sign-off. Ideal for newsletters with a strong author voice.\",\n tags: [\"editor\", \"note\", \"letter\", \"personal\", \"voice\"],\n create: () =>\n mod(\"content.editor_note\", \"Editor's Note\", [\n text(\"Hi {{first_name}},\", { paddingTop: 24, paddingBottom: 8 }),\n text(\n \"This week I've been thinking about what makes a newsletter feel like a letter rather than a broadcast. Spoiler: it's not the format, it's the tone.\",\n { paddingBottom: 8, lineHeight: 1.7 }\n ),\n text(\"Let me know what you think — just hit reply.\", { paddingBottom: 8, lineHeight: 1.7 }),\n text(\"— Jane\", { fontFamily: \"{fonts.heading}\", paddingBottom: 24 }),\n ]),\n },\n {\n type: \"content.tip_box\",\n category: \"content\",\n name: \"Tip / Callout Box\",\n description: \"Highlighted background box with an icon, short title and one-paragraph tip. Use for 'pro tips', notes, and warnings.\",\n tags: [\"tip\", \"callout\", \"box\", \"highlight\", \"note\"],\n create: () =>\n mod(\n \"content.tip_box\",\n \"Tip Box\",\n [\n text(\"💡 PRO TIP\", {\n color: \"{colors.primary}\",\n fontSize: 12,\n fontWeight: \"bold\",\n letterSpacing: 2,\n paddingTop: 16,\n paddingBottom: 4,\n }),\n text(\"Always preview your email on mobile before sending — most opens happen there.\", { paddingBottom: 16 }),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0, paddingLeft: 16, paddingRight: 16 }\n ),\n },\n {\n type: \"content.numbered_list\",\n category: \"content\",\n name: \"Numbered List\",\n description: \"Vertical numbered list of 4-5 short items with optional sub-text. Use for tutorials, checklists and 'how-to' newsletters.\",\n tags: [\"list\", \"numbered\", \"tutorial\", \"checklist\", \"how-to\"],\n create: () =>\n mod(\"content.numbered_list\", \"Numbered List\", [\n heading(\"How to do it in 4 steps\", { paddingTop: 16, paddingBottom: 12 }),\n text(\"1. Define the goal\", { fontWeight: \"bold\", paddingTop: 4, paddingBottom: 2 }),\n muted(\"Write down the outcome in one sentence.\"),\n text(\"2. List constraints\", { fontWeight: \"bold\", paddingTop: 8, paddingBottom: 2 }),\n muted(\"Time, budget, scope. Be specific.\"),\n text(\"3. Plan the smallest version\", { fontWeight: \"bold\", paddingTop: 8, paddingBottom: 2 }),\n muted(\"What can you ship this week?\"),\n text(\"4. Ship it\", { fontWeight: \"bold\", paddingTop: 8, paddingBottom: 2 }),\n muted(\"Refine after real feedback.\", { fontSize: 14 }),\n spacer(16),\n ]),\n },\n {\n type: \"content.bullet_list\",\n category: \"content\",\n name: \"Bullet List\",\n description: \"Simple unordered list of takeaways or facts. Concise summary block.\",\n tags: [\"list\", \"bullets\", \"takeaways\", \"summary\"],\n create: () =>\n mod(\"content.bullet_list\", \"Bullets\", [\n heading(\"Key takeaways\", { paddingTop: 16, paddingBottom: 8 }),\n text(\"• Newsletters are growing 20% YoY\", { paddingTop: 2, paddingBottom: 2 }),\n text(\"• Mobile opens crossed 70%\", { paddingTop: 2, paddingBottom: 2 }),\n text(\"• Plain-text emails outperform image-heavy ones in B2B\", { paddingTop: 2, paddingBottom: 2 }),\n text(\"• Personalization drives 2x click-through\", { paddingTop: 2, paddingBottom: 16 }),\n ]),\n },\n {\n type: \"content.qa\",\n category: \"content\",\n name: \"Q&A Block\",\n description: \"Question in bold followed by an answer paragraph. Use for FAQ, reader mailbags, or AMAs.\",\n tags: [\"qa\", \"faq\", \"ama\", \"mailbag\", \"reader-questions\"],\n create: () =>\n mod(\"content.qa\", \"Q&A\", [\n eyebrow(\"Reader question\"),\n text(\"Q: How do I get my first 100 subscribers?\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 18,\n fontWeight: \"bold\",\n paddingTop: 4,\n paddingBottom: 8,\n lineHeight: 1.3,\n }),\n text(\n \"A: Tell ten people who already know you. Then ask each of them to forward to one friend. The first 100 don't come from algorithms — they come from your network.\",\n { paddingBottom: 24, lineHeight: 1.7 }\n ),\n ]),\n },\n {\n type: \"content.stats_row\",\n category: \"content\",\n name: \"Stat Row\",\n description: \"Big numbers with short labels (e.g. '12k readers · 4.8★ rating · 96% open rate'). Used for impact summaries and social proof.\",\n tags: [\"stats\", \"numbers\", \"metrics\", \"social-proof\"],\n create: () =>\n mod(\n \"content.stats_row\",\n \"Stat Row\",\n [\n eyebrow(\"By the numbers\", { align: \"center\" }),\n text(\"12,400\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 36,\n fontWeight: \"bold\",\n align: \"center\",\n color: \"{colors.primary}\",\n paddingTop: 4,\n paddingBottom: 0,\n }),\n muted(\"active readers this month\", { align: \"center\", fontSize: 13 }),\n spacer(8),\n text(\"96% · 4.8★ · 32 issues shipped\", {\n align: \"center\",\n color: \"{colors.text}\",\n fontSize: 14,\n paddingBottom: 24,\n }),\n ]\n ),\n },\n {\n type: \"content.timeline\",\n category: \"content\",\n name: \"Timeline / What Happened\",\n description: \"Chronological list of recent events with dates. Used by news roundups and changelog newsletters.\",\n tags: [\"timeline\", \"changelog\", \"news\", \"events\", \"what-happened\"],\n create: () =>\n mod(\"content.timeline\", \"Timeline\", [\n eyebrow(\"This week\"),\n text(\"Mon · Acme launches plan B\", { fontWeight: \"bold\", paddingTop: 8, paddingBottom: 2 }),\n muted(\"After 6 months of beta testing.\", { fontSize: 14 }),\n text(\"Wed · New funding round announced\", { fontWeight: \"bold\", paddingTop: 8, paddingBottom: 2 }),\n muted(\"$24M Series A led by Foundry.\", { fontSize: 14 }),\n text(\"Fri · Industry report drops\", { fontWeight: \"bold\", paddingTop: 8, paddingBottom: 2 }),\n muted(\"Open rates up across the board.\", { fontSize: 14, paddingBottom: 24 }),\n ]),\n },\n {\n type: \"content.podcast_episode\",\n category: \"content\",\n name: \"Podcast Episode\",\n description: \"Episode artwork, episode number, title, short description and a 'Listen' button. For shows that announce episodes by email.\",\n tags: [\"podcast\", \"episode\", \"audio\", \"listen\", \"show\"],\n create: () =>\n mod(\"content.podcast_episode\", \"Podcast Episode\", [\n image(PLACEHOLDER(220, 220, \"Cover\"), \"Cover\", { width: 220, borderRadius: 12 }),\n text(\"EPISODE 042\", {\n color: \"{colors.primary}\",\n fontSize: 11,\n fontWeight: \"bold\",\n letterSpacing: 2,\n align: \"center\",\n paddingTop: 12,\n paddingBottom: 4,\n }),\n heading(\"Why publishers are betting on email\", { align: \"center\", paddingTop: 0, paddingBottom: 4 }),\n muted(\"With Jane Doe · 38 min\", { align: \"center\", fontSize: 13 }),\n button(\"Listen now\", \"https://example.com\"),\n spacer(16),\n ]),\n },\n {\n type: \"content.video_thumbnail\",\n category: \"content\",\n name: \"Video Thumbnail\",\n description: \"Video thumbnail with overlay-feeling play button (image only, links to a hosted player). Title and duration below.\",\n tags: [\"video\", \"thumbnail\", \"watch\", \"play\", \"media\"],\n create: () =>\n mod(\"content.video_thumbnail\", \"Video\", [\n image(PLACEHOLDER(560, 315, \"▶ Watch\"), \"Video\", { width: 560, link: \"#\", borderRadius: 8 }),\n heading(\"Watch: a guided tour of our 2026 launches\", { paddingTop: 12, paddingBottom: 4 }),\n muted(\"4 min watch\", { fontSize: 13, paddingBottom: 16 }),\n ]),\n },\n {\n type: \"content.event_card\",\n category: \"content\",\n name: \"Event Card\",\n description: \"Date badge with event title, location, time and an RSVP button. For event-driven newsletters and community digests.\",\n tags: [\"event\", \"rsvp\", \"community\", \"date\", \"card\"],\n create: () =>\n mod(\n \"content.event_card\",\n \"Event\",\n [\n text(\"MAY\", {\n align: \"center\",\n color: \"{colors.buttonText}\",\n fontSize: 12,\n fontWeight: \"bold\",\n letterSpacing: 2,\n paddingTop: 12,\n paddingBottom: 0,\n }),\n text(\"12\", {\n align: \"center\",\n color: \"{colors.buttonText}\",\n fontSize: 36,\n fontWeight: \"bold\",\n paddingTop: 0,\n paddingBottom: 12,\n }),\n ],\n { backgroundColor: \"{colors.primary}\", paddingTop: 0, paddingBottom: 0 }\n ),\n },\n {\n type: \"content.code_block\",\n category: \"content\",\n name: \"Code Snippet\",\n description: \"Monospaced code block on a tinted background. For developer newsletters and changelog excerpts.\",\n tags: [\"code\", \"snippet\", \"developer\", \"monospace\", \"changelog\"],\n create: () =>\n mod(\n \"content.code_block\",\n \"Code\",\n [\n text(\"npm install @one-million-lines/email-builder\", {\n fontFamily: \"Menlo, Consolas, monospace\",\n fontSize: 13,\n color: \"{colors.text}\",\n paddingTop: 16,\n paddingBottom: 16,\n paddingLeft: 16,\n paddingRight: 16,\n }),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0, paddingLeft: 16, paddingRight: 16 }\n ),\n },\n];\n","import type { ModuleDefinition } from \"./registry\";\nimport { text, image, mod, heading, muted, eyebrow, spacer, PLACEHOLDER } from \"./helpers\";\n\nexport const featureModules: ModuleDefinition[] = [\n {\n type: \"feature.list\",\n category: \"feature\",\n name: \"Checkmark Feature List\",\n description: \"Centered title with 3-4 short checkmarked benefits. Good for product newsletters and onboarding emails.\",\n tags: [\"features\", \"benefits\", \"checkmarks\", \"list\"],\n create: () =>\n mod(\"feature.list\", \"Feature List\", [\n heading(\"Why people love it\", { align: \"center\", paddingTop: 24 }),\n text(\"✓ Fast and reliable\", { align: \"center\" }),\n text(\"✓ Beautiful out of the box\", { align: \"center\" }),\n text(\"✓ Backed by humans, not bots\", { align: \"center\", paddingBottom: 24 }),\n ]),\n },\n {\n type: \"feature.icon_three\",\n category: \"feature\",\n name: \"Three Icon Features\",\n description: \"Three stacked feature blocks with an emoji/icon, short title and one-line description. Use to highlight 3 product capabilities.\",\n tags: [\"features\", \"icons\", \"three-up\", \"product\"],\n create: () =>\n mod(\"feature.icon_three\", \"Three Features\", [\n text(\"⚡\", { align: \"center\", fontSize: 32, paddingTop: 24, paddingBottom: 4 }),\n text(\"Fast\", { align: \"center\", fontWeight: \"bold\", paddingBottom: 2 }),\n muted(\"Built to render in milliseconds.\", { align: \"center\", fontSize: 14 }),\n spacer(16),\n text(\"🧩\", { align: \"center\", fontSize: 32, paddingBottom: 4 }),\n text(\"Modular\", { align: \"center\", fontWeight: \"bold\", paddingBottom: 2 }),\n muted(\"Compose any layout from blocks.\", { align: \"center\", fontSize: 14 }),\n spacer(16),\n text(\"🤖\", { align: \"center\", fontSize: 32, paddingBottom: 4 }),\n text(\"AI-ready\", { align: \"center\", fontWeight: \"bold\", paddingBottom: 2 }),\n muted(\"Edit emails as JSON, not HTML.\", { align: \"center\", fontSize: 14, paddingBottom: 24 }),\n ]),\n },\n {\n type: \"feature.before_after\",\n category: \"feature\",\n name: \"Before / After\",\n description: \"Two stacked images labeled 'Before' and 'After'. For product transformations, redesigns and case studies.\",\n tags: [\"before-after\", \"comparison\", \"case-study\", \"transformation\"],\n create: () =>\n mod(\"feature.before_after\", \"Before / After\", [\n eyebrow(\"Before\"),\n image(PLACEHOLDER(560, 280, \"Before\"), \"Before\", { width: 560 }),\n spacer(8),\n eyebrow(\"After\"),\n image(PLACEHOLDER(560, 280, \"After\"), \"After\", { width: 560 }),\n spacer(16),\n ]),\n },\n {\n type: \"feature.benefit_pair\",\n category: \"feature\",\n name: \"Image + Benefit Pair\",\n description: \"Repeat-use block: one supporting image plus a title and benefit paragraph beside it. Stack 2-3 of these for a feature tour.\",\n tags: [\"benefit\", \"feature\", \"image-text\", \"pair\"],\n create: () =>\n mod(\"feature.benefit_pair\", \"Benefit Pair\", [\n image(PLACEHOLDER(560, 240, \"Feature\"), \"Feature\", { width: 560, paddingTop: 16 }),\n heading(\"Send 10x faster\", { paddingTop: 12, paddingBottom: 4 }),\n text(\"Reusable modules and theme tokens let teams ship campaigns in minutes, not days.\", { paddingBottom: 24 }),\n ]),\n },\n {\n type: \"feature.testimonial\",\n category: \"feature\",\n name: \"Testimonial\",\n description: \"Customer quote in large type with avatar and attribution. Social proof block.\",\n tags: [\"testimonial\", \"review\", \"social-proof\", \"customer\"],\n create: () =>\n mod(\"feature.testimonial\", \"Testimonial\", [\n text(\"“This cut our email production from a week to an afternoon.”\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 22,\n align: \"center\",\n paddingTop: 24,\n paddingBottom: 12,\n lineHeight: 1.4,\n }),\n image(PLACEHOLDER(56, 56, \"👤\"), \"Customer\", { width: 56, borderRadius: 28 }),\n text(\"Alex Kim · Head of Lifecycle, Acme\", {\n align: \"center\",\n color: \"{colors.muted}\",\n fontSize: 13,\n paddingTop: 4,\n paddingBottom: 24,\n }),\n ]),\n },\n {\n type: \"feature.logo_strip\",\n category: \"feature\",\n name: \"Customer Logo Strip\",\n description: \"Small horizontal row implying customer logos for credibility ('Trusted by'). Logos shown as a placeholder image.\",\n tags: [\"logos\", \"trusted-by\", \"social-proof\", \"strip\"],\n create: () =>\n mod(\"feature.logo_strip\", \"Logo Strip\", [\n muted(\"TRUSTED BY\", { align: \"center\", fontSize: 11 }),\n image(PLACEHOLDER(520, 60, \"LOGOS\"), \"Customer logos\", { width: 520, paddingTop: 8, paddingBottom: 16 }),\n ]),\n },\n];\n","import type { ModuleDefinition } from \"./registry\";\nimport { text, mod, button, spacer, image, heading, muted, eyebrow, PLACEHOLDER } from \"./helpers\";\n\nexport const ctaModules: ModuleDefinition[] = [\n {\n type: \"cta.simple\",\n category: \"call_to_action\",\n name: \"Simple CTA\",\n description: \"Centered headline + body + primary button. The default call-to-action block for any newsletter or promo.\",\n tags: [\"cta\", \"primary\", \"centered\", \"button\"],\n create: () =>\n mod(\"cta.simple\", \"Simple CTA\", [\n heading(\"Ready to get started?\", { align: \"center\", paddingTop: 24 }),\n muted(\"Create better emails faster.\", { align: \"center\" }),\n button(\"Start now\", \"https://example.com\"),\n spacer(16),\n ]),\n },\n {\n type: \"cta.banner\",\n category: \"call_to_action\",\n name: \"Colored Banner CTA\",\n description: \"Full-width colored band with eyebrow, big headline and a contrasting button. Use to draw attention to sales or launches.\",\n tags: [\"cta\", \"banner\", \"colored\", \"promo\", \"sale\"],\n create: () =>\n mod(\n \"cta.banner\",\n \"CTA Banner\",\n [\n text(\"Limited time offer\", {\n color: \"{colors.buttonText}\",\n align: \"center\",\n fontSize: 14,\n paddingTop: 24,\n paddingBottom: 4,\n }),\n text(\"Save 30% this week only\", {\n color: \"{colors.buttonText}\",\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 28,\n fontWeight: \"bold\",\n paddingBottom: 16,\n }),\n button(\"Shop the sale\"),\n spacer(24),\n ],\n { backgroundColor: \"{colors.primary}\", paddingTop: 0, paddingBottom: 0 }\n ),\n },\n {\n type: \"cta.button_only\",\n category: \"call_to_action\",\n name: \"Button Only\",\n description: \"Single primary button on a clean background. Use as a follow-up CTA after a content block.\",\n tags: [\"cta\", \"button\", \"minimal\"],\n create: () => mod(\"cta.button_only\", \"Button\", [button(\"Click here\", \"https://example.com\")]),\n },\n {\n type: \"cta.dual_button\",\n category: \"call_to_action\",\n name: \"Two Button Choice\",\n description: \"Two side-by-side actions: a primary and a ghost-styled secondary. Use when offering 'Learn more' vs 'Get started'.\",\n tags: [\"cta\", \"buttons\", \"two-options\", \"choice\"],\n create: () =>\n mod(\"cta.dual_button\", \"Two Buttons\", [\n heading(\"Pick your path\", { align: \"center\", paddingTop: 24 }),\n muted(\"Choose what fits your team.\", { align: \"center\" }),\n button(\"Get started\", \"https://example.com\"),\n button(\"Learn more\", \"https://example.com\", { backgroundColor: \"transparent\", color: \"{colors.primary}\" }),\n spacer(16),\n ]),\n },\n {\n type: \"cta.image_overlay\",\n category: \"call_to_action\",\n name: \"Image + Overlay CTA\",\n description: \"Lead image with a headline, supporting text, and a button immediately below. Strong visual call to action.\",\n tags: [\"cta\", \"image\", \"visual\", \"hero\"],\n create: () =>\n mod(\"cta.image_overlay\", \"Image CTA\", [\n image(PLACEHOLDER(560, 280, \"Visual\"), \"Visual\", { width: 560, paddingTop: 16 }),\n heading(\"Stop guessing. Start measuring.\", { align: \"center\", paddingTop: 16 }),\n muted(\"Free for 14 days. No credit card.\", { align: \"center\" }),\n button(\"Try it free\"),\n spacer(16),\n ]),\n },\n {\n type: \"cta.subscribe\",\n category: \"call_to_action\",\n name: \"Subscribe / Forward\",\n description: \"Friendly 'Was this forwarded? Subscribe' block that grows the list virally. Common at the end of newsletters.\",\n tags: [\"cta\", \"subscribe\", \"forward\", \"growth\", \"newsletter\"],\n create: () =>\n mod(\n \"cta.subscribe\",\n \"Subscribe\",\n [\n eyebrow(\"Was this forwarded?\", { align: \"center\" }),\n heading(\"Get the next issue in your inbox\", { align: \"center\", paddingTop: 0, paddingBottom: 8 }),\n button(\"Subscribe free\"),\n spacer(16),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n },\n {\n type: \"cta.referral\",\n category: \"call_to_action\",\n name: \"Referral / Share\",\n description: \"Encourages readers to share the newsletter with a unique referral link. Includes a 'Share' button and a personalized URL.\",\n tags: [\"cta\", \"referral\", \"share\", \"viral\", \"growth\"],\n create: () =>\n mod(\"cta.referral\", \"Referral\", [\n eyebrow(\"Tell a friend\", { align: \"center\" }),\n heading(\"Share & earn perks\", { align: \"center\", paddingTop: 0, paddingBottom: 8 }),\n muted(\"Refer 3 friends and unlock the bonus issue.\", { align: \"center\" }),\n text(\"yourname.com/r/abc123\", {\n align: \"center\",\n color: \"{colors.primary}\",\n fontFamily: \"Menlo, Consolas, monospace\",\n fontSize: 14,\n paddingTop: 8,\n paddingBottom: 8,\n }),\n button(\"Share now\"),\n spacer(16),\n ]),\n },\n {\n type: \"cta.upgrade\",\n category: \"call_to_action\",\n name: \"Upgrade / Paid\",\n description: \"Conversion block that promotes a paid plan or premium tier. Includes price, benefits and an upgrade button.\",\n tags: [\"cta\", \"upgrade\", \"paid\", \"premium\", \"conversion\"],\n create: () =>\n mod(\n \"cta.upgrade\",\n \"Upgrade\",\n [\n eyebrow(\"Become a member\", { align: \"center\" }),\n heading(\"$5 / month\", { align: \"center\", level: 1 }),\n muted(\"Unlock the archive, weekly bonus and member chat.\", { align: \"center\", fontSize: 14 }),\n button(\"Upgrade\"),\n spacer(16),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n },\n {\n type: \"cta.feedback\",\n category: \"call_to_action\",\n name: \"Feedback Reply\",\n description: \"Asks the reader to reply with feedback ('Hit reply and let me know'). Personal, no button.\",\n tags: [\"cta\", \"feedback\", \"reply\", \"personal\"],\n create: () =>\n mod(\"cta.feedback\", \"Feedback\", [\n text(\"How did this issue land for you? Just hit reply — I read every message.\", {\n align: \"center\",\n paddingTop: 24,\n paddingBottom: 24,\n lineHeight: 1.6,\n }),\n ]),\n },\n];\n","import type { ModuleDefinition } from \"./registry\";\nimport {\n text,\n image,\n mod,\n button,\n spacer,\n divider,\n heading,\n muted,\n eyebrow,\n PLACEHOLDER,\n product,\n productGrid,\n} from \"./helpers\";\n\nexport const ecommerceModules: ModuleDefinition[] = [\n {\n type: \"ecom.product_single\",\n category: \"ecommerce\",\n name: \"Single Product\",\n description: \"One product with image, title, price, short description and Buy button. Use to feature a hero product. Supports old/final price and per-product link.\",\n tags: [\"product\", \"single\", \"buy\", \"hero\"],\n create: () =>\n mod(\"ecom.product_single\", \"Single Product\", [\n productGrid(\n [\n product({\n name: \"Linen Tote Bag\",\n image: PLACEHOLDER(560, 400, \"Product\"),\n oldPrice: \"$59.00\",\n finalPrice: \"$39.00\",\n description: \"Heavyweight natural linen, made in Portugal.\",\n }),\n ],\n { columns: 1, showOldPrice: true, showDescription: true, buttonLabel: \"Buy now\" }\n ),\n ]),\n },\n {\n type: \"ecom.product_grid_2\",\n category: \"ecommerce\",\n name: \"Product Grid (2 up)\",\n description: \"Two products side-by-side on desktop, stacked on mobile. Each card has image, name, old/final price, optional description and Shop button. Curated picks layout.\",\n tags: [\"product\", \"grid\", \"two-up\", \"curated\", \"responsive\"],\n create: () =>\n mod(\"ecom.product_grid_2\", \"Product Grid 2\", [\n productGrid(\n [\n product({ name: \"Product A\", finalPrice: \"$29\", oldPrice: \"$39\" }),\n product({ name: \"Product B\", finalPrice: \"$34\", oldPrice: \"$45\" }),\n ],\n { columns: 2, showOldPrice: true }\n ),\n ]),\n },\n {\n type: \"ecom.product_grid_3\",\n category: \"ecommerce\",\n name: \"Product Grid (3 up)\",\n description: \"Three product cards in a row on desktop, stacked on mobile. Use for 'New arrivals' or 'Bestsellers' rows.\",\n tags: [\"product\", \"grid\", \"three-up\", \"bestsellers\", \"new-arrivals\", \"responsive\"],\n create: () =>\n mod(\"ecom.product_grid_3\", \"Product Grid 3\", [\n eyebrow(\"New arrivals\", { align: \"center\" }),\n productGrid(\n [\n product({ name: \"Product 1\", finalPrice: \"$19\" }),\n product({ name: \"Product 2\", finalPrice: \"$24\" }),\n product({ name: \"Product 3\", finalPrice: \"$32\" }),\n ],\n { columns: 3, showOldPrice: false }\n ),\n ]),\n },\n {\n type: \"ecom.collection_banner\",\n category: \"ecommerce\",\n name: \"Collection Banner\",\n description: \"Wide collection banner with title and 'Shop the collection' button overlaying or under an image. Use for category drops.\",\n tags: [\"collection\", \"banner\", \"category\", \"drop\"],\n create: () =>\n mod(\"ecom.collection_banner\", \"Collection\", [\n image(PLACEHOLDER(560, 300, \"Collection\"), \"Collection\", { width: 560 }),\n heading(\"Spring Collection 2026\", { align: \"center\", paddingTop: 16 }),\n muted(\"Lighter fabrics, brighter colors.\", { align: \"center\" }),\n button(\"Shop the collection\"),\n spacer(16),\n ]),\n },\n {\n type: \"ecom.discount\",\n category: \"ecommerce\",\n name: \"Discount Code\",\n description: \"Big discount code in monospaced caps with 'Your code' label and a Redeem button.\",\n tags: [\"discount\", \"promo\", \"code\", \"coupon\"],\n create: () =>\n mod(\"ecom.discount\", \"Discount Code\", [\n muted(\"Your code\", { align: \"center\" }),\n text(\"SAVE20\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 36,\n fontWeight: \"bold\",\n align: \"center\",\n color: \"{colors.primary}\",\n letterSpacing: 4,\n paddingTop: 4,\n paddingBottom: 16,\n }),\n button(\"Redeem\"),\n spacer(24),\n ]),\n },\n {\n type: \"ecom.flash_sale\",\n category: \"ecommerce\",\n name: \"Flash Sale Banner\",\n description: \"Urgency-driven banner with countdown-style copy ('Ends in 24h'), discount value and a shop button.\",\n tags: [\"flash-sale\", \"urgency\", \"promo\", \"banner\", \"countdown\"],\n create: () =>\n mod(\n \"ecom.flash_sale\",\n \"Flash Sale\",\n [\n text(\"⏰ FLASH SALE — ENDS IN 24H\", {\n color: \"{colors.buttonText}\",\n align: \"center\",\n fontWeight: \"bold\",\n letterSpacing: 2,\n paddingTop: 16,\n paddingBottom: 4,\n }),\n text(\"Up to 50% off everything\", {\n color: \"{colors.buttonText}\",\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 28,\n fontWeight: \"bold\",\n paddingBottom: 12,\n }),\n button(\"Shop now\", \"#\", { backgroundColor: \"{colors.surface}\", color: \"{colors.primary}\" }),\n spacer(16),\n ],\n { backgroundColor: \"{colors.primary}\", paddingTop: 0, paddingBottom: 0 }\n ),\n },\n {\n type: \"ecom.abandoned_cart\",\n category: \"ecommerce\",\n name: \"Abandoned Cart Reminder\",\n description: \"Friendly reminder showing the items left in the cart with a return-to-cart button. For cart recovery automations.\",\n tags: [\"abandoned-cart\", \"recovery\", \"automation\", \"reminder\"],\n create: () =>\n mod(\"ecom.abandoned_cart\", \"Abandoned Cart\", [\n heading(\"You left something behind\", { align: \"center\", paddingTop: 16 }),\n muted(\"Pick up where you left off.\", { align: \"center\" }),\n spacer(8),\n productGrid(\n [\n product({\n name: \"Linen Tote Bag\",\n image: PLACEHOLDER(400, 400, \"Item\"),\n finalPrice: \"$39\",\n oldPrice: \"$49\",\n }),\n ],\n { columns: 1, showOldPrice: true, buttonLabel: \"Return to cart\" }\n ),\n ]),\n },\n {\n type: \"ecom.review_request\",\n category: \"ecommerce\",\n name: \"Review Request\",\n description: \"Post-purchase block asking for a 1-5 star rating with stacked star buttons. For review-collection emails.\",\n tags: [\"review\", \"rating\", \"post-purchase\", \"feedback\"],\n create: () =>\n mod(\"ecom.review_request\", \"Review\", [\n heading(\"How did we do?\", { align: \"center\", paddingTop: 24 }),\n muted(\"Tap a star to leave a quick review.\", { align: \"center\" }),\n text(\"☆ ☆ ☆ ☆ ☆\", {\n align: \"center\",\n fontSize: 32,\n color: \"{colors.primary}\",\n paddingTop: 12,\n paddingBottom: 24,\n link: \"#\",\n }),\n ]),\n },\n {\n type: \"ecom.gift_guide\",\n category: \"ecommerce\",\n name: \"Gift Guide Pick\",\n description: \"Editorial gift-guide pick: persona eyebrow + a single product card with full details (image, name, old/final price, description, CTA).\",\n tags: [\"gift-guide\", \"curated\", \"editorial\", \"holiday\"],\n create: () =>\n mod(\"ecom.gift_guide\", \"Gift Pick\", [\n eyebrow(\"For the home cook\"),\n productGrid(\n [\n product({\n name: \"Cast Iron Skillet\",\n image: PLACEHOLDER(560, 300, \"Pick\"),\n oldPrice: \"$119\",\n finalPrice: \"$89\",\n description: \"Pre-seasoned, lifetime-guarantee. Made in USA.\",\n }),\n ],\n { columns: 1, showOldPrice: true, showDescription: true, buttonLabel: \"View product\" }\n ),\n ]),\n },\n {\n type: \"ecom.bestseller_list\",\n category: \"ecommerce\",\n name: \"Bestseller Grid\",\n description: \"Top products grid (3 up) with old/final prices. Used by retailers for weekly bestsellers.\",\n tags: [\"bestsellers\", \"grid\", \"ranking\", \"top\"],\n create: () =>\n mod(\"ecom.bestseller_list\", \"Bestsellers\", [\n eyebrow(\"Top 3 this week\"),\n productGrid(\n [\n product({ name: \"Linen Tote\", finalPrice: \"$39\", oldPrice: \"$49\" }),\n product({ name: \"Ceramic Mug\", finalPrice: \"$24\" }),\n product({ name: \"Brass Lamp\", finalPrice: \"$129\", oldPrice: \"$149\" }),\n ],\n { columns: 3, showOldPrice: true }\n ),\n ]),\n },\n];\n","import type { ModuleDefinition } from \"./registry\";\nimport { text, mod, divider, button, spacer, heading, muted, image, eyebrow, PLACEHOLDER } from \"./helpers\";\n\nexport const transactionalModules: ModuleDefinition[] = [\n {\n type: \"tx.order_summary\",\n category: \"transactional\",\n name: \"Order Summary\",\n description: \"Order confirmation summary: order number, line items with thumbnails and totals row. Used in post-purchase emails.\",\n tags: [\"order\", \"summary\", \"receipt\", \"post-purchase\", \"ecommerce\"],\n create: () =>\n mod(\"tx.order_summary\", \"Order Summary\", [\n eyebrow(\"Order #1024\"),\n heading(\"Thanks for your order\", { paddingTop: 0 }),\n muted(\"We'll email you again when it ships.\"),\n divider({ paddingTop: 16, paddingBottom: 8 }),\n text(\"Linen Tote Bag · 1 × $39.00\", { paddingTop: 4, paddingBottom: 4 }),\n text(\"Ceramic Mug · 2 × $24.00\", { paddingTop: 4, paddingBottom: 4 }),\n divider({ paddingTop: 8, paddingBottom: 8 }),\n text(\"Subtotal: $87.00\", { paddingTop: 2, paddingBottom: 2 }),\n text(\"Shipping: $5.00\", { paddingTop: 2, paddingBottom: 2 }),\n text(\"Total: $92.00\", { fontWeight: \"bold\", paddingTop: 2, paddingBottom: 16 }),\n ]),\n },\n {\n type: \"tx.shipping_update\",\n category: \"transactional\",\n name: \"Shipping Update\",\n description: \"Shipping confirmation with tracking number, carrier, expected delivery date and a Track button.\",\n tags: [\"shipping\", \"tracking\", \"delivery\", \"post-purchase\"],\n create: () =>\n mod(\"tx.shipping_update\", \"Shipping Update\", [\n text(\"📦\", { align: \"center\", fontSize: 40, paddingTop: 24 }),\n heading(\"Your order is on the way\", { align: \"center\", paddingTop: 8 }),\n muted(\"Carrier: USPS · Expected: May 4, 2026\", { align: \"center\" }),\n text(\"Tracking: 9400 1108 ...\", { align: \"center\", color: \"{colors.muted}\", fontFamily: \"Menlo, Consolas, monospace\", fontSize: 13 }),\n button(\"Track package\"),\n spacer(16),\n ]),\n },\n {\n type: \"tx.invoice\",\n category: \"transactional\",\n name: \"Invoice\",\n description: \"Itemized invoice with billing period, services and totals. Used by SaaS and B2B billing emails.\",\n tags: [\"invoice\", \"billing\", \"saas\", \"b2b\", \"receipt\"],\n create: () =>\n mod(\"tx.invoice\", \"Invoice\", [\n eyebrow(\"Invoice INV-2026-04\"),\n heading(\"April 2026 invoice\"),\n muted(\"Billed to: Acme Inc · Period: Apr 1 – Apr 30\"),\n divider({ paddingTop: 16, paddingBottom: 8 }),\n text(\"Pro plan · $49.00\", { paddingTop: 4, paddingBottom: 4 }),\n text(\"Add-on seats (3) · $36.00\", { paddingTop: 4, paddingBottom: 4 }),\n divider({ paddingTop: 8, paddingBottom: 8 }),\n text(\"Total due: $85.00\", { fontWeight: \"bold\", paddingBottom: 16 }),\n button(\"Download invoice (PDF)\"),\n spacer(16),\n ]),\n },\n {\n type: \"tx.password_reset\",\n category: \"transactional\",\n name: \"Password Reset\",\n description: \"Authentication email with a reset button and a fallback link. Includes 'expires in X minutes' notice.\",\n tags: [\"auth\", \"password\", \"reset\", \"security\"],\n create: () =>\n mod(\"tx.password_reset\", \"Password Reset\", [\n heading(\"Reset your password\", { align: \"center\", paddingTop: 16 }),\n text(\"Click the button below to set a new password. This link expires in 30 minutes.\", {\n align: \"center\",\n paddingBottom: 16,\n }),\n button(\"Reset password\"),\n muted(\"If the button doesn't work, paste this link in your browser:\", { align: \"center\", fontSize: 12 }),\n text(\"https://example.com/reset/abc123\", {\n align: \"center\",\n color: \"{colors.primary}\",\n fontSize: 12,\n paddingBottom: 24,\n }),\n ]),\n },\n {\n type: \"tx.verify_email\",\n category: \"transactional\",\n name: \"Verify Email\",\n description: \"Single-purpose 'verify your email' transactional with one centered button.\",\n tags: [\"auth\", \"verify\", \"email-confirmation\"],\n create: () =>\n mod(\"tx.verify_email\", \"Verify Email\", [\n heading(\"One last step\", { align: \"center\", paddingTop: 16 }),\n text(\"Confirm your email address to activate your account.\", { align: \"center\", paddingBottom: 8 }),\n button(\"Verify email\"),\n spacer(24),\n ]),\n },\n {\n type: \"tx.appointment\",\n category: \"transactional\",\n name: \"Appointment Confirmation\",\n description: \"Booking/meeting confirmation with date, time, location and add-to-calendar links.\",\n tags: [\"appointment\", \"booking\", \"calendar\", \"meeting\"],\n create: () =>\n mod(\"tx.appointment\", \"Appointment\", [\n eyebrow(\"Confirmed\", { align: \"center\" }),\n heading(\"Your appointment is set\", { align: \"center\", paddingTop: 0 }),\n text(\"Tuesday, May 12 · 10:00 AM\", { align: \"center\", fontWeight: \"bold\", paddingTop: 8 }),\n muted(\"123 Main St, Suite 4 · Brooklyn, NY\", { align: \"center\" }),\n button(\"Add to calendar\"),\n spacer(16),\n ]),\n },\n];\n","import type { ModuleDefinition } from \"./registry\";\nimport { text, mod, image, eyebrow, PLACEHOLDER, muted, spacer } from \"./helpers\";\n\nexport const socialModules: ModuleDefinition[] = [\n {\n type: \"social.icons\",\n category: \"social\",\n name: \"Social Icons Row\",\n description: \"Centered 'Follow us' label with text-link icons in a row. Light footer-style social block.\",\n tags: [\"social\", \"follow\", \"icons\", \"row\"],\n create: () =>\n mod(\"social.icons\", \"Social Icons\", [\n muted(\"Follow us\", { align: \"center\" }),\n text(\"Twitter · Instagram · LinkedIn · YouTube\", {\n align: \"center\",\n color: \"{colors.primary}\",\n paddingBottom: 16,\n }),\n ]),\n },\n {\n type: \"social.share\",\n category: \"social\",\n name: \"Share This Email\",\n description: \"'Share this email' bar with Forward · Tweet · Share text links. Used at the end of newsletters.\",\n tags: [\"social\", \"share\", \"forward\", \"viral\"],\n create: () =>\n mod(\"social.share\", \"Share Bar\", [\n text(\"Share this email\", { align: \"center\", paddingTop: 8 }),\n text(\"Forward · Tweet · Share\", {\n align: \"center\",\n color: \"{colors.primary}\",\n paddingBottom: 8,\n }),\n ]),\n },\n {\n type: \"social.featured_post\",\n category: \"social\",\n name: \"Featured Social Post\",\n description: \"Embed-style preview of a single social post: avatar, name, post text and a link to view it on the platform.\",\n tags: [\"social\", \"post\", \"embed\", \"twitter\", \"instagram\"],\n create: () =>\n mod(\n \"social.featured_post\",\n \"Social Post\",\n [\n eyebrow(\"From the community\"),\n image(PLACEHOLDER(48, 48, \"👤\"), \"Avatar\", { width: 48, borderRadius: 24 }),\n text(\"@maker · 2h\", { color: \"{colors.muted}\", fontSize: 13, paddingTop: 4, paddingBottom: 4 }),\n text(\"\\\"Just shipped my newsletter using OpenPostcards. Honestly the smoothest email build I've ever done.\\\"\", {\n paddingBottom: 8,\n lineHeight: 1.6,\n }),\n text(\"View on Twitter →\", { color: \"{colors.primary}\", paddingBottom: 16, link: \"#\" }),\n ]\n ),\n },\n {\n type: \"social.instagram_grid\",\n category: \"social\",\n name: \"Instagram Grid\",\n description: \"3 small square thumbnails in a row representing recent Instagram posts, with handle and link.\",\n tags: [\"social\", \"instagram\", \"grid\", \"thumbnails\"],\n create: () =>\n mod(\"social.instagram_grid\", \"IG Grid\", [\n muted(\"@youraccount on Instagram\", { align: \"center\" }),\n image(PLACEHOLDER(180, 180, \"1\"), \"Post 1\", { width: 180 }),\n image(PLACEHOLDER(180, 180, \"2\"), \"Post 2\", { width: 180 }),\n image(PLACEHOLDER(180, 180, \"3\"), \"Post 3\", { width: 180 }),\n text(\"View profile →\", { align: \"center\", color: \"{colors.primary}\", paddingTop: 8, paddingBottom: 16, link: \"#\" }),\n ]),\n },\n {\n type: \"social.community_stats\",\n category: \"social\",\n name: \"Community Stats\",\n description: \"Short '12k Twitter · 4k IG · 2k YT' style row used to show following sizes.\",\n tags: [\"social\", \"stats\", \"community\", \"following\"],\n create: () =>\n mod(\"social.community_stats\", \"Community Stats\", [\n eyebrow(\"Join the community\", { align: \"center\" }),\n text(\"12k Twitter · 4k Instagram · 2k YouTube\", { align: \"center\", paddingBottom: 16 }),\n spacer(8),\n ]),\n },\n];\n","import type { ModuleDefinition } from \"./registry\";\nimport { text, mod, divider, image, muted, PLACEHOLDER } from \"./helpers\";\n\nconst baseFooterStyle = {\n backgroundColor: \"{colors.background}\",\n paddingTop: 0,\n paddingBottom: 0,\n};\n\nexport const footerModules: ModuleDefinition[] = [\n {\n type: \"footer.simple\",\n category: \"footer\",\n name: \"Simple Footer\",\n description: \"Minimal footer with copyright, address and unsubscribe links. The default for any newsletter.\",\n tags: [\"footer\", \"simple\", \"copyright\", \"unsubscribe\"],\n create: () =>\n mod(\n \"footer.simple\",\n \"Simple Footer\",\n [\n muted(\"© 2026 Your Company. All rights reserved.\", { align: \"center\", fontSize: 12 }),\n muted(\"123 Main St · City · Country\", { align: \"center\", fontSize: 12 }),\n text(\"Unsubscribe · View in browser\", {\n align: \"center\",\n color: \"{colors.muted}\",\n fontSize: 12,\n paddingTop: 4,\n paddingBottom: 24,\n }),\n ],\n { ...baseFooterStyle, paddingTop: 24 }\n ),\n },\n {\n type: \"footer.social\",\n category: \"footer\",\n name: \"Footer with Social\",\n description: \"Footer with social links row above the legal text.\",\n tags: [\"footer\", \"social\", \"links\"],\n create: () =>\n mod(\n \"footer.social\",\n \"Social Footer\",\n [\n text(\"Follow us\", { align: \"center\", paddingTop: 24 }),\n text(\"Twitter · Instagram · LinkedIn\", {\n align: \"center\",\n color: \"{colors.primary}\",\n paddingBottom: 12,\n }),\n divider(),\n muted(\"© 2026 Your Company · Unsubscribe\", {\n align: \"center\",\n fontSize: 12,\n }),\n text(\" \", { align: \"center\", paddingBottom: 24 }),\n ],\n baseFooterStyle\n ),\n },\n {\n type: \"footer.legal\",\n category: \"footer\",\n name: \"Legal Footer\",\n description: \"Long-form footer with explanation of why the user is receiving the email plus privacy/terms/unsubscribe links. Used by enterprise and finance newsletters.\",\n tags: [\"footer\", \"legal\", \"compliance\", \"enterprise\"],\n create: () =>\n mod(\n \"footer.legal\",\n \"Legal Footer\",\n [\n text(\n \"You are receiving this email because you signed up for our newsletter. If you no longer wish to receive emails, you can unsubscribe at any time.\",\n {\n align: \"center\",\n color: \"{colors.muted}\",\n fontSize: 11,\n lineHeight: 1.6,\n paddingTop: 24,\n }\n ),\n text(\"Privacy Policy · Terms · Unsubscribe\", {\n align: \"center\",\n color: \"{colors.muted}\",\n fontSize: 11,\n paddingBottom: 24,\n }),\n ],\n baseFooterStyle\n ),\n },\n {\n type: \"footer.publisher\",\n category: \"footer\",\n name: \"Publisher Footer\",\n description: \"Magazine-style sign-off with logo, publication name, masthead credits, address and links.\",\n tags: [\"footer\", \"publisher\", \"magazine\", \"masthead\", \"editorial\"],\n create: () =>\n mod(\n \"footer.publisher\",\n \"Publisher Footer\",\n [\n image(PLACEHOLDER(120, 36, \"LOGO\"), \"Logo\", { width: 120, paddingTop: 24, paddingBottom: 8 }),\n text(\"THE WEEKLY\", {\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontWeight: \"bold\",\n letterSpacing: 4,\n paddingTop: 0,\n paddingBottom: 4,\n }),\n muted(\"Editor: Jane Doe · Producer: Alex Kim\", { align: \"center\", fontSize: 12 }),\n divider({ paddingTop: 12, paddingBottom: 12 }),\n muted(\"© 2026 The Weekly · 350 Madison Ave · NY 10017\", { align: \"center\", fontSize: 11 }),\n text(\"Manage preferences · Unsubscribe\", {\n align: \"center\",\n color: \"{colors.muted}\",\n fontSize: 11,\n paddingTop: 4,\n paddingBottom: 24,\n }),\n ],\n baseFooterStyle\n ),\n },\n {\n type: \"footer.app_links\",\n category: \"footer\",\n name: \"Footer with App Store Badges\",\n description: \"Footer including 'Get the app' app-store and play-store badge images. For consumer brand newsletters.\",\n tags: [\"footer\", \"app\", \"download\", \"ios\", \"android\"],\n create: () =>\n mod(\n \"footer.app_links\",\n \"App Footer\",\n [\n text(\"Get the app\", { align: \"center\", fontWeight: \"bold\", paddingTop: 24, paddingBottom: 8 }),\n image(PLACEHOLDER(135, 40, \"App Store\"), \"App Store\", { width: 135, align: \"center\", paddingTop: 0, paddingBottom: 4 }),\n image(PLACEHOLDER(135, 40, \"Google Play\"), \"Google Play\", { width: 135, align: \"center\", paddingTop: 0, paddingBottom: 16 }),\n divider(),\n muted(\"© 2026 Your Brand · Unsubscribe\", { align: \"center\", fontSize: 11 }),\n text(\" \", { align: \"center\", paddingBottom: 24 }),\n ],\n baseFooterStyle\n ),\n },\n {\n type: \"footer.address_only\",\n category: \"footer\",\n name: \"Address Only\",\n description: \"Just a centered postal address line — required for CAN-SPAM compliance when other footers are minimal.\",\n tags: [\"footer\", \"address\", \"compliance\", \"can-spam\"],\n create: () =>\n mod(\n \"footer.address_only\",\n \"Address\",\n [\n muted(\"Your Company · 123 Main St · Brooklyn, NY 11201 · USA\", {\n align: \"center\",\n fontSize: 11,\n }),\n text(\" \", { align: \"center\", paddingBottom: 16 }),\n ],\n { ...baseFooterStyle, paddingTop: 16 }\n ),\n },\n {\n type: \"footer.preferences\",\n category: \"footer\",\n name: \"Manage Preferences\",\n description: \"Footer that emphasizes preference management ('Update your preferences', 'Send less often'). Reduces unsubscribes.\",\n tags: [\"footer\", \"preferences\", \"frequency\", \"retention\"],\n create: () =>\n mod(\n \"footer.preferences\",\n \"Preferences\",\n [\n text(\"Getting too many emails?\", { align: \"center\", paddingTop: 24, paddingBottom: 4 }),\n text(\"Update your preferences · Send less often · Unsubscribe\", {\n align: \"center\",\n color: \"{colors.primary}\",\n fontSize: 13,\n paddingBottom: 16,\n }),\n divider(),\n muted(\"© 2026 Your Company\", { align: \"center\", fontSize: 11 }),\n text(\" \", { align: \"center\", paddingBottom: 24 }),\n ],\n baseFooterStyle\n ),\n },\n {\n type: \"footer.signature\",\n category: \"footer\",\n name: \"Signature Sign-off\",\n description: \"Personal hand-signed style sign-off with author name and tiny legal block. For solo creator newsletters.\",\n tags: [\"footer\", \"signature\", \"personal\", \"creator\", \"sign-off\"],\n create: () =>\n mod(\n \"footer.signature\",\n \"Signature\",\n [\n text(\"Until next week,\", { paddingTop: 24, paddingBottom: 4 }),\n text(\"— Jane\", { fontFamily: \"{fonts.heading}\", fontSize: 22, paddingBottom: 16 }),\n divider(),\n muted(\"Reply directly · Unsubscribe · 123 Main St, Brooklyn\", {\n fontSize: 11,\n align: \"center\",\n }),\n text(\" \", { align: \"center\", paddingBottom: 24 }),\n ],\n { ...baseFooterStyle, paddingTop: 0 }\n ),\n },\n];\n","// Aggregates and registers every default module pack.\nimport { moduleRegistry, type ModuleDefinition } from \"./registry\";\nimport { basicModules } from \"./basic\";\nimport { headerModules } from \"./header\";\nimport { menuModules } from \"./menu\";\nimport { contentModules } from \"./content\";\nimport { featureModules } from \"./feature\";\nimport { ctaModules } from \"./cta\";\nimport { ecommerceModules } from \"./ecommerce\";\nimport { transactionalModules } from \"./transactional\";\nimport { socialModules } from \"./social\";\nimport { footerModules } from \"./footer\";\n\nexport const defaultModules: ModuleDefinition[] = [\n ...basicModules,\n ...headerModules,\n ...menuModules,\n ...contentModules,\n ...featureModules,\n ...ctaModules,\n ...ecommerceModules,\n ...transactionalModules,\n ...socialModules,\n ...footerModules,\n];\n\nlet registered = false;\nexport function registerDefaultModules() {\n if (registered) return;\n for (const d of defaultModules) moduleRegistry.register(d);\n registered = true;\n}\n\nexport {\n basicModules,\n headerModules,\n menuModules,\n contentModules,\n featureModules,\n ctaModules,\n ecommerceModules,\n transactionalModules,\n socialModules,\n footerModules,\n};\n","import { useEffect } from \"react\";\nimport { TopBar } from \"./editor/TopBar\";\nimport { LeftSidebar } from \"./editor/LeftSidebar\";\nimport { Canvas } from \"./editor/Canvas\";\nimport { RightSidebar } from \"./editor/RightSidebar\";\nimport { registerDefaultModules } from \"./modules/defaultModules\";\nimport { moduleRegistry } from \"./modules/registry\";\nimport { useEmailStore } from \"./store/emailStore\";\n// Register all built-in templates (each module self-registers on import).\nimport \"./templates\";\n\n// Register default modules once at module load.\nregisterDefaultModules();\n\nexport function App() {\n const { doc, addModule, loadFromLocalStorage } = useEmailStore();\n\n useEffect(() => {\n loadFromLocalStorage();\n // Seed a starter email if empty.\n if (useEmailStore.getState().doc.modules.length === 0) {\n const seeds = [\"header.hero\", \"content.headline_body\", \"cta.simple\", \"footer.simple\"];\n for (const t of seeds) {\n const def = moduleRegistry.get(t);\n if (def) addModule(def.create());\n }\n useEmailStore.setState({ selection: { kind: \"email\" }, past: [], future: [] });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Auto-save to localStorage on doc change.\n useEffect(() => {\n const id = setTimeout(() => useEmailStore.getState().saveToLocalStorage(), 500);\n return () => clearTimeout(id);\n }, [doc]);\n\n return (\n <div className=\"oml-email-builder h-full w-full flex flex-col bg-gray-100\">\n <TopBar />\n <div className=\"flex flex-1 overflow-hidden\">\n <LeftSidebar />\n <Canvas />\n <RightSidebar />\n </div>\n </div>\n );\n}\n","// A small example gallery.\n//\n// This demonstrates the shape of a gallery pack: a handful of ready-made\n// modules across several categories. Registering it drops these blocks at the\n// TOP of their respective category panels, badged \"New\".\n//\n// Real embedders typically build galleries dynamically (see ../gallery/README.md)\n// or fetch them from a backend and call `galleryRegistry.registerGallery(...)`.\n\nimport type { GalleryDefinition } from \"./registry\";\nimport {\n text,\n image,\n button,\n mod,\n divider,\n eyebrow,\n heading,\n muted,\n product,\n productGrid,\n PLACEHOLDER,\n} from \"../modules/helpers\";\n\nexport const sampleGallery: GalleryDefinition = {\n id: \"starter-gallery\",\n name: \"Starter Gallery\",\n description:\n \"A curated set of extra header, content, ecommerce and menu styles to showcase how galleries extend the builder.\",\n badge: \"New\",\n items: [\n {\n type: \"gallery.header.gradient_hero\",\n category: \"header\",\n name: \"Gradient Hero\",\n description:\n \"Bold centered hero with an eyebrow, oversized headline and a primary button on a tinted background. Great for launch announcements.\",\n tags: [\"hero\", \"gradient\", \"launch\", \"cta\", \"bold\"],\n create: () =>\n mod(\n \"gallery.header.gradient_hero\",\n \"Gradient Hero\",\n [\n eyebrow(\"Introducing\", { align: \"center\" }),\n heading(\"Something new is here\", {\n level: 1,\n align: \"center\",\n paddingTop: 4,\n paddingBottom: 8,\n }),\n text(\"A fresh way to reach your audience — crafted for the inbox.\", {\n align: \"center\",\n color: \"{colors.muted}\",\n fontSize: 16,\n paddingBottom: 20,\n }),\n button(\"Explore now\", \"#\", { align: \"center\" }),\n ],\n { backgroundColor: \"{colors.surface}\", paddingTop: 40, paddingBottom: 40 }\n ),\n },\n {\n type: \"gallery.content.quote\",\n category: \"content\",\n name: \"Pull Quote\",\n description:\n \"Large centered quotation with an attribution line. Use to highlight a testimonial or a memorable line.\",\n tags: [\"quote\", \"testimonial\", \"highlight\", \"pull-quote\"],\n create: () =>\n mod(\"gallery.content.quote\", \"Pull Quote\", [\n text(\"“This is the fastest we've ever shipped a campaign.”\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 24,\n align: \"center\",\n lineHeight: 1.4,\n paddingTop: 28,\n paddingBottom: 8,\n }),\n muted(\"— A very happy customer\", { align: \"center\", paddingBottom: 28 }),\n ]),\n },\n {\n type: \"gallery.content.stat_row\",\n category: \"content\",\n name: \"Stat Row\",\n description:\n \"Three short number + label pairs in a row. Use to show traction, metrics or highlights.\",\n tags: [\"stats\", \"metrics\", \"numbers\", \"row\", \"kpi\"],\n create: () =>\n mod(\"gallery.content.stat_row\", \"Stat Row\", [\n heading(\"By the numbers\", { align: \"center\", paddingTop: 24 }),\n text(\n \"<b>10k+</b> subscribers · <b>98%</b> delivery · <b>4.9★</b> rating\",\n { align: \"center\", color: \"{colors.muted}\", paddingBottom: 24 }\n ),\n ]),\n },\n {\n type: \"gallery.ecommerce.single_product\",\n category: \"ecommerce\",\n name: \"Single Product Spotlight\",\n description:\n \"One product with image, name, price and buy button. Use to feature a hero product.\",\n tags: [\"product\", \"spotlight\", \"single\", \"buy\", \"shop\"],\n create: () =>\n mod(\"gallery.ecommerce.single_product\", \"Product Spotlight\", [\n productGrid(\n [\n product({\n name: \"The Signature Bag\",\n finalPrice: \"$129\",\n oldPrice: \"$159\",\n description: \"Handmade, built to last.\",\n image: PLACEHOLDER(520, 520, \"Product\"),\n }),\n ],\n { columns: 1, showDescription: true, buttonLabel: \"Buy now\" }\n ),\n ]),\n },\n {\n type: \"gallery.menu.pill_nav\",\n category: \"menu\",\n name: \"Pill Navigation\",\n description:\n \"Centered row of navigation links with a divider below. Compact top-of-email menu.\",\n tags: [\"menu\", \"nav\", \"links\", \"pill\"],\n create: () =>\n mod(\"gallery.menu.pill_nav\", \"Pill Navigation\", [\n image(PLACEHOLDER(120, 32, \"LOGO\"), \"Logo\", { width: 120, paddingBottom: 8 }),\n text(\n '<a href=\"#\">Shop</a> <a href=\"#\">New</a> <a href=\"#\">Sale</a> <a href=\"#\">About</a>',\n { align: \"center\", color: \"{colors.primary}\", paddingBottom: 8 }\n ),\n divider({ paddingTop: 4, paddingBottom: 0 }),\n ]),\n },\n ],\n};\n","// Public surface for the gallery module.\nimport type { Plugin, BuilderHandle } from \"../core/plugins\";\nimport { galleryRegistry, type GalleryDefinition } from \"./registry\";\n\nexport { galleryRegistry } from \"./registry\";\nexport type { GalleryDefinition, GalleryItem } from \"./registry\";\nexport { sampleGallery } from \"./sampleGallery\";\n\n/**\n * Plugin factory that registers one or more galleries with the builder.\n *\n * @example\n * import { registerPlugin } from \"@one-million-lines/email-builder\";\n * import { galleryPlugin, sampleGallery } from \"@one-million-lines/email-builder\";\n * registerPlugin(galleryPlugin(sampleGallery));\n */\nexport function galleryPlugin(...galleries: GalleryDefinition[]): Plugin {\n return {\n name: \"gallery\",\n // Galleries are just extra modules; reuse the \"modules\" plugin type.\n type: \"modules\",\n setup(_builder: BuilderHandle) {\n for (const g of galleries) galleryRegistry.registerGallery(g);\n },\n };\n}\n","// HTTP AI provider.\n//\n// Wraps a backend endpoint (see ../../backend) as an `AIProvider`. The provider\n// POSTs an `AIRequest` as JSON and expects an `AIResponse` JSON body back.\n// The backend is responsible for talking to the actual model; the client stays\n// model-agnostic and only speaks the builder's structured AI protocol.\n\nimport type { AIProvider, AIRequest, AIResponse } from \"../core/aiActions\";\n\nexport interface HttpAIProviderOptions {\n /** Absolute or same-origin URL that implements POST /ai/generate. Required. */\n endpoint: string;\n /** Extra headers (e.g. Authorization). */\n headers?: Record<string, string>;\n /** Send cookies with the request. Default: false. */\n withCredentials?: boolean;\n /** Abort the request after this many ms. Default: 60000. */\n timeoutMs?: number;\n /**\n * Map a raw server JSON body to an `AIResponse`.\n * Default expects the body to already be an `AIResponse`.\n */\n transformResponse?: (body: unknown) => AIResponse;\n}\n\nconst defaultTransform = (body: unknown): AIResponse => {\n if (body && typeof body === \"object\") return body as AIResponse;\n throw new Error(\"AI server returned a non-object response.\");\n};\n\n/**\n * Create an {@link AIProvider} backed by an HTTP endpoint.\n *\n * @example\n * const provider = createHttpAIProvider({ endpoint: \"http://localhost:3001/ai/generate\" });\n */\nexport function createHttpAIProvider(opts: HttpAIProviderOptions): AIProvider {\n const transform = opts.transformResponse ?? defaultTransform;\n const timeoutMs = opts.timeoutMs ?? 60000;\n\n return {\n async generate(req: AIRequest): Promise<AIResponse> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const res = await fetch(opts.endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...(opts.headers ?? {}) },\n credentials: opts.withCredentials ? \"include\" : \"same-origin\",\n body: JSON.stringify(req),\n signal: controller.signal,\n });\n\n let body: unknown = null;\n const raw = await res.text();\n try {\n body = raw ? JSON.parse(raw) : null;\n } catch {\n // leave body null; handled below\n }\n\n if (!res.ok) {\n const msg =\n (body && typeof body === \"object\" && \"error\" in body &&\n typeof (body as { error: unknown }).error === \"string\"\n ? (body as { error: string }).error\n : null) ?? `AI request failed (HTTP ${res.status})`;\n throw new Error(msg);\n }\n\n return transform(body);\n } catch (err) {\n if (err instanceof DOMException && err.name === \"AbortError\") {\n throw new Error(`AI request timed out after ${timeoutMs}ms`);\n }\n throw err instanceof Error ? err : new Error(String(err));\n } finally {\n clearTimeout(timer);\n }\n },\n };\n}\n","// Public surface for the AI assistant module.\nimport type { Plugin, BuilderHandle } from \"../core/plugins\";\nimport type { AIProvider } from \"../core/aiActions\";\nimport { createHttpAIProvider, type HttpAIProviderOptions } from \"./provider\";\n\nexport { createHttpAIProvider } from \"./provider\";\nexport type { HttpAIProviderOptions } from \"./provider\";\nexport { buildCatalog } from \"./catalog\";\nexport type { CatalogEntry } from \"./catalog\";\nexport { applyAIResponse } from \"./applyResponse\";\nexport type { ApplyResult } from \"./applyResponse\";\nexport { AIChatPanel, useAIAvailable } from \"./AIChatPanel\";\nexport {\n getAIProvider as getActiveAIProvider,\n setAIProvider as setActiveAIProvider,\n} from \"./state\";\n\nexport interface AIAssistantOptions extends HttpAIProviderOptions {}\n\n/**\n * Plugin factory that wires an HTTP-backed AI provider into the builder and\n * enables the chat panel.\n *\n * @example\n * import { registerPlugin } from \"@one-million-lines/email-builder\";\n * import { aiAssistantPlugin } from \"@one-million-lines/email-builder\";\n * registerPlugin(aiAssistantPlugin({ endpoint: \"http://localhost:3001/ai/generate\" }));\n */\nexport function aiAssistantPlugin(opts: AIAssistantOptions): Plugin {\n const provider: AIProvider = createHttpAIProvider(opts);\n return {\n name: \"ai-assistant\",\n type: \"ai-provider\",\n setup(builder: BuilderHandle) {\n builder.setAIProvider(provider);\n },\n };\n}\n","// Image Uploader plugin.\n// Registers an AssetProvider that POSTs the picked file to a configured\n// HTTP endpoint and returns the public URL the server responds with.\n//\n// See ./README.md for the wire protocol and server examples.\n\nimport type { Plugin, AssetProvider, BuilderHandle } from \"../../core/plugins\";\n\nexport interface ImageUploaderOptions {\n /** Absolute or same-origin URL the file is POSTed to. Required. */\n endpoint: string;\n /** Form field name for the file. Default: \"file\". */\n fieldName?: string;\n /** Extra headers (e.g. Authorization). Cookies/credentials are sent if `withCredentials` is true. */\n headers?: Record<string, string>;\n /** Send credentials (cookies). Default: false. */\n withCredentials?: boolean;\n /** Max file size in MB. Default: 10. */\n maxSizeMB?: number;\n /** Comma-separated MIME types accepted by the file picker. Default: \"image/*\". */\n accept?: string;\n /**\n * Map a successful server JSON body to `{ url, alt? }`.\n * Default expects `{ url: string, alt?: string }`.\n */\n transformResponse?: (body: unknown) => { url: string; alt?: string };\n /** Optional progress callback for the active upload. */\n onProgress?: (percent: number) => void;\n}\n\nconst defaultTransform = (body: unknown): { url: string; alt?: string } => {\n if (body && typeof body === \"object\" && \"url\" in body && typeof (body as { url: unknown }).url === \"string\") {\n const b = body as { url: string; alt?: string };\n return { url: b.url, alt: typeof b.alt === \"string\" ? b.alt : undefined };\n }\n throw new Error('Server response missing \"url\" string field.');\n};\n\nexport function createImageUploaderProvider(opts: ImageUploaderOptions): AssetProvider {\n const fieldName = opts.fieldName ?? \"file\";\n const maxSize = (opts.maxSizeMB ?? 10) * 1024 * 1024;\n const transform = opts.transformResponse ?? defaultTransform;\n\n return {\n upload(file: File) {\n if (!file.type.startsWith(\"image/\")) {\n return Promise.reject(new Error(`Not an image: ${file.type || \"unknown\"}`));\n }\n if (file.size > maxSize) {\n return Promise.reject(\n new Error(`File too large: ${(file.size / 1024 / 1024).toFixed(2)} MB > ${opts.maxSizeMB ?? 10} MB`)\n );\n }\n\n return new Promise<{ url: string; alt?: string }>((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n const fd = new FormData();\n fd.append(fieldName, file, file.name);\n\n xhr.open(\"POST\", opts.endpoint, true);\n xhr.withCredentials = !!opts.withCredentials;\n if (opts.headers) {\n for (const [k, v] of Object.entries(opts.headers)) xhr.setRequestHeader(k, v);\n }\n\n if (opts.onProgress && xhr.upload) {\n xhr.upload.onprogress = (e) => {\n if (e.lengthComputable) opts.onProgress!(Math.round((e.loaded / e.total) * 100));\n };\n }\n\n xhr.onload = () => {\n const ok = xhr.status >= 200 && xhr.status < 300;\n let body: unknown = null;\n try {\n body = xhr.responseText ? JSON.parse(xhr.responseText) : null;\n } catch {\n // not JSON\n }\n if (!ok) {\n const msg =\n (body && typeof body === \"object\" && \"error\" in body && typeof (body as { error: unknown }).error === \"string\"\n ? (body as { error: string }).error\n : null) ?? `Upload failed (HTTP ${xhr.status})`;\n return reject(new Error(msg));\n }\n try {\n resolve(transform(body));\n } catch (err) {\n reject(err instanceof Error ? err : new Error(String(err)));\n }\n };\n\n xhr.onerror = () => reject(new Error(\"Network error during upload\"));\n xhr.onabort = () => reject(new Error(\"Upload aborted\"));\n xhr.send(fd);\n });\n },\n };\n}\n\n/**\n * Plugin factory. Pass to `registerPlugin()` exported by the builder.\n *\n * @example\n * import { registerPlugin } from \"@one-million-lines/email-builder\";\n * import { imageUploaderPlugin } from \"@one-million-lines/email-builder\";\n * registerPlugin(imageUploaderPlugin({ endpoint: \"/api/upload\" }));\n */\nexport function imageUploaderPlugin(opts: ImageUploaderOptions): Plugin {\n return {\n name: \"image-uploader\",\n type: \"asset-provider\",\n setup(b: BuilderHandle) {\n b.registerAssetProvider(createImageUploaderProvider(opts));\n },\n };\n}\n\nexport const ACCEPT_DEFAULT = \"image/*\";\n","// Public API for embedding the editor in React apps and as a vanilla wrapper.\n// Note: Vue wrapper is left as a stub (drop-in via createEmailBuilder + a Vue component).\nimport { createRoot, type Root } from \"react-dom/client\";\nimport { createElement, useEffect } from \"react\";\nimport \"./lib.css\";\nimport type { EmailDocument, Theme } from \"./core/types\";\nimport { documentSchema } from \"./core/validation\";\nimport { renderEmailHtml } from \"./core/renderer\";\nimport { useEmailStore } from \"./store/emailStore\";\nimport { App } from \"./App\";\nimport { registerDefaultModules } from \"./modules/defaultModules\";\nimport { moduleRegistry, type ModuleDefinition } from \"./modules/registry\";\nimport type { AIProvider } from \"./core/aiActions\";\nimport { builder, registerPlugin, type Plugin } from \"./core/plugins\";\nimport { galleryRegistry, type GalleryDefinition } from \"./gallery\";\nimport { createHttpAIProvider, type HttpAIProviderOptions } from \"./ai\";\n\nexport interface EmailBuilderProps {\n initialDocument?: EmailDocument;\n modules?: ModuleDefinition[];\n themes?: Theme[];\n /** Galleries of extra ready-made blocks, surfaced on top of each category. */\n galleries?: GalleryDefinition[];\n aiProvider?: AIProvider;\n /**\n * Convenience: wire the built-in HTTP AI provider (the Python backend) by URL.\n * Ignored when `aiProvider` is provided.\n */\n aiEndpoint?: string | HttpAIProviderOptions;\n onChange?: (doc: EmailDocument) => void;\n onExportHtml?: (html: string) => void;\n}\n\n/** React component wrapper. */\nexport function EmailBuilder(props: EmailBuilderProps) {\n useEffect(() => {\n registerDefaultModules();\n if (props.modules) for (const m of props.modules) moduleRegistry.register(m);\n if (props.galleries) for (const g of props.galleries) galleryRegistry.registerGallery(g);\n if (props.themes) useEmailStore.setState({ themes: props.themes });\n if (props.aiProvider) builder.setAIProvider(props.aiProvider);\n else if (props.aiEndpoint) {\n const opts =\n typeof props.aiEndpoint === \"string\" ? { endpoint: props.aiEndpoint } : props.aiEndpoint;\n builder.setAIProvider(createHttpAIProvider(opts));\n }\n if (props.initialDocument) {\n const r = documentSchema.safeParse(props.initialDocument);\n if (r.success) useEmailStore.getState().applyDoc(r.data as EmailDocument, false);\n }\n const unsub = useEmailStore.subscribe((s, prev) => {\n if (s.doc !== prev.doc) props.onChange?.(s.doc);\n });\n return () => unsub();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Expose export helper via prop callback.\n useEffect(() => {\n if (!props.onExportHtml) return;\n return useEmailStore.subscribe((s, prev) => {\n if (s.doc !== prev.doc) props.onExportHtml?.(renderEmailHtml(s.doc));\n });\n }, [props.onExportHtml]);\n\n return createElement(App);\n}\n\n/** Vanilla JS factory. */\nexport interface VanillaOptions extends EmailBuilderProps {\n container: HTMLElement;\n}\n\nexport interface VanillaInstance {\n destroy: () => void;\n getDocument: () => EmailDocument;\n exportHtml: () => string;\n exportJson: () => string;\n}\n\nexport function createEmailBuilder(opts: VanillaOptions): VanillaInstance {\n const root: Root = createRoot(opts.container);\n root.render(createElement(EmailBuilder, opts));\n return {\n destroy: () => root.unmount(),\n getDocument: () => useEmailStore.getState().doc,\n exportHtml: () => useEmailStore.getState().exportHtml(),\n exportJson: () => useEmailStore.getState().exportJson(),\n };\n}\n\n// Re-exports for plugin authors.\nexport type { Plugin, ModuleDefinition, AIProvider, EmailDocument, Theme };\nexport { registerPlugin, renderEmailHtml, documentSchema };\nexport { imageUploaderPlugin } from \"./plugins/imageUploader\";\nexport type { ImageUploaderOptions } from \"./plugins/imageUploader\";\n\n// Gallery module — extra ready-made blocks surfaced on top of each category.\nexport { galleryRegistry, galleryPlugin, sampleGallery } from \"./gallery\";\nexport type { GalleryDefinition, GalleryItem } from \"./gallery\";\n\n// AI assistant module — chat-driven editing backed by the Python service.\nexport {\n aiAssistantPlugin,\n createHttpAIProvider,\n buildCatalog,\n applyAIResponse,\n} from \"./ai\";\nexport type {\n AIAssistantOptions,\n HttpAIProviderOptions,\n CatalogEntry,\n ApplyResult,\n} from \"./ai\";\nexport { mockAIProvider, applyAIActions, validateAIDocument } from \"./core/aiActions\";\nexport type { AIAction, AIRequest, AIResponse } from \"./core/aiActions\";\n\nexport { templateRegistry, TEMPLATE_CATEGORY_LABELS } from \"./templates\";\nexport type { TemplateDefinition, TemplateCategory } from \"./templates\";\nexport {\n ALGORITHMS,\n ALGORITHM_BY_ID,\n FALLBACK_OPTIONS,\n defaultLogic as defaultRecommendationsLogic,\n readLogic as readRecommendationsLogic,\n toLegacyShape as recommendationsToLegacyShape,\n} from \"./recommendations/logic\";\nexport type {\n RecommendationsLogic,\n RecommendationFilters,\n StackEntry,\n AlgorithmDefinition,\n AlgorithmParamSpec,\n FallbackId,\n RecommendationMode,\n} from \"./recommendations/logic\";\n"],"x_google_ignoreList":[26,27,28,29],"mappings":"ytBAEA,IAAM,EAAa,EAAA,EAAE,MAAM,CAAC,EAAA,EAAE,OAAO,EAAG,EAAA,EAAE,OAAO,EAAG,EAAA,EAAE,QAAQ,EAAG,EAAA,EAAE,OAAO,EAAA,EAAE,OAAO,EAAG,EAAA,EAAE,IAAI,CAAC,CAAC,CAAC,EACzF,EAAc,EAAA,EAAE,OAAO,EAAA,EAAE,OAAO,EAAG,CAAU,CAAC,CAAC,SAAS,EAExD,EAAgB,EAAA,EAAE,mBAAmB,OAAQ,CACjD,EAAA,EAAE,OAAO,CACP,GAAI,EAAA,EAAE,OAAO,EACb,KAAM,EAAA,EAAE,QAAQ,MAAM,EACtB,KAAM,EAAA,EAAE,OAAO,CAAC,CAAC,SAAS,EAC1B,QAAS,EAAA,EAAE,OAAO,EAClB,MAAO,CACT,CAAC,EACD,EAAA,EAAE,OAAO,CACP,GAAI,EAAA,EAAE,OAAO,EACb,KAAM,EAAA,EAAE,QAAQ,OAAO,EACvB,IAAK,EAAA,EAAE,OAAO,EACd,IAAK,EAAA,EAAE,OAAO,CAAC,CAAC,SAAS,EACzB,KAAM,EAAA,EAAE,OAAO,CAAC,CAAC,SAAS,EAC1B,MAAO,CACT,CAAC,EACD,EAAA,EAAE,OAAO,CACP,GAAI,EAAA,EAAE,OAAO,EACb,KAAM,EAAA,EAAE,QAAQ,QAAQ,EACxB,MAAO,EAAA,EAAE,OAAO,EAChB,KAAM,EAAA,EAAE,OAAO,EACf,MAAO,CACT,CAAC,EACD,EAAA,EAAE,OAAO,CACP,GAAI,EAAA,EAAE,OAAO,EACb,KAAM,EAAA,EAAE,QAAQ,QAAQ,EACxB,OAAQ,EAAA,EAAE,OAAO,CACnB,CAAC,EACD,EAAA,EAAE,OAAO,CACP,GAAI,EAAA,EAAE,OAAO,EACb,KAAM,EAAA,EAAE,QAAQ,SAAS,EACzB,MAAO,CACT,CAAC,EACD,EAAA,EAAE,OAAO,CACP,GAAI,EAAA,EAAE,OAAO,EACb,KAAM,EAAA,EAAE,QAAQ,aAAa,EAC7B,SAAU,EAAA,EAAE,MACV,EAAA,EAAE,OAAO,CACP,GAAI,EAAA,EAAE,OAAO,EACb,MAAO,EAAA,EAAE,OAAO,EAChB,SAAU,EAAA,EAAE,OAAO,CAAC,CAAC,SAAS,EAC9B,KAAM,EAAA,EAAE,OAAO,EACf,SAAU,EAAA,EAAE,OAAO,CAAC,CAAC,SAAS,EAC9B,WAAY,EAAA,EAAE,OAAO,EACrB,YAAa,EAAA,EAAE,OAAO,CAAC,CAAC,SAAS,EACjC,KAAM,EAAA,EAAE,OAAO,CAAC,CAAC,SAAS,EAC1B,YAAa,EAAA,EAAE,OAAO,CAAC,CAAC,SAAS,CACnC,CAAC,CACH,EACA,QAAS,EAAA,EAAE,MAAM,CAAC,EAAA,EAAE,QAAQ,CAAC,EAAG,EAAA,EAAE,QAAQ,CAAC,EAAG,EAAA,EAAE,QAAQ,CAAC,CAAC,CAAC,EAC3D,aAAc,EAAA,EAAE,QAAQ,EACxB,WAAY,EAAA,EAAE,QAAQ,EACtB,gBAAiB,EAAA,EAAE,QAAQ,EAC3B,YAAa,EAAA,EAAE,OAAO,CAAC,CAAC,SAAS,EACjC,MAAO,CACT,CAAC,CACH,CAAC,EAEY,EAAe,EAAA,EAAE,OAAO,CACnC,GAAI,EAAA,EAAE,OAAO,EACb,KAAM,EAAA,EAAE,OAAO,EACf,KAAM,EAAA,EAAE,OAAO,EACf,MAAO,EACP,SAAU,EAAA,EAAE,MAAM,CAAa,EAC/B,KAAM,EAAA,EAAE,OAAO,EAAA,EAAE,OAAO,EAAG,EAAA,EAAE,IAAI,CAAC,CAAC,CAAC,SAAS,CAC/C,CAAC,EAEY,EAAc,EAAA,EAAE,OAAO,CAClC,GAAI,EAAA,EAAE,OAAO,EACb,KAAM,EAAA,EAAE,OAAO,EACf,OAAQ,EAAA,EAAE,OAAO,CACf,OAAQ,EAAA,EAAE,OAAO,EAAA,EAAE,OAAO,EAAG,EAAA,EAAE,OAAO,CAAC,EACvC,MAAO,EAAA,EAAE,OAAO,EAAA,EAAE,OAAO,EAAG,EAAA,EAAE,OAAO,CAAC,EACtC,QAAS,EAAA,EAAE,OAAO,EAAA,EAAE,OAAO,EAAG,EAAA,EAAE,OAAO,CAAC,EACxC,OAAQ,EAAA,EAAE,OAAO,EAAA,EAAE,OAAO,EAAG,EAAA,EAAE,OAAO,CAAC,CACzC,CAAC,CACH,CAAC,EAEY,EAAiB,EAAA,EAAE,OAAO,CACrC,QAAS,EAAA,EAAE,OAAO,EAClB,KAAM,EAAA,EAAE,OAAO,CAAE,KAAM,EAAA,EAAE,OAAO,EAAG,YAAa,EAAA,EAAE,OAAO,CAAE,CAAC,EAC5D,MAAO,EACP,SAAU,EAAA,EAAE,OAAO,CACjB,MAAO,EAAA,EAAE,OAAO,EAChB,gBAAiB,EAAA,EAAE,OAAO,EAC1B,uBAAwB,EAAA,EAAE,OAAO,CACnC,CAAC,EACD,QAAS,EAAA,EAAE,MAAM,CAAY,CAC/B,CAAC,EC1FD,SAAgB,EAAa,EAAgB,EAAuB,CAClE,GAAI,OAAO,GAAU,SAAU,OAAO,EACtC,IAAM,EAAI,EAAM,MAAM,gBAAgB,EACtC,GAAI,CAAC,EAAG,OAAO,EACf,IAAM,EAAO,EAAE,EAAE,CAAC,MAAM,GAAG,EACvB,EAAe,EAAM,OACzB,IAAK,IAAM,KAAK,EACd,GAAI,GAAO,OAAO,GAAQ,UAAY,KAAM,EAC1C,EAAO,EAAgC,QAEvC,OAAO,EAGX,OAAO,CACT,CAEA,SAAgB,EACd,EACA,EACyB,CACzB,GAAI,CAAC,EAAO,MAAO,CAAC,EACpB,IAAM,EAA+B,CAAC,EACtC,IAAK,GAAM,CAAC,EAAG,KAAM,OAAO,QAAQ,CAAK,EACvC,EAAI,GAAK,EAAa,EAAG,CAAK,EAEhC,OAAO,CACT,CC7BA,SAAgB,EAAI,EAAS,KAAc,CACzC,MAAO,GAAG,EAAO,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAG,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,GAC/F,CAEA,SAAgB,EAAW,EAAmB,CAC5C,OAAO,EACJ,QAAQ,KAAM,OAAO,CAAC,CACtB,QAAQ,KAAM,MAAM,CAAC,CACrB,QAAQ,KAAM,MAAM,CAAC,CACrB,QAAQ,KAAM,QAAQ,CAC3B,CAEA,SAAgB,EAAQ,EAAiC,CACvD,GAAI,CAAC,EAAK,MAAO,IACjB,GAAI,CACF,IAAM,EAAI,IAAI,IAAI,EAAK,qBAAqB,EAE5C,MADK,CAAC,QAAS,SAAU,SAAS,CAAC,CAAC,SAAS,EAAE,QAAQ,EAChD,EAD0D,GAEnE,MAAQ,CACN,MAAO,GACT,CACF,CCHA,SAAS,EAAG,EAAuB,EAAW,EAAW,CACvD,MAAO,GAAG,GAAK,EAAS,GAC1B,CAEA,SAAS,GAAY,EAAwC,CAC3D,IAAM,EAAkB,CAAC,EACzB,IAAK,GAAM,CAAC,EAAG,KAAM,OAAO,QAAQ,CAAK,EACnC,GAAyB,MAAQ,IAAM,IAC3C,EAAM,KAAK,GAAG,EAAE,GAAG,GAAG,EAExB,OAAO,EAAM,KAAK,GAAG,CACvB,CAEA,SAAS,GAAe,EAAsC,EAAsB,CAClF,IAAM,EAAW,EAAa,EAAa,CAAK,EAC1C,EAA8B,CAAC,EAC/B,GAAO,EAAgB,EAAc,EAAS,KAAO,CACrD,GAA6B,MAAQ,IAAQ,KACjD,EAAI,GAAU,GAAG,IAAM,EAAO,aAChC,EAgBA,OAfA,EAAI,cAAe,EAAS,UAAU,EAClC,EAAS,WAAa,IAAA,IAAW,EAAI,YAAa,EAAS,SAAU,IAAI,EAC7E,EAAI,cAAe,EAAS,UAAU,EAClC,EAAS,gBAAkB,IAAA,IAAW,EAAI,iBAAkB,EAAS,cAAe,IAAI,EAC5F,EAAI,cAAe,EAAS,UAAU,EACtC,EAAI,QAAS,EAAS,KAAK,EAC3B,EAAI,aAAc,EAAS,KAAK,EAChC,EAAI,mBAAoB,EAAS,eAAe,EAC5C,EAAS,aAAe,IAAA,IAAW,EAAI,cAAe,EAAS,WAAY,IAAI,EAC/E,EAAS,gBAAkB,IAAA,IAAW,EAAI,iBAAkB,EAAS,cAAe,IAAI,EACxF,EAAS,cAAgB,IAAA,IAAW,EAAI,eAAgB,EAAS,YAAa,IAAI,EAClF,EAAS,eAAiB,IAAA,IAAW,EAAI,gBAAiB,EAAS,aAAc,IAAI,EACrF,EAAS,eAAiB,IAAA,IAAW,EAAI,gBAAiB,EAAS,aAAc,IAAI,EACrF,EAAS,QAAU,IAAA,IAAW,EAAI,QAAS,EAAS,MAAO,IAAI,EAC/D,EAAS,SAAW,IAAA,IAAW,EAAI,SAAU,EAAS,OAAQ,IAAI,EAC/D,OAAO,QAAQ,CAAG,CAAC,CACvB,KAAK,CAAC,EAAG,KAAO,GAAG,EAAE,GAAG,GAAG,CAAC,CAC5B,KAAK,GAAG,CACb,CAQA,SAAS,GAAU,EAAwB,CAEzC,MADA,GAAI,aAAa,GAAK,EACf,IAAI,EAAI,aAAa,GAC9B,CAEA,SAAS,GACP,EACA,EACe,CACf,IAAM,EAAS,GAAO,OAChB,EAAS,GAAO,OACtB,GAAI,CAAC,GAAU,CAAC,EAAQ,OAAO,KAC/B,IAAM,EAAM,GAAU,CAAG,EACzB,GAAI,GAAU,OAAO,KAAK,CAAM,CAAC,CAAC,OAAS,EAAG,CAC5C,IAAM,EAAM,GAAe,EAAQ,EAAI,KAAK,EACxC,IACF,EAAI,YAAY,KAAK,6CAA6C,EAAI,GAAG,EAAI,GAAG,EAC5E,EAAO,QAAU,IAAA,IACnB,EAAI,YAAY,KACd,6CAA6C,EAAI,iBAAiB,EAAO,MAAM,8DACjF,EAGN,CAWA,OAVI,IAAW,UACb,EAAI,YAAY,KACd,6CAA6C,EAAI,sEACnD,EAEE,IAAW,WACb,EAAI,YAAY,KACd,6CAA6C,EAAI,4BACnD,EAEK,CACT,CAEA,SAAS,GAAW,EAAiB,EAAwB,CAC3D,IAAM,EAAI,EAAc,EAAG,OAAS,CAAC,EAA+B,EAAI,KAAK,EACvE,EAAM,GAAY,CACtB,cAAe,EAAE,YAAc,+BAC/B,YAAa,EAAE,SAAW,GAAG,EAAE,SAAS,IAAM,OAC9C,cAAe,EAAE,YAAc,IAC/B,iBAAkB,EAAE,cAAgB,GAAG,EAAE,cAAc,IAAM,IAAA,GAC7D,cAAe,EAAE,YAAc,SAC/B,MAAO,EAAE,OAAS,UAClB,aAAc,EAAE,OAAS,OACzB,cAAe,EAAG,EAAE,WAAsB,CAAC,EAC3C,iBAAkB,EAAG,EAAE,cAAyB,CAAC,EACjD,eAAgB,EAAG,EAAE,YAAuB,EAAE,EAC9C,gBAAiB,EAAG,EAAE,aAAwB,EAAE,EAChD,uBAAwB,UACxB,2BAA4B,OAC5B,uBAAwB,OACxB,OAAQ,CACV,CAAC,EACK,EAAO,EAAE,KACT,EAAQ,EACV,YAAY,EAAQ,CAAI,EAAE,oDAAoD,EAAG,QAAQ,MACzF,EAAG,QACD,EAAM,GAAc,EAAK,EAAG,KAAgC,EAClE,MAAO,OAAO,EAAM,WAAW,EAAI,GAAK,GAAG,UAAU,EAAI,IAAI,EAAM,OACrE,CAEA,SAAS,GAAY,EAAkB,EAAwB,CAC7D,IAAM,EAAI,EAAc,EAAG,OAAS,CAAC,EAA+B,EAAI,KAAK,EACvE,EAAU,GAAY,CAC1B,aAAc,EAAE,OAAS,SACzB,cAAe,EAAG,EAAE,WAAsB,CAAC,EAC3C,iBAAkB,EAAG,EAAE,cAAyB,CAAC,EACjD,eAAgB,EAAG,EAAE,YAAuB,CAAC,EAC7C,gBAAiB,EAAG,EAAE,aAAwB,CAAC,EAC/C,YAAa,IACb,cAAe,GACjB,CAAC,EACK,EAAS,GAAY,CACzB,QAAS,QACT,YAAa,OACb,MAAO,EAAE,MAAQ,GAAG,EAAE,MAAM,IAAM,OAClC,OAAQ,EAAE,OAAS,GAAG,EAAE,OAAO,IAAM,OACrC,gBAAiB,EAAE,aAAe,GAAG,EAAE,aAAa,IAAM,IAAA,GAC1D,OAAQ,EACR,QAAS,OACT,kBAAmB,OACnB,yBAA0B,UAC1B,OAAQ,EAAE,QAAU,UAAY,CAAC,EAAE,MAAQ,SAAW,IAAA,EACxD,CAAC,EACK,EAAY,EAAE,MAAQ,WAAW,EAAE,MAAM,GAAK,GAC9C,EAAM,aAAa,EAAW,EAAG,GAAG,EAAE,SAAS,EAAW,EAAG,KAAO,EAAE,EAAE,GAAG,EAAU,UAAU,EAAO,MACtG,EAAU,EAAG,KAAO,YAAY,EAAQ,EAAG,IAAI,EAAE,IAAI,EAAI,MAAQ,EACjE,EAAM,GAAc,EAAK,EAAG,KAAgC,EAClE,MAAO,OAAO,EAAM,WAAW,EAAI,GAAK,GAAG,UAAU,EAAQ,IAAI,EAAQ,OAC3E,CAEA,SAAS,GAAa,EAAmB,EAAwB,CAC/D,IAAM,EAAI,EAAc,EAAG,OAAS,CAAC,EAA+B,EAAI,KAAK,EAEvE,EAAU,GAAY,CAC1B,aAFa,EAAE,OAAoB,SAGnC,cAAe,EAAG,EAAE,WAAsB,EAAE,EAC5C,iBAAkB,EAAG,EAAE,cAAyB,EAAE,EAClD,eAAgB,EAAG,EAAE,YAAuB,EAAE,EAC9C,gBAAiB,EAAG,EAAE,aAAwB,EAAE,CAClD,CAAC,EACK,EAAM,EAAE,iBAA8B,UACtC,EAAS,EAAE,OAAoB,UAC/B,EAAU,EAAE,cAA2B,EACvC,EAAY,EAAE,UAAuB,GACrC,EAAc,EAAE,YAAyB,+BACzC,EAAc,EAAE,YAAyB,OAEzC,EAAS,GAAY,CACzB,QAAS,eACT,mBAAoB,EACpB,QACA,cAAe,EACf,YAAa,GAAG,EAAS,IACzB,cAAe,EACf,kBAAmB,OACnB,gBAAiB,GAAG,EAAO,IAC3B,QAAS,YACT,kBAAmB,IACnB,cAAe,OACf,2BAA4B,MAC9B,CAAC,EACK,EAAQ,EAAW,EAAG,KAAK,EAC3B,EAAO,EAAQ,EAAG,IAAI,EAEtB,EAAM;6GAC+F,EAAK,mEAFhG,KAAK,IAAI,GAAI,KAAK,MAAO,EAAS,GAAM,GAAG,CAEwH,EAAQ,2BAA2B,EAAG;;uBAEpM,EAAM,eAAe,EAAW,aAAa,EAAS,iBAAiB,EAAW,KAAK,EAAM;;cAG5G,EAAO,kCAAkC,EAAK,WAAW,EAAO,IAAI,EAAM,sBAC1E,EAAM,GAAc,EAAK,EAAG,KAAgC,EAClE,MAAO,OAAO,EAAM,WAAW,EAAI,GAAK,GAAG,UAAU,EAAQ,IAAI,IAAM,EAAK,OAC9E,CAEA,SAAS,GAAa,EAA2B,CAC/C,MAAO,sBAAsB,EAAG,OAAO,iBAAiB,EAAG,OAAO,6DACpE,CAEA,SAAS,GAAc,EAAoB,EAAwB,CACjE,IAAM,EAAI,EAAc,EAAG,OAAS,CAAC,EAA+B,EAAI,KAAK,EACvE,EAAS,EAAG,EAAE,WAAsB,CAAC,EACrC,EAAS,EAAG,EAAE,cAAyB,CAAC,EACxC,EAAS,EAAE,OAAoB,UAErC,MAAO,2BAA2B,EAAO,kBAAkB,EAAO,oCAD/C,EAAE,WAAwB,EACmE,WAAW,EAAM,8BACnI,CAEA,SAAS,GAAc,EAAkB,EAAwB,CAC/D,OAAQ,EAAG,KAAX,CACE,IAAK,OACH,OAAO,GAAW,EAAI,CAAG,EAC3B,IAAK,QACH,OAAO,GAAY,EAAI,CAAG,EAC5B,IAAK,SACH,OAAO,GAAa,EAAI,CAAG,EAC7B,IAAK,SACH,OAAO,GAAa,CAAE,EACxB,IAAK,UACH,OAAO,GAAc,EAAI,CAAG,EAC9B,IAAK,cACH,OAAO,GAAkB,EAAI,CAAG,CACpC,CACF,CAEA,SAAS,GAAkB,EAAwB,EAAwB,CACzE,IAAM,EAAI,EAAc,EAAG,OAAS,CAAC,EAA+B,EAAI,KAAK,EACvE,EAAO,EAAG,QACV,EAAW,EAAG,SAAS,MAAM,EAAG,EAAO,CAAC,EACxC,EACH,EAAE,qBAAmC,EAAE,iBAA8B,cAClE,EAAa,EAAE,WAAwB,gBACvC,EAAc,EAAE,iBAA8B,mBAC9C,EAAY,EAAE,eAA4B,UAC1C,EAAS,EAAE,uBAAoC,4BAC/C,EAAY,EAAE,aAA0B,sBACxC,EAAU,EAAE,cAA2B,EACvC,EAAS,EAAG,EAAE,WAAsB,EAAE,EACtC,EAAS,EAAG,EAAE,cAAyB,EAAE,EACzC,EAAO,EAAG,EAAE,YAAuB,EAAE,EACrC,EAAO,EAAG,EAAE,aAAwB,EAAE,EAEtC,EAAc,GAAG,KAAK,MAAM,IAAM,CAAI,EAAE,GAGxC,GAAQ,EAAY,IAA0B,CAClD,IAAM,EAAa,0CAA0C,EAAiB,EAAY,EAAI,KAAK,EAAE,qCAAqC,EACxI,EAAE,UACJ,EAAE,SACI,EAAW,EAAG,cAAgB,EAAE,SAClC,wCAAwC,EAAiB,EAAU,EAAI,KAAK,EAAE,kEAAkE,EAC9I,EAAE,QACJ,EAAE,SACF,GACE,EAAO,EAAG,iBAAmB,EAAE,YACjC,wHAAwH,EAAW,EAAE,WAAW,EAAE,QAClJ,GACE,EAAW,EAAE,aAAe,EAAG,aAAe,WAC9C,EAAO,EAAE,MAAQ,IACjB,EAAM,EAAG,WACX,gIAAgI,EAC9H,EACA,EAAI,KACN,EAAE;6DACmD,EAAQ,CAAI,EAAE,8FAA8F,EAAiB,EAAO,EAAI,KAAK,EAAE,wCAAwC,EAAiB,EAAU,EAAI,KAAK,EAAE,kEAAkE,EAAW,CAAQ,EAAE;6CACpU,EAAQ,CAAI,EAAE,+HAA+H,EAAiB,EAAU,EAAI,KAAK,EAAE,oBAAoB,EAAiB,EAAO,EAAI,KAAK,EAAE,4CAA4C,EAAW,CAAQ,EAAE,wCAChV,GACE,EAAM,aAAa,EAAW,EAAE,KAAK,EAAE,SAAS,EAAW,EAAE,UAAY,EAAE,IAAI,EAAE,qIAAqI,EAAO,SAC7N,EAAa,EAAE,KACjB,YAAY,EAAQ,EAAE,IAAI,EAAE,gDAAgD,EAAI,MAChF,EAGJ,MAAO,mDAAmD,EAAO,EAAI,EAAE,oBAAkC,EAAY;+GACV,EAAiB,EAAQ,EAAI,KAAK,EAAE,iBAAiB,EAAO;2DAChH,EAAW;6HACuD,EAAiB,EAAW,EAAI,KAAK,EAAE,qBAAqB,EAAW,EAAE,IAAI,EAAE;sFACtH,IAAW,EAAW;MACtG,EAAO,4CAA4C,EAAK,YAAc,GAAG;MACzE,EAAM,8DAA8D,EAAI,YAAc,GAAG;;MAG7F,EAGM,EAAiB,CAAC,EACxB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAS,OAAQ,GAAK,EAAM,CAC9C,IAAM,EAAQ,EAAS,MAAM,EAAG,EAAI,CAAI,EAClC,EAAM,EACT,KAAK,EAAG,IAAQ,EAAK,EAAG,IAAQ,EAAM,OAAS,CAAC,CAAC,CAAC,CAClD,KAAK;CAAI,EAEN,EAAO,EAAO,EAAM,OACtB,EAAS,GACb,IAAK,IAAI,EAAI,EAAG,EAAI,EAAM,IACxB,GAAU,kCAAkC,EAAY,gBAE1D,EAAK,KAAK,OAAO,IAAM,EAAO,MAAM,CACtC,CAGA,IAAM,EAAM,GAAc,EAAK,EAAG,KAAgC,EAClE,MAAO,OAAO,EAAM,WAAW,EAAI,GAAK,GAAG,kBAAkB,EAAO,GAAG,EAAK,GAAG,EAAO,GAAG,EAAK;;;EAG9F,EAAK,KAAK;CAAI,EAAE;;;OAIlB,CAEA,SAAS,EAAiB,EAA2B,EAAsB,CACzE,GAAI,CAAC,EAAO,MAAO,GACnB,IAAM,EAAI,EAAa,EAAO,CAAK,EACnC,OAAO,OAAO,GAAM,SAAW,EAAI,OAAO,CAAC,CAC7C,CAEA,SAAS,GAAa,EAAgB,EAAwB,CAC5D,IAAM,EAAI,EAAc,EAAE,OAAS,CAAC,EAA+B,EAAI,KAAK,EACtE,EAAM,GAAY,CACtB,mBAAoB,EAAE,gBACtB,cAAe,EAAG,EAAE,WAAsB,CAAC,EAC3C,iBAAkB,EAAG,EAAE,cAAyB,CAAC,EACjD,eAAgB,EAAG,EAAE,YAAuB,CAAC,EAC7C,gBAAiB,EAAG,EAAE,aAAwB,CAAC,EAC/C,gBAAiB,EAAE,aAAe,GAAG,EAAE,aAAa,IAAM,IAAA,EAC5D,CAAC,EACK,EAAQ,EAAE,SAAS,IAAK,GAAM,GAAc,EAAG,CAAG,CAAC,CAAC,CAAC,KAAK;CAAI,EAC9D,EAAM,GAAc,EAAK,EAAE,KAAgC,EACjE,MAAO,UAAU,EAAM,WAAW,EAAI,GAAK,GAAG,UAAU,EAAI,IAAI,EAAM,WACxE,CAEA,SAAgB,GAAgB,EAA4B,CAC1D,IAAM,EAAK,EAAa,EAAI,SAAS,gBAAiB,EAAI,KAAK,EACzD,EAAM,EAAa,EAAI,SAAS,uBAAwB,EAAI,KAAK,EACjE,EAAQ,EAAI,SAAS,MACrB,EAAiB,CAAE,MAAO,EAAI,MAAO,YAAa,CAAC,EAAG,aAAc,CAAE,EAAG,CAAE,CAAE,EAC7E,EAAO,EAAI,QAAQ,IAAK,GAAM,GAAa,EAAG,CAAG,CAAC,CAAC,CAAC,KAAK;CAAI,EAC7D,EAAc,EAAW,EAAI,KAAK,aAAe,EAAE,EACnD,EAAY,EAAI,YAAY,KAAK;CAAI,EAE3C,MAAO;;;;;;;;;;SAUA,EAAW,EAAI,KAAK,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;EAsBjC,EAAU;;;6DAGiD,EAAG;iFACiB,EAAY;6GACgB,EAAG;;0DAEtD,EAAM;gEACA,EAAM,4DAA4D,EAAM,eAAe,EAAM,sBAAsB,EAAI;EACrL,EAAK;;;;;;QAOP,CC3YA,IAAa,GAAqB,CAChC,GAAI,eACJ,KAAM,eACN,OAAQ,CACN,OAAQ,CACN,WAAY,UACZ,QAAS,UACT,QAAS,UACT,KAAM,UACN,MAAO,UACP,iBAAkB,UAClB,WAAY,SACd,EACA,MAAO,CACL,QAAS,+BACT,KAAM,+BACN,OAAQ,8BACV,EACA,QAAS,CAAE,GAAI,EAAG,GAAI,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,EAAG,EAChD,OAAQ,CAAE,GAAI,EAAG,GAAI,EAAG,GAAI,EAAG,CACjC,CACF,EAEa,EAAwB,CACnC,GAAI,kBACJ,KAAM,kBACN,OAAQ,CACN,OAAQ,CACN,WAAY,UACZ,QAAS,UACT,QAAS,UACT,KAAM,UACN,MAAO,UACP,iBAAkB,UAClB,WAAY,SACd,EACA,MAAO,CACL,QAAS,iBACT,KAAM,+BACN,OAAQ,8BACV,EACA,QAAS,CAAE,GAAI,EAAG,GAAI,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,EAAG,EAChD,OAAQ,CAAE,GAAI,EAAG,GAAI,EAAG,GAAI,EAAG,CACjC,CACF,EAEa,GAAqB,CAChC,GAAI,eACJ,KAAM,eACN,OAAQ,CACN,OAAQ,CACN,WAAY,UACZ,QAAS,UACT,QAAS,UACT,KAAM,UACN,MAAO,UACP,iBAAkB,UAClB,WAAY,SACd,EACA,MAAO,CACL,QAAS,iBACT,KAAM,iBACN,OAAQ,8BACV,EACA,QAAS,CAAE,GAAI,EAAG,GAAI,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,EAAG,EAChD,OAAQ,CAAE,GAAI,EAAG,GAAI,EAAG,GAAI,CAAE,CAChC,CACF,EAEa,EAAkB,CAC7B,GAAI,YACJ,KAAM,YACN,OAAQ,CACN,OAAQ,CACN,WAAY,UACZ,QAAS,UACT,QAAS,UACT,KAAM,UACN,MAAO,UACP,iBAAkB,UAClB,WAAY,SACd,EACA,MAAO,CACL,QAAS,iBACT,KAAM,+BACN,OAAQ,8BACV,EACA,QAAS,CAAE,GAAI,EAAG,GAAI,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,EAAG,EAChD,OAAQ,CAAE,GAAI,EAAG,GAAI,EAAG,GAAI,EAAG,CACjC,CACF,EAEa,EAA6B,CACxC,GAAI,uBACJ,KAAM,uBACN,OAAQ,CACN,OAAQ,CACN,WAAY,UACZ,QAAS,UACT,QAAS,UACT,KAAM,UACN,MAAO,UACP,iBAAkB,UAClB,WAAY,SACd,EACA,MAAO,CACL,QAAS,oCACT,KAAM,oCACN,OAAQ,8BACV,EACA,QAAS,CAAE,GAAI,EAAG,GAAI,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,EAAG,EAChD,OAAQ,CAAE,GAAI,EAAG,GAAI,EAAG,GAAI,CAAE,CAChC,CACF,EAEa,GAAyB,CACpC,GACA,EACA,GACA,EACA,CACF,EC3DM,GAAc,sBAEpB,SAAS,GAAS,EAA6B,CAC7C,MAAO,CACL,QAAS,MACT,KAAM,CAAE,KAAM,iBAAkB,YAAa,EAAG,EAChD,QACA,SAAU,CACR,MAAO,IACP,gBAAiB,sBACjB,uBAAwB,kBAC1B,EACA,QAAS,CAAC,CACZ,CACF,CAEA,IAAa,GAAA,EAAA,EAAA,OAAA,EAA+B,EAAK,KAAS,CACxD,IAAK,GAAS,GAAc,EAAE,EAC9B,UAAW,CAAE,KAAM,OAAQ,EAC3B,KAAM,CAAC,EACP,OAAQ,CAAC,EACT,OAAQ,GACR,SAAU,UAEV,aAAe,GAAQ,EAAI,CAAE,UAAW,CAAI,CAAC,EAC7C,YAAc,GAAS,EAAI,CAAE,SAAU,CAAK,CAAC,EAE7C,UAAW,EAAM,EAAO,KACtB,EAAK,GACE,EAEE,CAAE,IAAK,EAAM,KADP,CAAC,GAAG,EAAE,KAAM,EAAE,GAAG,CAAC,CAAC,MAAM,GAClB,EAAM,OAAQ,CAAC,CAAE,EAFnB,CAAE,IAAK,CAAK,CAG/B,EAEH,SACE,EAAK,GACC,EAAE,KAAK,SAAW,EAAU,EAEzB,CACL,IAFW,EAAE,KAAK,EAAE,KAAK,OAAS,GAGlC,KAAM,EAAE,KAAK,MAAM,EAAG,EAAE,EACxB,OAAQ,CAAC,EAAE,IAAK,GAAG,EAAE,MAAM,CAC7B,CACD,EAEH,SACE,EAAK,GAAM,CACT,GAAI,EAAE,OAAO,SAAW,EAAG,OAAO,EAClC,GAAM,CAAC,EAAM,GAAG,GAAQ,EAAE,OAC1B,MAAO,CAAE,IAAK,EAAM,KAAM,CAAC,GAAG,EAAE,KAAM,EAAE,GAAG,EAAG,OAAQ,CAAK,CAC7D,CAAC,EAEH,WAAY,EAAK,IAAU,CACzB,GAAM,CAAE,MAAK,YAAa,EAAI,EACxB,EAAM,GAAS,EAAI,QAAQ,OAC3B,EAAU,CAAC,GAAG,EAAI,OAAO,EAC/B,EAAQ,OAAO,EAAK,EAAG,CAAG,EAC1B,EAAS,CAAE,GAAG,EAAK,SAAQ,CAAC,EAC5B,EAAI,CAAE,UAAW,CAAE,KAAM,SAAU,SAAU,EAAI,EAAG,CAAE,CAAC,CACzD,EAEA,aAAe,GAAa,CAC1B,GAAM,CAAE,MAAK,YAAa,EAAI,EACxB,EAAU,EAAI,QAAQ,OAAQ,GAAM,EAAE,KAAO,CAAQ,EAC3D,EAAS,CAAE,GAAG,EAAK,SAAQ,CAAC,EAC5B,EAAI,CAAE,UAAW,CAAE,KAAM,OAAQ,CAAE,CAAC,CACtC,EAEA,gBAAkB,GAAa,CAC7B,GAAM,CAAE,MAAK,YAAa,EAAI,EACxB,EAAM,EAAI,QAAQ,UAAW,GAAM,EAAE,KAAO,CAAQ,EAC1D,GAAI,IAAQ,GAAI,OAChB,IAAM,EAAW,EAAI,QAAQ,GACvB,EAAqB,CACzB,GAAG,EACH,GAAI,EAAI,QAAQ,EAChB,SAAU,EAAS,SAAS,IAAK,IAAO,CAAE,GAAG,EAAG,GAAI,EAAI,IAAI,CAAE,EAAE,CAClE,EACM,EAAU,CAAC,GAAG,EAAI,OAAO,EAC/B,EAAQ,OAAO,EAAM,EAAG,EAAG,CAAK,EAChC,EAAS,CAAE,GAAG,EAAK,SAAQ,CAAC,EAC5B,EAAI,CAAE,UAAW,CAAE,KAAM,SAAU,SAAU,EAAM,EAAG,CAAE,CAAC,CAC3D,EAEA,gBAAiB,EAAW,IAAY,CACtC,GAAM,CAAE,MAAK,YAAa,EAAI,EAC9B,GAAI,IAAc,EAAS,OAC3B,IAAM,EAAU,CAAC,GAAG,EAAI,OAAO,EACzB,CAAC,GAAS,EAAQ,OAAO,EAAW,CAAC,EAC3C,EAAQ,OAAO,EAAS,EAAG,CAAK,EAChC,EAAS,CAAE,GAAG,EAAK,SAAQ,CAAC,CAC9B,EAEA,cAAe,EAAU,IAAU,CACjC,GAAM,CAAE,MAAK,YAAa,EAAI,EACxB,EAAU,EAAI,QAAQ,IAAK,GAC/B,EAAE,KAAO,EAAW,CAAE,GAAG,EAAG,GAAG,EAAO,MAAO,CAAE,GAAG,EAAE,MAAO,GAAG,EAAM,KAAM,CAAE,EAAI,CAClF,EACA,EAAS,CAAE,GAAG,EAAK,SAAQ,CAAC,CAC9B,EAEA,eAAgB,EAAU,EAAW,IAAU,CAC7C,GAAM,CAAE,MAAK,YAAa,EAAI,EACxB,EAAU,EAAI,QAAQ,IAAK,GAAM,CACrC,GAAI,EAAE,KAAO,EAAU,OAAO,EAC9B,IAAM,EAAW,EAAE,SAAS,IAAK,GAAM,CACrC,GAAI,EAAE,KAAO,EAAW,OAAO,EAC/B,IAAM,EAAO,CAAE,GAAG,EAAG,GAAG,CAAM,EAO9B,MANI,UAAW,GAAK,UAAW,IAC7B,EAA8C,MAAQ,CACpD,GAAI,EAA0C,MAC9C,GAAI,EAA8C,KACpD,GAEK,CACT,CAAC,EACD,MAAO,CAAE,GAAG,EAAG,UAAS,CAC1B,CAAC,EACD,EAAS,CAAE,GAAG,EAAK,SAAQ,CAAC,CAC9B,EAEA,eAAgB,EAAU,IAAc,CACtC,GAAM,CAAE,MAAK,YAAa,EAAI,EACxB,EAAU,EAAI,QAAQ,IAAK,GAC/B,EAAE,KAAO,EACL,CAAE,GAAG,EAAG,SAAU,EAAE,SAAS,OAAQ,GAAM,EAAE,KAAO,CAAS,CAAE,EAC/D,CACN,EACA,EAAS,CAAE,GAAG,EAAK,SAAQ,CAAC,EAC5B,EAAI,CAAE,UAAW,CAAE,KAAM,SAAU,UAAS,CAAE,CAAC,CACjD,EAEA,gBAAiB,EAAU,EAAW,IAAY,CAChD,GAAM,CAAE,MAAK,YAAa,EAAI,EACxB,EAAU,EAAI,QAAQ,IAAK,GAAM,CAIrC,GAHI,EAAE,KAAO,GACT,EAAY,GAAK,GAAa,EAAE,SAAS,QACzC,EAAU,GAAK,GAAW,EAAE,SAAS,QACrC,IAAc,EAAS,OAAO,EAClC,IAAM,EAAW,CAAC,GAAG,EAAE,QAAQ,EACzB,CAAC,GAAS,EAAS,OAAO,EAAW,CAAC,EAE5C,OADA,EAAS,OAAO,EAAS,EAAG,CAAK,EAC1B,CAAE,GAAG,EAAG,UAAS,CAC1B,CAAC,EACD,EAAS,CAAE,GAAG,EAAK,SAAQ,CAAC,CAC9B,EAEA,aAAc,EAAU,EAAW,IAAQ,CACzC,GAAM,CAAE,MAAK,kBAAmB,EAAI,EAC9B,EAAI,EAAI,QAAQ,KAAM,GAAM,EAAE,KAAO,CAAQ,EACnD,GAAI,CAAC,EAAG,OACR,IAAM,EAAM,EAAE,SAAS,UAAW,GAAM,EAAE,KAAO,CAAS,EACtD,IAAQ,IACZ,EAAe,EAAU,EAAK,EAAM,CAAG,CACzC,EAEA,WAAa,GAAU,CACrB,GAAM,CAAE,MAAK,YAAa,EAAI,EAC9B,EAAS,CAAE,GAAG,EAAK,OAAM,CAAC,CAC5B,EAEA,WAAa,GAAU,CACrB,GAAM,CAAE,MAAK,YAAa,EAAI,EAC9B,EAAS,CAAE,GAAG,EAAK,KAAM,CAAE,GAAG,EAAI,KAAM,GAAG,CAAM,CAAE,CAAC,CACtD,EAEA,eAAiB,GAAU,CACzB,GAAM,CAAE,MAAK,YAAa,EAAI,EAC9B,EAAS,CAAE,GAAG,EAAK,SAAU,CAAE,GAAG,EAAI,SAAU,GAAG,CAAM,CAAE,CAAC,CAC9D,EAEA,aAAe,GAAQ,CACrB,IAAM,EAAO,EAAI,MAAM,EACvB,EAAI,CAAC,CAAC,SAAS,CAAI,EACnB,EAAI,CAAE,UAAW,CAAE,KAAM,OAAQ,EAAG,KAAM,CAAC,EAAG,OAAQ,CAAC,CAAE,CAAC,CAC5D,EAEA,kBAAqB,CACnB,GAAM,CAAE,MAAK,YAAa,EAAI,EAC9B,EAAS,GAAS,EAAI,KAAK,CAAC,EAC5B,EAAI,CAAE,UAAW,CAAE,KAAM,OAAQ,EAAG,KAAM,CAAC,EAAG,OAAQ,CAAC,CAAE,CAAC,CAC5D,EAEA,eAAkB,KAAK,UAAU,EAAI,CAAC,CAAC,IAAK,KAAM,CAAC,EAEnD,WAAa,GAAS,CACpB,GAAI,CACF,IAAM,EAAS,KAAK,MAAM,CAAI,EACxB,EAAS,EAAe,UAAU,CAAM,EAK9C,OAJK,EAAO,SAGZ,EAAI,CAAC,CAAC,SAAS,EAAO,IAAqB,EACpC,CAAE,GAAI,EAAK,GAHT,CAAE,GAAI,GAAO,MAAO,EAAO,MAAM,OAAQ,CAIpD,OAAS,EAAG,CACV,MAAO,CAAE,GAAI,GAAO,MAAQ,EAAY,OAAQ,CAClD,CACF,EAEA,eAAkB,GAAgB,EAAI,CAAC,CAAC,GAAG,EAE3C,yBAA4B,CAC1B,GAAI,CACF,IAAM,EAAM,aAAa,QAAQ,EAAW,EAC5C,GAAI,CAAC,EAAK,OACV,IAAM,EAAS,EAAe,UAAU,KAAK,MAAM,CAAG,CAAC,EACnD,EAAO,SACT,EAAI,CAAE,IAAK,EAAO,KAAuB,KAAM,CAAC,EAAG,OAAQ,CAAC,CAAE,CAAC,CAEnE,MAAQ,CAER,CACF,EAEA,uBAA0B,CACxB,aAAa,QAAQ,GAAa,KAAK,UAAU,EAAI,CAAC,CAAC,GAAG,CAAC,CAC7D,CACF,EAAE,ECjOW,EAAmB,IAAI,KApBb,CACrB,UAAoB,IAAI,IAExB,SAAS,EAAyB,CAChC,KAAK,UAAU,IAAI,EAAI,GAAI,CAAG,CAChC,CAEA,IAAI,EAA4C,CAC9C,OAAO,KAAK,UAAU,IAAI,CAAE,CAC9B,CAEA,MAA6B,CAC3B,OAAO,MAAM,KAAK,KAAK,UAAU,OAAO,CAAC,CAC3C,CAEA,WAAW,EAA6C,CACtD,OAAO,KAAK,KAAK,CAAC,CAAC,OAAQ,GAAM,EAAE,WAAa,CAAG,CACrD,CACF,EAIa,GAA6D,CACxE,WAAY,aACZ,UAAW,YACX,eAAgB,iBAChB,eAAgB,iBAChB,WAAY,aACZ,MAAO,QACP,cAAe,gBACf,WAAY,YACd,EC9Da,GACX,EACA,EAeK,CAAC,IACW,CAEjB,IAAM,EAAe,EAAK,UAAY,GAChC,EAA0C,CAC9C,YAAa,GACb,aAAc,EAChB,EAGA,OAFI,GAAgB,GAAI,EAAe,SAAW,KAAK,IAAI,GAAI,KAAK,MAAM,EAAe,GAAI,CAAC,EACrF,GAAgB,KAAI,EAAe,SAAW,KAAK,IAAI,GAAI,KAAK,MAAM,EAAe,GAAI,CAAC,GAC5F,CACL,GAAI,EAAI,IAAI,EACZ,KAAM,OACN,KAAM,EAAK,KACX,UACA,MAAO,CACL,WAAY,EAAK,YAAc,eAC/B,SAAU,EACV,WAAY,EAAK,WACjB,MAAO,EAAK,OAAS,gBACrB,MAAO,EAAK,OAAS,OACrB,WAAY,EAAK,YAAc,EAC/B,cAAe,EAAK,eAAiB,EACrC,YAAa,EAAK,aAAe,GACjC,aAAc,EAAK,cAAgB,GACnC,WAAY,EAAK,YAAc,IAC/B,cAAe,EAAK,cACpB,KAAM,EAAK,KACX,OAAQ,CAAE,GAAG,EAAgB,GAAI,EAAK,QAAU,CAAC,CAAG,CACtD,CACF,CACF,EAEa,GACX,EACA,EACA,EASK,CAAC,IACW,CACjB,IAAM,EAAI,EAAK,OAAS,IAElB,EAA0C,EAAI,IAAM,CAAE,MAAO,IAAK,MAAO,QAAS,EAAI,CAAC,EAC7F,MAAO,CACL,GAAI,EAAI,IAAI,EACZ,KAAM,QACN,MACA,MACA,KAAM,EAAK,KACX,MAAO,CACL,MAAO,EACP,OAAQ,EAAK,OACb,MAAO,EAAK,OAAS,SACrB,WAAY,EAAK,YAAc,EAC/B,cAAe,EAAK,eAAiB,EACrC,aAAc,EAAK,aACnB,OAAQ,CAAE,GAAG,EAAgB,GAAI,EAAK,QAAU,CAAC,CAAG,CACtD,CACF,CACF,EAEa,GACX,EACA,EAAO,IACP,EASK,CAAC,KACY,CAClB,GAAI,EAAI,IAAI,EACZ,KAAM,SACN,QACA,OACA,MAAO,CACL,gBAAiB,EAAK,iBAAmB,4BACzC,MAAO,EAAK,OAAS,sBACrB,WAAY,iBACZ,SAAU,EAAK,UAAY,GAC3B,aAAc,EAAK,cAAgB,EACnC,MAAO,EAAK,OAAS,SACrB,WAAY,EAAK,YAAc,GAC/B,cAAe,EAAK,eAAiB,GAErC,OAAQ,CAAE,MAAO,SAAU,GAAI,EAAK,QAAU,CAAC,CAAG,CACpD,CACF,GAEa,GAAU,EAAS,MAAsB,CACpD,GAAI,EAAI,IAAI,EACZ,KAAM,SACN,QACF,GAEa,GACX,EAAiG,CAAC,KAChF,CAClB,GAAI,EAAI,IAAI,EACZ,KAAM,UACN,MAAO,CACL,MAAO,EAAK,OAAS,UACrB,UAAW,EAAK,WAAa,EAC7B,WAAY,EAAK,YAAc,EAC/B,cAAe,EAAK,eAAiB,CACvC,CACF,GAEa,GACX,EACA,EACA,EACA,KACiB,CACjB,GAAI,EAAI,QAAQ,EAChB,OACA,OACA,MAAO,GAAS,CACd,gBAAiB,mBACjB,WAAY,GACZ,cAAe,GACf,OAAQ,CAAE,YAAa,EAAG,aAAc,CAAE,CAC5C,EACA,UACF,GAGa,GACX,EACA,EAMI,CAAC,IAGE,EAAK,EAAS,CACnB,KAAM,WACN,WAAY,kBACZ,SAAU,EAAK,UAAY,CAJb,EAAG,GAAI,EAAG,GAAI,EAAG,EAIJ,EAAM,EAAK,OAAS,GAC/C,WAAY,OACZ,MAAO,EAAK,MACZ,WAAY,EAAK,YAAc,GAC/B,cAAe,EAAK,eAAiB,EACrC,WAAY,IACd,CAAC,EAGU,GACX,EACA,EAA6F,CAAC,IAE9F,EAAK,EAAQ,YAAY,EAAG,CAC1B,SAAU,GACV,WAAY,OACZ,MAAO,mBACP,cAAe,EACf,MAAO,EAAK,MACZ,WAAY,EAAK,YAAc,GAC/B,cAAe,EAAK,eAAiB,CACvC,CAAC,EAEU,GACX,EACA,EAQI,CAAC,IAEL,EAAK,EAAS,CACZ,MAAO,iBACP,MAAO,EAAK,MACZ,SAAU,EAAK,UAAY,GAC3B,WAAY,EAAK,WACjB,cAAe,EAAK,cACpB,WAAY,EAAK,WACjB,KAAM,EAAK,KACX,cAAe,EAAK,aACtB,CAAC,EAEU,GAAe,EAAW,EAAW,EAAQ,UACxD,wBAAwB,EAAE,GAAG,EAAE,QAAQ,mBAAmB,CAAK,IAE7D,GAAc,EACL,EAAW,IACtB,IAAe,EACR,CACL,GAAI,EAAI,MAAM,EACd,MAAO,EAAE,OAAS,EAAY,IAAK,IAAK,EAAE,IAAI,EAC9C,SAAU,EAAE,UAAY,EAAE,KAC1B,KAAM,EAAE,KACR,WAAY,EAAE,WACd,SAAU,EAAE,SACZ,YAAa,EAAE,YACf,KAAM,EAAE,MAAQ,IAChB,YAAa,EAAE,WACjB,GAGW,GACX,EACA,EAiBK,CAAC,KACkB,CACxB,GAAI,EAAI,IAAI,EACZ,KAAM,cACN,WACA,QAAS,EAAK,UAAY,EAAS,QAAU,EAAI,EAAI,GACrD,aAAc,EAAK,cAAgB,EAAS,KAAM,GAAM,CAAC,CAAC,EAAE,QAAQ,EACpE,WAAY,EAAK,YAAc,GAC/B,gBAAiB,EAAK,iBAAmB,GACzC,YAAa,EAAK,aAAe,WACjC,MAAO,CACL,oBAAqB,EAAK,qBAAuB,mBACjD,UAAW,EAAK,WAAa,gBAC7B,gBAAiB,EAAK,iBAAmB,mBACzC,cAAe,EAAK,eAAiB,UACrC,sBAAuB,EAAK,uBAAyB,4BACrD,YAAa,EAAK,aAAe,sBACjC,aAAc,EAAK,cAAgB,EACnC,WAAY,EAAK,YAAc,EAC/B,cAAe,EAAK,eAAiB,EACrC,YAAa,EAAK,aAAe,GACjC,aAAc,EAAK,cAAgB,EACrC,CACF,GCtJA,EAAiB,SAAS,CAlHxB,GAAI,oBACJ,KAAM,oBACN,SAAU,aACV,YACE,qHACF,KAAM,CAAC,aAAc,YAAa,SAAU,YAAY,EACxD,UAAW,6DACX,WAA6B,CAC3B,QAAS,MACT,KAAM,CACJ,KAAM,+BACN,YAAa,2DACf,EACA,MAAO,EACP,SAAU,CACR,MAAO,IACP,gBAAiB,sBACjB,uBAAwB,kBAC1B,EACA,QAAS,CACP,EAAI,kBAAmB,WAAY,CACjC,EAAK,aAAc,CACjB,MAAO,SACP,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,cAAe,EACf,WAAY,GACZ,cAAe,CACjB,CAAC,EACD,EAAM,4BAA6B,CAAE,MAAO,SAAU,cAAe,EAAG,CAAC,EACzE,EAAQ,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,CAC7C,CAAC,EACD,EAAI,kBAAmB,aAAc,CACnC,EAAQ,aAAc,CAAE,WAAY,EAAG,CAAC,EACxC,EAAQ,8CAA+C,CACrD,SAAU,GACV,WAAY,EACZ,cAAe,EACjB,CAAC,EACD,EAAM,EAAY,IAAK,IAAK,YAAY,EAAG,WAAY,CAAE,MAAO,GAAI,CAAC,EACrE,EACE,qJACA,CAAE,WAAY,GAAI,cAAe,EAAG,CACtC,EACA,EAAK,wBAAyB,CAC5B,MAAO,mBACP,WAAY,OACZ,KAAM,IACN,cAAe,CACjB,CAAC,CACH,CAAC,EACD,EAAI,sBAAuB,mBAAoB,CAC7C,EAAQ,iBAAkB,CAAE,WAAY,EAAG,CAAC,EAC5C,EAAQ,mBAAoB,CAAE,cAAe,EAAG,CAAC,EACjD,EAAK,yCAA0C,CAC7C,WAAY,OACZ,KAAM,IACN,WAAY,EACZ,cAAe,CACjB,CAAC,EACD,EAAM,kEAAmE,CACvE,cAAe,EACjB,CAAC,EACD,EAAQ,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,EAC3C,EAAK,+CAAgD,CACnD,WAAY,OACZ,KAAM,IACN,cAAe,CACjB,CAAC,EACD,EAAM,oEAAqE,CACzE,cAAe,EACjB,CAAC,EACD,EAAQ,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,EAC3C,EAAK,8CAA+C,CAClD,WAAY,OACZ,KAAM,IACN,cAAe,CACjB,CAAC,EACD,EAAM,6DAA8D,CAClE,cAAe,EACjB,CAAC,CACH,CAAC,EACD,EAAI,sBAAuB,sBAAuB,CAChD,EAAQ,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,EAC3C,EAAK,sCAAuC,CAC1C,MAAO,SACP,WAAY,GACZ,cAAe,EACjB,CAAC,EACD,EAAO,mBAAoB,GAAG,EAC9B,EAAO,EAAE,CACX,CAAC,EACD,EACE,gBACA,SACA,CACE,EAAM,iDAAkD,CACtD,MAAO,SACP,WAAY,EACd,CAAC,EACD,EAAM,mCAAoC,CACxC,MAAO,SACP,WAAY,EACZ,cAAe,GACf,KAAM,GACR,CAAC,CACH,EACA,CAAE,gBAAiB,sBAAuB,WAAY,EAAG,cAAe,CAAE,CAC5E,CACF,CACF,EAGwB,CAAG,ECR7B,EAAiB,SAAS,CA5GxB,GAAI,aACJ,KAAM,mBACN,SAAU,YACV,YACE,+HACF,KAAM,CAAC,YAAa,OAAQ,QAAS,WAAY,SAAS,EAC1D,UAAW,6DACX,WAA6B,CAC3B,QAAS,MACT,KAAM,CACJ,KAAM,wBACN,YAAa,wCACf,EACA,MAAO,EACP,SAAU,CACR,MAAO,IACP,gBAAiB,sBACjB,uBAAwB,kBAC1B,EACA,QAAS,CACP,EACE,aACA,aACA,CACE,EAAK,6BAA8B,CACjC,MAAO,sBACP,MAAO,SACP,WAAY,OACZ,cAAe,EACf,WAAY,GACZ,cAAe,CACjB,CAAC,EACD,EAAK,2BAA4B,CAC/B,MAAO,sBACP,MAAO,SACP,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,cAAe,EACjB,CAAC,EACD,EAAO,gBAAiB,IAAK,CAC3B,gBAAiB,mBACjB,MAAO,kBACT,CAAC,EACD,EAAO,EAAE,CACX,EACA,CAAE,gBAAiB,mBAAoB,WAAY,EAAG,cAAe,CAAE,CACzE,EACA,EAAI,qBAAsB,oBAAqB,CAC7C,EAAK,gBAAiB,CACpB,MAAO,SACP,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,WAAY,GACZ,cAAe,EACjB,CAAC,EACD,EACE,CACE,EAAQ,CACN,KAAM,iBACN,MAAO,EAAY,IAAK,IAAK,MAAM,EACnC,SAAU,MACV,WAAY,KACd,CAAC,EACD,EAAQ,CACN,KAAM,kBACN,MAAO,EAAY,IAAK,IAAK,SAAS,EACtC,SAAU,MACV,WAAY,KACd,CAAC,EACD,EAAQ,CACN,KAAM,kBACN,MAAO,EAAY,IAAK,IAAK,MAAM,EACnC,SAAU,OACV,WAAY,KACd,CAAC,CACH,EACA,CAAE,QAAS,EAAG,aAAc,GAAM,YAAa,YAAa,CAC9D,CACF,CAAC,EACD,EAAI,cAAe,YAAa,CAC9B,EAAK,6CAA8C,CACjD,MAAO,SACP,WAAY,OACZ,WAAY,GACZ,cAAe,EACjB,CAAC,EACD,EAAO,WAAY,GAAG,EACtB,EAAO,EAAE,CACX,CAAC,EACD,EACE,gBACA,SACA,CACE,EAAM,oDAAqD,CACzD,MAAO,SACP,WAAY,GACZ,cAAe,GACf,KAAM,GACR,CAAC,CACH,EACA,CAAE,gBAAiB,sBAAuB,WAAY,EAAG,cAAe,CAAE,CAC5E,CACF,CACF,EAGwB,CAAG,ECD7B,EAAiB,SAAS,CAzGxB,GAAI,iBACJ,KAAM,0BACN,SAAU,iBACV,YACE,sIACF,KAAM,CAAC,iBAAkB,WAAY,aAAc,WAAW,EAC9D,UAAW,gEACX,WAA6B,CAC3B,QAAS,MACT,KAAM,CACJ,KAAM,4BACN,YAAa,gDACf,EACA,MAAO,EACP,SAAU,CACR,MAAO,IACP,gBAAiB,sBACjB,uBAAwB,kBAC1B,EACA,QAAS,CACP,EAAI,cAAe,OAAQ,CACzB,EAAK,OAAQ,CACX,MAAO,SACP,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,cAAe,EACf,WAAY,GACZ,cAAe,EACjB,CAAC,CACH,CAAC,EACD,EAAI,YAAa,WAAY,CAC3B,EAAQ,4BAA6B,CACnC,MAAO,SACP,SAAU,GACV,WAAY,GACZ,cAAe,CACjB,CAAC,EACD,EAAM,uDAAwD,CAC5D,MAAO,SACP,cAAe,EACjB,CAAC,CACH,CAAC,EACD,EAAI,kBAAmB,aAAc,CACnC,EACE,CACE,EAAQ,CACN,KAAM,iBACN,MAAO,EAAY,IAAK,IAAK,MAAM,EACnC,SAAU,MACV,WAAY,MACZ,YAAa,8CACf,CAAC,EACD,EAAQ,CACN,KAAM,oBACN,MAAO,EAAY,IAAK,IAAK,SAAS,EACtC,WAAY,MACZ,YAAa,mCACf,CAAC,CACH,EACA,CAAE,QAAS,EAAG,aAAc,GAAM,gBAAiB,GAAM,YAAa,gBAAiB,CACzF,CACF,CAAC,EACD,EAAI,eAAgB,iBAAkB,CACpC,EAAQ,CAAE,WAAY,EAAG,cAAe,EAAG,CAAC,EAC5C,EAAK,kCAAmC,CACtC,MAAO,SACP,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,cAAe,CACjB,CAAC,EACD,EAAK,aAAc,CACjB,MAAO,SACP,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,MAAO,mBACP,cAAe,EACf,cAAe,EACjB,CAAC,EACD,EAAO,qBAAqB,EAC5B,EAAO,EAAE,CACX,CAAC,EACD,EACE,gBACA,SACA,CACE,EAAM,6BAA8B,CAClC,MAAO,SACP,WAAY,EACd,CAAC,EACD,EAAM,4BAA6B,CACjC,MAAO,SACP,WAAY,EACZ,cAAe,GACf,KAAM,GACR,CAAC,CACH,EACA,CAAE,gBAAiB,sBAAuB,WAAY,EAAG,cAAe,CAAE,CAC5E,CACF,CACF,EAGwB,CAAG,ECgB7B,EAAiB,SAAS,CAzHxB,GAAI,iBACJ,KAAM,wBACN,SAAU,iBACV,YACE,sHACF,KAAM,CAAC,SAAU,OAAQ,eAAgB,WAAW,EACpD,UAAW,2DACX,WAA6B,CAC3B,QAAS,MACT,KAAM,CACJ,KAAM,sBACN,YAAa,gDACf,EACA,MAAO,GACP,SAAU,CACR,MAAO,IACP,gBAAiB,sBACjB,uBAAwB,kBAC1B,EACA,QAAS,CACP,EACE,kBACA,kBACA,CACE,EAAM,EAAY,IAAK,IAAK,UAAU,EAAG,gBAAiB,CACxD,MAAO,IACP,WAAY,EACZ,cAAe,CACjB,CAAC,EACD,EAAK,WAAY,CACf,MAAO,SACP,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,MAAO,mBACP,cAAe,EACf,WAAY,GACZ,cAAe,CACjB,CAAC,EACD,EAAK,qCAAsC,CACzC,MAAO,SACP,MAAO,gBACP,cAAe,EACjB,CAAC,EACD,EAAO,gBAAiB,GAAG,EAC3B,EAAO,EAAE,CACX,EACA,CAAE,gBAAiB,mBAAoB,WAAY,EAAG,cAAe,CAAE,CACzE,EACA,EAAI,kBAAmB,iBAAkB,CACvC,EAAM,iBAAkB,CACtB,MAAO,SACP,cAAe,EACf,WAAY,GACZ,cAAe,CACjB,CAAC,EACD,EAAQ,mBAAoB,CAC1B,MAAO,SACP,SAAU,GACV,cAAe,EACjB,CAAC,EACD,EACE,CACE,EAAQ,CACN,KAAM,oBACN,MAAO,EAAY,IAAK,IAAK,QAAQ,EACrC,WAAY,MACd,CAAC,EACD,EAAQ,CACN,KAAM,kBACN,MAAO,EAAY,IAAK,IAAK,MAAM,EACnC,WAAY,MACd,CAAC,EACD,EAAQ,CACN,KAAM,kBACN,MAAO,EAAY,IAAK,IAAK,MAAM,EACnC,WAAY,MACd,CAAC,CACH,EACA,CAAE,QAAS,EAAG,aAAc,GAAO,YAAa,MAAO,CACzD,CACF,CAAC,EACD,EACE,mBACA,eACA,CACE,EAAK,+BAAgC,CACnC,MAAO,SACP,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,MAAO,gBACP,WAAY,GACZ,cAAe,EACjB,CAAC,EACD,EAAO,kBAAmB,GAAG,EAC7B,EAAO,EAAE,CACX,EACA,CAAE,gBAAiB,mBAAoB,WAAY,EAAG,cAAe,CAAE,CACzE,EACA,EACE,eACA,SACA,CACE,EAAM,6CAA8C,CAClD,MAAO,SACP,WAAY,EACd,CAAC,EACD,EAAM,mCAAoC,CACxC,MAAO,SACP,WAAY,EACZ,cAAe,GACf,KAAM,GACR,CAAC,CACH,EACA,CAAE,gBAAiB,sBAAuB,WAAY,EAAG,cAAe,CAAE,CAC5E,CACF,CACF,EAGwB,CAAG,ECnD7B,EAAiB,SAAS,CAvExB,GAAI,qBACJ,KAAM,4BACN,SAAU,aACV,YACE,2GACF,KAAM,CAAC,UAAW,aAAc,OAAQ,WAAW,EACnD,UAAW,0DACX,WAA6B,CAC3B,QAAS,MACT,KAAM,CACJ,KAAM,kBACN,YAAa,gDACf,EACA,MAAO,GACP,SAAU,CACR,MAAO,IACP,gBAAiB,sBACjB,uBAAwB,kBAC1B,EACA,QAAS,CACP,EAAI,cAAe,OAAQ,CACzB,EAAM,EAAY,IAAK,GAAI,MAAM,EAAG,OAAQ,CAAE,MAAO,IAAK,WAAY,EAAG,CAAC,CAC5E,CAAC,EACD,EAAI,eAAgB,UAAW,CAC7B,EAAQ,4BAA6B,CACnC,MAAO,SACP,SAAU,GACV,WAAY,EACZ,cAAe,CACjB,CAAC,EACD,EACE,2IACA,CAAE,MAAO,SAAU,cAAe,EAAG,CACvC,CACF,CAAC,EACD,EAAI,oBAAqB,YAAa,CACpC,EAAK,yBAA0B,CAAE,WAAY,OAAQ,WAAY,EAAG,cAAe,CAAE,CAAC,EACtF,EAAM,uDAAwD,CAAE,cAAe,EAAG,CAAC,EACnF,EAAQ,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,EAC3C,EAAK,6BAA8B,CAAE,WAAY,OAAQ,WAAY,EAAG,cAAe,CAAE,CAAC,EAC1F,EAAM,+CAAgD,CAAE,cAAe,EAAG,CAAC,EAC3E,EAAQ,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,EAC3C,EAAK,0BAA2B,CAAE,WAAY,OAAQ,WAAY,EAAG,cAAe,CAAE,CAAC,EACvF,EAAM,gDAAiD,CAAE,cAAe,EAAG,CAAC,CAC9E,CAAC,EACD,EAAI,UAAW,eAAgB,CAC7B,EAAO,YAAa,GAAG,EACvB,EAAO,CAAC,EACR,EAAM,sDAAuD,CAAE,MAAO,SAAU,cAAe,EAAG,CAAC,CACrG,CAAC,EACD,EACE,gBACA,SACA,CACE,EAAM,gDAAiD,CACrD,MAAO,SACP,WAAY,EACd,CAAC,EACD,EAAM,qCAAsC,CAC1C,MAAO,SACP,WAAY,EACZ,cAAe,GACf,KAAM,GACR,CAAC,CACH,EACA,CAAE,gBAAiB,sBAAuB,WAAY,EAAG,cAAe,CAAE,CAC5E,CACF,CACF,EAGwB,CAAG,ECxE7B,IAAM,GAA0B,CAC9B,GAAI,eACJ,KAAM,eACN,SAAU,QACV,YACE,kHACF,KAAM,CAAC,QAAS,SAAU,OAAQ,aAAc,QAAQ,EACxD,UAAW,iEACX,WAA6B,CAC3B,QAAS,MACT,KAAM,CACJ,KAAM,mCACN,YAAa,wEACf,EACA,MAAO,EACP,SAAU,CACR,MAAO,IACP,gBAAiB,sBACjB,uBAAwB,kBAC1B,EACA,QAAS,CACP,EAAI,cAAe,OAAQ,CACzB,EAAK,cAAe,CAClB,MAAO,SACP,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,cAAe,EACf,WAAY,GACZ,cAAe,EACjB,CAAC,CACH,CAAC,EACD,EAAI,aAAc,aAAc,CAC9B,EAAM,EAAY,IAAK,IAAK,aAAa,EAAG,cAAe,CACzD,MAAO,IACP,WAAY,EACZ,cAAe,EACjB,CAAC,EACD,EAAQ,kBAAmB,CACzB,MAAO,SACP,SAAU,GACV,WAAY,EACZ,cAAe,CACjB,CAAC,EACD,EAAM,kDAAmD,CACvD,MAAO,SACP,cAAe,EACjB,CAAC,CACH,CAAC,EACD,EACE,qBACA,gBACA,CACE,EAAK,4BAA6B,CAChC,MAAO,SACP,WAAY,OACZ,WAAY,GACZ,cAAe,CACjB,CAAC,EACD,EAAK,uBAAwB,CAAE,MAAO,SAAU,cAAe,CAAE,CAAC,EAClE,EAAK,iDAAkD,CACrD,MAAO,SACP,cAAe,EACjB,CAAC,EACD,EAAO,cAAe,GAAG,EACzB,EAAO,EAAE,CACX,EACA,CAAE,gBAAiB,sBAAuB,WAAY,EAAG,cAAe,CAAE,CAC5E,EACA,EAAI,iBAAkB,SAAU,CAC9B,EAAQ,CAAE,WAAY,GAAI,cAAe,EAAG,CAAC,EAC7C,GAAY,mBAAmB,EAC/B,GAAU,OAAQ,mCAAmC,EACrD,GAAU,QAAS,oDAAoD,EACvE,GAAU,QAAS,4BAA4B,EAC/C,GAAU,QAAS,mCAAmC,EACtD,GAAU,QAAS,qBAAqB,EACxC,EAAO,EAAE,CACX,CAAC,EACD,EACE,gBACA,SACA,CACE,EAAM,gDAAiD,CACrD,MAAO,SACP,WAAY,EACd,CAAC,EACD,EAAM,mCAAoC,CACxC,MAAO,SACP,WAAY,EACZ,cAAe,GACf,KAAM,GACR,CAAC,CACH,EACA,CAAE,gBAAiB,sBAAuB,WAAY,EAAG,cAAe,CAAE,CAC5E,CACF,CACF,EACF,EAEA,SAAS,GAAY,EAAW,CAC9B,OAAO,EAAK,EAAG,CACb,WAAY,iBACZ,MAAO,iBACP,SAAU,GACV,WAAY,OACZ,cAAe,EACf,cAAe,EACjB,CAAC,CACH,CAEA,SAAS,GAAU,EAAc,EAAe,CAC9C,OAAO,EAAK,MAAM,EAAK,WAAW,IAAS,CACzC,WAAY,EACZ,cAAe,CACjB,CAAC,CACH,CAEA,EAAiB,SAAS,EAAG,ECT7B,EAAiB,SAAS,CA9GxB,GAAI,gBACJ,KAAM,gBACN,SAAU,gBACV,YACE,qHACF,KAAM,CAAC,gBAAiB,UAAW,QAAS,cAAc,EAC1D,UAAW,kEACX,WAA6B,CAC3B,QAAS,MACT,KAAM,CACJ,KAAM,kCACN,YAAa,6CACf,EACA,MAAO,GACP,SAAU,CACR,MAAO,IACP,gBAAiB,sBACjB,uBAAwB,kBAC1B,EACA,QAAS,CACP,EAAI,cAAe,OAAQ,CACzB,EAAK,OAAQ,CACX,MAAO,SACP,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,cAAe,EACf,WAAY,GACZ,cAAe,EACjB,CAAC,CACH,CAAC,EACD,EAAI,oBAAqB,eAAgB,CACvC,EAAQ,kCAAmC,CACzC,MAAO,SACP,SAAU,GACV,WAAY,EACZ,cAAe,CACjB,CAAC,EACD,EAAM,wCAAyC,CAC7C,MAAO,SACP,cAAe,EACjB,CAAC,CACH,CAAC,EACD,EAAI,WAAY,QAAS,CACvB,EAAK,QAAS,CACZ,SAAU,GACV,cAAe,EACf,WAAY,OACZ,MAAO,iBACP,WAAY,EACZ,cAAe,EACjB,CAAC,EACD,EAAK,mCAAoC,CACvC,WAAY,OACZ,cAAe,CACjB,CAAC,EACD,EAAM,SAAU,CAAE,cAAe,EAAG,CAAC,EACrC,EAAQ,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,EAC3C,EAAK,6BAA8B,CAAE,WAAY,OAAQ,cAAe,CAAE,CAAC,EAC3E,EAAM,SAAU,CAAE,cAAe,EAAG,CAAC,EACrC,EAAQ,CAAE,WAAY,EAAG,cAAe,EAAG,CAAC,EAC5C,EAAK,oBAAqB,CAAE,MAAO,QAAS,cAAe,CAAE,CAAC,EAC9D,EAAK,mBAAoB,CAAE,MAAO,QAAS,cAAe,CAAE,CAAC,EAC7D,EAAK,wBAAyB,CAC5B,MAAO,QACP,SAAU,GACV,cAAe,EACjB,CAAC,CACH,CAAC,EACD,EACE,cACA,mBACA,CACE,EAAK,cAAe,CAClB,SAAU,GACV,cAAe,EACf,WAAY,OACZ,MAAO,iBACP,WAAY,GACZ,cAAe,CACjB,CAAC,EACD,EAAK,uDAAwD,CAC3D,cAAe,EACjB,CAAC,EACD,EAAO,iBAAkB,GAAG,EAC5B,EAAO,EAAE,CACX,EACA,CAAE,gBAAiB,sBAAuB,WAAY,EAAG,cAAe,CAAE,CAC5E,EACA,EACE,cACA,OACA,CACE,EAAM,6CAA8C,CAClD,MAAO,SACP,WAAY,EACd,CAAC,EACD,EAAM,wBAAyB,CAC7B,MAAO,SACP,WAAY,EACZ,cAAe,GACf,KAAM,GACR,CAAC,CACH,EACA,CAAE,gBAAiB,sBAAuB,WAAY,EAAG,cAAe,CAAE,CAC5E,CACF,CACF,EAGwB,CAAG,EC9G7B,IAAM,GAA0B,CAC9B,GAAI,cACJ,KAAM,2BACN,SAAU,aACV,YACE,sHACF,KAAM,CAAC,OAAQ,SAAU,aAAc,OAAO,EAC9C,UAAW,8DACX,WAA6B,CAC3B,QAAS,MACT,KAAM,CACJ,KAAM,wBACN,YAAa,mEACf,EACA,MAAO,EACP,SAAU,CACR,MAAO,IACP,gBAAiB,sBACjB,uBAAwB,kBAC1B,EACA,QAAS,CACP,EAAI,qBAAsB,qBAAsB,CAC9C,EAAK,aAAc,CACjB,MAAO,SACP,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,cAAe,EACf,WAAY,GACZ,cAAe,CACjB,CAAC,EACD,EAAM,4BAA6B,CAAE,MAAO,SAAU,cAAe,EAAG,CAAC,EACzE,EAAQ,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,CAC7C,CAAC,EACD,GACE,wDACA,mFACA,yBACA,EAAY,IAAK,IAAK,QAAQ,CAChC,EACA,GACE,iCACA,mFACA,0BACA,EAAY,IAAK,IAAK,QAAQ,CAChC,EACA,GACE,iCACA,gFACA,wBACA,EAAY,IAAK,IAAK,QAAQ,CAChC,EACA,EACE,gBACA,SACA,CACE,EAAM,kCAAmC,CACvC,MAAO,SACP,WAAY,EACd,CAAC,EACD,EAAM,6CAA8C,CAClD,MAAO,SACP,WAAY,EACZ,cAAe,GACf,KAAM,GACR,CAAC,CACH,EACA,CAAE,gBAAiB,sBAAuB,WAAY,EAAG,cAAe,CAAE,CAC5E,CACF,CACF,EACF,EAEA,SAAS,GAAK,EAAe,EAAa,EAAgB,EAAa,CACrE,OAAO,EAAI,eAAgB,OAAQ,CACjC,EAAM,EAAK,EAAO,CAAE,MAAO,IAAK,WAAY,GAAI,cAAe,EAAG,CAAC,EACnE,EAAQ,EAAO,CAAE,SAAU,GAAI,cAAe,CAAE,CAAC,EACjD,EAAK,EAAK,CAAE,cAAe,CAAE,CAAC,EAC9B,EAAM,EAAQ,CAAE,cAAe,CAAE,CAAC,EAClC,EAAK,uBAAwB,CAC3B,MAAO,mBACP,WAAY,OACZ,KAAM,IACN,WAAY,EACZ,cAAe,CACjB,CAAC,EACD,EAAO,CAAC,CACV,CAAC,CACH,CAEA,EAAiB,SAAS,EAAG,ECzF7B,SAAgB,GAAe,CAAE,OAAM,WAAkB,CACvD,IAAM,EAAe,EAAe,GAAM,EAAE,YAAY,EAClD,EAAa,EAAe,GAAM,EAAE,IAAI,QAAQ,OAAS,CAAC,EAE1D,CAAC,EAAU,IAAA,EAAA,EAAA,SAAA,CAAkD,KAAK,EAClE,CAAC,EAAO,IAAA,EAAA,EAAA,SAAA,CAAqB,EAAE,GAErC,EAAA,EAAA,UAAA,KAAgB,CACd,GAAI,CAAC,EAAM,OACX,IAAM,EAAS,GAAqB,CAC9B,EAAE,MAAQ,UAAU,EAAQ,CAClC,EAEA,OADA,OAAO,iBAAiB,UAAW,CAAK,MAC3B,OAAO,oBAAoB,UAAW,CAAK,CAC1D,EAAG,CAAC,EAAM,CAAO,CAAC,EAElB,IAAM,GAAA,EAAA,EAAA,QAAA,KAAoB,EAAiB,KAAK,EAAG,CAAC,CAAI,CAAC,EAEnD,GAAA,EAAA,EAAA,QAAA,KAAyB,CAC7B,IAAI,EAAO,EAEX,GADI,IAAa,QAAO,EAAO,EAAK,OAAQ,GAAM,EAAE,WAAa,CAAQ,GACrE,EAAM,KAAK,EAAG,CAChB,IAAM,EAAI,EAAM,YAAY,EAC5B,EAAO,EAAK,OACT,GACC,EAAE,KAAK,YAAY,CAAC,CAAC,SAAS,CAAC,GAC/B,EAAE,YAAY,YAAY,CAAC,CAAC,SAAS,CAAC,IACrC,EAAE,MAAQ,CAAC,EAAA,CAAG,KAAM,GAAQ,EAAI,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC,CAC9D,CACF,CACA,OAAO,CACT,EAAG,CAAC,EAAK,EAAU,CAAK,CAAC,EAEzB,GAAI,CAAC,EAAM,OAAO,KAElB,IAAM,EAAc,GAA4B,CAE5C,GACA,CAAC,OAAO,QACN,YAAY,EAAI,KAAK,6CACvB,IAIF,EAAa,CAAG,EAChB,EAAQ,EACV,EAEM,EAAsE,CAC1E,CAAE,IAAK,MAAO,MAAO,eAAgB,EACrC,GAAI,OAAO,QAAQ,EAAwB,CAAC,CAEzC,KAAK,CAAC,EAAK,MAAY,CAAE,MAAK,OAAM,EAAE,CAC3C,EAEA,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,iEACb,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,4GAAf,EAEE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,mFAAf,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAU,kDAAyC,uBAEnD,CAAA,GACJ,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAU,oCAA2B,gDAErC,CAAA,CACA,CAAA,CAAA,GACL,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,QAAS,EACT,UAAU,8EACV,aAAW,kBAEX,EAAA,EAAA,IAAA,CAAC,EAAA,EAAD,CAAG,KAAM,EAAK,CAAA,CACR,CAAA,CACL,KAEL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,uCAAf,EAEE,EAAA,EAAA,KAAA,CAAC,QAAD,CAAO,UAAU,uFAAjB,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,yBAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAA,OAAD,CACE,KAAM,GACN,UAAU,iFACX,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,QAAD,CACE,MAAO,EACP,SAAW,GAAM,EAAS,EAAE,OAAO,KAAK,EACxC,YAAY,UACZ,UAAU,qHACX,CAAA,CACE,KACL,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAU,uBACX,EAAW,IAAK,IAGb,EAAA,EAAA,IAAA,CAAC,KAAD,CAAA,UACE,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,YAAe,EAAY,EAAE,GAAG,EAChC,UACE,uEANO,EAAE,MAAQ,EAQb,4BACA,kDAGL,EAAE,KACG,CAAA,CACN,EAZK,EAAE,GAYP,CAEP,CACC,CAAA,CACC,KAGP,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,sCACb,EAAS,SAAW,GACnB,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,mEAA0D,qBAEpE,CAAA,GAEL,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,+EACZ,EAAS,IAAK,IACb,EAAA,EAAA,IAAA,CAAC,GAAD,CAEE,IAAK,EACL,WAAc,EAAW,CAAC,CAC3B,EAHM,EAAE,EAGR,CACF,CACE,CAAA,CAEH,CAAA,CACH,GACF,GACF,CAAA,CAET,CAEA,SAAS,GAAa,CACpB,MACA,UAIC,CACD,OACE,EAAA,EAAA,KAAA,CAAC,SAAD,CACE,QAAS,EACT,UAAU,kLAFZ,EAIE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,4DACZ,EAAI,WACH,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,IAAK,EAAI,UACT,IAAK,EAAI,KACT,UAAU,gEACX,CAAA,GAED,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,mEAA0D,YAEpE,CAAA,CAEJ,CAAA,GACL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,mCAAf,EACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,6DACZ,GAAyB,EAAI,SAC3B,CAAA,GACL,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,+DACZ,EAAI,IACF,CAAA,GACL,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,iDACZ,EAAI,WACF,CAAA,CACF,GACC,GAEZ,CC1LA,SAAgB,IAAS,CACvB,GAAM,CAAE,MAAK,aAAY,OAAM,OAAM,OAAM,SAAQ,aAAY,aAAY,aAAY,qBAAoB,WAAU,cAAa,iBAChI,EAAc,EACV,GAAA,EAAA,EAAA,OAAA,CAAmC,IAAI,EACvC,CAAC,EAAY,IAAA,EAAA,EAAA,SAAA,CAA0B,EAAK,EAC5C,CAAC,EAAe,IAAA,EAAA,EAAA,SAAA,CAA6B,EAAK,EAElD,MAAoB,CACpB,EAAI,QAAQ,SAAW,GACvB,OAAO,QAAQ,uDAAuD,GACxE,EAAc,CAElB,EAEM,GAAgB,EAAkB,EAAiB,IAAiB,CACxE,IAAM,EAAO,IAAI,KAAK,CAAC,CAAO,EAAG,CAAE,MAAK,CAAC,EACnC,EAAM,IAAI,gBAAgB,CAAI,EAC9B,EAAI,SAAS,cAAc,GAAG,EACpC,EAAE,KAAO,EACT,EAAE,SAAW,EACb,EAAE,MAAM,EACR,IAAI,gBAAgB,CAAG,CACzB,EAgCA,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,wFAAf,EACE,EAAA,EAAA,IAAA,CAAC,QAAD,CACE,UAAU,4FACV,MAAO,EAAI,KAAK,KAChB,SAAW,GAAM,EAAW,CAAE,KAAM,EAAE,OAAO,KAAM,CAAC,CACrD,CAAA,GACD,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,2CAAf,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,mEAAf,EACE,EAAA,EAAA,KAAA,CAAC,SAAD,CACE,MAAM,kBACN,YAAe,EAAY,SAAS,EACpC,UAAW,uEACT,IAAa,UAAY,gCAAkC,+CAJ/D,EAOE,EAAA,EAAA,IAAA,CAAC,EAAA,QAAD,CAAS,KAAM,EAAK,CAAA,EAAC,UACf,KACR,EAAA,EAAA,KAAA,CAAC,SAAD,CACE,MAAM,iBACN,YAAe,EAAY,QAAQ,EACnC,UAAW,uEACT,IAAa,SAAW,gCAAkC,+CAJ9D,EAOE,EAAA,EAAA,IAAA,CAAC,EAAA,WAAD,CAAY,KAAM,EAAK,CAAA,EAAC,SAClB,GACL,KACL,EAAA,EAAA,KAAA,CAAC,GAAD,CAAY,MAAM,mBAAmB,YAAe,EAAiB,EAAI,WAAzE,EACE,EAAA,EAAA,IAAA,CAAC,EAAA,eAAD,CAAgB,KAAM,EAAK,CAAA,EAAC,YAClB,KACZ,EAAA,EAAA,KAAA,CAAC,GAAD,CAAY,MAAM,eAAe,QAAS,EAAa,SAAU,EAAI,QAAQ,SAAW,WAAxF,EACE,EAAA,EAAA,IAAA,CAAC,EAAA,UAAD,CAAW,KAAM,EAAK,CAAA,EAAC,QACb,KACZ,EAAA,EAAA,IAAA,CAAC,GAAD,CAAU,CAAA,GACV,EAAA,EAAA,IAAA,CAAC,GAAD,CAAY,MAAM,OAAO,QAAS,EAAM,SAAU,EAAK,SAAW,YAChE,EAAA,EAAA,IAAA,CAAC,EAAA,MAAD,CAAO,KAAM,EAAK,CAAA,CACR,CAAA,GACZ,EAAA,EAAA,IAAA,CAAC,GAAD,CAAY,MAAM,OAAO,QAAS,EAAM,SAAU,EAAO,SAAW,YAClE,EAAA,EAAA,IAAA,CAAC,EAAA,MAAD,CAAO,KAAM,EAAK,CAAA,CACR,CAAA,GACZ,EAAA,EAAA,IAAA,CAAC,GAAD,CAAU,CAAA,GACV,EAAA,EAAA,IAAA,CAAC,GAAD,CAAY,MAAM,qBAAqB,QAAS,YAC9C,EAAA,EAAA,IAAA,CAAC,EAAA,KAAD,CAAM,KAAM,EAAK,CAAA,CACP,CAAA,GACZ,EAAA,EAAA,KAAA,CAAC,GAAD,CAAY,MAAM,UAAU,YAxDN,CAC1B,IAAM,EAAO,EAAW,EAClB,EAAI,OAAO,KAAK,GAAI,QAAQ,EAC9B,IACF,EAAE,SAAS,MAAM,CAAI,EACrB,EAAE,SAAS,MAAM,GAEnB,EAAc,EAAI,EAClB,eAAiB,EAAc,EAAK,EAAG,GAAG,CAC5C,WA+CM,EACE,EAAA,EAAA,IAAA,CAAC,EAAA,IAAD,CAAK,KAAM,EAAK,CAAA,EAAC,IAAE,EAAa,SAAW,SACjC,KACZ,EAAA,EAAA,IAAA,CAAC,GAAD,CAAU,CAAA,GACV,EAAA,EAAA,KAAA,CAAC,GAAD,CAAY,MAAM,cAAc,YAAe,EAAQ,SAAS,MAAM,WAAtE,EACE,EAAA,EAAA,IAAA,CAAC,EAAA,OAAD,CAAQ,KAAM,EAAK,CAAA,EAAC,SACV,KACZ,EAAA,EAAA,IAAA,CAAC,QAAD,CAAO,IAAK,EAAS,KAAK,OAAO,OAAO,QAAQ,OAAA,GAAO,SAzEvC,GAA2C,CAC/D,IAAM,EAAO,EAAE,OAAO,QAAQ,GACzB,IACL,EAAK,KAAK,CAAC,CAAC,KAAM,GAAS,CACzB,IAAM,EAAI,EAAW,CAAI,EACpB,EAAE,IAAI,MAAM,kBAAkB,EAAE,OAAO,CAC9C,CAAC,EACD,EAAE,OAAO,MAAQ,GACnB,CAiEsF,CAAA,GAChF,EAAA,EAAA,KAAA,CAAC,GAAD,CAAY,MAAM,cAAc,YA9EP,CAC7B,EAAa,GAAG,EAAI,KAAK,MAAQ,QAAQ,OAAQ,EAAW,EAAG,kBAAkB,CACnF,WA4EM,EACE,EAAA,EAAA,IAAA,CAAC,EAAA,SAAD,CAAU,KAAM,EAAK,CAAA,EAAC,OACZ,KACZ,EAAA,EAAA,KAAA,CAAC,GAAD,CAAY,MAAM,cAAc,YAtFP,CAC7B,IAAM,EAAO,EAAW,EACxB,EAAa,GAAG,EAAI,KAAK,MAAQ,QAAQ,OAAQ,EAAM,WAAW,CACpE,EAmFiE,QAAA,YAA3D,EACE,EAAA,EAAA,IAAA,CAAC,EAAA,SAAD,CAAU,KAAM,EAAK,CAAA,EAAC,cACZ,GACT,KACL,EAAA,EAAA,IAAA,CAAC,GAAD,CAAgB,KAAM,EAAe,YAAe,EAAiB,EAAK,CAAI,CAAA,CAC3E,GAET,CAEA,SAAS,GAAW,CAClB,WACA,UACA,WACA,QACA,WAOC,CACD,OACE,EAAA,EAAA,IAAA,CAAC,SAAD,CACS,QACG,WACD,UACT,UAAW,6EACT,EACI,gEACA,yFAGL,UACK,CAAA,CAEZ,CAEA,SAAS,IAAU,CACjB,OAAO,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,2BAA6B,CAAA,CACrD,CC5GA,IAAa,GAAiB,IAAI,KApBb,CACnB,QAAkB,IAAI,IAEtB,SAAS,EAAuB,CAC9B,KAAK,QAAQ,IAAI,EAAI,KAAM,CAAG,CAChC,CAEA,IAAI,EAA4C,CAC9C,OAAO,KAAK,QAAQ,IAAI,CAAI,CAC9B,CAEA,MAA2B,CACzB,OAAO,MAAM,KAAK,KAAK,QAAQ,OAAO,CAAC,CACzC,CAEA,WAAW,EAA8C,CACvD,OAAO,KAAK,KAAK,CAAC,CAAC,OAAQ,GAAM,EAAE,WAAa,CAAQ,CAC1D,CACF,EAIa,GAAkD,CAC7D,MAAO,QACP,KAAM,OACN,OAAQ,SACR,QAAS,UACT,QAAS,UACT,eAAgB,iBAChB,UAAW,YACX,cAAe,gBACf,OAAQ,SACR,OAAQ,QACV,ECyDa,GAAkB,IAAI,KA1Eb,CACpB,UAAoB,IAAI,IAExB,MAA+B,CAAC,EAChC,UAAoB,IAAI,IACxB,QAAkB,EAGlB,gBAAgB,EAAwB,CAElC,KAAK,UAAU,IAAI,EAAI,EAAE,GAAG,KAAK,cAAc,EAAI,GAAI,EAAK,EAChE,KAAK,UAAU,IAAI,EAAI,GAAI,CAAG,EAC9B,IAAK,IAAM,KAAQ,EAAI,MACrB,KAAK,MAAM,KAAK,CAAE,GAAG,EAAM,UAAW,EAAI,GAAI,MAAO,EAAI,KAAM,CAAC,EAElE,KAAK,KAAK,CACZ,CAGA,aAAa,EAAmB,EAAwB,EAAgB,CACjE,KAAK,UAAU,IAAI,CAAS,GAC/B,KAAK,UAAU,IAAI,EAAW,CAAE,GAAI,EAAW,KAAM,EAAW,MAAO,CAAC,CAAE,CAAC,EAE7E,IAAM,EAAU,KAAK,UAAU,IAAI,CAAS,EAC5C,EAAQ,MAAM,KAAK,CAAI,EACvB,KAAK,MAAM,KAAK,CAAE,GAAG,EAAM,YAAW,MAAO,GAAS,EAAQ,KAAM,CAAC,EACrE,KAAK,KAAK,CACZ,CAGA,cAAc,EAAmB,EAAO,GAAM,CAC5C,KAAK,UAAU,OAAO,CAAS,EAC/B,KAAK,MAAQ,KAAK,MAAM,OAAQ,GAAM,EAAE,YAAc,CAAS,EAC3D,GAAM,KAAK,KAAK,CACtB,CAGA,MAAsB,CACpB,OAAO,KAAK,KACd,CAGA,WAAW,EAAyC,CAClD,OAAO,KAAK,MAAM,OAAQ,GAAM,EAAE,WAAa,CAAQ,CACzD,CAGA,eAAqC,CACnC,OAAO,MAAM,KAAK,KAAK,UAAU,OAAO,CAAC,CAC3C,CAGA,IAAI,EAAuC,CACzC,OAAO,KAAK,MAAM,KAAM,GAAM,EAAE,OAAS,CAAI,CAC/C,CAIA,UAAa,IACX,KAAK,UAAU,IAAI,CAAQ,MACd,CACX,KAAK,UAAU,OAAO,CAAQ,CAChC,GAIF,gBAA4B,KAAK,QAEjC,MAAe,CACb,KAAK,SAAW,EAChB,IAAK,IAAM,KAAK,KAAK,UAAW,EAAE,CACpC,CACF,ECxGI,GAA8B,KAC5B,GAAY,IAAI,IAClB,GAAU,EAEd,SAAS,IAAO,CACd,IAAW,EACX,IAAK,IAAM,KAAK,GAAW,EAAE,CAC/B,CAGA,SAAgB,GAAc,EAAyB,CACjD,KAAa,IACjB,GAAW,EACX,GAAK,EACP,CAGA,SAAgB,IAAmC,CACjD,OAAO,EACT,CAGA,IAAa,GAAuB,IAClC,GAAU,IAAI,CAAQ,MACT,CACX,GAAU,OAAO,CAAQ,CAC3B,GAIW,OAAqC,GCZlD,SAAgB,IAA+B,CAC7C,IAAM,EAAiC,GAAgB,KAAK,CAAC,CAAC,IAAK,IAAS,CAC1E,KAAM,EAAI,KACV,SAAU,EAAI,SACd,KAAM,EAAI,KACV,YAAa,EAAI,YACjB,KAAM,EAAI,MAAQ,CAAC,EACnB,OAAQ,UACR,OAAQ,EAAI,OAAO,CACrB,EAAE,EAEI,EAAe,IAAI,IAAI,EAAe,IAAK,GAAM,EAAE,IAAI,CAAC,EAExD,EAAgC,GACnC,KAAK,CAAC,CACN,OAAQ,GAAQ,CAAC,EAAa,IAAI,EAAI,IAAI,CAAC,CAAC,CAC5C,IAAK,IAAS,CACb,KAAM,EAAI,KACV,SAAU,EAAI,SACd,KAAM,EAAI,KACV,YAAa,EAAI,YACjB,KAAM,EAAI,MAAQ,CAAC,EACnB,OAAQ,SACR,OAAQ,EAAI,OAAO,CACrB,EAAE,EAEJ,MAAO,CAAC,GAAG,EAAgB,GAAG,CAAa,CAC7C,CCdA,SAAgB,GACd,EACA,EACe,CACf,IAAI,EAAO,EACX,IAAK,IAAM,KAAK,EACd,EAAO,GAAc,EAAM,CAAC,EAE9B,OAAO,CACT,CAEA,SAAS,GAAc,EAAoB,EAAiC,CAC1E,OAAQ,EAAO,KAAf,CACE,IAAK,cACH,MAAO,CAAE,GAAG,EAAK,KAAM,CAAE,GAAG,EAAI,KAAM,GAAG,EAAO,KAAM,CAAE,EAC1D,IAAK,kBACH,MAAO,CAAE,GAAG,EAAK,SAAU,CAAE,GAAG,EAAI,SAAU,GAAG,EAAO,KAAM,CAAE,EAClE,IAAK,cACH,MAAO,CAAE,GAAG,EAAK,MAAO,EAAO,KAAM,EACvC,IAAK,gBAAiB,CACpB,IAAM,EAAM,EAAO,OAAS,EAAI,QAAQ,OAClC,EAAU,CAAC,GAAG,EAAI,OAAO,EAE/B,OADA,EAAQ,OAAO,EAAK,EAAG,EAAO,MAAM,EAC7B,CAAE,GAAG,EAAK,SAAQ,CAC3B,CACA,IAAK,gBACH,MAAO,CAAE,GAAG,EAAK,QAAS,EAAI,QAAQ,OAAQ,GAAM,EAAE,KAAO,EAAO,QAAQ,CAAE,EAChF,IAAK,gBACH,MAAO,CACL,GAAG,EACH,QAAS,EAAI,QAAQ,IAAK,GACxB,EAAE,KAAO,EAAO,SAAW,CAAE,GAAG,EAAG,GAAG,EAAO,KAAM,EAAI,CACzD,CACF,EACF,IAAK,iBACH,MAAO,CACL,GAAG,EACH,QAAS,EAAI,QAAQ,IAAK,GACpB,EAAE,KAAO,EAAO,SACb,CACL,GAAG,EACH,SAAU,EAAE,SAAS,IAAK,GACxB,EAAE,KAAO,EAAO,UAAa,CAAE,GAAG,EAAG,GAAG,EAAO,KAAM,EAAiB,CACxE,CACF,EANqC,CAOtC,CACH,CACJ,CACF,CAGA,SAAgB,GAAmB,EAEF,CAC/B,IAAM,EAAS,EAAe,UAAU,CAAG,EAE3C,OADI,EAAO,QAAgB,CAAE,GAAI,GAAM,SAAU,EAAO,IAAsB,EACvE,CAAE,GAAI,GAAO,MAAO,EAAO,MAAM,OAAQ,CAClD,CAGA,IAAa,GAA6B,CACxC,MAAM,SAAS,EAAK,CAUlB,OATI,EAAI,OAAS,gBAAkB,EAAI,YAC9B,CAAE,KAAM,gBAAgB,EAAI,aAAc,EAE/C,EAAI,OAAS,mBACR,CAAE,KAAM,+BAAgC,EAE7C,EAAI,OAAS,mBACR,CAAE,KAAM,8CAA+C,EAEzD,CAAE,QAAS,CAAC,CAAE,CACvB,CACF,EClGA,SAAS,GAAY,EAAa,CAChC,OAAO,KAAK,MAAM,KAAK,UAAU,CAAK,CAAC,CACzC,CAGA,SAAS,GAAa,EAA+B,CACnD,IAAM,EAAQ,GAAS,CAAG,EAC1B,MAAO,CACL,GAAG,EACH,GAAI,EAAI,QAAQ,EAChB,UAAW,EAAM,UAAY,CAAC,EAAA,CAAG,IAAK,IAAO,CAAE,GAAG,EAAG,GAAI,EAAI,IAAI,CAAE,EAAE,CACvE,CACF,CAMA,SAAS,GAAiB,EAAiC,CACzD,OAAO,EAAQ,IAAK,GAClB,EAAE,OAAS,gBAAkB,CAAE,GAAG,EAAG,OAAQ,GAAa,EAAE,MAAM,CAAE,EAAI,CAC1E,CACF,CAcA,SAAgB,GACd,EACA,EACkE,CAElE,GAAI,EAAI,SAAU,CAChB,IAAM,EAAY,GAAmB,GAAS,EAAI,QAAQ,CAAC,EAE3D,OADK,EAAU,GACR,CACL,GAAI,GACJ,OAAQ,CACN,SAAU,EAAU,SACpB,KAAM,EAAI,KACV,QAAS,uDACX,CACF,EAR0B,CAAE,GAAI,GAAO,MAAO,EAAU,KAAM,CAShE,CAGA,GAAI,EAAI,SAAW,EAAI,QAAQ,OAAS,EAAG,CAEzC,IAAM,EAAY,GAAmB,GADxB,GAAe,EAAK,GAAiB,EAAI,OAAO,CACf,CAAI,CAAC,EAEnD,OADK,EAAU,GACR,CACL,GAAI,GACJ,OAAQ,CACN,SAAU,EAAU,SACpB,KAAM,EAAI,KACV,QAAS,GAAiB,EAAI,OAAO,CACvC,CACF,EAR0B,CAAE,GAAI,GAAO,MAAO,EAAU,KAAM,CAShE,CAGA,MAAO,CACL,GAAI,GACJ,OAAQ,CACN,SAAU,EACV,KAAM,EAAI,KACV,QAAS,EAAI,KAAO,GAAK,4BAC3B,CACF,CACF,CAEA,SAAS,GAAiB,EAA6B,CACrD,IAAM,EAAiC,CAAC,EACxC,IAAK,IAAM,KAAK,EAAS,EAAO,EAAE,OAAS,EAAO,EAAE,OAAS,GAAK,EAClE,IAAM,EAAgC,CACpC,cAAe,cACf,cAAe,gBACf,cAAe,gBACf,eAAgB,iBAChB,YAAa,eACb,gBAAiB,mBACjB,YAAa,eACf,EACM,EAAQ,OAAO,QAAQ,CAAM,CAAC,CAAC,KAAK,CAAC,EAAM,KAAO,CACtD,IAAM,EAAO,EAAM,IAAS,EAC5B,OAAO,EAAI,EAAI,GAAG,EAAE,GAAG,EAAK,GAAK,CACnC,CAAC,EACD,OAAO,EAAM,OAAS,YAAY,EAAM,KAAK,IAAI,EAAE,GAAK,qBAC1D,CCnGA,IAAM,GAAc,CAClB,6CACA,sDACA,wDACF,EAGA,SAAgB,IAA0B,CAGxC,OADA,EAAA,EAAA,qBAAA,CAAqB,GAAqB,GAAsB,EAAoB,EAC7E,GAAc,IAAM,IAC7B,CAEA,SAAgB,IAAc,CAC5B,GAAM,CAAE,MAAK,YAAa,EAAc,EAClC,CAAC,EAAU,IAAA,EAAA,EAAA,SAAA,CAAuC,CAAC,CAAC,EACpD,CAAC,EAAO,IAAA,EAAA,EAAA,SAAA,CAAqB,EAAE,EAC/B,CAAC,EAAM,IAAA,EAAA,EAAA,SAAA,CAAoB,EAAK,EAChC,GAAA,EAAA,EAAA,OAAA,CAAiC,IAAI,GAE3C,EAAA,EAAA,UAAA,KAAgB,CACd,EAAQ,SAAS,SAAS,CAAE,IAAK,EAAQ,QAAQ,YAAa,CAAC,CACjE,EAAG,CAAC,EAAU,CAAI,CAAC,EAEnB,IAAM,EAAO,KAAO,IAAmB,CACrC,IAAM,EAAW,GAAc,EAC/B,GAAI,CAAC,GAAY,CAAC,EAAO,KAAK,GAAK,EAAM,OACzC,IAAM,EAAuB,CAAE,GAAI,OAAO,WAAW,EAAG,KAAM,OAAQ,KAAM,CAAO,EACnF,EAAa,GAAM,CAAC,GAAG,EAAG,CAAO,CAAC,EAClC,EAAS,EAAE,EACX,EAAQ,EAAI,EAEZ,IAAM,EAAiB,CACrB,KAAM,eACN,SAAU,EACV,YAAa,EACb,QAAS,CAAE,QAAS,GAAa,CAAE,CACrC,EAEA,GAAI,CACF,IAAM,EAAM,MAAM,EAAS,SAAS,CAAG,EACjC,EAAU,GAAgB,EAAK,CAAG,EACxC,GAAI,CAAC,EAAQ,GACX,EAAc,gDAAgD,EAAQ,MAAM,GAAI,EAAI,MAC/E,CACL,GAAM,CAAE,WAAU,OAAM,WAAY,EAAQ,OACxC,IAAa,GAAK,EAAS,CAAQ,EACvC,EAAc,CAAC,EAAM,CAAO,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK;;CAAM,GAAK,OAAO,CACvE,CACF,OAAS,EAAK,CACZ,EAAe,EAAc,SAAW,yBAA0B,EAAI,CACxE,QAAU,CACR,EAAQ,EAAK,CACf,CACF,EAEM,GAAiB,EAAc,EAAQ,KAC3C,EAAa,GAAM,CAAC,GAAG,EAAG,CAAE,GAAI,OAAO,WAAW,EAAG,KAAM,YAAa,OAAM,OAAM,CAAC,CAAC,EAExF,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,gCAAf,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,wCAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAA,SAAD,CAAU,KAAM,GAAI,UAAU,eAAiB,CAAA,GAC/C,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAU,uEAA8D,cAExE,CAAA,CACD,KAEL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,IAAK,EAAS,UAAU,2DAA7B,CACG,EAAS,SAAW,IACnB,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,iCAAf,EACE,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAU,gBAAO,6EAEjB,CAAA,GACH,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,iCACZ,GAAY,IAAK,IAChB,EAAA,EAAA,IAAA,CAAC,SAAD,CAEE,YAAe,EAAK,CAAC,EACrB,UAAU,0IAET,CACK,EALD,CAKC,CACT,CACE,CAAA,CACF,IAEN,EAAS,IAAK,IACb,EAAA,EAAA,KAAA,CAAC,MAAD,CAEE,UAAW,oDACT,EAAE,OAAS,OACP,8CACA,EAAE,MACF,sEACA,8DAPR,CAUG,EAAE,QACD,EAAA,EAAA,IAAA,CAAC,EAAA,cAAD,CAAe,KAAM,GAAI,UAAU,sBAAsB,cAAA,EAAa,CAAA,EAEvE,EAAE,IACA,GAbE,EAAE,EAaJ,CACN,EACA,IACC,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,sEAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAA,QAAD,CAAS,KAAM,GAAI,UAAU,cAAgB,CAAA,EAAC,YAC3C,GAEJ,KAEL,EAAA,EAAA,KAAA,CAAC,OAAD,CACE,UAAU,8BACV,SAAW,GAAM,CACf,EAAE,eAAe,EACjB,EAAK,CAAK,CACZ,WALF,EAOE,EAAA,EAAA,IAAA,CAAC,WAAD,CACE,MAAO,EACP,SAAW,GAAM,EAAS,EAAE,OAAO,KAAK,EACxC,UAAY,GAAM,CACZ,EAAE,MAAQ,SAAW,CAAC,EAAE,WAC1B,EAAE,eAAe,EACjB,EAAK,CAAK,EAEd,EACA,KAAM,EACN,YAAY,0CACZ,UAAU,0GACX,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,KAAK,SACL,SAAU,GAAQ,CAAC,EAAM,KAAK,EAC9B,MAAM,OACN,UAAU,qFAET,GAAO,EAAA,EAAA,IAAA,CAAC,EAAA,QAAD,CAAS,KAAM,GAAI,UAAU,cAAgB,CAAA,GAAI,EAAA,EAAA,IAAA,CAAC,EAAA,KAAD,CAAM,KAAM,EAAK,CAAA,CACpE,CAAA,CACJ,GACH,GAET,CClIA,IAAM,GAAqF,CACzF,CAAE,GAAI,QAAS,KAAM,EAAA,MAAO,EAC5B,CAAE,GAAI,OAAQ,KAAM,EAAA,IAAK,EACzB,CAAE,GAAI,SAAU,KAAM,EAAA,cAAe,EACrC,CAAE,GAAI,UAAW,KAAM,EAAA,IAAK,EAC5B,CAAE,GAAI,UAAW,KAAM,EAAA,IAAK,EAC5B,CAAE,GAAI,iBAAkB,KAAM,EAAA,iBAAkB,EAChD,CAAE,GAAI,YAAa,KAAM,EAAA,YAAa,EACtC,CAAE,GAAI,gBAAiB,KAAM,EAAA,OAAQ,EACrC,CAAE,GAAI,SAAU,KAAM,EAAA,MAAO,EAC7B,CAAE,GAAI,SAAU,KAAM,EAAA,uBAAwB,CAChD,EAEA,SAAgB,IAAc,CAC5B,GAAM,CAAC,EAAQ,IAAA,EAAA,EAAA,SAAA,CAEb,QAAQ,EACJ,CAAE,YAAW,SAAQ,aAAY,OAAQ,EAAc,EACvD,EAAc,GAAe,GAGnC,EAAA,EAAA,qBAAA,CACE,GAAgB,UAChB,GAAgB,YAChB,GAAgB,WAClB,EAEA,IAAM,EAAa,GAAgB,KAAK,CAAC,CAAC,OAAS,EAEnD,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,kEAAf,EAEE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,+FAAf,CACG,IACC,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,GAAG,KACH,MAAM,KACN,KAAM,EAAA,SACN,OAAQ,IAAW,KACnB,YAAe,EAAU,IAAI,EAC7B,OAAA,EACD,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,4BAA8B,CAAA,CAC7C,CAAA,CAAA,GAEJ,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,GAAG,SACH,MAAM,SACN,KAAM,EAAA,OACN,OAAQ,IAAW,SACnB,YAAe,EAAU,QAAQ,CAClC,CAAA,EACA,IACC,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,GAAG,UACH,MAAM,UACN,KAAM,EAAA,OACN,OAAQ,IAAW,UACnB,YAAe,EAAU,SAAS,CACnC,CAAA,GAEH,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,4BAA8B,CAAA,EAC5C,GAAW,IAAK,IACf,EAAA,EAAA,IAAA,CAAC,GAAD,CAEE,GAAI,EAAE,GACN,MAAO,GAAgB,EAAE,IACzB,KAAM,EAAE,KACR,OAAQ,IAAW,EAAE,GACrB,YAAe,EAAU,EAAE,EAAE,CAC9B,EANM,EAAE,EAMR,CACF,GACD,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,oBACb,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,GAAG,SACH,MAAM,SACN,KAAM,EAAA,QACN,OAAQ,IAAW,SACnB,YAAe,EAAU,QAAQ,CAClC,CAAA,CACE,CAAA,CACF,KAGL,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,oCACZ,IAAW,UACV,EAAA,EAAA,IAAA,CAAC,GAAD,CAAc,CAAA,EACZ,IAAW,MACb,EAAA,EAAA,IAAA,CAAC,GAAD,CAAc,CAAA,EACZ,IAAW,WACb,EAAA,EAAA,IAAA,CAAC,GAAD,CAAc,MAAQ,GAAS,EAAU,EAAK,OAAO,CAAC,CAAI,CAAA,EACxD,IAAW,UACb,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAU,4EAAmE,QAE7E,CAAA,GACJ,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,+BACZ,EAAO,IAAK,IAGT,EAAA,EAAA,KAAA,CAAC,SAAD,CAEE,YAAe,EAAW,CAAC,EAC3B,UAAW,kDALE,EAAI,MAAM,KAAO,EAAE,GAO1B,6BACA,4DANR,EASE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,wCAAf,EACE,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,UAAU,kBACV,MAAO,CAAE,WAAY,EAAE,OAAO,OAAO,OAAQ,CAC9C,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,UAAU,yCACV,MAAO,CAAE,WAAY,EAAE,OAAO,OAAO,OAAQ,CAC9C,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,UAAU,kBACV,MAAO,CAAE,WAAY,EAAE,OAAO,OAAO,IAAK,CAC3C,CAAA,CACE,KACL,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,+BAAuB,EAAE,IAAU,CAAA,CAC5C,GAvBD,EAAE,EAuBD,CAEX,CACE,CAAA,CACL,CAAA,CAAA,GAEF,EAAA,EAAA,IAAA,CAAC,GAAD,CAAe,SAAU,EAAQ,MAAQ,GAAW,EAAU,EAAO,CAAC,CAAI,CAAA,CAEzE,CAAA,CACF,GAET,CAIA,SAAS,GAAW,CAClB,QACA,KAAM,EACN,SACA,UACA,UAQC,CACD,OACE,EAAA,EAAA,KAAA,CAAC,SAAD,CACW,UACT,MAAO,EACP,UAAW,sFACT,EACI,2BACA,EACA,iCACA,4CARR,EAWE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAM,KAAM,EAAK,CAAA,GACjB,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,qCAA6B,CAAY,CAAA,CACnD,GAEZ,CAIA,SAAS,GAAc,CACrB,WACA,SAIC,CACD,IAAM,EAAe,GAAgB,WAAW,CAAQ,EAClD,EAAU,GAAe,WAAW,CAAQ,EAElD,OACE,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAU,4EACX,GAAgB,EACf,CAAA,GACJ,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,kCAAf,CACG,EAAa,IAAK,IACjB,EAAA,EAAA,IAAA,CAAC,GAAD,CAEE,KAAM,EAAK,KACX,MAAO,EAAK,OAAS,MACrB,YAAe,EAAM,EAAK,MAAM,CACjC,EAJM,EAAK,IAIX,CACF,EACA,EAAQ,IAAK,IACZ,EAAA,EAAA,IAAA,CAAC,GAAD,CAA2B,KAAM,EAAI,KAAM,YAAe,EAAM,EAAI,MAAM,CAAI,EAA7D,EAAI,IAAyD,CAC/E,EACA,EAAa,SAAW,GAAK,EAAQ,SAAW,IAC/C,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,yDAAgD,kCAE1D,CAAA,CAEJ,GACL,CAAA,CAAA,CAEN,CAIA,SAAS,GAAa,CAAE,SAAiD,CACvE,IAAM,EAAY,GAAgB,cAAc,EAC1C,EAAQ,GAAgB,KAAK,EAanC,OAXI,EAAM,SAAW,GAEjB,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAU,4EAAmE,SAE7E,CAAA,GACJ,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAU,wCAA+B,sBAAuB,CAAA,CACnE,CAAA,CAAA,GAKJ,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAU,4EAAmE,SAE7E,CAAA,GACJ,EAAA,EAAA,KAAA,CAAC,IAAD,CAAG,UAAU,0CAAb,CACG,EAAM,OAAO,WAAS,EAAM,SAAW,EAAI,GAAK,IAAI,WAAS,EAAU,OAAQ,IAC/E,EAAU,SAAW,EAAI,UAAY,WACrC,KACH,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,+BACZ,EAAU,IAAK,GAAM,CACpB,IAAM,EAAS,EAAM,OAAQ,GAAM,EAAE,YAAc,EAAE,EAAE,EAEvD,OADI,EAAO,SAAW,EAAU,MAE9B,EAAA,EAAA,KAAA,CAAC,MAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,wDAAgD,EAAE,IAAU,CAAA,GAC3E,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,kCACZ,EAAO,IAAK,IACX,EAAA,EAAA,IAAA,CAAC,GAAD,CAEE,KAAM,EAAK,KACX,MAAO,EAAK,OAAS,MACrB,IAAK,GAAgB,EAAK,UAC1B,YAAe,EAAM,CAAI,CAC1B,EALM,EAAK,IAKX,CACF,CACE,CAAA,CACF,CAAA,EAbK,EAAE,EAaP,CAET,CAAC,CACE,CAAA,CACL,CAAA,CAAA,CAEN,CAIA,SAAS,GAAW,CAClB,OACA,UACA,QACA,OAMC,CACD,OACE,EAAA,EAAA,KAAA,CAAC,SAAD,CACW,UACT,UAAU,+HAFZ,CAIG,IACC,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,uIACb,CACG,CAAA,GAER,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,gHACZ,CACE,CAAA,GACL,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,6CAAqC,CAAU,CAAA,EAC7D,IAAO,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,qCAA6B,CAAS,CAAA,CACvD,GAEZ,CAIA,SAAS,IAAc,CACrB,GAAM,CAAE,MAAK,YAAW,eAAc,iBAAgB,eAAc,mBAClE,EAAc,EAehB,OAbI,EAAI,QAAQ,SAAW,GAEvB,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAU,4EAAmE,QAE7E,CAAA,GACJ,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAU,wCAA+B,8DAEzC,CAAA,CACH,CAAA,CAAA,GAKJ,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAU,4EAAmE,QAE7E,CAAA,GACJ,EAAA,EAAA,KAAA,CAAC,IAAD,CAAG,UAAU,0CAAb,CACG,EAAI,QAAQ,OAAO,SAAO,EAAI,QAAQ,SAAW,EAAI,GAAK,IAAI,oBAC9D,KACH,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAU,+BACX,EAAI,QAAQ,KAAK,EAAG,KAGjB,EAAA,EAAA,KAAA,CAAC,KAAD,CAEE,UAAW,+FAJA,GAAW,OAAS,SAAW,GAAW,WAAa,EAAE,GAM9D,2CACA,mDAEN,YAAe,EAAa,CAAE,KAAM,SAAU,SAAU,EAAE,EAAG,CAAC,WAPhE,EASE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,kDAA0C,EAAI,CAAQ,CAAA,GACtE,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAU,2BAAhB,CACG,EAAE,MACH,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAU,0CAAhB,CAAiD,IAC7C,EAAE,SAAS,OAAO,GAChB,GACF,KACN,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,SAAU,IAAM,EAChB,QAAU,GAAM,CACd,EAAE,gBAAgB,EAClB,EAAe,EAAG,EAAI,CAAC,CACzB,EACA,UAAU,8DACV,MAAM,oBAEN,EAAA,EAAA,IAAA,CAAC,EAAA,QAAD,CAAS,KAAM,EAAK,CAAA,CACd,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,SAAU,IAAM,EAAI,QAAQ,OAAS,EACrC,QAAU,GAAM,CACd,EAAE,gBAAgB,EAClB,EAAe,EAAG,EAAI,CAAC,CACzB,EACA,UAAU,8DACV,MAAM,sBAEN,EAAA,EAAA,IAAA,CAAC,EAAA,UAAD,CAAW,KAAM,EAAK,CAAA,CAChB,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,QAAU,GAAM,CACd,EAAE,gBAAgB,EAClB,EAAgB,EAAE,EAAE,CACtB,EACA,UAAU,0CACV,MAAM,sBAEN,EAAA,EAAA,IAAA,CAAC,EAAA,KAAD,CAAM,KAAM,EAAK,CAAA,CACX,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,QAAU,GAAM,CACd,EAAE,gBAAgB,EAClB,EAAa,EAAE,EAAE,CACnB,EACA,UAAU,yCACV,MAAM,mBAEN,EAAA,EAAA,IAAA,CAAC,EAAA,OAAD,CAAQ,KAAM,EAAK,CAAA,CACb,CAAA,CACN,GAzDG,EAAE,EAyDL,CAEP,CACC,CAAA,CACJ,CAAA,CAAA,CAEN,CC/ZA,SAAS,IAAkB,CACzB,IAAK,IAAI,EAAO,UAAU,OAAQ,EAAW,MAAM,CAAI,EAAG,EAAO,EAAG,EAAO,EAAM,IAC/E,EAAK,GAAQ,UAAU,GAGzB,OAAA,EAAA,EAAA,QAAA,KAAqB,GAAQ,CAC3B,EAAK,QAAQ,GAAO,EAAI,CAAI,CAAC,CAC/B,EACA,CAAI,CACN,CAGA,IAAM,GAAY,OAAO,OAAW,KAAsB,OAAO,WAAa,QAAsB,OAAO,SAAS,gBAAkB,OAEtI,SAAS,GAAS,EAAS,CACzB,IAAM,EAAgB,OAAO,UAAU,SAAS,KAAK,CAAO,EAC5D,OAAO,IAAkB,mBACzB,IAAkB,iBACpB,CAEA,SAAS,GAAO,EAAM,CACpB,MAAO,aAAc,CACvB,CAEA,SAAS,EAAU,EAAQ,CAezB,OAZK,EAID,GAAS,CAAM,EACV,EAGJ,GAAO,CAAM,EAIwC,EAAO,eAAyD,aAA+C,OAHhK,OARA,MAYX,CAEA,SAAS,GAAW,EAAM,CACxB,GAAM,CACJ,YACE,EAAU,CAAI,EAClB,OAAO,aAAgB,CACzB,CAEA,SAAS,GAAc,EAAM,CAK3B,OAJI,GAAS,CAAI,EACR,GAGF,aAAgB,EAAU,CAAI,CAAC,CAAC,WACzC,CAEA,SAAS,GAAa,EAAM,CAC1B,OAAO,aAAgB,EAAU,CAAI,CAAC,CAAC,UACzC,CAEA,SAAS,GAAiB,EAAQ,CAqBhC,OApBK,EAID,GAAS,CAAM,EACV,EAAO,SAGX,GAAO,CAAM,EAId,GAAW,CAAM,EACZ,EAGL,GAAc,CAAM,GAAK,GAAa,CAAM,EACvC,EAAO,cAGT,SAXE,SARA,QAoBX,CAOA,IAAM,GAA4B,GAAYA,EAAAA,gBAAkBC,EAAAA,UAEhE,SAAS,GAAS,EAAS,CACzB,IAAM,GAAA,EAAA,EAAA,OAAA,CAAoB,CAAO,EAIjC,OAHA,OAAgC,CAC9B,EAAW,QAAU,CACvB,CAAC,GACD,EAAA,EAAA,YAAA,CAAmB,UAAY,CAC7B,IAAK,IAAI,EAAO,UAAU,OAAQ,EAAW,MAAM,CAAI,EAAG,EAAO,EAAG,EAAO,EAAM,IAC/E,EAAK,GAAQ,UAAU,GAGzB,OAAO,EAAW,SAAW,KAAO,IAAK,GAAI,EAAW,QAAQ,GAAG,CAAI,CACzE,EAAG,CAAC,CAAC,CACP,CAEA,SAAS,IAAc,CACrB,IAAM,GAAA,EAAA,EAAA,OAAA,CAAqB,IAAI,EAU/B,MAAO,EAAA,EAAA,EAAA,YAAA,EATkB,EAAU,IAAa,CAC9C,EAAY,QAAU,YAAY,EAAU,CAAQ,CACtD,EAAG,CAAC,CAOM,GAAA,EAAA,EAAA,YAAA,KANsB,CAC1B,EAAY,UAAY,OAC1B,cAAc,EAAY,OAAO,EACjC,EAAY,QAAU,KAE1B,EAAG,CAAC,CACa,CAAC,CACpB,CAEA,SAAS,GAAe,EAAO,EAAc,CACvC,IAAiB,IAAK,KACxB,EAAe,CAAC,CAAK,GAGvB,IAAM,GAAA,EAAA,EAAA,OAAA,CAAkB,CAAK,EAM7B,OALA,OAAgC,CAC1B,EAAS,UAAY,IACvB,EAAS,QAAU,EAEvB,EAAG,CAAY,EACR,CACT,CAEA,SAAS,GAAY,EAAU,EAAc,CAC3C,IAAM,GAAA,EAAA,EAAA,OAAA,CAAkB,EACxB,OAAA,EAAA,EAAA,QAAA,KAAqB,CACnB,IAAM,EAAW,EAAS,EAAS,OAAO,EAE1C,MADA,GAAS,QAAU,EACZ,CACT,EACA,CAAC,GAAG,CAAY,CAAC,CACnB,CAEA,SAAS,GAAW,EAAU,CAC5B,IAAM,EAAkB,GAAS,CAAQ,EACnC,GAAA,EAAA,EAAA,OAAA,CAAc,IAAI,EASxB,MAAO,CAAC,GAAA,EAAA,EAAA,YAAA,CARuB,GAAW,CACpC,IAAY,EAAK,SACnB,IAAmD,EAAS,EAAK,OAAO,EAG1E,EAAK,QAAU,CACjB,EACA,CAAC,CACsB,CAAC,CAC1B,CAEA,SAAS,GAAY,EAAO,CAC1B,IAAM,GAAA,EAAA,EAAA,OAAA,CAAa,EAInB,OAHA,EAAA,EAAA,UAAA,KAAgB,CACd,EAAI,QAAU,CAChB,EAAG,CAAC,CAAK,CAAC,EACH,EAAI,OACb,CAEA,IAAI,GAAM,CAAC,EACX,SAAS,GAAY,EAAQ,EAAO,CAClC,OAAA,EAAA,EAAA,QAAA,KAAqB,CACnB,GAAI,EACF,OAAO,EAGT,IAAM,EAAK,GAAI,IAAW,KAAO,EAAI,GAAI,GAAU,EAEnD,MADA,IAAI,GAAU,EACP,EAAS,IAAM,CACxB,EAAG,CAAC,EAAQ,CAAK,CAAC,CACpB,CAEA,SAAS,GAAmB,EAAU,CACpC,OAAO,SAAU,EAAQ,CACvB,IAAK,IAAI,EAAO,UAAU,OAAQ,EAAkB,MAAM,EAAO,EAAI,EAAO,EAAI,CAAC,EAAG,EAAO,EAAG,EAAO,EAAM,IACzG,EAAY,EAAO,GAAK,UAAU,GAGpC,OAAO,EAAY,QAAQ,EAAa,IAAe,CACrD,IAAM,EAAU,OAAO,QAAQ,CAAU,EAEzC,IAAK,GAAM,CAAC,EAAK,KAAoB,EAAS,CAC5C,IAAM,EAAQ,EAAY,GAEtB,GAAS,OACX,EAAY,GAAO,EAAQ,EAAW,EAE1C,CAEA,OAAO,CACT,EAAG,CAAE,GAAG,CACR,CAAC,CACH,CACF,CAEA,IAAM,GAAmB,GAAmB,CAAC,EACvC,GAAwB,GAAmB,EAAE,EAEnD,SAAS,GAA+B,EAAO,CAC7C,MAAO,YAAa,GAAS,YAAa,CAC5C,CAEA,SAAS,GAAgB,EAAO,CAC9B,GAAI,CAAC,EACH,MAAO,GAGT,GAAM,CACJ,iBACE,EAAU,EAAM,MAAM,EAC1B,OAAO,GAAiB,aAAiB,CAC3C,CAEA,SAAS,GAAa,EAAO,CAC3B,GAAI,CAAC,EACH,MAAO,GAGT,GAAM,CACJ,cACE,EAAU,EAAM,MAAM,EAC1B,OAAO,GAAc,aAAiB,CACxC,CAMA,SAAS,GAAoB,EAAO,CAClC,GAAI,GAAa,CAAK,MAChB,EAAM,SAAW,EAAM,QAAQ,OAAQ,CACzC,GAAM,CACJ,QAAS,EACT,QAAS,GACP,EAAM,QAAQ,GAClB,MAAO,CACL,IACA,GACF,CACF,MAAO,GAAI,EAAM,gBAAkB,EAAM,eAAe,OAAQ,CAC9D,GAAM,CACJ,QAAS,EACT,QAAS,GACP,EAAM,eAAe,GACzB,MAAO,CACL,IACA,GACF,CACF,EAUF,OAPI,GAA+B,CAAK,EAC/B,CACL,EAAG,EAAM,QACT,EAAG,EAAM,OACX,EAGK,IACT,CAEA,IAAM,GAAmB,OAAO,OAAO,CACrC,UAAW,CACT,SAAS,EAAW,CAClB,GAAI,CAAC,EACH,OAGF,GAAM,CACJ,IACA,KACE,EACJ,MAAO,gBAAkB,EAAI,KAAK,MAAM,CAAC,EAAI,GAAK,QAAU,EAAI,KAAK,MAAM,CAAC,EAAI,GAAK,QACvF,CAEF,EACA,MAAO,CACL,SAAS,EAAW,CAClB,GAAI,CAAC,EACH,OAGF,GAAM,CACJ,SACA,UACE,EACJ,MAAO,UAAY,EAAS,YAAc,EAAS,GACrD,CAEF,EACA,UAAW,CACT,SAAS,EAAW,CACb,KAIL,MAAO,CAAC,GAAI,UAAU,SAAS,CAAS,EAAG,GAAI,MAAM,SAAS,CAAS,CAAC,CAAC,CAAC,KAAK,GAAG,CACpF,CAEF,EACA,WAAY,CACV,SAAS,EAAM,CACb,GAAI,CACF,WACA,WACA,UACE,EACJ,OAAO,EAAW,IAAM,EAAW,MAAQ,CAC7C,CAEF,CACF,CAAC,EAEK,GAAW,yIACjB,SAAS,GAAuB,EAAS,CAKvC,OAJI,EAAQ,QAAQ,EAAQ,EACnB,EAGF,EAAQ,cAAc,EAAQ,CACvC,CCvUA,IAAM,GAAe,CACnB,QAAS,MACX,EACA,SAAS,GAAW,EAAM,CACxB,GAAI,CACF,KACA,SACE,EACJ,OAAOC,EAAAA,QAAM,cAAc,MAAO,CAC5B,KACJ,MAAO,EACT,EAAG,CAAK,CACV,CAEA,SAAS,GAAW,EAAM,CACxB,GAAI,CACF,KACA,eACA,eAAe,aACb,EAgBJ,OAAOA,EAAAA,QAAM,cAAc,MAAO,CAC5B,KACJ,MAAO,CAfP,SAAU,QACV,IAAK,EACL,KAAM,EACN,MAAO,EACP,OAAQ,EACR,OAAQ,GACR,OAAQ,EACR,QAAS,EACT,SAAU,SACV,KAAM,gBACN,SAAU,cACV,WAAY,QAIQ,EACpB,KAAM,SACN,YAAa,EACb,cAAe,EACjB,EAAG,CAAY,CACjB,CAEA,SAAS,IAAkB,CACzB,GAAM,CAAC,EAAc,IAAA,EAAA,EAAA,SAAA,CAA4B,EAAE,EAMnD,MAAO,CACL,UAAA,EAAA,EAAA,YAAA,CAN2B,GAAS,CAChC,GAAS,MACX,EAAgB,CAAK,CAEzB,EAAG,CAAC,CAEK,EACP,cACF,CACF,CCpDA,IAAM,IAAiC,EAAA,EAAA,cAAA,CAAc,IAAI,EAEzD,SAAS,GAAc,EAAU,CAC/B,IAAM,GAAA,EAAA,EAAA,WAAA,CAA8B,EAAiB,GACrD,EAAA,EAAA,UAAA,KAAgB,CACd,GAAI,CAAC,EACH,MAAU,MAAM,8DAA8D,EAIhF,OADoB,EAAiB,CACpB,CACnB,EAAG,CAAC,EAAU,CAAgB,CAAC,CACjC,CAEA,SAAS,IAAwB,CAC/B,GAAM,CAAC,IAAA,EAAA,EAAA,SAAA,KAA4B,IAAI,GAAK,EACtC,GAAA,EAAA,EAAA,YAAA,CAA+B,IACnC,EAAU,IAAI,CAAQ,MACT,EAAU,OAAO,CAAQ,GACrC,CAAC,CAAS,CAAC,EAYd,MAAO,EAAA,EAAA,EAAA,YAAA,CAXsB,GAAQ,CACnC,GAAI,CACF,OACA,SACE,EACJ,EAAU,QAAQ,GAGS,EAAS,EAAA,EAAyC,KAAK,EAAU,CAAK,CAChG,CACH,EAAG,CAAC,CAAS,CACE,EAAG,CAAgB,CACpC,CAEA,IAAM,GAAkC,CACtC,UAAW;;;;GACb,EACM,GAAuB,CAC3B,YAAY,EAAM,CAChB,GAAI,CACF,UACE,EACJ,MAAO,4BAA8B,EAAO,GAAK,GACnD,EAEA,WAAW,EAAO,CAChB,GAAI,CACF,SACA,QACE,EAMJ,OAJI,EACK,kBAAoB,EAAO,GAAK,kCAAoC,EAAK,GAAK,IAGhF,kBAAoB,EAAO,GAAK,sCACzC,EAEA,UAAU,EAAO,CACf,GAAI,CACF,SACA,QACE,EAMJ,OAJI,EACK,kBAAoB,EAAO,GAAK,oCAAsC,EAAK,GAG7E,kBAAoB,EAAO,GAAK,eACzC,EAEA,aAAa,EAAO,CAClB,GAAI,CACF,UACE,EACJ,MAAO,0CAA4C,EAAO,GAAK,eACjE,CAEF,EAEA,SAAS,GAAc,EAAM,CAC3B,GAAI,CACF,gBAAgB,GAChB,YACA,0BACA,2BAA2B,IACzB,EACE,CACJ,WACA,gBACE,GAAgB,EACd,EAAe,GAAY,eAAe,EAC1C,CAAC,EAAS,IAAA,EAAA,EAAA,SAAA,CAAuB,EAAK,EA+D5C,IA9DA,EAAA,EAAA,UAAA,KAAgB,CACd,EAAW,EAAI,CACjB,EAAG,CAAC,CAAC,EACL,IAAA,EAAA,EAAA,QAAA,MAA6B,CAC3B,YAAY,EAAO,CACjB,GAAI,CACF,UACE,EACJ,EAAS,EAAc,YAAY,CACjC,QACF,CAAC,CAAC,CACJ,EAEA,WAAW,EAAO,CAChB,GAAI,CACF,SACA,QACE,EAEA,EAAc,YAChB,EAAS,EAAc,WAAW,CAChC,SACA,MACF,CAAC,CAAC,CAEN,EAEA,WAAW,EAAO,CAChB,GAAI,CACF,SACA,QACE,EACJ,EAAS,EAAc,WAAW,CAChC,SACA,MACF,CAAC,CAAC,CACJ,EAEA,UAAU,EAAO,CACf,GAAI,CACF,SACA,QACE,EACJ,EAAS,EAAc,UAAU,CAC/B,SACA,MACF,CAAC,CAAC,CACJ,EAEA,aAAa,EAAO,CAClB,GAAI,CACF,SACA,QACE,EACJ,EAAS,EAAc,aAAa,CAClC,SACA,MACF,CAAC,CAAC,CACJ,CAEF,GAAI,CAAC,EAAU,CAAa,CAAC,CAAC,EAE1B,CAAC,EACH,OAAO,KAGT,IAAM,EAASC,EAAAA,QAAM,cAAcA,EAAAA,QAAM,SAAU,KAAMA,EAAAA,QAAM,cAAc,GAAY,CACvF,GAAI,EACJ,MAAO,EAAyB,SAClC,CAAC,EAAGA,EAAAA,QAAM,cAAc,GAAY,CAClC,GAAI,EACU,cAChB,CAAC,CAAC,EACF,OAAO,GAAA,EAAA,EAAA,aAAA,CAAyB,EAAQ,CAAS,EAAI,CACvD,CAEA,IAAI,GAEH,SAAU,EAAQ,CACjB,EAAO,UAAe,YACtB,EAAO,SAAc,WACrB,EAAO,QAAa,UACpB,EAAO,WAAgB,aACvB,EAAO,SAAc,WACrB,EAAO,kBAAuB,oBAC9B,EAAO,qBAA0B,uBACjC,EAAO,oBAAyB,qBAClC,EAAA,CAAG,AAAW,IAAS,CAAC,CAAE,EAE1B,SAAS,IAAO,CAAC,CAEjB,SAAS,GAAU,EAAQ,EAAS,CAClC,OAAA,EAAA,EAAA,QAAA,MAAsB,CACpB,SACA,QAAS,GAA4B,CAAC,CACxC,GACA,CAAC,EAAQ,CAAO,CAAC,CACnB,CAEA,SAAS,IAAa,CACpB,IAAK,IAAI,EAAO,UAAU,OAAQ,EAAc,MAAM,CAAI,EAAG,EAAO,EAAG,EAAO,EAAM,IAClF,EAAQ,GAAQ,UAAU,GAG5B,OAAA,EAAA,EAAA,QAAA,KAAqB,CAAC,GAAG,CAAO,CAAC,CAAC,OAAO,GAAU,GAAU,IAAI,EACjE,CAAC,GAAG,CAAO,CAAC,CACd,CAEA,IAAM,GAAkC,OAAO,OAAO,CACpD,EAAG,EACH,EAAG,CACL,CAAC,EAKD,SAAS,GAAgB,EAAI,EAAI,CAC/B,OAAO,KAAK,MAAc,EAAG,EAAI,EAAG,IAAG,GAAc,EAAG,EAAI,EAAG,IAAG,CAAE,CACtE,CAmBA,SAAS,GAAkB,EAAM,EAAO,CACtC,GAAI,CACF,KAAM,CACJ,MAAO,IAEP,EACA,CACF,KAAM,CACJ,MAAO,IAEP,EACJ,OAAO,EAAI,CACb,CAKA,SAAS,GAAmB,EAAO,EAAO,CACxC,GAAI,CACF,KAAM,CACJ,MAAO,IAEP,EACA,CACF,KAAM,CACJ,MAAO,IAEP,EACJ,OAAO,EAAI,CACb,CAMA,SAAS,GAAmB,EAAO,CACjC,GAAI,CACF,OACA,MACA,SACA,SACE,EACJ,MAAO,CAAC,CACN,EAAG,EACH,EAAG,CACL,EAAG,CACD,EAAG,EAAO,EACV,EAAG,CACL,EAAG,CACD,EAAG,EACH,EAAG,EAAM,CACX,EAAG,CACD,EAAG,EAAO,EACV,EAAG,EAAM,CACX,CAAC,CACH,CACA,SAAS,GAAkB,EAAY,EAAU,CAC/C,GAAI,CAAC,GAAc,EAAW,SAAW,EACvC,OAAO,KAGT,GAAM,CAAC,GAAkB,EACzB,OAAO,EAAW,EAAe,GAAY,CAC/C,CAMA,SAAS,GAAkB,EAAM,EAAM,EAAK,CAS1C,OARI,IAAS,IAAK,KAChB,EAAO,EAAK,MAGV,IAAQ,IAAK,KACf,EAAM,EAAK,KAGN,CACL,EAAG,EAAO,EAAK,MAAQ,GACvB,EAAG,EAAM,EAAK,OAAS,EACzB,CACF,CAOA,IAAM,GAAgB,GAAQ,CAC5B,GAAI,CACF,gBACA,iBACA,uBACE,EACE,EAAa,GAAkB,EAAe,EAAc,KAAM,EAAc,GAAG,EACnF,EAAa,CAAC,EAEpB,IAAK,IAAM,KAAsB,EAAqB,CACpD,GAAM,CACJ,MACE,EACE,EAAO,EAAe,IAAI,CAAE,EAElC,GAAI,EAAM,CACR,IAAM,EAAc,GAAgB,GAAkB,CAAI,EAAG,CAAU,EACvE,EAAW,KAAK,CACd,KACA,KAAM,CACJ,qBACA,MAAO,CACT,CACF,CAAC,CACH,CACF,CAEA,OAAO,EAAW,KAAK,EAAiB,CAC1C,EAOM,GAAiB,GAAQ,CAC7B,GAAI,CACF,gBACA,iBACA,uBACE,EACE,EAAU,GAAmB,CAAa,EAC1C,EAAa,CAAC,EAEpB,IAAK,IAAM,KAAsB,EAAqB,CACpD,GAAM,CACJ,MACE,EACE,EAAO,EAAe,IAAI,CAAE,EAElC,GAAI,EAAM,CACR,IAAM,EAAc,GAAmB,CAAI,EACrC,EAAY,EAAQ,QAAQ,EAAa,EAAQ,IAC9C,EAAc,GAAgB,EAAY,GAAQ,CAAM,EAC9D,CAAC,EACE,EAAoB,QAAQ,EAAY,EAAA,CAAG,QAAQ,CAAC,CAAC,EAC3D,EAAW,KAAK,CACd,KACA,KAAM,CACJ,qBACA,MAAO,CACT,CACF,CAAC,CACH,CACF,CAEA,OAAO,EAAW,KAAK,EAAiB,CAC1C,EAMA,SAAS,GAAqB,EAAO,EAAQ,CAC3C,IAAM,EAAM,KAAK,IAAI,EAAO,IAAK,EAAM,GAAG,EACpC,EAAO,KAAK,IAAI,EAAO,KAAM,EAAM,IAAI,EACvC,EAAQ,KAAK,IAAI,EAAO,KAAO,EAAO,MAAO,EAAM,KAAO,EAAM,KAAK,EACrE,EAAS,KAAK,IAAI,EAAO,IAAM,EAAO,OAAQ,EAAM,IAAM,EAAM,MAAM,EACtE,EAAQ,EAAQ,EAChB,EAAS,EAAS,EAExB,GAAI,EAAO,GAAS,EAAM,EAAQ,CAChC,IAAM,EAAa,EAAO,MAAQ,EAAO,OACnC,EAAY,EAAM,MAAQ,EAAM,OAChC,EAAmB,EAAQ,EAC3B,EAAoB,GAAoB,EAAa,EAAY,GACvE,OAAO,OAAO,EAAkB,QAAQ,CAAC,CAAC,CAC5C,CAGA,MAAO,EACT,CAMA,IAAM,GAAmB,GAAQ,CAC/B,GAAI,CACF,gBACA,iBACA,uBACE,EACE,EAAa,CAAC,EAEpB,IAAK,IAAM,KAAsB,EAAqB,CACpD,GAAM,CACJ,MACE,EACE,EAAO,EAAe,IAAI,CAAE,EAElC,GAAI,EAAM,CACR,IAAM,EAAoB,GAAqB,EAAM,CAAa,EAE9D,EAAoB,GACtB,EAAW,KAAK,CACd,KACA,KAAM,CACJ,qBACA,MAAO,CACT,CACF,CAAC,CAEL,CACF,CAEA,OAAO,EAAW,KAAK,EAAkB,CAC3C,EA+DA,SAAS,GAAY,EAAW,EAAO,EAAO,CAC5C,MAAO,CAAE,GAAG,EACV,OAAQ,GAAS,EAAQ,EAAM,MAAQ,EAAM,MAAQ,EACrD,OAAQ,GAAS,EAAQ,EAAM,OAAS,EAAM,OAAS,CACzD,CACF,CAEA,SAAS,GAAa,EAAO,EAAO,CAClC,OAAO,GAAS,EAAQ,CACtB,EAAG,EAAM,KAAO,EAAM,KACtB,EAAG,EAAM,IAAM,EAAM,GACvB,EAAI,EACN,CAEA,SAAS,GAAuB,EAAU,CACxC,OAAO,SAA0B,EAAM,CACrC,IAAK,IAAI,EAAO,UAAU,OAAQ,EAAkB,MAAM,EAAO,EAAI,EAAO,EAAI,CAAC,EAAG,EAAO,EAAG,EAAO,EAAM,IACzG,EAAY,EAAO,GAAK,UAAU,GAGpC,OAAO,EAAY,QAAQ,EAAK,KAAgB,CAAE,GAAG,EACnD,IAAK,EAAI,IAAM,EAAW,EAAW,EACrC,OAAQ,EAAI,OAAS,EAAW,EAAW,EAC3C,KAAM,EAAI,KAAO,EAAW,EAAW,EACvC,MAAO,EAAI,MAAQ,EAAW,EAAW,CAC3C,GAAI,CAAE,GAAG,CACT,CAAC,CACH,CACF,CACA,IAAM,GAA+B,GAAuB,CAAC,EAE7D,SAAS,GAAe,EAAW,CACjC,GAAI,EAAU,WAAW,WAAW,EAAG,CACrC,IAAM,EAAiB,EAAU,MAAM,EAAG,EAAE,CAAC,CAAC,MAAM,IAAI,EACxD,MAAO,CACL,EAAG,CAAC,EAAe,IACnB,EAAG,CAAC,EAAe,IACnB,OAAQ,CAAC,EAAe,GACxB,OAAQ,CAAC,EAAe,EAC1B,CACF,MAAO,GAAI,EAAU,WAAW,SAAS,EAAG,CAC1C,IAAM,EAAiB,EAAU,MAAM,EAAG,EAAE,CAAC,CAAC,MAAM,IAAI,EACxD,MAAO,CACL,EAAG,CAAC,EAAe,GACnB,EAAG,CAAC,EAAe,GACnB,OAAQ,CAAC,EAAe,GACxB,OAAQ,CAAC,EAAe,EAC1B,CACF,CAEA,OAAO,IACT,CAEA,SAAS,GAAiB,EAAM,EAAW,EAAiB,CAC1D,IAAM,EAAkB,GAAe,CAAS,EAEhD,GAAI,CAAC,EACH,OAAO,EAGT,GAAM,CACJ,SACA,SACA,EAAG,EACH,EAAG,GACD,EACE,EAAI,EAAK,KAAO,GAAc,EAAI,GAAU,WAAW,CAAe,EACtE,EAAI,EAAK,IAAM,GAAc,EAAI,GAAU,WAAW,EAAgB,MAAM,EAAgB,QAAQ,GAAG,EAAI,CAAC,CAAC,EAC7G,EAAI,EAAS,EAAK,MAAQ,EAAS,EAAK,MACxC,EAAI,EAAS,EAAK,OAAS,EAAS,EAAK,OAC/C,MAAO,CACL,MAAO,EACP,OAAQ,EACR,IAAK,EACL,MAAO,EAAI,EACX,OAAQ,EAAI,EACZ,KAAM,CACR,CACF,CAEA,IAAM,GAAiB,CACrB,gBAAiB,EACnB,EAKA,SAAS,GAAc,EAAS,EAAS,CACnC,IAAY,IAAK,KACnB,EAAU,IAGZ,IAAI,EAAO,EAAQ,sBAAsB,EAEzC,GAAI,EAAQ,gBAAiB,CAC3B,GAAM,CACJ,YACA,mBACE,EAAU,CAAO,CAAC,CAAC,iBAAiB,CAAO,EAE3C,IACF,EAAO,GAAiB,EAAM,EAAW,CAAe,EAE5D,CAEA,GAAM,CACJ,MACA,OACA,QACA,SACA,SACA,SACE,EACJ,MAAO,CACL,MACA,OACA,QACA,SACA,SACA,OACF,CACF,CAUA,SAAS,GAA+B,EAAS,CAC/C,OAAO,GAAc,EAAS,CAC5B,gBAAiB,EACnB,CAAC,CACH,CAEA,SAAS,GAAoB,EAAS,CACpC,IAAM,EAAQ,EAAQ,WAChB,EAAS,EAAQ,YACvB,MAAO,CACL,IAAK,EACL,KAAM,EACN,MAAO,EACP,OAAQ,EACR,QACA,QACF,CACF,CAEA,SAAS,GAAQ,EAAM,EAAe,CAKpC,OAJI,IAAkB,IAAK,KACzB,EAAgB,EAAU,CAAI,CAAC,CAAC,iBAAiB,CAAI,GAGhD,EAAc,WAAa,OACpC,CAEA,SAAS,GAAa,EAAS,EAAe,CACxC,IAAkB,IAAK,KACzB,EAAgB,EAAU,CAAO,CAAC,CAAC,iBAAiB,CAAO,GAG7D,IAAM,EAAgB,wBAEtB,MAAO,CADa,WAAY,YAAa,WAC7B,CAAC,CAAC,KAAK,GAAY,CACjC,IAAM,EAAQ,EAAc,GAC5B,OAAO,OAAO,GAAU,SAAW,EAAc,KAAK,CAAK,EAAI,EACjE,CAAC,CACH,CAEA,SAAS,GAAuB,EAAS,EAAO,CAC9C,IAAM,EAAgB,CAAC,EAEvB,SAAS,EAAwB,EAAM,CAKrC,GAJI,GAAS,MAAQ,EAAc,QAAU,GAIzC,CAAC,EACH,OAAO,EAGT,GAAI,GAAW,CAAI,GAAK,EAAK,kBAAoB,MAAQ,CAAC,EAAc,SAAS,EAAK,gBAAgB,EAEpG,OADA,EAAc,KAAK,EAAK,gBAAgB,EACjC,EAOT,GAJI,CAAC,GAAc,CAAI,GAAK,GAAa,CAAI,GAIzC,EAAc,SAAS,CAAI,EAC7B,OAAO,EAGT,IAAM,EAAgB,EAAU,CAAO,CAAC,CAAC,iBAAiB,CAAI,EAY9D,OAVI,IAAS,GACP,GAAa,EAAM,CAAa,GAClC,EAAc,KAAK,CAAI,EAIvB,GAAQ,EAAM,CAAa,EACtB,EAGF,EAAwB,EAAK,UAAU,CAChD,CAMA,OAJK,EAIE,EAAwB,CAAO,EAH7B,CAIX,CACA,SAAS,GAA2B,EAAM,CACxC,GAAM,CAAC,GAA2B,GAAuB,EAAM,CAAC,EAChE,OAAO,GAA4D,IACrE,CAEA,SAAS,GAAqB,EAAS,CAqBrC,MApBI,CAAC,IAAa,CAAC,EACV,KAGL,GAAS,CAAO,EACX,EAGJ,GAAO,CAAO,EAIf,GAAW,CAAO,GAAK,IAAY,GAAiB,CAAO,CAAC,CAAC,iBACxD,OAGL,GAAc,CAAO,EAChB,EAGF,KAXE,IAYX,CAEA,SAAS,GAAqB,EAAS,CAKrC,OAJI,GAAS,CAAO,EACX,EAAQ,QAGV,EAAQ,UACjB,CACA,SAAS,GAAqB,EAAS,CAKrC,OAJI,GAAS,CAAO,EACX,EAAQ,QAGV,EAAQ,SACjB,CACA,SAAS,GAAqB,EAAS,CACrC,MAAO,CACL,EAAG,GAAqB,CAAO,EAC/B,EAAG,GAAqB,CAAO,CACjC,CACF,CAEA,IAAI,GAEH,SAAU,EAAW,CACpB,EAAU,EAAU,QAAa,GAAK,UACtC,EAAU,EAAU,SAAc,IAAM,UAC1C,EAAA,CAAG,AAAc,IAAY,CAAC,CAAE,EAEhC,SAAS,GAA2B,EAAS,CAK3C,MAJI,CAAC,IAAa,CAAC,EACV,GAGF,IAAY,SAAS,gBAC9B,CAEA,SAAS,GAAkB,EAAoB,CAC7C,IAAM,EAAY,CAChB,EAAG,EACH,EAAG,CACL,EACM,EAAa,GAA2B,CAAkB,EAAI,CAClE,OAAQ,OAAO,YACf,MAAO,OAAO,UAChB,EAAI,CACF,OAAQ,EAAmB,aAC3B,MAAO,EAAmB,WAC5B,EACM,EAAY,CAChB,EAAG,EAAmB,YAAc,EAAW,MAC/C,EAAG,EAAmB,aAAe,EAAW,MAClD,EAKA,MAAO,CACL,MALY,EAAmB,WAAa,EAAU,EAMtD,OALa,EAAmB,YAAc,EAAU,EAMxD,SALe,EAAmB,WAAa,EAAU,EAMzD,QALc,EAAmB,YAAc,EAAU,EAMzD,YACA,WACF,CACF,CAEA,IAAM,GAAmB,CACvB,EAAG,GACH,EAAG,EACL,EACA,SAAS,GAA2B,EAAiB,EAAqB,EAAM,EAAc,EAAqB,CACjH,GAAI,CACF,MACA,OACA,QACA,UACE,EAEA,IAAiB,IAAK,KACxB,EAAe,IAGb,IAAwB,IAAK,KAC/B,EAAsB,IAGxB,GAAM,CACJ,QACA,WACA,SACA,WACE,GAAkB,CAAe,EAC/B,EAAY,CAChB,EAAG,EACH,EAAG,CACL,EACM,EAAQ,CACZ,EAAG,EACH,EAAG,CACL,EACM,EAAY,CAChB,OAAQ,EAAoB,OAAS,EAAoB,EACzD,MAAO,EAAoB,MAAQ,EAAoB,CACzD,EAsBA,MApBI,CAAC,GAAS,GAAO,EAAoB,IAAM,EAAU,QAEvD,EAAU,EAAI,EAAU,SACxB,EAAM,EAAI,EAAe,KAAK,KAAK,EAAoB,IAAM,EAAU,OAAS,GAAO,EAAU,MAAM,GAC9F,CAAC,GAAY,GAAU,EAAoB,OAAS,EAAU,SAEvE,EAAU,EAAI,EAAU,QACxB,EAAM,EAAI,EAAe,KAAK,KAAK,EAAoB,OAAS,EAAU,OAAS,GAAU,EAAU,MAAM,GAG3G,CAAC,GAAW,GAAS,EAAoB,MAAQ,EAAU,OAE7D,EAAU,EAAI,EAAU,QACxB,EAAM,EAAI,EAAe,KAAK,KAAK,EAAoB,MAAQ,EAAU,MAAQ,GAAS,EAAU,KAAK,GAChG,CAAC,GAAU,GAAQ,EAAoB,KAAO,EAAU,QAEjE,EAAU,EAAI,EAAU,SACxB,EAAM,EAAI,EAAe,KAAK,KAAK,EAAoB,KAAO,EAAU,MAAQ,GAAQ,EAAU,KAAK,GAGlG,CACL,YACA,OACF,CACF,CAEA,SAAS,GAAqB,EAAS,CACrC,GAAI,IAAY,SAAS,iBAAkB,CACzC,GAAM,CACJ,aACA,eACE,OACJ,MAAO,CACL,IAAK,EACL,KAAM,EACN,MAAO,EACP,OAAQ,EACR,MAAO,EACP,OAAQ,CACV,CACF,CAEA,GAAM,CACJ,MACA,OACA,QACA,UACE,EAAQ,sBAAsB,EAClC,MAAO,CACL,MACA,OACA,QACA,SACA,MAAO,EAAQ,YACf,OAAQ,EAAQ,YAClB,CACF,CAEA,SAAS,GAAiB,EAAqB,CAC7C,OAAO,EAAoB,QAAQ,EAAK,IAC/B,GAAI,EAAK,GAAqB,CAAI,CAAC,EACzC,EAAkB,CACvB,CACA,SAAS,GAAiB,EAAqB,CAC7C,OAAO,EAAoB,QAAQ,EAAK,IAC/B,EAAM,GAAqB,CAAI,EACrC,CAAC,CACN,CACA,SAAS,GAAiB,EAAqB,CAC7C,OAAO,EAAoB,QAAQ,EAAK,IAC/B,EAAM,GAAqB,CAAI,EACrC,CAAC,CACN,CAEA,SAAS,GAAuB,EAAS,EAAS,CAKhD,GAJI,IAAY,IAAK,KACnB,EAAU,IAGR,CAAC,EACH,OAGF,GAAM,CACJ,MACA,OACA,SACA,SACE,EAAQ,CAAO,EACa,GAA2B,CAEhC,IAIvB,GAAU,GAAK,GAAS,GAAK,GAAO,OAAO,aAAe,GAAQ,OAAO,aAC3E,EAAQ,eAAe,CACrB,MAAO,SACP,OAAQ,QACV,CAAC,CAEL,CAEA,IAAM,GAAa,CAAC,CAAC,IAAK,CAAC,OAAQ,OAAO,EAAG,EAAgB,EAAG,CAAC,IAAK,CAAC,MAAO,QAAQ,EAAG,EAAgB,CAAC,EACpG,GAAN,KAAW,CACT,YAAY,EAAM,EAAS,CACzB,KAAK,KAAO,IAAK,GACjB,KAAK,MAAQ,IAAK,GAClB,KAAK,OAAS,IAAK,GACnB,KAAK,IAAM,IAAK,GAChB,KAAK,OAAS,IAAK,GACnB,KAAK,MAAQ,IAAK,GAClB,KAAK,KAAO,IAAK,GACjB,IAAM,EAAsB,GAAuB,CAAO,EACpD,EAAgB,GAAiB,CAAmB,EAC1D,KAAK,KAAO,CAAE,GAAG,CACjB,EACA,KAAK,MAAQ,EAAK,MAClB,KAAK,OAAS,EAAK,OAEnB,IAAK,GAAM,CAAC,EAAM,EAAM,KAAoB,GAC1C,IAAK,IAAM,KAAO,EAChB,OAAO,eAAe,KAAM,EAAK,CAC/B,QAAW,CACT,IAAM,EAAiB,EAAgB,CAAmB,EACpD,EAAsB,EAAc,GAAQ,EAClD,OAAO,KAAK,KAAK,GAAO,CAC1B,EACA,WAAY,EACd,CAAC,EAIL,OAAO,eAAe,KAAM,OAAQ,CAClC,WAAY,EACd,CAAC,CACH,CAEF,EAEM,GAAN,KAAgB,CACd,YAAY,EAAQ,CAClB,KAAK,OAAS,IAAK,GACnB,KAAK,UAAY,CAAC,EAElB,KAAK,cAAkB,CACrB,KAAK,UAAU,QAAQ,GAGE,KAAK,QAAwC,oBAAoB,GAAG,CAAQ,CACpG,CACH,EAEA,KAAK,OAAS,CAChB,CAEA,IAAI,EAAW,EAAS,EAAS,CAC/B,IAAI,GAEH,EAAgB,KAAK,SAAW,MAAgB,EAAc,iBAAiB,EAAW,EAAS,CAAO,EAC3G,KAAK,UAAU,KAAK,CAAC,EAAW,EAAS,CAAO,CAAC,CACnD,CAEF,EAEA,SAAS,GAAuB,EAAQ,CAMtC,GAAM,CACJ,eACE,EAAU,CAAM,EACpB,OAAO,aAAkB,EAAc,EAAS,GAAiB,CAAM,CACzE,CAEA,SAAS,GAAoB,EAAO,EAAa,CAC/C,IAAM,EAAK,KAAK,IAAI,EAAM,CAAC,EACrB,EAAK,KAAK,IAAI,EAAM,CAAC,EAkB3B,OAhBI,OAAO,GAAgB,SAClB,KAAK,KAAK,GAAM,EAAI,GAAM,CAAC,EAAI,EAGpC,MAAO,GAAe,MAAO,EACxB,EAAK,EAAY,GAAK,EAAK,EAAY,EAG5C,MAAO,EACF,EAAK,EAAY,EAGtB,MAAO,EACF,EAAK,EAAY,EAGnB,EACT,CAEA,IAAI,IAEH,SAAU,EAAW,CACpB,EAAU,MAAW,QACrB,EAAU,UAAe,YACzB,EAAU,QAAa,UACvB,EAAU,YAAiB,cAC3B,EAAU,OAAY,SACtB,EAAU,gBAAqB,kBAC/B,EAAU,iBAAsB,kBAClC,EAAA,CAAG,AAAc,KAAY,CAAC,CAAE,EAEhC,SAAS,GAAe,EAAO,CAC7B,EAAM,eAAe,CACvB,CACA,SAAS,GAAgB,EAAO,CAC9B,EAAM,gBAAgB,CACxB,CAEA,IAAI,GAEH,SAAU,EAAc,CACvB,EAAa,MAAW,QACxB,EAAa,KAAU,YACvB,EAAa,MAAW,aACxB,EAAa,KAAU,YACvB,EAAa,GAAQ,UACrB,EAAa,IAAS,SACtB,EAAa,MAAW,QACxB,EAAa,IAAS,KACxB,EAAA,CAAG,AAAiB,IAAe,CAAC,CAAE,EAEtC,IAAM,GAAuB,CAC3B,MAAO,CAAC,EAAa,MAAO,EAAa,KAAK,EAC9C,OAAQ,CAAC,EAAa,GAAG,EACzB,IAAK,CAAC,EAAa,MAAO,EAAa,MAAO,EAAa,GAAG,CAChE,EACM,IAAmC,EAAO,IAAS,CACvD,GAAI,CACF,sBACE,EAEJ,OAAQ,EAAM,KAAd,CACE,KAAK,EAAa,MAChB,MAAO,CAAE,GAAG,EACV,EAAG,EAAmB,EAAI,EAC5B,EAEF,KAAK,EAAa,KAChB,MAAO,CAAE,GAAG,EACV,EAAG,EAAmB,EAAI,EAC5B,EAEF,KAAK,EAAa,KAChB,MAAO,CAAE,GAAG,EACV,EAAG,EAAmB,EAAI,EAC5B,EAEF,KAAK,EAAa,GAChB,MAAO,CAAE,GAAG,EACV,EAAG,EAAmB,EAAI,EAC5B,CACJ,CAGF,EAEM,GAAN,KAAqB,CACnB,YAAY,EAAO,CACjB,KAAK,MAAQ,IAAK,GAClB,KAAK,kBAAoB,GACzB,KAAK,qBAAuB,IAAK,GACjC,KAAK,UAAY,IAAK,GACtB,KAAK,gBAAkB,IAAK,GAC5B,KAAK,MAAQ,EACb,GAAM,CACJ,MAAO,CACL,WAEA,EACJ,KAAK,MAAQ,EACb,KAAK,UAAY,IAAI,GAAU,GAAiB,CAAM,CAAC,EACvD,KAAK,gBAAkB,IAAI,GAAU,EAAU,CAAM,CAAC,EACtD,KAAK,cAAgB,KAAK,cAAc,KAAK,IAAI,EACjD,KAAK,aAAe,KAAK,aAAa,KAAK,IAAI,EAC/C,KAAK,OAAO,CACd,CAEA,QAAS,CACP,KAAK,YAAY,EACjB,KAAK,gBAAgB,IAAI,GAAU,OAAQ,KAAK,YAAY,EAC5D,KAAK,gBAAgB,IAAI,GAAU,iBAAkB,KAAK,YAAY,EACtE,eAAiB,KAAK,UAAU,IAAI,GAAU,QAAS,KAAK,aAAa,CAAC,CAC5E,CAEA,aAAc,CACZ,GAAM,CACJ,aACA,WACE,KAAK,MACH,EAAO,EAAW,KAAK,QAEzB,GACF,GAAuB,CAAI,EAG7B,EAAQ,EAAkB,CAC5B,CAEA,cAAc,EAAO,CACnB,GAAI,GAAgB,CAAK,EAAG,CAC1B,GAAM,CACJ,SACA,UACA,WACE,KAAK,MACH,CACJ,gBAAgB,GAChB,mBAAmB,GACnB,iBAAiB,UACf,EACE,CACJ,QACE,EAEJ,GAAI,EAAc,IAAI,SAAS,CAAI,EAAG,CACpC,KAAK,UAAU,CAAK,EACpB,MACF,CAEA,GAAI,EAAc,OAAO,SAAS,CAAI,EAAG,CACvC,KAAK,aAAa,CAAK,EACvB,MACF,CAEA,GAAM,CACJ,iBACE,EAAQ,QACN,EAAqB,EAAgB,CACzC,EAAG,EAAc,KACjB,EAAG,EAAc,GACnB,EAAI,GAEJ,AACE,KAAK,uBAAuB,EAG9B,IAAM,EAAiB,EAAiB,EAAO,CAC7C,SACA,QAAS,EAAQ,QACjB,oBACF,CAAC,EAED,GAAI,EAAgB,CAClB,IAAM,EAAmB,GAAS,EAAgB,CAAkB,EAC9D,EAAc,CAClB,EAAG,EACH,EAAG,CACL,EACM,CACJ,uBACE,EAAQ,QAEZ,IAAK,IAAM,KAAmB,EAAqB,CACjD,IAAM,EAAY,EAAM,KAClB,CACJ,QACA,UACA,SACA,WACA,YACA,aACE,GAAkB,CAAe,EAC/B,EAAoB,GAAqB,CAAe,EACxD,EAAqB,CACzB,EAAG,KAAK,IAAI,IAAc,EAAa,MAAQ,EAAkB,MAAQ,EAAkB,MAAQ,EAAI,EAAkB,MAAO,KAAK,IAAI,IAAc,EAAa,MAAQ,EAAkB,KAAO,EAAkB,KAAO,EAAkB,MAAQ,EAAG,EAAe,CAAC,CAAC,EAC5Q,EAAG,KAAK,IAAI,IAAc,EAAa,KAAO,EAAkB,OAAS,EAAkB,OAAS,EAAI,EAAkB,OAAQ,KAAK,IAAI,IAAc,EAAa,KAAO,EAAkB,IAAM,EAAkB,IAAM,EAAkB,OAAS,EAAG,EAAe,CAAC,CAAC,CAC9Q,EACM,EAAa,IAAc,EAAa,OAAS,CAAC,GAAW,IAAc,EAAa,MAAQ,CAAC,EACjG,EAAa,IAAc,EAAa,MAAQ,CAAC,GAAY,IAAc,EAAa,IAAM,CAAC,EAErG,GAAI,GAAc,EAAmB,IAAM,EAAe,EAAG,CAC3D,IAAM,EAAuB,EAAgB,WAAa,EAAiB,EACrE,EAA4B,IAAc,EAAa,OAAS,GAAwB,EAAU,GAAK,IAAc,EAAa,MAAQ,GAAwB,EAAU,EAElL,GAAI,GAA6B,CAAC,EAAiB,EAAG,CAGpD,EAAgB,SAAS,CACvB,KAAM,EACN,SAAU,CACZ,CAAC,EACD,MACF,CAEI,EACF,EAAY,EAAI,EAAgB,WAAa,EAE7C,EAAY,EAAI,IAAc,EAAa,MAAQ,EAAgB,WAAa,EAAU,EAAI,EAAgB,WAAa,EAAU,EAGnI,EAAY,GACd,EAAgB,SAAS,CACvB,KAAM,CAAC,EAAY,EACnB,SAAU,CACZ,CAAC,EAGH,KACF,MAAO,GAAI,GAAc,EAAmB,IAAM,EAAe,EAAG,CAClE,IAAM,EAAuB,EAAgB,UAAY,EAAiB,EACpE,EAA4B,IAAc,EAAa,MAAQ,GAAwB,EAAU,GAAK,IAAc,EAAa,IAAM,GAAwB,EAAU,EAE/K,GAAI,GAA6B,CAAC,EAAiB,EAAG,CAGpD,EAAgB,SAAS,CACvB,IAAK,EACL,SAAU,CACZ,CAAC,EACD,MACF,CAEI,EACF,EAAY,EAAI,EAAgB,UAAY,EAE5C,EAAY,EAAI,IAAc,EAAa,KAAO,EAAgB,UAAY,EAAU,EAAI,EAAgB,UAAY,EAAU,EAGhI,EAAY,GACd,EAAgB,SAAS,CACvB,IAAK,CAAC,EAAY,EAClB,SAAU,CACZ,CAAC,EAGH,KACF,CACF,CAEA,KAAK,WAAW,EAAO,GAAI,GAAS,EAAgB,KAAK,oBAAoB,EAAG,CAAW,CAAC,CAC9F,CACF,CACF,CAEA,WAAW,EAAO,EAAa,CAC7B,GAAM,CACJ,UACE,KAAK,MACT,EAAM,eAAe,EACrB,EAAO,CAAW,CACpB,CAEA,UAAU,EAAO,CACf,GAAM,CACJ,SACE,KAAK,MACT,EAAM,eAAe,EACrB,KAAK,OAAO,EACZ,EAAM,CACR,CAEA,aAAa,EAAO,CAClB,GAAM,CACJ,YACE,KAAK,MACT,EAAM,eAAe,EACrB,KAAK,OAAO,EACZ,EAAS,CACX,CAEA,QAAS,CACP,KAAK,UAAU,UAAU,EACzB,KAAK,gBAAgB,UAAU,CACjC,CAEF,EACA,GAAe,WAAa,CAAC,CAC3B,UAAW,YACX,SAAU,EAAO,EAAM,IAAU,CAC/B,GAAI,CACF,gBAAgB,GAChB,gBACE,EACA,CACF,UACE,EACE,CACJ,QACE,EAAM,YAEV,GAAI,EAAc,MAAM,SAAS,CAAI,EAAG,CACtC,IAAM,EAAY,EAAO,cAAc,QAUvC,OARI,GAAa,EAAM,SAAW,EACzB,IAGT,EAAM,eAAe,EACrB,IAA6C,CAC3C,MAAO,EAAM,WACf,CAAC,EACM,GACT,CAEA,MAAO,EACT,CACF,CAAC,EAED,SAAS,GAAqB,EAAY,CACxC,MAAO,GAAQ,GAAc,aAAc,EAC7C,CAEA,SAAS,GAAkB,EAAY,CACrC,MAAO,GAAQ,GAAc,UAAW,EAC1C,CAEA,IAAM,GAAN,KAA4B,CAC1B,YAAY,EAAO,EAAQ,EAAgB,CAGrC,IAAmB,IAAK,KAC1B,EAAiB,GAAuB,EAAM,MAAM,MAAM,GAG5D,KAAK,MAAQ,IAAK,GAClB,KAAK,OAAS,IAAK,GACnB,KAAK,kBAAoB,GACzB,KAAK,SAAW,IAAK,GACrB,KAAK,UAAY,GACjB,KAAK,mBAAqB,IAAK,GAC/B,KAAK,UAAY,KACjB,KAAK,UAAY,IAAK,GACtB,KAAK,kBAAoB,IAAK,GAC9B,KAAK,gBAAkB,IAAK,GAC5B,KAAK,MAAQ,EACb,KAAK,OAAS,EACd,GAAM,CACJ,SACE,EACE,CACJ,UACE,EACJ,KAAK,MAAQ,EACb,KAAK,OAAS,EACd,KAAK,SAAW,GAAiB,CAAM,EACvC,KAAK,kBAAoB,IAAI,GAAU,KAAK,QAAQ,EACpD,KAAK,UAAY,IAAI,GAAU,CAAc,EAC7C,KAAK,gBAAkB,IAAI,GAAU,EAAU,CAAM,CAAC,EACtD,KAAK,mBAA6C,GAAoB,CAAK,GAAoC,GAC/G,KAAK,YAAc,KAAK,YAAY,KAAK,IAAI,EAC7C,KAAK,WAAa,KAAK,WAAW,KAAK,IAAI,EAC3C,KAAK,UAAY,KAAK,UAAU,KAAK,IAAI,EACzC,KAAK,aAAe,KAAK,aAAa,KAAK,IAAI,EAC/C,KAAK,cAAgB,KAAK,cAAc,KAAK,IAAI,EACjD,KAAK,oBAAsB,KAAK,oBAAoB,KAAK,IAAI,EAC7D,KAAK,OAAO,CACd,CAEA,QAAS,CACP,GAAM,CACJ,SACA,MAAO,CACL,QAAS,CACP,uBACA,gCAGF,KAgBJ,GAfA,KAAK,UAAU,IAAI,EAAO,KAAK,KAAM,KAAK,WAAY,CACpD,QAAS,EACX,CAAC,EACD,KAAK,UAAU,IAAI,EAAO,IAAI,KAAM,KAAK,SAAS,EAE9C,EAAO,QACT,KAAK,UAAU,IAAI,EAAO,OAAO,KAAM,KAAK,YAAY,EAG1D,KAAK,gBAAgB,IAAI,GAAU,OAAQ,KAAK,YAAY,EAC5D,KAAK,gBAAgB,IAAI,GAAU,UAAW,EAAc,EAC5D,KAAK,gBAAgB,IAAI,GAAU,iBAAkB,KAAK,YAAY,EACtE,KAAK,gBAAgB,IAAI,GAAU,YAAa,EAAc,EAC9D,KAAK,kBAAkB,IAAI,GAAU,QAAS,KAAK,aAAa,EAE5D,EAAsB,CACxB,GAAI,GAA8B,MAAQ,EAA2B,CACnE,MAAO,KAAK,MAAM,MAClB,WAAY,KAAK,MAAM,WACvB,QAAS,KAAK,MAAM,OACtB,CAAC,EACC,OAAO,KAAK,YAAY,EAG1B,GAAI,GAAkB,CAAoB,EAAG,CAC3C,KAAK,UAAY,WAAW,KAAK,YAAa,EAAqB,KAAK,EACxE,KAAK,cAAc,CAAoB,EACvC,MACF,CAEA,GAAI,GAAqB,CAAoB,EAAG,CAC9C,KAAK,cAAc,CAAoB,EACvC,MACF,CACF,CAEA,KAAK,YAAY,CACnB,CAEA,QAAS,CACP,KAAK,UAAU,UAAU,EACzB,KAAK,gBAAgB,UAAU,EAG/B,WAAW,KAAK,kBAAkB,UAAW,EAAE,EAE3C,KAAK,YAAc,OACrB,aAAa,KAAK,SAAS,EAC3B,KAAK,UAAY,KAErB,CAEA,cAAc,EAAY,EAAQ,CAChC,GAAM,CACJ,SACA,aACE,KAAK,MACT,EAAU,EAAQ,EAAY,KAAK,mBAAoB,CAAM,CAC/D,CAEA,aAAc,CACZ,GAAM,CACJ,sBACE,KACE,CACJ,WACE,KAAK,MAEL,IACF,KAAK,UAAY,GAEjB,KAAK,kBAAkB,IAAI,GAAU,MAAO,GAAiB,CAC3D,QAAS,EACX,CAAC,EAED,KAAK,oBAAoB,EAEzB,KAAK,kBAAkB,IAAI,GAAU,gBAAiB,KAAK,mBAAmB,EAC9E,EAAQ,CAAkB,EAE9B,CAEA,WAAW,EAAO,CAGhB,GAAM,CACJ,YACA,qBACA,SACE,KACE,CACJ,SACA,QAAS,CACP,yBAEA,EAEJ,GAAI,CAAC,EACH,OAGF,IAAM,EAAuC,GAAoB,CAAK,GAAqC,GACrG,EAAQ,GAAS,EAAoB,CAAW,EAEtD,GAAI,CAAC,GAAa,EAAsB,CACtC,GAAI,GAAqB,CAAoB,EAAG,CAC9C,GAAI,EAAqB,WAAa,MAAQ,GAAoB,EAAO,EAAqB,SAAS,EACrG,OAAO,KAAK,aAAa,EAG3B,GAAI,GAAoB,EAAO,EAAqB,QAAQ,EAC1D,OAAO,KAAK,YAAY,CAE5B,CAEA,GAAI,GAAkB,CAAoB,GACpC,GAAoB,EAAO,EAAqB,SAAS,EAC3D,OAAO,KAAK,aAAa,EAI7B,KAAK,cAAc,EAAsB,CAAK,EAC9C,MACF,CAEI,EAAM,YACR,EAAM,eAAe,EAGvB,EAAO,CAAW,CACpB,CAEA,WAAY,CACV,GAAM,CACJ,UACA,SACE,KAAK,MACT,KAAK,OAAO,EAEP,KAAK,WACR,EAAQ,KAAK,MAAM,MAAM,EAG3B,EAAM,CACR,CAEA,cAAe,CACb,GAAM,CACJ,UACA,YACE,KAAK,MACT,KAAK,OAAO,EAEP,KAAK,WACR,EAAQ,KAAK,MAAM,MAAM,EAG3B,EAAS,CACX,CAEA,cAAc,EAAO,CACf,EAAM,OAAS,EAAa,KAC9B,KAAK,aAAa,CAEtB,CAEA,qBAAsB,CACpB,IAAI,GAEH,EAAwB,KAAK,SAAS,aAAa,IAAM,MAAgB,EAAsB,gBAAgB,CAClH,CAEF,EAEM,GAAS,CACb,OAAQ,CACN,KAAM,eACR,EACA,KAAM,CACJ,KAAM,aACR,EACA,IAAK,CACH,KAAM,WACR,CACF,EACM,GAAN,cAA4B,EAAsB,CAChD,YAAY,EAAO,CACjB,GAAM,CACJ,SACE,EAGE,EAAiB,GAAiB,EAAM,MAAM,EACpD,MAAM,EAAO,GAAQ,CAAc,CACrC,CAEF,EACA,GAAc,WAAa,CAAC,CAC1B,UAAW,gBACX,SAAU,EAAM,IAAU,CACxB,GAAI,CACF,YAAa,GACX,EACA,CACF,gBACE,EASJ,MAPI,CAAC,EAAM,WAAa,EAAM,SAAW,EAChC,IAGT,IAA6C,CAC3C,OACF,CAAC,EACM,GACT,CACF,CAAC,EAED,IAAM,GAAW,CACf,KAAM,CACJ,KAAM,WACR,EACA,IAAK,CACH,KAAM,SACR,CACF,EACI,IAEH,SAAU,EAAa,CACtB,EAAY,EAAY,WAAgB,GAAK,YAC/C,EAAA,CAAG,AAAgB,KAAc,CAAC,CAAE,EAEpC,IAAM,GAAN,cAA0B,EAAsB,CAC9C,YAAY,EAAO,CACjB,MAAM,EAAO,GAAU,GAAiB,EAAM,MAAM,MAAM,CAAC,CAC7D,CAEF,EACA,GAAY,WAAa,CAAC,CACxB,UAAW,cACX,SAAU,EAAM,IAAU,CACxB,GAAI,CACF,YAAa,GACX,EACA,CACF,gBACE,EASJ,OAPI,EAAM,SAAW,GAAY,WACxB,IAGT,IAA6C,CAC3C,OACF,CAAC,EACM,GACT,CACF,CAAC,EAED,IAAM,GAAW,CACf,OAAQ,CACN,KAAM,aACR,EACA,KAAM,CACJ,KAAM,WACR,EACA,IAAK,CACH,KAAM,UACR,CACF,EACM,GAAN,cAA0B,EAAsB,CAC9C,YAAY,EAAO,CACjB,MAAM,EAAO,EAAQ,CACvB,CAEA,OAAO,OAAQ,CAQb,OAJA,OAAO,iBAAiB,GAAS,KAAK,KAAM,EAAM,CAChD,QAAS,GACT,QAAS,EACX,CAAC,EACM,UAAoB,CACzB,OAAO,oBAAoB,GAAS,KAAK,KAAM,CAAI,CACrD,EAGA,SAAS,GAAO,CAAC,CACnB,CAEF,EACA,GAAY,WAAa,CAAC,CACxB,UAAW,eACX,SAAU,EAAM,IAAU,CACxB,GAAI,CACF,YAAa,GACX,EACA,CACF,gBACE,EACE,CACJ,WACE,EASJ,OAPI,EAAQ,OAAS,EACZ,IAGT,IAA6C,CAC3C,OACF,CAAC,EACM,GACT,CACF,CAAC,EAED,IAAI,IAEH,SAAU,EAAqB,CAC9B,EAAoB,EAAoB,QAAa,GAAK,UAC1D,EAAoB,EAAoB,cAAmB,GAAK,eAClE,EAAA,CAAG,AAAwB,KAAsB,CAAC,CAAE,EAEpD,IAAI,IAEH,SAAU,EAAgB,CACzB,EAAe,EAAe,UAAe,GAAK,YAClD,EAAe,EAAe,kBAAuB,GAAK,mBAC5D,EAAA,CAAG,AAAmB,KAAiB,CAAC,CAAE,EAE1C,SAAS,GAAgB,EAAM,CAC7B,GAAI,CACF,eACA,YAAY,GAAoB,QAChC,YACA,eACA,UACA,WAAW,EACX,QAAQ,GAAe,UACvB,qBACA,sBACA,0BACA,QACA,aACE,EACE,EAAe,GAAgB,CACnC,QACA,SAAU,CAAC,CACb,CAAC,EACK,CAAC,EAAuB,GAA2B,GAAY,EAC/D,GAAA,EAAA,EAAA,OAAA,CAAqB,CACzB,EAAG,EACH,EAAG,CACL,CAAC,EACK,GAAA,EAAA,EAAA,OAAA,CAAyB,CAC7B,EAAG,EACH,EAAG,CACL,CAAC,EACK,GAAA,EAAA,EAAA,QAAA,KAAqB,CACzB,OAAQ,EAAR,CACE,KAAK,GAAoB,QACvB,OAAO,EAAqB,CAC1B,IAAK,EAAmB,EACxB,OAAQ,EAAmB,EAC3B,KAAM,EAAmB,EACzB,MAAO,EAAmB,CAC5B,EAAI,KAEN,KAAK,GAAoB,cACvB,OAAO,CACX,CACF,EAAG,CAAC,EAAW,EAAc,CAAkB,CAAC,EAC1C,GAAA,EAAA,EAAA,OAAA,CAA4B,IAAI,EAChC,GAAA,EAAA,EAAA,YAAA,KAA+B,CACnC,IAAM,EAAkB,EAAmB,QAE3C,GAAI,CAAC,EACH,OAGF,IAAM,EAAa,EAAY,QAAQ,EAAI,EAAgB,QAAQ,EAC7D,EAAY,EAAY,QAAQ,EAAI,EAAgB,QAAQ,EAClE,EAAgB,SAAS,EAAY,CAAS,CAChD,EAAG,CAAC,CAAC,EACC,GAAA,EAAA,EAAA,QAAA,KAA0C,IAAU,GAAe,UAAY,CAAC,GAAG,CAAmB,CAAC,CAAC,QAAQ,EAAI,EAAqB,CAAC,EAAO,CAAmB,CAAC,GAC3K,EAAA,EAAA,UAAA,KAAgB,CACd,GAAI,CAAC,GAAW,CAAC,EAAoB,QAAU,CAAC,EAAM,CACpD,EAAwB,EACxB,MACF,CAEA,IAAK,IAAM,KAAmB,EAA2B,CACvD,GAAK,IAAuC,CAAe,IAAO,GAChE,SAGF,IAAM,EAAQ,EAAoB,QAAQ,CAAe,EACnD,EAAsB,EAAwB,GAEpD,GAAI,CAAC,EACH,SAGF,GAAM,CACJ,YACA,SACE,GAA2B,EAAiB,EAAqB,EAAM,EAAc,CAAS,EAElG,IAAK,IAAM,IAAQ,CAAC,IAAK,GAAG,EACrB,EAAa,EAAK,CAAC,EAAU,MAChC,EAAM,GAAQ,EACd,EAAU,GAAQ,GAItB,GAAI,EAAM,EAAI,GAAK,EAAM,EAAI,EAAG,CAC9B,EAAwB,EACxB,EAAmB,QAAU,EAC7B,EAAsB,EAAY,CAAQ,EAC1C,EAAY,QAAU,EACtB,EAAgB,QAAU,EAC1B,MACF,CACF,CAEA,EAAY,QAAU,CACpB,EAAG,EACH,EAAG,CACL,EACA,EAAgB,QAAU,CACxB,EAAG,EACH,EAAG,CACL,EACA,EAAwB,CAC1B,EACA,CAAC,EAAc,EAAY,EAAW,EAAyB,EAAS,EACxE,KAAK,UAAU,CAAI,EACnB,KAAK,UAAU,CAAY,EAAG,EAAuB,EAAqB,EAA2B,EACrG,KAAK,UAAU,CAAS,CAAC,CAAC,CAC5B,CACA,IAAM,GAAsB,CAC1B,EAAG,EACA,EAAU,UAAW,IACrB,EAAU,SAAU,EACvB,EACA,EAAG,EACA,EAAU,UAAW,IACrB,EAAU,SAAU,EACvB,CACF,EAEA,SAAS,GAAgB,EAAO,CAC9B,GAAI,CACF,QACA,YACE,EACE,EAAgB,GAAY,CAAK,EACvC,OAAO,GAAY,GAAkB,CACnC,GAAI,GAAY,CAAC,GAAiB,CAAC,EAEjC,OAAO,GAGT,IAAM,EAAY,CAChB,EAAG,KAAK,KAAK,EAAM,EAAI,EAAc,CAAC,EACtC,EAAG,KAAK,KAAK,EAAM,EAAI,EAAc,CAAC,CACxC,EAEA,MAAO,CACL,EAAG,EACA,EAAU,UAAW,EAAe,EAAE,EAAU,WAAa,EAAU,IAAM,IAC7E,EAAU,SAAU,EAAe,EAAE,EAAU,UAAY,EAAU,IAAM,CAC9E,EACA,EAAG,EACA,EAAU,UAAW,EAAe,EAAE,EAAU,WAAa,EAAU,IAAM,IAC7E,EAAU,SAAU,EAAe,EAAE,EAAU,UAAY,EAAU,IAAM,CAC9E,CACF,CACF,EAAG,CAAC,EAAU,EAAO,CAAa,CAAC,CACrC,CAEA,SAAS,GAAc,EAAgB,EAAI,CACzC,IAAM,EAAgB,GAAM,KAAgC,IAAA,GAAzB,EAAe,IAAI,CAAE,EAClD,EAAO,EAAgB,EAAc,KAAK,QAAU,KAC1D,OAAO,GAAY,GAGb,GAAM,KACD,KAMM,GAAsB,GAA6B,KACjE,CAAC,EAAM,CAAE,CAAC,CACf,CAEA,SAAS,GAAqB,EAAS,EAAqB,CAC1D,OAAA,EAAA,EAAA,QAAA,KAAqB,EAAQ,QAAQ,EAAa,IAAW,CAC3D,GAAM,CACJ,OAAQ,GACN,EACE,EAAmB,EAAO,WAAW,IAAI,IAAc,CAC3D,UAAW,EAAU,UACrB,QAAS,EAAoB,EAAU,QAAS,CAAM,CACxD,EAAE,EACF,MAAO,CAAC,GAAG,EAAa,GAAG,CAAgB,CAC7C,EAAG,CAAC,CAAC,EAAG,CAAC,EAAS,CAAmB,CAAC,CACxC,CAEA,IAAI,IAEH,SAAU,EAAmB,CAC5B,EAAkB,EAAkB,OAAY,GAAK,SACrD,EAAkB,EAAkB,eAAoB,GAAK,iBAC7D,EAAkB,EAAkB,cAAmB,GAAK,eAC9D,EAAA,CAAG,AAAsB,KAAoB,CAAC,CAAE,EAEhD,IAAI,IAEH,SAAU,EAAoB,CAC7B,EAAmB,UAAe,WACpC,EAAA,CAAG,AAAuB,KAAqB,CAAC,CAAE,EAElD,IAAM,GAA4B,IAAI,IACtC,SAAS,GAAsB,EAAY,EAAM,CAC/C,GAAI,CACF,WACA,eACA,UACE,EACE,CAAC,EAAO,IAAA,EAAA,EAAA,SAAA,CAAqB,IAAI,EACjC,CACJ,YACA,UACA,YACE,EACE,GAAA,EAAA,EAAA,OAAA,CAAuB,CAAU,EACjC,EAAW,EAAW,EACtB,EAAc,GAAe,CAAQ,EACrC,GAAA,EAAA,EAAA,YAAA,CAAyC,SAAU,EAAK,CACxD,IAAQ,IAAK,KACf,EAAM,CAAC,GAGL,GAAY,SAIhB,EAAS,GACH,IAAU,KACL,EAGF,EAAM,OAAO,EAAI,OAAO,GAAM,CAAC,EAAM,SAAS,CAAE,CAAC,CAAC,CAC1D,CACH,EAAG,CAAC,CAAW,CAAC,EACV,GAAA,EAAA,EAAA,OAAA,CAAmB,IAAI,EACvB,EAAiB,GAAY,GAAiB,CAClD,GAAI,GAAY,CAAC,EACf,OAAO,GAGT,GAAI,CAAC,GAAiB,IAAkB,IAAgB,EAAc,UAAY,GAAc,GAAS,KAAM,CAC7G,IAAM,EAAM,IAAI,IAEhB,IAAK,IAAI,KAAa,EAAY,CAChC,GAAI,CAAC,EACH,SAGF,GAAI,GAAS,EAAM,OAAS,GAAK,CAAC,EAAM,SAAS,EAAU,EAAE,GAAK,EAAU,KAAK,QAAS,CAExF,EAAI,IAAI,EAAU,GAAI,EAAU,KAAK,OAAO,EAC5C,QACF,CAEA,IAAM,EAAO,EAAU,KAAK,QACtB,EAAO,EAAO,IAAI,GAAK,EAAQ,CAAI,EAAG,CAAI,EAAI,KACpD,EAAU,KAAK,QAAU,EAErB,GACF,EAAI,IAAI,EAAU,GAAI,CAAI,CAE9B,CAEA,OAAO,CACT,CAEA,OAAO,CACT,EAAG,CAAC,EAAY,EAAO,EAAU,EAAU,CAAO,CAAC,EA6BnD,OA5BA,EAAA,EAAA,UAAA,KAAgB,CACd,EAAc,QAAU,CAC1B,EAAG,CAAC,CAAU,CAAC,GACf,EAAA,EAAA,UAAA,KAAgB,CACV,GAIJ,EAA2B,CAC7B,EACA,CAAC,EAAU,CAAQ,CAAC,GACpB,EAAA,EAAA,UAAA,KAAgB,CACV,GAAS,EAAM,OAAS,GAC1B,EAAS,IAAI,CAEjB,EACA,CAAC,KAAK,UAAU,CAAK,CAAC,CAAC,GACvB,EAAA,EAAA,UAAA,KAAgB,CACV,GAAY,OAAO,GAAc,UAAY,EAAU,UAAY,OAIvE,EAAU,QAAU,eAAiB,CACnC,EAA2B,EAC3B,EAAU,QAAU,IACtB,EAAG,CAAS,EACd,EACA,CAAC,EAAW,EAAU,EAA4B,GAAG,CAAY,CAAC,EAC3D,CACL,iBACA,6BACA,mBAAoB,GAAS,IAC/B,EAEA,SAAS,GAAa,CACpB,OAAQ,EAAR,CACE,KAAK,GAAkB,OACrB,MAAO,GAET,KAAK,GAAkB,eACrB,OAAO,EAET,QACE,MAAO,CAAC,CACZ,CACF,CACF,CAEA,SAAS,GAAgB,EAAO,EAAW,CACzC,OAAO,GAAY,GACZ,EAID,IAIG,OAAO,GAAc,WAAa,EAAU,CAAK,EAAI,GAPnD,KAQR,CAAC,EAAW,CAAK,CAAC,CACvB,CAEA,SAAS,GAAe,EAAM,EAAS,CACrC,OAAO,GAAgB,EAAM,CAAO,CACtC,CAOA,SAAS,GAAoB,EAAM,CACjC,GAAI,CACF,WACA,YACE,EACE,EAAkB,GAAS,CAAQ,EACnC,GAAA,EAAA,EAAA,QAAA,KAAiC,CACrC,GAAI,GAAY,OAAO,OAAW,KAAsB,OAAO,mBAAqB,OAClF,OAGF,GAAM,CACJ,oBACE,OACJ,OAAO,IAAI,EAAiB,CAAe,CAC7C,EAAG,CAAC,EAAiB,CAAQ,CAAC,EAI9B,OAHA,EAAA,EAAA,UAAA,SACe,GAAqD,WAAW,EAC5E,CAAC,CAAgB,CAAC,EACd,CACT,CAOA,SAAS,GAAkB,EAAM,CAC/B,GAAI,CACF,WACA,YACE,EACE,EAAe,GAAS,CAAQ,EAChC,GAAA,EAAA,EAAA,QAAA,KAA+B,CACnC,GAAI,GAAY,OAAO,OAAW,KAAsB,OAAO,iBAAmB,OAChF,OAGF,GAAM,CACJ,kBACE,OACJ,OAAO,IAAI,EAAe,CAAY,CACxC,EACA,CAAC,CAAQ,CAAC,EAIV,OAHA,EAAA,EAAA,UAAA,SACe,GAAiD,WAAW,EACxE,CAAC,CAAc,CAAC,EACZ,CACT,CAEA,SAAS,GAAe,EAAS,CAC/B,OAAO,IAAI,GAAK,GAAc,CAAO,EAAG,CAAO,CACjD,CAEA,SAAS,GAAQ,EAAS,EAAS,EAAc,CAC3C,IAAY,IAAK,KACnB,EAAU,IAGZ,GAAM,CAAC,EAAM,IAAA,EAAA,EAAA,SAAA,CAAoB,IAAI,EAErC,SAAS,GAAc,CACrB,EAAQ,GAAe,CACrB,GAAI,CAAC,EACH,OAAO,KAGT,GAAI,EAAQ,cAAgB,GAK1B,OAAe,GAAoC,GAA+B,KAGpF,IAAM,EAAU,EAAQ,CAAO,EAM/B,OAJI,KAAK,UAAU,CAAW,IAAM,KAAK,UAAU,CAAO,EACjD,EAGF,CACT,CAAC,CACH,CAEA,IAAM,EAAmB,GAAoB,CAC3C,SAAS,EAAS,CACX,KAIL,IAAK,IAAM,KAAU,EAAS,CAC5B,GAAM,CACJ,OACA,UACE,EAEJ,GAAI,IAAS,aAAe,aAAkB,aAAe,EAAO,SAAS,CAAO,EAAG,CACrF,EAAY,EACZ,KACF,CACF,CACF,CAEF,CAAC,EACK,EAAiB,GAAkB,CACvC,SAAU,CACZ,CAAC,EAeD,OAdA,OAAgC,CAC9B,EAAY,EAER,GACF,GAAiD,QAAQ,CAAO,EAChE,GAAqD,QAAQ,SAAS,KAAM,CAC1E,UAAW,GACX,QAAS,EACX,CAAC,IAED,GAAiD,WAAW,EAC5D,GAAqD,WAAW,EAEpE,EAAG,CAAC,CAAO,CAAC,EACL,CACT,CAEA,SAAS,GAAa,EAAM,CAE1B,OAAO,GAAa,EADA,GAAgB,CACA,CAAC,CACvC,CAEA,IAAM,GAAiB,CAAC,EACxB,SAAS,GAAuB,EAAM,CACpC,IAAM,GAAA,EAAA,EAAA,OAAA,CAAsB,CAAI,EAC1B,EAAY,GAAY,GACvB,EAID,GAAiB,IAAkB,IAAkB,GAAQ,EAAa,SAAW,EAAK,aAAe,EAAa,QAAQ,WACzH,EAGF,GAAuB,CAAI,EAPzB,GAQR,CAAC,CAAI,CAAC,EAIT,OAHA,EAAA,EAAA,UAAA,KAAgB,CACd,EAAa,QAAU,CACzB,EAAG,CAAC,CAAI,CAAC,EACF,CACT,CAEA,SAAS,GAAiB,EAAU,CAClC,GAAM,CAAC,EAAmB,IAAA,EAAA,EAAA,SAAA,CAAiC,IAAI,EACzD,GAAA,EAAA,EAAA,OAAA,CAAsB,CAAQ,EAE9B,GAAA,EAAA,EAAA,YAAA,CAA2B,GAAS,CACxC,IAAM,EAAmB,GAAqB,EAAM,MAAM,EAErD,GAIL,EAAqB,GACd,GAIL,EAAkB,IAAI,EAAkB,GAAqB,CAAgB,CAAC,EACvE,IAAI,IAAI,CAAiB,GAJvB,IAKV,CACH,EAAG,CAAC,CAAC,EAkCL,OAjCA,EAAA,EAAA,UAAA,KAAgB,CACd,IAAM,EAAmB,EAAa,QAEtC,GAAI,IAAa,EAAkB,CACjC,EAAQ,CAAgB,EACxB,IAAM,EAAU,EAAS,IAAI,GAAW,CACtC,IAAM,EAAoB,GAAqB,CAAO,EAStD,OAPI,GACF,EAAkB,iBAAiB,SAAU,EAAc,CACzD,QAAS,EACX,CAAC,EACM,CAAC,EAAmB,GAAqB,CAAiB,CAAC,GAG7D,IACT,CAAC,CAAC,CAAC,OAAO,GAAS,GAAS,IAAI,EAChC,EAAqB,EAAQ,OAAS,IAAI,IAAI,CAAO,EAAI,IAAI,EAC7D,EAAa,QAAU,CACzB,CAEA,UAAa,CACX,EAAQ,CAAQ,EAChB,EAAQ,CAAgB,CAC1B,EAEA,SAAS,EAAQ,EAAU,CACzB,EAAS,QAAQ,GAAW,CAE1B,GAD+C,CAC/B,CAAC,EAAsC,oBAAoB,SAAU,CAAY,CACnG,CAAC,CACH,CACF,EAAG,CAAC,EAAc,CAAQ,CAAC,GAC3B,EAAA,EAAA,QAAA,KACM,EAAS,OACJ,EAAoB,MAAM,KAAK,EAAkB,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAK,IAAgB,GAAI,EAAK,CAAW,EAAG,EAAkB,EAAI,GAAiB,CAAQ,EAGhK,GACN,CAAC,EAAU,CAAiB,CAAC,CAClC,CAEA,SAAS,GAAsB,EAAe,EAAc,CACtD,IAAiB,IAAK,KACxB,EAAe,CAAC,GAGlB,IAAM,GAAA,EAAA,EAAA,OAAA,CAA8B,IAAI,EAgBxC,OAfA,EAAA,EAAA,UAAA,KAAgB,CACd,EAAqB,QAAU,IACjC,EACA,CAAY,GACZ,EAAA,EAAA,UAAA,KAAgB,CACd,IAAM,EAAmB,IAAkB,GAEvC,GAAoB,CAAC,EAAqB,UAC5C,EAAqB,QAAU,GAG7B,CAAC,GAAoB,EAAqB,UAC5C,EAAqB,QAAU,KAEnC,EAAG,CAAC,CAAa,CAAC,EACX,EAAqB,QAAU,GAAS,EAAe,EAAqB,OAAO,EAAI,EAChG,CAEA,SAAS,GAAe,EAAS,EAC/B,EAAA,EAAA,UAAA,KAAgB,CACd,GAAI,CAAC,GACH,OAGF,IAAM,EAAc,EAAQ,IAAI,GAAQ,CACtC,GAAI,CACF,UACE,EACJ,OAAO,EAAO,OAAS,KAAO,IAAK,GAAI,EAAO,MAAM,CACtD,CAAC,EACD,UAAa,CACX,IAAK,IAAM,KAAY,EACrB,IAAqC,CAEzC,CACF,EAEA,EAAQ,IAAI,GAAS,CACnB,GAAI,CACF,UACE,EACJ,OAAO,CACT,CAAC,CAAC,CACJ,CAEA,SAAS,GAAsB,EAAW,EAAI,CAC5C,OAAA,EAAA,EAAA,QAAA,KACS,EAAU,QAAQ,EAAK,IAAS,CACrC,GAAI,CACF,YACA,WACE,EAMJ,MAJA,GAAI,GAAa,GAAS,CACxB,EAAQ,EAAO,CAAE,CACnB,EAEO,CACT,EAAG,CAAC,CAAC,EACJ,CAAC,EAAW,CAAE,CAAC,CACpB,CAEA,SAAS,GAAc,EAAS,CAC9B,OAAA,EAAA,EAAA,QAAA,KAAqB,EAAU,GAAoB,CAAO,EAAI,KAAM,CAAC,CAAO,CAAC,CAC/E,CAEA,IAAM,GAAiB,CAAC,EACxB,SAAS,GAAS,EAAU,EAAS,CAC/B,IAAY,IAAK,KACnB,EAAU,IAGZ,GAAM,CAAC,GAAgB,EACjB,EAAa,GAAc,EAAe,EAAU,CAAY,EAAI,IAAI,EACxE,CAAC,EAAO,IAAA,EAAA,EAAA,SAAA,CAAqB,EAAc,EAEjD,SAAS,GAAe,CACtB,MACO,EAAS,OAIP,EAAS,IAAI,GAAW,GAA2B,CAAO,EAAI,EAAa,IAAI,GAAK,EAAQ,CAAO,EAAG,CAAO,CAAC,EAH5G,EAIV,CACH,CAEA,IAAM,EAAiB,GAAkB,CACvC,SAAU,CACZ,CAAC,EAMD,OALA,OAAgC,CAC9B,GAAiD,WAAW,EAC5D,EAAa,EACb,EAAS,QAAQ,GAAW,GAAiD,QAAQ,CAAO,CAAC,CAC/F,EAAG,CAAC,CAAQ,CAAC,EACN,CACT,CAEA,SAAS,GAAkB,EAAM,CAC/B,GAAI,CAAC,EACH,OAAO,KAGT,GAAI,EAAK,SAAS,OAAS,EACzB,OAAO,EAGT,IAAM,EAAa,EAAK,SAAS,GACjC,OAAO,GAAc,CAAU,EAAI,EAAa,CAClD,CAEA,SAAS,GAAwB,EAAM,CACrC,GAAI,CACF,WACE,EACE,CAAC,EAAM,IAAA,EAAA,EAAA,SAAA,CAAoB,IAAI,EAiB/B,EAAiB,GAAkB,CACvC,UAAA,EAAA,EAAA,YAAA,CAjB+B,GAAW,CAC1C,IAAK,GAAM,CACT,YACG,EACH,GAAI,GAAc,CAAM,EAAG,CACzB,EAAQ,GAAQ,CACd,IAAM,EAAU,EAAQ,CAAM,EAC9B,OAAO,EAAO,CAAE,GAAG,EACjB,MAAO,EAAQ,MACf,OAAQ,EAAQ,MAClB,EAAI,CACN,CAAC,EACD,KACF,CAEJ,EAAG,CAAC,CAAO,CAEY,CACvB,CAAC,EAWK,CAAC,EAAS,GAAU,IAAA,EAAA,EAAA,YAAA,CAVW,GAAW,CAC9C,IAAM,EAAO,GAAkB,CAAO,EACtC,GAAiD,WAAW,EAExD,GACF,GAAiD,QAAQ,CAAI,EAG/D,EAAQ,EAAO,EAAQ,CAAI,EAAI,IAAI,CACrC,EAAG,CAAC,EAAS,CAAc,CACyB,CAAC,EACrD,OAAA,EAAA,EAAA,QAAA,MAAsB,CACpB,UACA,OACA,QACF,GAAI,CAAC,EAAM,EAAS,CAAM,CAAC,CAC7B,CAEA,IAAM,GAAiB,CAAC,CACtB,OAAQ,GACR,QAAS,CAAC,CACZ,EAAG,CACD,OAAQ,GACR,QAAS,CAAC,CACZ,CAAC,EACK,GAAc,CAClB,QAAS,CAAC,CACZ,EACM,GAAgC,CACpC,UAAW,CACT,QAAS,EACX,EACA,UAAW,CACT,QAAS,GACT,SAAU,GAAkB,cAC5B,UAAW,GAAmB,SAChC,EACA,YAAa,CACX,QAAS,EACX,CACF,EAEM,GAAN,cAAqC,GAAI,CACvC,IAAI,EAAI,CAGN,OAAO,GAAM,KAAuE,IAAA,GAAlD,MAAM,IAAI,CAAE,GAA0B,IAAA,EAC1E,CAEA,SAAU,CACR,OAAO,MAAM,KAAK,KAAK,OAAO,CAAC,CACjC,CAEA,YAAa,CACX,OAAO,KAAK,QAAQ,CAAC,CAAC,OAAO,GAAQ,CACnC,GAAI,CACF,YACE,EACJ,MAAO,CAAC,CACV,CAAC,CACH,CAEA,WAAW,EAAI,CAGb,OAA6C,KAAK,IAAI,CAAE,CAAA,EAAgC,KAAK,SAA2C,IAAA,EAC1I,CAEF,EAEM,GAAuB,CAC3B,eAAgB,KAChB,OAAQ,KACR,WAAY,KACZ,eAAgB,KAChB,WAAY,KACZ,kBAAmB,KACnB,eAA6B,IAAI,IACjC,eAA6B,IAAI,IACjC,oBAAkC,IAAI,GACtC,KAAM,KACN,YAAa,CACX,QAAS,CACP,QAAS,IACX,EACA,KAAM,KACN,OAAQ,EACV,EACA,oBAAqB,CAAC,EACtB,wBAAyB,CAAC,EAC1B,uBAAwB,GACxB,2BAA4B,GAC5B,WAAY,KACZ,mBAAoB,EACtB,EACM,GAAyB,CAC7B,eAAgB,KAChB,WAAY,CAAC,EACb,OAAQ,KACR,eAAgB,KAChB,kBAAmB,CACjB,UAAW,EACb,EACA,SAAU,GACV,eAA6B,IAAI,IACjC,KAAM,KACN,2BAA4B,EAC9B,EACM,IAA+B,EAAA,EAAA,cAAA,CAAc,EAAsB,EACnE,IAA6B,EAAA,EAAA,cAAA,CAAc,EAAoB,EAErE,SAAS,IAAkB,CACzB,MAAO,CACL,UAAW,CACT,OAAQ,KACR,mBAAoB,CAClB,EAAG,EACH,EAAG,CACL,EACA,MAAO,IAAI,IACX,UAAW,CACT,EAAG,EACH,EAAG,CACL,CACF,EACA,UAAW,CACT,WAAY,IAAI,EAClB,CACF,CACF,CACA,SAAS,GAAQ,EAAO,EAAQ,CAC9B,OAAQ,EAAO,KAAf,CACE,KAAK,EAAO,UACV,MAAO,CAAE,GAAG,EACV,UAAW,CAAE,GAAG,EAAM,UACpB,mBAAoB,EAAO,mBAC3B,OAAQ,EAAO,MACjB,CACF,EAEF,KAAK,EAAO,SAKV,OAJI,EAAM,UAAU,QAAU,KACrB,EAGF,CAAE,GAAG,EACV,UAAW,CAAE,GAAG,EAAM,UACpB,UAAW,CACT,EAAG,EAAO,YAAY,EAAI,EAAM,UAAU,mBAAmB,EAC7D,EAAG,EAAO,YAAY,EAAI,EAAM,UAAU,mBAAmB,CAC/D,CACF,CACF,EAEF,KAAK,EAAO,QACZ,KAAK,EAAO,WACV,MAAO,CAAE,GAAG,EACV,UAAW,CAAE,GAAG,EAAM,UACpB,OAAQ,KACR,mBAAoB,CAClB,EAAG,EACH,EAAG,CACL,EACA,UAAW,CACT,EAAG,EACH,EAAG,CACL,CACF,CACF,EAEF,KAAK,EAAO,kBACV,CACE,GAAM,CACJ,WACE,EACE,CACJ,MACE,EACE,EAAa,IAAI,GAAuB,EAAM,UAAU,UAAU,EAExE,OADA,EAAW,IAAI,EAAI,CAAO,EACnB,CAAE,GAAG,EACV,UAAW,CAAE,GAAG,EAAM,UACpB,YACF,CACF,CACF,CAEF,KAAK,EAAO,qBACV,CACE,GAAM,CACJ,KACA,MACA,YACE,EACE,EAAU,EAAM,UAAU,WAAW,IAAI,CAAE,EAEjD,GAAI,CAAC,GAAW,IAAQ,EAAQ,IAC9B,OAAO,EAGT,IAAM,EAAa,IAAI,GAAuB,EAAM,UAAU,UAAU,EAIxE,OAHA,EAAW,IAAI,EAAI,CAAE,GAAG,EACtB,UACF,CAAC,EACM,CAAE,GAAG,EACV,UAAW,CAAE,GAAG,EAAM,UACpB,YACF,CACF,CACF,CAEF,KAAK,EAAO,oBACV,CACE,GAAM,CACJ,KACA,OACE,EACE,EAAU,EAAM,UAAU,WAAW,IAAI,CAAE,EAEjD,GAAI,CAAC,GAAW,IAAQ,EAAQ,IAC9B,OAAO,EAGT,IAAM,EAAa,IAAI,GAAuB,EAAM,UAAU,UAAU,EAExE,OADA,EAAW,OAAO,CAAE,EACb,CAAE,GAAG,EACV,UAAW,CAAE,GAAG,EAAM,UACpB,YACF,CACF,CACF,CAEF,QAEI,OAAO,CAEb,CACF,CAEA,SAAS,GAAa,EAAM,CAC1B,GAAI,CACF,YACE,EACE,CACJ,SACA,iBACA,mBAAA,EAAA,EAAA,WAAA,CACa,EAAe,EACxB,EAAyB,GAAY,CAAc,EACnD,EAAmB,GAAY,GAAiC,EAAE,EAgDxE,OA9CA,EAAA,EAAA,UAAA,KAAgB,CACV,OAIA,CAAC,GAAkB,GAA0B,GAAoB,KAAM,CAKzE,GAJI,CAAC,GAAgB,CAAsB,GAIvC,SAAS,gBAAkB,EAAuB,OAEpD,OAGF,IAAM,EAAgB,EAAe,IAAI,CAAgB,EAEzD,GAAI,CAAC,EACH,OAGF,GAAM,CACJ,gBACA,QACE,EAEJ,GAAI,CAAC,EAAc,SAAW,CAAC,EAAK,QAClC,OAGF,0BAA4B,CAC1B,IAAK,IAAM,IAAW,CAAC,EAAc,QAAS,EAAK,OAAO,EAAG,CAC3D,GAAI,CAAC,EACH,SAGF,IAAM,EAAgB,GAAuB,CAAO,EAEpD,GAAI,EAAe,CACjB,EAAc,MAAM,EACpB,KACF,CACF,CACF,CAAC,CACH,CACF,EAAG,CAAC,EAAgB,EAAU,EAAgB,EAAkB,CAAsB,CAAC,EAChF,IACT,CAEA,SAAS,GAAe,EAAW,EAAM,CACvC,GAAI,CACF,YACA,GAAG,GACD,EACJ,OAAO,GAAa,MAAQ,EAAU,OAAS,EAAU,QAAQ,EAAa,IACrE,EAAS,CACd,UAAW,EACX,GAAG,CACL,CAAC,EACA,CAAS,EAAI,CAClB,CAEA,SAAS,GAA0B,EAAQ,CACzC,OAAA,EAAA,EAAA,QAAA,MAAsB,CACpB,UAAW,CAAE,GAAG,GAA8B,UAC5C,GAAI,GAAiC,SACvC,EACA,UAAW,CAAE,GAAG,GAA8B,UAC5C,GAAI,GAAiC,SACvC,EACA,YAAa,CAAE,GAAG,GAA8B,YAC9C,GAAI,GAAiC,WACvC,CACF,GACA,CAAC,GAAiC,UAAW,GAAiC,UAAW,GAAiC,WAAW,CAAC,CACxI,CAEA,SAAS,GAAiC,EAAM,CAC9C,GAAI,CACF,aACA,UACA,cACA,SAAS,IACP,EACE,GAAA,EAAA,EAAA,OAAA,CAAqB,EAAK,EAC1B,CACJ,IACA,KACE,OAAO,GAAW,UAAY,CAChC,EAAG,EACH,EAAG,CACL,EAAI,EACJ,OAAgC,CAG9B,GAFiB,CAAC,GAAK,CAAC,GAER,CAAC,EAAY,CAC3B,EAAY,QAAU,GACtB,MACF,CAEA,GAAI,EAAY,SAAW,CAAC,EAG1B,OAIF,IAAM,EAAO,GAAyC,KAAK,QAE3D,GAAI,CAAC,GAAQ,EAAK,cAAgB,GAGhC,OAIF,IAAM,EAAY,GADL,EAAQ,CACa,EAAG,CAAW,EAahD,GAXK,IACH,EAAU,EAAI,GAGX,IACH,EAAU,EAAI,GAIhB,EAAY,QAAU,GAElB,KAAK,IAAI,EAAU,CAAC,EAAI,GAAK,KAAK,IAAI,EAAU,CAAC,EAAI,EAAG,CAC1D,IAAM,EAA0B,GAA2B,CAAI,EAE3D,GACF,EAAwB,SAAS,CAC/B,IAAK,EAAU,EACf,KAAM,EAAU,CAClB,CAAC,CAEL,CACF,EAAG,CAAC,EAAY,EAAG,EAAG,EAAa,CAAO,CAAC,CAC7C,CAEA,IAAM,IAAsC,EAAA,EAAA,cAAA,CAAc,CAAE,GAAG,GAC7D,OAAQ,EACR,OAAQ,CACV,CAAC,EACG,IAEH,SAAU,EAAQ,CACjB,EAAO,EAAO,cAAmB,GAAK,gBACtC,EAAO,EAAO,aAAkB,GAAK,eACrC,EAAO,EAAO,YAAiB,GAAK,aACtC,EAAA,CAAG,AAAW,KAAS,CAAC,CAAE,EAE1B,IAAM,IAA0B,EAAA,EAAA,KAAA,CAAK,SAAoB,EAAM,CAG7D,GAAI,CACF,KACA,gBACA,aAAa,GACb,WACA,UAAU,GACV,qBAAqB,GACrB,YACA,YACA,GAAG,GACD,EAEE,CAAC,EAAO,IAAA,EAAA,EAAA,WAAA,CADW,GAAS,IAAA,GAAW,EACf,EACxB,CAAC,EAAsB,GAA2B,GAAsB,EACxE,CAAC,EAAQ,IAAA,EAAA,EAAA,SAAA,CAAsB,GAAO,aAAa,EACnD,EAAgB,IAAW,GAAO,YAClC,CACJ,UAAW,CACT,OAAQ,EACR,MAAO,EACP,aAEF,UAAW,CACT,WAAY,IAEZ,EACE,EAAO,GAAY,KAAsC,KAA/B,EAAe,IAAI,CAAQ,EACrD,GAAA,EAAA,EAAA,OAAA,CAAqB,CACzB,QAAS,KACT,WAAY,IACd,CAAC,EACK,GAAA,EAAA,EAAA,QAAA,KAGG,GAAY,KAKf,KALsB,CACxB,GAAI,EAEJ,KAAoB,GAA6B,MAA6B,GAC9E,KAAM,CACR,EACC,CAAC,EAAU,CAAI,CAAC,EACb,GAAA,EAAA,EAAA,OAAA,CAAmB,IAAI,EACvB,CAAC,GAAc,KAAA,EAAA,EAAA,SAAA,CAA4B,IAAI,EAC/C,CAAC,GAAgB,KAAA,EAAA,EAAA,SAAA,CAA8B,IAAI,EACnD,GAAc,GAAe,EAAO,OAAO,OAAO,CAAK,CAAC,EACxD,GAAyB,GAAY,iBAAkB,CAAE,EACzD,IAAA,EAAA,EAAA,QAAA,KAA2C,EAAoB,WAAW,EAAG,CAAC,CAAmB,CAAC,EAClG,GAAyB,GAA0B,CAAS,EAC5D,CACJ,kBACA,8BACA,uBACE,GAAsB,GAA4B,CACpD,SAAU,EACV,aAAc,CAAC,EAAU,EAAG,EAAU,CAAC,EACvC,OAAQ,GAAuB,SACjC,CAAC,EACK,EAAa,GAAc,EAAgB,CAAQ,EACnD,IAAA,EAAA,EAAA,QAAA,KAAsC,GAAiB,GAAoB,EAAc,EAAI,KAAM,CAAC,EAAc,CAAC,EACnH,GAAoB,GAAuB,EAC3C,GAAwB,GAAe,EAAY,GAAuB,UAAU,OAAO,EACjG,GAAiC,CAC/B,WAAY,GAAY,KAAsC,KAA/B,EAAe,IAAI,CAAQ,EAC1D,OAAQ,GAAkB,wBAC1B,YAAa,GACb,QAAS,GAAuB,UAAU,OAC5C,CAAC,EACD,IAAM,EAAiB,GAAQ,EAAY,GAAuB,UAAU,QAAS,EAAqB,EACpG,GAAoB,GAAQ,EAAa,EAAW,cAAgB,IAAI,EACxE,GAAA,EAAA,EAAA,OAAA,CAAuB,CAC3B,eAAgB,KAChB,OAAQ,KACR,aACA,cAAe,KACf,WAAY,KACZ,kBACA,iBACA,aAAc,KACd,iBAAkB,KAClB,sBACA,KAAM,KACN,oBAAqB,CAAC,EACtB,wBAAyB,IAC3B,CAAC,EACK,EAAW,EAAoB,WAAoC,EAAc,QAAQ,MAA+C,EAAE,EAC1I,GAAc,GAAwB,CAC1C,QAAS,GAAuB,YAAY,OAC9C,CAAC,EAEK,GAAwC,GAAY,QAAQ,SAA2C,EACvG,GAAmB,EAAqC,GAAY,MAAoC,EAAiB,KACzH,EAAkB,GAAQ,GAAY,QAAQ,SAAW,GAAY,MAGrE,EAAgB,GAAa,EAAkB,KAAO,CAAc,EAEpE,GAAa,GAAc,GAAe,EAAU,EAAY,EAAI,IAAI,EAExE,EAAsB,GAAuB,EAAgB,GAA8B,EAAa,IAAI,EAC5G,EAA0B,GAAS,CAAmB,EAEtD,EAAoB,GAAe,EAAW,CAClD,UAAW,CACT,EAAG,EAAU,EAAI,EAAc,EAC/B,EAAG,EAAU,EAAI,EAAc,EAC/B,OAAQ,EACR,OAAQ,CACV,EACA,kBACA,SACA,iBACA,qBACA,oBACA,KAAM,EAAc,QAAQ,KAC5B,gBAAiB,GAAY,KAC7B,sBACA,0BACA,aACF,CAAC,EACK,EAAqB,GAAwB,GAAI,GAAuB,CAAS,EAAI,KACrF,EAAgB,GAAiB,CAAmB,EAEpD,EAAmB,GAAsB,CAAa,EAEtD,EAAwB,GAAsB,EAAe,CAAC,CAAc,CAAC,EAC7E,EAA0B,GAAI,EAAmB,CAAgB,EACjE,EAAgB,GAAmB,GAAgB,GAAkB,CAAiB,EAAI,KAC1F,EAAa,GAAU,EAAgB,EAAmB,CAC9D,SACA,gBACA,kBACA,oBAAqB,GACrB,oBACF,CAAC,EAAI,KACC,GAAS,GAAkB,EAAY,IAAI,EAC3C,CAAC,EAAM,IAAA,EAAA,EAAA,SAAA,CAAoB,IAAI,EAI/B,GAAY,GADO,EAAkB,EAAoB,GAAI,EAAmB,CAAqB,EAC7C,GAA6B,MAA6B,KAAM,CAAc,EACtI,IAAA,EAAA,EAAA,OAAA,CAAyB,IAAI,EAC7B,IAAA,EAAA,EAAA,YAAA,EAAiC,EAAO,IAAU,CACtD,GAAI,CACF,OAAQ,EACR,WACE,EAEJ,GAAI,EAAU,SAAW,KACvB,OAGF,IAAM,EAAa,EAAe,IAAI,EAAU,OAAO,EAEvD,GAAI,CAAC,EACH,OAGF,IAAM,EAAiB,EAAM,YACvB,EAAiB,IAAI,EAAO,CAChC,OAAQ,EAAU,QAClB,aACA,MAAO,EACP,UAGA,QAAS,EAET,QAAQ,EAAI,CAGV,GAAI,CAFkB,EAAe,IAAI,CAExB,EACf,OAGF,GAAM,CACJ,eACE,GAAY,QACV,EAAQ,CACZ,IACF,EACA,IAA2C,CAAK,EAChD,EAAqB,CACnB,KAAM,cACN,OACF,CAAC,CACH,EAEA,UAAU,EAAI,EAAY,EAAoB,EAAQ,CAGpD,GAAI,CAFkB,EAAe,IAAI,CAExB,EACf,OAGF,GAAM,CACJ,iBACE,GAAY,QACV,EAAQ,CACZ,KACA,aACA,qBACA,QACF,EACA,IAA+C,CAAK,EACpD,EAAqB,CACnB,KAAM,gBACN,OACF,CAAC,CACH,EAEA,QAAQ,EAAoB,CAC1B,IAAM,EAAK,EAAU,QAErB,GAAI,GAAM,KACR,OAGF,IAAM,EAAgB,EAAe,IAAI,CAAE,EAE3C,GAAI,CAAC,EACH,OAGF,GAAM,CACJ,eACE,GAAY,QACV,EAAQ,CACZ,iBACA,OAAQ,CACN,KACA,KAAM,EAAc,KACpB,KAAM,CACR,CACF,GACA,EAAA,EAAA,wBAAA,KAA8B,CAC5B,IAA2C,CAAK,EAChD,EAAU,GAAO,YAAY,EAC7B,EAAS,CACP,KAAM,EAAO,UACb,qBACA,OAAQ,CACV,CAAC,EACD,EAAqB,CACnB,KAAM,cACN,OACF,CAAC,EACD,GAAgB,GAAgB,OAAO,EACvC,GAAkB,CAAc,CAClC,CAAC,CACH,EAEA,OAAO,EAAa,CAClB,EAAS,CACP,KAAM,EAAO,SACb,aACF,CAAC,CACH,EAEA,MAAO,EAAc,EAAO,OAAO,EACnC,SAAU,EAAc,EAAO,UAAU,CAC3C,CAAC,EACD,GAAgB,QAAU,EAE1B,SAAS,EAAc,EAAM,CAC3B,OAAO,gBAAyB,CAC9B,GAAM,CACJ,SACA,aACA,OACA,2BACE,EAAc,QACd,EAAQ,KAEZ,GAAI,GAAU,EAAyB,CACrC,GAAM,CACJ,cACE,GAAY,QAChB,EAAQ,CACN,iBACQ,SACR,aACA,MAAO,EACP,MACF,EAEI,IAAS,EAAO,SAAW,OAAO,GAAe,YAG/C,MAFuB,QAAQ,QAAQ,EAAW,CAAK,CAAC,IAG1D,EAAO,EAAO,WAGpB,CAEA,EAAU,QAAU,MACpB,EAAA,EAAA,wBAAA,KAA8B,CAC5B,EAAS,CACP,MACF,CAAC,EACD,EAAU,GAAO,aAAa,EAC9B,EAAQ,IAAI,EACZ,GAAgB,IAAI,EACpB,GAAkB,IAAI,EACtB,GAAgB,QAAU,KAC1B,IAAM,EAAY,IAAS,EAAO,QAAU,YAAc,eAE1D,GAAI,EAAO,CACT,IAAM,EAAU,GAAY,QAAQ,GACpC,IAAmC,CAAK,EACxC,EAAqB,CACnB,KAAM,EACN,OACF,CAAC,CACH,CACF,CAAC,CACH,CACF,CACF,EACA,CAAC,CAAc,CAAC,EA2BV,GAAa,GAAqB,GAAA,EAAA,EAAA,YAAA,EA1Be,EAAS,KACtD,EAAO,IAAW,CACxB,IAAM,EAAc,EAAM,YACpB,EAAsB,EAAe,IAAI,CAAM,EAErD,GACA,EAAU,UAAY,MACtB,CAAC,GACD,EAAY,QAAU,EAAY,iBAChC,OAGF,IAAM,EAAoB,CACxB,OAAQ,CACV,EACuB,EAAQ,EAAO,EAAO,QAAS,CAErC,IAAM,KACrB,EAAY,OAAS,CACnB,WAAY,EAAO,MACrB,EACA,EAAU,QAAU,EACpB,GAAkB,EAAO,CAAM,EAEnC,EACC,CAAC,EAAgB,EAAiB,CAC4C,CAAC,EAClF,GAAe,CAAO,EACtB,OAAgC,CAC1B,GAAkB,IAAW,GAAO,cACtC,EAAU,GAAO,WAAW,CAEhC,EAAG,CAAC,EAAgB,CAAM,CAAC,GAC3B,EAAA,EAAA,UAAA,KAAgB,CACd,GAAM,CACJ,cACE,GAAY,QACV,CACJ,SACA,iBACA,aACA,QACE,EAAc,QAElB,GAAI,CAAC,GAAU,CAAC,EACd,OAGF,IAAM,EAAQ,CACZ,SACA,iBACA,aACA,MAAO,CACL,EAAG,EAAwB,EAC3B,EAAG,EAAwB,CAC7B,EACA,MACF,GACA,EAAA,EAAA,wBAAA,KAA8B,CAC5B,IAAyC,CAAK,EAC9C,EAAqB,CACnB,KAAM,aACN,OACF,CAAC,CACH,CAAC,CACH,EACA,CAAC,EAAwB,EAAG,EAAwB,CAAC,CAAC,GACtD,EAAA,EAAA,UAAA,KAAgB,CACd,GAAM,CACJ,SACA,iBACA,aACA,sBACA,2BACE,EAAc,QAElB,GAAI,CAAC,GAAU,EAAU,SAAW,MAAQ,CAAC,GAAkB,CAAC,EAC9D,OAGF,GAAM,CACJ,cACE,GAAY,QACV,EAAgB,EAAoB,IAAI,EAAM,EAC9C,EAAO,GAAiB,EAAc,KAAK,QAAU,CACzD,GAAI,EAAc,GAClB,KAAM,EAAc,KAAK,QACzB,KAAM,EAAc,KACpB,SAAU,EAAc,QAC1B,EAAI,KACE,EAAQ,CACZ,SACA,iBACA,aACA,MAAO,CACL,EAAG,EAAwB,EAC3B,EAAG,EAAwB,CAC7B,EACA,MACF,GACA,EAAA,EAAA,wBAAA,KAA8B,CAC5B,EAAQ,CAAI,EACZ,IAAyC,CAAK,EAC9C,EAAqB,CACnB,KAAM,aACN,OACF,CAAC,CACH,CAAC,CACH,EACA,CAAC,EAAM,CAAC,EACR,OAAgC,CAC9B,EAAc,QAAU,CACtB,kBACA,SACA,aACA,gBACA,aACA,kBACA,iBACA,gBACA,oBACA,sBACA,OACA,sBACA,yBACF,EACA,EAAY,QAAU,CACpB,QAAS,GACT,WAAY,CACd,CACF,EAAG,CAAC,EAAQ,EAAY,EAAY,EAAe,EAAgB,GAAc,GAAkB,GAAgB,EAAqB,EAAM,EAAqB,CAAuB,CAAC,EAC3L,GAAgB,CAAE,GAAG,GACnB,MAAO,EACP,aAAc,EACd,qBACA,sBACA,yBACF,CAAC,EACD,IAAM,IAAA,EAAA,EAAA,QAAA,MAoBG,CAlBL,SACA,aACA,iBACA,kBACA,aACA,qBACA,eACA,iBACA,sBACA,kBACA,OACA,8BACA,sBACA,0BACA,0BACA,sBACA,aAEW,GACZ,CAAC,EAAQ,EAAY,EAAgB,GAAgB,EAAY,GAAmB,GAAa,EAAgB,EAAqB,GAAgB,EAAM,GAA4B,EAAqB,EAAyB,GAAwB,GAAoB,EAAU,CAAC,EAC1R,IAAA,EAAA,EAAA,QAAA,MAcG,CAZL,kBACA,cACA,SACA,iBACA,kBAAmB,CACjB,UAAW,EACb,EACA,WACA,iBACA,OACA,6BAEW,GACZ,CAAC,GAAgB,GAAY,EAAQ,EAAgB,EAAU,GAAwB,EAAgB,EAAM,EAA0B,CAAC,EAC3I,OAAOA,EAAAA,QAAM,cAAc,GAAkB,SAAU,CACrD,MAAO,CACT,EAAGA,EAAAA,QAAM,cAAc,GAAgB,SAAU,CAC/C,MAAO,EACT,EAAGA,EAAAA,QAAM,cAAc,GAAc,SAAU,CAC7C,MAAO,EACT,EAAGA,EAAAA,QAAM,cAAc,GAAuB,SAAU,CACtD,MAAO,EACT,EAAG,CAAQ,CAAC,EAAGA,EAAAA,QAAM,cAAc,GAAc,CAC/C,SAAW,GAA+C,eAAkB,EAC9E,CAAC,CAAC,EAAGA,EAAAA,QAAM,cAAc,GAAe,CAAE,GAAG,EAC3C,wBAAyB,EAC3B,CAAC,CAAC,EAEF,SAAS,IAAyB,CAChC,IAAM,EAAkC,IAA6C,oBAAuB,GACtG,EAA6B,OAAO,GAAe,SAAW,EAAW,UAAY,GAAQ,IAAe,GAC5G,EAAU,GAAiB,CAAC,GAAkC,CAAC,EAQrE,OANI,OAAO,GAAe,SACjB,CAAE,GAAG,EACV,SACF,EAGK,CACL,SACF,CACF,CACF,CAAC,EAEK,IAA2B,EAAA,EAAA,cAAA,CAAc,IAAI,EAC7C,GAAc,SACdC,GAAY,YAClB,SAAS,GAAa,EAAM,CAC1B,GAAI,CACF,KACA,OACA,WAAW,GACX,cACE,EACE,EAAM,GAAYA,EAAS,EAC3B,CACJ,aACA,iBACA,SACA,iBACA,oBACA,iBACA,SAAA,EAAA,EAAA,WAAA,CACa,EAAe,EACxB,CACJ,OAAO,GACP,kBAAkB,YAClB,WAAW,GACT,GAAkC,CAAC,EACjC,EAAc,GAAiC,KAAQ,EACvD,GAAA,EAAA,EAAA,WAAA,CAAuB,EAAa,GAAyB,EAAW,EACxE,CAAC,EAAM,GAAc,GAAW,EAChC,CAAC,EAAe,GAAuB,GAAW,EAClD,EAAY,GAAsB,EAAY,CAAE,EAChD,EAAU,GAAe,CAAI,EA0BnC,OAzBA,QACE,EAAe,IAAI,EAAI,CACrB,KACA,MACA,OACA,gBACA,KAAM,CACR,CAAC,MACY,CACX,IAAM,EAAO,EAAe,IAAI,CAAE,EAE9B,GAAQ,EAAK,MAAQ,GACvB,EAAe,OAAO,CAAE,CAE5B,GAEF,CAAC,EAAgB,CAAE,CAAC,EASb,CACL,SACA,iBACA,iBACA,YAAA,EAAA,EAAA,QAAA,MAZwC,CACxC,OACA,WACA,gBAAiB,EACjB,eAAgB,GAAc,IAAS,GAAc,GAAO,IAAA,GAC5D,uBAAwB,EACxB,mBAAoB,EAAkB,SACxC,GAAI,CAAC,EAAU,EAAM,EAAU,EAAY,EAAiB,EAAkB,SAAS,CAKxD,EAC7B,aACA,UAAW,EAAW,IAAA,GAAY,EAClC,OACA,OACA,aACA,sBACA,WACF,CACF,CAEA,SAAS,IAAgB,CACvB,OAAA,EAAA,EAAA,WAAA,CAAkB,EAAa,CACjC,CAEA,IAAMC,GAAc,YACd,GAA8B,CAClC,QAAS,EACX,EACA,SAAS,GAAa,EAAM,CAC1B,GAAI,CACF,OACA,WAAW,GACX,KACA,wBACE,EACE,EAAM,GAAYA,EAAW,EAC7B,CACJ,SACA,WACA,OACA,+BAAA,EAAA,EAAA,WAAA,CACa,EAAe,EACxB,GAAA,EAAA,EAAA,OAAA,CAAkB,CACtB,UACF,CAAC,EACK,GAAA,EAAA,EAAA,OAAA,CAAiC,EAAK,EACtC,GAAA,EAAA,EAAA,OAAA,CAAc,IAAI,EAClB,GAAA,EAAA,EAAA,OAAA,CAAoB,IAAI,EACxB,CACJ,SAAU,EACV,wBACA,QAAS,GACP,CAAE,GAAG,GACP,GAAG,CACL,EACM,EAAM,GAAe,GAAwD,CAAE,EAmB/E,EAAiB,GAAkB,CACvC,UAAA,EAAA,EAAA,YAAA,KAnBqC,CACrC,GAAI,CAAC,EAAwB,QAAS,CAGpC,EAAwB,QAAU,GAClC,MACF,CAEI,EAAW,SAAW,MACxB,aAAa,EAAW,OAAO,EAGjC,EAAW,QAAU,eAAiB,CACpC,EAA2B,MAAM,QAAQ,EAAI,OAAO,EAAI,EAAI,QAAU,CAAC,EAAI,OAAO,CAAC,EACnF,EAAW,QAAU,IACvB,EAAG,CAAqB,CAC1B,EACA,CAAC,CAAqB,CAEC,EACrB,SAAU,GAA0B,CAAC,CACvC,CAAC,EAeK,CAAC,EAAS,GAAc,IAAA,EAAA,EAAA,YAAA,EAdQ,EAAY,IAAoB,CAC/D,IAID,IACF,EAAe,UAAU,CAAe,EACxC,EAAwB,QAAU,IAGhC,GACF,EAAe,QAAQ,CAAU,EAErC,EAAG,CAAC,CAAc,CACsC,CAAC,EACnD,EAAU,GAAe,CAAI,EAwCnC,OAvCA,EAAA,EAAA,UAAA,KAAgB,CACV,CAAC,GAAkB,CAAC,EAAQ,UAIhC,EAAe,WAAW,EAC1B,EAAwB,QAAU,GAClC,EAAe,QAAQ,EAAQ,OAAO,EACxC,EAAG,CAAC,EAAS,CAAc,CAAC,GAC5B,EAAA,EAAA,UAAA,MACE,EAAS,CACP,KAAM,EAAO,kBACb,QAAS,CACP,KACA,MACA,WACA,KAAM,EACN,OACA,KAAM,CACR,CACF,CAAC,MACY,EAAS,CACpB,KAAM,EAAO,oBACb,MACA,IACF,CAAC,GAEH,CAAC,CAAE,CAAC,GACJ,EAAA,EAAA,UAAA,KAAgB,CACV,IAAa,EAAS,QAAQ,WAChC,EAAS,CACP,KAAM,EAAO,qBACb,KACA,MACA,UACF,CAAC,EACD,EAAS,QAAQ,SAAW,EAEhC,EAAG,CAAC,EAAI,EAAK,EAAU,CAAQ,CAAC,EACzB,CACL,SACA,OACA,OAAS,GAA6B,KAAQ,EAC9C,KAAM,EACN,OACA,YACF,CACF,CCh/GA,SAAS,GAAU,EAAO,EAAM,EAAI,CAClC,IAAM,EAAW,EAAM,MAAM,EAE7B,OADA,EAAS,OAAO,EAAK,EAAI,EAAS,OAAS,EAAK,EAAI,EAAG,EAAS,OAAO,EAAM,CAAC,CAAC,CAAC,EAAE,EAC3E,CACT,CAYA,SAAS,GAAe,EAAO,EAAO,CACpC,OAAO,EAAM,QAAQ,EAAa,EAAI,IAAU,CAC9C,IAAM,EAAO,EAAM,IAAI,CAAE,EAMzB,OAJI,IACF,EAAY,GAAS,GAGhB,CACT,EAAG,MAAM,EAAM,MAAM,CAAC,CACxB,CAEA,SAAS,GAAa,EAAO,CAC3B,OAAO,IAAU,MAAQ,GAAS,CACpC,CAEA,SAAS,GAAW,EAAG,EAAG,CACxB,GAAI,IAAM,EACR,MAAO,GAGT,GAAI,EAAE,SAAW,EAAE,OACjB,MAAO,GAGT,IAAK,IAAI,EAAI,EAAG,EAAI,EAAE,OAAQ,IAC5B,GAAI,EAAE,KAAO,EAAE,GACb,MAAO,GAIX,MAAO,EACT,CAEA,SAAS,GAAkB,EAAU,CAQnC,OAPI,OAAO,GAAa,UACf,CACL,UAAW,EACX,UAAW,CACb,EAGK,CACT,CA8EA,IAAM,GAAsB,GAAQ,CAClC,GAAI,CACF,QACA,cACA,YACA,SACE,EACE,EAAW,GAAU,EAAO,EAAW,CAAW,EAClD,EAAU,EAAM,GAChB,EAAU,EAAS,GAMzB,MAJI,CAAC,GAAW,CAAC,EACR,KAGF,CACL,EAAG,EAAQ,KAAO,EAAQ,KAC1B,EAAG,EAAQ,IAAM,EAAQ,IACzB,OAAQ,EAAQ,MAAQ,EAAQ,MAChC,OAAQ,EAAQ,OAAS,EAAQ,MACnC,CACF,EAmCM,GAAiB,CACrB,OAAQ,EACR,OAAQ,CACV,EACM,GAA8B,GAAQ,CAG1C,GAAI,CACF,cACA,eAAgB,EAChB,QACA,QACA,aACE,EACE,EAAuC,EAAM,IAA6C,EAEhG,GAAI,CAAC,EACH,OAAO,KAGT,GAAI,IAAU,EAAa,CACzB,IAAM,EAAgB,EAAM,GAM5B,OAJK,EAIE,CACL,EAAG,EACH,EAAG,EAAc,EAAY,EAAc,IAAM,EAAc,QAAU,EAAe,IAAM,EAAe,QAAU,EAAc,IAAM,EAAe,IAC1J,GAAG,EACL,EAPS,IAQX,CAEA,IAAM,EAAU,GAAa,EAAO,EAAO,CAAW,EAkBtD,OAhBI,EAAQ,GAAe,GAAS,EAC3B,CACL,EAAG,EACH,EAAG,CAAC,EAAe,OAAS,EAC5B,GAAG,EACL,EAGE,EAAQ,GAAe,GAAS,EAC3B,CACL,EAAG,EACH,EAAG,EAAe,OAAS,EAC3B,GAAG,EACL,EAGK,CACL,EAAG,EACH,EAAG,EACH,GAAG,EACL,CACF,EAEA,SAAS,GAAa,EAAa,EAAO,EAAa,CACrD,IAAM,EAAc,EAAY,GAC1B,EAAe,EAAY,EAAQ,GACnC,EAAW,EAAY,EAAQ,GAUrC,OARK,EAID,EAAc,EACT,EAAe,EAAY,KAAO,EAAa,IAAM,EAAa,QAAU,EAAW,EAAS,KAAO,EAAY,IAAM,EAAY,QAAU,EAGjJ,EAAW,EAAS,KAAO,EAAY,IAAM,EAAY,QAAU,EAAe,EAAY,KAAO,EAAa,IAAM,EAAa,QAAU,EAP7I,CAQX,CAEA,IAAM,GAAY,WACZ,GAAuB,EAAA,QAAM,cAAc,CAC/C,YAAa,GACb,YAAa,GACb,kBAAmB,GACnB,MAAO,CAAC,EACR,UAAW,GACX,eAAgB,GAChB,YAAa,CAAC,EACd,SAAU,GACV,SAAU,CACR,UAAW,GACX,UAAW,EACb,CACF,CAAC,EACD,SAAS,GAAgB,EAAM,CAC7B,GAAI,CACF,WACA,KACA,MAAO,EACP,WAAW,GACX,SAAU,EAAe,IACvB,EACE,CACJ,SACA,cACA,iBACA,OACA,8BACE,GAAc,EACZ,EAAc,GAAY,GAAW,CAAE,EACvC,EAAyB,EAAY,OAAS,KAC9C,GAAA,EAAA,EAAA,QAAA,KAAsB,EAAiB,IAAI,GAAQ,OAAO,GAAS,UAAY,OAAQ,EAAO,EAAK,GAAK,CAAI,EAAG,CAAC,CAAgB,CAAC,EACjI,EAAa,GAAU,KACvB,EAAc,EAAS,EAAM,QAAQ,EAAO,EAAE,EAAI,GAClD,EAAY,EAAO,EAAM,QAAQ,EAAK,EAAE,EAAI,GAC5C,GAAA,EAAA,EAAA,OAAA,CAA0B,CAAK,EAC/B,EAAmB,CAAC,GAAW,EAAO,EAAiB,OAAO,EAC9D,EAAoB,IAAc,IAAM,IAAgB,IAAM,EAC9D,EAAW,GAAkB,CAAY,EAC/C,OAAgC,CAC1B,GAAoB,GACtB,EAA2B,CAAK,CAEpC,EAAG,CAAC,EAAkB,EAAO,EAAY,CAA0B,CAAC,GACpE,EAAA,EAAA,UAAA,KAAgB,CACd,EAAiB,QAAU,CAC7B,EAAG,CAAC,CAAK,CAAC,EACV,IAAM,GAAA,EAAA,EAAA,QAAA,MAA8B,CAClC,cACA,cACA,WACA,oBACA,QACA,YACA,iBACA,YAAa,GAAe,EAAO,CAAc,EACjD,UACF,GACA,CAAC,EAAa,EAAa,EAAS,UAAW,EAAS,UAAW,EAAmB,EAAO,EAAW,EAAgB,EAAgB,CAAQ,CAAC,EACjJ,OAAOC,EAAAA,QAAM,cAAc,GAAQ,SAAU,CAC3C,MAAO,CACT,EAAG,CAAQ,CACb,CAEA,IAAM,GAAwB,GAAQ,CACpC,GAAI,CACF,KACA,QACA,cACA,aACE,EACJ,OAAO,GAAU,EAAO,EAAa,CAAS,CAAC,CAAC,QAAQ,CAAE,CAC5D,EACM,GAA8B,GAAS,CAC3C,GAAI,CACF,cACA,YACA,cACA,QACA,QACA,WACA,gBACA,sBACA,cACE,EAcJ,MAZI,CAAC,GAAc,CAAC,GAIhB,IAAkB,GAAS,IAAU,EAChC,GAGL,EACK,GAGF,IAAa,GAAS,IAAgB,CAC/C,EACM,GAAoB,CACxB,SAAU,IACV,OAAQ,MACV,EACM,GAAqB,YACrB,GAAkC,GAAI,WAAW,SAAS,CAC9D,SAAU,GACV,SAAU,EACV,OAAQ,QACV,CAAC,EACK,GAAoB,CACxB,gBAAiB,UACnB,EAOA,SAAS,GAAoB,EAAM,CACjC,GAAI,CACF,WACA,QACA,OACA,QACE,EACE,CAAC,EAAkB,IAAA,EAAA,EAAA,SAAA,CAAgC,IAAI,EACvD,GAAA,EAAA,EAAA,OAAA,CAAuB,CAAK,EA+BlC,OA9BA,OAAgC,CAC9B,GAAI,CAAC,GAAY,IAAU,EAAc,SAAW,EAAK,QAAS,CAChE,IAAM,EAAU,EAAK,QAErB,GAAI,EAAS,CACX,IAAM,EAAU,GAAc,EAAK,QAAS,CAC1C,gBAAiB,EACnB,CAAC,EACK,EAAQ,CACZ,EAAG,EAAQ,KAAO,EAAQ,KAC1B,EAAG,EAAQ,IAAM,EAAQ,IACzB,OAAQ,EAAQ,MAAQ,EAAQ,MAChC,OAAQ,EAAQ,OAAS,EAAQ,MACnC,GAEI,EAAM,GAAK,EAAM,IACnB,EAAoB,CAAK,CAE7B,CACF,CAEI,IAAU,EAAc,UAC1B,EAAc,QAAU,EAE5B,EAAG,CAAC,EAAU,EAAO,EAAM,CAAI,CAAC,GAChC,EAAA,EAAA,UAAA,KAAgB,CACV,GACF,EAAoB,IAAI,CAE5B,EAAG,CAAC,CAAgB,CAAC,EACd,CACT,CAEA,SAAS,GAAY,EAAM,CACzB,GAAI,CACF,uBAAuB,GACvB,WAAY,EACZ,SAAU,EACV,KAAM,EACN,cAAc,GACd,KACA,SAAU,EACV,uBACA,aAAa,IACX,EACE,CACJ,QACA,cACA,cACA,SAAU,EACV,oBACA,cACA,YACA,iBACA,SAAU,IAAA,EAAA,EAAA,WAAA,CACG,EAAO,EAChB,EAAW,GAAuB,EAAe,CAAc,EAC/D,EAAQ,EAAM,QAAQ,CAAE,EACxB,GAAA,EAAA,EAAA,QAAA,MAAsB,CAC1B,SAAU,CACR,cACA,QACA,OACF,EACA,GAAG,CACL,GAAI,CAAC,EAAa,EAAY,EAAO,CAAK,CAAC,EACrC,GAAA,EAAA,EAAA,QAAA,KAA0C,EAAM,MAAM,EAAM,QAAQ,CAAE,CAAC,EAAG,CAAC,EAAO,CAAE,CAAC,EACrF,CACJ,OACA,OACA,SACA,WAAY,IACV,GAAa,CACf,KACA,OACA,SAAU,EAAS,UACnB,qBAAsB,CACpB,sBAAuB,EACvB,GAAG,CACL,CACF,CAAC,EACK,CACJ,UACA,kBACA,kBACA,cACA,WAAY,GACZ,aACA,cACA,QACA,uBACA,cACE,GAAa,CACf,KACA,OACA,WAAY,CAAE,GAAG,GACf,GAAG,CACL,EACA,SAAU,EAAS,SACrB,CAAC,EACK,EAAa,GAAgB,GAAqB,EAAmB,EACrE,GAAY,EAAQ,GACpB,GAAe,IAAa,CAAC,GAAqB,GAAa,CAAW,GAAK,GAAa,CAAS,EACrG,GAA2B,CAAC,GAAkB,GAG9C,EAAiB,IAFQ,IAA4B,GAAe,GAAY,QACrE,GAAwC,EAAA,CACgD,CACvG,MAAO,EACP,kBACA,cACA,YACA,OACF,CAAC,EAAI,KACC,GAAW,GAAa,CAAW,GAAK,GAAa,CAAS,EAAI,EAAY,CAClF,KACA,QACA,cACA,WACF,CAAC,EAAI,EACC,EAAW,IAAiC,GAC5C,GAAA,EAAA,EAAA,OAAA,CAAkB,CACtB,WACA,QACA,YACA,aACF,CAAC,EACK,GAAmB,IAAU,EAAS,QAAQ,MAC9C,GAA6B,EAAqB,CACtD,UACA,cACA,cACA,aACA,KACA,QACA,QACA,SAAU,EAAS,QAAQ,SAC3B,cAAe,EAAS,QAAQ,MAChC,oBAAqB,EAAS,QAAQ,YACtC,aACA,YAAa,EAAS,QAAQ,UAAY,IAC5C,CAAC,EACK,GAAmB,GAAoB,CAC3C,SAAU,CAAC,GACX,QACA,OACA,MACF,CAAC,EA6BD,OA5BA,EAAA,EAAA,UAAA,KAAgB,CACV,IAAa,EAAS,QAAQ,WAAa,KAC7C,EAAS,QAAQ,SAAW,IAG1B,IAAgB,EAAS,QAAQ,cACnC,EAAS,QAAQ,YAAc,GAG7B,IAAU,EAAS,QAAQ,QAC7B,EAAS,QAAQ,MAAQ,EAE7B,EAAG,CAAC,GAAW,GAAU,EAAa,CAAK,CAAC,GAC5C,EAAA,EAAA,UAAA,KAAgB,CACd,GAAI,IAAa,EAAS,QAAQ,SAChC,OAGF,GAAI,GAAY,MAAQ,EAAS,QAAQ,UAAY,KAAM,CACzD,EAAS,QAAQ,SAAW,EAC5B,MACF,CAEA,IAAM,EAAY,eAAiB,CACjC,EAAS,QAAQ,SAAW,CAC9B,EAAG,EAAE,EACL,UAAa,aAAa,CAAS,CACrC,EAAG,CAAC,CAAQ,CAAC,EACN,CACL,UACA,cACA,cACA,OACA,OACA,QACA,YACA,QACA,SACA,aACA,cACA,aACA,OACA,YACA,QACA,aACA,uBACA,uBACA,uBACA,UAAW,IAA8C,EACzD,WAAY,EAAc,CAC5B,EAEA,SAAS,GAAgB,CACvB,GACA,IACA,IAAoB,EAAS,QAAQ,WAAa,EAChD,OAAO,GAGL,SAA4B,CAAC,GAAgB,EAAc,GAAK,CAAC,KAIjE,IAAa,IACf,OAAO,GAAI,WAAW,SAAS,CAAE,GAAG,EAClC,SAAU,EACZ,CAAC,CAIL,CACF,CAEA,SAAS,GAAuB,EAAe,EAAgB,CAW7D,OARI,OAAO,GAAkB,UACpB,CACL,UAAW,EAEX,UAAW,EACb,EAGK,CACL,UAAoC,GAA+C,WAA6C,EAAe,UAC/I,UAAoC,GAA+C,WAA6C,EAAe,SACjJ,CACF,CAEA,SAAS,GAAgB,EAAO,CAC9B,GAAI,CAAC,EACH,MAAO,GAGT,IAAM,EAAO,EAAM,KAAK,QAMxB,MAJA,GAAI,GAAQ,aAAc,GAAQ,OAAO,EAAK,UAAa,UAAY,gBAAiB,EAAK,UAAY,UAAW,EAAK,UAAY,UAAW,EAAK,SAKvJ,CAEA,IAAM,GAAa,CAAC,EAAa,KAAM,EAAa,MAAO,EAAa,GAAI,EAAa,IAAI,EACvF,IAA+B,EAAO,IAAS,CACnD,GAAI,CACF,QAAS,CACP,SACA,gBACA,iBACA,sBACA,OACA,wBAEA,EAEJ,GAAI,GAAW,SAAS,EAAM,IAAI,EAAG,CAGnC,GAFA,EAAM,eAAe,EAEjB,CAAC,GAAU,CAAC,EACd,OAGF,IAAM,EAAqB,CAAC,EAC5B,EAAoB,WAAW,CAAC,CAAC,QAAQ,GAAS,CAChD,GAAI,CAAC,GAAS,GAAS,MAAQ,EAAM,SACnC,OAGF,IAAM,EAAO,EAAe,IAAI,EAAM,EAAE,EAEnC,KAIL,OAAQ,EAAM,KAAd,CACE,KAAK,EAAa,KACZ,EAAc,IAAM,EAAK,KAC3B,EAAmB,KAAK,CAAK,EAG/B,MAEF,KAAK,EAAa,GACZ,EAAc,IAAM,EAAK,KAC3B,EAAmB,KAAK,CAAK,EAG/B,MAEF,KAAK,EAAa,KACZ,EAAc,KAAO,EAAK,MAC5B,EAAmB,KAAK,CAAK,EAG/B,MAEF,KAAK,EAAa,MACZ,EAAc,KAAO,EAAK,MAC5B,EAAmB,KAAK,CAAK,EAG/B,KACJ,CACF,CAAC,EACD,IAAM,EAAa,GAAe,CAChC,SACe,gBACf,iBACA,oBAAqB,EACrB,mBAAoB,IACtB,CAAC,EACG,EAAY,GAAkB,EAAY,IAAI,EAMlD,GAJI,IAAe,GAA6B,IAAO,EAAW,OAAS,IACzE,EAAY,EAAW,EAAE,CAAC,IAGxB,GAAa,KAAM,CACrB,IAAM,EAAkB,EAAoB,IAAI,EAAO,EAAE,EACnD,EAAe,EAAoB,IAAI,CAAS,EAChD,EAAU,EAAe,EAAe,IAAI,EAAa,EAAE,EAAI,KAC/D,EAAU,GAA6C,KAAK,QAElE,GAAI,GAAW,GAAW,GAAmB,EAAc,CAEzD,IAAM,EADqB,GAAuB,CACG,CAAC,CAAC,MAAM,EAAS,IAAU,EAAoB,KAAW,CAAO,EAChH,EAAmB,GAAgB,EAAiB,CAAY,EAChE,EAAgB,GAAQ,EAAiB,CAAY,EACrD,EAAS,GAA+B,CAAC,EAAmB,CAChE,EAAG,EACH,EAAG,CACL,EAAI,CACF,EAAG,EAAgB,EAAc,MAAQ,EAAQ,MAAQ,EACzD,EAAG,EAAgB,EAAc,OAAS,EAAQ,OAAS,CAC7D,EACM,EAAkB,CACtB,EAAG,EAAQ,KACX,EAAG,EAAQ,GACb,EAEA,OADuB,EAAO,GAAK,EAAO,EAAI,EAAkB,GAAS,EAAiB,CAAM,CAElG,CACF,CACF,CAGF,EAEA,SAAS,GAAgB,EAAG,EAAG,CAK7B,MAJI,CAAC,GAAgB,CAAC,GAAK,CAAC,GAAgB,CAAC,EACpC,GAGF,EAAE,KAAK,QAAQ,SAAS,cAAgB,EAAE,KAAK,QAAQ,SAAS,WACzE,CAEA,SAAS,GAAQ,EAAG,EAAG,CASrB,MARI,CAAC,GAAgB,CAAC,GAAK,CAAC,GAAgB,CAAC,GAIzC,CAAC,GAAgB,EAAG,CAAC,EAChB,GAGF,EAAE,KAAK,QAAQ,SAAS,MAAQ,EAAE,KAAK,QAAQ,SAAS,KACjE,CC1uBA,IAAM,GAAe,IAOrB,SAAS,GAAa,EAAwB,CAC5C,IAAM,EAAM,EAAM,QAAQ,IAAK,EAAE,EACjC,GAAI,EAAI,SAAW,GAAK,EAAI,SAAW,EAGrC,OADI,IAAU,SAAW,IAAU,QAAU,IAAU,UAGzD,IAAM,EAAO,EAAI,SAAW,EAAI,EAAI,MAAM,EAAE,CAAC,CAAC,IAAK,GAAM,EAAI,CAAC,CAAC,CAAC,KAAK,EAAE,EAAI,EACrE,EAAI,SAAS,EAAK,MAAM,EAAG,CAAC,EAAG,EAAE,EAAI,IACrC,EAAI,SAAS,EAAK,MAAM,EAAG,CAAC,EAAG,EAAE,EAAI,IACrC,EAAI,SAAS,EAAK,MAAM,EAAG,CAAC,EAAG,EAAE,EAAI,IAG3C,MADY,OAAS,EAAI,MAAS,EAAI,MAAS,EAClC,GACf,CAEA,SAAS,GACP,EACA,EACyB,CACzB,IAAM,EAAQ,GAAS,CAAC,EACxB,GAAI,IAAa,SAAU,OAAO,EAClC,IAAM,EAAU,EAAK,QAAkD,CAAC,EACxE,MAAO,CAAE,GAAG,EAAM,GAAG,CAAO,CAC9B,CAEA,SAAgB,IAAS,CACvB,GAAM,CACJ,MACA,YACA,eACA,iBACA,eACA,kBACA,gBACA,cACA,YACE,EAAc,EAEZ,EAAU,GACd,GAAU,GAAe,CAAE,qBAAsB,CAAE,SAAU,CAAE,CAAE,CAAC,EAClE,GAAU,GAAgB,CAAE,iBAAkB,EAA4B,CAAC,CAC7E,EAEM,EAAiB,GAAoB,CACzC,GAAM,CAAE,SAAQ,QAAS,EACzB,GAAI,CAAC,GAAQ,EAAO,KAAO,EAAK,GAAI,OACpC,IAAM,EAAO,EAAI,QAAQ,UAAW,GAAM,EAAE,KAAO,EAAO,EAAE,EACtD,EAAK,EAAI,QAAQ,UAAW,GAAM,EAAE,KAAO,EAAK,EAAE,EACpD,IAAS,IAAM,IAAO,IAC1B,EAAe,EAAM,CAAE,CACzB,GAGA,EAAA,EAAA,UAAA,KAAgB,CACd,IAAM,EAAW,GAAqB,CACpC,GAAI,EAAE,MAAQ,UAAY,EAAE,MAAQ,YAAa,OACjD,IAAM,EAAS,EAAE,OACb,EAAO,UAAY,SAAW,EAAO,UAAY,YAAc,EAAO,oBAEtE,GAAW,OAAS,SAAU,EAAa,EAAU,QAAQ,EACxD,GAAW,OAAS,WAC3B,EAAc,EAAU,SAAU,EAAU,SAAS,EACzD,EAEA,OADA,OAAO,iBAAiB,UAAW,CAAO,MAC7B,OAAO,oBAAoB,UAAW,CAAO,CAC5D,EAAG,CAAC,EAAW,EAAc,CAAa,CAAC,EAE3C,IAAM,EAAK,EAAa,EAAI,SAAS,gBAAiB,EAAI,KAAK,EACzD,EAAM,EAAa,EAAI,SAAS,uBAAwB,EAAI,KAAK,EAEjE,EAAe,EAAI,QAAQ,IAAK,GAAM,EAAE,EAAE,EAC1C,EAAc,IAAa,SAAW,GAAe,EAAI,SAAS,MAExE,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,UAAU,yBACV,MAAO,CAAE,WAAY,CAAG,EACxB,YAAe,EAAa,CAAE,KAAM,OAAQ,CAAC,YAE7C,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,qCACb,EAAA,EAAA,KAAA,CAAC,MAAD,CACE,UAAW,yCAAyC,IAAa,SAAW,+CAAiD,KAC7H,MAAO,CAAE,MAAO,EAAa,WAAY,EAAK,UAAW,GAAI,EAC7D,QAAU,GAAM,EAAE,gBAAgB,WAHpC,CAKG,EAAI,QAAQ,SAAW,IACtB,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,kDAAyC,iEAEnD,CAAA,GAEP,EAAA,EAAA,IAAA,CAAC,GAAD,CAAqB,UAAS,mBAAoB,GAAe,UAAW,YAC1E,EAAA,EAAA,IAAA,CAAC,GAAD,CAAiB,MAAO,EAAc,SAAU,YAC7C,EAAI,QAAQ,KAAK,EAAG,KACnB,EAAA,EAAA,IAAA,CAAC,GAAD,CAEE,IAAK,EACL,MAAO,EACG,WACV,SAAU,GAAW,OAAS,UAAY,EAAU,WAAa,EAAE,GACnE,YACE,GAAW,OAAS,WAAa,EAAU,WAAa,EAAE,GACtD,EAAU,UACV,KAEN,MAAO,EAAI,MACX,mBAAsB,EAAa,CAAE,KAAM,SAAU,SAAU,EAAE,EAAG,CAAC,EACrE,gBAAkB,GAChB,EAAa,CAAE,KAAM,UAAW,SAAU,EAAE,GAAI,UAAW,CAAK,CAAC,EAEnE,gBAAmB,EAAgB,EAAE,EAAE,EACvC,aAAgB,EAAa,EAAE,EAAE,CAClC,EAjBM,EAAE,EAiBR,CACF,CACc,CAAA,CACP,CAAA,CACT,GACF,CAAA,CACF,CAAA,CAET,CAEA,SAAS,GAAe,EAWrB,CACD,GAAM,CAAE,aAAY,YAAW,aAAY,YAAW,aAAY,cAAe,GAAY,CAC3F,GAAI,EAAM,IAAI,EAChB,CAAC,EAUD,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,IAAK,EAAmB,MAAA,CAT7B,UAAW,GAAI,UAAU,SAAS,CAAS,EAC3C,aACA,QAAS,EAAa,GAAM,EAC5B,SAAU,WAGV,OAAQ,EAAM,SAAW,GAAK,MAGD,YAC3B,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,IAAK,EAAM,IACX,SAAU,EAAM,SAChB,SAAU,EAAM,SAChB,YAAa,EAAM,YACnB,MAAO,EAAM,MACb,eAAgB,EAAM,eACtB,gBAAiB,EAAM,gBACvB,YAAa,EAAM,YACnB,SAAU,EAAM,SAChB,YACE,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,GAAI,EACJ,GAAI,EACJ,UAAU,wEACV,MAAM,kBACN,QAAU,GAAM,EAAE,gBAAgB,YAElC,EAAA,EAAA,IAAA,CAAC,EAAA,aAAD,CAAc,KAAM,EAAK,CAAA,CACnB,CAAA,CAEX,CAAA,CACE,CAAA,CAET,CAEA,SAAS,GAAW,CAClB,MACA,WACA,WACA,cACA,QACA,iBACA,kBACA,cACA,WACA,cAYC,CACD,IAAM,EAAY,EAAI,OAAS,CAAC,EAEhC,GADe,EAAS,SACT,EAAU,OAAO,KAEhC,IAAM,EAAI,EADK,GAAY,EAAU,CACd,EAAQ,CAAK,EAC9B,CAAC,EAAS,IAAA,EAAA,EAAA,SAAA,CAAuB,EAAK,EAkB5C,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CACE,MAAO,CAlBT,gBAAiB,EAAE,gBACnB,WAAa,EAAE,YAAyB,EACxC,cAAgB,EAAE,eAA4B,EAC9C,YAAc,EAAE,aAA0B,EAC1C,aAAe,EAAE,cAA2B,EAC5C,aAAc,EAAE,aAChB,SAAU,WACV,QAAS,EACL,oBACA,EACA,qBACA,yBACJ,cAAe,GACf,OAAQ,SAKC,EACP,QAAU,GAAM,CACd,EAAE,gBAAgB,EAClB,EAAe,CACjB,EACA,iBAAoB,EAAW,EAAI,EACnC,iBAAoB,EAAW,EAAK,WAPtC,CAUG,CAAC,GAAY,IACZ,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,uHAAf,CAA6H,oBACzG,EAAI,IACnB,IAEN,IAGC,EAAA,EAAA,KAAA,CAAC,MAAD,CACE,UAAU,0FACV,QAAU,GAAM,EAAE,gBAAgB,WAFpC,CAIG,GACD,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,QAAU,GAAM,CACd,EAAE,gBAAgB,EAClB,EAAY,CACd,EACA,UAAU,2CACV,MAAM,sBAEN,EAAA,EAAA,IAAA,CAAC,EAAA,KAAD,CAAM,KAAM,EAAK,CAAA,CACX,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,QAAU,GAAM,CACd,EAAE,gBAAgB,EAClB,EAAS,CACX,EACA,UAAU,0CACV,MAAM,mBAEN,EAAA,EAAA,IAAA,CAAC,EAAA,OAAD,CAAQ,KAAM,EAAK,CAAA,CACb,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,4DACb,EAAI,IACD,CAAA,CACH,IAEN,EAAI,SAAS,KAAK,EAAG,KACpB,EAAA,EAAA,IAAA,CAAC,GAAD,CAEE,GAAI,EACJ,MAAO,EACP,cAAe,EAAI,SAAS,OAClB,WACH,QACP,SAAU,EAAI,GACd,eAAgB,EAChB,SAAU,IAAgB,EAAE,GAC5B,aAAgB,EAAgB,EAAE,EAAE,EACpB,gBACjB,EAXM,EAAE,EAWR,CACF,CACE,GAET,CAEA,SAAS,GAAY,CACnB,KACA,QACA,gBACA,WACA,QACA,WACA,iBACA,WACA,WACA,kBAYC,CACD,IAAM,EAAc,EAAe,GAAM,EAAE,WAAW,EAChD,EAAgB,EAAe,GAAM,EAAE,aAAa,EAG1D,GAFiB,EAA2C,OACpC,SACT,EAAU,OAAO,KAChC,IAAM,EAAiC,CAGrC,QAAS,EAAW,oBAAsB,8BAC1C,cAAe,GACf,SAAU,UACZ,EAIM,EAAU,GAAwB,CAEtC,GADA,EAAE,gBAAgB,EACd,CAAC,GAAkB,CAAC,EAAU,CAChC,EAAe,EACf,MACF,CACA,EAAS,CACX,EAEM,EAAU,IACd,EAAA,EAAA,KAAA,CAAC,MAAD,CACE,UAAU,4FACV,QAAU,GAAM,EAAE,gBAAgB,WAFpC,EAIE,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,YAAe,EAAe,EAC9B,UAAU,4CACV,MAAM,gCAEN,EAAA,EAAA,IAAA,CAAC,EAAA,cAAD,CAAe,KAAM,EAAK,CAAA,CACpB,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,SAAU,IAAU,EACpB,YAAe,EAAY,EAAU,EAAG,GAAI,EAAE,EAC9C,UAAU,gEACV,MAAM,oBAEN,EAAA,EAAA,IAAA,CAAC,EAAA,QAAD,CAAS,KAAM,EAAK,CAAA,CACd,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,SAAU,IAAU,EAAgB,EACpC,YAAe,EAAY,EAAU,EAAG,GAAI,CAAC,EAC7C,UAAU,gEACV,MAAM,sBAEN,EAAA,EAAA,IAAA,CAAC,EAAA,UAAD,CAAW,KAAM,EAAK,CAAA,CAChB,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,YAAe,EAAc,EAAU,EAAG,EAAE,EAC5C,UAAU,0CACV,MAAM,2BAEN,EAAA,EAAA,IAAA,CAAC,EAAA,OAAD,CAAQ,KAAM,EAAK,CAAA,CACb,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,0DACb,EAAG,IACA,CAAA,CACH,IAGD,EAAY,IAChB,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,MAAO,EAAW,QAAS,WAAhC,CACG,EACA,CACE,IAGP,OAAQ,EAAG,KAAX,CACE,IAAK,OACH,OAAO,GAAS,EAAA,EAAA,IAAA,CAAC,GAAD,CAAgB,KAAc,WAAiB,QAAiB,UAAW,CAAA,CAAC,EAC9F,IAAK,QACH,OAAO,GAAS,EAAA,EAAA,IAAA,CAAC,GAAD,CAAiB,KAAc,WAAiB,OAAQ,CAAA,CAAC,EAC3E,IAAK,SACH,OAAO,GAAS,EAAA,EAAA,IAAA,CAAC,GAAD,CAAkB,KAAc,WAAiB,OAAQ,CAAA,CAAC,EAC5E,IAAK,SACH,OAAO,GAAS,EAAA,EAAA,IAAA,CAAC,GAAD,CAAkB,IAAK,CAAA,CAAC,EAC1C,IAAK,UACH,OAAO,GAAS,EAAA,EAAA,IAAA,CAAC,GAAD,CAAmB,KAAc,WAAiB,OAAQ,CAAA,CAAC,EAC7E,IAAK,cACH,OAAO,GAAS,EAAA,EAAA,IAAA,CAAC,GAAD,CAAuB,KAAc,WAAiB,OAAQ,CAAA,CAAC,CACnF,CACF,CAEA,SAAS,GAAW,CAClB,KACA,WACA,QACA,YAMC,CACD,IAAM,EAAgB,EAAe,GAAM,EAAE,aAAa,EAEpD,EAAI,EADK,GAAY,EAAG,MAAkC,CACzC,EAAQ,CAAK,EAC9B,EAAS,EAAE,OAAoB,UAK/B,EAAe,GAAa,CAAK,EAoBvC,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CACS,MAAA,CAnBT,WAAY,EAAE,WACd,SAAU,EAAE,SACZ,WAAY,EAAE,WACd,cAAe,EAAE,cACjB,WAAY,EAAE,WACd,QACA,UAAW,EAAE,MACb,WAAa,EAAE,YAAyB,EACxC,cAAgB,EAAE,eAA4B,EAC9C,YAAc,EAAE,aAA0B,GAC1C,aAAe,EAAE,cAA2B,GAC5C,OAAQ,EACR,UAAW,QACX,GAAI,EACA,CAAE,WAAY,sDAAuD,EACrE,IAAA,EAIK,EACP,gBAAA,GACA,+BAAA,GACA,OAAS,GAAM,CACb,IAAM,EAAO,EAAE,cAAc,UACzB,IAAS,EAAG,SACd,EAAc,EAAU,EAAG,GAAI,CAAE,QAAS,CAAK,CAAyB,CAE5E,EACA,wBAAyB,CAAE,OAAQ,EAAG,OAAQ,CAC/C,CAAA,CAEL,CAEA,SAAS,GAAY,CAAE,KAAI,WAAU,SAA6E,CAEhH,IAAM,EAAI,EADK,GAAY,EAAG,MAAkC,CACzC,EAAQ,CAAK,EAC9B,EAA4B,CAChC,UAAY,EAAE,OAA8C,SAC5D,WAAa,EAAE,YAAyB,EACxC,cAAgB,EAAE,eAA4B,EAC9C,YAAc,EAAE,aAA0B,EAC1C,aAAe,EAAE,cAA2B,CAC9C,EACM,EAA2B,CAC/B,QAAS,eACT,SAAU,OACV,MAAO,EAAE,MACT,OAAS,EAAE,QAAqB,OAChC,aAAc,EAAE,YAClB,EACA,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,MAAO,YACV,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,IAAK,EAAG,IAAK,IAAK,EAAG,KAAO,GAAI,MAAO,CAAM,CAAA,CAC/C,CAAA,CAET,CAEA,SAAS,GAAa,CAAE,KAAI,WAAU,SAA8E,CAElH,IAAM,EAAI,EADK,GAAY,EAAG,MAAkC,CACzC,EAAQ,CAAK,EAmBpC,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,MAAO,CAlBZ,UAAY,EAAE,OAA8C,SAC5D,WAAa,EAAE,YAAyB,GACxC,cAAgB,EAAE,eAA4B,GAC9C,YAAc,EAAE,aAA0B,GAC1C,aAAe,EAAE,cAA2B,EAchC,YACV,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,MAAO,CAZf,QAAS,eACT,gBAAkB,EAAE,iBAA8B,UAClD,MAAQ,EAAE,OAAoB,OAC9B,WAAY,EAAE,WACd,SAAW,EAAE,UAAuB,GACpC,WAAa,EAAE,YAAoD,OACnE,aAAe,EAAE,cAA2B,EAC5C,QAAS,YACT,eAAgB,MAID,WAAM,EAAG,KAAY,CAAA,CAC/B,CAAA,CAET,CAEA,SAAS,GAAa,CAAE,MAA6B,CACnD,OAAO,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,MAAO,CAAE,OAAQ,EAAG,OAAQ,WAAY,kBAAmB,CAAI,CAAA,CAC7E,CAEA,SAAS,GAAc,CAAE,KAAI,WAAU,SAA+E,CAEpH,IAAM,EAAI,EADK,GAAY,EAAG,MAAkC,CACzC,EAAQ,CAAK,EACpC,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,MAAO,CACL,WAAa,EAAE,YAAyB,EACxC,cAAgB,EAAE,eAA4B,CAChD,YAEA,EAAA,EAAA,IAAA,CAAC,KAAD,CACE,MAAO,CACL,OAAQ,EACR,UAAW,GAAI,EAAE,WAAwB,EAAE,WAAY,EAAE,OAAoB,YAC7E,OAAQ,CACV,CACD,CAAA,CACE,CAAA,CAET,CAEA,SAAS,GAAkB,CACzB,KACA,WACA,SAKC,CAED,IAAM,EAAI,EADK,GAAY,EAAG,MAAkC,CACzC,EAAQ,CAAK,EAC9B,EAAW,IAAa,SACxB,EAAO,EAAG,QACV,EACH,EAAE,qBAAmC,EAAE,iBAA8B,cAClE,EAAa,EAAE,WAAwB,UACvC,EAAc,EAAE,iBAA8B,UAC9C,EAAY,EAAE,eAA4B,UAC1C,EAAS,EAAE,uBAAoC,UAC/C,EAAY,EAAE,aAA0B,UACxC,EAAU,EAAE,cAA2B,EAY7C,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,MAAO,CAVZ,WAAa,EAAE,YAAyB,GACxC,cAAgB,EAAE,eAA4B,GAC9C,YAAc,EAAE,aAA0B,GAC1C,aAAe,EAAE,cAA2B,GAC5C,QAAS,OACT,SAAU,OACV,IAAK,CAIO,WACT,EAAG,SAAS,IAAK,IAUd,EAAA,EAAA,KAAA,CAAC,MAAD,CAAgB,MAAO,CARvB,MAAO,EAAW,OAAS,QAAQ,IAAM,EAAK,UAC9C,WAAY,EACZ,aAAc,EACd,SAAU,SACV,QAAS,OACT,cAAe,QAGQ,WAAvB,EACE,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,IAAK,EAAE,MACP,IAAK,EAAE,UAAY,EAAE,KACrB,MAAO,CAAE,QAAS,QAAS,MAAO,OAAQ,OAAQ,OAAQ,aAAc,CAAO,CAChF,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,MAAO,CACL,QAAS,qBACT,WAAY,+BACZ,SAAU,GACV,WAAY,OACZ,MAAO,EACP,WAAY,GACd,WAEC,EAAE,IACA,CAAA,GACL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,MAAO,CAAE,QAAS,kBAAmB,WAAY,8BAA+B,WAArF,CACG,EAAG,cAAgB,EAAE,WACpB,EAAA,EAAA,IAAA,CAAC,OAAD,CACE,UAAU,YACV,MAAO,CACL,MAAO,EACP,eAAgB,eAChB,SAAU,GACV,YAAa,CACf,WAEC,EAAE,QACC,CAAA,GAER,EAAA,EAAA,IAAA,CAAC,OAAD,CACE,UAAU,cACV,MAAO,CAAE,MAAO,EAAY,WAAY,OAAQ,SAAU,EAAG,WAE5D,EAAE,UACC,CAAA,CACH,IACJ,EAAG,iBAAmB,EAAE,cACvB,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,MAAO,CACL,QAAS,kBACT,WAAY,+BACZ,SAAU,GACV,MAAO,UACP,WAAY,GACd,WAEC,EAAE,WACA,CAAA,EAEN,EAAG,aACF,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,MAAO,CAAE,QAAS,qBAAsB,UAAW,SAAU,UAAW,MAAO,YAClF,EAAA,EAAA,IAAA,CAAC,OAAD,CACE,MAAO,CACL,QAAS,eACT,QAAS,YACT,WAAY,+BACZ,SAAU,GACV,WAAY,OACZ,MAAO,EACP,gBAAiB,EACjB,aAAc,CAChB,WAEC,EAAE,aAAe,EAAG,aAAe,UAChC,CAAA,CACH,CAAA,CAEJ,GAtEK,EAAE,EAsEP,CAER,CACE,CAAA,CAET,CCxpBA,IAAM,GAAkB,CAAC,EACrB,GAAsC,KAG7B,GAAyB,CACpC,eAAiB,GAAQ,GAAe,SAAS,CAAG,EACpD,cAAgB,GAAM,GAAO,KAAK,CAAC,EACnC,sBAAwB,GAAM,CAC5B,GAAgB,CAClB,EACA,cAAgB,GAAM,CAGpB,GAAsB,CAAC,CACzB,CACF,EAEA,SAAgB,GAAe,EAAgB,CAC7C,EAAO,MAAM,EAAO,CACtB,CAMA,SAAgB,IAAyC,CACvD,OAAO,EACT,CCkBA,IAAM,GAAgC,CACpC,IAAK,OACL,MAAO,cACP,KAAM,SACN,QAAS,EACT,QAAS,CACP,CAAE,MAAO,EAAG,MAAO,aAAc,EACjC,CAAE,MAAO,GAAI,MAAO,cAAe,EACnC,CAAE,MAAO,GAAI,MAAO,cAAe,CACrC,CACF,EAEa,GAAoC,CAC/C,CAAE,GAAI,iBAAkB,MAAO,4BAA6B,MAAO,YAAa,EAChF,CAAE,GAAI,wBAAyB,MAAO,4BAA6B,MAAO,UAAW,OAAQ,CAAC,EAAS,CAAE,EACzG,CAAE,GAAI,mBAAoB,MAAO,uBAAwB,MAAO,UAAW,OAAQ,CAAC,EAAS,CAAE,EAC/F,CAAE,GAAI,eAAgB,MAAO,kBAAmB,MAAO,UAAW,OAAQ,CAAC,EAAS,CAAE,EACtF,CAAE,GAAI,aAAc,MAAO,sBAAuB,MAAO,YAAa,EACtE,CAAE,GAAI,SAAU,MAAO,kBAAmB,MAAO,YAAa,EAC9D,CAAE,GAAI,oBAAqB,MAAO,+BAAgC,MAAO,YAAa,EACtF,CAAE,GAAI,eAAgB,MAAO,eAAgB,MAAO,YAAa,EACjE,CAAE,GAAI,iBAAkB,MAAO,0BAA2B,MAAO,YAAa,EAC9E,CAAE,GAAI,kBAAmB,MAAO,wBAAyB,MAAO,YAAa,EAC7E,CAAE,GAAI,gBAAiB,MAAO,+BAAgC,MAAO,SAAU,EAC/E,CAAE,GAAI,aAAc,MAAO,qCAAsC,MAAO,SAAU,EAClF,CAAE,GAAI,iBAAkB,MAAO,uBAAwB,MAAO,UAAW,EACzE,CAAE,GAAI,uBAAwB,MAAO,2BAA4B,MAAO,UAAW,EACnF,CAAE,GAAI,uBAAwB,MAAO,8BAA+B,MAAO,UAAW,EACtF,CAAE,GAAI,gBAAiB,MAAO,gBAAiB,MAAO,YAAa,CACrE,EAEa,GAAuD,OAAO,YACzE,GAAW,IAAK,GAAM,CAAC,EAAE,GAAI,CAAC,CAAC,CACjC,EAEa,GAAqF,CAChG,CAAE,MAAO,cAAe,MAAO,wBAAyB,YAAa,+CAAgD,EACrH,CAAE,MAAO,SAAU,MAAO,gCAAiC,YAAa,uDAAwD,EAChI,CAAE,MAAO,SAAU,MAAO,kBAAmB,YAAa,kCAAmC,EAC7F,CAAE,MAAO,OAAQ,MAAO,gBAAiB,YAAa,qDAAsD,CAC9G,EAIA,SAAgB,GAAa,EAAa,EAAyB,CACjE,MAAO,CACL,KAAM,cACN,aACA,WAAY,GACZ,eAAgB,CAAC,EACjB,MAAO,CAAC,CAAE,UAAW,gBAAiB,CAAC,EACvC,SAAU,cACV,QAAS,CACP,gBAAiB,CAAC,EAClB,gBAAiB,CAAC,EAClB,kBAAmB,CAAC,EACpB,kBAAmB,CAAC,EACpB,SAAU,EACV,SAAU,EACV,SAAU,GACV,YAAa,GACb,WAAY,GACZ,aAAc,GACd,WAAY,GACZ,UAAW,EACb,CACF,CACF,CAGA,SAAgB,GAAU,EAAwE,CAChG,GAAI,CAAC,EAAM,OAAO,KAClB,IAAM,EAAM,EAAK,gBAEjB,MADI,CAAC,GAAO,OAAO,GAAQ,SAAiB,KACrC,CACT,CAGA,SAAgB,GAAe,EAAyB,CAEtD,OADK,GAAG,SACD,EAAE,SAAS,KAAM,GAAM,EAAE,OAAS,aAAa,EAD7B,EAE3B,CAGA,SAAgB,GAAiB,EAAwB,CACvD,GAAI,CAAC,GAAG,SAAU,MAAO,GACzB,IAAI,EAAI,EACR,IAAK,IAAM,KAAK,EAAE,SACZ,EAAE,OAAS,gBAAe,GAAK,EAAE,SAAS,QAEhD,OAAO,CACT,CAGA,SAAgB,GAAc,EAAyB,CACrD,MAAO,CACL,OAAQ,CACN,UAAW,EAAE,OAAS,SAAW,SAAW,cAC5C,QAAS,CACP,KAAM,EAAE,QAAQ,gBAChB,SAAU,EAAE,QAAQ,iBACtB,EACA,QAAS,CACP,KAAM,EAAE,QAAQ,gBAChB,SAAU,EAAE,QAAQ,iBACtB,EACA,YAAa,EAAE,QAAQ,aAAe,GACtC,WAAY,EAAE,QAAQ,YAAc,GACpC,aAAc,EAAE,QAAQ,cAAgB,GACxC,WAAY,EAAE,QAAQ,YAAc,GACpC,UAAW,EAAE,QAAQ,WAAa,GAClC,SAAU,EAAE,QAAQ,UAAY,EAClC,EACA,WAAY,OAAO,EAAE,UAAU,EAC/B,SAAU,EAAE,SACZ,MAAO,EAAE,OAAS,SAAW,CAAC,EAAI,EAAE,MACpC,SAAU,OAAO,EAAE,QAAQ,UAAY,CAAC,EACxC,SAAU,OAAO,EAAE,QAAQ,UAAY,CAAC,EACxC,WAAY,EAAE,YAAc,GAC5B,eAAgB,EAAE,cACpB,CACF,CC5KA,SAAgB,GAAqB,CAAE,OAAc,CACnD,IAAM,EAAe,EAAe,GAAM,EAAE,YAAY,EAClD,EAAQ,GAAiB,CAAG,GAAK,EACjC,EAAQ,GAAU,EAAI,IAAI,GAAK,GAAa,CAAK,EAEjD,EAAU,GAAyC,CACvD,IAAM,EAAO,CAAE,GAAG,EAAO,GAAG,CAAM,EAClC,EAAa,EAAI,GAAI,CAAE,KAAM,CAAE,GAAI,EAAI,MAAQ,CAAC,EAAI,gBAAiB,CAAK,CAAE,CAAC,CAC/E,EAKA,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,gFAAf,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,iFAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAA,SAAD,CAAU,KAAM,GAAI,UAAU,eAAiB,CAAA,GAC/C,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,uEAA8D,iBAExE,CAAA,CACF,KAGL,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,kDACb,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,kCAAf,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,OAAQ,EAAM,OAAS,SAEvB,MAAM,eACN,SAAS,wBACT,YAAe,EAAO,CAAE,KAAM,QAAS,CAAC,CACzC,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,OAAQ,EAAM,OAAS,cAEvB,MAAM,cACN,SAAS,uBACT,YAAe,EAAO,CAAE,KAAM,aAAc,CAAC,CAC9C,CAAA,CACE,GACF,CAAA,GAGL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,kCAAf,EACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAO,MAAM,8BAAb,EACE,EAAA,EAAA,IAAA,CAAC,QAAD,CACE,KAAK,SACL,IAAK,EACL,IAAK,GACL,MAAO,EAAM,WACb,SAAW,GAAM,EAAO,CAAE,WAAY,OAAO,EAAE,OAAO,KAAK,GAAK,CAAE,CAAC,EACnE,UAAW,EACZ,CAAA,GACD,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,0CAAf,CAAgD,aACnC,EAAM,QAAM,IAAU,EAAI,GAAK,IAAI,iBAC3C,GACA,IAEN,EAAM,OAAS,UACd,EAAA,EAAA,IAAA,CAAC,GAAD,CAAsB,QAAe,QAAS,CAAA,GAE9C,EAAA,EAAA,IAAA,CAAC,GAAD,CACS,QACC,SACO,cAtDF,GACrB,EAAO,CAAE,QAAS,CAAE,GAAG,EAAM,QAAS,GAAG,CAAM,CAAE,CAAC,CAsD3C,CAAA,GAGH,EAAA,EAAA,KAAA,CAAC,UAAD,CAAS,UAAU,0CAAnB,EACE,EAAA,EAAA,IAAA,CAAC,UAAD,CAAS,UAAU,wFAA+E,iBAEzF,CAAA,GACT,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,0FACZ,KAAK,UAAU,EAAO,KAAM,CAAC,CAC3B,CAAA,CACE,GACN,GACF,GAET,CAIA,SAAS,GAAc,CACrB,QACA,UAIC,CACD,OACE,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,wBACX,EAAA,EAAA,IAAA,CAAC,QAAD,CACE,KAAK,OACL,YAAY,oBACZ,MAAO,EAAM,YAAc,GAC3B,SAAW,GAAM,EAAO,CAAE,WAAY,EAAE,OAAO,KAAM,CAAC,EACtD,UAAW,EACZ,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,kDACX,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,MAAO,EAAM,eACb,SAAW,GAAM,EAAO,CAAE,eAAgB,CAAE,CAAC,EAC7C,YAAY,gBACb,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,qCAA4B,0DAEtC,CAAA,CACL,CAAA,CAAA,CAEN,CAEA,SAAS,GAAmB,CAC1B,QACA,SACA,iBAKC,CACD,GAAM,CAAC,EAAU,IAAA,EAAA,EAAA,SAAA,CAAwB,EAAK,EAC9C,OACE,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,oDAAf,EACE,EAAA,EAAA,KAAA,CAAC,QAAD,CAAO,UAAU,6CAAjB,CAAqD,qBACxB,GACtB,KACP,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,SAAU,EAAM,MAAM,QAAA,EACtB,SAAU,EAAM,MAAM,IAAK,GAAM,EAAE,SAAS,EAC5C,OAAS,GAAO,EAAO,CAAE,MAAO,CAAC,GAAG,EAAM,MAAO,CAAE,UAAW,CAAG,CAAC,CAAE,CAAC,CACtE,CAAA,CACE,KACL,EAAA,EAAA,IAAA,CAAC,GAAD,CAAW,MAAO,EAAM,MAAO,SAAW,GAAU,EAAO,CAAE,OAAM,CAAC,CAAI,CAAA,CACrE,CAAA,CAAA,GAEL,EAAA,EAAA,KAAA,CAAC,EAAD,CAAO,MAAM,oBAAb,EACE,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,MAAO,EAAM,SACb,SAAW,GACT,EAAO,CAAE,SAAU,EAAE,OAAO,KAA0C,CAAC,EAEzE,UAAW,YAEV,GAAiB,IAAK,IACrB,EAAA,EAAA,IAAA,CAAC,SAAD,CAAsB,MAAO,EAAE,eAC5B,EAAE,KACG,EAFK,EAAE,KAEP,CACT,CACK,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,0CACZ,GAAiB,KAAM,GAAM,EAAE,QAAU,EAAM,QAAQ,CAAC,EAAE,WACxD,CAAA,CACA,KAEP,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,MAAM,4BACN,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,mCAAf,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAM,OAAQ,CAAC,EAAU,YAAe,EAAY,EAAK,WAAG,OAEtD,CAAA,GACN,EAAA,EAAA,IAAA,CAAC,GAAD,CAAM,OAAQ,EAAU,YAAe,EAAY,EAAI,WAAG,UAEpD,CAAA,CACH,GAER,CAAA,GAED,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,6BACX,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,MAAO,EAAM,QAAQ,gBACrB,SAAW,GAAM,EAAc,CAAE,gBAAiB,CAAE,CAAC,EACrD,YAAY,gBACb,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,6BACX,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,MAAO,EAAM,QAAQ,gBACrB,SAAW,GAAM,EAAc,CAAE,gBAAiB,CAAE,CAAC,EACrD,YAAY,gBACb,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,+BACX,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,MAAO,EAAM,QAAQ,kBACrB,SAAW,GAAM,EAAc,CAAE,kBAAmB,CAAE,CAAC,EACvD,YAAY,cACb,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,+BACX,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,MAAO,EAAM,QAAQ,kBACrB,SAAW,GAAM,EAAc,CAAE,kBAAmB,CAAE,CAAC,EACvD,YAAY,cACb,CAAA,CACI,CAAA,GAEP,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,kCAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,0BACX,EAAA,EAAA,IAAA,CAAC,QAAD,CACE,KAAK,SACL,IAAK,EACL,MAAO,EAAM,QAAQ,UAAY,EACjC,SAAW,GAAM,EAAc,CAAE,SAAU,OAAO,EAAE,OAAO,KAAK,GAAK,CAAE,CAAC,EACxE,UAAW,EACZ,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,0BACX,EAAA,EAAA,IAAA,CAAC,QAAD,CACE,KAAK,SACL,IAAK,EACL,MAAO,EAAM,QAAQ,UAAY,EACjC,SAAW,GAAM,EAAc,CAAE,SAAU,OAAO,EAAE,OAAO,KAAK,GAAK,CAAE,CAAC,EACxE,UAAW,EACZ,CAAA,CACI,CAAA,CACJ,KAEL,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,MAAM,kBACN,QAAS,CAAC,CAAC,EAAM,QAAQ,SACzB,SAAW,GAAM,EAAc,CAAE,SAAU,CAAE,CAAC,CAC/C,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,MAAM,0CACN,QAAS,CAAC,CAAC,EAAM,QAAQ,YACzB,SAAW,GAAM,EAAc,CAAE,YAAa,CAAE,CAAC,CAClD,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,MAAM,eACN,QAAS,CAAC,CAAC,EAAM,QAAQ,WACzB,SAAW,GAAM,EAAc,CAAE,WAAY,CAAE,CAAC,CACjD,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,MAAM,2BACN,QAAS,CAAC,CAAC,EAAM,QAAQ,aACzB,SAAW,GAAM,EAAc,CAAE,aAAc,CAAE,CAAC,CACnD,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,MAAM,uBACN,QAAS,CAAC,CAAC,EAAM,QAAQ,WACzB,SAAW,GAAM,EAAc,CAAE,WAAY,CAAE,CAAC,CACjD,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,gDACX,EAAA,EAAA,IAAA,CAAC,QAAD,CACE,KAAK,OACL,YAAY,eACZ,MAAO,EAAM,QAAQ,WAAa,GAClC,SAAW,GAAM,EAAc,CAAE,UAAW,EAAE,OAAO,KAAM,CAAC,EAC5D,UAAW,EACZ,CAAA,CACI,CAAA,EAEN,IACC,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,oCACX,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,MAAO,EAAM,QAAQ,UAAY,CAAC,EAClC,SAAW,GAAM,EAAc,CAAE,SAAU,CAAE,CAAC,CAC/C,CAAA,CACI,CAAA,CAET,CAAA,CAAA,CAEN,CAIA,IAAM,GACJ,8GAEF,SAAS,GAAS,CAChB,SACA,OACA,QACA,WACA,WAOC,CACD,OACE,EAAA,EAAA,KAAA,CAAC,SAAD,CACW,UACT,UACE,gFACC,EACG,kDACA,2DANR,EASE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,8BAAgC,EAAS,gBAAkB,0BAA3E,CACG,GACD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,iCAAyB,CAAY,CAAA,CAClD,KACL,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,qCAA6B,CAAe,CAAA,CACtD,GAEZ,CAEA,SAAS,GAAc,CAAE,QAAO,SAAqD,CACnF,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,gFAAf,EACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,2EACZ,CACE,CAAA,EACJ,CACE,GAET,CAEA,SAAS,EAAM,CAAE,QAAO,YAAmE,CACzF,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,QAAD,CAAO,UAAU,wDAAgD,CAAa,CAAA,EAC7E,CACE,CAAA,CAAA,CAET,CAEA,SAAS,GAAK,CACZ,SACA,UACA,YAKC,CACD,OACE,EAAA,EAAA,IAAA,CAAC,SAAD,CACW,UACT,UACE,0EACC,EAAS,yBAA2B,+CAGtC,UACK,CAAA,CAEZ,CAEA,SAAS,GAAU,CACjB,QACA,UACA,YAKC,CACD,OACE,EAAA,EAAA,KAAA,CAAC,QAAD,CAAO,UAAU,8EAAjB,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAA,SAAO,CAAY,CAAA,GACnB,EAAA,EAAA,IAAA,CAAC,QAAD,CACE,KAAK,WACI,UACT,SAAW,GAAM,EAAS,EAAE,OAAO,OAAO,EAC1C,UAAU,yBACX,CAAA,CACI,GAEX,CAEA,SAAS,GAAU,CACjB,QACA,YAIC,CACD,GAAI,EAAM,SAAW,EACnB,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,+GAAf,CAAqH,6BAC1F,EAAA,EAAA,IAAA,CAAC,IAAD,CAAA,SAAG,eAAgB,CAAA,EAAC,YAC1C,IAGT,IAAM,GAAQ,EAAW,IAAgB,CACvC,IAAM,EAAI,EAAI,EACd,GAAI,EAAI,GAAK,GAAK,EAAM,OAAQ,OAChC,IAAM,EAAO,EAAM,MAAM,EACzB,CAAC,EAAK,GAAI,EAAK,IAAM,CAAC,EAAK,GAAI,EAAK,EAAE,EACtC,EAAS,CAAI,CACf,EACM,EAAU,GAAc,EAAS,EAAM,QAAQ,EAAG,IAAM,IAAM,CAAC,CAAC,EAChE,GAAY,EAAW,EAAa,IAA2B,CACnE,IAAM,EAAO,EAAM,MAAM,EACzB,EAAK,GAAK,CAAE,GAAG,EAAK,GAAI,OAAQ,CAAE,GAAI,EAAK,EAAE,CAAC,QAAU,CAAC,GAAK,GAAM,CAAM,CAAE,EAC5E,EAAS,CAAI,CACf,EACA,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,uBACZ,EAAM,KAAK,EAAG,IAAM,CACnB,IAAM,EAAM,GAAgB,EAAE,WAC9B,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAEE,UAAU,mFAFZ,EAIE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,mCAAf,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,iDACb,GAAK,OAAS,EAAE,SACb,CAAA,GACN,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,MAAM,UACN,YAAe,EAAK,EAAG,EAAE,EACzB,SAAU,IAAM,EAChB,UAAU,sEAEV,EAAA,EAAA,IAAA,CAAC,EAAA,UAAD,CAAW,KAAM,EAAK,CAAA,CAChB,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,MAAM,YACN,YAAe,EAAK,EAAG,CAAC,EACxB,SAAU,IAAM,EAAM,OAAS,EAC/B,UAAU,sEAEV,EAAA,EAAA,IAAA,CAAC,EAAA,YAAD,CAAa,KAAM,EAAK,CAAA,CAClB,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,MAAM,SACN,YAAe,EAAO,CAAC,EACvB,UAAU,iDAEV,EAAA,EAAA,IAAA,CAAC,EAAA,OAAD,CAAQ,KAAM,EAAK,CAAA,CACb,CAAA,CACL,IACJ,GAAK,QAAQ,IAAK,IACjB,EAAA,EAAA,KAAA,CAAC,MAAD,CAAiB,UAAU,mCAA3B,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,mDAA2C,EAAE,KAAY,CAAA,EACxE,EAAE,OAAS,UACV,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,MAAO,OAAO,EAAE,SAAS,EAAE,MAAQ,EAAE,SAAW,EAAE,EAClD,SAAW,GAAM,EAAS,EAAG,EAAE,IAAK,EAAE,OAAO,KAAK,EAClD,UAAU,8EAET,EAAE,SAAS,IAAK,IACf,EAAA,EAAA,IAAA,CAAC,SAAD,CAA8B,MAAO,OAAO,EAAE,KAAK,WAChD,EAAE,KACG,EAFK,OAAO,EAAE,KAAK,CAEnB,CACT,CACK,CAAA,GAER,EAAA,EAAA,IAAA,CAAC,QAAD,CACE,KAAM,EAAE,OAAS,SAAW,SAAW,OACvC,MAAO,OAAO,EAAE,SAAS,EAAE,MAAQ,EAAE,SAAW,EAAE,EAClD,SAAW,GACT,EACE,EACA,EAAE,IACF,EAAE,OAAS,SAAW,OAAO,EAAE,OAAO,KAAK,EAAI,EAAE,OAAO,KAC1D,EAEF,UAAU,2DACX,CAAA,CAEA,GA5BK,EAAE,GA4BP,CACN,CACE,GA9DE,CA8DF,CAET,CAAC,CACE,CAAA,CAET,CAEA,SAAS,GAAqB,CAC5B,WACA,WACA,UAKC,CACD,GAAM,CAAC,EAAM,IAAA,EAAA,EAAA,SAAA,CAAoB,EAAK,EACtC,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,oBAAf,EACE,EAAA,EAAA,KAAA,CAAC,SAAD,CACY,WACV,YAAe,EAAS,GAAM,CAAC,CAAC,EAChC,UACE,kFACC,EACG,+CACA,qDAPR,EAUE,EAAA,EAAA,IAAA,CAAC,EAAA,KAAD,CAAM,KAAM,EAAK,CAAA,EAAC,MACZ,IACP,GAAQ,CAAC,IACR,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,qBAAqB,YAAe,EAAQ,EAAK,CAAI,CAAA,GACpE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,6HACZ,GAAW,IAAK,GAAM,CACrB,IAAM,EAAO,EAAS,SAAS,EAAE,EAAE,EACnC,OACE,EAAA,EAAA,KAAA,CAAC,SAAD,CAEE,SAAU,EACV,YAAe,CACb,EAAO,EAAE,EAAE,EACX,EAAQ,EAAK,CACf,EACA,UACE,iDACC,EACG,mCACA,+DAXR,CAcG,EAAE,MACF,IAAQ,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,4BAAmB,SAAa,CAAA,CACnD,GAfD,EAAE,EAeD,CAEZ,CAAC,CACE,CAAA,CACL,CAAA,CAAA,CAED,GAET,CAEA,SAAS,GAAW,CAClB,QACA,WACA,eAKC,CACD,GAAM,CAAC,EAAO,IAAA,EAAA,EAAA,SAAA,CAAqB,EAAE,EAC/B,MAAY,CAChB,IAAM,EAAI,EAAM,KAAK,EAChB,IACD,EAAM,SAAS,CAAC,IACpB,EAAS,CAAC,GAAG,EAAO,CAAC,CAAC,EACtB,EAAS,EAAE,GACb,EACA,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,sHAAf,CACG,EAAM,IAAK,IACV,EAAA,EAAA,KAAA,CAAC,OAAD,CAEE,UAAU,sGAFZ,CAIG,GACD,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,YAAe,EAAS,EAAM,OAAQ,GAAM,IAAM,CAAG,CAAC,EACtD,UAAU,6CAEV,EAAA,EAAA,IAAA,CAAC,EAAA,EAAD,CAAG,KAAM,EAAK,CAAA,CACR,CAAA,CACJ,GAVC,CAUD,CACP,GACD,EAAA,EAAA,IAAA,CAAC,QAAD,CACE,MAAO,EACP,SAAW,GAAM,EAAS,EAAE,OAAO,KAAK,EACxC,UAAY,GAAM,CACZ,EAAE,MAAQ,SAAW,EAAE,MAAQ,KACjC,EAAE,eAAe,EACjB,EAAI,GACK,EAAE,MAAQ,aAAe,CAAC,GAAS,EAAM,QAClD,EAAS,EAAM,MAAM,EAAG,EAAE,CAAC,CAE/B,EACA,OAAQ,EACR,YAAa,EAAM,SAAW,EAAI,EAAc,GAChD,UAAU,iEACX,CAAA,CACE,GAET,CAEA,SAAS,GAAS,CAChB,QACA,YAIC,CACD,GAAM,CAAC,EAAM,IAAA,EAAA,EAAA,SAAA,KAA0B,KAAK,UAAU,EAAO,KAAM,CAAC,CAAC,EAC/D,CAAC,EAAO,IAAA,EAAA,EAAA,SAAA,CAAoC,IAAI,EACtD,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,WAAD,CACE,MAAO,EACP,SAAW,GAAM,CACf,IAAM,EAAI,EAAE,OAAO,MACnB,EAAQ,CAAC,EACT,GAAI,CACF,IAAM,EAAS,KAAK,MAAM,GAAK,IAAI,EACnC,EAAS,IAAI,EACb,EAAS,CAAM,CACjB,OAAS,EAAK,CACZ,EAAS,OAAQ,EAAc,OAAO,CAAC,CACzC,CACF,EACA,KAAM,EACN,WAAY,GACZ,UAAU,qHACX,CAAA,EACA,IAAS,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,yCAAiC,CAAW,CAAA,CAClE,CAAA,CAAA,CAET,CCvmBA,SAAgB,IAAe,CAC7B,GAAM,CAAE,YAAW,MAAK,YAAa,EAAc,EAEnD,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,2EAAf,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,4DAA4D,IAAa,SAAW,8CAAgD,sDAApJ,CACG,IAAa,UAAW,EAAA,EAAA,IAAA,CAAC,EAAA,WAAD,CAAY,KAAM,EAAK,CAAA,GAAI,EAAA,EAAA,IAAA,CAAC,EAAA,QAAD,CAAS,KAAM,EAAK,CAAA,EAAE,WACjE,EAAS,SACf,KACL,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,eACZ,CAAC,GAAa,EAAU,OAAS,SAChC,EAAA,EAAA,IAAA,CAAC,GAAD,CAAqB,CAAA,EACnB,EAAU,OAAS,cACd,CACL,IAAM,EAAI,EAAI,QAAQ,KAAM,GAAM,EAAE,KAAO,EAAU,QAAQ,EAC7D,OAAO,GAAI,EAAA,EAAA,IAAA,CAAC,GAAD,CAAa,IAAK,CAAI,CAAA,GAAI,EAAA,EAAA,IAAA,CAAC,GAAD,CAAQ,CAAA,CAC/C,EAAA,CAAG,OAEI,CACL,IAAM,EAAI,EAAI,QAAQ,KAAM,GAAM,EAAE,KAAO,EAAU,QAAQ,EACvD,EAAK,GAAG,SAAS,KAAM,GAAM,EAAE,KAAO,EAAU,SAAS,EAC/D,OAAO,GAAK,GAAK,EAAA,EAAA,IAAA,CAAC,GAAD,CAAc,IAAK,EAAO,IAAK,CAAA,GAAI,EAAA,EAAA,IAAA,CAAC,GAAD,CAAQ,CAAA,CAC9D,EAAA,CAAG,CAEF,CAAA,CACF,GAET,CAEA,SAAS,IAAQ,CACf,OAAO,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,iCAAwB,mBAAsB,CAAA,CACtE,CAKA,SAAS,GAAU,EAAmC,EAAgC,CACpF,GAAI,IAAa,SAAU,OAAO,EAClC,IAAM,EAAU,EAAS,QAAkD,CAAC,EAC5E,MAAO,CAAE,GAAG,EAAU,GAAG,CAAO,CAClC,CAGA,SAAS,GACP,EACA,EACA,EACyB,CACzB,GAAI,IAAa,SAAU,MAAO,CAAE,GAAG,EAAU,GAAG,CAAM,EAC1D,IAAM,EAAU,EAAS,QAAkD,CAAC,EAC5E,MAAO,CAAE,GAAG,EAAU,OAAQ,CAAE,GAAG,EAAQ,GAAG,CAAM,CAAE,CACxD,CAEA,SAAS,GAAY,CAAE,cAAuC,CAE5D,OADK,GAEH,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,4FAAmF,QAE7F,CAAA,EAJgB,IAM1B,CAEA,SAAS,GAAgB,CACvB,SACA,YAIC,CACD,OACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,uBACX,EAAA,EAAA,KAAA,CAAC,GAAD,CACE,MAAO,GAAU,GACjB,SAAW,GAAM,CACf,IAAM,EAAI,EAAE,OAAO,MACnB,EAAS,IAAM,GAAK,IAAA,GAAa,CAA0B,CAC7D,WALF,EAOE,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,MAAM,YAAG,aAAmB,CAAA,GACpC,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,MAAM,kBAAS,gBAAsB,CAAA,GAC7C,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,MAAM,mBAAU,iBAAuB,CAAA,CACzC,GACH,CAAA,CAEX,CAEA,SAAS,GAAW,CAAE,YAA2C,CAC/D,OACE,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAU,mEACX,UACC,CAAA,CAER,CAEA,SAAS,EAAM,CAAE,QAAO,YAAmE,CACzF,OACE,EAAA,EAAA,KAAA,CAAC,QAAD,CAAO,UAAU,sBAAjB,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,wDAAgD,CAAY,CAAA,EAC3E,CACI,GAEX,CAEA,SAAS,EAAU,EAAoD,CACrE,OACE,EAAA,EAAA,IAAA,CAAC,QAAD,CACE,GAAI,EACJ,UAAU,oGACX,CAAA,CAEL,CAEA,SAAS,EAAY,EAAoD,CACvE,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,KAAK,SAAS,GAAI,CAAQ,CAAA,CAC9C,CAEA,SAAS,GAAc,CACrB,QACA,WACA,SAKC,CACD,IAAM,EAAW,GAAiB,EAC5B,GAAA,EAAA,EAAA,OAAA,CAA0C,IAAI,EAC9C,CAAC,EAAM,IAAA,EAAA,EAAA,SAAA,CAAoB,EAAK,EAChC,CAAC,EAAK,IAAA,EAAA,EAAA,SAAA,CAAkC,IAAI,EAE5C,EAAa,KAAO,IAAe,CAClC,KAEL,CADA,EAAQ,EAAI,EACZ,EAAO,IAAI,EACX,GAAI,CACF,IAAM,EAAM,MAAM,EAAS,OAAO,CAAI,EACtC,EAAS,EAAI,GAAG,EACZ,EAAI,KAAO,GAAO,EAAM,EAAI,GAAG,CACrC,OAAS,EAAG,CACV,EAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,CAAC,CACnD,QAAU,CACR,EAAQ,EAAK,EACT,EAAQ,UAAS,EAAQ,QAAQ,MAAQ,GAC/C,CAVW,CAWb,EAEA,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,sBAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,MAAO,GAAS,GAAI,SAAW,GAAM,EAAS,EAAE,OAAO,KAAK,CAAI,CAAA,EAC1E,IACC,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,QAAD,CACE,IAAK,EACL,KAAK,OACL,OAAO,UACP,UAAU,SACV,SAAW,GAAM,CACf,IAAM,EAAI,EAAE,OAAO,QAAQ,GACvB,GAAG,EAAgB,CAAC,CAC1B,CACD,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,KAAK,SACL,SAAU,EACV,YAAe,EAAQ,SAAS,MAAM,EACtC,UAAU,2HACV,MAAM,wBAEL,GAAO,EAAA,EAAA,IAAA,CAAC,EAAA,QAAD,CAAS,KAAM,GAAI,UAAU,cAAgB,CAAA,GAAI,EAAA,EAAA,IAAA,CAAC,EAAA,OAAD,CAAQ,KAAM,EAAK,CAAA,CACtE,CAAA,CACR,CAAA,CAAA,CAED,IACJ,IAAO,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAU,yCAAiC,CAAO,CAAA,EAC5D,CAAC,IACA,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAU,0CAAiC,gEAE3C,CAAA,CAEF,CAAA,CAAA,CAET,CAEA,SAAS,EAAW,CAClB,QACA,WACA,gBAKC,CACD,IAAM,EAAQ,EAAe,GAAM,EAAE,IAAI,KAAK,EACxC,EAAU,OAAO,GAAU,UAAY,EAAM,WAAW,GAAG,EAI3D,GAAA,EAAA,EAAA,OAAA,CACJ,GAAgB,EAAa,WAAW,GAAG,EAAI,EAAe,EAAU,EAAQ,IAAA,EAClF,GACA,EAAA,EAAA,UAAA,KAAgB,CACV,EAAS,EAAa,QAAU,EAC3B,GAAgB,EAAa,WAAW,GAAG,IAAG,EAAa,QAAU,EAChF,EAAG,CAAC,EAAO,EAAS,CAAY,CAAC,EAGjC,IAAM,OAAmB,CACvB,IAAM,EAAW,EAAa,EAAO,CAAK,EAM1C,OALI,OAAO,GAAa,UAAY,gCAAgC,KAAK,CAAQ,EACxE,EAAS,SAAW,EACvB,IAAM,EAAS,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAK,GAAM,EAAI,CAAC,CAAC,CAAC,KAAK,EAAE,EAC3D,EAEC,SACT,EAAA,CAAG,EAEG,EAAc,GAAgB,EAAa,QAC3C,EAAW,CAAC,CAAC,GAAe,IAAgB,EAG5C,CAAC,EAAM,IAAA,EAAA,EAAA,SAAA,CAAoB,GAAS,EAAE,EAG5C,OAFA,EAAA,EAAA,UAAA,KAAgB,EAAQ,GAAS,EAAE,EAAG,CAAC,CAAK,CAAC,GAG3C,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,mCAAf,EACE,EAAA,EAAA,KAAA,CAAC,QAAD,CACE,UAAU,0FACV,MAAO,EAAU,WAAW,EAAU,sBAAwB,aAC9D,MAAO,CAAE,WAAY,CAAU,WAHjC,EAKE,EAAA,EAAA,IAAA,CAAC,QAAD,CACE,KAAK,QACL,MAAO,EACP,SAAW,GAAM,EAAS,EAAE,OAAO,KAAK,EACxC,UAAU,2CACX,CAAA,EACA,IACC,EAAA,EAAA,IAAA,CAAC,OAAD,CACE,UAAU,sEACV,MAAO,CAAE,YAAa,uBAAwB,CAC/C,CAAA,CAEE,KACP,EAAA,EAAA,IAAA,CAAC,QAAD,CACE,MAAO,EACP,SAAW,GAAM,EAAQ,EAAE,OAAO,KAAK,EACvC,WAAc,IAAS,GAAS,EAAS,CAAI,EAC7C,UAAY,GAAM,CACZ,EAAE,MAAQ,SAAS,EAAG,OAA4B,KAAK,CAC7D,EACA,UAAU,8GACX,CAAA,EACA,IACC,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,KAAK,SACL,YAAe,EAAS,CAAY,EACpC,UAAU,4EACV,MAAO,YAAY,cAEnB,EAAA,EAAA,IAAA,CAAC,EAAA,UAAD,CAAW,KAAM,EAAK,CAAA,CAChB,CAAA,CAEP,GAET,CAEA,SAAS,GAAO,EAAsD,CACpE,OACE,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,GAAI,EACJ,UAAU,6GACX,CAAA,CAEL,CAIA,SAAS,IAAqB,CAC5B,GAAM,CAAE,MAAK,aAAY,kBAAmB,EAAc,EAC1D,OACE,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAA,SAAY,OAAiB,CAAA,GAC7B,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,iBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAO,EAAI,KAAK,KAChB,SAAW,GAAM,EAAW,CAAE,KAAM,EAAE,OAAO,KAAM,CAAC,CACrD,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,yBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAO,EAAI,KAAK,YAChB,SAAW,GAAM,EAAW,CAAE,YAAa,EAAE,OAAO,KAAM,CAAC,CAC5D,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,uBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAO,EAAI,SAAS,MACpB,SAAW,GAAM,EAAe,CAAE,MAAO,OAAO,EAAE,OAAO,KAAK,GAAK,GAAI,CAAC,CACzE,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,6BACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAO,EAAI,SAAS,gBACpB,SAAW,GAAM,EAAe,CAAE,gBAAiB,CAAE,CAAC,CACvD,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,qCACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAO,EAAI,SAAS,uBACpB,SAAW,GAAM,EAAe,CAAE,uBAAwB,CAAE,CAAC,CAC9D,CAAA,CACI,CAAA,GAEP,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,8CAAf,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAA,SAAY,kCAA4C,CAAA,GACxD,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,6BAAf,EACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,uBAAe,EAAI,MAAM,IAAU,CAAA,GAClD,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,gDACZ,OAAO,QAAQ,EAAI,MAAM,OAAO,MAAM,CAAC,CAAC,KAAK,CAAC,EAAG,MAChD,EAAA,EAAA,KAAA,CAAC,MAAD,CAAa,UAAU,mCAAvB,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,kBAAkB,MAAO,CAAE,WAAY,CAAE,CAAI,CAAA,GAC7D,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,oBAAY,CAAQ,CAAA,CACjC,GAHK,CAGL,CACN,CACE,CAAA,CACF,GACF,GACL,CAAA,CAAA,CAEN,CAIA,SAAS,GAAY,CAAE,OAA6B,CAClD,IAAM,EAAe,EAAe,GAAM,EAAE,YAAY,EAClD,EAAW,EAAe,GAAM,EAAE,QAAQ,EAC1C,EAAY,EAAI,OAAS,CAAC,EAC1B,EAAQ,GAAU,EAAU,CAAQ,EACpC,EAAa,IAAI,IAAI,OAAO,KAAM,EAAS,QAAsC,CAAC,CAAC,CAAC,EACpF,EAAO,GACX,EAAa,EAAI,GAAI,CAAE,MAAO,GAAgB,EAAU,EAAO,CAAQ,CAAE,CAAC,EAC5E,OACE,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAA,SAAa,EAAI,IAAiB,CAAA,GAClC,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,OAAO,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,CAAE,oBAAgB,EAAA,EAAA,IAAA,CAAC,GAAD,CAAa,WAAY,EAAW,IAAI,iBAAiB,CAAI,CAAA,CAAG,CAAA,CAAA,YAC9F,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,iBAA8B,GAC5C,SAAW,GAAM,EAAI,CAAE,gBAAiB,CAAE,CAAC,CAC5C,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,GAAD,CAAsB,QAAmB,aAAY,MAAO,CAAM,CAAA,GAClE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,OAAO,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,CAAE,iBAAa,EAAA,EAAA,IAAA,CAAC,GAAD,CAAa,WAAY,EAAW,IAAI,cAAc,CAAI,CAAA,CAAG,CAAA,CAAA,YACxF,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,cAA2B,EACzC,SAAW,GAAM,EAAI,CAAE,aAAc,OAAO,EAAE,OAAO,KAAK,CAAE,CAAC,CAC9D,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,OAAQ,EAAS,OACjB,SAAW,GAAM,EAAa,EAAI,GAAI,CAAE,MAAO,CAAE,GAAG,EAAU,OAAQ,CAAE,CAAE,CAAC,CAC5E,CAAA,EACA,GAAe,CAAG,IAAK,EAAA,EAAA,IAAA,CAAC,GAAD,CAA2B,KAAM,CAAA,CACzD,CAAA,CAAA,CAEN,CAIA,SAAS,GAAa,CAAE,MAAK,MAA8C,CACzE,OAAQ,EAAG,KAAX,CACE,IAAK,OACH,OAAO,EAAA,EAAA,IAAA,CAAC,GAAD,CAAuB,MAAS,IAAK,CAAA,EAC9C,IAAK,QACH,OAAO,EAAA,EAAA,IAAA,CAAC,GAAD,CAAwB,MAAS,IAAK,CAAA,EAC/C,IAAK,SACH,OAAO,EAAA,EAAA,IAAA,CAAC,GAAD,CAAyB,MAAS,IAAK,CAAA,EAChD,IAAK,SACH,OAAO,EAAA,EAAA,IAAA,CAAC,GAAD,CAAyB,MAAS,IAAK,CAAA,EAChD,IAAK,UACH,OAAO,EAAA,EAAA,IAAA,CAAC,GAAD,CAA0B,MAAS,IAAK,CAAA,EACjD,IAAK,cACH,OAAO,EAAA,EAAA,IAAA,CAAC,GAAD,CAA8B,MAAS,IAAK,CAAA,CACvD,CACF,CAEA,SAAS,GAAc,CACrB,QACA,aACA,SAKC,CACD,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,uCACX,CAAC,aAAc,gBAAiB,cAAe,cAAc,CAAC,CAAW,IAAK,IAC9E,EAAA,EAAA,IAAA,CAAC,EAAD,CAAe,OAAO,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,CAAG,EAAE,QAAQ,UAAW,MAAM,GAAE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAa,WAAY,CAAC,CAAC,GAAY,IAAI,CAAC,CAAI,CAAA,CAAG,CAAA,CAAA,YACvG,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,IAAiB,EAC/B,SAAW,GAAM,EAAM,EAAG,GAAI,OAAO,EAAE,OAAO,KAAK,CAAE,CAAC,CACvD,CAAA,CACI,EALK,CAKL,CACR,CACE,CAAA,CAET,CAEA,SAAS,GAAmC,EAAkB,EAAO,CACnE,IAAM,EAAgB,EAAe,GAAM,EAAE,aAAa,EAC1D,MAAQ,IAAsB,EAAc,EAAI,GAAI,EAAG,GAAI,CAA8B,CAC3F,CAEA,SAAS,GAAiB,CAAE,MAAK,MAA6C,CAC5E,IAAM,EAAQ,GAAW,EAAK,CAAE,EAC1B,EAAW,EAAe,GAAM,EAAE,QAAQ,EAC1C,EAAY,EAAG,OAAS,CAAC,EACzB,EAAQ,GAAU,EAAU,CAAQ,EACpC,EAAa,IAAI,IAAI,OAAO,KAAM,EAAS,QAAsC,CAAC,CAAC,CAAC,EACpF,EAAY,GAChB,EAAM,CAAE,MAAO,GAAgB,EAAU,EAAG,CAAQ,CAAE,CAAyB,EACjF,OACE,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAA,SAAY,MAAgB,CAAA,GAC5B,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,oBACX,EAAA,EAAA,IAAA,CAAC,WAAD,CACE,MAAO,EAAG,QAAQ,QAAQ,cAAe;CAAI,EAC7C,SAAW,GACT,EAAM,CAAE,QAAS,EAAE,OAAO,MAAM,QAAQ,MAAO,OAAO,CAAE,CAAyB,EAEnF,KAAM,EACN,UAAU,oGACX,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,wBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,YAAyB,GACvC,SAAW,GAAM,EAAS,CAAE,WAAY,EAAE,OAAO,KAAM,CAAC,CACzD,CAAA,CACI,CAAA,GACP,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,kCAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,sBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,UAAuB,GACrC,SAAW,GAAM,EAAS,CAAE,SAAU,OAAO,EAAE,OAAO,KAAK,CAAE,CAAC,CAC/D,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,mBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAO,OAAO,EAAM,YAAc,EAAE,EACpC,SAAW,GAAM,EAAS,CAAE,WAAY,EAAE,OAAO,OAAS,IAAA,EAAU,CAAC,CACtE,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,wBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,KAAM,GACN,MAAQ,EAAM,YAAyB,IACvC,SAAW,GAAM,EAAS,CAAE,WAAY,OAAO,EAAE,OAAO,KAAK,CAAE,CAAC,CACjE,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,2BACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,eAA4B,EAC1C,SAAW,GAAM,EAAS,CAAE,cAAe,OAAO,EAAE,OAAO,KAAK,CAAE,CAAC,CACpE,CAAA,CACI,CAAA,CACJ,KACL,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,kBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,OAAoB,UAClC,SAAW,GAAM,EAAS,CAAE,MAAO,CAAE,CAAC,CACvC,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,kBACX,EAAA,EAAA,KAAA,CAAC,GAAD,CACE,MAAQ,EAAM,OAAoB,OAClC,SAAW,GAAM,EAAS,CAAE,MAAO,EAAE,OAAO,KAAM,CAAC,WAFrD,EAIE,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,MAAM,gBAAO,MAAY,CAAA,GACjC,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,MAAM,kBAAS,QAAc,CAAA,GACrC,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,MAAM,iBAAQ,OAAa,CAAA,CAC7B,GACH,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,qBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,MAAmB,GACjC,SAAW,GAAM,EAAS,CAAE,KAAM,EAAE,OAAO,KAAM,CAAC,CACnD,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,GAAD,CAAsB,QAAmB,aAAY,MAAO,CAAW,CAAA,GACvE,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,OAAQ,EAAS,OACjB,SAAW,GAAM,EAAM,CAAE,MAAO,CAAE,GAAG,EAAU,OAAQ,CAAE,CAAE,CAAyB,CACrF,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,YACE,EAAM,CAAE,QAAS,GAAG,EAAG,QAAQ,GAAI,CAAyB,EAE9D,UAAU,2HACX,qBAEO,CAAA,CACR,CAAA,CAAA,CAEN,CAEA,SAAS,GAAkB,CAAE,MAAK,MAA8C,CAC9E,IAAM,EAAQ,GAAW,EAAK,CAAE,EAC1B,EAAW,EAAe,GAAM,EAAE,QAAQ,EAC1C,EAAY,EAAG,OAAS,CAAC,EACzB,EAAQ,GAAU,EAAU,CAAQ,EACpC,EAAa,IAAI,IAAI,OAAO,KAAM,EAAS,QAAsC,CAAC,CAAC,CAAC,EACpF,EAAY,GAChB,EAAM,CAAE,MAAO,GAAgB,EAAU,EAAG,CAAQ,CAAE,CAA0B,EAClF,OACE,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAA,SAAY,OAAiB,CAAA,GAC7B,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,sBACX,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,MAAO,EAAG,IACV,SAAW,GAAQ,EAAM,CAAE,IAAK,CAAI,CAA0B,EAC9D,MAAQ,GAAQ,EAAM,CAAE,KAAI,CAA0B,CACvD,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,qBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAO,EAAG,KAAO,GACjB,SAAW,GAAM,EAAM,CAAE,IAAK,EAAE,OAAO,KAAM,CAA0B,CACxE,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,iBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAO,EAAG,MAAQ,GAClB,SAAW,GAAM,EAAM,CAAE,KAAM,EAAE,OAAO,KAAM,CAA0B,CACzE,CAAA,CACI,CAAA,GACP,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,kCAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,OAAO,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,CAAE,SAAK,EAAA,EAAA,IAAA,CAAC,GAAD,CAAa,WAAY,EAAW,IAAI,OAAO,CAAI,CAAA,CAAG,CAAA,CAAA,YACzE,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,OAAoB,EAClC,SAAW,GAAM,EAAS,CAAE,MAAO,OAAO,EAAE,OAAO,KAAK,CAAE,CAAC,CAC5D,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,OAAO,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,CAAE,UAAM,EAAA,EAAA,IAAA,CAAC,GAAD,CAAa,WAAY,EAAW,IAAI,QAAQ,CAAI,CAAA,CAAG,CAAA,CAAA,YAC3E,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,QAAqB,EACnC,SAAW,GAAM,EAAS,CAAE,OAAQ,OAAO,EAAE,OAAO,KAAK,GAAK,IAAA,EAAU,CAAC,CAC1E,CAAA,CACI,CAAA,CACJ,KACL,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,0BACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,cAA2B,EACzC,SAAW,GAAM,EAAS,CAAE,aAAc,OAAO,EAAE,OAAO,KAAK,CAAE,CAAC,CACnE,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,kBACX,EAAA,EAAA,KAAA,CAAC,GAAD,CACE,MAAQ,EAAM,OAAoB,SAClC,SAAW,GAAM,EAAS,CAAE,MAAO,EAAE,OAAO,KAAM,CAAC,WAFrD,EAIE,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,MAAM,gBAAO,MAAY,CAAA,GACjC,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,MAAM,kBAAS,QAAc,CAAA,GACrC,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,MAAM,iBAAQ,OAAa,CAAA,CAC7B,GACH,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,GAAD,CAAsB,QAAmB,aAAY,MAAO,CAAW,CAAA,GACvE,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,OAAQ,EAAS,OACjB,SAAW,GAAM,EAAM,CAAE,MAAO,CAAE,GAAG,EAAU,OAAQ,CAAE,CAAE,CAA0B,CACtF,CAAA,CACD,CAAA,CAAA,CAEN,CAEA,SAAS,GAAmB,CAAE,MAAK,MAA+C,CAChF,IAAM,EAAQ,GAAW,EAAK,CAAE,EAC1B,EAAW,EAAe,GAAM,EAAE,QAAQ,EAC1C,EAAY,EAAG,OAAS,CAAC,EACzB,EAAQ,GAAU,EAAU,CAAQ,EACpC,EAAa,IAAI,IAAI,OAAO,KAAM,EAAS,QAAsC,CAAC,CAAC,CAAC,EACpF,EAAY,GAChB,EAAM,CAAE,MAAO,GAAgB,EAAU,EAAG,CAAQ,CAAE,CAA2B,EACnF,OACE,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAA,SAAY,QAAkB,CAAA,GAC9B,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,kBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,MAAO,EAAG,MAAO,SAAW,GAAM,EAAM,CAAE,MAAO,EAAE,OAAO,KAAM,CAA2B,CAAI,CAAA,CACrG,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,iBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,MAAO,EAAG,KAAM,SAAW,GAAM,EAAM,CAAE,KAAM,EAAE,OAAO,KAAM,CAA2B,CAAI,CAAA,CACnG,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,6BACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,iBAA8B,GAC5C,SAAW,GAAM,EAAS,CAAE,gBAAiB,CAAE,CAAC,CACjD,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,uBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,OAAoB,UAClC,SAAW,GAAM,EAAS,CAAE,MAAO,CAAE,CAAC,CACvC,CAAA,CACI,CAAA,GACP,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,kCAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,sBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,UAAuB,GACrC,SAAW,GAAM,EAAS,CAAE,SAAU,OAAO,EAAE,OAAO,KAAK,CAAE,CAAC,CAC/D,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,0BACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,cAA2B,EACzC,SAAW,GAAM,EAAS,CAAE,aAAc,OAAO,EAAE,OAAO,KAAK,CAAE,CAAC,CACnE,CAAA,CACI,CAAA,CACJ,KACL,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,kBACX,EAAA,EAAA,KAAA,CAAC,GAAD,CACE,MAAQ,EAAM,OAAoB,SAClC,SAAW,GAAM,EAAS,CAAE,MAAO,EAAE,OAAO,KAAM,CAAC,WAFrD,EAIE,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,MAAM,gBAAO,MAAY,CAAA,GACjC,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,MAAM,kBAAS,QAAc,CAAA,GACrC,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,MAAM,iBAAQ,OAAa,CAAA,CAC7B,GACH,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,GAAD,CAAsB,QAAmB,aAAY,MAAO,CAAW,CAAA,GACvE,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,OAAQ,EAAS,OACjB,SAAW,GAAM,EAAM,CAAE,MAAO,CAAE,GAAG,EAAU,OAAQ,CAAE,CAAE,CAA2B,CACvF,CAAA,CACD,CAAA,CAAA,CAEN,CAEA,SAAS,GAAmB,CAAE,MAAK,MAA+C,CAChF,IAAM,EAAQ,GAAW,EAAK,CAAE,EAChC,OACE,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAA,SAAY,QAAkB,CAAA,GAC9B,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,wBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAO,EAAG,OACV,SAAW,GAAM,EAAM,CAAE,OAAQ,OAAO,EAAE,OAAO,KAAK,GAAK,CAAE,CAA2B,CACzF,CAAA,CACI,CAAA,CACP,CAAA,CAAA,CAEN,CAEA,SAAS,GAAoB,CAAE,MAAK,MAAgD,CAClF,IAAM,EAAQ,GAAW,EAAK,CAAE,EAC1B,EAAW,EAAe,GAAM,EAAE,QAAQ,EAC1C,EAAY,EAAG,OAAS,CAAC,EACzB,EAAQ,GAAU,EAAU,CAAQ,EACpC,EAAa,IAAI,IAAI,OAAO,KAAM,EAAS,QAAsC,CAAC,CAAC,CAAC,EACpF,EAAY,GAChB,EAAM,CAAE,MAAO,GAAgB,EAAU,EAAG,CAAQ,CAAE,CAA4B,EACpF,OACE,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAA,SAAY,SAAmB,CAAA,GAC/B,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,kBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,OAAoB,UAClC,SAAW,GAAM,EAAS,CAAE,MAAO,CAAE,CAAC,CACvC,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,sBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,WAAwB,EACtC,SAAW,GAAM,EAAS,CAAE,UAAW,OAAO,EAAE,OAAO,KAAK,CAAE,CAAC,CAChE,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,GAAD,CAAsB,QAAmB,aAAY,MAAO,CAAW,CAAA,GACvE,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,OAAQ,EAAS,OACjB,SAAW,GAAM,EAAM,CAAE,MAAO,CAAE,GAAG,EAAU,OAAQ,CAAE,CAAE,CAA4B,CACxF,CAAA,CACD,CAAA,CAAA,CAEN,CAIA,SAAS,GAAW,EAAO,EAAY,CACrC,IAAM,EAAI,EAAO,EACjB,MAAO,CACL,GAAI,KAAK,KAAK,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAG,CAAC,IAC5D,MAAO,6CAA6C,IACpD,SAAU,WAAW,IACrB,KAAM,WAAW,IACjB,SAAU,MACV,WAAY,MACZ,YAAa,6BACb,KAAM,GACR,CACF,CAEA,SAAS,GAAwB,CAAE,MAAK,MAAoD,CAC1F,IAAM,EAAQ,GAAW,EAAK,CAAE,EAC1B,EAAW,EAAe,GAAM,EAAE,QAAQ,EAC1C,EAAY,EAAG,OAAS,CAAC,EACzB,EAAQ,GAAU,EAAU,CAAQ,EACpC,EAAY,GAChB,EAAM,CAAE,MAAO,GAAgB,EAAU,EAAG,CAAQ,CAAE,CAAgC,EAElF,EAAe,GACnB,EAAM,CAAE,UAAS,CAAgC,EAE7C,EAAc,GAAuB,CAEzC,IAAM,EAAS,EACX,EAAW,EAAG,SAAS,MAAM,EACjC,GAAI,EAAS,OAAS,EACpB,KAAO,EAAS,OAAS,GAAQ,EAAS,KAAK,GAAW,EAAS,MAAM,CAAC,EAE5E,EAAM,CAAE,UAAS,UAAS,CAAgC,CAC5D,EAEA,OACE,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAA,SAAY,cAAwB,CAAA,GAEpC,EAAA,EAAA,KAAA,CAAC,EAAD,CAAO,MAAM,6BAAb,EACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,wDACZ,CAAC,EAAG,EAAG,CAAC,CAAC,CAAC,IAAK,IACd,EAAA,EAAA,KAAA,CAAC,SAAD,CAEE,YAAe,EAAW,CAAc,EACxC,UAAW,oCACT,EAAG,UAAY,EAAI,gCAAkC,+CAJzD,CAOG,EAAE,IAAE,IAAM,EAAI,MAAQ,MACjB,GAPD,CAOC,CACT,CACE,CAAA,GACL,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAU,0CAAiC,sCAAuC,CAAA,CAChF,KAEP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,2BACX,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,QAAS,EAAG,aACZ,SAAW,GAAM,EAAM,CAAE,aAAc,CAAE,CAAgC,CAC1E,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,6BACX,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,QAAS,EAAG,gBACZ,SAAW,GAAM,EAAM,CAAE,gBAAiB,CAAE,CAAgC,CAC7E,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,wBACX,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,QAAS,EAAG,WACZ,SAAW,GAAM,EAAM,CAAE,WAAY,CAAE,CAAgC,CACxE,CAAA,CACI,CAAA,EACN,EAAG,aACF,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,iCACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAO,EAAG,aAAe,GACzB,YAAY,WACZ,SAAW,GAAM,EAAM,CAAE,YAAa,EAAE,OAAO,KAAM,CAAgC,CACtF,CAAA,CACI,CAAA,GAGT,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,8CAAf,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,kDAAf,EACE,EAAA,EAAA,KAAA,CAAC,GAAD,CAAA,SAAA,CAAY,aAAW,EAAG,SAAS,OAAO,GAAa,CAAA,CAAA,GACvD,EAAA,EAAA,KAAA,CAAC,SAAD,CACE,YAAe,EAAY,CAAC,GAAG,EAAG,SAAU,GAAW,EAAG,SAAS,MAAM,CAAC,CAAC,EAC3E,UAAU,2FACV,MAAM,uBAHR,EAKE,EAAA,EAAA,IAAA,CAAC,EAAA,KAAD,CAAM,KAAM,EAAK,CAAA,EAAC,MACZ,GACL,IACJ,EAAG,SAAS,KAAK,EAAG,KACnB,EAAA,EAAA,IAAA,CAAC,GAAD,CAEE,MAAO,EACP,QAAS,EACT,aAAc,EAAG,aACjB,gBAAiB,EAAG,gBACpB,WAAY,EAAG,WACf,SAAW,GAAO,CAChB,IAAM,EAAO,CAAC,GAAG,EAAG,QAAQ,EAC5B,EAAK,GAAO,EACZ,EAAY,CAAI,CAClB,EACA,aAAgB,EAAY,EAAG,SAAS,QAAQ,EAAG,IAAM,IAAM,CAAG,CAAC,CACpE,EAZM,EAAE,EAYR,CACF,CACE,KAEL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,8CAAf,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAA,SAAY,OAAiB,CAAA,GAC7B,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,4BACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,qBAAkC,GAChD,SAAW,GAAM,EAAS,CAAE,oBAAqB,CAAE,CAAC,CACrD,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,uBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,WAAwB,GACtC,SAAW,GAAM,EAAS,CAAE,UAAW,CAAE,CAAC,CAC3C,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,8BACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,iBAA8B,GAC5C,SAAW,GAAM,EAAS,CAAE,gBAAiB,CAAE,CAAC,CACjD,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,4BACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,eAA4B,GAC1C,SAAW,GAAM,EAAS,CAAE,cAAe,CAAE,CAAC,CAC/C,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,8BACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,uBAAoC,GAClD,SAAW,GAAM,EAAS,CAAE,sBAAuB,CAAE,CAAC,CACvD,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,8BACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,aAA0B,GACxC,SAAW,GAAM,EAAS,CAAE,YAAa,CAAE,CAAC,CAC7C,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,wBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAQ,EAAM,cAA2B,EACzC,SAAW,GAAM,EAAS,CAAE,aAAc,OAAO,EAAE,OAAO,KAAK,CAAE,CAAC,CACnE,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,GAAD,CAAsB,QAAO,MAAO,CAAW,CAAA,CAC5C,GACL,CAAA,CAAA,CAEN,CAEA,SAAS,GAAO,CAAE,UAAS,YAAkE,CAC3F,OACE,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,YAAe,EAAS,CAAC,CAAO,EAChC,UAAW,4EACT,EAAU,cAAgB,0BAG5B,EAAA,EAAA,IAAA,CAAC,OAAD,CACE,UAAW,6EACT,EAAU,gBAAkB,mBAE/B,CAAA,CACK,CAAA,CAEZ,CAEA,SAAS,GAAW,CAClB,QACA,UACA,eACA,kBACA,aACA,WACA,YASC,CACD,IAAM,EAAO,GAAwB,EAAS,CAAE,GAAG,EAAS,GAAG,CAAE,CAAC,EAClE,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,8DAAf,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,kDAAf,EACE,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAU,mDAAhB,CAA0D,IAAE,EAAQ,CAAQ,KAC5E,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,QAAS,EACT,UAAU,mCACV,MAAM,2BAEN,EAAA,EAAA,IAAA,CAAC,EAAA,OAAD,CAAQ,KAAM,EAAK,CAAA,CACb,CAAA,CACL,KACL,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,iBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,MAAO,EAAQ,KAAM,SAAW,GAAM,EAAI,CAAE,KAAM,EAAE,OAAO,KAAM,CAAC,CAAI,CAAA,CAC5E,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,sBACX,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,MAAO,EAAQ,MACf,SAAW,GAAQ,EAAI,CAAE,MAAO,CAAI,CAAC,EACrC,MAAQ,GAAQ,EAAI,CAAE,SAAU,CAAI,CAAC,CACtC,CAAA,CACI,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,iBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAO,EAAQ,MAAQ,GACvB,SAAW,GAAM,EAAI,CAAE,KAAM,EAAE,OAAO,KAAM,CAAC,CAC9C,CAAA,CACI,CAAA,GACP,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,kCAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,wBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAO,EAAQ,WACf,SAAW,GAAM,EAAI,CAAE,WAAY,EAAE,OAAO,KAAM,CAAC,CACpD,CAAA,CACI,CAAA,EACN,IACC,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,sBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAO,EAAQ,UAAY,GAC3B,SAAW,GAAM,EAAI,CAAE,SAAU,EAAE,OAAO,KAAM,CAAC,CAClD,CAAA,CACI,CAAA,CAEN,IACJ,IACC,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,wBACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAO,EAAQ,aAAe,GAC9B,SAAW,GAAM,EAAI,CAAE,YAAa,EAAE,OAAO,KAAM,CAAC,CACrD,CAAA,CACI,CAAA,EAER,IACC,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAM,oCACX,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAO,EAAQ,aAAe,GAC9B,YAAY,kBACZ,SAAW,GAAM,EAAI,CAAE,YAAa,EAAE,OAAO,OAAS,IAAA,EAAU,CAAC,CAClE,CAAA,CACI,CAAA,CAEN,GAET,CCp8BA,IAAa,GAAmC,CAC9C,CACE,KAAM,aACN,SAAU,QACV,KAAM,aACN,YAAa,wGACb,KAAM,CAAC,OAAQ,YAAa,MAAM,EAClC,WACE,EAAI,aAAc,aAAc,CAAC,EAAK,wBAAyB,CAAE,KAAM,MAAO,CAAC,CAAC,CAAC,CACrF,EACA,CACE,KAAM,gBACN,SAAU,QACV,KAAM,UACN,YAAa,2GACb,KAAM,CAAC,UAAW,QAAS,SAAS,EACpC,WACE,EAAI,gBAAiB,UAAW,CAC9B,EAAK,0BAA2B,CAC9B,KAAM,WACN,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,WAAY,GACZ,cAAe,EACf,WAAY,IACd,CAAC,CACH,CAAC,CACL,EACA,CACE,KAAM,cACN,SAAU,QACV,KAAM,QACN,YAAa,8FACb,KAAM,CAAC,QAAS,QAAS,OAAO,EAChC,WAAc,EAAI,cAAe,QAAS,CAAC,EAAM,EAAY,IAAK,GAAG,EAAG,aAAa,CAAC,CAAC,CACzF,EACA,CACE,KAAM,sBACN,SAAU,QACV,KAAM,qBACN,YAAa,4FACb,KAAM,CAAC,QAAS,UAAW,WAAW,EACtC,WACE,EAAI,sBAAuB,kBAAmB,CAC5C,EAAM,EAAY,IAAK,GAAG,EAAG,OAAO,EACpC,EAAK,4BAA6B,CAChC,MAAO,iBACP,SAAU,GACV,MAAO,SACP,WAAY,EACZ,cAAe,EACjB,CAAC,CACH,CAAC,CACL,EACA,CACE,KAAM,eACN,SAAU,QACV,KAAM,SACN,YAAa,qEACb,KAAM,CAAC,SAAU,UAAW,KAAK,EACjC,WAAc,EAAI,eAAgB,SAAU,CAAC,EAAO,EAAE,CAAC,CAAC,CAC1D,EACA,CACE,KAAM,gBACN,SAAU,QACV,KAAM,UACN,YAAa,4EACb,KAAM,CAAC,UAAW,YAAa,MAAM,EACrC,WAAc,EAAI,gBAAiB,UAAW,CAAC,EAAQ,CAAC,CAAC,CAC3D,CACF,ECvEa,GAAoC,CAC/C,CACE,KAAM,cACN,SAAU,SACV,KAAM,gBACN,YAAa,uFACb,KAAM,CAAC,OAAQ,QAAS,UAAU,EAClC,WACE,EAAI,cAAe,cAAe,CAChC,EAAM,EAAY,IAAK,GAAI,MAAM,EAAG,OAAQ,CAAE,MAAO,IAAK,WAAY,GAAI,cAAe,EAAG,CAAC,CAC/F,CAAC,CACL,EACA,CACE,KAAM,8BACN,SAAU,SACV,KAAM,yBACN,YAAa,iIACb,KAAM,CAAC,OAAQ,OAAQ,QAAS,cAAe,YAAY,EAC3D,WACE,EAAI,8BAA+B,cAAe,CAChD,EAAM,EAAY,IAAK,GAAI,MAAM,EAAG,OAAQ,CAAE,MAAO,IAAK,MAAO,OAAQ,WAAY,GAAI,cAAe,EAAG,CAAC,EAC5G,EAAK,8BAA+B,CAClC,MAAO,iBACP,SAAU,GACV,MAAO,QACP,WAAY,EACZ,cAAe,EACjB,CAAC,EACD,EAAQ,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,CAC7C,CAAC,CACL,EACA,CACE,KAAM,qBACN,SAAU,SACV,KAAM,uBACN,YAAa,mIACb,KAAM,CAAC,WAAY,cAAe,YAAa,QAAS,YAAa,UAAU,EAC/E,WACE,EACE,qBACA,WACA,CACE,EAAK,aAAc,CACjB,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,MAAO,SACP,cAAe,EACf,WAAY,GACZ,cAAe,CACjB,CAAC,EACD,EAAK,wCAAyC,CAC5C,MAAO,iBACP,MAAO,SACP,SAAU,GACV,cAAe,EACjB,CAAC,EACD,EAAQ,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,CAC7C,CACF,CACJ,EACA,CACE,KAAM,cACN,SAAU,SACV,KAAM,6BACN,YAAa,iGACb,KAAM,CAAC,OAAQ,WAAY,QAAS,OAAQ,SAAS,EACrD,WACE,EAAI,cAAe,OAAQ,CACzB,EAAK,gCAAiC,CACpC,KAAM,WACN,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,MAAO,SACP,WAAY,GACZ,WAAY,GACd,CAAC,EACD,EAAK,6BAA8B,CACjC,MAAO,iBACP,MAAO,SACP,cAAe,EACjB,CAAC,EACD,EAAM,EAAY,IAAK,IAAK,MAAM,EAAG,OAAQ,CAAE,MAAO,GAAI,CAAC,CAC7D,CAAC,CACL,EACA,CACE,KAAM,wBACN,SAAU,SACV,KAAM,iBACN,YAAa,wHACb,KAAM,CAAC,OAAQ,OAAQ,QAAS,YAAa,SAAS,EACtD,WACE,EAAI,wBAAyB,YAAa,CACxC,EAAK,mBAAoB,CACvB,SAAU,GACV,WAAY,OACZ,MAAO,mBACP,cAAe,EACf,MAAO,SACP,WAAY,GACZ,cAAe,CACjB,CAAC,EACD,EAAK,4BAA6B,CAChC,KAAM,WACN,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,MAAO,SACP,WAAY,KACZ,cAAe,CACjB,CAAC,EACD,EAAK,4DAA6D,CAChE,MAAO,iBACP,MAAO,SACP,SAAU,GACV,cAAe,EACjB,CAAC,CACH,CAAC,CACL,EACA,CACE,KAAM,sBACN,SAAU,SACV,KAAM,mBACN,YAAa,wGACb,KAAM,CAAC,eAAgB,MAAO,QAAS,OAAO,EAC9C,WACE,EACE,sBACA,eACA,CACE,EAAK,qCAAsC,CACzC,MAAO,sBACP,MAAO,SACP,SAAU,GACV,WAAY,GACZ,cAAe,EACjB,CAAC,CACH,EACA,CAAE,gBAAiB,mBAAoB,WAAY,EAAG,cAAe,CAAE,CACzE,CACJ,EACA,CACE,KAAM,gCACN,SAAU,SACV,KAAM,yBACN,YAAa,gHACb,KAAM,CAAC,OAAQ,kBAAmB,YAAa,WAAW,EAC1D,WACE,EAAI,gCAAiC,sBAAuB,CAC1D,EAAK,kBAAmB,CACtB,MAAO,iBACP,SAAU,GACV,MAAO,QACP,WAAY,EACZ,cAAe,EACf,KAAM,GACR,CAAC,EACD,EAAM,EAAY,IAAK,GAAI,MAAM,EAAG,OAAQ,CAAE,MAAO,IAAK,WAAY,EAAG,cAAe,EAAG,CAAC,CAC9F,CAAC,CACL,EACA,CACE,KAAM,iBACN,SAAU,SACV,KAAM,iBACN,YAAa,mGACb,KAAM,CAAC,UAAW,aAAc,WAAY,cAAc,EAC1D,WACE,EAAI,iBAAkB,UAAW,CAC/B,EAAK,oCAAqC,CACxC,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,MAAO,SACP,WAAY,GACZ,cAAe,CACjB,CAAC,EACD,EAAK,kDAAmD,CACtD,MAAO,iBACP,MAAO,SACP,cAAe,EACjB,CAAC,CACH,CAAC,CACL,EACA,CACE,KAAM,2BACN,SAAU,SACV,KAAM,iBACN,YAAa,yEACb,KAAM,CAAC,OAAQ,UAAW,OAAO,EACjC,WACE,EAAI,2BAA4B,iBAAkB,CAChD,EAAM,EAAY,IAAK,GAAI,MAAM,EAAG,OAAQ,CAAE,MAAO,IAAK,WAAY,GAAI,cAAe,CAAE,CAAC,EAC5F,EAAK,sCAAuC,CAC1C,MAAO,SACP,MAAO,iBACP,SAAU,GACV,cAAe,EACjB,CAAC,CACH,CAAC,CACL,EACA,CACE,KAAM,qBACN,SAAU,SACV,KAAM,qBACN,YAAa,+HACb,KAAM,CAAC,QAAS,WAAY,QAAS,aAAc,OAAO,EAC1D,WACE,EAAI,qBAAsB,cAAe,CACvC,EAAK,oBAAqB,CACxB,MAAO,mBACP,SAAU,GACV,WAAY,OACZ,cAAe,EACf,MAAO,SACP,WAAY,GACZ,cAAe,CACjB,CAAC,EACD,EAAK,sCAAuC,CAC1C,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,MAAO,SACP,cAAe,GACf,WAAY,GACd,CAAC,CACH,CAAC,CACL,CACF,ECpOa,GAAkC,CAC7C,CACE,KAAM,kBACN,SAAU,OACV,KAAM,iBACN,YAAa,6GACb,KAAM,CAAC,OAAQ,MAAO,aAAc,aAAa,EACjD,WACE,EAAI,kBAAmB,kBAAmB,CACxC,EAAK,gDAAiD,CACpD,MAAO,SACP,MAAO,gBACP,SAAU,GACV,WAAY,GACZ,cAAe,EACjB,CAAC,CACH,CAAC,CACL,EACA,CACE,KAAM,gBACN,SAAU,OACV,KAAM,eACN,YAAa,kIACb,KAAM,CAAC,OAAQ,WAAY,OAAQ,SAAU,OAAO,EACpD,WACE,EAAI,gBAAiB,eAAgB,CACnC,EAAQ,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,EAC3C,EAAK,4CAA6C,CAChD,MAAO,SACP,MAAO,mBACP,SAAU,GACV,WAAY,OACZ,cAAe,EACf,WAAY,EACZ,cAAe,CACjB,CAAC,EACD,EAAQ,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,CAC7C,CAAC,CACL,EACA,CACE,KAAM,qBACN,SAAU,OACV,KAAM,gBACN,YAAa,sHACb,KAAM,CAAC,MAAO,OAAQ,QAAS,UAAW,mBAAmB,EAC7D,WACE,EACE,qBACA,gBACA,CACE,EAAK,gBAAiB,CACpB,SAAU,GACV,WAAY,OACZ,MAAO,iBACP,cAAe,EACf,WAAY,GACZ,cAAe,CACjB,CAAC,EACD,EAAK,gCAAiC,CAAE,SAAU,GAAI,WAAY,EAAG,cAAe,EAAG,KAAM,OAAQ,CAAC,EACtG,EAAK,6BAA8B,CAAE,SAAU,GAAI,WAAY,EAAG,cAAe,EAAG,KAAM,QAAS,CAAC,EACpG,EAAK,gCAAiC,CAAE,SAAU,GAAI,WAAY,EAAG,cAAe,EAAG,KAAM,KAAM,CAAC,EACpG,EAAK,oBAAqB,CAAE,SAAU,GAAI,WAAY,EAAG,cAAe,GAAI,KAAM,SAAU,CAAC,CAC/F,EACA,CAAE,gBAAiB,sBAAuB,WAAY,EAAG,cAAe,EAAG,YAAa,GAAI,aAAc,EAAG,CAC/G,CACJ,EACA,CACE,KAAM,iBACN,SAAU,OACV,KAAM,sBACN,YAAa,sGACb,KAAM,CAAC,OAAQ,UAAW,QAAS,OAAO,EAC1C,WACE,EAAI,iBAAkB,eAAgB,CACpC,EAAK,4CAA6C,CAChD,MAAO,SACP,MAAO,mBACP,SAAU,GACV,WAAY,GACZ,cAAe,EACjB,CAAC,CACH,CAAC,CACL,CACF,ECnFa,GAAqC,CAChD,CACE,KAAM,wBACN,SAAU,UACV,KAAM,kBACN,YAAa,yFACb,KAAM,CAAC,WAAY,OAAQ,YAAa,SAAS,EACjD,WACE,EAAI,wBAAyB,kBAAmB,CAC9C,EAAQ,wBAAyB,CAAE,WAAY,EAAG,CAAC,EACnD,EACE,oHACA,CAAE,cAAe,EAAG,CACtB,CACF,CAAC,CACL,EACA,CACE,KAAM,qBACN,SAAU,UACV,KAAM,aACN,YAAa,yJACb,KAAM,CAAC,OAAQ,QAAS,UAAW,OAAQ,YAAa,WAAW,EACnE,WACE,EAAI,qBAAsB,aAAc,CACtC,EAAQ,YAAY,EACpB,EAAQ,0CAA2C,CAAE,MAAO,EAAG,cAAe,CAAE,CAAC,EACjF,EAAM,2BAA4B,CAAE,SAAU,EAAG,CAAC,EAClD,EAAM,EAAY,IAAK,IAAK,MAAM,EAAG,OAAQ,CAAE,MAAO,IAAK,WAAY,EAAG,CAAC,EAC3E,EACE,8IACA,CAAE,WAAY,EAAG,CACnB,EACA,EAAK,qBAAsB,CACzB,MAAO,mBACP,WAAY,OACZ,WAAY,EACZ,cAAe,GACf,KAAM,GACR,CAAC,CACH,CAAC,CACL,EACA,CACE,KAAM,0BACN,SAAU,UACV,KAAM,uBACN,YAAa,4IACb,KAAM,CAAC,UAAW,UAAW,OAAQ,WAAY,YAAY,EAC7D,WACE,EAAI,0BAA2B,eAAgB,CAC7C,EAAM,EAAY,IAAK,IAAK,SAAS,EAAG,UAAW,CAAE,MAAO,GAAI,CAAC,EACjE,EAAK,UAAW,CACd,MAAO,mBACP,SAAU,GACV,WAAY,OACZ,cAAe,EACf,WAAY,GACZ,cAAe,CACjB,CAAC,EACD,EAAQ,wCAAyC,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,EACpF,EAAK,6FAA8F,CACjG,cAAe,CACjB,CAAC,EACD,EAAK,cAAe,CAAE,MAAO,mBAAoB,WAAY,OAAQ,cAAe,GAAI,KAAM,GAAI,CAAC,CACrG,CAAC,CACL,EACA,CACE,KAAM,qBACN,SAAU,UACV,KAAM,sBACN,YAAa,qFACb,KAAM,CAAC,QAAS,OAAQ,UAAW,SAAS,EAC5C,WACE,EAAI,qBAAsB,eAAgB,CACxC,EAAM,EAAY,IAAK,IAAK,SAAS,EAAG,UAAW,CAAE,MAAO,GAAI,CAAC,EACjE,EAAQ,gBAAiB,CAAE,WAAY,GAAI,cAAe,CAAE,CAAC,EAC7D,EAAK,yEAAyE,CAChF,CAAC,CACL,EACA,CACE,KAAM,8BACN,SAAU,UACV,KAAM,qBACN,YAAa,uIACb,KAAM,CAAC,aAAc,WAAY,eAAgB,SAAS,EAC1D,WACE,EAAI,8BAA+B,cAAe,CAChD,EAAQ,cAAc,EACtB,EAAM,EAAY,IAAK,IAAK,SAAS,EAAG,UAAW,CAAE,MAAO,GAAI,CAAC,EACjE,EAAK,gBAAiB,CAAE,WAAY,OAAQ,WAAY,EAAG,cAAe,CAAE,CAAC,EAC7E,EAAK,8BAA+B,CAAE,SAAU,GAAI,cAAe,EAAG,CAAC,EACvE,EAAM,EAAY,IAAK,IAAK,SAAS,EAAG,UAAW,CAAE,MAAO,GAAI,CAAC,EACjE,EAAK,gBAAiB,CAAE,WAAY,OAAQ,WAAY,EAAG,cAAe,CAAE,CAAC,EAC7E,EAAK,8BAA+B,CAAE,SAAU,GAAI,cAAe,EAAG,CAAC,CACzE,CAAC,CACL,EACA,CACE,KAAM,sBACN,SAAU,UACV,KAAM,yBACN,YAAa,0GACb,KAAM,CAAC,OAAQ,QAAS,UAAW,QAAS,iBAAiB,EAC7D,WACE,EAAI,sBAAuB,cAAe,CACxC,EAAQ,aAAa,EACrB,EAAK,mCAAoC,CACvC,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,WAAY,EACZ,cAAe,EACf,KAAM,GACR,CAAC,EACD,EAAM,wDAAyD,CAAE,SAAU,EAAG,CAAC,EAC/E,EAAQ,CAAE,WAAY,GAAI,cAAe,CAAE,CAAC,EAC5C,EAAK,oCAAqC,CACxC,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,WAAY,EACZ,cAAe,EACf,KAAM,GACR,CAAC,EACD,EAAM,yDAA0D,CAAE,SAAU,EAAG,CAAC,EAChF,EAAQ,CAAE,WAAY,GAAI,cAAe,CAAE,CAAC,EAC5C,EAAK,oCAAqC,CACxC,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,WAAY,EACZ,cAAe,EACf,KAAM,GACR,CAAC,EACD,EAAM,2CAA4C,CAAE,SAAU,GAAI,cAAe,EAAG,CAAC,CACvF,CAAC,CACL,EACA,CACE,KAAM,gBACN,SAAU,UACV,KAAM,aACN,YAAa,yFACb,KAAM,CAAC,QAAS,aAAc,YAAa,aAAa,EACxD,WACE,EAAI,gBAAiB,aAAc,CACjC,EAAK,wDAAyD,CAC5D,WAAY,kBACZ,SAAU,GACV,MAAO,SACP,WAAY,GACZ,WAAY,GACd,CAAC,EACD,EAAK,kBAAmB,CAAE,MAAO,iBAAkB,MAAO,SAAU,cAAe,EAAG,CAAC,CACzF,CAAC,CACL,EACA,CACE,KAAM,wBACN,SAAU,UACV,KAAM,gBACN,YAAa,+GACb,KAAM,CAAC,SAAU,SAAU,SAAU,UAAU,EAC/C,WACE,EAAI,wBAAyB,SAAU,CACrC,EAAM,EAAY,GAAI,GAAI,IAAI,EAAG,SAAU,CAAE,MAAO,GAAI,aAAc,GAAI,WAAY,GAAI,cAAe,CAAE,CAAC,EAC5G,EAAK,WAAY,CAAE,MAAO,SAAU,WAAY,OAAQ,WAAY,EAAG,cAAe,CAAE,CAAC,EACzF,EAAM,qBAAsB,CAAE,MAAO,SAAU,SAAU,EAAG,CAAC,EAC7D,EAAO,EAAE,CACX,CAAC,CACL,EACA,CACE,KAAM,sBACN,SAAU,UACV,KAAM,gBACN,YAAa,uIACb,KAAM,CAAC,SAAU,OAAQ,SAAU,WAAY,OAAO,EACtD,WACE,EAAI,sBAAuB,gBAAiB,CAC1C,EAAK,qBAAsB,CAAE,WAAY,GAAI,cAAe,CAAE,CAAC,EAC/D,EACE,sJACA,CAAE,cAAe,EAAG,WAAY,GAAI,CACtC,EACA,EAAK,+CAAgD,CAAE,cAAe,EAAG,WAAY,GAAI,CAAC,EAC1F,EAAK,SAAU,CAAE,WAAY,kBAAmB,cAAe,EAAG,CAAC,CACrE,CAAC,CACL,EACA,CACE,KAAM,kBACN,SAAU,UACV,KAAM,oBACN,YAAa,uHACb,KAAM,CAAC,MAAO,UAAW,MAAO,YAAa,MAAM,EACnD,WACE,EACE,kBACA,UACA,CACE,EAAK,aAAc,CACjB,MAAO,mBACP,SAAU,GACV,WAAY,OACZ,cAAe,EACf,WAAY,GACZ,cAAe,CACjB,CAAC,EACD,EAAK,gFAAiF,CAAE,cAAe,EAAG,CAAC,CAC7G,EACA,CAAE,gBAAiB,sBAAuB,WAAY,EAAG,cAAe,EAAG,YAAa,GAAI,aAAc,EAAG,CAC/G,CACJ,EACA,CACE,KAAM,wBACN,SAAU,UACV,KAAM,gBACN,YAAa,4HACb,KAAM,CAAC,OAAQ,WAAY,WAAY,YAAa,QAAQ,EAC5D,WACE,EAAI,wBAAyB,gBAAiB,CAC5C,EAAQ,0BAA2B,CAAE,WAAY,GAAI,cAAe,EAAG,CAAC,EACxE,EAAK,qBAAsB,CAAE,WAAY,OAAQ,WAAY,EAAG,cAAe,CAAE,CAAC,EAClF,EAAM,yCAAyC,EAC/C,EAAK,sBAAuB,CAAE,WAAY,OAAQ,WAAY,EAAG,cAAe,CAAE,CAAC,EACnF,EAAM,mCAAmC,EACzC,EAAK,+BAAgC,CAAE,WAAY,OAAQ,WAAY,EAAG,cAAe,CAAE,CAAC,EAC5F,EAAM,8BAA8B,EACpC,EAAK,aAAc,CAAE,WAAY,OAAQ,WAAY,EAAG,cAAe,CAAE,CAAC,EAC1E,EAAM,8BAA+B,CAAE,SAAU,EAAG,CAAC,EACrD,EAAO,EAAE,CACX,CAAC,CACL,EACA,CACE,KAAM,sBACN,SAAU,UACV,KAAM,cACN,YAAa,sEACb,KAAM,CAAC,OAAQ,UAAW,YAAa,SAAS,EAChD,WACE,EAAI,sBAAuB,UAAW,CACpC,EAAQ,gBAAiB,CAAE,WAAY,GAAI,cAAe,CAAE,CAAC,EAC7D,EAAK,oCAAqC,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,EAC7E,EAAK,6BAA8B,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,EACtE,EAAK,yDAA0D,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,EAClG,EAAK,4CAA6C,CAAE,WAAY,EAAG,cAAe,EAAG,CAAC,CACxF,CAAC,CACL,EACA,CACE,KAAM,aACN,SAAU,UACV,KAAM,YACN,YAAa,2FACb,KAAM,CAAC,KAAM,MAAO,MAAO,UAAW,kBAAkB,EACxD,WACE,EAAI,aAAc,MAAO,CACvB,EAAQ,iBAAiB,EACzB,EAAK,4CAA6C,CAChD,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,WAAY,EACZ,cAAe,EACf,WAAY,GACd,CAAC,EACD,EACE,mKACA,CAAE,cAAe,GAAI,WAAY,GAAI,CACvC,CACF,CAAC,CACL,EACA,CACE,KAAM,oBACN,SAAU,UACV,KAAM,WACN,YAAa,gIACb,KAAM,CAAC,QAAS,UAAW,UAAW,cAAc,EACpD,WACE,EACE,oBACA,WACA,CACE,EAAQ,iBAAkB,CAAE,MAAO,QAAS,CAAC,EAC7C,EAAK,SAAU,CACb,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,MAAO,SACP,MAAO,mBACP,WAAY,EACZ,cAAe,CACjB,CAAC,EACD,EAAM,4BAA6B,CAAE,MAAO,SAAU,SAAU,EAAG,CAAC,EACpE,EAAO,CAAC,EACR,EAAK,iCAAkC,CACrC,MAAO,SACP,MAAO,gBACP,SAAU,GACV,cAAe,EACjB,CAAC,CACH,CACF,CACJ,EACA,CACE,KAAM,mBACN,SAAU,UACV,KAAM,2BACN,YAAa,mGACb,KAAM,CAAC,WAAY,YAAa,OAAQ,SAAU,eAAe,EACjE,WACE,EAAI,mBAAoB,WAAY,CAClC,EAAQ,WAAW,EACnB,EAAK,6BAA8B,CAAE,WAAY,OAAQ,WAAY,EAAG,cAAe,CAAE,CAAC,EAC1F,EAAM,kCAAmC,CAAE,SAAU,EAAG,CAAC,EACzD,EAAK,oCAAqC,CAAE,WAAY,OAAQ,WAAY,EAAG,cAAe,CAAE,CAAC,EACjG,EAAM,gCAAiC,CAAE,SAAU,EAAG,CAAC,EACvD,EAAK,8BAA+B,CAAE,WAAY,OAAQ,WAAY,EAAG,cAAe,CAAE,CAAC,EAC3F,EAAM,kCAAmC,CAAE,SAAU,GAAI,cAAe,EAAG,CAAC,CAC9E,CAAC,CACL,EACA,CACE,KAAM,0BACN,SAAU,UACV,KAAM,kBACN,YAAa,8HACb,KAAM,CAAC,UAAW,UAAW,QAAS,SAAU,MAAM,EACtD,WACE,EAAI,0BAA2B,kBAAmB,CAChD,EAAM,EAAY,IAAK,IAAK,OAAO,EAAG,QAAS,CAAE,MAAO,IAAK,aAAc,EAAG,CAAC,EAC/E,EAAK,cAAe,CAClB,MAAO,mBACP,SAAU,GACV,WAAY,OACZ,cAAe,EACf,MAAO,SACP,WAAY,GACZ,cAAe,CACjB,CAAC,EACD,EAAQ,sCAAuC,CAAE,MAAO,SAAU,WAAY,EAAG,cAAe,CAAE,CAAC,EACnG,EAAM,yBAA0B,CAAE,MAAO,SAAU,SAAU,EAAG,CAAC,EACjE,EAAO,aAAc,qBAAqB,EAC1C,EAAO,EAAE,CACX,CAAC,CACL,EACA,CACE,KAAM,0BACN,SAAU,UACV,KAAM,kBACN,YAAa,qHACb,KAAM,CAAC,QAAS,YAAa,QAAS,OAAQ,OAAO,EACrD,WACE,EAAI,0BAA2B,QAAS,CACtC,EAAM,EAAY,IAAK,IAAK,SAAS,EAAG,QAAS,CAAE,MAAO,IAAK,KAAM,IAAK,aAAc,CAAE,CAAC,EAC3F,EAAQ,4CAA6C,CAAE,WAAY,GAAI,cAAe,CAAE,CAAC,EACzF,EAAM,cAAe,CAAE,SAAU,GAAI,cAAe,EAAG,CAAC,CAC1D,CAAC,CACL,EACA,CACE,KAAM,qBACN,SAAU,UACV,KAAM,aACN,YAAa,sHACb,KAAM,CAAC,QAAS,OAAQ,YAAa,OAAQ,MAAM,EACnD,WACE,EACE,qBACA,QACA,CACE,EAAK,MAAO,CACV,MAAO,SACP,MAAO,sBACP,SAAU,GACV,WAAY,OACZ,cAAe,EACf,WAAY,GACZ,cAAe,CACjB,CAAC,EACD,EAAK,KAAM,CACT,MAAO,SACP,MAAO,sBACP,SAAU,GACV,WAAY,OACZ,WAAY,EACZ,cAAe,EACjB,CAAC,CACH,EACA,CAAE,gBAAiB,mBAAoB,WAAY,EAAG,cAAe,CAAE,CACzE,CACJ,EACA,CACE,KAAM,qBACN,SAAU,UACV,KAAM,eACN,YAAa,kGACb,KAAM,CAAC,OAAQ,UAAW,YAAa,YAAa,WAAW,EAC/D,WACE,EACE,qBACA,OACA,CACE,EAAK,+CAAgD,CACnD,WAAY,6BACZ,SAAU,GACV,MAAO,gBACP,WAAY,GACZ,cAAe,GACf,YAAa,GACb,aAAc,EAChB,CAAC,CACH,EACA,CAAE,gBAAiB,sBAAuB,WAAY,EAAG,cAAe,EAAG,YAAa,GAAI,aAAc,EAAG,CAC/G,CACJ,CACF,ECxZa,GAAqC,CAChD,CACE,KAAM,eACN,SAAU,UACV,KAAM,yBACN,YAAa,0GACb,KAAM,CAAC,WAAY,WAAY,aAAc,MAAM,EACnD,WACE,EAAI,eAAgB,eAAgB,CAClC,EAAQ,qBAAsB,CAAE,MAAO,SAAU,WAAY,EAAG,CAAC,EACjE,EAAK,sBAAuB,CAAE,MAAO,QAAS,CAAC,EAC/C,EAAK,6BAA8B,CAAE,MAAO,QAAS,CAAC,EACtD,EAAK,+BAAgC,CAAE,MAAO,SAAU,cAAe,EAAG,CAAC,CAC7E,CAAC,CACL,EACA,CACE,KAAM,qBACN,SAAU,UACV,KAAM,sBACN,YAAa,kIACb,KAAM,CAAC,WAAY,QAAS,WAAY,SAAS,EACjD,WACE,EAAI,qBAAsB,iBAAkB,CAC1C,EAAK,IAAK,CAAE,MAAO,SAAU,SAAU,GAAI,WAAY,GAAI,cAAe,CAAE,CAAC,EAC7E,EAAK,OAAQ,CAAE,MAAO,SAAU,WAAY,OAAQ,cAAe,CAAE,CAAC,EACtE,EAAM,mCAAoC,CAAE,MAAO,SAAU,SAAU,EAAG,CAAC,EAC3E,EAAO,EAAE,EACT,EAAK,KAAM,CAAE,MAAO,SAAU,SAAU,GAAI,cAAe,CAAE,CAAC,EAC9D,EAAK,UAAW,CAAE,MAAO,SAAU,WAAY,OAAQ,cAAe,CAAE,CAAC,EACzE,EAAM,kCAAmC,CAAE,MAAO,SAAU,SAAU,EAAG,CAAC,EAC1E,EAAO,EAAE,EACT,EAAK,KAAM,CAAE,MAAO,SAAU,SAAU,GAAI,cAAe,CAAE,CAAC,EAC9D,EAAK,WAAY,CAAE,MAAO,SAAU,WAAY,OAAQ,cAAe,CAAE,CAAC,EAC1E,EAAM,iCAAkC,CAAE,MAAO,SAAU,SAAU,GAAI,cAAe,EAAG,CAAC,CAC9F,CAAC,CACL,EACA,CACE,KAAM,uBACN,SAAU,UACV,KAAM,iBACN,YAAa,4GACb,KAAM,CAAC,eAAgB,aAAc,aAAc,gBAAgB,EACnE,WACE,EAAI,uBAAwB,iBAAkB,CAC5C,EAAQ,QAAQ,EAChB,EAAM,EAAY,IAAK,IAAK,QAAQ,EAAG,SAAU,CAAE,MAAO,GAAI,CAAC,EAC/D,EAAO,CAAC,EACR,EAAQ,OAAO,EACf,EAAM,EAAY,IAAK,IAAK,OAAO,EAAG,QAAS,CAAE,MAAO,GAAI,CAAC,EAC7D,EAAO,EAAE,CACX,CAAC,CACL,EACA,CACE,KAAM,uBACN,SAAU,UACV,KAAM,uBACN,YAAa,8HACb,KAAM,CAAC,UAAW,UAAW,aAAc,MAAM,EACjD,WACE,EAAI,uBAAwB,eAAgB,CAC1C,EAAM,EAAY,IAAK,IAAK,SAAS,EAAG,UAAW,CAAE,MAAO,IAAK,WAAY,EAAG,CAAC,EACjF,EAAQ,kBAAmB,CAAE,WAAY,GAAI,cAAe,CAAE,CAAC,EAC/D,EAAK,mFAAoF,CAAE,cAAe,EAAG,CAAC,CAChH,CAAC,CACL,EACA,CACE,KAAM,sBACN,SAAU,UACV,KAAM,cACN,YAAa,gFACb,KAAM,CAAC,cAAe,SAAU,eAAgB,UAAU,EAC1D,WACE,EAAI,sBAAuB,cAAe,CACxC,EAAK,+DAAgE,CACnE,WAAY,kBACZ,SAAU,GACV,MAAO,SACP,WAAY,GACZ,cAAe,GACf,WAAY,GACd,CAAC,EACD,EAAM,EAAY,GAAI,GAAI,IAAI,EAAG,WAAY,CAAE,MAAO,GAAI,aAAc,EAAG,CAAC,EAC5E,EAAK,qCAAsC,CACzC,MAAO,SACP,MAAO,iBACP,SAAU,GACV,WAAY,EACZ,cAAe,EACjB,CAAC,CACH,CAAC,CACL,EACA,CACE,KAAM,qBACN,SAAU,UACV,KAAM,sBACN,YAAa,mHACb,KAAM,CAAC,QAAS,aAAc,eAAgB,OAAO,EACrD,WACE,EAAI,qBAAsB,aAAc,CACtC,EAAM,aAAc,CAAE,MAAO,SAAU,SAAU,EAAG,CAAC,EACrD,EAAM,EAAY,IAAK,GAAI,OAAO,EAAG,iBAAkB,CAAE,MAAO,IAAK,WAAY,EAAG,cAAe,EAAG,CAAC,CACzG,CAAC,CACL,CACF,ECvGa,GAAiC,CAC5C,CACE,KAAM,aACN,SAAU,iBACV,KAAM,aACN,YAAa,2GACb,KAAM,CAAC,MAAO,UAAW,WAAY,QAAQ,EAC7C,WACE,EAAI,aAAc,aAAc,CAC9B,EAAQ,wBAAyB,CAAE,MAAO,SAAU,WAAY,EAAG,CAAC,EACpE,EAAM,+BAAgC,CAAE,MAAO,QAAS,CAAC,EACzD,EAAO,YAAa,qBAAqB,EACzC,EAAO,EAAE,CACX,CAAC,CACL,EACA,CACE,KAAM,aACN,SAAU,iBACV,KAAM,qBACN,YAAa,2HACb,KAAM,CAAC,MAAO,SAAU,UAAW,QAAS,MAAM,EAClD,WACE,EACE,aACA,aACA,CACE,EAAK,qBAAsB,CACzB,MAAO,sBACP,MAAO,SACP,SAAU,GACV,WAAY,GACZ,cAAe,CACjB,CAAC,EACD,EAAK,0BAA2B,CAC9B,MAAO,sBACP,MAAO,SACP,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,cAAe,EACjB,CAAC,EACD,EAAO,eAAe,EACtB,EAAO,EAAE,CACX,EACA,CAAE,gBAAiB,mBAAoB,WAAY,EAAG,cAAe,CAAE,CACzE,CACJ,EACA,CACE,KAAM,kBACN,SAAU,iBACV,KAAM,cACN,YAAa,6FACb,KAAM,CAAC,MAAO,SAAU,SAAS,EACjC,WAAc,EAAI,kBAAmB,SAAU,CAAC,EAAO,aAAc,qBAAqB,CAAC,CAAC,CAC9F,EACA,CACE,KAAM,kBACN,SAAU,iBACV,KAAM,oBACN,YAAa,qHACb,KAAM,CAAC,MAAO,UAAW,cAAe,QAAQ,EAChD,WACE,EAAI,kBAAmB,cAAe,CACpC,EAAQ,iBAAkB,CAAE,MAAO,SAAU,WAAY,EAAG,CAAC,EAC7D,EAAM,8BAA+B,CAAE,MAAO,QAAS,CAAC,EACxD,EAAO,cAAe,qBAAqB,EAC3C,EAAO,aAAc,sBAAuB,CAAE,gBAAiB,cAAe,MAAO,kBAAmB,CAAC,EACzG,EAAO,EAAE,CACX,CAAC,CACL,EACA,CACE,KAAM,oBACN,SAAU,iBACV,KAAM,sBACN,YAAa,6GACb,KAAM,CAAC,MAAO,QAAS,SAAU,MAAM,EACvC,WACE,EAAI,oBAAqB,YAAa,CACpC,EAAM,EAAY,IAAK,IAAK,QAAQ,EAAG,SAAU,CAAE,MAAO,IAAK,WAAY,EAAG,CAAC,EAC/E,EAAQ,kCAAmC,CAAE,MAAO,SAAU,WAAY,EAAG,CAAC,EAC9E,EAAM,oCAAqC,CAAE,MAAO,QAAS,CAAC,EAC9D,EAAO,aAAa,EACpB,EAAO,EAAE,CACX,CAAC,CACL,EACA,CACE,KAAM,gBACN,SAAU,iBACV,KAAM,sBACN,YAAa,gHACb,KAAM,CAAC,MAAO,YAAa,UAAW,SAAU,YAAY,EAC5D,WACE,EACE,gBACA,YACA,CACE,EAAQ,sBAAuB,CAAE,MAAO,QAAS,CAAC,EAClD,EAAQ,mCAAoC,CAAE,MAAO,SAAU,WAAY,EAAG,cAAe,CAAE,CAAC,EAChG,EAAO,gBAAgB,EACvB,EAAO,EAAE,CACX,EACA,CAAE,gBAAiB,sBAAuB,WAAY,EAAG,cAAe,CAAE,CAC5E,CACJ,EACA,CACE,KAAM,eACN,SAAU,iBACV,KAAM,mBACN,YAAa,4HACb,KAAM,CAAC,MAAO,WAAY,QAAS,QAAS,QAAQ,EACpD,WACE,EAAI,eAAgB,WAAY,CAC9B,EAAQ,gBAAiB,CAAE,MAAO,QAAS,CAAC,EAC5C,EAAQ,qBAAsB,CAAE,MAAO,SAAU,WAAY,EAAG,cAAe,CAAE,CAAC,EAClF,EAAM,8CAA+C,CAAE,MAAO,QAAS,CAAC,EACxE,EAAK,wBAAyB,CAC5B,MAAO,SACP,MAAO,mBACP,WAAY,6BACZ,SAAU,GACV,WAAY,EACZ,cAAe,CACjB,CAAC,EACD,EAAO,WAAW,EAClB,EAAO,EAAE,CACX,CAAC,CACL,EACA,CACE,KAAM,cACN,SAAU,iBACV,KAAM,iBACN,YAAa,8GACb,KAAM,CAAC,MAAO,UAAW,OAAQ,UAAW,YAAY,EACxD,WACE,EACE,cACA,UACA,CACE,EAAQ,kBAAmB,CAAE,MAAO,QAAS,CAAC,EAC9C,EAAQ,aAAc,CAAE,MAAO,SAAU,MAAO,CAAE,CAAC,EACnD,EAAM,oDAAqD,CAAE,MAAO,SAAU,SAAU,EAAG,CAAC,EAC5F,EAAO,SAAS,EAChB,EAAO,EAAE,CACX,EACA,CAAE,gBAAiB,sBAAuB,WAAY,EAAG,cAAe,CAAE,CAC5E,CACJ,EACA,CACE,KAAM,eACN,SAAU,iBACV,KAAM,iBACN,YAAa,6FACb,KAAM,CAAC,MAAO,WAAY,QAAS,UAAU,EAC7C,WACE,EAAI,eAAgB,WAAY,CAC9B,EAAK,0EAA2E,CAC9E,MAAO,SACP,WAAY,GACZ,cAAe,GACf,WAAY,GACd,CAAC,CACH,CAAC,CACL,CACF,ECtJa,GAAuC,CAClD,CACE,KAAM,sBACN,SAAU,YACV,KAAM,iBACN,YAAa,wJACb,KAAM,CAAC,UAAW,SAAU,MAAO,MAAM,EACzC,WACE,EAAI,sBAAuB,iBAAkB,CAC3C,EACE,CACE,EAAQ,CACN,KAAM,iBACN,MAAO,EAAY,IAAK,IAAK,SAAS,EACtC,SAAU,SACV,WAAY,SACZ,YAAa,8CACf,CAAC,CACH,EACA,CAAE,QAAS,EAAG,aAAc,GAAM,gBAAiB,GAAM,YAAa,SAAU,CAClF,CACF,CAAC,CACL,EACA,CACE,KAAM,sBACN,SAAU,YACV,KAAM,sBACN,YAAa,mKACb,KAAM,CAAC,UAAW,OAAQ,SAAU,UAAW,YAAY,EAC3D,WACE,EAAI,sBAAuB,iBAAkB,CAC3C,EACE,CACE,EAAQ,CAAE,KAAM,YAAa,WAAY,MAAO,SAAU,KAAM,CAAC,EACjE,EAAQ,CAAE,KAAM,YAAa,WAAY,MAAO,SAAU,KAAM,CAAC,CACnE,EACA,CAAE,QAAS,EAAG,aAAc,EAAK,CACnC,CACF,CAAC,CACL,EACA,CACE,KAAM,sBACN,SAAU,YACV,KAAM,sBACN,YAAa,4GACb,KAAM,CAAC,UAAW,OAAQ,WAAY,cAAe,eAAgB,YAAY,EACjF,WACE,EAAI,sBAAuB,iBAAkB,CAC3C,EAAQ,eAAgB,CAAE,MAAO,QAAS,CAAC,EAC3C,EACE,CACE,EAAQ,CAAE,KAAM,YAAa,WAAY,KAAM,CAAC,EAChD,EAAQ,CAAE,KAAM,YAAa,WAAY,KAAM,CAAC,EAChD,EAAQ,CAAE,KAAM,YAAa,WAAY,KAAM,CAAC,CAClD,EACA,CAAE,QAAS,EAAG,aAAc,EAAM,CACpC,CACF,CAAC,CACL,EACA,CACE,KAAM,yBACN,SAAU,YACV,KAAM,oBACN,YAAa,2HACb,KAAM,CAAC,aAAc,SAAU,WAAY,MAAM,EACjD,WACE,EAAI,yBAA0B,aAAc,CAC1C,EAAM,EAAY,IAAK,IAAK,YAAY,EAAG,aAAc,CAAE,MAAO,GAAI,CAAC,EACvE,EAAQ,yBAA0B,CAAE,MAAO,SAAU,WAAY,EAAG,CAAC,EACrE,EAAM,oCAAqC,CAAE,MAAO,QAAS,CAAC,EAC9D,EAAO,qBAAqB,EAC5B,EAAO,EAAE,CACX,CAAC,CACL,EACA,CACE,KAAM,gBACN,SAAU,YACV,KAAM,gBACN,YAAa,mFACb,KAAM,CAAC,WAAY,QAAS,OAAQ,QAAQ,EAC5C,WACE,EAAI,gBAAiB,gBAAiB,CACpC,EAAM,YAAa,CAAE,MAAO,QAAS,CAAC,EACtC,EAAK,SAAU,CACb,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,MAAO,SACP,MAAO,mBACP,cAAe,EACf,WAAY,EACZ,cAAe,EACjB,CAAC,EACD,EAAO,QAAQ,EACf,EAAO,EAAE,CACX,CAAC,CACL,EACA,CACE,KAAM,kBACN,SAAU,YACV,KAAM,oBACN,YAAa,qGACb,KAAM,CAAC,aAAc,UAAW,QAAS,SAAU,WAAW,EAC9D,WACE,EACE,kBACA,aACA,CACE,EAAK,6BAA8B,CACjC,MAAO,sBACP,MAAO,SACP,WAAY,OACZ,cAAe,EACf,WAAY,GACZ,cAAe,CACjB,CAAC,EACD,EAAK,2BAA4B,CAC/B,MAAO,sBACP,MAAO,SACP,WAAY,kBACZ,SAAU,GACV,WAAY,OACZ,cAAe,EACjB,CAAC,EACD,EAAO,WAAY,IAAK,CAAE,gBAAiB,mBAAoB,MAAO,kBAAmB,CAAC,EAC1F,EAAO,EAAE,CACX,EACA,CAAE,gBAAiB,mBAAoB,WAAY,EAAG,cAAe,CAAE,CACzE,CACJ,EACA,CACE,KAAM,sBACN,SAAU,YACV,KAAM,0BACN,YAAa,oHACb,KAAM,CAAC,iBAAkB,WAAY,aAAc,UAAU,EAC7D,WACE,EAAI,sBAAuB,iBAAkB,CAC3C,EAAQ,4BAA6B,CAAE,MAAO,SAAU,WAAY,EAAG,CAAC,EACxE,EAAM,8BAA+B,CAAE,MAAO,QAAS,CAAC,EACxD,EAAO,CAAC,EACR,EACE,CACE,EAAQ,CACN,KAAM,iBACN,MAAO,EAAY,IAAK,IAAK,MAAM,EACnC,WAAY,MACZ,SAAU,KACZ,CAAC,CACH,EACA,CAAE,QAAS,EAAG,aAAc,GAAM,YAAa,gBAAiB,CAClE,CACF,CAAC,CACL,EACA,CACE,KAAM,sBACN,SAAU,YACV,KAAM,iBACN,YAAa,4GACb,KAAM,CAAC,SAAU,SAAU,gBAAiB,UAAU,EACtD,WACE,EAAI,sBAAuB,SAAU,CACnC,EAAQ,iBAAkB,CAAE,MAAO,SAAU,WAAY,EAAG,CAAC,EAC7D,EAAM,sCAAuC,CAAE,MAAO,QAAS,CAAC,EAChE,EAAK,YAAa,CAChB,MAAO,SACP,SAAU,GACV,MAAO,mBACP,WAAY,GACZ,cAAe,GACf,KAAM,GACR,CAAC,CACH,CAAC,CACL,EACA,CACE,KAAM,kBACN,SAAU,YACV,KAAM,kBACN,YAAa,yIACb,KAAM,CAAC,aAAc,UAAW,YAAa,SAAS,EACtD,WACE,EAAI,kBAAmB,YAAa,CAClC,EAAQ,mBAAmB,EAC3B,EACE,CACE,EAAQ,CACN,KAAM,oBACN,MAAO,EAAY,IAAK,IAAK,MAAM,EACnC,SAAU,OACV,WAAY,MACZ,YAAa,gDACf,CAAC,CACH,EACA,CAAE,QAAS,EAAG,aAAc,GAAM,gBAAiB,GAAM,YAAa,cAAe,CACvF,CACF,CAAC,CACL,EACA,CACE,KAAM,uBACN,SAAU,YACV,KAAM,kBACN,YAAa,4FACb,KAAM,CAAC,cAAe,OAAQ,UAAW,KAAK,EAC9C,WACE,EAAI,uBAAwB,cAAe,CACzC,EAAQ,iBAAiB,EACzB,EACE,CACE,EAAQ,CAAE,KAAM,aAAc,WAAY,MAAO,SAAU,KAAM,CAAC,EAClE,EAAQ,CAAE,KAAM,cAAe,WAAY,KAAM,CAAC,EAClD,EAAQ,CAAE,KAAM,aAAc,WAAY,OAAQ,SAAU,MAAO,CAAC,CACtE,EACA,CAAE,QAAS,EAAG,aAAc,EAAK,CACnC,CACF,CAAC,CACL,CACF,ECrOa,GAA2C,CACtD,CACE,KAAM,mBACN,SAAU,gBACV,KAAM,gBACN,YAAa,qHACb,KAAM,CAAC,QAAS,UAAW,UAAW,gBAAiB,WAAW,EAClE,WACE,EAAI,mBAAoB,gBAAiB,CACvC,EAAQ,aAAa,EACrB,EAAQ,wBAAyB,CAAE,WAAY,CAAE,CAAC,EAClD,EAAM,sCAAsC,EAC5C,EAAQ,CAAE,WAAY,GAAI,cAAe,CAAE,CAAC,EAC5C,EAAK,8BAA+B,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,EACvE,EAAK,2BAA4B,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,EACpE,EAAQ,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,EAC3C,EAAK,mBAAoB,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,EAC5D,EAAK,kBAAmB,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,EAC3D,EAAK,gBAAiB,CAAE,WAAY,OAAQ,WAAY,EAAG,cAAe,EAAG,CAAC,CAChF,CAAC,CACL,EACA,CACE,KAAM,qBACN,SAAU,gBACV,KAAM,kBACN,YAAa,kGACb,KAAM,CAAC,WAAY,WAAY,WAAY,eAAe,EAC1D,WACE,EAAI,qBAAsB,kBAAmB,CAC3C,EAAK,KAAM,CAAE,MAAO,SAAU,SAAU,GAAI,WAAY,EAAG,CAAC,EAC5D,EAAQ,2BAA4B,CAAE,MAAO,SAAU,WAAY,CAAE,CAAC,EACtE,EAAM,wCAAyC,CAAE,MAAO,QAAS,CAAC,EAClE,EAAK,0BAA2B,CAAE,MAAO,SAAU,MAAO,iBAAkB,WAAY,6BAA8B,SAAU,EAAG,CAAC,EACpI,EAAO,eAAe,EACtB,EAAO,EAAE,CACX,CAAC,CACL,EACA,CACE,KAAM,aACN,SAAU,gBACV,KAAM,UACN,YAAa,kGACb,KAAM,CAAC,UAAW,UAAW,OAAQ,MAAO,SAAS,EACrD,WACE,EAAI,aAAc,UAAW,CAC3B,EAAQ,qBAAqB,EAC7B,EAAQ,oBAAoB,EAC5B,EAAM,8CAA8C,EACpD,EAAQ,CAAE,WAAY,GAAI,cAAe,CAAE,CAAC,EAC5C,EAAK,oBAAqB,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,EAC7D,EAAK,4BAA6B,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,EACrE,EAAQ,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,EAC3C,EAAK,oBAAqB,CAAE,WAAY,OAAQ,cAAe,EAAG,CAAC,EACnE,EAAO,wBAAwB,EAC/B,EAAO,EAAE,CACX,CAAC,CACL,EACA,CACE,KAAM,oBACN,SAAU,gBACV,KAAM,iBACN,YAAa,wGACb,KAAM,CAAC,OAAQ,WAAY,QAAS,UAAU,EAC9C,WACE,EAAI,oBAAqB,iBAAkB,CACzC,EAAQ,sBAAuB,CAAE,MAAO,SAAU,WAAY,EAAG,CAAC,EAClE,EAAK,iFAAkF,CACrF,MAAO,SACP,cAAe,EACjB,CAAC,EACD,EAAO,gBAAgB,EACvB,EAAM,+DAAgE,CAAE,MAAO,SAAU,SAAU,EAAG,CAAC,EACvG,EAAK,mCAAoC,CACvC,MAAO,SACP,MAAO,mBACP,SAAU,GACV,cAAe,EACjB,CAAC,CACH,CAAC,CACL,EACA,CACE,KAAM,kBACN,SAAU,gBACV,KAAM,eACN,YAAa,6EACb,KAAM,CAAC,OAAQ,SAAU,oBAAoB,EAC7C,WACE,EAAI,kBAAmB,eAAgB,CACrC,EAAQ,gBAAiB,CAAE,MAAO,SAAU,WAAY,EAAG,CAAC,EAC5D,EAAK,uDAAwD,CAAE,MAAO,SAAU,cAAe,CAAE,CAAC,EAClG,EAAO,cAAc,EACrB,EAAO,EAAE,CACX,CAAC,CACL,EACA,CACE,KAAM,iBACN,SAAU,gBACV,KAAM,2BACN,YAAa,oFACb,KAAM,CAAC,cAAe,UAAW,WAAY,SAAS,EACtD,WACE,EAAI,iBAAkB,cAAe,CACnC,EAAQ,YAAa,CAAE,MAAO,QAAS,CAAC,EACxC,EAAQ,0BAA2B,CAAE,MAAO,SAAU,WAAY,CAAE,CAAC,EACrE,EAAK,6BAA8B,CAAE,MAAO,SAAU,WAAY,OAAQ,WAAY,CAAE,CAAC,EACzF,EAAM,sCAAuC,CAAE,MAAO,QAAS,CAAC,EAChE,EAAO,iBAAiB,EACxB,EAAO,EAAE,CACX,CAAC,CACL,CACF,EC9Ga,GAAoC,CAC/C,CACE,KAAM,eACN,SAAU,SACV,KAAM,mBACN,YAAa,6FACb,KAAM,CAAC,SAAU,SAAU,QAAS,KAAK,EACzC,WACE,EAAI,eAAgB,eAAgB,CAClC,EAAM,YAAa,CAAE,MAAO,QAAS,CAAC,EACtC,EAAK,2CAA4C,CAC/C,MAAO,SACP,MAAO,mBACP,cAAe,EACjB,CAAC,CACH,CAAC,CACL,EACA,CACE,KAAM,eACN,SAAU,SACV,KAAM,mBACN,YAAa,kGACb,KAAM,CAAC,SAAU,QAAS,UAAW,OAAO,EAC5C,WACE,EAAI,eAAgB,YAAa,CAC/B,EAAK,mBAAoB,CAAE,MAAO,SAAU,WAAY,CAAE,CAAC,EAC3D,EAAK,0BAA2B,CAC9B,MAAO,SACP,MAAO,mBACP,cAAe,CACjB,CAAC,CACH,CAAC,CACL,EACA,CACE,KAAM,uBACN,SAAU,SACV,KAAM,uBACN,YAAa,8GACb,KAAM,CAAC,SAAU,OAAQ,QAAS,UAAW,WAAW,EACxD,WACE,EACE,uBACA,cACA,CACE,EAAQ,oBAAoB,EAC5B,EAAM,EAAY,GAAI,GAAI,IAAI,EAAG,SAAU,CAAE,MAAO,GAAI,aAAc,EAAG,CAAC,EAC1E,EAAK,cAAe,CAAE,MAAO,iBAAkB,SAAU,GAAI,WAAY,EAAG,cAAe,CAAE,CAAC,EAC9F,EAAK,uGAA0G,CAC7G,cAAe,EACf,WAAY,GACd,CAAC,EACD,EAAK,oBAAqB,CAAE,MAAO,mBAAoB,cAAe,GAAI,KAAM,GAAI,CAAC,CACvF,CACF,CACJ,EACA,CACE,KAAM,wBACN,SAAU,SACV,KAAM,iBACN,YAAa,gGACb,KAAM,CAAC,SAAU,YAAa,OAAQ,YAAY,EAClD,WACE,EAAI,wBAAyB,UAAW,CACtC,EAAM,4BAA6B,CAAE,MAAO,QAAS,CAAC,EACtD,EAAM,EAAY,IAAK,IAAK,GAAG,EAAG,SAAU,CAAE,MAAO,GAAI,CAAC,EAC1D,EAAM,EAAY,IAAK,IAAK,GAAG,EAAG,SAAU,CAAE,MAAO,GAAI,CAAC,EAC1D,EAAM,EAAY,IAAK,IAAK,GAAG,EAAG,SAAU,CAAE,MAAO,GAAI,CAAC,EAC1D,EAAK,iBAAkB,CAAE,MAAO,SAAU,MAAO,mBAAoB,WAAY,EAAG,cAAe,GAAI,KAAM,GAAI,CAAC,CACpH,CAAC,CACL,EACA,CACE,KAAM,yBACN,SAAU,SACV,KAAM,kBACN,YAAa,8EACb,KAAM,CAAC,SAAU,QAAS,YAAa,WAAW,EAClD,WACE,EAAI,yBAA0B,kBAAmB,CAC/C,EAAQ,qBAAsB,CAAE,MAAO,QAAS,CAAC,EACjD,EAAK,0CAA2C,CAAE,MAAO,SAAU,cAAe,EAAG,CAAC,EACtF,EAAO,CAAC,CACV,CAAC,CACL,CACF,ECnFM,GAAkB,CACtB,gBAAiB,sBACjB,WAAY,EACZ,cAAe,CACjB,EAEa,GAAoC,CAC/C,CACE,KAAM,gBACN,SAAU,SACV,KAAM,gBACN,YAAa,gGACb,KAAM,CAAC,SAAU,SAAU,YAAa,aAAa,EACrD,WACE,EACE,gBACA,gBACA,CACE,EAAM,4CAA6C,CAAE,MAAO,SAAU,SAAU,EAAG,CAAC,EACpF,EAAM,+BAAgC,CAAE,MAAO,SAAU,SAAU,EAAG,CAAC,EACvE,EAAK,gCAAiC,CACpC,MAAO,SACP,MAAO,iBACP,SAAU,GACV,WAAY,EACZ,cAAe,EACjB,CAAC,CACH,EACA,CAAE,GAAG,GAAiB,WAAY,EAAG,CACvC,CACJ,EACA,CACE,KAAM,gBACN,SAAU,SACV,KAAM,qBACN,YAAa,qDACb,KAAM,CAAC,SAAU,SAAU,OAAO,EAClC,WACE,EACE,gBACA,gBACA,CACE,EAAK,YAAa,CAAE,MAAO,SAAU,WAAY,EAAG,CAAC,EACrD,EAAK,iCAAkC,CACrC,MAAO,SACP,MAAO,mBACP,cAAe,EACjB,CAAC,EACD,EAAQ,EACR,EAAM,oCAAqC,CACzC,MAAO,SACP,SAAU,EACZ,CAAC,EACD,EAAK,IAAK,CAAE,MAAO,SAAU,cAAe,EAAG,CAAC,CAClD,EACA,EACF,CACJ,EACA,CACE,KAAM,eACN,SAAU,SACV,KAAM,eACN,YAAa,6JACb,KAAM,CAAC,SAAU,QAAS,aAAc,YAAY,EACpD,WACE,EACE,eACA,eACA,CACE,EACE,mJACA,CACE,MAAO,SACP,MAAO,iBACP,SAAU,GACV,WAAY,IACZ,WAAY,EACd,CACF,EACA,EAAK,uCAAwC,CAC3C,MAAO,SACP,MAAO,iBACP,SAAU,GACV,cAAe,EACjB,CAAC,CACH,EACA,EACF,CACJ,EACA,CACE,KAAM,mBACN,SAAU,SACV,KAAM,mBACN,YAAa,4FACb,KAAM,CAAC,SAAU,YAAa,WAAY,WAAY,WAAW,EACjE,WACE,EACE,mBACA,mBACA,CACE,EAAM,EAAY,IAAK,GAAI,MAAM,EAAG,OAAQ,CAAE,MAAO,IAAK,WAAY,GAAI,cAAe,CAAE,CAAC,EAC5F,EAAK,aAAc,CACjB,MAAO,SACP,WAAY,kBACZ,WAAY,OACZ,cAAe,EACf,WAAY,EACZ,cAAe,CACjB,CAAC,EACD,EAAM,wCAAyC,CAAE,MAAO,SAAU,SAAU,EAAG,CAAC,EAChF,EAAQ,CAAE,WAAY,GAAI,cAAe,EAAG,CAAC,EAC7C,EAAM,iDAAkD,CAAE,MAAO,SAAU,SAAU,EAAG,CAAC,EACzF,EAAK,mCAAoC,CACvC,MAAO,SACP,MAAO,iBACP,SAAU,GACV,WAAY,EACZ,cAAe,EACjB,CAAC,CACH,EACA,EACF,CACJ,EACA,CACE,KAAM,mBACN,SAAU,SACV,KAAM,+BACN,YAAa,wGACb,KAAM,CAAC,SAAU,MAAO,WAAY,MAAO,SAAS,EACpD,WACE,EACE,mBACA,aACA,CACE,EAAK,cAAe,CAAE,MAAO,SAAU,WAAY,OAAQ,WAAY,GAAI,cAAe,CAAE,CAAC,EAC7F,EAAM,EAAY,IAAK,GAAI,WAAW,EAAG,YAAa,CAAE,MAAO,IAAK,MAAO,SAAU,WAAY,EAAG,cAAe,CAAE,CAAC,EACtH,EAAM,EAAY,IAAK,GAAI,aAAa,EAAG,cAAe,CAAE,MAAO,IAAK,MAAO,SAAU,WAAY,EAAG,cAAe,EAAG,CAAC,EAC3H,EAAQ,EACR,EAAM,kCAAmC,CAAE,MAAO,SAAU,SAAU,EAAG,CAAC,EAC1E,EAAK,IAAK,CAAE,MAAO,SAAU,cAAe,EAAG,CAAC,CAClD,EACA,EACF,CACJ,EACA,CACE,KAAM,sBACN,SAAU,SACV,KAAM,eACN,YAAa,yGACb,KAAM,CAAC,SAAU,UAAW,aAAc,UAAU,EACpD,WACE,EACE,sBACA,UACA,CACE,EAAM,wDAAyD,CAC7D,MAAO,SACP,SAAU,EACZ,CAAC,EACD,EAAK,IAAK,CAAE,MAAO,SAAU,cAAe,EAAG,CAAC,CAClD,EACA,CAAE,GAAG,GAAiB,WAAY,EAAG,CACvC,CACJ,EACA,CACE,KAAM,qBACN,SAAU,SACV,KAAM,qBACN,YAAa,qHACb,KAAM,CAAC,SAAU,cAAe,YAAa,WAAW,EACxD,WACE,EACE,qBACA,cACA,CACE,EAAK,2BAA4B,CAAE,MAAO,SAAU,WAAY,GAAI,cAAe,CAAE,CAAC,EACtF,EAAK,0DAA2D,CAC9D,MAAO,SACP,MAAO,mBACP,SAAU,GACV,cAAe,EACjB,CAAC,EACD,EAAQ,EACR,EAAM,sBAAuB,CAAE,MAAO,SAAU,SAAU,EAAG,CAAC,EAC9D,EAAK,IAAK,CAAE,MAAO,SAAU,cAAe,EAAG,CAAC,CAClD,EACA,EACF,CACJ,EACA,CACE,KAAM,mBACN,SAAU,SACV,KAAM,qBACN,YAAa,2GACb,KAAM,CAAC,SAAU,YAAa,WAAY,UAAW,UAAU,EAC/D,WACE,EACE,mBACA,YACA,CACE,EAAK,mBAAoB,CAAE,WAAY,GAAI,cAAe,CAAE,CAAC,EAC7D,EAAK,SAAU,CAAE,WAAY,kBAAmB,SAAU,GAAI,cAAe,EAAG,CAAC,EACjF,EAAQ,EACR,EAAM,uDAAwD,CAC5D,SAAU,GACV,MAAO,QACT,CAAC,EACD,EAAK,IAAK,CAAE,MAAO,SAAU,cAAe,EAAG,CAAC,CAClD,EACA,CAAE,GAAG,GAAiB,WAAY,CAAE,CACtC,CACJ,CACF,EC1Ma,GAAqC,CAChD,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,EACL,EAEI,GAAa,GACjB,SAAgB,IAAyB,CACnC,OACJ,KAAK,IAAM,KAAK,GAAgB,GAAe,SAAS,CAAC,EACzD,GAAa,EAD4C,CAE3D,CCnBA,GAAuB,EAEvB,SAAgB,IAAM,CACpB,GAAM,CAAE,MAAK,YAAW,wBAAyB,EAAc,EAsB/D,OApBA,EAAA,EAAA,UAAA,KAAgB,CAGd,GAFA,EAAqB,EAEjB,EAAc,SAAS,CAAC,CAAC,IAAI,QAAQ,SAAW,EAAG,CAErD,IAAK,IAAM,IAAK,CADD,cAAe,wBAAyB,aAAc,eACrD,EAAO,CACrB,IAAM,EAAM,GAAe,IAAI,CAAC,EAC5B,GAAK,EAAU,EAAI,OAAO,CAAC,CACjC,CACA,EAAc,SAAS,CAAE,UAAW,CAAE,KAAM,OAAQ,EAAG,KAAM,CAAC,EAAG,OAAQ,CAAC,CAAE,CAAC,CAC/E,CAEF,EAAG,CAAC,CAAC,GAGL,EAAA,EAAA,UAAA,KAAgB,CACd,IAAM,EAAK,eAAiB,EAAc,SAAS,CAAC,CAAC,mBAAmB,EAAG,GAAG,EAC9E,UAAa,aAAa,CAAE,CAC9B,EAAG,CAAC,CAAG,CAAC,GAGN,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,qEAAf,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAS,CAAA,GACT,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,uCAAf,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAc,CAAA,GACd,EAAA,EAAA,IAAA,CAAC,GAAD,CAAS,CAAA,GACT,EAAA,EAAA,IAAA,CAAC,GAAD,CAAe,CAAA,CACZ,GACF,GAET,CCvBA,IAAa,GAAmC,CAC9C,GAAI,kBACJ,KAAM,kBACN,YACE,kHACF,MAAO,MACP,MAAO,CACL,CACE,KAAM,+BACN,SAAU,SACV,KAAM,gBACN,YACE,sIACF,KAAM,CAAC,OAAQ,WAAY,SAAU,MAAO,MAAM,EAClD,WACE,EACE,+BACA,gBACA,CACE,EAAQ,cAAe,CAAE,MAAO,QAAS,CAAC,EAC1C,EAAQ,wBAAyB,CAC/B,MAAO,EACP,MAAO,SACP,WAAY,EACZ,cAAe,CACjB,CAAC,EACD,EAAK,8DAA+D,CAClE,MAAO,SACP,MAAO,iBACP,SAAU,GACV,cAAe,EACjB,CAAC,EACD,EAAO,cAAe,IAAK,CAAE,MAAO,QAAS,CAAC,CAChD,EACA,CAAE,gBAAiB,mBAAoB,WAAY,GAAI,cAAe,EAAG,CAC3E,CACJ,EACA,CACE,KAAM,wBACN,SAAU,UACV,KAAM,aACN,YACE,yGACF,KAAM,CAAC,QAAS,cAAe,YAAa,YAAY,EACxD,WACE,EAAI,wBAAyB,aAAc,CACzC,EAAK,uDAAwD,CAC3D,WAAY,kBACZ,SAAU,GACV,MAAO,SACP,WAAY,IACZ,WAAY,GACZ,cAAe,CACjB,CAAC,EACD,EAAM,0BAA2B,CAAE,MAAO,SAAU,cAAe,EAAG,CAAC,CACzE,CAAC,CACL,EACA,CACE,KAAM,2BACN,SAAU,UACV,KAAM,WACN,YACE,0FACF,KAAM,CAAC,QAAS,UAAW,UAAW,MAAO,KAAK,EAClD,WACE,EAAI,2BAA4B,WAAY,CAC1C,EAAQ,iBAAkB,CAAE,MAAO,SAAU,WAAY,EAAG,CAAC,EAC7D,EACE,6FACA,CAAE,MAAO,SAAU,MAAO,iBAAkB,cAAe,EAAG,CAChE,CACF,CAAC,CACL,EACA,CACE,KAAM,mCACN,SAAU,YACV,KAAM,2BACN,YACE,qFACF,KAAM,CAAC,UAAW,YAAa,SAAU,MAAO,MAAM,EACtD,WACE,EAAI,mCAAoC,oBAAqB,CAC3D,EACE,CACE,EAAQ,CACN,KAAM,oBACN,WAAY,OACZ,SAAU,OACV,YAAa,2BACb,MAAO,EAAY,IAAK,IAAK,SAAS,CACxC,CAAC,CACH,EACA,CAAE,QAAS,EAAG,gBAAiB,GAAM,YAAa,SAAU,CAC9D,CACF,CAAC,CACL,EACA,CACE,KAAM,wBACN,SAAU,OACV,KAAM,kBACN,YACE,oFACF,KAAM,CAAC,OAAQ,MAAO,QAAS,MAAM,EACrC,WACE,EAAI,wBAAyB,kBAAmB,CAC9C,EAAM,EAAY,IAAK,GAAI,MAAM,EAAG,OAAQ,CAAE,MAAO,IAAK,cAAe,CAAE,CAAC,EAC5E,EACE,2GACA,CAAE,MAAO,SAAU,MAAO,mBAAoB,cAAe,CAAE,CACjE,EACA,EAAQ,CAAE,WAAY,EAAG,cAAe,CAAE,CAAC,CAC7C,CAAC,CACL,CACF,CACF,EC1HA,SAAgB,GAAc,GAAG,EAAwC,CACvE,MAAO,CACL,KAAM,UAEN,KAAM,UACN,MAAM,EAAyB,CAC7B,IAAK,IAAM,KAAK,EAAW,GAAgB,gBAAgB,CAAC,CAC9D,CACF,CACF,CCAA,IAAM,GAAoB,GAA8B,CACtD,GAAI,GAAQ,OAAO,GAAS,SAAU,OAAO,EAC7C,MAAU,MAAM,2CAA2C,CAC7D,EAQA,SAAgB,GAAqB,EAAyC,CAC5E,IAAM,EAAY,EAAK,mBAAqB,GACtC,EAAY,EAAK,WAAa,IAEpC,MAAO,CACL,MAAM,SAAS,EAAqC,CAClD,IAAM,EAAa,IAAI,gBACjB,EAAQ,eAAiB,EAAW,MAAM,EAAG,CAAS,EAC5D,GAAI,CACF,IAAM,EAAM,MAAM,MAAM,EAAK,SAAU,CACrC,OAAQ,OACR,QAAS,CAAE,eAAgB,mBAAoB,GAAI,EAAK,SAAW,CAAC,CAAG,EACvE,YAAa,EAAK,gBAAkB,UAAY,cAChD,KAAM,KAAK,UAAU,CAAG,EACxB,OAAQ,EAAW,MACrB,CAAC,EAEG,EAAgB,KACd,EAAM,MAAM,EAAI,KAAK,EAC3B,GAAI,CACF,EAAO,EAAM,KAAK,MAAM,CAAG,EAAI,IACjC,MAAQ,CAER,CAEA,GAAI,CAAC,EAAI,GAAI,CACX,IAAM,GACH,GAAQ,OAAO,GAAS,UAAY,UAAW,GAChD,OAAQ,EAA4B,OAAU,SACzC,EAA2B,MAC5B,OAAS,2BAA2B,EAAI,OAAO,GACrD,MAAU,MAAM,CAAG,CACrB,CAEA,OAAO,EAAU,CAAI,CACvB,OAAS,EAAK,CAIZ,MAHI,aAAe,cAAgB,EAAI,OAAS,aACpC,MAAM,8BAA8B,EAAU,GAAG,EAEvD,aAAe,MAAQ,EAAU,MAAM,OAAO,CAAG,CAAC,CAC1D,QAAU,CACR,aAAa,CAAK,CACpB,CACF,CACF,CACF,CCrDA,SAAgB,GAAkB,EAAkC,CAClE,IAAM,EAAuB,GAAqB,CAAI,EACtD,MAAO,CACL,KAAM,eACN,KAAM,cACN,MAAM,EAAwB,CAC5B,EAAQ,cAAc,CAAQ,CAChC,CACF,CACF,CCPA,IAAM,GAAoB,GAAiD,CACzE,GAAI,GAAQ,OAAO,GAAS,UAAY,QAAS,GAAQ,OAAQ,EAA0B,KAAQ,SAAU,CAC3G,IAAM,EAAI,EACV,MAAO,CAAE,IAAK,EAAE,IAAK,IAAK,OAAO,EAAE,KAAQ,SAAW,EAAE,IAAM,IAAA,EAAU,CAC1E,CACA,MAAU,MAAM,6CAA6C,CAC/D,EAEA,SAAgB,GAA4B,EAA2C,CACrF,IAAM,EAAY,EAAK,WAAa,OAC9B,GAAW,EAAK,WAAa,IAAM,KAAO,KAC1C,EAAY,EAAK,mBAAqB,GAE5C,MAAO,CACL,OAAO,EAAY,CAUjB,OATK,EAAK,KAAK,WAAW,QAAQ,EAG9B,EAAK,KAAO,EACP,QAAQ,OACT,MAAM,oBAAoB,EAAK,KAAO,KAAO,KAAA,CAAM,QAAQ,CAAC,EAAE,QAAQ,EAAK,WAAa,GAAG,IAAI,CACrG,EAGK,IAAI,SAAwC,EAAS,IAAW,CACrE,IAAM,EAAM,IAAI,eACV,EAAK,IAAI,SAKf,GAJA,EAAG,OAAO,EAAW,EAAM,EAAK,IAAI,EAEpC,EAAI,KAAK,OAAQ,EAAK,SAAU,EAAI,EACpC,EAAI,gBAAkB,CAAC,CAAC,EAAK,gBACzB,EAAK,QACP,IAAK,GAAM,CAAC,EAAG,KAAM,OAAO,QAAQ,EAAK,OAAO,EAAG,EAAI,iBAAiB,EAAG,CAAC,EAG1E,EAAK,YAAc,EAAI,SACzB,EAAI,OAAO,WAAc,GAAM,CACzB,EAAE,kBAAkB,EAAK,WAAY,KAAK,MAAO,EAAE,OAAS,EAAE,MAAS,GAAG,CAAC,CACjF,GAGF,EAAI,WAAe,CACjB,IAAM,EAAK,EAAI,QAAU,KAAO,EAAI,OAAS,IACzC,EAAgB,KACpB,GAAI,CACF,EAAO,EAAI,aAAe,KAAK,MAAM,EAAI,YAAY,EAAI,IAC3D,MAAQ,CAER,CACA,GAAI,CAAC,EAAI,CACP,IAAM,GACH,GAAQ,OAAO,GAAS,UAAY,UAAW,GAAQ,OAAQ,EAA4B,OAAU,SACjG,EAA2B,MAC5B,OAAS,uBAAuB,EAAI,OAAO,GACjD,OAAO,EAAW,MAAM,CAAG,CAAC,CAC9B,CACA,GAAI,CACF,EAAQ,EAAU,CAAI,CAAC,CACzB,OAAS,EAAK,CACZ,EAAO,aAAe,MAAQ,EAAU,MAAM,OAAO,CAAG,CAAC,CAAC,CAC5D,CACF,EAEA,EAAI,YAAgB,EAAW,MAAM,6BAA6B,CAAC,EACnE,EAAI,YAAgB,EAAW,MAAM,gBAAgB,CAAC,EACtD,EAAI,KAAK,CAAE,CACb,CAAC,EAlDQ,QAAQ,OAAW,MAAM,iBAAiB,EAAK,MAAQ,WAAW,CAAC,CAmD9E,CACF,CACF,CAUA,SAAgB,GAAoB,EAAoC,CACtE,MAAO,CACL,KAAM,iBACN,KAAM,iBACN,MAAM,EAAkB,CACtB,EAAE,sBAAsB,GAA4B,CAAI,CAAC,CAC3D,CACF,CACF,CCnFA,SAAgB,GAAa,EAA0B,CA+BrD,OA9BA,EAAA,EAAA,UAAA,KAAgB,CAEd,GADA,GAAuB,EACnB,EAAM,QAAS,IAAK,IAAM,KAAK,EAAM,QAAS,GAAe,SAAS,CAAC,EAC3E,GAAI,EAAM,UAAW,IAAK,IAAM,KAAK,EAAM,UAAW,GAAgB,gBAAgB,CAAC,EAEvF,GADI,EAAM,QAAQ,EAAc,SAAS,CAAE,OAAQ,EAAM,MAAO,CAAC,EAC7D,EAAM,WAAY,GAAQ,cAAc,EAAM,UAAU,OACvD,GAAI,EAAM,WAAY,CACzB,IAAM,EACJ,OAAO,EAAM,YAAe,SAAW,CAAE,SAAU,EAAM,UAAW,EAAI,EAAM,WAChF,GAAQ,cAAc,GAAqB,CAAI,CAAC,CAClD,CACA,GAAI,EAAM,gBAAiB,CACzB,IAAM,EAAI,EAAe,UAAU,EAAM,eAAe,EACpD,EAAE,SAAS,EAAc,SAAS,CAAC,CAAC,SAAS,EAAE,KAAuB,EAAK,CACjF,CACA,IAAM,EAAQ,EAAc,WAAW,EAAG,IAAS,CAC7C,EAAE,MAAQ,EAAK,KAAK,EAAM,WAAW,EAAE,GAAG,CAChD,CAAC,EACD,UAAa,EAAM,CAErB,EAAG,CAAC,CAAC,GAGL,EAAA,EAAA,UAAA,KAAgB,CACT,KAAM,aACX,OAAO,EAAc,WAAW,EAAG,IAAS,CACtC,EAAE,MAAQ,EAAK,KAAK,EAAM,eAAe,GAAgB,EAAE,GAAG,CAAC,CACrE,CAAC,CACH,EAAG,CAAC,EAAM,YAAY,CAAC,GAEvB,EAAA,EAAA,cAAA,CAAqB,EAAG,CAC1B,CAcA,SAAgB,GAAmB,EAAuC,CACxE,IAAM,GAAA,EAAA,EAAA,WAAA,CAAwB,EAAK,SAAS,EAE5C,OADA,EAAK,QAAA,EAAA,EAAA,cAAA,CAAqB,GAAc,CAAI,CAAC,EACtC,CACL,YAAe,EAAK,QAAQ,EAC5B,gBAAmB,EAAc,SAAS,CAAC,CAAC,IAC5C,eAAkB,EAAc,SAAS,CAAC,CAAC,WAAW,EACtD,eAAkB,EAAc,SAAS,CAAC,CAAC,WAAW,CACxD,CACF"}
|
|
1
|
+
{"version":3,"file":"email-builder.cjs","names":["useLayoutEffect","useEffect","React","React","ID_PREFIX","ID_PREFIX$1","React"],"sources":["../src/core/validation.ts","../src/core/theme.ts","../src/core/utils.ts","../src/core/renderer.ts","../src/themes/defaultThemes.ts","../src/store/emailStore.ts","../src/templates/registry.ts","../src/modules/helpers.ts","../src/templates/weeklyNewsletter.ts","../src/templates/flashSale.ts","../src/templates/abandonedCart.ts","../src/templates/productLaunch.ts","../src/templates/welcomeOnboarding.ts","../src/templates/eventInvite.ts","../src/templates/orderReceipt.ts","../src/templates/blogDigest.ts","../src/editor/TemplatesModal.tsx","../src/editor/TopBar.tsx","../src/modules/registry.ts","../src/ai/state.ts","../src/ai/catalog.ts","../src/core/aiActions.ts","../src/ai/applyResponse.ts","../src/ai/AIChatPanel.tsx","../src/editor/LeftSidebar.tsx","../node_modules/@dnd-kit/utilities/dist/utilities.esm.js","../node_modules/@dnd-kit/accessibility/dist/accessibility.esm.js","../node_modules/@dnd-kit/core/dist/core.esm.js","../node_modules/@dnd-kit/sortable/dist/sortable.esm.js","../src/editor/Canvas.tsx","../src/core/plugins.ts","../src/recommendations/logic.ts","../src/editor/RecommendationsPanel.tsx","../src/editor/RightSidebar.tsx","../src/modules/basic.ts","../src/modules/header.ts","../src/modules/menu.ts","../src/modules/content.ts","../src/modules/feature.ts","../src/modules/cta.ts","../src/modules/ecommerce.ts","../src/modules/transactional.ts","../src/modules/social.ts","../src/modules/footer.ts","../src/modules/defaultModules.ts","../src/App.tsx","../src/ai/provider.ts","../src/ai/index.ts","../src/plugins/imageUploader/index.ts","../src/index.ts"],"sourcesContent":["import { z } from \"zod\";\n\nconst styleValue = z.union([z.string(), z.number(), z.boolean(), z.record(z.string(), z.any())]);\nconst styleSchema = z.record(z.string(), styleValue).optional();\n\nconst elementSchema = z.discriminatedUnion(\"type\", [\n z.object({\n id: z.string(),\n type: z.literal(\"text\"),\n role: z.string().optional(),\n content: z.string(),\n style: styleSchema,\n }),\n z.object({\n id: z.string(),\n type: z.literal(\"image\"),\n src: z.string(),\n alt: z.string().optional(),\n link: z.string().optional(),\n style: styleSchema,\n }),\n z.object({\n id: z.string(),\n type: z.literal(\"button\"),\n label: z.string(),\n link: z.string(),\n style: styleSchema,\n }),\n z.object({\n id: z.string(),\n type: z.literal(\"spacer\"),\n height: z.number(),\n }),\n z.object({\n id: z.string(),\n type: z.literal(\"divider\"),\n style: styleSchema,\n }),\n z.object({\n id: z.string(),\n type: z.literal(\"productGrid\"),\n products: z.array(\n z.object({\n id: z.string(),\n image: z.string(),\n imageAlt: z.string().optional(),\n name: z.string(),\n oldPrice: z.string().optional(),\n finalPrice: z.string(),\n description: z.string().optional(),\n link: z.string().optional(),\n buttonLabel: z.string().optional(),\n })\n ),\n columns: z.union([z.literal(1), z.literal(2), z.literal(3)]),\n showOldPrice: z.boolean(),\n showButton: z.boolean(),\n showDescription: z.boolean(),\n buttonLabel: z.string().optional(),\n style: styleSchema,\n }),\n]);\n\nexport const moduleSchema = z.object({\n id: z.string(),\n type: z.string(),\n name: z.string(),\n style: styleSchema,\n children: z.array(elementSchema),\n data: z.record(z.string(), z.any()).optional(),\n});\n\nexport const themeSchema = z.object({\n id: z.string(),\n name: z.string(),\n tokens: z.object({\n colors: z.record(z.string(), z.string()),\n fonts: z.record(z.string(), z.string()),\n spacing: z.record(z.string(), z.number()),\n radius: z.record(z.string(), z.number()),\n }),\n});\n\nexport const documentSchema = z.object({\n version: z.string(),\n meta: z.object({ name: z.string(), previewText: z.string() }),\n theme: themeSchema,\n settings: z.object({\n width: z.number(),\n backgroundColor: z.string(),\n contentBackgroundColor: z.string(),\n }),\n modules: z.array(moduleSchema),\n});\n\nexport type ValidatedDocument = z.infer<typeof documentSchema>;\n","// Theme token resolution. Tokens use {colors.primary} or {spacing.md} syntax.\nimport type { Theme } from \"./types\";\n\nexport function resolveToken(value: unknown, theme: Theme): unknown {\n if (typeof value !== \"string\") return value;\n const m = value.match(/^\\{([\\w.]+)\\}$/);\n if (!m) return value;\n const path = m[1].split(\".\");\n let cur: unknown = theme.tokens;\n for (const p of path) {\n if (cur && typeof cur === \"object\" && p in (cur as Record<string, unknown>)) {\n cur = (cur as Record<string, unknown>)[p];\n } else {\n return value;\n }\n }\n return cur;\n}\n\nexport function resolveStyle(\n style: Record<string, unknown> | undefined | null,\n theme: Theme\n): Record<string, unknown> {\n if (!style) return {};\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(style)) {\n out[k] = resolveToken(v, theme);\n }\n return out;\n}\n","export function uid(prefix = \"id\"): string {\n return `${prefix}_${Math.random().toString(36).slice(2, 9)}${Date.now().toString(36).slice(-3)}`;\n}\n\nexport function escapeHtml(s: string): string {\n return s\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\");\n}\n\nexport function safeUrl(url: string | undefined): string {\n if (!url) return \"#\";\n try {\n const u = new URL(url, \"https://example.com\");\n if (![\"http:\", \"https:\", \"mailto:\"].includes(u.protocol)) return \"#\";\n return url;\n } catch {\n return \"#\";\n }\n}\n","// Table-based HTML email renderer. Inline CSS, ESP-friendly.\n// Responsive via @media (max-width:600px) class overrides + Outlook (MSO) fallbacks.\nimport type {\n EmailDocument,\n EmailModule,\n EmailElement,\n TextElement,\n ImageElement,\n ButtonElement,\n SpacerElement,\n DividerElement,\n ProductGridElement,\n Product,\n Theme,\n} from \"./types\";\nimport { resolveStyle, resolveToken } from \"./theme\";\nimport { escapeHtml, safeUrl } from \"./utils\";\n\nfunction px(n: number | undefined, fallback = 0): string {\n return `${n ?? fallback}px`;\n}\n\nfunction styleString(style: Record<string, unknown>): string {\n const parts: string[] = [];\n for (const [k, v] of Object.entries(style)) {\n if (v === undefined || v === null || v === \"\") continue;\n parts.push(`${k}:${v}`);\n }\n return parts.join(\";\");\n}\n\nfunction mobileCssBlock(mobileStyle: Record<string, unknown>, theme: Theme): string {\n const resolved = resolveStyle(mobileStyle, theme);\n const map: Record<string, string> = {};\n const set = (cssKey: string, val: unknown, suffix = \"\") => {\n if (val === undefined || val === null || val === \"\") return;\n map[cssKey] = `${val}${suffix} !important`;\n };\n set(\"font-family\", resolved.fontFamily);\n if (resolved.fontSize !== undefined) set(\"font-size\", resolved.fontSize, \"px\");\n set(\"line-height\", resolved.lineHeight);\n if (resolved.letterSpacing !== undefined) set(\"letter-spacing\", resolved.letterSpacing, \"px\");\n set(\"font-weight\", resolved.fontWeight);\n set(\"color\", resolved.color);\n set(\"text-align\", resolved.align);\n set(\"background-color\", resolved.backgroundColor);\n if (resolved.paddingTop !== undefined) set(\"padding-top\", resolved.paddingTop, \"px\");\n if (resolved.paddingBottom !== undefined) set(\"padding-bottom\", resolved.paddingBottom, \"px\");\n if (resolved.paddingLeft !== undefined) set(\"padding-left\", resolved.paddingLeft, \"px\");\n if (resolved.paddingRight !== undefined) set(\"padding-right\", resolved.paddingRight, \"px\");\n if (resolved.borderRadius !== undefined) set(\"border-radius\", resolved.borderRadius, \"px\");\n if (resolved.width !== undefined) set(\"width\", resolved.width, \"px\");\n if (resolved.height !== undefined) set(\"height\", resolved.height, \"px\");\n return Object.entries(map)\n .map(([k, v]) => `${k}:${v}`)\n .join(\";\");\n}\n\ninterface RenderCtx {\n theme: Theme;\n mobileRules: string[];\n classCounter: { n: number };\n}\n\nfunction nextClass(ctx: RenderCtx): string {\n ctx.classCounter.n += 1;\n return `r${ctx.classCounter.n}`;\n}\n\nfunction collectMobile(\n ctx: RenderCtx,\n style: Record<string, unknown> | undefined\n): string | null {\n const mobile = style?.mobile as Record<string, unknown> | undefined;\n const hideOn = style?.hideOn as \"mobile\" | \"desktop\" | undefined;\n if (!mobile && !hideOn) return null;\n const cls = nextClass(ctx);\n if (mobile && Object.keys(mobile).length > 0) {\n const css = mobileCssBlock(mobile, ctx.theme);\n if (css) {\n ctx.mobileRules.push(`@media only screen and (max-width:600px){.${cls}{${css}}}`);\n if (mobile.width !== undefined) {\n ctx.mobileRules.push(\n `@media only screen and (max-width:600px){.${cls} img{max-width:${mobile.width}px !important;width:100% !important;height:auto !important;}}`\n );\n }\n }\n }\n if (hideOn === \"mobile\") {\n ctx.mobileRules.push(\n `@media only screen and (max-width:600px){.${cls}{display:none !important;mso-hide:all;max-height:0;overflow:hidden;}}`\n );\n }\n if (hideOn === \"desktop\") {\n ctx.mobileRules.push(\n `@media only screen and (min-width:601px){.${cls}{display:none !important;}}`\n );\n }\n return cls;\n}\n\nfunction renderText(el: TextElement, ctx: RenderCtx): string {\n const s = resolveStyle((el.style ?? {}) as Record<string, unknown>, ctx.theme);\n const css = styleString({\n \"font-family\": s.fontFamily ?? \"Arial, Helvetica, sans-serif\",\n \"font-size\": s.fontSize ? `${s.fontSize}px` : \"16px\",\n \"line-height\": s.lineHeight ?? 1.5,\n \"letter-spacing\": s.letterSpacing ? `${s.letterSpacing}px` : undefined,\n \"font-weight\": s.fontWeight ?? \"normal\",\n color: s.color ?? \"#111827\",\n \"text-align\": s.align ?? \"left\",\n \"padding-top\": px(s.paddingTop as number, 8),\n \"padding-bottom\": px(s.paddingBottom as number, 8),\n \"padding-left\": px(s.paddingLeft as number, 16),\n \"padding-right\": px(s.paddingRight as number, 16),\n \"mso-line-height-rule\": \"exactly\",\n \"-webkit-text-size-adjust\": \"100%\",\n \"-ms-text-size-adjust\": \"100%\",\n margin: 0,\n });\n const link = s.link as string | undefined;\n const inner = link\n ? `<a href=\"${safeUrl(link)}\" style=\"color:inherit;text-decoration:underline\">${el.content}</a>`\n : el.content;\n const cls = collectMobile(ctx, el.style as Record<string, unknown>);\n return `<div${cls ? ` class=\"${cls}\"` : \"\"} style=\"${css}\">${inner}</div>`;\n}\n\nfunction renderImage(el: ImageElement, ctx: RenderCtx): string {\n const s = resolveStyle((el.style ?? {}) as Record<string, unknown>, ctx.theme);\n const wrapCss = styleString({\n \"text-align\": s.align ?? \"center\",\n \"padding-top\": px(s.paddingTop as number, 0),\n \"padding-bottom\": px(s.paddingBottom as number, 0),\n \"padding-left\": px(s.paddingLeft as number, 0),\n \"padding-right\": px(s.paddingRight as number, 0),\n \"font-size\": \"0\",\n \"line-height\": \"0\",\n });\n const imgCss = styleString({\n display: \"block\",\n \"max-width\": \"100%\",\n width: s.width ? `${s.width}px` : \"100%\",\n height: s.height ? `${s.height}px` : \"auto\",\n \"border-radius\": s.borderRadius ? `${s.borderRadius}px` : undefined,\n border: 0,\n outline: \"none\",\n \"text-decoration\": \"none\",\n \"-ms-interpolation-mode\": \"bicubic\",\n margin: s.align === \"center\" || !s.align ? \"0 auto\" : undefined,\n });\n const widthAttr = s.width ? ` width=\"${s.width}\"` : \"\";\n const img = `<img src=\"${escapeHtml(el.src)}\" alt=\"${escapeHtml(el.alt ?? \"\")}\"${widthAttr} style=\"${imgCss}\" />`;\n const wrapped = el.link ? `<a href=\"${safeUrl(el.link)}\">${img}</a>` : img;\n const cls = collectMobile(ctx, el.style as Record<string, unknown>);\n return `<div${cls ? ` class=\"${cls}\"` : \"\"} style=\"${wrapCss}\">${wrapped}</div>`;\n}\n\nfunction renderButton(el: ButtonElement, ctx: RenderCtx): string {\n const s = resolveStyle((el.style ?? {}) as Record<string, unknown>, ctx.theme);\n const align = (s.align as string) ?? \"center\";\n const wrapCss = styleString({\n \"text-align\": align,\n \"padding-top\": px(s.paddingTop as number, 12),\n \"padding-bottom\": px(s.paddingBottom as number, 12),\n \"padding-left\": px(s.paddingLeft as number, 16),\n \"padding-right\": px(s.paddingRight as number, 16),\n });\n const bg = (s.backgroundColor as string) ?? \"#3A7D52\";\n const color = (s.color as string) ?? \"#FFFFFF\";\n const radius = (s.borderRadius as number) ?? 6;\n const fontSize = (s.fontSize as number) ?? 16;\n const fontFamily = (s.fontFamily as string) ?? \"Arial, Helvetica, sans-serif\";\n const fontWeight = (s.fontWeight as string) ?? \"bold\";\n\n const btnCss = styleString({\n display: \"inline-block\",\n \"background-color\": bg,\n color,\n \"font-family\": fontFamily,\n \"font-size\": `${fontSize}px`,\n \"font-weight\": fontWeight,\n \"text-decoration\": \"none\",\n \"border-radius\": `${radius}px`,\n padding: \"14px 28px\",\n \"mso-padding-alt\": \"0\",\n \"line-height\": \"100%\",\n \"-webkit-text-size-adjust\": \"none\",\n });\n const label = escapeHtml(el.label);\n const href = safeUrl(el.link);\n const arcsize = Math.min(50, Math.round((radius / 22) * 100));\n const vml = `<!--[if mso]>\n<v:roundrect xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:w=\"urn:schemas-microsoft-com:office:word\" href=\"${href}\" style=\"height:44px;v-text-anchor:middle;width:200px;\" arcsize=\"${arcsize}%\" stroke=\"f\" fillcolor=\"${bg}\">\n<w:anchorlock/>\n<center style=\"color:${color};font-family:${fontFamily};font-size:${fontSize}px;font-weight:${fontWeight};\">${label}</center>\n</v:roundrect>\n<![endif]-->`;\n const html = `<!--[if !mso]><!-- --><a href=\"${href}\" style=\"${btnCss}\">${label}</a><!--<![endif]-->`;\n const cls = collectMobile(ctx, el.style as Record<string, unknown>);\n return `<div${cls ? ` class=\"${cls}\"` : \"\"} style=\"${wrapCss}\">${vml}${html}</div>`;\n}\n\nfunction renderSpacer(el: SpacerElement): string {\n return `<div style=\"height:${el.height}px;line-height:${el.height}px;font-size:1px;mso-line-height-rule:exactly;\"> </div>`;\n}\n\nfunction renderDivider(el: DividerElement, ctx: RenderCtx): string {\n const s = resolveStyle((el.style ?? {}) as Record<string, unknown>, ctx.theme);\n const padTop = px(s.paddingTop as number, 8);\n const padBot = px(s.paddingBottom as number, 8);\n const color = (s.color as string) ?? \"#E5E7EB\";\n const thickness = (s.thickness as number) ?? 1;\n return `<div style=\"padding-top:${padTop};padding-bottom:${padBot};\"><hr style=\"border:0;border-top:${thickness}px solid ${color};margin:0;height:0;\" /></div>`;\n}\n\nfunction renderElement(el: EmailElement, ctx: RenderCtx): string {\n switch (el.type) {\n case \"text\":\n return renderText(el, ctx);\n case \"image\":\n return renderImage(el, ctx);\n case \"button\":\n return renderButton(el, ctx);\n case \"spacer\":\n return renderSpacer(el);\n case \"divider\":\n return renderDivider(el, ctx);\n case \"productGrid\":\n return renderProductGrid(el, ctx);\n }\n}\n\nfunction renderProductGrid(el: ProductGridElement, ctx: RenderCtx): string {\n const s = resolveStyle((el.style ?? {}) as Record<string, unknown>, ctx.theme);\n const cols = el.columns;\n const products = el.products.slice(0, cols * 6); // sane upper bound\n const cardBg =\n (s.cardBackgroundColor as string) ?? (s.backgroundColor as string) ?? \"transparent\";\n const nameColor = (s.nameColor as string) ?? \"{colors.text}\";\n const finalColor = (s.finalPriceColor as string) ?? \"{colors.primary}\";\n const oldColor = (s.oldPriceColor as string) ?? \"#9CA3AF\";\n const btnBg = (s.buttonBackgroundColor as string) ?? \"{colors.buttonBackground}\";\n const btnColor = (s.buttonColor as string) ?? \"{colors.buttonText}\";\n const radius = (s.borderRadius as number) ?? 0;\n const padTop = px(s.paddingTop as number, 16);\n const padBot = px(s.paddingBottom as number, 16);\n const padL = px(s.paddingLeft as number, 16);\n const padR = px(s.paddingRight as number, 16);\n\n const colWidthPct = `${Math.floor(100 / cols)}%`;\n\n // Build product card HTML.\n const card = (p: Product, last: boolean): string => {\n const finalPrice = `<span class=\"final_price\" style=\"color:${resolveTokenSafe(finalColor, ctx.theme)};font-weight:bold;font-size:18px;\">${escapeHtml(\n p.finalPrice\n )}</span>`;\n const oldPrice = el.showOldPrice && p.oldPrice\n ? `<span class=\"old_price\" style=\"color:${resolveTokenSafe(oldColor, ctx.theme)};text-decoration:line-through;font-size:14px;margin-right:8px;\">${escapeHtml(\n p.oldPrice\n )}</span>`\n : \"\";\n const desc = el.showDescription && p.description\n ? `<div style=\"font-family:Arial,Helvetica,sans-serif;font-size:13px;line-height:1.5;color:#6B7280;padding:0 0 12px 0;\">${escapeHtml(p.description)}</div>`\n : \"\";\n const btnLabel = p.buttonLabel ?? el.buttonLabel ?? \"Shop now\";\n const link = p.link ?? \"#\";\n const btn = el.showButton\n ? `<table role=\"presentation\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"margin:0 auto;\"><tr><td align=\"center\" bgcolor=\"${resolveTokenSafe(\n btnBg,\n ctx.theme\n )}\" style=\"border-radius:6px;\"><!--[if mso]>\n<v:roundrect xmlns:v=\"urn:schemas-microsoft-com:vml\" href=\"${safeUrl(link)}\" style=\"height:36px;v-text-anchor:middle;width:140px;\" arcsize=\"15%\" stroke=\"f\" fillcolor=\"${resolveTokenSafe(btnBg, ctx.theme)}\"><w:anchorlock/><center style=\"color:${resolveTokenSafe(btnColor, ctx.theme)};font-family:Arial,sans-serif;font-size:13px;font-weight:bold;\">${escapeHtml(btnLabel)}</center></v:roundrect>\n<![endif]--><!--[if !mso]><!-- --><a href=\"${safeUrl(link)}\" style=\"display:inline-block;padding:10px 18px;font-family:Arial,Helvetica,sans-serif;font-size:13px;font-weight:bold;color:${resolveTokenSafe(btnColor, ctx.theme)};background-color:${resolveTokenSafe(btnBg, ctx.theme)};border-radius:6px;text-decoration:none;\">${escapeHtml(btnLabel)}</a><!--<![endif]--></td></tr></table>`\n : \"\";\n const img = `<img src=\"${escapeHtml(p.image)}\" alt=\"${escapeHtml(p.imageAlt ?? p.name)}\" width=\"100%\" style=\"display:block;width:100%;max-width:100%;height:auto;border:0;outline:none;text-decoration:none;border-radius:${radius}px;\" />`;\n const imgWrapped = p.link\n ? `<a href=\"${safeUrl(p.link)}\" style=\"text-decoration:none;color:inherit;\">${img}</a>`\n : img;\n\n // Each cell: stack on mobile via class. Vertical-align top.\n return `<td class=\"stack\" valign=\"top\" style=\"padding:0 ${last ? 0 : 8}px 16px ${last ? 0 : 0}px;width:${colWidthPct};vertical-align:top;\">\n <table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"background-color:${resolveTokenSafe(cardBg, ctx.theme)};border-radius:${radius}px;\">\n <tr><td style=\"padding:0;font-size:0;line-height:0;\">${imgWrapped}</td></tr>\n <tr><td style=\"padding:12px 12px 4px 12px;font-family:Arial,Helvetica,sans-serif;font-size:15px;font-weight:bold;color:${resolveTokenSafe(nameColor, ctx.theme)};line-height:1.3;\">${escapeHtml(p.name)}</td></tr>\n <tr><td style=\"padding:0 12px 8px 12px;font-family:Arial,Helvetica,sans-serif;\">${oldPrice}${finalPrice}</td></tr>\n ${desc ? `<tr><td style=\"padding:0 12px 4px 12px;\">${desc}</td></tr>` : \"\"}\n ${btn ? `<tr><td align=\"center\" style=\"padding:4px 12px 12px 12px;\">${btn}</td></tr>` : \"\"}\n </table>\n</td>`;\n };\n\n // Group products into rows of `cols`.\n const rows: string[] = [];\n for (let i = 0; i < products.length; i += cols) {\n const slice = products.slice(i, i + cols);\n const tds = slice\n .map((p, idx) => card(p, idx === slice.length - 1))\n .join(\"\\n\");\n // Pad with empty cells if last row is short to keep widths even on desktop.\n const pads = cols - slice.length;\n let padTds = \"\";\n for (let j = 0; j < pads; j++) {\n padTds += `<td class=\"stack\" style=\"width:${colWidthPct};\"> </td>`;\n }\n rows.push(`<tr>${tds}${padTds}</tr>`);\n }\n\n // Mobile: each .stack td becomes block, full-width.\n const cls = collectMobile(ctx, el.style as Record<string, unknown>);\n return `<div${cls ? ` class=\"${cls}\"` : \"\"} style=\"padding:${padTop} ${padR} ${padBot} ${padL};\">\n<!--[if mso | IE]><table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\"><tr><td><![endif]-->\n<table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"width:100%;border-collapse:separate;border-spacing:0;\">\n${rows.join(\"\\n\")}\n</table>\n<!--[if mso | IE]></td></tr></table><![endif]-->\n</div>`;\n}\n\nfunction resolveTokenSafe(value: string | undefined, theme: Theme): string {\n if (!value) return \"\";\n const r = resolveToken(value, theme);\n return typeof r === \"string\" ? r : String(r);\n}\n\nfunction renderModule(m: EmailModule, ctx: RenderCtx): string {\n const s = resolveStyle((m.style ?? {}) as Record<string, unknown>, ctx.theme);\n const css = styleString({\n \"background-color\": s.backgroundColor,\n \"padding-top\": px(s.paddingTop as number, 0),\n \"padding-bottom\": px(s.paddingBottom as number, 0),\n \"padding-left\": px(s.paddingLeft as number, 0),\n \"padding-right\": px(s.paddingRight as number, 0),\n \"border-radius\": s.borderRadius ? `${s.borderRadius}px` : undefined,\n });\n const inner = m.children.map((c) => renderElement(c, ctx)).join(\"\\n\");\n const cls = collectMobile(ctx, m.style as Record<string, unknown>);\n return `<tr><td${cls ? ` class=\"${cls}\"` : \"\"} style=\"${css}\">${inner}</td></tr>`;\n}\n\nexport function renderEmailHtml(doc: EmailDocument): string {\n const bg = resolveToken(doc.settings.backgroundColor, doc.theme) as string;\n const cbg = resolveToken(doc.settings.contentBackgroundColor, doc.theme) as string;\n const width = doc.settings.width;\n const ctx: RenderCtx = { theme: doc.theme, mobileRules: [], classCounter: { n: 0 } };\n const body = doc.modules.map((m) => renderModule(m, ctx)).join(\"\\n\");\n const previewText = escapeHtml(doc.meta.previewText ?? \"\");\n const mobileCss = ctx.mobileRules.join(\"\\n\");\n\n return `<!doctype html>\n<html lang=\"en\" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:o=\"urn:schemas-microsoft-com:office:office\">\n<head>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\" />\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n<meta name=\"x-apple-disable-message-reformatting\" />\n<meta name=\"format-detection\" content=\"telephone=no,address=no,email=no,date=no\" />\n<meta name=\"color-scheme\" content=\"light dark\" />\n<meta name=\"supported-color-schemes\" content=\"light dark\" />\n<title>${escapeHtml(doc.meta.name)}</title>\n<!--[if gte mso 9]><xml><o:OfficeDocumentSettings><o:AllowPNG/><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings></xml><![endif]-->\n<style>\n html,body{margin:0 !important;padding:0 !important;height:100% !important;width:100% !important;}\n *{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;}\n table,td{mso-table-lspace:0pt !important;mso-table-rspace:0pt !important;border-collapse:collapse;}\n table{border-spacing:0 !important;border-collapse:collapse !important;table-layout:fixed !important;margin:0 auto !important;}\n img{-ms-interpolation-mode:bicubic;border:0;height:auto;line-height:100%;outline:none;text-decoration:none;}\n a{text-decoration:none;}\n a[x-apple-data-detectors]{color:inherit !important;text-decoration:none !important;font-size:inherit !important;font-family:inherit !important;font-weight:inherit !important;line-height:inherit !important;}\n u + #body a{color:inherit;text-decoration:none;}\n #MessageViewBody a{color:inherit;text-decoration:none;}\n @media only screen and (max-width:600px){\n .email-container{width:100% !important;max-width:100% !important;}\n .email-content{width:100% !important;max-width:100% !important;}\n .stack{display:block !important;width:100% !important;max-width:100% !important;box-sizing:border-box;padding:0 0 16px 0 !important;}\n .center-on-mobile{text-align:center !important;}\n .full-on-mobile{width:100% !important;height:auto !important;max-width:100% !important;}\n }\n /* Price classes — override these to restyle prices project-wide. */\n .final_price{font-weight:bold;}\n .old_price{text-decoration:line-through;color:#9CA3AF;margin-right:8px;}\n${mobileCss}\n</style>\n</head>\n<body id=\"body\" style=\"margin:0;padding:0;background-color:${bg};\">\n<div style=\"display:none;max-height:0;overflow:hidden;opacity:0;mso-hide:all;\">${previewText}</div>\n<table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"background-color:${bg};\">\n <tr><td align=\"center\" style=\"padding:0;\">\n <!--[if mso | IE]><table role=\"presentation\" width=\"${width}\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" align=\"center\"><tr><td><![endif]-->\n <table role=\"presentation\" class=\"email-container\" width=\"${width}\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"width:${width}px;max-width:${width}px;background-color:${cbg};margin:0 auto;\">\n${body}\n </table>\n <!--[if mso | IE]></td></tr></table><![endif]-->\n </td></tr>\n</table>\n</body>\n</html>`;\n}\n","import type { Theme } from \"../core/types\";\n\nexport const minimalSaaS: Theme = {\n id: \"minimal-saas\",\n name: \"Minimal SaaS\",\n tokens: {\n colors: {\n background: \"#F4F5F7\",\n surface: \"#FFFFFF\",\n primary: \"#2563EB\",\n text: \"#0F172A\",\n muted: \"#64748B\",\n buttonBackground: \"#2563EB\",\n buttonText: \"#FFFFFF\",\n },\n fonts: {\n heading: \"Helvetica, Arial, sans-serif\",\n body: \"Helvetica, Arial, sans-serif\",\n button: \"Helvetica, Arial, sans-serif\",\n },\n spacing: { xs: 4, sm: 8, md: 16, lg: 24, xl: 40 },\n radius: { sm: 4, md: 8, lg: 16 },\n },\n};\n\nexport const ecommercePromo: Theme = {\n id: \"ecommerce-promo\",\n name: \"Ecommerce Promo\",\n tokens: {\n colors: {\n background: \"#FFF7ED\",\n surface: \"#FFFFFF\",\n primary: \"#EA580C\",\n text: \"#1C1917\",\n muted: \"#78716C\",\n buttonBackground: \"#EA580C\",\n buttonText: \"#FFFFFF\",\n },\n fonts: {\n heading: \"Georgia, serif\",\n body: \"Arial, Helvetica, sans-serif\",\n button: \"Arial, Helvetica, sans-serif\",\n },\n spacing: { xs: 4, sm: 8, md: 16, lg: 24, xl: 40 },\n radius: { sm: 4, md: 8, lg: 24 },\n },\n};\n\nexport const luxuryBlack: Theme = {\n id: \"luxury-black\",\n name: \"Luxury Black\",\n tokens: {\n colors: {\n background: \"#000000\",\n surface: \"#0A0A0A\",\n primary: \"#D4AF37\",\n text: \"#F5F5F5\",\n muted: \"#9CA3AF\",\n buttonBackground: \"#D4AF37\",\n buttonText: \"#000000\",\n },\n fonts: {\n heading: \"Georgia, serif\",\n body: \"Georgia, serif\",\n button: \"Helvetica, Arial, sans-serif\",\n },\n spacing: { xs: 4, sm: 8, md: 16, lg: 24, xl: 48 },\n radius: { sm: 0, md: 0, lg: 0 },\n },\n};\n\nexport const greenEco: Theme = {\n id: \"green-eco\",\n name: \"Green Eco\",\n tokens: {\n colors: {\n background: \"#BEC0B6\",\n surface: \"#FFFFFF\",\n primary: \"#3A7D52\",\n text: \"#2C2928\",\n muted: \"#6B6B6B\",\n buttonBackground: \"#3A7D52\",\n buttonText: \"#FFFFFF\",\n },\n fonts: {\n heading: \"Georgia, serif\",\n body: \"Arial, Helvetica, sans-serif\",\n button: \"Arial, Helvetica, sans-serif\",\n },\n spacing: { xs: 4, sm: 8, md: 16, lg: 24, xl: 40 },\n radius: { sm: 4, md: 8, lg: 16 },\n },\n};\n\nexport const newsletterEditorial: Theme = {\n id: \"newsletter-editorial\",\n name: \"Newsletter Editorial\",\n tokens: {\n colors: {\n background: \"#FAFAF9\",\n surface: \"#FFFFFF\",\n primary: \"#111827\",\n text: \"#111827\",\n muted: \"#6B7280\",\n buttonBackground: \"#111827\",\n buttonText: \"#FFFFFF\",\n },\n fonts: {\n heading: \"Georgia, 'Times New Roman', serif\",\n body: \"Georgia, 'Times New Roman', serif\",\n button: \"Helvetica, Arial, sans-serif\",\n },\n spacing: { xs: 4, sm: 8, md: 16, lg: 32, xl: 48 },\n radius: { sm: 2, md: 4, lg: 8 },\n },\n};\n\nexport const defaultThemes: Theme[] = [\n minimalSaaS,\n ecommercePromo,\n luxuryBlack,\n greenEco,\n newsletterEditorial,\n];\n","import { create } from \"zustand\";\nimport type {\n EmailDocument,\n EmailModule,\n EmailElement,\n Theme,\n Selection,\n} from \"../core/types\";\nimport { uid } from \"../core/utils\";\nimport { documentSchema } from \"../core/validation\";\nimport { renderEmailHtml } from \"../core/renderer\";\nimport { defaultThemes } from \"../themes/defaultThemes\";\nimport type { TemplateDefinition } from \"../templates/registry\";\n\nconst HISTORY_LIMIT = 50;\n\nexport type ViewMode = \"desktop\" | \"mobile\";\n\ninterface State {\n doc: EmailDocument;\n selection: Selection;\n past: EmailDocument[];\n future: EmailDocument[];\n themes: Theme[];\n viewMode: ViewMode;\n\n // Mutations\n setSelection: (sel: Selection) => void;\n setViewMode: (mode: ViewMode) => void;\n applyDoc: (next: EmailDocument, push?: boolean) => void;\n undo: () => void;\n redo: () => void;\n\n addModule: (mod: EmailModule, index?: number) => void;\n deleteModule: (moduleId: string) => void;\n duplicateModule: (moduleId: string) => void;\n reorderModules: (fromIndex: number, toIndex: number) => void;\n\n updateModule: (moduleId: string, patch: Partial<EmailModule>) => void;\n updateElement: (\n moduleId: string,\n elementId: string,\n patch: Partial<EmailElement>\n ) => void;\n deleteElement: (moduleId: string, elementId: string) => void;\n reorderElement: (moduleId: string, fromIndex: number, toIndex: number) => void;\n moveElement: (moduleId: string, elementId: string, dir: -1 | 1) => void;\n\n applyTheme: (theme: Theme) => void;\n updateMeta: (patch: Partial<EmailDocument[\"meta\"]>) => void;\n updateSettings: (patch: Partial<EmailDocument[\"settings\"]>) => void;\n\n // Templates\n loadTemplate: (def: TemplateDefinition) => void;\n resetDocument: () => void;\n\n // I/O\n exportJson: () => string;\n importJson: (json: string) => { ok: true } | { ok: false; error: string };\n exportHtml: () => string;\n loadFromLocalStorage: () => void;\n saveToLocalStorage: () => void;\n}\n\nconst STORAGE_KEY = \"openpostcards.draft\";\n\nfunction emptyDoc(theme: Theme): EmailDocument {\n return {\n version: \"1.0\",\n meta: { name: \"Untitled email\", previewText: \"\" },\n theme,\n settings: {\n width: 600,\n backgroundColor: \"{colors.background}\",\n contentBackgroundColor: \"{colors.surface}\",\n },\n modules: [],\n };\n}\n\nexport const useEmailStore = create<State>((set, get) => ({\n doc: emptyDoc(defaultThemes[0]),\n selection: { kind: \"email\" },\n past: [],\n future: [],\n themes: defaultThemes,\n viewMode: \"desktop\",\n\n setSelection: (sel) => set({ selection: sel }),\n setViewMode: (mode) => set({ viewMode: mode }),\n\n applyDoc: (next, push = true) =>\n set((s) => {\n if (!push) return { doc: next };\n const past = [...s.past, s.doc].slice(-HISTORY_LIMIT);\n return { doc: next, past, future: [] };\n }),\n\n undo: () =>\n set((s) => {\n if (s.past.length === 0) return s;\n const prev = s.past[s.past.length - 1];\n return {\n doc: prev,\n past: s.past.slice(0, -1),\n future: [s.doc, ...s.future],\n };\n }),\n\n redo: () =>\n set((s) => {\n if (s.future.length === 0) return s;\n const [next, ...rest] = s.future;\n return { doc: next, past: [...s.past, s.doc], future: rest };\n }),\n\n addModule: (mod, index) => {\n const { doc, applyDoc } = get();\n const idx = index ?? doc.modules.length;\n const modules = [...doc.modules];\n modules.splice(idx, 0, mod);\n applyDoc({ ...doc, modules });\n set({ selection: { kind: \"module\", moduleId: mod.id } });\n },\n\n deleteModule: (moduleId) => {\n const { doc, applyDoc } = get();\n const modules = doc.modules.filter((m) => m.id !== moduleId);\n applyDoc({ ...doc, modules });\n set({ selection: { kind: \"email\" } });\n },\n\n duplicateModule: (moduleId) => {\n const { doc, applyDoc } = get();\n const idx = doc.modules.findIndex((m) => m.id === moduleId);\n if (idx === -1) return;\n const original = doc.modules[idx];\n const clone: EmailModule = {\n ...original,\n id: uid(\"module\"),\n children: original.children.map((c) => ({ ...c, id: uid(\"el\") })),\n };\n const modules = [...doc.modules];\n modules.splice(idx + 1, 0, clone);\n applyDoc({ ...doc, modules });\n set({ selection: { kind: \"module\", moduleId: clone.id } });\n },\n\n reorderModules: (fromIndex, toIndex) => {\n const { doc, applyDoc } = get();\n if (fromIndex === toIndex) return;\n const modules = [...doc.modules];\n const [moved] = modules.splice(fromIndex, 1);\n modules.splice(toIndex, 0, moved);\n applyDoc({ ...doc, modules });\n },\n\n updateModule: (moduleId, patch) => {\n const { doc, applyDoc } = get();\n const modules = doc.modules.map((m) =>\n m.id === moduleId ? { ...m, ...patch, style: { ...m.style, ...patch.style } } : m\n );\n applyDoc({ ...doc, modules });\n },\n\n updateElement: (moduleId, elementId, patch) => {\n const { doc, applyDoc } = get();\n const modules = doc.modules.map((m) => {\n if (m.id !== moduleId) return m;\n const children = m.children.map((c) => {\n if (c.id !== elementId) return c;\n const next = { ...c, ...patch } as EmailElement;\n if (\"style\" in c && \"style\" in patch) {\n (next as { style?: Record<string, unknown> }).style = {\n ...(c as { style?: Record<string, unknown> }).style,\n ...(patch as { style?: Record<string, unknown> }).style,\n };\n }\n return next;\n });\n return { ...m, children };\n });\n applyDoc({ ...doc, modules });\n },\n\n deleteElement: (moduleId, elementId) => {\n const { doc, applyDoc } = get();\n const modules = doc.modules.map((m) =>\n m.id === moduleId\n ? { ...m, children: m.children.filter((c) => c.id !== elementId) }\n : m\n );\n applyDoc({ ...doc, modules });\n set({ selection: { kind: \"module\", moduleId } });\n },\n\n reorderElement: (moduleId, fromIndex, toIndex) => {\n const { doc, applyDoc } = get();\n const modules = doc.modules.map((m) => {\n if (m.id !== moduleId) return m;\n if (fromIndex < 0 || fromIndex >= m.children.length) return m;\n if (toIndex < 0 || toIndex >= m.children.length) return m;\n if (fromIndex === toIndex) return m;\n const children = [...m.children];\n const [moved] = children.splice(fromIndex, 1);\n children.splice(toIndex, 0, moved);\n return { ...m, children };\n });\n applyDoc({ ...doc, modules });\n },\n\n moveElement: (moduleId, elementId, dir) => {\n const { doc, reorderElement } = get();\n const m = doc.modules.find((x) => x.id === moduleId);\n if (!m) return;\n const idx = m.children.findIndex((c) => c.id === elementId);\n if (idx === -1) return;\n reorderElement(moduleId, idx, idx + dir);\n },\n\n applyTheme: (theme) => {\n const { doc, applyDoc } = get();\n applyDoc({ ...doc, theme });\n },\n\n updateMeta: (patch) => {\n const { doc, applyDoc } = get();\n applyDoc({ ...doc, meta: { ...doc.meta, ...patch } });\n },\n\n updateSettings: (patch) => {\n const { doc, applyDoc } = get();\n applyDoc({ ...doc, settings: { ...doc.settings, ...patch } });\n },\n\n loadTemplate: (def) => {\n const next = def.build();\n get().applyDoc(next);\n set({ selection: { kind: \"email\" }, past: [], future: [] });\n },\n\n resetDocument: () => {\n const { doc, applyDoc } = get();\n applyDoc(emptyDoc(doc.theme));\n set({ selection: { kind: \"email\" }, past: [], future: [] });\n },\n\n exportJson: () => JSON.stringify(get().doc, null, 2),\n\n importJson: (json) => {\n try {\n const parsed = JSON.parse(json);\n const result = documentSchema.safeParse(parsed);\n if (!result.success) {\n return { ok: false, error: result.error.message };\n }\n get().applyDoc(result.data as EmailDocument);\n return { ok: true };\n } catch (e) {\n return { ok: false, error: (e as Error).message };\n }\n },\n\n exportHtml: () => renderEmailHtml(get().doc),\n\n loadFromLocalStorage: () => {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return;\n const result = documentSchema.safeParse(JSON.parse(raw));\n if (result.success) {\n set({ doc: result.data as EmailDocument, past: [], future: [] });\n }\n } catch {\n // ignore corrupt drafts\n }\n },\n\n saveToLocalStorage: () => {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(get().doc));\n },\n}));\n","// Template = a complete EmailDocument factory. Templates are JSON-shaped\n// (their `build()` returns the same `EmailDocument` JSON used by the editor),\n// but they are written as TypeScript factories so they can:\n// - reuse element helpers (text, image, productGrid, ...)\n// - generate fresh ids on every load (avoiding id collisions)\n// - reference theme tokens like {colors.primary}.\n//\n// Each template file exports a `TemplateDefinition` and self-registers with\n// `templateRegistry.register(def)` via the aggregator in ./index.ts.\n\nimport type { EmailDocument } from \"../core/types\";\n\nexport type TemplateCategory =\n | \"newsletter\"\n | \"ecommerce\"\n | \"abandoned_cart\"\n | \"product_launch\"\n | \"onboarding\"\n | \"event\"\n | \"transactional\"\n | \"publishing\";\n\nexport interface TemplateDefinition {\n id: string;\n name: string;\n category: TemplateCategory;\n /** Human + AI readable description. */\n description: string;\n /** Free-form tags for search. */\n tags?: string[];\n /** Optional preview image URL (https or data: URI). */\n thumbnail?: string;\n /** Returns a fresh `EmailDocument` JSON with new ids every call. */\n build: () => EmailDocument;\n}\n\nclass TemplateRegistry {\n private templates = new Map<string, TemplateDefinition>();\n\n register(def: TemplateDefinition) {\n this.templates.set(def.id, def);\n }\n\n get(id: string): TemplateDefinition | undefined {\n return this.templates.get(id);\n }\n\n list(): TemplateDefinition[] {\n return Array.from(this.templates.values());\n }\n\n byCategory(cat: TemplateCategory): TemplateDefinition[] {\n return this.list().filter((t) => t.category === cat);\n }\n}\n\nexport const templateRegistry = new TemplateRegistry();\n\nexport const TEMPLATE_CATEGORY_LABELS: Record<TemplateCategory, string> = {\n newsletter: \"Newsletter\",\n ecommerce: \"Ecommerce\",\n abandoned_cart: \"Abandoned Cart\",\n product_launch: \"Product Launch\",\n onboarding: \"Onboarding\",\n event: \"Event\",\n transactional: \"Transactional\",\n publishing: \"Publishing\",\n};\n","// Shared element builders for module definitions.\n// Keeps individual module files terse and consistent.\nimport type { EmailElement, EmailModule, Product, ProductGridElement } from \"../core/types\";\nimport { uid } from \"../core/utils\";\n\nexport const text = (\n content: string,\n opts: Partial<{\n role: \"headline\" | \"subheadline\" | \"body\" | \"caption\";\n fontSize: number;\n fontFamily: string;\n fontWeight: number | string;\n color: string;\n align: \"left\" | \"center\" | \"right\";\n paddingTop: number;\n paddingBottom: number;\n paddingLeft: number;\n paddingRight: number;\n lineHeight: number;\n letterSpacing: number;\n link: string;\n mobile: Record<string, unknown>;\n }> = {}\n): EmailElement => {\n // Sensible mobile defaults: tighter side padding, slightly smaller large headings.\n const baseFontSize = opts.fontSize ?? 16;\n const mobileDefaults: Record<string, unknown> = {\n paddingLeft: 16,\n paddingRight: 16,\n };\n if (baseFontSize >= 28) mobileDefaults.fontSize = Math.max(22, Math.round(baseFontSize * 0.78));\n else if (baseFontSize >= 22) mobileDefaults.fontSize = Math.max(20, Math.round(baseFontSize * 0.85));\n return {\n id: uid(\"el\"),\n type: \"text\",\n role: opts.role,\n content,\n style: {\n fontFamily: opts.fontFamily ?? \"{fonts.body}\",\n fontSize: baseFontSize,\n fontWeight: opts.fontWeight,\n color: opts.color ?? \"{colors.text}\",\n align: opts.align ?? \"left\",\n paddingTop: opts.paddingTop ?? 8,\n paddingBottom: opts.paddingBottom ?? 8,\n paddingLeft: opts.paddingLeft ?? 24,\n paddingRight: opts.paddingRight ?? 24,\n lineHeight: opts.lineHeight ?? 1.5,\n letterSpacing: opts.letterSpacing,\n link: opts.link,\n mobile: { ...mobileDefaults, ...(opts.mobile ?? {}) },\n },\n };\n};\n\nexport const image = (\n src: string,\n alt: string,\n opts: Partial<{\n width: number;\n height: number;\n align: \"left\" | \"center\" | \"right\";\n link: string;\n paddingTop: number;\n paddingBottom: number;\n borderRadius: number;\n mobile: Record<string, unknown>;\n }> = {}\n): EmailElement => {\n const w = opts.width ?? 552;\n // Mobile: cap to viewport width (account for outer 16px padding).\n const mobileDefaults: Record<string, unknown> = w > 343 ? { width: 343, align: \"center\" } : {};\n return {\n id: uid(\"el\"),\n type: \"image\",\n src,\n alt,\n link: opts.link,\n style: {\n width: w,\n height: opts.height,\n align: opts.align ?? \"center\",\n paddingTop: opts.paddingTop ?? 8,\n paddingBottom: opts.paddingBottom ?? 8,\n borderRadius: opts.borderRadius,\n mobile: { ...mobileDefaults, ...(opts.mobile ?? {}) },\n },\n };\n};\n\nexport const button = (\n label: string,\n link = \"#\",\n opts: Partial<{\n align: \"left\" | \"center\" | \"right\";\n backgroundColor: string;\n color: string;\n fontSize: number;\n borderRadius: number;\n paddingTop: number;\n paddingBottom: number;\n mobile: Record<string, unknown>;\n }> = {}\n): EmailElement => ({\n id: uid(\"el\"),\n type: \"button\",\n label,\n link,\n style: {\n backgroundColor: opts.backgroundColor ?? \"{colors.buttonBackground}\",\n color: opts.color ?? \"{colors.buttonText}\",\n fontFamily: \"{fonts.button}\",\n fontSize: opts.fontSize ?? 16,\n borderRadius: opts.borderRadius ?? 8,\n align: opts.align ?? \"center\",\n paddingTop: opts.paddingTop ?? 16,\n paddingBottom: opts.paddingBottom ?? 16,\n // On mobile, full-width touch-friendly button.\n mobile: { align: \"center\", ...(opts.mobile ?? {}) },\n },\n});\n\nexport const spacer = (height = 16): EmailElement => ({\n id: uid(\"el\"),\n type: \"spacer\",\n height,\n});\n\nexport const divider = (\n opts: Partial<{ color: string; thickness: number; paddingTop: number; paddingBottom: number }> = {}\n): EmailElement => ({\n id: uid(\"el\"),\n type: \"divider\",\n style: {\n color: opts.color ?? \"#E5E7EB\",\n thickness: opts.thickness ?? 1,\n paddingTop: opts.paddingTop ?? 8,\n paddingBottom: opts.paddingBottom ?? 8,\n },\n});\n\nexport const mod = (\n type: string,\n name: string,\n children: EmailElement[],\n style?: EmailModule[\"style\"]\n): EmailModule => ({\n id: uid(\"module\"),\n type,\n name,\n style: style ?? {\n backgroundColor: \"{colors.surface}\",\n paddingTop: 16,\n paddingBottom: 16,\n mobile: { paddingLeft: 0, paddingRight: 0 },\n },\n children,\n});\n\n// Heading shortcut for newsletter article titles.\nexport const heading = (\n content: string,\n opts: {\n level?: 1 | 2 | 3;\n align?: \"left\" | \"center\" | \"right\";\n paddingTop?: number;\n paddingBottom?: number;\n fontSize?: number;\n } = {}\n) => {\n const sizes = { 1: 32, 2: 24, 3: 18 } as const;\n return text(content, {\n role: \"headline\",\n fontFamily: \"{fonts.heading}\",\n fontSize: opts.fontSize ?? sizes[opts.level ?? 2],\n fontWeight: \"bold\",\n align: opts.align,\n paddingTop: opts.paddingTop ?? 16,\n paddingBottom: opts.paddingBottom ?? 8,\n lineHeight: 1.25,\n });\n};\n\nexport const eyebrow = (\n content: string,\n opts: { align?: \"left\" | \"center\" | \"right\"; paddingTop?: number; paddingBottom?: number } = {}\n) =>\n text(content.toUpperCase(), {\n fontSize: 12,\n fontWeight: \"bold\",\n color: \"{colors.primary}\",\n letterSpacing: 2,\n align: opts.align,\n paddingTop: opts.paddingTop ?? 16,\n paddingBottom: opts.paddingBottom ?? 4,\n });\n\nexport const muted = (\n content: string,\n opts: {\n align?: \"left\" | \"center\" | \"right\";\n fontSize?: number;\n paddingTop?: number;\n paddingBottom?: number;\n lineHeight?: number;\n link?: string;\n letterSpacing?: number;\n } = {}\n) =>\n text(content, {\n color: \"{colors.muted}\",\n align: opts.align,\n fontSize: opts.fontSize ?? 14,\n paddingTop: opts.paddingTop,\n paddingBottom: opts.paddingBottom,\n lineHeight: opts.lineHeight,\n link: opts.link,\n letterSpacing: opts.letterSpacing,\n });\n\nexport const PLACEHOLDER = (w: number, h: number, label = \"Image\") =>\n `https://placehold.co/${w}x${h}?text=${encodeURIComponent(label)}`;\n\nlet productSeed = 0;\nexport const product = (p: Partial<Product> & { name: string; finalPrice: string }): Product => {\n productSeed += 1;\n return {\n id: uid(\"prod\"),\n image: p.image ?? PLACEHOLDER(400, 400, p.name),\n imageAlt: p.imageAlt ?? p.name,\n name: p.name,\n finalPrice: p.finalPrice,\n oldPrice: p.oldPrice,\n description: p.description,\n link: p.link ?? \"#\",\n buttonLabel: p.buttonLabel,\n };\n};\n\nexport const productGrid = (\n products: Product[],\n opts: Partial<{\n columns: 1 | 2 | 3;\n showOldPrice: boolean;\n showButton: boolean;\n showDescription: boolean;\n buttonLabel: string;\n cardBackgroundColor: string;\n nameColor: string;\n finalPriceColor: string;\n oldPriceColor: string;\n buttonBackgroundColor: string;\n buttonColor: string;\n borderRadius: number;\n paddingTop: number;\n paddingBottom: number;\n paddingLeft: number;\n paddingRight: number;\n }> = {}\n): ProductGridElement => ({\n id: uid(\"el\"),\n type: \"productGrid\",\n products,\n columns: opts.columns ?? (products.length >= 3 ? 3 : 2),\n showOldPrice: opts.showOldPrice ?? products.some((p) => !!p.oldPrice),\n showButton: opts.showButton ?? true,\n showDescription: opts.showDescription ?? false,\n buttonLabel: opts.buttonLabel ?? \"Shop now\",\n style: {\n cardBackgroundColor: opts.cardBackgroundColor ?? \"{colors.surface}\",\n nameColor: opts.nameColor ?? \"{colors.text}\",\n finalPriceColor: opts.finalPriceColor ?? \"{colors.primary}\",\n oldPriceColor: opts.oldPriceColor ?? \"#9CA3AF\",\n buttonBackgroundColor: opts.buttonBackgroundColor ?? \"{colors.buttonBackground}\",\n buttonColor: opts.buttonColor ?? \"{colors.buttonText}\",\n borderRadius: opts.borderRadius ?? 8,\n paddingTop: opts.paddingTop ?? 8,\n paddingBottom: opts.paddingBottom ?? 8,\n paddingLeft: opts.paddingLeft ?? 16,\n paddingRight: opts.paddingRight ?? 16,\n },\n});\n","import type { EmailDocument } from \"../core/types\";\nimport { templateRegistry, type TemplateDefinition } from \"./registry\";\nimport { newsletterEditorial } from \"../themes/defaultThemes\";\nimport {\n mod,\n text,\n image,\n button,\n spacer,\n divider,\n heading,\n muted,\n eyebrow,\n PLACEHOLDER,\n} from \"../modules/helpers\";\n\nconst def: TemplateDefinition = {\n id: \"weekly-newsletter\",\n name: \"The Weekly Digest\",\n category: \"newsletter\",\n description:\n \"Editorial weekly newsletter with masthead, in-this-issue table of contents, three article summaries, and a footer.\",\n tags: [\"newsletter\", \"editorial\", \"weekly\", \"publishing\"],\n thumbnail: \"https://placehold.co/600x800/F5F1EA/1F2937?text=The+Weekly\",\n build: (): EmailDocument => ({\n version: \"1.0\",\n meta: {\n name: \"The Weekly Digest — Issue 42\",\n previewText: \"This week: AI in the newsroom, three reads, and a recipe.\",\n },\n theme: newsletterEditorial,\n settings: {\n width: 600,\n backgroundColor: \"{colors.background}\",\n contentBackgroundColor: \"{colors.surface}\",\n },\n modules: [\n mod(\"header.masthead\", \"Masthead\", [\n text(\"THE WEEKLY\", {\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 32,\n fontWeight: \"bold\",\n letterSpacing: 6,\n paddingTop: 32,\n paddingBottom: 4,\n }),\n muted(\"Issue 42 · April 30, 2026\", { align: \"center\", paddingBottom: 24 }),\n divider({ paddingTop: 0, paddingBottom: 0 }),\n ]),\n mod(\"content.article\", \"Lead Story\", [\n eyebrow(\"LEAD STORY\", { paddingTop: 24 }),\n heading(\"AI Comes to the Newsroom — and It's Helping\", {\n fontSize: 28,\n paddingTop: 4,\n paddingBottom: 12,\n }),\n image(PLACEHOLDER(560, 320, \"Lead+Story\"), \"Newsroom\", { width: 560 }),\n text(\n \"A new generation of editorial assistants is changing how stories get written, fact-checked and published. Here's what we found in three newsrooms.\",\n { paddingTop: 16, paddingBottom: 12 }\n ),\n text(\"Read the full piece →\", {\n color: \"{colors.primary}\",\n fontWeight: \"bold\",\n link: \"#\",\n paddingBottom: 8,\n }),\n ]),\n mod(\"content.three_reads\", \"Three More Reads\", [\n eyebrow(\"ALSO THIS WEEK\", { paddingTop: 16 }),\n heading(\"Three more reads\", { paddingBottom: 12 }),\n text(\"01 · The hidden cost of free tier APIs\", {\n fontWeight: \"bold\",\n link: \"#\",\n paddingTop: 4,\n paddingBottom: 4,\n }),\n muted(\"How startups are quietly burning runway on metered cloud calls.\", {\n paddingBottom: 12,\n }),\n divider({ paddingTop: 4, paddingBottom: 4 }),\n text(\"02 · A field guide to product-led onboarding\", {\n fontWeight: \"bold\",\n link: \"#\",\n paddingBottom: 4,\n }),\n muted(\"Stop sending welcome emails. Start designing the first 5 minutes.\", {\n paddingBottom: 12,\n }),\n divider({ paddingTop: 4, paddingBottom: 4 }),\n text(\"03 · Inside the new Madrid co-working scene\", {\n fontWeight: \"bold\",\n link: \"#\",\n paddingBottom: 4,\n }),\n muted(\"Why founders are leaving Lisbon for Spain's quiet capital.\", {\n paddingBottom: 16,\n }),\n ]),\n mod(\"cta.subscribe_share\", \"Forward to a friend\", [\n divider({ paddingTop: 8, paddingBottom: 8 }),\n text(\"Liked this? Forward it to a friend.\", {\n align: \"center\",\n paddingTop: 16,\n paddingBottom: 12,\n }),\n button(\"Share The Weekly\", \"#\"),\n spacer(16),\n ]),\n mod(\n \"footer.simple\",\n \"Footer\",\n [\n muted(\"© 2026 The Weekly · 350 Madison Ave · NY 10017\", {\n align: \"center\",\n paddingTop: 16,\n }),\n muted(\"Manage preferences · Unsubscribe\", {\n align: \"center\",\n paddingTop: 4,\n paddingBottom: 24,\n link: \"#\",\n }),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n ],\n }),\n};\n\ntemplateRegistry.register(def);\nexport default def;\n","import type { EmailDocument } from \"../core/types\";\nimport { templateRegistry, type TemplateDefinition } from \"./registry\";\nimport { ecommercePromo } from \"../themes/defaultThemes\";\nimport {\n mod,\n text,\n spacer,\n button,\n productGrid,\n product,\n PLACEHOLDER,\n muted,\n} from \"../modules/helpers\";\n\nconst def: TemplateDefinition = {\n id: \"flash-sale\",\n name: \"Flash Sale — 24h\",\n category: \"ecommerce\",\n description:\n \"Urgency-driven 24-hour flash sale with countdown headline, three featured products with old/final prices, and a closing CTA.\",\n tags: [\"ecommerce\", \"sale\", \"promo\", \"discount\", \"urgency\"],\n thumbnail: \"https://placehold.co/600x800/EA580C/FFFFFF?text=FLASH+SALE\",\n build: (): EmailDocument => ({\n version: \"1.0\",\n meta: {\n name: \"Flash Sale — 24h only\",\n previewText: \"Up to 50% off — ends midnight tonight.\",\n },\n theme: ecommercePromo,\n settings: {\n width: 600,\n backgroundColor: \"{colors.background}\",\n contentBackgroundColor: \"{colors.surface}\",\n },\n modules: [\n mod(\n \"hero.flash\",\n \"Flash hero\",\n [\n text(\"⏰ FLASH SALE — ENDS IN 24H\", {\n color: \"{colors.buttonText}\",\n align: \"center\",\n fontWeight: \"bold\",\n letterSpacing: 3,\n paddingTop: 24,\n paddingBottom: 8,\n }),\n text(\"Up to 50% off everything\", {\n color: \"{colors.buttonText}\",\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 32,\n fontWeight: \"bold\",\n paddingBottom: 16,\n }),\n button(\"Shop the sale\", \"#\", {\n backgroundColor: \"{colors.surface}\",\n color: \"{colors.primary}\",\n }),\n spacer(24),\n ],\n { backgroundColor: \"{colors.primary}\", paddingTop: 0, paddingBottom: 0 }\n ),\n mod(\"ecom.featured_grid\", \"Featured products\", [\n text(\"Today's picks\", {\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 24,\n fontWeight: \"bold\",\n paddingTop: 24,\n paddingBottom: 16,\n }),\n productGrid(\n [\n product({\n name: \"Linen Tote Bag\",\n image: PLACEHOLDER(400, 400, \"Tote\"),\n oldPrice: \"$59\",\n finalPrice: \"$29\",\n }),\n product({\n name: \"Ceramic Mug Set\",\n image: PLACEHOLDER(400, 400, \"Mug+Set\"),\n oldPrice: \"$48\",\n finalPrice: \"$24\",\n }),\n product({\n name: \"Brass Desk Lamp\",\n image: PLACEHOLDER(400, 400, \"Lamp\"),\n oldPrice: \"$159\",\n finalPrice: \"$79\",\n }),\n ],\n { columns: 3, showOldPrice: true, buttonLabel: \"Add to bag\" }\n ),\n ]),\n mod(\"cta.urgency\", \"Final CTA\", [\n text(\"Don't sleep on it — this ends at midnight.\", {\n align: \"center\",\n fontWeight: \"bold\",\n paddingTop: 16,\n paddingBottom: 12,\n }),\n button(\"Shop now\", \"#\"),\n spacer(24),\n ]),\n mod(\n \"footer.simple\",\n \"Footer\",\n [\n muted(\"© 2026 Acme Co · Unsubscribe · Manage preferences\", {\n align: \"center\",\n paddingTop: 16,\n paddingBottom: 24,\n link: \"#\",\n }),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n ],\n }),\n};\n\ntemplateRegistry.register(def);\nexport default def;\n","import type { EmailDocument } from \"../core/types\";\nimport { templateRegistry, type TemplateDefinition } from \"./registry\";\nimport { greenEco } from \"../themes/defaultThemes\";\nimport {\n mod,\n text,\n spacer,\n button,\n productGrid,\n product,\n PLACEHOLDER,\n heading,\n muted,\n divider,\n} from \"../modules/helpers\";\n\nconst def: TemplateDefinition = {\n id: \"abandoned-cart\",\n name: \"Abandoned Cart Recovery\",\n category: \"abandoned_cart\",\n description:\n \"Friendly reminder showing items left in the cart, a discount nudge, and a return-to-cart button. For automated cart-recovery flows.\",\n tags: [\"abandoned-cart\", \"recovery\", \"automation\", \"ecommerce\"],\n thumbnail: \"https://placehold.co/600x800/F5F1EA/2C2928?text=Cart+Reminder\",\n build: (): EmailDocument => ({\n version: \"1.0\",\n meta: {\n name: \"You left something behind\",\n previewText: \"Your cart is waiting — and we saved your spot.\",\n },\n theme: greenEco,\n settings: {\n width: 600,\n backgroundColor: \"{colors.background}\",\n contentBackgroundColor: \"{colors.surface}\",\n },\n modules: [\n mod(\"header.logo\", \"Logo\", [\n text(\"ACME\", {\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 22,\n fontWeight: \"bold\",\n letterSpacing: 4,\n paddingTop: 24,\n paddingBottom: 24,\n }),\n ]),\n mod(\"hero.text\", \"Headline\", [\n heading(\"You left something behind\", {\n align: \"center\",\n fontSize: 28,\n paddingTop: 16,\n paddingBottom: 8,\n }),\n muted(\"We saved your bag. Pick up right where you left off.\", {\n align: \"center\",\n paddingBottom: 16,\n }),\n ]),\n mod(\"ecom.cart_items\", \"Cart items\", [\n productGrid(\n [\n product({\n name: \"Linen Tote Bag\",\n image: PLACEHOLDER(400, 400, \"Tote\"),\n oldPrice: \"$59\",\n finalPrice: \"$39\",\n description: \"Heavyweight natural linen, made in Portugal.\",\n }),\n product({\n name: \"Cast Iron Skillet\",\n image: PLACEHOLDER(400, 400, \"Skillet\"),\n finalPrice: \"$89\",\n description: \"Pre-seasoned, lifetime guarantee.\",\n }),\n ],\n { columns: 1, showOldPrice: true, showDescription: true, buttonLabel: \"Return to cart\" }\n ),\n ]),\n mod(\"cta.discount\", \"Discount nudge\", [\n divider({ paddingTop: 8, paddingBottom: 16 }),\n text(\"Here's 10% off to seal the deal\", {\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 22,\n fontWeight: \"bold\",\n paddingBottom: 4,\n }),\n text(\"COMEBACK10\", {\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 28,\n fontWeight: \"bold\",\n color: \"{colors.primary}\",\n letterSpacing: 4,\n paddingBottom: 16,\n }),\n button(\"Complete your order\"),\n spacer(24),\n ]),\n mod(\n \"footer.simple\",\n \"Footer\",\n [\n muted(\"Questions? hello@acme.shop\", {\n align: \"center\",\n paddingTop: 16,\n }),\n muted(\"© 2026 Acme · Unsubscribe\", {\n align: \"center\",\n paddingTop: 4,\n paddingBottom: 24,\n link: \"#\",\n }),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n ],\n }),\n};\n\ntemplateRegistry.register(def);\nexport default def;\n","import type { EmailDocument } from \"../core/types\";\nimport { templateRegistry, type TemplateDefinition } from \"./registry\";\nimport { luxuryBlack } from \"../themes/defaultThemes\";\nimport {\n mod,\n text,\n spacer,\n button,\n image,\n productGrid,\n product,\n PLACEHOLDER,\n heading,\n muted,\n} from \"../modules/helpers\";\n\nconst def: TemplateDefinition = {\n id: \"product-launch\",\n name: \"Product Launch — Drop\",\n category: \"product_launch\",\n description:\n \"Bold full-bleed product launch announcement: hero image, big headline, three new products, and an early-access CTA.\",\n tags: [\"launch\", \"drop\", \"new-arrivals\", \"ecommerce\"],\n thumbnail: \"https://placehold.co/600x800/000000/D4AF37?text=NEW+DROP\",\n build: (): EmailDocument => ({\n version: \"1.0\",\n meta: {\n name: \"AUREX 02 — New Drop\",\n previewText: \"The new collection lands today. Limited stock.\",\n },\n theme: luxuryBlack,\n settings: {\n width: 600,\n backgroundColor: \"{colors.background}\",\n contentBackgroundColor: \"{colors.surface}\",\n },\n modules: [\n mod(\n \"hero.full_bleed\",\n \"Full-bleed hero\",\n [\n image(PLACEHOLDER(600, 700, \"AUREX+02\"), \"AUREX 02 hero\", {\n width: 600,\n paddingTop: 0,\n paddingBottom: 0,\n }),\n text(\"AUREX 02\", {\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 40,\n fontWeight: \"bold\",\n color: \"{colors.primary}\",\n letterSpacing: 6,\n paddingTop: 32,\n paddingBottom: 8,\n }),\n text(\"Pure performance. Limited release.\", {\n align: \"center\",\n color: \"{colors.text}\",\n paddingBottom: 24,\n }),\n button(\"Shop the drop\", \"#\"),\n spacer(40),\n ],\n { backgroundColor: \"{colors.surface}\", paddingTop: 0, paddingBottom: 0 }\n ),\n mod(\"ecom.collection\", \"The Collection\", [\n muted(\"THE COLLECTION\", {\n align: \"center\",\n letterSpacing: 4,\n paddingTop: 24,\n paddingBottom: 4,\n }),\n heading(\"Meet the line-up\", {\n align: \"center\",\n fontSize: 26,\n paddingBottom: 16,\n }),\n productGrid(\n [\n product({\n name: \"AUREX 02 — Carbon\",\n image: PLACEHOLDER(400, 400, \"Carbon\"),\n finalPrice: \"$329\",\n }),\n product({\n name: \"AUREX 02 — Sand\",\n image: PLACEHOLDER(400, 400, \"Sand\"),\n finalPrice: \"$329\",\n }),\n product({\n name: \"AUREX 02 — Sage\",\n image: PLACEHOLDER(400, 400, \"Sage\"),\n finalPrice: \"$329\",\n }),\n ],\n { columns: 3, showOldPrice: false, buttonLabel: \"View\" }\n ),\n ]),\n mod(\n \"cta.early_access\",\n \"Early access\",\n [\n text(\"Members get 24h early access\", {\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 22,\n fontWeight: \"bold\",\n color: \"{colors.text}\",\n paddingTop: 32,\n paddingBottom: 16,\n }),\n button(\"Become a member\", \"#\"),\n spacer(40),\n ],\n { backgroundColor: \"{colors.surface}\", paddingTop: 0, paddingBottom: 0 }\n ),\n mod(\n \"footer.brand\",\n \"Footer\",\n [\n muted(\"AUREX · Designed in Berlin · Made in Italy\", {\n align: \"center\",\n paddingTop: 16,\n }),\n muted(\"Manage preferences · Unsubscribe\", {\n align: \"center\",\n paddingTop: 4,\n paddingBottom: 24,\n link: \"#\",\n }),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n ],\n }),\n};\n\ntemplateRegistry.register(def);\nexport default def;\n","import type { EmailDocument } from \"../core/types\";\nimport { templateRegistry, type TemplateDefinition } from \"./registry\";\nimport { minimalSaaS } from \"../themes/defaultThemes\";\nimport {\n mod,\n text,\n spacer,\n button,\n divider,\n heading,\n muted,\n PLACEHOLDER,\n image,\n} from \"../modules/helpers\";\n\nconst def: TemplateDefinition = {\n id: \"welcome-onboarding\",\n name: \"SaaS Welcome & Onboarding\",\n category: \"onboarding\",\n description:\n \"First-touch SaaS welcome with a personal note, a 3-step getting-started checklist, and a CTA to the app.\",\n tags: [\"welcome\", \"onboarding\", \"saas\", \"checklist\"],\n thumbnail: \"https://placehold.co/600x800/F4F5F7/2563EB?text=Welcome\",\n build: (): EmailDocument => ({\n version: \"1.0\",\n meta: {\n name: \"Welcome to Acme\",\n previewText: \"Three quick steps to get the most out of Acme.\",\n },\n theme: minimalSaaS,\n settings: {\n width: 600,\n backgroundColor: \"{colors.background}\",\n contentBackgroundColor: \"{colors.surface}\",\n },\n modules: [\n mod(\"header.logo\", \"Logo\", [\n image(PLACEHOLDER(120, 40, \"ACME\"), \"Acme\", { width: 120, paddingTop: 24 }),\n ]),\n mod(\"hero.welcome\", \"Welcome\", [\n heading(\"Welcome aboard, friend 👋\", {\n align: \"center\",\n fontSize: 28,\n paddingTop: 8,\n paddingBottom: 8,\n }),\n text(\n \"I'm Maya, the founder of Acme. Thanks for signing up — I wanted to send you a quick note (and a 3-step checklist) so you get value fast.\",\n { align: \"center\", paddingBottom: 24 }\n ),\n ]),\n mod(\"content.checklist\", \"Checklist\", [\n text(\"✅ 1. Connect your data\", { fontWeight: \"bold\", paddingTop: 8, paddingBottom: 4 }),\n muted(\"Hook up Stripe, HubSpot or Salesforce in 30 seconds.\", { paddingBottom: 12 }),\n divider({ paddingTop: 4, paddingBottom: 4 }),\n text(\"⚡ 2. Run your first report\", { fontWeight: \"bold\", paddingTop: 4, paddingBottom: 4 }),\n muted(\"Pick a template, click Run, watch the magic.\", { paddingBottom: 12 }),\n divider({ paddingTop: 4, paddingBottom: 4 }),\n text(\"👯 3. Invite a teammate\", { fontWeight: \"bold\", paddingTop: 4, paddingBottom: 4 }),\n muted(\"Acme is more fun (and useful) with your team.\", { paddingBottom: 16 }),\n ]),\n mod(\"cta.app\", \"Open the app\", [\n button(\"Open Acme\", \"#\"),\n spacer(8),\n muted(\"Or reply to this email — a real human will read it.\", { align: \"center\", paddingBottom: 24 }),\n ]),\n mod(\n \"footer.simple\",\n \"Footer\",\n [\n muted(\"Acme, Inc · 100 Market St · San Francisco, CA\", {\n align: \"center\",\n paddingTop: 16,\n }),\n muted(\"Manage notifications · Unsubscribe\", {\n align: \"center\",\n paddingTop: 4,\n paddingBottom: 24,\n link: \"#\",\n }),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n ],\n }),\n};\n\ntemplateRegistry.register(def);\nexport default def;\n","import type { EmailDocument } from \"../core/types\";\nimport { templateRegistry, type TemplateDefinition } from \"./registry\";\nimport { newsletterEditorial } from \"../themes/defaultThemes\";\nimport {\n mod,\n text,\n spacer,\n button,\n image,\n divider,\n heading,\n muted,\n PLACEHOLDER,\n} from \"../modules/helpers\";\n\nconst def: TemplateDefinition = {\n id: \"event-invite\",\n name: \"Event Invite\",\n category: \"event\",\n description:\n \"Invite to a live event with a header image, date / time / location card, agenda highlights, and an RSVP button.\",\n tags: [\"event\", \"invite\", \"rsvp\", \"conference\", \"meetup\"],\n thumbnail: \"https://placehold.co/600x800/111827/FAFAF9?text=You're+Invited\",\n build: (): EmailDocument => ({\n version: \"1.0\",\n meta: {\n name: \"You're invited: Acme Summit 2026\",\n previewText: \"Join us June 12 in Brooklyn for talks, food and a rooftop after-party.\",\n },\n theme: newsletterEditorial,\n settings: {\n width: 600,\n backgroundColor: \"{colors.background}\",\n contentBackgroundColor: \"{colors.surface}\",\n },\n modules: [\n mod(\"header.logo\", \"Logo\", [\n text(\"ACME SUMMIT\", {\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 18,\n fontWeight: \"bold\",\n letterSpacing: 6,\n paddingTop: 24,\n paddingBottom: 16,\n }),\n ]),\n mod(\"hero.event\", \"Event hero\", [\n image(PLACEHOLDER(600, 320, \"Acme+Summit\"), \"Acme Summit\", {\n width: 600,\n paddingTop: 0,\n paddingBottom: 16,\n }),\n heading(\"You're invited.\", {\n align: \"center\",\n fontSize: 32,\n paddingTop: 8,\n paddingBottom: 4,\n }),\n muted(\"A one-day gathering for builders. Brooklyn, NY.\", {\n align: \"center\",\n paddingBottom: 24,\n }),\n ]),\n mod(\n \"content.event_card\",\n \"Event details\",\n [\n text(\"📅 Friday, June 12, 2026\", {\n align: \"center\",\n fontWeight: \"bold\",\n paddingTop: 24,\n paddingBottom: 4,\n }),\n text(\"⏰ 9:00 AM — 6:00 PM\", { align: \"center\", paddingBottom: 4 }),\n text(\"📍 The Invisible Dog · 51 Bergen St, Brooklyn\", {\n align: \"center\",\n paddingBottom: 16,\n }),\n button(\"RSVP — free\", \"#\"),\n spacer(24),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n mod(\"content.agenda\", \"Agenda\", [\n divider({ paddingTop: 16, paddingBottom: 16 }),\n eyebrowText(\"AGENDA HIGHLIGHTS\"),\n agendaRow(\"9:30\", \"Opening keynote — Maya Chen, Acme\"),\n agendaRow(\"11:00\", \"Workshop: shipping AI features users actually want\"),\n agendaRow(\"13:00\", \"Lunch + open conversations\"),\n agendaRow(\"15:30\", \"Panel: building durable companies\"),\n agendaRow(\"18:00\", \"Rooftop after-party\"),\n spacer(16),\n ]),\n mod(\n \"footer.simple\",\n \"Footer\",\n [\n muted(\"Acme, Inc · 100 Market St · San Francisco, CA\", {\n align: \"center\",\n paddingTop: 16,\n }),\n muted(\"Update preferences · Unsubscribe\", {\n align: \"center\",\n paddingTop: 4,\n paddingBottom: 24,\n link: \"#\",\n }),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n ],\n }),\n};\n\nfunction eyebrowText(s: string) {\n return text(s, {\n fontFamily: \"{fonts.button}\",\n color: \"{colors.muted}\",\n fontSize: 11,\n fontWeight: \"bold\",\n letterSpacing: 3,\n paddingBottom: 12,\n });\n}\n\nfunction agendaRow(time: string, label: string) {\n return text(`<b>${time}</b> · ${label}`, {\n paddingTop: 6,\n paddingBottom: 6,\n });\n}\n\ntemplateRegistry.register(def);\nexport default def;\n","import type { EmailDocument } from \"../core/types\";\nimport { templateRegistry, type TemplateDefinition } from \"./registry\";\nimport { minimalSaaS } from \"../themes/defaultThemes\";\nimport {\n mod,\n text,\n spacer,\n button,\n divider,\n heading,\n muted,\n} from \"../modules/helpers\";\n\nconst def: TemplateDefinition = {\n id: \"order-receipt\",\n name: \"Order Receipt\",\n category: \"transactional\",\n description:\n \"Transactional order confirmation with order number, an itemized table, totals, shipping address and a help footer.\",\n tags: [\"transactional\", \"receipt\", \"order\", \"confirmation\"],\n thumbnail: \"https://placehold.co/600x800/F4F5F7/0F172A?text=Order+%23A12345\",\n build: (): EmailDocument => ({\n version: \"1.0\",\n meta: {\n name: \"Your order #A12345 is confirmed\",\n previewText: \"Thanks for your order! Here's your receipt.\",\n },\n theme: minimalSaaS,\n settings: {\n width: 600,\n backgroundColor: \"{colors.background}\",\n contentBackgroundColor: \"{colors.surface}\",\n },\n modules: [\n mod(\"header.logo\", \"Logo\", [\n text(\"ACME\", {\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 22,\n fontWeight: \"bold\",\n letterSpacing: 4,\n paddingTop: 24,\n paddingBottom: 24,\n }),\n ]),\n mod(\"hero.confirmation\", \"Confirmation\", [\n heading(\"Thanks, your order is confirmed\", {\n align: \"center\",\n fontSize: 26,\n paddingTop: 8,\n paddingBottom: 4,\n }),\n muted(\"Order #A12345 · placed April 30, 2026\", {\n align: \"center\",\n paddingBottom: 24,\n }),\n ]),\n mod(\"tx.items\", \"Items\", [\n text(\"ITEMS\", {\n fontSize: 11,\n letterSpacing: 3,\n fontWeight: \"bold\",\n color: \"{colors.muted}\",\n paddingTop: 8,\n paddingBottom: 12,\n }),\n text(\"Linen Tote Bag · Natural · Qty 1\", {\n fontWeight: \"bold\",\n paddingBottom: 4,\n }),\n muted(\"$39.00\", { paddingBottom: 12 }),\n divider({ paddingTop: 4, paddingBottom: 4 }),\n text(\"Ceramic Mug · Sand · Qty 2\", { fontWeight: \"bold\", paddingBottom: 4 }),\n muted(\"$48.00\", { paddingBottom: 16 }),\n divider({ paddingTop: 8, paddingBottom: 12 }),\n text(\"Subtotal · $87.00\", { align: \"right\", paddingBottom: 4 }),\n text(\"Shipping · $9.00\", { align: \"right\", paddingBottom: 4 }),\n text(\"<b>Total · $96.00</b>\", {\n align: \"right\",\n fontSize: 18,\n paddingBottom: 16,\n }),\n ]),\n mod(\n \"tx.shipping\",\n \"Shipping address\",\n [\n text(\"SHIPPING TO\", {\n fontSize: 11,\n letterSpacing: 3,\n fontWeight: \"bold\",\n color: \"{colors.muted}\",\n paddingTop: 16,\n paddingBottom: 8,\n }),\n text(\"Alex Rada<br/>350 Madison Ave<br/>New York, NY 10017\", {\n paddingBottom: 16,\n }),\n button(\"Track shipment\", \"#\"),\n spacer(16),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n mod(\n \"footer.help\",\n \"Help\",\n [\n muted(\"Questions about your order? help@acme.shop\", {\n align: \"center\",\n paddingTop: 16,\n }),\n muted(\"© 2026 Acme · Privacy\", {\n align: \"center\",\n paddingTop: 4,\n paddingBottom: 24,\n link: \"#\",\n }),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n ],\n }),\n};\n\ntemplateRegistry.register(def);\nexport default def;\n","import type { EmailDocument } from \"../core/types\";\nimport { templateRegistry, type TemplateDefinition } from \"./registry\";\nimport { newsletterEditorial } from \"../themes/defaultThemes\";\nimport {\n mod,\n text,\n spacer,\n image,\n divider,\n heading,\n muted,\n PLACEHOLDER,\n} from \"../modules/helpers\";\n\nconst def: TemplateDefinition = {\n id: \"blog-digest\",\n name: \"Blog / Publishing Digest\",\n category: \"publishing\",\n description:\n \"Editorial digest of three blog posts: each with a thumbnail, title, dek and read-link. Best for media and creators.\",\n tags: [\"blog\", \"digest\", \"publishing\", \"media\"],\n thumbnail: \"https://placehold.co/600x800/FAFAF9/111827?text=Blog+Digest\",\n build: (): EmailDocument => ({\n version: \"1.0\",\n meta: {\n name: \"This week on the blog\",\n previewText: \"Three new pieces — including our deep dive on micro-SaaS in 2026.\",\n },\n theme: newsletterEditorial,\n settings: {\n width: 600,\n backgroundColor: \"{colors.background}\",\n contentBackgroundColor: \"{colors.surface}\",\n },\n modules: [\n mod(\"header.publication\", \"Publication header\", [\n text(\"THE LEDGER\", {\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 22,\n fontWeight: \"bold\",\n letterSpacing: 6,\n paddingTop: 32,\n paddingBottom: 4,\n }),\n muted(\"Notes on building, weekly\", { align: \"center\", paddingBottom: 24 }),\n divider({ paddingTop: 0, paddingBottom: 0 }),\n ]),\n post(\n \"Micro-SaaS in 2026: smaller, sharper, more profitable\",\n \"Why the next wave of indie founders is winning by going narrower than you think.\",\n \"Maya Chen · 8 min read\",\n PLACEHOLDER(560, 280, \"Post+1\")\n ),\n post(\n \"Stop A/B testing your homepage\",\n \"An evidence-based case for spending that energy on your activation flow instead.\",\n \"Jordan Lee · 6 min read\",\n PLACEHOLDER(560, 280, \"Post+2\")\n ),\n post(\n \"The five-line founder check-in\",\n \"A weekly journaling pattern that keeps the team aligned and the founder sane.\",\n \"Sam Park · 4 min read\",\n PLACEHOLDER(560, 280, \"Post+3\")\n ),\n mod(\n \"footer.simple\",\n \"Footer\",\n [\n muted(\"The Ledger · Published Tuesdays\", {\n align: \"center\",\n paddingTop: 16,\n }),\n muted(\"© 2026 · Manage subscription · Unsubscribe\", {\n align: \"center\",\n paddingTop: 4,\n paddingBottom: 24,\n link: \"#\",\n }),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n ],\n }),\n};\n\nfunction post(title: string, dek: string, byline: string, img: string) {\n return mod(\"content.post\", \"Post\", [\n image(img, title, { width: 560, paddingTop: 24, paddingBottom: 16 }),\n heading(title, { fontSize: 24, paddingBottom: 8 }),\n text(dek, { paddingBottom: 8 }),\n muted(byline, { paddingBottom: 4 }),\n text(\"Read the full post →\", {\n color: \"{colors.primary}\",\n fontWeight: \"bold\",\n link: \"#\",\n paddingTop: 4,\n paddingBottom: 8,\n }),\n spacer(8),\n ]);\n}\n\ntemplateRegistry.register(def);\nexport default def;\n","import { useEffect, useMemo, useState } from \"react\";\nimport { X, Search } from \"lucide-react\";\nimport { useEmailStore } from \"../store/emailStore\";\nimport {\n templateRegistry,\n TEMPLATE_CATEGORY_LABELS,\n type TemplateCategory,\n type TemplateDefinition,\n} from \"../templates\";\n\ninterface Props {\n open: boolean;\n onClose: () => void;\n}\n\nexport function TemplatesModal({ open, onClose }: Props) {\n const loadTemplate = useEmailStore((s) => s.loadTemplate);\n const hasContent = useEmailStore((s) => s.doc.modules.length > 0);\n\n const [category, setCategory] = useState<TemplateCategory | \"all\">(\"all\");\n const [query, setQuery] = useState(\"\");\n\n useEffect(() => {\n if (!open) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [open, onClose]);\n\n const all = useMemo(() => templateRegistry.list(), [open]);\n\n const filtered = useMemo(() => {\n let list = all;\n if (category !== \"all\") list = list.filter((t) => t.category === category);\n if (query.trim()) {\n const q = query.toLowerCase();\n list = list.filter(\n (t) =>\n t.name.toLowerCase().includes(q) ||\n t.description.toLowerCase().includes(q) ||\n (t.tags ?? []).some((tag) => tag.toLowerCase().includes(q))\n );\n }\n return list;\n }, [all, category, query]);\n\n if (!open) return null;\n\n const handlePick = (def: TemplateDefinition) => {\n if (\n hasContent &&\n !window.confirm(\n `Loading \"${def.name}\" will replace your current email. Continue?`\n )\n ) {\n return;\n }\n loadTemplate(def);\n onClose();\n };\n\n const categories: Array<{ key: TemplateCategory | \"all\"; label: string }> = [\n { key: \"all\", label: \"All templates\" },\n ...(Object.entries(TEMPLATE_CATEGORY_LABELS) as Array<\n [TemplateCategory, string]\n >).map(([key, label]) => ({ key, label })),\n ];\n\n return (\n <div className=\"fixed inset-0 z-50 flex bg-black/60 backdrop-blur-sm\">\n <div className=\"m-auto flex h-[92vh] w-[96vw] max-w-350 flex-col overflow-hidden rounded-2xl bg-white shadow-2xl\">\n {/* Header */}\n <div className=\"flex items-center justify-between border-b border-neutral-200 px-6 py-4\">\n <div>\n <h2 className=\"text-lg font-semibold text-neutral-900\">\n Start from a template\n </h2>\n <p className=\"text-sm text-neutral-500\">\n Pick a fully-built email and tweak from there.\n </p>\n </div>\n <button\n onClick={onClose}\n className=\"rounded-lg p-2 text-neutral-500 hover:bg-neutral-100 hover:text-neutral-900\"\n aria-label=\"Close\"\n >\n <X size={20} />\n </button>\n </div>\n\n <div className=\"flex flex-1 overflow-hidden\">\n {/* Sidebar */}\n <aside className=\"w-56 shrink-0 overflow-y-auto border-r border-neutral-200 bg-neutral-50 p-3\">\n <div className=\"relative mb-3\">\n <Search\n size={14}\n className=\"pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-neutral-400\"\n />\n <input\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder=\"Search…\"\n className=\"w-full rounded-md border border-neutral-200 bg-white py-1.5 pl-7 pr-2 text-sm outline-none focus:border-neutral-400\"\n />\n </div>\n <ul className=\"space-y-0.5\">\n {categories.map((c) => {\n const active = c.key === category;\n return (\n <li key={c.key}>\n <button\n onClick={() => setCategory(c.key)}\n className={\n \"block w-full rounded-md px-2.5 py-1.5 text-left text-sm transition \" +\n (active\n ? \"bg-neutral-900 text-white\"\n : \"text-neutral-700 hover:bg-neutral-200\")\n }\n >\n {c.label}\n </button>\n </li>\n );\n })}\n </ul>\n </aside>\n\n {/* Grid */}\n <main className=\"flex-1 overflow-y-auto p-6\">\n {filtered.length === 0 ? (\n <div className=\"grid h-full place-items-center text-sm text-neutral-500\">\n No templates match.\n </div>\n ) : (\n <div className=\"grid grid-cols-2 gap-5 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5\">\n {filtered.map((t) => (\n <TemplateCard\n key={t.id}\n def={t}\n onPick={() => handlePick(t)}\n />\n ))}\n </div>\n )}\n </main>\n </div>\n </div>\n </div>\n );\n}\n\nfunction TemplateCard({\n def,\n onPick,\n}: {\n def: TemplateDefinition;\n onPick: () => void;\n}) {\n return (\n <button\n onClick={onPick}\n className=\"group flex flex-col overflow-hidden rounded-xl border border-neutral-200 bg-white text-left transition hover:-translate-y-0.5 hover:border-neutral-400 hover:shadow-lg\"\n >\n <div className=\"aspect-3/4 w-full overflow-hidden bg-neutral-100\">\n {def.thumbnail ? (\n <img\n src={def.thumbnail}\n alt={def.name}\n className=\"h-full w-full object-cover transition group-hover:scale-[1.02]\"\n />\n ) : (\n <div className=\"grid h-full place-items-center text-xs text-neutral-400\">\n No preview\n </div>\n )}\n </div>\n <div className=\"flex flex-col gap-1 p-3\">\n <div className=\"text-xs uppercase tracking-wider text-neutral-500\">\n {TEMPLATE_CATEGORY_LABELS[def.category]}\n </div>\n <div className=\"line-clamp-1 text-sm font-semibold text-neutral-900\">\n {def.name}\n </div>\n <div className=\"line-clamp-2 text-xs text-neutral-500\">\n {def.description}\n </div>\n </div>\n </button>\n );\n}\n","import { useEmailStore } from \"../store/emailStore\";\nimport { Undo2, Redo2, Save, Download, Upload, Eye, FileCode, Monitor, Smartphone, LayoutTemplate, RotateCcw, ChevronDown } from \"lucide-react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { TemplatesModal } from \"./TemplatesModal\";\n\nexport function TopBar() {\n const { doc, updateMeta, undo, redo, past, future, exportJson, importJson, exportHtml, saveToLocalStorage, viewMode, setViewMode, resetDocument } =\n useEmailStore();\n const fileRef = useRef<HTMLInputElement>(null);\n const [previewing, setPreviewing] = useState(false);\n const [templatesOpen, setTemplatesOpen] = useState(false);\n\n const handleReset = () => {\n if (doc.modules.length === 0) return;\n if (window.confirm(\"Reset the editor? Your current email will be cleared.\")) {\n resetDocument();\n }\n };\n\n const downloadFile = (filename: string, content: string, type: string) => {\n const blob = new Blob([content], { type });\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = filename;\n a.click();\n URL.revokeObjectURL(url);\n };\n\n const handleExportHtml = () => {\n const html = exportHtml();\n downloadFile(`${doc.meta.name || \"email\"}.html`, html, \"text/html\");\n };\n\n const handleExportJson = () => {\n downloadFile(`${doc.meta.name || \"email\"}.json`, exportJson(), \"application/json\");\n };\n\n const handleImport = (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n file.text().then((text) => {\n const r = importJson(text);\n if (!r.ok) alert(`Import failed: ${r.error}`);\n });\n e.target.value = \"\";\n };\n\n const handlePreview = () => {\n const html = exportHtml();\n const w = window.open(\"\", \"_blank\");\n if (w) {\n w.document.write(html);\n w.document.close();\n }\n setPreviewing(true);\n setTimeout(() => setPreviewing(false), 600);\n };\n\n return (\n <div className=\"flex items-center h-12 px-4 bg-white border-b border-gray-200 shrink-0\">\n {/* Left: email name */}\n <div className=\"shrink-0 w-48\">\n <input\n className=\"font-medium text-sm px-2 py-1 rounded hover:bg-gray-50 focus:bg-gray-50 outline-none w-full\"\n value={doc.meta.name}\n onChange={(e) => updateMeta({ name: e.target.value })}\n />\n </div>\n\n {/* Center: all action buttons */}\n <div className=\"flex-1 flex items-center justify-center gap-1\">\n <div className=\"inline-flex items-center bg-gray-100 rounded p-0.5 mr-1\">\n <button\n title=\"Desktop preview\"\n onClick={() => setViewMode(\"desktop\")}\n className={`flex items-center gap-1 px-2 py-1 rounded text-xs transition-colors ${\n viewMode === \"desktop\" ? \"bg-white shadow text-gray-900\" : \"text-gray-500 hover:text-gray-700\"\n }`}\n >\n <Monitor size={14} /> Desktop\n </button>\n <button\n title=\"Mobile preview\"\n onClick={() => setViewMode(\"mobile\")}\n className={`flex items-center gap-1 px-2 py-1 rounded text-xs transition-colors ${\n viewMode === \"mobile\" ? \"bg-white shadow text-gray-900\" : \"text-gray-500 hover:text-gray-700\"\n }`}\n >\n <Smartphone size={14} /> Mobile\n </button>\n </div>\n <ToolButton title=\"Browse templates\" onClick={() => setTemplatesOpen(true)}>\n <LayoutTemplate size={16} /> Templates\n </ToolButton>\n <ToolButton title=\"Reset editor\" onClick={handleReset} disabled={doc.modules.length === 0}>\n <RotateCcw size={16} /> Reset\n </ToolButton>\n <Divider />\n <ToolButton title=\"Undo\" onClick={undo} disabled={past.length === 0}>\n <Undo2 size={16} />\n </ToolButton>\n <ToolButton title=\"Redo\" onClick={redo} disabled={future.length === 0}>\n <Redo2 size={16} />\n </ToolButton>\n <Divider />\n <ToolButton title=\"Save draft (local)\" onClick={saveToLocalStorage}>\n <Save size={16} />\n </ToolButton>\n <ToolButton title=\"Preview\" onClick={handlePreview}>\n <Eye size={16} /> {previewing ? \"Opened\" : \"Preview\"}\n </ToolButton>\n </div>\n\n {/* Right: Export dropdown */}\n <div className=\"shrink-0 flex justify-end w-48\">\n <input ref={fileRef} type=\"file\" accept=\".json\" hidden onChange={handleImport} />\n <ExportDropdown\n onImport={() => fileRef.current?.click()}\n onExportJson={handleExportJson}\n onExportHtml={handleExportHtml}\n />\n </div>\n\n <TemplatesModal open={templatesOpen} onClose={() => setTemplatesOpen(false)} />\n </div>\n );\n}\n\n// ---------- Export dropdown ----------\n\nfunction ExportDropdown({\n onImport,\n onExportJson,\n onExportHtml,\n}: {\n onImport: () => void;\n onExportJson: () => void;\n onExportHtml: () => void;\n}) {\n const [open, setOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n // Close when clicking outside the dropdown.\n useEffect(() => {\n if (!open) return;\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false);\n };\n document.addEventListener(\"mousedown\", handler);\n return () => document.removeEventListener(\"mousedown\", handler);\n }, [open]);\n\n return (\n <div ref={ref} className=\"relative\">\n <button\n onClick={() => setOpen((v) => !v)}\n className=\"flex items-center gap-1.5 px-2.5 py-1.5 rounded text-sm text-gray-700 hover:bg-gray-100 border border-gray-200 transition-colors\"\n title=\"Import / Export\"\n >\n <FileCode size={16} />\n Export\n <ChevronDown size={14} className={`transition-transform ${open ? \"rotate-180\" : \"\"}`} />\n </button>\n\n {open && (\n <div className=\"absolute right-0 top-full mt-1 w-48 bg-white border border-gray-200 rounded-lg shadow-lg z-50 py-1 text-sm\">\n <DropdownItem\n icon={<Upload size={14} />}\n label=\"Import JSON\"\n onClick={() => { onImport(); setOpen(false); }}\n />\n <div className=\"mx-2 my-1 border-t border-gray-100\" />\n <DropdownItem\n icon={<Download size={14} />}\n label=\"Export JSON\"\n onClick={() => { onExportJson(); setOpen(false); }}\n />\n <DropdownItem\n icon={<FileCode size={14} />}\n label=\"Export HTML\"\n onClick={() => { onExportHtml(); setOpen(false); }}\n />\n </div>\n )}\n </div>\n );\n}\n\nfunction DropdownItem({\n icon,\n label,\n onClick,\n highlight,\n}: {\n icon: React.ReactNode;\n label: string;\n onClick: () => void;\n highlight?: boolean;\n}) {\n return (\n <button\n onClick={onClick}\n className={`w-full flex items-center gap-2 px-3 py-2 hover:bg-gray-50 transition-colors text-left ${\n highlight ? \"text-blue-600 font-medium\" : \"text-gray-700\"\n }`}\n >\n {icon}\n {label}\n </button>\n );\n}\n\n// ---------- Shared primitives ----------\n\nfunction ToolButton({\n children,\n onClick,\n disabled,\n title,\n primary,\n}: {\n children: React.ReactNode;\n onClick?: () => void;\n disabled?: boolean;\n title?: string;\n primary?: boolean;\n}) {\n return (\n <button\n title={title}\n disabled={disabled}\n onClick={onClick}\n className={`flex items-center gap-1.5 px-2.5 py-1.5 rounded text-sm transition-colors ${\n primary\n ? \"bg-blue-600 text-white hover:bg-blue-700 disabled:bg-gray-300\"\n : \"text-gray-700 hover:bg-gray-100 disabled:text-gray-300 disabled:hover:bg-transparent\"\n }`}\n >\n {children}\n </button>\n );\n}\n\nfunction Divider() {\n return <div className=\"w-px h-5 bg-gray-200 mx-1\" />;\n}\n\n","import type { EmailModule } from \"../core/types\";\n\nexport type ModuleCategory =\n | \"basic\"\n | \"menu\"\n | \"header\"\n | \"content\"\n | \"feature\"\n | \"call_to_action\"\n | \"ecommerce\"\n | \"transactional\"\n | \"social\"\n | \"footer\";\n\nexport interface ModuleDefinition {\n type: string;\n category: ModuleCategory;\n name: string;\n /** Human + AI readable summary of the module's structure, intent and content slots. Used by AI to choose modules when assembling templates. */\n description: string;\n /** Free-form tags to help AI semantic search: e.g. [\"product\", \"grid\", \"ecommerce\", \"3-column\"]. */\n tags?: string[];\n thumbnail?: string;\n /** Returns a fresh module JSON with new ids. */\n create: () => EmailModule;\n}\n\nclass ModuleRegistry {\n private modules = new Map<string, ModuleDefinition>();\n\n register(def: ModuleDefinition) {\n this.modules.set(def.type, def);\n }\n\n get(type: string): ModuleDefinition | undefined {\n return this.modules.get(type);\n }\n\n list(): ModuleDefinition[] {\n return Array.from(this.modules.values());\n }\n\n byCategory(category: ModuleCategory): ModuleDefinition[] {\n return this.list().filter((m) => m.category === category);\n }\n}\n\nexport const moduleRegistry = new ModuleRegistry();\n\nexport const CATEGORY_LABELS: Record<ModuleCategory, string> = {\n basic: \"Basic\",\n menu: \"Menu\",\n header: \"Header\",\n content: \"Content\",\n feature: \"Feature\",\n call_to_action: \"Call to Action\",\n ecommerce: \"Ecommerce\",\n transactional: \"Transactional\",\n social: \"Social\",\n footer: \"Footer\",\n};\n","// Reactive holder for the configured AI provider.\n//\n// The editor's AI chat panel only appears when a provider has been wired up\n// (via the `aiProvider` prop, the `aiAssistantPlugin`, or `builder.setAIProvider`).\n// Because providers are configured imperatively, this small reactive store lets\n// React components show/hide the panel the moment a provider is (un)set.\n\nimport type { AIProvider } from \"../core/aiActions\";\n\ntype Listener = () => void;\n\nlet provider: AIProvider | null = null;\nconst listeners = new Set<Listener>();\nlet version = 0;\n\nfunction emit() {\n version += 1;\n for (const l of listeners) l();\n}\n\n/** Set (or clear) the active AI provider. Notifies subscribers. */\nexport function setAIProvider(next: AIProvider | null) {\n if (provider === next) return;\n provider = next;\n emit();\n}\n\n/** The active AI provider, or null when AI is not configured. */\nexport function getAIProvider(): AIProvider | null {\n return provider;\n}\n\n/** Subscribe to provider changes (for `useSyncExternalStore`). */\nexport const subscribeAIProvider = (listener: Listener): (() => void) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n};\n\n/** Monotonic version; changes whenever the provider is set or cleared. */\nexport const getAIProviderVersion = (): number => version;\n","// Module catalog for the AI backend.\n//\n// The backend must only ever produce modules the editor can actually render.\n// To guarantee that, the client sends a *catalog* of every available module —\n// all built-in modules — including one concrete `sample` of each module's JSON.\n// The model picks module `type`s from this catalog and the backend assembles\n// the email from the real samples, so the output is always valid and visible.\n\nimport type { EmailModule } from \"../core/types\";\nimport { moduleRegistry } from \"../modules/registry\";\n\nexport interface CatalogEntry {\n type: string;\n category: string;\n name: string;\n description: string;\n tags: string[];\n source: \"module\";\n /** A concrete, renderable instance of the module (ids included). */\n sample: EmailModule;\n}\n\n/**\n * Build the catalog sent to the AI backend.\n */\nexport function buildCatalog(): CatalogEntry[] {\n return moduleRegistry.list().map((def) => ({\n type: def.type,\n category: def.category,\n name: def.name,\n description: def.description,\n tags: def.tags ?? [],\n source: \"module\" as const,\n sample: def.create(),\n }));\n}\n","// AI action interface. AI must edit JSON, not HTML.\nimport type { EmailDocument, EmailModule, Theme } from \"../core/types\";\nimport { documentSchema } from \"../core/validation\";\n\nexport type AIAction =\n | { type: \"update_meta\"; patch: Partial<EmailDocument[\"meta\"]> }\n | { type: \"update_settings\"; patch: Partial<EmailDocument[\"settings\"]> }\n | { type: \"apply_theme\"; theme: Theme }\n | { type: \"insert_module\"; index?: number; module: EmailModule }\n | { type: \"delete_module\"; moduleId: string }\n | { type: \"update_module\"; moduleId: string; patch: Partial<EmailModule> }\n | {\n type: \"update_element\";\n moduleId: string;\n elementId: string;\n patch: Record<string, unknown>;\n };\n\nexport interface AIRequest {\n task:\n | \"create_email\"\n | \"rewrite_text\"\n | \"generate_subject\"\n | \"generate_preview\"\n | \"translate\"\n | \"adapt_tone\"\n | \"apply_theme\";\n document?: EmailDocument;\n instruction?: string;\n context?: Record<string, unknown>;\n}\n\nexport interface AIResponse {\n actions?: AIAction[];\n document?: EmailDocument;\n text?: string;\n}\n\nexport interface AIProvider {\n generate(req: AIRequest): Promise<AIResponse>;\n}\n\nexport function applyAIActions(\n doc: EmailDocument,\n actions: AIAction[]\n): EmailDocument {\n let next = doc;\n for (const a of actions) {\n next = applyAIAction(next, a);\n }\n return next;\n}\n\nfunction applyAIAction(doc: EmailDocument, action: AIAction): EmailDocument {\n switch (action.type) {\n case \"update_meta\":\n return { ...doc, meta: { ...doc.meta, ...action.patch } };\n case \"update_settings\":\n return { ...doc, settings: { ...doc.settings, ...action.patch } };\n case \"apply_theme\":\n return { ...doc, theme: action.theme };\n case \"insert_module\": {\n const idx = action.index ?? doc.modules.length;\n const modules = [...doc.modules];\n modules.splice(idx, 0, action.module);\n return { ...doc, modules };\n }\n case \"delete_module\":\n return { ...doc, modules: doc.modules.filter((m) => m.id !== action.moduleId) };\n case \"update_module\":\n return {\n ...doc,\n modules: doc.modules.map((m) =>\n m.id === action.moduleId ? { ...m, ...action.patch } : m\n ),\n };\n case \"update_element\":\n return {\n ...doc,\n modules: doc.modules.map((m) => {\n if (m.id !== action.moduleId) return m;\n return {\n ...m,\n children: m.children.map((c) =>\n c.id === action.elementId ? ({ ...c, ...action.patch } as typeof c) : c\n ),\n };\n }),\n };\n }\n}\n\n/** Validate an AI-returned document before applying. */\nexport function validateAIDocument(doc: unknown):\n | { ok: true; document: EmailDocument }\n | { ok: false; error: string } {\n const result = documentSchema.safeParse(doc);\n if (result.success) return { ok: true, document: result.data as EmailDocument };\n return { ok: false, error: result.error.message };\n}\n\n/** Mock AI provider for demos and tests. Returns deterministic patches. */\nexport const mockAIProvider: AIProvider = {\n async generate(req) {\n if (req.task === \"rewrite_text\" && req.instruction) {\n return { text: `[AI rewrite] ${req.instruction}` };\n }\n if (req.task === \"generate_subject\") {\n return { text: \"Your weekly insight is here ✨\" };\n }\n if (req.task === \"generate_preview\") {\n return { text: \"A short summary that nudges readers to open.\" };\n }\n return { actions: [] };\n },\n};\n","// Safely apply an AI response to the current document.\n//\n// Every AI-produced change is funnelled through here so the editor never trusts\n// raw model output: ids are regenerated to avoid collisions, actions are applied\n// with the existing `applyAIActions` reducer, and the final document is validated\n// with the Zod `documentSchema` before it is handed back to the store.\n\nimport type { EmailDocument, EmailModule } from \"../core/types\";\nimport type { AIAction, AIResponse } from \"../core/aiActions\";\nimport { applyAIActions, validateAIDocument } from \"../core/aiActions\";\nimport { uid } from \"../core/utils\";\n\n/** Drop `undefined`-valued keys anywhere in the document via a JSON round-trip.\n *\n * Module helpers leave optional style fields as `undefined`; those keys survive\n * in-memory but fail Zod validation. Serializing removes them so validation is\n * meaningful and the stored document stays clean. */\nfunction sanitize<T>(value: T): T {\n return JSON.parse(JSON.stringify(value)) as T;\n}\n\n/** Deep-clone a module with fresh ids for the module and all its children. */\nfunction withFreshIds(mod: EmailModule): EmailModule {\n const clone = sanitize(mod);\n return {\n ...clone,\n id: uid(\"module\"),\n children: (clone.children ?? []).map((c) => ({ ...c, id: uid(\"el\") })),\n };\n}\n\n/**\n * Regenerate ids on any module the AI wants to insert. This keeps ids unique\n * even when the backend reuses a catalog `sample` (which ships with stable ids).\n */\nfunction normalizeActions(actions: AIAction[]): AIAction[] {\n return actions.map((a) =>\n a.type === \"insert_module\" ? { ...a, module: withFreshIds(a.module) } : a\n );\n}\n\nexport interface ApplyResult {\n document: EmailDocument;\n /** Assistant chat text, if any. */\n text?: string;\n /** Short human summary of what changed, for the chat log. */\n summary: string;\n}\n\n/**\n * Apply an {@link AIResponse} to `doc`. Returns the next document plus a summary,\n * or an error string when the result fails validation.\n */\nexport function applyAIResponse(\n doc: EmailDocument,\n res: AIResponse\n): { ok: true; result: ApplyResult } | { ok: false; error: string } {\n // 1) A full replacement document takes precedence when present.\n if (res.document) {\n const validated = validateAIDocument(sanitize(res.document));\n if (!validated.ok) return { ok: false, error: validated.error };\n return {\n ok: true,\n result: {\n document: validated.document,\n text: res.text,\n summary: \"Replaced the email with a freshly generated document.\",\n },\n };\n }\n\n // 2) Otherwise apply structured actions.\n if (res.actions && res.actions.length > 0) {\n const next = applyAIActions(doc, normalizeActions(res.actions));\n const validated = validateAIDocument(sanitize(next));\n if (!validated.ok) return { ok: false, error: validated.error };\n return {\n ok: true,\n result: {\n document: validated.document,\n text: res.text,\n summary: summarizeActions(res.actions),\n },\n };\n }\n\n // 3) Text-only response (e.g. rewrite suggestions, subject lines).\n return {\n ok: true,\n result: {\n document: doc,\n text: res.text,\n summary: res.text ? \"\" : \"No changes were suggested.\",\n },\n };\n}\n\nfunction summarizeActions(actions: AIAction[]): string {\n const counts: Record<string, number> = {};\n for (const a of actions) counts[a.type] = (counts[a.type] ?? 0) + 1;\n const label: Record<string, string> = {\n insert_module: \"added block\",\n delete_module: \"removed block\",\n update_module: \"updated block\",\n update_element: \"edited content\",\n update_meta: \"updated meta\",\n update_settings: \"updated settings\",\n apply_theme: \"applied theme\",\n };\n const parts = Object.entries(counts).map(([type, n]) => {\n const base = label[type] ?? type;\n return n > 1 ? `${n} ${base}s` : base;\n });\n return parts.length ? `Applied: ${parts.join(\", \")}.` : \"No changes applied.\";\n}\n","import { useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport { Sparkles, Send, Loader2, AlertTriangle } from \"lucide-react\";\nimport { useEmailStore } from \"../store/emailStore\";\nimport type { AIRequest } from \"../core/aiActions\";\nimport { getAIProvider, subscribeAIProvider, getAIProviderVersion } from \"./state\";\nimport { buildCatalog } from \"./catalog\";\nimport { applyAIResponse } from \"./applyResponse\";\n\ninterface ChatMessage {\n id: string;\n role: \"user\" | \"assistant\";\n text: string;\n error?: boolean;\n}\n\nconst SUGGESTIONS = [\n \"Create a welcome email for new subscribers\",\n \"Build a flash sale announcement with a product grid\",\n \"Write a weekly newsletter with a lead story and footer\",\n];\n\n/** Hook: is an AI provider currently configured? Reactive. */\nexport function useAIAvailable(): boolean {\n // Re-render whenever the provider version changes, then read current state.\n useSyncExternalStore(subscribeAIProvider, getAIProviderVersion, getAIProviderVersion);\n return getAIProvider() !== null;\n}\n\nexport function AIChatPanel() {\n const { doc, applyDoc } = useEmailStore();\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [input, setInput] = useState(\"\");\n const [busy, setBusy] = useState(false);\n const listRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n listRef.current?.scrollTo({ top: listRef.current.scrollHeight });\n }, [messages, busy]);\n\n const send = async (prompt: string) => {\n const provider = getAIProvider();\n if (!provider || !prompt.trim() || busy) return;\n const userMsg: ChatMessage = { id: crypto.randomUUID(), role: \"user\", text: prompt };\n setMessages((m) => [...m, userMsg]);\n setInput(\"\");\n setBusy(true);\n\n const req: AIRequest = {\n task: \"create_email\",\n document: doc,\n instruction: prompt,\n context: { catalog: buildCatalog() },\n };\n\n try {\n const res = await provider.generate(req);\n const applied = applyAIResponse(doc, res);\n if (!applied.ok) {\n pushAssistant(`I produced an invalid document and stopped. (${applied.error})`, true);\n } else {\n const { document, text, summary } = applied.result;\n if (document !== doc) applyDoc(document);\n pushAssistant([text, summary].filter(Boolean).join(\"\\n\\n\") || \"Done.\");\n }\n } catch (err) {\n pushAssistant((err as Error).message || \"The AI request failed.\", true);\n } finally {\n setBusy(false);\n }\n };\n\n const pushAssistant = (text: string, error = false) =>\n setMessages((m) => [...m, { id: crypto.randomUUID(), role: \"assistant\", text, error }]);\n\n return (\n <div className=\"flex flex-col h-full\">\n <div className=\"flex items-center gap-2 mb-2\">\n <Sparkles size={16} className=\"text-blue-600\" />\n <h3 className=\"text-xs font-semibold uppercase tracking-wide text-gray-500\">\n AI Assistant\n </h3>\n </div>\n\n <div ref={listRef} className=\"flex-1 overflow-y-auto pr-1 flex flex-col gap-2\">\n {messages.length === 0 && (\n <div className=\"text-xs text-gray-500\">\n <p className=\"mb-2\">\n Describe the email you want and I'll assemble it from the available blocks.\n </p>\n <div className=\"flex flex-col gap-1.5\">\n {SUGGESTIONS.map((s) => (\n <button\n key={s}\n onClick={() => send(s)}\n className=\"text-left text-xs px-2.5 py-2 rounded border border-gray-200 bg-white hover:border-blue-400 hover:bg-blue-50 transition-colors\"\n >\n {s}\n </button>\n ))}\n </div>\n </div>\n )}\n {messages.map((m) => (\n <div\n key={m.id}\n className={`text-xs rounded-lg px-3 py-2 whitespace-pre-wrap ${\n m.role === \"user\"\n ? \"bg-blue-600 text-white self-end max-w-[85%]\"\n : m.error\n ? \"bg-red-50 text-red-700 border border-red-200 self-start max-w-[95%]\"\n : \"bg-gray-100 text-gray-800 self-start max-w-[95%]\"\n }`}\n >\n {m.error && (\n <AlertTriangle size={12} className=\"inline mr-1 -mt-0.5\" aria-hidden />\n )}\n {m.text}\n </div>\n ))}\n {busy && (\n <div className=\"text-xs text-gray-500 flex items-center gap-1.5 self-start\">\n <Loader2 size={12} className=\"animate-spin\" /> Thinking…\n </div>\n )}\n </div>\n\n <form\n className=\"mt-2 flex items-end gap-1.5\"\n onSubmit={(e) => {\n e.preventDefault();\n send(input);\n }}\n >\n <textarea\n value={input}\n onChange={(e) => setInput(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n send(input);\n }\n }}\n rows={2}\n placeholder=\"Ask the AI to build or edit your email…\"\n className=\"flex-1 resize-none text-xs rounded border border-gray-300 px-2 py-1.5 outline-none focus:border-blue-500\"\n />\n <button\n type=\"submit\"\n disabled={busy || !input.trim()}\n title=\"Send\"\n className=\"p-2 rounded bg-blue-600 text-white hover:bg-blue-700 disabled:bg-gray-300\"\n >\n {busy ? <Loader2 size={14} className=\"animate-spin\" /> : <Send size={14} />}\n </button>\n </form>\n </div>\n );\n}\n","import { useState } from \"react\";\nimport { useEmailStore } from \"../store/emailStore\";\nimport { moduleRegistry, CATEGORY_LABELS, type ModuleCategory } from \"../modules/registry\";\nimport { AIChatPanel, useAIAvailable } from \"../ai/AIChatPanel\";\nimport {\n Square,\n Menu,\n LayoutTemplate,\n Type,\n Star,\n MousePointerClick,\n ShoppingCart,\n Receipt,\n Share2,\n AlignVerticalJustifyEnd,\n Palette,\n Layers,\n Sparkles,\n ArrowUp,\n ArrowDown,\n Trash2,\n Copy,\n} from \"lucide-react\";\n\nconst CATEGORIES: { id: ModuleCategory; icon: React.ComponentType<{ size?: number }> }[] = [\n { id: \"basic\", icon: Square },\n { id: \"menu\", icon: Menu },\n { id: \"header\", icon: LayoutTemplate },\n { id: \"content\", icon: Type },\n { id: \"feature\", icon: Star },\n { id: \"call_to_action\", icon: MousePointerClick },\n { id: \"ecommerce\", icon: ShoppingCart },\n { id: \"transactional\", icon: Receipt },\n { id: \"social\", icon: Share2 },\n { id: \"footer\", icon: AlignVerticalJustifyEnd },\n];\n\nexport function LeftSidebar() {\n const [active, setActive] = useState<ModuleCategory | \"themes\" | \"layers\" | \"ai\">(\"layers\");\n const { addModule, themes, applyTheme, doc } = useEmailStore();\n const aiAvailable = useAIAvailable();\n\n return (\n <div className=\"flex h-full bg-white border-r border-gray-200 shrink-0\">\n {/* Category rail */}\n <div className=\"w-16 border-r border-gray-200 flex flex-col items-center py-2 gap-1\">\n {aiAvailable && (\n <>\n <button\n onClick={() => setActive(\"ai\")}\n title=\"AI Assistant\"\n className={`flex flex-col items-center gap-0.5 w-14 py-2 rounded text-[10px] transition-colors ${\n active === \"ai\" ? \"bg-blue-50 text-blue-700\" : \"text-blue-600 hover:bg-blue-50\"\n }`}\n >\n <Sparkles size={20} />\n <span>AI</span>\n </button>\n <div className=\"h-px w-10 bg-gray-200 my-1\" />\n </>\n )}\n <button\n onClick={() => setActive(\"layers\")}\n title=\"Layout overview\"\n className={`flex flex-col items-center gap-0.5 w-14 py-2 rounded text-[10px] transition-colors ${\n active === \"layers\" ? \"bg-blue-50 text-blue-700\" : \"text-gray-600 hover:bg-gray-50\"\n }`}\n >\n <Layers size={20} />\n <span>Layers</span>\n </button>\n <div className=\"h-px w-10 bg-gray-200 my-1\" />\n {CATEGORIES.map((c) => {\n const Icon = c.icon;\n const isActive = active === c.id;\n return (\n <button\n key={c.id}\n onClick={() => setActive(c.id)}\n title={CATEGORY_LABELS[c.id]}\n className={`flex flex-col items-center gap-0.5 w-14 py-2 rounded text-[10px] transition-colors ${\n isActive ? \"bg-blue-50 text-blue-700\" : \"text-gray-600 hover:bg-gray-50\"\n }`}\n >\n <Icon size={20} />\n <span className=\"leading-tight text-center\">{CATEGORY_LABELS[c.id]}</span>\n </button>\n );\n })}\n <div className=\"mt-auto\">\n <button\n onClick={() => setActive(\"themes\")}\n title=\"Themes\"\n className={`flex flex-col items-center gap-0.5 w-14 py-2 rounded text-[10px] transition-colors ${\n active === \"themes\" ? \"bg-blue-50 text-blue-700\" : \"text-gray-600 hover:bg-gray-50\"\n }`}\n >\n <Palette size={20} />\n <span>Themes</span>\n </button>\n </div>\n </div>\n\n {/* Module list panel */}\n <div className=\"w-64 overflow-y-auto p-3\">\n {active === \"layers\" ? (\n <LayersPanel />\n ) : active === \"ai\" ? (\n <AIChatPanel />\n ) : active === \"themes\" ? (\n <>\n <h3 className=\"text-xs font-semibold uppercase tracking-wide text-gray-500 mb-3\">\n Themes\n </h3>\n <div className=\"flex flex-col gap-2\">\n {themes.map((t) => {\n const isActive = doc.theme.id === t.id;\n return (\n <button\n key={t.id}\n onClick={() => applyTheme(t)}\n className={`text-left p-3 rounded border transition-colors ${\n isActive\n ? \"border-blue-500 bg-blue-50\"\n : \"border-gray-200 hover:border-gray-300 bg-white\"\n }`}\n >\n <div className=\"flex items-center gap-2 mb-2\">\n <div\n className=\"w-4 h-4 rounded\"\n style={{ background: t.tokens.colors.primary }}\n />\n <div\n className=\"w-4 h-4 rounded border border-gray-200\"\n style={{ background: t.tokens.colors.surface }}\n />\n <div\n className=\"w-4 h-4 rounded\"\n style={{ background: t.tokens.colors.text }}\n />\n </div>\n <div className=\"text-sm font-medium\">{t.name}</div>\n </button>\n );\n })}\n </div>\n </>\n ) : (\n <>\n <h3 className=\"text-xs font-semibold uppercase tracking-wide text-gray-500 mb-3\">\n {CATEGORY_LABELS[active]}\n </h3>\n <div className=\"grid grid-cols-1 gap-2\">\n {moduleRegistry.byCategory(active).map((def) => (\n <button\n key={def.type}\n onClick={() => addModule(def.create())}\n className=\"text-left p-3 rounded border border-gray-200 bg-white hover:border-blue-400 hover:shadow-sm transition-all\"\n >\n <div className=\"h-12 bg-gray-50 rounded mb-2 flex items-center justify-center text-xs text-gray-400\">\n {def.name}\n </div>\n <div className=\"text-xs font-medium text-gray-700\">{def.name}</div>\n </button>\n ))}\n {moduleRegistry.byCategory(active).length === 0 && (\n <div className=\"text-xs text-gray-400 italic py-4 text-center\">\n No modules in this category yet.\n </div>\n )}\n </div>\n </>\n )}\n </div>\n </div>\n );\n}\n\n// ---------- Layers (layout overview) panel ----------\n\nfunction LayersPanel() {\n const { doc, selection, setSelection, reorderModules, deleteModule, duplicateModule } =\n useEmailStore();\n\n if (doc.modules.length === 0) {\n return (\n <>\n <h3 className=\"text-xs font-semibold uppercase tracking-wide text-gray-500 mb-3\">\n Layout\n </h3>\n <p className=\"text-xs text-gray-400 italic\">\n No blocks yet. Pick a category from the rail to add modules.\n </p>\n </>\n );\n }\n\n return (\n <>\n <h3 className=\"text-xs font-semibold uppercase tracking-wide text-gray-500 mb-1\">\n Layout\n </h3>\n <p className=\"text-[10px] text-gray-400 mb-3\">\n {doc.modules.length} block{doc.modules.length === 1 ? \"\" : \"s\"} · click to select\n </p>\n <ul className=\"flex flex-col gap-1\">\n {doc.modules.map((m, i) => {\n const active = selection?.kind !== \"email\" && selection?.moduleId === m.id;\n return (\n <li\n key={m.id}\n className={`flex items-center gap-1 rounded border px-2 py-1.5 text-xs cursor-pointer transition-colors ${\n active\n ? \"border-blue-500 bg-blue-50 text-blue-900\"\n : \"border-gray-200 bg-white hover:border-gray-300\"\n }`}\n onClick={() => setSelection({ kind: \"module\", moduleId: m.id })}\n >\n <span className=\"text-[10px] text-gray-400 w-4 shrink-0\">{i + 1}</span>\n <span className=\"flex-1 truncate\">\n {m.name}\n <span className=\"text-[10px] text-gray-400 ml-1\">\n ({m.children.length})\n </span>\n </span>\n <button\n disabled={i === 0}\n onClick={(e) => {\n e.stopPropagation();\n reorderModules(i, i - 1);\n }}\n className=\"p-0.5 text-gray-500 hover:text-blue-600 disabled:opacity-30\"\n title=\"Move up\"\n >\n <ArrowUp size={12} />\n </button>\n <button\n disabled={i === doc.modules.length - 1}\n onClick={(e) => {\n e.stopPropagation();\n reorderModules(i, i + 1);\n }}\n className=\"p-0.5 text-gray-500 hover:text-blue-600 disabled:opacity-30\"\n title=\"Move down\"\n >\n <ArrowDown size={12} />\n </button>\n <button\n onClick={(e) => {\n e.stopPropagation();\n duplicateModule(m.id);\n }}\n className=\"p-0.5 text-gray-500 hover:text-blue-600\"\n title=\"Duplicate\"\n >\n <Copy size={12} />\n </button>\n <button\n onClick={(e) => {\n e.stopPropagation();\n deleteModule(m.id);\n }}\n className=\"p-0.5 text-gray-500 hover:text-red-600\"\n title=\"Delete\"\n >\n <Trash2 size={12} />\n </button>\n </li>\n );\n })}\n </ul>\n </>\n );\n}\n","import { useMemo, useLayoutEffect, useEffect, useRef, useCallback } from 'react';\n\nfunction useCombinedRefs() {\n for (var _len = arguments.length, refs = new Array(_len), _key = 0; _key < _len; _key++) {\n refs[_key] = arguments[_key];\n }\n\n return useMemo(() => node => {\n refs.forEach(ref => ref(node));\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n refs);\n}\n\n// https://github.com/facebook/react/blob/master/packages/shared/ExecutionEnvironment.js\nconst canUseDOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';\n\nfunction isWindow(element) {\n const elementString = Object.prototype.toString.call(element);\n return elementString === '[object Window]' || // In Electron context the Window object serializes to [object global]\n elementString === '[object global]';\n}\n\nfunction isNode(node) {\n return 'nodeType' in node;\n}\n\nfunction getWindow(target) {\n var _target$ownerDocument, _target$ownerDocument2;\n\n if (!target) {\n return window;\n }\n\n if (isWindow(target)) {\n return target;\n }\n\n if (!isNode(target)) {\n return window;\n }\n\n return (_target$ownerDocument = (_target$ownerDocument2 = target.ownerDocument) == null ? void 0 : _target$ownerDocument2.defaultView) != null ? _target$ownerDocument : window;\n}\n\nfunction isDocument(node) {\n const {\n Document\n } = getWindow(node);\n return node instanceof Document;\n}\n\nfunction isHTMLElement(node) {\n if (isWindow(node)) {\n return false;\n }\n\n return node instanceof getWindow(node).HTMLElement;\n}\n\nfunction isSVGElement(node) {\n return node instanceof getWindow(node).SVGElement;\n}\n\nfunction getOwnerDocument(target) {\n if (!target) {\n return document;\n }\n\n if (isWindow(target)) {\n return target.document;\n }\n\n if (!isNode(target)) {\n return document;\n }\n\n if (isDocument(target)) {\n return target;\n }\n\n if (isHTMLElement(target) || isSVGElement(target)) {\n return target.ownerDocument;\n }\n\n return document;\n}\n\n/**\r\n * A hook that resolves to useEffect on the server and useLayoutEffect on the client\r\n * @param callback {function} Callback function that is invoked when the dependencies of the hook change\r\n */\n\nconst useIsomorphicLayoutEffect = canUseDOM ? useLayoutEffect : useEffect;\n\nfunction useEvent(handler) {\n const handlerRef = useRef(handler);\n useIsomorphicLayoutEffect(() => {\n handlerRef.current = handler;\n });\n return useCallback(function () {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n return handlerRef.current == null ? void 0 : handlerRef.current(...args);\n }, []);\n}\n\nfunction useInterval() {\n const intervalRef = useRef(null);\n const set = useCallback((listener, duration) => {\n intervalRef.current = setInterval(listener, duration);\n }, []);\n const clear = useCallback(() => {\n if (intervalRef.current !== null) {\n clearInterval(intervalRef.current);\n intervalRef.current = null;\n }\n }, []);\n return [set, clear];\n}\n\nfunction useLatestValue(value, dependencies) {\n if (dependencies === void 0) {\n dependencies = [value];\n }\n\n const valueRef = useRef(value);\n useIsomorphicLayoutEffect(() => {\n if (valueRef.current !== value) {\n valueRef.current = value;\n }\n }, dependencies);\n return valueRef;\n}\n\nfunction useLazyMemo(callback, dependencies) {\n const valueRef = useRef();\n return useMemo(() => {\n const newValue = callback(valueRef.current);\n valueRef.current = newValue;\n return newValue;\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [...dependencies]);\n}\n\nfunction useNodeRef(onChange) {\n const onChangeHandler = useEvent(onChange);\n const node = useRef(null);\n const setNodeRef = useCallback(element => {\n if (element !== node.current) {\n onChangeHandler == null ? void 0 : onChangeHandler(element, node.current);\n }\n\n node.current = element;\n }, //eslint-disable-next-line\n []);\n return [node, setNodeRef];\n}\n\nfunction usePrevious(value) {\n const ref = useRef();\n useEffect(() => {\n ref.current = value;\n }, [value]);\n return ref.current;\n}\n\nlet ids = {};\nfunction useUniqueId(prefix, value) {\n return useMemo(() => {\n if (value) {\n return value;\n }\n\n const id = ids[prefix] == null ? 0 : ids[prefix] + 1;\n ids[prefix] = id;\n return prefix + \"-\" + id;\n }, [prefix, value]);\n}\n\nfunction createAdjustmentFn(modifier) {\n return function (object) {\n for (var _len = arguments.length, adjustments = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n adjustments[_key - 1] = arguments[_key];\n }\n\n return adjustments.reduce((accumulator, adjustment) => {\n const entries = Object.entries(adjustment);\n\n for (const [key, valueAdjustment] of entries) {\n const value = accumulator[key];\n\n if (value != null) {\n accumulator[key] = value + modifier * valueAdjustment;\n }\n }\n\n return accumulator;\n }, { ...object\n });\n };\n}\n\nconst add = /*#__PURE__*/createAdjustmentFn(1);\nconst subtract = /*#__PURE__*/createAdjustmentFn(-1);\n\nfunction hasViewportRelativeCoordinates(event) {\n return 'clientX' in event && 'clientY' in event;\n}\n\nfunction isKeyboardEvent(event) {\n if (!event) {\n return false;\n }\n\n const {\n KeyboardEvent\n } = getWindow(event.target);\n return KeyboardEvent && event instanceof KeyboardEvent;\n}\n\nfunction isTouchEvent(event) {\n if (!event) {\n return false;\n }\n\n const {\n TouchEvent\n } = getWindow(event.target);\n return TouchEvent && event instanceof TouchEvent;\n}\n\n/**\r\n * Returns the normalized x and y coordinates for mouse and touch events.\r\n */\n\nfunction getEventCoordinates(event) {\n if (isTouchEvent(event)) {\n if (event.touches && event.touches.length) {\n const {\n clientX: x,\n clientY: y\n } = event.touches[0];\n return {\n x,\n y\n };\n } else if (event.changedTouches && event.changedTouches.length) {\n const {\n clientX: x,\n clientY: y\n } = event.changedTouches[0];\n return {\n x,\n y\n };\n }\n }\n\n if (hasViewportRelativeCoordinates(event)) {\n return {\n x: event.clientX,\n y: event.clientY\n };\n }\n\n return null;\n}\n\nconst CSS = /*#__PURE__*/Object.freeze({\n Translate: {\n toString(transform) {\n if (!transform) {\n return;\n }\n\n const {\n x,\n y\n } = transform;\n return \"translate3d(\" + (x ? Math.round(x) : 0) + \"px, \" + (y ? Math.round(y) : 0) + \"px, 0)\";\n }\n\n },\n Scale: {\n toString(transform) {\n if (!transform) {\n return;\n }\n\n const {\n scaleX,\n scaleY\n } = transform;\n return \"scaleX(\" + scaleX + \") scaleY(\" + scaleY + \")\";\n }\n\n },\n Transform: {\n toString(transform) {\n if (!transform) {\n return;\n }\n\n return [CSS.Translate.toString(transform), CSS.Scale.toString(transform)].join(' ');\n }\n\n },\n Transition: {\n toString(_ref) {\n let {\n property,\n duration,\n easing\n } = _ref;\n return property + \" \" + duration + \"ms \" + easing;\n }\n\n }\n});\n\nconst SELECTOR = 'a,frame,iframe,input:not([type=hidden]):not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),*[tabindex]';\nfunction findFirstFocusableNode(element) {\n if (element.matches(SELECTOR)) {\n return element;\n }\n\n return element.querySelector(SELECTOR);\n}\n\nexport { CSS, add, canUseDOM, findFirstFocusableNode, getEventCoordinates, getOwnerDocument, getWindow, hasViewportRelativeCoordinates, isDocument, isHTMLElement, isKeyboardEvent, isNode, isSVGElement, isTouchEvent, isWindow, subtract, useCombinedRefs, useEvent, useInterval, useIsomorphicLayoutEffect, useLatestValue, useLazyMemo, useNodeRef, usePrevious, useUniqueId };\n//# sourceMappingURL=utilities.esm.js.map\n","import React, { useState, useCallback } from 'react';\n\nconst hiddenStyles = {\n display: 'none'\n};\nfunction HiddenText(_ref) {\n let {\n id,\n value\n } = _ref;\n return React.createElement(\"div\", {\n id: id,\n style: hiddenStyles\n }, value);\n}\n\nfunction LiveRegion(_ref) {\n let {\n id,\n announcement,\n ariaLiveType = \"assertive\"\n } = _ref;\n // Hide element visually but keep it readable by screen readers\n const visuallyHidden = {\n position: 'fixed',\n top: 0,\n left: 0,\n width: 1,\n height: 1,\n margin: -1,\n border: 0,\n padding: 0,\n overflow: 'hidden',\n clip: 'rect(0 0 0 0)',\n clipPath: 'inset(100%)',\n whiteSpace: 'nowrap'\n };\n return React.createElement(\"div\", {\n id: id,\n style: visuallyHidden,\n role: \"status\",\n \"aria-live\": ariaLiveType,\n \"aria-atomic\": true\n }, announcement);\n}\n\nfunction useAnnouncement() {\n const [announcement, setAnnouncement] = useState('');\n const announce = useCallback(value => {\n if (value != null) {\n setAnnouncement(value);\n }\n }, []);\n return {\n announce,\n announcement\n };\n}\n\nexport { HiddenText, LiveRegion, useAnnouncement };\n//# sourceMappingURL=accessibility.esm.js.map\n","import React, { createContext, useContext, useEffect, useState, useCallback, useMemo, useRef, memo, useReducer, cloneElement, forwardRef } from 'react';\nimport { createPortal, unstable_batchedUpdates } from 'react-dom';\nimport { useUniqueId, getEventCoordinates, getWindow, isDocument, isHTMLElement, isSVGElement, canUseDOM, isWindow, isNode, getOwnerDocument, add, isKeyboardEvent, subtract, useLazyMemo, useInterval, usePrevious, useLatestValue, useEvent, useIsomorphicLayoutEffect, useNodeRef, findFirstFocusableNode, CSS } from '@dnd-kit/utilities';\nimport { useAnnouncement, HiddenText, LiveRegion } from '@dnd-kit/accessibility';\n\nconst DndMonitorContext = /*#__PURE__*/createContext(null);\n\nfunction useDndMonitor(listener) {\n const registerListener = useContext(DndMonitorContext);\n useEffect(() => {\n if (!registerListener) {\n throw new Error('useDndMonitor must be used within a children of <DndContext>');\n }\n\n const unsubscribe = registerListener(listener);\n return unsubscribe;\n }, [listener, registerListener]);\n}\n\nfunction useDndMonitorProvider() {\n const [listeners] = useState(() => new Set());\n const registerListener = useCallback(listener => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n }, [listeners]);\n const dispatch = useCallback(_ref => {\n let {\n type,\n event\n } = _ref;\n listeners.forEach(listener => {\n var _listener$type;\n\n return (_listener$type = listener[type]) == null ? void 0 : _listener$type.call(listener, event);\n });\n }, [listeners]);\n return [dispatch, registerListener];\n}\n\nconst defaultScreenReaderInstructions = {\n draggable: \"\\n To pick up a draggable item, press the space bar.\\n While dragging, use the arrow keys to move the item.\\n Press space again to drop the item in its new position, or press escape to cancel.\\n \"\n};\nconst defaultAnnouncements = {\n onDragStart(_ref) {\n let {\n active\n } = _ref;\n return \"Picked up draggable item \" + active.id + \".\";\n },\n\n onDragOver(_ref2) {\n let {\n active,\n over\n } = _ref2;\n\n if (over) {\n return \"Draggable item \" + active.id + \" was moved over droppable area \" + over.id + \".\";\n }\n\n return \"Draggable item \" + active.id + \" is no longer over a droppable area.\";\n },\n\n onDragEnd(_ref3) {\n let {\n active,\n over\n } = _ref3;\n\n if (over) {\n return \"Draggable item \" + active.id + \" was dropped over droppable area \" + over.id;\n }\n\n return \"Draggable item \" + active.id + \" was dropped.\";\n },\n\n onDragCancel(_ref4) {\n let {\n active\n } = _ref4;\n return \"Dragging was cancelled. Draggable item \" + active.id + \" was dropped.\";\n }\n\n};\n\nfunction Accessibility(_ref) {\n let {\n announcements = defaultAnnouncements,\n container,\n hiddenTextDescribedById,\n screenReaderInstructions = defaultScreenReaderInstructions\n } = _ref;\n const {\n announce,\n announcement\n } = useAnnouncement();\n const liveRegionId = useUniqueId(\"DndLiveRegion\");\n const [mounted, setMounted] = useState(false);\n useEffect(() => {\n setMounted(true);\n }, []);\n useDndMonitor(useMemo(() => ({\n onDragStart(_ref2) {\n let {\n active\n } = _ref2;\n announce(announcements.onDragStart({\n active\n }));\n },\n\n onDragMove(_ref3) {\n let {\n active,\n over\n } = _ref3;\n\n if (announcements.onDragMove) {\n announce(announcements.onDragMove({\n active,\n over\n }));\n }\n },\n\n onDragOver(_ref4) {\n let {\n active,\n over\n } = _ref4;\n announce(announcements.onDragOver({\n active,\n over\n }));\n },\n\n onDragEnd(_ref5) {\n let {\n active,\n over\n } = _ref5;\n announce(announcements.onDragEnd({\n active,\n over\n }));\n },\n\n onDragCancel(_ref6) {\n let {\n active,\n over\n } = _ref6;\n announce(announcements.onDragCancel({\n active,\n over\n }));\n }\n\n }), [announce, announcements]));\n\n if (!mounted) {\n return null;\n }\n\n const markup = React.createElement(React.Fragment, null, React.createElement(HiddenText, {\n id: hiddenTextDescribedById,\n value: screenReaderInstructions.draggable\n }), React.createElement(LiveRegion, {\n id: liveRegionId,\n announcement: announcement\n }));\n return container ? createPortal(markup, container) : markup;\n}\n\nvar Action;\n\n(function (Action) {\n Action[\"DragStart\"] = \"dragStart\";\n Action[\"DragMove\"] = \"dragMove\";\n Action[\"DragEnd\"] = \"dragEnd\";\n Action[\"DragCancel\"] = \"dragCancel\";\n Action[\"DragOver\"] = \"dragOver\";\n Action[\"RegisterDroppable\"] = \"registerDroppable\";\n Action[\"SetDroppableDisabled\"] = \"setDroppableDisabled\";\n Action[\"UnregisterDroppable\"] = \"unregisterDroppable\";\n})(Action || (Action = {}));\n\nfunction noop() {}\n\nfunction useSensor(sensor, options) {\n return useMemo(() => ({\n sensor,\n options: options != null ? options : {}\n }), // eslint-disable-next-line react-hooks/exhaustive-deps\n [sensor, options]);\n}\n\nfunction useSensors() {\n for (var _len = arguments.length, sensors = new Array(_len), _key = 0; _key < _len; _key++) {\n sensors[_key] = arguments[_key];\n }\n\n return useMemo(() => [...sensors].filter(sensor => sensor != null), // eslint-disable-next-line react-hooks/exhaustive-deps\n [...sensors]);\n}\n\nconst defaultCoordinates = /*#__PURE__*/Object.freeze({\n x: 0,\n y: 0\n});\n\n/**\r\n * Returns the distance between two points\r\n */\nfunction distanceBetween(p1, p2) {\n return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));\n}\n\nfunction getRelativeTransformOrigin(event, rect) {\n const eventCoordinates = getEventCoordinates(event);\n\n if (!eventCoordinates) {\n return '0 0';\n }\n\n const transformOrigin = {\n x: (eventCoordinates.x - rect.left) / rect.width * 100,\n y: (eventCoordinates.y - rect.top) / rect.height * 100\n };\n return transformOrigin.x + \"% \" + transformOrigin.y + \"%\";\n}\n\n/**\r\n * Sort collisions from smallest to greatest value\r\n */\nfunction sortCollisionsAsc(_ref, _ref2) {\n let {\n data: {\n value: a\n }\n } = _ref;\n let {\n data: {\n value: b\n }\n } = _ref2;\n return a - b;\n}\n/**\r\n * Sort collisions from greatest to smallest value\r\n */\n\nfunction sortCollisionsDesc(_ref3, _ref4) {\n let {\n data: {\n value: a\n }\n } = _ref3;\n let {\n data: {\n value: b\n }\n } = _ref4;\n return b - a;\n}\n/**\r\n * Returns the coordinates of the corners of a given rectangle:\r\n * [TopLeft {x, y}, TopRight {x, y}, BottomLeft {x, y}, BottomRight {x, y}]\r\n */\n\nfunction cornersOfRectangle(_ref5) {\n let {\n left,\n top,\n height,\n width\n } = _ref5;\n return [{\n x: left,\n y: top\n }, {\n x: left + width,\n y: top\n }, {\n x: left,\n y: top + height\n }, {\n x: left + width,\n y: top + height\n }];\n}\nfunction getFirstCollision(collisions, property) {\n if (!collisions || collisions.length === 0) {\n return null;\n }\n\n const [firstCollision] = collisions;\n return property ? firstCollision[property] : firstCollision;\n}\n\n/**\r\n * Returns the coordinates of the center of a given ClientRect\r\n */\n\nfunction centerOfRectangle(rect, left, top) {\n if (left === void 0) {\n left = rect.left;\n }\n\n if (top === void 0) {\n top = rect.top;\n }\n\n return {\n x: left + rect.width * 0.5,\n y: top + rect.height * 0.5\n };\n}\n/**\r\n * Returns the closest rectangles from an array of rectangles to the center of a given\r\n * rectangle.\r\n */\n\n\nconst closestCenter = _ref => {\n let {\n collisionRect,\n droppableRects,\n droppableContainers\n } = _ref;\n const centerRect = centerOfRectangle(collisionRect, collisionRect.left, collisionRect.top);\n const collisions = [];\n\n for (const droppableContainer of droppableContainers) {\n const {\n id\n } = droppableContainer;\n const rect = droppableRects.get(id);\n\n if (rect) {\n const distBetween = distanceBetween(centerOfRectangle(rect), centerRect);\n collisions.push({\n id,\n data: {\n droppableContainer,\n value: distBetween\n }\n });\n }\n }\n\n return collisions.sort(sortCollisionsAsc);\n};\n\n/**\r\n * Returns the closest rectangles from an array of rectangles to the corners of\r\n * another rectangle.\r\n */\n\nconst closestCorners = _ref => {\n let {\n collisionRect,\n droppableRects,\n droppableContainers\n } = _ref;\n const corners = cornersOfRectangle(collisionRect);\n const collisions = [];\n\n for (const droppableContainer of droppableContainers) {\n const {\n id\n } = droppableContainer;\n const rect = droppableRects.get(id);\n\n if (rect) {\n const rectCorners = cornersOfRectangle(rect);\n const distances = corners.reduce((accumulator, corner, index) => {\n return accumulator + distanceBetween(rectCorners[index], corner);\n }, 0);\n const effectiveDistance = Number((distances / 4).toFixed(4));\n collisions.push({\n id,\n data: {\n droppableContainer,\n value: effectiveDistance\n }\n });\n }\n }\n\n return collisions.sort(sortCollisionsAsc);\n};\n\n/**\r\n * Returns the intersecting rectangle area between two rectangles\r\n */\n\nfunction getIntersectionRatio(entry, target) {\n const top = Math.max(target.top, entry.top);\n const left = Math.max(target.left, entry.left);\n const right = Math.min(target.left + target.width, entry.left + entry.width);\n const bottom = Math.min(target.top + target.height, entry.top + entry.height);\n const width = right - left;\n const height = bottom - top;\n\n if (left < right && top < bottom) {\n const targetArea = target.width * target.height;\n const entryArea = entry.width * entry.height;\n const intersectionArea = width * height;\n const intersectionRatio = intersectionArea / (targetArea + entryArea - intersectionArea);\n return Number(intersectionRatio.toFixed(4));\n } // Rectangles do not overlap, or overlap has an area of zero (edge/corner overlap)\n\n\n return 0;\n}\n/**\r\n * Returns the rectangles that has the greatest intersection area with a given\r\n * rectangle in an array of rectangles.\r\n */\n\nconst rectIntersection = _ref => {\n let {\n collisionRect,\n droppableRects,\n droppableContainers\n } = _ref;\n const collisions = [];\n\n for (const droppableContainer of droppableContainers) {\n const {\n id\n } = droppableContainer;\n const rect = droppableRects.get(id);\n\n if (rect) {\n const intersectionRatio = getIntersectionRatio(rect, collisionRect);\n\n if (intersectionRatio > 0) {\n collisions.push({\n id,\n data: {\n droppableContainer,\n value: intersectionRatio\n }\n });\n }\n }\n }\n\n return collisions.sort(sortCollisionsDesc);\n};\n\n/**\r\n * Check if a given point is contained within a bounding rectangle\r\n */\n\nfunction isPointWithinRect(point, rect) {\n const {\n top,\n left,\n bottom,\n right\n } = rect;\n return top <= point.y && point.y <= bottom && left <= point.x && point.x <= right;\n}\n/**\r\n * Returns the rectangles that the pointer is hovering over\r\n */\n\n\nconst pointerWithin = _ref => {\n let {\n droppableContainers,\n droppableRects,\n pointerCoordinates\n } = _ref;\n\n if (!pointerCoordinates) {\n return [];\n }\n\n const collisions = [];\n\n for (const droppableContainer of droppableContainers) {\n const {\n id\n } = droppableContainer;\n const rect = droppableRects.get(id);\n\n if (rect && isPointWithinRect(pointerCoordinates, rect)) {\n /* There may be more than a single rectangle intersecting\r\n * with the pointer coordinates. In order to sort the\r\n * colliding rectangles, we measure the distance between\r\n * the pointer and the corners of the intersecting rectangle\r\n */\n const corners = cornersOfRectangle(rect);\n const distances = corners.reduce((accumulator, corner) => {\n return accumulator + distanceBetween(pointerCoordinates, corner);\n }, 0);\n const effectiveDistance = Number((distances / 4).toFixed(4));\n collisions.push({\n id,\n data: {\n droppableContainer,\n value: effectiveDistance\n }\n });\n }\n }\n\n return collisions.sort(sortCollisionsAsc);\n};\n\nfunction adjustScale(transform, rect1, rect2) {\n return { ...transform,\n scaleX: rect1 && rect2 ? rect1.width / rect2.width : 1,\n scaleY: rect1 && rect2 ? rect1.height / rect2.height : 1\n };\n}\n\nfunction getRectDelta(rect1, rect2) {\n return rect1 && rect2 ? {\n x: rect1.left - rect2.left,\n y: rect1.top - rect2.top\n } : defaultCoordinates;\n}\n\nfunction createRectAdjustmentFn(modifier) {\n return function adjustClientRect(rect) {\n for (var _len = arguments.length, adjustments = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n adjustments[_key - 1] = arguments[_key];\n }\n\n return adjustments.reduce((acc, adjustment) => ({ ...acc,\n top: acc.top + modifier * adjustment.y,\n bottom: acc.bottom + modifier * adjustment.y,\n left: acc.left + modifier * adjustment.x,\n right: acc.right + modifier * adjustment.x\n }), { ...rect\n });\n };\n}\nconst getAdjustedRect = /*#__PURE__*/createRectAdjustmentFn(1);\n\nfunction parseTransform(transform) {\n if (transform.startsWith('matrix3d(')) {\n const transformArray = transform.slice(9, -1).split(/, /);\n return {\n x: +transformArray[12],\n y: +transformArray[13],\n scaleX: +transformArray[0],\n scaleY: +transformArray[5]\n };\n } else if (transform.startsWith('matrix(')) {\n const transformArray = transform.slice(7, -1).split(/, /);\n return {\n x: +transformArray[4],\n y: +transformArray[5],\n scaleX: +transformArray[0],\n scaleY: +transformArray[3]\n };\n }\n\n return null;\n}\n\nfunction inverseTransform(rect, transform, transformOrigin) {\n const parsedTransform = parseTransform(transform);\n\n if (!parsedTransform) {\n return rect;\n }\n\n const {\n scaleX,\n scaleY,\n x: translateX,\n y: translateY\n } = parsedTransform;\n const x = rect.left - translateX - (1 - scaleX) * parseFloat(transformOrigin);\n const y = rect.top - translateY - (1 - scaleY) * parseFloat(transformOrigin.slice(transformOrigin.indexOf(' ') + 1));\n const w = scaleX ? rect.width / scaleX : rect.width;\n const h = scaleY ? rect.height / scaleY : rect.height;\n return {\n width: w,\n height: h,\n top: y,\n right: x + w,\n bottom: y + h,\n left: x\n };\n}\n\nconst defaultOptions = {\n ignoreTransform: false\n};\n/**\r\n * Returns the bounding client rect of an element relative to the viewport.\r\n */\n\nfunction getClientRect(element, options) {\n if (options === void 0) {\n options = defaultOptions;\n }\n\n let rect = element.getBoundingClientRect();\n\n if (options.ignoreTransform) {\n const {\n transform,\n transformOrigin\n } = getWindow(element).getComputedStyle(element);\n\n if (transform) {\n rect = inverseTransform(rect, transform, transformOrigin);\n }\n }\n\n const {\n top,\n left,\n width,\n height,\n bottom,\n right\n } = rect;\n return {\n top,\n left,\n width,\n height,\n bottom,\n right\n };\n}\n/**\r\n * Returns the bounding client rect of an element relative to the viewport.\r\n *\r\n * @remarks\r\n * The ClientRect returned by this method does not take into account transforms\r\n * applied to the element it measures.\r\n *\r\n */\n\nfunction getTransformAgnosticClientRect(element) {\n return getClientRect(element, {\n ignoreTransform: true\n });\n}\n\nfunction getWindowClientRect(element) {\n const width = element.innerWidth;\n const height = element.innerHeight;\n return {\n top: 0,\n left: 0,\n right: width,\n bottom: height,\n width,\n height\n };\n}\n\nfunction isFixed(node, computedStyle) {\n if (computedStyle === void 0) {\n computedStyle = getWindow(node).getComputedStyle(node);\n }\n\n return computedStyle.position === 'fixed';\n}\n\nfunction isScrollable(element, computedStyle) {\n if (computedStyle === void 0) {\n computedStyle = getWindow(element).getComputedStyle(element);\n }\n\n const overflowRegex = /(auto|scroll|overlay)/;\n const properties = ['overflow', 'overflowX', 'overflowY'];\n return properties.some(property => {\n const value = computedStyle[property];\n return typeof value === 'string' ? overflowRegex.test(value) : false;\n });\n}\n\nfunction getScrollableAncestors(element, limit) {\n const scrollParents = [];\n\n function findScrollableAncestors(node) {\n if (limit != null && scrollParents.length >= limit) {\n return scrollParents;\n }\n\n if (!node) {\n return scrollParents;\n }\n\n if (isDocument(node) && node.scrollingElement != null && !scrollParents.includes(node.scrollingElement)) {\n scrollParents.push(node.scrollingElement);\n return scrollParents;\n }\n\n if (!isHTMLElement(node) || isSVGElement(node)) {\n return scrollParents;\n }\n\n if (scrollParents.includes(node)) {\n return scrollParents;\n }\n\n const computedStyle = getWindow(element).getComputedStyle(node);\n\n if (node !== element) {\n if (isScrollable(node, computedStyle)) {\n scrollParents.push(node);\n }\n }\n\n if (isFixed(node, computedStyle)) {\n return scrollParents;\n }\n\n return findScrollableAncestors(node.parentNode);\n }\n\n if (!element) {\n return scrollParents;\n }\n\n return findScrollableAncestors(element);\n}\nfunction getFirstScrollableAncestor(node) {\n const [firstScrollableAncestor] = getScrollableAncestors(node, 1);\n return firstScrollableAncestor != null ? firstScrollableAncestor : null;\n}\n\nfunction getScrollableElement(element) {\n if (!canUseDOM || !element) {\n return null;\n }\n\n if (isWindow(element)) {\n return element;\n }\n\n if (!isNode(element)) {\n return null;\n }\n\n if (isDocument(element) || element === getOwnerDocument(element).scrollingElement) {\n return window;\n }\n\n if (isHTMLElement(element)) {\n return element;\n }\n\n return null;\n}\n\nfunction getScrollXCoordinate(element) {\n if (isWindow(element)) {\n return element.scrollX;\n }\n\n return element.scrollLeft;\n}\nfunction getScrollYCoordinate(element) {\n if (isWindow(element)) {\n return element.scrollY;\n }\n\n return element.scrollTop;\n}\nfunction getScrollCoordinates(element) {\n return {\n x: getScrollXCoordinate(element),\n y: getScrollYCoordinate(element)\n };\n}\n\nvar Direction;\n\n(function (Direction) {\n Direction[Direction[\"Forward\"] = 1] = \"Forward\";\n Direction[Direction[\"Backward\"] = -1] = \"Backward\";\n})(Direction || (Direction = {}));\n\nfunction isDocumentScrollingElement(element) {\n if (!canUseDOM || !element) {\n return false;\n }\n\n return element === document.scrollingElement;\n}\n\nfunction getScrollPosition(scrollingContainer) {\n const minScroll = {\n x: 0,\n y: 0\n };\n const dimensions = isDocumentScrollingElement(scrollingContainer) ? {\n height: window.innerHeight,\n width: window.innerWidth\n } : {\n height: scrollingContainer.clientHeight,\n width: scrollingContainer.clientWidth\n };\n const maxScroll = {\n x: scrollingContainer.scrollWidth - dimensions.width,\n y: scrollingContainer.scrollHeight - dimensions.height\n };\n const isTop = scrollingContainer.scrollTop <= minScroll.y;\n const isLeft = scrollingContainer.scrollLeft <= minScroll.x;\n const isBottom = scrollingContainer.scrollTop >= maxScroll.y;\n const isRight = scrollingContainer.scrollLeft >= maxScroll.x;\n return {\n isTop,\n isLeft,\n isBottom,\n isRight,\n maxScroll,\n minScroll\n };\n}\n\nconst defaultThreshold = {\n x: 0.2,\n y: 0.2\n};\nfunction getScrollDirectionAndSpeed(scrollContainer, scrollContainerRect, _ref, acceleration, thresholdPercentage) {\n let {\n top,\n left,\n right,\n bottom\n } = _ref;\n\n if (acceleration === void 0) {\n acceleration = 10;\n }\n\n if (thresholdPercentage === void 0) {\n thresholdPercentage = defaultThreshold;\n }\n\n const {\n isTop,\n isBottom,\n isLeft,\n isRight\n } = getScrollPosition(scrollContainer);\n const direction = {\n x: 0,\n y: 0\n };\n const speed = {\n x: 0,\n y: 0\n };\n const threshold = {\n height: scrollContainerRect.height * thresholdPercentage.y,\n width: scrollContainerRect.width * thresholdPercentage.x\n };\n\n if (!isTop && top <= scrollContainerRect.top + threshold.height) {\n // Scroll Up\n direction.y = Direction.Backward;\n speed.y = acceleration * Math.abs((scrollContainerRect.top + threshold.height - top) / threshold.height);\n } else if (!isBottom && bottom >= scrollContainerRect.bottom - threshold.height) {\n // Scroll Down\n direction.y = Direction.Forward;\n speed.y = acceleration * Math.abs((scrollContainerRect.bottom - threshold.height - bottom) / threshold.height);\n }\n\n if (!isRight && right >= scrollContainerRect.right - threshold.width) {\n // Scroll Right\n direction.x = Direction.Forward;\n speed.x = acceleration * Math.abs((scrollContainerRect.right - threshold.width - right) / threshold.width);\n } else if (!isLeft && left <= scrollContainerRect.left + threshold.width) {\n // Scroll Left\n direction.x = Direction.Backward;\n speed.x = acceleration * Math.abs((scrollContainerRect.left + threshold.width - left) / threshold.width);\n }\n\n return {\n direction,\n speed\n };\n}\n\nfunction getScrollElementRect(element) {\n if (element === document.scrollingElement) {\n const {\n innerWidth,\n innerHeight\n } = window;\n return {\n top: 0,\n left: 0,\n right: innerWidth,\n bottom: innerHeight,\n width: innerWidth,\n height: innerHeight\n };\n }\n\n const {\n top,\n left,\n right,\n bottom\n } = element.getBoundingClientRect();\n return {\n top,\n left,\n right,\n bottom,\n width: element.clientWidth,\n height: element.clientHeight\n };\n}\n\nfunction getScrollOffsets(scrollableAncestors) {\n return scrollableAncestors.reduce((acc, node) => {\n return add(acc, getScrollCoordinates(node));\n }, defaultCoordinates);\n}\nfunction getScrollXOffset(scrollableAncestors) {\n return scrollableAncestors.reduce((acc, node) => {\n return acc + getScrollXCoordinate(node);\n }, 0);\n}\nfunction getScrollYOffset(scrollableAncestors) {\n return scrollableAncestors.reduce((acc, node) => {\n return acc + getScrollYCoordinate(node);\n }, 0);\n}\n\nfunction scrollIntoViewIfNeeded(element, measure) {\n if (measure === void 0) {\n measure = getClientRect;\n }\n\n if (!element) {\n return;\n }\n\n const {\n top,\n left,\n bottom,\n right\n } = measure(element);\n const firstScrollableAncestor = getFirstScrollableAncestor(element);\n\n if (!firstScrollableAncestor) {\n return;\n }\n\n if (bottom <= 0 || right <= 0 || top >= window.innerHeight || left >= window.innerWidth) {\n element.scrollIntoView({\n block: 'center',\n inline: 'center'\n });\n }\n}\n\nconst properties = [['x', ['left', 'right'], getScrollXOffset], ['y', ['top', 'bottom'], getScrollYOffset]];\nclass Rect {\n constructor(rect, element) {\n this.rect = void 0;\n this.width = void 0;\n this.height = void 0;\n this.top = void 0;\n this.bottom = void 0;\n this.right = void 0;\n this.left = void 0;\n const scrollableAncestors = getScrollableAncestors(element);\n const scrollOffsets = getScrollOffsets(scrollableAncestors);\n this.rect = { ...rect\n };\n this.width = rect.width;\n this.height = rect.height;\n\n for (const [axis, keys, getScrollOffset] of properties) {\n for (const key of keys) {\n Object.defineProperty(this, key, {\n get: () => {\n const currentOffsets = getScrollOffset(scrollableAncestors);\n const scrollOffsetsDeltla = scrollOffsets[axis] - currentOffsets;\n return this.rect[key] + scrollOffsetsDeltla;\n },\n enumerable: true\n });\n }\n }\n\n Object.defineProperty(this, 'rect', {\n enumerable: false\n });\n }\n\n}\n\nclass Listeners {\n constructor(target) {\n this.target = void 0;\n this.listeners = [];\n\n this.removeAll = () => {\n this.listeners.forEach(listener => {\n var _this$target;\n\n return (_this$target = this.target) == null ? void 0 : _this$target.removeEventListener(...listener);\n });\n };\n\n this.target = target;\n }\n\n add(eventName, handler, options) {\n var _this$target2;\n\n (_this$target2 = this.target) == null ? void 0 : _this$target2.addEventListener(eventName, handler, options);\n this.listeners.push([eventName, handler, options]);\n }\n\n}\n\nfunction getEventListenerTarget(target) {\n // If the `event.target` element is removed from the document events will still be targeted\n // at it, and hence won't always bubble up to the window or document anymore.\n // If there is any risk of an element being removed while it is being dragged,\n // the best practice is to attach the event listeners directly to the target.\n // https://developer.mozilla.org/en-US/docs/Web/API/EventTarget\n const {\n EventTarget\n } = getWindow(target);\n return target instanceof EventTarget ? target : getOwnerDocument(target);\n}\n\nfunction hasExceededDistance(delta, measurement) {\n const dx = Math.abs(delta.x);\n const dy = Math.abs(delta.y);\n\n if (typeof measurement === 'number') {\n return Math.sqrt(dx ** 2 + dy ** 2) > measurement;\n }\n\n if ('x' in measurement && 'y' in measurement) {\n return dx > measurement.x && dy > measurement.y;\n }\n\n if ('x' in measurement) {\n return dx > measurement.x;\n }\n\n if ('y' in measurement) {\n return dy > measurement.y;\n }\n\n return false;\n}\n\nvar EventName;\n\n(function (EventName) {\n EventName[\"Click\"] = \"click\";\n EventName[\"DragStart\"] = \"dragstart\";\n EventName[\"Keydown\"] = \"keydown\";\n EventName[\"ContextMenu\"] = \"contextmenu\";\n EventName[\"Resize\"] = \"resize\";\n EventName[\"SelectionChange\"] = \"selectionchange\";\n EventName[\"VisibilityChange\"] = \"visibilitychange\";\n})(EventName || (EventName = {}));\n\nfunction preventDefault(event) {\n event.preventDefault();\n}\nfunction stopPropagation(event) {\n event.stopPropagation();\n}\n\nvar KeyboardCode;\n\n(function (KeyboardCode) {\n KeyboardCode[\"Space\"] = \"Space\";\n KeyboardCode[\"Down\"] = \"ArrowDown\";\n KeyboardCode[\"Right\"] = \"ArrowRight\";\n KeyboardCode[\"Left\"] = \"ArrowLeft\";\n KeyboardCode[\"Up\"] = \"ArrowUp\";\n KeyboardCode[\"Esc\"] = \"Escape\";\n KeyboardCode[\"Enter\"] = \"Enter\";\n KeyboardCode[\"Tab\"] = \"Tab\";\n})(KeyboardCode || (KeyboardCode = {}));\n\nconst defaultKeyboardCodes = {\n start: [KeyboardCode.Space, KeyboardCode.Enter],\n cancel: [KeyboardCode.Esc],\n end: [KeyboardCode.Space, KeyboardCode.Enter, KeyboardCode.Tab]\n};\nconst defaultKeyboardCoordinateGetter = (event, _ref) => {\n let {\n currentCoordinates\n } = _ref;\n\n switch (event.code) {\n case KeyboardCode.Right:\n return { ...currentCoordinates,\n x: currentCoordinates.x + 25\n };\n\n case KeyboardCode.Left:\n return { ...currentCoordinates,\n x: currentCoordinates.x - 25\n };\n\n case KeyboardCode.Down:\n return { ...currentCoordinates,\n y: currentCoordinates.y + 25\n };\n\n case KeyboardCode.Up:\n return { ...currentCoordinates,\n y: currentCoordinates.y - 25\n };\n }\n\n return undefined;\n};\n\nclass KeyboardSensor {\n constructor(props) {\n this.props = void 0;\n this.autoScrollEnabled = false;\n this.referenceCoordinates = void 0;\n this.listeners = void 0;\n this.windowListeners = void 0;\n this.props = props;\n const {\n event: {\n target\n }\n } = props;\n this.props = props;\n this.listeners = new Listeners(getOwnerDocument(target));\n this.windowListeners = new Listeners(getWindow(target));\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n this.attach();\n }\n\n attach() {\n this.handleStart();\n this.windowListeners.add(EventName.Resize, this.handleCancel);\n this.windowListeners.add(EventName.VisibilityChange, this.handleCancel);\n setTimeout(() => this.listeners.add(EventName.Keydown, this.handleKeyDown));\n }\n\n handleStart() {\n const {\n activeNode,\n onStart\n } = this.props;\n const node = activeNode.node.current;\n\n if (node) {\n scrollIntoViewIfNeeded(node);\n }\n\n onStart(defaultCoordinates);\n }\n\n handleKeyDown(event) {\n if (isKeyboardEvent(event)) {\n const {\n active,\n context,\n options\n } = this.props;\n const {\n keyboardCodes = defaultKeyboardCodes,\n coordinateGetter = defaultKeyboardCoordinateGetter,\n scrollBehavior = 'smooth'\n } = options;\n const {\n code\n } = event;\n\n if (keyboardCodes.end.includes(code)) {\n this.handleEnd(event);\n return;\n }\n\n if (keyboardCodes.cancel.includes(code)) {\n this.handleCancel(event);\n return;\n }\n\n const {\n collisionRect\n } = context.current;\n const currentCoordinates = collisionRect ? {\n x: collisionRect.left,\n y: collisionRect.top\n } : defaultCoordinates;\n\n if (!this.referenceCoordinates) {\n this.referenceCoordinates = currentCoordinates;\n }\n\n const newCoordinates = coordinateGetter(event, {\n active,\n context: context.current,\n currentCoordinates\n });\n\n if (newCoordinates) {\n const coordinatesDelta = subtract(newCoordinates, currentCoordinates);\n const scrollDelta = {\n x: 0,\n y: 0\n };\n const {\n scrollableAncestors\n } = context.current;\n\n for (const scrollContainer of scrollableAncestors) {\n const direction = event.code;\n const {\n isTop,\n isRight,\n isLeft,\n isBottom,\n maxScroll,\n minScroll\n } = getScrollPosition(scrollContainer);\n const scrollElementRect = getScrollElementRect(scrollContainer);\n const clampedCoordinates = {\n x: Math.min(direction === KeyboardCode.Right ? scrollElementRect.right - scrollElementRect.width / 2 : scrollElementRect.right, Math.max(direction === KeyboardCode.Right ? scrollElementRect.left : scrollElementRect.left + scrollElementRect.width / 2, newCoordinates.x)),\n y: Math.min(direction === KeyboardCode.Down ? scrollElementRect.bottom - scrollElementRect.height / 2 : scrollElementRect.bottom, Math.max(direction === KeyboardCode.Down ? scrollElementRect.top : scrollElementRect.top + scrollElementRect.height / 2, newCoordinates.y))\n };\n const canScrollX = direction === KeyboardCode.Right && !isRight || direction === KeyboardCode.Left && !isLeft;\n const canScrollY = direction === KeyboardCode.Down && !isBottom || direction === KeyboardCode.Up && !isTop;\n\n if (canScrollX && clampedCoordinates.x !== newCoordinates.x) {\n const newScrollCoordinates = scrollContainer.scrollLeft + coordinatesDelta.x;\n const canScrollToNewCoordinates = direction === KeyboardCode.Right && newScrollCoordinates <= maxScroll.x || direction === KeyboardCode.Left && newScrollCoordinates >= minScroll.x;\n\n if (canScrollToNewCoordinates && !coordinatesDelta.y) {\n // We don't need to update coordinates, the scroll adjustment alone will trigger\n // logic to auto-detect the new container we are over\n scrollContainer.scrollTo({\n left: newScrollCoordinates,\n behavior: scrollBehavior\n });\n return;\n }\n\n if (canScrollToNewCoordinates) {\n scrollDelta.x = scrollContainer.scrollLeft - newScrollCoordinates;\n } else {\n scrollDelta.x = direction === KeyboardCode.Right ? scrollContainer.scrollLeft - maxScroll.x : scrollContainer.scrollLeft - minScroll.x;\n }\n\n if (scrollDelta.x) {\n scrollContainer.scrollBy({\n left: -scrollDelta.x,\n behavior: scrollBehavior\n });\n }\n\n break;\n } else if (canScrollY && clampedCoordinates.y !== newCoordinates.y) {\n const newScrollCoordinates = scrollContainer.scrollTop + coordinatesDelta.y;\n const canScrollToNewCoordinates = direction === KeyboardCode.Down && newScrollCoordinates <= maxScroll.y || direction === KeyboardCode.Up && newScrollCoordinates >= minScroll.y;\n\n if (canScrollToNewCoordinates && !coordinatesDelta.x) {\n // We don't need to update coordinates, the scroll adjustment alone will trigger\n // logic to auto-detect the new container we are over\n scrollContainer.scrollTo({\n top: newScrollCoordinates,\n behavior: scrollBehavior\n });\n return;\n }\n\n if (canScrollToNewCoordinates) {\n scrollDelta.y = scrollContainer.scrollTop - newScrollCoordinates;\n } else {\n scrollDelta.y = direction === KeyboardCode.Down ? scrollContainer.scrollTop - maxScroll.y : scrollContainer.scrollTop - minScroll.y;\n }\n\n if (scrollDelta.y) {\n scrollContainer.scrollBy({\n top: -scrollDelta.y,\n behavior: scrollBehavior\n });\n }\n\n break;\n }\n }\n\n this.handleMove(event, add(subtract(newCoordinates, this.referenceCoordinates), scrollDelta));\n }\n }\n }\n\n handleMove(event, coordinates) {\n const {\n onMove\n } = this.props;\n event.preventDefault();\n onMove(coordinates);\n }\n\n handleEnd(event) {\n const {\n onEnd\n } = this.props;\n event.preventDefault();\n this.detach();\n onEnd();\n }\n\n handleCancel(event) {\n const {\n onCancel\n } = this.props;\n event.preventDefault();\n this.detach();\n onCancel();\n }\n\n detach() {\n this.listeners.removeAll();\n this.windowListeners.removeAll();\n }\n\n}\nKeyboardSensor.activators = [{\n eventName: 'onKeyDown',\n handler: (event, _ref, _ref2) => {\n let {\n keyboardCodes = defaultKeyboardCodes,\n onActivation\n } = _ref;\n let {\n active\n } = _ref2;\n const {\n code\n } = event.nativeEvent;\n\n if (keyboardCodes.start.includes(code)) {\n const activator = active.activatorNode.current;\n\n if (activator && event.target !== activator) {\n return false;\n }\n\n event.preventDefault();\n onActivation == null ? void 0 : onActivation({\n event: event.nativeEvent\n });\n return true;\n }\n\n return false;\n }\n}];\n\nfunction isDistanceConstraint(constraint) {\n return Boolean(constraint && 'distance' in constraint);\n}\n\nfunction isDelayConstraint(constraint) {\n return Boolean(constraint && 'delay' in constraint);\n}\n\nclass AbstractPointerSensor {\n constructor(props, events, listenerTarget) {\n var _getEventCoordinates;\n\n if (listenerTarget === void 0) {\n listenerTarget = getEventListenerTarget(props.event.target);\n }\n\n this.props = void 0;\n this.events = void 0;\n this.autoScrollEnabled = true;\n this.document = void 0;\n this.activated = false;\n this.initialCoordinates = void 0;\n this.timeoutId = null;\n this.listeners = void 0;\n this.documentListeners = void 0;\n this.windowListeners = void 0;\n this.props = props;\n this.events = events;\n const {\n event\n } = props;\n const {\n target\n } = event;\n this.props = props;\n this.events = events;\n this.document = getOwnerDocument(target);\n this.documentListeners = new Listeners(this.document);\n this.listeners = new Listeners(listenerTarget);\n this.windowListeners = new Listeners(getWindow(target));\n this.initialCoordinates = (_getEventCoordinates = getEventCoordinates(event)) != null ? _getEventCoordinates : defaultCoordinates;\n this.handleStart = this.handleStart.bind(this);\n this.handleMove = this.handleMove.bind(this);\n this.handleEnd = this.handleEnd.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n this.handleKeydown = this.handleKeydown.bind(this);\n this.removeTextSelection = this.removeTextSelection.bind(this);\n this.attach();\n }\n\n attach() {\n const {\n events,\n props: {\n options: {\n activationConstraint,\n bypassActivationConstraint\n }\n }\n } = this;\n this.listeners.add(events.move.name, this.handleMove, {\n passive: false\n });\n this.listeners.add(events.end.name, this.handleEnd);\n\n if (events.cancel) {\n this.listeners.add(events.cancel.name, this.handleCancel);\n }\n\n this.windowListeners.add(EventName.Resize, this.handleCancel);\n this.windowListeners.add(EventName.DragStart, preventDefault);\n this.windowListeners.add(EventName.VisibilityChange, this.handleCancel);\n this.windowListeners.add(EventName.ContextMenu, preventDefault);\n this.documentListeners.add(EventName.Keydown, this.handleKeydown);\n\n if (activationConstraint) {\n if (bypassActivationConstraint != null && bypassActivationConstraint({\n event: this.props.event,\n activeNode: this.props.activeNode,\n options: this.props.options\n })) {\n return this.handleStart();\n }\n\n if (isDelayConstraint(activationConstraint)) {\n this.timeoutId = setTimeout(this.handleStart, activationConstraint.delay);\n this.handlePending(activationConstraint);\n return;\n }\n\n if (isDistanceConstraint(activationConstraint)) {\n this.handlePending(activationConstraint);\n return;\n }\n }\n\n this.handleStart();\n }\n\n detach() {\n this.listeners.removeAll();\n this.windowListeners.removeAll(); // Wait until the next event loop before removing document listeners\n // This is necessary because we listen for `click` and `selection` events on the document\n\n setTimeout(this.documentListeners.removeAll, 50);\n\n if (this.timeoutId !== null) {\n clearTimeout(this.timeoutId);\n this.timeoutId = null;\n }\n }\n\n handlePending(constraint, offset) {\n const {\n active,\n onPending\n } = this.props;\n onPending(active, constraint, this.initialCoordinates, offset);\n }\n\n handleStart() {\n const {\n initialCoordinates\n } = this;\n const {\n onStart\n } = this.props;\n\n if (initialCoordinates) {\n this.activated = true; // Stop propagation of click events once activation constraints are met\n\n this.documentListeners.add(EventName.Click, stopPropagation, {\n capture: true\n }); // Remove any text selection from the document\n\n this.removeTextSelection(); // Prevent further text selection while dragging\n\n this.documentListeners.add(EventName.SelectionChange, this.removeTextSelection);\n onStart(initialCoordinates);\n }\n }\n\n handleMove(event) {\n var _getEventCoordinates2;\n\n const {\n activated,\n initialCoordinates,\n props\n } = this;\n const {\n onMove,\n options: {\n activationConstraint\n }\n } = props;\n\n if (!initialCoordinates) {\n return;\n }\n\n const coordinates = (_getEventCoordinates2 = getEventCoordinates(event)) != null ? _getEventCoordinates2 : defaultCoordinates;\n const delta = subtract(initialCoordinates, coordinates); // Constraint validation\n\n if (!activated && activationConstraint) {\n if (isDistanceConstraint(activationConstraint)) {\n if (activationConstraint.tolerance != null && hasExceededDistance(delta, activationConstraint.tolerance)) {\n return this.handleCancel();\n }\n\n if (hasExceededDistance(delta, activationConstraint.distance)) {\n return this.handleStart();\n }\n }\n\n if (isDelayConstraint(activationConstraint)) {\n if (hasExceededDistance(delta, activationConstraint.tolerance)) {\n return this.handleCancel();\n }\n }\n\n this.handlePending(activationConstraint, delta);\n return;\n }\n\n if (event.cancelable) {\n event.preventDefault();\n }\n\n onMove(coordinates);\n }\n\n handleEnd() {\n const {\n onAbort,\n onEnd\n } = this.props;\n this.detach();\n\n if (!this.activated) {\n onAbort(this.props.active);\n }\n\n onEnd();\n }\n\n handleCancel() {\n const {\n onAbort,\n onCancel\n } = this.props;\n this.detach();\n\n if (!this.activated) {\n onAbort(this.props.active);\n }\n\n onCancel();\n }\n\n handleKeydown(event) {\n if (event.code === KeyboardCode.Esc) {\n this.handleCancel();\n }\n }\n\n removeTextSelection() {\n var _this$document$getSel;\n\n (_this$document$getSel = this.document.getSelection()) == null ? void 0 : _this$document$getSel.removeAllRanges();\n }\n\n}\n\nconst events = {\n cancel: {\n name: 'pointercancel'\n },\n move: {\n name: 'pointermove'\n },\n end: {\n name: 'pointerup'\n }\n};\nclass PointerSensor extends AbstractPointerSensor {\n constructor(props) {\n const {\n event\n } = props; // Pointer events stop firing if the target is unmounted while dragging\n // Therefore we attach listeners to the owner document instead\n\n const listenerTarget = getOwnerDocument(event.target);\n super(props, events, listenerTarget);\n }\n\n}\nPointerSensor.activators = [{\n eventName: 'onPointerDown',\n handler: (_ref, _ref2) => {\n let {\n nativeEvent: event\n } = _ref;\n let {\n onActivation\n } = _ref2;\n\n if (!event.isPrimary || event.button !== 0) {\n return false;\n }\n\n onActivation == null ? void 0 : onActivation({\n event\n });\n return true;\n }\n}];\n\nconst events$1 = {\n move: {\n name: 'mousemove'\n },\n end: {\n name: 'mouseup'\n }\n};\nvar MouseButton;\n\n(function (MouseButton) {\n MouseButton[MouseButton[\"RightClick\"] = 2] = \"RightClick\";\n})(MouseButton || (MouseButton = {}));\n\nclass MouseSensor extends AbstractPointerSensor {\n constructor(props) {\n super(props, events$1, getOwnerDocument(props.event.target));\n }\n\n}\nMouseSensor.activators = [{\n eventName: 'onMouseDown',\n handler: (_ref, _ref2) => {\n let {\n nativeEvent: event\n } = _ref;\n let {\n onActivation\n } = _ref2;\n\n if (event.button === MouseButton.RightClick) {\n return false;\n }\n\n onActivation == null ? void 0 : onActivation({\n event\n });\n return true;\n }\n}];\n\nconst events$2 = {\n cancel: {\n name: 'touchcancel'\n },\n move: {\n name: 'touchmove'\n },\n end: {\n name: 'touchend'\n }\n};\nclass TouchSensor extends AbstractPointerSensor {\n constructor(props) {\n super(props, events$2);\n }\n\n static setup() {\n // Adding a non-capture and non-passive `touchmove` listener in order\n // to force `event.preventDefault()` calls to work in dynamically added\n // touchmove event handlers. This is required for iOS Safari.\n window.addEventListener(events$2.move.name, noop, {\n capture: false,\n passive: false\n });\n return function teardown() {\n window.removeEventListener(events$2.move.name, noop);\n }; // We create a new handler because the teardown function of another sensor\n // could remove our event listener if we use a referentially equal listener.\n\n function noop() {}\n }\n\n}\nTouchSensor.activators = [{\n eventName: 'onTouchStart',\n handler: (_ref, _ref2) => {\n let {\n nativeEvent: event\n } = _ref;\n let {\n onActivation\n } = _ref2;\n const {\n touches\n } = event;\n\n if (touches.length > 1) {\n return false;\n }\n\n onActivation == null ? void 0 : onActivation({\n event\n });\n return true;\n }\n}];\n\nvar AutoScrollActivator;\n\n(function (AutoScrollActivator) {\n AutoScrollActivator[AutoScrollActivator[\"Pointer\"] = 0] = \"Pointer\";\n AutoScrollActivator[AutoScrollActivator[\"DraggableRect\"] = 1] = \"DraggableRect\";\n})(AutoScrollActivator || (AutoScrollActivator = {}));\n\nvar TraversalOrder;\n\n(function (TraversalOrder) {\n TraversalOrder[TraversalOrder[\"TreeOrder\"] = 0] = \"TreeOrder\";\n TraversalOrder[TraversalOrder[\"ReversedTreeOrder\"] = 1] = \"ReversedTreeOrder\";\n})(TraversalOrder || (TraversalOrder = {}));\n\nfunction useAutoScroller(_ref) {\n let {\n acceleration,\n activator = AutoScrollActivator.Pointer,\n canScroll,\n draggingRect,\n enabled,\n interval = 5,\n order = TraversalOrder.TreeOrder,\n pointerCoordinates,\n scrollableAncestors,\n scrollableAncestorRects,\n delta,\n threshold\n } = _ref;\n const scrollIntent = useScrollIntent({\n delta,\n disabled: !enabled\n });\n const [setAutoScrollInterval, clearAutoScrollInterval] = useInterval();\n const scrollSpeed = useRef({\n x: 0,\n y: 0\n });\n const scrollDirection = useRef({\n x: 0,\n y: 0\n });\n const rect = useMemo(() => {\n switch (activator) {\n case AutoScrollActivator.Pointer:\n return pointerCoordinates ? {\n top: pointerCoordinates.y,\n bottom: pointerCoordinates.y,\n left: pointerCoordinates.x,\n right: pointerCoordinates.x\n } : null;\n\n case AutoScrollActivator.DraggableRect:\n return draggingRect;\n }\n }, [activator, draggingRect, pointerCoordinates]);\n const scrollContainerRef = useRef(null);\n const autoScroll = useCallback(() => {\n const scrollContainer = scrollContainerRef.current;\n\n if (!scrollContainer) {\n return;\n }\n\n const scrollLeft = scrollSpeed.current.x * scrollDirection.current.x;\n const scrollTop = scrollSpeed.current.y * scrollDirection.current.y;\n scrollContainer.scrollBy(scrollLeft, scrollTop);\n }, []);\n const sortedScrollableAncestors = useMemo(() => order === TraversalOrder.TreeOrder ? [...scrollableAncestors].reverse() : scrollableAncestors, [order, scrollableAncestors]);\n useEffect(() => {\n if (!enabled || !scrollableAncestors.length || !rect) {\n clearAutoScrollInterval();\n return;\n }\n\n for (const scrollContainer of sortedScrollableAncestors) {\n if ((canScroll == null ? void 0 : canScroll(scrollContainer)) === false) {\n continue;\n }\n\n const index = scrollableAncestors.indexOf(scrollContainer);\n const scrollContainerRect = scrollableAncestorRects[index];\n\n if (!scrollContainerRect) {\n continue;\n }\n\n const {\n direction,\n speed\n } = getScrollDirectionAndSpeed(scrollContainer, scrollContainerRect, rect, acceleration, threshold);\n\n for (const axis of ['x', 'y']) {\n if (!scrollIntent[axis][direction[axis]]) {\n speed[axis] = 0;\n direction[axis] = 0;\n }\n }\n\n if (speed.x > 0 || speed.y > 0) {\n clearAutoScrollInterval();\n scrollContainerRef.current = scrollContainer;\n setAutoScrollInterval(autoScroll, interval);\n scrollSpeed.current = speed;\n scrollDirection.current = direction;\n return;\n }\n }\n\n scrollSpeed.current = {\n x: 0,\n y: 0\n };\n scrollDirection.current = {\n x: 0,\n y: 0\n };\n clearAutoScrollInterval();\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [acceleration, autoScroll, canScroll, clearAutoScrollInterval, enabled, interval, // eslint-disable-next-line react-hooks/exhaustive-deps\n JSON.stringify(rect), // eslint-disable-next-line react-hooks/exhaustive-deps\n JSON.stringify(scrollIntent), setAutoScrollInterval, scrollableAncestors, sortedScrollableAncestors, scrollableAncestorRects, // eslint-disable-next-line react-hooks/exhaustive-deps\n JSON.stringify(threshold)]);\n}\nconst defaultScrollIntent = {\n x: {\n [Direction.Backward]: false,\n [Direction.Forward]: false\n },\n y: {\n [Direction.Backward]: false,\n [Direction.Forward]: false\n }\n};\n\nfunction useScrollIntent(_ref2) {\n let {\n delta,\n disabled\n } = _ref2;\n const previousDelta = usePrevious(delta);\n return useLazyMemo(previousIntent => {\n if (disabled || !previousDelta || !previousIntent) {\n // Reset scroll intent tracking when auto-scrolling is disabled\n return defaultScrollIntent;\n }\n\n const direction = {\n x: Math.sign(delta.x - previousDelta.x),\n y: Math.sign(delta.y - previousDelta.y)\n }; // Keep track of the user intent to scroll in each direction for both axis\n\n return {\n x: {\n [Direction.Backward]: previousIntent.x[Direction.Backward] || direction.x === -1,\n [Direction.Forward]: previousIntent.x[Direction.Forward] || direction.x === 1\n },\n y: {\n [Direction.Backward]: previousIntent.y[Direction.Backward] || direction.y === -1,\n [Direction.Forward]: previousIntent.y[Direction.Forward] || direction.y === 1\n }\n };\n }, [disabled, delta, previousDelta]);\n}\n\nfunction useCachedNode(draggableNodes, id) {\n const draggableNode = id != null ? draggableNodes.get(id) : undefined;\n const node = draggableNode ? draggableNode.node.current : null;\n return useLazyMemo(cachedNode => {\n var _ref;\n\n if (id == null) {\n return null;\n } // In some cases, the draggable node can unmount while dragging\n // This is the case for virtualized lists. In those situations,\n // we fall back to the last known value for that node.\n\n\n return (_ref = node != null ? node : cachedNode) != null ? _ref : null;\n }, [node, id]);\n}\n\nfunction useCombineActivators(sensors, getSyntheticHandler) {\n return useMemo(() => sensors.reduce((accumulator, sensor) => {\n const {\n sensor: Sensor\n } = sensor;\n const sensorActivators = Sensor.activators.map(activator => ({\n eventName: activator.eventName,\n handler: getSyntheticHandler(activator.handler, sensor)\n }));\n return [...accumulator, ...sensorActivators];\n }, []), [sensors, getSyntheticHandler]);\n}\n\nvar MeasuringStrategy;\n\n(function (MeasuringStrategy) {\n MeasuringStrategy[MeasuringStrategy[\"Always\"] = 0] = \"Always\";\n MeasuringStrategy[MeasuringStrategy[\"BeforeDragging\"] = 1] = \"BeforeDragging\";\n MeasuringStrategy[MeasuringStrategy[\"WhileDragging\"] = 2] = \"WhileDragging\";\n})(MeasuringStrategy || (MeasuringStrategy = {}));\n\nvar MeasuringFrequency;\n\n(function (MeasuringFrequency) {\n MeasuringFrequency[\"Optimized\"] = \"optimized\";\n})(MeasuringFrequency || (MeasuringFrequency = {}));\n\nconst defaultValue = /*#__PURE__*/new Map();\nfunction useDroppableMeasuring(containers, _ref) {\n let {\n dragging,\n dependencies,\n config\n } = _ref;\n const [queue, setQueue] = useState(null);\n const {\n frequency,\n measure,\n strategy\n } = config;\n const containersRef = useRef(containers);\n const disabled = isDisabled();\n const disabledRef = useLatestValue(disabled);\n const measureDroppableContainers = useCallback(function (ids) {\n if (ids === void 0) {\n ids = [];\n }\n\n if (disabledRef.current) {\n return;\n }\n\n setQueue(value => {\n if (value === null) {\n return ids;\n }\n\n return value.concat(ids.filter(id => !value.includes(id)));\n });\n }, [disabledRef]);\n const timeoutId = useRef(null);\n const droppableRects = useLazyMemo(previousValue => {\n if (disabled && !dragging) {\n return defaultValue;\n }\n\n if (!previousValue || previousValue === defaultValue || containersRef.current !== containers || queue != null) {\n const map = new Map();\n\n for (let container of containers) {\n if (!container) {\n continue;\n }\n\n if (queue && queue.length > 0 && !queue.includes(container.id) && container.rect.current) {\n // This container does not need to be re-measured\n map.set(container.id, container.rect.current);\n continue;\n }\n\n const node = container.node.current;\n const rect = node ? new Rect(measure(node), node) : null;\n container.rect.current = rect;\n\n if (rect) {\n map.set(container.id, rect);\n }\n }\n\n return map;\n }\n\n return previousValue;\n }, [containers, queue, dragging, disabled, measure]);\n useEffect(() => {\n containersRef.current = containers;\n }, [containers]);\n useEffect(() => {\n if (disabled) {\n return;\n }\n\n measureDroppableContainers();\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [dragging, disabled]);\n useEffect(() => {\n if (queue && queue.length > 0) {\n setQueue(null);\n }\n }, //eslint-disable-next-line react-hooks/exhaustive-deps\n [JSON.stringify(queue)]);\n useEffect(() => {\n if (disabled || typeof frequency !== 'number' || timeoutId.current !== null) {\n return;\n }\n\n timeoutId.current = setTimeout(() => {\n measureDroppableContainers();\n timeoutId.current = null;\n }, frequency);\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [frequency, disabled, measureDroppableContainers, ...dependencies]);\n return {\n droppableRects,\n measureDroppableContainers,\n measuringScheduled: queue != null\n };\n\n function isDisabled() {\n switch (strategy) {\n case MeasuringStrategy.Always:\n return false;\n\n case MeasuringStrategy.BeforeDragging:\n return dragging;\n\n default:\n return !dragging;\n }\n }\n}\n\nfunction useInitialValue(value, computeFn) {\n return useLazyMemo(previousValue => {\n if (!value) {\n return null;\n }\n\n if (previousValue) {\n return previousValue;\n }\n\n return typeof computeFn === 'function' ? computeFn(value) : value;\n }, [computeFn, value]);\n}\n\nfunction useInitialRect(node, measure) {\n return useInitialValue(node, measure);\n}\n\n/**\r\n * Returns a new MutationObserver instance.\r\n * If `MutationObserver` is undefined in the execution environment, returns `undefined`.\r\n */\n\nfunction useMutationObserver(_ref) {\n let {\n callback,\n disabled\n } = _ref;\n const handleMutations = useEvent(callback);\n const mutationObserver = useMemo(() => {\n if (disabled || typeof window === 'undefined' || typeof window.MutationObserver === 'undefined') {\n return undefined;\n }\n\n const {\n MutationObserver\n } = window;\n return new MutationObserver(handleMutations);\n }, [handleMutations, disabled]);\n useEffect(() => {\n return () => mutationObserver == null ? void 0 : mutationObserver.disconnect();\n }, [mutationObserver]);\n return mutationObserver;\n}\n\n/**\r\n * Returns a new ResizeObserver instance bound to the `onResize` callback.\r\n * If `ResizeObserver` is undefined in the execution environment, returns `undefined`.\r\n */\n\nfunction useResizeObserver(_ref) {\n let {\n callback,\n disabled\n } = _ref;\n const handleResize = useEvent(callback);\n const resizeObserver = useMemo(() => {\n if (disabled || typeof window === 'undefined' || typeof window.ResizeObserver === 'undefined') {\n return undefined;\n }\n\n const {\n ResizeObserver\n } = window;\n return new ResizeObserver(handleResize);\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [disabled]);\n useEffect(() => {\n return () => resizeObserver == null ? void 0 : resizeObserver.disconnect();\n }, [resizeObserver]);\n return resizeObserver;\n}\n\nfunction defaultMeasure(element) {\n return new Rect(getClientRect(element), element);\n}\n\nfunction useRect(element, measure, fallbackRect) {\n if (measure === void 0) {\n measure = defaultMeasure;\n }\n\n const [rect, setRect] = useState(null);\n\n function measureRect() {\n setRect(currentRect => {\n if (!element) {\n return null;\n }\n\n if (element.isConnected === false) {\n var _ref;\n\n // Fall back to last rect we measured if the element is\n // no longer connected to the DOM.\n return (_ref = currentRect != null ? currentRect : fallbackRect) != null ? _ref : null;\n }\n\n const newRect = measure(element);\n\n if (JSON.stringify(currentRect) === JSON.stringify(newRect)) {\n return currentRect;\n }\n\n return newRect;\n });\n }\n\n const mutationObserver = useMutationObserver({\n callback(records) {\n if (!element) {\n return;\n }\n\n for (const record of records) {\n const {\n type,\n target\n } = record;\n\n if (type === 'childList' && target instanceof HTMLElement && target.contains(element)) {\n measureRect();\n break;\n }\n }\n }\n\n });\n const resizeObserver = useResizeObserver({\n callback: measureRect\n });\n useIsomorphicLayoutEffect(() => {\n measureRect();\n\n if (element) {\n resizeObserver == null ? void 0 : resizeObserver.observe(element);\n mutationObserver == null ? void 0 : mutationObserver.observe(document.body, {\n childList: true,\n subtree: true\n });\n } else {\n resizeObserver == null ? void 0 : resizeObserver.disconnect();\n mutationObserver == null ? void 0 : mutationObserver.disconnect();\n }\n }, [element]);\n return rect;\n}\n\nfunction useRectDelta(rect) {\n const initialRect = useInitialValue(rect);\n return getRectDelta(rect, initialRect);\n}\n\nconst defaultValue$1 = [];\nfunction useScrollableAncestors(node) {\n const previousNode = useRef(node);\n const ancestors = useLazyMemo(previousValue => {\n if (!node) {\n return defaultValue$1;\n }\n\n if (previousValue && previousValue !== defaultValue$1 && node && previousNode.current && node.parentNode === previousNode.current.parentNode) {\n return previousValue;\n }\n\n return getScrollableAncestors(node);\n }, [node]);\n useEffect(() => {\n previousNode.current = node;\n }, [node]);\n return ancestors;\n}\n\nfunction useScrollOffsets(elements) {\n const [scrollCoordinates, setScrollCoordinates] = useState(null);\n const prevElements = useRef(elements); // To-do: Throttle the handleScroll callback\n\n const handleScroll = useCallback(event => {\n const scrollingElement = getScrollableElement(event.target);\n\n if (!scrollingElement) {\n return;\n }\n\n setScrollCoordinates(scrollCoordinates => {\n if (!scrollCoordinates) {\n return null;\n }\n\n scrollCoordinates.set(scrollingElement, getScrollCoordinates(scrollingElement));\n return new Map(scrollCoordinates);\n });\n }, []);\n useEffect(() => {\n const previousElements = prevElements.current;\n\n if (elements !== previousElements) {\n cleanup(previousElements);\n const entries = elements.map(element => {\n const scrollableElement = getScrollableElement(element);\n\n if (scrollableElement) {\n scrollableElement.addEventListener('scroll', handleScroll, {\n passive: true\n });\n return [scrollableElement, getScrollCoordinates(scrollableElement)];\n }\n\n return null;\n }).filter(entry => entry != null);\n setScrollCoordinates(entries.length ? new Map(entries) : null);\n prevElements.current = elements;\n }\n\n return () => {\n cleanup(elements);\n cleanup(previousElements);\n };\n\n function cleanup(elements) {\n elements.forEach(element => {\n const scrollableElement = getScrollableElement(element);\n scrollableElement == null ? void 0 : scrollableElement.removeEventListener('scroll', handleScroll);\n });\n }\n }, [handleScroll, elements]);\n return useMemo(() => {\n if (elements.length) {\n return scrollCoordinates ? Array.from(scrollCoordinates.values()).reduce((acc, coordinates) => add(acc, coordinates), defaultCoordinates) : getScrollOffsets(elements);\n }\n\n return defaultCoordinates;\n }, [elements, scrollCoordinates]);\n}\n\nfunction useScrollOffsetsDelta(scrollOffsets, dependencies) {\n if (dependencies === void 0) {\n dependencies = [];\n }\n\n const initialScrollOffsets = useRef(null);\n useEffect(() => {\n initialScrollOffsets.current = null;\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n dependencies);\n useEffect(() => {\n const hasScrollOffsets = scrollOffsets !== defaultCoordinates;\n\n if (hasScrollOffsets && !initialScrollOffsets.current) {\n initialScrollOffsets.current = scrollOffsets;\n }\n\n if (!hasScrollOffsets && initialScrollOffsets.current) {\n initialScrollOffsets.current = null;\n }\n }, [scrollOffsets]);\n return initialScrollOffsets.current ? subtract(scrollOffsets, initialScrollOffsets.current) : defaultCoordinates;\n}\n\nfunction useSensorSetup(sensors) {\n useEffect(() => {\n if (!canUseDOM) {\n return;\n }\n\n const teardownFns = sensors.map(_ref => {\n let {\n sensor\n } = _ref;\n return sensor.setup == null ? void 0 : sensor.setup();\n });\n return () => {\n for (const teardown of teardownFns) {\n teardown == null ? void 0 : teardown();\n }\n };\n }, // TO-DO: Sensors length could theoretically change which would not be a valid dependency\n // eslint-disable-next-line react-hooks/exhaustive-deps\n sensors.map(_ref2 => {\n let {\n sensor\n } = _ref2;\n return sensor;\n }));\n}\n\nfunction useSyntheticListeners(listeners, id) {\n return useMemo(() => {\n return listeners.reduce((acc, _ref) => {\n let {\n eventName,\n handler\n } = _ref;\n\n acc[eventName] = event => {\n handler(event, id);\n };\n\n return acc;\n }, {});\n }, [listeners, id]);\n}\n\nfunction useWindowRect(element) {\n return useMemo(() => element ? getWindowClientRect(element) : null, [element]);\n}\n\nconst defaultValue$2 = [];\nfunction useRects(elements, measure) {\n if (measure === void 0) {\n measure = getClientRect;\n }\n\n const [firstElement] = elements;\n const windowRect = useWindowRect(firstElement ? getWindow(firstElement) : null);\n const [rects, setRects] = useState(defaultValue$2);\n\n function measureRects() {\n setRects(() => {\n if (!elements.length) {\n return defaultValue$2;\n }\n\n return elements.map(element => isDocumentScrollingElement(element) ? windowRect : new Rect(measure(element), element));\n });\n }\n\n const resizeObserver = useResizeObserver({\n callback: measureRects\n });\n useIsomorphicLayoutEffect(() => {\n resizeObserver == null ? void 0 : resizeObserver.disconnect();\n measureRects();\n elements.forEach(element => resizeObserver == null ? void 0 : resizeObserver.observe(element));\n }, [elements]);\n return rects;\n}\n\nfunction getMeasurableNode(node) {\n if (!node) {\n return null;\n }\n\n if (node.children.length > 1) {\n return node;\n }\n\n const firstChild = node.children[0];\n return isHTMLElement(firstChild) ? firstChild : node;\n}\n\nfunction useDragOverlayMeasuring(_ref) {\n let {\n measure\n } = _ref;\n const [rect, setRect] = useState(null);\n const handleResize = useCallback(entries => {\n for (const {\n target\n } of entries) {\n if (isHTMLElement(target)) {\n setRect(rect => {\n const newRect = measure(target);\n return rect ? { ...rect,\n width: newRect.width,\n height: newRect.height\n } : newRect;\n });\n break;\n }\n }\n }, [measure]);\n const resizeObserver = useResizeObserver({\n callback: handleResize\n });\n const handleNodeChange = useCallback(element => {\n const node = getMeasurableNode(element);\n resizeObserver == null ? void 0 : resizeObserver.disconnect();\n\n if (node) {\n resizeObserver == null ? void 0 : resizeObserver.observe(node);\n }\n\n setRect(node ? measure(node) : null);\n }, [measure, resizeObserver]);\n const [nodeRef, setRef] = useNodeRef(handleNodeChange);\n return useMemo(() => ({\n nodeRef,\n rect,\n setRef\n }), [rect, nodeRef, setRef]);\n}\n\nconst defaultSensors = [{\n sensor: PointerSensor,\n options: {}\n}, {\n sensor: KeyboardSensor,\n options: {}\n}];\nconst defaultData = {\n current: {}\n};\nconst defaultMeasuringConfiguration = {\n draggable: {\n measure: getTransformAgnosticClientRect\n },\n droppable: {\n measure: getTransformAgnosticClientRect,\n strategy: MeasuringStrategy.WhileDragging,\n frequency: MeasuringFrequency.Optimized\n },\n dragOverlay: {\n measure: getClientRect\n }\n};\n\nclass DroppableContainersMap extends Map {\n get(id) {\n var _super$get;\n\n return id != null ? (_super$get = super.get(id)) != null ? _super$get : undefined : undefined;\n }\n\n toArray() {\n return Array.from(this.values());\n }\n\n getEnabled() {\n return this.toArray().filter(_ref => {\n let {\n disabled\n } = _ref;\n return !disabled;\n });\n }\n\n getNodeFor(id) {\n var _this$get$node$curren, _this$get;\n\n return (_this$get$node$curren = (_this$get = this.get(id)) == null ? void 0 : _this$get.node.current) != null ? _this$get$node$curren : undefined;\n }\n\n}\n\nconst defaultPublicContext = {\n activatorEvent: null,\n active: null,\n activeNode: null,\n activeNodeRect: null,\n collisions: null,\n containerNodeRect: null,\n draggableNodes: /*#__PURE__*/new Map(),\n droppableRects: /*#__PURE__*/new Map(),\n droppableContainers: /*#__PURE__*/new DroppableContainersMap(),\n over: null,\n dragOverlay: {\n nodeRef: {\n current: null\n },\n rect: null,\n setRef: noop\n },\n scrollableAncestors: [],\n scrollableAncestorRects: [],\n measuringConfiguration: defaultMeasuringConfiguration,\n measureDroppableContainers: noop,\n windowRect: null,\n measuringScheduled: false\n};\nconst defaultInternalContext = {\n activatorEvent: null,\n activators: [],\n active: null,\n activeNodeRect: null,\n ariaDescribedById: {\n draggable: ''\n },\n dispatch: noop,\n draggableNodes: /*#__PURE__*/new Map(),\n over: null,\n measureDroppableContainers: noop\n};\nconst InternalContext = /*#__PURE__*/createContext(defaultInternalContext);\nconst PublicContext = /*#__PURE__*/createContext(defaultPublicContext);\n\nfunction getInitialState() {\n return {\n draggable: {\n active: null,\n initialCoordinates: {\n x: 0,\n y: 0\n },\n nodes: new Map(),\n translate: {\n x: 0,\n y: 0\n }\n },\n droppable: {\n containers: new DroppableContainersMap()\n }\n };\n}\nfunction reducer(state, action) {\n switch (action.type) {\n case Action.DragStart:\n return { ...state,\n draggable: { ...state.draggable,\n initialCoordinates: action.initialCoordinates,\n active: action.active\n }\n };\n\n case Action.DragMove:\n if (state.draggable.active == null) {\n return state;\n }\n\n return { ...state,\n draggable: { ...state.draggable,\n translate: {\n x: action.coordinates.x - state.draggable.initialCoordinates.x,\n y: action.coordinates.y - state.draggable.initialCoordinates.y\n }\n }\n };\n\n case Action.DragEnd:\n case Action.DragCancel:\n return { ...state,\n draggable: { ...state.draggable,\n active: null,\n initialCoordinates: {\n x: 0,\n y: 0\n },\n translate: {\n x: 0,\n y: 0\n }\n }\n };\n\n case Action.RegisterDroppable:\n {\n const {\n element\n } = action;\n const {\n id\n } = element;\n const containers = new DroppableContainersMap(state.droppable.containers);\n containers.set(id, element);\n return { ...state,\n droppable: { ...state.droppable,\n containers\n }\n };\n }\n\n case Action.SetDroppableDisabled:\n {\n const {\n id,\n key,\n disabled\n } = action;\n const element = state.droppable.containers.get(id);\n\n if (!element || key !== element.key) {\n return state;\n }\n\n const containers = new DroppableContainersMap(state.droppable.containers);\n containers.set(id, { ...element,\n disabled\n });\n return { ...state,\n droppable: { ...state.droppable,\n containers\n }\n };\n }\n\n case Action.UnregisterDroppable:\n {\n const {\n id,\n key\n } = action;\n const element = state.droppable.containers.get(id);\n\n if (!element || key !== element.key) {\n return state;\n }\n\n const containers = new DroppableContainersMap(state.droppable.containers);\n containers.delete(id);\n return { ...state,\n droppable: { ...state.droppable,\n containers\n }\n };\n }\n\n default:\n {\n return state;\n }\n }\n}\n\nfunction RestoreFocus(_ref) {\n let {\n disabled\n } = _ref;\n const {\n active,\n activatorEvent,\n draggableNodes\n } = useContext(InternalContext);\n const previousActivatorEvent = usePrevious(activatorEvent);\n const previousActiveId = usePrevious(active == null ? void 0 : active.id); // Restore keyboard focus on the activator node\n\n useEffect(() => {\n if (disabled) {\n return;\n }\n\n if (!activatorEvent && previousActivatorEvent && previousActiveId != null) {\n if (!isKeyboardEvent(previousActivatorEvent)) {\n return;\n }\n\n if (document.activeElement === previousActivatorEvent.target) {\n // No need to restore focus\n return;\n }\n\n const draggableNode = draggableNodes.get(previousActiveId);\n\n if (!draggableNode) {\n return;\n }\n\n const {\n activatorNode,\n node\n } = draggableNode;\n\n if (!activatorNode.current && !node.current) {\n return;\n }\n\n requestAnimationFrame(() => {\n for (const element of [activatorNode.current, node.current]) {\n if (!element) {\n continue;\n }\n\n const focusableNode = findFirstFocusableNode(element);\n\n if (focusableNode) {\n focusableNode.focus();\n break;\n }\n }\n });\n }\n }, [activatorEvent, disabled, draggableNodes, previousActiveId, previousActivatorEvent]);\n return null;\n}\n\nfunction applyModifiers(modifiers, _ref) {\n let {\n transform,\n ...args\n } = _ref;\n return modifiers != null && modifiers.length ? modifiers.reduce((accumulator, modifier) => {\n return modifier({\n transform: accumulator,\n ...args\n });\n }, transform) : transform;\n}\n\nfunction useMeasuringConfiguration(config) {\n return useMemo(() => ({\n draggable: { ...defaultMeasuringConfiguration.draggable,\n ...(config == null ? void 0 : config.draggable)\n },\n droppable: { ...defaultMeasuringConfiguration.droppable,\n ...(config == null ? void 0 : config.droppable)\n },\n dragOverlay: { ...defaultMeasuringConfiguration.dragOverlay,\n ...(config == null ? void 0 : config.dragOverlay)\n }\n }), // eslint-disable-next-line react-hooks/exhaustive-deps\n [config == null ? void 0 : config.draggable, config == null ? void 0 : config.droppable, config == null ? void 0 : config.dragOverlay]);\n}\n\nfunction useLayoutShiftScrollCompensation(_ref) {\n let {\n activeNode,\n measure,\n initialRect,\n config = true\n } = _ref;\n const initialized = useRef(false);\n const {\n x,\n y\n } = typeof config === 'boolean' ? {\n x: config,\n y: config\n } : config;\n useIsomorphicLayoutEffect(() => {\n const disabled = !x && !y;\n\n if (disabled || !activeNode) {\n initialized.current = false;\n return;\n }\n\n if (initialized.current || !initialRect) {\n // Return early if layout shift scroll compensation was already attempted\n // or if there is no initialRect to compare to.\n return;\n } // Get the most up to date node ref for the active draggable\n\n\n const node = activeNode == null ? void 0 : activeNode.node.current;\n\n if (!node || node.isConnected === false) {\n // Return early if there is no attached node ref or if the node is\n // disconnected from the document.\n return;\n }\n\n const rect = measure(node);\n const rectDelta = getRectDelta(rect, initialRect);\n\n if (!x) {\n rectDelta.x = 0;\n }\n\n if (!y) {\n rectDelta.y = 0;\n } // Only perform layout shift scroll compensation once\n\n\n initialized.current = true;\n\n if (Math.abs(rectDelta.x) > 0 || Math.abs(rectDelta.y) > 0) {\n const firstScrollableAncestor = getFirstScrollableAncestor(node);\n\n if (firstScrollableAncestor) {\n firstScrollableAncestor.scrollBy({\n top: rectDelta.y,\n left: rectDelta.x\n });\n }\n }\n }, [activeNode, x, y, initialRect, measure]);\n}\n\nconst ActiveDraggableContext = /*#__PURE__*/createContext({ ...defaultCoordinates,\n scaleX: 1,\n scaleY: 1\n});\nvar Status;\n\n(function (Status) {\n Status[Status[\"Uninitialized\"] = 0] = \"Uninitialized\";\n Status[Status[\"Initializing\"] = 1] = \"Initializing\";\n Status[Status[\"Initialized\"] = 2] = \"Initialized\";\n})(Status || (Status = {}));\n\nconst DndContext = /*#__PURE__*/memo(function DndContext(_ref) {\n var _sensorContext$curren, _dragOverlay$nodeRef$, _dragOverlay$rect, _over$rect;\n\n let {\n id,\n accessibility,\n autoScroll = true,\n children,\n sensors = defaultSensors,\n collisionDetection = rectIntersection,\n measuring,\n modifiers,\n ...props\n } = _ref;\n const store = useReducer(reducer, undefined, getInitialState);\n const [state, dispatch] = store;\n const [dispatchMonitorEvent, registerMonitorListener] = useDndMonitorProvider();\n const [status, setStatus] = useState(Status.Uninitialized);\n const isInitialized = status === Status.Initialized;\n const {\n draggable: {\n active: activeId,\n nodes: draggableNodes,\n translate\n },\n droppable: {\n containers: droppableContainers\n }\n } = state;\n const node = activeId != null ? draggableNodes.get(activeId) : null;\n const activeRects = useRef({\n initial: null,\n translated: null\n });\n const active = useMemo(() => {\n var _node$data;\n\n return activeId != null ? {\n id: activeId,\n // It's possible for the active node to unmount while dragging\n data: (_node$data = node == null ? void 0 : node.data) != null ? _node$data : defaultData,\n rect: activeRects\n } : null;\n }, [activeId, node]);\n const activeRef = useRef(null);\n const [activeSensor, setActiveSensor] = useState(null);\n const [activatorEvent, setActivatorEvent] = useState(null);\n const latestProps = useLatestValue(props, Object.values(props));\n const draggableDescribedById = useUniqueId(\"DndDescribedBy\", id);\n const enabledDroppableContainers = useMemo(() => droppableContainers.getEnabled(), [droppableContainers]);\n const measuringConfiguration = useMeasuringConfiguration(measuring);\n const {\n droppableRects,\n measureDroppableContainers,\n measuringScheduled\n } = useDroppableMeasuring(enabledDroppableContainers, {\n dragging: isInitialized,\n dependencies: [translate.x, translate.y],\n config: measuringConfiguration.droppable\n });\n const activeNode = useCachedNode(draggableNodes, activeId);\n const activationCoordinates = useMemo(() => activatorEvent ? getEventCoordinates(activatorEvent) : null, [activatorEvent]);\n const autoScrollOptions = getAutoScrollerOptions();\n const initialActiveNodeRect = useInitialRect(activeNode, measuringConfiguration.draggable.measure);\n useLayoutShiftScrollCompensation({\n activeNode: activeId != null ? draggableNodes.get(activeId) : null,\n config: autoScrollOptions.layoutShiftCompensation,\n initialRect: initialActiveNodeRect,\n measure: measuringConfiguration.draggable.measure\n });\n const activeNodeRect = useRect(activeNode, measuringConfiguration.draggable.measure, initialActiveNodeRect);\n const containerNodeRect = useRect(activeNode ? activeNode.parentElement : null);\n const sensorContext = useRef({\n activatorEvent: null,\n active: null,\n activeNode,\n collisionRect: null,\n collisions: null,\n droppableRects,\n draggableNodes,\n draggingNode: null,\n draggingNodeRect: null,\n droppableContainers,\n over: null,\n scrollableAncestors: [],\n scrollAdjustedTranslate: null\n });\n const overNode = droppableContainers.getNodeFor((_sensorContext$curren = sensorContext.current.over) == null ? void 0 : _sensorContext$curren.id);\n const dragOverlay = useDragOverlayMeasuring({\n measure: measuringConfiguration.dragOverlay.measure\n }); // Use the rect of the drag overlay if it is mounted\n\n const draggingNode = (_dragOverlay$nodeRef$ = dragOverlay.nodeRef.current) != null ? _dragOverlay$nodeRef$ : activeNode;\n const draggingNodeRect = isInitialized ? (_dragOverlay$rect = dragOverlay.rect) != null ? _dragOverlay$rect : activeNodeRect : null;\n const usesDragOverlay = Boolean(dragOverlay.nodeRef.current && dragOverlay.rect); // The delta between the previous and new position of the draggable node\n // is only relevant when there is no drag overlay\n\n const nodeRectDelta = useRectDelta(usesDragOverlay ? null : activeNodeRect); // Get the window rect of the dragging node\n\n const windowRect = useWindowRect(draggingNode ? getWindow(draggingNode) : null); // Get scrollable ancestors of the dragging node\n\n const scrollableAncestors = useScrollableAncestors(isInitialized ? overNode != null ? overNode : activeNode : null);\n const scrollableAncestorRects = useRects(scrollableAncestors); // Apply modifiers\n\n const modifiedTranslate = applyModifiers(modifiers, {\n transform: {\n x: translate.x - nodeRectDelta.x,\n y: translate.y - nodeRectDelta.y,\n scaleX: 1,\n scaleY: 1\n },\n activatorEvent,\n active,\n activeNodeRect,\n containerNodeRect,\n draggingNodeRect,\n over: sensorContext.current.over,\n overlayNodeRect: dragOverlay.rect,\n scrollableAncestors,\n scrollableAncestorRects,\n windowRect\n });\n const pointerCoordinates = activationCoordinates ? add(activationCoordinates, translate) : null;\n const scrollOffsets = useScrollOffsets(scrollableAncestors); // Represents the scroll delta since dragging was initiated\n\n const scrollAdjustment = useScrollOffsetsDelta(scrollOffsets); // Represents the scroll delta since the last time the active node rect was measured\n\n const activeNodeScrollDelta = useScrollOffsetsDelta(scrollOffsets, [activeNodeRect]);\n const scrollAdjustedTranslate = add(modifiedTranslate, scrollAdjustment);\n const collisionRect = draggingNodeRect ? getAdjustedRect(draggingNodeRect, modifiedTranslate) : null;\n const collisions = active && collisionRect ? collisionDetection({\n active,\n collisionRect,\n droppableRects,\n droppableContainers: enabledDroppableContainers,\n pointerCoordinates\n }) : null;\n const overId = getFirstCollision(collisions, 'id');\n const [over, setOver] = useState(null); // When there is no drag overlay used, we need to account for the\n // window scroll delta\n\n const appliedTranslate = usesDragOverlay ? modifiedTranslate : add(modifiedTranslate, activeNodeScrollDelta);\n const transform = adjustScale(appliedTranslate, (_over$rect = over == null ? void 0 : over.rect) != null ? _over$rect : null, activeNodeRect);\n const activeSensorRef = useRef(null);\n const instantiateSensor = useCallback((event, _ref2) => {\n let {\n sensor: Sensor,\n options\n } = _ref2;\n\n if (activeRef.current == null) {\n return;\n }\n\n const activeNode = draggableNodes.get(activeRef.current);\n\n if (!activeNode) {\n return;\n }\n\n const activatorEvent = event.nativeEvent;\n const sensorInstance = new Sensor({\n active: activeRef.current,\n activeNode,\n event: activatorEvent,\n options,\n // Sensors need to be instantiated with refs for arguments that change over time\n // otherwise they are frozen in time with the stale arguments\n context: sensorContext,\n\n onAbort(id) {\n const draggableNode = draggableNodes.get(id);\n\n if (!draggableNode) {\n return;\n }\n\n const {\n onDragAbort\n } = latestProps.current;\n const event = {\n id\n };\n onDragAbort == null ? void 0 : onDragAbort(event);\n dispatchMonitorEvent({\n type: 'onDragAbort',\n event\n });\n },\n\n onPending(id, constraint, initialCoordinates, offset) {\n const draggableNode = draggableNodes.get(id);\n\n if (!draggableNode) {\n return;\n }\n\n const {\n onDragPending\n } = latestProps.current;\n const event = {\n id,\n constraint,\n initialCoordinates,\n offset\n };\n onDragPending == null ? void 0 : onDragPending(event);\n dispatchMonitorEvent({\n type: 'onDragPending',\n event\n });\n },\n\n onStart(initialCoordinates) {\n const id = activeRef.current;\n\n if (id == null) {\n return;\n }\n\n const draggableNode = draggableNodes.get(id);\n\n if (!draggableNode) {\n return;\n }\n\n const {\n onDragStart\n } = latestProps.current;\n const event = {\n activatorEvent,\n active: {\n id,\n data: draggableNode.data,\n rect: activeRects\n }\n };\n unstable_batchedUpdates(() => {\n onDragStart == null ? void 0 : onDragStart(event);\n setStatus(Status.Initializing);\n dispatch({\n type: Action.DragStart,\n initialCoordinates,\n active: id\n });\n dispatchMonitorEvent({\n type: 'onDragStart',\n event\n });\n setActiveSensor(activeSensorRef.current);\n setActivatorEvent(activatorEvent);\n });\n },\n\n onMove(coordinates) {\n dispatch({\n type: Action.DragMove,\n coordinates\n });\n },\n\n onEnd: createHandler(Action.DragEnd),\n onCancel: createHandler(Action.DragCancel)\n });\n activeSensorRef.current = sensorInstance;\n\n function createHandler(type) {\n return async function handler() {\n const {\n active,\n collisions,\n over,\n scrollAdjustedTranslate\n } = sensorContext.current;\n let event = null;\n\n if (active && scrollAdjustedTranslate) {\n const {\n cancelDrop\n } = latestProps.current;\n event = {\n activatorEvent,\n active: active,\n collisions,\n delta: scrollAdjustedTranslate,\n over\n };\n\n if (type === Action.DragEnd && typeof cancelDrop === 'function') {\n const shouldCancel = await Promise.resolve(cancelDrop(event));\n\n if (shouldCancel) {\n type = Action.DragCancel;\n }\n }\n }\n\n activeRef.current = null;\n unstable_batchedUpdates(() => {\n dispatch({\n type\n });\n setStatus(Status.Uninitialized);\n setOver(null);\n setActiveSensor(null);\n setActivatorEvent(null);\n activeSensorRef.current = null;\n const eventName = type === Action.DragEnd ? 'onDragEnd' : 'onDragCancel';\n\n if (event) {\n const handler = latestProps.current[eventName];\n handler == null ? void 0 : handler(event);\n dispatchMonitorEvent({\n type: eventName,\n event\n });\n }\n });\n };\n }\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [draggableNodes]);\n const bindActivatorToSensorInstantiator = useCallback((handler, sensor) => {\n return (event, active) => {\n const nativeEvent = event.nativeEvent;\n const activeDraggableNode = draggableNodes.get(active);\n\n if ( // Another sensor is already instantiating\n activeRef.current !== null || // No active draggable\n !activeDraggableNode || // Event has already been captured\n nativeEvent.dndKit || nativeEvent.defaultPrevented) {\n return;\n }\n\n const activationContext = {\n active: activeDraggableNode\n };\n const shouldActivate = handler(event, sensor.options, activationContext);\n\n if (shouldActivate === true) {\n nativeEvent.dndKit = {\n capturedBy: sensor.sensor\n };\n activeRef.current = active;\n instantiateSensor(event, sensor);\n }\n };\n }, [draggableNodes, instantiateSensor]);\n const activators = useCombineActivators(sensors, bindActivatorToSensorInstantiator);\n useSensorSetup(sensors);\n useIsomorphicLayoutEffect(() => {\n if (activeNodeRect && status === Status.Initializing) {\n setStatus(Status.Initialized);\n }\n }, [activeNodeRect, status]);\n useEffect(() => {\n const {\n onDragMove\n } = latestProps.current;\n const {\n active,\n activatorEvent,\n collisions,\n over\n } = sensorContext.current;\n\n if (!active || !activatorEvent) {\n return;\n }\n\n const event = {\n active,\n activatorEvent,\n collisions,\n delta: {\n x: scrollAdjustedTranslate.x,\n y: scrollAdjustedTranslate.y\n },\n over\n };\n unstable_batchedUpdates(() => {\n onDragMove == null ? void 0 : onDragMove(event);\n dispatchMonitorEvent({\n type: 'onDragMove',\n event\n });\n });\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [scrollAdjustedTranslate.x, scrollAdjustedTranslate.y]);\n useEffect(() => {\n const {\n active,\n activatorEvent,\n collisions,\n droppableContainers,\n scrollAdjustedTranslate\n } = sensorContext.current;\n\n if (!active || activeRef.current == null || !activatorEvent || !scrollAdjustedTranslate) {\n return;\n }\n\n const {\n onDragOver\n } = latestProps.current;\n const overContainer = droppableContainers.get(overId);\n const over = overContainer && overContainer.rect.current ? {\n id: overContainer.id,\n rect: overContainer.rect.current,\n data: overContainer.data,\n disabled: overContainer.disabled\n } : null;\n const event = {\n active,\n activatorEvent,\n collisions,\n delta: {\n x: scrollAdjustedTranslate.x,\n y: scrollAdjustedTranslate.y\n },\n over\n };\n unstable_batchedUpdates(() => {\n setOver(over);\n onDragOver == null ? void 0 : onDragOver(event);\n dispatchMonitorEvent({\n type: 'onDragOver',\n event\n });\n });\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [overId]);\n useIsomorphicLayoutEffect(() => {\n sensorContext.current = {\n activatorEvent,\n active,\n activeNode,\n collisionRect,\n collisions,\n droppableRects,\n draggableNodes,\n draggingNode,\n draggingNodeRect,\n droppableContainers,\n over,\n scrollableAncestors,\n scrollAdjustedTranslate\n };\n activeRects.current = {\n initial: draggingNodeRect,\n translated: collisionRect\n };\n }, [active, activeNode, collisions, collisionRect, draggableNodes, draggingNode, draggingNodeRect, droppableRects, droppableContainers, over, scrollableAncestors, scrollAdjustedTranslate]);\n useAutoScroller({ ...autoScrollOptions,\n delta: translate,\n draggingRect: collisionRect,\n pointerCoordinates,\n scrollableAncestors,\n scrollableAncestorRects\n });\n const publicContext = useMemo(() => {\n const context = {\n active,\n activeNode,\n activeNodeRect,\n activatorEvent,\n collisions,\n containerNodeRect,\n dragOverlay,\n draggableNodes,\n droppableContainers,\n droppableRects,\n over,\n measureDroppableContainers,\n scrollableAncestors,\n scrollableAncestorRects,\n measuringConfiguration,\n measuringScheduled,\n windowRect\n };\n return context;\n }, [active, activeNode, activeNodeRect, activatorEvent, collisions, containerNodeRect, dragOverlay, draggableNodes, droppableContainers, droppableRects, over, measureDroppableContainers, scrollableAncestors, scrollableAncestorRects, measuringConfiguration, measuringScheduled, windowRect]);\n const internalContext = useMemo(() => {\n const context = {\n activatorEvent,\n activators,\n active,\n activeNodeRect,\n ariaDescribedById: {\n draggable: draggableDescribedById\n },\n dispatch,\n draggableNodes,\n over,\n measureDroppableContainers\n };\n return context;\n }, [activatorEvent, activators, active, activeNodeRect, dispatch, draggableDescribedById, draggableNodes, over, measureDroppableContainers]);\n return React.createElement(DndMonitorContext.Provider, {\n value: registerMonitorListener\n }, React.createElement(InternalContext.Provider, {\n value: internalContext\n }, React.createElement(PublicContext.Provider, {\n value: publicContext\n }, React.createElement(ActiveDraggableContext.Provider, {\n value: transform\n }, children)), React.createElement(RestoreFocus, {\n disabled: (accessibility == null ? void 0 : accessibility.restoreFocus) === false\n })), React.createElement(Accessibility, { ...accessibility,\n hiddenTextDescribedById: draggableDescribedById\n }));\n\n function getAutoScrollerOptions() {\n const activeSensorDisablesAutoscroll = (activeSensor == null ? void 0 : activeSensor.autoScrollEnabled) === false;\n const autoScrollGloballyDisabled = typeof autoScroll === 'object' ? autoScroll.enabled === false : autoScroll === false;\n const enabled = isInitialized && !activeSensorDisablesAutoscroll && !autoScrollGloballyDisabled;\n\n if (typeof autoScroll === 'object') {\n return { ...autoScroll,\n enabled\n };\n }\n\n return {\n enabled\n };\n }\n});\n\nconst NullContext = /*#__PURE__*/createContext(null);\nconst defaultRole = 'button';\nconst ID_PREFIX = 'Draggable';\nfunction useDraggable(_ref) {\n let {\n id,\n data,\n disabled = false,\n attributes\n } = _ref;\n const key = useUniqueId(ID_PREFIX);\n const {\n activators,\n activatorEvent,\n active,\n activeNodeRect,\n ariaDescribedById,\n draggableNodes,\n over\n } = useContext(InternalContext);\n const {\n role = defaultRole,\n roleDescription = 'draggable',\n tabIndex = 0\n } = attributes != null ? attributes : {};\n const isDragging = (active == null ? void 0 : active.id) === id;\n const transform = useContext(isDragging ? ActiveDraggableContext : NullContext);\n const [node, setNodeRef] = useNodeRef();\n const [activatorNode, setActivatorNodeRef] = useNodeRef();\n const listeners = useSyntheticListeners(activators, id);\n const dataRef = useLatestValue(data);\n useIsomorphicLayoutEffect(() => {\n draggableNodes.set(id, {\n id,\n key,\n node,\n activatorNode,\n data: dataRef\n });\n return () => {\n const node = draggableNodes.get(id);\n\n if (node && node.key === key) {\n draggableNodes.delete(id);\n }\n };\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [draggableNodes, id]);\n const memoizedAttributes = useMemo(() => ({\n role,\n tabIndex,\n 'aria-disabled': disabled,\n 'aria-pressed': isDragging && role === defaultRole ? true : undefined,\n 'aria-roledescription': roleDescription,\n 'aria-describedby': ariaDescribedById.draggable\n }), [disabled, role, tabIndex, isDragging, roleDescription, ariaDescribedById.draggable]);\n return {\n active,\n activatorEvent,\n activeNodeRect,\n attributes: memoizedAttributes,\n isDragging,\n listeners: disabled ? undefined : listeners,\n node,\n over,\n setNodeRef,\n setActivatorNodeRef,\n transform\n };\n}\n\nfunction useDndContext() {\n return useContext(PublicContext);\n}\n\nconst ID_PREFIX$1 = 'Droppable';\nconst defaultResizeObserverConfig = {\n timeout: 25\n};\nfunction useDroppable(_ref) {\n let {\n data,\n disabled = false,\n id,\n resizeObserverConfig\n } = _ref;\n const key = useUniqueId(ID_PREFIX$1);\n const {\n active,\n dispatch,\n over,\n measureDroppableContainers\n } = useContext(InternalContext);\n const previous = useRef({\n disabled\n });\n const resizeObserverConnected = useRef(false);\n const rect = useRef(null);\n const callbackId = useRef(null);\n const {\n disabled: resizeObserverDisabled,\n updateMeasurementsFor,\n timeout: resizeObserverTimeout\n } = { ...defaultResizeObserverConfig,\n ...resizeObserverConfig\n };\n const ids = useLatestValue(updateMeasurementsFor != null ? updateMeasurementsFor : id);\n const handleResize = useCallback(() => {\n if (!resizeObserverConnected.current) {\n // ResizeObserver invokes the `handleResize` callback as soon as `observe` is called,\n // assuming the element is rendered and displayed.\n resizeObserverConnected.current = true;\n return;\n }\n\n if (callbackId.current != null) {\n clearTimeout(callbackId.current);\n }\n\n callbackId.current = setTimeout(() => {\n measureDroppableContainers(Array.isArray(ids.current) ? ids.current : [ids.current]);\n callbackId.current = null;\n }, resizeObserverTimeout);\n }, //eslint-disable-next-line react-hooks/exhaustive-deps\n [resizeObserverTimeout]);\n const resizeObserver = useResizeObserver({\n callback: handleResize,\n disabled: resizeObserverDisabled || !active\n });\n const handleNodeChange = useCallback((newElement, previousElement) => {\n if (!resizeObserver) {\n return;\n }\n\n if (previousElement) {\n resizeObserver.unobserve(previousElement);\n resizeObserverConnected.current = false;\n }\n\n if (newElement) {\n resizeObserver.observe(newElement);\n }\n }, [resizeObserver]);\n const [nodeRef, setNodeRef] = useNodeRef(handleNodeChange);\n const dataRef = useLatestValue(data);\n useEffect(() => {\n if (!resizeObserver || !nodeRef.current) {\n return;\n }\n\n resizeObserver.disconnect();\n resizeObserverConnected.current = false;\n resizeObserver.observe(nodeRef.current);\n }, [nodeRef, resizeObserver]);\n useEffect(() => {\n dispatch({\n type: Action.RegisterDroppable,\n element: {\n id,\n key,\n disabled,\n node: nodeRef,\n rect,\n data: dataRef\n }\n });\n return () => dispatch({\n type: Action.UnregisterDroppable,\n key,\n id\n });\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [id]);\n useEffect(() => {\n if (disabled !== previous.current.disabled) {\n dispatch({\n type: Action.SetDroppableDisabled,\n id,\n key,\n disabled\n });\n previous.current.disabled = disabled;\n }\n }, [id, key, disabled, dispatch]);\n return {\n active,\n rect,\n isOver: (over == null ? void 0 : over.id) === id,\n node: nodeRef,\n over,\n setNodeRef\n };\n}\n\nfunction AnimationManager(_ref) {\n let {\n animation,\n children\n } = _ref;\n const [clonedChildren, setClonedChildren] = useState(null);\n const [element, setElement] = useState(null);\n const previousChildren = usePrevious(children);\n\n if (!children && !clonedChildren && previousChildren) {\n setClonedChildren(previousChildren);\n }\n\n useIsomorphicLayoutEffect(() => {\n if (!element) {\n return;\n }\n\n const key = clonedChildren == null ? void 0 : clonedChildren.key;\n const id = clonedChildren == null ? void 0 : clonedChildren.props.id;\n\n if (key == null || id == null) {\n setClonedChildren(null);\n return;\n }\n\n Promise.resolve(animation(id, element)).then(() => {\n setClonedChildren(null);\n });\n }, [animation, clonedChildren, element]);\n return React.createElement(React.Fragment, null, children, clonedChildren ? cloneElement(clonedChildren, {\n ref: setElement\n }) : null);\n}\n\nconst defaultTransform = {\n x: 0,\n y: 0,\n scaleX: 1,\n scaleY: 1\n};\nfunction NullifiedContextProvider(_ref) {\n let {\n children\n } = _ref;\n return React.createElement(InternalContext.Provider, {\n value: defaultInternalContext\n }, React.createElement(ActiveDraggableContext.Provider, {\n value: defaultTransform\n }, children));\n}\n\nconst baseStyles = {\n position: 'fixed',\n touchAction: 'none'\n};\n\nconst defaultTransition = activatorEvent => {\n const isKeyboardActivator = isKeyboardEvent(activatorEvent);\n return isKeyboardActivator ? 'transform 250ms ease' : undefined;\n};\n\nconst PositionedOverlay = /*#__PURE__*/forwardRef((_ref, ref) => {\n let {\n as,\n activatorEvent,\n adjustScale,\n children,\n className,\n rect,\n style,\n transform,\n transition = defaultTransition\n } = _ref;\n\n if (!rect) {\n return null;\n }\n\n const scaleAdjustedTransform = adjustScale ? transform : { ...transform,\n scaleX: 1,\n scaleY: 1\n };\n const styles = { ...baseStyles,\n width: rect.width,\n height: rect.height,\n top: rect.top,\n left: rect.left,\n transform: CSS.Transform.toString(scaleAdjustedTransform),\n transformOrigin: adjustScale && activatorEvent ? getRelativeTransformOrigin(activatorEvent, rect) : undefined,\n transition: typeof transition === 'function' ? transition(activatorEvent) : transition,\n ...style\n };\n return React.createElement(as, {\n className,\n style: styles,\n ref\n }, children);\n});\n\nconst defaultDropAnimationSideEffects = options => _ref => {\n let {\n active,\n dragOverlay\n } = _ref;\n const originalStyles = {};\n const {\n styles,\n className\n } = options;\n\n if (styles != null && styles.active) {\n for (const [key, value] of Object.entries(styles.active)) {\n if (value === undefined) {\n continue;\n }\n\n originalStyles[key] = active.node.style.getPropertyValue(key);\n active.node.style.setProperty(key, value);\n }\n }\n\n if (styles != null && styles.dragOverlay) {\n for (const [key, value] of Object.entries(styles.dragOverlay)) {\n if (value === undefined) {\n continue;\n }\n\n dragOverlay.node.style.setProperty(key, value);\n }\n }\n\n if (className != null && className.active) {\n active.node.classList.add(className.active);\n }\n\n if (className != null && className.dragOverlay) {\n dragOverlay.node.classList.add(className.dragOverlay);\n }\n\n return function cleanup() {\n for (const [key, value] of Object.entries(originalStyles)) {\n active.node.style.setProperty(key, value);\n }\n\n if (className != null && className.active) {\n active.node.classList.remove(className.active);\n }\n };\n};\n\nconst defaultKeyframeResolver = _ref2 => {\n let {\n transform: {\n initial,\n final\n }\n } = _ref2;\n return [{\n transform: CSS.Transform.toString(initial)\n }, {\n transform: CSS.Transform.toString(final)\n }];\n};\n\nconst defaultDropAnimationConfiguration = {\n duration: 250,\n easing: 'ease',\n keyframes: defaultKeyframeResolver,\n sideEffects: /*#__PURE__*/defaultDropAnimationSideEffects({\n styles: {\n active: {\n opacity: '0'\n }\n }\n })\n};\nfunction useDropAnimation(_ref3) {\n let {\n config,\n draggableNodes,\n droppableContainers,\n measuringConfiguration\n } = _ref3;\n return useEvent((id, node) => {\n if (config === null) {\n return;\n }\n\n const activeDraggable = draggableNodes.get(id);\n\n if (!activeDraggable) {\n return;\n }\n\n const activeNode = activeDraggable.node.current;\n\n if (!activeNode) {\n return;\n }\n\n const measurableNode = getMeasurableNode(node);\n\n if (!measurableNode) {\n return;\n }\n\n const {\n transform\n } = getWindow(node).getComputedStyle(node);\n const parsedTransform = parseTransform(transform);\n\n if (!parsedTransform) {\n return;\n }\n\n const animation = typeof config === 'function' ? config : createDefaultDropAnimation(config);\n scrollIntoViewIfNeeded(activeNode, measuringConfiguration.draggable.measure);\n return animation({\n active: {\n id,\n data: activeDraggable.data,\n node: activeNode,\n rect: measuringConfiguration.draggable.measure(activeNode)\n },\n draggableNodes,\n dragOverlay: {\n node,\n rect: measuringConfiguration.dragOverlay.measure(measurableNode)\n },\n droppableContainers,\n measuringConfiguration,\n transform: parsedTransform\n });\n });\n}\n\nfunction createDefaultDropAnimation(options) {\n const {\n duration,\n easing,\n sideEffects,\n keyframes\n } = { ...defaultDropAnimationConfiguration,\n ...options\n };\n return _ref4 => {\n let {\n active,\n dragOverlay,\n transform,\n ...rest\n } = _ref4;\n\n if (!duration) {\n // Do not animate if animation duration is zero.\n return;\n }\n\n const delta = {\n x: dragOverlay.rect.left - active.rect.left,\n y: dragOverlay.rect.top - active.rect.top\n };\n const scale = {\n scaleX: transform.scaleX !== 1 ? active.rect.width * transform.scaleX / dragOverlay.rect.width : 1,\n scaleY: transform.scaleY !== 1 ? active.rect.height * transform.scaleY / dragOverlay.rect.height : 1\n };\n const finalTransform = {\n x: transform.x - delta.x,\n y: transform.y - delta.y,\n ...scale\n };\n const animationKeyframes = keyframes({ ...rest,\n active,\n dragOverlay,\n transform: {\n initial: transform,\n final: finalTransform\n }\n });\n const [firstKeyframe] = animationKeyframes;\n const lastKeyframe = animationKeyframes[animationKeyframes.length - 1];\n\n if (JSON.stringify(firstKeyframe) === JSON.stringify(lastKeyframe)) {\n // The start and end keyframes are the same, infer that there is no animation needed.\n return;\n }\n\n const cleanup = sideEffects == null ? void 0 : sideEffects({\n active,\n dragOverlay,\n ...rest\n });\n const animation = dragOverlay.node.animate(animationKeyframes, {\n duration,\n easing,\n fill: 'forwards'\n });\n return new Promise(resolve => {\n animation.onfinish = () => {\n cleanup == null ? void 0 : cleanup();\n resolve();\n };\n });\n };\n}\n\nlet key = 0;\nfunction useKey(id) {\n return useMemo(() => {\n if (id == null) {\n return;\n }\n\n key++;\n return key;\n }, [id]);\n}\n\nconst DragOverlay = /*#__PURE__*/React.memo(_ref => {\n let {\n adjustScale = false,\n children,\n dropAnimation: dropAnimationConfig,\n style,\n transition,\n modifiers,\n wrapperElement = 'div',\n className,\n zIndex = 999\n } = _ref;\n const {\n activatorEvent,\n active,\n activeNodeRect,\n containerNodeRect,\n draggableNodes,\n droppableContainers,\n dragOverlay,\n over,\n measuringConfiguration,\n scrollableAncestors,\n scrollableAncestorRects,\n windowRect\n } = useDndContext();\n const transform = useContext(ActiveDraggableContext);\n const key = useKey(active == null ? void 0 : active.id);\n const modifiedTransform = applyModifiers(modifiers, {\n activatorEvent,\n active,\n activeNodeRect,\n containerNodeRect,\n draggingNodeRect: dragOverlay.rect,\n over,\n overlayNodeRect: dragOverlay.rect,\n scrollableAncestors,\n scrollableAncestorRects,\n transform,\n windowRect\n });\n const initialRect = useInitialValue(activeNodeRect);\n const dropAnimation = useDropAnimation({\n config: dropAnimationConfig,\n draggableNodes,\n droppableContainers,\n measuringConfiguration\n }); // We need to wait for the active node to be measured before connecting the drag overlay ref\n // otherwise collisions can be computed against a mispositioned drag overlay\n\n const ref = initialRect ? dragOverlay.setRef : undefined;\n return React.createElement(NullifiedContextProvider, null, React.createElement(AnimationManager, {\n animation: dropAnimation\n }, active && key ? React.createElement(PositionedOverlay, {\n key: key,\n id: active.id,\n ref: ref,\n as: wrapperElement,\n activatorEvent: activatorEvent,\n adjustScale: adjustScale,\n className: className,\n transition: transition,\n rect: initialRect,\n style: {\n zIndex,\n ...style\n },\n transform: modifiedTransform\n }, children) : null));\n});\n\nexport { AutoScrollActivator, DndContext, DragOverlay, KeyboardCode, KeyboardSensor, MeasuringFrequency, MeasuringStrategy, MouseSensor, PointerSensor, TouchSensor, TraversalOrder, applyModifiers, closestCenter, closestCorners, defaultAnnouncements, defaultCoordinates, defaultDropAnimationConfiguration as defaultDropAnimation, defaultDropAnimationSideEffects, defaultKeyboardCoordinateGetter, defaultScreenReaderInstructions, getClientRect, getFirstCollision, getScrollableAncestors, pointerWithin, rectIntersection, useDndContext, useDndMonitor, useDraggable, useDroppable, useSensor, useSensors };\n//# sourceMappingURL=core.esm.js.map\n","import React, { useMemo, useRef, useEffect, useState, useContext } from 'react';\nimport { useDndContext, getClientRect, useDroppable, useDraggable, closestCorners, getFirstCollision, getScrollableAncestors, KeyboardCode } from '@dnd-kit/core';\nimport { useUniqueId, useIsomorphicLayoutEffect, CSS, useCombinedRefs, isKeyboardEvent, subtract } from '@dnd-kit/utilities';\n\n/**\r\n * Move an array item to a different position. Returns a new array with the item moved to the new position.\r\n */\nfunction arrayMove(array, from, to) {\n const newArray = array.slice();\n newArray.splice(to < 0 ? newArray.length + to : to, 0, newArray.splice(from, 1)[0]);\n return newArray;\n}\n\n/**\r\n * Swap an array item to a different position. Returns a new array with the item swapped to the new position.\r\n */\nfunction arraySwap(array, from, to) {\n const newArray = array.slice();\n newArray[from] = array[to];\n newArray[to] = array[from];\n return newArray;\n}\n\nfunction getSortedRects(items, rects) {\n return items.reduce((accumulator, id, index) => {\n const rect = rects.get(id);\n\n if (rect) {\n accumulator[index] = rect;\n }\n\n return accumulator;\n }, Array(items.length));\n}\n\nfunction isValidIndex(index) {\n return index !== null && index >= 0;\n}\n\nfunction itemsEqual(a, b) {\n if (a === b) {\n return true;\n }\n\n if (a.length !== b.length) {\n return false;\n }\n\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) {\n return false;\n }\n }\n\n return true;\n}\n\nfunction normalizeDisabled(disabled) {\n if (typeof disabled === 'boolean') {\n return {\n draggable: disabled,\n droppable: disabled\n };\n }\n\n return disabled;\n}\n\n// To-do: We should be calculating scale transformation\nconst defaultScale = {\n scaleX: 1,\n scaleY: 1\n};\nconst horizontalListSortingStrategy = _ref => {\n var _rects$activeIndex;\n\n let {\n rects,\n activeNodeRect: fallbackActiveRect,\n activeIndex,\n overIndex,\n index\n } = _ref;\n const activeNodeRect = (_rects$activeIndex = rects[activeIndex]) != null ? _rects$activeIndex : fallbackActiveRect;\n\n if (!activeNodeRect) {\n return null;\n }\n\n const itemGap = getItemGap(rects, index, activeIndex);\n\n if (index === activeIndex) {\n const newIndexRect = rects[overIndex];\n\n if (!newIndexRect) {\n return null;\n }\n\n return {\n x: activeIndex < overIndex ? newIndexRect.left + newIndexRect.width - (activeNodeRect.left + activeNodeRect.width) : newIndexRect.left - activeNodeRect.left,\n y: 0,\n ...defaultScale\n };\n }\n\n if (index > activeIndex && index <= overIndex) {\n return {\n x: -activeNodeRect.width - itemGap,\n y: 0,\n ...defaultScale\n };\n }\n\n if (index < activeIndex && index >= overIndex) {\n return {\n x: activeNodeRect.width + itemGap,\n y: 0,\n ...defaultScale\n };\n }\n\n return {\n x: 0,\n y: 0,\n ...defaultScale\n };\n};\n\nfunction getItemGap(rects, index, activeIndex) {\n const currentRect = rects[index];\n const previousRect = rects[index - 1];\n const nextRect = rects[index + 1];\n\n if (!currentRect || !previousRect && !nextRect) {\n return 0;\n }\n\n if (activeIndex < index) {\n return previousRect ? currentRect.left - (previousRect.left + previousRect.width) : nextRect.left - (currentRect.left + currentRect.width);\n }\n\n return nextRect ? nextRect.left - (currentRect.left + currentRect.width) : currentRect.left - (previousRect.left + previousRect.width);\n}\n\nconst rectSortingStrategy = _ref => {\n let {\n rects,\n activeIndex,\n overIndex,\n index\n } = _ref;\n const newRects = arrayMove(rects, overIndex, activeIndex);\n const oldRect = rects[index];\n const newRect = newRects[index];\n\n if (!newRect || !oldRect) {\n return null;\n }\n\n return {\n x: newRect.left - oldRect.left,\n y: newRect.top - oldRect.top,\n scaleX: newRect.width / oldRect.width,\n scaleY: newRect.height / oldRect.height\n };\n};\n\nconst rectSwappingStrategy = _ref => {\n let {\n activeIndex,\n index,\n rects,\n overIndex\n } = _ref;\n let oldRect;\n let newRect;\n\n if (index === activeIndex) {\n oldRect = rects[index];\n newRect = rects[overIndex];\n }\n\n if (index === overIndex) {\n oldRect = rects[index];\n newRect = rects[activeIndex];\n }\n\n if (!newRect || !oldRect) {\n return null;\n }\n\n return {\n x: newRect.left - oldRect.left,\n y: newRect.top - oldRect.top,\n scaleX: newRect.width / oldRect.width,\n scaleY: newRect.height / oldRect.height\n };\n};\n\n// To-do: We should be calculating scale transformation\nconst defaultScale$1 = {\n scaleX: 1,\n scaleY: 1\n};\nconst verticalListSortingStrategy = _ref => {\n var _rects$activeIndex;\n\n let {\n activeIndex,\n activeNodeRect: fallbackActiveRect,\n index,\n rects,\n overIndex\n } = _ref;\n const activeNodeRect = (_rects$activeIndex = rects[activeIndex]) != null ? _rects$activeIndex : fallbackActiveRect;\n\n if (!activeNodeRect) {\n return null;\n }\n\n if (index === activeIndex) {\n const overIndexRect = rects[overIndex];\n\n if (!overIndexRect) {\n return null;\n }\n\n return {\n x: 0,\n y: activeIndex < overIndex ? overIndexRect.top + overIndexRect.height - (activeNodeRect.top + activeNodeRect.height) : overIndexRect.top - activeNodeRect.top,\n ...defaultScale$1\n };\n }\n\n const itemGap = getItemGap$1(rects, index, activeIndex);\n\n if (index > activeIndex && index <= overIndex) {\n return {\n x: 0,\n y: -activeNodeRect.height - itemGap,\n ...defaultScale$1\n };\n }\n\n if (index < activeIndex && index >= overIndex) {\n return {\n x: 0,\n y: activeNodeRect.height + itemGap,\n ...defaultScale$1\n };\n }\n\n return {\n x: 0,\n y: 0,\n ...defaultScale$1\n };\n};\n\nfunction getItemGap$1(clientRects, index, activeIndex) {\n const currentRect = clientRects[index];\n const previousRect = clientRects[index - 1];\n const nextRect = clientRects[index + 1];\n\n if (!currentRect) {\n return 0;\n }\n\n if (activeIndex < index) {\n return previousRect ? currentRect.top - (previousRect.top + previousRect.height) : nextRect ? nextRect.top - (currentRect.top + currentRect.height) : 0;\n }\n\n return nextRect ? nextRect.top - (currentRect.top + currentRect.height) : previousRect ? currentRect.top - (previousRect.top + previousRect.height) : 0;\n}\n\nconst ID_PREFIX = 'Sortable';\nconst Context = /*#__PURE__*/React.createContext({\n activeIndex: -1,\n containerId: ID_PREFIX,\n disableTransforms: false,\n items: [],\n overIndex: -1,\n useDragOverlay: false,\n sortedRects: [],\n strategy: rectSortingStrategy,\n disabled: {\n draggable: false,\n droppable: false\n }\n});\nfunction SortableContext(_ref) {\n let {\n children,\n id,\n items: userDefinedItems,\n strategy = rectSortingStrategy,\n disabled: disabledProp = false\n } = _ref;\n const {\n active,\n dragOverlay,\n droppableRects,\n over,\n measureDroppableContainers\n } = useDndContext();\n const containerId = useUniqueId(ID_PREFIX, id);\n const useDragOverlay = Boolean(dragOverlay.rect !== null);\n const items = useMemo(() => userDefinedItems.map(item => typeof item === 'object' && 'id' in item ? item.id : item), [userDefinedItems]);\n const isDragging = active != null;\n const activeIndex = active ? items.indexOf(active.id) : -1;\n const overIndex = over ? items.indexOf(over.id) : -1;\n const previousItemsRef = useRef(items);\n const itemsHaveChanged = !itemsEqual(items, previousItemsRef.current);\n const disableTransforms = overIndex !== -1 && activeIndex === -1 || itemsHaveChanged;\n const disabled = normalizeDisabled(disabledProp);\n useIsomorphicLayoutEffect(() => {\n if (itemsHaveChanged && isDragging) {\n measureDroppableContainers(items);\n }\n }, [itemsHaveChanged, items, isDragging, measureDroppableContainers]);\n useEffect(() => {\n previousItemsRef.current = items;\n }, [items]);\n const contextValue = useMemo(() => ({\n activeIndex,\n containerId,\n disabled,\n disableTransforms,\n items,\n overIndex,\n useDragOverlay,\n sortedRects: getSortedRects(items, droppableRects),\n strategy\n }), // eslint-disable-next-line react-hooks/exhaustive-deps\n [activeIndex, containerId, disabled.draggable, disabled.droppable, disableTransforms, items, overIndex, droppableRects, useDragOverlay, strategy]);\n return React.createElement(Context.Provider, {\n value: contextValue\n }, children);\n}\n\nconst defaultNewIndexGetter = _ref => {\n let {\n id,\n items,\n activeIndex,\n overIndex\n } = _ref;\n return arrayMove(items, activeIndex, overIndex).indexOf(id);\n};\nconst defaultAnimateLayoutChanges = _ref2 => {\n let {\n containerId,\n isSorting,\n wasDragging,\n index,\n items,\n newIndex,\n previousItems,\n previousContainerId,\n transition\n } = _ref2;\n\n if (!transition || !wasDragging) {\n return false;\n }\n\n if (previousItems !== items && index === newIndex) {\n return false;\n }\n\n if (isSorting) {\n return true;\n }\n\n return newIndex !== index && containerId === previousContainerId;\n};\nconst defaultTransition = {\n duration: 200,\n easing: 'ease'\n};\nconst transitionProperty = 'transform';\nconst disabledTransition = /*#__PURE__*/CSS.Transition.toString({\n property: transitionProperty,\n duration: 0,\n easing: 'linear'\n});\nconst defaultAttributes = {\n roleDescription: 'sortable'\n};\n\n/*\r\n * When the index of an item changes while sorting,\r\n * we need to temporarily disable the transforms\r\n */\n\nfunction useDerivedTransform(_ref) {\n let {\n disabled,\n index,\n node,\n rect\n } = _ref;\n const [derivedTransform, setDerivedtransform] = useState(null);\n const previousIndex = useRef(index);\n useIsomorphicLayoutEffect(() => {\n if (!disabled && index !== previousIndex.current && node.current) {\n const initial = rect.current;\n\n if (initial) {\n const current = getClientRect(node.current, {\n ignoreTransform: true\n });\n const delta = {\n x: initial.left - current.left,\n y: initial.top - current.top,\n scaleX: initial.width / current.width,\n scaleY: initial.height / current.height\n };\n\n if (delta.x || delta.y) {\n setDerivedtransform(delta);\n }\n }\n }\n\n if (index !== previousIndex.current) {\n previousIndex.current = index;\n }\n }, [disabled, index, node, rect]);\n useEffect(() => {\n if (derivedTransform) {\n setDerivedtransform(null);\n }\n }, [derivedTransform]);\n return derivedTransform;\n}\n\nfunction useSortable(_ref) {\n let {\n animateLayoutChanges = defaultAnimateLayoutChanges,\n attributes: userDefinedAttributes,\n disabled: localDisabled,\n data: customData,\n getNewIndex = defaultNewIndexGetter,\n id,\n strategy: localStrategy,\n resizeObserverConfig,\n transition = defaultTransition\n } = _ref;\n const {\n items,\n containerId,\n activeIndex,\n disabled: globalDisabled,\n disableTransforms,\n sortedRects,\n overIndex,\n useDragOverlay,\n strategy: globalStrategy\n } = useContext(Context);\n const disabled = normalizeLocalDisabled(localDisabled, globalDisabled);\n const index = items.indexOf(id);\n const data = useMemo(() => ({\n sortable: {\n containerId,\n index,\n items\n },\n ...customData\n }), [containerId, customData, index, items]);\n const itemsAfterCurrentSortable = useMemo(() => items.slice(items.indexOf(id)), [items, id]);\n const {\n rect,\n node,\n isOver,\n setNodeRef: setDroppableNodeRef\n } = useDroppable({\n id,\n data,\n disabled: disabled.droppable,\n resizeObserverConfig: {\n updateMeasurementsFor: itemsAfterCurrentSortable,\n ...resizeObserverConfig\n }\n });\n const {\n active,\n activatorEvent,\n activeNodeRect,\n attributes,\n setNodeRef: setDraggableNodeRef,\n listeners,\n isDragging,\n over,\n setActivatorNodeRef,\n transform\n } = useDraggable({\n id,\n data,\n attributes: { ...defaultAttributes,\n ...userDefinedAttributes\n },\n disabled: disabled.draggable\n });\n const setNodeRef = useCombinedRefs(setDroppableNodeRef, setDraggableNodeRef);\n const isSorting = Boolean(active);\n const displaceItem = isSorting && !disableTransforms && isValidIndex(activeIndex) && isValidIndex(overIndex);\n const shouldDisplaceDragSource = !useDragOverlay && isDragging;\n const dragSourceDisplacement = shouldDisplaceDragSource && displaceItem ? transform : null;\n const strategy = localStrategy != null ? localStrategy : globalStrategy;\n const finalTransform = displaceItem ? dragSourceDisplacement != null ? dragSourceDisplacement : strategy({\n rects: sortedRects,\n activeNodeRect,\n activeIndex,\n overIndex,\n index\n }) : null;\n const newIndex = isValidIndex(activeIndex) && isValidIndex(overIndex) ? getNewIndex({\n id,\n items,\n activeIndex,\n overIndex\n }) : index;\n const activeId = active == null ? void 0 : active.id;\n const previous = useRef({\n activeId,\n items,\n newIndex,\n containerId\n });\n const itemsHaveChanged = items !== previous.current.items;\n const shouldAnimateLayoutChanges = animateLayoutChanges({\n active,\n containerId,\n isDragging,\n isSorting,\n id,\n index,\n items,\n newIndex: previous.current.newIndex,\n previousItems: previous.current.items,\n previousContainerId: previous.current.containerId,\n transition,\n wasDragging: previous.current.activeId != null\n });\n const derivedTransform = useDerivedTransform({\n disabled: !shouldAnimateLayoutChanges,\n index,\n node,\n rect\n });\n useEffect(() => {\n if (isSorting && previous.current.newIndex !== newIndex) {\n previous.current.newIndex = newIndex;\n }\n\n if (containerId !== previous.current.containerId) {\n previous.current.containerId = containerId;\n }\n\n if (items !== previous.current.items) {\n previous.current.items = items;\n }\n }, [isSorting, newIndex, containerId, items]);\n useEffect(() => {\n if (activeId === previous.current.activeId) {\n return;\n }\n\n if (activeId != null && previous.current.activeId == null) {\n previous.current.activeId = activeId;\n return;\n }\n\n const timeoutId = setTimeout(() => {\n previous.current.activeId = activeId;\n }, 50);\n return () => clearTimeout(timeoutId);\n }, [activeId]);\n return {\n active,\n activeIndex,\n attributes,\n data,\n rect,\n index,\n newIndex,\n items,\n isOver,\n isSorting,\n isDragging,\n listeners,\n node,\n overIndex,\n over,\n setNodeRef,\n setActivatorNodeRef,\n setDroppableNodeRef,\n setDraggableNodeRef,\n transform: derivedTransform != null ? derivedTransform : finalTransform,\n transition: getTransition()\n };\n\n function getTransition() {\n if ( // Temporarily disable transitions for a single frame to set up derived transforms\n derivedTransform || // Or to prevent items jumping to back to their \"new\" position when items change\n itemsHaveChanged && previous.current.newIndex === index) {\n return disabledTransition;\n }\n\n if (shouldDisplaceDragSource && !isKeyboardEvent(activatorEvent) || !transition) {\n return undefined;\n }\n\n if (isSorting || shouldAnimateLayoutChanges) {\n return CSS.Transition.toString({ ...transition,\n property: transitionProperty\n });\n }\n\n return undefined;\n }\n}\n\nfunction normalizeLocalDisabled(localDisabled, globalDisabled) {\n var _localDisabled$dragga, _localDisabled$droppa;\n\n if (typeof localDisabled === 'boolean') {\n return {\n draggable: localDisabled,\n // Backwards compatibility\n droppable: false\n };\n }\n\n return {\n draggable: (_localDisabled$dragga = localDisabled == null ? void 0 : localDisabled.draggable) != null ? _localDisabled$dragga : globalDisabled.draggable,\n droppable: (_localDisabled$droppa = localDisabled == null ? void 0 : localDisabled.droppable) != null ? _localDisabled$droppa : globalDisabled.droppable\n };\n}\n\nfunction hasSortableData(entry) {\n if (!entry) {\n return false;\n }\n\n const data = entry.data.current;\n\n if (data && 'sortable' in data && typeof data.sortable === 'object' && 'containerId' in data.sortable && 'items' in data.sortable && 'index' in data.sortable) {\n return true;\n }\n\n return false;\n}\n\nconst directions = [KeyboardCode.Down, KeyboardCode.Right, KeyboardCode.Up, KeyboardCode.Left];\nconst sortableKeyboardCoordinates = (event, _ref) => {\n let {\n context: {\n active,\n collisionRect,\n droppableRects,\n droppableContainers,\n over,\n scrollableAncestors\n }\n } = _ref;\n\n if (directions.includes(event.code)) {\n event.preventDefault();\n\n if (!active || !collisionRect) {\n return;\n }\n\n const filteredContainers = [];\n droppableContainers.getEnabled().forEach(entry => {\n if (!entry || entry != null && entry.disabled) {\n return;\n }\n\n const rect = droppableRects.get(entry.id);\n\n if (!rect) {\n return;\n }\n\n switch (event.code) {\n case KeyboardCode.Down:\n if (collisionRect.top < rect.top) {\n filteredContainers.push(entry);\n }\n\n break;\n\n case KeyboardCode.Up:\n if (collisionRect.top > rect.top) {\n filteredContainers.push(entry);\n }\n\n break;\n\n case KeyboardCode.Left:\n if (collisionRect.left > rect.left) {\n filteredContainers.push(entry);\n }\n\n break;\n\n case KeyboardCode.Right:\n if (collisionRect.left < rect.left) {\n filteredContainers.push(entry);\n }\n\n break;\n }\n });\n const collisions = closestCorners({\n active,\n collisionRect: collisionRect,\n droppableRects,\n droppableContainers: filteredContainers,\n pointerCoordinates: null\n });\n let closestId = getFirstCollision(collisions, 'id');\n\n if (closestId === (over == null ? void 0 : over.id) && collisions.length > 1) {\n closestId = collisions[1].id;\n }\n\n if (closestId != null) {\n const activeDroppable = droppableContainers.get(active.id);\n const newDroppable = droppableContainers.get(closestId);\n const newRect = newDroppable ? droppableRects.get(newDroppable.id) : null;\n const newNode = newDroppable == null ? void 0 : newDroppable.node.current;\n\n if (newNode && newRect && activeDroppable && newDroppable) {\n const newScrollAncestors = getScrollableAncestors(newNode);\n const hasDifferentScrollAncestors = newScrollAncestors.some((element, index) => scrollableAncestors[index] !== element);\n const hasSameContainer = isSameContainer(activeDroppable, newDroppable);\n const isAfterActive = isAfter(activeDroppable, newDroppable);\n const offset = hasDifferentScrollAncestors || !hasSameContainer ? {\n x: 0,\n y: 0\n } : {\n x: isAfterActive ? collisionRect.width - newRect.width : 0,\n y: isAfterActive ? collisionRect.height - newRect.height : 0\n };\n const rectCoordinates = {\n x: newRect.left,\n y: newRect.top\n };\n const newCoordinates = offset.x && offset.y ? rectCoordinates : subtract(rectCoordinates, offset);\n return newCoordinates;\n }\n }\n }\n\n return undefined;\n};\n\nfunction isSameContainer(a, b) {\n if (!hasSortableData(a) || !hasSortableData(b)) {\n return false;\n }\n\n return a.data.current.sortable.containerId === b.data.current.sortable.containerId;\n}\n\nfunction isAfter(a, b) {\n if (!hasSortableData(a) || !hasSortableData(b)) {\n return false;\n }\n\n if (!isSameContainer(a, b)) {\n return false;\n }\n\n return a.data.current.sortable.index < b.data.current.sortable.index;\n}\n\nexport { SortableContext, arrayMove, arraySwap, defaultAnimateLayoutChanges, defaultNewIndexGetter, hasSortableData, horizontalListSortingStrategy, rectSortingStrategy, rectSwappingStrategy, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy };\n//# sourceMappingURL=sortable.esm.js.map\n","import { useEmailStore } from \"../store/emailStore\";\nimport type {\n EmailModule,\n EmailElement,\n TextElement,\n ImageElement,\n ButtonElement,\n SpacerElement,\n DividerElement,\n ProductGridElement,\n Theme,\n} from \"../core/types\";\nimport { resolveStyle, resolveToken } from \"../core/theme\";\nimport { Copy, Trash2, GripVertical, ArrowUp, ArrowDown, MousePointer2 } from \"lucide-react\";\nimport {\n DndContext,\n closestCenter,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n type DragEndEvent,\n} from \"@dnd-kit/core\";\nimport {\n SortableContext,\n sortableKeyboardCoordinates,\n useSortable,\n verticalListSortingStrategy,\n arrayMove,\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { useEffect, useState } from \"react\";\n\nconst MOBILE_WIDTH = 375;\n\n/**\n * Returns true when `color` is white or very light (luminance > 0.82).\n * Used by TextRender to add a canvas-only text-shadow so white text remains\n * readable while editing, without affecting the exported HTML.\n */\nfunction isColorLight(color: string): boolean {\n const hex = color.replace(\"#\", \"\");\n if (hex.length !== 3 && hex.length !== 6) {\n // Named colours: handle the most common ones.\n if (color === \"white\" || color === \"#fff\" || color === \"#ffffff\") return true;\n return false;\n }\n const full = hex.length === 3 ? hex.split(\"\").map((c) => c + c).join(\"\") : hex;\n const r = parseInt(full.slice(0, 2), 16) / 255;\n const g = parseInt(full.slice(2, 4), 16) / 255;\n const b = parseInt(full.slice(4, 6), 16) / 255;\n // sRGB relative luminance (approximate)\n const lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;\n return lum > 0.82;\n}\n\nfunction mergeMobile(\n style: Record<string, unknown> | undefined,\n viewMode: \"desktop\" | \"mobile\"\n): Record<string, unknown> {\n const base = (style ?? {}) as Record<string, unknown>;\n if (viewMode !== \"mobile\") return base;\n const mobile = (base.mobile as Record<string, unknown> | undefined) ?? {};\n return { ...base, ...mobile };\n}\n\nexport function Canvas() {\n const {\n doc,\n selection,\n setSelection,\n reorderModules,\n deleteModule,\n duplicateModule,\n deleteElement,\n moveElement,\n viewMode,\n } = useEmailStore();\n\n const sensors = useSensors(\n useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),\n useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })\n );\n\n const handleDragEnd = (e: DragEndEvent) => {\n const { active, over } = e;\n if (!over || active.id === over.id) return;\n const from = doc.modules.findIndex((m) => m.id === active.id);\n const to = doc.modules.findIndex((m) => m.id === over.id);\n if (from === -1 || to === -1) return;\n reorderModules(from, to);\n };\n\n // Keyboard delete (modules and elements)\n useEffect(() => {\n const handler = (e: KeyboardEvent) => {\n if (e.key !== \"Delete\" && e.key !== \"Backspace\") return;\n const target = e.target as HTMLElement;\n if (target.tagName === \"INPUT\" || target.tagName === \"TEXTAREA\" || target.isContentEditable)\n return;\n if (selection?.kind === \"module\") deleteModule(selection.moduleId);\n else if (selection?.kind === \"element\")\n deleteElement(selection.moduleId, selection.elementId);\n };\n window.addEventListener(\"keydown\", handler);\n return () => window.removeEventListener(\"keydown\", handler);\n }, [selection, deleteModule, deleteElement]);\n\n const bg = resolveToken(doc.settings.backgroundColor, doc.theme) as string;\n const cbg = resolveToken(doc.settings.contentBackgroundColor, doc.theme) as string;\n\n const reorderedIds = doc.modules.map((m) => m.id);\n const canvasWidth = viewMode === \"mobile\" ? MOBILE_WIDTH : doc.settings.width;\n\n return (\n <div\n className=\"flex-1 overflow-y-auto\"\n style={{ background: bg }}\n onClick={() => setSelection({ kind: \"email\" })}\n >\n <div className=\"py-8 flex justify-center\">\n <div\n className={`shadow-lg transition-all duration-200 ${viewMode === \"mobile\" ? \"rounded-[28px] border-[10px] border-gray-800\" : \"\"}`}\n style={{ width: canvasWidth, background: cbg, minHeight: 300 }}\n onClick={(e) => e.stopPropagation()}\n >\n {doc.modules.length === 0 && (\n <div className=\"p-12 text-center text-gray-400 text-sm\">\n Add modules from the left sidebar to start building your email.\n </div>\n )}\n <DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>\n <SortableContext items={reorderedIds} strategy={verticalListSortingStrategy}>\n {doc.modules.map((m, i) => (\n <SortableModule\n key={m.id}\n mod={m}\n index={i}\n viewMode={viewMode}\n selected={selection?.kind === \"module\" && selection.moduleId === m.id}\n selectionEl={\n selection?.kind === \"element\" && selection.moduleId === m.id\n ? selection.elementId\n : null\n }\n theme={doc.theme}\n onSelectModule={() => setSelection({ kind: \"module\", moduleId: m.id })}\n onSelectElement={(elId) =>\n setSelection({ kind: \"element\", moduleId: m.id, elementId: elId })\n }\n onDuplicate={() => duplicateModule(m.id)}\n onDelete={() => deleteModule(m.id)}\n />\n ))}\n </SortableContext>\n </DndContext>\n </div>\n </div>\n </div>\n );\n}\n\nfunction SortableModule(props: {\n mod: EmailModule;\n index: number;\n viewMode: \"desktop\" | \"mobile\";\n selected: boolean;\n selectionEl: string | null;\n theme: Theme;\n onSelectModule: () => void;\n onSelectElement: (id: string) => void;\n onDuplicate: () => void;\n onDelete: () => void;\n}) {\n const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({\n id: props.mod.id,\n });\n const style: React.CSSProperties = {\n transform: CSS.Transform.toString(transform),\n transition,\n opacity: isDragging ? 0.5 : 1,\n position: \"relative\",\n // Lift the selected module above its siblings so the selection toolbar\n // (which overflows outside the block bounds) is never obscured.\n zIndex: props.selected ? 10 : \"auto\",\n };\n return (\n <div ref={setNodeRef} style={style}>\n <ModuleView\n mod={props.mod}\n viewMode={props.viewMode}\n selected={props.selected}\n selectionEl={props.selectionEl}\n theme={props.theme}\n onSelectModule={props.onSelectModule}\n onSelectElement={props.onSelectElement}\n onDuplicate={props.onDuplicate}\n onDelete={props.onDelete}\n dragHandle={\n <button\n {...attributes}\n {...listeners}\n className=\"bg-blue-600 text-white p-1 rounded cursor-grab active:cursor-grabbing\"\n title=\"Drag to reorder\"\n onClick={(e) => e.stopPropagation()}\n >\n <GripVertical size={14} />\n </button>\n }\n />\n </div>\n );\n}\n\nfunction ModuleView({\n mod,\n viewMode,\n selected,\n selectionEl,\n theme,\n onSelectModule,\n onSelectElement,\n onDuplicate,\n onDelete,\n dragHandle,\n}: {\n mod: EmailModule;\n viewMode: \"desktop\" | \"mobile\";\n selected: boolean;\n selectionEl: string | null;\n theme: Theme;\n onSelectModule: () => void;\n onSelectElement: (id: string) => void;\n onDuplicate: () => void;\n onDelete: () => void;\n dragHandle: React.ReactNode;\n}) {\n const rawStyle = (mod.style ?? {}) as Record<string, unknown>;\n const hideOn = rawStyle.hideOn as \"mobile\" | \"desktop\" | undefined;\n if (hideOn === viewMode) return null;\n const merged = mergeMobile(rawStyle, viewMode);\n const s = resolveStyle(merged, theme);\n const [hovered, setHovered] = useState(false);\n const moduleStyle: React.CSSProperties = {\n backgroundColor: s.backgroundColor as string,\n paddingTop: (s.paddingTop as number) ?? 0,\n paddingBottom: (s.paddingBottom as number) ?? 0,\n paddingLeft: (s.paddingLeft as number) ?? 0,\n paddingRight: (s.paddingRight as number) ?? 0,\n borderRadius: s.borderRadius as number,\n position: \"relative\",\n outline: selected\n ? \"2px solid #2563eb\"\n : hovered\n ? \"1px dashed #93c5fd\"\n : \"1px dashed transparent\",\n outlineOffset: -2,\n cursor: \"pointer\",\n };\n\n return (\n <div\n style={moduleStyle}\n onClick={(e) => {\n e.stopPropagation();\n onSelectModule();\n }}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n >\n {/* Hover label (when not selected) makes it obvious what block you're targeting */}\n {!selected && hovered && (\n <div className=\"absolute top-0 right-0 z-10 bg-blue-600 text-white text-[10px] px-1.5 py-0.5 rounded-bl pointer-events-none\">\n Click to select: {mod.name}\n </div>\n )}\n {selected && (\n // Toolbar sits INSIDE the block at the top-left so it is never clipped\n // by the scroll container or hidden above the first block in the canvas.\n <div\n className=\"absolute top-0 left-0 z-20 flex items-center gap-1 p-1 rounded-br bg-blue-600 shadow-md\"\n onClick={(e) => e.stopPropagation()}\n >\n {dragHandle}\n <button\n onClick={(e) => {\n e.stopPropagation();\n onDuplicate();\n }}\n className=\"text-white p-1 rounded hover:bg-blue-700\"\n title=\"Duplicate\"\n >\n <Copy size={14} />\n </button>\n <button\n onClick={(e) => {\n e.stopPropagation();\n onDelete();\n }}\n className=\"text-white p-1 rounded hover:bg-red-600\"\n title=\"Delete\"\n >\n <Trash2 size={14} />\n </button>\n <span className=\"text-white text-[10px] font-medium px-1.5 py-0.5\">\n {mod.name}\n </span>\n </div>\n )}\n {mod.children.map((c, i) => (\n <ElementView\n key={c.id}\n el={c}\n index={i}\n totalElements={mod.children.length}\n viewMode={viewMode}\n theme={theme}\n moduleId={mod.id}\n moduleSelected={selected}\n selected={selectionEl === c.id}\n onSelect={() => onSelectElement(c.id)}\n onSelectModule={onSelectModule}\n />\n ))}\n </div>\n );\n}\n\nfunction ElementView({\n el,\n index,\n totalElements,\n viewMode,\n theme,\n moduleId,\n moduleSelected,\n selected,\n onSelect,\n onSelectModule,\n}: {\n el: EmailElement;\n index: number;\n totalElements: number;\n viewMode: \"desktop\" | \"mobile\";\n theme: Theme;\n moduleId: string;\n moduleSelected: boolean;\n selected: boolean;\n onSelect: () => void;\n onSelectModule: () => void;\n}) {\n const moveElement = useEmailStore((s) => s.moveElement);\n const deleteElement = useEmailStore((s) => s.deleteElement);\n const elStyle = (el as { style?: Record<string, unknown> }).style;\n const hideOn = elStyle?.hideOn as \"mobile\" | \"desktop\" | undefined;\n if (hideOn === viewMode) return null;\n const wrapStyle: React.CSSProperties = {\n // Amber outline when selected; a faint border otherwise so element\n // boundaries stay visible even when text colour is white or near-white.\n outline: selected ? \"2px solid #f59e0b\" : \"1px dashed rgba(0,0,0,0.08)\",\n outlineOffset: -1,\n position: \"relative\",\n };\n // Two-click drilldown: clicking an element when its module is not selected\n // selects the MODULE first; a second click then drills into the element.\n // This makes module selection intuitive (you don't keep landing on a child).\n const handle = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (!moduleSelected && !selected) {\n onSelectModule();\n return;\n }\n onSelect();\n };\n\n const toolbar = selected && (\n <div\n className=\"absolute top-0 right-0 z-20 flex items-center gap-1 p-1 rounded-bl bg-amber-500 shadow-md\"\n onClick={(e) => e.stopPropagation()}\n >\n <button\n onClick={() => onSelectModule()}\n className=\"text-white p-1 rounded hover:bg-amber-600\"\n title=\"Select parent block\"\n >\n <MousePointer2 size={12} />\n </button>\n <button\n disabled={index === 0}\n onClick={() => moveElement(moduleId, el.id, -1)}\n className=\"text-white p-1 rounded disabled:opacity-40 hover:bg-amber-600\"\n title=\"Move up\"\n >\n <ArrowUp size={12} />\n </button>\n <button\n disabled={index === totalElements - 1}\n onClick={() => moveElement(moduleId, el.id, 1)}\n className=\"text-white p-1 rounded disabled:opacity-40 hover:bg-amber-600\"\n title=\"Move down\"\n >\n <ArrowDown size={12} />\n </button>\n <button\n onClick={() => deleteElement(moduleId, el.id)}\n className=\"text-white p-1 rounded hover:bg-red-600\"\n title=\"Delete element\"\n >\n <Trash2 size={12} />\n </button>\n <span className=\"text-white text-[10px] font-medium px-1 py-0.5\">\n {el.type}\n </span>\n </div>\n );\n\n const wrapWith = (inner: React.ReactNode) => (\n <div style={wrapStyle} onClick={handle}>\n {toolbar}\n {inner}\n </div>\n );\n\n switch (el.type) {\n case \"text\":\n return wrapWith(<TextRender el={el} viewMode={viewMode} theme={theme} moduleId={moduleId} />);\n case \"image\":\n return wrapWith(<ImageRender el={el} viewMode={viewMode} theme={theme} />);\n case \"button\":\n return wrapWith(<ButtonRender el={el} viewMode={viewMode} theme={theme} />);\n case \"spacer\":\n return wrapWith(<SpacerRender el={el} />);\n case \"divider\":\n return wrapWith(<DividerRender el={el} viewMode={viewMode} theme={theme} />);\n case \"productGrid\":\n return wrapWith(<ProductGridRender el={el} viewMode={viewMode} theme={theme} />);\n }\n}\n\nfunction TextRender({\n el,\n viewMode,\n theme,\n moduleId,\n}: {\n el: TextElement;\n viewMode: \"desktop\" | \"mobile\";\n theme: Theme;\n moduleId: string;\n}) {\n const updateElement = useEmailStore((s) => s.updateElement);\n const merged = mergeMobile(el.style as Record<string, unknown>, viewMode);\n const s = resolveStyle(merged, theme);\n const color = (s.color as string) ?? \"#000000\";\n\n // Canvas-only: add a subtle text-shadow when the text colour is very light\n // (white or near-white) so content is readable against any module background\n // while editing. This shadow is NOT present in the exported HTML.\n const isLightColor = isColorLight(color);\n\n const style: React.CSSProperties = {\n fontFamily: s.fontFamily as string,\n fontSize: s.fontSize as number,\n lineHeight: s.lineHeight as number,\n letterSpacing: s.letterSpacing as number,\n fontWeight: s.fontWeight as React.CSSProperties[\"fontWeight\"],\n color,\n textAlign: s.align as React.CSSProperties[\"textAlign\"],\n paddingTop: (s.paddingTop as number) ?? 8,\n paddingBottom: (s.paddingBottom as number) ?? 8,\n paddingLeft: (s.paddingLeft as number) ?? 16,\n paddingRight: (s.paddingRight as number) ?? 16,\n margin: 0,\n minHeight: \"1.5em\",\n ...(isLightColor\n ? { textShadow: \"0 0 8px rgba(0,0,0,0.55), 0 1px 2px rgba(0,0,0,0.45)\" }\n : undefined),\n };\n return (\n <div\n style={style}\n contentEditable\n suppressContentEditableWarning\n onBlur={(e) => {\n const next = e.currentTarget.innerHTML;\n if (next !== el.content) {\n updateElement(moduleId, el.id, { content: next } as Partial<TextElement>);\n }\n }}\n dangerouslySetInnerHTML={{ __html: el.content }}\n />\n );\n}\n\nfunction ImageRender({ el, viewMode, theme }: { el: ImageElement; viewMode: \"desktop\" | \"mobile\"; theme: Theme }) {\n const merged = mergeMobile(el.style as Record<string, unknown>, viewMode);\n const s = resolveStyle(merged, theme);\n const wrap: React.CSSProperties = {\n textAlign: (s.align as React.CSSProperties[\"textAlign\"]) ?? \"center\",\n paddingTop: (s.paddingTop as number) ?? 0,\n paddingBottom: (s.paddingBottom as number) ?? 0,\n paddingLeft: (s.paddingLeft as number) ?? 0,\n paddingRight: (s.paddingRight as number) ?? 0,\n };\n const img: React.CSSProperties = {\n display: \"inline-block\",\n maxWidth: \"100%\",\n width: s.width as number,\n height: (s.height as number) || \"auto\",\n borderRadius: s.borderRadius as number,\n };\n return (\n <div style={wrap}>\n <img src={el.src} alt={el.alt ?? \"\"} style={img} />\n </div>\n );\n}\n\nfunction ButtonRender({ el, viewMode, theme }: { el: ButtonElement; viewMode: \"desktop\" | \"mobile\"; theme: Theme }) {\n const merged = mergeMobile(el.style as Record<string, unknown>, viewMode);\n const s = resolveStyle(merged, theme);\n const wrap: React.CSSProperties = {\n textAlign: (s.align as React.CSSProperties[\"textAlign\"]) ?? \"center\",\n paddingTop: (s.paddingTop as number) ?? 12,\n paddingBottom: (s.paddingBottom as number) ?? 12,\n paddingLeft: (s.paddingLeft as number) ?? 16,\n paddingRight: (s.paddingRight as number) ?? 16,\n };\n const btn: React.CSSProperties = {\n display: \"inline-block\",\n backgroundColor: (s.backgroundColor as string) ?? \"#3A7D52\",\n color: (s.color as string) ?? \"#fff\",\n fontFamily: s.fontFamily as string,\n fontSize: (s.fontSize as number) ?? 16,\n fontWeight: (s.fontWeight as React.CSSProperties[\"fontWeight\"]) ?? \"bold\",\n borderRadius: (s.borderRadius as number) ?? 6,\n padding: \"12px 24px\",\n textDecoration: \"none\",\n };\n return (\n <div style={wrap}>\n <span style={btn}>{el.label}</span>\n </div>\n );\n}\n\nfunction SpacerRender({ el }: { el: SpacerElement }) {\n return <div style={{ height: el.height, background: \"rgba(0,0,0,0.02)\" }} />;\n}\n\nfunction DividerRender({ el, viewMode, theme }: { el: DividerElement; viewMode: \"desktop\" | \"mobile\"; theme: Theme }) {\n const merged = mergeMobile(el.style as Record<string, unknown>, viewMode);\n const s = resolveStyle(merged, theme);\n return (\n <div\n style={{\n paddingTop: (s.paddingTop as number) ?? 8,\n paddingBottom: (s.paddingBottom as number) ?? 8,\n }}\n >\n <hr\n style={{\n border: 0,\n borderTop: `${(s.thickness as number) ?? 1}px solid ${(s.color as string) ?? \"#E5E7EB\"}`,\n margin: 0,\n }}\n />\n </div>\n );\n}\n\nfunction ProductGridRender({\n el,\n viewMode,\n theme,\n}: {\n el: ProductGridElement;\n viewMode: \"desktop\" | \"mobile\";\n theme: Theme;\n}) {\n const merged = mergeMobile(el.style as Record<string, unknown>, viewMode);\n const s = resolveStyle(merged, theme);\n const isMobile = viewMode === \"mobile\";\n const cols = el.columns;\n const cardBg =\n (s.cardBackgroundColor as string) ?? (s.backgroundColor as string) ?? \"transparent\";\n const nameColor = (s.nameColor as string) ?? \"#111827\";\n const finalColor = (s.finalPriceColor as string) ?? \"#3A7D52\";\n const oldColor = (s.oldPriceColor as string) ?? \"#9CA3AF\";\n const btnBg = (s.buttonBackgroundColor as string) ?? \"#3A7D52\";\n const btnColor = (s.buttonColor as string) ?? \"#FFFFFF\";\n const radius = (s.borderRadius as number) ?? 0;\n\n const wrapStyle: React.CSSProperties = {\n paddingTop: (s.paddingTop as number) ?? 16,\n paddingBottom: (s.paddingBottom as number) ?? 16,\n paddingLeft: (s.paddingLeft as number) ?? 16,\n paddingRight: (s.paddingRight as number) ?? 16,\n display: \"flex\",\n flexWrap: \"wrap\",\n gap: 8,\n };\n\n return (\n <div style={wrapStyle}>\n {el.products.map((p) => {\n const cellStyle: React.CSSProperties = {\n width: isMobile ? \"100%\" : `calc(${100 / cols}% - 8px)`,\n background: cardBg,\n borderRadius: radius,\n overflow: \"hidden\",\n display: \"flex\",\n flexDirection: \"column\",\n };\n return (\n <div key={p.id} style={cellStyle}>\n <img\n src={p.image}\n alt={p.imageAlt ?? p.name}\n style={{ display: \"block\", width: \"100%\", height: \"auto\", borderRadius: radius }}\n />\n <div\n style={{\n padding: \"12px 12px 4px 12px\",\n fontFamily: \"Arial, Helvetica, sans-serif\",\n fontSize: 15,\n fontWeight: \"bold\",\n color: nameColor,\n lineHeight: 1.3,\n }}\n >\n {p.name}\n </div>\n <div style={{ padding: \"0 12px 8px 12px\", fontFamily: \"Arial, Helvetica, sans-serif\" }}>\n {el.showOldPrice && p.oldPrice && (\n <span\n className=\"old_price\"\n style={{\n color: oldColor,\n textDecoration: \"line-through\",\n fontSize: 14,\n marginRight: 8,\n }}\n >\n {p.oldPrice}\n </span>\n )}\n <span\n className=\"final_price\"\n style={{ color: finalColor, fontWeight: \"bold\", fontSize: 18 }}\n >\n {p.finalPrice}\n </span>\n </div>\n {el.showDescription && p.description && (\n <div\n style={{\n padding: \"0 12px 8px 12px\",\n fontFamily: \"Arial, Helvetica, sans-serif\",\n fontSize: 13,\n color: \"#6B7280\",\n lineHeight: 1.5,\n }}\n >\n {p.description}\n </div>\n )}\n {el.showButton && (\n <div style={{ padding: \"4px 12px 12px 12px\", textAlign: \"center\", marginTop: \"auto\" }}>\n <span\n style={{\n display: \"inline-block\",\n padding: \"10px 18px\",\n fontFamily: \"Arial, Helvetica, sans-serif\",\n fontSize: 13,\n fontWeight: \"bold\",\n color: btnColor,\n backgroundColor: btnBg,\n borderRadius: 6,\n }}\n >\n {p.buttonLabel ?? el.buttonLabel ?? \"Shop now\"}\n </span>\n </div>\n )}\n </div>\n );\n })}\n </div>\n );\n}\n","// Plugin API. Plugins can add modules, themes, AI providers, asset providers.\nimport type { ModuleDefinition } from \"../modules/registry\";\nimport { moduleRegistry } from \"../modules/registry\";\nimport type { Theme } from \"./types\";\nimport type { AIProvider } from \"./aiActions\";\nimport { setAIProvider as setReactiveAIProvider } from \"../ai/state\";\n\nexport interface AssetProvider {\n upload: (file: File) => Promise<{ url: string; alt?: string }>;\n}\n\nexport interface BuilderHandle {\n registerModule: (def: ModuleDefinition) => void;\n registerTheme: (theme: Theme) => void;\n registerAssetProvider: (provider: AssetProvider) => void;\n setAIProvider: (provider: AIProvider) => void;\n}\n\nexport type PluginType = \"modules\" | \"themes\" | \"asset-provider\" | \"ai-provider\";\n\nexport interface Plugin {\n name: string;\n type: PluginType;\n setup: (builder: BuilderHandle) => void;\n}\n\nconst themes: Theme[] = [];\nlet assetProvider: AssetProvider | null = null;\nlet aiProvider: AIProvider | null = null;\n\nexport const builder: BuilderHandle = {\n registerModule: (def) => moduleRegistry.register(def),\n registerTheme: (t) => themes.push(t),\n registerAssetProvider: (p) => {\n assetProvider = p;\n },\n setAIProvider: (p) => {\n aiProvider = p;\n // Notify the reactive store so the AI chat panel appears/updates.\n setReactiveAIProvider(p);\n },\n};\n\nexport function registerPlugin(plugin: Plugin) {\n plugin.setup(builder);\n}\n\nexport function getRegisteredThemes(): Theme[] {\n return themes;\n}\n\nexport function getAssetProvider(): AssetProvider | null {\n return assetProvider;\n}\n\nexport function getAIProvider(): AIProvider | null {\n return aiProvider;\n}\n","// Recommendation logic — ports the legacy Vibetrace logic-builder concept.\n// The full logic JSON is stored on the module under `module.data.recommendations`.\n// Any module that contains a `productGrid` child becomes \"product-aware\" and the\n// Recommendations panel auto-appears in the right sidebar when the module is selected.\n\nimport type { EmailModule } from \"../core/types\";\n\nexport type RecommendationMode = \"manual\" | \"recommender\";\n\nexport type FallbackId = \"smart-reccs\" | \"random\" | \"ignore\" | \"stop\";\n\nexport interface AlgorithmParamSpec {\n key: string;\n label: string;\n type: \"select\" | \"text\" | \"number\";\n options?: Array<{ value: string | number; label: string }>;\n default?: string | number;\n}\n\nexport interface AlgorithmDefinition {\n id: string;\n label: string;\n group?: \"behavioral\" | \"catalog\" | \"personal\" | \"contextual\";\n params?: AlgorithmParamSpec[];\n}\n\nexport interface StackEntry {\n algorithm: string;\n params?: Record<string, string | number | boolean>;\n}\n\nexport interface RecommendationFilters {\n /** Product IDs / SKUs to include (manual or boost). */\n includeProducts: string[];\n /** Product IDs / SKUs to exclude. */\n excludeProducts: string[];\n /** Categories to include. */\n includeCategories: string[];\n /** Categories to exclude. */\n excludeCategories: string[];\n minStock?: number;\n minPrice?: number;\n mainOnly?: boolean;\n higherPrice?: boolean;\n salesPrice?: boolean;\n sameCategory?: boolean;\n matchTitle?: boolean;\n /** Comma-separated property keys to match on, e.g. \"brand,color\". */\n sameField?: string;\n /** Free-form advanced JSON overrides. */\n advanced?: Record<string, unknown>;\n}\n\nexport interface RecommendationsLogic {\n mode: RecommendationMode;\n noProducts: number;\n /** Source feed id (for manual mode). */\n sourceFeed?: string;\n /** Manually-picked product ids (manual mode). */\n manualProducts: string[];\n /** Algorithm stack — tried in order. Max 3. */\n stack: StackEntry[];\n /** Last-resort algorithm. */\n fallback: FallbackId;\n filters: RecommendationFilters;\n}\n\n// ---------------------------------------------------------------------------\n// Algorithm catalog — ported from Vibetrace CONSTANTS.algorithms\n// ---------------------------------------------------------------------------\n\nconst daysParam: AlgorithmParamSpec = {\n key: \"days\",\n label: \"Time window\",\n type: \"select\",\n default: 7,\n options: [\n { value: 7, label: \"Last 7 days\" },\n { value: 14, label: \"Last 14 days\" },\n { value: 30, label: \"Last 30 days\" },\n ],\n};\n\nexport const ALGORITHMS: AlgorithmDefinition[] = [\n { id: \"abandoned-cart\", label: \"Abandoned basket products\", group: \"behavioral\" },\n { id: \"bestseller-conversion\", label: \"Best seller by Conversion\", group: \"catalog\", params: [daysParam] },\n { id: \"bestseller-units\", label: \"Best seller by Units\", group: \"catalog\", params: [daysParam] },\n { id: \"new-products\", label: \"New items added\", group: \"catalog\", params: [daysParam] },\n { id: \"cross-sell\", label: \"Products Cross-Sell\", group: \"contextual\" },\n { id: \"upsell\", label: \"Products Upsell\", group: \"contextual\" },\n { id: \"viewed-categories\", label: \"Items from viewed categories\", group: \"behavioral\" },\n { id: \"viewed-items\", label: \"Items viewed\", group: \"behavioral\" },\n { id: \"similar-basket\", label: \"Similar to basket items\", group: \"behavioral\" },\n { id: \"bought-together\", label: \"Items bought together\", group: \"contextual\" },\n { id: \"best-discount\", label: \"Items with the best discount\", group: \"catalog\" },\n { id: \"match-data\", label: \"Items matching specific attributes\", group: \"catalog\" },\n { id: \"last-purchased\", label: \"Last purchased items\", group: \"personal\" },\n { id: \"similar-to-purchased\", label: \"Similar to last purchase\", group: \"personal\" },\n { id: \"cross-sell-purchased\", label: \"Cross-sell to last purchase\", group: \"personal\" },\n { id: \"similar-items\", label: \"Similar items\", group: \"contextual\" },\n];\n\nexport const ALGORITHM_BY_ID: Record<string, AlgorithmDefinition> = Object.fromEntries(\n ALGORITHMS.map((a) => [a.id, a])\n);\n\nexport const FALLBACK_OPTIONS: Array<{ value: FallbackId; label: string; description: string }> = [\n { value: \"smart-reccs\", label: \"Smart Recommendations\", description: \"Best generic algorithm — recommended default.\" },\n { value: \"random\", label: \"Random items (strict filters)\", description: \"Random items that still pass include/exclude filters.\" },\n { value: \"ignore\", label: \"Ignore position\", description: \"Skip the slot if no items found.\" },\n { value: \"stop\", label: \"Don't display\", description: \"Don't render the email if the slot can't be filled.\" },\n];\n\nexport const MAX_STACK = 3;\n\nexport function defaultLogic(noProducts = 2): RecommendationsLogic {\n return {\n mode: \"recommender\",\n noProducts,\n sourceFeed: \"\",\n manualProducts: [],\n stack: [{ algorithm: \"abandoned-cart\" }],\n fallback: \"smart-reccs\",\n filters: {\n includeProducts: [],\n excludeProducts: [],\n includeCategories: [],\n excludeCategories: [],\n minStock: 0,\n minPrice: 0,\n mainOnly: false,\n higherPrice: false,\n salesPrice: false,\n sameCategory: false,\n matchTitle: false,\n sameField: \"\",\n },\n };\n}\n\n/** Read recommendations logic from a module, returning defaults if absent. */\nexport function readLogic(data: Record<string, unknown> | undefined): RecommendationsLogic | null {\n if (!data) return null;\n const raw = data[\"recommendations\"];\n if (!raw || typeof raw !== \"object\") return null;\n return raw as RecommendationsLogic;\n}\n\n/** A module is \"product-aware\" if any of its children renders products. */\nexport function isProductAware(m: EmailModule): boolean {\n if (!m?.children) return false;\n return m.children.some((c) => c.type === \"productGrid\");\n}\n\n/** Count of product slots the module currently shows (used as default noProducts). */\nexport function productSlotCount(m: EmailModule): number {\n if (!m?.children) return 0;\n let n = 0;\n for (const c of m.children) {\n if (c.type === \"productGrid\") n += c.products.length;\n }\n return n;\n}\n\n/** Serialize back to legacy Vibetrace-shaped JSON for backend interop. */\nexport function toLegacyShape(l: RecommendationsLogic) {\n return {\n params: {\n selection: l.mode === \"manual\" ? \"manual\" : \"recommender\",\n include: {\n item: l.filters.includeProducts,\n category: l.filters.includeCategories,\n },\n exclude: {\n item: l.filters.excludeProducts,\n category: l.filters.excludeCategories,\n },\n higherPrice: l.filters.higherPrice ?? false,\n salesPrice: l.filters.salesPrice ?? false,\n sameCategory: l.filters.sameCategory ?? false,\n matchTitle: l.filters.matchTitle ?? false,\n sameField: l.filters.sameField ?? \"\",\n mainOnly: l.filters.mainOnly ?? false,\n },\n noProducts: String(l.noProducts),\n fallback: l.fallback,\n stack: l.mode === \"manual\" ? [] : l.stack,\n minStock: String(l.filters.minStock ?? 0),\n minPrice: String(l.filters.minPrice ?? 0),\n sourceFeed: l.sourceFeed ?? \"\",\n manualProducts: l.manualProducts,\n };\n}\n","import { useState } from \"react\";\nimport { ChevronUp, ChevronDown, Trash2, Plus, X, Sparkles, Hand } from \"lucide-react\";\nimport { useEmailStore } from \"../store/emailStore\";\nimport type { EmailModule } from \"../core/types\";\nimport {\n ALGORITHMS,\n ALGORITHM_BY_ID,\n FALLBACK_OPTIONS,\n MAX_STACK,\n defaultLogic,\n readLogic,\n productSlotCount,\n type RecommendationsLogic,\n type StackEntry,\n} from \"../recommendations/logic\";\n\ninterface Props {\n mod: EmailModule;\n}\n\nexport function RecommendationsPanel({ mod }: Props) {\n const updateModule = useEmailStore((s) => s.updateModule);\n const slots = productSlotCount(mod) || 2;\n const logic = readLogic(mod.data) ?? defaultLogic(slots);\n\n const update = (patch: Partial<RecommendationsLogic>) => {\n const next = { ...logic, ...patch };\n updateModule(mod.id, { data: { ...(mod.data ?? {}), recommendations: next } });\n };\n\n const updateFilters = (patch: Partial<RecommendationsLogic[\"filters\"]>) =>\n update({ filters: { ...logic.filters, ...patch } });\n\n return (\n <div className=\"border border-blue-200 rounded-lg bg-blue-50/40 mt-4 overflow-hidden\">\n <div className=\"px-3 py-2 flex items-center gap-2 border-b border-blue-200 bg-blue-50\">\n <Sparkles size={14} className=\"text-blue-700\" />\n <div className=\"text-xs font-semibold text-blue-900 uppercase tracking-wide\">\n Products Source\n </div>\n </div>\n\n {/* Step 1 — choose how products are sourced */}\n <div className=\"p-3 bg-white border-b border-blue-100\">\n <div className=\"grid grid-cols-2 gap-2\">\n <ModeCard\n active={logic.mode === \"manual\"}\n \n title=\"Select Items\"\n subtitle=\"Hand-pick from a feed\"\n onClick={() => update({ mode: \"manual\" })}\n />\n <ModeCard\n active={logic.mode === \"recommender\"}\n \n title=\"Recommender\"\n subtitle=\"Algorithms + filters\"\n onClick={() => update({ mode: \"recommender\" })}\n />\n </div>\n </div>\n\n {/* Step 2 — per-mode body */}\n <div className=\"p-3 bg-white space-y-3\">\n <Field label=\"Number of products\">\n <input\n type=\"number\"\n min={1}\n max={20}\n value={logic.noProducts}\n onChange={(e) => update({ noProducts: Number(e.target.value) || 1 })}\n className={inputCls}\n />\n <div className=\"text-[11px] text-gray-500 mt-1\">\n Block has {slots} slot{slots === 1 ? \"\" : \"s\"} in the design.\n </div>\n </Field>\n\n {logic.mode === \"manual\" ? (\n <ManualSection logic={logic} update={update} />\n ) : (\n <RecommenderSection\n logic={logic}\n update={update}\n updateFilters={updateFilters}\n />\n )}\n\n <details className=\"border border-gray-200 rounded\">\n <summary className=\"px-2 py-1.5 text-[11px] font-medium text-gray-600 cursor-pointer select-none\">\n View saved JSON\n </summary>\n <pre className=\"text-[10px] bg-gray-900 text-gray-100 p-2 overflow-auto max-h-60 leading-tight\">\n {JSON.stringify(logic, null, 2)}\n </pre>\n </details>\n </div>\n </div>\n );\n}\n\n// ---------- Sections ----------\n\nfunction ManualSection({\n logic,\n update,\n}: {\n logic: RecommendationsLogic;\n update: (p: Partial<RecommendationsLogic>) => void;\n}) {\n return (\n <>\n <Field label=\"Source feed\">\n <input\n type=\"text\"\n placeholder=\"e.g. main-catalog\"\n value={logic.sourceFeed ?? \"\"}\n onChange={(e) => update({ sourceFeed: e.target.value })}\n className={inputCls}\n />\n </Field>\n <Field label=\"Items to include (product IDs / SKUs)\">\n <TokenInput\n value={logic.manualProducts}\n onChange={(v) => update({ manualProducts: v })}\n placeholder=\"Add product id\"\n />\n </Field>\n <div className=\"text-[11px] text-gray-500\">\n Items are sent to the renderer as-is in the order shown.\n </div>\n </>\n );\n}\n\nfunction RecommenderSection({\n logic,\n update,\n updateFilters,\n}: {\n logic: RecommendationsLogic;\n update: (p: Partial<RecommendationsLogic>) => void;\n updateFilters: (p: Partial<RecommendationsLogic[\"filters\"]>) => void;\n}) {\n const [advanced, setAdvanced] = useState(false);\n return (\n <>\n <div>\n <div className=\"flex items-center justify-between mb-1.5\">\n <label className=\"text-xs font-medium text-gray-700\">\n Algorithms (max {MAX_STACK})\n </label>\n <AddAlgorithmDropdown\n disabled={logic.stack.length >= MAX_STACK}\n existing={logic.stack.map((s) => s.algorithm)}\n onPick={(id) => update({ stack: [...logic.stack, { algorithm: id }] })}\n />\n </div>\n <StackList stack={logic.stack} onChange={(stack) => update({ stack })} />\n </div>\n\n <Field label=\"Fallback\">\n <select\n value={logic.fallback}\n onChange={(e) =>\n update({ fallback: e.target.value as RecommendationsLogic[\"fallback\"] })\n }\n className={inputCls}\n >\n {FALLBACK_OPTIONS.map((f) => (\n <option key={f.value} value={f.value}>\n {f.label}\n </option>\n ))}\n </select>\n <div className=\"text-[11px] text-gray-500 mt-1\">\n {FALLBACK_OPTIONS.find((f) => f.value === logic.fallback)?.description}\n </div>\n </Field>\n\n <SectionHeader\n title=\"Include & Exclude filters\"\n right={\n <div className=\"flex items-center gap-1\">\n <Pill active={!advanced} onClick={() => setAdvanced(false)}>\n Basic\n </Pill>\n <Pill active={advanced} onClick={() => setAdvanced(true)}>\n Advanced\n </Pill>\n </div>\n }\n />\n\n <Field label=\"Exclude products\">\n <TokenInput\n value={logic.filters.excludeProducts}\n onChange={(v) => updateFilters({ excludeProducts: v })}\n placeholder=\"Add product id\"\n />\n </Field>\n <Field label=\"Include products\">\n <TokenInput\n value={logic.filters.includeProducts}\n onChange={(v) => updateFilters({ includeProducts: v })}\n placeholder=\"Add product id\"\n />\n </Field>\n <Field label=\"Exclude categories\">\n <TokenInput\n value={logic.filters.excludeCategories}\n onChange={(v) => updateFilters({ excludeCategories: v })}\n placeholder=\"Add category\"\n />\n </Field>\n <Field label=\"Include categories\">\n <TokenInput\n value={logic.filters.includeCategories}\n onChange={(v) => updateFilters({ includeCategories: v })}\n placeholder=\"Add category\"\n />\n </Field>\n\n <div className=\"grid grid-cols-2 gap-2\">\n <Field label=\"Minimum stock\">\n <input\n type=\"number\"\n min={0}\n value={logic.filters.minStock ?? 0}\n onChange={(e) => updateFilters({ minStock: Number(e.target.value) || 0 })}\n className={inputCls}\n />\n </Field>\n <Field label=\"Minimum price\">\n <input\n type=\"number\"\n min={0}\n value={logic.filters.minPrice ?? 0}\n onChange={(e) => updateFilters({ minPrice: Number(e.target.value) || 0 })}\n className={inputCls}\n />\n </Field>\n </div>\n\n <ToggleRow\n label=\"Only main items\"\n checked={!!logic.filters.mainOnly}\n onChange={(v) => updateFilters({ mainOnly: v })}\n />\n <ToggleRow\n label=\"Higher price than current item (upsell)\"\n checked={!!logic.filters.higherPrice}\n onChange={(v) => updateFilters({ higherPrice: v })}\n />\n <ToggleRow\n label=\"On sale only\"\n checked={!!logic.filters.salesPrice}\n onChange={(v) => updateFilters({ salesPrice: v })}\n />\n <ToggleRow\n label=\"Same category as current\"\n checked={!!logic.filters.sameCategory}\n onChange={(v) => updateFilters({ sameCategory: v })}\n />\n <ToggleRow\n label=\"Match title keywords\"\n checked={!!logic.filters.matchTitle}\n onChange={(v) => updateFilters({ matchTitle: v })}\n />\n <Field label=\"Match same fields (comma-separated)\">\n <input\n type=\"text\"\n placeholder=\"brand, color\"\n value={logic.filters.sameField ?? \"\"}\n onChange={(e) => updateFilters({ sameField: e.target.value })}\n className={inputCls}\n />\n </Field>\n\n {advanced && (\n <Field label=\"Advanced JSON overrides\">\n <JsonEdit\n value={logic.filters.advanced ?? {}}\n onChange={(v) => updateFilters({ advanced: v })}\n />\n </Field>\n )}\n </>\n );\n}\n\n// ---------- Subcomponents ----------\n\nconst inputCls =\n \"w-full px-2 py-1.5 text-sm border border-gray-200 rounded focus:border-blue-500 focus:outline-none bg-white\";\n\nfunction ModeCard({\n active,\n icon,\n title,\n subtitle,\n onClick,\n}: {\n active: boolean;\n icon?: React.ReactNode;\n title: string;\n subtitle: string;\n onClick: () => void;\n}) {\n return (\n <button\n onClick={onClick}\n className={\n \"flex flex-col items-start gap-0.5 p-2.5 rounded border text-left transition \" +\n (active\n ? \"border-teal-600 bg-teal-50 ring-1 ring-teal-600\"\n : \"border-gray-200 bg-white hover:border-gray-300\")\n }\n >\n <div className={\"flex items-center gap-1.5 \" + (active ? \"text-teal-700\" : \"text-gray-700\")}>\n {icon}\n <span className=\"text-xs font-semibold\">{title}</span>\n </div>\n <span className=\"text-[10px] text-gray-500\">{subtitle}</span>\n </button>\n );\n}\n\nfunction SectionHeader({ title, right }: { title: string; right?: React.ReactNode }) {\n return (\n <div className=\"flex items-center justify-between border-t border-gray-200 pt-3 mt-3\">\n <div className=\"text-[11px] font-semibold uppercase tracking-wide text-gray-600\">\n {title}\n </div>\n {right}\n </div>\n );\n}\n\nfunction Field({ label, children }: { label: React.ReactNode; children: React.ReactNode }) {\n return (\n <div>\n <label className=\"block text-xs font-medium text-gray-700 mb-1\">{label}</label>\n {children}\n </div>\n );\n}\n\nfunction Pill({\n active,\n onClick,\n children,\n}: {\n active: boolean;\n onClick: () => void;\n children: React.ReactNode;\n}) {\n return (\n <button\n onClick={onClick}\n className={\n \"px-2 py-0.5 rounded text-[10px] font-semibold uppercase tracking-wide \" +\n (active ? \"bg-teal-600 text-white\" : \"bg-gray-100 text-gray-600 hover:bg-gray-200\")\n }\n >\n {children}\n </button>\n );\n}\n\nfunction ToggleRow({\n label,\n checked,\n onChange,\n}: {\n label: string;\n checked: boolean;\n onChange: (v: boolean) => void;\n}) {\n return (\n <label className=\"flex items-center justify-between gap-2 text-xs text-gray-700 py-1\">\n <span>{label}</span>\n <input\n type=\"checkbox\"\n checked={checked}\n onChange={(e) => onChange(e.target.checked)}\n className=\"h-4 w-4 accent-teal-600\"\n />\n </label>\n );\n}\n\nfunction StackList({\n stack,\n onChange,\n}: {\n stack: StackEntry[];\n onChange: (s: StackEntry[]) => void;\n}) {\n if (stack.length === 0) {\n return (\n <div className=\"text-[11px] text-gray-500 italic border border-dashed border-gray-300 rounded px-2 py-3 text-center\">\n No algorithms yet. Click <b>Add algorithm</b> to start.\n </div>\n );\n }\n const move = (i: number, dir: -1 | 1) => {\n const j = i + dir;\n if (j < 0 || j >= stack.length) return;\n const next = stack.slice();\n [next[i], next[j]] = [next[j], next[i]];\n onChange(next);\n };\n const remove = (i: number) => onChange(stack.filter((_, k) => k !== i));\n const setParam = (i: number, key: string, value: string | number) => {\n const next = stack.slice();\n next[i] = { ...next[i], params: { ...(next[i].params ?? {}), [key]: value } };\n onChange(next);\n };\n return (\n <div className=\"space-y-1.5\">\n {stack.map((s, i) => {\n const def = ALGORITHM_BY_ID[s.algorithm];\n return (\n <div\n key={i}\n className=\"border border-gray-200 rounded px-2 py-1.5 bg-white flex flex-col gap-1\"\n >\n <div className=\"flex items-center gap-1\">\n <span className=\"flex-1 text-xs text-gray-800 truncate\">\n {def?.label ?? s.algorithm}\n </span>\n <button\n title=\"Move up\"\n onClick={() => move(i, -1)}\n disabled={i === 0}\n className=\"p-1 text-gray-400 hover:text-gray-700 disabled:opacity-30\"\n >\n <ChevronUp size={13} />\n </button>\n <button\n title=\"Move down\"\n onClick={() => move(i, 1)}\n disabled={i === stack.length - 1}\n className=\"p-1 text-gray-400 hover:text-gray-700 disabled:opacity-30\"\n >\n <ChevronDown size={13} />\n </button>\n <button\n title=\"Remove\"\n onClick={() => remove(i)}\n className=\"p-1 text-gray-400 hover:text-red-600\"\n >\n <Trash2 size={13} />\n </button>\n </div>\n {def?.params?.map((p) => (\n <div key={p.key} className=\"flex items-center gap-2\">\n <span className=\"text-[10px] text-gray-500 w-20 shrink-0\">{p.label}</span>\n {p.type === \"select\" ? (\n <select\n value={String(s.params?.[p.key] ?? p.default ?? \"\")}\n onChange={(e) => setParam(i, p.key, e.target.value)}\n className=\"flex-1 text-xs border border-gray-200 rounded px-1.5 py-1 bg-white\"\n >\n {p.options?.map((o) => (\n <option key={String(o.value)} value={String(o.value)}>\n {o.label}\n </option>\n ))}\n </select>\n ) : (\n <input\n type={p.type === \"number\" ? \"number\" : \"text\"}\n value={String(s.params?.[p.key] ?? p.default ?? \"\")}\n onChange={(e) =>\n setParam(\n i,\n p.key,\n p.type === \"number\" ? Number(e.target.value) : e.target.value\n )\n }\n className=\"flex-1 text-xs border border-gray-200 rounded px-1.5 py-1\"\n />\n )}\n </div>\n ))}\n </div>\n );\n })}\n </div>\n );\n}\n\nfunction AddAlgorithmDropdown({\n disabled,\n existing,\n onPick,\n}: {\n disabled: boolean;\n existing: string[];\n onPick: (id: string) => void;\n}) {\n const [open, setOpen] = useState(false);\n return (\n <div className=\"relative\">\n <button\n disabled={disabled}\n onClick={() => setOpen((o) => !o)}\n className={\n \"flex items-center gap-1 px-2 py-1 rounded text-[11px] font-semibold uppercase \" +\n (disabled\n ? \"bg-gray-200 text-gray-400 cursor-not-allowed\"\n : \"bg-teal-600 text-white hover:bg-teal-700\")\n }\n >\n <Plus size={12} /> Add\n </button>\n {open && !disabled && (\n <>\n <div className=\"fixed inset-0 z-10\" onClick={() => setOpen(false)} />\n <div className=\"absolute right-0 top-full mt-1 w-64 max-h-80 overflow-auto bg-white border border-gray-200 rounded shadow-lg z-20\">\n {ALGORITHMS.map((a) => {\n const used = existing.includes(a.id);\n return (\n <button\n key={a.id}\n disabled={used}\n onClick={() => {\n onPick(a.id);\n setOpen(false);\n }}\n className={\n \"block w-full text-left px-2.5 py-1.5 text-xs \" +\n (used\n ? \"text-gray-400 cursor-not-allowed\"\n : \"text-gray-700 hover:bg-teal-50 hover:text-teal-700\")\n }\n >\n {a.label}\n {used && <span className=\"ml-1 text-[10px]\">· added</span>}\n </button>\n );\n })}\n </div>\n </>\n )}\n </div>\n );\n}\n\nfunction TokenInput({\n value,\n onChange,\n placeholder,\n}: {\n value: string[];\n onChange: (v: string[]) => void;\n placeholder?: string;\n}) {\n const [draft, setDraft] = useState(\"\");\n const add = () => {\n const v = draft.trim();\n if (!v) return;\n if (value.includes(v)) return;\n onChange([...value, v]);\n setDraft(\"\");\n };\n return (\n <div className=\"border border-gray-200 rounded bg-white p-1 flex flex-wrap items-center gap-1 focus-within:border-blue-500\">\n {value.map((tok) => (\n <span\n key={tok}\n className=\"inline-flex items-center gap-1 bg-gray-100 text-gray-800 text-[11px] rounded px-1.5 py-0.5\"\n >\n {tok}\n <button\n onClick={() => onChange(value.filter((x) => x !== tok))}\n className=\"text-gray-500 hover:text-red-600\"\n >\n <X size={10} />\n </button>\n </span>\n ))}\n <input\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \",\") {\n e.preventDefault();\n add();\n } else if (e.key === \"Backspace\" && !draft && value.length) {\n onChange(value.slice(0, -1));\n }\n }}\n onBlur={add}\n placeholder={value.length === 0 ? placeholder : \"\"}\n className=\"flex-1 min-w-20 outline-none text-xs bg-transparent px-1 py-0.5\"\n />\n </div>\n );\n}\n\nfunction JsonEdit({\n value,\n onChange,\n}: {\n value: Record<string, unknown>;\n onChange: (v: Record<string, unknown>) => void;\n}) {\n const [text, setText] = useState(() => JSON.stringify(value, null, 2));\n const [error, setError] = useState<string | null>(null);\n return (\n <div>\n <textarea\n value={text}\n onChange={(e) => {\n const t = e.target.value;\n setText(t);\n try {\n const parsed = JSON.parse(t || \"{}\");\n setError(null);\n onChange(parsed);\n } catch (err) {\n setError(String((err as Error).message));\n }\n }}\n rows={6}\n spellCheck={false}\n className=\"w-full font-mono text-[11px] border border-gray-200 rounded p-2 bg-gray-50 focus:border-blue-500 focus:outline-none\"\n />\n {error && <div className=\"text-[10px] text-red-600 mt-1\">{error}</div>}\n </div>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { useEmailStore } from \"../store/emailStore\";\nimport { resolveToken } from \"../core/theme\";\nimport { getAssetProvider } from \"../core/plugins\";\nimport { RecommendationsPanel } from \"./RecommendationsPanel\";\nimport { isProductAware } from \"../recommendations/logic\";\nimport type {\n EmailElement,\n EmailModule,\n TextElement,\n ImageElement,\n ButtonElement,\n SpacerElement,\n DividerElement,\n ProductGridElement,\n Product,\n} from \"../core/types\";\nimport { Smartphone, Monitor, Trash2, Plus, RotateCcw, Upload, Loader2, Check } from \"lucide-react\";\n\nexport function RightSidebar() {\n const { selection, doc, viewMode } = useEmailStore();\n\n return (\n <div className=\"w-72 bg-white border-l border-gray-200 shrink-0 overflow-y-auto\">\n <div className={`px-4 py-2 text-[11px] flex items-center gap-1.5 border-b ${viewMode === \"mobile\" ? \"bg-amber-50 text-amber-800 border-amber-200\" : \"bg-blue-50 text-blue-800 border-blue-100\"}`}>\n {viewMode === \"mobile\" ? <Smartphone size={12} /> : <Monitor size={12} />}\n Editing {viewMode} styles\n </div>\n <div className=\"p-4\">\n {!selection || selection.kind === \"email\" ? (\n <EmailSettingsPanel />\n ) : selection.kind === \"module\" ? (\n (() => {\n const m = doc.modules.find((x) => x.id === selection.moduleId);\n return m ? <ModulePanel mod={m} /> : <Empty />;\n })()\n ) : (\n (() => {\n const m = doc.modules.find((x) => x.id === selection.moduleId);\n const el = m?.children.find((c) => c.id === selection.elementId);\n return m && el ? <ElementPanel mod={m} el={el} /> : <Empty />;\n })()\n )}\n </div>\n </div>\n );\n}\n\nfunction Empty() {\n return <div className=\"text-xs text-gray-400\">Nothing selected.</div>;\n}\n\n// ---------- Mobile-aware style helpers ----------\n\n// Read merged style: in mobile view, base + mobile override; in desktop, just base.\nfunction readStyle(rawStyle: Record<string, unknown>, viewMode: \"desktop\" | \"mobile\") {\n if (viewMode !== \"mobile\") return rawStyle;\n const mobile = (rawStyle.mobile as Record<string, unknown> | undefined) ?? {};\n return { ...rawStyle, ...mobile };\n}\n\n// Write a patch into the right slot depending on view mode.\nfunction writeStylePatch(\n rawStyle: Record<string, unknown>,\n patch: Record<string, unknown>,\n viewMode: \"desktop\" | \"mobile\"\n): Record<string, unknown> {\n if (viewMode !== \"mobile\") return { ...rawStyle, ...patch };\n const mobile = (rawStyle.mobile as Record<string, unknown> | undefined) ?? {};\n return { ...rawStyle, mobile: { ...mobile, ...patch } };\n}\n\nfunction MobileBadge({ overridden }: { overridden: boolean }) {\n if (!overridden) return null;\n return (\n <span className=\"ml-1 text-[9px] uppercase tracking-wide bg-amber-100 text-amber-800 px-1 rounded\">\n mobile\n </span>\n );\n}\n\nfunction VisibilityField({\n hideOn,\n onChange,\n}: {\n hideOn: \"mobile\" | \"desktop\" | undefined;\n onChange: (v: \"mobile\" | \"desktop\" | undefined) => void;\n}) {\n return (\n <Field label=\"Visibility\">\n <Select\n value={hideOn ?? \"\"}\n onChange={(e) => {\n const v = e.target.value;\n onChange(v === \"\" ? undefined : (v as \"mobile\" | \"desktop\"));\n }}\n >\n <option value=\"\">Show on all</option>\n <option value=\"mobile\">Hide on mobile</option>\n <option value=\"desktop\">Hide on desktop</option>\n </Select>\n </Field>\n );\n}\n\nfunction PanelTitle({ children }: { children: React.ReactNode }) {\n return (\n <h3 className=\"text-xs font-semibold uppercase tracking-wide text-gray-500 mb-3\">\n {children}\n </h3>\n );\n}\n\nfunction Field({ label, children }: { label: React.ReactNode; children: React.ReactNode }) {\n return (\n <label className=\"block mb-3\">\n <span className=\"flex items-center text-xs text-gray-600 mb-1\">{label}</span>\n {children}\n </label>\n );\n}\n\nfunction TextInput(props: React.InputHTMLAttributes<HTMLInputElement>) {\n return (\n <input\n {...props}\n className=\"w-full px-2 py-1.5 text-sm border border-gray-200 rounded focus:border-blue-500 focus:outline-none\"\n />\n );\n}\n\nfunction NumberInput(props: React.InputHTMLAttributes<HTMLInputElement>) {\n return <TextInput type=\"number\" {...props} />;\n}\n\nfunction ImageUrlInput({\n value,\n onChange,\n onAlt,\n}: {\n value: string;\n onChange: (url: string) => void;\n onAlt?: (alt: string) => void;\n}) {\n const provider = getAssetProvider();\n const fileRef = useRef<HTMLInputElement | null>(null);\n const [busy, setBusy] = useState(false);\n const [err, setErr] = useState<string | null>(null);\n\n const handleFile = async (file: File) => {\n if (!provider) return;\n setBusy(true);\n setErr(null);\n try {\n const res = await provider.upload(file);\n onChange(res.url);\n if (res.alt && onAlt) onAlt(res.alt);\n } catch (e) {\n setErr(e instanceof Error ? e.message : String(e));\n } finally {\n setBusy(false);\n if (fileRef.current) fileRef.current.value = \"\";\n }\n };\n\n return (\n <div>\n <div className=\"flex gap-1\">\n <TextInput value={value ?? \"\"} onChange={(e) => onChange(e.target.value)} />\n {provider && (\n <>\n <input\n ref={fileRef}\n type=\"file\"\n accept=\"image/*\"\n className=\"hidden\"\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) void handleFile(f);\n }}\n />\n <button\n type=\"button\"\n disabled={busy}\n onClick={() => fileRef.current?.click()}\n className=\"shrink-0 px-2 py-1.5 text-xs border border-gray-200 rounded hover:bg-gray-50 disabled:opacity-50 flex items-center gap-1\"\n title=\"Upload image\"\n >\n {busy ? <Loader2 size={12} className=\"animate-spin\" /> : <Upload size={12} />}\n </button>\n </>\n )}\n </div>\n {err && <p className=\"text-[10px] text-red-600 mt-1\">{err}</p>}\n {!provider && (\n <p className=\"text-[10px] text-gray-400 mt-1\">\n Tip: register an image uploader plugin to enable file uploads.\n </p>\n )}\n </div>\n );\n}\n\nfunction ColorInput({\n value,\n onChange,\n defaultValue,\n}: {\n value: string;\n onChange: (v: string) => void;\n defaultValue?: string;\n}) {\n const theme = useEmailStore((s) => s.doc.theme);\n const isToken = typeof value === \"string\" && value.startsWith(\"{\");\n\n // Remember the most recent token seen so the user can reset back to it\n // even after picking a custom hex color.\n const lastTokenRef = useRef<string | undefined>(\n defaultValue && defaultValue.startsWith(\"{\") ? defaultValue : isToken ? value : undefined\n );\n useEffect(() => {\n if (isToken) lastTokenRef.current = value;\n else if (defaultValue && defaultValue.startsWith(\"{\")) lastTokenRef.current = defaultValue;\n }, [value, isToken, defaultValue]);\n\n // Hex shown in the native picker swatch (resolves tokens against theme).\n const swatchHex = (() => {\n const resolved = resolveToken(value, theme);\n if (typeof resolved === \"string\" && /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(resolved)) {\n return resolved.length === 4\n ? \"#\" + resolved.slice(1).split(\"\").map((c) => c + c).join(\"\")\n : resolved;\n }\n return \"#000000\";\n })();\n\n const resetTarget = defaultValue ?? lastTokenRef.current;\n const canReset = !!resetTarget && resetTarget !== value;\n\n // Local text mirrors prop but lets user type freely (commits on blur/Enter).\n const [text, setText] = useState(value ?? \"\");\n useEffect(() => setText(value ?? \"\"), [value]);\n\n return (\n <div className=\"flex gap-1 items-center\">\n <label\n className=\"relative w-9 h-8 border border-gray-200 rounded cursor-pointer overflow-hidden shrink-0\"\n title={isToken ? `Token → ${swatchHex} (click to override)` : \"Pick color\"}\n style={{ background: swatchHex }}\n >\n <input\n type=\"color\"\n value={swatchHex}\n onChange={(e) => onChange(e.target.value)}\n className=\"absolute inset-0 opacity-0 cursor-pointer\"\n />\n {isToken && (\n <span\n className=\"absolute inset-0 pointer-events-none border-2 border-dashed rounded\"\n style={{ borderColor: \"rgba(255,255,255,0.6)\" }}\n />\n )}\n </label>\n <input\n value={text}\n onChange={(e) => setText(e.target.value)}\n onBlur={() => text !== value && onChange(text)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") (e.target as HTMLInputElement).blur();\n }}\n className=\"w-full px-2 py-1.5 text-sm border border-gray-200 rounded focus:border-blue-500 focus:outline-none font-mono\"\n />\n {canReset && (\n <button\n type=\"button\"\n onClick={() => onChange(resetTarget!)}\n className=\"shrink-0 p-1.5 text-gray-400 hover:text-blue-600 hover:bg-blue-50 rounded\"\n title={`Reset to ${resetTarget}`}\n >\n <RotateCcw size={12} />\n </button>\n )}\n </div>\n );\n}\n\nfunction Select(props: React.SelectHTMLAttributes<HTMLSelectElement>) {\n return (\n <select\n {...props}\n className=\"w-full px-2 py-1.5 text-sm border border-gray-200 rounded focus:border-blue-500 focus:outline-none bg-white\"\n />\n );\n}\n\n// ---------- Email-level panel ----------\n\nfunction EmailSettingsPanel() {\n const { doc, updateMeta, updateSettings } = useEmailStore();\n return (\n <>\n <PanelTitle>Email</PanelTitle>\n <Field label=\"Name\">\n <TextInput\n value={doc.meta.name}\n onChange={(e) => updateMeta({ name: e.target.value })}\n />\n </Field>\n <Field label=\"Preview text\">\n <TextInput\n value={doc.meta.previewText}\n onChange={(e) => updateMeta({ previewText: e.target.value })}\n />\n </Field>\n <Field label=\"Width (px)\">\n <NumberInput\n value={doc.settings.width}\n onChange={(e) => updateSettings({ width: Number(e.target.value) || 600 })}\n />\n </Field>\n <Field label=\"Background color\">\n <ColorInput\n value={doc.settings.backgroundColor}\n onChange={(v) => updateSettings({ backgroundColor: v })}\n />\n </Field>\n <Field label=\"Content background color\">\n <ColorInput\n value={doc.settings.contentBackgroundColor}\n onChange={(v) => updateSettings({ contentBackgroundColor: v })}\n />\n </Field>\n\n <div className=\"mt-6 pt-4 border-t border-gray-100\">\n <ThemeEditor />\n </div>\n </>\n );\n}\n\n// ---------- Theme editor ----------\n\nfunction ThemeEditor() {\n const { doc, themes, applyTheme } = useEmailStore();\n const current = doc.theme;\n\n // Detect whether the current theme's colors have been customised vs the preset.\n const preset = themes.find((t) => t.id === current.id);\n const isCustomised =\n preset != null &&\n Object.entries(current.tokens.colors).some(([k, v]) => preset.tokens.colors[k] !== v);\n\n const updateColor = (key: string, hex: string) => {\n applyTheme({\n ...current,\n tokens: {\n ...current.tokens,\n colors: { ...current.tokens.colors, [key]: hex },\n },\n });\n };\n\n return (\n <>\n {/* ── Preset switcher ─────────────────────────────────────── */}\n <div className=\"flex items-center justify-between mb-2\">\n <PanelTitle>Theme</PanelTitle>\n {isCustomised && (\n <button\n onClick={() => preset && applyTheme(preset)}\n className=\"text-[10px] text-blue-600 hover:underline mb-3\"\n title=\"Discard color changes and restore the preset\"\n >\n Reset to preset\n </button>\n )}\n </div>\n <div className=\"flex flex-col gap-1.5 mb-4\">\n {themes.map((t) => {\n const active = t.id === current.id;\n return (\n <button\n key={t.id}\n onClick={() => applyTheme(t)}\n title={t.name}\n className={`flex items-center gap-2 px-2.5 py-2 rounded border text-xs transition-colors ${\n active\n ? \"border-blue-500 bg-blue-50 text-blue-700\"\n : \"border-gray-200 bg-white hover:border-gray-300 text-gray-700\"\n }`}\n >\n {/* Three color chips */}\n <span\n className=\"w-3 h-3 rounded-full shrink-0 ring-1 ring-black/10\"\n style={{ background: t.tokens.colors.primary }}\n />\n <span\n className=\"w-3 h-3 rounded-full shrink-0 ring-1 ring-black/10\"\n style={{ background: t.tokens.colors.background }}\n />\n <span\n className=\"w-3 h-3 rounded-full shrink-0 ring-1 ring-black/10\"\n style={{ background: t.tokens.colors.text }}\n />\n <span className=\"flex-1 text-left\">{t.name}</span>\n {active && <Check size={12} className=\"text-blue-600 shrink-0\" />}\n </button>\n );\n })}\n </div>\n\n {/* ── Editable color tokens ────────────────────────────────── */}\n <div className=\"text-xs font-semibold uppercase tracking-wide text-gray-500 mb-2\">\n Colors\n {isCustomised && (\n <span className=\"ml-2 normal-case font-normal text-[10px] bg-amber-100 text-amber-700 px-1.5 py-0.5 rounded\">\n customised\n </span>\n )}\n </div>\n <div className=\"flex flex-col gap-2\">\n {Object.entries(current.tokens.colors).map(([key, value]) => (\n <ThemeColorRow\n key={key}\n label={key}\n value={value}\n onChange={(hex) => updateColor(key, hex)}\n />\n ))}\n </div>\n </>\n );\n}\n\nfunction ThemeColorRow({\n label,\n value,\n onChange,\n}: {\n label: string;\n value: string;\n onChange: (hex: string) => void;\n}) {\n // Keep a local text value so the user can type freely; commits on blur / Enter.\n const [text, setText] = useState(value);\n useEffect(() => setText(value), [value]);\n\n // The native color picker needs a valid 6-digit hex.\n const pickerHex = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(value)\n ? value.length === 4\n ? \"#\" + value.slice(1).split(\"\").map((c) => c + c).join(\"\")\n : value\n : \"#000000\";\n\n const commit = (raw: string) => {\n const v = raw.trim();\n if (v) onChange(v);\n };\n\n return (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs text-gray-500 w-28 shrink-0 truncate\" title={label}>\n {label}\n </span>\n <label\n className=\"relative w-7 h-7 rounded border border-gray-200 cursor-pointer overflow-hidden shrink-0\"\n style={{ background: pickerHex }}\n title={`Pick ${label} color`}\n >\n <input\n type=\"color\"\n value={pickerHex}\n onChange={(e) => onChange(e.target.value)}\n className=\"absolute inset-0 opacity-0 cursor-pointer w-full h-full\"\n />\n </label>\n <input\n value={text}\n onChange={(e) => setText(e.target.value)}\n onBlur={() => commit(text)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") (e.target as HTMLInputElement).blur();\n }}\n className=\"flex-1 min-w-0 px-2 py-1 text-xs border border-gray-200 rounded focus:border-blue-500 focus:outline-none font-mono\"\n spellCheck={false}\n />\n </div>\n );\n}\n\n// ---------- Module panel ----------\n\nfunction ModulePanel({ mod }: { mod: EmailModule }) {\n const updateModule = useEmailStore((s) => s.updateModule);\n const viewMode = useEmailStore((s) => s.viewMode);\n const rawStyle = (mod.style ?? {}) as Record<string, unknown>;\n const style = readStyle(rawStyle, viewMode);\n const mobileKeys = new Set(Object.keys((rawStyle.mobile as Record<string, unknown>) ?? {}));\n const set = (patch: Record<string, unknown>) =>\n updateModule(mod.id, { style: writeStylePatch(rawStyle, patch, viewMode) });\n return (\n <>\n <PanelTitle>{mod.name}</PanelTitle>\n <Field label={<>Background color<MobileBadge overridden={mobileKeys.has(\"backgroundColor\")} /></>}>\n <ColorInput\n value={(style.backgroundColor as string) ?? \"\"}\n onChange={(v) => set({ backgroundColor: v })}\n />\n </Field>\n <PaddingFields style={style} mobileKeys={mobileKeys} onSet={set} />\n <Field label={<>Border radius<MobileBadge overridden={mobileKeys.has(\"borderRadius\")} /></>}>\n <NumberInput\n value={(style.borderRadius as number) ?? 0}\n onChange={(e) => set({ borderRadius: Number(e.target.value) })}\n />\n </Field>\n <VisibilityField\n hideOn={rawStyle.hideOn as \"mobile\" | \"desktop\" | undefined}\n onChange={(v) => updateModule(mod.id, { style: { ...rawStyle, hideOn: v } })}\n />\n {isProductAware(mod) && <RecommendationsPanel mod={mod} />}\n </>\n );\n}\n\n// ---------- Element panel ----------\n\nfunction ElementPanel({ mod, el }: { mod: EmailModule; el: EmailElement }) {\n switch (el.type) {\n case \"text\":\n return <TextElementPanel mod={mod} el={el} />;\n case \"image\":\n return <ImageElementPanel mod={mod} el={el} />;\n case \"button\":\n return <ButtonElementPanel mod={mod} el={el} />;\n case \"spacer\":\n return <SpacerElementPanel mod={mod} el={el} />;\n case \"divider\":\n return <DividerElementPanel mod={mod} el={el} />;\n case \"productGrid\":\n return <ProductGridElementPanel mod={mod} el={el} />;\n }\n}\n\nfunction PaddingFields({\n style,\n mobileKeys,\n onSet,\n}: {\n style: Record<string, unknown>;\n mobileKeys?: Set<string>;\n onSet: (p: Record<string, unknown>) => void;\n}) {\n return (\n <div className=\"grid grid-cols-2 gap-2 mb-3\">\n {([\"paddingTop\", \"paddingBottom\", \"paddingLeft\", \"paddingRight\"] as const).map((k) => (\n <Field key={k} label={<>{k.replace(\"padding\", \"Pad \")}<MobileBadge overridden={!!mobileKeys?.has(k)} /></>}>\n <NumberInput\n value={(style[k] as number) ?? 0}\n onChange={(e) => onSet({ [k]: Number(e.target.value) })}\n />\n </Field>\n ))}\n </div>\n );\n}\n\nfunction useElPatch<T extends EmailElement>(mod: EmailModule, el: T) {\n const updateElement = useEmailStore((s) => s.updateElement);\n return (patch: Partial<T>) => updateElement(mod.id, el.id, patch as Partial<EmailElement>);\n}\n\nfunction TextElementPanel({ mod, el }: { mod: EmailModule; el: TextElement }) {\n const patch = useElPatch(mod, el);\n const viewMode = useEmailStore((s) => s.viewMode);\n const rawStyle = (el.style ?? {}) as Record<string, unknown>;\n const style = readStyle(rawStyle, viewMode);\n const mobileKeys = new Set(Object.keys((rawStyle.mobile as Record<string, unknown>) ?? {}));\n const setStyle = (p: Record<string, unknown>) =>\n patch({ style: writeStylePatch(rawStyle, p, viewMode) } as Partial<TextElement>);\n return (\n <>\n <PanelTitle>Text</PanelTitle>\n <Field label=\"Content\">\n <textarea\n value={el.content.replace(/<br\\s*\\/?>/g, \"\\n\")}\n onChange={(e) =>\n patch({ content: e.target.value.replace(/\\n/g, \"<br/>\") } as Partial<TextElement>)\n }\n rows={3}\n className=\"w-full px-2 py-1.5 text-sm border border-gray-200 rounded focus:border-blue-500 focus:outline-none\"\n />\n </Field>\n <Field label=\"Font family\">\n <TextInput\n value={(style.fontFamily as string) ?? \"\"}\n onChange={(e) => setStyle({ fontFamily: e.target.value })}\n />\n </Field>\n <div className=\"grid grid-cols-2 gap-2\">\n <Field label=\"Font size\">\n <NumberInput\n value={(style.fontSize as number) ?? 16}\n onChange={(e) => setStyle({ fontSize: Number(e.target.value) })}\n />\n </Field>\n <Field label=\"Weight\">\n <TextInput\n value={String(style.fontWeight ?? \"\")}\n onChange={(e) => setStyle({ fontWeight: e.target.value || undefined })}\n />\n </Field>\n <Field label=\"Line height\">\n <NumberInput\n step={0.1}\n value={(style.lineHeight as number) ?? 1.5}\n onChange={(e) => setStyle({ lineHeight: Number(e.target.value) })}\n />\n </Field>\n <Field label=\"Letter spacing\">\n <NumberInput\n value={(style.letterSpacing as number) ?? 0}\n onChange={(e) => setStyle({ letterSpacing: Number(e.target.value) })}\n />\n </Field>\n </div>\n <Field label=\"Color\">\n <ColorInput\n value={(style.color as string) ?? \"#000000\"}\n onChange={(v) => setStyle({ color: v })}\n />\n </Field>\n <Field label=\"Align\">\n <Select\n value={(style.align as string) ?? \"left\"}\n onChange={(e) => setStyle({ align: e.target.value })}\n >\n <option value=\"left\">Left</option>\n <option value=\"center\">Center</option>\n <option value=\"right\">Right</option>\n </Select>\n </Field>\n <Field label=\"Link URL\">\n <TextInput\n value={(style.link as string) ?? \"\"}\n onChange={(e) => setStyle({ link: e.target.value })}\n />\n </Field>\n <PaddingFields style={style} mobileKeys={mobileKeys} onSet={setStyle} />\n <VisibilityField\n hideOn={rawStyle.hideOn as \"mobile\" | \"desktop\" | undefined}\n onChange={(v) => patch({ style: { ...rawStyle, hideOn: v } } as Partial<TextElement>)}\n />\n <button\n onClick={() =>\n patch({ content: `${el.content} ✨` } as Partial<TextElement>)\n }\n className=\"w-full mt-2 px-3 py-2 text-xs bg-purple-50 text-purple-700 border border-purple-200 rounded hover:bg-purple-100\"\n >\n ✨ AI rewrite (mock)\n </button>\n </>\n );\n}\n\nfunction ImageElementPanel({ mod, el }: { mod: EmailModule; el: ImageElement }) {\n const patch = useElPatch(mod, el);\n const viewMode = useEmailStore((s) => s.viewMode);\n const rawStyle = (el.style ?? {}) as Record<string, unknown>;\n const style = readStyle(rawStyle, viewMode);\n const mobileKeys = new Set(Object.keys((rawStyle.mobile as Record<string, unknown>) ?? {}));\n const setStyle = (p: Record<string, unknown>) =>\n patch({ style: writeStylePatch(rawStyle, p, viewMode) } as Partial<ImageElement>);\n return (\n <>\n <PanelTitle>Image</PanelTitle>\n <Field label=\"Image URL\">\n <ImageUrlInput\n value={el.src}\n onChange={(url) => patch({ src: url } as Partial<ImageElement>)}\n onAlt={(alt) => patch({ alt } as Partial<ImageElement>)}\n />\n </Field>\n <Field label=\"Alt text\">\n <TextInput\n value={el.alt ?? \"\"}\n onChange={(e) => patch({ alt: e.target.value } as Partial<ImageElement>)}\n />\n </Field>\n <Field label=\"Link\">\n <TextInput\n value={el.link ?? \"\"}\n onChange={(e) => patch({ link: e.target.value } as Partial<ImageElement>)}\n />\n </Field>\n <div className=\"grid grid-cols-2 gap-2\">\n <Field label={<>Width<MobileBadge overridden={mobileKeys.has(\"width\")} /></>}>\n <NumberInput\n value={(style.width as number) ?? 0}\n onChange={(e) => setStyle({ width: Number(e.target.value) })}\n />\n </Field>\n <Field label={<>Height<MobileBadge overridden={mobileKeys.has(\"height\")} /></>}>\n <NumberInput\n value={(style.height as number) ?? 0}\n onChange={(e) => setStyle({ height: Number(e.target.value) || undefined })}\n />\n </Field>\n </div>\n <Field label=\"Border radius\">\n <NumberInput\n value={(style.borderRadius as number) ?? 0}\n onChange={(e) => setStyle({ borderRadius: Number(e.target.value) })}\n />\n </Field>\n <Field label=\"Align\">\n <Select\n value={(style.align as string) ?? \"center\"}\n onChange={(e) => setStyle({ align: e.target.value })}\n >\n <option value=\"left\">Left</option>\n <option value=\"center\">Center</option>\n <option value=\"right\">Right</option>\n </Select>\n </Field>\n <PaddingFields style={style} mobileKeys={mobileKeys} onSet={setStyle} />\n <VisibilityField\n hideOn={rawStyle.hideOn as \"mobile\" | \"desktop\" | undefined}\n onChange={(v) => patch({ style: { ...rawStyle, hideOn: v } } as Partial<ImageElement>)}\n />\n </>\n );\n}\n\nfunction ButtonElementPanel({ mod, el }: { mod: EmailModule; el: ButtonElement }) {\n const patch = useElPatch(mod, el);\n const viewMode = useEmailStore((s) => s.viewMode);\n const rawStyle = (el.style ?? {}) as Record<string, unknown>;\n const style = readStyle(rawStyle, viewMode);\n const mobileKeys = new Set(Object.keys((rawStyle.mobile as Record<string, unknown>) ?? {}));\n const setStyle = (p: Record<string, unknown>) =>\n patch({ style: writeStylePatch(rawStyle, p, viewMode) } as Partial<ButtonElement>);\n return (\n <>\n <PanelTitle>Button</PanelTitle>\n <Field label=\"Label\">\n <TextInput value={el.label} onChange={(e) => patch({ label: e.target.value } as Partial<ButtonElement>)} />\n </Field>\n <Field label=\"Link\">\n <TextInput value={el.link} onChange={(e) => patch({ link: e.target.value } as Partial<ButtonElement>)} />\n </Field>\n <Field label=\"Background color\">\n <ColorInput\n value={(style.backgroundColor as string) ?? \"\"}\n onChange={(v) => setStyle({ backgroundColor: v })}\n />\n </Field>\n <Field label=\"Text color\">\n <ColorInput\n value={(style.color as string) ?? \"#FFFFFF\"}\n onChange={(v) => setStyle({ color: v })}\n />\n </Field>\n <div className=\"grid grid-cols-2 gap-2\">\n <Field label=\"Font size\">\n <NumberInput\n value={(style.fontSize as number) ?? 16}\n onChange={(e) => setStyle({ fontSize: Number(e.target.value) })}\n />\n </Field>\n <Field label=\"Border radius\">\n <NumberInput\n value={(style.borderRadius as number) ?? 6}\n onChange={(e) => setStyle({ borderRadius: Number(e.target.value) })}\n />\n </Field>\n </div>\n <Field label=\"Align\">\n <Select\n value={(style.align as string) ?? \"center\"}\n onChange={(e) => setStyle({ align: e.target.value })}\n >\n <option value=\"left\">Left</option>\n <option value=\"center\">Center</option>\n <option value=\"right\">Right</option>\n </Select>\n </Field>\n <PaddingFields style={style} mobileKeys={mobileKeys} onSet={setStyle} />\n <VisibilityField\n hideOn={rawStyle.hideOn as \"mobile\" | \"desktop\" | undefined}\n onChange={(v) => patch({ style: { ...rawStyle, hideOn: v } } as Partial<ButtonElement>)}\n />\n </>\n );\n}\n\nfunction SpacerElementPanel({ mod, el }: { mod: EmailModule; el: SpacerElement }) {\n const patch = useElPatch(mod, el);\n return (\n <>\n <PanelTitle>Spacer</PanelTitle>\n <Field label=\"Height (px)\">\n <NumberInput\n value={el.height}\n onChange={(e) => patch({ height: Number(e.target.value) || 0 } as Partial<SpacerElement>)}\n />\n </Field>\n </>\n );\n}\n\nfunction DividerElementPanel({ mod, el }: { mod: EmailModule; el: DividerElement }) {\n const patch = useElPatch(mod, el);\n const viewMode = useEmailStore((s) => s.viewMode);\n const rawStyle = (el.style ?? {}) as Record<string, unknown>;\n const style = readStyle(rawStyle, viewMode);\n const mobileKeys = new Set(Object.keys((rawStyle.mobile as Record<string, unknown>) ?? {}));\n const setStyle = (p: Record<string, unknown>) =>\n patch({ style: writeStylePatch(rawStyle, p, viewMode) } as Partial<DividerElement>);\n return (\n <>\n <PanelTitle>Divider</PanelTitle>\n <Field label=\"Color\">\n <ColorInput\n value={(style.color as string) ?? \"#E5E7EB\"}\n onChange={(v) => setStyle({ color: v })}\n />\n </Field>\n <Field label=\"Thickness\">\n <NumberInput\n value={(style.thickness as number) ?? 1}\n onChange={(e) => setStyle({ thickness: Number(e.target.value) })}\n />\n </Field>\n <PaddingFields style={style} mobileKeys={mobileKeys} onSet={setStyle} />\n <VisibilityField\n hideOn={rawStyle.hideOn as \"mobile\" | \"desktop\" | undefined}\n onChange={(v) => patch({ style: { ...rawStyle, hideOn: v } } as Partial<DividerElement>)}\n />\n </>\n );\n}\n\n// ---------- Product Grid panel ----------\n\nfunction newProduct(seed = 0): Product {\n const i = seed + 1;\n return {\n id: `p_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`,\n image: `https://placehold.co/400x400?text=Product+${i}`,\n imageAlt: `Product ${i}`,\n name: `Product ${i}`,\n oldPrice: \"$59\",\n finalPrice: \"$39\",\n description: \"Short product description.\",\n link: \"#\",\n };\n}\n\nfunction ProductGridElementPanel({ mod, el }: { mod: EmailModule; el: ProductGridElement }) {\n const patch = useElPatch(mod, el);\n const viewMode = useEmailStore((s) => s.viewMode);\n const rawStyle = (el.style ?? {}) as Record<string, unknown>;\n const style = readStyle(rawStyle, viewMode);\n const setStyle = (p: Record<string, unknown>) =>\n patch({ style: writeStylePatch(rawStyle, p, viewMode) } as Partial<ProductGridElement>);\n\n const setProducts = (products: Product[]) =>\n patch({ products } as Partial<ProductGridElement>);\n\n const setColumns = (columns: 1 | 2 | 3) => {\n // Resize products array to a sensible default for the new column count.\n const target = columns;\n let products = el.products.slice();\n if (products.length < target) {\n while (products.length < target) products.push(newProduct(products.length));\n }\n patch({ columns, products } as Partial<ProductGridElement>);\n };\n\n return (\n <>\n <PanelTitle>Product Grid</PanelTitle>\n\n <Field label=\"Columns (desktop)\">\n <div className=\"inline-flex bg-gray-100 rounded p-0.5 w-full\">\n {[1, 2, 3].map((n) => (\n <button\n key={n}\n onClick={() => setColumns(n as 1 | 2 | 3)}\n className={`flex-1 px-2 py-1 text-xs rounded ${\n el.columns === n ? \"bg-white shadow text-gray-900\" : \"text-gray-500 hover:text-gray-700\"\n }`}\n >\n {n} {n === 1 ? \"col\" : \"cols\"}\n </button>\n ))}\n </div>\n <p className=\"text-[10px] text-gray-400 mt-1\">Always stacks to 1 column on mobile.</p>\n </Field>\n\n <Field label=\"Show old price\">\n <Toggle\n checked={el.showOldPrice}\n onChange={(v) => patch({ showOldPrice: v } as Partial<ProductGridElement>)}\n />\n </Field>\n <Field label=\"Show description\">\n <Toggle\n checked={el.showDescription}\n onChange={(v) => patch({ showDescription: v } as Partial<ProductGridElement>)}\n />\n </Field>\n <Field label=\"Show button\">\n <Toggle\n checked={el.showButton}\n onChange={(v) => patch({ showButton: v } as Partial<ProductGridElement>)}\n />\n </Field>\n {el.showButton && (\n <Field label=\"Default button label\">\n <TextInput\n value={el.buttonLabel ?? \"\"}\n placeholder=\"Shop now\"\n onChange={(e) => patch({ buttonLabel: e.target.value } as Partial<ProductGridElement>)}\n />\n </Field>\n )}\n\n <div className=\"mt-4 pt-3 border-t border-gray-100\">\n <div className=\"flex items-center justify-between mb-2\">\n <PanelTitle>Products ({el.products.length})</PanelTitle>\n <button\n onClick={() => setProducts([...el.products, newProduct(el.products.length)])}\n className=\"flex items-center gap-1 px-1.5 py-0.5 text-[11px] text-blue-600 hover:bg-blue-50 rounded\"\n title=\"Add product\"\n >\n <Plus size={12} /> Add\n </button>\n </div>\n {el.products.map((p, idx) => (\n <ProductRow\n key={p.id}\n index={idx}\n product={p}\n showOldPrice={el.showOldPrice}\n showDescription={el.showDescription}\n showButton={el.showButton}\n onChange={(np) => {\n const next = [...el.products];\n next[idx] = np;\n setProducts(next);\n }}\n onDelete={() => setProducts(el.products.filter((_, i) => i !== idx))}\n />\n ))}\n </div>\n\n <div className=\"mt-4 pt-3 border-t border-gray-100\">\n <PanelTitle>Style</PanelTitle>\n <Field label=\"Card background\">\n <ColorInput\n value={(style.cardBackgroundColor as string) ?? \"\"}\n onChange={(v) => setStyle({ cardBackgroundColor: v })}\n />\n </Field>\n <Field label=\"Name color\">\n <ColorInput\n value={(style.nameColor as string) ?? \"\"}\n onChange={(v) => setStyle({ nameColor: v })}\n />\n </Field>\n <Field label=\"Final price color\">\n <ColorInput\n value={(style.finalPriceColor as string) ?? \"\"}\n onChange={(v) => setStyle({ finalPriceColor: v })}\n />\n </Field>\n <Field label=\"Old price color\">\n <ColorInput\n value={(style.oldPriceColor as string) ?? \"\"}\n onChange={(v) => setStyle({ oldPriceColor: v })}\n />\n </Field>\n <Field label=\"Button background\">\n <ColorInput\n value={(style.buttonBackgroundColor as string) ?? \"\"}\n onChange={(v) => setStyle({ buttonBackgroundColor: v })}\n />\n </Field>\n <Field label=\"Button text color\">\n <ColorInput\n value={(style.buttonColor as string) ?? \"\"}\n onChange={(v) => setStyle({ buttonColor: v })}\n />\n </Field>\n <Field label=\"Card radius\">\n <NumberInput\n value={(style.borderRadius as number) ?? 0}\n onChange={(e) => setStyle({ borderRadius: Number(e.target.value) })}\n />\n </Field>\n <PaddingFields style={style} onSet={setStyle} />\n </div>\n </>\n );\n}\n\nfunction Toggle({ checked, onChange }: { checked: boolean; onChange: (v: boolean) => void }) {\n return (\n <button\n onClick={() => onChange(!checked)}\n className={`relative inline-flex h-5 w-9 items-center rounded-full transition-colors ${\n checked ? \"bg-blue-600\" : \"bg-gray-300\"\n }`}\n >\n <span\n className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${\n checked ? \"translate-x-4\" : \"translate-x-0.5\"\n }`}\n />\n </button>\n );\n}\n\nfunction ProductRow({\n index,\n product,\n showOldPrice,\n showDescription,\n showButton,\n onChange,\n onDelete,\n}: {\n index: number;\n product: Product;\n showOldPrice: boolean;\n showDescription: boolean;\n showButton: boolean;\n onChange: (p: Product) => void;\n onDelete: () => void;\n}) {\n const set = (p: Partial<Product>) => onChange({ ...product, ...p });\n return (\n <div className=\"border border-gray-200 rounded p-2 mb-2 bg-gray-50\">\n <div className=\"flex items-center justify-between mb-2\">\n <span className=\"text-[11px] font-semibold text-gray-600\">#{index + 1}</span>\n <button\n onClick={onDelete}\n className=\"text-gray-400 hover:text-red-600\"\n title=\"Remove product\"\n >\n <Trash2 size={12} />\n </button>\n </div>\n <Field label=\"Name\">\n <TextInput value={product.name} onChange={(e) => set({ name: e.target.value })} />\n </Field>\n <Field label=\"Image URL\">\n <ImageUrlInput\n value={product.image}\n onChange={(url) => set({ image: url })}\n onAlt={(alt) => set({ imageAlt: alt })}\n />\n </Field>\n <Field label=\"Link\">\n <TextInput\n value={product.link ?? \"\"}\n onChange={(e) => set({ link: e.target.value })}\n />\n </Field>\n <div className=\"grid grid-cols-2 gap-2\">\n <Field label=\"Final price\">\n <TextInput\n value={product.finalPrice}\n onChange={(e) => set({ finalPrice: e.target.value })}\n />\n </Field>\n {showOldPrice && (\n <Field label=\"Old price\">\n <TextInput\n value={product.oldPrice ?? \"\"}\n onChange={(e) => set({ oldPrice: e.target.value })}\n />\n </Field>\n )}\n </div>\n {showDescription && (\n <Field label=\"Description\">\n <TextInput\n value={product.description ?? \"\"}\n onChange={(e) => set({ description: e.target.value })}\n />\n </Field>\n )}\n {showButton && (\n <Field label=\"Button label (override)\">\n <TextInput\n value={product.buttonLabel ?? \"\"}\n placeholder=\"Inherit default\"\n onChange={(e) => set({ buttonLabel: e.target.value || undefined })}\n />\n </Field>\n )}\n </div>\n );\n}\n","import type { ModuleDefinition } from \"./registry\";\nimport { text, image, spacer, divider, mod, PLACEHOLDER } from \"./helpers\";\n\nexport const basicModules: ModuleDefinition[] = [\n {\n type: \"basic.text\",\n category: \"basic\",\n name: \"Text Block\",\n description: \"Single editable paragraph of body copy. Use for short notes, intros, or filler text between sections.\",\n tags: [\"text\", \"paragraph\", \"body\"],\n create: () =>\n mod(\"basic.text\", \"Text Block\", [text(\"Write your text here.\", { role: \"body\" })]),\n },\n {\n type: \"basic.heading\",\n category: \"basic\",\n name: \"Heading\",\n description: \"Bold standalone heading using the theme heading font. Use to introduce a section without other elements.\",\n tags: [\"heading\", \"title\", \"section\"],\n create: () =>\n mod(\"basic.heading\", \"Heading\", [\n text(\"A clear section heading\", {\n role: \"headline\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 28,\n fontWeight: \"bold\",\n paddingTop: 16,\n paddingBottom: 8,\n lineHeight: 1.25,\n }),\n ]),\n },\n {\n type: \"basic.image\",\n category: \"basic\",\n name: \"Image\",\n description: \"Single full-width image, centered. Use for hero photography, illustrations, or screenshots.\",\n tags: [\"image\", \"media\", \"photo\"],\n create: () => mod(\"basic.image\", \"Image\", [image(PLACEHOLDER(600, 300), \"Placeholder\")]),\n },\n {\n type: \"basic.image_caption\",\n category: \"basic\",\n name: \"Image with Caption\",\n description: \"Image followed by a small italicized caption underneath. Editorial style for newsletters.\",\n tags: [\"image\", \"caption\", \"editorial\"],\n create: () =>\n mod(\"basic.image_caption\", \"Image + Caption\", [\n image(PLACEHOLDER(600, 360), \"Photo\"),\n text(\"Photo: caption goes here.\", {\n color: \"{colors.muted}\",\n fontSize: 13,\n align: \"center\",\n paddingTop: 4,\n paddingBottom: 16,\n }),\n ]),\n },\n {\n type: \"basic.spacer\",\n category: \"basic\",\n name: \"Spacer\",\n description: \"Empty vertical space. Use to separate modules with breathing room.\",\n tags: [\"spacer\", \"spacing\", \"gap\"],\n create: () => mod(\"basic.spacer\", \"Spacer\", [spacer(32)]),\n },\n {\n type: \"basic.divider\",\n category: \"basic\",\n name: \"Divider\",\n description: \"Thin horizontal rule across the email. Use to visually separate sections.\",\n tags: [\"divider\", \"separator\", \"rule\"],\n create: () => mod(\"basic.divider\", \"Divider\", [divider()]),\n },\n];\n","import type { ModuleDefinition } from \"./registry\";\nimport { text, image, mod, divider, PLACEHOLDER } from \"./helpers\";\n\nexport const headerModules: ModuleDefinition[] = [\n {\n type: \"header.logo\",\n category: \"header\",\n name: \"Logo Centered\",\n description: \"Centered brand logo. The simplest header used at the top of almost every newsletter.\",\n tags: [\"logo\", \"brand\", \"centered\"],\n create: () =>\n mod(\"header.logo\", \"Logo Header\", [\n image(PLACEHOLDER(180, 56, \"LOGO\"), \"Logo\", { width: 180, paddingTop: 24, paddingBottom: 24 }),\n ]),\n },\n {\n type: \"header.logo_left_date_right\",\n category: \"header\",\n name: \"Logo Left + Date Right\",\n description: \"Two-column header with logo on the left and a date or issue label on the right. Common for periodical newsletters and digests.\",\n tags: [\"logo\", \"date\", \"issue\", \"publication\", \"newsletter\"],\n create: () =>\n mod(\"header.logo_left_date_right\", \"Logo + Date\", [\n image(PLACEHOLDER(140, 36, \"LOGO\"), \"Logo\", { width: 140, align: \"left\", paddingTop: 16, paddingBottom: 16 }),\n text(\"Issue #128 · April 29, 2026\", {\n color: \"{colors.muted}\",\n fontSize: 13,\n align: \"right\",\n paddingTop: 0,\n paddingBottom: 16,\n }),\n divider({ paddingTop: 0, paddingBottom: 0 }),\n ]),\n },\n {\n type: \"header.publication\",\n category: \"header\",\n name: \"Publication Masthead\",\n description: \"Editorial masthead with publication name in serif type, tagline, and a divider. Mimics print magazine and newspaper newsletters.\",\n tags: [\"masthead\", \"publication\", \"editorial\", \"serif\", \"newspaper\", \"magazine\"],\n create: () =>\n mod(\n \"header.publication\",\n \"Masthead\",\n [\n text(\"THE WEEKLY\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 36,\n fontWeight: \"bold\",\n align: \"center\",\n letterSpacing: 6,\n paddingTop: 32,\n paddingBottom: 4,\n }),\n text(\"Curated reading for thoughtful people\", {\n color: \"{colors.muted}\",\n align: \"center\",\n fontSize: 13,\n paddingBottom: 16,\n }),\n divider({ paddingTop: 0, paddingBottom: 0 }),\n ]\n ),\n },\n {\n type: \"header.hero\",\n category: \"header\",\n name: \"Hero with Headline & Image\",\n description: \"Big headline, subtitle and a wide hero image. Use for the lead story or campaign announcement.\",\n tags: [\"hero\", \"headline\", \"image\", \"lead\", \"feature\"],\n create: () =>\n mod(\"header.hero\", \"Hero\", [\n text(\"Steps Towards a Greener World\", {\n role: \"headline\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 36,\n fontWeight: \"bold\",\n align: \"center\",\n paddingTop: 32,\n lineHeight: 1.2,\n }),\n text(\"Small actions, big impact.\", {\n color: \"{colors.muted}\",\n align: \"center\",\n paddingBottom: 16,\n }),\n image(PLACEHOLDER(560, 280, \"Hero\"), \"Hero\", { width: 560 }),\n ]),\n },\n {\n type: \"header.hero_text_only\",\n category: \"header\",\n name: \"Hero Text Only\",\n description: \"Centered eyebrow + large headline + supporting paragraph, no image. Editorial intro for opinion or essay newsletters.\",\n tags: [\"hero\", \"text\", \"essay\", \"editorial\", \"minimal\"],\n create: () =>\n mod(\"header.hero_text_only\", \"Hero Text\", [\n text(\"ESSAY · ISSUE 42\", {\n fontSize: 12,\n fontWeight: \"bold\",\n color: \"{colors.primary}\",\n letterSpacing: 3,\n align: \"center\",\n paddingTop: 32,\n paddingBottom: 8,\n }),\n text(\"On building things slowly\", {\n role: \"headline\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 40,\n fontWeight: \"bold\",\n align: \"center\",\n lineHeight: 1.15,\n paddingBottom: 8,\n }),\n text(\"Why patience and craft still win in a world of shortcuts.\", {\n color: \"{colors.muted}\",\n align: \"center\",\n fontSize: 16,\n paddingBottom: 32,\n }),\n ]),\n },\n {\n type: \"header.announcement\",\n category: \"header\",\n name: \"Announcement Bar\",\n description: \"Thin colored top bar with a single line of promotional text. Use for free shipping, sales, or alerts.\",\n tags: [\"announcement\", \"bar\", \"promo\", \"alert\"],\n create: () =>\n mod(\n \"header.announcement\",\n \"Announcement\",\n [\n text(\"✨ Free shipping on orders over $50\", {\n color: \"{colors.buttonText}\",\n align: \"center\",\n fontSize: 14,\n paddingTop: 12,\n paddingBottom: 12,\n }),\n ],\n { backgroundColor: \"{colors.primary}\", paddingTop: 0, paddingBottom: 0 }\n ),\n },\n {\n type: \"header.logo_with_view_browser\",\n category: \"header\",\n name: \"Logo + View in Browser\",\n description: \"Logo with a small 'View in browser' link above it. Standard for marketing newsletters that may render poorly.\",\n tags: [\"logo\", \"view-in-browser\", \"marketing\", \"preheader\"],\n create: () =>\n mod(\"header.logo_with_view_browser\", \"Logo + Browser Link\", [\n text(\"View in browser\", {\n color: \"{colors.muted}\",\n fontSize: 11,\n align: \"right\",\n paddingTop: 8,\n paddingBottom: 0,\n link: \"#\",\n }),\n image(PLACEHOLDER(160, 48, \"LOGO\"), \"Logo\", { width: 160, paddingTop: 8, paddingBottom: 16 }),\n ]),\n },\n {\n type: \"header.welcome\",\n category: \"header\",\n name: \"Welcome Header\",\n description: \"Friendly greeting with first name placeholder, used at the top of welcome and onboarding emails.\",\n tags: [\"welcome\", \"onboarding\", \"greeting\", \"personalized\"],\n create: () =>\n mod(\"header.welcome\", \"Welcome\", [\n text(\"👋 Welcome aboard, {{first_name}}\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 28,\n fontWeight: \"bold\",\n align: \"center\",\n paddingTop: 32,\n paddingBottom: 8,\n }),\n text(\"We're glad you're here. Here's what to do next.\", {\n color: \"{colors.muted}\",\n align: \"center\",\n paddingBottom: 16,\n }),\n ]),\n },\n {\n type: \"header.logo_with_tagline\",\n category: \"header\",\n name: \"Logo + Tagline\",\n description: \"Centered logo above a one-line tagline. Friendly brand-forward header.\",\n tags: [\"logo\", \"tagline\", \"brand\"],\n create: () =>\n mod(\"header.logo_with_tagline\", \"Logo + Tagline\", [\n image(PLACEHOLDER(160, 48, \"LOGO\"), \"Logo\", { width: 160, paddingTop: 24, paddingBottom: 4 }),\n text(\"Newsletters that respect your time.\", {\n align: \"center\",\n color: \"{colors.muted}\",\n fontSize: 14,\n paddingBottom: 24,\n }),\n ]),\n },\n {\n type: \"header.story_label\",\n category: \"header\",\n name: \"Story Label Header\",\n description: \"Small category label (e.g. 'Top story', 'Deep dive') above the masthead. Used by The Hustle, Morning Brew style newsletters.\",\n tags: [\"label\", \"category\", \"story\", \"newsletter\", \"topic\"],\n create: () =>\n mod(\"header.story_label\", \"Story Label\", [\n text(\"TODAY'S TOP STORY\", {\n color: \"{colors.primary}\",\n fontSize: 12,\n fontWeight: \"bold\",\n letterSpacing: 3,\n align: \"center\",\n paddingTop: 24,\n paddingBottom: 4,\n }),\n text(\"AI editing tools come for the inbox\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 28,\n fontWeight: \"bold\",\n align: \"center\",\n paddingBottom: 16,\n lineHeight: 1.2,\n }),\n ]),\n },\n];\n","import type { ModuleDefinition } from \"./registry\";\nimport { text, mod, divider } from \"./helpers\";\n\nexport const menuModules: ModuleDefinition[] = [\n {\n type: \"menu.horizontal\",\n category: \"menu\",\n name: \"Horizontal Nav\",\n description: \"Horizontal menu with 3-5 inline links separated by dots. Common publication navigation under the masthead.\",\n tags: [\"menu\", \"nav\", \"horizontal\", \"publication\"],\n create: () =>\n mod(\"menu.horizontal\", \"Horizontal Menu\", [\n text(\"Home · Articles · Podcast · About · Subscribe\", {\n align: \"center\",\n color: \"{colors.text}\",\n fontSize: 13,\n paddingTop: 12,\n paddingBottom: 12,\n }),\n ]),\n },\n {\n type: \"menu.sections\",\n category: \"menu\",\n name: \"Section Tabs\",\n description: \"Linked section labels representing the contents of today's issue (e.g. News · Markets · Tech · Culture). Used by daily digests.\",\n tags: [\"menu\", \"sections\", \"tabs\", \"digest\", \"daily\"],\n create: () =>\n mod(\"menu.sections\", \"Section Tabs\", [\n divider({ paddingTop: 0, paddingBottom: 8 }),\n text(\"NEWS · MARKETS · TECH · CULTURE · WEEKEND\", {\n align: \"center\",\n color: \"{colors.primary}\",\n fontSize: 11,\n fontWeight: \"bold\",\n letterSpacing: 2,\n paddingTop: 0,\n paddingBottom: 8,\n }),\n divider({ paddingTop: 0, paddingBottom: 8 }),\n ]),\n },\n {\n type: \"menu.in_this_issue\",\n category: \"menu\",\n name: \"In This Issue\",\n description: \"Table-of-contents box listing the items in this newsletter issue with anchor links. Helps readers scan long emails.\",\n tags: [\"toc\", \"menu\", \"issue\", \"summary\", \"table of contents\"],\n create: () =>\n mod(\n \"menu.in_this_issue\",\n \"In This Issue\",\n [\n text(\"IN THIS ISSUE\", {\n fontSize: 11,\n fontWeight: \"bold\",\n color: \"{colors.muted}\",\n letterSpacing: 2,\n paddingTop: 16,\n paddingBottom: 8,\n }),\n text(\"→ Lead story: AI in the inbox\", { fontSize: 14, paddingTop: 2, paddingBottom: 2, link: \"#lead\" }),\n text(\"→ 3 things worth your time\", { fontSize: 14, paddingTop: 2, paddingBottom: 2, link: \"#picks\" }),\n text(\"→ Reader question of the week\", { fontSize: 14, paddingTop: 2, paddingBottom: 2, link: \"#qa\" }),\n text(\"→ Upcoming events\", { fontSize: 14, paddingTop: 2, paddingBottom: 16, link: \"#events\" }),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 8, paddingBottom: 8, paddingLeft: 16, paddingRight: 16 }\n ),\n },\n {\n type: \"menu.cta_strip\",\n category: \"menu\",\n name: \"Linked Action Strip\",\n description: \"Three short text actions in a row (e.g. 'Read · Share · Reply'). Light alternative to a button bar.\",\n tags: [\"menu\", \"actions\", \"links\", \"strip\"],\n create: () =>\n mod(\"menu.cta_strip\", \"Action Strip\", [\n text(\"Read online · Share · Reply with feedback\", {\n align: \"center\",\n color: \"{colors.primary}\",\n fontSize: 13,\n paddingTop: 12,\n paddingBottom: 12,\n }),\n ]),\n },\n];\n","import type { ModuleDefinition } from \"./registry\";\nimport { text, image, mod, divider, spacer, button, eyebrow, heading, muted, PLACEHOLDER } from \"./helpers\";\n\nexport const contentModules: ModuleDefinition[] = [\n {\n type: \"content.headline_body\",\n category: \"content\",\n name: \"Headline + Body\",\n description: \"Section title with one paragraph of body text. The most generic written content block.\",\n tags: [\"headline\", \"body\", \"paragraph\", \"article\"],\n create: () =>\n mod(\"content.headline_body\", \"Headline + Body\", [\n heading(\"A compelling headline\", { paddingTop: 24 }),\n text(\n \"Tell your story with a clear, concise paragraph. Keep readers engaged with short sentences and meaningful detail.\",\n { paddingBottom: 24 }\n ),\n ]),\n },\n {\n type: \"content.lead_story\",\n category: \"content\",\n name: \"Lead Story\",\n description: \"Top story of the issue: eyebrow label, big headline, hero image, lead paragraph and a 'Continue reading' link. Used by news and editorial newsletters.\",\n tags: [\"lead\", \"story\", \"feature\", \"news\", \"editorial\", \"long-form\"],\n create: () =>\n mod(\"content.lead_story\", \"Lead Story\", [\n eyebrow(\"Lead story\"),\n heading(\"Inside the new wave of indie publishers\", { level: 1, paddingBottom: 4 }),\n muted(\"By Jane Doe · 6 min read\", { fontSize: 13 }),\n image(PLACEHOLDER(560, 320, \"Lead\"), \"Lead\", { width: 560, paddingTop: 12 }),\n text(\n \"A growing group of writers are leaving big media to build their own readerships, betting that quality and a direct relationship beat scale.\",\n { paddingTop: 16 }\n ),\n text(\"Continue reading →\", {\n color: \"{colors.primary}\",\n fontWeight: \"bold\",\n paddingTop: 4,\n paddingBottom: 24,\n link: \"#\",\n }),\n ]),\n },\n {\n type: \"content.article_summary\",\n category: \"content\",\n name: \"Article Summary Card\",\n description: \"Compact link-out card: image on top, category label, title, one-line summary, and 'Read more'. Use repeatedly to list secondary articles.\",\n tags: [\"article\", \"summary\", \"card\", \"link-out\", \"newsletter\"],\n create: () =>\n mod(\"content.article_summary\", \"Article Card\", [\n image(PLACEHOLDER(560, 280, \"Article\"), \"Article\", { width: 560 }),\n text(\"CULTURE\", {\n color: \"{colors.primary}\",\n fontSize: 11,\n fontWeight: \"bold\",\n letterSpacing: 2,\n paddingTop: 12,\n paddingBottom: 4,\n }),\n heading(\"How long-form writing made a comeback\", { paddingTop: 0, paddingBottom: 4 }),\n text(\"Why subscribers are paying for slower, deeper coverage — and what it means for publishers.\", {\n paddingBottom: 8,\n }),\n text(\"Read more →\", { color: \"{colors.primary}\", fontWeight: \"bold\", paddingBottom: 24, link: \"#\" }),\n ]),\n },\n {\n type: \"content.image_text\",\n category: \"content\",\n name: \"Image + Text Beside\",\n description: \"Image with article title and short summary stacked below. Standard editorial card.\",\n tags: [\"image\", \"text\", \"article\", \"stacked\"],\n create: () =>\n mod(\"content.image_text\", \"Image + Text\", [\n image(PLACEHOLDER(560, 300, \"Article\"), \"Article\", { width: 560 }),\n heading(\"Article title\", { paddingTop: 16, paddingBottom: 4 }),\n text(\"A short summary of the article goes here, two or three lines is plenty.\"),\n ]),\n },\n {\n type: \"content.two_column_articles\",\n category: \"content\",\n name: \"Two Column Stories\",\n description: \"Two short article previews shown side-by-side as stacked blocks (renders as full-width on mobile). Use to tease two related stories.\",\n tags: [\"two-column\", \"articles\", \"side-by-side\", \"preview\"],\n create: () =>\n mod(\"content.two_column_articles\", \"Two Stories\", [\n eyebrow(\"More to read\"),\n image(PLACEHOLDER(272, 180, \"Story A\"), \"Story A\", { width: 272 }),\n text(\"Story A title\", { fontWeight: \"bold\", paddingTop: 4, paddingBottom: 2 }),\n text(\"One sentence about story A.\", { fontSize: 14, paddingBottom: 16 }),\n image(PLACEHOLDER(272, 180, \"Story B\"), \"Story B\", { width: 272 }),\n text(\"Story B title\", { fontWeight: \"bold\", paddingTop: 4, paddingBottom: 2 }),\n text(\"One sentence about story B.\", { fontSize: 14, paddingBottom: 16 }),\n ]),\n },\n {\n type: \"content.three_picks\",\n category: \"content\",\n name: \"Three Picks (Numbered)\",\n description: \"Numbered list of three short recommendations or links. Used by curators ('3 things to read this week').\",\n tags: [\"list\", \"picks\", \"curated\", \"links\", \"recommendations\"],\n create: () =>\n mod(\"content.three_picks\", \"Three Picks\", [\n eyebrow(\"Three picks\"),\n text(\"01 / How to stay focused in 2026\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 18,\n fontWeight: \"bold\",\n paddingTop: 8,\n paddingBottom: 4,\n link: \"#\",\n }),\n muted(\"Notes on attention, deep work, and the slow internet.\", { fontSize: 14 }),\n divider({ paddingTop: 12, paddingBottom: 8 }),\n text(\"02 / The case for boring software\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 18,\n fontWeight: \"bold\",\n paddingTop: 8,\n paddingBottom: 4,\n link: \"#\",\n }),\n muted(\"Why teams are returning to simpler, predictable tools.\", { fontSize: 14 }),\n divider({ paddingTop: 12, paddingBottom: 8 }),\n text(\"03 / A short history of the inbox\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 18,\n fontWeight: \"bold\",\n paddingTop: 8,\n paddingBottom: 4,\n link: \"#\",\n }),\n muted(\"From memos to MIME, and what comes next.\", { fontSize: 14, paddingBottom: 24 }),\n ]),\n },\n {\n type: \"content.quote\",\n category: \"content\",\n name: \"Pull Quote\",\n description: \"Centered serif pull quote with attribution. Adds rhythm to long editorial newsletters.\",\n tags: [\"quote\", \"pull-quote\", \"editorial\", \"attribution\"],\n create: () =>\n mod(\"content.quote\", \"Pull Quote\", [\n text(\"“The best way to predict the future is to create it.”\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 22,\n align: \"center\",\n paddingTop: 24,\n lineHeight: 1.4,\n }),\n text(\"— Peter Drucker\", { color: \"{colors.muted}\", align: \"center\", paddingBottom: 24 }),\n ]),\n },\n {\n type: \"content.author_byline\",\n category: \"content\",\n name: \"Author Byline\",\n description: \"Round avatar + author name + role on one line. Drop above or below an article body for personal newsletters.\",\n tags: [\"author\", \"byline\", \"avatar\", \"personal\"],\n create: () =>\n mod(\"content.author_byline\", \"Byline\", [\n image(PLACEHOLDER(64, 64, \"👤\"), \"Author\", { width: 64, borderRadius: 32, paddingTop: 16, paddingBottom: 0 }),\n text(\"Jane Doe\", { align: \"center\", fontWeight: \"bold\", paddingTop: 8, paddingBottom: 0 }),\n muted(\"Editor, The Weekly\", { align: \"center\", fontSize: 13 }),\n spacer(16),\n ]),\n },\n {\n type: \"content.editor_note\",\n category: \"content\",\n name: \"Editor's Note\",\n description: \"Personal letter-style block: 'Hi {{first_name}}', a few paragraphs and a sign-off. Ideal for newsletters with a strong author voice.\",\n tags: [\"editor\", \"note\", \"letter\", \"personal\", \"voice\"],\n create: () =>\n mod(\"content.editor_note\", \"Editor's Note\", [\n text(\"Hi {{first_name}},\", { paddingTop: 24, paddingBottom: 8 }),\n text(\n \"This week I've been thinking about what makes a newsletter feel like a letter rather than a broadcast. Spoiler: it's not the format, it's the tone.\",\n { paddingBottom: 8, lineHeight: 1.7 }\n ),\n text(\"Let me know what you think — just hit reply.\", { paddingBottom: 8, lineHeight: 1.7 }),\n text(\"— Jane\", { fontFamily: \"{fonts.heading}\", paddingBottom: 24 }),\n ]),\n },\n {\n type: \"content.tip_box\",\n category: \"content\",\n name: \"Tip / Callout Box\",\n description: \"Highlighted background box with an icon, short title and one-paragraph tip. Use for 'pro tips', notes, and warnings.\",\n tags: [\"tip\", \"callout\", \"box\", \"highlight\", \"note\"],\n create: () =>\n mod(\n \"content.tip_box\",\n \"Tip Box\",\n [\n text(\"💡 PRO TIP\", {\n color: \"{colors.primary}\",\n fontSize: 12,\n fontWeight: \"bold\",\n letterSpacing: 2,\n paddingTop: 16,\n paddingBottom: 4,\n }),\n text(\"Always preview your email on mobile before sending — most opens happen there.\", { paddingBottom: 16 }),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0, paddingLeft: 16, paddingRight: 16 }\n ),\n },\n {\n type: \"content.numbered_list\",\n category: \"content\",\n name: \"Numbered List\",\n description: \"Vertical numbered list of 4-5 short items with optional sub-text. Use for tutorials, checklists and 'how-to' newsletters.\",\n tags: [\"list\", \"numbered\", \"tutorial\", \"checklist\", \"how-to\"],\n create: () =>\n mod(\"content.numbered_list\", \"Numbered List\", [\n heading(\"How to do it in 4 steps\", { paddingTop: 16, paddingBottom: 12 }),\n text(\"1. Define the goal\", { fontWeight: \"bold\", paddingTop: 4, paddingBottom: 2 }),\n muted(\"Write down the outcome in one sentence.\"),\n text(\"2. List constraints\", { fontWeight: \"bold\", paddingTop: 8, paddingBottom: 2 }),\n muted(\"Time, budget, scope. Be specific.\"),\n text(\"3. Plan the smallest version\", { fontWeight: \"bold\", paddingTop: 8, paddingBottom: 2 }),\n muted(\"What can you ship this week?\"),\n text(\"4. Ship it\", { fontWeight: \"bold\", paddingTop: 8, paddingBottom: 2 }),\n muted(\"Refine after real feedback.\", { fontSize: 14 }),\n spacer(16),\n ]),\n },\n {\n type: \"content.bullet_list\",\n category: \"content\",\n name: \"Bullet List\",\n description: \"Simple unordered list of takeaways or facts. Concise summary block.\",\n tags: [\"list\", \"bullets\", \"takeaways\", \"summary\"],\n create: () =>\n mod(\"content.bullet_list\", \"Bullets\", [\n heading(\"Key takeaways\", { paddingTop: 16, paddingBottom: 8 }),\n text(\"• Newsletters are growing 20% YoY\", { paddingTop: 2, paddingBottom: 2 }),\n text(\"• Mobile opens crossed 70%\", { paddingTop: 2, paddingBottom: 2 }),\n text(\"• Plain-text emails outperform image-heavy ones in B2B\", { paddingTop: 2, paddingBottom: 2 }),\n text(\"• Personalization drives 2x click-through\", { paddingTop: 2, paddingBottom: 16 }),\n ]),\n },\n {\n type: \"content.qa\",\n category: \"content\",\n name: \"Q&A Block\",\n description: \"Question in bold followed by an answer paragraph. Use for FAQ, reader mailbags, or AMAs.\",\n tags: [\"qa\", \"faq\", \"ama\", \"mailbag\", \"reader-questions\"],\n create: () =>\n mod(\"content.qa\", \"Q&A\", [\n eyebrow(\"Reader question\"),\n text(\"Q: How do I get my first 100 subscribers?\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 18,\n fontWeight: \"bold\",\n paddingTop: 4,\n paddingBottom: 8,\n lineHeight: 1.3,\n }),\n text(\n \"A: Tell ten people who already know you. Then ask each of them to forward to one friend. The first 100 don't come from algorithms — they come from your network.\",\n { paddingBottom: 24, lineHeight: 1.7 }\n ),\n ]),\n },\n {\n type: \"content.stats_row\",\n category: \"content\",\n name: \"Stat Row\",\n description: \"Big numbers with short labels (e.g. '12k readers · 4.8★ rating · 96% open rate'). Used for impact summaries and social proof.\",\n tags: [\"stats\", \"numbers\", \"metrics\", \"social-proof\"],\n create: () =>\n mod(\n \"content.stats_row\",\n \"Stat Row\",\n [\n eyebrow(\"By the numbers\", { align: \"center\" }),\n text(\"12,400\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 36,\n fontWeight: \"bold\",\n align: \"center\",\n color: \"{colors.primary}\",\n paddingTop: 4,\n paddingBottom: 0,\n }),\n muted(\"active readers this month\", { align: \"center\", fontSize: 13 }),\n spacer(8),\n text(\"96% · 4.8★ · 32 issues shipped\", {\n align: \"center\",\n color: \"{colors.text}\",\n fontSize: 14,\n paddingBottom: 24,\n }),\n ]\n ),\n },\n {\n type: \"content.timeline\",\n category: \"content\",\n name: \"Timeline / What Happened\",\n description: \"Chronological list of recent events with dates. Used by news roundups and changelog newsletters.\",\n tags: [\"timeline\", \"changelog\", \"news\", \"events\", \"what-happened\"],\n create: () =>\n mod(\"content.timeline\", \"Timeline\", [\n eyebrow(\"This week\"),\n text(\"Mon · Acme launches plan B\", { fontWeight: \"bold\", paddingTop: 8, paddingBottom: 2 }),\n muted(\"After 6 months of beta testing.\", { fontSize: 14 }),\n text(\"Wed · New funding round announced\", { fontWeight: \"bold\", paddingTop: 8, paddingBottom: 2 }),\n muted(\"$24M Series A led by Foundry.\", { fontSize: 14 }),\n text(\"Fri · Industry report drops\", { fontWeight: \"bold\", paddingTop: 8, paddingBottom: 2 }),\n muted(\"Open rates up across the board.\", { fontSize: 14, paddingBottom: 24 }),\n ]),\n },\n {\n type: \"content.podcast_episode\",\n category: \"content\",\n name: \"Podcast Episode\",\n description: \"Episode artwork, episode number, title, short description and a 'Listen' button. For shows that announce episodes by email.\",\n tags: [\"podcast\", \"episode\", \"audio\", \"listen\", \"show\"],\n create: () =>\n mod(\"content.podcast_episode\", \"Podcast Episode\", [\n image(PLACEHOLDER(220, 220, \"Cover\"), \"Cover\", { width: 220, borderRadius: 12 }),\n text(\"EPISODE 042\", {\n color: \"{colors.primary}\",\n fontSize: 11,\n fontWeight: \"bold\",\n letterSpacing: 2,\n align: \"center\",\n paddingTop: 12,\n paddingBottom: 4,\n }),\n heading(\"Why publishers are betting on email\", { align: \"center\", paddingTop: 0, paddingBottom: 4 }),\n muted(\"With Jane Doe · 38 min\", { align: \"center\", fontSize: 13 }),\n button(\"Listen now\", \"https://example.com\"),\n spacer(16),\n ]),\n },\n {\n type: \"content.video_thumbnail\",\n category: \"content\",\n name: \"Video Thumbnail\",\n description: \"Video thumbnail with overlay-feeling play button (image only, links to a hosted player). Title and duration below.\",\n tags: [\"video\", \"thumbnail\", \"watch\", \"play\", \"media\"],\n create: () =>\n mod(\"content.video_thumbnail\", \"Video\", [\n image(PLACEHOLDER(560, 315, \"▶ Watch\"), \"Video\", { width: 560, link: \"#\", borderRadius: 8 }),\n heading(\"Watch: a guided tour of our 2026 launches\", { paddingTop: 12, paddingBottom: 4 }),\n muted(\"4 min watch\", { fontSize: 13, paddingBottom: 16 }),\n ]),\n },\n {\n type: \"content.event_card\",\n category: \"content\",\n name: \"Event Card\",\n description: \"Date badge with event title, location, time and an RSVP button. For event-driven newsletters and community digests.\",\n tags: [\"event\", \"rsvp\", \"community\", \"date\", \"card\"],\n create: () =>\n mod(\n \"content.event_card\",\n \"Event\",\n [\n text(\"MAY\", {\n align: \"center\",\n color: \"{colors.buttonText}\",\n fontSize: 12,\n fontWeight: \"bold\",\n letterSpacing: 2,\n paddingTop: 12,\n paddingBottom: 0,\n }),\n text(\"12\", {\n align: \"center\",\n color: \"{colors.buttonText}\",\n fontSize: 36,\n fontWeight: \"bold\",\n paddingTop: 0,\n paddingBottom: 12,\n }),\n ],\n { backgroundColor: \"{colors.primary}\", paddingTop: 0, paddingBottom: 0 }\n ),\n },\n {\n type: \"content.code_block\",\n category: \"content\",\n name: \"Code Snippet\",\n description: \"Monospaced code block on a tinted background. For developer newsletters and changelog excerpts.\",\n tags: [\"code\", \"snippet\", \"developer\", \"monospace\", \"changelog\"],\n create: () =>\n mod(\n \"content.code_block\",\n \"Code\",\n [\n text(\"npm install @one-million-lines/email-builder\", {\n fontFamily: \"Menlo, Consolas, monospace\",\n fontSize: 13,\n color: \"{colors.text}\",\n paddingTop: 16,\n paddingBottom: 16,\n paddingLeft: 16,\n paddingRight: 16,\n }),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0, paddingLeft: 16, paddingRight: 16 }\n ),\n },\n];\n","import type { ModuleDefinition } from \"./registry\";\nimport { text, image, button, mod, divider, heading, muted, eyebrow, spacer, product, productGrid, PLACEHOLDER } from \"./helpers\";\n\nexport const featureModules: ModuleDefinition[] = [\n {\n type: \"feature.list\",\n category: \"feature\",\n name: \"Checkmark Feature List\",\n description: \"Centered title with 3-4 short checkmarked benefits. Good for product newsletters and onboarding emails.\",\n tags: [\"features\", \"benefits\", \"checkmarks\", \"list\"],\n create: () =>\n mod(\"feature.list\", \"Feature List\", [\n heading(\"Why people love it\", { align: \"center\", paddingTop: 24 }),\n text(\"✓ Fast and reliable\", { align: \"center\" }),\n text(\"✓ Beautiful out of the box\", { align: \"center\" }),\n text(\"✓ Backed by humans, not bots\", { align: \"center\", paddingBottom: 24 }),\n ]),\n },\n {\n type: \"feature.icon_three\",\n category: \"feature\",\n name: \"Three Icon Features\",\n description: \"Three stacked feature blocks with an emoji/icon, short title and one-line description. Use to highlight 3 product capabilities.\",\n tags: [\"features\", \"icons\", \"three-up\", \"product\"],\n create: () =>\n mod(\"feature.icon_three\", \"Three Features\", [\n text(\"⚡\", { align: \"center\", fontSize: 32, paddingTop: 24, paddingBottom: 4 }),\n text(\"Fast\", { align: \"center\", fontWeight: \"bold\", paddingBottom: 2 }),\n muted(\"Built to render in milliseconds.\", { align: \"center\", fontSize: 14 }),\n spacer(16),\n text(\"🧩\", { align: \"center\", fontSize: 32, paddingBottom: 4 }),\n text(\"Modular\", { align: \"center\", fontWeight: \"bold\", paddingBottom: 2 }),\n muted(\"Compose any layout from blocks.\", { align: \"center\", fontSize: 14 }),\n spacer(16),\n text(\"🤖\", { align: \"center\", fontSize: 32, paddingBottom: 4 }),\n text(\"AI-ready\", { align: \"center\", fontWeight: \"bold\", paddingBottom: 2 }),\n muted(\"Edit emails as JSON, not HTML.\", { align: \"center\", fontSize: 14, paddingBottom: 24 }),\n ]),\n },\n {\n type: \"feature.before_after\",\n category: \"feature\",\n name: \"Before / After\",\n description: \"Two stacked images labeled 'Before' and 'After'. For product transformations, redesigns and case studies.\",\n tags: [\"before-after\", \"comparison\", \"case-study\", \"transformation\"],\n create: () =>\n mod(\"feature.before_after\", \"Before / After\", [\n eyebrow(\"Before\"),\n image(PLACEHOLDER(560, 280, \"Before\"), \"Before\", { width: 560 }),\n spacer(8),\n eyebrow(\"After\"),\n image(PLACEHOLDER(560, 280, \"After\"), \"After\", { width: 560 }),\n spacer(16),\n ]),\n },\n {\n type: \"feature.benefit_pair\",\n category: \"feature\",\n name: \"Image + Benefit Pair\",\n description: \"Repeat-use block: one supporting image plus a title and benefit paragraph beside it. Stack 2-3 of these for a feature tour.\",\n tags: [\"benefit\", \"feature\", \"image-text\", \"pair\"],\n create: () =>\n mod(\"feature.benefit_pair\", \"Benefit Pair\", [\n image(PLACEHOLDER(560, 240, \"Feature\"), \"Feature\", { width: 560, paddingTop: 16 }),\n heading(\"Send 10x faster\", { paddingTop: 12, paddingBottom: 4 }),\n text(\"Reusable modules and theme tokens let teams ship campaigns in minutes, not days.\", { paddingBottom: 24 }),\n ]),\n },\n {\n type: \"feature.testimonial\",\n category: \"feature\",\n name: \"Testimonial\",\n description: \"Customer quote in large type with avatar and attribution. Social proof block.\",\n tags: [\"testimonial\", \"review\", \"social-proof\", \"customer\"],\n create: () =>\n mod(\"feature.testimonial\", \"Testimonial\", [\n text(\"\\u201cThis cut our email production from a week to an afternoon.\\u201d\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 22,\n align: \"center\",\n paddingTop: 24,\n paddingBottom: 12,\n lineHeight: 1.4,\n }),\n image(PLACEHOLDER(56, 56, \"👤\"), \"Customer\", { width: 56, borderRadius: 28 }),\n text(\"Alex Kim · Head of Lifecycle, Acme\", {\n align: \"center\",\n color: \"{colors.muted}\",\n fontSize: 13,\n paddingTop: 4,\n paddingBottom: 24,\n }),\n ]),\n },\n {\n type: \"feature.logo_strip\",\n category: \"feature\",\n name: \"Customer Logo Strip\",\n description: \"Small horizontal row implying customer logos for credibility ('Trusted by'). Logos shown as a placeholder image.\",\n tags: [\"logos\", \"trusted-by\", \"social-proof\", \"strip\"],\n create: () =>\n mod(\"feature.logo_strip\", \"Logo Strip\", [\n muted(\"TRUSTED BY\", { align: \"center\", fontSize: 11 }),\n image(PLACEHOLDER(520, 60, \"LOGOS\"), \"Customer logos\", { width: 520, paddingTop: 8, paddingBottom: 16 }),\n ]),\n },\n // ---------- Additional feature blocks ----------\n {\n type: \"feature.gradient_hero\",\n category: \"feature\",\n name: \"Gradient Hero CTA\",\n description: \"Bold centered hero with an eyebrow, oversized headline and a primary CTA button. Great for launch announcements and campaign openers.\",\n tags: [\"hero\", \"launch\", \"cta\", \"bold\", \"announcement\"],\n create: () =>\n mod(\n \"feature.gradient_hero\",\n \"Gradient Hero CTA\",\n [\n eyebrow(\"Introducing\", { align: \"center\" }),\n heading(\"Something new is here\", {\n level: 1,\n align: \"center\",\n paddingTop: 4,\n paddingBottom: 8,\n }),\n text(\"A fresh way to reach your audience — crafted for the inbox.\", {\n align: \"center\",\n color: \"{colors.muted}\",\n fontSize: 16,\n paddingBottom: 20,\n }),\n button(\"Explore now\", \"#\", { align: \"center\" }),\n ],\n { backgroundColor: \"{colors.surface}\", paddingTop: 40, paddingBottom: 40 }\n ),\n },\n {\n type: \"feature.pull_quote\",\n category: \"feature\",\n name: \"Pull Quote\",\n description: \"Large centered quotation with an attribution line. Use to highlight a testimonial or a memorable line.\",\n tags: [\"quote\", \"testimonial\", \"highlight\", \"pull-quote\"],\n create: () =>\n mod(\"feature.pull_quote\", \"Pull Quote\", [\n text(\"\\u201cThis is the fastest we\\u2019ve ever shipped a campaign.\\u201d\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 24,\n align: \"center\",\n lineHeight: 1.4,\n paddingTop: 28,\n paddingBottom: 8,\n }),\n muted(\"— A very happy customer\", { align: \"center\", paddingBottom: 28 }),\n ]),\n },\n {\n type: \"feature.stat_row\",\n category: \"feature\",\n name: \"Stat Row\",\n description: \"Three short number + label pairs in a row. Use to show traction, metrics or highlights.\",\n tags: [\"stats\", \"metrics\", \"numbers\", \"row\", \"kpi\"],\n create: () =>\n mod(\"feature.stat_row\", \"Stat Row\", [\n heading(\"By the numbers\", { align: \"center\", paddingTop: 24 }),\n text(\n \"<b>10k+</b> subscribers \\u00b7 <b>98%</b> delivery \\u00b7 <b>4.9\\u2605</b> rating\",\n { align: \"center\", color: \"{colors.muted}\", paddingBottom: 24 }\n ),\n ]),\n },\n {\n type: \"feature.single_product_spotlight\",\n category: \"feature\",\n name: \"Single Product Spotlight\",\n description: \"One product with image, name, price and buy button. Use to feature a hero product in a feature-focused email.\",\n tags: [\"product\", \"spotlight\", \"single\", \"buy\", \"shop\", \"ecommerce\"],\n create: () =>\n mod(\"feature.single_product_spotlight\", \"Product Spotlight\", [\n productGrid(\n [\n product({\n name: \"The Signature Bag\",\n finalPrice: \"$129\",\n oldPrice: \"$159\",\n description: \"Handmade, built to last.\",\n image: PLACEHOLDER(520, 520, \"Product\"),\n }),\n ],\n { columns: 1, showDescription: true, buttonLabel: \"Buy now\" }\n ),\n ]),\n },\n {\n type: \"feature.pill_nav\",\n category: \"feature\",\n name: \"Pill Navigation\",\n description: \"Centered row of navigation links with a divider below. Compact feature nav block for use inside email content sections.\",\n tags: [\"menu\", \"nav\", \"links\", \"pill\"],\n create: () =>\n mod(\"feature.pill_nav\", \"Pill Navigation\", [\n image(PLACEHOLDER(120, 32, \"LOGO\"), \"Logo\", { width: 120, paddingBottom: 8 }),\n text(\n '<a href=\"#\">Shop</a> <a href=\"#\">New</a> <a href=\"#\">Sale</a> <a href=\"#\">About</a>',\n { align: \"center\", color: \"{colors.primary}\", paddingBottom: 8 }\n ),\n divider({ paddingTop: 4, paddingBottom: 0 }),\n ]),\n },\n];\n","import type { ModuleDefinition } from \"./registry\";\nimport { text, mod, button, spacer, image, heading, muted, eyebrow, PLACEHOLDER } from \"./helpers\";\n\nexport const ctaModules: ModuleDefinition[] = [\n {\n type: \"cta.simple\",\n category: \"call_to_action\",\n name: \"Simple CTA\",\n description: \"Centered headline + body + primary button. The default call-to-action block for any newsletter or promo.\",\n tags: [\"cta\", \"primary\", \"centered\", \"button\"],\n create: () =>\n mod(\"cta.simple\", \"Simple CTA\", [\n heading(\"Ready to get started?\", { align: \"center\", paddingTop: 24 }),\n muted(\"Create better emails faster.\", { align: \"center\" }),\n button(\"Start now\", \"https://example.com\"),\n spacer(16),\n ]),\n },\n {\n type: \"cta.banner\",\n category: \"call_to_action\",\n name: \"Colored Banner CTA\",\n description: \"Full-width colored band with eyebrow, big headline and a contrasting button. Use to draw attention to sales or launches.\",\n tags: [\"cta\", \"banner\", \"colored\", \"promo\", \"sale\"],\n create: () =>\n mod(\n \"cta.banner\",\n \"CTA Banner\",\n [\n text(\"Limited time offer\", {\n color: \"{colors.buttonText}\",\n align: \"center\",\n fontSize: 14,\n paddingTop: 24,\n paddingBottom: 4,\n }),\n text(\"Save 30% this week only\", {\n color: \"{colors.buttonText}\",\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 28,\n fontWeight: \"bold\",\n paddingBottom: 16,\n }),\n button(\"Shop the sale\"),\n spacer(24),\n ],\n { backgroundColor: \"{colors.primary}\", paddingTop: 0, paddingBottom: 0 }\n ),\n },\n {\n type: \"cta.button_only\",\n category: \"call_to_action\",\n name: \"Button Only\",\n description: \"Single primary button on a clean background. Use as a follow-up CTA after a content block.\",\n tags: [\"cta\", \"button\", \"minimal\"],\n create: () => mod(\"cta.button_only\", \"Button\", [button(\"Click here\", \"https://example.com\")]),\n },\n {\n type: \"cta.dual_button\",\n category: \"call_to_action\",\n name: \"Two Button Choice\",\n description: \"Two side-by-side actions: a primary and a ghost-styled secondary. Use when offering 'Learn more' vs 'Get started'.\",\n tags: [\"cta\", \"buttons\", \"two-options\", \"choice\"],\n create: () =>\n mod(\"cta.dual_button\", \"Two Buttons\", [\n heading(\"Pick your path\", { align: \"center\", paddingTop: 24 }),\n muted(\"Choose what fits your team.\", { align: \"center\" }),\n button(\"Get started\", \"https://example.com\"),\n button(\"Learn more\", \"https://example.com\", { backgroundColor: \"transparent\", color: \"{colors.primary}\" }),\n spacer(16),\n ]),\n },\n {\n type: \"cta.image_overlay\",\n category: \"call_to_action\",\n name: \"Image + Overlay CTA\",\n description: \"Lead image with a headline, supporting text, and a button immediately below. Strong visual call to action.\",\n tags: [\"cta\", \"image\", \"visual\", \"hero\"],\n create: () =>\n mod(\"cta.image_overlay\", \"Image CTA\", [\n image(PLACEHOLDER(560, 280, \"Visual\"), \"Visual\", { width: 560, paddingTop: 16 }),\n heading(\"Stop guessing. Start measuring.\", { align: \"center\", paddingTop: 16 }),\n muted(\"Free for 14 days. No credit card.\", { align: \"center\" }),\n button(\"Try it free\"),\n spacer(16),\n ]),\n },\n {\n type: \"cta.subscribe\",\n category: \"call_to_action\",\n name: \"Subscribe / Forward\",\n description: \"Friendly 'Was this forwarded? Subscribe' block that grows the list virally. Common at the end of newsletters.\",\n tags: [\"cta\", \"subscribe\", \"forward\", \"growth\", \"newsletter\"],\n create: () =>\n mod(\n \"cta.subscribe\",\n \"Subscribe\",\n [\n eyebrow(\"Was this forwarded?\", { align: \"center\" }),\n heading(\"Get the next issue in your inbox\", { align: \"center\", paddingTop: 0, paddingBottom: 8 }),\n button(\"Subscribe free\"),\n spacer(16),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n },\n {\n type: \"cta.referral\",\n category: \"call_to_action\",\n name: \"Referral / Share\",\n description: \"Encourages readers to share the newsletter with a unique referral link. Includes a 'Share' button and a personalized URL.\",\n tags: [\"cta\", \"referral\", \"share\", \"viral\", \"growth\"],\n create: () =>\n mod(\"cta.referral\", \"Referral\", [\n eyebrow(\"Tell a friend\", { align: \"center\" }),\n heading(\"Share & earn perks\", { align: \"center\", paddingTop: 0, paddingBottom: 8 }),\n muted(\"Refer 3 friends and unlock the bonus issue.\", { align: \"center\" }),\n text(\"yourname.com/r/abc123\", {\n align: \"center\",\n color: \"{colors.primary}\",\n fontFamily: \"Menlo, Consolas, monospace\",\n fontSize: 14,\n paddingTop: 8,\n paddingBottom: 8,\n }),\n button(\"Share now\"),\n spacer(16),\n ]),\n },\n {\n type: \"cta.upgrade\",\n category: \"call_to_action\",\n name: \"Upgrade / Paid\",\n description: \"Conversion block that promotes a paid plan or premium tier. Includes price, benefits and an upgrade button.\",\n tags: [\"cta\", \"upgrade\", \"paid\", \"premium\", \"conversion\"],\n create: () =>\n mod(\n \"cta.upgrade\",\n \"Upgrade\",\n [\n eyebrow(\"Become a member\", { align: \"center\" }),\n heading(\"$5 / month\", { align: \"center\", level: 1 }),\n muted(\"Unlock the archive, weekly bonus and member chat.\", { align: \"center\", fontSize: 14 }),\n button(\"Upgrade\"),\n spacer(16),\n ],\n { backgroundColor: \"{colors.background}\", paddingTop: 0, paddingBottom: 0 }\n ),\n },\n {\n type: \"cta.feedback\",\n category: \"call_to_action\",\n name: \"Feedback Reply\",\n description: \"Asks the reader to reply with feedback ('Hit reply and let me know'). Personal, no button.\",\n tags: [\"cta\", \"feedback\", \"reply\", \"personal\"],\n create: () =>\n mod(\"cta.feedback\", \"Feedback\", [\n text(\"How did this issue land for you? Just hit reply — I read every message.\", {\n align: \"center\",\n paddingTop: 24,\n paddingBottom: 24,\n lineHeight: 1.6,\n }),\n ]),\n },\n];\n","import type { ModuleDefinition } from \"./registry\";\nimport {\n text,\n image,\n mod,\n button,\n spacer,\n divider,\n heading,\n muted,\n eyebrow,\n PLACEHOLDER,\n product,\n productGrid,\n} from \"./helpers\";\n\nexport const ecommerceModules: ModuleDefinition[] = [\n {\n type: \"ecom.product_single\",\n category: \"ecommerce\",\n name: \"Single Product\",\n description: \"One product with image, title, price, short description and Buy button. Use to feature a hero product. Supports old/final price and per-product link.\",\n tags: [\"product\", \"single\", \"buy\", \"hero\"],\n create: () =>\n mod(\"ecom.product_single\", \"Single Product\", [\n productGrid(\n [\n product({\n name: \"Linen Tote Bag\",\n image: PLACEHOLDER(560, 400, \"Product\"),\n oldPrice: \"$59.00\",\n finalPrice: \"$39.00\",\n description: \"Heavyweight natural linen, made in Portugal.\",\n }),\n ],\n { columns: 1, showOldPrice: true, showDescription: true, buttonLabel: \"Buy now\" }\n ),\n ]),\n },\n {\n type: \"ecom.product_grid_2\",\n category: \"ecommerce\",\n name: \"Product Grid (2 up)\",\n description: \"Two products side-by-side on desktop, stacked on mobile. Each card has image, name, old/final price, optional description and Shop button. Curated picks layout.\",\n tags: [\"product\", \"grid\", \"two-up\", \"curated\", \"responsive\"],\n create: () =>\n mod(\"ecom.product_grid_2\", \"Product Grid 2\", [\n productGrid(\n [\n product({ name: \"Product A\", finalPrice: \"$29\", oldPrice: \"$39\" }),\n product({ name: \"Product B\", finalPrice: \"$34\", oldPrice: \"$45\" }),\n ],\n { columns: 2, showOldPrice: true }\n ),\n ]),\n },\n {\n type: \"ecom.product_grid_3\",\n category: \"ecommerce\",\n name: \"Product Grid (3 up)\",\n description: \"Three product cards in a row on desktop, stacked on mobile. Use for 'New arrivals' or 'Bestsellers' rows.\",\n tags: [\"product\", \"grid\", \"three-up\", \"bestsellers\", \"new-arrivals\", \"responsive\"],\n create: () =>\n mod(\"ecom.product_grid_3\", \"Product Grid 3\", [\n eyebrow(\"New arrivals\", { align: \"center\" }),\n productGrid(\n [\n product({ name: \"Product 1\", finalPrice: \"$19\" }),\n product({ name: \"Product 2\", finalPrice: \"$24\" }),\n product({ name: \"Product 3\", finalPrice: \"$32\" }),\n ],\n { columns: 3, showOldPrice: false }\n ),\n ]),\n },\n {\n type: \"ecom.collection_banner\",\n category: \"ecommerce\",\n name: \"Collection Banner\",\n description: \"Wide collection banner with title and 'Shop the collection' button overlaying or under an image. Use for category drops.\",\n tags: [\"collection\", \"banner\", \"category\", \"drop\"],\n create: () =>\n mod(\"ecom.collection_banner\", \"Collection\", [\n image(PLACEHOLDER(560, 300, \"Collection\"), \"Collection\", { width: 560 }),\n heading(\"Spring Collection 2026\", { align: \"center\", paddingTop: 16 }),\n muted(\"Lighter fabrics, brighter colors.\", { align: \"center\" }),\n button(\"Shop the collection\"),\n spacer(16),\n ]),\n },\n {\n type: \"ecom.discount\",\n category: \"ecommerce\",\n name: \"Discount Code\",\n description: \"Big discount code in monospaced caps with 'Your code' label and a Redeem button.\",\n tags: [\"discount\", \"promo\", \"code\", \"coupon\"],\n create: () =>\n mod(\"ecom.discount\", \"Discount Code\", [\n muted(\"Your code\", { align: \"center\" }),\n text(\"SAVE20\", {\n fontFamily: \"{fonts.heading}\",\n fontSize: 36,\n fontWeight: \"bold\",\n align: \"center\",\n color: \"{colors.primary}\",\n letterSpacing: 4,\n paddingTop: 4,\n paddingBottom: 16,\n }),\n button(\"Redeem\"),\n spacer(24),\n ]),\n },\n {\n type: \"ecom.flash_sale\",\n category: \"ecommerce\",\n name: \"Flash Sale Banner\",\n description: \"Urgency-driven banner with countdown-style copy ('Ends in 24h'), discount value and a shop button.\",\n tags: [\"flash-sale\", \"urgency\", \"promo\", \"banner\", \"countdown\"],\n create: () =>\n mod(\n \"ecom.flash_sale\",\n \"Flash Sale\",\n [\n text(\"⏰ FLASH SALE — ENDS IN 24H\", {\n color: \"{colors.buttonText}\",\n align: \"center\",\n fontWeight: \"bold\",\n letterSpacing: 2,\n paddingTop: 16,\n paddingBottom: 4,\n }),\n text(\"Up to 50% off everything\", {\n color: \"{colors.buttonText}\",\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontSize: 28,\n fontWeight: \"bold\",\n paddingBottom: 12,\n }),\n button(\"Shop now\", \"#\", { backgroundColor: \"{colors.surface}\", color: \"{colors.primary}\" }),\n spacer(16),\n ],\n { backgroundColor: \"{colors.primary}\", paddingTop: 0, paddingBottom: 0 }\n ),\n },\n {\n type: \"ecom.abandoned_cart\",\n category: \"ecommerce\",\n name: \"Abandoned Cart Reminder\",\n description: \"Friendly reminder showing the items left in the cart with a return-to-cart button. For cart recovery automations.\",\n tags: [\"abandoned-cart\", \"recovery\", \"automation\", \"reminder\"],\n create: () =>\n mod(\"ecom.abandoned_cart\", \"Abandoned Cart\", [\n heading(\"You left something behind\", { align: \"center\", paddingTop: 16 }),\n muted(\"Pick up where you left off.\", { align: \"center\" }),\n spacer(8),\n productGrid(\n [\n product({\n name: \"Linen Tote Bag\",\n image: PLACEHOLDER(400, 400, \"Item\"),\n finalPrice: \"$39\",\n oldPrice: \"$49\",\n }),\n ],\n { columns: 1, showOldPrice: true, buttonLabel: \"Return to cart\" }\n ),\n ]),\n },\n {\n type: \"ecom.review_request\",\n category: \"ecommerce\",\n name: \"Review Request\",\n description: \"Post-purchase block asking for a 1-5 star rating with stacked star buttons. For review-collection emails.\",\n tags: [\"review\", \"rating\", \"post-purchase\", \"feedback\"],\n create: () =>\n mod(\"ecom.review_request\", \"Review\", [\n heading(\"How did we do?\", { align: \"center\", paddingTop: 24 }),\n muted(\"Tap a star to leave a quick review.\", { align: \"center\" }),\n text(\"☆ ☆ ☆ ☆ ☆\", {\n align: \"center\",\n fontSize: 32,\n color: \"{colors.primary}\",\n paddingTop: 12,\n paddingBottom: 24,\n link: \"#\",\n }),\n ]),\n },\n {\n type: \"ecom.gift_guide\",\n category: \"ecommerce\",\n name: \"Gift Guide Pick\",\n description: \"Editorial gift-guide pick: persona eyebrow + a single product card with full details (image, name, old/final price, description, CTA).\",\n tags: [\"gift-guide\", \"curated\", \"editorial\", \"holiday\"],\n create: () =>\n mod(\"ecom.gift_guide\", \"Gift Pick\", [\n eyebrow(\"For the home cook\"),\n productGrid(\n [\n product({\n name: \"Cast Iron Skillet\",\n image: PLACEHOLDER(560, 300, \"Pick\"),\n oldPrice: \"$119\",\n finalPrice: \"$89\",\n description: \"Pre-seasoned, lifetime-guarantee. Made in USA.\",\n }),\n ],\n { columns: 1, showOldPrice: true, showDescription: true, buttonLabel: \"View product\" }\n ),\n ]),\n },\n {\n type: \"ecom.bestseller_list\",\n category: \"ecommerce\",\n name: \"Bestseller Grid\",\n description: \"Top products grid (3 up) with old/final prices. Used by retailers for weekly bestsellers.\",\n tags: [\"bestsellers\", \"grid\", \"ranking\", \"top\"],\n create: () =>\n mod(\"ecom.bestseller_list\", \"Bestsellers\", [\n eyebrow(\"Top 3 this week\"),\n productGrid(\n [\n product({ name: \"Linen Tote\", finalPrice: \"$39\", oldPrice: \"$49\" }),\n product({ name: \"Ceramic Mug\", finalPrice: \"$24\" }),\n product({ name: \"Brass Lamp\", finalPrice: \"$129\", oldPrice: \"$149\" }),\n ],\n { columns: 3, showOldPrice: true }\n ),\n ]),\n },\n];\n","import type { ModuleDefinition } from \"./registry\";\nimport { text, mod, divider, button, spacer, heading, muted, image, eyebrow, PLACEHOLDER } from \"./helpers\";\n\nexport const transactionalModules: ModuleDefinition[] = [\n {\n type: \"tx.order_summary\",\n category: \"transactional\",\n name: \"Order Summary\",\n description: \"Order confirmation summary: order number, line items with thumbnails and totals row. Used in post-purchase emails.\",\n tags: [\"order\", \"summary\", \"receipt\", \"post-purchase\", \"ecommerce\"],\n create: () =>\n mod(\"tx.order_summary\", \"Order Summary\", [\n eyebrow(\"Order #1024\"),\n heading(\"Thanks for your order\", { paddingTop: 0 }),\n muted(\"We'll email you again when it ships.\"),\n divider({ paddingTop: 16, paddingBottom: 8 }),\n text(\"Linen Tote Bag · 1 × $39.00\", { paddingTop: 4, paddingBottom: 4 }),\n text(\"Ceramic Mug · 2 × $24.00\", { paddingTop: 4, paddingBottom: 4 }),\n divider({ paddingTop: 8, paddingBottom: 8 }),\n text(\"Subtotal: $87.00\", { paddingTop: 2, paddingBottom: 2 }),\n text(\"Shipping: $5.00\", { paddingTop: 2, paddingBottom: 2 }),\n text(\"Total: $92.00\", { fontWeight: \"bold\", paddingTop: 2, paddingBottom: 16 }),\n ]),\n },\n {\n type: \"tx.shipping_update\",\n category: \"transactional\",\n name: \"Shipping Update\",\n description: \"Shipping confirmation with tracking number, carrier, expected delivery date and a Track button.\",\n tags: [\"shipping\", \"tracking\", \"delivery\", \"post-purchase\"],\n create: () =>\n mod(\"tx.shipping_update\", \"Shipping Update\", [\n text(\"📦\", { align: \"center\", fontSize: 40, paddingTop: 24 }),\n heading(\"Your order is on the way\", { align: \"center\", paddingTop: 8 }),\n muted(\"Carrier: USPS · Expected: May 4, 2026\", { align: \"center\" }),\n text(\"Tracking: 9400 1108 ...\", { align: \"center\", color: \"{colors.muted}\", fontFamily: \"Menlo, Consolas, monospace\", fontSize: 13 }),\n button(\"Track package\"),\n spacer(16),\n ]),\n },\n {\n type: \"tx.invoice\",\n category: \"transactional\",\n name: \"Invoice\",\n description: \"Itemized invoice with billing period, services and totals. Used by SaaS and B2B billing emails.\",\n tags: [\"invoice\", \"billing\", \"saas\", \"b2b\", \"receipt\"],\n create: () =>\n mod(\"tx.invoice\", \"Invoice\", [\n eyebrow(\"Invoice INV-2026-04\"),\n heading(\"April 2026 invoice\"),\n muted(\"Billed to: Acme Inc · Period: Apr 1 – Apr 30\"),\n divider({ paddingTop: 16, paddingBottom: 8 }),\n text(\"Pro plan · $49.00\", { paddingTop: 4, paddingBottom: 4 }),\n text(\"Add-on seats (3) · $36.00\", { paddingTop: 4, paddingBottom: 4 }),\n divider({ paddingTop: 8, paddingBottom: 8 }),\n text(\"Total due: $85.00\", { fontWeight: \"bold\", paddingBottom: 16 }),\n button(\"Download invoice (PDF)\"),\n spacer(16),\n ]),\n },\n {\n type: \"tx.password_reset\",\n category: \"transactional\",\n name: \"Password Reset\",\n description: \"Authentication email with a reset button and a fallback link. Includes 'expires in X minutes' notice.\",\n tags: [\"auth\", \"password\", \"reset\", \"security\"],\n create: () =>\n mod(\"tx.password_reset\", \"Password Reset\", [\n heading(\"Reset your password\", { align: \"center\", paddingTop: 16 }),\n text(\"Click the button below to set a new password. This link expires in 30 minutes.\", {\n align: \"center\",\n paddingBottom: 16,\n }),\n button(\"Reset password\"),\n muted(\"If the button doesn't work, paste this link in your browser:\", { align: \"center\", fontSize: 12 }),\n text(\"https://example.com/reset/abc123\", {\n align: \"center\",\n color: \"{colors.primary}\",\n fontSize: 12,\n paddingBottom: 24,\n }),\n ]),\n },\n {\n type: \"tx.verify_email\",\n category: \"transactional\",\n name: \"Verify Email\",\n description: \"Single-purpose 'verify your email' transactional with one centered button.\",\n tags: [\"auth\", \"verify\", \"email-confirmation\"],\n create: () =>\n mod(\"tx.verify_email\", \"Verify Email\", [\n heading(\"One last step\", { align: \"center\", paddingTop: 16 }),\n text(\"Confirm your email address to activate your account.\", { align: \"center\", paddingBottom: 8 }),\n button(\"Verify email\"),\n spacer(24),\n ]),\n },\n {\n type: \"tx.appointment\",\n category: \"transactional\",\n name: \"Appointment Confirmation\",\n description: \"Booking/meeting confirmation with date, time, location and add-to-calendar links.\",\n tags: [\"appointment\", \"booking\", \"calendar\", \"meeting\"],\n create: () =>\n mod(\"tx.appointment\", \"Appointment\", [\n eyebrow(\"Confirmed\", { align: \"center\" }),\n heading(\"Your appointment is set\", { align: \"center\", paddingTop: 0 }),\n text(\"Tuesday, May 12 · 10:00 AM\", { align: \"center\", fontWeight: \"bold\", paddingTop: 8 }),\n muted(\"123 Main St, Suite 4 · Brooklyn, NY\", { align: \"center\" }),\n button(\"Add to calendar\"),\n spacer(16),\n ]),\n },\n];\n","import type { ModuleDefinition } from \"./registry\";\nimport { text, mod, image, eyebrow, PLACEHOLDER, muted, spacer } from \"./helpers\";\n\nexport const socialModules: ModuleDefinition[] = [\n {\n type: \"social.icons\",\n category: \"social\",\n name: \"Social Icons Row\",\n description: \"Centered 'Follow us' label with text-link icons in a row. Light footer-style social block.\",\n tags: [\"social\", \"follow\", \"icons\", \"row\"],\n create: () =>\n mod(\"social.icons\", \"Social Icons\", [\n muted(\"Follow us\", { align: \"center\" }),\n text(\"Twitter · Instagram · LinkedIn · YouTube\", {\n align: \"center\",\n color: \"{colors.primary}\",\n paddingBottom: 16,\n }),\n ]),\n },\n {\n type: \"social.share\",\n category: \"social\",\n name: \"Share This Email\",\n description: \"'Share this email' bar with Forward · Tweet · Share text links. Used at the end of newsletters.\",\n tags: [\"social\", \"share\", \"forward\", \"viral\"],\n create: () =>\n mod(\"social.share\", \"Share Bar\", [\n text(\"Share this email\", { align: \"center\", paddingTop: 8 }),\n text(\"Forward · Tweet · Share\", {\n align: \"center\",\n color: \"{colors.primary}\",\n paddingBottom: 8,\n }),\n ]),\n },\n {\n type: \"social.featured_post\",\n category: \"social\",\n name: \"Featured Social Post\",\n description: \"Embed-style preview of a single social post: avatar, name, post text and a link to view it on the platform.\",\n tags: [\"social\", \"post\", \"embed\", \"twitter\", \"instagram\"],\n create: () =>\n mod(\n \"social.featured_post\",\n \"Social Post\",\n [\n eyebrow(\"From the community\"),\n image(PLACEHOLDER(48, 48, \"👤\"), \"Avatar\", { width: 48, borderRadius: 24 }),\n text(\"@maker · 2h\", { color: \"{colors.muted}\", fontSize: 13, paddingTop: 4, paddingBottom: 4 }),\n text(\"\\\"Just shipped my newsletter using OpenPostcards. Honestly the smoothest email build I've ever done.\\\"\", {\n paddingBottom: 8,\n lineHeight: 1.6,\n }),\n text(\"View on Twitter →\", { color: \"{colors.primary}\", paddingBottom: 16, link: \"#\" }),\n ]\n ),\n },\n {\n type: \"social.instagram_grid\",\n category: \"social\",\n name: \"Instagram Grid\",\n description: \"3 small square thumbnails in a row representing recent Instagram posts, with handle and link.\",\n tags: [\"social\", \"instagram\", \"grid\", \"thumbnails\"],\n create: () =>\n mod(\"social.instagram_grid\", \"IG Grid\", [\n muted(\"@youraccount on Instagram\", { align: \"center\" }),\n image(PLACEHOLDER(180, 180, \"1\"), \"Post 1\", { width: 180 }),\n image(PLACEHOLDER(180, 180, \"2\"), \"Post 2\", { width: 180 }),\n image(PLACEHOLDER(180, 180, \"3\"), \"Post 3\", { width: 180 }),\n text(\"View profile →\", { align: \"center\", color: \"{colors.primary}\", paddingTop: 8, paddingBottom: 16, link: \"#\" }),\n ]),\n },\n {\n type: \"social.community_stats\",\n category: \"social\",\n name: \"Community Stats\",\n description: \"Short '12k Twitter · 4k IG · 2k YT' style row used to show following sizes.\",\n tags: [\"social\", \"stats\", \"community\", \"following\"],\n create: () =>\n mod(\"social.community_stats\", \"Community Stats\", [\n eyebrow(\"Join the community\", { align: \"center\" }),\n text(\"12k Twitter · 4k Instagram · 2k YouTube\", { align: \"center\", paddingBottom: 16 }),\n spacer(8),\n ]),\n },\n];\n","import type { ModuleDefinition } from \"./registry\";\nimport { text, mod, divider, image, muted, PLACEHOLDER } from \"./helpers\";\n\nconst baseFooterStyle = {\n backgroundColor: \"{colors.background}\",\n paddingTop: 0,\n paddingBottom: 0,\n};\n\nexport const footerModules: ModuleDefinition[] = [\n {\n type: \"footer.simple\",\n category: \"footer\",\n name: \"Simple Footer\",\n description: \"Minimal footer with copyright, address and unsubscribe links. The default for any newsletter.\",\n tags: [\"footer\", \"simple\", \"copyright\", \"unsubscribe\"],\n create: () =>\n mod(\n \"footer.simple\",\n \"Simple Footer\",\n [\n muted(\"© 2026 Your Company. All rights reserved.\", { align: \"center\", fontSize: 12 }),\n muted(\"123 Main St · City · Country\", { align: \"center\", fontSize: 12 }),\n text(\"Unsubscribe · View in browser\", {\n align: \"center\",\n color: \"{colors.muted}\",\n fontSize: 12,\n paddingTop: 4,\n paddingBottom: 24,\n }),\n ],\n { ...baseFooterStyle, paddingTop: 24 }\n ),\n },\n {\n type: \"footer.social\",\n category: \"footer\",\n name: \"Footer with Social\",\n description: \"Footer with social links row above the legal text.\",\n tags: [\"footer\", \"social\", \"links\"],\n create: () =>\n mod(\n \"footer.social\",\n \"Social Footer\",\n [\n text(\"Follow us\", { align: \"center\", paddingTop: 24 }),\n text(\"Twitter · Instagram · LinkedIn\", {\n align: \"center\",\n color: \"{colors.primary}\",\n paddingBottom: 12,\n }),\n divider(),\n muted(\"© 2026 Your Company · Unsubscribe\", {\n align: \"center\",\n fontSize: 12,\n }),\n text(\" \", { align: \"center\", paddingBottom: 24 }),\n ],\n baseFooterStyle\n ),\n },\n {\n type: \"footer.legal\",\n category: \"footer\",\n name: \"Legal Footer\",\n description: \"Long-form footer with explanation of why the user is receiving the email plus privacy/terms/unsubscribe links. Used by enterprise and finance newsletters.\",\n tags: [\"footer\", \"legal\", \"compliance\", \"enterprise\"],\n create: () =>\n mod(\n \"footer.legal\",\n \"Legal Footer\",\n [\n text(\n \"You are receiving this email because you signed up for our newsletter. If you no longer wish to receive emails, you can unsubscribe at any time.\",\n {\n align: \"center\",\n color: \"{colors.muted}\",\n fontSize: 11,\n lineHeight: 1.6,\n paddingTop: 24,\n }\n ),\n text(\"Privacy Policy · Terms · Unsubscribe\", {\n align: \"center\",\n color: \"{colors.muted}\",\n fontSize: 11,\n paddingBottom: 24,\n }),\n ],\n baseFooterStyle\n ),\n },\n {\n type: \"footer.publisher\",\n category: \"footer\",\n name: \"Publisher Footer\",\n description: \"Magazine-style sign-off with logo, publication name, masthead credits, address and links.\",\n tags: [\"footer\", \"publisher\", \"magazine\", \"masthead\", \"editorial\"],\n create: () =>\n mod(\n \"footer.publisher\",\n \"Publisher Footer\",\n [\n image(PLACEHOLDER(120, 36, \"LOGO\"), \"Logo\", { width: 120, paddingTop: 24, paddingBottom: 8 }),\n text(\"THE WEEKLY\", {\n align: \"center\",\n fontFamily: \"{fonts.heading}\",\n fontWeight: \"bold\",\n letterSpacing: 4,\n paddingTop: 0,\n paddingBottom: 4,\n }),\n muted(\"Editor: Jane Doe · Producer: Alex Kim\", { align: \"center\", fontSize: 12 }),\n divider({ paddingTop: 12, paddingBottom: 12 }),\n muted(\"© 2026 The Weekly · 350 Madison Ave · NY 10017\", { align: \"center\", fontSize: 11 }),\n text(\"Manage preferences · Unsubscribe\", {\n align: \"center\",\n color: \"{colors.muted}\",\n fontSize: 11,\n paddingTop: 4,\n paddingBottom: 24,\n }),\n ],\n baseFooterStyle\n ),\n },\n {\n type: \"footer.app_links\",\n category: \"footer\",\n name: \"Footer with App Store Badges\",\n description: \"Footer including 'Get the app' app-store and play-store badge images. For consumer brand newsletters.\",\n tags: [\"footer\", \"app\", \"download\", \"ios\", \"android\"],\n create: () =>\n mod(\n \"footer.app_links\",\n \"App Footer\",\n [\n text(\"Get the app\", { align: \"center\", fontWeight: \"bold\", paddingTop: 24, paddingBottom: 8 }),\n image(PLACEHOLDER(135, 40, \"App Store\"), \"App Store\", { width: 135, align: \"center\", paddingTop: 0, paddingBottom: 4 }),\n image(PLACEHOLDER(135, 40, \"Google Play\"), \"Google Play\", { width: 135, align: \"center\", paddingTop: 0, paddingBottom: 16 }),\n divider(),\n muted(\"© 2026 Your Brand · Unsubscribe\", { align: \"center\", fontSize: 11 }),\n text(\" \", { align: \"center\", paddingBottom: 24 }),\n ],\n baseFooterStyle\n ),\n },\n {\n type: \"footer.address_only\",\n category: \"footer\",\n name: \"Address Only\",\n description: \"Just a centered postal address line — required for CAN-SPAM compliance when other footers are minimal.\",\n tags: [\"footer\", \"address\", \"compliance\", \"can-spam\"],\n create: () =>\n mod(\n \"footer.address_only\",\n \"Address\",\n [\n muted(\"Your Company · 123 Main St · Brooklyn, NY 11201 · USA\", {\n align: \"center\",\n fontSize: 11,\n }),\n text(\" \", { align: \"center\", paddingBottom: 16 }),\n ],\n { ...baseFooterStyle, paddingTop: 16 }\n ),\n },\n {\n type: \"footer.preferences\",\n category: \"footer\",\n name: \"Manage Preferences\",\n description: \"Footer that emphasizes preference management ('Update your preferences', 'Send less often'). Reduces unsubscribes.\",\n tags: [\"footer\", \"preferences\", \"frequency\", \"retention\"],\n create: () =>\n mod(\n \"footer.preferences\",\n \"Preferences\",\n [\n text(\"Getting too many emails?\", { align: \"center\", paddingTop: 24, paddingBottom: 4 }),\n text(\"Update your preferences · Send less often · Unsubscribe\", {\n align: \"center\",\n color: \"{colors.primary}\",\n fontSize: 13,\n paddingBottom: 16,\n }),\n divider(),\n muted(\"© 2026 Your Company\", { align: \"center\", fontSize: 11 }),\n text(\" \", { align: \"center\", paddingBottom: 24 }),\n ],\n baseFooterStyle\n ),\n },\n {\n type: \"footer.signature\",\n category: \"footer\",\n name: \"Signature Sign-off\",\n description: \"Personal hand-signed style sign-off with author name and tiny legal block. For solo creator newsletters.\",\n tags: [\"footer\", \"signature\", \"personal\", \"creator\", \"sign-off\"],\n create: () =>\n mod(\n \"footer.signature\",\n \"Signature\",\n [\n text(\"Until next week,\", { paddingTop: 24, paddingBottom: 4 }),\n text(\"— Jane\", { fontFamily: \"{fonts.heading}\", fontSize: 22, paddingBottom: 16 }),\n divider(),\n muted(\"Reply directly · Unsubscribe · 123 Main St, Brooklyn\", {\n fontSize: 11,\n align: \"center\",\n }),\n text(\" \", { align: \"center\", paddingBottom: 24 }),\n ],\n { ...baseFooterStyle, paddingTop: 0 }\n ),\n },\n];\n","// Aggregates and registers every default module pack.\nimport { moduleRegistry, type ModuleDefinition } from \"./registry\";\nimport { basicModules } from \"./basic\";\nimport { headerModules } from \"./header\";\nimport { menuModules } from \"./menu\";\nimport { contentModules } from \"./content\";\nimport { featureModules } from \"./feature\";\nimport { ctaModules } from \"./cta\";\nimport { ecommerceModules } from \"./ecommerce\";\nimport { transactionalModules } from \"./transactional\";\nimport { socialModules } from \"./social\";\nimport { footerModules } from \"./footer\";\n\nexport const defaultModules: ModuleDefinition[] = [\n ...basicModules,\n ...headerModules,\n ...menuModules,\n ...contentModules,\n ...featureModules,\n ...ctaModules,\n ...ecommerceModules,\n ...transactionalModules,\n ...socialModules,\n ...footerModules,\n];\n\nlet registered = false;\nexport function registerDefaultModules() {\n if (registered) return;\n for (const d of defaultModules) moduleRegistry.register(d);\n registered = true;\n}\n\nexport {\n basicModules,\n headerModules,\n menuModules,\n contentModules,\n featureModules,\n ctaModules,\n ecommerceModules,\n transactionalModules,\n socialModules,\n footerModules,\n};\n","import { useEffect } from \"react\";\nimport { TopBar } from \"./editor/TopBar\";\nimport { LeftSidebar } from \"./editor/LeftSidebar\";\nimport { Canvas } from \"./editor/Canvas\";\nimport { RightSidebar } from \"./editor/RightSidebar\";\nimport { registerDefaultModules } from \"./modules/defaultModules\";\nimport { moduleRegistry } from \"./modules/registry\";\nimport { useEmailStore } from \"./store/emailStore\";\n// Register all built-in templates (each module self-registers on import).\nimport \"./templates\";\n\n// Register default modules once at module load.\nregisterDefaultModules();\n\nexport function App() {\n const { doc, addModule, loadFromLocalStorage } = useEmailStore();\n\n useEffect(() => {\n loadFromLocalStorage();\n // Seed a starter email if empty.\n if (useEmailStore.getState().doc.modules.length === 0) {\n const seeds = [\"header.hero\", \"content.headline_body\", \"cta.simple\", \"footer.simple\"];\n for (const t of seeds) {\n const def = moduleRegistry.get(t);\n if (def) addModule(def.create());\n }\n useEmailStore.setState({ selection: { kind: \"email\" }, past: [], future: [] });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Auto-save to localStorage on doc change.\n useEffect(() => {\n const id = setTimeout(() => useEmailStore.getState().saveToLocalStorage(), 500);\n return () => clearTimeout(id);\n }, [doc]);\n\n return (\n <div className=\"oml-email-builder h-full w-full flex flex-col bg-gray-100\">\n <TopBar />\n <div className=\"flex flex-1 overflow-hidden\">\n <LeftSidebar />\n <Canvas />\n <RightSidebar />\n </div>\n </div>\n );\n}\n","// HTTP AI provider.\n//\n// Wraps a backend endpoint (see ../../backend) as an `AIProvider`. The provider\n// POSTs an `AIRequest` as JSON and expects an `AIResponse` JSON body back.\n// The backend is responsible for talking to the actual model; the client stays\n// model-agnostic and only speaks the builder's structured AI protocol.\n\nimport type { AIProvider, AIRequest, AIResponse } from \"../core/aiActions\";\n\nexport interface HttpAIProviderOptions {\n /** Absolute or same-origin URL that implements POST /ai/generate. Required. */\n endpoint: string;\n /** Extra headers (e.g. Authorization). */\n headers?: Record<string, string>;\n /** Send cookies with the request. Default: false. */\n withCredentials?: boolean;\n /** Abort the request after this many ms. Default: 60000. */\n timeoutMs?: number;\n /**\n * Map a raw server JSON body to an `AIResponse`.\n * Default expects the body to already be an `AIResponse`.\n */\n transformResponse?: (body: unknown) => AIResponse;\n}\n\nconst defaultTransform = (body: unknown): AIResponse => {\n if (body && typeof body === \"object\") return body as AIResponse;\n throw new Error(\"AI server returned a non-object response.\");\n};\n\n/**\n * Create an {@link AIProvider} backed by an HTTP endpoint.\n *\n * @example\n * const provider = createHttpAIProvider({ endpoint: \"http://localhost:3001/ai/generate\" });\n */\nexport function createHttpAIProvider(opts: HttpAIProviderOptions): AIProvider {\n const transform = opts.transformResponse ?? defaultTransform;\n const timeoutMs = opts.timeoutMs ?? 60000;\n\n return {\n async generate(req: AIRequest): Promise<AIResponse> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const res = await fetch(opts.endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...(opts.headers ?? {}) },\n credentials: opts.withCredentials ? \"include\" : \"same-origin\",\n body: JSON.stringify(req),\n signal: controller.signal,\n });\n\n let body: unknown = null;\n const raw = await res.text();\n try {\n body = raw ? JSON.parse(raw) : null;\n } catch {\n // leave body null; handled below\n }\n\n if (!res.ok) {\n const msg =\n (body && typeof body === \"object\" && \"error\" in body &&\n typeof (body as { error: unknown }).error === \"string\"\n ? (body as { error: string }).error\n : null) ?? `AI request failed (HTTP ${res.status})`;\n throw new Error(msg);\n }\n\n return transform(body);\n } catch (err) {\n if (err instanceof DOMException && err.name === \"AbortError\") {\n throw new Error(`AI request timed out after ${timeoutMs}ms`);\n }\n throw err instanceof Error ? err : new Error(String(err));\n } finally {\n clearTimeout(timer);\n }\n },\n };\n}\n","// Public surface for the AI assistant module.\nimport type { Plugin, BuilderHandle } from \"../core/plugins\";\nimport type { AIProvider } from \"../core/aiActions\";\nimport { createHttpAIProvider, type HttpAIProviderOptions } from \"./provider\";\n\nexport { createHttpAIProvider } from \"./provider\";\nexport type { HttpAIProviderOptions } from \"./provider\";\nexport { buildCatalog } from \"./catalog\";\nexport type { CatalogEntry } from \"./catalog\";\nexport { applyAIResponse } from \"./applyResponse\";\nexport type { ApplyResult } from \"./applyResponse\";\nexport { AIChatPanel, useAIAvailable } from \"./AIChatPanel\";\nexport {\n getAIProvider as getActiveAIProvider,\n setAIProvider as setActiveAIProvider,\n} from \"./state\";\n\nexport interface AIAssistantOptions extends HttpAIProviderOptions {}\n\n/**\n * Plugin factory that wires an HTTP-backed AI provider into the builder and\n * enables the chat panel.\n *\n * @example\n * import { registerPlugin } from \"@one-million-lines/email-builder\";\n * import { aiAssistantPlugin } from \"@one-million-lines/email-builder\";\n * registerPlugin(aiAssistantPlugin({ endpoint: \"http://localhost:3001/ai/generate\" }));\n */\nexport function aiAssistantPlugin(opts: AIAssistantOptions): Plugin {\n const provider: AIProvider = createHttpAIProvider(opts);\n return {\n name: \"ai-assistant\",\n type: \"ai-provider\",\n setup(builder: BuilderHandle) {\n builder.setAIProvider(provider);\n },\n };\n}\n","// Image Uploader plugin.\n// Registers an AssetProvider that POSTs the picked file to a configured\n// HTTP endpoint and returns the public URL the server responds with.\n//\n// See ./README.md for the wire protocol and server examples.\n\nimport type { Plugin, AssetProvider, BuilderHandle } from \"../../core/plugins\";\n\nexport interface ImageUploaderOptions {\n /** Absolute or same-origin URL the file is POSTed to. Required. */\n endpoint: string;\n /** Form field name for the file. Default: \"file\". */\n fieldName?: string;\n /** Extra headers (e.g. Authorization). Cookies/credentials are sent if `withCredentials` is true. */\n headers?: Record<string, string>;\n /** Send credentials (cookies). Default: false. */\n withCredentials?: boolean;\n /** Max file size in MB. Default: 10. */\n maxSizeMB?: number;\n /** Comma-separated MIME types accepted by the file picker. Default: \"image/*\". */\n accept?: string;\n /**\n * Map a successful server JSON body to `{ url, alt? }`.\n * Default expects `{ url: string, alt?: string }`.\n */\n transformResponse?: (body: unknown) => { url: string; alt?: string };\n /** Optional progress callback for the active upload. */\n onProgress?: (percent: number) => void;\n}\n\nconst defaultTransform = (body: unknown): { url: string; alt?: string } => {\n if (body && typeof body === \"object\" && \"url\" in body && typeof (body as { url: unknown }).url === \"string\") {\n const b = body as { url: string; alt?: string };\n return { url: b.url, alt: typeof b.alt === \"string\" ? b.alt : undefined };\n }\n throw new Error('Server response missing \"url\" string field.');\n};\n\nexport function createImageUploaderProvider(opts: ImageUploaderOptions): AssetProvider {\n const fieldName = opts.fieldName ?? \"file\";\n const maxSize = (opts.maxSizeMB ?? 10) * 1024 * 1024;\n const transform = opts.transformResponse ?? defaultTransform;\n\n return {\n upload(file: File) {\n if (!file.type.startsWith(\"image/\")) {\n return Promise.reject(new Error(`Not an image: ${file.type || \"unknown\"}`));\n }\n if (file.size > maxSize) {\n return Promise.reject(\n new Error(`File too large: ${(file.size / 1024 / 1024).toFixed(2)} MB > ${opts.maxSizeMB ?? 10} MB`)\n );\n }\n\n return new Promise<{ url: string; alt?: string }>((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n const fd = new FormData();\n fd.append(fieldName, file, file.name);\n\n xhr.open(\"POST\", opts.endpoint, true);\n xhr.withCredentials = !!opts.withCredentials;\n if (opts.headers) {\n for (const [k, v] of Object.entries(opts.headers)) xhr.setRequestHeader(k, v);\n }\n\n if (opts.onProgress && xhr.upload) {\n xhr.upload.onprogress = (e) => {\n if (e.lengthComputable) opts.onProgress!(Math.round((e.loaded / e.total) * 100));\n };\n }\n\n xhr.onload = () => {\n const ok = xhr.status >= 200 && xhr.status < 300;\n let body: unknown = null;\n try {\n body = xhr.responseText ? JSON.parse(xhr.responseText) : null;\n } catch {\n // not JSON\n }\n if (!ok) {\n const msg =\n (body && typeof body === \"object\" && \"error\" in body && typeof (body as { error: unknown }).error === \"string\"\n ? (body as { error: string }).error\n : null) ?? `Upload failed (HTTP ${xhr.status})`;\n return reject(new Error(msg));\n }\n try {\n resolve(transform(body));\n } catch (err) {\n reject(err instanceof Error ? err : new Error(String(err)));\n }\n };\n\n xhr.onerror = () => reject(new Error(\"Network error during upload\"));\n xhr.onabort = () => reject(new Error(\"Upload aborted\"));\n xhr.send(fd);\n });\n },\n };\n}\n\n/**\n * Plugin factory. Pass to `registerPlugin()` exported by the builder.\n *\n * @example\n * import { registerPlugin } from \"@one-million-lines/email-builder\";\n * import { imageUploaderPlugin } from \"@one-million-lines/email-builder\";\n * registerPlugin(imageUploaderPlugin({ endpoint: \"/api/upload\" }));\n */\nexport function imageUploaderPlugin(opts: ImageUploaderOptions): Plugin {\n return {\n name: \"image-uploader\",\n type: \"asset-provider\",\n setup(b: BuilderHandle) {\n b.registerAssetProvider(createImageUploaderProvider(opts));\n },\n };\n}\n\nexport const ACCEPT_DEFAULT = \"image/*\";\n","// Public API for embedding the editor in React apps and as a vanilla wrapper.\n// Note: Vue wrapper is left as a stub (drop-in via createEmailBuilder + a Vue component).\nimport { createRoot, type Root } from \"react-dom/client\";\nimport { createElement, useEffect } from \"react\";\nimport \"./lib.css\";\nimport type { EmailDocument, Theme } from \"./core/types\";\nimport { documentSchema } from \"./core/validation\";\nimport { renderEmailHtml } from \"./core/renderer\";\nimport { useEmailStore } from \"./store/emailStore\";\nimport { App } from \"./App\";\nimport { registerDefaultModules } from \"./modules/defaultModules\";\nimport { moduleRegistry, type ModuleDefinition } from \"./modules/registry\";\nimport type { AIProvider } from \"./core/aiActions\";\nimport { builder, registerPlugin, type Plugin } from \"./core/plugins\";\nimport { createHttpAIProvider, type HttpAIProviderOptions } from \"./ai\";\n\nexport interface EmailBuilderProps {\n initialDocument?: EmailDocument;\n modules?: ModuleDefinition[];\n themes?: Theme[];\n aiProvider?: AIProvider;\n /**\n * Convenience: wire the built-in HTTP AI provider (the Python backend) by URL.\n * Ignored when `aiProvider` is provided.\n */\n aiEndpoint?: string | HttpAIProviderOptions;\n onChange?: (doc: EmailDocument) => void;\n onExportHtml?: (html: string) => void;\n}\n\n/** React component wrapper. */\nexport function EmailBuilder(props: EmailBuilderProps) {\n useEffect(() => {\n registerDefaultModules();\n if (props.modules) for (const m of props.modules) moduleRegistry.register(m);\n if (props.themes) useEmailStore.setState({ themes: props.themes });\n if (props.aiProvider) builder.setAIProvider(props.aiProvider);\n else if (props.aiEndpoint) {\n const opts =\n typeof props.aiEndpoint === \"string\" ? { endpoint: props.aiEndpoint } : props.aiEndpoint;\n builder.setAIProvider(createHttpAIProvider(opts));\n }\n if (props.initialDocument) {\n const r = documentSchema.safeParse(props.initialDocument);\n if (r.success) useEmailStore.getState().applyDoc(r.data as EmailDocument, false);\n }\n const unsub = useEmailStore.subscribe((s, prev) => {\n if (s.doc !== prev.doc) props.onChange?.(s.doc);\n });\n return () => unsub();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Expose export helper via prop callback.\n useEffect(() => {\n if (!props.onExportHtml) return;\n return useEmailStore.subscribe((s, prev) => {\n if (s.doc !== prev.doc) props.onExportHtml?.(renderEmailHtml(s.doc));\n });\n }, [props.onExportHtml]);\n\n return createElement(App);\n}\n\n/** Vanilla JS factory. */\nexport interface VanillaOptions extends EmailBuilderProps {\n container: HTMLElement;\n}\n\nexport interface VanillaInstance {\n destroy: () => void;\n getDocument: () => EmailDocument;\n exportHtml: () => string;\n exportJson: () => string;\n}\n\nexport function createEmailBuilder(opts: VanillaOptions): VanillaInstance {\n const root: Root = createRoot(opts.container);\n root.render(createElement(EmailBuilder, opts));\n return {\n destroy: () => root.unmount(),\n getDocument: () => useEmailStore.getState().doc,\n exportHtml: () => useEmailStore.getState().exportHtml(),\n exportJson: () => useEmailStore.getState().exportJson(),\n };\n}\n\n// Re-exports for plugin authors.\nexport type { Plugin, ModuleDefinition, AIProvider, EmailDocument, Theme };\nexport { registerPlugin, renderEmailHtml, documentSchema };\nexport { imageUploaderPlugin } from \"./plugins/imageUploader\";\nexport type { ImageUploaderOptions } from \"./plugins/imageUploader\";\n\n// AI assistant module — chat-driven editing backed by the Python service.\nexport {\n aiAssistantPlugin,\n createHttpAIProvider,\n buildCatalog,\n applyAIResponse,\n} from \"./ai\";\nexport type {\n AIAssistantOptions,\n HttpAIProviderOptions,\n CatalogEntry,\n ApplyResult,\n} from \"./ai\";\nexport { mockAIProvider, applyAIActions, validateAIDocument } from \"./core/aiActions\";\nexport type { AIAction, AIRequest, AIResponse } from \"./core/aiActions\";\n\nexport { templateRegistry, TEMPLATE_CATEGORY_LABELS } from \"./templates\";\nexport type { TemplateDefinition, TemplateCategory } from \"./templates\";\nexport {\n ALGORITHMS,\n ALGORITHM_BY_ID,\n FALLBACK_OPTIONS,\n defaultLogic as defaultRecommendationsLogic,\n readLogic as readRecommendationsLogic,\n toLegacyShape as recommendationsToLegacyShape,\n} from \"./recommendations/logic\";\nexport type {\n RecommendationsLogic,\n RecommendationFilters,\n StackEntry,\n AlgorithmDefinition,\n AlgorithmParamSpec,\n FallbackId,\n RecommendationMode,\n} from \"./recommendations/logic\";\n"],"x_google_ignoreList":[25,26,27,28],"mappings":"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"}
|