@react-email/editor 1.3.2 → 1.3.3

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.
@@ -113,12 +113,45 @@ function injectThemeCss(styles, options = {}) {
113
113
  const container = options.scopeSelector ?? ".tiptap-extended .tiptap.ProseMirror";
114
114
  const prefix = ".node-";
115
115
  const styleId = options.styleId ?? "tiptap-extended-theme-css";
116
+ const getNodeSelector = (classReference) => `${container} ${prefix}${classReference}`;
117
+ const getSelectors = (classReference) => {
118
+ switch (classReference) {
119
+ case "body": return [container];
120
+ case "reset": return [];
121
+ case "list": return [
122
+ getNodeSelector("list"),
123
+ getNodeSelector("bulletList"),
124
+ getNodeSelector("orderedList")
125
+ ];
126
+ case "bulletList": return [getNodeSelector("bulletList")];
127
+ case "orderedList": return [getNodeSelector("orderedList")];
128
+ case "nestedList": return [
129
+ getNodeSelector("nestedList"),
130
+ `${container} .node-list .node-list`,
131
+ `${container} .node-bulletList .node-bulletList`,
132
+ `${container} .node-bulletList .node-orderedList`,
133
+ `${container} .node-orderedList .node-bulletList`,
134
+ `${container} .node-orderedList .node-orderedList`
135
+ ];
136
+ case "listParagraph": return [`${container} .node-listItem > .node-paragraph`];
137
+ default: return [getNodeSelector(classReference)];
138
+ }
139
+ };
140
+ const resetStyles = styles.reset ?? {};
116
141
  const css = Object.entries(styles).reduce((acc, [key, value]) => {
117
- return `${acc}${key === "body" ? container : `${container} ${prefix}${key}`}{${Object.entries(value).reduce((acc, [prop, val]) => {
142
+ const classReference = key;
143
+ const selectors = getSelectors(classReference);
144
+ if (selectors.length === 0) return acc;
145
+ const resolvedStyles = RESET_NODE_TYPES.has(classReference) ? {
146
+ ...resetStyles,
147
+ ...value
148
+ } : value;
149
+ const cssString = Object.entries(resolvedStyles).reduce((acc, [prop, val]) => {
118
150
  const normalizeProp = prop.replace(/([A-Z])/g, "-$1").toLowerCase();
119
151
  if (val === void 0) return acc;
120
152
  return `${acc}${normalizeProp}:${val};`;
121
- }, "")}}`;
153
+ }, "");
154
+ return `${acc}${selectors.join(",")}{${cssString}}`;
122
155
  }, "");
123
156
  let styleTag = document.getElementById(styleId);
124
157
  if (!styleTag) {
@@ -161,6 +194,9 @@ const PANEL_SECTION_TITLES = {
161
194
  h2: "Subtitle",
162
195
  h3: "Heading",
163
196
  paragraph: "Paragraph",
197
+ list: "List",
198
+ "nested-list": "Nested List",
199
+ "list-item": "List Item",
164
200
  link: "Link",
165
201
  image: "Image",
166
202
  button: "Button",
@@ -366,6 +402,27 @@ const THEME_BASIC = [
366
402
  classReference: "paragraph",
367
403
  inputs: []
368
404
  },
405
+ {
406
+ id: "list",
407
+ title: "List",
408
+ category: "Text",
409
+ classReference: "list",
410
+ inputs: []
411
+ },
412
+ {
413
+ id: "nested-list",
414
+ title: "Nested List",
415
+ category: "Text",
416
+ classReference: "nestedList",
417
+ inputs: []
418
+ },
419
+ {
420
+ id: "list-item",
421
+ title: "List Item",
422
+ category: "Text",
423
+ classReference: "listItem",
424
+ inputs: []
425
+ },
369
426
  {
370
427
  id: "link",
371
428
  title: "Link",
@@ -715,6 +772,27 @@ const THEME_MINIMAL = [
715
772
  classReference: "paragraph",
716
773
  inputs: []
717
774
  },
775
+ {
776
+ id: "list",
777
+ title: "List",
778
+ category: "Text",
779
+ classReference: "list",
780
+ inputs: []
781
+ },
782
+ {
783
+ id: "nested-list",
784
+ title: "Nested List",
785
+ category: "Text",
786
+ classReference: "nestedList",
787
+ inputs: []
788
+ },
789
+ {
790
+ id: "list-item",
791
+ title: "List Item",
792
+ category: "Text",
793
+ classReference: "listItem",
794
+ inputs: []
795
+ },
718
796
  {
719
797
  id: "link",
720
798
  title: "Link",
@@ -785,14 +863,16 @@ const RESET_BASIC = {
785
863
  paddingLeft: "1.1em",
786
864
  paddingBottom: "1em"
787
865
  },
866
+ bulletList: { listStyleType: "disc" },
867
+ orderedList: { listStyleType: "decimal" },
788
868
  nestedList: {
789
869
  paddingLeft: "1.1em",
790
870
  paddingBottom: "0"
791
871
  },
792
872
  listItem: {
793
873
  marginLeft: "1em",
794
- marginBottom: "0.3em",
795
- marginTop: "0.3em"
874
+ paddingBottom: "0.3em",
875
+ paddingTop: "0.3em"
796
876
  },
797
877
  listParagraph: {
798
878
  padding: "0",
@@ -813,12 +893,24 @@ const RESET_BASIC = {
813
893
  footer: { fontSize: "0.8em" },
814
894
  hr: {
815
895
  paddingBottom: "1em",
896
+ borderStyle: "solid",
816
897
  borderWidth: "2px"
817
898
  },
818
899
  image: { maxWidth: "100%" },
819
900
  button: {
820
901
  lineHeight: "100%",
821
- display: "inline-block"
902
+ display: "inline-block",
903
+ paddingTop: "0.625em",
904
+ paddingRight: "1.25em",
905
+ paddingBottom: "0.625em",
906
+ paddingLeft: "1.25em",
907
+ backgroundColor: "#000000",
908
+ color: "#ffffff",
909
+ borderRadius: "0.375em",
910
+ fontWeight: 500,
911
+ fontSize: "0.875em",
912
+ textDecoration: "none",
913
+ textAlign: "center"
822
914
  },
823
915
  inlineCode: {
824
916
  paddingTop: "0.25em",
@@ -830,6 +922,13 @@ const RESET_BASIC = {
830
922
  borderRadius: "4px"
831
923
  },
832
924
  codeBlock: {
925
+ background: "#f1f5f9",
926
+ borderRadius: "4px",
927
+ paddingTop: "0.75rem",
928
+ paddingRight: "1rem",
929
+ paddingBottom: "0.75rem",
930
+ paddingLeft: "1rem",
931
+ overflowX: "auto",
833
932
  fontFamily: "monospace",
834
933
  fontWeight: "500",
835
934
  fontSize: ".92em"
@@ -852,9 +951,14 @@ const RESET_THEMES = {
852
951
  return acc;
853
952
  }, {}),
854
953
  reset: RESET_BASIC.reset,
855
- button: RESET_BASIC.button,
954
+ button: {
955
+ lineHeight: RESET_BASIC.button.lineHeight,
956
+ display: RESET_BASIC.button.display
957
+ },
856
958
  image: RESET_BASIC.image,
857
959
  list: RESET_BASIC.list,
960
+ bulletList: RESET_BASIC.bulletList,
961
+ orderedList: RESET_BASIC.orderedList,
858
962
  nestedList: RESET_BASIC.nestedList,
859
963
  listItem: RESET_BASIC.listItem,
860
964
  listParagraph: RESET_BASIC.listParagraph,
@@ -1179,6 +1283,9 @@ const PANEL_SECTION_IDS = new Set([
1179
1283
  "container",
1180
1284
  "typography",
1181
1285
  "paragraph",
1286
+ "list",
1287
+ "nested-list",
1288
+ "list-item",
1182
1289
  "link",
1183
1290
  "image",
1184
1291
  "button",
@@ -1192,6 +1299,9 @@ const PANEL_SECTION_IDS_BY_TITLE = {
1192
1299
  container: "container",
1193
1300
  typography: "typography",
1194
1301
  paragraph: "paragraph",
1302
+ list: "list",
1303
+ "nested list": "nested-list",
1304
+ "list item": "list-item",
1195
1305
  link: "link",
1196
1306
  image: "image",
1197
1307
  button: "button",
@@ -1201,6 +1311,9 @@ const PANEL_SECTION_IDS_BY_TITLE = {
1201
1311
  const PANEL_SECTION_IDS_BY_CLASS_REFERENCE = {
1202
1312
  container: "container",
1203
1313
  paragraph: "paragraph",
1314
+ list: "list",
1315
+ nestedList: "nested-list",
1316
+ listItem: "list-item",
1204
1317
  link: "link",
1205
1318
  image: "image",
1206
1319
  button: "button",
@@ -1278,6 +1391,9 @@ const CLASS_REFERENCE_TO_PANEL_ID = {
1278
1391
  link: "link",
1279
1392
  image: "image",
1280
1393
  button: "button",
1394
+ list: "list",
1395
+ nestedList: "nested-list",
1396
+ listItem: "list-item",
1281
1397
  codeBlock: "code-block",
1282
1398
  inlineCode: "inline-code"
1283
1399
  };
@@ -1381,13 +1497,21 @@ function getMergedCssJs(theme, panelStyles) {
1381
1497
  return mergeCssJs(RESET_THEMES[theme], parsed);
1382
1498
  }
1383
1499
  /**
1384
- * Returns resolved React.CSSProperties for a node when you already have merged CssJs
1385
- * (e.g. in the serializer where there is no editor). Centralizes which theme keys
1386
- * apply to which node type.
1500
+ * Node types and theme component keys that should receive the universal
1501
+ * `reset` CSS (e.g. `margin: 0; padding: 0`) layered underneath their own
1502
+ * theme styles. Shared between `getResolvedNodeStyles` (email serializer)
1503
+ * and `injectThemeCss` (editor preview) so both surfaces stay in sync.
1504
+ *
1505
+ * Includes both raw tiptap node names (e.g. `tableCell`) and theme
1506
+ * component keys (e.g. `list`) because the serializer matches against both.
1507
+ *
1508
+ * `bulletList` and `orderedList` are intentionally omitted: their elements
1509
+ * already carry the shared `node-list` class, so the `list` reset rule
1510
+ * covers them without forcing the dedicated `.node-bulletList` /
1511
+ * `.node-orderedList` rules to redundantly emit `margin: 0; padding: 0`.
1387
1512
  */
1388
1513
  const RESET_NODE_TYPES = new Set([
1389
1514
  "body",
1390
- "bulletList",
1391
1515
  "button",
1392
1516
  "columns",
1393
1517
  "div",
@@ -1398,7 +1522,6 @@ const RESET_NODE_TYPES = new Set([
1398
1522
  "listItem",
1399
1523
  "listParagraph",
1400
1524
  "nestedList",
1401
- "orderedList",
1402
1525
  "table",
1403
1526
  "paragraph",
1404
1527
  "tableCell",
@@ -1406,6 +1529,11 @@ const RESET_NODE_TYPES = new Set([
1406
1529
  "tableRow",
1407
1530
  "youtube"
1408
1531
  ]);
1532
+ /**
1533
+ * Returns resolved React.CSSProperties for a node when you already have merged CssJs
1534
+ * (e.g. in the serializer where there is no editor). Centralizes which theme keys
1535
+ * apply to which node type.
1536
+ */
1409
1537
  function getResolvedNodeStyles(node, depth, mergedCssJs) {
1410
1538
  const key = getThemeComponentKey(node.type ?? "", depth, node.attrs ?? {});
1411
1539
  if (!key) {
@@ -1588,6 +1716,6 @@ const EmailTheming = Extension.create({
1588
1716
  }
1589
1717
  });
1590
1718
  //#endregion
1591
- export { resolveResetValue as C, getThemeBodyFontSizePx as S, getGlobalContent as T, EDITOR_THEMES as _, getThemeComponentKey as a, SUPPORTED_CSS_PROPERTIES as b, setGlobalStyles as c, createTheme as d, extendTheme as f, DEFAULT_INBOX_FONT_SIZE_PX as g, themeStylesToPanelOverrides as h, getResolvedNodeStyles as i, stylesToCss as l, parseCssValue as m, getEmailTheming as n, setCurrentTheme as o, isThemeConfig as p, getMergedCssJs as r, setGlobalCssInjected as s, EmailTheming as t, useEmailTheming as u, INBOX_EMAIL_DEFAULTS as v, GlobalContent as w, getPanelTitle as x, RESET_THEMES as y };
1719
+ export { getThemeBodyFontSizePx as C, getGlobalContent as E, getPanelTitle as S, GlobalContent as T, DEFAULT_INBOX_FONT_SIZE_PX as _, getResolvedNodeStyles as a, RESET_THEMES as b, setGlobalCssInjected as c, useEmailTheming as d, createTheme as f, themeStylesToPanelOverrides as g, parseCssValue as h, getMergedCssJs as i, setGlobalStyles as l, isThemeConfig as m, RESET_NODE_TYPES as n, getThemeComponentKey as o, extendTheme as p, getEmailTheming as r, setCurrentTheme as s, EmailTheming as t, stylesToCss as u, EDITOR_THEMES as v, resolveResetValue as w, SUPPORTED_CSS_PROPERTIES as x, INBOX_EMAIL_DEFAULTS as y };
1592
1720
 
1593
- //# sourceMappingURL=extension-TtsG0Puz.mjs.map
1721
+ //# sourceMappingURL=extension-M9mAMex9.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-M9mAMex9.mjs","names":[],"sources":["../src/extensions/global-content.ts","../src/plugins/email-theming/css-transforms.ts","../src/plugins/email-theming/themes.ts","../src/plugins/email-theming/normalization.ts","../src/plugins/email-theming/theme-config.ts","../src/plugins/email-theming/extension.tsx"],"sourcesContent":["import { type Editor, mergeAttributes, Node } from '@tiptap/core';\n\nconst GLOBAL_CONTENT_NODE_TYPE = 'globalContent' as const;\n\nexport interface GlobalContentOptions {\n key: string;\n data: Record<string, unknown>;\n}\n\ndeclare module '@tiptap/core' {\n interface GlobalContent<ReturnType> {\n setGlobalContent: (key: string, value: unknown) => ReturnType;\n }\n\n interface Commands<ReturnType> {\n globalContent: GlobalContent<ReturnType>;\n }\n}\n\nlet cachedGlobalPosition: number | null = null;\n\nfunction findGlobalContentPositions(doc: Editor['state']['doc']) {\n const positions: number[] = [];\n\n doc.descendants((node, position) => {\n if (node.type.name === GLOBAL_CONTENT_NODE_TYPE) {\n positions.push(position);\n }\n });\n\n return positions;\n}\n\nfunction getCachedGlobalContentPosition(doc: Editor['state']['doc']) {\n if (cachedGlobalPosition != null) {\n try {\n if (\n doc.nodeAt(cachedGlobalPosition)?.type.name === GLOBAL_CONTENT_NODE_TYPE\n ) {\n return cachedGlobalPosition;\n }\n } catch {\n cachedGlobalPosition = null;\n }\n }\n\n const positions = findGlobalContentPositions(doc);\n cachedGlobalPosition = positions[0] ?? null;\n return cachedGlobalPosition;\n}\n\nexport function getGlobalContent(key: string, editor: Editor): unknown | null {\n const position = getCachedGlobalContentPosition(editor.state.doc);\n if (cachedGlobalPosition == null) {\n return null;\n }\n return editor.state.doc.nodeAt(position)?.attrs.data[key] ?? null;\n}\n\nexport const GlobalContent = Node.create<GlobalContentOptions>({\n name: GLOBAL_CONTENT_NODE_TYPE,\n\n addOptions() {\n return {\n key: GLOBAL_CONTENT_NODE_TYPE,\n data: {},\n };\n },\n\n group: 'block',\n\n selectable: false,\n draggable: false,\n atom: true,\n\n addAttributes() {\n return {\n data: {\n default: this.options.data,\n },\n };\n },\n\n parseHTML() {\n return [{ tag: `div[data-type=\"${this.name}\"]` }];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n 'div',\n mergeAttributes(HTMLAttributes, {\n 'data-type': this.name,\n // The node needs to have a width and height, so then\n // internal TipTap extension can find the first node position\n // and calculate the correct position of the document container\n style:\n 'width: 100%; height: 1px; visibility: hidden; background-color: transparent;',\n }),\n ];\n },\n\n addCommands() {\n return {\n setGlobalContent:\n (key: string, value: unknown) =>\n ({ tr, dispatch }) => {\n const ensureGlobalPosition = () => {\n const positions = findGlobalContentPositions(tr.doc);\n\n for (let i = positions.length - 1; i > 0; i--) {\n tr.delete(positions[i], positions[i] + 1);\n }\n\n const pos = positions[0] ?? -1;\n if (pos >= 0) {\n cachedGlobalPosition = pos;\n } else {\n cachedGlobalPosition = 0;\n tr.insert(0, this.type.create());\n }\n };\n\n if (dispatch) {\n ensureGlobalPosition();\n\n if (cachedGlobalPosition == null) {\n return false;\n }\n tr.setNodeAttribute(cachedGlobalPosition, 'data', {\n ...tr.doc.nodeAt(cachedGlobalPosition)?.attrs.data,\n [key]: value,\n });\n }\n\n return true;\n },\n };\n },\n});\n","import { ensureBorderStyleFallback } from '../../utils/styles';\nimport { RESET_NODE_TYPES } from './extension';\nimport type { CssJs, KnownThemeComponents, PanelGroup } from './types';\n\nexport function transformToCssJs(\n styleArray: PanelGroup[],\n baseFontSize: number,\n): CssJs {\n const cssJS = {} as CssJs;\n\n if (!Array.isArray(styleArray)) {\n return cssJS;\n }\n\n for (const style of styleArray) {\n for (const input of style.inputs) {\n let value = input.value;\n\n // If there's a unit property, append it to the value\n if (input.unit && typeof value === 'number') {\n // if font size prop convert px unit to em to adjust size in mobile\n if (input.prop === 'fontSize') {\n value = `${value / baseFontSize}em`;\n } else {\n value = `${value}${input.unit}`;\n }\n }\n\n if (!input.classReference) {\n continue;\n }\n\n if (!cssJS[input.classReference]) {\n cssJS[input.classReference] = {};\n }\n\n // @ts-expect-error -- backward compatibility: 'h-padding' is a legacy prop not in KnownCssProperties\n if (input.prop === 'h-padding') {\n cssJS[input.classReference].paddingLeft = value;\n cssJS[input.classReference].paddingRight = value;\n\n continue;\n }\n\n // @ts-expect-error -- input.prop is KnownCssProperties but CssJs values are React.CSSProperties; dynamic assignment is intentional\n cssJS[input.classReference][input.prop] = value;\n }\n }\n\n for (const key of Object.keys(cssJS)) {\n ensureBorderStyleFallback(\n cssJS[key as keyof CssJs] as Record<string, string | number>,\n );\n }\n\n return cssJS;\n}\n\nexport function mergeCssJs(original: CssJs, newCssJs: CssJs) {\n const merged = { ...original };\n\n for (const key in newCssJs) {\n const keyType = key as keyof CssJs;\n\n if (\n Object.hasOwn(merged, key) &&\n typeof merged[keyType] === 'object' &&\n !Array.isArray(merged[keyType])\n ) {\n merged[keyType] = {\n ...merged[keyType],\n ...newCssJs[keyType],\n };\n } else {\n merged[keyType] = newCssJs[keyType];\n }\n }\n\n return merged;\n}\n\nexport function injectThemeCss(\n styles: CssJs,\n options: { styleId?: string; scopeSelector?: string } = {},\n) {\n const container =\n options.scopeSelector ?? '.tiptap-extended .tiptap.ProseMirror';\n const prefix = '.node-';\n const styleId = options.styleId ?? 'tiptap-extended-theme-css';\n const getNodeSelector = (classReference: string) =>\n `${container} ${prefix}${classReference}`;\n const getSelectors = (classReference: KnownThemeComponents) => {\n switch (classReference) {\n case 'body':\n return [container];\n case 'reset':\n return [];\n case 'list':\n return [\n getNodeSelector('list'),\n getNodeSelector('bulletList'),\n getNodeSelector('orderedList'),\n ];\n case 'bulletList':\n return [getNodeSelector('bulletList')];\n case 'orderedList':\n return [getNodeSelector('orderedList')];\n case 'nestedList':\n return [\n getNodeSelector('nestedList'),\n `${container} .node-list .node-list`,\n `${container} .node-bulletList .node-bulletList`,\n `${container} .node-bulletList .node-orderedList`,\n `${container} .node-orderedList .node-bulletList`,\n `${container} .node-orderedList .node-orderedList`,\n ];\n case 'listParagraph':\n return [`${container} .node-listItem > .node-paragraph`];\n default:\n return [getNodeSelector(classReference)];\n }\n };\n const resetStyles = styles.reset ?? {};\n\n const css = Object.entries(styles).reduce((acc, [key, value]) => {\n const classReference = key as KnownThemeComponents;\n const selectors = getSelectors(classReference);\n if (selectors.length === 0) {\n return acc;\n }\n\n const resolvedStyles = RESET_NODE_TYPES.has(classReference)\n ? { ...resetStyles, ...value }\n : value;\n\n const cssString = Object.entries(resolvedStyles).reduce(\n (acc, [prop, val]) => {\n const normalizeProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n\n if (val === undefined) {\n return acc;\n }\n\n return `${acc}${normalizeProp}:${val};`;\n },\n '',\n );\n\n return `${acc}${selectors.join(',')}{${cssString}}`;\n }, '');\n\n let styleTag = document.getElementById(styleId) as HTMLStyleElement;\n\n if (!styleTag) {\n styleTag = document.createElement('style');\n styleTag.textContent = css;\n styleTag.id = styleId;\n\n document.head.appendChild(styleTag);\n\n return;\n }\n\n styleTag.textContent = css;\n}\n\nexport function injectGlobalPlainCss(\n css?: string | null,\n options: { styleId?: string; scopeSelector?: string } = {},\n) {\n const styleId = options.styleId ?? 'global-editor-style';\n const container = options.scopeSelector ?? '.tiptap-extended .ProseMirror';\n let styleElement = document.getElementById(styleId);\n\n if (!css) {\n if (styleElement) {\n styleElement.textContent = '';\n }\n return;\n }\n\n if (!styleElement) {\n styleElement = document.createElement('style');\n styleElement.id = styleId;\n document.head.appendChild(styleElement);\n }\n\n // Remove CSS within @media (prefers-color-scheme: dark) blocks\n const cleanedCSS = css.replace(\n /@media\\s?\\(prefers-color-scheme:\\s?dark\\)\\s?{([\\s\\S]+?})\\s*}/g,\n '',\n );\n\n // TODO: Figure out a way to extract the body and apply the styles out of the nested .tiptap-extended\n styleElement.textContent = `${container} { ${cleanedCSS} }`;\n}\n","import type {\n EditorTheme,\n PanelGroup,\n PanelSectionId,\n ResetTheme,\n SupportedCssProperties,\n} from './types';\n\n/**\n * Single source of truth for panel section display titles.\n * Titles are resolved from here at render time via `getPanelTitle`,\n * so they never depend on what's persisted in the DB.\n */\nconst PANEL_SECTION_TITLES: Record<PanelSectionId, string> = {\n body: 'Background',\n container: 'Body',\n typography: 'Text',\n h1: 'Title',\n h2: 'Subtitle',\n h3: 'Heading',\n paragraph: 'Paragraph',\n list: 'List',\n 'nested-list': 'Nested List',\n 'list-item': 'List Item',\n link: 'Link',\n image: 'Image',\n button: 'Button',\n 'code-block': 'Code Block',\n 'inline-code': 'Inline Code',\n};\n\n/**\n * Resolves the display title for a panel group.\n * Uses the `id` lookup when available, falls back to the\n * DB-persisted `title` for backwards compatibility.\n */\nexport function getPanelTitle(group: PanelGroup): string {\n if (group.id && group.id in PANEL_SECTION_TITLES) {\n return PANEL_SECTION_TITLES[group.id];\n }\n return group.title;\n}\n\nconst THEME_BASIC: PanelGroup[] = [\n {\n id: 'body',\n title: 'Background',\n classReference: 'body',\n inputs: [\n {\n label: 'Background',\n type: 'color',\n value: '#ffffff',\n prop: 'backgroundColor',\n classReference: 'body',\n },\n {\n label: 'Padding Top',\n type: 'number',\n value: undefined,\n unit: 'px',\n prop: 'paddingTop',\n classReference: 'body',\n },\n {\n label: 'Padding Right',\n type: 'number',\n value: undefined,\n unit: 'px',\n prop: 'paddingRight',\n classReference: 'body',\n },\n {\n label: 'Padding Bottom',\n type: 'number',\n value: undefined,\n unit: 'px',\n prop: 'paddingBottom',\n classReference: 'body',\n },\n {\n label: 'Padding Left',\n type: 'number',\n value: undefined,\n unit: 'px',\n prop: 'paddingLeft',\n classReference: 'body',\n },\n ],\n },\n {\n id: 'container',\n title: 'Content',\n classReference: 'container',\n inputs: [\n {\n label: 'Align',\n type: 'select',\n value: 'left',\n options: {\n left: 'Left',\n center: 'Center',\n right: 'Right',\n },\n prop: 'align',\n classReference: 'container',\n },\n {\n label: 'Width',\n type: 'number',\n value: 600,\n unit: 'px',\n prop: 'width',\n classReference: 'container',\n },\n {\n label: 'Height',\n type: 'number',\n unit: 'px',\n prop: 'height',\n classReference: 'container',\n },\n {\n label: 'Text',\n type: 'color',\n value: '#000000',\n prop: 'color',\n classReference: 'container',\n },\n {\n label: 'Background',\n type: 'color',\n value: '#ffffff',\n prop: 'backgroundColor',\n classReference: 'container',\n },\n {\n label: 'Padding Top',\n type: 'number',\n value: 0,\n unit: 'px',\n prop: 'paddingTop',\n classReference: 'container',\n },\n {\n label: 'Padding Right',\n type: 'number',\n value: 0,\n unit: 'px',\n prop: 'paddingRight',\n classReference: 'container',\n },\n {\n label: 'Padding Bottom',\n type: 'number',\n value: 0,\n unit: 'px',\n prop: 'paddingBottom',\n classReference: 'container',\n },\n {\n label: 'Padding Left',\n type: 'number',\n value: 0,\n unit: 'px',\n prop: 'paddingLeft',\n classReference: 'container',\n },\n {\n label: 'Corner radius',\n type: 'number',\n value: 0,\n unit: 'px',\n prop: 'borderRadius',\n classReference: 'container',\n },\n {\n label: 'Border color',\n type: 'color',\n value: '#000000',\n prop: 'borderColor',\n classReference: 'container',\n },\n ],\n },\n {\n id: 'typography',\n title: 'Text',\n classReference: 'body',\n inputs: [\n {\n label: 'Font size',\n type: 'number',\n value: 14,\n unit: 'px',\n prop: 'fontSize',\n classReference: 'body',\n },\n {\n label: 'Line Height',\n type: 'number',\n value: 155,\n unit: '%',\n prop: 'lineHeight',\n classReference: 'container',\n },\n ],\n },\n {\n id: 'h1',\n title: 'Title',\n category: 'Text',\n classReference: 'h1',\n inputs: [],\n },\n {\n id: 'h2',\n title: 'Subtitle',\n category: 'Text',\n classReference: 'h2',\n inputs: [],\n },\n {\n id: 'h3',\n title: 'Heading',\n category: 'Text',\n classReference: 'h3',\n inputs: [],\n },\n {\n id: 'paragraph',\n title: 'Paragraph',\n category: 'Text',\n classReference: 'paragraph',\n inputs: [],\n },\n {\n id: 'list',\n title: 'List',\n category: 'Text',\n classReference: 'list',\n inputs: [],\n },\n {\n id: 'nested-list',\n title: 'Nested List',\n category: 'Text',\n classReference: 'nestedList',\n inputs: [],\n },\n {\n id: 'list-item',\n title: 'List Item',\n category: 'Text',\n classReference: 'listItem',\n inputs: [],\n },\n {\n id: 'link',\n title: 'Link',\n classReference: 'link',\n inputs: [\n {\n label: 'Color',\n type: 'color',\n value: '#0670DB',\n prop: 'color',\n classReference: 'link',\n },\n {\n label: 'Decoration',\n type: 'select',\n value: 'underline',\n prop: 'textDecoration',\n options: {\n underline: 'Underline',\n none: 'None',\n },\n classReference: 'link',\n },\n ],\n },\n {\n id: 'image',\n title: 'Image',\n classReference: 'image',\n inputs: [\n {\n label: 'Border radius',\n type: 'number',\n value: 8,\n unit: 'px',\n prop: 'borderRadius',\n classReference: 'image',\n },\n ],\n },\n {\n id: 'button',\n title: 'Button',\n classReference: 'button',\n inputs: [\n {\n label: 'Background',\n type: 'color',\n value: '#000000',\n prop: 'backgroundColor',\n classReference: 'button',\n },\n {\n label: 'Text color',\n type: 'color',\n value: '#ffffff',\n prop: 'color',\n classReference: 'button',\n },\n {\n label: 'Radius',\n type: 'number',\n value: 4,\n unit: 'px',\n prop: 'borderRadius',\n classReference: 'button',\n },\n {\n label: 'Padding Top',\n type: 'number',\n value: 7,\n unit: 'px',\n prop: 'paddingTop',\n classReference: 'button',\n },\n {\n label: 'Padding Right',\n type: 'number',\n value: 12,\n unit: 'px',\n prop: 'paddingRight',\n classReference: 'button',\n },\n {\n label: 'Padding Bottom',\n type: 'number',\n value: 7,\n unit: 'px',\n prop: 'paddingBottom',\n classReference: 'button',\n },\n {\n label: 'Padding Left',\n type: 'number',\n value: 12,\n unit: 'px',\n prop: 'paddingLeft',\n classReference: 'button',\n },\n ],\n },\n {\n id: 'code-block',\n title: 'Code Block',\n classReference: 'codeBlock',\n inputs: [\n {\n label: 'Border Radius',\n type: 'number',\n value: 4,\n unit: 'px',\n prop: 'borderRadius',\n classReference: 'codeBlock',\n },\n {\n label: 'Padding Top',\n type: 'number',\n value: 12,\n unit: 'px',\n prop: 'paddingTop',\n classReference: 'codeBlock',\n },\n {\n label: 'Padding Bottom',\n type: 'number',\n value: 12,\n unit: 'px',\n prop: 'paddingBottom',\n classReference: 'codeBlock',\n },\n {\n label: 'Padding Left',\n type: 'number',\n value: 16,\n unit: 'px',\n prop: 'paddingLeft',\n classReference: 'codeBlock',\n },\n {\n label: 'Padding Right',\n type: 'number',\n value: 16,\n unit: 'px',\n prop: 'paddingRight',\n classReference: 'codeBlock',\n },\n ],\n },\n {\n id: 'inline-code',\n title: 'Inline Code',\n classReference: 'inlineCode',\n inputs: [\n {\n label: 'Background',\n type: 'color',\n value: '#e5e7eb',\n prop: 'backgroundColor',\n classReference: 'inlineCode',\n },\n {\n label: 'Text color',\n type: 'color',\n value: '#1e293b',\n prop: 'color',\n classReference: 'inlineCode',\n },\n {\n label: 'Radius',\n type: 'number',\n value: 4,\n unit: 'px',\n prop: 'borderRadius',\n classReference: 'inlineCode',\n },\n ],\n },\n];\n\nconst THEME_MINIMAL: PanelGroup[] = [\n {\n id: 'body',\n title: 'Background',\n classReference: 'body',\n inputs: [\n {\n label: 'Background',\n type: 'color',\n value: '#ffffff',\n prop: 'backgroundColor',\n classReference: 'body',\n },\n {\n label: 'Padding Top',\n type: 'number',\n value: undefined,\n unit: 'px',\n prop: 'paddingTop',\n classReference: 'body',\n },\n {\n label: 'Padding Right',\n type: 'number',\n value: undefined,\n unit: 'px',\n prop: 'paddingRight',\n classReference: 'body',\n },\n {\n label: 'Padding Bottom',\n type: 'number',\n value: undefined,\n unit: 'px',\n prop: 'paddingBottom',\n classReference: 'body',\n },\n {\n label: 'Padding Left',\n type: 'number',\n value: undefined,\n unit: 'px',\n prop: 'paddingLeft',\n classReference: 'body',\n },\n ],\n },\n {\n id: 'container',\n title: 'Content',\n classReference: 'container',\n inputs: [\n {\n label: 'Align',\n type: 'select',\n value: 'left',\n options: {\n left: 'Left',\n center: 'Center',\n right: 'Right',\n },\n prop: 'align',\n classReference: 'container',\n },\n {\n label: 'Width',\n type: 'number',\n value: 600,\n unit: 'px',\n prop: 'width',\n classReference: 'container',\n },\n {\n label: 'Height',\n type: 'number',\n unit: 'px',\n prop: 'height',\n classReference: 'container',\n },\n {\n label: 'Text',\n type: 'color',\n value: '#000000',\n prop: 'color',\n classReference: 'container',\n },\n {\n label: 'Background',\n type: 'color',\n value: '#ffffff',\n prop: 'backgroundColor',\n classReference: 'container',\n },\n {\n label: 'Padding Top',\n type: 'number',\n value: 0,\n unit: 'px',\n prop: 'paddingTop',\n classReference: 'container',\n },\n {\n label: 'Padding Right',\n type: 'number',\n value: 0,\n unit: 'px',\n prop: 'paddingRight',\n classReference: 'container',\n },\n {\n label: 'Padding Bottom',\n type: 'number',\n value: 0,\n unit: 'px',\n prop: 'paddingBottom',\n classReference: 'container',\n },\n {\n label: 'Padding Left',\n type: 'number',\n value: 0,\n unit: 'px',\n prop: 'paddingLeft',\n classReference: 'container',\n },\n {\n label: 'Corner radius',\n type: 'number',\n value: 0,\n unit: 'px',\n prop: 'borderRadius',\n classReference: 'container',\n },\n {\n label: 'Border color',\n type: 'color',\n value: '#000000',\n prop: 'borderColor',\n classReference: 'container',\n },\n ],\n },\n {\n id: 'typography',\n title: 'Text',\n classReference: 'body',\n inputs: [],\n },\n {\n id: 'h1',\n title: 'Title',\n category: 'Text',\n classReference: 'h1',\n inputs: [],\n },\n {\n id: 'h2',\n title: 'Subtitle',\n category: 'Text',\n classReference: 'h2',\n inputs: [],\n },\n {\n id: 'h3',\n title: 'Heading',\n category: 'Text',\n classReference: 'h3',\n inputs: [],\n },\n {\n id: 'paragraph',\n title: 'Paragraph',\n category: 'Text',\n classReference: 'paragraph',\n inputs: [],\n },\n {\n id: 'list',\n title: 'List',\n category: 'Text',\n classReference: 'list',\n inputs: [],\n },\n {\n id: 'nested-list',\n title: 'Nested List',\n category: 'Text',\n classReference: 'nestedList',\n inputs: [],\n },\n {\n id: 'list-item',\n title: 'List Item',\n category: 'Text',\n classReference: 'listItem',\n inputs: [],\n },\n {\n id: 'link',\n title: 'Link',\n classReference: 'link',\n inputs: [],\n },\n {\n id: 'image',\n title: 'Image',\n classReference: 'image',\n inputs: [],\n },\n {\n id: 'button',\n title: 'Button',\n classReference: 'button',\n inputs: [],\n },\n {\n id: 'code-block',\n title: 'Code Block',\n classReference: 'codeBlock',\n inputs: [],\n },\n {\n id: 'inline-code',\n title: 'Inline Code',\n classReference: 'inlineCode',\n inputs: [],\n },\n];\n\nconst RESET_BASIC: ResetTheme = {\n reset: {\n margin: '0',\n padding: '0',\n },\n body: {\n fontFamily:\n \"-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif\",\n fontSize: '14px',\n minHeight: '100%',\n lineHeight: '155%',\n },\n container: {},\n h1: {\n fontSize: '2.25em',\n lineHeight: '1.44em',\n paddingTop: '0.389em',\n fontWeight: 600,\n },\n h2: {\n fontSize: '1.8em',\n lineHeight: '1.44em',\n paddingTop: '0.389em',\n fontWeight: 600,\n },\n h3: {\n fontSize: '1.4em',\n lineHeight: '1.08em',\n paddingTop: '0.389em',\n fontWeight: 600,\n },\n paragraph: {\n fontSize: '1em',\n paddingTop: '0.5em',\n paddingBottom: '0.5em',\n },\n list: {\n paddingLeft: '1.1em',\n paddingBottom: '1em',\n },\n bulletList: {\n listStyleType: 'disc',\n },\n orderedList: {\n listStyleType: 'decimal',\n },\n nestedList: {\n paddingLeft: '1.1em',\n paddingBottom: '0',\n },\n listItem: {\n marginLeft: '1em',\n paddingBottom: '0.3em',\n paddingTop: '0.3em',\n },\n listParagraph: { padding: '0', margin: '0' },\n blockquote: {\n borderLeft: '3px solid #acb3be',\n color: '#7e8a9a',\n marginLeft: 0,\n paddingLeft: '0.8em',\n fontSize: '1.1em',\n fontFamily:\n \"-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif\",\n },\n link: { color: '#0670DB', textDecoration: 'underline' },\n footer: {\n fontSize: '0.8em',\n },\n hr: {\n paddingBottom: '1em',\n borderStyle: 'solid',\n borderWidth: '2px',\n },\n image: {\n maxWidth: '100%',\n },\n button: {\n lineHeight: '100%',\n display: 'inline-block',\n paddingTop: '0.625em',\n paddingRight: '1.25em',\n paddingBottom: '0.625em',\n paddingLeft: '1.25em',\n backgroundColor: '#000000',\n color: '#ffffff',\n borderRadius: '0.375em',\n fontWeight: 500,\n fontSize: '0.875em',\n textDecoration: 'none',\n textAlign: 'center',\n },\n inlineCode: {\n paddingTop: '0.25em',\n paddingBottom: '0.25em',\n paddingLeft: '0.4em',\n paddingRight: '0.4em',\n background: '#e5e7eb',\n color: '#1e293b',\n borderRadius: '4px',\n },\n codeBlock: {\n background: '#f1f5f9',\n borderRadius: '4px',\n paddingTop: '0.75rem',\n paddingRight: '1rem',\n paddingBottom: '0.75rem',\n paddingLeft: '1rem',\n overflowX: 'auto',\n fontFamily: 'monospace',\n fontWeight: '500',\n fontSize: '.92em',\n },\n codeTag: {\n lineHeight: '130%',\n fontFamily: 'monospace',\n fontSize: '.92em',\n },\n section: {\n padding: '10px 20px 10px 20px',\n boxSizing: 'border-box' as const,\n },\n};\n\nconst RESET_MINIMAL: ResetTheme = {\n ...Object.keys(RESET_BASIC).reduce<ResetTheme>((acc, key) => {\n acc[key as keyof ResetTheme] = {};\n return acc;\n }, {} as ResetTheme),\n reset: RESET_BASIC.reset,\n button: {\n lineHeight: RESET_BASIC.button.lineHeight,\n display: RESET_BASIC.button.display,\n },\n image: RESET_BASIC.image,\n list: RESET_BASIC.list,\n bulletList: RESET_BASIC.bulletList,\n orderedList: RESET_BASIC.orderedList,\n nestedList: RESET_BASIC.nestedList,\n listItem: RESET_BASIC.listItem,\n listParagraph: RESET_BASIC.listParagraph,\n link: RESET_BASIC.link,\n};\n\nexport const RESET_THEMES: Record<EditorTheme, ResetTheme> = {\n basic: RESET_BASIC,\n minimal: RESET_MINIMAL,\n};\n\nexport function resolveResetValue(\n value: string | number | undefined,\n targetUnit: 'px' | '%',\n bodyFontSizePx: number,\n): number | undefined {\n if (value === undefined) {\n return undefined;\n }\n const str = String(value);\n const num = Number.parseFloat(str);\n if (Number.isNaN(num)) {\n return undefined;\n }\n if (str.endsWith('em')) {\n return targetUnit === 'px' ? Math.floor(num * bodyFontSizePx) : num * 100;\n }\n return num;\n}\n\nexport const EDITOR_THEMES: Record<EditorTheme, PanelGroup[]> = {\n minimal: THEME_MINIMAL,\n basic: THEME_BASIC,\n};\n\nexport function getThemeBodyFontSizePx(theme: EditorTheme): number {\n for (const group of EDITOR_THEMES[theme]) {\n if (group.classReference !== 'body') {\n continue;\n }\n for (const input of group.inputs) {\n if (input.prop === 'fontSize' && typeof input.value === 'number') {\n return input.value;\n }\n }\n }\n return 14;\n}\n\n/**\n * Use to make the preview nicer once the theme might miss some\n * important properties to make layout accurate\n */\nexport const DEFAULT_INBOX_FONT_SIZE_PX = 14;\nexport const INBOX_EMAIL_DEFAULTS: Partial<ResetTheme> = {\n body: {\n color: '#000000',\n fontFamily:\n \"-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif\",\n fontSize: `${DEFAULT_INBOX_FONT_SIZE_PX}px`,\n },\n container: {\n width: 600,\n },\n};\n\nexport const SUPPORTED_CSS_PROPERTIES: SupportedCssProperties = {\n align: {\n label: 'Align',\n type: 'select',\n options: {\n left: 'Left',\n center: 'Center',\n right: 'Right',\n },\n defaultValue: 'left',\n category: 'layout',\n },\n backgroundColor: {\n label: 'Background',\n type: 'color',\n excludeNodes: ['image', 'youtube'],\n defaultValue: '#ffffff',\n category: 'appearance',\n },\n color: {\n label: 'Text color',\n type: 'color',\n excludeNodes: ['image', 'youtube'],\n defaultValue: '#000000',\n category: 'typography',\n },\n fontSize: {\n label: 'Font size',\n type: 'number',\n unit: 'px',\n excludeNodes: ['image', 'youtube'],\n defaultValue: 14,\n category: 'typography',\n },\n fontWeight: {\n label: 'Font weight',\n type: 'select',\n options: {\n 300: 'Light',\n 400: 'Normal',\n 600: 'Semi Bold',\n 700: 'Bold',\n 800: 'Extra Bold',\n },\n excludeNodes: ['image', 'youtube'],\n defaultValue: 400,\n category: 'typography',\n },\n letterSpacing: {\n label: 'Letter spacing',\n type: 'number',\n unit: 'px',\n excludeNodes: ['image', 'youtube'],\n defaultValue: 0,\n category: 'typography',\n },\n lineHeight: {\n label: 'Line height',\n type: 'number',\n unit: '%',\n defaultValue: 155,\n category: 'typography',\n },\n textDecoration: {\n label: 'Text decoration',\n type: 'select',\n options: {\n none: 'None',\n underline: 'Underline',\n 'line-through': 'Line-through',\n },\n defaultValue: 'none',\n category: 'typography',\n },\n borderRadius: {\n label: 'Border Radius',\n type: 'number',\n unit: 'px',\n defaultValue: 8,\n category: 'appearance',\n },\n borderTopLeftRadius: {\n label: 'Border Radius (Top-Left)',\n type: 'number',\n unit: 'px',\n defaultValue: 8,\n category: 'appearance',\n },\n borderTopRightRadius: {\n label: 'Border Radius (Top-Right)',\n type: 'number',\n unit: 'px',\n defaultValue: 8,\n category: 'appearance',\n },\n borderBottomLeftRadius: {\n label: 'Border Radius (Bottom-Left)',\n type: 'number',\n unit: 'px',\n defaultValue: 8,\n category: 'appearance',\n },\n borderBottomRightRadius: {\n label: 'Border Radius (Bottom-Right)',\n type: 'number',\n unit: 'px',\n defaultValue: 8,\n category: 'appearance',\n },\n borderWidth: {\n label: 'Border Width',\n type: 'number',\n unit: 'px',\n defaultValue: 1,\n category: 'appearance',\n },\n borderTopWidth: {\n label: 'Border Top Width',\n type: 'number',\n unit: 'px',\n defaultValue: 1,\n category: 'appearance',\n },\n borderRightWidth: {\n label: 'Border Right Width',\n type: 'number',\n unit: 'px',\n defaultValue: 1,\n category: 'appearance',\n },\n borderBottomWidth: {\n label: 'Border Bottom Width',\n type: 'number',\n unit: 'px',\n defaultValue: 1,\n category: 'appearance',\n },\n borderLeftWidth: {\n label: 'Border Left Width',\n type: 'number',\n unit: 'px',\n defaultValue: 1,\n category: 'appearance',\n },\n borderStyle: {\n label: 'Border Style',\n type: 'select',\n options: {\n solid: 'Solid',\n dashed: 'Dashed',\n dotted: 'Dotted',\n },\n defaultValue: 'solid',\n category: 'appearance',\n },\n borderTopStyle: {\n label: 'Border Top Style',\n type: 'select',\n options: {\n solid: 'Solid',\n dashed: 'Dashed',\n dotted: 'Dotted',\n },\n defaultValue: 'solid',\n category: 'appearance',\n },\n borderRightStyle: {\n label: 'Border Right Style',\n type: 'select',\n options: {\n solid: 'Solid',\n dashed: 'Dashed',\n dotted: 'Dotted',\n },\n defaultValue: 'solid',\n category: 'appearance',\n },\n borderBottomStyle: {\n label: 'Border Bottom Style',\n type: 'select',\n options: {\n solid: 'Solid',\n dashed: 'Dashed',\n dotted: 'Dotted',\n },\n defaultValue: 'solid',\n category: 'appearance',\n },\n borderLeftStyle: {\n label: 'Border Left Style',\n type: 'select',\n options: {\n solid: 'Solid',\n dashed: 'Dashed',\n dotted: 'Dotted',\n },\n defaultValue: 'solid',\n category: 'appearance',\n },\n borderColor: {\n label: 'Border Color',\n type: 'color',\n defaultValue: '#000000',\n category: 'appearance',\n },\n borderTopColor: {\n label: 'Border Top Color',\n type: 'color',\n defaultValue: '#000000',\n category: 'appearance',\n },\n borderRightColor: {\n label: 'Border Right Color',\n type: 'color',\n defaultValue: '#000000',\n category: 'appearance',\n },\n borderBottomColor: {\n label: 'Border Bottom Color',\n type: 'color',\n defaultValue: '#000000',\n category: 'appearance',\n },\n borderLeftColor: {\n label: 'Border Left Color',\n type: 'color',\n defaultValue: '#000000',\n category: 'appearance',\n },\n padding: {\n label: 'Padding',\n type: 'number',\n unit: 'px',\n defaultValue: 8,\n category: 'layout',\n },\n paddingTop: {\n label: 'Padding Top',\n type: 'number',\n unit: 'px',\n defaultValue: 8,\n category: 'layout',\n },\n paddingLeft: {\n label: 'Padding Left',\n type: 'number',\n unit: 'px',\n defaultValue: 8,\n category: 'layout',\n },\n paddingBottom: {\n label: 'Padding Bottom',\n type: 'number',\n unit: 'px',\n defaultValue: 8,\n category: 'layout',\n },\n paddingRight: {\n label: 'Padding Right',\n type: 'number',\n unit: 'px',\n defaultValue: 8,\n category: 'layout',\n },\n width: {\n label: 'Width',\n type: 'number',\n unit: 'px',\n defaultValue: 600,\n category: 'layout',\n },\n height: {\n label: 'Height',\n type: 'number',\n unit: 'px',\n defaultValue: 400,\n category: 'layout',\n },\n};\n","import { EDITOR_THEMES } from './themes';\nimport type {\n EditorTheme,\n KnownThemeComponents,\n PanelGroup,\n PanelSectionId,\n} from './types';\n\nconst PANEL_SECTION_IDS = new Set<PanelSectionId>([\n 'body',\n 'container',\n 'typography',\n 'paragraph',\n 'list',\n 'nested-list',\n 'list-item',\n 'link',\n 'image',\n 'button',\n 'code-block',\n 'inline-code',\n]);\n\nconst PANEL_SECTION_IDS_BY_TITLE: Record<string, PanelSectionId> = {\n background: 'body',\n body: 'body',\n content: 'container',\n container: 'container',\n typography: 'typography',\n paragraph: 'paragraph',\n list: 'list',\n 'nested list': 'nested-list',\n 'list item': 'list-item',\n link: 'link',\n image: 'image',\n button: 'button',\n 'code block': 'code-block',\n 'inline code': 'inline-code',\n};\n\nconst PANEL_SECTION_IDS_BY_CLASS_REFERENCE: Partial<\n Record<KnownThemeComponents, PanelSectionId>\n> = {\n container: 'container',\n paragraph: 'paragraph',\n list: 'list',\n nestedList: 'nested-list',\n listItem: 'list-item',\n link: 'link',\n image: 'image',\n button: 'button',\n codeBlock: 'code-block',\n inlineCode: 'inline-code',\n};\n\nfunction isPanelSectionId(value: unknown): value is PanelSectionId {\n return (\n typeof value === 'string' && PANEL_SECTION_IDS.has(value as PanelSectionId)\n );\n}\n\nfunction normalizeTitle(title: string | undefined): string {\n return title?.trim().toLowerCase().replace(/\\s+/g, ' ') ?? '';\n}\n\nfunction resolvePanelSectionId(group: PanelGroup): PanelSectionId | null {\n if (isPanelSectionId(group.id)) {\n return group.id;\n }\n\n const normalizedTitle = normalizeTitle(group.title);\n\n if (group.classReference === 'body') {\n if (normalizedTitle === 'typography') {\n return 'typography';\n }\n\n return 'body';\n }\n\n if (\n group.classReference &&\n PANEL_SECTION_IDS_BY_CLASS_REFERENCE[group.classReference]\n ) {\n return PANEL_SECTION_IDS_BY_CLASS_REFERENCE[group.classReference] ?? null;\n }\n\n return PANEL_SECTION_IDS_BY_TITLE[normalizedTitle] ?? null;\n}\n\nfunction normalizePanelInputs(\n inputs: PanelGroup['inputs'],\n defaultInputs: PanelGroup['inputs'],\n fallbackClassReference?: KnownThemeComponents,\n): PanelGroup['inputs'] {\n if (!Array.isArray(inputs)) {\n return [];\n }\n\n return inputs.map((input) => {\n const defaultInput = defaultInputs.find(\n (candidate) => candidate.prop === input.prop,\n );\n\n return {\n ...defaultInput,\n ...input,\n classReference:\n input.classReference ??\n defaultInput?.classReference ??\n fallbackClassReference,\n };\n });\n}\n\nexport function inferThemeFromPanelStyles(\n panelStyles: PanelGroup[] | null | undefined,\n): EditorTheme | null {\n if (!Array.isArray(panelStyles) || panelStyles.length === 0) {\n return null;\n }\n\n let finalTheme: EditorTheme | null = null;\n for (const group of panelStyles) {\n if (!Array.isArray(group?.inputs)) {\n finalTheme = null;\n break;\n }\n\n if (group.inputs.length !== 0) {\n finalTheme = 'basic';\n break;\n }\n\n finalTheme = 'minimal';\n }\n\n return finalTheme;\n}\n\nexport function normalizeThemePanelStyles(\n theme: EditorTheme,\n panelStyles: PanelGroup[] | null | undefined,\n): PanelGroup[] | null {\n if (!Array.isArray(panelStyles)) {\n return null;\n }\n\n return panelStyles.map((group) => {\n const panelId = resolvePanelSectionId(group);\n\n if (!panelId) {\n return group;\n }\n\n const defaultGroup = EDITOR_THEMES[theme].find(\n (candidate) => candidate.id === panelId,\n );\n\n if (!defaultGroup) {\n return group;\n }\n\n return {\n ...group,\n id: panelId,\n title: defaultGroup.title,\n classReference: defaultGroup.classReference,\n inputs: normalizePanelInputs(\n group.inputs,\n defaultGroup.inputs,\n defaultGroup.classReference,\n ),\n };\n });\n}\n","import { SUPPORTED_CSS_PROPERTIES } from './themes';\nimport type {\n EditorTheme,\n EditorThemeInput,\n KnownCssProperties,\n PanelGroup,\n PanelSectionId,\n ThemeableComponent,\n ThemeComponentStyles,\n ThemeConfig,\n} from './types';\n\nconst CLASS_REFERENCE_TO_PANEL_ID: Record<ThemeableComponent, PanelSectionId> =\n {\n body: 'body',\n container: 'container',\n h1: 'h1',\n h2: 'h2',\n h3: 'h3',\n paragraph: 'paragraph',\n link: 'link',\n image: 'image',\n button: 'button',\n list: 'list',\n nestedList: 'nested-list',\n listItem: 'list-item',\n codeBlock: 'code-block',\n inlineCode: 'inline-code',\n };\n\nexport function parseCssValue(value: string | number): {\n value: string | number;\n unit?: 'px' | '%';\n} {\n if (typeof value === 'number') {\n return { value };\n }\n const pxMatch = /^(-?\\d+(?:\\.\\d+)?)px$/.exec(value);\n if (pxMatch) {\n return { value: Number.parseFloat(pxMatch[1]), unit: 'px' };\n }\n const percentMatch = /^(-?\\d+(?:\\.\\d+)?)%$/.exec(value);\n if (percentMatch) {\n return { value: Number.parseFloat(percentMatch[1]), unit: '%' };\n }\n return { value };\n}\n\nexport function isThemeConfig(\n theme: EditorThemeInput | undefined,\n): theme is ThemeConfig {\n return typeof theme === 'object' && theme !== null && 'styles' in theme;\n}\n\nexport function themeStylesToPanelOverrides(\n styles: ThemeComponentStyles,\n basePanels: PanelGroup[],\n): PanelGroup[] {\n const result: PanelGroup[] = basePanels.map((group) => ({\n ...group,\n inputs: group.inputs.map((input) => ({ ...input })),\n }));\n\n for (const [component, cssProps] of Object.entries(styles) as [\n ThemeableComponent,\n React.CSSProperties,\n ][]) {\n if (!cssProps) continue;\n const panelId = CLASS_REFERENCE_TO_PANEL_ID[component];\n\n const group = result.find((g) => g.id === panelId);\n if (!group) continue;\n\n for (const [cssProp, cssValue] of Object.entries(cssProps) as [\n KnownCssProperties,\n string | number,\n ][]) {\n if (cssValue === undefined) continue;\n\n const existingInput = group.inputs.find(\n (i) => i.prop === cssProp && i.classReference === component,\n );\n\n const parsed = parseCssValue(cssValue);\n\n if (existingInput) {\n existingInput.value = parsed.value;\n if (parsed.unit !== undefined) {\n existingInput.unit = parsed.unit;\n }\n } else {\n const propMeta = SUPPORTED_CSS_PROPERTIES[cssProp];\n group.inputs.push({\n label: propMeta?.label ?? cssProp,\n type: propMeta?.type ?? 'text',\n prop: cssProp,\n classReference: component,\n value: parsed.value,\n unit: parsed.unit ?? propMeta?.unit,\n options: propMeta?.options,\n });\n }\n }\n }\n\n return result;\n}\n\nexport function createTheme(styles: ThemeComponentStyles): ThemeConfig {\n return { styles };\n}\n\nexport function extendTheme(\n base: EditorTheme,\n overrides: ThemeComponentStyles,\n): ThemeConfig {\n return { extends: base, styles: overrides };\n}\n","import type { Editor, JSONContent } from '@tiptap/core';\nimport { Extension } from '@tiptap/core';\nimport { Plugin, PluginKey } from '@tiptap/pm/state';\nimport { useEditorState } from '@tiptap/react';\nimport type * as React from 'react';\nimport { Body, Head, Html, Preview } from 'react-email';\nimport type { SerializerPlugin } from '../../core/serializer/serializer-plugin';\nimport { getGlobalContent } from '../../extensions/global-content';\nimport {\n injectGlobalPlainCss,\n injectThemeCss,\n mergeCssJs,\n transformToCssJs,\n} from './css-transforms';\nimport {\n inferThemeFromPanelStyles,\n normalizeThemePanelStyles,\n} from './normalization';\nimport { isThemeConfig, themeStylesToPanelOverrides } from './theme-config';\nimport {\n DEFAULT_INBOX_FONT_SIZE_PX,\n EDITOR_THEMES,\n RESET_THEMES,\n} from './themes';\nimport type {\n CssJs,\n EditorTheme,\n EditorThemeInput,\n KnownThemeComponents,\n PanelGroup,\n} from './types';\n\n/**\n * Maps a document node (type + attrs) to the theme component key used for style lookup.\n * Centralizes all node-type → theme-component knowledge.\n */\nexport function getThemeComponentKey(\n nodeType: string,\n depth: number,\n attrs: Record<string, unknown> = {},\n): KnownThemeComponents | null {\n switch (nodeType) {\n case 'paragraph':\n if (depth > 0) {\n return 'listParagraph';\n }\n return 'paragraph';\n case 'heading': {\n const level = attrs.level as number | undefined;\n return `h${level ?? 1}` as KnownThemeComponents;\n }\n case 'blockquote':\n return 'blockquote';\n case 'button':\n return 'button';\n case 'container':\n return 'container';\n case 'section':\n return 'section';\n case 'footer':\n return 'footer';\n case 'image':\n return 'image';\n case 'youtube':\n case 'twitter':\n return 'image';\n case 'orderedList':\n case 'bulletList':\n if (depth > 0) {\n return 'nestedList';\n }\n return 'list';\n case 'listItem':\n return 'listItem';\n case 'codeBlock':\n return 'codeBlock';\n case 'code':\n return 'inlineCode';\n case 'link':\n return 'link';\n case 'horizontalRule':\n return 'hr';\n default:\n return null;\n }\n}\n\n/**\n * Returns merged theme styles (reset + panel styles) for the given editor.\n * Use when you have editor access and need the full CssJs map.\n */\nexport function getMergedCssJs(\n theme: EditorTheme,\n panelStyles: PanelGroup[] | undefined,\n): CssJs {\n const panels: PanelGroup[] =\n normalizeThemePanelStyles(theme, panelStyles) ?? EDITOR_THEMES[theme];\n const parsed = transformToCssJs(panels, DEFAULT_INBOX_FONT_SIZE_PX);\n const merged = mergeCssJs(RESET_THEMES[theme], parsed);\n\n return merged;\n}\n\n/**\n * Node types and theme component keys that should receive the universal\n * `reset` CSS (e.g. `margin: 0; padding: 0`) layered underneath their own\n * theme styles. Shared between `getResolvedNodeStyles` (email serializer)\n * and `injectThemeCss` (editor preview) so both surfaces stay in sync.\n *\n * Includes both raw tiptap node names (e.g. `tableCell`) and theme\n * component keys (e.g. `list`) because the serializer matches against both.\n *\n * `bulletList` and `orderedList` are intentionally omitted: their elements\n * already carry the shared `node-list` class, so the `list` reset rule\n * covers them without forcing the dedicated `.node-bulletList` /\n * `.node-orderedList` rules to redundantly emit `margin: 0; padding: 0`.\n */\nexport const RESET_NODE_TYPES = new Set<string>([\n 'body',\n 'button',\n 'columns',\n 'div',\n 'h1',\n 'h2',\n 'h3',\n 'list',\n 'listItem',\n 'listParagraph',\n 'nestedList',\n 'table',\n 'paragraph',\n 'tableCell',\n 'tableHeader',\n 'tableRow',\n 'youtube',\n]);\n\n/**\n * Returns resolved React.CSSProperties for a node when you already have merged CssJs\n * (e.g. in the serializer where there is no editor). Centralizes which theme keys\n * apply to which node type.\n */\nexport function getResolvedNodeStyles(\n node: JSONContent,\n depth: number,\n mergedCssJs: CssJs,\n): React.CSSProperties {\n const key = getThemeComponentKey(node.type ?? '', depth, node.attrs ?? {});\n if (!key) {\n if (RESET_NODE_TYPES.has(node.type ?? '')) {\n return mergedCssJs.reset ?? {};\n }\n return {};\n }\n const component = mergedCssJs[key] ?? {};\n const shouldReset =\n RESET_NODE_TYPES.has(key) || RESET_NODE_TYPES.has(node.type ?? '');\n if (shouldReset) {\n const reset = mergedCssJs.reset ?? {};\n return { ...reset, ...component };\n }\n return { ...component };\n}\n\nexport function stylesToCss(\n styles: PanelGroup[],\n theme: EditorTheme,\n): Record<KnownThemeComponents, React.CSSProperties> {\n const parsed = transformToCssJs(\n normalizeThemePanelStyles(theme, styles) ?? EDITOR_THEMES[theme],\n DEFAULT_INBOX_FONT_SIZE_PX,\n );\n return mergeCssJs(RESET_THEMES[theme], parsed);\n}\n\nfunction resolveThemeConfig(config: EditorThemeInput): {\n baseTheme: EditorTheme;\n panels: PanelGroup[] | undefined;\n} {\n if (!isThemeConfig(config)) {\n return { baseTheme: config, panels: undefined };\n }\n const baseTheme: EditorTheme = config.extends ?? 'minimal';\n const basePanels = EDITOR_THEMES[baseTheme];\n const panels = themeStylesToPanelOverrides(config.styles, basePanels);\n return { baseTheme, panels };\n}\n\nexport function getEmailTheming(editor: Editor) {\n const theme = getEmailTheme(editor);\n const normalizedStyles =\n normalizeThemePanelStyles(theme, getEmailStyles(editor)) ??\n EDITOR_THEMES[theme];\n\n return {\n styles: normalizedStyles,\n theme,\n css: getEmailCss(editor),\n };\n}\n\nexport function useEmailTheming(editor: Editor | null) {\n return useEditorState({\n editor,\n selector({ editor: ed }) {\n if (!ed) {\n return null;\n }\n return getEmailTheming(ed);\n },\n });\n}\n\nfunction getEmailStyles(editor: Editor) {\n return getGlobalContent('styles', editor) as PanelGroup[] | null;\n}\n\n/**\n * Sets the global panel styles on the editor document.\n * Persists into the `GlobalContent` node under the `'styles'` key.\n */\nexport function setGlobalStyles(editor: Editor, styles: PanelGroup[]): boolean {\n return editor.commands.setGlobalContent('styles', styles);\n}\n\n/**\n * Sets the current email theme on the editor document.\n * Persists into the `GlobalContent` node under the `'theme'` key.\n */\nexport function setCurrentTheme(editor: Editor, theme: EditorTheme): boolean {\n return editor.commands.setGlobalContent('theme', theme);\n}\n\n/**\n * Sets the global CSS string injected into the email `<head>`.\n * Persists into the `GlobalContent` node under the `'css'` key.\n */\nexport function setGlobalCssInjected(editor: Editor, css: string): boolean {\n return editor.commands.setGlobalContent('css', css);\n}\n\nfunction getEmailTheme(editor: Editor): EditorTheme {\n const extensionOptions = (\n editor.extensionManager.extensions.find(\n (extension) => extension.name === 'theming',\n ) as { options?: { theme?: EditorThemeInput } }\n )?.options?.theme;\n\n if (isThemeConfig(extensionOptions)) {\n return extensionOptions.extends ?? 'minimal';\n }\n\n if (extensionOptions === 'basic' || extensionOptions === 'minimal') {\n return extensionOptions;\n }\n\n const globalTheme = getGlobalContent('theme', editor) as EditorTheme | null;\n if (globalTheme === 'basic' || globalTheme === 'minimal') {\n return globalTheme;\n }\n\n const inferredTheme = inferThemeFromPanelStyles(getEmailStyles(editor));\n if (inferredTheme) {\n return inferredTheme;\n }\n\n return 'basic';\n}\n\nfunction getEmailCss(editor: Editor) {\n return getGlobalContent('css', editor) as string | null;\n}\n\nexport const EmailTheming = Extension.create<{\n theme?: EditorThemeInput;\n serializerPlugin: SerializerPlugin;\n}>({\n name: 'theming',\n\n addOptions() {\n return {\n theme: undefined as EditorThemeInput | undefined,\n serializerPlugin: {\n getNodeStyles(node, depth, editor): React.CSSProperties {\n const theming = getEmailTheming(editor);\n\n return getResolvedNodeStyles(\n node,\n depth,\n getMergedCssJs(theming.theme, theming.styles),\n );\n },\n BaseTemplate({ previewText, children, editor }) {\n const { css: globalCss, styles, theme } = getEmailTheming(editor);\n const mergedStyles = getMergedCssJs(theme, styles);\n\n return (\n <Html>\n <Head>\n <meta content=\"width=device-width\" name=\"viewport\" />\n <meta content=\"IE=edge\" httpEquiv=\"X-UA-Compatible\" />\n <meta name=\"x-apple-disable-message-reformatting\" />\n <meta\n content=\"telephone=no,address=no,email=no,date=no,url=no\"\n name=\"format-detection\"\n />\n\n {globalCss && <style>{globalCss}</style>}\n </Head>\n {previewText && previewText !== '' && (\n <Preview>{previewText}</Preview>\n )}\n\n <Body style={mergedStyles.body}>{children}</Body>\n </Html>\n );\n },\n } satisfies SerializerPlugin,\n };\n },\n\n addProseMirrorPlugins() {\n const { editor } = this;\n const scopeId = `tiptap-theme-${Math.random().toString(36).slice(2, 10)}`;\n const scopeAttribute = 'data-editor-theme-scope';\n const scopeSelector = `.tiptap.ProseMirror[${scopeAttribute}=\"${scopeId}\"]`;\n const themeStyleId = `${scopeId}-theme`;\n const globalStyleId = `${scopeId}-global`;\n\n return [\n new Plugin({\n key: new PluginKey('themingStyleInjector'),\n view(view) {\n let prevStyles: PanelGroup[] | null = null;\n let prevTheme: EditorTheme | null = null;\n let prevCss: string | null = null;\n let seededFromConfig = false;\n\n view.dom.setAttribute(scopeAttribute, scopeId);\n\n const sync = () => {\n if (!seededFromConfig) {\n seededFromConfig = true;\n const extensionTheme = (\n editor.extensionManager.extensions.find(\n (ext) => ext.name === 'theming',\n ) as { options?: { theme?: EditorThemeInput } }\n )?.options?.theme;\n\n if (isThemeConfig(extensionTheme)) {\n const { baseTheme, panels } =\n resolveThemeConfig(extensionTheme);\n if (panels && !getGlobalContent('styles', editor)) {\n editor.commands.setGlobalContent('styles', panels);\n }\n if (!getGlobalContent('theme', editor)) {\n editor.commands.setGlobalContent('theme', baseTheme);\n }\n }\n }\n\n const theme = getEmailTheme(editor);\n const styles = getEmailStyles(editor);\n const resolvedStyles = styles ?? EDITOR_THEMES[theme];\n const css = getEmailCss(editor);\n\n if (styles !== prevStyles || theme !== prevTheme) {\n prevStyles = styles as PanelGroup[] | null;\n prevTheme = theme;\n const mergedCssJs = getMergedCssJs(theme, resolvedStyles);\n injectThemeCss(mergedCssJs, {\n scopeSelector,\n styleId: themeStyleId,\n });\n }\n\n if (css !== prevCss) {\n prevCss = css;\n injectGlobalPlainCss(css, {\n scopeSelector,\n styleId: globalStyleId,\n });\n }\n };\n\n sync();\n\n return {\n update: sync,\n destroy() {\n document.getElementById(themeStyleId)?.remove();\n document.getElementById(globalStyleId)?.remove();\n view.dom.removeAttribute(scopeAttribute);\n },\n };\n },\n }),\n ];\n },\n});\n"],"mappings":"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AM;IACN,OAAO;IACP,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,gBAAgB;IACjB;GACF;EACF;CACD;EACE,IAAI;EACJ,OAAO;EACP,gBAAgB;EAChB,QAAQ,CACN;GACE,OAAO;GACP,MAAM;GACN,OAAO;GACP,MAAM;GACN,MAAM;GACN,gBAAgB;GACjB,EACD;GACE,OAAO;GACP,MAAM;GACN,OAAO;GACP,MAAM;GACN,MAAM;GACN,gBAAgB;GACjB,CACF;EACF;CACD;EACE,IAAI;EACJ,OAAO;EACP,UAAU;EACV,gBAAgB;EAChB,QAAQ,EAAE;EACX;CACD;EACE,IAAI;EACJ,OAAO;EACP,UAAU;EACV,gBAAgB;EAChB,QAAQ,EAAE;EACX;CACD;EACE,IAAI;EACJ,OAAO;EACP,UAAU;EACV,gBAAgB;EAChB,QAAQ,EAAE;EACX;CACD;EACE,IAAI;EACJ,OAAO;EACP,UAAU;EACV,gBAAgB;EAChB,QAAQ,EAAE;EACX;CACD;EACE,IAAI;EACJ,OAAO;EACP,UAAU;EACV,gBAAgB;EAChB,QAAQ,EAAE;EACX;CACD;EACE,IAAI;EACJ,OAAO;EACP,UAAU;EACV,gBAAgB;EAChB,QAAQ,EAAE;EACX;CACD;EACE,IAAI;EACJ,OAAO;EACP,UAAU;EACV,gBAAgB;EAChB,QAAQ,EAAE;EACX;CACD;EACE,IAAI;EACJ,OAAO;EACP,gBAAgB;EAChB,QAAQ,CACN;GACE,OAAO;GACP,MAAM;GACN,OAAO;GACP,MAAM;GACN,gBAAgB;GACjB,EACD;GACE,OAAO;GACP,MAAM;GACN,OAAO;GACP,MAAM;GACN,SAAS;IACP,WAAW;IACX,MAAM;IACP;GACD,gBAAgB;GACjB,CACF;EACF;CACD;EACE,IAAI;EACJ,OAAO;EACP,gBAAgB;EAChB,QAAQ,CACN;GACE,OAAO;GACP,MAAM;GACN,OAAO;GACP,MAAM;GACN,MAAM;GACN,gBAAgB;GACjB,CACF;EACF;CACD;EACE,IAAI;EACJ,OAAO;EACP,gBAAgB;EAChB,QAAQ;GACN;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACF;EACF;CACD;EACE,IAAI;EACJ,OAAO;EACP,gBAAgB;EAChB,QAAQ;GACN;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACF;EACF;CACD;EACE,IAAI;EACJ,OAAO;EACP,gBAAgB;EAChB,QAAQ;GACN;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACF;EACF;CACF;AAED,MAAM,gBAA8B;CAClC;EACE,IAAI;EACJ,OAAO;EACP,gBAAgB;EAChB,QAAQ;GACN;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO,KAAA;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO,KAAA;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO,KAAA;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO,KAAA;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACF;EACF;CACD;EACE,IAAI;EACJ,OAAO;EACP,gBAAgB;EAChB,QAAQ;GACN;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,SAAS;KACP,MAAM;KACN,QAAQ;KACR,OAAO;KACR;IACD,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;IACN,gBAAgB;IACjB;GACD;IACE,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,g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AAc,CAAC,SAAS,UAAU;EAClC,cAAc;EACd,UAAU;EACX;CACD,OAAO;EACL,OAAO;EACP,MAAM;EACN,cAAc,CAAC,SAAS,UAAU;EAClC,cAAc;EACd,UAAU;EACX;CACD,UAAU;EACR,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc,CAAC,SAAS,UAAU;EAClC,cAAc;EACd,UAAU;EACX;CACD,YAAY;EACV,OAAO;EACP,MAAM;EACN,SAAS;GACP,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACN;EACD,cAAc,CAAC,SAAS,UAAU;EAClC,cAAc;EACd,UAAU;EACX;CACD,eAAe;EACb,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc,CAAC,SAAS,UAAU;EAClC,cAAc;EACd,UAAU;EACX;CACD,YAAY;EACV,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,gBAAgB;EACd,OAAO;EACP,MAAM;EACN,SAAS;GACP,MAAM;GACN,WAAW;GACX,gBAAgB;GACjB;EACD,cAAc;EACd,UAAU;EACX;CACD,cAAc;EACZ,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,qBAAqB;EACnB,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,sBAAsB;EACpB,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,wBAAwB;EACtB,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,yBAAyB;EACvB,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,aAAa;EACX,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,gBAAgB;EACd,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,kBAAkB;EAChB,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,mBAAmB;EACjB,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,iBAAiB;EACf,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,aAAa;EACX,OAAO;EACP,MAAM;EACN,SAAS;GACP,OAAO;GACP,QAAQ;GACR,QAAQ;GACT;EACD,cAAc;EACd,UAAU;EACX;CACD,gBAAgB;EACd,OAAO;EACP,MAAM;EACN,SAAS;GACP,OAAO;GACP,QAAQ;GACR,QAAQ;GACT;EACD,cAAc;EACd,UAAU;EACX;CACD,kBAAkB;EAChB,OAAO;EACP,MAAM;EACN,SAAS;GACP,OAAO;GACP,QAAQ;GACR,QAAQ;GACT;EACD,cAAc;EACd,UAAU;EACX;CACD,mBAAmB;EACjB,OAAO;EACP,MAAM;EACN,SAAS;GACP,OAAO;GACP,QAAQ;GACR,QAAQ;GACT;EACD,cAAc;EACd,UAAU;EACX;CACD,iBAAiB;EACf,OAAO;EACP,MAAM;EACN,SAAS;GACP,OAAO;GACP,QAAQ;GACR,QAAQ;GACT;EACD,cAAc;EACd,UAAU;EACX;CACD,aAAa;EACX,OAAO;EACP,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,gBAAgB;EACd,OAAO;EACP,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,kBAAkB;EAChB,OAAO;EACP,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,mBAAmB;EACjB,OAAO;EACP,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,iBAAiB;EACf,OAAO;EACP,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,SAAS;EACP,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,YAAY;EACV,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,aAAa;EACX,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,eAAe;EACb,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc;EACd,UAAU;EACX;CACD,cAAc;EACZ,OAAO;EACP,MAAM;EACN,MAAM;EACN,cAAc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"}