@meta-1/editor 0.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +458 -0
- package/package.json +100 -0
- package/src/editor/constants.tsx +66 -0
- package/src/editor/container.css +46 -0
- package/src/editor/control/character-count/index.tsx +39 -0
- package/src/editor/control/drag-handle/index.tsx +85 -0
- package/src/editor/control/drag-handle/use.content.actions.ts +71 -0
- package/src/editor/control/drag-handle/use.data.ts +29 -0
- package/src/editor/control/drag-handle/use.handle.id.ts +6 -0
- package/src/editor/control/index.tsx +35 -0
- package/src/editor/editor.css +626 -0
- package/src/editor/extension/block-quote-figure/BlockquoteFigure.ts +73 -0
- package/src/editor/extension/block-quote-figure/Quote/Quote.ts +31 -0
- package/src/editor/extension/block-quote-figure/Quote/index.ts +1 -0
- package/src/editor/extension/block-quote-figure/QuoteCaption/QuoteCaption.ts +54 -0
- package/src/editor/extension/block-quote-figure/QuoteCaption/index.ts +1 -0
- package/src/editor/extension/block-quote-figure/index.ts +1 -0
- package/src/editor/extension/document/index.ts +5 -0
- package/src/editor/extension/figcaption/Figcaption.ts +90 -0
- package/src/editor/extension/figcaption/index.ts +1 -0
- package/src/editor/extension/figure/Figure.ts +62 -0
- package/src/editor/extension/figure/index.ts +1 -0
- package/src/editor/extension/font-size/FontSize.ts +64 -0
- package/src/editor/extension/font-size/index.ts +1 -0
- package/src/editor/extension/global-drag-handle/clipboard-serializer.ts +28 -0
- package/src/editor/extension/global-drag-handle/index.ts +377 -0
- package/src/editor/extension/heading/index.ts +13 -0
- package/src/editor/extension/horizontal-rule/HorizontalRule.ts +10 -0
- package/src/editor/extension/horizontal-rule/index.ts +1 -0
- package/src/editor/extension/image/index.ts +5 -0
- package/src/editor/extension/image-block/ImageBlock.ts +103 -0
- package/src/editor/extension/image-block/components/ImageBlockMenu.tsx +100 -0
- package/src/editor/extension/image-block/components/ImageBlockView.tsx +47 -0
- package/src/editor/extension/image-block/components/ImageBlockWidth.tsx +40 -0
- package/src/editor/extension/image-block/index.ts +1 -0
- package/src/editor/extension/image-upload/ImageUpload.ts +58 -0
- package/src/editor/extension/image-upload/index.ts +1 -0
- package/src/editor/extension/image-upload/view/ImageUpload.tsx +27 -0
- package/src/editor/extension/image-upload/view/ImageUploader.tsx +64 -0
- package/src/editor/extension/image-upload/view/hooks.ts +109 -0
- package/src/editor/extension/image-upload/view/index.tsx +1 -0
- package/src/editor/extension/index.ts +30 -0
- package/src/editor/extension/link/Link.ts +39 -0
- package/src/editor/extension/link/index.ts +1 -0
- package/src/editor/extension/multi-column/Column.ts +33 -0
- package/src/editor/extension/multi-column/Columns.ts +65 -0
- package/src/editor/extension/multi-column/index.ts +2 -0
- package/src/editor/extension/multi-column/menus/ColumnsMenu.tsx +82 -0
- package/src/editor/extension/multi-column/menus/index.ts +1 -0
- package/src/editor/extension/selection/Selection.ts +36 -0
- package/src/editor/extension/selection/index.ts +1 -0
- package/src/editor/extension/slash-command/MenuList.tsx +145 -0
- package/src/editor/extension/slash-command/groups.ts +153 -0
- package/src/editor/extension/slash-command/index.ts +277 -0
- package/src/editor/extension/slash-command/types.ts +25 -0
- package/src/editor/extension/table/Cell.ts +126 -0
- package/src/editor/extension/table/Header.ts +89 -0
- package/src/editor/extension/table/Row.ts +8 -0
- package/src/editor/extension/table/Table.ts +9 -0
- package/src/editor/extension/table/index.ts +4 -0
- package/src/editor/extension/table/menus/TableColumn/index.tsx +73 -0
- package/src/editor/extension/table/menus/TableColumn/utils.ts +38 -0
- package/src/editor/extension/table/menus/TableRow/index.tsx +74 -0
- package/src/editor/extension/table/menus/TableRow/utils.ts +38 -0
- package/src/editor/extension/table/menus/index.tsx +2 -0
- package/src/editor/extension/table/utils.ts +258 -0
- package/src/editor/extension/task-item/index.ts +1 -0
- package/src/editor/extension/task-item/task-item.ts +225 -0
- package/src/editor/extension/task-list/index.ts +1 -0
- package/src/editor/extension/task-list/task-list.ts +81 -0
- package/src/editor/extension/trailing-node/index.ts +1 -0
- package/src/editor/extension/trailing-node/trailing-node.ts +70 -0
- package/src/editor/extension/unique-id/index.ts +1 -0
- package/src/editor/extension/unique-id/uniqueId.ts +123 -0
- package/src/editor/hooks.ts +264 -0
- package/src/editor/index.tsx +53 -0
- package/src/editor/menus/LinkMenu/LinkMenu.tsx +75 -0
- package/src/editor/menus/LinkMenu/index.tsx +1 -0
- package/src/editor/menus/TextMenu/TextMenu.tsx +193 -0
- package/src/editor/menus/TextMenu/components/AIDropdown.tsx +140 -0
- package/src/editor/menus/TextMenu/components/ContentTypePicker.tsx +76 -0
- package/src/editor/menus/TextMenu/components/EditLinkPopover.tsx +25 -0
- package/src/editor/menus/TextMenu/components/FontFamilyPicker.tsx +84 -0
- package/src/editor/menus/TextMenu/components/FontSizePicker.tsx +56 -0
- package/src/editor/menus/TextMenu/hooks/useTextmenuCommands.ts +96 -0
- package/src/editor/menus/TextMenu/hooks/useTextmenuContentTypes.ts +86 -0
- package/src/editor/menus/TextMenu/hooks/useTextmenuStates.ts +50 -0
- package/src/editor/menus/TextMenu/index.tsx +2 -0
- package/src/editor/menus/types.ts +21 -0
- package/src/editor/panels/Colorpicker/ColorButton.tsx +35 -0
- package/src/editor/panels/Colorpicker/Colorpicker.tsx +67 -0
- package/src/editor/panels/Colorpicker/index.tsx +2 -0
- package/src/editor/panels/LinkEditorPanel/LinkEditorPanel.tsx +76 -0
- package/src/editor/panels/LinkEditorPanel/index.tsx +1 -0
- package/src/editor/panels/LinkPreviewPanel/LinkPreviewPanel.tsx +32 -0
- package/src/editor/panels/LinkPreviewPanel/index.tsx +1 -0
- package/src/editor/panels/index.tsx +3 -0
- package/src/editor/types.tsx +38 -0
- package/src/editor/ui/Button/Button.tsx +70 -0
- package/src/editor/ui/Button/index.tsx +2 -0
- package/src/editor/ui/Dropdown/Dropdown.tsx +39 -0
- package/src/editor/ui/Dropdown/index.tsx +1 -0
- package/src/editor/ui/Icon.tsx +21 -0
- package/src/editor/ui/Loader/Loader.tsx +39 -0
- package/src/editor/ui/Loader/index.ts +1 -0
- package/src/editor/ui/Loader/types.ts +7 -0
- package/src/editor/ui/Panel/index.tsx +109 -0
- package/src/editor/ui/PopoverMenu.tsx +127 -0
- package/src/editor/ui/Spinner/Spinner.tsx +10 -0
- package/src/editor/ui/Spinner/index.tsx +1 -0
- package/src/editor/ui/Surface.tsx +27 -0
- package/src/editor/ui/Textarea/Textarea.tsx +20 -0
- package/src/editor/ui/Textarea/index.tsx +1 -0
- package/src/editor/ui/Toggle/Toggle.tsx +39 -0
- package/src/editor/ui/Toggle/index.tsx +1 -0
- package/src/editor/ui/Toolbar.tsx +107 -0
- package/src/editor/ui/Tooltip/index.tsx +77 -0
- package/src/editor/ui/Tooltip/types.ts +17 -0
- package/src/editor/utils/cssVar.ts +14 -0
- package/src/editor/utils/getRenderContainer.ts +39 -0
- package/src/editor/utils/index.ts +16 -0
- package/src/editor/utils/isCustomNodeSelected.ts +47 -0
- package/src/editor/utils/isTextSelected.ts +25 -0
- package/src/editor/utils/locale.ts +5 -0
- package/src/editor/viewer/index.tsx +26 -0
- package/src/globals.css +1 -0
- package/src/index.ts +7 -0
- package/src/locales/en-us.ts +133 -0
- package/src/locales/zh-cn.ts +133 -0
- package/src/locales/zh-tw.ts +133 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { type FC, useEffect, useRef, useState } from "react";
|
|
2
|
+
import { HamburgerMenuIcon, PlusIcon } from "@radix-ui/react-icons";
|
|
3
|
+
import type { Editor } from "@tiptap/react";
|
|
4
|
+
import classNames from "classnames";
|
|
5
|
+
|
|
6
|
+
import { Action, Dropdown } from "@meta-1/design";
|
|
7
|
+
import { i18n } from "../../utils/locale";
|
|
8
|
+
import { useContentActions } from "./use.content.actions";
|
|
9
|
+
import type { NodeData } from "./use.data";
|
|
10
|
+
|
|
11
|
+
export type DragHandleControlProps = {
|
|
12
|
+
className?: string;
|
|
13
|
+
editor: Editor;
|
|
14
|
+
id: string;
|
|
15
|
+
data: NodeData;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const DragHandleControl: FC<DragHandleControlProps> = (props) => {
|
|
19
|
+
const { editor, data } = props;
|
|
20
|
+
const handleRef = useRef<HTMLDivElement>(null);
|
|
21
|
+
const actions = useContentActions(editor!, data.currentNode!, data.currentPos!);
|
|
22
|
+
const [menuOpen, setMenuOpen] = useState(false);
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
setMenuOpen(false);
|
|
26
|
+
}, [data.currentNode, data.hidden]);
|
|
27
|
+
|
|
28
|
+
const actionClassName = "w-7 h-7 !p-0";
|
|
29
|
+
return (
|
|
30
|
+
<div className="!left-0 absolute bg-black" id={props.id} ref={handleRef} style={{ top: -1000 }}>
|
|
31
|
+
<div className="absolute right-0 flex space-x-1 pr-3">
|
|
32
|
+
<Action className={actionClassName} onClick={actions.handleAdd}>
|
|
33
|
+
<PlusIcon />
|
|
34
|
+
</Action>
|
|
35
|
+
<div className="relative">
|
|
36
|
+
<Action className={classNames(actionClassName, "relative z-1")} onClick={() => setMenuOpen(true)}>
|
|
37
|
+
<HamburgerMenuIcon />
|
|
38
|
+
</Action>
|
|
39
|
+
<Dropdown
|
|
40
|
+
align="start"
|
|
41
|
+
asChild={true}
|
|
42
|
+
className={data.hidden ? "hidden" : ""}
|
|
43
|
+
items={[
|
|
44
|
+
{
|
|
45
|
+
label: i18n("dragHandle.actions.clear"),
|
|
46
|
+
type: "item",
|
|
47
|
+
id: "clear-formatting",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
label: i18n("dragHandle.actions.duplicate"),
|
|
51
|
+
type: "item",
|
|
52
|
+
id: "duplicate",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
type: "separator",
|
|
56
|
+
id: "separator",
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
label: i18n("dragHandle.actions.delete"),
|
|
60
|
+
type: "item",
|
|
61
|
+
id: "delete",
|
|
62
|
+
},
|
|
63
|
+
]}
|
|
64
|
+
modal={false}
|
|
65
|
+
onItemClick={(item) => {
|
|
66
|
+
if (item.id === "clear-formatting") {
|
|
67
|
+
actions.resetTextFormatting();
|
|
68
|
+
} else if (item.id === "duplicate") {
|
|
69
|
+
actions.duplicateNode();
|
|
70
|
+
} else if (item.id === "delete") {
|
|
71
|
+
actions.deleteNode();
|
|
72
|
+
}
|
|
73
|
+
}}
|
|
74
|
+
onOpenChange={setMenuOpen}
|
|
75
|
+
open={menuOpen}
|
|
76
|
+
>
|
|
77
|
+
<Action className={classNames(actionClassName, "invisible absolute top-0 left-0 z-0")}>
|
|
78
|
+
<HamburgerMenuIcon />
|
|
79
|
+
</Action>
|
|
80
|
+
</Dropdown>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
);
|
|
85
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
import type { ResolvedPos } from "@tiptap/pm/model";
|
|
3
|
+
import type { Editor } from "@tiptap/react";
|
|
4
|
+
|
|
5
|
+
export const useContentActions = (editor: Editor, resolvedPos: ResolvedPos, nodePos: number) => {
|
|
6
|
+
const currentNode = resolvedPos?.node();
|
|
7
|
+
const currentNodePos = resolvedPos?.depth === 0 ? resolvedPos?.pos : resolvedPos?.before();
|
|
8
|
+
|
|
9
|
+
const resetTextFormatting = useCallback(() => {
|
|
10
|
+
const chain = editor.chain();
|
|
11
|
+
|
|
12
|
+
chain.setNodeSelection(currentNodePos).unsetAllMarks();
|
|
13
|
+
|
|
14
|
+
if (currentNode?.type.name !== "paragraph") {
|
|
15
|
+
chain.setParagraph();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
chain.run();
|
|
19
|
+
}, [editor, currentNodePos, currentNode?.type.name]);
|
|
20
|
+
|
|
21
|
+
const duplicateNode = useCallback(() => {
|
|
22
|
+
let currentPos = currentNodePos;
|
|
23
|
+
if (["imageBlock", "imageUpload", "horizontalRule"].includes(currentNode?.type.name)) {
|
|
24
|
+
currentPos = nodePos;
|
|
25
|
+
}
|
|
26
|
+
editor
|
|
27
|
+
.chain()
|
|
28
|
+
.setMeta("hideDragHandle", true)
|
|
29
|
+
.insertContentAt(currentPos + (currentNode?.nodeSize || 0), currentNode.toJSON())
|
|
30
|
+
.run();
|
|
31
|
+
}, [editor, currentNodePos, currentNode, nodePos]);
|
|
32
|
+
|
|
33
|
+
const deleteNode = useCallback(() => {
|
|
34
|
+
let currentPos = currentNodePos;
|
|
35
|
+
if (["imageBlock", "imageUpload", "horizontalRule"].includes(currentNode?.type.name)) {
|
|
36
|
+
currentPos = nodePos;
|
|
37
|
+
}
|
|
38
|
+
editor.chain().setMeta("hideDragHandle", true).setNodeSelection(currentPos).deleteSelection().run();
|
|
39
|
+
}, [editor, currentNodePos, nodePos, currentNode?.type.name]);
|
|
40
|
+
|
|
41
|
+
const handleAdd = useCallback(() => {
|
|
42
|
+
const nodePos = resolvedPos?.depth === 0 ? resolvedPos.pos + 1 : resolvedPos.after(1);
|
|
43
|
+
const insertPos = nodePos;
|
|
44
|
+
const currentNodeIsEmptyParagraph =
|
|
45
|
+
resolvedPos?.depth === 1 && currentNode?.type.name === "paragraph" && currentNode?.content?.size === 0;
|
|
46
|
+
const focusPos = currentNodeIsEmptyParagraph ? nodePos : nodePos + 2;
|
|
47
|
+
|
|
48
|
+
editor
|
|
49
|
+
.chain()
|
|
50
|
+
.command(({ dispatch, tr, state }) => {
|
|
51
|
+
if (dispatch) {
|
|
52
|
+
if (currentNodeIsEmptyParagraph) {
|
|
53
|
+
tr.insertText("/", resolvedPos.pos, resolvedPos.pos + 1);
|
|
54
|
+
} else {
|
|
55
|
+
tr.insert(insertPos, state.schema.nodes.paragraph.create(null, [state.schema.text("/")]));
|
|
56
|
+
}
|
|
57
|
+
return dispatch(tr);
|
|
58
|
+
}
|
|
59
|
+
return true;
|
|
60
|
+
})
|
|
61
|
+
.focus(focusPos)
|
|
62
|
+
.run();
|
|
63
|
+
}, [currentNode, editor, resolvedPos]);
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
resetTextFormatting,
|
|
67
|
+
duplicateNode,
|
|
68
|
+
deleteNode,
|
|
69
|
+
handleAdd,
|
|
70
|
+
};
|
|
71
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useCallback, useState } from "react";
|
|
2
|
+
import type { ResolvedPos } from "@tiptap/pm/model";
|
|
3
|
+
|
|
4
|
+
export type NodeData = {
|
|
5
|
+
currentNode?: ResolvedPos;
|
|
6
|
+
currentPos?: number;
|
|
7
|
+
handleNodeChange: (node: ResolvedPos, nodePos: number) => void;
|
|
8
|
+
setHidden: (hidden: boolean) => void;
|
|
9
|
+
hidden: boolean;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const useData = (): NodeData => {
|
|
13
|
+
const [currentNode, setCurrentNode] = useState<ResolvedPos>();
|
|
14
|
+
const [currentPos, setCurrentPos] = useState<number>();
|
|
15
|
+
const [hidden, setHidden] = useState(false);
|
|
16
|
+
|
|
17
|
+
const handleNodeChange = useCallback((node: ResolvedPos, nodePos: number) => {
|
|
18
|
+
setCurrentNode(node);
|
|
19
|
+
setCurrentPos(nodePos);
|
|
20
|
+
}, []);
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
currentNode,
|
|
24
|
+
currentPos,
|
|
25
|
+
handleNodeChange,
|
|
26
|
+
setHidden,
|
|
27
|
+
hidden,
|
|
28
|
+
};
|
|
29
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { FC, RefObject } from "react";
|
|
2
|
+
import type { Editor } from "@tiptap/react";
|
|
3
|
+
|
|
4
|
+
import ImageBlockMenu from "../extension/image-block/components/ImageBlockMenu";
|
|
5
|
+
import ColumnsMenu from "../extension/multi-column/menus/ColumnsMenu";
|
|
6
|
+
import { TableColumnMenu, TableRowMenu } from "../extension/table/menus";
|
|
7
|
+
import LinkMenu from "../menus/LinkMenu/LinkMenu";
|
|
8
|
+
import { TextMenu } from "../menus/TextMenu";
|
|
9
|
+
import { CharacterCountControl } from "./character-count";
|
|
10
|
+
import { DragHandleControl } from "./drag-handle";
|
|
11
|
+
import type { NodeData } from "./drag-handle/use.data";
|
|
12
|
+
|
|
13
|
+
export type EditorControllerProps = {
|
|
14
|
+
limit?: number;
|
|
15
|
+
editor: Editor | null;
|
|
16
|
+
handleId: string;
|
|
17
|
+
appendTo: RefObject<HTMLElement | null>;
|
|
18
|
+
data: NodeData;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const EditorController: FC<EditorControllerProps> = (props) => {
|
|
22
|
+
const { limit, data, editor, handleId, appendTo } = props;
|
|
23
|
+
return editor ? (
|
|
24
|
+
<>
|
|
25
|
+
{limit ? <CharacterCountControl editor={editor} limit={limit} /> : null}
|
|
26
|
+
<DragHandleControl data={data} editor={editor} id={handleId} />
|
|
27
|
+
<LinkMenu appendTo={appendTo} editor={editor} />
|
|
28
|
+
<TextMenu editor={editor} />
|
|
29
|
+
<ColumnsMenu appendTo={appendTo} editor={editor} />
|
|
30
|
+
<TableRowMenu appendTo={appendTo} editor={editor} />
|
|
31
|
+
<TableColumnMenu appendTo={appendTo} editor={editor} />
|
|
32
|
+
<ImageBlockMenu appendTo={appendTo} editor={editor} />
|
|
33
|
+
</>
|
|
34
|
+
) : null;
|
|
35
|
+
};
|