feat(notebook): support text direction controls (#6293)
This commit is contained in:
1 parent
c56b91570b
commit
d44bc06a93
5 files changed
+124
-20
No files matched your search
@@ -39,6 +39,8 @@ import {
|
||||
IconRowRemove,
|
||||
IconTableOff,
|
||||
IconTablePlus,
|
||||
IconTextDirectionLtr,
|
||||
IconTextDirectionRtl,
|
||||
IconX,
|
||||
} from "@tabler/icons-react";
|
||||
import { Color } from "@tiptap/extension-color";
|
||||
@@ -66,6 +68,7 @@ import { useI18n, useScopedI18n } from "@homarr/translation/client";
|
||||
import type { TablerIcon } from "@homarr/ui";
|
||||
|
||||
import type { WidgetComponentProps } from "../definition";
|
||||
import { NotebookTextDirection, setTextDirection } from "./text-direction";
|
||||
|
||||
import "@mantine/tiptap/styles.css";
|
||||
import "./notebook.css";
|
||||
@@ -171,6 +174,7 @@ export function Notebook({ options, setOptions, isEditMode, boardId, itemId }: W
|
||||
}),
|
||||
TaskList.configure({ itemTypeName: "taskItem" }),
|
||||
TextAlign.configure({ types: ["heading", "paragraph"] }),
|
||||
NotebookTextDirection,
|
||||
TextStyle,
|
||||
],
|
||||
shouldRerenderOnTransaction: true,
|
||||
@@ -347,6 +351,22 @@ export function Notebook({ options, setOptions, isEditMode, boardId, itemId }: W
|
||||
position: t("widget.notebook.align.right"),
|
||||
})}
|
||||
/>
|
||||
<RichTextEditor.Control
|
||||
title={tControls("directionLtr")}
|
||||
aria-label={tControls("directionLtr")}
|
||||
active={editor?.isActive({ dir: "ltr" })}
|
||||
onClick={() => editor && setTextDirection(editor, "ltr").run()}
|
||||
>
|
||||
<IconTextDirectionLtr {...controlIconProps} />
|
||||
</RichTextEditor.Control>
|
||||
<RichTextEditor.Control
|
||||
title={tControls("directionRtl")}
|
||||
aria-label={tControls("directionRtl")}
|
||||
active={editor?.isActive({ dir: "rtl" })}
|
||||
onClick={() => editor && setTextDirection(editor, "rtl").run()}
|
||||
>
|
||||
<IconTextDirectionRtl {...controlIconProps} />
|
||||
</RichTextEditor.Control>
|
||||
</RichTextEditor.ControlsGroup>
|
||||
|
||||
<RichTextEditor.ControlsGroup>
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import { Editor } from "@tiptap/react";
|
||||
import { StarterKit } from "@tiptap/starter-kit";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { NotebookTextDirection, setTextDirection } from "./text-direction";
|
||||
|
||||
describe("notebook text direction", () => {
|
||||
it("persists right-to-left direction in the notebook HTML", () => {
|
||||
const editor = new Editor({
|
||||
content: "<p>יש לי 16GB</p>",
|
||||
extensions: [StarterKit, NotebookTextDirection],
|
||||
});
|
||||
|
||||
setTextDirection(editor, "rtl").run();
|
||||
|
||||
expect(editor.getHTML()).toBe('<p dir="rtl">יש לי 16GB</p>');
|
||||
editor.destroy();
|
||||
});
|
||||
|
||||
it("reads and changes an existing direction attribute", () => {
|
||||
const editor = new Editor({
|
||||
content: '<h2 dir="rtl">Heading</h2>',
|
||||
extensions: [StarterKit, NotebookTextDirection],
|
||||
});
|
||||
|
||||
expect(editor.getHTML()).toBe('<h2 dir="rtl">Heading</h2>');
|
||||
|
||||
editor.commands.setTextSelection(1);
|
||||
setTextDirection(editor, "ltr").run();
|
||||
|
||||
expect(editor.getHTML()).toContain('<h2 dir="ltr">Heading</h2>');
|
||||
editor.destroy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
import { Extension } from "@tiptap/react";
|
||||
import type { Editor } from "@tiptap/react";
|
||||
|
||||
export type TextDirection = "ltr" | "rtl";
|
||||
|
||||
export const NotebookTextDirection = Extension.create({
|
||||
name: "notebookTextDirection",
|
||||
|
||||
addGlobalAttributes() {
|
||||
return [
|
||||
{
|
||||
types: ["heading", "paragraph"],
|
||||
attributes: {
|
||||
dir: {
|
||||
default: null,
|
||||
parseHTML: (element) => element.getAttribute("dir"),
|
||||
renderHTML: ({ dir }: { dir?: TextDirection }) => (dir ? { dir } : {}),
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
});
|
||||
|
||||
export function setTextDirection(editor: Editor, direction: TextDirection) {
|
||||
const nodeType = editor.isActive("heading") ? "heading" : "paragraph";
|
||||
return editor.chain().focus().updateAttributes(nodeType, { dir: direction });
|
||||
}
|
||||
Reference in new issue
Block a user