Skip to content

Commit

Permalink
[PULSE-42] feat: text alignment for all editors (#5847)
Browse files Browse the repository at this point in the history
* feat: text alignment for editors

* fix: text alignment types

* fix: build errors

* fix: build error

* fix: toolbar movement post alignment selection

* fix: callout type

* fix: image node types

* chore: add ts error warning
  • Loading branch information
aaryan610 authored Nov 5, 2024
1 parent bb311b7 commit b4de055
Show file tree
Hide file tree
Showing 27 changed files with 641 additions and 324 deletions.
1 change: 1 addition & 0 deletions packages/editor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"@tiptap/extension-placeholder": "^2.3.0",
"@tiptap/extension-task-item": "^2.1.13",
"@tiptap/extension-task-list": "^2.1.13",
"@tiptap/extension-text-align": "^2.8.0",
"@tiptap/extension-text-style": "^2.7.1",
"@tiptap/extension-underline": "^2.1.13",
"@tiptap/pm": "^2.1.13",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { Editor } from "@tiptap/core";
import { AlignCenter, AlignLeft, AlignRight, LucideIcon } from "lucide-react";
// components
import { TextAlignItem } from "@/components/menus";
// helpers
import { cn } from "@/helpers/common";
// types
import { TEditorCommands } from "@/types";

type Props = {
editor: Editor;
onClose: () => void;
};

export const TextAlignmentSelector: React.FC<Props> = (props) => {
const { editor, onClose } = props;

const menuItem = TextAlignItem(editor);

const textAlignmentOptions: {
itemKey: TEditorCommands;
renderKey: string;
icon: LucideIcon;
command: () => void;
isActive: () => boolean;
}[] = [
{
itemKey: "text-align",
renderKey: "text-align-left",
icon: AlignLeft,
command: () =>
menuItem.command({
alignment: "left",
}),
isActive: () =>
menuItem.isActive({
alignment: "left",
}),
},
{
itemKey: "text-align",
renderKey: "text-align-center",
icon: AlignCenter,
command: () =>
menuItem.command({
alignment: "center",
}),
isActive: () =>
menuItem.isActive({
alignment: "center",
}),
},
{
itemKey: "text-align",
renderKey: "text-align-right",
icon: AlignRight,
command: () =>
menuItem.command({
alignment: "right",
}),
isActive: () =>
menuItem.isActive({
alignment: "right",
}),
},
];

return (
<div className="flex gap-0.5 px-2">
{textAlignmentOptions.map((item) => (
<button
key={item.renderKey}
type="button"
onClick={(e) => {
e.stopPropagation();
item.command();
onClose();
}}
className={cn(
"size-7 grid place-items-center rounded text-custom-text-300 hover:bg-custom-background-80 active:bg-custom-background-80 transition-colors",
{
"bg-custom-background-80 text-custom-text-100": item.isActive(),
}
)}
>
<item.icon className="size-4" />
</button>
))}
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ type Props = {
export const BubbleMenuColorSelector: FC<Props> = (props) => {
const { editor, isOpen, setIsOpen } = props;

const activeTextColor = COLORS_LIST.find((c) => TextColorItem(editor).isActive(c.key));
const activeBackgroundColor = COLORS_LIST.find((c) => BackgroundColorItem(editor).isActive(c.key));
const activeTextColor = COLORS_LIST.find((c) => TextColorItem(editor).isActive({ color: c.key }));
const activeBackgroundColor = COLORS_LIST.find((c) => BackgroundColorItem(editor).isActive({ color: c.key }));

return (
<div className="relative h-full">
Expand Down Expand Up @@ -64,7 +64,7 @@ export const BubbleMenuColorSelector: FC<Props> = (props) => {
style={{
backgroundColor: color.textColor,
}}
onClick={() => TextColorItem(editor).command(color.key)}
onClick={() => TextColorItem(editor).command({ color: color.key })}
/>
))}
<button
Expand All @@ -87,7 +87,7 @@ export const BubbleMenuColorSelector: FC<Props> = (props) => {
style={{
backgroundColor: color.backgroundColor,
}}
onClick={() => BackgroundColorItem(editor).command(color.key)}
onClick={() => BackgroundColorItem(editor).command({ color: color.key })}
/>
))}
<button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import {
} from "@/components/menus";
// helpers
import { cn } from "@/helpers/common";
// types
import { TEditorCommands } from "@/types";

type Props = {
editor: Editor;
Expand All @@ -29,7 +31,7 @@ type Props = {
export const BubbleMenuNodeSelector: FC<Props> = (props) => {
const { editor, isOpen, setIsOpen } = props;

const items: EditorMenuItem[] = [
const items: EditorMenuItem<TEditorCommands>[] = [
TextItem(editor),
HeadingOneItem(editor),
HeadingTwoItem(editor),
Expand All @@ -44,7 +46,7 @@ export const BubbleMenuNodeSelector: FC<Props> = (props) => {
CodeItem(editor),
];

const activeItem = items.filter((item) => item.isActive("")).pop() ?? {
const activeItem = items.filter((item) => item.isActive()).pop() ?? {
name: "Multiple",
};

Expand Down
18 changes: 14 additions & 4 deletions packages/editor/src/core/components/menus/bubble-menu/root.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { FC, useEffect, useState } from "react";
import { BubbleMenu, BubbleMenuProps, isNodeSelection } from "@tiptap/react";
import { BubbleMenu, BubbleMenuProps, Editor, isNodeSelection } from "@tiptap/react";
// components
import {
BoldItem,
BubbleMenuColorSelector,
BubbleMenuLinkSelector,
BubbleMenuNodeSelector,
CodeItem,
EditorMenuItem,
ItalicItem,
StrikeThroughItem,
UnderLineItem,
Expand All @@ -16,6 +15,8 @@ import {
import { isCellSelection } from "@/extensions/table/table/utilities/is-cell-selection";
// helpers
import { cn } from "@/helpers/common";
// local components
import { TextAlignmentSelector } from "./alignment-selector";

type EditorBubbleMenuProps = Omit<BubbleMenuProps, "children">;

Expand All @@ -26,7 +27,7 @@ export const EditorBubbleMenu: FC<EditorBubbleMenuProps> = (props: any) => {
const [isColorSelectorOpen, setIsColorSelectorOpen] = useState(false);
const [isSelecting, setIsSelecting] = useState(false);

const items: EditorMenuItem[] = props.editor.isActive("code")
const basicFormattingOptions = props.editor.isActive("code")
? [CodeItem(props.editor)]
: [BoldItem(props.editor), ItalicItem(props.editor), UnderLineItem(props.editor), StrikeThroughItem(props.editor)];

Expand Down Expand Up @@ -132,7 +133,7 @@ export const EditorBubbleMenu: FC<EditorBubbleMenuProps> = (props: any) => {
)}
</div>
<div className="flex gap-0.5 px-2">
{items.map((item) => (
{basicFormattingOptions.map((item) => (
<button
key={item.key}
type="button"
Expand All @@ -151,6 +152,15 @@ export const EditorBubbleMenu: FC<EditorBubbleMenuProps> = (props: any) => {
</button>
))}
</div>
<TextAlignmentSelector
editor={props.editor}
onClose={() => {
const editor = props.editor as Editor;
if (!editor) return;
const pos = editor.state.selection.to;
editor.commands.setTextSelection(pos ?? 0);
}}
/>
</>
)}
</BubbleMenu>
Expand Down
Loading

0 comments on commit b4de055

Please sign in to comment.