@mdxeditor/editor 2.5.0 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,6 +10,7 @@ The component supports the core markdown syntax and certain extensions, includin
10
10
 
11
11
  ```jsx
12
12
  import {MDXEditor, headingsPlugin} from '@mdxeditor/editor';
13
+ import '@mdxeditor/editor/style.css';
13
14
 
14
15
  export default function App() {
15
16
  return <MDXEditor markdown={'# Hello World'} plugins={[headingsPlugin()]} />;
@@ -21,7 +22,11 @@ The best place to get started using the component is the [documentation](https:/
21
22
 
22
23
  ## Help and support
23
24
 
24
- Should you encounter any issues, please [create an issue](https://github.com/mdx-editor/editor/issues), but check if there's something similar already open first.
25
+ If you find a bug, check if something similar is not reported already in the [issues](https://github.com/mdx-editor/editor/issues). If not, [create a new issue](https://github.com/mdx-editor/editor/issues/new?assignees=&labels=bug&projects=&template=1.bug.md&title=%5BBUG%5D).
26
+
27
+ If you're integrating the component in your commercial project and need dedicated assistance with your issues in exchange of sponsorship, [contact me over email](mailto:petyo@mdxeditor.dev).
28
+
29
+ If you want to discuss ideas [join the Discord server](https://discord.gg/4q7U2Hc) or start a discussion in the [Discussions](https://github.com/mdx-editor/editor/discussions) section.
25
30
 
26
31
  ## License
27
32
 
package/dist/MDXEditor.js CHANGED
@@ -37,7 +37,7 @@ const RichTextEditor = () => {
37
37
  editorWrappers$,
38
38
  placeholder$
39
39
  );
40
- return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, topAreaChildren.map((Child, index) => /* @__PURE__ */ React__default.createElement(Child, { key: index })), /* @__PURE__ */ React__default.createElement(RenderRecursiveWrappers, { wrappers: editorWrappers }, /* @__PURE__ */ React__default.createElement("div", { className: classNames(styles.rootContentEditableWrapper) }, /* @__PURE__ */ React__default.createElement(
40
+ return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, topAreaChildren.map((Child, index) => /* @__PURE__ */ React__default.createElement(Child, { key: index })), /* @__PURE__ */ React__default.createElement(RenderRecursiveWrappers, { wrappers: editorWrappers }, /* @__PURE__ */ React__default.createElement("div", { className: (classNames(styles.rootContentEditableWrapper), "mdxeditor-root-contenteditable") }, /* @__PURE__ */ React__default.createElement(
41
41
  RichTextPlugin,
42
42
  {
43
43
  contentEditable: /* @__PURE__ */ React__default.createElement(ContentEditable, { className: classNames(styles.contentEditable, contentEditableClassName) }),
@@ -71,13 +71,12 @@ const EditorRootElement = ({ children, className }) => {
71
71
  const setEditorRootElementRef = usePublisher(editorRootElementRef$);
72
72
  React__default.useEffect(() => {
73
73
  const popupContainer = document.createElement("div");
74
- popupContainer.classList.add(styles.editorRoot);
75
- popupContainer.classList.add(styles.popupContainer);
76
- if (className) {
77
- className.trim().split(" ").forEach((c) => {
78
- popupContainer.classList.add(c);
79
- });
80
- }
74
+ popupContainer.classList.add(
75
+ "mdxeditor-popup-container",
76
+ styles.editorRoot,
77
+ styles.popupContainer,
78
+ ...(className ?? "").trim().split(" ").filter(Boolean)
79
+ );
81
80
  document.body.appendChild(popupContainer);
82
81
  editorRootElementRef.current = popupContainer;
83
82
  setEditorRootElementRef(editorRootElementRef);
@@ -85,7 +84,7 @@ const EditorRootElement = ({ children, className }) => {
85
84
  popupContainer.remove();
86
85
  };
87
86
  }, [className, editorRootElementRef, setEditorRootElementRef]);
88
- return /* @__PURE__ */ React__default.createElement("div", { className: classNames(styles.editorRoot, styles.editorWrapper, className, "mdxeditor") }, children);
87
+ return /* @__PURE__ */ React__default.createElement("div", { className: classNames("mdxeditor", styles.editorRoot, styles.editorWrapper, className) }, children);
89
88
  };
90
89
  const Methods = ({ mdxRef }) => {
91
90
  const realm = useRealm();
package/dist/index.d.ts CHANGED
@@ -476,10 +476,6 @@ export declare interface CodeBlockEditorProps {
476
476
  * Note: you don't need to unsubscribe, the emiter has a single subscription model.
477
477
  */
478
478
  focusEmitter: VoidEmitter;
479
- /**
480
- * The theme CodeMirrorEditor used.
481
- */
482
- theme: SandpackThemeProp;
483
479
  }
484
480
 
485
481
  /**
@@ -537,13 +533,9 @@ export declare const codeBlockPlugin: (params?: {
537
533
  * The default language to use when creating a new code block if no language is passed.
538
534
  */
539
535
  defaultCodeBlockLanguage?: string | undefined;
540
- /**
541
- * The theme of CodeMirrorEditor
542
- */
543
- theme?: SandpackThemeProp | undefined;
544
536
  } | undefined) => RealmPlugin;
545
537
 
546
- export declare const CodeMirrorEditor: ({ language, nodeKey, code, focusEmitter, theme }: CodeBlockEditorProps) => React_2.JSX.Element;
538
+ export declare const CodeMirrorEditor: ({ language, nodeKey, code, focusEmitter }: CodeBlockEditorProps) => React_2.JSX.Element;
547
539
 
548
540
  /**
549
541
  * A plugin that adds lets users edit code blocks with CodeMirror.
@@ -551,8 +543,21 @@ export declare const CodeMirrorEditor: ({ language, nodeKey, code, focusEmitter,
551
543
  */
552
544
  export declare const codeMirrorPlugin: (params?: {
553
545
  codeBlockLanguages: Record<string, string>;
546
+ /**
547
+ * The theme of CodeMirrorEditor
548
+ */
549
+ theme?: SandpackThemeProp | undefined;
554
550
  } | undefined) => RealmPlugin;
555
551
 
552
+ /**
553
+ * The theme CodeMirrorEditor used.
554
+ * It can be "light" | "dark" | "auto",
555
+ * or the theme in "@codesandbox/sandpack-themes" package,
556
+ * or you can also custom one,
557
+ * learn more https://sandpack.codesandbox.io/docs/getting-started/themes#custom-theme
558
+ */
559
+ export declare const codeMirrorTheme$: NodeRef<SandpackThemeProp>;
560
+
556
561
  /**
557
562
  * A toolbar component that lets the user toggle code formatting.
558
563
  * Use for inline `code` elements (like variables, methods, etc).
@@ -1756,6 +1761,17 @@ export declare const markdownShortcutPlugin: (params?: unknown) => RealmPlugin;
1756
1761
  */
1757
1762
  export declare const markdownSourceEditorValue$: NodeRef<string>;
1758
1763
 
1764
+ /**
1765
+ * A plugin that limits the maximum length of the text content of the editor.
1766
+ * Adapted from the Lexical plugin. https://github.com/facebook/lexical/blob/main/packages/lexical-playground/src/plugins/MaxLengthPlugin/index.tsx
1767
+ * @example
1768
+ * ```tsx
1769
+ * <MDXEditor plugins={[maxLengthPlugin(100)]} markdown={'hello world'} />
1770
+ * ```
1771
+ * @group Utilities
1772
+ */
1773
+ export declare const maxLengthPlugin: (params?: number | undefined) => RealmPlugin;
1774
+
1759
1775
  /**
1760
1776
  * A block-level HTML node.
1761
1777
  * @group HTML
@@ -2506,15 +2522,6 @@ export declare function tap<T>(arg: T, proc: (arg: T) => unknown): T;
2506
2522
  */
2507
2523
  export declare const thematicBreakPlugin: (params?: unknown) => RealmPlugin;
2508
2524
 
2509
- /**
2510
- * The theme CodeMirrorEditor used.
2511
- * It can be "light" | "dark" | "auto",
2512
- * or the theme in "@codesandbox/sandpack-themes" package,
2513
- * or you can also custom one,
2514
- * learn more https://sandpack.codesandbox.io/docs/getting-started/themes#custom-theme
2515
- */
2516
- export declare const theme$: NodeRef<SandpackThemeProp>;
2517
-
2518
2525
  /**
2519
2526
  * Takes a value and applies a function to it.
2520
2527
  * @group Utils
package/dist/index.js CHANGED
@@ -12,12 +12,13 @@ import { disableAutoLink$, linkPlugin } from "./plugins/link/index.js";
12
12
  import { INSERT_IMAGE_COMMAND, closeImageDialog$, disableImageResize$, imageAutocompleteSuggestions$, imageDialogState$, imagePlugin, imagePreviewHandler$, imageUploadHandler$, insertImage$, openEditImageDialog$, openNewImageDialog$, saveImage$ } from "./plugins/image/index.js";
13
13
  import { frontmatterDialogOpen$, frontmatterPlugin, hasFrontmatter$, insertFrontmatter$, removeFrontmatter$ } from "./plugins/frontmatter/index.js";
14
14
  import { quotePlugin } from "./plugins/quote/index.js";
15
+ import { maxLengthPlugin } from "./plugins/maxlength/index.js";
15
16
  import { insertJsx$, isMdastJsxNode, jsxPlugin } from "./plugins/jsx/index.js";
16
17
  import { GenericJsxEditor } from "./jsx-editors/GenericJsxEditor.js";
17
18
  import { insertSandpack$, sandpackConfig$, sandpackPlugin } from "./plugins/sandpack/index.js";
18
- import { codeBlockLanguages$, codeMirrorPlugin, insertCodeMirror$ } from "./plugins/codemirror/index.js";
19
+ import { codeBlockLanguages$, codeMirrorPlugin, codeMirrorTheme$, insertCodeMirror$ } from "./plugins/codemirror/index.js";
19
20
  import { CodeMirrorEditor } from "./plugins/codemirror/CodeMirrorEditor.js";
20
- import { appendCodeBlockEditorDescriptor$, codeBlockPlugin, defaultCodeBlockLanguage$, insertCodeBlock$, theme$ } from "./plugins/codeblock/index.js";
21
+ import { appendCodeBlockEditorDescriptor$, codeBlockPlugin, defaultCodeBlockLanguage$, insertCodeBlock$ } from "./plugins/codeblock/index.js";
21
22
  import { directivesPlugin, insertDirective$ } from "./plugins/directives/index.js";
22
23
  import { ADMONITION_TYPES, AdmonitionDirectiveDescriptor } from "./directive-editors/AdmonitionDirectiveDescriptor.js";
23
24
  import { GenericDirectiveEditor } from "./directive-editors/GenericDirectiveEditor.js";
@@ -164,6 +165,7 @@ export {
164
165
  codeBlockLanguages$,
165
166
  codeBlockPlugin,
166
167
  codeMirrorPlugin,
168
+ codeMirrorTheme$,
167
169
  compose,
168
170
  composerChildren$,
169
171
  contentEditableClassName$,
@@ -242,6 +244,7 @@ export {
242
244
  markdownProcessingError$,
243
245
  markdownShortcutPlugin,
244
246
  markdownSourceEditorValue$,
247
+ maxLengthPlugin,
245
248
  mdastExtensions$,
246
249
  nestedEditorChildren$,
247
250
  noop,
@@ -269,7 +272,6 @@ export {
269
272
  tablePlugin,
270
273
  tap,
271
274
  thematicBreakPlugin,
272
- theme$,
273
275
  thrush,
274
276
  toMarkdownExtensions$,
275
277
  toMarkdownOptions$,
@@ -7,7 +7,6 @@ var __publicField = (obj, key, value) => {
7
7
  import { useCellValue } from "@mdxeditor/gurx";
8
8
  import { DecoratorNode } from "lexical";
9
9
  import React__default from "react";
10
- import { theme$ } from "./index.js";
11
10
  import { voidEmitter } from "../../utils/voidEmitter.js";
12
11
  import { codeBlockEditorDescriptors$, NESTED_EDITOR_UPDATED_COMMAND } from "../core/index.js";
13
12
  class CodeBlockNode extends DecoratorNode {
@@ -88,8 +87,7 @@ class CodeBlockNode extends DecoratorNode {
88
87
  language: this.getLanguage(),
89
88
  codeBlockNode: this,
90
89
  nodeKey: this.getKey(),
91
- focusEmitter: this.__focusEmitter,
92
- theme: "auto"
90
+ focusEmitter: this.__focusEmitter
93
91
  }
94
92
  );
95
93
  }
@@ -142,7 +140,6 @@ const CodeBlockEditorContainer = (props) => {
142
140
  }
143
141
  const Editor = descriptor.Editor;
144
142
  const { codeBlockNode: _, parentEditor: __, ...restProps } = props;
145
- restProps.theme = useCellValue(theme$);
146
143
  return /* @__PURE__ */ React__default.createElement(CodeBlockEditorContextProvider, { parentEditor: props.parentEditor, lexicalNode: props.codeBlockNode }, /* @__PURE__ */ React__default.createElement(Editor, { ...restProps }));
147
144
  };
148
145
  function $createCodeBlockNode(options) {
@@ -6,7 +6,6 @@ import { $isCodeBlockNode, useCodeBlockEditorContext } from "./CodeBlockNode.js"
6
6
  import { Cell, Signal, withLatestFrom, map } from "@mdxeditor/gurx";
7
7
  import { realmPlugin } from "../../RealmWithPlugins.js";
8
8
  const defaultCodeBlockLanguage$ = Cell("");
9
- const theme$ = Cell("auto");
10
9
  const insertCodeBlock$ = Signal((r) => {
11
10
  r.link(
12
11
  r.pipe(
@@ -23,7 +22,6 @@ const appendCodeBlockEditorDescriptor$ = Appender(codeBlockEditorDescriptors$);
23
22
  const codeBlockPlugin = realmPlugin({
24
23
  update(realm, params) {
25
24
  realm.pub(defaultCodeBlockLanguage$, (params == null ? void 0 : params.defaultCodeBlockLanguage) || "");
26
- realm.pub(theme$, (params == null ? void 0 : params.theme) || "auto");
27
25
  },
28
26
  init(realm, params) {
29
27
  realm.pubIn({
@@ -43,6 +41,5 @@ export {
43
41
  codeBlockPlugin,
44
42
  defaultCodeBlockLanguage$,
45
43
  insertCodeBlock$,
46
- theme$,
47
44
  useCodeBlockEditorContext
48
45
  };
@@ -4,10 +4,11 @@ import styles from "../../styles/ui.module.css.js";
4
4
  import { useCodeBlockEditorContext } from "../codeblock/CodeBlockNode.js";
5
5
  import { readOnly$ } from "../core/index.js";
6
6
  import { useCodeMirrorRef } from "../sandpack/useCodeMirrorRef.js";
7
- import { useCellValue } from "@mdxeditor/gurx";
8
- const CodeMirrorEditor = ({ language, nodeKey, code, focusEmitter, theme }) => {
7
+ import { useCellValues } from "@mdxeditor/gurx";
8
+ import { codeMirrorTheme$ } from "./index.js";
9
+ const CodeMirrorEditor = ({ language, nodeKey, code, focusEmitter }) => {
9
10
  const codeMirrorRef = useCodeMirrorRef(nodeKey, "codeblock", "jsx", focusEmitter);
10
- const readOnly = useCellValue(readOnly$);
11
+ const [readOnly, theme] = useCellValues(readOnly$, codeMirrorTheme$);
11
12
  const { setCode } = useCodeBlockEditorContext();
12
13
  React__default.useEffect(() => {
13
14
  var _a, _b;
@@ -24,13 +24,18 @@ const insertCodeMirror$ = Signal((r) => {
24
24
  insertCodeBlock$
25
25
  );
26
26
  });
27
+ const codeMirrorTheme$ = Cell("auto");
27
28
  const codeMirrorPlugin = realmPlugin({
28
29
  update(r, params) {
29
- r.pub(codeBlockLanguages$, params == null ? void 0 : params.codeBlockLanguages);
30
+ r.pubIn({
31
+ [codeBlockLanguages$]: params == null ? void 0 : params.codeBlockLanguages,
32
+ [codeMirrorTheme$]: (params == null ? void 0 : params.theme) || "auto"
33
+ });
30
34
  },
31
35
  init(r, params) {
32
36
  r.pubIn({
33
37
  [codeBlockLanguages$]: params == null ? void 0 : params.codeBlockLanguages,
38
+ [codeMirrorTheme$]: (params == null ? void 0 : params.theme) || "auto",
34
39
  [appendCodeBlockEditorDescriptor$]: buildCodeBlockDescriptor((params == null ? void 0 : params.codeBlockLanguages) || {})
35
40
  });
36
41
  }
@@ -47,5 +52,6 @@ function buildCodeBlockDescriptor(codeBlockLanguages) {
47
52
  export {
48
53
  codeBlockLanguages$,
49
54
  codeMirrorPlugin,
55
+ codeMirrorTheme$,
50
56
  insertCodeMirror$
51
57
  };
@@ -6,7 +6,7 @@ import styles from "../../styles/ui.module.css.js";
6
6
  import { useCellValues } from "@mdxeditor/gurx";
7
7
  const DiffSourceWrapper = ({ children }) => {
8
8
  const [error, viewMode] = useCellValues(markdownProcessingError$, viewMode$);
9
- return /* @__PURE__ */ React__default.createElement("div", null, error ? /* @__PURE__ */ React__default.createElement("div", { className: styles.markdownParseError }, /* @__PURE__ */ React__default.createElement("p", null, error.error, "."), /* @__PURE__ */ React__default.createElement("p", null, "You can fix the errors in source mode and switch to rich text mode when you are ready.")) : null, /* @__PURE__ */ React__default.createElement("div", { style: { display: viewMode === "rich-text" && error == null ? "block" : "none" } }, children), viewMode === "diff" ? /* @__PURE__ */ React__default.createElement(DiffViewer, null) : null, viewMode === "source" ? /* @__PURE__ */ React__default.createElement(SourceEditor, null) : null);
9
+ return /* @__PURE__ */ React__default.createElement("div", { className: "mdxeditor-diff-source-wrapper" }, error ? /* @__PURE__ */ React__default.createElement("div", { className: styles.markdownParseError }, /* @__PURE__ */ React__default.createElement("p", null, error.error, "."), /* @__PURE__ */ React__default.createElement("p", null, "You can fix the errors in source mode and switch to rich text mode when you are ready.")) : null, /* @__PURE__ */ React__default.createElement("div", { className: "mdxeditor-rich-text-editor", style: { display: viewMode === "rich-text" && error == null ? "block" : "none" } }, children), viewMode === "diff" ? /* @__PURE__ */ React__default.createElement(DiffViewer, null) : null, viewMode === "source" ? /* @__PURE__ */ React__default.createElement(SourceEditor, null) : null);
10
10
  };
11
11
  export {
12
12
  DiffSourceWrapper
@@ -71,7 +71,7 @@ const DiffViewer = () => {
71
71
  cmMergeViewRef.current = null;
72
72
  };
73
73
  }, [onUpdate, cmExtensions]);
74
- return /* @__PURE__ */ React__default.createElement("div", { ref: elRef });
74
+ return /* @__PURE__ */ React__default.createElement("div", { ref: elRef, className: "mdxeditor-diff-editor" });
75
75
  };
76
76
  export {
77
77
  DiffViewer
@@ -52,7 +52,7 @@ const SourceEditor = () => {
52
52
  },
53
53
  [markdown2, readOnly, updateMarkdown, cmExtensions, triggerOnBlur]
54
54
  );
55
- return /* @__PURE__ */ React__default.createElement("div", { ref, className: "cm-sourceView" });
55
+ return /* @__PURE__ */ React__default.createElement("div", { ref, className: "cm-sourceView mdxeditor-source-editor" });
56
56
  };
57
57
  export {
58
58
  COMMON_STATE_CONFIG_EXTENSIONS,
@@ -0,0 +1,36 @@
1
+ import { trimTextContentFromAnchor } from "@lexical/selection";
2
+ import { $restoreEditorState } from "@lexical/utils";
3
+ import { RootNode, $getSelection, $isRangeSelection } from "lexical";
4
+ import { realmPlugin } from "../../RealmWithPlugins.js";
5
+ import { createRootEditorSubscription$ } from "../core/index.js";
6
+ const maxLengthPlugin = realmPlugin({
7
+ init: (realm, maxLength = Infinity) => {
8
+ realm.pub(createRootEditorSubscription$, (editor) => {
9
+ let lastRestoredEditorState = null;
10
+ return editor.registerNodeTransform(RootNode, (rootNode) => {
11
+ const selection = $getSelection();
12
+ if (!$isRangeSelection(selection) || !selection.isCollapsed()) {
13
+ return;
14
+ }
15
+ const prevEditorState = editor.getEditorState();
16
+ const prevTextContentSize = prevEditorState.read(() => rootNode.getTextContentSize());
17
+ const textContentSize = rootNode.getTextContentSize();
18
+ if (prevTextContentSize !== textContentSize) {
19
+ const delCount = textContentSize - maxLength;
20
+ const anchor = selection.anchor;
21
+ if (delCount > 0) {
22
+ if (prevTextContentSize === maxLength && lastRestoredEditorState !== prevEditorState) {
23
+ lastRestoredEditorState = prevEditorState;
24
+ $restoreEditorState(editor, prevEditorState);
25
+ } else {
26
+ trimTextContentFromAnchor(editor, anchor, delCount);
27
+ }
28
+ }
29
+ }
30
+ });
31
+ });
32
+ }
33
+ });
34
+ export {
35
+ maxLengthPlugin
36
+ };
@@ -29,7 +29,15 @@ const SelectContent = ({
29
29
  className = styles.selectContainer
30
30
  }) => {
31
31
  const editorRootElementRef = useCellValue(editorRootElementRef$);
32
- return /* @__PURE__ */ React__default.createElement(RadixSelect.Portal, { container: editorRootElementRef == null ? void 0 : editorRootElementRef.current }, /* @__PURE__ */ React__default.createElement(RadixSelect.Content, { className, onCloseAutoFocus: (e) => e.preventDefault(), position: "popper" }, /* @__PURE__ */ React__default.createElement(RadixSelect.Viewport, { "data-editor-dropdown": true }, children)));
32
+ return /* @__PURE__ */ React__default.createElement(RadixSelect.Portal, { container: editorRootElementRef == null ? void 0 : editorRootElementRef.current }, /* @__PURE__ */ React__default.createElement(
33
+ RadixSelect.Content,
34
+ {
35
+ className: classNames(className, "mdxeditor-select-content"),
36
+ onCloseAutoFocus: (e) => e.preventDefault(),
37
+ position: "popper"
38
+ },
39
+ /* @__PURE__ */ React__default.createElement(RadixSelect.Viewport, { "data-editor-dropdown": true }, children)
40
+ ));
33
41
  };
34
42
  const SelectButtonTrigger = ({
35
43
  children,
@@ -22,7 +22,7 @@ const Root = ({ readOnly, children }) => {
22
22
  return /* @__PURE__ */ React__default.createElement(
23
23
  RadixToolbar.Root,
24
24
  {
25
- className: classNames(styles.toolbarRoot, { [styles.readOnlyToolbarRoot]: readOnly }),
25
+ className: classNames("mdxeditor-toolbar", styles.toolbarRoot, { [styles.readOnlyToolbarRoot]: readOnly }),
26
26
  ...readOnly ? { tabIndex: -1 } : {}
27
27
  },
28
28
  children
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "*.css"
12
12
  ],
13
13
  "type": "module",
14
- "version": "2.5.0",
14
+ "version": "2.6.0",
15
15
  "description": "React component for rich text markdown editing",
16
16
  "scripts": {
17
17
  "build": "vite build",