@monolith-forensics/monolith-ui 1.1.45 → 1.1.47
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/MonolithUIProvider/GlobalStyle.js +18 -0
- package/dist/MonolithUIProvider/MonolithUIProvider.d.ts +1 -1
- package/dist/RichTextEditor/Enums/Extensions.d.ts +15 -0
- package/dist/RichTextEditor/Enums/Extensions.js +16 -0
- package/dist/RichTextEditor/Enums/SlashCommands.d.ts +13 -0
- package/dist/RichTextEditor/Enums/SlashCommands.js +14 -0
- package/dist/RichTextEditor/Extensions/SlashCommandList.d.ts +9 -0
- package/dist/RichTextEditor/Extensions/SlashCommandList.js +138 -0
- package/dist/RichTextEditor/Extensions/getSlashCommand.d.ts +10 -0
- package/dist/RichTextEditor/Extensions/getSlashCommand.js +296 -0
- package/dist/RichTextEditor/Extensions/getTiptapExtensions.d.ts +11 -0
- package/dist/RichTextEditor/Extensions/getTiptapExtensions.js +178 -0
- package/dist/RichTextEditor/Plugins/UploadImagesPlugin.d.ts +16 -0
- package/dist/RichTextEditor/Plugins/UploadImagesPlugin.js +114 -0
- package/dist/RichTextEditor/RichTextEditor.d.ts +22 -0
- package/dist/RichTextEditor/RichTextEditor.js +302 -0
- package/dist/RichTextEditor/Toolbar/Control.d.ts +14 -0
- package/dist/RichTextEditor/Toolbar/Control.js +33 -0
- package/dist/RichTextEditor/Toolbar/Controls.d.ts +21 -0
- package/dist/RichTextEditor/Toolbar/Controls.js +120 -0
- package/dist/RichTextEditor/Toolbar/ControlsGroup.d.ts +8 -0
- package/dist/RichTextEditor/Toolbar/ControlsGroup.js +26 -0
- package/dist/RichTextEditor/Toolbar/Labels.d.ts +41 -0
- package/dist/RichTextEditor/Toolbar/Labels.js +46 -0
- package/dist/RichTextEditor/Toolbar/Toolbar.d.ts +7 -0
- package/dist/RichTextEditor/Toolbar/Toolbar.js +17 -0
- package/dist/RichTextEditor/Toolbar/index.d.ts +1 -0
- package/dist/RichTextEditor/Toolbar/index.js +1 -0
- package/dist/RichTextEditor/index.d.ts +3 -0
- package/dist/RichTextEditor/index.js +3 -0
- package/dist/TextAreaInput/TextAreaInput.js +2 -25
- package/dist/Utilities/calculateFileHash.d.ts +8 -0
- package/dist/Utilities/calculateFileHash.js +38 -0
- package/dist/Utilities/readFileAsBuffer.d.ts +2 -0
- package/dist/Utilities/readFileAsBuffer.js +10 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +19 -1
|
@@ -47,5 +47,23 @@ const GlobalStyle = createGlobalStyle `
|
|
|
47
47
|
text-decoration: none;
|
|
48
48
|
color: unset;
|
|
49
49
|
}
|
|
50
|
+
|
|
51
|
+
::-webkit-scrollbar {
|
|
52
|
+
width: 6px;
|
|
53
|
+
height: 5px;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
::-webkit-scrollbar-track {
|
|
57
|
+
background: ${(props) => props.theme.scrollbar.track};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
::-webkit-scrollbar-thumb {
|
|
61
|
+
|
|
62
|
+
background: ${(props) => props.theme.scrollbar.thumb}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
::-webkit-scrollbar-thumb:hover {
|
|
66
|
+
background: ${(props) => props.theme.scrollbar.thumbHover};
|
|
67
|
+
}
|
|
50
68
|
`;
|
|
51
69
|
export default GlobalStyle;
|
|
@@ -11,7 +11,7 @@ export interface MonolithUIContextType {
|
|
|
11
11
|
}
|
|
12
12
|
export declare const MonolithUIContext: React.Context<MonolithUIContextType | undefined>;
|
|
13
13
|
interface MonolithUIProviderProps {
|
|
14
|
-
children
|
|
14
|
+
children?: React.ReactNode | React.ReactNode[];
|
|
15
15
|
theme?: DefaultTheme;
|
|
16
16
|
defaultColorScheme?: ColorScheme;
|
|
17
17
|
colorScheme?: ColorScheme;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
declare enum Extensions {
|
|
2
|
+
HorizontalRule = "horizontalRule",
|
|
3
|
+
Underline = "underline",
|
|
4
|
+
TextAlign = "textAlign",
|
|
5
|
+
Table = "table",
|
|
6
|
+
TableCell = "tableCell",
|
|
7
|
+
TableHeader = "tableHeader",
|
|
8
|
+
TableRow = "tableRow",
|
|
9
|
+
Placeholder = "placeholder",
|
|
10
|
+
Focus = "focus",
|
|
11
|
+
Image = "image",
|
|
12
|
+
CustomStorage = "storage",
|
|
13
|
+
SlashCommand = "slashCommand"
|
|
14
|
+
}
|
|
15
|
+
export default Extensions;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
var Extensions;
|
|
2
|
+
(function (Extensions) {
|
|
3
|
+
Extensions["HorizontalRule"] = "horizontalRule";
|
|
4
|
+
Extensions["Underline"] = "underline";
|
|
5
|
+
Extensions["TextAlign"] = "textAlign";
|
|
6
|
+
Extensions["Table"] = "table";
|
|
7
|
+
Extensions["TableCell"] = "tableCell";
|
|
8
|
+
Extensions["TableHeader"] = "tableHeader";
|
|
9
|
+
Extensions["TableRow"] = "tableRow";
|
|
10
|
+
Extensions["Placeholder"] = "placeholder";
|
|
11
|
+
Extensions["Focus"] = "focus";
|
|
12
|
+
Extensions["Image"] = "image";
|
|
13
|
+
Extensions["CustomStorage"] = "storage";
|
|
14
|
+
Extensions["SlashCommand"] = "slashCommand";
|
|
15
|
+
})(Extensions || (Extensions = {}));
|
|
16
|
+
export default Extensions;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
declare enum SlashCommands {
|
|
2
|
+
Text = "Text",
|
|
3
|
+
Heading1 = "Heading 1",
|
|
4
|
+
Heading2 = "Heading 2",
|
|
5
|
+
Heading3 = "Heading 3",
|
|
6
|
+
Heading4 = "Heading 4",
|
|
7
|
+
BulletList = "Bullet List",
|
|
8
|
+
NumberedList = "Numbered List",
|
|
9
|
+
CurrentDate = "Current Date",
|
|
10
|
+
CurrentTimestamp = "Current Timestamp",
|
|
11
|
+
Image = "Image"
|
|
12
|
+
}
|
|
13
|
+
export default SlashCommands;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
var SlashCommands;
|
|
2
|
+
(function (SlashCommands) {
|
|
3
|
+
SlashCommands["Text"] = "Text";
|
|
4
|
+
SlashCommands["Heading1"] = "Heading 1";
|
|
5
|
+
SlashCommands["Heading2"] = "Heading 2";
|
|
6
|
+
SlashCommands["Heading3"] = "Heading 3";
|
|
7
|
+
SlashCommands["Heading4"] = "Heading 4";
|
|
8
|
+
SlashCommands["BulletList"] = "Bullet List";
|
|
9
|
+
SlashCommands["NumberedList"] = "Numbered List";
|
|
10
|
+
SlashCommands["CurrentDate"] = "Current Date";
|
|
11
|
+
SlashCommands["CurrentTimestamp"] = "Current Timestamp";
|
|
12
|
+
SlashCommands["Image"] = "Image";
|
|
13
|
+
})(SlashCommands || (SlashCommands = {}));
|
|
14
|
+
export default SlashCommands;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
interface SlashCommandListProps {
|
|
2
|
+
className?: string;
|
|
3
|
+
items: any[];
|
|
4
|
+
command: (item: any) => void;
|
|
5
|
+
editor: any;
|
|
6
|
+
range: any;
|
|
7
|
+
}
|
|
8
|
+
declare const SlashCommandList: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<SlashCommandListProps, never>> & string & Omit<({ className, items, command, editor, range }: SlashCommandListProps) => import("react/jsx-runtime").JSX.Element | null, keyof import("react").Component<any, {}, any>>;
|
|
9
|
+
export default SlashCommandList;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useLayoutEffect, useRef, useState, } from "react";
|
|
3
|
+
import styled from "styled-components";
|
|
4
|
+
const updateScrollView = (container, item) => {
|
|
5
|
+
const containerHeight = container.offsetHeight;
|
|
6
|
+
const itemHeight = item ? item.offsetHeight : 0;
|
|
7
|
+
const top = item.offsetTop;
|
|
8
|
+
const bottom = top + itemHeight;
|
|
9
|
+
if (top < container.scrollTop) {
|
|
10
|
+
container.scrollTop -= container.scrollTop - top + 5;
|
|
11
|
+
}
|
|
12
|
+
else if (bottom > containerHeight + container.scrollTop) {
|
|
13
|
+
container.scrollTop += bottom - containerHeight - container.scrollTop + 5;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
const SlashCommandList = styled(({ className, items, command, editor, range }) => {
|
|
17
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
18
|
+
const selectItem = useCallback((index) => {
|
|
19
|
+
const item = items[index];
|
|
20
|
+
if (item) {
|
|
21
|
+
command(item);
|
|
22
|
+
}
|
|
23
|
+
}, [
|
|
24
|
+
// complete,
|
|
25
|
+
range,
|
|
26
|
+
command,
|
|
27
|
+
editor,
|
|
28
|
+
items,
|
|
29
|
+
]);
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
const navigationKeys = ["ArrowUp", "ArrowDown", "Enter"];
|
|
32
|
+
const onKeyDown = (e) => {
|
|
33
|
+
if (navigationKeys.includes(e.key)) {
|
|
34
|
+
e.preventDefault();
|
|
35
|
+
e.stopPropagation();
|
|
36
|
+
if (e.key === "ArrowUp") {
|
|
37
|
+
setSelectedIndex((selectedIndex + items.length - 1) % items.length);
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
if (e.key === "ArrowDown") {
|
|
41
|
+
setSelectedIndex((selectedIndex + 1) % items.length);
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
if (e.key === "Enter") {
|
|
45
|
+
selectItem(selectedIndex);
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
document === null || document === void 0 ? void 0 : document.addEventListener("keydown", onKeyDown);
|
|
52
|
+
return () => {
|
|
53
|
+
document === null || document === void 0 ? void 0 : document.removeEventListener("keydown", onKeyDown);
|
|
54
|
+
};
|
|
55
|
+
}, [items, selectedIndex, selectItem, setSelectedIndex]);
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
setSelectedIndex(0);
|
|
58
|
+
}, [items]);
|
|
59
|
+
const commandListContainer = useRef(null);
|
|
60
|
+
useLayoutEffect(() => {
|
|
61
|
+
const container = commandListContainer === null || commandListContainer === void 0 ? void 0 : commandListContainer.current;
|
|
62
|
+
const item = container === null || container === void 0 ? void 0 : container.children[selectedIndex];
|
|
63
|
+
if (item && container)
|
|
64
|
+
updateScrollView(container, item);
|
|
65
|
+
}, [selectedIndex]);
|
|
66
|
+
return items.length > 0 ? (_jsx("div", { id: "slash-command", ref: commandListContainer, className: className + " slash-command", children: items.map((item, index) => {
|
|
67
|
+
return (_jsxs("button", { className: `slash-command-item ${index === selectedIndex ? "selected" : ""}`, onClick: () => selectItem(index), children: [_jsx("div", { className: "item-icon", children: _jsx(item.icon, { size: 18 }) }), _jsxs("div", { children: [_jsx("div", { className: "item-title", children: item.title }), _jsx("div", { className: "item-description", children: item.description })] })] }, index));
|
|
68
|
+
}) })) : null;
|
|
69
|
+
}) `
|
|
70
|
+
&.slash-command {
|
|
71
|
+
display: flex;
|
|
72
|
+
flex-direction: column;
|
|
73
|
+
gap: 0.25rem;
|
|
74
|
+
z-index: 16001;
|
|
75
|
+
height: auto;
|
|
76
|
+
max-height: 330px;
|
|
77
|
+
width: 18rem;
|
|
78
|
+
overflow-y: auto;
|
|
79
|
+
border: 1px solid ${({ theme }) => theme.palette.divider};
|
|
80
|
+
border-radius: 0.375rem;
|
|
81
|
+
background-color: ${({ theme }) => theme.palette.background.default};
|
|
82
|
+
padding: 0.5rem;
|
|
83
|
+
transition: all 0.2s ease-in-out;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.slash-command-item {
|
|
87
|
+
display: flex;
|
|
88
|
+
width: 100%;
|
|
89
|
+
align-items: center;
|
|
90
|
+
justify-content: flex-start;
|
|
91
|
+
border-radius: 0.375rem;
|
|
92
|
+
padding: 0.25rem 0.5rem;
|
|
93
|
+
text-align: left;
|
|
94
|
+
font-size: 0.875rem;
|
|
95
|
+
color: ${({ theme }) => theme.palette.text.primary};
|
|
96
|
+
background-color: ${({ theme }) => theme.palette.background.default};
|
|
97
|
+
outline: none;
|
|
98
|
+
border: none;
|
|
99
|
+
|
|
100
|
+
&:hover {
|
|
101
|
+
background-color: ${({ theme }) => theme.palette.action.hover};
|
|
102
|
+
cursor: pointer;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.slash-command-item.selected {
|
|
107
|
+
background-color: ${({ theme }) => theme.palette.action.hover};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.item-icon {
|
|
111
|
+
display: flex;
|
|
112
|
+
width: 2.5rem;
|
|
113
|
+
height: 2.5rem;
|
|
114
|
+
align-items: center;
|
|
115
|
+
justify-content: center;
|
|
116
|
+
border-radius: 0.375rem;
|
|
117
|
+
border: 1px solid ${({ theme }) => theme.palette.divider};
|
|
118
|
+
margin-right: 0.5rem;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.item-title {
|
|
122
|
+
font-weight: 600;
|
|
123
|
+
font-size: 0.8rem;
|
|
124
|
+
margin-bottom: 0.125rem;
|
|
125
|
+
text-overflow: ellipsis;
|
|
126
|
+
overflow: hidden;
|
|
127
|
+
white-space: nowrap;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.item-description {
|
|
131
|
+
font-size: 0.75rem;
|
|
132
|
+
color: ${({ theme }) => theme.palette.text.secondary};
|
|
133
|
+
text-overflow: ellipsis;
|
|
134
|
+
overflow: hidden;
|
|
135
|
+
white-space: nowrap;
|
|
136
|
+
}
|
|
137
|
+
`;
|
|
138
|
+
export default SlashCommandList;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Extension } from "@tiptap/core";
|
|
2
|
+
import { HandleImageUpload } from "../Plugins/UploadImagesPlugin.js";
|
|
3
|
+
import SlashCommands from "../Enums/SlashCommands";
|
|
4
|
+
type CommandName = keyof typeof SlashCommands;
|
|
5
|
+
interface SlashCommandOptions {
|
|
6
|
+
handleImageUpload?: HandleImageUpload;
|
|
7
|
+
commands?: CommandName[];
|
|
8
|
+
}
|
|
9
|
+
declare const getSlashCommand: (options?: SlashCommandOptions) => Extension;
|
|
10
|
+
export default getSlashCommand;
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { Extension } from "@tiptap/core";
|
|
11
|
+
import Suggestion from "@tiptap/suggestion";
|
|
12
|
+
import { ReactRenderer } from "@tiptap/react";
|
|
13
|
+
import tippy from "tippy.js";
|
|
14
|
+
import { Heading1, Heading2, Heading3, Heading4, List, ListOrdered, Text, Image as ImageIcon, Calendar, ClockIcon, } from "lucide-react";
|
|
15
|
+
import { startImageUpload, } from "../Plugins/UploadImagesPlugin.js";
|
|
16
|
+
import { PluginKey } from "@tiptap/pm/state";
|
|
17
|
+
import SlashCommandList from "./SlashCommandList";
|
|
18
|
+
import SlashCommands from "../Enums/SlashCommands";
|
|
19
|
+
import moment from "moment/moment.js";
|
|
20
|
+
const SlashCommandPluginKey = new PluginKey("slash-command");
|
|
21
|
+
const Command = Extension.create({
|
|
22
|
+
name: "slash-command",
|
|
23
|
+
priority: 1000,
|
|
24
|
+
addKeyboardShortcuts() {
|
|
25
|
+
return {
|
|
26
|
+
Enter: ({ editor }) => {
|
|
27
|
+
// Prevent Enter key when slash command is active
|
|
28
|
+
const slashCommandState = SlashCommandPluginKey.getState(editor.state);
|
|
29
|
+
if (slashCommandState && slashCommandState.active) {
|
|
30
|
+
return true; // Returning true prevents default behavior.
|
|
31
|
+
}
|
|
32
|
+
return false; // Returning false allows default behavior.
|
|
33
|
+
},
|
|
34
|
+
ArrowUp: ({ editor }) => {
|
|
35
|
+
// Prevent ArrowUp key when slash command is active
|
|
36
|
+
const slashCommandState = SlashCommandPluginKey.getState(editor.state);
|
|
37
|
+
if (slashCommandState && slashCommandState.active) {
|
|
38
|
+
return true; // Returning true prevents default behavior.
|
|
39
|
+
}
|
|
40
|
+
return false; // Returning false allows default behavior.
|
|
41
|
+
},
|
|
42
|
+
ArrowDown: ({ editor }) => {
|
|
43
|
+
// Prevent ArrowDown key when slash command is active
|
|
44
|
+
const slashCommandState = SlashCommandPluginKey.getState(editor.state);
|
|
45
|
+
if (slashCommandState && slashCommandState.active) {
|
|
46
|
+
return true; // Returning true prevents default behavior.
|
|
47
|
+
}
|
|
48
|
+
return false; // Returning false allows default behavior.
|
|
49
|
+
},
|
|
50
|
+
// Add more keys here as needed
|
|
51
|
+
};
|
|
52
|
+
},
|
|
53
|
+
addOptions() {
|
|
54
|
+
return {
|
|
55
|
+
suggestion: {
|
|
56
|
+
char: "/",
|
|
57
|
+
pluginKey: SlashCommandPluginKey,
|
|
58
|
+
command: ({ editor, range, props }) => {
|
|
59
|
+
props.command({ editor, range });
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
addProseMirrorPlugins() {
|
|
65
|
+
return [
|
|
66
|
+
Suggestion(Object.assign({ editor: this.editor }, this.options.suggestion)),
|
|
67
|
+
];
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
const getCommandItems = (values, options) => {
|
|
71
|
+
var _a;
|
|
72
|
+
if ((_a = options === null || options === void 0 ? void 0 : options.commands) === null || _a === void 0 ? void 0 : _a.includes(SlashCommands.Image)) {
|
|
73
|
+
// Assert that options.handleImageUpload is defined
|
|
74
|
+
if (!options.handleImageUpload) {
|
|
75
|
+
throw new Error("options.handleImageUpload is required when using the Image command.");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return [
|
|
79
|
+
{
|
|
80
|
+
title: SlashCommands.Text,
|
|
81
|
+
description: "Just start typing with plain text.",
|
|
82
|
+
searchTerms: ["p", "paragraph"],
|
|
83
|
+
icon: Text,
|
|
84
|
+
command: ({ editor, range }) => {
|
|
85
|
+
editor
|
|
86
|
+
.chain()
|
|
87
|
+
.focus()
|
|
88
|
+
.deleteRange(range)
|
|
89
|
+
.toggleNode("paragraph", "paragraph")
|
|
90
|
+
.run();
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
title: SlashCommands.Heading1,
|
|
95
|
+
description: "Large section heading.",
|
|
96
|
+
searchTerms: ["title", "big", "large"],
|
|
97
|
+
icon: Heading1,
|
|
98
|
+
command: ({ editor, range }) => {
|
|
99
|
+
editor
|
|
100
|
+
.chain()
|
|
101
|
+
.focus()
|
|
102
|
+
.deleteRange(range)
|
|
103
|
+
.setNode("heading", { level: 1 })
|
|
104
|
+
.run();
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
title: SlashCommands.Heading2,
|
|
109
|
+
description: "Medium section heading.",
|
|
110
|
+
searchTerms: ["subtitle", "medium"],
|
|
111
|
+
icon: Heading2,
|
|
112
|
+
command: ({ editor, range }) => {
|
|
113
|
+
editor
|
|
114
|
+
.chain()
|
|
115
|
+
.focus()
|
|
116
|
+
.deleteRange(range)
|
|
117
|
+
.setNode("heading", { level: 2 })
|
|
118
|
+
.run();
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
title: SlashCommands.Heading3,
|
|
123
|
+
description: "Small section heading.",
|
|
124
|
+
searchTerms: ["subtitle", "small"],
|
|
125
|
+
icon: Heading3,
|
|
126
|
+
command: ({ editor, range }) => {
|
|
127
|
+
editor
|
|
128
|
+
.chain()
|
|
129
|
+
.focus()
|
|
130
|
+
.deleteRange(range)
|
|
131
|
+
.setNode("heading", { level: 3 })
|
|
132
|
+
.run();
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
title: SlashCommands.Heading4,
|
|
137
|
+
description: "Smaller section heading.",
|
|
138
|
+
searchTerms: ["subtitle", "small"],
|
|
139
|
+
icon: Heading4,
|
|
140
|
+
command: ({ editor, range }) => {
|
|
141
|
+
editor
|
|
142
|
+
.chain()
|
|
143
|
+
.focus()
|
|
144
|
+
.deleteRange(range)
|
|
145
|
+
.setNode("heading", { level: 4 })
|
|
146
|
+
.run();
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
title: SlashCommands.BulletList,
|
|
151
|
+
description: "Create a simple bullet list.",
|
|
152
|
+
searchTerms: ["unordered", "point", "bullet"],
|
|
153
|
+
icon: List,
|
|
154
|
+
command: ({ editor, range }) => {
|
|
155
|
+
editor.chain().focus().deleteRange(range).toggleBulletList().run();
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
title: SlashCommands.NumberedList,
|
|
160
|
+
description: "Create a list with numbering.",
|
|
161
|
+
searchTerms: ["ordered", "numbered"],
|
|
162
|
+
icon: ListOrdered,
|
|
163
|
+
command: ({ editor, range }) => {
|
|
164
|
+
editor.chain().focus().deleteRange(range).toggleOrderedList().run();
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
title: SlashCommands.CurrentDate,
|
|
169
|
+
description: "Insert the current date.",
|
|
170
|
+
searchTerms: ["date"],
|
|
171
|
+
icon: Calendar,
|
|
172
|
+
command: ({ editor, range }) => {
|
|
173
|
+
const currentDate = moment().format("YYYY-MM-DD");
|
|
174
|
+
editor
|
|
175
|
+
.chain()
|
|
176
|
+
.focus()
|
|
177
|
+
.deleteRange(range)
|
|
178
|
+
.insertContent(currentDate)
|
|
179
|
+
.run();
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
title: SlashCommands.CurrentTimestamp,
|
|
184
|
+
description: "Insert the current timestamp.",
|
|
185
|
+
searchTerms: ["timestamp"],
|
|
186
|
+
icon: ClockIcon,
|
|
187
|
+
command: ({ editor, range }) => {
|
|
188
|
+
const currentDate = moment().format("YYYY-MM-DD HH:mm:ss Z");
|
|
189
|
+
editor
|
|
190
|
+
.chain()
|
|
191
|
+
.focus()
|
|
192
|
+
.deleteRange(range)
|
|
193
|
+
.insertContent(currentDate)
|
|
194
|
+
.run();
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
title: SlashCommands.Image,
|
|
199
|
+
description: "Upload an image from your computer.",
|
|
200
|
+
searchTerms: ["photo", "picture", "media"],
|
|
201
|
+
icon: ImageIcon,
|
|
202
|
+
command: ({ editor, range }) => {
|
|
203
|
+
editor.chain().focus().deleteRange(range).run();
|
|
204
|
+
// upload image
|
|
205
|
+
const input = document.createElement("input");
|
|
206
|
+
input.type = "file";
|
|
207
|
+
input.accept = "image/*";
|
|
208
|
+
input.onchange = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
209
|
+
var _a;
|
|
210
|
+
if ((_a = input.files) === null || _a === void 0 ? void 0 : _a.length) {
|
|
211
|
+
const file = input.files[0];
|
|
212
|
+
// places the image before the cursor, otherwise the image is placed after the cursor on a new line
|
|
213
|
+
const pos = editor.view.state.selection.from - 1;
|
|
214
|
+
if (options === null || options === void 0 ? void 0 : options.handleImageUpload) {
|
|
215
|
+
startImageUpload(file, editor.view, pos, options === null || options === void 0 ? void 0 : options.handleImageUpload);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
input.click();
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
]
|
|
223
|
+
.filter((item) => {
|
|
224
|
+
if (options === null || options === void 0 ? void 0 : options.commands) {
|
|
225
|
+
return options.commands.includes(item.title);
|
|
226
|
+
}
|
|
227
|
+
return true;
|
|
228
|
+
})
|
|
229
|
+
.filter((item) => {
|
|
230
|
+
var _a, _b;
|
|
231
|
+
if (typeof (values === null || values === void 0 ? void 0 : values.query) === "string" && ((_a = values === null || values === void 0 ? void 0 : values.query) === null || _a === void 0 ? void 0 : _a.length) > 0) {
|
|
232
|
+
const search = (_b = values === null || values === void 0 ? void 0 : values.query) === null || _b === void 0 ? void 0 : _b.toLowerCase();
|
|
233
|
+
return (item.title.toLowerCase().includes(search) ||
|
|
234
|
+
item.description.toLowerCase().includes(search) ||
|
|
235
|
+
(item.searchTerms &&
|
|
236
|
+
item.searchTerms.some((term) => term.includes(search))));
|
|
237
|
+
}
|
|
238
|
+
return true;
|
|
239
|
+
});
|
|
240
|
+
};
|
|
241
|
+
const renderItems = () => {
|
|
242
|
+
let component = null;
|
|
243
|
+
let popup = null;
|
|
244
|
+
return {
|
|
245
|
+
onStart: (props) => {
|
|
246
|
+
component = new ReactRenderer(SlashCommandList, {
|
|
247
|
+
props,
|
|
248
|
+
editor: props.editor,
|
|
249
|
+
});
|
|
250
|
+
// @ts-ignore
|
|
251
|
+
popup = tippy("body", {
|
|
252
|
+
getReferenceClientRect: props.clientRect,
|
|
253
|
+
appendTo: () => document.body,
|
|
254
|
+
content: component.element,
|
|
255
|
+
showOnCreate: true,
|
|
256
|
+
interactive: true,
|
|
257
|
+
trigger: "manual",
|
|
258
|
+
placement: "bottom-start",
|
|
259
|
+
zIndex: 16000,
|
|
260
|
+
});
|
|
261
|
+
},
|
|
262
|
+
onUpdate: (props) => {
|
|
263
|
+
component === null || component === void 0 ? void 0 : component.updateProps(props);
|
|
264
|
+
popup &&
|
|
265
|
+
popup[0].setProps({
|
|
266
|
+
getReferenceClientRect: props.clientRect,
|
|
267
|
+
});
|
|
268
|
+
},
|
|
269
|
+
onKeyDown: ({ event }) => {
|
|
270
|
+
var _a;
|
|
271
|
+
if (event.key === "Escape") {
|
|
272
|
+
popup === null || popup === void 0 ? void 0 : popup[0].hide();
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
// @ts-ignore
|
|
276
|
+
return (_a = component === null || component === void 0 ? void 0 : component.ref) === null || _a === void 0 ? void 0 : _a.onKeyDown({ event });
|
|
277
|
+
},
|
|
278
|
+
onExit: (e) => {
|
|
279
|
+
// process close of popup on next tick
|
|
280
|
+
// to avoid conflict with the keyboard "enter" event
|
|
281
|
+
setTimeout(() => {
|
|
282
|
+
popup === null || popup === void 0 ? void 0 : popup[0].destroy();
|
|
283
|
+
component === null || component === void 0 ? void 0 : component.destroy();
|
|
284
|
+
}, 0);
|
|
285
|
+
},
|
|
286
|
+
};
|
|
287
|
+
};
|
|
288
|
+
const getSlashCommand = (options) => {
|
|
289
|
+
return Command.configure({
|
|
290
|
+
suggestion: {
|
|
291
|
+
items: (e) => getCommandItems(e, options),
|
|
292
|
+
render: renderItems,
|
|
293
|
+
},
|
|
294
|
+
});
|
|
295
|
+
};
|
|
296
|
+
export default getSlashCommand;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Extension } from "@tiptap/core";
|
|
2
|
+
import { HandleImageUpload } from "../Plugins/UploadImagesPlugin";
|
|
3
|
+
import Extensions from "../Enums/Extensions";
|
|
4
|
+
export type ExtensionType = (typeof Extensions)[keyof typeof Extensions];
|
|
5
|
+
interface GetTipTapExtensionsProps {
|
|
6
|
+
extensions?: ExtensionType[];
|
|
7
|
+
slashCommands?: any[];
|
|
8
|
+
handleImageUpload?: HandleImageUpload;
|
|
9
|
+
}
|
|
10
|
+
declare const getTipTapExtensions: (props: GetTipTapExtensionsProps) => Extension[];
|
|
11
|
+
export default getTipTapExtensions;
|