@collabchron/notiq 0.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.
Files changed (188) hide show
  1. package/README.md +71 -0
  2. package/components.json +21 -0
  3. package/eslint.config.mjs +16 -0
  4. package/next.config.ts +12 -0
  5. package/package.json +108 -0
  6. package/postcss.config.mjs +5 -0
  7. package/public/file.svg +1 -0
  8. package/public/globe.svg +1 -0
  9. package/public/images/icons/plus.svg +10 -0
  10. package/public/next.svg +1 -0
  11. package/public/vercel.svg +1 -0
  12. package/public/window.svg +1 -0
  13. package/src/app/actions.ts +2 -0
  14. package/src/app/api/ai/route.ts +175 -0
  15. package/src/app/api/edgestore/[...edgestore]/route.ts +28 -0
  16. package/src/app/favicon.ico +0 -0
  17. package/src/app/globals.css +205 -0
  18. package/src/app/layout.tsx +38 -0
  19. package/src/app/page.tsx +12 -0
  20. package/src/components/editor/Core.tsx +220 -0
  21. package/src/components/editor/hooks/instructions-messages.ts +300 -0
  22. package/src/components/editor/hooks/use-mobile.ts +19 -0
  23. package/src/components/editor/hooks/useReport.ts +67 -0
  24. package/src/components/editor/hooks/useResizeObservert.ts +22 -0
  25. package/src/components/editor/index.tsx +39 -0
  26. package/src/components/editor/lexical-on-change.tsx +28 -0
  27. package/src/components/editor/nodes/CollapsibleNode/CollapsibleContainerNode.ts +92 -0
  28. package/src/components/editor/nodes/CollapsibleNode/CollapsibleContentNode.ts +65 -0
  29. package/src/components/editor/nodes/CollapsibleNode/CollapsibleTitleNode.ts +105 -0
  30. package/src/components/editor/nodes/EquationNode/EquationComponent.tsx +143 -0
  31. package/src/components/editor/nodes/EquationNode/EquationNode.tsx +170 -0
  32. package/src/components/editor/nodes/ExcalidrawNode/ExcalidrawComponent.tsx +228 -0
  33. package/src/components/editor/nodes/ExcalidrawNode/ExcalidrawImage.tsx +137 -0
  34. package/src/components/editor/nodes/ExcalidrawNode/ImageResizer.tsx +317 -0
  35. package/src/components/editor/nodes/ExcalidrawNode/index.tsx +204 -0
  36. package/src/components/editor/nodes/FigmaNode/FigmaNode.tsx +134 -0
  37. package/src/components/editor/nodes/Hint/HintComponet.tsx +221 -0
  38. package/src/components/editor/nodes/Hint/index.tsx +190 -0
  39. package/src/components/editor/nodes/ImageNode/index.tsx +328 -0
  40. package/src/components/editor/nodes/InlineImageNode/InlineImageComponent.tsx +383 -0
  41. package/src/components/editor/nodes/InlineImageNode/InlineImageNode.css +94 -0
  42. package/src/components/editor/nodes/InlineImageNode/InlineImageNode.tsx +309 -0
  43. package/src/components/editor/nodes/LayoutNode/LayoutContainerNode.ts +146 -0
  44. package/src/components/editor/nodes/LayoutNode/LayoutItemNode.ts +79 -0
  45. package/src/components/editor/nodes/PollNode/index.tsx +204 -0
  46. package/src/components/editor/nodes/Stepper/index.tsx +260 -0
  47. package/src/components/editor/nodes/TweetNode/index.tsx +214 -0
  48. package/src/components/editor/nodes/index.ts +81 -0
  49. package/src/components/editor/plugins/AutoEmbedPlugin/index.tsx +350 -0
  50. package/src/components/editor/plugins/AutoLinkPlugin/index.tsx +56 -0
  51. package/src/components/editor/plugins/CodeActionMenuPlugin/components/CopyButton.tsx +70 -0
  52. package/src/components/editor/plugins/CodeActionMenuPlugin/components/PrettierButton.tsx +192 -0
  53. package/src/components/editor/plugins/CodeActionMenuPlugin/index.tsx +217 -0
  54. package/src/components/editor/plugins/CodeActionMenuPlugin/utils.ts +26 -0
  55. package/src/components/editor/plugins/CodeHighlightPlugin/index.ts +21 -0
  56. package/src/components/editor/plugins/CollapsiblePlugin/Collapsible.css +76 -0
  57. package/src/components/editor/plugins/CollapsiblePlugin/index.ts +228 -0
  58. package/src/components/editor/plugins/DragDropPastePlugin/index.tsx +44 -0
  59. package/src/components/editor/plugins/DraggableBlockPlugin/index.tsx +52 -0
  60. package/src/components/editor/plugins/EquationsPlugin/index.tsx +85 -0
  61. package/src/components/editor/plugins/ExcalidrawPlugin/index.tsx +98 -0
  62. package/src/components/editor/plugins/FigmaPlugin/index.tsx +42 -0
  63. package/src/components/editor/plugins/FloatingLinkEditorPlugin/index.tsx +445 -0
  64. package/src/components/editor/plugins/FloatingTextFormatToolbarPlugin/index.tsx +275 -0
  65. package/src/components/editor/plugins/ImagesPlugin/index.tsx +222 -0
  66. package/src/components/editor/plugins/InlineImagePlugin/index.tsx +351 -0
  67. package/src/components/editor/plugins/LayoutPlugin/index.tsx +238 -0
  68. package/src/components/editor/plugins/LinkPlugin/index.tsx +36 -0
  69. package/src/components/editor/plugins/LinkWithMetaData/index.tsx +271 -0
  70. package/src/components/editor/plugins/MarkdownShortcutPlugin/index.tsx +11 -0
  71. package/src/components/editor/plugins/MarkdownTransformers/index.tsx +304 -0
  72. package/src/components/editor/plugins/PollPlugin/index.tsx +49 -0
  73. package/src/components/editor/plugins/ShortcutsPlugin/index.tsx +180 -0
  74. package/src/components/editor/plugins/ShortcutsPlugin/shortcuts.ts +253 -0
  75. package/src/components/editor/plugins/SlashCommand/index.tsx +621 -0
  76. package/src/components/editor/plugins/SpeechToTextPlugin/index.ts +127 -0
  77. package/src/components/editor/plugins/TabFocusPlugin/index.ts +58 -0
  78. package/src/components/editor/plugins/TableCellActionMenuPlugin/index.tsx +759 -0
  79. package/src/components/editor/plugins/TableCellResizer/index.tsx +438 -0
  80. package/src/components/editor/plugins/TableHoverActionsPlugin/index.tsx +314 -0
  81. package/src/components/editor/plugins/TablePlugin/index.tsx +99 -0
  82. package/src/components/editor/plugins/ToolbarPlugin/index.tsx +522 -0
  83. package/src/components/editor/plugins/TwitterPlugin/index.ts +35 -0
  84. package/src/components/editor/plugins/YouTubeNode/index.tsx +179 -0
  85. package/src/components/editor/plugins/YouTubePlugin/index.ts +41 -0
  86. package/src/components/editor/themes/editor-theme.ts +113 -0
  87. package/src/components/editor/themes/theme.css +377 -0
  88. package/src/components/editor/utils/ai.ts +291 -0
  89. package/src/components/editor/utils/canUseDOM.ts +12 -0
  90. package/src/components/editor/utils/editorFormatting.ts +282 -0
  91. package/src/components/editor/utils/environment.ts +50 -0
  92. package/src/components/editor/utils/extract-data.ts +166 -0
  93. package/src/components/editor/utils/getAllLexicalChildren.ts +13 -0
  94. package/src/components/editor/utils/getDOMRangeRect.ts +27 -0
  95. package/src/components/editor/utils/getSelectedNode.ts +27 -0
  96. package/src/components/editor/utils/gif.ts +29 -0
  97. package/src/components/editor/utils/invariant.ts +15 -0
  98. package/src/components/editor/utils/setFloatingElemPosition.ts +51 -0
  99. package/src/components/editor/utils/setFloatingElemPositionForLinkEditor.ts +40 -0
  100. package/src/components/editor/utils/setNodePlaceholderFromSelection/getNodePlaceholder.ts +51 -0
  101. package/src/components/editor/utils/setNodePlaceholderFromSelection/setNodePlaceholderFromSelection.ts +15 -0
  102. package/src/components/editor/utils/setNodePlaceholderFromSelection/setPlaceholderOnSelection.ts +114 -0
  103. package/src/components/editor/utils/setNodePlaceholderFromSelection/styles.css +6 -0
  104. package/src/components/editor/utils/url.ts +109 -0
  105. package/src/components/editor/utils/useLayoutEffect.ts +13 -0
  106. package/src/components/providers/QueryProvider.tsx +15 -0
  107. package/src/components/providers/SharedHistoryContext.tsx +28 -0
  108. package/src/components/providers/ToolbarContext.tsx +123 -0
  109. package/src/components/providers/theme-provider.tsx +11 -0
  110. package/src/components/theme/ModeToggle.tsx +40 -0
  111. package/src/components/ui/FileInput.tsx +40 -0
  112. package/src/components/ui/Input.css +32 -0
  113. package/src/components/ui/Select.css +42 -0
  114. package/src/components/ui/Select.tsx +36 -0
  115. package/src/components/ui/TextInput.tsx +48 -0
  116. package/src/components/ui/ai/ai-button.tsx +574 -0
  117. package/src/components/ui/ai/border.tsx +99 -0
  118. package/src/components/ui/ai/placeholder-input-vanish.tsx +282 -0
  119. package/src/components/ui/button.tsx +89 -0
  120. package/src/components/ui/card.tsx +76 -0
  121. package/src/components/ui/checkbox.tsx +30 -0
  122. package/src/components/ui/command.tsx +153 -0
  123. package/src/components/ui/dialog/Dialog.css +25 -0
  124. package/src/components/ui/dialog/Dialog.tsx +34 -0
  125. package/src/components/ui/dialog.tsx +122 -0
  126. package/src/components/ui/drop-downs/background-color.tsx +183 -0
  127. package/src/components/ui/drop-downs/block-format.tsx +159 -0
  128. package/src/components/ui/drop-downs/code.tsx +42 -0
  129. package/src/components/ui/drop-downs/color.tsx +177 -0
  130. package/src/components/ui/drop-downs/font-size.tsx +138 -0
  131. package/src/components/ui/drop-downs/font.tsx +155 -0
  132. package/src/components/ui/drop-downs/index.tsx +122 -0
  133. package/src/components/ui/drop-downs/insert-node.tsx +213 -0
  134. package/src/components/ui/drop-downs/text-align.tsx +123 -0
  135. package/src/components/ui/drop-downs/text-format.tsx +104 -0
  136. package/src/components/ui/dropdown-menu.tsx +201 -0
  137. package/src/components/ui/equation/EquationEditor.css +38 -0
  138. package/src/components/ui/equation/EquationEditor.tsx +56 -0
  139. package/src/components/ui/equation/KatexEquationAlterer.css +41 -0
  140. package/src/components/ui/equation/KatexEquationAlterer.tsx +83 -0
  141. package/src/components/ui/equation/KatexRenderer.tsx +66 -0
  142. package/src/components/ui/excalidraw/ExcalidrawModal.css +64 -0
  143. package/src/components/ui/excalidraw/ExcalidrawModal.tsx +234 -0
  144. package/src/components/ui/excalidraw/Modal.css +62 -0
  145. package/src/components/ui/excalidraw/Modal.tsx +110 -0
  146. package/src/components/ui/hover-card.tsx +29 -0
  147. package/src/components/ui/image/error-image.tsx +17 -0
  148. package/src/components/ui/image/file-upload.tsx +240 -0
  149. package/src/components/ui/image/image-resizer.tsx +297 -0
  150. package/src/components/ui/image/image-toolbar.tsx +264 -0
  151. package/src/components/ui/image/index.tsx +408 -0
  152. package/src/components/ui/image/lazy-image.tsx +68 -0
  153. package/src/components/ui/image/lazy-video.tsx +71 -0
  154. package/src/components/ui/input.tsx +22 -0
  155. package/src/components/ui/models/custom-dialog.tsx +320 -0
  156. package/src/components/ui/models/insert-gif.tsx +90 -0
  157. package/src/components/ui/models/insert-image.tsx +52 -0
  158. package/src/components/ui/models/insert-poll.tsx +29 -0
  159. package/src/components/ui/models/insert-table.tsx +62 -0
  160. package/src/components/ui/models/use-model.tsx +91 -0
  161. package/src/components/ui/poll/poll-component.tsx +304 -0
  162. package/src/components/ui/popover.tsx +33 -0
  163. package/src/components/ui/progress.tsx +28 -0
  164. package/src/components/ui/scroll-area.tsx +48 -0
  165. package/src/components/ui/separator.tsx +31 -0
  166. package/src/components/ui/skeleton.tsx +15 -0
  167. package/src/components/ui/sonner.tsx +31 -0
  168. package/src/components/ui/stepper/step.tsx +179 -0
  169. package/src/components/ui/stepper/stepper.tsx +89 -0
  170. package/src/components/ui/textarea.tsx +22 -0
  171. package/src/components/ui/toggle.tsx +71 -0
  172. package/src/components/ui/tooltip.tsx +32 -0
  173. package/src/components/ui/write/text-format-floting-toolbar.tsx +346 -0
  174. package/src/lib/edgestore.ts +9 -0
  175. package/src/lib/pinecone-client.ts +0 -0
  176. package/src/lib/utils.ts +6 -0
  177. package/src/utils/docSerialization.ts +77 -0
  178. package/src/utils/emoji-list.ts +16615 -0
  179. package/src/utils/getDOMRangeRect.ts +27 -0
  180. package/src/utils/getSelectedNode.ts +27 -0
  181. package/src/utils/getThemeSelector.ts +25 -0
  182. package/src/utils/isMobileWidth.ts +7 -0
  183. package/src/utils/joinClasses.ts +13 -0
  184. package/src/utils/setFloatingElemPosition.ts +74 -0
  185. package/src/utils/setFloatingElemPositionForLinkEditor.ts +46 -0
  186. package/src/utils/swipe.ts +127 -0
  187. package/src/utils/url.ts +38 -0
  188. package/tsconfig.json +27 -0
@@ -0,0 +1,190 @@
1
+ import {
2
+ createCommand,
3
+ createEditor,
4
+ DecoratorNode,
5
+ LexicalCommand,
6
+ LexicalEditor,
7
+ LexicalNode,
8
+ NodeKey,
9
+ SerializedEditor,
10
+ SerializedLexicalNode,
11
+ Spread,
12
+ $getSelection,
13
+ $isRangeSelection,
14
+ COMMAND_PRIORITY_LOW,
15
+ } from "lexical";
16
+ import React, { Suspense, useEffect } from "react";
17
+ import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
18
+ const HintComponent = React.lazy(() => import("./HintComponet"));
19
+
20
+ export type HintType = "success" | "warning" | "info" | "error" | "hint";
21
+
22
+
23
+ export type SerializedHint = Spread<
24
+ {
25
+ type: "hint";
26
+ variant: HintType;
27
+ caption: SerializedEditor;
28
+ },
29
+ SerializedLexicalNode
30
+ >;
31
+
32
+ export class Hint extends DecoratorNode<React.ReactElement> {
33
+ __variant: HintType;
34
+ __caption: LexicalEditor;
35
+
36
+ constructor(variant: HintType, caption?: LexicalEditor, key?: NodeKey) {
37
+ super(key);
38
+ this.__variant = variant;
39
+ if (!caption) {
40
+ const initialEditorState = {
41
+ root: {
42
+ children: [
43
+ {
44
+ children: [
45
+ {
46
+ detail: 0,
47
+ format: 0,
48
+ mode: "normal",
49
+ style: "",
50
+ text: " ",
51
+ type: "text",
52
+ version: 1,
53
+ },
54
+ ],
55
+ direction: null,
56
+ format: "",
57
+ indent: 0,
58
+ type: "paragraph",
59
+ version: 1,
60
+ textFormat: 0,
61
+ textStyle: "",
62
+ },
63
+ ],
64
+ direction: null,
65
+ format: "",
66
+ indent: 0,
67
+ type: "root",
68
+ version: 1,
69
+ },
70
+ };
71
+
72
+ const newEditor = createEditor();
73
+ const parsedEditorState = newEditor.parseEditorState(JSON.stringify(initialEditorState));
74
+ newEditor.setEditorState(parsedEditorState);
75
+
76
+ this.__caption = newEditor;
77
+ } else {
78
+ this.__caption = caption;
79
+ }
80
+ }
81
+
82
+ static getType(): string {
83
+ return "hint";
84
+ }
85
+
86
+ static clone(node: Hint): Hint {
87
+ return new Hint(node.__variant, node.__caption, node.__key);
88
+ }
89
+ static importJSON(serializedNode: SerializedHint): Hint {
90
+ return new Hint(
91
+ serializedNode.variant, // Change from type to variant
92
+ undefined
93
+ ).updateFromJSON(serializedNode);
94
+ }
95
+
96
+
97
+ setVariant(variant: HintType) {
98
+ const self = this.getWritable(); // Get mutable instance
99
+ self.__variant = variant;
100
+ return self;
101
+ }
102
+
103
+ createDOM(): HTMLElement {
104
+ const element = document.createElement("div");
105
+ element.className = `hint-${this.__type}`;
106
+ return element;
107
+ }
108
+
109
+ updateFromJSON(serializedNode: SerializedHint): this {
110
+ super.updateFromJSON(serializedNode);
111
+ const nestedEditor = this.__caption;
112
+ const editorState = nestedEditor.parseEditorState(serializedNode.caption.editorState);
113
+ if (!editorState.isEmpty()) {
114
+ nestedEditor.setEditorState(editorState);
115
+ }
116
+ return this;
117
+ }
118
+
119
+ exportJSON(): SerializedHint {
120
+ return {
121
+ ...super.exportJSON(),
122
+ variant: this.__variant,
123
+ type: "hint",
124
+ caption: this.__caption.toJSON(),
125
+ };
126
+ }
127
+
128
+ updateDOM(): false {
129
+ return false;
130
+ }
131
+
132
+ decorate(): React.ReactElement {
133
+ return (
134
+ <Suspense fallback={null}>
135
+ <HintComponent
136
+ type={this.__variant}
137
+ captionEditor={this.__caption}
138
+ nodeKey={this.getKey()}
139
+ />
140
+ </Suspense>
141
+ );
142
+ }
143
+ }
144
+
145
+ export function $isHintNode(
146
+ node: LexicalNode | null | undefined
147
+ ): node is Hint {
148
+ return node instanceof Hint;
149
+ }
150
+
151
+ export function $createHintNode(
152
+ type: HintType,
153
+ ): Hint {
154
+ return new Hint(type);
155
+ }
156
+
157
+ export const INSERT_HINT_COMMAND: LexicalCommand<HintType> = createCommand();
158
+
159
+ export function $insertHintNode(type: HintType) {
160
+ const selection = $getSelection();
161
+ if ($isRangeSelection(selection)) {
162
+ const hintNode = $createHintNode(type);
163
+ selection.insertNodes([hintNode]);
164
+ }
165
+ }
166
+
167
+
168
+
169
+ export default function HintPlugin() {
170
+ const [editor] = useLexicalComposerContext();
171
+ useEffect(() => {
172
+ if (!editor.hasNodes([Hint])) {
173
+ throw new Error("Hint: Hint not registered on editor");
174
+ }
175
+ }, [editor]);
176
+ useEffect(() => {
177
+ return editor.registerCommand(
178
+ INSERT_HINT_COMMAND,
179
+ (payload: HintType, editor: LexicalEditor) => {
180
+ editor.update(() => {
181
+ $insertHintNode(payload);
182
+ });
183
+ return true;
184
+ },
185
+ COMMAND_PRIORITY_LOW
186
+ );
187
+ }, [editor]);
188
+
189
+ return null;
190
+ }
@@ -0,0 +1,328 @@
1
+ import type {
2
+ DOMConversionMap,
3
+ DOMConversionOutput,
4
+ DOMExportOutput,
5
+ EditorConfig,
6
+ LexicalEditor,
7
+ LexicalNode,
8
+ LexicalUpdateJSON,
9
+ NodeKey,
10
+ SerializedEditor,
11
+ SerializedLexicalNode,
12
+ Spread,
13
+ } from "lexical";
14
+ import type { JSX } from "react";
15
+
16
+ import { $applyNodeReplacement, createEditor, DecoratorNode } from "lexical";
17
+ import * as React from "react";
18
+ import { Suspense } from "react";
19
+
20
+ const ImageComponent = React.lazy(() => import("@/components/ui/image"));
21
+ export type alignmentType =
22
+ | "center"
23
+ | "left"
24
+ | "right"
25
+ | "bottom"
26
+ | "end"
27
+ | "start";
28
+
29
+ export interface ImagePayload {
30
+ altText: string;
31
+ caption?: LexicalEditor;
32
+ height?: number;
33
+ key?: NodeKey;
34
+ maxWidth?: number;
35
+ showCaption?: boolean;
36
+ src: string;
37
+ captionsEnabled?: boolean;
38
+ alignment?: alignmentType;
39
+ width?: number;
40
+ rounded?: number;
41
+ }
42
+
43
+ function isGoogleDocCheckboxImg(img: HTMLImageElement): boolean {
44
+ return (
45
+ img.parentElement != null &&
46
+ img.parentElement.tagName === "LI" &&
47
+ img.previousSibling === null &&
48
+ img.getAttribute("aria-roledescription") === "checkbox"
49
+ );
50
+ }
51
+
52
+ function $convertImageElement(domNode: Node): null | DOMConversionOutput {
53
+ const img = domNode as HTMLImageElement;
54
+ if (img.src.startsWith("file:///") || isGoogleDocCheckboxImg(img)) {
55
+ return null;
56
+ }
57
+ const { alt: altText, src, width, height } = img;
58
+ const node = $createImageNode({
59
+ altText,
60
+ height,
61
+ src,
62
+ width,
63
+ alignment: "center",
64
+ rounded: 0,
65
+ });
66
+ return { node };
67
+ }
68
+
69
+ export type SerializedImageNode = Spread<
70
+ {
71
+ altText: string;
72
+ caption: SerializedEditor;
73
+ height?: number;
74
+ maxWidth: number;
75
+ showCaption: boolean;
76
+ src: string;
77
+ rounded?: number;
78
+ alignment: alignmentType;
79
+ width?: number;
80
+ },
81
+ SerializedLexicalNode
82
+ >;
83
+
84
+ export class ImageNode extends DecoratorNode<JSX.Element> {
85
+ __src: string;
86
+ __altText: string;
87
+ __width: "inherit" | number;
88
+ __height: "inherit" | number;
89
+ __maxWidth: number;
90
+ __showCaption: boolean;
91
+ __caption: LexicalEditor;
92
+ __captionsEnabled: boolean;
93
+ __rounded: number;
94
+ __alignment: alignmentType;
95
+
96
+ static getType(): string {
97
+ return "image";
98
+ }
99
+
100
+ static clone(node: ImageNode): ImageNode {
101
+ return new ImageNode(
102
+ node.__src,
103
+ node.__altText,
104
+ node.__maxWidth,
105
+ node.__width,
106
+ node.__height,
107
+ node.__showCaption,
108
+ node.__caption,
109
+ node.__captionsEnabled,
110
+ node.__key,
111
+ node.__rounded,
112
+ node.__alignment
113
+ );
114
+ }
115
+
116
+ static importJSON(serializedNode: SerializedImageNode): ImageNode {
117
+ const {
118
+ altText,
119
+ height,
120
+ width,
121
+ maxWidth,
122
+ src,
123
+ showCaption,
124
+ alignment,
125
+ rounded,
126
+ } = serializedNode;
127
+ return $createImageNode({
128
+ altText,
129
+ height,
130
+ maxWidth,
131
+ showCaption,
132
+ src,
133
+ width,
134
+ rounded,
135
+ alignment,
136
+ }).updateFromJSON(serializedNode);
137
+ }
138
+ setAlignment(newAlignment: alignmentType) {
139
+ const writable = this.getWritable();
140
+ writable.__alignment = newAlignment;
141
+ }
142
+ getWidth(): number | "inherit" {
143
+ return this.__width;
144
+ }
145
+ getHeight(): number | "inherit" {
146
+ return this.__height;
147
+ }
148
+ setRounded(rounded: number): void {
149
+ const writable = this.getWritable();
150
+ writable.__rounded = rounded;
151
+ }
152
+ updateFromJSON(serializedNode: LexicalUpdateJSON<SerializedImageNode>): this {
153
+ const node = super.updateFromJSON(serializedNode);
154
+ const { caption } = serializedNode;
155
+
156
+ const nestedEditor = node.__caption;
157
+ const editorState = nestedEditor.parseEditorState(caption.editorState);
158
+ if (!editorState.isEmpty()) {
159
+ nestedEditor.setEditorState(editorState);
160
+ }
161
+ return node;
162
+ }
163
+
164
+ exportDOM(): DOMExportOutput {
165
+ const element = document.createElement("img");
166
+ element.setAttribute("src", this.__src);
167
+ element.setAttribute("alt", this.__altText);
168
+ element.setAttribute("width", this.__width.toString());
169
+ element.setAttribute("height", this.__height.toString());
170
+ return { element };
171
+ }
172
+
173
+ static importDOM(): DOMConversionMap | null {
174
+ return {
175
+ img: () => ({
176
+ conversion: $convertImageElement,
177
+ priority: 0,
178
+ }),
179
+ };
180
+ }
181
+ setSrc(src: string) {
182
+ const self = this.getWritable();
183
+ self.__src = src;
184
+ }
185
+
186
+ constructor(
187
+ src: string,
188
+ altText: string,
189
+ maxWidth: number,
190
+ width?: "inherit" | number,
191
+ height?: "inherit" | number,
192
+ showCaption?: boolean,
193
+ caption?: LexicalEditor,
194
+ captionsEnabled?: boolean,
195
+ key?: NodeKey,
196
+ rounded: number = 0,
197
+ alignment: alignmentType = "center"
198
+ ) {
199
+ super(key);
200
+ this.__src = src;
201
+ this.__altText = altText;
202
+ this.__maxWidth = maxWidth;
203
+ this.__width = width || "inherit";
204
+ this.__height = height || "inherit";
205
+ this.__showCaption = showCaption || false;
206
+ this.__alignment = alignment;
207
+ this.__rounded = rounded;
208
+ this.__caption =
209
+ caption ||
210
+ createEditor({
211
+ nodes: [],
212
+ });
213
+ this.__captionsEnabled = captionsEnabled || captionsEnabled === undefined;
214
+ }
215
+
216
+ exportJSON(): SerializedImageNode {
217
+ return {
218
+ ...super.exportJSON(),
219
+ altText: this.getAltText(),
220
+ caption: this.__caption.toJSON(),
221
+ height: this.__height === "inherit" ? 0 : this.__height,
222
+ maxWidth: this.__maxWidth,
223
+ showCaption: this.__showCaption,
224
+ rounded: this.__rounded,
225
+ alignment: this.__alignment,
226
+ src: this.getSrc(),
227
+ width: this.__width === "inherit" ? 0 : this.__width,
228
+ };
229
+ }
230
+
231
+ setWidthAndHeight(
232
+ width: "inherit" | number,
233
+ height: "inherit" | number
234
+ ): void {
235
+ const writable = this.getWritable();
236
+ writable.__width = width;
237
+ writable.__height = height;
238
+ }
239
+
240
+ setShowCaption(showCaption: boolean): void {
241
+ const writable = this.getWritable();
242
+ writable.__showCaption = showCaption;
243
+ }
244
+
245
+ createDOM(config: EditorConfig): HTMLElement {
246
+ const span = document.createElement("span");
247
+ const theme = config.theme;
248
+ const className = theme.image;
249
+ if (className !== undefined) {
250
+ span.className = className;
251
+ }
252
+ return span;
253
+ }
254
+
255
+ updateDOM(): false {
256
+ return false;
257
+ }
258
+
259
+ getSrc(): string {
260
+ return this.__src;
261
+ }
262
+
263
+ getAltText(): string {
264
+ return this.__altText;
265
+ }
266
+
267
+ decorate(): JSX.Element {
268
+ return (
269
+ <Suspense fallback={null}>
270
+ <div
271
+ style={{
272
+ textAlign: this.__alignment as React.CSSProperties["textAlign"],
273
+ }}
274
+ >
275
+ <ImageComponent
276
+ src={this.__src}
277
+ altText={this.__altText}
278
+ width={this.__width}
279
+ height={this.__height}
280
+ maxWidth={this.__maxWidth}
281
+ nodeKey={this.getKey()}
282
+ showCaption={this.__showCaption}
283
+ caption={this.__caption}
284
+ captionsEnabled={this.__captionsEnabled}
285
+ resizable={true}
286
+ rounded={this.__rounded}
287
+ />
288
+ </div>
289
+ </Suspense>
290
+ );
291
+ }
292
+ }
293
+
294
+ export function $createImageNode({
295
+ altText,
296
+ height,
297
+ maxWidth = 500,
298
+ captionsEnabled,
299
+ src,
300
+ width,
301
+ showCaption,
302
+ caption,
303
+ key,
304
+ rounded,
305
+ alignment,
306
+ }: ImagePayload): ImageNode {
307
+ return $applyNodeReplacement(
308
+ new ImageNode(
309
+ src,
310
+ altText,
311
+ maxWidth,
312
+ width,
313
+ height,
314
+ showCaption,
315
+ caption,
316
+ captionsEnabled,
317
+ key,
318
+ rounded,
319
+ alignment
320
+ )
321
+ );
322
+ }
323
+
324
+ export function $isImageNode(
325
+ node: LexicalNode | null | undefined
326
+ ): node is ImageNode {
327
+ return node instanceof ImageNode;
328
+ }