1 import {$isElementNode, BaseSelection, LexicalEditor} from "lexical";
2 import {EditorButtonDefinition} from "../../framework/buttons";
3 import alignLeftIcon from "@icons/editor/align-left.svg";
4 import {EditorUiContext} from "../../framework/core";
5 import alignCenterIcon from "@icons/editor/align-center.svg";
6 import alignRightIcon from "@icons/editor/align-right.svg";
7 import alignJustifyIcon from "@icons/editor/align-justify.svg";
8 import ltrIcon from "@icons/editor/direction-ltr.svg";
9 import rtlIcon from "@icons/editor/direction-rtl.svg";
11 $getBlockElementNodesInSelection,
12 $selectionContainsAlignment, $selectionContainsDirection, $selectSingleNode, $toggleSelection, getLastSelection
13 } from "../../../utils/selection";
14 import {CommonBlockAlignment} from "../../../nodes/_common";
15 import {nodeHasAlignment} from "../../../utils/nodes";
18 function setAlignmentForSelection(editor: LexicalEditor, alignment: CommonBlockAlignment): void {
19 const selection = getLastSelection(editor);
20 const selectionNodes = selection?.getNodes() || [];
22 // Handle inline node selection alignment
23 if (selectionNodes.length === 1 && $isElementNode(selectionNodes[0]) && selectionNodes[0].isInline() && nodeHasAlignment(selectionNodes[0])) {
24 selectionNodes[0].setAlignment(alignment);
25 $selectSingleNode(selectionNodes[0]);
26 $toggleSelection(editor);
30 // Handle normal block/range alignment
31 const elements = $getBlockElementNodesInSelection(selection);
32 for (const node of elements) {
33 if (nodeHasAlignment(node)) {
34 node.setAlignment(alignment)
37 $toggleSelection(editor);
40 function setDirectionForSelection(context: EditorUiContext, direction: 'ltr' | 'rtl'): void {
41 const selection = getLastSelection(context.editor);
43 const elements = $getBlockElementNodesInSelection(selection);
44 for (const node of elements) {
45 node.setDirection(direction);
48 context.manager.triggerFutureStateRefresh();
51 export const alignLeft: EditorButtonDefinition = {
54 action(context: EditorUiContext) {
55 context.editor.update(() => setAlignmentForSelection(context.editor, 'left'));
57 isActive(selection: BaseSelection|null) {
58 return $selectionContainsAlignment(selection, 'left');
62 export const alignCenter: EditorButtonDefinition = {
63 label: 'Align center',
64 icon: alignCenterIcon,
65 action(context: EditorUiContext) {
66 context.editor.update(() => setAlignmentForSelection(context.editor, 'center'));
68 isActive(selection: BaseSelection|null) {
69 return $selectionContainsAlignment(selection, 'center');
73 export const alignRight: EditorButtonDefinition = {
76 action(context: EditorUiContext) {
77 context.editor.update(() => setAlignmentForSelection(context.editor, 'right'));
79 isActive(selection: BaseSelection|null) {
80 return $selectionContainsAlignment(selection, 'right');
84 export const alignJustify: EditorButtonDefinition = {
85 label: 'Align justify',
86 icon: alignJustifyIcon,
87 action(context: EditorUiContext) {
88 context.editor.update(() => setAlignmentForSelection(context.editor, 'justify'));
90 isActive(selection: BaseSelection|null) {
91 return $selectionContainsAlignment(selection, 'justify');
95 export const directionLTR: EditorButtonDefinition = {
96 label: 'Left to right',
98 action(context: EditorUiContext) {
99 context.editor.update(() => setDirectionForSelection(context, 'ltr'));
101 isActive(selection: BaseSelection|null) {
102 return $selectionContainsDirection(selection, 'ltr');
106 export const directionRTL: EditorButtonDefinition = {
107 label: 'Right to left',
109 action(context: EditorUiContext) {
110 context.editor.update(() => setDirectionForSelection(context, 'rtl'));
112 isActive(selection: BaseSelection|null) {
113 return $selectionContainsDirection(selection, 'rtl');