1
0
Code Issues Pull Requests Packages Projects Releases Wiki Activity GitHub Gitee
Files
inke/packages/core/src/ui/editor/bubble-menu/table-selector.tsx
2023-10-22 10:52:46 +08:00

164 lines
5.4 KiB
TypeScript

import { Editor } from "@tiptap/core";
import {
ChevronDown,
LucideIcon,
Rows,
PanelTop,
PanelBottom,
PanelRight,
PanelLeft,
Trash2,
SplitSquareHorizontal,
Heading1,
} from "lucide-react";
import { Dispatch, FC, SetStateAction } from "react";
import * as Popover from "@radix-ui/react-popover";
export interface BubbleTableMenuItem {
name: string;
icon: LucideIcon;
action: () => boolean;
}
interface TableSelectorProps {
editor: Editor;
isOpen: boolean;
setIsOpen: Dispatch<SetStateAction<boolean>>;
}
const TABLE_COLUMN_CMDS = (editor: Editor): BubbleTableMenuItem[] => {
return [
{
name: "Add column before",
icon: PanelLeft,
action: () => editor.chain().focus().addColumnBefore().run(),
},
{
name: "Add column after",
icon: PanelRight,
action: () => editor.chain().focus().addColumnAfter().run(),
},
{
name: "Delete column",
icon: Trash2,
action: () => editor.chain().focus().deleteColumn().run(),
},
];
};
const TABLE_ROW_CMDS = (editor: Editor): BubbleTableMenuItem[] => {
return [
{
name: "Add row before",
icon: PanelTop,
action: () => editor.chain().focus().addRowBefore().run(),
},
{
name: "Add row after",
icon: PanelBottom,
action: () => editor.chain().focus().addRowAfter().run(),
},
{
name: "Delete row",
icon: Trash2,
action: () => editor.chain().focus().deleteRow().run(),
},
];
};
const TABLE_CELL_CMDS = (editor: Editor): BubbleTableMenuItem[] => {
return [
{
name: "Merge or split",
icon: SplitSquareHorizontal,
action: () => editor.chain().focus().mergeOrSplit().run(),
},
{
name: "Toggle header cell",
icon: Heading1,
action: () => editor.chain().focus().toggleHeaderCell().run(),
},
{
name: "Delete table",
icon: Trash2,
action: () => editor.chain().focus().deleteTable().run(),
},
];
};
export const TableSelector: FC<TableSelectorProps> = ({
editor,
isOpen,
setIsOpen,
}) => {
return (
<Popover.Root open={isOpen}>
<div className="novel-relative novel-h-full">
<Popover.Trigger
className="novel-flex novel-h-full novel-items-center novel-gap-1 novel-p-2 novel-text-sm novel-font-medium novel-text-stone-600 hover:novel-bg-stone-100 active:novel-bg-stone-200"
onClick={() => setIsOpen(!isOpen)}>
<span className="novel-rounded-sm novel-px-1">Table</span>
<ChevronDown className="novel-h-4 novel-w-4" />
</Popover.Trigger>
<Popover.Content
align="start"
className="novel-z-[99999] novel-my-1 novel-flex novel-max-h-80 novel-w-48 novel-flex-col novel-overflow-hidden novel-overflow-y-auto novel-rounded novel-border novel-border-stone-200 novel-bg-white novel-p-1 novel-shadow-xl novel-animate-in novel-fade-in novel-slide-in-from-top-1">
<div className="novel-my-1 novel-px-2 novel-text-sm novel-text-stone-500">
Column
</div>
{TABLE_COLUMN_CMDS(editor).map((item, index) => (
<button
key={index}
onClick={() => item.action()}
className="novel-flex novel-items-center novel-justify-between novel-rounded-sm novel-px-2 novel-py-1 novel-text-sm novel-text-stone-600 hover:novel-bg-stone-100"
type="button">
<div className="novel-flex novel-items-center novel-space-x-2">
<div className="novel-rounded-sm novel-px-1 novel-py-px novel-font-medium">
<item.icon className="w-4 h-4 novel-text-slate-400" />
</div>
<span>{item.name}</span>
</div>
</button>
))}
<div className="novel-my-1 novel-px-2 novel-text-sm novel-text-stone-500">
Row
</div>
{TABLE_ROW_CMDS(editor).map((item, index) => (
<button
key={index}
onClick={() => item.action()}
className="novel-flex novel-items-center novel-justify-between novel-rounded-sm novel-px-2 novel-py-1 novel-text-sm novel-text-stone-600 hover:novel-bg-stone-100"
type="button">
<div className="novel-flex novel-items-center novel-space-x-2">
<div className="novel-rounded-sm novel-px-1 novel-py-px novel-font-medium">
<item.icon className="w-4 h-4 novel-text-slate-400" />
</div>
<span>{item.name}</span>
</div>
</button>
))}
<div className="novel-my-1 novel-px-2 novel-text-sm novel-text-stone-500">
Cell
</div>
{TABLE_CELL_CMDS(editor).map((item, index) => (
<button
key={index}
onClick={() => item.action()}
className="novel-flex novel-items-center novel-justify-between novel-rounded-sm novel-px-2 novel-py-1 novel-text-sm novel-text-stone-600 hover:novel-bg-stone-100"
type="button">
<div className="novel-flex novel-items-center novel-space-x-2">
<div className="novel-rounded-sm novel-px-1 novel-py-px novel-font-medium">
<item.icon className="w-4 h-4 novel-text-slate-400" />
</div>
<span>{item.name}</span>
</div>
</button>
))}
</Popover.Content>
</div>
</Popover.Root>
);
};