tetrons 2.3.22 → 2.3.24
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/dist/app/page.d.ts +2 -0
- package/dist/app/page.jsx +51 -0
- package/dist/components/UI/Button.tsx +0 -0
- package/dist/components/UI/Dropdown.tsx +0 -0
- package/dist/components/components/tetrons/EditorContent.tsx +60 -62
- package/dist/components/tetrons/EditorContent.d.ts +6 -0
- package/dist/components/tetrons/EditorContent.tsx +280 -0
- package/dist/components/tetrons/ResizableImage.ts +39 -0
- package/dist/components/tetrons/ResizableImageComponent.tsx +77 -0
- package/dist/components/tetrons/ResizableVideo.ts +66 -0
- package/dist/components/tetrons/ResizableVideoComponent.tsx +56 -0
- package/dist/components/tetrons/extensions/Spellcheck.ts +50 -0
- package/dist/components/tetrons/helpers.ts +0 -0
- package/dist/components/tetrons/toolbar/ActionGroup.tsx +218 -0
- package/dist/components/tetrons/toolbar/ClipboardGroup.tsx +58 -0
- package/dist/components/tetrons/toolbar/FileGroup.tsx +66 -0
- package/dist/components/tetrons/toolbar/FontStyleGroup.tsx +194 -0
- package/dist/components/tetrons/toolbar/InsertGroup.tsx +267 -0
- package/dist/components/tetrons/toolbar/ListAlignGroup.tsx +69 -0
- package/dist/components/tetrons/toolbar/MiscGroup.d.ts +7 -0
- package/dist/components/tetrons/toolbar/MiscGroup.jsx +55 -0
- package/dist/components/tetrons/toolbar/MiscGroup.tsx +104 -0
- package/dist/components/tetrons/toolbar/TableContextMenu.tsx +91 -0
- package/dist/components/tetrons/toolbar/TetronsToolbar.d.ts +6 -0
- package/dist/components/tetrons/toolbar/TetronsToolbar.tsx +71 -0
- package/dist/components/tetrons/toolbar/ToolbarButton.tsx +36 -0
- package/dist/components/tetrons/toolbar/extensions/Comment.ts +72 -0
- package/dist/components/tetrons/toolbar/extensions/Embed.ts +113 -0
- package/dist/components/tetrons/toolbar/extensions/FontFamily.ts +43 -0
- package/dist/components/tetrons/toolbar/extensions/FontSize.ts +43 -0
- package/dist/components/tetrons/toolbar/extensions/ResizableTable.ts +16 -0
- package/dist/components/tetrons/toolbar/marks/Subscript.ts +45 -0
- package/dist/components/tetrons/toolbar/marks/Superscript.ts +45 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +17366 -22
- package/dist/index.mjs +4705 -4592
- package/dist/styles/styles/tetrons.css +1 -1
- package/dist/styles/tetrons.css +1 -1
- package/dist/utils/checkGrammar.d.ts +25 -0
- package/dist/utils/checkGrammar.js +17 -0
- package/package.json +9 -9
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import React, { useEffect, useState } from "react";
|
|
4
|
+
import { Editor } from "@tiptap/react";
|
|
5
|
+
|
|
6
|
+
interface ContextMenuProps {
|
|
7
|
+
editor: Editor;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default function TableContextMenu({ editor }: ContextMenuProps) {
|
|
11
|
+
const [menuPosition, setMenuPosition] = useState<{
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
} | null>(null);
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const handleContextMenu = (event: MouseEvent) => {
|
|
18
|
+
const target = event.target as HTMLElement;
|
|
19
|
+
|
|
20
|
+
if (target.closest("td") || target.closest("th")) {
|
|
21
|
+
event.preventDefault();
|
|
22
|
+
setMenuPosition({ x: event.pageX, y: event.pageY });
|
|
23
|
+
} else {
|
|
24
|
+
setMenuPosition(null);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const handleClick = () => setMenuPosition(null);
|
|
29
|
+
|
|
30
|
+
document.addEventListener("contextmenu", handleContextMenu);
|
|
31
|
+
document.addEventListener("click", handleClick);
|
|
32
|
+
|
|
33
|
+
return () => {
|
|
34
|
+
document.removeEventListener("contextmenu", handleContextMenu);
|
|
35
|
+
document.removeEventListener("click", handleClick);
|
|
36
|
+
};
|
|
37
|
+
}, []);
|
|
38
|
+
|
|
39
|
+
const insertRowAbove = () => editor.chain().focus().addRowBefore().run();
|
|
40
|
+
const insertRowBelow = () => editor.chain().focus().addRowAfter().run();
|
|
41
|
+
const insertColLeft = () => editor.chain().focus().addColumnBefore().run();
|
|
42
|
+
const insertColRight = () => editor.chain().focus().addColumnAfter().run();
|
|
43
|
+
const deleteRow = () => editor.chain().focus().deleteRow().run();
|
|
44
|
+
const deleteCol = () => editor.chain().focus().deleteColumn().run();
|
|
45
|
+
|
|
46
|
+
if (!menuPosition) return null;
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<ul
|
|
50
|
+
className="absolute bg-white shadow border rounded text-sm z-50"
|
|
51
|
+
style={{ top: menuPosition.y, left: menuPosition.x }}
|
|
52
|
+
>
|
|
53
|
+
<li
|
|
54
|
+
className="px-3 py-1 hover:bg-gray-100 cursor-pointer"
|
|
55
|
+
onClick={insertRowAbove}
|
|
56
|
+
>
|
|
57
|
+
Insert Row Above
|
|
58
|
+
</li>
|
|
59
|
+
<li
|
|
60
|
+
className="px-3 py-1 hover:bg-gray-100 cursor-pointer"
|
|
61
|
+
onClick={insertRowBelow}
|
|
62
|
+
>
|
|
63
|
+
Insert Row Below
|
|
64
|
+
</li>
|
|
65
|
+
<li
|
|
66
|
+
className="px-3 py-1 hover:bg-gray-100 cursor-pointer"
|
|
67
|
+
onClick={insertColLeft}
|
|
68
|
+
>
|
|
69
|
+
Insert Column Left
|
|
70
|
+
</li>
|
|
71
|
+
<li
|
|
72
|
+
className="px-3 py-1 hover:bg-gray-100 cursor-pointer"
|
|
73
|
+
onClick={insertColRight}
|
|
74
|
+
>
|
|
75
|
+
Insert Column Right
|
|
76
|
+
</li>
|
|
77
|
+
<li
|
|
78
|
+
className="px-3 py-1 hover:bg-red-100 cursor-pointer"
|
|
79
|
+
onClick={deleteRow}
|
|
80
|
+
>
|
|
81
|
+
Delete Row
|
|
82
|
+
</li>
|
|
83
|
+
<li
|
|
84
|
+
className="px-3 py-1 hover:bg-red-100 cursor-pointer"
|
|
85
|
+
onClick={deleteCol}
|
|
86
|
+
>
|
|
87
|
+
Delete Column
|
|
88
|
+
</li>
|
|
89
|
+
</ul>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import React, { useEffect, useState } from "react";
|
|
4
|
+
import type { Editor } from "@tiptap/react";
|
|
5
|
+
|
|
6
|
+
import ActionGroup from "./ActionGroup";
|
|
7
|
+
import ClipboardGroup from "./ClipboardGroup";
|
|
8
|
+
import FontStyleGroup from "./FontStyleGroup";
|
|
9
|
+
import InsertGroup from "./InsertGroup";
|
|
10
|
+
import ListAlignGroup from "./ListAlignGroup";
|
|
11
|
+
import MiscGroup from "./MiscGroup";
|
|
12
|
+
import FileGroup from "./FileGroup";
|
|
13
|
+
|
|
14
|
+
export default function TetronsToolbar({
|
|
15
|
+
editor,
|
|
16
|
+
version,
|
|
17
|
+
}: {
|
|
18
|
+
editor: Editor;
|
|
19
|
+
version: "free" | "pro" | "premium" | "platinum";
|
|
20
|
+
}) {
|
|
21
|
+
const [autoSave, setAutoSave] = useState(false);
|
|
22
|
+
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (!editor) return;
|
|
25
|
+
|
|
26
|
+
const handleUpdate = () => {
|
|
27
|
+
if (!autoSave) return;
|
|
28
|
+
const content = editor.getJSON();
|
|
29
|
+
fetch("/api/save", {
|
|
30
|
+
method: "POST",
|
|
31
|
+
headers: { "Content-Type": "application/json" },
|
|
32
|
+
body: JSON.stringify(content),
|
|
33
|
+
}).catch((err) => console.error("Auto-save failed:", err));
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
editor.on("update", handleUpdate);
|
|
37
|
+
return () => {
|
|
38
|
+
editor.off("update", handleUpdate);
|
|
39
|
+
};
|
|
40
|
+
}, [autoSave, editor]);
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<div className="tetrons-toolbar">
|
|
44
|
+
{version !== "free" && (
|
|
45
|
+
<div className="group">
|
|
46
|
+
<input
|
|
47
|
+
type="checkbox"
|
|
48
|
+
id="autoSave"
|
|
49
|
+
checked={autoSave}
|
|
50
|
+
onChange={(e) => setAutoSave(e.target.checked)}
|
|
51
|
+
/>
|
|
52
|
+
<label htmlFor="autoSave">Auto Save</label>
|
|
53
|
+
</div>
|
|
54
|
+
)}
|
|
55
|
+
|
|
56
|
+
{["pro", "premium", "platinum"].includes(version) && (
|
|
57
|
+
<FileGroup editor={editor} />
|
|
58
|
+
)}
|
|
59
|
+
<ClipboardGroup editor={editor} />
|
|
60
|
+
<FontStyleGroup editor={editor} />
|
|
61
|
+
<ListAlignGroup editor={editor} />
|
|
62
|
+
{["premium", "platinum"].includes(version) && (
|
|
63
|
+
<>
|
|
64
|
+
<InsertGroup editor={editor} />
|
|
65
|
+
<ActionGroup editor={editor} />
|
|
66
|
+
</>
|
|
67
|
+
)}
|
|
68
|
+
{version === "platinum" && <MiscGroup editor={editor} />}
|
|
69
|
+
</div>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { IconType } from "react-icons";
|
|
3
|
+
|
|
4
|
+
export type ToolbarButtonProps = {
|
|
5
|
+
icon: IconType;
|
|
6
|
+
onClick: () => void;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
title?: string;
|
|
9
|
+
label?: string;
|
|
10
|
+
isActive?: boolean;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const ToolbarButton = React.forwardRef<HTMLButtonElement, ToolbarButtonProps>(
|
|
14
|
+
(
|
|
15
|
+
{ icon: Icon, onClick, disabled = false, title, label, isActive = false },
|
|
16
|
+
ref
|
|
17
|
+
) => {
|
|
18
|
+
return (
|
|
19
|
+
<button
|
|
20
|
+
type="button"
|
|
21
|
+
ref={ref}
|
|
22
|
+
onClick={onClick}
|
|
23
|
+
disabled={disabled}
|
|
24
|
+
title={title ?? label}
|
|
25
|
+
aria-label={title ?? label}
|
|
26
|
+
className={`toolbar-button ${isActive ? "active" : ""}`}
|
|
27
|
+
>
|
|
28
|
+
<Icon size={20} />
|
|
29
|
+
</button>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
ToolbarButton.displayName = "ToolbarButton";
|
|
35
|
+
|
|
36
|
+
export default ToolbarButton;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Mark, mergeAttributes } from "@tiptap/core";
|
|
2
|
+
|
|
3
|
+
export interface CommentOptions {
|
|
4
|
+
HTMLAttributes: {
|
|
5
|
+
class?: string;
|
|
6
|
+
style?: string;
|
|
7
|
+
[key: string]: unknown;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
declare module "@tiptap/core" {
|
|
12
|
+
interface Commands<ReturnType> {
|
|
13
|
+
comment: {
|
|
14
|
+
setComment: (comment: string) => ReturnType;
|
|
15
|
+
unsetComment: () => ReturnType;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const Comment = Mark.create<CommentOptions>({
|
|
21
|
+
name: "comment",
|
|
22
|
+
|
|
23
|
+
addOptions() {
|
|
24
|
+
return {
|
|
25
|
+
HTMLAttributes: {},
|
|
26
|
+
};
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
addAttributes() {
|
|
30
|
+
return {
|
|
31
|
+
comment: {
|
|
32
|
+
default: "",
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
parseHTML() {
|
|
38
|
+
return [
|
|
39
|
+
{
|
|
40
|
+
tag: "span[data-comment]",
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
renderHTML({ HTMLAttributes }) {
|
|
46
|
+
return [
|
|
47
|
+
"span",
|
|
48
|
+
mergeAttributes(HTMLAttributes, {
|
|
49
|
+
"data-comment": HTMLAttributes.comment,
|
|
50
|
+
class: "comment-highlight",
|
|
51
|
+
title: HTMLAttributes.comment,
|
|
52
|
+
style: "background-color: rgba(255, 230, 0, 0.3);",
|
|
53
|
+
}),
|
|
54
|
+
0,
|
|
55
|
+
];
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
addCommands() {
|
|
59
|
+
return {
|
|
60
|
+
setComment:
|
|
61
|
+
(comment) =>
|
|
62
|
+
({ commands }) => {
|
|
63
|
+
return commands.setMark(this.name, { comment });
|
|
64
|
+
},
|
|
65
|
+
unsetComment:
|
|
66
|
+
() =>
|
|
67
|
+
({ commands }) => {
|
|
68
|
+
return commands.unsetMark(this.name);
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
});
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { Node, mergeAttributes, CommandProps } from "@tiptap/core";
|
|
2
|
+
|
|
3
|
+
export const Embed = Node.create({
|
|
4
|
+
name: "embed",
|
|
5
|
+
group: "block",
|
|
6
|
+
atom: true,
|
|
7
|
+
|
|
8
|
+
addAttributes() {
|
|
9
|
+
return {
|
|
10
|
+
src: { default: null },
|
|
11
|
+
width: { default: 560 },
|
|
12
|
+
height: { default: 315 },
|
|
13
|
+
};
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
parseHTML() {
|
|
17
|
+
return [{ tag: "iframe[src]" }];
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
renderHTML({ HTMLAttributes }) {
|
|
21
|
+
return ["iframe", mergeAttributes(HTMLAttributes)];
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
addCommands() {
|
|
25
|
+
return {
|
|
26
|
+
setEmbed: ((attributes: {
|
|
27
|
+
src: string;
|
|
28
|
+
width?: number;
|
|
29
|
+
height?: number;
|
|
30
|
+
}) => {
|
|
31
|
+
return ({ chain }: CommandProps): boolean => {
|
|
32
|
+
return chain()
|
|
33
|
+
.insertContent({
|
|
34
|
+
type: this.name,
|
|
35
|
+
attrs: attributes,
|
|
36
|
+
})
|
|
37
|
+
.run();
|
|
38
|
+
};
|
|
39
|
+
}).bind(this),
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
addNodeView() {
|
|
44
|
+
return ({ node, getPos, editor }) => {
|
|
45
|
+
const container = document.createElement('div');
|
|
46
|
+
container.style.position = 'relative';
|
|
47
|
+
container.style.display = 'inline-block';
|
|
48
|
+
container.style.width = node.attrs.width + 'px';
|
|
49
|
+
container.style.height = node.attrs.height + 'px';
|
|
50
|
+
|
|
51
|
+
const iframe = document.createElement('iframe');
|
|
52
|
+
iframe.setAttribute('src', node.attrs.src);
|
|
53
|
+
iframe.setAttribute('frameborder', '0');
|
|
54
|
+
iframe.setAttribute('allowfullscreen', 'true');
|
|
55
|
+
iframe.style.width = '100%';
|
|
56
|
+
iframe.style.height = '100%';
|
|
57
|
+
container.appendChild(iframe);
|
|
58
|
+
|
|
59
|
+
const handle = document.createElement('div');
|
|
60
|
+
handle.style.position = 'absolute';
|
|
61
|
+
handle.style.width = '16px';
|
|
62
|
+
handle.style.height = '16px';
|
|
63
|
+
handle.style.right = '0';
|
|
64
|
+
handle.style.bottom = '0';
|
|
65
|
+
handle.style.cursor = 'se-resize';
|
|
66
|
+
handle.style.background = 'rgba(0,0,0,0.5)';
|
|
67
|
+
handle.style.borderRadius = '2px';
|
|
68
|
+
container.appendChild(handle);
|
|
69
|
+
|
|
70
|
+
let startX: number, startY: number, startWidth: number, startHeight: number;
|
|
71
|
+
|
|
72
|
+
const onMouseDown = (event: MouseEvent) => {
|
|
73
|
+
event.preventDefault();
|
|
74
|
+
startX = event.clientX;
|
|
75
|
+
startY = event.clientY;
|
|
76
|
+
startWidth = container.offsetWidth;
|
|
77
|
+
startHeight = container.offsetHeight;
|
|
78
|
+
window.addEventListener('mousemove', onMouseMove);
|
|
79
|
+
window.addEventListener('mouseup', onMouseUp);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const onMouseMove = (event: MouseEvent) => {
|
|
83
|
+
const newWidth = Math.max(100, startWidth + (event.clientX - startX));
|
|
84
|
+
const newHeight = Math.max(100, startHeight + (event.clientY - startY));
|
|
85
|
+
container.style.width = newWidth + 'px';
|
|
86
|
+
container.style.height = newHeight + 'px';
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const onMouseUp = () => {
|
|
90
|
+
window.removeEventListener("mousemove", onMouseMove);
|
|
91
|
+
window.removeEventListener("mouseup", onMouseUp);
|
|
92
|
+
|
|
93
|
+
editor.commands.command(({ tr }) => {
|
|
94
|
+
tr.setNodeMarkup(getPos(), undefined, {
|
|
95
|
+
...node.attrs,
|
|
96
|
+
width: container.offsetWidth,
|
|
97
|
+
height: container.offsetHeight,
|
|
98
|
+
});
|
|
99
|
+
return true;
|
|
100
|
+
});
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
handle.addEventListener('mousedown', onMouseDown);
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
dom: container,
|
|
107
|
+
destroy() {
|
|
108
|
+
handle.removeEventListener('mousedown', onMouseDown);
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
},
|
|
113
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Mark, mergeAttributes } from '@tiptap/core';
|
|
2
|
+
|
|
3
|
+
declare module '@tiptap/core' {
|
|
4
|
+
interface Commands<ReturnType> {
|
|
5
|
+
fontFamily: {
|
|
6
|
+
setFontFamily: (font: string) => ReturnType;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const FontFamily = Mark.create({
|
|
12
|
+
name: 'fontFamily',
|
|
13
|
+
|
|
14
|
+
addAttributes() {
|
|
15
|
+
return {
|
|
16
|
+
font: {
|
|
17
|
+
default: null,
|
|
18
|
+
parseHTML: element => element.style.fontFamily.replace(/['"]/g, ''),
|
|
19
|
+
renderHTML: attributes => {
|
|
20
|
+
if (!attributes.font) return {};
|
|
21
|
+
return { style: `font-family: ${attributes.font}` };
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
parseHTML() {
|
|
28
|
+
return [{ style: 'font-family' }];
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
renderHTML({ HTMLAttributes }) {
|
|
32
|
+
return ['span', mergeAttributes(HTMLAttributes), 0];
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
addCommands() {
|
|
36
|
+
return {
|
|
37
|
+
setFontFamily:
|
|
38
|
+
font =>
|
|
39
|
+
({ commands }) =>
|
|
40
|
+
commands.setMark(this.name, { font }),
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Mark, mergeAttributes } from "@tiptap/core";
|
|
2
|
+
|
|
3
|
+
declare module "@tiptap/core" {
|
|
4
|
+
interface Commands<ReturnType> {
|
|
5
|
+
fontSize: {
|
|
6
|
+
setFontSize: (size: string) => ReturnType;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const FontSize = Mark.create({
|
|
12
|
+
name: "fontSize",
|
|
13
|
+
|
|
14
|
+
addAttributes() {
|
|
15
|
+
return {
|
|
16
|
+
size: {
|
|
17
|
+
default: null,
|
|
18
|
+
parseHTML: (element) => element.style.fontSize,
|
|
19
|
+
renderHTML: (attributes) => {
|
|
20
|
+
if (!attributes.size) return {};
|
|
21
|
+
return { style: `font-size: ${attributes.size}` };
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
parseHTML() {
|
|
28
|
+
return [{ style: "font-size" }];
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
renderHTML({ HTMLAttributes }) {
|
|
32
|
+
return ["span", mergeAttributes(HTMLAttributes), 0];
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
addCommands() {
|
|
36
|
+
return {
|
|
37
|
+
setFontSize:
|
|
38
|
+
(size) =>
|
|
39
|
+
({ commands }) =>
|
|
40
|
+
commands.setMark(this.name, { size }),
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Table } from "@tiptap/extension-table";
|
|
2
|
+
import { columnResizing, tableEditing } from "prosemirror-tables";
|
|
3
|
+
import { Plugin } from "prosemirror-state";
|
|
4
|
+
|
|
5
|
+
export const ResizableTable = Table.extend({
|
|
6
|
+
addOptions() {
|
|
7
|
+
return {
|
|
8
|
+
...this.parent?.(),
|
|
9
|
+
resizable: true,
|
|
10
|
+
};
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
addProseMirrorPlugins(): Plugin[] {
|
|
14
|
+
return [columnResizing({ handleWidth: 5 }), tableEditing()];
|
|
15
|
+
},
|
|
16
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Mark, markInputRule, markPasteRule } from "@tiptap/core";
|
|
2
|
+
|
|
3
|
+
export const Subscript = Mark.create({
|
|
4
|
+
name: "subscript",
|
|
5
|
+
|
|
6
|
+
excludes: "superscript",
|
|
7
|
+
|
|
8
|
+
parseHTML() {
|
|
9
|
+
return [{ tag: "sub" }, { style: "vertical-align: sub" }];
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
renderHTML() {
|
|
13
|
+
return ["sub", 0];
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
addCommands() {
|
|
17
|
+
return {
|
|
18
|
+
toggleSubscript:
|
|
19
|
+
() =>
|
|
20
|
+
({ chain }) =>
|
|
21
|
+
chain()
|
|
22
|
+
.unsetMark("superscript")
|
|
23
|
+
.toggleMark(this.name)
|
|
24
|
+
.run(),
|
|
25
|
+
};
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
addInputRules() {
|
|
29
|
+
return [
|
|
30
|
+
markInputRule({
|
|
31
|
+
find: /~([^~]+)~/,
|
|
32
|
+
type: this.type,
|
|
33
|
+
}),
|
|
34
|
+
];
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
addPasteRules() {
|
|
38
|
+
return [
|
|
39
|
+
markPasteRule({
|
|
40
|
+
find: /~([^~]+)~/g,
|
|
41
|
+
type: this.type,
|
|
42
|
+
}),
|
|
43
|
+
];
|
|
44
|
+
},
|
|
45
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Mark, markInputRule, markPasteRule } from "@tiptap/core";
|
|
2
|
+
|
|
3
|
+
export const Superscript = Mark.create({
|
|
4
|
+
name: "superscript",
|
|
5
|
+
|
|
6
|
+
excludes: "subscript",
|
|
7
|
+
|
|
8
|
+
parseHTML() {
|
|
9
|
+
return [{ tag: "sup" }, { style: "vertical-align: super" }];
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
renderHTML() {
|
|
13
|
+
return ["sup", 0];
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
addCommands() {
|
|
17
|
+
return {
|
|
18
|
+
toggleSuperscript:
|
|
19
|
+
() =>
|
|
20
|
+
({ chain }) =>
|
|
21
|
+
chain()
|
|
22
|
+
.unsetMark("subscript")
|
|
23
|
+
.toggleMark(this.name)
|
|
24
|
+
.run(),
|
|
25
|
+
};
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
addInputRules() {
|
|
29
|
+
return [
|
|
30
|
+
markInputRule({
|
|
31
|
+
find: /\^([^^]+)\^/,
|
|
32
|
+
type: this.type,
|
|
33
|
+
}),
|
|
34
|
+
];
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
addPasteRules() {
|
|
38
|
+
return [
|
|
39
|
+
markPasteRule({
|
|
40
|
+
find: /\^([^^]+)\^/g,
|
|
41
|
+
type: this.type,
|
|
42
|
+
}),
|
|
43
|
+
];
|
|
44
|
+
},
|
|
45
|
+
});
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import EditorContent from "./components/tetrons/EditorContent";
|
|
2
2
|
export declare function initializeTetrons(apiKey: string): Promise<void>;
|
|
3
|
-
export declare function getTetronsVersion(): "" | "
|
|
3
|
+
export declare function getTetronsVersion(): "" | "platinum" | "free" | "pro" | "premium";
|
|
4
4
|
export declare function isApiKeyValid(): boolean;
|
|
5
5
|
export { EditorContent };
|
|
6
6
|
export default EditorContent;
|