@monolith-forensics/monolith-ui 1.9.1-dev.1 → 1.9.1-dev.11
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/DropDownMenu/components/MenuItemList.js +32 -12
- package/dist/DropDownMenu/components/StyledInnerItemContainer.js +1 -0
- package/dist/MonolithUIProvider/MonolithUIProvider.d.ts +23 -0
- package/dist/RichTextEditor/Components/BubbleMenu.d.ts +8 -8
- package/dist/RichTextEditor/Components/BubbleMenu.js +195 -93
- package/dist/RichTextEditor/Components/CodeBlockBaseButton.d.ts +18 -0
- package/dist/RichTextEditor/Components/CodeBlockBaseButton.js +6 -0
- package/dist/RichTextEditor/Components/CodeBlockCopyButton.d.ts +9 -0
- package/dist/RichTextEditor/Components/CodeBlockCopyButton.js +42 -0
- package/dist/RichTextEditor/Components/CodeBlockFormatButton.d.ts +10 -0
- package/dist/RichTextEditor/Components/CodeBlockFormatButton.js +60 -0
- package/dist/RichTextEditor/Components/CodeBlockLanguageSelect.d.ts +9 -0
- package/dist/RichTextEditor/Components/CodeBlockLanguageSelect.js +30 -0
- package/dist/RichTextEditor/Components/CodeBlockNodeView.d.ts +3 -0
- package/dist/RichTextEditor/Components/CodeBlockNodeView.js +28 -0
- package/dist/RichTextEditor/Components/CodeBlockWrapButton.d.ts +10 -0
- package/dist/RichTextEditor/Components/CodeBlockWrapButton.js +17 -0
- package/dist/RichTextEditor/Components/LinkEditor.d.ts +8 -0
- package/dist/RichTextEditor/Components/LinkEditor.js +94 -0
- package/dist/RichTextEditor/Enums/Controls.d.ts +5 -1
- package/dist/RichTextEditor/Enums/Controls.js +4 -0
- package/dist/RichTextEditor/Enums/Extensions.d.ts +4 -0
- package/dist/RichTextEditor/Enums/Extensions.js +4 -0
- package/dist/RichTextEditor/Enums/HighlightColors.d.ts +9 -0
- package/dist/RichTextEditor/Enums/HighlightColors.js +10 -0
- package/dist/RichTextEditor/Enums/SlashCommands.d.ts +2 -0
- package/dist/RichTextEditor/Enums/SlashCommands.js +2 -0
- package/dist/RichTextEditor/Extensions/SlashCommandList.js +0 -1
- package/dist/RichTextEditor/Extensions/getSlashCommand.js +25 -1
- package/dist/RichTextEditor/Extensions/getTiptapExtensions.d.ts +10 -2
- package/dist/RichTextEditor/Extensions/getTiptapExtensions.js +158 -31
- package/dist/RichTextEditor/Plugins/ImageActionsPlugin.js +6 -109
- package/dist/RichTextEditor/Plugins/UploadImagesPlugin.js +1 -0
- package/dist/RichTextEditor/RichTextEditor.d.ts +4 -2
- package/dist/RichTextEditor/RichTextEditor.js +323 -13
- package/dist/RichTextEditor/Toolbar/Control.d.ts +6 -2
- package/dist/RichTextEditor/Toolbar/Control.js +13 -6
- package/dist/RichTextEditor/Toolbar/Controls.d.ts +2 -0
- package/dist/RichTextEditor/Toolbar/Controls.js +14 -0
- package/dist/RichTextEditor/Toolbar/ControlsGroup.js +1 -0
- package/dist/RichTextEditor/Toolbar/Toolbar.js +61 -9
- package/dist/RichTextEditor/Utils/codeBlockUtils.d.ts +20 -0
- package/dist/RichTextEditor/Utils/codeBlockUtils.js +137 -0
- package/dist/RichTextEditor/Utils/codeUtils.d.ts +3 -0
- package/dist/RichTextEditor/Utils/codeUtils.js +12 -0
- package/dist/RichTextEditor/Utils/linkUtils.d.ts +19 -0
- package/dist/RichTextEditor/Utils/linkUtils.js +57 -0
- package/dist/theme/variants.js +46 -0
- package/package.json +8 -1
- package/dist/RichTextEditor/Extensions/BubbleMenuExtension.d.ts +0 -7
- package/dist/RichTextEditor/Extensions/BubbleMenuExtension.js +0 -157
|
@@ -56,11 +56,18 @@ const buildGroupedDisplayList = (items) => {
|
|
|
56
56
|
const ListViewPort = styled.div.attrs({ className: "ListViewPort" }) `
|
|
57
57
|
display: flex;
|
|
58
58
|
flex-direction: column;
|
|
59
|
+
flex: 1 1 auto;
|
|
60
|
+
min-height: 0;
|
|
59
61
|
width: 100%;
|
|
60
62
|
`;
|
|
63
|
+
const MenuItemListRoot = styled.div `
|
|
64
|
+
display: flex;
|
|
65
|
+
flex-direction: column;
|
|
66
|
+
height: 100%;
|
|
67
|
+
min-height: 0;
|
|
68
|
+
`;
|
|
61
69
|
const ListScroller = styled.div `
|
|
62
70
|
scrollbar-color: ${({ theme }) => `${theme.scrollbar.thumb} ${theme.scrollbar.track}`};
|
|
63
|
-
scrollbar-gutter: stable;
|
|
64
71
|
scrollbar-width: thin;
|
|
65
72
|
|
|
66
73
|
&::-webkit-scrollbar {
|
|
@@ -234,16 +241,6 @@ export const MenuItemList = ({ menuItems, searchable, onSearch, manualSearch, dy
|
|
|
234
241
|
list.addEventListener("scroll", handleOnScroll);
|
|
235
242
|
return () => list.removeEventListener("scroll", handleOnScroll);
|
|
236
243
|
}, [dynamicOptionHeight, handleOnScroll, isLoading, renderOption]);
|
|
237
|
-
useLayoutEffect(() => {
|
|
238
|
-
var _a;
|
|
239
|
-
if (targetElm.current) {
|
|
240
|
-
const viewPortDimensions = (_a = targetElm.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
|
|
241
|
-
setViewPortDimensions({
|
|
242
|
-
width: viewPortDimensions.width,
|
|
243
|
-
height: viewPortDimensions.height,
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
}, [targetElm.current, isLoading]);
|
|
247
244
|
const overscanCount = 10;
|
|
248
245
|
const sizeTokens = getControlSizeTokens(size || "sm");
|
|
249
246
|
const itemHeight = sizeTokens.menuRowHeight;
|
|
@@ -267,6 +264,29 @@ export const MenuItemList = ({ menuItems, searchable, onSearch, manualSearch, dy
|
|
|
267
264
|
? estimatedHeight
|
|
268
265
|
: 200;
|
|
269
266
|
const width = "100%";
|
|
267
|
+
useLayoutEffect(() => {
|
|
268
|
+
const target = targetElm.current;
|
|
269
|
+
if (!target)
|
|
270
|
+
return;
|
|
271
|
+
const updateDimensions = () => {
|
|
272
|
+
const nextDimensions = target.getBoundingClientRect();
|
|
273
|
+
setViewPortDimensions((currentDimensions) => {
|
|
274
|
+
const width = Math.ceil(nextDimensions.width);
|
|
275
|
+
const height = Math.floor(nextDimensions.height);
|
|
276
|
+
if (currentDimensions.width === width &&
|
|
277
|
+
currentDimensions.height === height) {
|
|
278
|
+
return currentDimensions;
|
|
279
|
+
}
|
|
280
|
+
return { width, height };
|
|
281
|
+
});
|
|
282
|
+
};
|
|
283
|
+
updateDimensions();
|
|
284
|
+
if (typeof ResizeObserver === "undefined")
|
|
285
|
+
return;
|
|
286
|
+
const observer = new ResizeObserver(updateDimensions);
|
|
287
|
+
observer.observe(target);
|
|
288
|
+
return () => observer.disconnect();
|
|
289
|
+
}, [displayItemsKey, isLoading]);
|
|
270
290
|
const setItemSize = useCallback((index, measuredSize) => {
|
|
271
291
|
var _a;
|
|
272
292
|
if (itemSizeMap.current[index] === measuredSize)
|
|
@@ -335,7 +355,7 @@ export const MenuItemList = ({ menuItems, searchable, onSearch, manualSearch, dy
|
|
|
335
355
|
(item === null || item === void 0 ? void 0 : item.label) ||
|
|
336
356
|
(typeof item === "string" || typeof item === "number" ? item : null) }, index));
|
|
337
357
|
};
|
|
338
|
-
return (_jsxs(
|
|
358
|
+
return (_jsxs(MenuItemListRoot, { children: [searchable && (_jsx(SearchInput, { variant: "outlined", size: size, placeholder: "Search", defaultValue: searchValue, onChange: (e) => {
|
|
339
359
|
if (!manualSearch) {
|
|
340
360
|
handleSearch(e);
|
|
341
361
|
}
|
|
@@ -81,6 +81,29 @@ export interface MonolithDefaultTheme {
|
|
|
81
81
|
action: {
|
|
82
82
|
hover: string;
|
|
83
83
|
};
|
|
84
|
+
codeBlock?: {
|
|
85
|
+
background: string;
|
|
86
|
+
text: string;
|
|
87
|
+
border: string;
|
|
88
|
+
selection: string;
|
|
89
|
+
syntax: {
|
|
90
|
+
comment: string;
|
|
91
|
+
punctuation: string;
|
|
92
|
+
property: string;
|
|
93
|
+
selector: string;
|
|
94
|
+
operator: string;
|
|
95
|
+
keyword: string;
|
|
96
|
+
string: string;
|
|
97
|
+
number: string;
|
|
98
|
+
function: string;
|
|
99
|
+
variable: string;
|
|
100
|
+
tag: string;
|
|
101
|
+
attribute: string;
|
|
102
|
+
literal: string;
|
|
103
|
+
deleted: string;
|
|
104
|
+
inserted: string;
|
|
105
|
+
};
|
|
106
|
+
};
|
|
84
107
|
divider: string;
|
|
85
108
|
};
|
|
86
109
|
header: {
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import { Extensions } from "../Enums";
|
|
2
2
|
import { DropDownItem, DropDownMenuProps } from "../../DropDownMenu";
|
|
3
|
-
import { ReactElement } from "react";
|
|
3
|
+
import { ReactElement, ReactNode } from "react";
|
|
4
4
|
import { ButtonProps } from "../../Button";
|
|
5
5
|
import { Editor } from "@tiptap/react";
|
|
6
|
-
export interface
|
|
6
|
+
export interface BubbleMenuContentProps {
|
|
7
7
|
className?: string;
|
|
8
8
|
editor: Editor;
|
|
9
|
-
rect: DOMRect;
|
|
10
|
-
open: boolean;
|
|
11
|
-
onOpen?: (element: HTMLElement) => void;
|
|
12
9
|
customMenuItems?: BubbleItem[];
|
|
13
10
|
}
|
|
14
11
|
interface BubbleMenuDropDownItem extends DropDownItem {
|
|
@@ -20,7 +17,7 @@ export type BubbleItem = {
|
|
|
20
17
|
name: Extensions | string;
|
|
21
18
|
icon?: React.FC<any>;
|
|
22
19
|
type: "menu";
|
|
23
|
-
label?:
|
|
20
|
+
label?: ReactNode;
|
|
24
21
|
items: BubbleMenuDropDownItem[];
|
|
25
22
|
arrow?: boolean;
|
|
26
23
|
isActive?: (editor: Editor) => boolean;
|
|
@@ -32,12 +29,15 @@ export type BubbleItem = {
|
|
|
32
29
|
name: Extensions | string;
|
|
33
30
|
icon?: React.FC<any>;
|
|
34
31
|
type: "button";
|
|
35
|
-
label?:
|
|
32
|
+
label?: ReactNode;
|
|
36
33
|
arrow?: boolean;
|
|
37
34
|
isActive?: (editor: Editor) => boolean;
|
|
38
35
|
buttonRender?: (props: any) => ReactElement;
|
|
39
36
|
buttonProps?: Partial<ButtonProps>;
|
|
40
37
|
onClick?: (editor: Editor) => void;
|
|
41
38
|
};
|
|
42
|
-
|
|
39
|
+
export type BubbleMenuOptions = {
|
|
40
|
+
customMenuItems?: BubbleItem[];
|
|
41
|
+
};
|
|
42
|
+
declare const BubbleMenu: React.FC<BubbleMenuContentProps>;
|
|
43
43
|
export default BubbleMenu;
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import styled, { useTheme } from "styled-components";
|
|
3
3
|
import { Extensions } from "../Enums";
|
|
4
|
-
import { BoldIcon, ItalicIcon, UnderlineIcon, CaseSensitiveIcon, ListIcon, ListOrderedIcon, StrikethroughIcon, Heading1Icon, Heading2Icon, Heading3Icon, Heading4Icon, RemoveFormattingIcon, SquircleIcon, } from "lucide-react";
|
|
4
|
+
import { BoldIcon, CodeIcon, ItalicIcon, UnderlineIcon, CaseSensitiveIcon, ListIcon, ListOrderedIcon, SquareCodeIcon, StrikethroughIcon, Heading1Icon, Heading2Icon, Heading3Icon, Heading4Icon, HighlighterIcon, LinkIcon, PaletteIcon, RemoveFormattingIcon, SquircleIcon, } from "lucide-react";
|
|
5
5
|
import { DropDownMenu, } from "../../DropDownMenu";
|
|
6
|
-
import {
|
|
7
|
-
import { useEffect, useRef } from "react";
|
|
6
|
+
import { useEffect, useState } from "react";
|
|
8
7
|
import { Button } from "../../Button";
|
|
9
8
|
import TextColors from "../Enums/TextColors";
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
import HighlightColors from "../Enums/HighlightColors";
|
|
10
|
+
import LinkEditor from "./LinkEditor";
|
|
11
|
+
import { hasInlineCode, toggleInlineCode } from "../Utils/codeUtils";
|
|
12
|
+
import { hasSyntaxHighlightedCodeBlock, toggleCodeBlock, } from "../Utils/codeBlockUtils";
|
|
13
|
+
const getMenuItems = (editor, customMenuItems, theme, openLinkEditor) => {
|
|
14
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
12
15
|
const node = (_c = (_b = (_a = editor === null || editor === void 0 ? void 0 : editor.state) === null || _a === void 0 ? void 0 : _a.selection) === null || _b === void 0 ? void 0 : _b.$from) === null || _c === void 0 ? void 0 : _c.parent;
|
|
13
16
|
const pos = (_e = (_d = editor === null || editor === void 0 ? void 0 : editor.state) === null || _d === void 0 ? void 0 : _d.selection) === null || _e === void 0 ? void 0 : _e.$from;
|
|
14
17
|
let withinUnorderedList = false;
|
|
@@ -24,6 +27,11 @@ const getMenuItems = (editor, customMenuItems, theme) => {
|
|
|
24
27
|
}
|
|
25
28
|
});
|
|
26
29
|
const attrs = node === null || node === void 0 ? void 0 : node.attrs;
|
|
30
|
+
const supportsSyntaxCodeBlock = hasSyntaxHighlightedCodeBlock(editor);
|
|
31
|
+
const supportsInlineCode = hasInlineCode(editor);
|
|
32
|
+
const supportsColor = Boolean(editor.extensionManager.extensions.find((extension) => extension.name === "color"));
|
|
33
|
+
const supportsHighlight = Boolean(editor.extensionManager.extensions.find((extension) => extension.name === "highlight"));
|
|
34
|
+
const supportsLink = Boolean(editor.extensionManager.extensions.find((extension) => extension.name === "link"));
|
|
27
35
|
let nodeTypeLabel = "Select Type";
|
|
28
36
|
let nodeTypeIcon = null;
|
|
29
37
|
if (withinOrderedList) {
|
|
@@ -38,7 +46,11 @@ const getMenuItems = (editor, customMenuItems, theme) => {
|
|
|
38
46
|
nodeTypeLabel = "Text";
|
|
39
47
|
nodeTypeIcon = _jsx(CaseSensitiveIcon, { size: 16 });
|
|
40
48
|
}
|
|
41
|
-
else if (((_g = node === null || node === void 0 ? void 0 : node.type) === null || _g === void 0 ? void 0 : _g.name) === "
|
|
49
|
+
else if (((_g = node === null || node === void 0 ? void 0 : node.type) === null || _g === void 0 ? void 0 : _g.name) === "codeBlock") {
|
|
50
|
+
nodeTypeLabel = "Code Block";
|
|
51
|
+
nodeTypeIcon = _jsx(SquareCodeIcon, { size: 16 });
|
|
52
|
+
}
|
|
53
|
+
else if (((_h = node === null || node === void 0 ? void 0 : node.type) === null || _h === void 0 ? void 0 : _h.name) === "heading") {
|
|
42
54
|
const level = attrs === null || attrs === void 0 ? void 0 : attrs.level;
|
|
43
55
|
nodeTypeLabel = `Heading ${level}`;
|
|
44
56
|
nodeTypeIcon =
|
|
@@ -50,7 +62,6 @@ const getMenuItems = (editor, customMenuItems, theme) => {
|
|
|
50
62
|
name: "node_type",
|
|
51
63
|
label: nodeTypeLabel,
|
|
52
64
|
type: "menu",
|
|
53
|
-
arrow: true,
|
|
54
65
|
buttonProps: {
|
|
55
66
|
leftSection: nodeTypeIcon,
|
|
56
67
|
style: { fontSize: 11, padding: "4px" },
|
|
@@ -62,13 +73,17 @@ const getMenuItems = (editor, customMenuItems, theme) => {
|
|
|
62
73
|
data: {
|
|
63
74
|
Icon: CaseSensitiveIcon,
|
|
64
75
|
command: (editor) => {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
76
|
+
if (editor.isActive("bulletList") ||
|
|
77
|
+
editor.isActive("orderedList")) {
|
|
78
|
+
editor
|
|
79
|
+
.chain()
|
|
80
|
+
.focus()
|
|
81
|
+
.liftListItem("listItem")
|
|
82
|
+
.setParagraph()
|
|
83
|
+
.run();
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
editor.chain().focus().setParagraph().run();
|
|
72
87
|
},
|
|
73
88
|
},
|
|
74
89
|
},
|
|
@@ -132,50 +147,120 @@ const getMenuItems = (editor, customMenuItems, theme) => {
|
|
|
132
147
|
},
|
|
133
148
|
},
|
|
134
149
|
},
|
|
150
|
+
...(supportsSyntaxCodeBlock
|
|
151
|
+
? [
|
|
152
|
+
{
|
|
153
|
+
label: "Code Block",
|
|
154
|
+
value: "code_block",
|
|
155
|
+
data: {
|
|
156
|
+
Icon: SquareCodeIcon,
|
|
157
|
+
command: (editor) => {
|
|
158
|
+
toggleCodeBlock(editor);
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
]
|
|
163
|
+
: []),
|
|
135
164
|
],
|
|
136
165
|
dropDownProps: {
|
|
137
166
|
renderOption: (item) => (_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 5 }, children: [_jsx(item.data.Icon, { size: 16 }), item.label] })),
|
|
138
167
|
},
|
|
139
168
|
},
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
label: "Color",
|
|
143
|
-
type: "menu",
|
|
144
|
-
arrow: true,
|
|
145
|
-
buttonProps: {
|
|
146
|
-
// leftSection: nodeTypeIcon,
|
|
147
|
-
style: { fontSize: 11, padding: "4px" },
|
|
148
|
-
},
|
|
149
|
-
items: [
|
|
169
|
+
...(supportsColor
|
|
170
|
+
? [
|
|
150
171
|
{
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
172
|
+
name: "color",
|
|
173
|
+
label: _jsx(PaletteIcon, { size: 14 }),
|
|
174
|
+
type: "menu",
|
|
175
|
+
buttonProps: {
|
|
176
|
+
style: { fontSize: 11, padding: "4px" },
|
|
177
|
+
},
|
|
178
|
+
items: [
|
|
179
|
+
{
|
|
180
|
+
label: "Default",
|
|
181
|
+
value: "default",
|
|
182
|
+
onClick: () => {
|
|
183
|
+
editor === null || editor === void 0 ? void 0 : editor.chain().focus().unsetColor().run();
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
...Object.keys(TextColors).map((color) => {
|
|
187
|
+
const colorKey = color;
|
|
188
|
+
return {
|
|
189
|
+
label: color,
|
|
190
|
+
value: TextColors[colorKey],
|
|
191
|
+
onClick: () => {
|
|
192
|
+
editor === null || editor === void 0 ? void 0 : editor.chain().focus().setColor(TextColors[colorKey]).run();
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
}),
|
|
196
|
+
],
|
|
197
|
+
dropDownProps: {
|
|
198
|
+
renderOption: (item) => (_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 5 }, children: [_jsx(SquircleIcon, { size: 12, color: item.value === "default"
|
|
199
|
+
? theme.palette.text.primary
|
|
200
|
+
: item.value, style: {
|
|
201
|
+
backgroundColor: item.value === "default"
|
|
202
|
+
? theme.palette.text.primary
|
|
203
|
+
: item.value,
|
|
204
|
+
borderRadius: "3px",
|
|
205
|
+
} }), item.label] })),
|
|
155
206
|
},
|
|
156
207
|
},
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
208
|
+
]
|
|
209
|
+
: []),
|
|
210
|
+
...(supportsHighlight
|
|
211
|
+
? [
|
|
212
|
+
{
|
|
213
|
+
name: Extensions.Highlight,
|
|
214
|
+
label: _jsx(HighlighterIcon, { size: 14 }),
|
|
215
|
+
type: "menu",
|
|
216
|
+
buttonProps: {
|
|
217
|
+
style: { fontSize: 11, padding: "4px" },
|
|
218
|
+
},
|
|
219
|
+
items: [
|
|
220
|
+
{
|
|
221
|
+
label: "Default",
|
|
222
|
+
value: "default",
|
|
223
|
+
onClick: () => {
|
|
224
|
+
editor === null || editor === void 0 ? void 0 : editor.chain().focus().unsetHighlight().run();
|
|
225
|
+
},
|
|
164
226
|
},
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
227
|
+
...Object.keys(HighlightColors).map((color) => {
|
|
228
|
+
const colorKey = color;
|
|
229
|
+
return {
|
|
230
|
+
label: color,
|
|
231
|
+
value: HighlightColors[colorKey],
|
|
232
|
+
onClick: () => {
|
|
233
|
+
editor === null || editor === void 0 ? void 0 : editor.chain().focus().setHighlight({ color: HighlightColors[colorKey] }).run();
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
}),
|
|
237
|
+
],
|
|
238
|
+
dropDownProps: {
|
|
239
|
+
renderOption: (item) => (_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 5 }, children: [_jsx(SquircleIcon, { size: 12, color: item.value === "default"
|
|
240
|
+
? theme.palette.text.primary
|
|
241
|
+
: item.value, style: {
|
|
242
|
+
backgroundColor: item.value === "default"
|
|
243
|
+
? "transparent"
|
|
244
|
+
: item.value,
|
|
245
|
+
borderRadius: "3px",
|
|
246
|
+
} }), item.label] })),
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
]
|
|
250
|
+
: []),
|
|
251
|
+
...(supportsLink
|
|
252
|
+
? [
|
|
253
|
+
{
|
|
254
|
+
name: Extensions.Link,
|
|
255
|
+
icon: LinkIcon,
|
|
256
|
+
type: "button",
|
|
257
|
+
isActive: (editor) => editor.isActive("link"),
|
|
258
|
+
onClick: () => {
|
|
259
|
+
openLinkEditor();
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
]
|
|
263
|
+
: []),
|
|
179
264
|
{
|
|
180
265
|
name: Extensions.Bold,
|
|
181
266
|
icon: BoldIcon,
|
|
@@ -212,6 +297,32 @@ const getMenuItems = (editor, customMenuItems, theme) => {
|
|
|
212
297
|
editor.chain().focus().toggleStrike().run();
|
|
213
298
|
},
|
|
214
299
|
},
|
|
300
|
+
...(supportsInlineCode
|
|
301
|
+
? [
|
|
302
|
+
{
|
|
303
|
+
name: Extensions.Code,
|
|
304
|
+
icon: CodeIcon,
|
|
305
|
+
type: "button",
|
|
306
|
+
isActive: (editor) => editor.isActive("code"),
|
|
307
|
+
onClick: (editor) => {
|
|
308
|
+
toggleInlineCode(editor);
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
]
|
|
312
|
+
: []),
|
|
313
|
+
...(supportsSyntaxCodeBlock
|
|
314
|
+
? [
|
|
315
|
+
{
|
|
316
|
+
name: Extensions.CodeBlock,
|
|
317
|
+
icon: SquareCodeIcon,
|
|
318
|
+
type: "button",
|
|
319
|
+
isActive: (editor) => editor.isActive("codeBlock"),
|
|
320
|
+
onClick: (editor) => {
|
|
321
|
+
toggleCodeBlock(editor);
|
|
322
|
+
},
|
|
323
|
+
},
|
|
324
|
+
]
|
|
325
|
+
: []),
|
|
215
326
|
{
|
|
216
327
|
name: Extensions.ClearFormatting,
|
|
217
328
|
icon: RemoveFormattingIcon,
|
|
@@ -224,12 +335,11 @@ const getMenuItems = (editor, customMenuItems, theme) => {
|
|
|
224
335
|
];
|
|
225
336
|
};
|
|
226
337
|
const BubbleMenuContent = styled.div `
|
|
227
|
-
position: fixed;
|
|
228
338
|
display: flex;
|
|
229
339
|
justify-content: space-between;
|
|
230
340
|
align-items: center;
|
|
231
341
|
padding: 2px;
|
|
232
|
-
gap:
|
|
342
|
+
gap: 4px;
|
|
233
343
|
|
|
234
344
|
color: ${({ theme }) => theme.palette.text.primary};
|
|
235
345
|
background-color: ${({ theme }) => theme.palette.input.background};
|
|
@@ -272,51 +382,43 @@ const BubbleItemButton = styled(Button) `
|
|
|
272
382
|
background-color: ${({ theme }) => theme.palette.action.hover};
|
|
273
383
|
}
|
|
274
384
|
`;
|
|
275
|
-
const
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
385
|
+
const CodeBlockBubbleTools = ({ editor, theme, }) => {
|
|
386
|
+
const nodeTypeMenu = getMenuItems(editor, [], theme, () => undefined).find((item) => item.name === "node_type");
|
|
387
|
+
return (_jsx(_Fragment, { children: (nodeTypeMenu === null || nodeTypeMenu === void 0 ? void 0 : nodeTypeMenu.type) === "menu" && (_jsx(DropDownMenu, Object.assign({ data: nodeTypeMenu.items, size: "xs", arrow: nodeTypeMenu.arrow, buttonProps: nodeTypeMenu.buttonProps, variant: "subtle", buttonRender: nodeTypeMenu.buttonRender, onItemSelect: (item) => { var _a, _b; return (_b = (_a = item === null || item === void 0 ? void 0 : item.data) === null || _a === void 0 ? void 0 : _a.command) === null || _b === void 0 ? void 0 : _b.call(_a, editor, ""); }, dropDownProps: {
|
|
388
|
+
style: { width: 135 },
|
|
389
|
+
} }, nodeTypeMenu.dropDownProps, { children: nodeTypeMenu.icon
|
|
390
|
+
? (_jsx(nodeTypeMenu.icon, { size: 14 }))
|
|
391
|
+
: (nodeTypeMenu.label || nodeTypeMenu.name) }))) }));
|
|
392
|
+
};
|
|
393
|
+
const BubbleMenu = ({ className, editor, customMenuItems = [], }) => {
|
|
279
394
|
const theme = useTheme();
|
|
280
|
-
|
|
281
|
-
if (open && onOpen) {
|
|
282
|
-
onOpen(elements.floating);
|
|
283
|
-
}
|
|
284
|
-
}, [open, onOpen, elements.floating]);
|
|
285
|
-
const elementWidth = ((_a = elements.floating) === null || _a === void 0 ? void 0 : _a.offsetWidth) || 0;
|
|
395
|
+
const [linkEditorOpen, setLinkEditorOpen] = useState(false);
|
|
286
396
|
const { from, to } = editor.state.selection;
|
|
287
397
|
const selectedText = editor.state.doc.textBetween(from, to, "\n", "\n");
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
if (
|
|
294
|
-
|
|
398
|
+
const isLinkSelection = editor.isActive("link");
|
|
399
|
+
const isCodeBlockSelection = editor.isActive("codeBlock") && hasSyntaxHighlightedCodeBlock(editor);
|
|
400
|
+
useEffect(() => {
|
|
401
|
+
setLinkEditorOpen(false);
|
|
402
|
+
}, [from, to]);
|
|
403
|
+
if (isLinkSelection || linkEditorOpen) {
|
|
404
|
+
return (_jsx(BubbleMenuContent, { className: className, children: _jsx(LinkEditor, { editor: editor, autoFocus: true, onClose: () => setLinkEditorOpen(false) }) }));
|
|
295
405
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
if (rightOverflow > -10) {
|
|
299
|
-
left -= rightOverflow + 10; // add some padding
|
|
406
|
+
if (isCodeBlockSelection) {
|
|
407
|
+
return (_jsx(BubbleMenuContent, { className: className, children: _jsx(CodeBlockBubbleTools, { editor: editor, theme: theme }) }));
|
|
300
408
|
}
|
|
301
|
-
return (_jsx(
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
var _a;
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
style: { width: 135 },
|
|
316
|
-
} }, item.dropDownProps, { children: item.icon
|
|
317
|
-
? (_jsx(item.icon, { size: 14 }))
|
|
318
|
-
: (item.label || item.name) }), item.name));
|
|
319
|
-
}
|
|
320
|
-
}) })) }));
|
|
409
|
+
return (_jsx(BubbleMenuContent, { className: className, children: getMenuItems(editor, customMenuItems, theme, () => setLinkEditorOpen(true)).map((item) => {
|
|
410
|
+
var _a;
|
|
411
|
+
if (item.type === "button") {
|
|
412
|
+
const isActive = (_a = item.isActive) === null || _a === void 0 ? void 0 : _a.call(item, editor);
|
|
413
|
+
return (_jsx(BubbleItemButton, { variant: "subtle", onClick: () => { var _a; return (_a = item === null || item === void 0 ? void 0 : item.onClick) === null || _a === void 0 ? void 0 : _a.call(item, editor); }, color: isActive ? "primary" : undefined, selected: isActive, children: item.icon && _jsx(item.icon, { size: 14 }) }, item.name));
|
|
414
|
+
}
|
|
415
|
+
if (item.type === "menu") {
|
|
416
|
+
return (_jsx(DropDownMenu, Object.assign({ data: item.items, size: "xs", arrow: item.arrow, buttonProps: item.buttonProps, variant: "subtle", buttonRender: item.buttonRender, onItemSelect: (item) => { var _a, _b; return (_b = (_a = item === null || item === void 0 ? void 0 : item.data) === null || _a === void 0 ? void 0 : _a.command) === null || _b === void 0 ? void 0 : _b.call(_a, editor, selectedText); }, dropDownProps: {
|
|
417
|
+
style: { width: 135 },
|
|
418
|
+
} }, item.dropDownProps, { children: item.icon
|
|
419
|
+
? (_jsx(item.icon, { size: 14 }))
|
|
420
|
+
: (item.label || item.name) }), item.name));
|
|
421
|
+
}
|
|
422
|
+
}) }));
|
|
321
423
|
};
|
|
322
424
|
export default BubbleMenu;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare const CodeBlockBaseButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
2
|
+
ref?: import("react").RefObject<HTMLButtonElement>;
|
|
3
|
+
children?: import("react").ReactNode | string;
|
|
4
|
+
className?: string;
|
|
5
|
+
loading?: boolean;
|
|
6
|
+
leftSection?: import("react").ReactNode;
|
|
7
|
+
rightSection?: import("react").ReactNode;
|
|
8
|
+
href?: string | null;
|
|
9
|
+
download?: string | null;
|
|
10
|
+
fullWidth?: boolean;
|
|
11
|
+
size?: import("../../core").Size;
|
|
12
|
+
variant?: import("../../core").Variant;
|
|
13
|
+
color?: import("../../Button").ButtonColor;
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
selected?: boolean;
|
|
16
|
+
justify?: "start" | "center" | "end";
|
|
17
|
+
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
|
|
18
|
+
}, never>> & string & Omit<import("react").FC<import("../../Button").ButtonProps>, keyof import("react").Component<any, {}, any>>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Editor } from "@tiptap/react";
|
|
2
|
+
type CodeBlockCopyButtonProps = {
|
|
3
|
+
className?: string;
|
|
4
|
+
editor?: Editor | null;
|
|
5
|
+
text?: string;
|
|
6
|
+
size?: "xs" | "sm";
|
|
7
|
+
};
|
|
8
|
+
declare const CodeBlockCopyButton: ({ className, editor, text, size, }: CodeBlockCopyButtonProps) => import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export default CodeBlockCopyButton;
|
|
@@ -0,0 +1,42 @@
|
|
|
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 { jsx as _jsx } from "react/jsx-runtime";
|
|
11
|
+
import { useEffect, useState } from "react";
|
|
12
|
+
import { CheckIcon, CopyIcon } from "lucide-react";
|
|
13
|
+
import { copyCodeBlockText, getActiveCodeBlockText, } from "../Utils/codeBlockUtils";
|
|
14
|
+
import { CodeBlockBaseButton } from "./CodeBlockBaseButton";
|
|
15
|
+
const CodeBlockCopyButton = ({ className, editor, text, size = "xs", }) => {
|
|
16
|
+
const [copied, setCopied] = useState(false);
|
|
17
|
+
const [copyFailed, setCopyFailed] = useState(false);
|
|
18
|
+
const code = text !== null && text !== void 0 ? text : getActiveCodeBlockText(editor || null);
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (!copied && !copyFailed)
|
|
21
|
+
return;
|
|
22
|
+
const timeout = window.setTimeout(() => {
|
|
23
|
+
setCopied(false);
|
|
24
|
+
setCopyFailed(false);
|
|
25
|
+
}, 1400);
|
|
26
|
+
return () => window.clearTimeout(timeout);
|
|
27
|
+
}, [copied, copyFailed]);
|
|
28
|
+
return (_jsx(CodeBlockBaseButton, { className: className, size: size, variant: "outlined", title: copyFailed ? "Unable to copy" : copied ? "Copied" : "Copy code", "aria-label": copyFailed ? "Unable to copy code" : copied ? "Copied" : "Copy code", disabled: !code, onClick: (event) => __awaiter(void 0, void 0, void 0, function* () {
|
|
29
|
+
event.preventDefault();
|
|
30
|
+
event.stopPropagation();
|
|
31
|
+
try {
|
|
32
|
+
yield copyCodeBlockText(code);
|
|
33
|
+
setCopied(true);
|
|
34
|
+
setCopyFailed(false);
|
|
35
|
+
}
|
|
36
|
+
catch (_a) {
|
|
37
|
+
setCopied(false);
|
|
38
|
+
setCopyFailed(true);
|
|
39
|
+
}
|
|
40
|
+
}), children: copied ? _jsx(CheckIcon, { size: 14 }) : _jsx(CopyIcon, { size: 14 }) }));
|
|
41
|
+
};
|
|
42
|
+
export default CodeBlockCopyButton;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Editor } from "@tiptap/react";
|
|
2
|
+
type CodeBlockFormatButtonProps = {
|
|
3
|
+
className?: string;
|
|
4
|
+
editor?: Editor | null;
|
|
5
|
+
language?: string;
|
|
6
|
+
onFormat?: () => Promise<void>;
|
|
7
|
+
size?: "xs" | "sm";
|
|
8
|
+
};
|
|
9
|
+
declare const CodeBlockFormatButton: ({ className, editor, language, onFormat, size, }: CodeBlockFormatButtonProps) => import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export default CodeBlockFormatButton;
|