mirror of
https://github.com/docmost/docmost.git
synced 2026-05-15 13:14:11 +08:00
feat: Tiptap V3 migration (#1854)
* Tiptap3 migration - WIP * fix collaboration * remove unused code * fix flicker * disable duplicate extensions * update tiptap version * Switch to useEditorState - Set shouldRerenderOnTransaction to false * fix editable state * add tippyoptions for reference * merge main * tiptap 3.6.1 * fix bubble menu * fix converter * fix menus * fix collaboration caret css * fix: Set `isInitialized` to force immediate react node view rendering * feat: Migrate tippy.js menus to Floating UI * feat: Update collaboration connection for HocusPocus v3 * fix: Connect/disconnect websocketProvider * cleanup * cleanup * feat: Improved placeholder and upload handling for images * feat: Improved placeholder and upload handling for videos * refactor: Image node and view clean-up * feat: Improved placeholder and upload handling for attachments * fix: Video view styles * fix: Transaction handling on asset upload * fix: Use imageDimensionsFromStream * feat: Multiple file upload, improved placeholders, local previews * fix: Drag & drop, paste upload * fix: Allow media as attachment * * add skeleton pulse animation * add translation strings * fix attachment view responsiveness * fix collab connection status display * Tiptap v3.17.0 * fix suggestion menu exit bug * fix search shortcut * fix history editor css * tiptap 3.17.1 --------- Co-authored-by: Arek Nawo <areknawo@areknawo.com>
This commit is contained in:
@@ -1,6 +1,4 @@
|
||||
import { BubbleMenu as BaseBubbleMenu } from "@tiptap/react";
|
||||
import React, { useCallback } from "react";
|
||||
|
||||
import {
|
||||
EditorMenuProps,
|
||||
ShouldShowProps,
|
||||
@@ -17,6 +15,7 @@ import {
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { TableBackgroundColor } from "./table-background-color";
|
||||
import { TableTextAlignment } from "./table-text-alignment";
|
||||
import { BubbleMenu } from "@tiptap/react/menus";
|
||||
|
||||
export const TableCellMenu = React.memo(
|
||||
({ editor, appendTo }: EditorMenuProps): JSX.Element => {
|
||||
@@ -29,7 +28,7 @@ export const TableCellMenu = React.memo(
|
||||
|
||||
return isCellSelection(state.selection);
|
||||
},
|
||||
[editor],
|
||||
[editor]
|
||||
);
|
||||
|
||||
const mergeCells = useCallback(() => {
|
||||
@@ -53,23 +52,27 @@ export const TableCellMenu = React.memo(
|
||||
}, [editor]);
|
||||
|
||||
return (
|
||||
<BaseBubbleMenu
|
||||
<BubbleMenu
|
||||
editor={editor}
|
||||
pluginKey="table-cell-menu"
|
||||
updateDelay={0}
|
||||
tippyOptions={{
|
||||
appendTo: () => {
|
||||
return appendTo?.current;
|
||||
appendTo={() => {
|
||||
return appendTo?.current;
|
||||
}}
|
||||
ref={(element) => {
|
||||
element.style.zIndex = "99";
|
||||
}}
|
||||
options={{
|
||||
offset: {
|
||||
mainAxis: 15,
|
||||
},
|
||||
offset: [0, 15],
|
||||
zIndex: 99,
|
||||
}}
|
||||
shouldShow={shouldShow}
|
||||
>
|
||||
<ActionIcon.Group>
|
||||
<TableBackgroundColor editor={editor} />
|
||||
<TableTextAlignment editor={editor} />
|
||||
|
||||
|
||||
<Tooltip position="top" label={t("Merge cells")}>
|
||||
<ActionIcon
|
||||
onClick={mergeCells}
|
||||
@@ -125,9 +128,9 @@ export const TableCellMenu = React.memo(
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
</ActionIcon.Group>
|
||||
</BaseBubbleMenu>
|
||||
</BubbleMenu>
|
||||
);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
export default TableCellMenu;
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
import {
|
||||
BubbleMenu as BaseBubbleMenu,
|
||||
posToDOMRect,
|
||||
findParentNode,
|
||||
} from "@tiptap/react";
|
||||
import { posToDOMRect, findParentNode } from "@tiptap/react";
|
||||
import { Node as PMNode } from "@tiptap/pm/model";
|
||||
import React, { useCallback } from "react";
|
||||
|
||||
import {
|
||||
EditorMenuProps,
|
||||
ShouldShowProps,
|
||||
@@ -17,9 +12,12 @@ import {
|
||||
IconColumnRemove,
|
||||
IconRowInsertBottom,
|
||||
IconRowInsertTop,
|
||||
IconRowRemove, IconTableColumn, IconTableRow,
|
||||
IconRowRemove,
|
||||
IconTableColumn,
|
||||
IconTableRow,
|
||||
IconTrashX,
|
||||
} from '@tabler/icons-react';
|
||||
} from "@tabler/icons-react";
|
||||
import { BubbleMenu } from "@tiptap/react/menus";
|
||||
import { isCellSelection } from "@docmost/editor-ext";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
@@ -34,20 +32,28 @@ export const TableMenu = React.memo(
|
||||
|
||||
return editor.isActive("table") && !isCellSelection(state.selection);
|
||||
},
|
||||
[editor],
|
||||
[editor]
|
||||
);
|
||||
|
||||
const getReferenceClientRect = useCallback(() => {
|
||||
const getReferencedVirtualElement = useCallback(() => {
|
||||
const { selection } = editor.state;
|
||||
const predicate = (node: PMNode) => node.type.name === "table";
|
||||
const parent = findParentNode(predicate)(selection);
|
||||
|
||||
if (parent) {
|
||||
const dom = editor.view.nodeDOM(parent?.pos) as HTMLElement;
|
||||
return dom.getBoundingClientRect();
|
||||
const rect = dom.getBoundingClientRect();
|
||||
return {
|
||||
getBoundingClientRect: () => rect,
|
||||
getClientRects: () => [rect],
|
||||
};
|
||||
}
|
||||
|
||||
return posToDOMRect(editor.view, selection.from, selection.to);
|
||||
const rect = posToDOMRect(editor.view, selection.from, selection.to);
|
||||
return {
|
||||
getBoundingClientRect: () => rect,
|
||||
getClientRects: () => [rect],
|
||||
};
|
||||
}, [editor]);
|
||||
|
||||
const toggleHeaderColumn = useCallback(() => {
|
||||
@@ -87,42 +93,33 @@ export const TableMenu = React.memo(
|
||||
}, [editor]);
|
||||
|
||||
return (
|
||||
<BaseBubbleMenu
|
||||
<BubbleMenu
|
||||
editor={editor}
|
||||
pluginKey="table-menu"
|
||||
updateDelay={0}
|
||||
tippyOptions={{
|
||||
getReferenceClientRect: getReferenceClientRect,
|
||||
offset: [0, 15],
|
||||
zIndex: 99,
|
||||
popperOptions: {
|
||||
modifiers: [
|
||||
{
|
||||
name: "preventOverflow",
|
||||
enabled: true,
|
||||
options: {
|
||||
altAxis: true,
|
||||
boundary: "clippingParents",
|
||||
padding: 8,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "flip",
|
||||
enabled: true,
|
||||
options: {
|
||||
boundary: editor.options.element,
|
||||
fallbackPlacements: ["top", "bottom"],
|
||||
padding: { top: 35, left: 8, right: 8, bottom: -Infinity },
|
||||
},
|
||||
},
|
||||
],
|
||||
resizeDelay={0}
|
||||
getReferencedVirtualElement={getReferencedVirtualElement}
|
||||
ref={(element) => {
|
||||
element.style.zIndex = "99";
|
||||
}}
|
||||
options={{
|
||||
placement: "top",
|
||||
offset: {
|
||||
mainAxis: 15,
|
||||
},
|
||||
flip: {
|
||||
fallbackPlacements: ["top", "bottom"],
|
||||
padding: { top: 35 + 15, left: 8, right: 8, bottom: -Infinity },
|
||||
boundary: editor.options.element as HTMLElement,
|
||||
},
|
||||
shift: {
|
||||
padding: 8 + 15,
|
||||
crossAxis: true,
|
||||
},
|
||||
}}
|
||||
shouldShow={shouldShow}
|
||||
>
|
||||
<ActionIcon.Group>
|
||||
<Tooltip position="top" label={t("Add left column")}
|
||||
>
|
||||
<Tooltip position="top" label={t("Add left column")}>
|
||||
<ActionIcon
|
||||
onClick={addColumnLeft}
|
||||
variant="default"
|
||||
@@ -188,8 +185,7 @@ export const TableMenu = React.memo(
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip position="top" label={t("Toggle header row")}
|
||||
>
|
||||
<Tooltip position="top" label={t("Toggle header row")}>
|
||||
<ActionIcon
|
||||
onClick={toggleHeaderRow}
|
||||
variant="default"
|
||||
@@ -200,8 +196,7 @@ export const TableMenu = React.memo(
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip position="top" label={t("Toggle header column")}
|
||||
>
|
||||
<Tooltip position="top" label={t("Toggle header column")}>
|
||||
<ActionIcon
|
||||
onClick={toggleHeaderColumn}
|
||||
variant="default"
|
||||
@@ -224,9 +219,9 @@ export const TableMenu = React.memo(
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
</ActionIcon.Group>
|
||||
</BaseBubbleMenu>
|
||||
</BubbleMenu>
|
||||
);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
export default TableMenu;
|
||||
|
||||
Reference in New Issue
Block a user