]> BookStack Code Mirror - bookstack/commitdiff
Lexical: Added RTL/LTR actions
authorDan Brown <redacted>
Mon, 16 Sep 2024 11:29:46 +0000 (12:29 +0100)
committerDan Brown <redacted>
Mon, 16 Sep 2024 11:29:46 +0000 (12:29 +0100)
Kinda useless though due to Lexical reconciler :(

resources/icons/editor/direction-ltr.svg [new file with mode: 0644]
resources/icons/editor/direction-rtl.svg [new file with mode: 0644]
resources/js/wysiwyg/ui/defaults/buttons/alignments.ts
resources/js/wysiwyg/ui/toolbars.ts
resources/js/wysiwyg/utils/selection.ts

diff --git a/resources/icons/editor/direction-ltr.svg b/resources/icons/editor/direction-ltr.svg
new file mode 100644 (file)
index 0000000..16befc7
--- /dev/null
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M440-800v400q0 17-11.5 28.5T400-360q-17 0-28.5-11.5T360-400v-160q-66 0-113-47t-47-113q0-66 47-113t113-47h280q17 0 28.5 11.5T680-840q0 17-11.5 28.5T640-800h-40v400q0 17-11.5 28.5T560-360q-17 0-28.5-11.5T520-400v-400h-80Zm-80 160v-160q-33 0-56.5 23.5T280-720q0 33 23.5 56.5T360-640Zm0-80Zm328 520H160q-17 0-28.5-11.5T120-240q0-17 11.5-28.5T160-280h528l-36-36q-11-11-11-28t11-28q11-11 28-11t28 11l104 104q12 12 12 28t-12 28L708-108q-11 11-28 11t-28-11q-11-11-11-28t11-28l36-36Z"/></svg>
\ No newline at end of file
diff --git a/resources/icons/editor/direction-rtl.svg b/resources/icons/editor/direction-rtl.svg
new file mode 100644 (file)
index 0000000..5125472
--- /dev/null
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M440-800v400q0 17-11.5 28.5T400-360q-17 0-28.5-11.5T360-400v-160q-66 0-113-47t-47-113q0-66 47-113t113-47h280q17 0 28.5 11.5T680-840q0 17-11.5 28.5T640-800h-40v400q0 17-11.5 28.5T560-360q-17 0-28.5-11.5T520-400v-400h-80ZM272-200l36 36q11 11 11 28t-11 28q-11 11-28 11t-28-11L148-212q-12-12-12-28t12-28l104-104q11-11 28-11t28 11q11 11 11 28t-11 28l-36 36h528q17 0 28.5 11.5T840-240q0 17-11.5 28.5T800-200H272Zm88-440v-160q-33 0-56.5 23.5T280-720q0 33 23.5 56.5T360-640Zm0-80Z"/></svg>
\ No newline at end of file
index 329b1195609a4821b9489bf5a8e9585aa415bea2..130fd6b726c676ca5f0a1f9d157eb9288f3f147f 100644 (file)
@@ -5,15 +5,17 @@ import {EditorUiContext} from "../../framework/core";
 import alignCenterIcon from "@icons/editor/align-center.svg";
 import alignRightIcon from "@icons/editor/align-right.svg";
 import alignJustifyIcon from "@icons/editor/align-justify.svg";
+import ltrIcon from "@icons/editor/direction-ltr.svg";
+import rtlIcon from "@icons/editor/direction-rtl.svg";
 import {
     $getBlockElementNodesInSelection,
-    $selectionContainsAlignment, $selectSingleNode, $toggleSelection, getLastSelection
+    $selectionContainsAlignment, $selectionContainsDirection, $selectSingleNode, $toggleSelection, getLastSelection
 } from "../../../utils/selection";
 import {CommonBlockAlignment} from "../../../nodes/_common";
 import {nodeHasAlignment} from "../../../utils/nodes";
 
 
-function setAlignmentForSection(editor: LexicalEditor, alignment: CommonBlockAlignment): void {
+function setAlignmentForSelection(editor: LexicalEditor, alignment: CommonBlockAlignment): void {
     const selection = getLastSelection(editor);
     const selectionNodes = selection?.getNodes() || [];
 
@@ -35,11 +37,21 @@ function setAlignmentForSection(editor: LexicalEditor, alignment: CommonBlockAli
     $toggleSelection(editor);
 }
 
+function setDirectionForSelection(editor: LexicalEditor, direction: 'ltr' | 'rtl'): void {
+    const selection = getLastSelection(editor);
+
+    const elements = $getBlockElementNodesInSelection(selection);
+    for (const node of elements) {
+        console.log('setting direction', node);
+        node.setDirection(direction);
+    }
+}
+
 export const alignLeft: EditorButtonDefinition = {
     label: 'Align left',
     icon: alignLeftIcon,
     action(context: EditorUiContext) {
-        context.editor.update(() => setAlignmentForSection(context.editor, 'left'));
+        context.editor.update(() => setAlignmentForSelection(context.editor, 'left'));
     },
     isActive(selection: BaseSelection|null) {
         return $selectionContainsAlignment(selection, 'left');
@@ -50,7 +62,7 @@ export const alignCenter: EditorButtonDefinition = {
     label: 'Align center',
     icon: alignCenterIcon,
     action(context: EditorUiContext) {
-        context.editor.update(() => setAlignmentForSection(context.editor, 'center'));
+        context.editor.update(() => setAlignmentForSelection(context.editor, 'center'));
     },
     isActive(selection: BaseSelection|null) {
         return $selectionContainsAlignment(selection, 'center');
@@ -61,7 +73,7 @@ export const alignRight: EditorButtonDefinition = {
     label: 'Align right',
     icon: alignRightIcon,
     action(context: EditorUiContext) {
-        context.editor.update(() => setAlignmentForSection(context.editor, 'right'));
+        context.editor.update(() => setAlignmentForSelection(context.editor, 'right'));
     },
     isActive(selection: BaseSelection|null) {
         return $selectionContainsAlignment(selection, 'right');
@@ -72,9 +84,31 @@ export const alignJustify: EditorButtonDefinition = {
     label: 'Align justify',
     icon: alignJustifyIcon,
     action(context: EditorUiContext) {
-        context.editor.update(() => setAlignmentForSection(context.editor, 'justify'));
+        context.editor.update(() => setAlignmentForSelection(context.editor, 'justify'));
     },
     isActive(selection: BaseSelection|null) {
         return $selectionContainsAlignment(selection, 'justify');
     }
 };
+
+export const directionLTR: EditorButtonDefinition = {
+    label: 'Left to right',
+    icon: ltrIcon,
+    action(context: EditorUiContext) {
+        context.editor.update(() => setDirectionForSelection(context.editor, 'ltr'));
+    },
+    isActive(selection: BaseSelection|null) {
+        return $selectionContainsDirection(selection, 'ltr');
+    }
+};
+
+export const directionRTL: EditorButtonDefinition = {
+    label: 'Right to left',
+    icon: rtlIcon,
+    action(context: EditorUiContext) {
+        context.editor.update(() => setDirectionForSelection(context.editor, 'rtl'));
+    },
+    isActive(selection: BaseSelection|null) {
+        return $selectionContainsDirection(selection, 'rtl');
+    }
+};
\ No newline at end of file
index 0ad638410add5cb47788df92d241cfd399b41127..b064a2a9f1b0f67a19a0d7fb8bad86da810ab585 100644 (file)
@@ -51,7 +51,14 @@ import {
     textColor,
     underline
 } from "./defaults/buttons/inline-formats";
-import {alignCenter, alignJustify, alignLeft, alignRight} from "./defaults/buttons/alignments";
+import {
+    alignCenter,
+    alignJustify,
+    alignLeft,
+    alignRight,
+    directionLTR,
+    directionRTL
+} from "./defaults/buttons/alignments";
 import {
     bulletList,
     indentDecrease,
@@ -117,11 +124,13 @@ export function getMainEditorFullToolbar(): EditorContainerUiElement {
         ]),
 
         // Alignment
-        new EditorOverflowContainer(4, [
+        new EditorOverflowContainer(6, [ // TODO - Dynamic
             new EditorButton(alignLeft),
             new EditorButton(alignCenter),
             new EditorButton(alignRight),
             new EditorButton(alignJustify),
+            new EditorButton(directionLTR), // TODO - Dynamic
+            new EditorButton(directionRTL), // TODO - Dynamic
         ]),
 
         // Lists
index 2110ea4beb9404d7cc03090db1bb4dc64bb0b578..f1055d98ac84113160d27c1cd6b67abc1df50264 100644 (file)
@@ -2,7 +2,7 @@ import {
     $createNodeSelection,
     $createParagraphNode, $createRangeSelection,
     $getRoot,
-    $getSelection, $isDecoratorNode,
+    $getSelection, $isBlockElementNode, $isDecoratorNode,
     $isElementNode,
     $isTextNode,
     $setSelection,
@@ -199,6 +199,22 @@ export function $selectionContainsAlignment(selection: BaseSelection | null, ali
     return false;
 }
 
+export function $selectionContainsDirection(selection: BaseSelection | null, direction: 'rtl'|'ltr'): boolean {
+
+    const nodes = [
+        ...(selection?.getNodes() || []),
+        ...$getBlockElementNodesInSelection(selection)
+    ];
+
+    for (const node of nodes) {
+        if ($isBlockElementNode(node) && node.getDirection() === direction) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 export function $getBlockElementNodesInSelection(selection: BaseSelection | null): ElementNode[] {
     if (!selection) {
         return [];