]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/ui/defaults/form-definitions.ts
Lexical: Started media node support
[bookstack] / resources / js / wysiwyg / ui / defaults / form-definitions.ts
1 import {EditorFormDefinition, EditorSelectFormFieldDefinition} from "../framework/forms";
2 import {EditorUiContext} from "../framework/core";
3 import {$createLinkNode} from "@lexical/link";
4 import {$createTextNode, $getSelection} from "lexical";
5 import {$createImageNode} from "../../nodes/image";
6 import {setEditorContentFromHtml} from "../../actions";
7 import {$createMediaNodeFromHtml} from "../../nodes/media";
8
9
10 export const link: EditorFormDefinition = {
11     submitText: 'Apply',
12     action(formData, context: EditorUiContext) {
13         context.editor.update(() => {
14
15             const selection = $getSelection();
16
17             const linkNode = $createLinkNode(formData.get('url')?.toString() || '', {
18                 title: formData.get('title')?.toString() || '',
19                 target: formData.get('target')?.toString() || '',
20             });
21             linkNode.append($createTextNode(formData.get('text')?.toString() || ''));
22
23             selection?.insertNodes([linkNode]);
24         });
25         return true;
26     },
27     fields: [
28         {
29             label: 'URL',
30             name: 'url',
31             type: 'text',
32         },
33         {
34             label: 'Text to display',
35             name: 'text',
36             type: 'text',
37         },
38         {
39             label: 'Title',
40             name: 'title',
41             type: 'text',
42         },
43         {
44             label: 'Open link in...',
45             name: 'target',
46             type: 'select',
47             valuesByLabel: {
48                 'Current window': '',
49                 'New window': '_blank',
50             }
51         } as EditorSelectFormFieldDefinition,
52     ],
53 };
54
55 export const image: EditorFormDefinition = {
56     submitText: 'Apply',
57     action(formData, context: EditorUiContext) {
58         context.editor.update(() => {
59             const selection = $getSelection();
60             const imageNode = $createImageNode(formData.get('src')?.toString() || '', {
61                 alt: formData.get('alt')?.toString() || '',
62                 height: Number(formData.get('height')?.toString() || '0'),
63                 width: Number(formData.get('width')?.toString() || '0'),
64             });
65             selection?.insertNodes([imageNode]);
66         });
67         return true;
68     },
69     fields: [
70         {
71             label: 'Source',
72             name: 'src',
73             type: 'text',
74         },
75         {
76             label: 'Alternative description',
77             name: 'alt',
78             type: 'text',
79         },
80         {
81             label: 'Width',
82             name: 'width',
83             type: 'text',
84         },
85         {
86             label: 'Height',
87             name: 'height',
88             type: 'text',
89         },
90     ],
91 };
92
93 export const media: EditorFormDefinition = {
94     submitText: 'Save',
95     action(formData, context: EditorUiContext) {
96
97         // TODO - Get media from selection
98
99         const embedCode = (formData.get('embed') || '').toString().trim();
100         if (embedCode) {
101             context.editor.update(() => {
102                 const node = $createMediaNodeFromHtml(embedCode);
103                 // TODO - Replace existing or insert new
104             });
105
106             return true;
107         }
108
109         const src = (formData.get('src') || '').toString().trim();
110         const height = (formData.get('height') || '').toString().trim();
111         const width = (formData.get('width') || '').toString().trim();
112
113         // TODO - Update existing or insert new
114
115         return true;
116     },
117     fields: [
118         {
119             label: 'Source',
120             name: 'src',
121             type: 'text',
122         },
123         {
124             label: 'Width',
125             name: 'width',
126             type: 'text',
127         },
128         {
129             label: 'Height',
130             name: 'height',
131             type: 'text',
132         },
133         // TODO - Tabbed interface to separate this option
134         {
135             label: 'Paste your embed code below:',
136             name: 'embed',
137             type: 'textarea',
138         },
139     ],
140 };
141
142 export const source: EditorFormDefinition = {
143     submitText: 'Save',
144     action(formData, context: EditorUiContext) {
145         setEditorContentFromHtml(context.editor, formData.get('source')?.toString() || '');
146         return true;
147     },
148     fields: [
149         {
150             label: 'Source',
151             name: 'source',
152             type: 'textarea',
153         },
154     ],
155 };