@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.
Files changed (130) hide show
  1. package/README.md +458 -0
  2. package/package.json +100 -0
  3. package/src/editor/constants.tsx +66 -0
  4. package/src/editor/container.css +46 -0
  5. package/src/editor/control/character-count/index.tsx +39 -0
  6. package/src/editor/control/drag-handle/index.tsx +85 -0
  7. package/src/editor/control/drag-handle/use.content.actions.ts +71 -0
  8. package/src/editor/control/drag-handle/use.data.ts +29 -0
  9. package/src/editor/control/drag-handle/use.handle.id.ts +6 -0
  10. package/src/editor/control/index.tsx +35 -0
  11. package/src/editor/editor.css +626 -0
  12. package/src/editor/extension/block-quote-figure/BlockquoteFigure.ts +73 -0
  13. package/src/editor/extension/block-quote-figure/Quote/Quote.ts +31 -0
  14. package/src/editor/extension/block-quote-figure/Quote/index.ts +1 -0
  15. package/src/editor/extension/block-quote-figure/QuoteCaption/QuoteCaption.ts +54 -0
  16. package/src/editor/extension/block-quote-figure/QuoteCaption/index.ts +1 -0
  17. package/src/editor/extension/block-quote-figure/index.ts +1 -0
  18. package/src/editor/extension/document/index.ts +5 -0
  19. package/src/editor/extension/figcaption/Figcaption.ts +90 -0
  20. package/src/editor/extension/figcaption/index.ts +1 -0
  21. package/src/editor/extension/figure/Figure.ts +62 -0
  22. package/src/editor/extension/figure/index.ts +1 -0
  23. package/src/editor/extension/font-size/FontSize.ts +64 -0
  24. package/src/editor/extension/font-size/index.ts +1 -0
  25. package/src/editor/extension/global-drag-handle/clipboard-serializer.ts +28 -0
  26. package/src/editor/extension/global-drag-handle/index.ts +377 -0
  27. package/src/editor/extension/heading/index.ts +13 -0
  28. package/src/editor/extension/horizontal-rule/HorizontalRule.ts +10 -0
  29. package/src/editor/extension/horizontal-rule/index.ts +1 -0
  30. package/src/editor/extension/image/index.ts +5 -0
  31. package/src/editor/extension/image-block/ImageBlock.ts +103 -0
  32. package/src/editor/extension/image-block/components/ImageBlockMenu.tsx +100 -0
  33. package/src/editor/extension/image-block/components/ImageBlockView.tsx +47 -0
  34. package/src/editor/extension/image-block/components/ImageBlockWidth.tsx +40 -0
  35. package/src/editor/extension/image-block/index.ts +1 -0
  36. package/src/editor/extension/image-upload/ImageUpload.ts +58 -0
  37. package/src/editor/extension/image-upload/index.ts +1 -0
  38. package/src/editor/extension/image-upload/view/ImageUpload.tsx +27 -0
  39. package/src/editor/extension/image-upload/view/ImageUploader.tsx +64 -0
  40. package/src/editor/extension/image-upload/view/hooks.ts +109 -0
  41. package/src/editor/extension/image-upload/view/index.tsx +1 -0
  42. package/src/editor/extension/index.ts +30 -0
  43. package/src/editor/extension/link/Link.ts +39 -0
  44. package/src/editor/extension/link/index.ts +1 -0
  45. package/src/editor/extension/multi-column/Column.ts +33 -0
  46. package/src/editor/extension/multi-column/Columns.ts +65 -0
  47. package/src/editor/extension/multi-column/index.ts +2 -0
  48. package/src/editor/extension/multi-column/menus/ColumnsMenu.tsx +82 -0
  49. package/src/editor/extension/multi-column/menus/index.ts +1 -0
  50. package/src/editor/extension/selection/Selection.ts +36 -0
  51. package/src/editor/extension/selection/index.ts +1 -0
  52. package/src/editor/extension/slash-command/MenuList.tsx +145 -0
  53. package/src/editor/extension/slash-command/groups.ts +153 -0
  54. package/src/editor/extension/slash-command/index.ts +277 -0
  55. package/src/editor/extension/slash-command/types.ts +25 -0
  56. package/src/editor/extension/table/Cell.ts +126 -0
  57. package/src/editor/extension/table/Header.ts +89 -0
  58. package/src/editor/extension/table/Row.ts +8 -0
  59. package/src/editor/extension/table/Table.ts +9 -0
  60. package/src/editor/extension/table/index.ts +4 -0
  61. package/src/editor/extension/table/menus/TableColumn/index.tsx +73 -0
  62. package/src/editor/extension/table/menus/TableColumn/utils.ts +38 -0
  63. package/src/editor/extension/table/menus/TableRow/index.tsx +74 -0
  64. package/src/editor/extension/table/menus/TableRow/utils.ts +38 -0
  65. package/src/editor/extension/table/menus/index.tsx +2 -0
  66. package/src/editor/extension/table/utils.ts +258 -0
  67. package/src/editor/extension/task-item/index.ts +1 -0
  68. package/src/editor/extension/task-item/task-item.ts +225 -0
  69. package/src/editor/extension/task-list/index.ts +1 -0
  70. package/src/editor/extension/task-list/task-list.ts +81 -0
  71. package/src/editor/extension/trailing-node/index.ts +1 -0
  72. package/src/editor/extension/trailing-node/trailing-node.ts +70 -0
  73. package/src/editor/extension/unique-id/index.ts +1 -0
  74. package/src/editor/extension/unique-id/uniqueId.ts +123 -0
  75. package/src/editor/hooks.ts +264 -0
  76. package/src/editor/index.tsx +53 -0
  77. package/src/editor/menus/LinkMenu/LinkMenu.tsx +75 -0
  78. package/src/editor/menus/LinkMenu/index.tsx +1 -0
  79. package/src/editor/menus/TextMenu/TextMenu.tsx +193 -0
  80. package/src/editor/menus/TextMenu/components/AIDropdown.tsx +140 -0
  81. package/src/editor/menus/TextMenu/components/ContentTypePicker.tsx +76 -0
  82. package/src/editor/menus/TextMenu/components/EditLinkPopover.tsx +25 -0
  83. package/src/editor/menus/TextMenu/components/FontFamilyPicker.tsx +84 -0
  84. package/src/editor/menus/TextMenu/components/FontSizePicker.tsx +56 -0
  85. package/src/editor/menus/TextMenu/hooks/useTextmenuCommands.ts +96 -0
  86. package/src/editor/menus/TextMenu/hooks/useTextmenuContentTypes.ts +86 -0
  87. package/src/editor/menus/TextMenu/hooks/useTextmenuStates.ts +50 -0
  88. package/src/editor/menus/TextMenu/index.tsx +2 -0
  89. package/src/editor/menus/types.ts +21 -0
  90. package/src/editor/panels/Colorpicker/ColorButton.tsx +35 -0
  91. package/src/editor/panels/Colorpicker/Colorpicker.tsx +67 -0
  92. package/src/editor/panels/Colorpicker/index.tsx +2 -0
  93. package/src/editor/panels/LinkEditorPanel/LinkEditorPanel.tsx +76 -0
  94. package/src/editor/panels/LinkEditorPanel/index.tsx +1 -0
  95. package/src/editor/panels/LinkPreviewPanel/LinkPreviewPanel.tsx +32 -0
  96. package/src/editor/panels/LinkPreviewPanel/index.tsx +1 -0
  97. package/src/editor/panels/index.tsx +3 -0
  98. package/src/editor/types.tsx +38 -0
  99. package/src/editor/ui/Button/Button.tsx +70 -0
  100. package/src/editor/ui/Button/index.tsx +2 -0
  101. package/src/editor/ui/Dropdown/Dropdown.tsx +39 -0
  102. package/src/editor/ui/Dropdown/index.tsx +1 -0
  103. package/src/editor/ui/Icon.tsx +21 -0
  104. package/src/editor/ui/Loader/Loader.tsx +39 -0
  105. package/src/editor/ui/Loader/index.ts +1 -0
  106. package/src/editor/ui/Loader/types.ts +7 -0
  107. package/src/editor/ui/Panel/index.tsx +109 -0
  108. package/src/editor/ui/PopoverMenu.tsx +127 -0
  109. package/src/editor/ui/Spinner/Spinner.tsx +10 -0
  110. package/src/editor/ui/Spinner/index.tsx +1 -0
  111. package/src/editor/ui/Surface.tsx +27 -0
  112. package/src/editor/ui/Textarea/Textarea.tsx +20 -0
  113. package/src/editor/ui/Textarea/index.tsx +1 -0
  114. package/src/editor/ui/Toggle/Toggle.tsx +39 -0
  115. package/src/editor/ui/Toggle/index.tsx +1 -0
  116. package/src/editor/ui/Toolbar.tsx +107 -0
  117. package/src/editor/ui/Tooltip/index.tsx +77 -0
  118. package/src/editor/ui/Tooltip/types.ts +17 -0
  119. package/src/editor/utils/cssVar.ts +14 -0
  120. package/src/editor/utils/getRenderContainer.ts +39 -0
  121. package/src/editor/utils/index.ts +16 -0
  122. package/src/editor/utils/isCustomNodeSelected.ts +47 -0
  123. package/src/editor/utils/isTextSelected.ts +25 -0
  124. package/src/editor/utils/locale.ts +5 -0
  125. package/src/editor/viewer/index.tsx +26 -0
  126. package/src/globals.css +1 -0
  127. package/src/index.ts +7 -0
  128. package/src/locales/en-us.ts +133 -0
  129. package/src/locales/zh-cn.ts +133 -0
  130. 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,6 @@
1
+ import { useMemo, useState } from "react";
2
+
3
+ export const useHandleId = () => {
4
+ const [handleId] = useState<number>(Date.now());
5
+ return useMemo(() => `drag-handle-${handleId}`, [handleId]);
6
+ };
@@ -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
+ };