Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 11 additions & 20 deletions src/shared/lib/mui-tiptap/controls/controlled-bubble-menu.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { ReactNode, useCallback } from "react";
import {
Fade,
Paper,
type PaperProps,
Popover,
type PopoverProps,
type PopoverVirtualElement,
useTheme,
} from "@mui/material";
import { type Editor, isNodeSelection, posToDOMRect } from "@tiptap/core";
import { makeStyles } from "tss-react/mui";
Expand Down Expand Up @@ -77,7 +75,6 @@ export default function ControlledBubbleMenu({
const { classes, cx } = useStyles(undefined, {
props: { classes: overrideClasses },
});
const theme = useTheme();

const defaultAnchorEl = useCallback((): VirtualElement => {
const { ranges } = editor.state.selection;
Expand Down Expand Up @@ -119,24 +116,18 @@ export default function ControlledBubbleMenu({
}}
transformOrigin={{ vertical: "top", horizontal: "left" }}
className={cx(controlledBubbleMenuClasses.root, classes.root, className)}
transitionDuration={{
enter: theme.transitions.duration.enteringScreen,
exit: 0,
}}
>
<Fade in={open}>
<Paper
elevation={7}
{...PaperProps}
className={cx(
controlledBubbleMenuClasses.paper,
classes.paper,
PaperProps?.className
)}
>
{children}
</Paper>
</Fade>
<Paper
elevation={7}
{...PaperProps}
className={cx(
controlledBubbleMenuClasses.paper,
classes.paper,
PaperProps?.className
)}
>
{children}
</Paper>
</Popover>
);
}
59 changes: 40 additions & 19 deletions src/shared/lib/mui-tiptap/controls/table-bubble-menu.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { findParentNodeClosestToPos, posToDOMRect } from "@tiptap/core";
import { useMemo } from "react";
import { useMemo, useCallback, useEffect, useState } from "react";
import { makeStyles } from "tss-react/mui";
import type { Except } from "type-fest";
import { type PopoverVirtualElement } from "@mui/material";
Expand All @@ -13,14 +13,8 @@ import { useRichTextEditorContext } from "../context";
import TableMenuControls, {
type TableMenuControlsProps,
} from "./table-menu-controls";
import useDebouncedFocus from "../hooks/use-debounced-focus";
import DebounceRender, {
type DebounceRenderProps,
} from "../utils/debounce-render";

export type TableBubbleMenuProps = {
disableDebounce?: boolean;
DebounceProps?: Except<DebounceRenderProps, "children">;
labels?: TableMenuControlsProps["labels"];
} & Partial<Except<ControlledBubbleMenuProps, "open" | "editor" | "children">>;

Expand All @@ -34,15 +28,12 @@ const useStyles = makeStyles({
}));

export default function TableBubbleMenu({
disableDebounce = false,
DebounceProps,
labels,
...controlledBubbleMenuProps
}: TableBubbleMenuProps) {
const editor = useRichTextEditorContext();
const { classes } = useStyles();

const isEditorFocusedDebounced = useDebouncedFocus({ editor });
const [isManuallyHidden, setIsManuallyHidden] = useState(false);

const bubbleMenuAnchorEl = useMemo(
() =>
Expand All @@ -61,7 +52,7 @@ export default function TableBubbleMenu({
nearestTableParent.pos
) as Maybe<HTMLElement | undefined>;

const tableDomNode = wrapperDomNode?.querySelector("admin");
const tableDomNode = wrapperDomNode?.querySelector("table");
if (tableDomNode) {
return tableDomNode.getBoundingClientRect();
}
Expand All @@ -77,18 +68,52 @@ export default function TableBubbleMenu({
[editor]
);

const handleClose = useCallback(() => {
setIsManuallyHidden(true);
if (editor) {
editor.commands.blur();
}
}, [editor]);

useEffect(() => {
if (!editor?.isActive("table")) {
setIsManuallyHidden(false);
}
}, [editor?.isActive("table")]);

useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === "Escape" && editor?.isActive("table")) {
handleClose();
}
};

document.addEventListener("keydown", handleKeyDown);
return () => {
document.removeEventListener("keydown", handleKeyDown);
};
}, [editor, handleClose]);

if (!editor?.isEditable) {
return null;
}

const controls = (
<TableMenuControls className={classes.controls} labels={labels} />
<TableMenuControls
className={classes.controls}
labels={labels}
onClose={handleClose}
/>
);

// Логика показа меню - активная таблица и не скрыто вручную
const shouldShowMenu = editor.isActive("table") && !isManuallyHidden;

return (
<ControlledBubbleMenu
editor={editor}
open={isEditorFocusedDebounced && editor.isActive("table")}
open={shouldShowMenu}
onClose={handleClose}
anchorEl={bubbleMenuAnchorEl as PopoverVirtualElement}
placement={{
anchorOrigin: { vertical: "top", horizontal: "left" },
Expand All @@ -104,11 +129,7 @@ export default function TableBubbleMenu({
flipPadding={{ top: 35, left: 8, right: 8, bottom: -Infinity }}
{...controlledBubbleMenuProps}
>
{disableDebounce ? (
controls
) : (
<DebounceRender {...DebounceProps}>{controls}</DebounceRender>
)}
{controls}
</ControlledBubbleMenu>
);
}
18 changes: 18 additions & 0 deletions src/shared/lib/mui-tiptap/controls/table-menu-controls.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import FormatColorFill from "@mui/icons-material/FormatColorFill";
import GridOff from "@mui/icons-material/GridOff";
import Close from "@mui/icons-material/Close";

import MenuDivider from "./menu-divider";
import { useRichTextEditorContext } from "../context";
Expand All @@ -18,6 +19,7 @@ import LayoutColumnFill from "../icons/layout-column-fill";

export type TableMenuControlsProps = {
className?: string;
onClose?: () => void;

labels?: {
insertColumnBefore?: string;
Expand All @@ -38,6 +40,7 @@ export type TableMenuControlsProps = {
export default function TableMenuControls({
className,
labels,
onClose,
}: TableMenuControlsProps) {
const editor = useRichTextEditorContext();
return (
Expand Down Expand Up @@ -134,6 +137,21 @@ export default function TableMenuControls({
onClick={() => editor?.chain().focus().deleteTable().run()}
disabled={!editor?.can().deleteTable()}
/>

<MenuDivider />

<MenuButton
tooltipLabel="Close"
IconComponent={Close}
onClick={() => {
if (onClose) {
onClose();
} else {
editor?.commands.blur();
}
}}
disabled={!editor?.isEditable}
/>
</MenuControlsContainer>
);
}