@react-email/editor 0.0.0-experimental.16 → 0.0.0-experimental.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,12 +1,12 @@
1
1
  import * as ReactEmailComponents from "@react-email/components";
2
- import { Body as Body$1, Button as Button$1, CodeBlock, Column, Head, Html, Preview, Row, Section as Section$1, pretty, render, toPlainText } from "@react-email/components";
2
+ import { Body as Body$1, Button as Button$1, CodeBlock, Column, Head, Heading as Heading$1, Hr, Html, Link as Link$1, Preview, Row, Section as Section$1, pretty, render, toPlainText } from "@react-email/components";
3
3
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
- import { Extension, Mark, Node as Node$1, findChildren, markInputRule, markPasteRule, mergeAttributes } from "@tiptap/core";
4
+ import { Extension, InputRule, Mark, Node as Node$1, findChildren, markInputRule, markPasteRule, mergeAttributes } from "@tiptap/core";
5
5
  import { UndoRedo } from "@tiptap/extensions";
6
- import { ReactRenderer, useCurrentEditor, useEditor as useEditor$1, useEditorState } from "@tiptap/react";
6
+ import { NodeViewContent, NodeViewWrapper, ReactNodeViewRenderer, ReactRenderer, useCurrentEditor, useEditor as useEditor$1, useEditorState } from "@tiptap/react";
7
7
  import * as React from "react";
8
8
  import { useCallback, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState } from "react";
9
- import { StarterKit } from "@tiptap/starter-kit";
9
+ import TipTapStarterKit from "@tiptap/starter-kit";
10
10
  import BlockquoteBase from "@tiptap/extension-blockquote";
11
11
  import BulletListBase from "@tiptap/extension-bullet-list";
12
12
  import CodeBase from "@tiptap/extension-code";
@@ -15,8 +15,11 @@ import { Plugin, PluginKey, TextSelection } from "@tiptap/pm/state";
15
15
  import { Decoration, DecorationSet } from "@tiptap/pm/view";
16
16
  import { fromHtml } from "hast-util-from-html";
17
17
  import Prism from "prismjs";
18
+ import HorizontalRule from "@tiptap/extension-horizontal-rule";
18
19
  import HardBreakBase from "@tiptap/extension-hard-break";
20
+ import { Heading as Heading$2 } from "@tiptap/extension-heading";
19
21
  import ItalicBase from "@tiptap/extension-italic";
22
+ import TiptapLink from "@tiptap/extension-link";
20
23
  import ListItemBase from "@tiptap/extension-list-item";
21
24
  import OrderedListBase from "@tiptap/extension-ordered-list";
22
25
  import ParagraphBase from "@tiptap/extension-paragraph";
@@ -1132,10 +1135,153 @@ const Div = EmailNode.create({
1132
1135
  }
1133
1136
  });
1134
1137
 
1138
+ //#endregion
1139
+ //#region src/extensions/divider.tsx
1140
+ const Divider = EmailNode.from(HorizontalRule.extend({
1141
+ addAttributes() {
1142
+ return { class: { default: "divider" } };
1143
+ },
1144
+ addInputRules() {
1145
+ return [new InputRule({
1146
+ find: /^(?:---|—-|___\s|\*\*\*\s)$/,
1147
+ handler: ({ state, range }) => {
1148
+ const attributes = {};
1149
+ const { tr } = state;
1150
+ const start = range.from;
1151
+ const end = range.to;
1152
+ tr.insert(start - 1, this.type.create(attributes)).delete(tr.mapping.map(start), tr.mapping.map(end));
1153
+ }
1154
+ })];
1155
+ },
1156
+ addNodeView() {
1157
+ return ReactNodeViewRenderer((props) => {
1158
+ const node = props.node;
1159
+ const { class: className, ...rest } = node.attrs;
1160
+ return /* @__PURE__ */ jsx(NodeViewWrapper, { children: /* @__PURE__ */ jsx(Hr, {
1161
+ ...rest,
1162
+ className: "node-hr",
1163
+ style: inlineCssToJs(node.attrs.style)
1164
+ }) });
1165
+ });
1166
+ }
1167
+ }), ({ node, style }) => {
1168
+ return /* @__PURE__ */ jsx(Hr, {
1169
+ className: node.attrs?.class || void 0,
1170
+ style: {
1171
+ ...style,
1172
+ ...inlineCssToJs(node.attrs?.style)
1173
+ }
1174
+ });
1175
+ });
1176
+
1177
+ //#endregion
1178
+ //#region src/extensions/global-content.ts
1179
+ const GLOBAL_CONTENT_NODE_TYPE = "globalContent";
1180
+ let cachedGlobalPosition = null;
1181
+ function findGlobalContentPositions(doc) {
1182
+ const positions = [];
1183
+ doc.descendants((node, position) => {
1184
+ if (node.type.name === GLOBAL_CONTENT_NODE_TYPE) positions.push(position);
1185
+ });
1186
+ return positions;
1187
+ }
1188
+ function getCachedGlobalContentPosition(doc) {
1189
+ if (cachedGlobalPosition != null) try {
1190
+ if (doc.nodeAt(cachedGlobalPosition)?.type.name === GLOBAL_CONTENT_NODE_TYPE) return cachedGlobalPosition;
1191
+ } catch {
1192
+ cachedGlobalPosition = null;
1193
+ }
1194
+ cachedGlobalPosition = findGlobalContentPositions(doc)[0] ?? null;
1195
+ return cachedGlobalPosition;
1196
+ }
1197
+ function getGlobalContent(key, editor) {
1198
+ const position = getCachedGlobalContentPosition(editor.state.doc);
1199
+ if (cachedGlobalPosition == null) return null;
1200
+ return editor.state.doc.nodeAt(position)?.attrs.data[key] ?? null;
1201
+ }
1202
+ const GlobalContent = Node$1.create({
1203
+ name: GLOBAL_CONTENT_NODE_TYPE,
1204
+ addOptions() {
1205
+ return {
1206
+ key: GLOBAL_CONTENT_NODE_TYPE,
1207
+ data: {}
1208
+ };
1209
+ },
1210
+ group: "block",
1211
+ selectable: false,
1212
+ draggable: false,
1213
+ atom: true,
1214
+ addAttributes() {
1215
+ return { data: { default: this.options.data } };
1216
+ },
1217
+ parseHTML() {
1218
+ return [{ tag: `div[data-type="${this.name}"]` }];
1219
+ },
1220
+ renderHTML({ HTMLAttributes }) {
1221
+ return ["div", mergeAttributes(HTMLAttributes, {
1222
+ "data-type": this.name,
1223
+ style: "width: 100%; height: 1px; visibility: hidden;"
1224
+ })];
1225
+ },
1226
+ addCommands() {
1227
+ return { setGlobalContent: (key, value) => ({ tr, dispatch }) => {
1228
+ const ensureGlobalPosition = () => {
1229
+ const positions = findGlobalContentPositions(tr.doc);
1230
+ for (let i = positions.length - 1; i > 0; i--) tr.delete(positions[i], positions[i] + 1);
1231
+ const pos = positions[0] ?? -1;
1232
+ if (pos >= 0) cachedGlobalPosition = pos;
1233
+ else {
1234
+ cachedGlobalPosition = 0;
1235
+ tr.insert(0, this.type.create());
1236
+ }
1237
+ };
1238
+ if (dispatch) {
1239
+ ensureGlobalPosition();
1240
+ if (cachedGlobalPosition == null) return false;
1241
+ tr.setNodeAttribute(cachedGlobalPosition, "data", {
1242
+ ...tr.doc.nodeAt(cachedGlobalPosition)?.attrs.data,
1243
+ [key]: value
1244
+ });
1245
+ }
1246
+ return true;
1247
+ } };
1248
+ }
1249
+ });
1250
+
1135
1251
  //#endregion
1136
1252
  //#region src/extensions/hard-break.tsx
1137
1253
  const HardBreak = EmailNode.from(HardBreakBase, () => /* @__PURE__ */ jsx("br", {}));
1138
1254
 
1255
+ //#endregion
1256
+ //#region src/extensions/heading.tsx
1257
+ const Heading = EmailNode.from(Heading$2.extend({ addNodeView() {
1258
+ return ReactNodeViewRenderer(({ node }) => {
1259
+ const level = node.attrs.level ?? 1;
1260
+ const { class: className, ...rest } = node.attrs;
1261
+ const attrs = {
1262
+ ...rest,
1263
+ className: `node-h${level} ${className}`,
1264
+ style: inlineCssToJs(node.attrs.style)
1265
+ };
1266
+ return /* @__PURE__ */ jsx(NodeViewWrapper, { children: /* @__PURE__ */ jsx(Heading$1, {
1267
+ as: `h${level}`,
1268
+ ...attrs,
1269
+ children: /* @__PURE__ */ jsx(NodeViewContent, {})
1270
+ }) });
1271
+ });
1272
+ } }), ({ children, node, style }) => {
1273
+ return /* @__PURE__ */ jsx(Heading$1, {
1274
+ as: `h${node.attrs?.level ?? 1}`,
1275
+ className: node.attrs?.class || void 0,
1276
+ style: {
1277
+ ...style,
1278
+ ...inlineCssToJs(node.attrs?.style),
1279
+ ...getTextAlignment(node.attrs?.align ?? node.attrs?.alignment)
1280
+ },
1281
+ children
1282
+ });
1283
+ });
1284
+
1139
1285
  //#endregion
1140
1286
  //#region src/extensions/italic.tsx
1141
1287
  const Italic = EmailMark.from(ItalicBase, ({ children, style }) => /* @__PURE__ */ jsx("em", {
@@ -1143,6 +1289,160 @@ const Italic = EmailMark.from(ItalicBase, ({ children, style }) => /* @__PURE__
1143
1289
  children
1144
1290
  }));
1145
1291
 
1292
+ //#endregion
1293
+ //#region src/extensions/preserved-style.tsx
1294
+ const PreservedStyle = EmailMark.create({
1295
+ name: "preservedStyle",
1296
+ addAttributes() {
1297
+ return { style: {
1298
+ default: null,
1299
+ parseHTML: (element) => element.getAttribute("style"),
1300
+ renderHTML: (attributes) => {
1301
+ if (!attributes.style) return {};
1302
+ return { style: attributes.style };
1303
+ }
1304
+ } };
1305
+ },
1306
+ parseHTML() {
1307
+ return [{
1308
+ tag: "span[style]",
1309
+ getAttrs: (element) => {
1310
+ if (typeof element === "string") return false;
1311
+ const style = element.getAttribute("style");
1312
+ if (style && hasPreservableStyles(style)) return { style };
1313
+ return false;
1314
+ }
1315
+ }];
1316
+ },
1317
+ renderHTML({ HTMLAttributes }) {
1318
+ return [
1319
+ "span",
1320
+ mergeAttributes(HTMLAttributes),
1321
+ 0
1322
+ ];
1323
+ },
1324
+ renderToReactEmail({ children, mark }) {
1325
+ return /* @__PURE__ */ jsx("span", {
1326
+ style: mark.attrs?.style ? inlineCssToJs(mark.attrs.style) : void 0,
1327
+ children
1328
+ });
1329
+ }
1330
+ });
1331
+ const LINK_INDICATOR_STYLES = [
1332
+ "color",
1333
+ "text-decoration",
1334
+ "text-decoration-line",
1335
+ "text-decoration-color",
1336
+ "text-decoration-style"
1337
+ ];
1338
+ function parseStyleString(styleString) {
1339
+ const temp = document.createElement("div");
1340
+ temp.style.cssText = styleString;
1341
+ return temp.style;
1342
+ }
1343
+ function hasBackground(style) {
1344
+ const bgColor = style.backgroundColor;
1345
+ const bg = style.background;
1346
+ if (bgColor && bgColor !== "transparent" && bgColor !== "rgba(0, 0, 0, 0)") return true;
1347
+ if (bg && bg !== "transparent" && bg !== "none" && bg !== "rgba(0, 0, 0, 0)") return true;
1348
+ return false;
1349
+ }
1350
+ function hasPreservableStyles(styleString) {
1351
+ return processStylesForUnlink(styleString) !== null;
1352
+ }
1353
+ /**
1354
+ * Processes styles when unlinking:
1355
+ * - Has background (button-like): preserve all styles
1356
+ * - No background: strip link-indicator styles (color, text-decoration), keep the rest
1357
+ */
1358
+ function processStylesForUnlink(styleString) {
1359
+ if (!styleString) return null;
1360
+ const style = parseStyleString(styleString);
1361
+ if (hasBackground(style)) return styleString;
1362
+ const filtered = [];
1363
+ for (let i = 0; i < style.length; i++) {
1364
+ const prop = style[i];
1365
+ if (LINK_INDICATOR_STYLES.includes(prop)) continue;
1366
+ const value = style.getPropertyValue(prop);
1367
+ if (value) filtered.push(`${prop}: ${value}`);
1368
+ }
1369
+ return filtered.length > 0 ? filtered.join("; ") : null;
1370
+ }
1371
+
1372
+ //#endregion
1373
+ //#region src/extensions/link.tsx
1374
+ const Link = EmailMark.from(TiptapLink, ({ children, mark, style }) => {
1375
+ const linkMarkStyle = mark.attrs?.style ? inlineCssToJs(mark.attrs.style) : {};
1376
+ return /* @__PURE__ */ jsx(Link$1, {
1377
+ href: mark.attrs?.href ?? void 0,
1378
+ rel: mark.attrs?.rel ?? void 0,
1379
+ style: {
1380
+ ...style,
1381
+ ...linkMarkStyle
1382
+ },
1383
+ target: mark.attrs?.target ?? void 0,
1384
+ ...mark.attrs?.["ses:no-track"] ? { "ses:no-track": mark.attrs["ses:no-track"] } : {},
1385
+ children
1386
+ });
1387
+ }).extend({
1388
+ parseHTML() {
1389
+ return [{
1390
+ tag: "a[target]:not([data-id=\"react-email-button\"])",
1391
+ getAttrs: (node) => {
1392
+ if (typeof node === "string") return false;
1393
+ const element = node;
1394
+ const attrs = {};
1395
+ Array.from(element.attributes).forEach((attr) => {
1396
+ attrs[attr.name] = attr.value;
1397
+ });
1398
+ return attrs;
1399
+ }
1400
+ }, {
1401
+ tag: "a[href]:not([data-id=\"react-email-button\"])",
1402
+ getAttrs: (node) => {
1403
+ if (typeof node === "string") return false;
1404
+ const element = node;
1405
+ const attrs = {};
1406
+ Array.from(element.attributes).forEach((attr) => {
1407
+ attrs[attr.name] = attr.value;
1408
+ });
1409
+ return attrs;
1410
+ }
1411
+ }];
1412
+ },
1413
+ addAttributes() {
1414
+ return {
1415
+ ...this.parent?.(),
1416
+ "ses:no-track": {
1417
+ default: null,
1418
+ parseHTML: (element) => element.getAttribute("ses:no-track")
1419
+ }
1420
+ };
1421
+ },
1422
+ addCommands() {
1423
+ return {
1424
+ ...this.parent?.(),
1425
+ unsetLink: () => ({ state, chain }) => {
1426
+ const { from } = state.selection;
1427
+ const linkStyle = state.doc.resolve(from).marks().find((m) => m.type.name === "link")?.attrs?.style ?? null;
1428
+ const preservedStyle = processStylesForUnlink(linkStyle);
1429
+ const shouldRemoveUnderline = preservedStyle !== linkStyle;
1430
+ if (preservedStyle) {
1431
+ const cmd = chain().extendMarkRange("link").unsetMark("link").setMark("preservedStyle", { style: preservedStyle });
1432
+ return shouldRemoveUnderline ? cmd.unsetMark("underline").run() : cmd.run();
1433
+ }
1434
+ return chain().extendMarkRange("link").unsetMark("link").unsetMark("underline").run();
1435
+ }
1436
+ };
1437
+ },
1438
+ addKeyboardShortcuts() {
1439
+ return { "Mod-k": () => {
1440
+ editorEventBus.dispatch("bubble-menu:add-link", void 0);
1441
+ return this.editor.chain().focus().toggleLink({ href: "" }).run();
1442
+ } };
1443
+ }
1444
+ });
1445
+
1146
1446
  //#endregion
1147
1447
  //#region src/extensions/list-item.tsx
1148
1448
  const ListItem = EmailNode.from(ListItemBase, ({ children, node, style }) => /* @__PURE__ */ jsx("li", {
@@ -1267,86 +1567,6 @@ const Placeholder = TipTapPlaceholder.configure({
1267
1567
  includeChildren: true
1268
1568
  });
1269
1569
 
1270
- //#endregion
1271
- //#region src/extensions/preserved-style.tsx
1272
- const PreservedStyle = EmailMark.create({
1273
- name: "preservedStyle",
1274
- addAttributes() {
1275
- return { style: {
1276
- default: null,
1277
- parseHTML: (element) => element.getAttribute("style"),
1278
- renderHTML: (attributes) => {
1279
- if (!attributes.style) return {};
1280
- return { style: attributes.style };
1281
- }
1282
- } };
1283
- },
1284
- parseHTML() {
1285
- return [{
1286
- tag: "span[style]",
1287
- getAttrs: (element) => {
1288
- if (typeof element === "string") return false;
1289
- const style = element.getAttribute("style");
1290
- if (style && hasPreservableStyles(style)) return { style };
1291
- return false;
1292
- }
1293
- }];
1294
- },
1295
- renderHTML({ HTMLAttributes }) {
1296
- return [
1297
- "span",
1298
- mergeAttributes(HTMLAttributes),
1299
- 0
1300
- ];
1301
- },
1302
- renderToReactEmail({ children, mark }) {
1303
- return /* @__PURE__ */ jsx("span", {
1304
- style: mark.attrs?.style ? inlineCssToJs(mark.attrs.style) : void 0,
1305
- children
1306
- });
1307
- }
1308
- });
1309
- const LINK_INDICATOR_STYLES = [
1310
- "color",
1311
- "text-decoration",
1312
- "text-decoration-line",
1313
- "text-decoration-color",
1314
- "text-decoration-style"
1315
- ];
1316
- function parseStyleString(styleString) {
1317
- const temp = document.createElement("div");
1318
- temp.style.cssText = styleString;
1319
- return temp.style;
1320
- }
1321
- function hasBackground(style) {
1322
- const bgColor = style.backgroundColor;
1323
- const bg = style.background;
1324
- if (bgColor && bgColor !== "transparent" && bgColor !== "rgba(0, 0, 0, 0)") return true;
1325
- if (bg && bg !== "transparent" && bg !== "none" && bg !== "rgba(0, 0, 0, 0)") return true;
1326
- return false;
1327
- }
1328
- function hasPreservableStyles(styleString) {
1329
- return processStylesForUnlink(styleString) !== null;
1330
- }
1331
- /**
1332
- * Processes styles when unlinking:
1333
- * - Has background (button-like): preserve all styles
1334
- * - No background: strip link-indicator styles (color, text-decoration), keep the rest
1335
- */
1336
- function processStylesForUnlink(styleString) {
1337
- if (!styleString) return null;
1338
- const style = parseStyleString(styleString);
1339
- if (hasBackground(style)) return styleString;
1340
- const filtered = [];
1341
- for (let i = 0; i < style.length; i++) {
1342
- const prop = style[i];
1343
- if (LINK_INDICATOR_STYLES.includes(prop)) continue;
1344
- const value = style.getPropertyValue(prop);
1345
- if (value) filtered.push(`${prop}: ${value}`);
1346
- }
1347
- return filtered.length > 0 ? filtered.join("; ") : null;
1348
- }
1349
-
1350
1570
  //#endregion
1351
1571
  //#region src/extensions/preview-text.ts
1352
1572
  const PreviewText = Node$1.create({
@@ -1938,44 +2158,13 @@ const ColumnsColumn = EmailNode.create({
1938
2158
 
1939
2159
  //#endregion
1940
2160
  //#region src/extensions/index.ts
1941
- const coreExtensions = [
1942
- StarterKit.configure({
1943
- undoRedo: false,
1944
- heading: false,
1945
- link: false,
1946
- underline: false,
1947
- trailingNode: false,
1948
- bold: false,
1949
- italic: false,
1950
- strike: false,
1951
- code: false,
1952
- paragraph: false,
1953
- bulletList: false,
1954
- orderedList: false,
1955
- listItem: false,
1956
- blockquote: false,
1957
- hardBreak: false,
1958
- gapcursor: false,
1959
- codeBlock: false,
1960
- horizontalRule: false,
1961
- dropcursor: {
1962
- color: "#61a8f8",
1963
- class: "rounded-full animate-[fade-in_300ms_ease-in-out] !z-40",
1964
- width: 4
1965
- }
1966
- }),
1967
- CodeBlockPrism.configure({
1968
- defaultLanguage: "javascript",
1969
- HTMLAttributes: { class: "prism node-codeBlock" }
1970
- }),
1971
- Code.configure({ HTMLAttributes: {
1972
- class: "node-inlineCode",
1973
- spellcheck: "false"
1974
- } }),
1975
- Paragraph.configure({ HTMLAttributes: { class: "node-paragraph" } }),
1976
- BulletList.configure({ HTMLAttributes: { class: "node-bulletList" } }),
1977
- OrderedList.configure({ HTMLAttributes: { class: "node-orderedList" } }),
1978
- Blockquote.configure({ HTMLAttributes: { class: "node-blockquote" } }),
2161
+ const starterKitExtensions = {
2162
+ CodeBlockPrism,
2163
+ Code,
2164
+ Paragraph,
2165
+ BulletList,
2166
+ OrderedList,
2167
+ Blockquote,
1979
2168
  ListItem,
1980
2169
  HardBreak,
1981
2170
  Italic,
@@ -1983,6 +2172,9 @@ const coreExtensions = [
1983
2172
  PreviewText,
1984
2173
  Bold,
1985
2174
  Strike,
2175
+ Heading,
2176
+ Divider,
2177
+ Link,
1986
2178
  Sup,
1987
2179
  Uppercase,
1988
2180
  PreservedStyle,
@@ -1994,80 +2186,162 @@ const coreExtensions = [
1994
2186
  Div,
1995
2187
  Button,
1996
2188
  Section,
1997
- AlignmentAttribute.configure({ types: [
1998
- "heading",
1999
- "paragraph",
2000
- "image",
2001
- "blockquote",
2002
- "codeBlock",
2003
- "bulletList",
2004
- "orderedList",
2005
- "listItem",
2006
- "button",
2007
- "youtube",
2008
- "twitter",
2009
- "table",
2010
- "tableRow",
2011
- "tableCell",
2012
- "tableHeader",
2013
- "columnsColumn"
2014
- ] }),
2015
- StyleAttribute.configure({ types: [
2016
- "heading",
2017
- "paragraph",
2018
- "image",
2019
- "blockquote",
2020
- "codeBlock",
2021
- "bulletList",
2022
- "orderedList",
2023
- "listItem",
2024
- "button",
2025
- "youtube",
2026
- "twitter",
2027
- "horizontalRule",
2028
- "footer",
2029
- "section",
2030
- "div",
2031
- "body",
2032
- "table",
2033
- "tableRow",
2034
- "tableCell",
2035
- "tableHeader",
2036
- "columnsColumn",
2037
- "link"
2038
- ] }),
2039
- ClassAttribute.configure({ types: [
2040
- "heading",
2041
- "paragraph",
2042
- "image",
2043
- "blockquote",
2044
- "bulletList",
2045
- "orderedList",
2046
- "listItem",
2047
- "button",
2048
- "youtube",
2049
- "twitter",
2050
- "horizontalRule",
2051
- "footer",
2052
- "section",
2053
- "div",
2054
- "body",
2055
- "table",
2056
- "tableRow",
2057
- "tableCell",
2058
- "tableHeader",
2059
- "columnsColumn",
2060
- "link"
2061
- ] }),
2062
- MaxNesting.configure({
2063
- maxDepth: 50,
2064
- nodeTypes: [
2065
- "section",
2066
- "bulletList",
2067
- "orderedList"
2068
- ]
2069
- })
2070
- ];
2189
+ GlobalContent,
2190
+ AlignmentAttribute,
2191
+ StyleAttribute,
2192
+ ClassAttribute,
2193
+ MaxNesting
2194
+ };
2195
+ const StarterKit = Extension.create({
2196
+ name: "reactEmailStarterKit",
2197
+ addOptions() {
2198
+ return {
2199
+ TiptapStarterKit: {},
2200
+ CodeBlockPrism: {
2201
+ defaultLanguage: "javascript",
2202
+ HTMLAttributes: { class: "prism node-codeBlock" }
2203
+ },
2204
+ Code: { HTMLAttributes: {
2205
+ class: "node-inlineCode",
2206
+ spellcheck: "false"
2207
+ } },
2208
+ Paragraph: { HTMLAttributes: { class: "node-paragraph" } },
2209
+ BulletList: { HTMLAttributes: { class: "node-bulletList" } },
2210
+ OrderedList: { HTMLAttributes: { class: "node-orderedList" } },
2211
+ Blockquote: { HTMLAttributes: { class: "node-blockquote" } },
2212
+ ListItem: {},
2213
+ HardBreak: {},
2214
+ Italic: {},
2215
+ Placeholder: {},
2216
+ PreviewText: {},
2217
+ Bold: {},
2218
+ Strike: {},
2219
+ Heading: {},
2220
+ Divider: {},
2221
+ Link: {},
2222
+ Sup: {},
2223
+ Uppercase: {},
2224
+ PreservedStyle: {},
2225
+ Table: {},
2226
+ TableRow: {},
2227
+ TableCell: {},
2228
+ TableHeader: {},
2229
+ Body: {},
2230
+ Div: {},
2231
+ Button: {},
2232
+ Section: {},
2233
+ GlobalContent: {},
2234
+ AlignmentAttribute: { types: [
2235
+ "heading",
2236
+ "paragraph",
2237
+ "image",
2238
+ "blockquote",
2239
+ "codeBlock",
2240
+ "bulletList",
2241
+ "orderedList",
2242
+ "listItem",
2243
+ "button",
2244
+ "youtube",
2245
+ "twitter",
2246
+ "table",
2247
+ "tableRow",
2248
+ "tableCell",
2249
+ "tableHeader",
2250
+ "columnsColumn"
2251
+ ] },
2252
+ StyleAttribute: { types: [
2253
+ "heading",
2254
+ "paragraph",
2255
+ "image",
2256
+ "blockquote",
2257
+ "codeBlock",
2258
+ "bulletList",
2259
+ "orderedList",
2260
+ "listItem",
2261
+ "button",
2262
+ "youtube",
2263
+ "twitter",
2264
+ "horizontalRule",
2265
+ "footer",
2266
+ "section",
2267
+ "div",
2268
+ "body",
2269
+ "table",
2270
+ "tableRow",
2271
+ "tableCell",
2272
+ "tableHeader",
2273
+ "columnsColumn",
2274
+ "link"
2275
+ ] },
2276
+ ClassAttribute: { types: [
2277
+ "heading",
2278
+ "paragraph",
2279
+ "image",
2280
+ "blockquote",
2281
+ "bulletList",
2282
+ "orderedList",
2283
+ "listItem",
2284
+ "button",
2285
+ "youtube",
2286
+ "twitter",
2287
+ "horizontalRule",
2288
+ "footer",
2289
+ "section",
2290
+ "div",
2291
+ "body",
2292
+ "table",
2293
+ "tableRow",
2294
+ "tableCell",
2295
+ "tableHeader",
2296
+ "columnsColumn",
2297
+ "link"
2298
+ ] },
2299
+ MaxNesting: {
2300
+ maxDepth: 50,
2301
+ nodeTypes: [
2302
+ "section",
2303
+ "bulletList",
2304
+ "orderedList"
2305
+ ]
2306
+ }
2307
+ };
2308
+ },
2309
+ addExtensions() {
2310
+ const extensions = [];
2311
+ if (this.options.TiptapStarterKit !== false) extensions.push(TipTapStarterKit.configure({
2312
+ undoRedo: false,
2313
+ heading: false,
2314
+ link: false,
2315
+ underline: false,
2316
+ trailingNode: false,
2317
+ bold: false,
2318
+ italic: false,
2319
+ strike: false,
2320
+ code: false,
2321
+ paragraph: false,
2322
+ bulletList: false,
2323
+ orderedList: false,
2324
+ listItem: false,
2325
+ blockquote: false,
2326
+ hardBreak: false,
2327
+ gapcursor: false,
2328
+ codeBlock: false,
2329
+ horizontalRule: false,
2330
+ dropcursor: {
2331
+ color: "#61a8f8",
2332
+ class: "rounded-full animate-[fade-in_300ms_ease-in-out] !z-40",
2333
+ width: 4
2334
+ },
2335
+ ...this.options.TiptapStarterKit
2336
+ }));
2337
+ for (const [name, extension] of Object.entries(starterKitExtensions)) {
2338
+ const key = name;
2339
+ const extensionOptions = this.options[key];
2340
+ if (extensionOptions !== false) extensions.push(extension.configure(extensionOptions));
2341
+ }
2342
+ return extensions;
2343
+ }
2344
+ });
2071
2345
 
2072
2346
  //#endregion
2073
2347
  //#region src/core/create-drop-handler.ts
@@ -2226,13 +2500,14 @@ function useEditor({ content, extensions = [], onUpdate, onPaste, onUploadImage,
2226
2500
  const [contentError, setContentError] = React.useState(null);
2227
2501
  const isCollaborative = hasCollaborationExtension(extensions);
2228
2502
  const effectiveExtensions = React.useMemo(() => [
2229
- ...coreExtensions,
2503
+ StarterKit,
2230
2504
  ...isCollaborative ? [] : [UndoRedo],
2231
2505
  ...extensions
2232
2506
  ], [extensions, isCollaborative]);
2233
2507
  const editor = useEditor$1({
2234
2508
  content: isCollaborative ? void 0 : content,
2235
2509
  extensions: effectiveExtensions,
2510
+ editable,
2236
2511
  immediatelyRender: false,
2237
2512
  enableContentCheck: true,
2238
2513
  onContentError({ editor: editor$1, error, disableCollaboration }) {
@@ -3846,5 +4121,5 @@ function createSlashCommand(options) {
3846
4121
  const SlashCommand = createSlashCommand();
3847
4122
 
3848
4123
  //#endregion
3849
- export { AlignmentAttribute, BULLET_LIST, BUTTON, Blockquote, Body, Bold, BubbleMenu, BubbleMenuAlignCenter, BubbleMenuAlignLeft, BubbleMenuAlignRight, BubbleMenuBold, BubbleMenuCode, BubbleMenuDefault, BubbleMenuItalic, BubbleMenuItem, BubbleMenuItemGroup, BubbleMenuLinkSelector, BubbleMenuNodeSelector, BubbleMenuRoot, BubbleMenuSeparator, BubbleMenuStrike, BubbleMenuUnderline, BubbleMenuUppercase, BulletList, Button, ButtonBubbleMenu, ButtonBubbleMenuDefault, ButtonBubbleMenuEditLink, ButtonBubbleMenuRoot, ButtonBubbleMenuToolbar, CODE, COLUMN_PARENT_TYPES, ClassAttribute, Code, CodeBlockPrism, ColumnsColumn, CommandList, DIVIDER, Div, EmailNode, FOUR_COLUMNS, FourColumns, H1, H2, H3, HardBreak, ImageBubbleMenu, ImageBubbleMenuDefault, ImageBubbleMenuEditLink, ImageBubbleMenuRoot, ImageBubbleMenuToolbar, Italic, LinkBubbleMenu, LinkBubbleMenuDefault, LinkBubbleMenuEditLink, LinkBubbleMenuForm, LinkBubbleMenuOpenLink, LinkBubbleMenuRoot, LinkBubbleMenuToolbar, LinkBubbleMenuUnlink, ListItem, MAX_COLUMNS_DEPTH, MaxNesting, NUMBERED_LIST, NodeSelectorContent, NodeSelectorRoot, NodeSelectorTrigger, OrderedList, Paragraph, Placeholder, PreservedStyle, PreviewText, QUOTE, SECTION, Section, SlashCommand, Strike, StyleAttribute, Sup, TEXT, THREE_COLUMNS, TWO_COLUMNS, Table, TableCell, TableHeader, TableRow, ThreeColumns, TwoColumns, Uppercase, composeReactEmail, coreExtensions, createSlashCommand, defaultSlashCommands, editorEventBus, filterAndRankItems, getColumnsDepth, isAtMaxColumnsDepth, isInsideNode, processStylesForUnlink, scoreItem, setTextAlignment, useButtonBubbleMenuContext, useEditor, useImageBubbleMenuContext, useLinkBubbleMenuContext };
4124
+ export { AlignmentAttribute, BULLET_LIST, BUTTON, Blockquote, Body, Bold, BubbleMenu, BubbleMenuAlignCenter, BubbleMenuAlignLeft, BubbleMenuAlignRight, BubbleMenuBold, BubbleMenuCode, BubbleMenuDefault, BubbleMenuItalic, BubbleMenuItem, BubbleMenuItemGroup, BubbleMenuLinkSelector, BubbleMenuNodeSelector, BubbleMenuRoot, BubbleMenuSeparator, BubbleMenuStrike, BubbleMenuUnderline, BubbleMenuUppercase, BulletList, Button, ButtonBubbleMenu, ButtonBubbleMenuDefault, ButtonBubbleMenuEditLink, ButtonBubbleMenuRoot, ButtonBubbleMenuToolbar, CODE, COLUMN_PARENT_TYPES, ClassAttribute, Code, CodeBlockPrism, ColumnsColumn, CommandList, DIVIDER, Div, Divider, EmailNode, FOUR_COLUMNS, FourColumns, GlobalContent, H1, H2, H3, HardBreak, Heading, ImageBubbleMenu, ImageBubbleMenuDefault, ImageBubbleMenuEditLink, ImageBubbleMenuRoot, ImageBubbleMenuToolbar, Italic, Link, LinkBubbleMenu, LinkBubbleMenuDefault, LinkBubbleMenuEditLink, LinkBubbleMenuForm, LinkBubbleMenuOpenLink, LinkBubbleMenuRoot, LinkBubbleMenuToolbar, LinkBubbleMenuUnlink, ListItem, MAX_COLUMNS_DEPTH, MaxNesting, NUMBERED_LIST, NodeSelectorContent, NodeSelectorRoot, NodeSelectorTrigger, OrderedList, Paragraph, Placeholder, PreservedStyle, PreviewText, QUOTE, SECTION, Section, SlashCommand, StarterKit, Strike, StyleAttribute, Sup, TEXT, THREE_COLUMNS, TWO_COLUMNS, Table, TableCell, TableHeader, TableRow, ThreeColumns, TwoColumns, Uppercase, composeReactEmail, createSlashCommand, defaultSlashCommands, editorEventBus, filterAndRankItems, getColumnsDepth, getGlobalContent, isAtMaxColumnsDepth, isInsideNode, processStylesForUnlink, scoreItem, setTextAlignment, useButtonBubbleMenuContext, useEditor, useImageBubbleMenuContext, useLinkBubbleMenuContext };
3850
4125
  //# sourceMappingURL=index.mjs.map