5 EditorSelectFormFieldDefinition
6 } from "../../framework/forms";
7 import {EditorUiContext} from "../../framework/core";
8 import {$createNodeSelection, $getSelection, $insertNodes, $setSelection} from "lexical";
9 import {$isImageNode, ImageNode} from "@lexical/rich-text/LexicalImageNode";
10 import {LinkNode} from "@lexical/link";
11 import {$createMediaNodeFromHtml, $createMediaNodeFromSrc, $isMediaNode, MediaNode} from "@lexical/rich-text/LexicalMediaNode";
12 import {$getNodeFromSelection, getLastSelection} from "../../../utils/selection";
13 import {EditorFormModal} from "../../framework/modals";
14 import {EditorActionField} from "../../framework/blocks/action-field";
15 import {EditorButton} from "../../framework/buttons";
16 import {showImageManager} from "../../../utils/images";
17 import searchImageIcon from "@icons/editor/image-search.svg";
18 import searchIcon from "@icons/search.svg";
19 import {showLinkSelector} from "../../../utils/links";
20 import {LinkField} from "../../framework/blocks/link-field";
21 import {insertOrUpdateLink} from "../../../utils/formats";
23 export function $showImageForm(image: ImageNode, context: EditorUiContext) {
24 const imageModal: EditorFormModal = context.manager.createModal('image');
25 const height = image.getHeight();
26 const width = image.getWidth();
30 alt: image.getAltText(),
31 height: height === 0 ? '' : String(height),
32 width: width === 0 ? '' : String(width),
35 imageModal.show(formData);
38 export const image: EditorFormDefinition = {
40 async action(formData, context: EditorUiContext) {
41 context.editor.update(() => {
42 const selection = getLastSelection(context.editor);
43 const selectedImage = $getNodeFromSelection(selection, $isImageNode);
44 if ($isImageNode(selectedImage)) {
45 selectedImage.setSrc(formData.get('src')?.toString() || '');
46 selectedImage.setAltText(formData.get('alt')?.toString() || '');
48 selectedImage.setWidth(Number(formData.get('width')?.toString() || '0'));
49 selectedImage.setHeight(Number(formData.get('height')?.toString() || '0'));
57 return new EditorActionField(
64 label: 'Browse files',
65 icon: searchImageIcon,
66 action(context: EditorUiContext) {
67 showImageManager((image) => {
68 const modal = context.manager.getActiveModal('image');
70 modal.getForm().setValues({
71 src: image.thumbs?.display || image.url,
82 label: 'Alternative description',
99 export function $showLinkForm(link: LinkNode|null, context: EditorUiContext) {
100 const linkModal = context.manager.createModal('link');
103 const formDefaults: Record<string, string> = {
105 text: link.getTextContent(),
106 title: link.getTitle() || '',
107 target: link.getTarget() || '',
110 context.editor.update(() => {
111 const selection = $createNodeSelection();
112 selection.add(link.getKey());
113 $setSelection(selection);
116 linkModal.show(formDefaults);
118 context.editor.getEditorState().read(() => {
119 const selection = $getSelection();
120 const text = selection?.getTextContent() || '';
121 const formDefaults = {text};
122 linkModal.show(formDefaults);
127 export const link: EditorFormDefinition = {
129 async action(formData, context: EditorUiContext) {
130 insertOrUpdateLink(context.editor, {
131 url: formData.get('url')?.toString() || '',
132 title: formData.get('title')?.toString() || '',
133 target: formData.get('target')?.toString() || '',
134 text: formData.get('text')?.toString() || '',
141 return new EditorActionField(
142 new LinkField(new EditorFormField({
148 label: 'Browse links',
150 action(context: EditorUiContext) {
151 showLinkSelector(entity => {
152 const modal = context.manager.getActiveModal('link');
154 modal.getForm().setValues({
167 label: 'Text to display',
177 label: 'Open link in...',
181 'Current window': '',
182 'New window': '_blank',
184 } as EditorSelectFormFieldDefinition,
188 export const media: EditorFormDefinition = {
190 async action(formData, context: EditorUiContext) {
191 const selectedNode: MediaNode|null = await (new Promise((res, rej) => {
192 context.editor.getEditorState().read(() => {
193 const node = $getNodeFromSelection($getSelection(), $isMediaNode);
194 res(node as MediaNode|null);
198 const embedCode = (formData.get('embed') || '').toString().trim();
200 context.editor.update(() => {
201 const node = $createMediaNodeFromHtml(embedCode);
202 if (selectedNode && node) {
203 selectedNode.replace(node)
205 $insertNodes([node]);
212 context.editor.update(() => {
213 const src = (formData.get('src') || '').toString().trim();
214 const height = (formData.get('height') || '').toString().trim();
215 const width = (formData.get('width') || '').toString().trim();
217 const updateNode = selectedNode || $createMediaNodeFromSrc(src);
218 updateNode.setSrc(src);
219 updateNode.setWidthAndHeight(width, height);
221 $insertNodes([updateNode]);
230 return new EditorFormTabs([
255 label: 'Paste your embed code below:',