]> BookStack Code Mirror - bookstack/blobdiff - resources/js/wysiwyg/ui/defaults/form-definitions.ts
Lexical: Got media node core work & form done
[bookstack] / resources / js / wysiwyg / ui / defaults / form-definitions.ts
index 457efa421e7171155d04771d0457e87004e19acd..a2242c338739f8993939a755eb3964e13c399b1b 100644 (file)
@@ -1,12 +1,17 @@
 import {EditorFormDefinition, EditorSelectFormFieldDefinition} from "../framework/forms";
 import {EditorUiContext} from "../framework/core";
 import {$createLinkNode} from "@lexical/link";
-import {$createTextNode, $getSelection} from "lexical";
+import {$createTextNode, $getSelection, LexicalNode} from "lexical";
+import {$createImageNode} from "../../nodes/image";
+import {setEditorContentFromHtml} from "../../actions";
+import {$createMediaNodeFromHtml, $createMediaNodeFromSrc, $isMediaNode, MediaNode} from "../../nodes/media";
+import {$getNodeFromSelection} from "../../helpers";
+import {$insertNodeToNearestRoot} from "@lexical/utils";
 
 
 export const link: EditorFormDefinition = {
     submitText: 'Apply',
-    action(formData, context: EditorUiContext) {
+    async action(formData, context: EditorUiContext) {
         context.editor.update(() => {
 
             const selection = $getSelection();
@@ -47,4 +52,121 @@ export const link: EditorFormDefinition = {
             }
         } as EditorSelectFormFieldDefinition,
     ],
+};
+
+export const image: EditorFormDefinition = {
+    submitText: 'Apply',
+    async action(formData, context: EditorUiContext) {
+        context.editor.update(() => {
+            const selection = $getSelection();
+            const imageNode = $createImageNode(formData.get('src')?.toString() || '', {
+                alt: formData.get('alt')?.toString() || '',
+                height: Number(formData.get('height')?.toString() || '0'),
+                width: Number(formData.get('width')?.toString() || '0'),
+            });
+            selection?.insertNodes([imageNode]);
+        });
+        return true;
+    },
+    fields: [
+        {
+            label: 'Source',
+            name: 'src',
+            type: 'text',
+        },
+        {
+            label: 'Alternative description',
+            name: 'alt',
+            type: 'text',
+        },
+        {
+            label: 'Width',
+            name: 'width',
+            type: 'text',
+        },
+        {
+            label: 'Height',
+            name: 'height',
+            type: 'text',
+        },
+    ],
+};
+
+export const media: EditorFormDefinition = {
+    submitText: 'Save',
+    async action(formData, context: EditorUiContext) {
+        const selectedNode: MediaNode|null = await (new Promise((res, rej) => {
+            context.editor.getEditorState().read(() => {
+                const node = $getNodeFromSelection($getSelection(), $isMediaNode);
+                res(node as MediaNode|null);
+            });
+        }));
+
+        const embedCode = (formData.get('embed') || '').toString().trim();
+        if (embedCode) {
+            context.editor.update(() => {
+                const node = $createMediaNodeFromHtml(embedCode);
+                if (selectedNode && node) {
+                    selectedNode.replace(node)
+                } else if (node) {
+                    $insertNodeToNearestRoot(node);
+                }
+            });
+
+            return true;
+        }
+
+        context.editor.update(() => {
+            const src = (formData.get('src') || '').toString().trim();
+            const height = (formData.get('height') || '').toString().trim();
+            const width = (formData.get('width') || '').toString().trim();
+
+            const updateNode = selectedNode || $createMediaNodeFromSrc(src);
+            updateNode.setSrc(src);
+            updateNode.setWidthAndHeight(width, height);
+            if (!selectedNode) {
+                $insertNodeToNearestRoot(updateNode);
+            }
+        });
+
+        return true;
+    },
+    fields: [
+        {
+            label: 'Source',
+            name: 'src',
+            type: 'text',
+        },
+        {
+            label: 'Width',
+            name: 'width',
+            type: 'text',
+        },
+        {
+            label: 'Height',
+            name: 'height',
+            type: 'text',
+        },
+        // TODO - Tabbed interface to separate this option
+        {
+            label: 'Paste your embed code below:',
+            name: 'embed',
+            type: 'textarea',
+        },
+    ],
+};
+
+export const source: EditorFormDefinition = {
+    submitText: 'Save',
+    async action(formData, context: EditorUiContext) {
+        setEditorContentFromHtml(context.editor, formData.get('source')?.toString() || '');
+        return true;
+    },
+    fields: [
+        {
+            label: 'Source',
+            name: 'source',
+            type: 'textarea',
+        },
+    ],
 };
\ No newline at end of file