@mdxeditor/editor 0.10.0-alpha.1 → 0.10.0-alpha.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.
Files changed (53) hide show
  1. package/dist/MDXEditor.d.ts +29 -0
  2. package/dist/MDXEditor.js +1 -1
  3. package/dist/directive-editors/AdmonitionDirectiveDescriptor.d.ts +13 -0
  4. package/dist/directive-editors/GenericDirectiveEditor.d.ts +5 -0
  5. package/dist/importMarkdownToLexical.js +1 -1
  6. package/dist/index.d.ts +2 -0
  7. package/dist/index.js +9 -1
  8. package/dist/jsx-editors/GenericJsxEditor.d.ts +5 -0
  9. package/dist/plugins/core/NestedLexicalEditor.d.ts +9 -2
  10. package/dist/plugins/core/PropertyPopover.d.ts +17 -2
  11. package/dist/plugins/diff-source/SourceEditor.js +2 -0
  12. package/dist/plugins/diff-source/index.d.ts +1 -0
  13. package/dist/plugins/image/ImageEditor.d.ts +3 -1
  14. package/dist/plugins/image/ImageEditor.js +29 -6
  15. package/dist/plugins/image/ImageNode.d.ts +11 -1
  16. package/dist/plugins/image/ImageNode.js +37 -9
  17. package/dist/plugins/image/ImageResizer.d.ts +18 -0
  18. package/dist/plugins/image/ImageResizer.js +214 -0
  19. package/dist/plugins/image/LexicalImageVisitor.js +27 -6
  20. package/dist/plugins/image/MdastImageVisitor.d.ts +3 -0
  21. package/dist/plugins/image/MdastImageVisitor.js +72 -1
  22. package/dist/plugins/image/index.d.ts +4 -0
  23. package/dist/plugins/image/index.js +3 -1
  24. package/dist/plugins/jsx/MdastMdxJsxElementVisitor.js +1 -1
  25. package/dist/plugins/jsx/index.d.ts +9 -0
  26. package/dist/plugins/lists/LexicalListVisitor.js +0 -1
  27. package/dist/plugins/table/TableEditor.js +25 -15
  28. package/dist/plugins/toolbar/components/BlockTypeSelect.d.ts +4 -0
  29. package/dist/plugins/toolbar/components/BoldItalicUnderlineToggles.d.ts +3 -0
  30. package/dist/plugins/toolbar/components/ChangeAdmonitionType.d.ts +4 -0
  31. package/dist/plugins/toolbar/components/ChangeCodeMirrorLanguage.d.ts +5 -0
  32. package/dist/plugins/toolbar/components/ChangeCodeMirrorLanguage.js +2 -2
  33. package/dist/plugins/toolbar/components/CodeToggle.d.ts +4 -0
  34. package/dist/plugins/toolbar/components/CreateLink.d.ts +4 -0
  35. package/dist/plugins/toolbar/components/DiffSourceToggleWrapper.d.ts +5 -0
  36. package/dist/plugins/toolbar/components/InsertAdmonition.d.ts +4 -0
  37. package/dist/plugins/toolbar/components/InsertCodeBlock.d.ts +5 -0
  38. package/dist/plugins/toolbar/components/InsertFrontmatter.d.ts +4 -0
  39. package/dist/plugins/toolbar/components/InsertImage.d.ts +4 -0
  40. package/dist/plugins/toolbar/components/InsertSandpack.d.ts +4 -0
  41. package/dist/plugins/toolbar/components/InsertTable.d.ts +4 -0
  42. package/dist/plugins/toolbar/components/InsertThematicBreak.d.ts +4 -0
  43. package/dist/plugins/toolbar/components/KitchenSinkToolbar.d.ts +5 -0
  44. package/dist/plugins/toolbar/components/ListsToggle.d.ts +5 -0
  45. package/dist/plugins/toolbar/components/ShowSandpackInfo.d.ts +5 -0
  46. package/dist/plugins/toolbar/components/UndoRedo.d.ts +3 -0
  47. package/dist/plugins/toolbar/primitives/TooltipWrap.d.ts +3 -0
  48. package/dist/plugins/toolbar/primitives/select.d.ts +19 -0
  49. package/dist/plugins/toolbar/primitives/toolbar.d.ts +80 -5
  50. package/dist/style.css +232 -158
  51. package/dist/styles/ui.module.css.js +105 -75
  52. package/dist/utils/lexicalHelpers.js +2 -2
  53. package/package.json +12 -1
@@ -1,12 +1,38 @@
1
1
  import React from 'react';
2
2
  import { RealmPluginInitializer } from './gurx';
3
3
  import { ToMarkdownOptions } from './exportMarkdownFromLexical';
4
+ /**
5
+ * The properties of the {@link MDXEditor} React component.
6
+ */
4
7
  export interface MDXEditorProps {
8
+ /**
9
+ * the CSS class to apply to the content editable element of the editor.
10
+ * Use this to style the various content elements like lists and blockquotes.
11
+ */
5
12
  contentEditableClassName?: string;
13
+ /**
14
+ * The markdown to edit. Notice that this is read only when the component is mounted.
15
+ * To change the component content dynamically, use the `MDXEditorMethods.setMarkdown` method.
16
+ */
6
17
  markdown: string;
18
+ /**
19
+ * Triggered when the editor value changes. The callback is not throttled, you can use any throttling mechanism
20
+ * if you intend to do auto-saving.
21
+ */
7
22
  onChange?: (markdown: string) => void;
23
+ /**
24
+ * The markdown options used to generate the resulting markdown.
25
+ * See {@link https://github.com/syntax-tree/mdast-util-to-markdown#options | the mdast-util-to-markdown docs} for the full list of options.
26
+ */
8
27
  toMarkdownOptions?: ToMarkdownOptions;
28
+ /**
29
+ * The plugins to use in the editor.
30
+ */
9
31
  plugins?: React.ComponentProps<typeof RealmPluginInitializer>['plugins'];
32
+ /**
33
+ * The class name to apply to the root component element. Use this if you want to change the editor dimensions, maximum height, etc.
34
+ * For a content-specific styling, Use `contentEditableClassName` property.
35
+ */
10
36
  className?: string;
11
37
  }
12
38
  /**
@@ -28,4 +54,7 @@ export interface MDXEditorMethods {
28
54
  */
29
55
  setMarkdown: (value: string) => void;
30
56
  }
57
+ /**
58
+ * The MDXEditor React component. See {@link MDXEditorProps} for the list of properties supported and the {@link MDXEditorMethods} for the methods accessible through the ref.
59
+ */
31
60
  export declare const MDXEditor: React.ForwardRefExoticComponent<MDXEditorProps & React.RefAttributes<MDXEditorMethods>>;
package/dist/MDXEditor.js CHANGED
@@ -62,7 +62,7 @@ const EditorRootElement = ({ children, className }) => {
62
62
  React__default.useEffect(() => {
63
63
  setEditorRootElementRef(editorRootElementRef);
64
64
  }, [editorRootElementRef, setEditorRootElementRef]);
65
- return /* @__PURE__ */ React__default.createElement("div", { className: classNames(styles.editorRoot, styles.editorWrapper, className), ref: editorRootElementRef }, children);
65
+ return /* @__PURE__ */ React__default.createElement("div", { className: classNames(styles.editorRoot, styles.editorWrapper, className, "mdxeditor"), ref: editorRootElementRef }, children);
66
66
  };
67
67
  const Methods = ({ mdxRef }) => {
68
68
  const realm = corePluginHooks.useRealmContext();
@@ -1,4 +1,17 @@
1
1
  import { DirectiveDescriptor } from '../plugins/directives';
2
+ /** @internal */
2
3
  export declare const ADMONITION_TYPES: readonly ["note", "tip", "danger", "info", "caution"];
4
+ /** @internal */
3
5
  export type AdmonitionKind = (typeof ADMONITION_TYPES)[number];
6
+ /**
7
+ * Pass this descriptor to the `directivesPlugin` `directiveDescriptors` parameter to enable {@link https://docusaurus.io/docs/markdown-features/admonitions | markdown admonitions}.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * <MDXEditor
12
+ * plugins={[
13
+ * directivesPlugin({ directiveDescriptors: [ AdmonitionDirectiveDescriptor] }),
14
+ * ]} />
15
+ * ```
16
+ */
4
17
  export declare const AdmonitionDirectiveDescriptor: DirectiveDescriptor;
@@ -1,3 +1,8 @@
1
1
  import React from 'react';
2
2
  import { DirectiveEditorProps } from '../plugins/directives';
3
+ /**
4
+ * A generic editor that can be used as an universal UI for any directive.
5
+ * Allows editing of the directive content and properties.
6
+ * Use this editor for the {@link DirectiveDescriptor} Editor option.
7
+ */
3
8
  export declare const GenericDirectiveEditor: React.FC<DirectiveEditorProps>;
@@ -28,7 +28,7 @@ function importMdastTreeToLexical({ root, mdastRoot, visitors }) {
28
28
  return visitor2.testNode(mdastNode);
29
29
  });
30
30
  if (!visitor) {
31
- throw new Error(`no MdastImportVisitor found for ${mdastNode.type}`, {
31
+ throw new Error(`no MdastImportVisitor found for ${mdastNode.type} ${JSON.stringify(mdastNode)}`, {
32
32
  cause: mdastNode
33
33
  });
34
34
  }
package/dist/index.d.ts CHANGED
@@ -47,3 +47,5 @@ export * from './plugins/toolbar/primitives/toolbar';
47
47
  export * from './plugins/toolbar/primitives/DialogButton';
48
48
  export * from './plugins/toolbar/primitives/TooltipWrap';
49
49
  export * from './plugins/toolbar/primitives/select';
50
+ export * from './plugins/core/NestedLexicalEditor';
51
+ export * from './plugins/core/PropertyPopover';
package/dist/index.js CHANGED
@@ -42,6 +42,8 @@ import { Button, ButtonOrDropdownButton, ButtonWithTooltip, ConditionalContents,
42
42
  import { DialogButton } from "./plugins/toolbar/primitives/DialogButton.js";
43
43
  import { TooltipWrap } from "./plugins/toolbar/primitives/TooltipWrap.js";
44
44
  import { Select, SelectButtonTrigger, SelectContent, SelectItem, SelectTrigger } from "./plugins/toolbar/primitives/select.js";
45
+ import { NestedEditorsContext, NestedLexicalEditor, useLexicalNodeRemove, useMdastNodeUpdater, useNestedEditorContext } from "./plugins/core/NestedLexicalEditor.js";
46
+ import { PropertyPopover } from "./plugins/core/PropertyPopover.js";
45
47
  import { useCodeBlockEditorContext } from "./plugins/codeblock/CodeBlockNode.js";
46
48
  export {
47
49
  ADMONITION_TYPES,
@@ -72,6 +74,9 @@ export {
72
74
  ListsToggle,
73
75
  MDXEditor,
74
76
  MultipleChoiceToggleGroup,
77
+ NestedEditorsContext,
78
+ NestedLexicalEditor,
79
+ PropertyPopover,
75
80
  Root,
76
81
  Select,
77
82
  SelectButtonTrigger,
@@ -131,5 +136,8 @@ export {
131
136
  toolbarPlugin,
132
137
  toolbarPluginHooks,
133
138
  toolbarSystem,
134
- useCodeBlockEditorContext
139
+ useCodeBlockEditorContext,
140
+ useLexicalNodeRemove,
141
+ useMdastNodeUpdater,
142
+ useNestedEditorContext
135
143
  };
@@ -1,3 +1,8 @@
1
1
  import React from 'react';
2
2
  import { JsxEditorProps } from '../plugins/jsx';
3
+ /**
4
+ * A generic editor that can be used as an universal UI for any JSX element.
5
+ * Allows editing of the element content and properties.
6
+ * Use this editor for the {@link JsxComponentDescriptor} Editor option.
7
+ */
3
8
  export declare const GenericJsxEditor: React.FC<JsxEditorProps>;
@@ -13,7 +13,14 @@ interface NestedEditorsContextValue<T extends Node> {
13
13
  };
14
14
  focusEmitter: VoidEmitter;
15
15
  }
16
+ /**
17
+ * Use this context to provide the necessary values to the {@link NestedLexicalEditor} React component.
18
+ * Place it as a wrapper in your custom lexical node decorators.
19
+ */
16
20
  export declare const NestedEditorsContext: React.Context<NestedEditorsContextValue<Node<import("unist").Data>> | undefined>;
21
+ /**
22
+ * A hook to get the current {@link NestedEditorsContext} value. Use this in your custom editor components.
23
+ */
17
24
  export declare const useNestedEditorContext: <T extends Mdast.Content>() => NestedEditorsContextValue<T>;
18
25
  /**
19
26
  * A hook that returns a function that can be used to update the mdast node. Use this in your custom editor components.
@@ -24,7 +31,7 @@ export declare function useMdastNodeUpdater<T extends Mdast.Content>(): (node: P
24
31
  */
25
32
  export declare function useLexicalNodeRemove(): () => void;
26
33
  /**
27
- * The properties of the {@link NestedEditor} React Component.
34
+ * The properties of the {@link NestedLexicalEditor} React component.
28
35
  * @typeParam T - The type of the mdast node of the editor.
29
36
  */
30
37
  export interface NestedEditorProps<T extends Mdast.Content> {
@@ -62,7 +69,7 @@ export interface NestedEditorProps<T extends Mdast.Content> {
62
69
  * children: Mdast.PhrasingContent[]
63
70
  * }
64
71
  *
65
- * return <NestedEditor<CalloutDirectiveNode> getContent={node => node.children} getUpdatedMdastNode={(node, children) => ({ ...node, children })} />
72
+ * return <NestedLexicalEditor<CalloutDirectiveNode> getContent={node => node.children} getUpdatedMdastNode={(node, children) => ({ ...node, children })} />
66
73
  * ```
67
74
  */
68
75
  export declare const NestedLexicalEditor: <T extends Mdast.Content>(props: NestedEditorProps<T>) => React.JSX.Element;
@@ -1,8 +1,23 @@
1
1
  import React from 'react';
2
- interface PropertyPopoverProps {
2
+ /**
3
+ * The properties of the {@link PropertyPopover} React component.
4
+ */
5
+ export interface PropertyPopoverProps {
6
+ /**
7
+ * The properties to edit. The key is the name of the property, and the value is the initial value.
8
+ */
3
9
  properties: Record<string, string>;
10
+ /**
11
+ * Triggered when the user edits the property values.
12
+ */
4
13
  onChange: (values: Record<string, string>) => void;
14
+ /**
15
+ * The title to display in the popover.
16
+ */
5
17
  title: string;
6
18
  }
19
+ /**
20
+ * A React component that can be used in custom editors to edit the properties of the node.
21
+ * Displays a simple, static key/value editing UI in a popover.
22
+ */
7
23
  export declare const PropertyPopover: React.FC<PropertyPopoverProps>;
8
- export {};
@@ -3,6 +3,7 @@ import { SandpackProvider, CodeEditor } from "@codesandbox/sandpack-react";
3
3
  import React__default from "react";
4
4
  import { diffSourcePluginHooks } from "./index.js";
5
5
  import { corePluginHooks } from "../core/index.js";
6
+ import { EditorView } from "@codemirror/view";
6
7
  const SourceEditor = () => {
7
8
  const [markdown$1] = corePluginHooks.useEmitterValues("markdown");
8
9
  const updateMarkdown = diffSourcePluginHooks.usePublisher("markdownSourceEditorValue");
@@ -10,6 +11,7 @@ const SourceEditor = () => {
10
11
  return /* @__PURE__ */ React__default.createElement("div", null, /* @__PURE__ */ React__default.createElement(React__default.Suspense, { fallback: null }, /* @__PURE__ */ React__default.createElement(SandpackProvider, null, /* @__PURE__ */ React__default.createElement(
11
12
  CodeEditor,
12
13
  {
14
+ extensions: [EditorView.lineWrapping],
13
15
  showLineNumbers: true,
14
16
  additionalLanguages: [{ name: "markdown", extensions: ["md"], language: markdown() }],
15
17
  initMode: "lazy",
@@ -1,4 +1,5 @@
1
1
  /// <reference types="react" />
2
+ /** @internal */
2
3
  export type ViewMode = 'rich-text' | 'source' | 'diff';
3
4
  /** @internal */
4
5
  export declare const diffSourceSystem: import("../../gurx").SystemSpec<[import("../../gurx").SystemSpec<[], (r: import("../../gurx").Realm) => {
@@ -3,5 +3,7 @@ export interface ImageEditorProps {
3
3
  nodeKey: string;
4
4
  src: string;
5
5
  title?: string;
6
+ width: number | 'inherit';
7
+ height: number | 'inherit';
6
8
  }
7
- export declare function ImageEditor({ src, title, nodeKey }: ImageEditorProps): JSX.Element;
9
+ export declare function ImageEditor({ src, title, nodeKey, width, height }: ImageEditorProps): JSX.Element;
@@ -6,6 +6,7 @@ import { $isNodeSelection, $getSelection, $getNodeByKey, $setSelection, SELECTIO
6
6
  import styles from "../../styles/ui.module.css.js";
7
7
  import classNames from "classnames";
8
8
  import { $isImageNode } from "./ImageNode.js";
9
+ import ImageResizer from "./ImageResizer.js";
9
10
  const imageCache = /* @__PURE__ */ new Set();
10
11
  function useSuspenseImage(src) {
11
12
  if (!imageCache.has(src)) {
@@ -23,18 +24,21 @@ function LazyImage({
23
24
  title,
24
25
  className,
25
26
  imageRef,
26
- src
27
+ src,
28
+ width,
29
+ height
27
30
  }) {
28
31
  useSuspenseImage(src);
29
- return /* @__PURE__ */ React__default.createElement("img", { className: className || void 0, src, title, ref: imageRef, draggable: "false" });
32
+ return /* @__PURE__ */ React__default.createElement("img", { className: className || void 0, src, title, ref: imageRef, draggable: "false", width, height });
30
33
  }
31
- function ImageEditor({ src, title, nodeKey }) {
34
+ function ImageEditor({ src, title, nodeKey, width, height }) {
32
35
  const imageRef = React__default.useRef(null);
33
36
  const buttonRef = React__default.useRef(null);
34
37
  const [isSelected, setSelected, clearSelection] = useLexicalNodeSelection(nodeKey);
35
38
  const [editor] = useLexicalComposerContext();
36
39
  const [selection, setSelection] = React__default.useState(null);
37
40
  const activeEditorRef = React__default.useRef(null);
41
+ const [isResizing, setIsResizing] = React__default.useState(false);
38
42
  const onDelete = React__default.useCallback(
39
43
  (payload) => {
40
44
  if (isSelected && $isNodeSelection($getSelection())) {
@@ -101,6 +105,9 @@ function ImageEditor({ src, title, nodeKey }) {
101
105
  CLICK_COMMAND,
102
106
  (payload) => {
103
107
  const event = payload;
108
+ if (isResizing) {
109
+ return true;
110
+ }
104
111
  if (event.target === imageRef.current) {
105
112
  if (event.shiftKey) {
106
113
  setSelected(!isSelected);
@@ -134,12 +141,28 @@ function ImageEditor({ src, title, nodeKey }) {
134
141
  isMounted = false;
135
142
  unregister();
136
143
  };
137
- }, [clearSelection, editor, isSelected, nodeKey, onDelete, onEnter, onEscape, setSelected]);
144
+ }, [clearSelection, editor, isResizing, isSelected, nodeKey, onDelete, onEnter, onEscape, setSelected]);
145
+ const onResizeEnd = (nextWidth, nextHeight) => {
146
+ setTimeout(() => {
147
+ setIsResizing(false);
148
+ }, 200);
149
+ editor.update(() => {
150
+ const node = $getNodeByKey(nodeKey);
151
+ if ($isImageNode(node)) {
152
+ node.setWidthAndHeight(nextWidth, nextHeight);
153
+ }
154
+ });
155
+ };
156
+ const onResizeStart = () => {
157
+ setIsResizing(true);
158
+ };
138
159
  const draggable = $isNodeSelection(selection);
139
160
  const isFocused = isSelected;
140
- return /* @__PURE__ */ React__default.createElement(React__default.Suspense, { fallback: null }, /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement("div", { draggable, className: styles.imageWrapper, "data-editor-block-type": "image" }, /* @__PURE__ */ React__default.createElement(
161
+ return /* @__PURE__ */ React__default.createElement(React__default.Suspense, { fallback: null }, /* @__PURE__ */ React__default.createElement("div", { className: styles.imageWrapper, "data-editor-block-type": "image" }, /* @__PURE__ */ React__default.createElement("div", { draggable }, /* @__PURE__ */ React__default.createElement(
141
162
  LazyImage,
142
163
  {
164
+ width,
165
+ height,
143
166
  className: classNames({
144
167
  [styles.focusedImage]: isFocused
145
168
  }),
@@ -147,7 +170,7 @@ function ImageEditor({ src, title, nodeKey }) {
147
170
  title: title || "",
148
171
  imageRef
149
172
  }
150
- ))));
173
+ )), draggable && isFocused && /* @__PURE__ */ React__default.createElement(ImageResizer, { editor, imageRef, onResizeStart, onResizeEnd })));
151
174
  }
152
175
  export {
153
176
  ImageEditor
@@ -7,6 +7,8 @@ import { DecoratorNode } from 'lexical';
7
7
  export type SerializedImageNode = Spread<{
8
8
  altText: string;
9
9
  title?: string;
10
+ width?: number;
11
+ height?: number;
10
12
  src: string;
11
13
  type: 'image';
12
14
  version: 1;
@@ -18,18 +20,24 @@ export declare class ImageNode extends DecoratorNode<JSX.Element> {
18
20
  __src: string;
19
21
  __altText: string;
20
22
  __title: string | undefined;
23
+ __width: 'inherit' | number;
24
+ __height: 'inherit' | number;
21
25
  static getType(): string;
22
26
  static clone(node: ImageNode): ImageNode;
23
27
  static importJSON(serializedNode: SerializedImageNode): ImageNode;
24
28
  exportDOM(): DOMExportOutput;
25
29
  static importDOM(): DOMConversionMap | null;
26
- constructor(src: string, altText: string, title: string | undefined, key?: NodeKey);
30
+ constructor(src: string, altText: string, title: string | undefined, width?: 'inherit' | number, height?: 'inherit' | number, key?: NodeKey);
27
31
  exportJSON(): SerializedImageNode;
32
+ setWidthAndHeight(width: 'inherit' | number, height: 'inherit' | number): void;
28
33
  createDOM(config: EditorConfig): HTMLElement;
29
34
  updateDOM(): false;
30
35
  getSrc(): string;
31
36
  getAltText(): string;
32
37
  getTitle(): string | undefined;
38
+ getHeight(): 'inherit' | number;
39
+ getWidth(): 'inherit' | number;
40
+ hasExplicitDimensions(): boolean;
33
41
  setTitle(title: string | undefined): void;
34
42
  decorate(_parentEditor: LexicalEditor): JSX.Element;
35
43
  }
@@ -38,6 +46,8 @@ export declare class ImageNode extends DecoratorNode<JSX.Element> {
38
46
  */
39
47
  export interface CreateImageNodeOptions {
40
48
  altText: string;
49
+ width?: number;
50
+ height?: number;
41
51
  title?: string;
42
52
  key?: NodeKey;
43
53
  src: string;
@@ -9,34 +9,40 @@ import { DecoratorNode } from "lexical";
9
9
  import { ImageEditor } from "./ImageEditor.js";
10
10
  function convertImageElement(domNode) {
11
11
  if (domNode instanceof HTMLImageElement) {
12
- const { alt: altText, src, title } = domNode;
13
- const node = $createImageNode({ altText, src, title });
12
+ const { alt: altText, src, title, width, height } = domNode;
13
+ const node = $createImageNode({ altText, src, title, width, height });
14
14
  return { node };
15
15
  }
16
16
  return null;
17
17
  }
18
18
  class ImageNode extends DecoratorNode {
19
- constructor(src, altText, title, key) {
19
+ constructor(src, altText, title, width, height, key) {
20
20
  super(key);
21
21
  __publicField(this, "__src");
22
22
  __publicField(this, "__altText");
23
23
  __publicField(this, "__title");
24
+ __publicField(this, "__width");
25
+ __publicField(this, "__height");
24
26
  this.__src = src;
25
27
  this.__title = title;
26
28
  this.__altText = altText;
29
+ this.__width = width || "inherit";
30
+ this.__height = height || "inherit";
27
31
  }
28
32
  static getType() {
29
33
  return "image";
30
34
  }
31
35
  static clone(node) {
32
- return new ImageNode(node.__src, node.__altText, node.__title, node.__key);
36
+ return new ImageNode(node.__src, node.__altText, node.__title, node.__width, node.__height, node.__key);
33
37
  }
34
38
  static importJSON(serializedNode) {
35
- const { altText, title, src } = serializedNode;
39
+ const { altText, title, src, width, height } = serializedNode;
36
40
  const node = $createImageNode({
37
41
  altText,
38
42
  title,
39
- src
43
+ src,
44
+ height,
45
+ width
40
46
  });
41
47
  return node;
42
48
  }
@@ -47,6 +53,12 @@ class ImageNode extends DecoratorNode {
47
53
  if (this.__title) {
48
54
  element.setAttribute("title", this.__title);
49
55
  }
56
+ if (this.__width) {
57
+ element.setAttribute("width", this.__width.toString());
58
+ }
59
+ if (this.__height) {
60
+ element.setAttribute("height", this.__height.toString());
61
+ }
50
62
  return { element };
51
63
  }
52
64
  static importDOM() {
@@ -61,11 +73,18 @@ class ImageNode extends DecoratorNode {
61
73
  return {
62
74
  altText: this.getAltText(),
63
75
  title: this.getTitle(),
76
+ height: this.__height === "inherit" ? 0 : this.__height,
77
+ width: this.__width === "inherit" ? 0 : this.__width,
64
78
  src: this.getSrc(),
65
79
  type: "image",
66
80
  version: 1
67
81
  };
68
82
  }
83
+ setWidthAndHeight(width, height) {
84
+ const writable = this.getWritable();
85
+ writable.__width = width;
86
+ writable.__height = height;
87
+ }
69
88
  createDOM(config) {
70
89
  const span = document.createElement("span");
71
90
  const theme = config.theme;
@@ -87,16 +106,25 @@ class ImageNode extends DecoratorNode {
87
106
  getTitle() {
88
107
  return this.__title;
89
108
  }
109
+ getHeight() {
110
+ return this.__height;
111
+ }
112
+ getWidth() {
113
+ return this.__width;
114
+ }
115
+ hasExplicitDimensions() {
116
+ return this.__width !== "inherit" || this.__height !== "inherit";
117
+ }
90
118
  setTitle(title) {
91
119
  this.getWritable().__title = title;
92
120
  }
93
121
  decorate(_parentEditor) {
94
- return /* @__PURE__ */ React__default.createElement(ImageEditor, { src: this.getSrc(), title: this.getTitle(), nodeKey: this.getKey() });
122
+ return /* @__PURE__ */ React__default.createElement(ImageEditor, { src: this.getSrc(), title: this.getTitle(), nodeKey: this.getKey(), width: this.__width, height: this.__height });
95
123
  }
96
124
  }
97
125
  function $createImageNode(options) {
98
- const { altText, title, src, key } = options;
99
- return new ImageNode(src, altText, title, key);
126
+ const { altText, title, src, key, width, height } = options;
127
+ return new ImageNode(src, altText, title, width, height, key);
100
128
  }
101
129
  function $isImageNode(node) {
102
130
  return node instanceof ImageNode;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ /// <reference types="react" />
9
+ import type { LexicalEditor } from 'lexical';
10
+ export default function ImageResizer({ onResizeStart, onResizeEnd, imageRef, maxWidth, editor }: {
11
+ editor: LexicalEditor;
12
+ imageRef: {
13
+ current: null | HTMLElement;
14
+ };
15
+ maxWidth?: number;
16
+ onResizeEnd: (width: 'inherit' | number, height: 'inherit' | number) => void;
17
+ onResizeStart: () => void;
18
+ }): JSX.Element;