Lexical: Added alignment detoggle, fixed inital focus area

This commit is contained in:
Dan Brown 2024-09-21 17:02:54 +01:00
parent 654a7a5d03
commit e6edd9340e
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
4 changed files with 19 additions and 16 deletions

View File

@ -22,5 +22,4 @@
## Bugs ## Bugs
- Focus/click area reduced to content area, single line on initial access
- List selection can get lost on nesting/unnesting - List selection can get lost on nesting/unnesting

View File

@ -1,4 +1,4 @@
import {$isElementNode, BaseSelection, LexicalEditor} from "lexical"; import {$isElementNode, BaseSelection} from "lexical";
import {EditorButtonDefinition} from "../../framework/buttons"; import {EditorButtonDefinition} from "../../framework/buttons";
import alignLeftIcon from "@icons/editor/align-left.svg"; import alignLeftIcon from "@icons/editor/align-left.svg";
import {EditorUiContext} from "../../framework/core"; import {EditorUiContext} from "../../framework/core";
@ -15,26 +15,28 @@ import {CommonBlockAlignment} from "../../../nodes/_common";
import {nodeHasAlignment} from "../../../utils/nodes"; import {nodeHasAlignment} from "../../../utils/nodes";
function setAlignmentForSelection(editor: LexicalEditor, alignment: CommonBlockAlignment): void { function setAlignmentForSelection(context: EditorUiContext, alignment: CommonBlockAlignment): void {
const selection = getLastSelection(editor); const selection = getLastSelection(context.editor);
const selectionNodes = selection?.getNodes() || []; const selectionNodes = selection?.getNodes() || [];
// Handle inline node selection alignment // Handle inline node selection alignment
if (selectionNodes.length === 1 && $isElementNode(selectionNodes[0]) && selectionNodes[0].isInline() && nodeHasAlignment(selectionNodes[0])) { if (selectionNodes.length === 1 && $isElementNode(selectionNodes[0]) && selectionNodes[0].isInline() && nodeHasAlignment(selectionNodes[0])) {
selectionNodes[0].setAlignment(alignment); selectionNodes[0].setAlignment(alignment);
$selectSingleNode(selectionNodes[0]); $selectSingleNode(selectionNodes[0]);
$toggleSelection(editor); context.manager.triggerFutureStateRefresh();
return; return;
} }
// Handle normal block/range alignment // Handle normal block/range alignment
const elements = $getBlockElementNodesInSelection(selection); const elements = $getBlockElementNodesInSelection(selection);
for (const node of elements) { const alignmentNodes = elements.filter(n => nodeHasAlignment(n));
if (nodeHasAlignment(node)) { const allAlreadyAligned = alignmentNodes.every(n => n.getAlignment() === alignment);
node.setAlignment(alignment) const newAlignment = allAlreadyAligned ? '' : alignment;
for (const node of alignmentNodes) {
node.setAlignment(newAlignment);
} }
}
$toggleSelection(editor); context.manager.triggerFutureStateRefresh();
} }
function setDirectionForSelection(context: EditorUiContext, direction: 'ltr' | 'rtl'): void { function setDirectionForSelection(context: EditorUiContext, direction: 'ltr' | 'rtl'): void {
@ -52,7 +54,7 @@ export const alignLeft: EditorButtonDefinition = {
label: 'Align left', label: 'Align left',
icon: alignLeftIcon, icon: alignLeftIcon,
action(context: EditorUiContext) { action(context: EditorUiContext) {
context.editor.update(() => setAlignmentForSelection(context.editor, 'left')); context.editor.update(() => setAlignmentForSelection(context, 'left'));
}, },
isActive(selection: BaseSelection|null) { isActive(selection: BaseSelection|null) {
return $selectionContainsAlignment(selection, 'left'); return $selectionContainsAlignment(selection, 'left');
@ -63,7 +65,7 @@ export const alignCenter: EditorButtonDefinition = {
label: 'Align center', label: 'Align center',
icon: alignCenterIcon, icon: alignCenterIcon,
action(context: EditorUiContext) { action(context: EditorUiContext) {
context.editor.update(() => setAlignmentForSelection(context.editor, 'center')); context.editor.update(() => setAlignmentForSelection(context, 'center'));
}, },
isActive(selection: BaseSelection|null) { isActive(selection: BaseSelection|null) {
return $selectionContainsAlignment(selection, 'center'); return $selectionContainsAlignment(selection, 'center');
@ -74,7 +76,7 @@ export const alignRight: EditorButtonDefinition = {
label: 'Align right', label: 'Align right',
icon: alignRightIcon, icon: alignRightIcon,
action(context: EditorUiContext) { action(context: EditorUiContext) {
context.editor.update(() => setAlignmentForSelection(context.editor, 'right')); context.editor.update(() => setAlignmentForSelection(context, 'right'));
}, },
isActive(selection: BaseSelection|null) { isActive(selection: BaseSelection|null) {
return $selectionContainsAlignment(selection, 'right'); return $selectionContainsAlignment(selection, 'right');
@ -85,7 +87,7 @@ export const alignJustify: EditorButtonDefinition = {
label: 'Align justify', label: 'Align justify',
icon: alignJustifyIcon, icon: alignJustifyIcon,
action(context: EditorUiContext) { action(context: EditorUiContext) {
context.editor.update(() => setAlignmentForSelection(context.editor, 'justify')); context.editor.update(() => setAlignmentForSelection(context, 'justify'));
}, },
isActive(selection: BaseSelection|null) { isActive(selection: BaseSelection|null) {
return $selectionContainsAlignment(selection, 'justify'); return $selectionContainsAlignment(selection, 'justify');

View File

@ -26,6 +26,7 @@ body.editor-is-fullscreen {
} }
} }
.editor-content-area { .editor-content-area {
min-height: 100%;
&:focus { &:focus {
outline: 0; outline: 0;
} }
@ -33,6 +34,7 @@ body.editor-is-fullscreen {
.editor-content-wrap { .editor-content-wrap {
position: relative; position: relative;
overflow-y: scroll; overflow-y: scroll;
flex: 1;
} }
// Buttons // Buttons

View File

@ -4,9 +4,9 @@
option:wysiwyg-editor:text-direction="{{ $locale->htmlDirection() }}" option:wysiwyg-editor:text-direction="{{ $locale->htmlDirection() }}"
option:wysiwyg-editor:image-upload-error-text="{{ trans('errors.image_upload_error') }}" option:wysiwyg-editor:image-upload-error-text="{{ trans('errors.image_upload_error') }}"
option:wysiwyg-editor:server-upload-limit-text="{{ trans('errors.server_upload_limit') }}" option:wysiwyg-editor:server-upload-limit-text="{{ trans('errors.server_upload_limit') }}"
class="flex-container-column flex-fill"> class="flex-container-column flex-fill flex">
<div class="editor-container flex-container-column flex-fill" refs="wysiwyg-editor@edit-container"> <div class="editor-container flex-container-column flex-fill flex" refs="wysiwyg-editor@edit-container">
</div> </div>
<div id="lexical-debug" style="white-space: pre-wrap; font-size: 12px; height: 200px; overflow-y: scroll; background-color: #000; padding: 1rem; border-radius: 4px; color: #FFF;"></div> <div id="lexical-debug" style="white-space: pre-wrap; font-size: 12px; height: 200px; overflow-y: scroll; background-color: #000; padding: 1rem; border-radius: 4px; color: #FFF;"></div>