mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-07-30 04:23:11 +03:00
Lexical: Range of bug fixes, Updated lexical version
- Updated selection change detection to be more accurate - Added UI refresh for extra actions - Fixed remove link deleting contents
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
import {createEditor, CreateEditorArgs, LexicalEditor} from 'lexical';
|
||||
import {$getSelection, createEditor, CreateEditorArgs, isCurrentlyReadOnlyMode, LexicalEditor} from 'lexical';
|
||||
import {createEmptyHistoryState, registerHistory} from '@lexical/history';
|
||||
import {registerRichText} from '@lexical/rich-text';
|
||||
import {mergeRegister} from '@lexical/utils';
|
||||
@ -69,7 +69,19 @@ export function createPageEditorInstance(container: HTMLElement, htmlContent: st
|
||||
}
|
||||
|
||||
let changeFromLoading = true;
|
||||
editor.registerUpdateListener(({editorState, dirtyElements, dirtyLeaves}) => {
|
||||
editor.registerUpdateListener(({dirtyElements, dirtyLeaves, editorState, prevEditorState}) => {
|
||||
// Watch for selection changes to update the UI on change
|
||||
// Used to be done via SELECTION_CHANGE_COMMAND but this would not always emit
|
||||
// for all selection changes, so this proved more reliable.
|
||||
const selectionChange = !(prevEditorState._selection?.is(editorState._selection) || false);
|
||||
if (selectionChange) {
|
||||
editor.update(() => {
|
||||
const selection = $getSelection();
|
||||
context.manager.triggerStateUpdate({
|
||||
editor, selection,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Emit change event to component system (for draft detection) on actual user content change
|
||||
if (dirtyElements.size > 0 || dirtyLeaves.size > 0) {
|
||||
|
@ -40,7 +40,7 @@ export class ImageNode extends ElementNode {
|
||||
alt: node.__alt,
|
||||
width: node.__width,
|
||||
height: node.__height,
|
||||
});
|
||||
}, node.__key);
|
||||
newNode.__alignment = node.__alignment;
|
||||
return newNode;
|
||||
}
|
||||
|
@ -16,6 +16,4 @@
|
||||
|
||||
## Bugs
|
||||
|
||||
- Removing link around image via button deletes image, not just link
|
||||
- `SELECTION_CHANGE_COMMAND` not fired when clicking out of a table cell. Prevents toolbar hiding on table unselect.
|
||||
- Template drag/drop not handled when outside core editor area (ignored in margin area).
|
@ -19,6 +19,7 @@ export const undo: EditorButtonDefinition = {
|
||||
icon: undoIcon,
|
||||
action(context: EditorUiContext) {
|
||||
context.editor.dispatchCommand(UNDO_COMMAND, undefined);
|
||||
context.manager.triggerFutureStateRefresh();
|
||||
},
|
||||
isActive(selection: BaseSelection|null): boolean {
|
||||
return false;
|
||||
@ -38,6 +39,7 @@ export const redo: EditorButtonDefinition = {
|
||||
icon: redoIcon,
|
||||
action(context: EditorUiContext) {
|
||||
context.editor.dispatchCommand(REDO_COMMAND, undefined);
|
||||
context.manager.triggerFutureStateRefresh();
|
||||
},
|
||||
isActive(selection: BaseSelection|null): boolean {
|
||||
return false;
|
||||
|
@ -6,7 +6,7 @@ import {
|
||||
$getRoot,
|
||||
$getSelection, $insertNodes,
|
||||
BaseSelection,
|
||||
ElementNode
|
||||
ElementNode, isCurrentlyReadOnlyMode
|
||||
} from "lexical";
|
||||
import {$isLinkNode, LinkNode} from "@lexical/link";
|
||||
import unlinkIcon from "@icons/editor/unlink.svg";
|
||||
@ -54,16 +54,17 @@ export const unlink: EditorButtonDefinition = {
|
||||
context.editor.update(() => {
|
||||
const selection = getLastSelection(context.editor);
|
||||
const selectedLink = $getNodeFromSelection(selection, $isLinkNode) as LinkNode | null;
|
||||
const selectionPoints = selection?.getStartEndPoints();
|
||||
|
||||
if (selectedLink) {
|
||||
const newNode = $createTextNode(selectedLink.getTextContent());
|
||||
selectedLink.replace(newNode);
|
||||
if (selectionPoints?.length === 2) {
|
||||
newNode.select(selectionPoints[0].offset, selectionPoints[1].offset);
|
||||
} else {
|
||||
newNode.select();
|
||||
const contents = selectedLink.getChildren().reverse();
|
||||
for (const child of contents) {
|
||||
selectedLink.insertAfter(child);
|
||||
}
|
||||
selectedLink.remove();
|
||||
|
||||
contents[contents.length - 1].selectStart();
|
||||
|
||||
context.manager.triggerFutureStateRefresh();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -108,7 +108,7 @@ export class EditorUIManager {
|
||||
this.contextToolbarDefinitionsByKey[key] = definition;
|
||||
}
|
||||
|
||||
protected triggerStateUpdate(update: EditorUiStateUpdate): void {
|
||||
triggerStateUpdate(update: EditorUiStateUpdate): void {
|
||||
setLastSelection(update.editor, update.selection);
|
||||
this.toolbar?.updateState(update);
|
||||
this.updateContextToolbars(update);
|
||||
@ -120,9 +120,20 @@ export class EditorUIManager {
|
||||
|
||||
triggerStateRefresh(): void {
|
||||
const editor = this.getContext().editor;
|
||||
this.triggerStateUpdate({
|
||||
const update = {
|
||||
editor,
|
||||
selection: getLastSelection(editor),
|
||||
};
|
||||
|
||||
this.triggerStateUpdate(update);
|
||||
this.updateContextToolbars(update);
|
||||
}
|
||||
|
||||
triggerFutureStateRefresh(): void {
|
||||
requestAnimationFrame(() => {
|
||||
this.getContext().editor.getEditorState().read(() => {
|
||||
this.triggerStateRefresh();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -195,15 +206,6 @@ export class EditorUIManager {
|
||||
}
|
||||
|
||||
protected setupEditor(editor: LexicalEditor) {
|
||||
// Update button states on editor selection change
|
||||
editor.registerCommand(SELECTION_CHANGE_COMMAND, () => {
|
||||
this.triggerStateUpdate({
|
||||
editor: editor,
|
||||
selection: $getSelection(),
|
||||
});
|
||||
return false;
|
||||
}, COMMAND_PRIORITY_LOW);
|
||||
|
||||
// Register our DOM decorate listener with the editor
|
||||
const domDecorateListener: DecoratorListener<EditorDecoratorAdapter> = (decorators: Record<NodeKey, EditorDecoratorAdapter>) => {
|
||||
editor.getEditorState().read(() => {
|
||||
|
Reference in New Issue
Block a user