@monolith-forensics/monolith-ui 1.9.1-dev.9 → 1.9.3-dev.1
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/Charts/BarChart/BarChart.js +28 -14
- package/dist/Charts/BarChart/BarChart.styled.d.ts +7 -2
- package/dist/Charts/BarChart/BarChart.styled.js +5 -1
- package/dist/Charts/BarChart/BarChart.types.d.ts +13 -5
- package/dist/Charts/ChartUtils/chartSizing.d.ts +20 -0
- package/dist/Charts/ChartUtils/chartSizing.js +83 -0
- package/dist/Charts/ChartUtils/index.d.ts +1 -0
- package/dist/Charts/ChartUtils/index.js +1 -0
- package/dist/Charts/HeatMap/HeatMap.js +28 -7
- package/dist/Charts/HeatMap/HeatMap.styled.d.ts +6 -2
- package/dist/Charts/HeatMap/HeatMap.styled.js +3 -0
- package/dist/Charts/HeatMap/HeatMap.types.d.ts +7 -1
- package/dist/Charts/LineChart/LineChart.js +34 -15
- package/dist/Charts/LineChart/LineChart.styled.d.ts +7 -2
- package/dist/Charts/LineChart/LineChart.styled.js +5 -1
- package/dist/Charts/LineChart/LineChart.types.d.ts +13 -5
- package/dist/Charts/PieChart/PieChart.js +48 -33
- package/dist/Charts/PieChart/PieChart.styled.d.ts +7 -2
- package/dist/Charts/PieChart/PieChart.styled.js +6 -1
- package/dist/Charts/PieChart/PieChart.types.d.ts +7 -3
- package/dist/DropDownMenu/components/MenuItemList.js +32 -12
- package/dist/DropDownMenu/components/StyledContent.js +1 -1
- package/dist/DropDownMenu/components/StyledInnerItemContainer.js +1 -0
- package/dist/FieldLabel/FieldLabel.js +3 -18
- package/dist/FileViewer/FileViewer.js +32 -8
- package/dist/FileViewer/viewers/ImageViewer.d.ts +1 -0
- package/dist/FileViewer/viewers/ImageViewer.js +36 -15
- package/dist/MonolithUIProvider/MonolithUIProvider.d.ts +23 -0
- package/dist/RichTextEditor/Components/BubbleMenu.d.ts +3 -3
- package/dist/RichTextEditor/Components/BubbleMenu.js +190 -51
- 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/Components/TableTools/TableCornerMenu.d.ts +2 -0
- package/dist/RichTextEditor/Components/TableTools/TableCornerMenu.js +19 -0
- package/dist/RichTextEditor/Components/TableTools/TableInsertControls.d.ts +2 -0
- package/dist/RichTextEditor/Components/TableTools/TableInsertControls.js +24 -0
- package/dist/RichTextEditor/Components/TableTools/TableRails.d.ts +2 -0
- package/dist/RichTextEditor/Components/TableTools/TableRails.js +180 -0
- package/dist/RichTextEditor/Components/TableTools/TableToolMenu.d.ts +5 -0
- package/dist/RichTextEditor/Components/TableTools/TableToolMenu.js +6 -0
- package/dist/RichTextEditor/Components/TableTools/TableTools.actions.d.ts +5 -0
- package/dist/RichTextEditor/Components/TableTools/TableTools.actions.js +183 -0
- package/dist/RichTextEditor/Components/TableTools/TableTools.commands.d.ts +16 -0
- package/dist/RichTextEditor/Components/TableTools/TableTools.commands.js +217 -0
- package/dist/RichTextEditor/Components/TableTools/TableTools.constants.d.ts +8 -0
- package/dist/RichTextEditor/Components/TableTools/TableTools.constants.js +11 -0
- package/dist/RichTextEditor/Components/TableTools/TableTools.d.ts +3 -0
- package/dist/RichTextEditor/Components/TableTools/TableTools.geometry.d.ts +23 -0
- package/dist/RichTextEditor/Components/TableTools/TableTools.geometry.js +75 -0
- package/dist/RichTextEditor/Components/TableTools/TableTools.js +3 -0
- package/dist/RichTextEditor/Components/TableTools/TableTools.selectors.d.ts +16 -0
- package/dist/RichTextEditor/Components/TableTools/TableTools.selectors.js +53 -0
- package/dist/RichTextEditor/Components/TableTools/TableTools.styled.d.ts +40 -0
- package/dist/RichTextEditor/Components/TableTools/TableTools.styled.js +167 -0
- package/dist/RichTextEditor/Components/TableTools/TableTools.types.d.ts +76 -0
- package/dist/RichTextEditor/Components/TableTools/TableTools.types.js +1 -0
- package/dist/RichTextEditor/Components/TableTools/TableTools.utils.d.ts +4 -0
- package/dist/RichTextEditor/Components/TableTools/TableTools.utils.js +4 -0
- package/dist/RichTextEditor/Components/TableTools/TableToolsPopover.d.ts +2 -0
- package/dist/RichTextEditor/Components/TableTools/TableToolsPopover.js +12 -0
- package/dist/RichTextEditor/Components/TableTools/index.d.ts +3 -0
- package/dist/RichTextEditor/Components/TableTools/index.js +2 -0
- package/dist/RichTextEditor/Enums/Controls.d.ts +7 -1
- package/dist/RichTextEditor/Enums/Controls.js +6 -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 +4 -1
- package/dist/RichTextEditor/Enums/SlashCommands.js +3 -0
- package/dist/RichTextEditor/Extensions/SlashCommandList.js +0 -1
- package/dist/RichTextEditor/Extensions/getSlashCommand.d.ts +23 -3
- package/dist/RichTextEditor/Extensions/getSlashCommand.js +53 -7
- package/dist/RichTextEditor/Extensions/getTiptapExtensions.d.ts +15 -2
- package/dist/RichTextEditor/Extensions/getTiptapExtensions.js +159 -24
- package/dist/RichTextEditor/Plugins/ImageActionsPlugin.js +4 -7
- package/dist/RichTextEditor/RichTextEditor.d.ts +9 -4
- package/dist/RichTextEditor/RichTextEditor.js +352 -14
- package/dist/RichTextEditor/Toolbar/Control.d.ts +6 -2
- package/dist/RichTextEditor/Toolbar/Control.js +13 -6
- package/dist/RichTextEditor/Toolbar/Controls.d.ts +6 -0
- package/dist/RichTextEditor/Toolbar/Controls.js +118 -1
- package/dist/RichTextEditor/Toolbar/ControlsGroup.js +17 -6
- package/dist/RichTextEditor/Toolbar/Labels.d.ts +1 -0
- package/dist/RichTextEditor/Toolbar/Labels.js +1 -0
- package/dist/RichTextEditor/Toolbar/Toolbar.d.ts +1 -2
- package/dist/RichTextEditor/Toolbar/Toolbar.js +32 -67
- 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/RichTextEditor/Utils/tableUtils.d.ts +1 -0
- package/dist/RichTextEditor/Utils/tableUtils.js +1 -0
- package/dist/SegmentedControl/SegmentedControl.js +1 -1
- package/dist/SegmentedControl/SegmentedControl.styles.d.ts +1 -0
- package/dist/SegmentedControl/SegmentedControl.styles.js +30 -14
- package/dist/SegmentedControl/SegmentedControl.utils.d.ts +1 -0
- package/dist/SegmentedControl/SegmentedControl.utils.js +5 -2
- package/dist/Table/Table.js +4 -3
- package/dist/Table/TableComponents.d.ts +3 -0
- package/dist/Table/TableComponents.js +47 -0
- package/dist/Table/TableHeader.js +1 -1
- package/dist/Table/TableMenu/TableMenu.js +4 -3
- package/dist/Table/TableProvider.js +39 -0
- package/dist/Table/TableRow.js +1 -1
- package/dist/Table/types.d.ts +6 -0
- package/dist/Utilities/getImageTextContent.d.ts +78 -0
- package/dist/Utilities/getImageTextContent.js +222 -0
- package/dist/core/controlSizes.js +9 -9
- package/dist/theme/variants.js +46 -0
- package/package.json +8 -1
|
@@ -2,9 +2,9 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import styled from "styled-components";
|
|
3
3
|
import { CodeViewer, ImageViewer, OfficeViewer, PdfViewer, VideoViewer, } from "./viewers";
|
|
4
4
|
import { FloatingPortal } from "@floating-ui/react";
|
|
5
|
-
import { DownloadIcon, XIcon, ZoomInIcon, ZoomOutIcon } from "lucide-react";
|
|
5
|
+
import { DownloadIcon, RotateCwIcon, XIcon, ZoomInIcon, ZoomOutIcon, } from "lucide-react";
|
|
6
6
|
import { Button } from "../Button";
|
|
7
|
-
import { useState } from "react";
|
|
7
|
+
import { useEffect, useState } from "react";
|
|
8
8
|
import Loader from "../Loader";
|
|
9
9
|
var ViewerTypes;
|
|
10
10
|
(function (ViewerTypes) {
|
|
@@ -24,7 +24,18 @@ const ZoomableViewerTypes = [
|
|
|
24
24
|
];
|
|
25
25
|
const RotatableViewerTypes = [ViewerTypes.Image];
|
|
26
26
|
const OfficeExtensions = ["doc", "docx", "xls", "xlsx", "ppt", "pptx"];
|
|
27
|
-
const ImageExtensions = [
|
|
27
|
+
const ImageExtensions = [
|
|
28
|
+
"jpg",
|
|
29
|
+
"jpeg",
|
|
30
|
+
"png",
|
|
31
|
+
"gif",
|
|
32
|
+
"webp",
|
|
33
|
+
"bmp",
|
|
34
|
+
"svg",
|
|
35
|
+
"avif",
|
|
36
|
+
"tif",
|
|
37
|
+
"tiff",
|
|
38
|
+
];
|
|
28
39
|
const VideoExtensions = ["mp4", "webm", "mov"];
|
|
29
40
|
const AudioExtensions = ["mp3", "wav"];
|
|
30
41
|
const PDFExtensions = ["pdf"];
|
|
@@ -125,10 +136,14 @@ const StyledInnerContainer = styled.div.attrs({
|
|
|
125
136
|
}
|
|
126
137
|
`;
|
|
127
138
|
const resolveViewerType = (file) => {
|
|
128
|
-
var _a, _b;
|
|
139
|
+
var _a, _b, _c;
|
|
129
140
|
let ext = (_a = file === null || file === void 0 ? void 0 : file.ext) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
141
|
+
const type = (_b = file === null || file === void 0 ? void 0 : file.type) === null || _b === void 0 ? void 0 : _b.toLowerCase();
|
|
130
142
|
if (!ext) {
|
|
131
|
-
ext = (
|
|
143
|
+
ext = (_c = file.name.split(".").pop()) === null || _c === void 0 ? void 0 : _c.toLowerCase();
|
|
144
|
+
}
|
|
145
|
+
if (type === null || type === void 0 ? void 0 : type.startsWith("image/")) {
|
|
146
|
+
return ViewerTypes.Image;
|
|
132
147
|
}
|
|
133
148
|
if (!ext) {
|
|
134
149
|
return ViewerTypes.Code;
|
|
@@ -158,19 +173,28 @@ const resolveViewerType = (file) => {
|
|
|
158
173
|
};
|
|
159
174
|
export const FileViewer = ({ file, open, isPending, onClose }) => {
|
|
160
175
|
const [zoomFactor, setZoomFactor] = useState(1);
|
|
176
|
+
const [rotation, setRotation] = useState(0);
|
|
177
|
+
useEffect(() => {
|
|
178
|
+
setZoomFactor(1);
|
|
179
|
+
setRotation(0);
|
|
180
|
+
}, [file === null || file === void 0 ? void 0 : file.url, file === null || file === void 0 ? void 0 : file.name, open]);
|
|
161
181
|
if (!open)
|
|
162
182
|
return null;
|
|
163
183
|
if (!file)
|
|
164
184
|
return null;
|
|
165
185
|
const viewerType = resolveViewerType(file);
|
|
186
|
+
const resetViewerState = () => {
|
|
187
|
+
setZoomFactor(1);
|
|
188
|
+
setRotation(0);
|
|
189
|
+
};
|
|
166
190
|
const handleBackgroundClick = (e) => {
|
|
167
191
|
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
168
|
-
|
|
192
|
+
resetViewerState();
|
|
169
193
|
};
|
|
170
194
|
return (_jsx(FloatingPortal, { preserveTabOrder: true, children: _jsxs(StyledContainer, { className: "mfui-FileViewer", children: [_jsxs(StyledMenu, { className: "FileViewer-menu", children: [_jsx(Button, { variant: "text", onClick: () => {
|
|
171
195
|
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
172
|
-
|
|
173
|
-
}, children: _jsx(XIcon, { size: 18 }) }), _jsx("div", { children: file.name }), _jsxs(StyledActionsMenu, { children: [ZoomableViewerTypes.includes(viewerType) && (_jsxs(_Fragment, { children: [_jsx(Button, { variant: "text", disabled: !file.url,
|
|
196
|
+
resetViewerState();
|
|
197
|
+
}, children: _jsx(XIcon, { size: 18 }) }), _jsx("div", { children: file.name }), _jsxs(StyledActionsMenu, { children: [ZoomableViewerTypes.includes(viewerType) && (_jsxs(_Fragment, { children: [_jsx(Button, { variant: "text", disabled: !file.url, "aria-label": "Zoom in", title: "Zoom in", onClick: () => setZoomFactor((prev) => prev * 1.1), children: _jsx(ZoomInIcon, { size: 18 }) }), _jsx(Button, { variant: "text", disabled: !file.url, "aria-label": "Zoom out", title: "Zoom out", onClick: () => setZoomFactor((prev) => prev * 0.9), children: _jsx(ZoomOutIcon, { size: 18 }) })] })), RotatableViewerTypes.includes(viewerType) && (_jsx(Button, { variant: "text", disabled: !file.url, "aria-label": "Rotate image", title: "Rotate image", onClick: () => setRotation((prev) => (prev + 90) % 360), children: _jsx(RotateCwIcon, { size: 18 }) })), _jsx("a", { href: file.url, download: file.name, style: { pointerEvents: !file.url ? "none" : "auto" }, children: _jsx(Button, { variant: "text", disabled: !file.url, children: _jsx(DownloadIcon, { size: 18 }) }) })] })] }), file.url ? (_jsxs(StyledInnerContainer, { onClick: handleBackgroundClick, "data-type": viewerType, children: [viewerType === ViewerTypes.PDF && (_jsx(PdfViewer, { file: file, zoomFactor: zoomFactor, isPending: isPending })), viewerType === ViewerTypes.Image && (_jsx(ImageViewer, { file: file, zoomFactor: zoomFactor, rotation: rotation, isPending: isPending })), viewerType === ViewerTypes.Video && (_jsx(VideoViewer, { file: file, zoomFactor: zoomFactor, isPending: isPending })), viewerType === ViewerTypes.Audio && (_jsx(VideoViewer, { file: file, zoomFactor: zoomFactor, isPending: isPending })), viewerType === ViewerTypes.Office && (_jsx(OfficeViewer, { file: file, isPending: isPending })), viewerType === ViewerTypes.Text && (_jsx(CodeViewer, { file: file, zoomFactor: zoomFactor, isPending: isPending })), viewerType === ViewerTypes.Code && (_jsx(CodeViewer, { file: file, zoomFactor: zoomFactor, isPending: isPending }))] })) : (_jsx(StyledInnerContainer, { children: _jsxs("div", { style: {
|
|
174
198
|
margin: "auto",
|
|
175
199
|
display: "flex",
|
|
176
200
|
gap: "10px",
|
|
@@ -10,9 +10,7 @@ const ImageViewerContainer = styled.div `
|
|
|
10
10
|
overflow: auto;
|
|
11
11
|
`;
|
|
12
12
|
const ImageCanvas = styled.div `
|
|
13
|
-
|
|
14
|
-
align-items: center;
|
|
15
|
-
justify-content: center;
|
|
13
|
+
position: relative;
|
|
16
14
|
flex: 0 0 auto;
|
|
17
15
|
min-width: 100%;
|
|
18
16
|
min-height: 100%;
|
|
@@ -20,8 +18,11 @@ const ImageCanvas = styled.div `
|
|
|
20
18
|
const Image = styled.img `
|
|
21
19
|
box-sizing: border-box;
|
|
22
20
|
display: block;
|
|
23
|
-
|
|
21
|
+
position: absolute;
|
|
22
|
+
top: 50%;
|
|
23
|
+
left: 50%;
|
|
24
24
|
object-fit: contain;
|
|
25
|
+
transform-origin: center;
|
|
25
26
|
|
|
26
27
|
// set orientation
|
|
27
28
|
image-orientation: from-image;
|
|
@@ -36,7 +37,7 @@ const StyledLoader = styled.div `
|
|
|
36
37
|
gap: 10px;
|
|
37
38
|
height: 100%;
|
|
38
39
|
`;
|
|
39
|
-
export const ImageViewer = ({ file, zoomFactor = 1, isPending }) => {
|
|
40
|
+
export const ImageViewer = ({ file, zoomFactor = 1, rotation = 0, isPending }) => {
|
|
40
41
|
const containerRef = useRef(null);
|
|
41
42
|
const [imageLoaded, setImageLoaded] = useState(false);
|
|
42
43
|
const [containerSize, setContainerSize] = useState({
|
|
@@ -47,6 +48,8 @@ export const ImageViewer = ({ file, zoomFactor = 1, isPending }) => {
|
|
|
47
48
|
naturalWidth: 0,
|
|
48
49
|
naturalHeight: 0,
|
|
49
50
|
});
|
|
51
|
+
const normalizedRotation = ((rotation % 360) + 360) % 360;
|
|
52
|
+
const isRotatedSideways = normalizedRotation % 180 !== 0;
|
|
50
53
|
const fittedDimensions = useMemo(() => {
|
|
51
54
|
const { naturalWidth, naturalHeight } = originalDimensions;
|
|
52
55
|
if (naturalWidth === 0 ||
|
|
@@ -54,16 +57,33 @@ export const ImageViewer = ({ file, zoomFactor = 1, isPending }) => {
|
|
|
54
57
|
containerSize.width === 0 ||
|
|
55
58
|
containerSize.height === 0) {
|
|
56
59
|
return {
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
canvasWidth: isRotatedSideways ? naturalHeight : naturalWidth,
|
|
61
|
+
canvasHeight: isRotatedSideways ? naturalWidth : naturalHeight,
|
|
62
|
+
imageWidth: naturalWidth,
|
|
63
|
+
imageHeight: naturalHeight,
|
|
59
64
|
};
|
|
60
65
|
}
|
|
61
|
-
const
|
|
66
|
+
const rotatedNaturalWidth = isRotatedSideways
|
|
67
|
+
? naturalHeight
|
|
68
|
+
: naturalWidth;
|
|
69
|
+
const rotatedNaturalHeight = isRotatedSideways
|
|
70
|
+
? naturalWidth
|
|
71
|
+
: naturalHeight;
|
|
72
|
+
const fitScale = Math.min(containerSize.width / rotatedNaturalWidth, containerSize.height / rotatedNaturalHeight);
|
|
73
|
+
const imageWidth = naturalWidth * fitScale * zoomFactor;
|
|
74
|
+
const imageHeight = naturalHeight * fitScale * zoomFactor;
|
|
62
75
|
return {
|
|
63
|
-
|
|
64
|
-
|
|
76
|
+
canvasWidth: isRotatedSideways ? imageHeight : imageWidth,
|
|
77
|
+
canvasHeight: isRotatedSideways ? imageWidth : imageHeight,
|
|
78
|
+
imageWidth,
|
|
79
|
+
imageHeight,
|
|
65
80
|
};
|
|
66
|
-
}, [
|
|
81
|
+
}, [
|
|
82
|
+
containerSize,
|
|
83
|
+
isRotatedSideways,
|
|
84
|
+
originalDimensions,
|
|
85
|
+
zoomFactor,
|
|
86
|
+
]);
|
|
67
87
|
useEffect(() => {
|
|
68
88
|
if (!file.url)
|
|
69
89
|
return;
|
|
@@ -104,11 +124,12 @@ export const ImageViewer = ({ file, zoomFactor = 1, isPending }) => {
|
|
|
104
124
|
return (_jsxs(StyledLoader, { children: [_jsx(Loader, { size: 50 }), _jsx("div", { children: "Loading Image..." })] }));
|
|
105
125
|
}
|
|
106
126
|
return (_jsxs(ImageViewerContainer, { ref: containerRef, className: "mfui-ImageViewer", children: [!showImage && (_jsxs(StyledLoader, { children: [_jsx(Loader, { size: 50 }), _jsx("div", { children: "Loading Image..." })] })), showImage && (_jsx(ImageCanvas, { style: {
|
|
107
|
-
width: fittedDimensions.
|
|
108
|
-
height: fittedDimensions.
|
|
127
|
+
width: fittedDimensions.canvasWidth,
|
|
128
|
+
height: fittedDimensions.canvasHeight,
|
|
109
129
|
}, children: _jsx(Image, { src: file.url, alt: file.name ? file.name : "Image", style: {
|
|
110
|
-
width: fittedDimensions.
|
|
111
|
-
height: fittedDimensions.
|
|
130
|
+
width: fittedDimensions.imageWidth,
|
|
131
|
+
height: fittedDimensions.imageHeight,
|
|
132
|
+
transform: `translate(-50%, -50%) rotate(${normalizedRotation}deg)`,
|
|
112
133
|
}, onClick: (e) => {
|
|
113
134
|
e.stopPropagation();
|
|
114
135
|
} }) }))] }));
|
|
@@ -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,6 +1,6 @@
|
|
|
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
6
|
export interface BubbleMenuContentProps {
|
|
@@ -17,7 +17,7 @@ export type BubbleItem = {
|
|
|
17
17
|
name: Extensions | string;
|
|
18
18
|
icon?: React.FC<any>;
|
|
19
19
|
type: "menu";
|
|
20
|
-
label?:
|
|
20
|
+
label?: ReactNode;
|
|
21
21
|
items: BubbleMenuDropDownItem[];
|
|
22
22
|
arrow?: boolean;
|
|
23
23
|
isActive?: (editor: Editor) => boolean;
|
|
@@ -29,7 +29,7 @@ export type BubbleItem = {
|
|
|
29
29
|
name: Extensions | string;
|
|
30
30
|
icon?: React.FC<any>;
|
|
31
31
|
type: "button";
|
|
32
|
-
label?:
|
|
32
|
+
label?: ReactNode;
|
|
33
33
|
arrow?: boolean;
|
|
34
34
|
isActive?: (editor: Editor) => boolean;
|
|
35
35
|
buttonRender?: (props: any) => ReactElement;
|
|
@@ -1,12 +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 { useEffect, useState } from "react";
|
|
6
7
|
import { Button } from "../../Button";
|
|
7
8
|
import TextColors from "../Enums/TextColors";
|
|
8
|
-
|
|
9
|
-
|
|
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;
|
|
10
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;
|
|
11
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;
|
|
12
17
|
let withinUnorderedList = false;
|
|
@@ -22,6 +27,11 @@ const getMenuItems = (editor, customMenuItems, theme) => {
|
|
|
22
27
|
}
|
|
23
28
|
});
|
|
24
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"));
|
|
25
35
|
let nodeTypeLabel = "Select Type";
|
|
26
36
|
let nodeTypeIcon = null;
|
|
27
37
|
if (withinOrderedList) {
|
|
@@ -36,7 +46,11 @@ const getMenuItems = (editor, customMenuItems, theme) => {
|
|
|
36
46
|
nodeTypeLabel = "Text";
|
|
37
47
|
nodeTypeIcon = _jsx(CaseSensitiveIcon, { size: 16 });
|
|
38
48
|
}
|
|
39
|
-
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") {
|
|
40
54
|
const level = attrs === null || attrs === void 0 ? void 0 : attrs.level;
|
|
41
55
|
nodeTypeLabel = `Heading ${level}`;
|
|
42
56
|
nodeTypeIcon =
|
|
@@ -48,7 +62,6 @@ const getMenuItems = (editor, customMenuItems, theme) => {
|
|
|
48
62
|
name: "node_type",
|
|
49
63
|
label: nodeTypeLabel,
|
|
50
64
|
type: "menu",
|
|
51
|
-
arrow: true,
|
|
52
65
|
buttonProps: {
|
|
53
66
|
leftSection: nodeTypeIcon,
|
|
54
67
|
style: { fontSize: 11, padding: "4px" },
|
|
@@ -60,13 +73,17 @@ const getMenuItems = (editor, customMenuItems, theme) => {
|
|
|
60
73
|
data: {
|
|
61
74
|
Icon: CaseSensitiveIcon,
|
|
62
75
|
command: (editor) => {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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();
|
|
70
87
|
},
|
|
71
88
|
},
|
|
72
89
|
},
|
|
@@ -130,50 +147,107 @@ const getMenuItems = (editor, customMenuItems, theme) => {
|
|
|
130
147
|
},
|
|
131
148
|
},
|
|
132
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
|
+
: []),
|
|
133
164
|
],
|
|
134
165
|
dropDownProps: {
|
|
135
166
|
renderOption: (item) => (_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 5 }, children: [_jsx(item.data.Icon, { size: 16 }), item.label] })),
|
|
136
167
|
},
|
|
137
168
|
},
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
label: "Color",
|
|
141
|
-
type: "menu",
|
|
142
|
-
arrow: true,
|
|
143
|
-
buttonProps: {
|
|
144
|
-
// leftSection: nodeTypeIcon,
|
|
145
|
-
style: { fontSize: 11, padding: "4px" },
|
|
146
|
-
},
|
|
147
|
-
items: [
|
|
169
|
+
...(supportsColor
|
|
170
|
+
? [
|
|
148
171
|
{
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
172
|
+
name: "color",
|
|
173
|
+
label: _jsx(PaletteIcon, { size: 14 }),
|
|
174
|
+
type: "menu",
|
|
175
|
+
buttonProps: {
|
|
176
|
+
style: { padding: "1px 6px" },
|
|
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] })),
|
|
153
206
|
},
|
|
154
207
|
},
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
208
|
+
]
|
|
209
|
+
: []),
|
|
210
|
+
...(supportsHighlight
|
|
211
|
+
? [
|
|
212
|
+
{
|
|
213
|
+
name: Extensions.Highlight,
|
|
214
|
+
label: _jsx(HighlighterIcon, { size: 14 }),
|
|
215
|
+
type: "menu",
|
|
216
|
+
buttonProps: {
|
|
217
|
+
style: { padding: "1px 6px" },
|
|
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
|
+
},
|
|
162
226
|
},
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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
|
+
: []),
|
|
177
251
|
{
|
|
178
252
|
name: Extensions.Bold,
|
|
179
253
|
icon: BoldIcon,
|
|
@@ -210,6 +284,45 @@ const getMenuItems = (editor, customMenuItems, theme) => {
|
|
|
210
284
|
editor.chain().focus().toggleStrike().run();
|
|
211
285
|
},
|
|
212
286
|
},
|
|
287
|
+
...(supportsLink
|
|
288
|
+
? [
|
|
289
|
+
{
|
|
290
|
+
name: Extensions.Link,
|
|
291
|
+
icon: LinkIcon,
|
|
292
|
+
type: "button",
|
|
293
|
+
isActive: (editor) => editor.isActive("link"),
|
|
294
|
+
onClick: () => {
|
|
295
|
+
openLinkEditor();
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
]
|
|
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
|
+
: []),
|
|
213
326
|
{
|
|
214
327
|
name: Extensions.ClearFormatting,
|
|
215
328
|
icon: RemoveFormattingIcon,
|
|
@@ -226,7 +339,7 @@ const BubbleMenuContent = styled.div `
|
|
|
226
339
|
justify-content: space-between;
|
|
227
340
|
align-items: center;
|
|
228
341
|
padding: 2px;
|
|
229
|
-
gap:
|
|
342
|
+
gap: 4px;
|
|
230
343
|
|
|
231
344
|
color: ${({ theme }) => theme.palette.text.primary};
|
|
232
345
|
background-color: ${({ theme }) => theme.palette.input.background};
|
|
@@ -242,6 +355,11 @@ const BubbleMenuContent = styled.div `
|
|
|
242
355
|
transform: scale(0.25); /* Start at half size */
|
|
243
356
|
animation: fadeInEffect 90ms forwards;
|
|
244
357
|
|
|
358
|
+
button {
|
|
359
|
+
min-width: 28px;
|
|
360
|
+
min-height: 28px;
|
|
361
|
+
}
|
|
362
|
+
|
|
245
363
|
/* Animation to handle the fade in */
|
|
246
364
|
@keyframes fadeInEffect {
|
|
247
365
|
0% {
|
|
@@ -258,7 +376,8 @@ const BubbleItemButton = styled(Button) `
|
|
|
258
376
|
font-size: 0.5rem;
|
|
259
377
|
font-weight: 500;
|
|
260
378
|
padding: 4px;
|
|
261
|
-
height:
|
|
379
|
+
height: 28px;
|
|
380
|
+
width: 28px;
|
|
262
381
|
|
|
263
382
|
&.is-active {
|
|
264
383
|
opacity: 1;
|
|
@@ -269,11 +388,31 @@ const BubbleItemButton = styled(Button) `
|
|
|
269
388
|
background-color: ${({ theme }) => theme.palette.action.hover};
|
|
270
389
|
}
|
|
271
390
|
`;
|
|
391
|
+
const CodeBlockBubbleTools = ({ editor, theme, }) => {
|
|
392
|
+
const nodeTypeMenu = getMenuItems(editor, [], theme, () => undefined).find((item) => item.name === "node_type");
|
|
393
|
+
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: {
|
|
394
|
+
style: { width: 135 },
|
|
395
|
+
} }, nodeTypeMenu.dropDownProps, { children: nodeTypeMenu.icon
|
|
396
|
+
? (_jsx(nodeTypeMenu.icon, { size: 14 }))
|
|
397
|
+
: (nodeTypeMenu.label || nodeTypeMenu.name) }))) }));
|
|
398
|
+
};
|
|
272
399
|
const BubbleMenu = ({ className, editor, customMenuItems = [], }) => {
|
|
273
400
|
const theme = useTheme();
|
|
401
|
+
const [linkEditorOpen, setLinkEditorOpen] = useState(false);
|
|
274
402
|
const { from, to } = editor.state.selection;
|
|
275
403
|
const selectedText = editor.state.doc.textBetween(from, to, "\n", "\n");
|
|
276
|
-
|
|
404
|
+
const isLinkSelection = editor.isActive("link");
|
|
405
|
+
const isCodeBlockSelection = editor.isActive("codeBlock") && hasSyntaxHighlightedCodeBlock(editor);
|
|
406
|
+
useEffect(() => {
|
|
407
|
+
setLinkEditorOpen(false);
|
|
408
|
+
}, [from, to]);
|
|
409
|
+
if (isLinkSelection || linkEditorOpen) {
|
|
410
|
+
return (_jsx(BubbleMenuContent, { className: className, children: _jsx(LinkEditor, { editor: editor, autoFocus: true, onClose: () => setLinkEditorOpen(false) }) }));
|
|
411
|
+
}
|
|
412
|
+
if (isCodeBlockSelection) {
|
|
413
|
+
return (_jsx(BubbleMenuContent, { className: className, children: _jsx(CodeBlockBubbleTools, { editor: editor, theme: theme }) }));
|
|
414
|
+
}
|
|
415
|
+
return (_jsx(BubbleMenuContent, { className: className, children: getMenuItems(editor, customMenuItems, theme, () => setLinkEditorOpen(true)).map((item) => {
|
|
277
416
|
var _a;
|
|
278
417
|
if (item.type === "button") {
|
|
279
418
|
const isActive = (_a = item.isActive) === null || _a === void 0 ? void 0 : _a.call(item, editor);
|
|
@@ -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;
|