@mdxeditor/editor 1.1.1 → 1.2.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.
@@ -10,14 +10,12 @@ const AdmonitionDirectiveDescriptor = {
10
10
  },
11
11
  Editor({ mdastNode }) {
12
12
  const {
13
- config: { theme },
14
- focusEmitter
13
+ config: { theme }
15
14
  } = useNestedEditorContext();
16
15
  return /* @__PURE__ */ React__default.createElement("div", { className: theme.admonition[mdastNode.name] }, /* @__PURE__ */ React__default.createElement(
17
16
  NestedLexicalEditor,
18
17
  {
19
18
  block: true,
20
- focusEmitter,
21
19
  getContent: (node) => node.children,
22
20
  getUpdatedMdastNode: (mdastNode2, children) => ({ ...mdastNode2, children })
23
21
  }
@@ -10,10 +10,11 @@ const PropertyPopover = ({ title, properties, onChange }) => {
10
10
  return /* @__PURE__ */ React__default.createElement(RadixPopover.Root, { open, onOpenChange: (v) => setOpen(v) }, /* @__PURE__ */ React__default.createElement(RadixPopover.Trigger, { className: styles.iconButton }, /* @__PURE__ */ React__default.createElement(SettingsIcon, { style: { display: "block" } })), /* @__PURE__ */ React__default.createElement(PopoverPortal, null, /* @__PURE__ */ React__default.createElement(PopoverContent, null, /* @__PURE__ */ React__default.createElement(
11
11
  "form",
12
12
  {
13
- onSubmit: handleSubmit((values) => {
14
- onChange(values);
13
+ onSubmit: (e) => {
14
+ void handleSubmit(onChange)(e);
15
15
  setOpen(false);
16
- })
16
+ e.nativeEvent.stopImmediatePropagation();
17
+ }
17
18
  },
18
19
  /* @__PURE__ */ React__default.createElement("h3", { className: styles.propertyPanelTitle }, title, " Attributes"),
19
20
  /* @__PURE__ */ React__default.createElement("table", { className: styles.propertyEditorTable }, /* @__PURE__ */ React__default.createElement("thead", null, /* @__PURE__ */ React__default.createElement("tr", null, /* @__PURE__ */ React__default.createElement("th", { className: styles.readOnlyColumnCell }, "Attribute"), /* @__PURE__ */ React__default.createElement("th", null, "Value"))), /* @__PURE__ */ React__default.createElement("tbody", null, Object.keys(properties).map((propName) => /* @__PURE__ */ React__default.createElement("tr", { key: propName }, /* @__PURE__ */ React__default.createElement("th", { className: styles.readOnlyColumnCell }, " ", propName, " "), /* @__PURE__ */ React__default.createElement("td", null, /* @__PURE__ */ React__default.createElement("input", { ...register(propName), className: styles.propertyEditorInput }))))), /* @__PURE__ */ React__default.createElement("tfoot", null, /* @__PURE__ */ React__default.createElement("tr", null, /* @__PURE__ */ React__default.createElement("td", { colSpan: 2 }, /* @__PURE__ */ React__default.createElement("div", { className: styles.buttonsFooter }, /* @__PURE__ */ React__default.createElement("button", { type: "submit", className: styles.primaryButton }, "Save"), /* @__PURE__ */ React__default.createElement(
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { Control, UseFormSetValue } from 'react-hook-form';
3
+ export declare const DownshiftAutoComplete: React.FC<{
4
+ suggestions: string[];
5
+ control: Control<any, any>;
6
+ setValue: UseFormSetValue<any>;
7
+ placeholder: string;
8
+ inputName: string;
9
+ autofocus?: boolean;
10
+ initialInputValue: string;
11
+ }>;
@@ -0,0 +1,66 @@
1
+ import { useCombobox } from "downshift";
2
+ import React__default from "react";
3
+ import { Controller } from "react-hook-form";
4
+ import styles from "../../../styles/ui.module.css.js";
5
+ import DropDownIcon from "../../../icons/arrow_drop_down.svg.js";
6
+ const MAX_SUGGESTIONS = 20;
7
+ const DownshiftAutoComplete = ({ autofocus, suggestions, control, inputName, placeholder, initialInputValue, setValue }) => {
8
+ const [items, setItems] = React__default.useState(suggestions.slice(0, MAX_SUGGESTIONS));
9
+ const enableAutoComplete = suggestions.length > 0;
10
+ const { isOpen, getToggleButtonProps, getMenuProps, getInputProps, highlightedIndex, getItemProps, selectedItem } = useCombobox({
11
+ initialInputValue,
12
+ onInputValueChange({ inputValue }) {
13
+ inputValue = (inputValue == null ? void 0 : inputValue.toLowerCase()) || "";
14
+ setValue(inputName, inputValue);
15
+ const matchingItems = [];
16
+ for (const suggestion of suggestions) {
17
+ if (suggestion.toLowerCase().includes(inputValue)) {
18
+ matchingItems.push(suggestion);
19
+ if (matchingItems.length >= MAX_SUGGESTIONS) {
20
+ break;
21
+ }
22
+ }
23
+ }
24
+ setItems(matchingItems);
25
+ },
26
+ items,
27
+ itemToString(item) {
28
+ return item ?? "";
29
+ }
30
+ });
31
+ const dropdownIsVisible = isOpen && items.length > 0;
32
+ return /* @__PURE__ */ React__default.createElement("div", { className: styles.downshiftAutocompleteContainer }, /* @__PURE__ */ React__default.createElement("div", { "data-visible-dropdown": dropdownIsVisible, className: styles.downshiftInputWrapper }, /* @__PURE__ */ React__default.createElement(
33
+ Controller,
34
+ {
35
+ name: inputName,
36
+ control,
37
+ render: ({ field }) => {
38
+ const downshiftSrcProps = getInputProps();
39
+ return /* @__PURE__ */ React__default.createElement(
40
+ "input",
41
+ {
42
+ ...downshiftSrcProps,
43
+ name: field.name,
44
+ placeholder,
45
+ className: styles.downshiftInput,
46
+ size: 30,
47
+ "data-editor-dialog": true,
48
+ autoFocus: autofocus
49
+ }
50
+ );
51
+ }
52
+ }
53
+ ), enableAutoComplete && /* @__PURE__ */ React__default.createElement("button", { "aria-label": "toggle menu", type: "button", ...getToggleButtonProps() }, /* @__PURE__ */ React__default.createElement(DropDownIcon, null))), /* @__PURE__ */ React__default.createElement("div", { className: styles.downshiftAutocompleteContainer }, /* @__PURE__ */ React__default.createElement("ul", { ...getMenuProps(), "data-visible": dropdownIsVisible }, items.map((item, index) => /* @__PURE__ */ React__default.createElement(
54
+ "li",
55
+ {
56
+ "data-selected": selectedItem === item,
57
+ "data-highlighted": highlightedIndex === index,
58
+ key: `${item}${index}`,
59
+ ...getItemProps({ item, index })
60
+ },
61
+ item
62
+ )))));
63
+ };
64
+ export {
65
+ DownshiftAutoComplete
66
+ };
@@ -28,7 +28,6 @@ const CmMergeView = ({ oldMarkdown, newMarkdown, onUpdate }) => {
28
28
  orientation: "a-b",
29
29
  revertControls: "a-to-b",
30
30
  gutter: true,
31
- collapseUnchanged: { margin: 2, minSize: 3 },
32
31
  a: {
33
32
  doc: oldMarkdown,
34
33
  extensions: [...COMMON_STATE_CONFIG_EXTENSIONS, EditorState.readOnly.of(true)]
@@ -46,20 +46,31 @@ const FrontmatterEditor = ({ yaml, onChange }) => {
46
46
  },
47
47
  [onChange, setFrontmatterDialogOpen, removeFrontmatter]
48
48
  );
49
- return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(Dialog.Root, { open: frontmatterDialogOpen, onOpenChange: (open) => setFrontmatterDialogOpen(open) }, /* @__PURE__ */ React__default.createElement(Dialog.Portal, { container: editorRootElementRef == null ? void 0 : editorRootElementRef.current }, /* @__PURE__ */ React__default.createElement(Dialog.Overlay, { className: styles.dialogOverlay }), /* @__PURE__ */ React__default.createElement(Dialog.Content, { className: styles.largeDialogContent, "data-editor-type": "frontmatter" }, /* @__PURE__ */ React__default.createElement(Dialog.Title, { className: styles.dialogTitle }, "Edit document frontmatter"), /* @__PURE__ */ React__default.createElement("form", { onSubmit: handleSubmit(onSubmit), onReset: () => setFrontmatterDialogOpen(false) }, /* @__PURE__ */ React__default.createElement("table", { className: styles.propertyEditorTable }, /* @__PURE__ */ React__default.createElement("colgroup", null, /* @__PURE__ */ React__default.createElement("col", null), /* @__PURE__ */ React__default.createElement("col", null), /* @__PURE__ */ React__default.createElement("col", null)), /* @__PURE__ */ React__default.createElement("thead", null, /* @__PURE__ */ React__default.createElement("tr", null, /* @__PURE__ */ React__default.createElement("th", null, "Key"), /* @__PURE__ */ React__default.createElement("th", null, "Value"), /* @__PURE__ */ React__default.createElement("th", null))), /* @__PURE__ */ React__default.createElement("tbody", null, fields.map((item, index) => {
50
- return /* @__PURE__ */ React__default.createElement("tr", { key: item.id }, /* @__PURE__ */ React__default.createElement("td", null, /* @__PURE__ */ React__default.createElement(TableInput, { ...register(`yamlConfig.${index}.key`, { required: true }), autofocusIfEmpty: true, readOnly })), /* @__PURE__ */ React__default.createElement("td", null, /* @__PURE__ */ React__default.createElement(TableInput, { ...register(`yamlConfig.${index}.value`, { required: true }), readOnly })), /* @__PURE__ */ React__default.createElement("td", null, /* @__PURE__ */ React__default.createElement("button", { type: "button", onClick: () => remove(index), className: styles.iconButton, disabled: readOnly }, /* @__PURE__ */ React__default.createElement(DeleteIcon, null))));
51
- })), /* @__PURE__ */ React__default.createElement("tfoot", null, /* @__PURE__ */ React__default.createElement("tr", null, /* @__PURE__ */ React__default.createElement("td", null, /* @__PURE__ */ React__default.createElement(
52
- "button",
49
+ return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(Dialog.Root, { open: frontmatterDialogOpen, onOpenChange: (open) => setFrontmatterDialogOpen(open) }, /* @__PURE__ */ React__default.createElement(Dialog.Portal, { container: editorRootElementRef == null ? void 0 : editorRootElementRef.current }, /* @__PURE__ */ React__default.createElement(Dialog.Overlay, { className: styles.dialogOverlay }), /* @__PURE__ */ React__default.createElement(Dialog.Content, { className: styles.largeDialogContent, "data-editor-type": "frontmatter" }, /* @__PURE__ */ React__default.createElement(Dialog.Title, { className: styles.dialogTitle }, "Edit document frontmatter"), /* @__PURE__ */ React__default.createElement(
50
+ "form",
53
51
  {
54
- disabled: readOnly,
55
- className: classNames(styles.primaryButton, styles.smallButton),
56
- type: "button",
57
- onClick: () => {
58
- append({ key: "", value: "" });
59
- }
52
+ onSubmit: (e) => {
53
+ void handleSubmit(onSubmit)(e);
54
+ e.nativeEvent.stopImmediatePropagation();
55
+ },
56
+ onReset: () => setFrontmatterDialogOpen(false)
60
57
  },
61
- "Add entry"
62
- ))))), /* @__PURE__ */ React__default.createElement("div", { style: { display: "flex", justifyContent: "flex-end", gap: "var(--spacing-2)" } }, /* @__PURE__ */ React__default.createElement("button", { type: "reset", className: styles.secondaryButton }, "Cancel"), /* @__PURE__ */ React__default.createElement("button", { type: "submit", className: styles.primaryButton }, "Save"))), /* @__PURE__ */ React__default.createElement(Dialog.Close, { asChild: true }, /* @__PURE__ */ React__default.createElement("button", { className: styles.dialogCloseButton, "aria-label": "Close" }, /* @__PURE__ */ React__default.createElement(CloseIcon, null)))))));
58
+ /* @__PURE__ */ React__default.createElement("table", { className: styles.propertyEditorTable }, /* @__PURE__ */ React__default.createElement("colgroup", null, /* @__PURE__ */ React__default.createElement("col", null), /* @__PURE__ */ React__default.createElement("col", null), /* @__PURE__ */ React__default.createElement("col", null)), /* @__PURE__ */ React__default.createElement("thead", null, /* @__PURE__ */ React__default.createElement("tr", null, /* @__PURE__ */ React__default.createElement("th", null, "Key"), /* @__PURE__ */ React__default.createElement("th", null, "Value"), /* @__PURE__ */ React__default.createElement("th", null))), /* @__PURE__ */ React__default.createElement("tbody", null, fields.map((item, index) => {
59
+ return /* @__PURE__ */ React__default.createElement("tr", { key: item.id }, /* @__PURE__ */ React__default.createElement("td", null, /* @__PURE__ */ React__default.createElement(TableInput, { ...register(`yamlConfig.${index}.key`, { required: true }), autofocusIfEmpty: true, readOnly })), /* @__PURE__ */ React__default.createElement("td", null, /* @__PURE__ */ React__default.createElement(TableInput, { ...register(`yamlConfig.${index}.value`, { required: true }), readOnly })), /* @__PURE__ */ React__default.createElement("td", null, /* @__PURE__ */ React__default.createElement("button", { type: "button", onClick: () => remove(index), className: styles.iconButton, disabled: readOnly }, /* @__PURE__ */ React__default.createElement(DeleteIcon, null))));
60
+ })), /* @__PURE__ */ React__default.createElement("tfoot", null, /* @__PURE__ */ React__default.createElement("tr", null, /* @__PURE__ */ React__default.createElement("td", null, /* @__PURE__ */ React__default.createElement(
61
+ "button",
62
+ {
63
+ disabled: readOnly,
64
+ className: classNames(styles.primaryButton, styles.smallButton),
65
+ type: "button",
66
+ onClick: () => {
67
+ append({ key: "", value: "" });
68
+ }
69
+ },
70
+ "Add entry"
71
+ ))))),
72
+ /* @__PURE__ */ React__default.createElement("div", { style: { display: "flex", justifyContent: "flex-end", gap: "var(--spacing-2)" } }, /* @__PURE__ */ React__default.createElement("button", { type: "submit", className: styles.primaryButton }, "Save"), /* @__PURE__ */ React__default.createElement("button", { type: "reset", className: styles.secondaryButton }, "Cancel"))
73
+ ), /* @__PURE__ */ React__default.createElement(Dialog.Close, { asChild: true }, /* @__PURE__ */ React__default.createElement("button", { className: styles.dialogCloseButton, "aria-label": "Close" }, /* @__PURE__ */ React__default.createElement(CloseIcon, null)))))));
63
74
  };
64
75
  const TableInput = React__default.forwardRef(({ className, autofocusIfEmpty: _, ...props }, ref) => {
65
76
  return /* @__PURE__ */ React__default.createElement("input", { className: classNames(styles.propertyEditorInput, className), ...props, ref });
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const ImageDialog: React.FC;
@@ -0,0 +1,68 @@
1
+ import * as Dialog from "@radix-ui/react-dialog";
2
+ import classNames from "classnames";
3
+ import React__default from "react";
4
+ import { useForm } from "react-hook-form";
5
+ import styles from "../../styles/ui.module.css.js";
6
+ import { corePluginHooks } from "../core/index.js";
7
+ import { imagePluginHooks } from "./index.js";
8
+ import { DownshiftAutoComplete } from "../core/ui/DownshiftAutoComplete.js";
9
+ const ImageDialog = () => {
10
+ const [imageAutocompleteSuggestions, state] = imagePluginHooks.useEmitterValues("imageAutocompleteSuggestions", "imageDialogState");
11
+ const saveImage = imagePluginHooks.usePublisher("saveImage");
12
+ const [editorRootElementRef] = corePluginHooks.useEmitterValues("editorRootElementRef");
13
+ const closeImageDialog = imagePluginHooks.usePublisher("closeImageDialog");
14
+ const { register, handleSubmit, control, setValue, reset } = useForm({
15
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
16
+ values: state.type === "editing" ? state.initialValues : {}
17
+ });
18
+ return /* @__PURE__ */ React__default.createElement(
19
+ Dialog.Root,
20
+ {
21
+ open: state.type !== "inactive",
22
+ onOpenChange: (open) => {
23
+ if (!open) {
24
+ closeImageDialog(true);
25
+ reset({ src: "", title: "", altText: "" });
26
+ }
27
+ }
28
+ },
29
+ /* @__PURE__ */ React__default.createElement(Dialog.Portal, { container: editorRootElementRef == null ? void 0 : editorRootElementRef.current }, /* @__PURE__ */ React__default.createElement(Dialog.Overlay, { className: styles.dialogOverlay }), /* @__PURE__ */ React__default.createElement(
30
+ Dialog.Content,
31
+ {
32
+ className: styles.dialogContent,
33
+ onOpenAutoFocus: (e) => {
34
+ e.preventDefault();
35
+ }
36
+ },
37
+ /* @__PURE__ */ React__default.createElement(
38
+ "form",
39
+ {
40
+ onSubmit: (e) => {
41
+ void handleSubmit(saveImage)(e);
42
+ reset({ src: "", title: "", altText: "" });
43
+ e.nativeEvent.stopImmediatePropagation();
44
+ },
45
+ className: styles.multiFieldForm
46
+ },
47
+ /* @__PURE__ */ React__default.createElement("div", { className: styles.formField }, /* @__PURE__ */ React__default.createElement("label", { htmlFor: "file" }, "Upload an image from your device:"), /* @__PURE__ */ React__default.createElement("input", { type: "file", ...register("file") })),
48
+ /* @__PURE__ */ React__default.createElement("div", { className: styles.formField }, /* @__PURE__ */ React__default.createElement("label", { htmlFor: "src" }, "Or add an image from an URL:"), /* @__PURE__ */ React__default.createElement(
49
+ DownshiftAutoComplete,
50
+ {
51
+ initialInputValue: state.type === "editing" ? state.initialValues.src || "" : "",
52
+ inputName: "src",
53
+ suggestions: imageAutocompleteSuggestions,
54
+ setValue,
55
+ control,
56
+ placeholder: "Select or paste an image src"
57
+ }
58
+ )),
59
+ /* @__PURE__ */ React__default.createElement("div", { className: styles.formField }, /* @__PURE__ */ React__default.createElement("label", { htmlFor: "alt" }, "Alt:"), /* @__PURE__ */ React__default.createElement("input", { type: "text", ...register("altText"), className: styles.textInput })),
60
+ /* @__PURE__ */ React__default.createElement("div", { className: styles.formField }, /* @__PURE__ */ React__default.createElement("label", { htmlFor: "title" }, "Title:"), /* @__PURE__ */ React__default.createElement("input", { type: "text", ...register("title"), className: styles.textInput })),
61
+ /* @__PURE__ */ React__default.createElement("div", { style: { display: "flex", justifyContent: "flex-end", gap: "var(--spacing-2)" } }, /* @__PURE__ */ React__default.createElement("button", { type: "submit", title: "Save", "aria-label": "Save", className: classNames(styles.primaryButton) }, "Save"), /* @__PURE__ */ React__default.createElement(Dialog.Close, { asChild: true }, /* @__PURE__ */ React__default.createElement("button", { type: "reset", title: "Cancel", "aria-label": "Cancel", className: classNames(styles.secondaryButton) }, "Cancel")))
62
+ )
63
+ ))
64
+ );
65
+ };
66
+ export {
67
+ ImageDialog
68
+ };
@@ -2,8 +2,9 @@
2
2
  export interface ImageEditorProps {
3
3
  nodeKey: string;
4
4
  src: string;
5
+ alt?: string;
5
6
  title?: string;
6
7
  width: number | 'inherit';
7
8
  height: number | 'inherit';
8
9
  }
9
- export declare function ImageEditor({ src, title, nodeKey, width, height }: ImageEditorProps): JSX.Element | null;
10
+ export declare function ImageEditor({ src, title, alt, nodeKey, width, height }: ImageEditorProps): JSX.Element | null;
@@ -2,12 +2,13 @@ import React__default from "react";
2
2
  import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext.js";
3
3
  import { useLexicalNodeSelection } from "@lexical/react/useLexicalNodeSelection.js";
4
4
  import { mergeRegister } from "@lexical/utils";
5
+ import classNames from "classnames";
5
6
  import { $isNodeSelection, $getSelection, $getNodeByKey, $setSelection, SELECTION_CHANGE_COMMAND, COMMAND_PRIORITY_LOW, CLICK_COMMAND, DRAGSTART_COMMAND, KEY_DELETE_COMMAND, KEY_BACKSPACE_COMMAND, KEY_ENTER_COMMAND, KEY_ESCAPE_COMMAND } from "lexical";
7
+ import { imagePluginHooks } from "./index.js";
8
+ import SettingsIcon from "../../icons/settings.svg.js";
6
9
  import styles from "../../styles/ui.module.css.js";
7
- import classNames from "classnames";
8
10
  import { $isImageNode } from "./ImageNode.js";
9
11
  import ImageResizer from "./ImageResizer.js";
10
- import { imagePluginHooks } from "./index.js";
11
12
  const imageCache = /* @__PURE__ */ new Set();
12
13
  function useSuspenseImage(src) {
13
14
  if (!imageCache.has(src)) {
@@ -23,6 +24,7 @@ function useSuspenseImage(src) {
23
24
  }
24
25
  function LazyImage({
25
26
  title,
27
+ alt,
26
28
  className,
27
29
  imageRef,
28
30
  src,
@@ -30,9 +32,21 @@ function LazyImage({
30
32
  height
31
33
  }) {
32
34
  useSuspenseImage(src);
33
- return /* @__PURE__ */ React__default.createElement("img", { className: className || void 0, src, title, ref: imageRef, draggable: "false", width, height });
35
+ return /* @__PURE__ */ React__default.createElement(
36
+ "img",
37
+ {
38
+ className: className || void 0,
39
+ alt,
40
+ src,
41
+ title,
42
+ ref: imageRef,
43
+ draggable: "false",
44
+ width,
45
+ height
46
+ }
47
+ );
34
48
  }
35
- function ImageEditor({ src, title, nodeKey, width, height }) {
49
+ function ImageEditor({ src, title, alt, nodeKey, width, height }) {
36
50
  const imageRef = React__default.useRef(null);
37
51
  const buttonRef = React__default.useRef(null);
38
52
  const [isSelected, setSelected, clearSelection] = useLexicalNodeSelection(nodeKey);
@@ -43,6 +57,7 @@ function ImageEditor({ src, title, nodeKey, width, height }) {
43
57
  const [disableImageResize] = imagePluginHooks.useEmitterValues("disableImageResize");
44
58
  const [imagePreviewHandler] = imagePluginHooks.useEmitterValues("imagePreviewHandler");
45
59
  const [imageSource, setImageSource] = React__default.useState(null);
60
+ const openEditImageDialog = imagePluginHooks.usePublisher("openEditImageDialog");
46
61
  const onDelete = React__default.useCallback(
47
62
  (payload) => {
48
63
  if (isSelected && $isNodeSelection($getSelection())) {
@@ -183,9 +198,27 @@ function ImageEditor({ src, title, nodeKey, width, height }) {
183
198
  }),
184
199
  src: imageSource,
185
200
  title: title || "",
201
+ alt: alt || "",
186
202
  imageRef
187
203
  }
188
- )), draggable && isFocused && !disableImageResize && /* @__PURE__ */ React__default.createElement(ImageResizer, { editor, imageRef, onResizeStart, onResizeEnd }))) : null;
204
+ )), draggable && isFocused && !disableImageResize && /* @__PURE__ */ React__default.createElement(ImageResizer, { editor, imageRef, onResizeStart, onResizeEnd }), /* @__PURE__ */ React__default.createElement(
205
+ "button",
206
+ {
207
+ className: classNames(styles.iconButton, styles.editImageButton),
208
+ title: "Edit image",
209
+ onClick: () => {
210
+ openEditImageDialog({
211
+ nodeKey,
212
+ initialValues: {
213
+ src: imageSource,
214
+ title: title || "",
215
+ altText: alt || ""
216
+ }
217
+ });
218
+ }
219
+ },
220
+ /* @__PURE__ */ React__default.createElement(SettingsIcon, null)
221
+ ))) : null;
189
222
  }
190
223
  export {
191
224
  ImageEditor
@@ -39,6 +39,8 @@ export declare class ImageNode extends DecoratorNode<JSX.Element> {
39
39
  getWidth(): 'inherit' | number;
40
40
  hasExplicitDimensions(): boolean;
41
41
  setTitle(title: string | undefined): void;
42
+ setSrc(src: string): void;
43
+ setAltText(altText: string | undefined): void;
42
44
  decorate(_parentEditor: LexicalEditor): JSX.Element;
43
45
  }
44
46
  /**
@@ -30,7 +30,7 @@ class ImageNode extends DecoratorNode {
30
30
  this.__height = height || "inherit";
31
31
  }
32
32
  static getType() {
33
- return "image";
33
+ return "icage";
34
34
  }
35
35
  static clone(node) {
36
36
  return new ImageNode(node.__src, node.__altText, node.__title, node.__width, node.__height, node.__key);
@@ -118,8 +118,24 @@ class ImageNode extends DecoratorNode {
118
118
  setTitle(title) {
119
119
  this.getWritable().__title = title;
120
120
  }
121
+ setSrc(src) {
122
+ this.getWritable().__src = src;
123
+ }
124
+ setAltText(altText) {
125
+ this.getWritable().__altText = altText ?? "";
126
+ }
121
127
  decorate(_parentEditor) {
122
- return /* @__PURE__ */ React__default.createElement(ImageEditor, { src: this.getSrc(), title: this.getTitle(), nodeKey: this.getKey(), width: this.__width, height: this.__height });
128
+ return /* @__PURE__ */ React__default.createElement(
129
+ ImageEditor,
130
+ {
131
+ src: this.getSrc(),
132
+ title: this.getTitle(),
133
+ nodeKey: this.getKey(),
134
+ width: this.__width,
135
+ height: this.__height,
136
+ alt: this.__altText
137
+ }
138
+ );
123
139
  }
124
140
  }
125
141
  function $createImageNode(options) {
@@ -15,6 +15,23 @@ import { CreateImageNodeOptions } from './ImageNode';
15
15
  export * from './ImageNode';
16
16
  export type ImageUploadHandler = ((image: File) => Promise<string>) | null;
17
17
  export type ImagePreviewHandler = ((imageSource: string) => Promise<string>) | null;
18
+ export interface InsertImageFormValues {
19
+ src?: string;
20
+ altText?: string;
21
+ title?: string;
22
+ file: FileList;
23
+ }
24
+ type InactiveImageDialogState = {
25
+ type: 'inactive';
26
+ };
27
+ type NewImageDialogState = {
28
+ type: 'new';
29
+ };
30
+ type EditingImageDialogState = {
31
+ type: 'editing';
32
+ nodeKey: string;
33
+ initialValues: Omit<InsertImageFormValues, 'file'>;
34
+ };
18
35
  /** @internal */
19
36
  export declare const imageSystem: SystemSpec<[SystemSpec<[], (r: Realm) => {
20
37
  activeEditor: RealmNode<LexicalEditor | null>;
@@ -127,10 +144,15 @@ export declare const imageSystem: SystemSpec<[SystemSpec<[], (r: Realm) => {
127
144
  insertDecoratorNode: RealmNode<() => DecoratorNode<unknown>>;
128
145
  onBlur: RealmNode<FocusEvent>;
129
146
  }]) => {
147
+ imageDialogState: RealmNode<InactiveImageDialogState | NewImageDialogState | EditingImageDialogState>;
148
+ saveImage: RealmNode<InsertImageFormValues>;
149
+ openNewImageDialog: RealmNode<true>;
150
+ openEditImageDialog: RealmNode<Omit<EditingImageDialogState, "type">>;
151
+ closeImageDialog: RealmNode<true>;
130
152
  imageUploadHandler: RealmNode<ImageUploadHandler>;
131
153
  imageAutocompleteSuggestions: RealmNode<string[]>;
132
154
  disableImageResize: RealmNode<boolean>;
133
- insertImage: RealmNode<string>;
155
+ insertImage: RealmNode<InsertImageFormValues>;
134
156
  imagePreviewHandler: RealmNode<ImagePreviewHandler>;
135
157
  }>;
136
158
  interface ImagePluginParams {
@@ -252,19 +274,29 @@ imagePlugin: PluginConstructor<SystemSpec<[SystemSpec<[], (r: Realm) => {
252
274
  insertDecoratorNode: RealmNode<() => DecoratorNode<unknown>>;
253
275
  onBlur: RealmNode<FocusEvent>;
254
276
  }]) => {
277
+ imageDialogState: RealmNode<InactiveImageDialogState | NewImageDialogState | EditingImageDialogState>;
278
+ saveImage: RealmNode<InsertImageFormValues>;
279
+ openNewImageDialog: RealmNode<true>;
280
+ openEditImageDialog: RealmNode<Omit<EditingImageDialogState, "type">>;
281
+ closeImageDialog: RealmNode<true>;
255
282
  imageUploadHandler: RealmNode<ImageUploadHandler>;
256
283
  imageAutocompleteSuggestions: RealmNode<string[]>;
257
284
  disableImageResize: RealmNode<boolean>;
258
- insertImage: RealmNode<string>;
285
+ insertImage: RealmNode<InsertImageFormValues>;
259
286
  imagePreviewHandler: RealmNode<ImagePreviewHandler>;
260
287
  }>, ImagePluginParams>,
261
288
  /** @internal */
262
289
  imagePluginHooks: {
263
290
  useRealmContext: () => TypedRealm<{
291
+ imageDialogState: RealmNode<InactiveImageDialogState | NewImageDialogState | EditingImageDialogState>;
292
+ saveImage: RealmNode<InsertImageFormValues>;
293
+ openNewImageDialog: RealmNode<true>;
294
+ openEditImageDialog: RealmNode<Omit<EditingImageDialogState, "type">>;
295
+ closeImageDialog: RealmNode<true>;
264
296
  imageUploadHandler: RealmNode<ImageUploadHandler>;
265
297
  imageAutocompleteSuggestions: RealmNode<string[]>;
266
298
  disableImageResize: RealmNode<boolean>;
267
- insertImage: RealmNode<string>;
299
+ insertImage: RealmNode<InsertImageFormValues>;
268
300
  imagePreviewHandler: RealmNode<ImagePreviewHandler>;
269
301
  } & {
270
302
  activeEditor: RealmNode<LexicalEditor | null>;
@@ -322,11 +354,16 @@ imagePluginHooks: {
322
354
  insertDecoratorNode: RealmNode<() => DecoratorNode<unknown>>;
323
355
  onBlur: RealmNode<FocusEvent>;
324
356
  }>;
325
- useEmitter: <K extends "jsxComponentDescriptors" | "jsxIsAvailable" | "toMarkdownOptions" | "toMarkdownExtensions" | "mdastExtensions" | "syntaxExtensions" | "markdown" | "activeEditor" | "inFocus" | "historyState" | "currentSelection" | "initialRootEditorState" | "rootEditor" | "createRootEditorSubscription" | "createActiveEditorSubscription" | "importVisitors" | "usedLexicalNodes" | "addImportVisitor" | "addLexicalNode" | "addSyntaxExtension" | "addMdastExtension" | "addToMarkdownExtension" | "addExportVisitor" | "exportVisitors" | "initialMarkdown" | "setMarkdown" | "editorRootElementRef" | "contentEditableClassName" | "placeholder" | "autoFocus" | "readOnly" | "composerChildren" | "addComposerChild" | "topAreaChildren" | "addTopAreaChild" | "nestedEditorChildren" | "addNestedEditorChild" | "editorWrappers" | "addEditorWrapper" | "currentFormat" | "editorInFocus" | "applyFormat" | "currentBlockType" | "applyBlockType" | "convertSelectionToNode" | "insertDecoratorNode" | "onBlur" | "imageUploadHandler" | "imageAutocompleteSuggestions" | "disableImageResize" | "insertImage" | "imagePreviewHandler">(key: K, callback: (value: ValueForKey<{
357
+ useEmitter: <K extends "jsxComponentDescriptors" | "jsxIsAvailable" | "toMarkdownOptions" | "toMarkdownExtensions" | "mdastExtensions" | "syntaxExtensions" | "markdown" | "activeEditor" | "inFocus" | "historyState" | "currentSelection" | "initialRootEditorState" | "rootEditor" | "createRootEditorSubscription" | "createActiveEditorSubscription" | "importVisitors" | "usedLexicalNodes" | "addImportVisitor" | "addLexicalNode" | "addSyntaxExtension" | "addMdastExtension" | "addToMarkdownExtension" | "addExportVisitor" | "exportVisitors" | "initialMarkdown" | "setMarkdown" | "editorRootElementRef" | "contentEditableClassName" | "placeholder" | "autoFocus" | "readOnly" | "composerChildren" | "addComposerChild" | "topAreaChildren" | "addTopAreaChild" | "nestedEditorChildren" | "addNestedEditorChild" | "editorWrappers" | "addEditorWrapper" | "currentFormat" | "editorInFocus" | "applyFormat" | "currentBlockType" | "applyBlockType" | "convertSelectionToNode" | "insertDecoratorNode" | "onBlur" | "imageDialogState" | "saveImage" | "openNewImageDialog" | "openEditImageDialog" | "closeImageDialog" | "imageUploadHandler" | "imageAutocompleteSuggestions" | "disableImageResize" | "insertImage" | "imagePreviewHandler">(key: K, callback: (value: ValueForKey<{
358
+ imageDialogState: RealmNode<InactiveImageDialogState | NewImageDialogState | EditingImageDialogState>;
359
+ saveImage: RealmNode<InsertImageFormValues>;
360
+ openNewImageDialog: RealmNode<true>;
361
+ openEditImageDialog: RealmNode<Omit<EditingImageDialogState, "type">>;
362
+ closeImageDialog: RealmNode<true>;
326
363
  imageUploadHandler: RealmNode<ImageUploadHandler>;
327
364
  imageAutocompleteSuggestions: RealmNode<string[]>;
328
365
  disableImageResize: RealmNode<boolean>;
329
- insertImage: RealmNode<string>;
366
+ insertImage: RealmNode<InsertImageFormValues>;
330
367
  imagePreviewHandler: RealmNode<ImagePreviewHandler>;
331
368
  } & {
332
369
  activeEditor: RealmNode<LexicalEditor | null>;
@@ -385,10 +422,15 @@ imagePluginHooks: {
385
422
  onBlur: RealmNode<FocusEvent>;
386
423
  }, K>) => void) => void;
387
424
  useEmitterValues: <K_1 extends SystemKeys<{
425
+ imageDialogState: RealmNode<InactiveImageDialogState | NewImageDialogState | EditingImageDialogState>;
426
+ saveImage: RealmNode<InsertImageFormValues>;
427
+ openNewImageDialog: RealmNode<true>;
428
+ openEditImageDialog: RealmNode<Omit<EditingImageDialogState, "type">>;
429
+ closeImageDialog: RealmNode<true>;
388
430
  imageUploadHandler: RealmNode<ImageUploadHandler>;
389
431
  imageAutocompleteSuggestions: RealmNode<string[]>;
390
432
  disableImageResize: RealmNode<boolean>;
391
- insertImage: RealmNode<string>;
433
+ insertImage: RealmNode<InsertImageFormValues>;
392
434
  imagePreviewHandler: RealmNode<ImagePreviewHandler>;
393
435
  } & {
394
436
  activeEditor: RealmNode<LexicalEditor | null>;
@@ -446,10 +488,15 @@ imagePluginHooks: {
446
488
  insertDecoratorNode: RealmNode<() => DecoratorNode<unknown>>;
447
489
  onBlur: RealmNode<FocusEvent>;
448
490
  }>>(...keys: K_1) => ValuesForKeys<{
491
+ imageDialogState: RealmNode<InactiveImageDialogState | NewImageDialogState | EditingImageDialogState>;
492
+ saveImage: RealmNode<InsertImageFormValues>;
493
+ openNewImageDialog: RealmNode<true>;
494
+ openEditImageDialog: RealmNode<Omit<EditingImageDialogState, "type">>;
495
+ closeImageDialog: RealmNode<true>;
449
496
  imageUploadHandler: RealmNode<ImageUploadHandler>;
450
497
  imageAutocompleteSuggestions: RealmNode<string[]>;
451
498
  disableImageResize: RealmNode<boolean>;
452
- insertImage: RealmNode<string>;
499
+ insertImage: RealmNode<InsertImageFormValues>;
453
500
  imagePreviewHandler: RealmNode<ImagePreviewHandler>;
454
501
  } & {
455
502
  activeEditor: RealmNode<LexicalEditor | null>;
@@ -508,10 +555,15 @@ imagePluginHooks: {
508
555
  onBlur: RealmNode<FocusEvent>;
509
556
  }, K_1>;
510
557
  usePubKeys: () => (values: SystemDict<{
558
+ imageDialogState: RealmNode<InactiveImageDialogState | NewImageDialogState | EditingImageDialogState>;
559
+ saveImage: RealmNode<InsertImageFormValues>;
560
+ openNewImageDialog: RealmNode<true>;
561
+ openEditImageDialog: RealmNode<Omit<EditingImageDialogState, "type">>;
562
+ closeImageDialog: RealmNode<true>;
511
563
  imageUploadHandler: RealmNode<ImageUploadHandler>;
512
564
  imageAutocompleteSuggestions: RealmNode<string[]>;
513
565
  disableImageResize: RealmNode<boolean>;
514
- insertImage: RealmNode<string>;
566
+ insertImage: RealmNode<InsertImageFormValues>;
515
567
  imagePreviewHandler: RealmNode<ImagePreviewHandler>;
516
568
  } & {
517
569
  activeEditor: RealmNode<LexicalEditor | null>;
@@ -569,11 +621,16 @@ imagePluginHooks: {
569
621
  insertDecoratorNode: RealmNode<() => DecoratorNode<unknown>>;
570
622
  onBlur: RealmNode<FocusEvent>;
571
623
  }>) => void;
572
- usePublisher: <K_2 extends "jsxComponentDescriptors" | "jsxIsAvailable" | "toMarkdownOptions" | "toMarkdownExtensions" | "mdastExtensions" | "syntaxExtensions" | "markdown" | "activeEditor" | "inFocus" | "historyState" | "currentSelection" | "initialRootEditorState" | "rootEditor" | "createRootEditorSubscription" | "createActiveEditorSubscription" | "importVisitors" | "usedLexicalNodes" | "addImportVisitor" | "addLexicalNode" | "addSyntaxExtension" | "addMdastExtension" | "addToMarkdownExtension" | "addExportVisitor" | "exportVisitors" | "initialMarkdown" | "setMarkdown" | "editorRootElementRef" | "contentEditableClassName" | "placeholder" | "autoFocus" | "readOnly" | "composerChildren" | "addComposerChild" | "topAreaChildren" | "addTopAreaChild" | "nestedEditorChildren" | "addNestedEditorChild" | "editorWrappers" | "addEditorWrapper" | "currentFormat" | "editorInFocus" | "applyFormat" | "currentBlockType" | "applyBlockType" | "convertSelectionToNode" | "insertDecoratorNode" | "onBlur" | "imageUploadHandler" | "imageAutocompleteSuggestions" | "disableImageResize" | "insertImage" | "imagePreviewHandler">(key: K_2) => (value: ValueForKey<{
624
+ usePublisher: <K_2 extends "jsxComponentDescriptors" | "jsxIsAvailable" | "toMarkdownOptions" | "toMarkdownExtensions" | "mdastExtensions" | "syntaxExtensions" | "markdown" | "activeEditor" | "inFocus" | "historyState" | "currentSelection" | "initialRootEditorState" | "rootEditor" | "createRootEditorSubscription" | "createActiveEditorSubscription" | "importVisitors" | "usedLexicalNodes" | "addImportVisitor" | "addLexicalNode" | "addSyntaxExtension" | "addMdastExtension" | "addToMarkdownExtension" | "addExportVisitor" | "exportVisitors" | "initialMarkdown" | "setMarkdown" | "editorRootElementRef" | "contentEditableClassName" | "placeholder" | "autoFocus" | "readOnly" | "composerChildren" | "addComposerChild" | "topAreaChildren" | "addTopAreaChild" | "nestedEditorChildren" | "addNestedEditorChild" | "editorWrappers" | "addEditorWrapper" | "currentFormat" | "editorInFocus" | "applyFormat" | "currentBlockType" | "applyBlockType" | "convertSelectionToNode" | "insertDecoratorNode" | "onBlur" | "imageDialogState" | "saveImage" | "openNewImageDialog" | "openEditImageDialog" | "closeImageDialog" | "imageUploadHandler" | "imageAutocompleteSuggestions" | "disableImageResize" | "insertImage" | "imagePreviewHandler">(key: K_2) => (value: ValueForKey<{
625
+ imageDialogState: RealmNode<InactiveImageDialogState | NewImageDialogState | EditingImageDialogState>;
626
+ saveImage: RealmNode<InsertImageFormValues>;
627
+ openNewImageDialog: RealmNode<true>;
628
+ openEditImageDialog: RealmNode<Omit<EditingImageDialogState, "type">>;
629
+ closeImageDialog: RealmNode<true>;
573
630
  imageUploadHandler: RealmNode<ImageUploadHandler>;
574
631
  imageAutocompleteSuggestions: RealmNode<string[]>;
575
632
  disableImageResize: RealmNode<boolean>;
576
- insertImage: RealmNode<string>;
633
+ insertImage: RealmNode<InsertImageFormValues>;
577
634
  imagePreviewHandler: RealmNode<ImagePreviewHandler>;
578
635
  } & {
579
636
  activeEditor: RealmNode<LexicalEditor | null>;