@monolith-forensics/monolith-ui 1.9.3-dev.0 → 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/FieldLabel/FieldLabel.js +3 -18
- package/dist/RichTextEditor/Extensions/getSlashCommand.d.ts +23 -3
- package/dist/RichTextEditor/Extensions/getSlashCommand.js +14 -6
- package/dist/RichTextEditor/Extensions/getTiptapExtensions.d.ts +5 -2
- package/dist/RichTextEditor/Extensions/getTiptapExtensions.js +3 -1
- package/dist/RichTextEditor/RichTextEditor.d.ts +6 -3
- package/dist/RichTextEditor/RichTextEditor.js +6 -6
- 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/package.json +1 -1
- package/dist/RichTextEditor/Components/TableCornerMenu.d.ts +0 -16
- package/dist/RichTextEditor/Components/TableCornerMenu.js +0 -202
- package/dist/RichTextEditor/Components/TableTools.d.ts +0 -44
- package/dist/RichTextEditor/Components/TableTools.js +0 -790
|
@@ -0,0 +1,222 @@
|
|
|
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
|
+
export const ImageOcrPageSegModes = {
|
|
11
|
+
OSD_ONLY: "0",
|
|
12
|
+
AUTO_OSD: "1",
|
|
13
|
+
AUTO_ONLY: "2",
|
|
14
|
+
AUTO: "3",
|
|
15
|
+
SINGLE_COLUMN: "4",
|
|
16
|
+
SINGLE_BLOCK_VERT_TEXT: "5",
|
|
17
|
+
SINGLE_BLOCK: "6",
|
|
18
|
+
SINGLE_LINE: "7",
|
|
19
|
+
SINGLE_WORD: "8",
|
|
20
|
+
CIRCLE_WORD: "9",
|
|
21
|
+
SINGLE_CHAR: "10",
|
|
22
|
+
SPARSE_TEXT: "11",
|
|
23
|
+
SPARSE_TEXT_OSD: "12",
|
|
24
|
+
RAW_LINE: "13",
|
|
25
|
+
};
|
|
26
|
+
const defaultDocumentOptions = {
|
|
27
|
+
preprocess: {
|
|
28
|
+
grayscale: true,
|
|
29
|
+
contrast: 1.25,
|
|
30
|
+
scale: 2,
|
|
31
|
+
maxDimension: 2800,
|
|
32
|
+
},
|
|
33
|
+
recognizeOptions: {
|
|
34
|
+
rotateAuto: true,
|
|
35
|
+
},
|
|
36
|
+
parameters: {
|
|
37
|
+
tessedit_pageseg_mode: ImageOcrPageSegModes.AUTO,
|
|
38
|
+
preserve_interword_spaces: "1",
|
|
39
|
+
user_defined_dpi: "300",
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
const defaultDriverLicenseOptions = {
|
|
43
|
+
preprocess: {
|
|
44
|
+
grayscale: true,
|
|
45
|
+
contrast: 1.45,
|
|
46
|
+
scale: 2.5,
|
|
47
|
+
maxDimension: 3200,
|
|
48
|
+
},
|
|
49
|
+
recognizeOptions: {
|
|
50
|
+
rotateAuto: true,
|
|
51
|
+
},
|
|
52
|
+
parameters: {
|
|
53
|
+
tessedit_pageseg_mode: ImageOcrPageSegModes.SPARSE_TEXT,
|
|
54
|
+
preserve_interword_spaces: "1",
|
|
55
|
+
user_defined_dpi: "300",
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
const mergeOptions = (defaults, options) => {
|
|
59
|
+
var _a, _b;
|
|
60
|
+
return Object.assign(Object.assign(Object.assign({}, defaults), options), { language: (_b = (_a = options.language) !== null && _a !== void 0 ? _a : defaults.language) !== null && _b !== void 0 ? _b : "eng", preprocess: Object.assign(Object.assign({}, defaults.preprocess), options.preprocess), recognizeOptions: Object.assign(Object.assign({}, defaults.recognizeOptions), options.recognizeOptions), parameters: Object.assign(Object.assign({}, defaults.parameters), options.parameters), workerOptions: Object.assign(Object.assign({}, defaults.workerOptions), options.workerOptions) });
|
|
61
|
+
};
|
|
62
|
+
const getResolvedOptions = (options) => {
|
|
63
|
+
switch (options.preset) {
|
|
64
|
+
case "document":
|
|
65
|
+
return mergeOptions(defaultDocumentOptions, options);
|
|
66
|
+
case "driver-license":
|
|
67
|
+
return mergeOptions(defaultDriverLicenseOptions, options);
|
|
68
|
+
default:
|
|
69
|
+
return mergeOptions({}, options);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
const getFallbackLines = (text) => {
|
|
73
|
+
return text
|
|
74
|
+
.split(/\r?\n/)
|
|
75
|
+
.map((line) => line.trim())
|
|
76
|
+
.filter(Boolean)
|
|
77
|
+
.map((line) => ({ text: line }));
|
|
78
|
+
};
|
|
79
|
+
const getLinesFromPage = (page) => {
|
|
80
|
+
var _a, _b;
|
|
81
|
+
const lines = (_b = (_a = page.blocks) === null || _a === void 0 ? void 0 : _a.flatMap((block) => block.paragraphs.flatMap((paragraph) => paragraph.lines))) !== null && _b !== void 0 ? _b : [];
|
|
82
|
+
if (!lines.length) {
|
|
83
|
+
return getFallbackLines(page.text);
|
|
84
|
+
}
|
|
85
|
+
return lines
|
|
86
|
+
.filter((line) => line.text.trim().length > 0)
|
|
87
|
+
.map((line) => ({
|
|
88
|
+
text: line.text,
|
|
89
|
+
confidence: line.confidence,
|
|
90
|
+
bbox: line.bbox
|
|
91
|
+
? {
|
|
92
|
+
x0: line.bbox.x0,
|
|
93
|
+
y0: line.bbox.y0,
|
|
94
|
+
x1: line.bbox.x1,
|
|
95
|
+
y1: line.bbox.y1,
|
|
96
|
+
}
|
|
97
|
+
: undefined,
|
|
98
|
+
}));
|
|
99
|
+
};
|
|
100
|
+
const loadImageBitmap = (image) => __awaiter(void 0, void 0, void 0, function* () {
|
|
101
|
+
if (typeof createImageBitmap === "function") {
|
|
102
|
+
return createImageBitmap(image);
|
|
103
|
+
}
|
|
104
|
+
const objectUrl = URL.createObjectURL(image);
|
|
105
|
+
try {
|
|
106
|
+
const img = new Image();
|
|
107
|
+
img.decoding = "async";
|
|
108
|
+
img.src = objectUrl;
|
|
109
|
+
yield img.decode();
|
|
110
|
+
const canvas = document.createElement("canvas");
|
|
111
|
+
canvas.width = img.naturalWidth;
|
|
112
|
+
canvas.height = img.naturalHeight;
|
|
113
|
+
const context = canvas.getContext("2d");
|
|
114
|
+
if (!context) {
|
|
115
|
+
throw new Error("Canvas rendering is not available.");
|
|
116
|
+
}
|
|
117
|
+
context.drawImage(img, 0, 0);
|
|
118
|
+
return createImageBitmap(canvas);
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
URL.revokeObjectURL(objectUrl);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
const hasPreprocessOptions = (preprocess) => {
|
|
125
|
+
return Boolean((preprocess === null || preprocess === void 0 ? void 0 : preprocess.grayscale) ||
|
|
126
|
+
(preprocess === null || preprocess === void 0 ? void 0 : preprocess.contrast) ||
|
|
127
|
+
(preprocess === null || preprocess === void 0 ? void 0 : preprocess.threshold) !== undefined ||
|
|
128
|
+
(preprocess === null || preprocess === void 0 ? void 0 : preprocess.scale));
|
|
129
|
+
};
|
|
130
|
+
const clampByte = (value) => Math.max(0, Math.min(255, value));
|
|
131
|
+
const preprocessImage = (image, preprocess) => __awaiter(void 0, void 0, void 0, function* () {
|
|
132
|
+
var _a, _b, _c;
|
|
133
|
+
if (!hasPreprocessOptions(preprocess)) {
|
|
134
|
+
return image;
|
|
135
|
+
}
|
|
136
|
+
const bitmap = yield loadImageBitmap(image);
|
|
137
|
+
const requestedScale = (_a = preprocess === null || preprocess === void 0 ? void 0 : preprocess.scale) !== null && _a !== void 0 ? _a : 1;
|
|
138
|
+
const maxDimension = (_b = preprocess === null || preprocess === void 0 ? void 0 : preprocess.maxDimension) !== null && _b !== void 0 ? _b : 3000;
|
|
139
|
+
const largestSourceDimension = Math.max(bitmap.width, bitmap.height);
|
|
140
|
+
const scale = Math.min(Math.max(requestedScale, 1), maxDimension / largestSourceDimension);
|
|
141
|
+
const width = Math.max(1, Math.round(bitmap.width * scale));
|
|
142
|
+
const height = Math.max(1, Math.round(bitmap.height * scale));
|
|
143
|
+
const canvas = document.createElement("canvas");
|
|
144
|
+
canvas.width = width;
|
|
145
|
+
canvas.height = height;
|
|
146
|
+
const context = canvas.getContext("2d", { willReadFrequently: true });
|
|
147
|
+
if (!context) {
|
|
148
|
+
throw new Error("Canvas rendering is not available.");
|
|
149
|
+
}
|
|
150
|
+
context.imageSmoothingEnabled = true;
|
|
151
|
+
context.imageSmoothingQuality = "high";
|
|
152
|
+
context.drawImage(bitmap, 0, 0, width, height);
|
|
153
|
+
bitmap.close();
|
|
154
|
+
const imageData = context.getImageData(0, 0, width, height);
|
|
155
|
+
const { data } = imageData;
|
|
156
|
+
const contrast = (_c = preprocess === null || preprocess === void 0 ? void 0 : preprocess.contrast) !== null && _c !== void 0 ? _c : 1;
|
|
157
|
+
const contrastFactor = contrast === 1 ? 1 : (259 * (255 * contrast - 255 + 255)) / (255 * (259 - (255 * contrast - 255)));
|
|
158
|
+
for (let index = 0; index < data.length; index += 4) {
|
|
159
|
+
let red = data[index];
|
|
160
|
+
let green = data[index + 1];
|
|
161
|
+
let blue = data[index + 2];
|
|
162
|
+
if ((preprocess === null || preprocess === void 0 ? void 0 : preprocess.grayscale) || (preprocess === null || preprocess === void 0 ? void 0 : preprocess.threshold) !== undefined) {
|
|
163
|
+
const luminance = 0.299 * red + 0.587 * green + 0.114 * blue;
|
|
164
|
+
red = luminance;
|
|
165
|
+
green = luminance;
|
|
166
|
+
blue = luminance;
|
|
167
|
+
}
|
|
168
|
+
if (contrast !== 1) {
|
|
169
|
+
red = clampByte(contrastFactor * (red - 128) + 128);
|
|
170
|
+
green = clampByte(contrastFactor * (green - 128) + 128);
|
|
171
|
+
blue = clampByte(contrastFactor * (blue - 128) + 128);
|
|
172
|
+
}
|
|
173
|
+
if ((preprocess === null || preprocess === void 0 ? void 0 : preprocess.threshold) !== undefined) {
|
|
174
|
+
const threshold = clampByte(preprocess.threshold);
|
|
175
|
+
const value = red >= threshold ? 255 : 0;
|
|
176
|
+
red = value;
|
|
177
|
+
green = value;
|
|
178
|
+
blue = value;
|
|
179
|
+
}
|
|
180
|
+
data[index] = red;
|
|
181
|
+
data[index + 1] = green;
|
|
182
|
+
data[index + 2] = blue;
|
|
183
|
+
}
|
|
184
|
+
context.putImageData(imageData, 0, 0);
|
|
185
|
+
return new Promise((resolve, reject) => {
|
|
186
|
+
canvas.toBlob((blob) => {
|
|
187
|
+
if (!blob) {
|
|
188
|
+
reject(new Error("Unable to prepare image for OCR."));
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
resolve(blob);
|
|
192
|
+
}, "image/png");
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
export const getImageTextContent = (image_1, ...args_1) => __awaiter(void 0, [image_1, ...args_1], void 0, function* (image, options = {}) {
|
|
196
|
+
if (!image.type.startsWith("image/")) {
|
|
197
|
+
throw new Error("getImageTextContent requires an image File.");
|
|
198
|
+
}
|
|
199
|
+
const { language, onProgress, parameters, preprocess, recognizeOptions, workerOptions, } = getResolvedOptions(options);
|
|
200
|
+
const { createWorker } = yield import("tesseract.js");
|
|
201
|
+
let worker;
|
|
202
|
+
try {
|
|
203
|
+
worker = yield createWorker(language, undefined, Object.assign(Object.assign({}, workerOptions), { logger: ({ progress, status }) => {
|
|
204
|
+
onProgress === null || onProgress === void 0 ? void 0 : onProgress({ progress, status });
|
|
205
|
+
} }));
|
|
206
|
+
if (parameters && Object.keys(parameters).length > 0) {
|
|
207
|
+
yield worker.setParameters(parameters);
|
|
208
|
+
}
|
|
209
|
+
const ocrImage = yield preprocessImage(image, preprocess);
|
|
210
|
+
const result = yield worker.recognize(ocrImage, recognizeOptions, { text: true, blocks: true });
|
|
211
|
+
const { data } = result;
|
|
212
|
+
return {
|
|
213
|
+
text: data.text,
|
|
214
|
+
confidence: data.confidence,
|
|
215
|
+
language,
|
|
216
|
+
lines: getLinesFromPage(data),
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
finally {
|
|
220
|
+
yield (worker === null || worker === void 0 ? void 0 : worker.terminate());
|
|
221
|
+
}
|
|
222
|
+
});
|
|
@@ -26,7 +26,7 @@ const CONTROL_SIZE_TOKENS = {
|
|
|
26
26
|
pillPaddingX: 6,
|
|
27
27
|
pillIconSize: 10,
|
|
28
28
|
pillGap: 4,
|
|
29
|
-
segmentedHeight:
|
|
29
|
+
segmentedHeight: 24,
|
|
30
30
|
segmentedFontSize: 11,
|
|
31
31
|
sectionTitleFontSize: 12,
|
|
32
32
|
sectionIconSize: 12,
|
|
@@ -57,7 +57,7 @@ const CONTROL_SIZE_TOKENS = {
|
|
|
57
57
|
pillPaddingX: 8,
|
|
58
58
|
pillIconSize: 12,
|
|
59
59
|
pillGap: 5,
|
|
60
|
-
segmentedHeight:
|
|
60
|
+
segmentedHeight: 28,
|
|
61
61
|
segmentedFontSize: 12,
|
|
62
62
|
sectionTitleFontSize: 13,
|
|
63
63
|
sectionIconSize: 12,
|
|
@@ -89,7 +89,7 @@ const CONTROL_SIZE_TOKENS = {
|
|
|
89
89
|
pillIconSize: 14,
|
|
90
90
|
pillGap: 5,
|
|
91
91
|
segmentedHeight: 32,
|
|
92
|
-
segmentedFontSize:
|
|
92
|
+
segmentedFontSize: 13,
|
|
93
93
|
sectionTitleFontSize: 14,
|
|
94
94
|
sectionIconSize: 14,
|
|
95
95
|
},
|
|
@@ -119,8 +119,8 @@ const CONTROL_SIZE_TOKENS = {
|
|
|
119
119
|
pillPaddingX: 12,
|
|
120
120
|
pillIconSize: 16,
|
|
121
121
|
pillGap: 5,
|
|
122
|
-
segmentedHeight:
|
|
123
|
-
segmentedFontSize:
|
|
122
|
+
segmentedHeight: 36,
|
|
123
|
+
segmentedFontSize: 14,
|
|
124
124
|
sectionTitleFontSize: 16,
|
|
125
125
|
sectionIconSize: 18,
|
|
126
126
|
},
|
|
@@ -150,8 +150,8 @@ const CONTROL_SIZE_TOKENS = {
|
|
|
150
150
|
pillPaddingX: 14,
|
|
151
151
|
pillIconSize: 18,
|
|
152
152
|
pillGap: 5,
|
|
153
|
-
segmentedHeight:
|
|
154
|
-
segmentedFontSize:
|
|
153
|
+
segmentedHeight: 44,
|
|
154
|
+
segmentedFontSize: 15,
|
|
155
155
|
sectionTitleFontSize: 18,
|
|
156
156
|
sectionIconSize: 24,
|
|
157
157
|
},
|
|
@@ -181,8 +181,8 @@ const CONTROL_SIZE_TOKENS = {
|
|
|
181
181
|
pillPaddingX: 16,
|
|
182
182
|
pillIconSize: 20,
|
|
183
183
|
pillGap: 5,
|
|
184
|
-
segmentedHeight:
|
|
185
|
-
segmentedFontSize:
|
|
184
|
+
segmentedHeight: 52,
|
|
185
|
+
segmentedFontSize: 16,
|
|
186
186
|
sectionTitleFontSize: 20,
|
|
187
187
|
sectionIconSize: 28,
|
|
188
188
|
},
|
package/package.json
CHANGED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { Editor } from "@tiptap/react";
|
|
2
|
-
import type { MouseEvent as ReactMouseEvent } from "react";
|
|
3
|
-
import type { TableRailTarget } from "./TableTools";
|
|
4
|
-
type TableCornerMenuProps = {
|
|
5
|
-
editor: Editor | null;
|
|
6
|
-
target: TableRailTarget;
|
|
7
|
-
opened: boolean;
|
|
8
|
-
onOpen: () => void;
|
|
9
|
-
onClose: () => void;
|
|
10
|
-
onAction: () => void;
|
|
11
|
-
onMouseEnter: () => void;
|
|
12
|
-
onMouseLeave: () => void;
|
|
13
|
-
onMouseDown: (event: ReactMouseEvent<HTMLButtonElement>) => void;
|
|
14
|
-
};
|
|
15
|
-
export declare const TableCornerMenu: ({ editor, target, opened, onOpen, onClose, onAction, onMouseEnter, onMouseLeave, onMouseDown, }: TableCornerMenuProps) => import("react/jsx-runtime").JSX.Element;
|
|
16
|
-
export {};
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { TextSelection } from "@tiptap/pm/state";
|
|
3
|
-
import { CopyIcon, EraserIcon, TablePropertiesIcon, Trash2Icon, } from "lucide-react";
|
|
4
|
-
import styled from "styled-components";
|
|
5
|
-
import { Button } from "../../Button";
|
|
6
|
-
import { getControlSizeTokens } from "../../core";
|
|
7
|
-
import { Popover } from "../../Popover";
|
|
8
|
-
const CORNER_BUTTON_SIZE = 18;
|
|
9
|
-
const VIEWPORT_PADDING = 8;
|
|
10
|
-
const clearTableContents = (editor, target) => {
|
|
11
|
-
if (!editor)
|
|
12
|
-
return false;
|
|
13
|
-
const paragraph = editor.state.schema.nodes.paragraph.createAndFill();
|
|
14
|
-
if (!paragraph)
|
|
15
|
-
return false;
|
|
16
|
-
const tr = editor.state.tr;
|
|
17
|
-
const { tableContext } = target;
|
|
18
|
-
const cells = tableContext.map
|
|
19
|
-
.cellsInRect({
|
|
20
|
-
left: 0,
|
|
21
|
-
right: tableContext.map.width,
|
|
22
|
-
top: 0,
|
|
23
|
-
bottom: tableContext.map.height,
|
|
24
|
-
})
|
|
25
|
-
.map((pos) => ({
|
|
26
|
-
pos,
|
|
27
|
-
node: tableContext.node.nodeAt(pos),
|
|
28
|
-
}))
|
|
29
|
-
.filter((cell) => Boolean(cell.node))
|
|
30
|
-
.sort((a, b) => b.pos - a.pos);
|
|
31
|
-
cells.forEach((cell) => {
|
|
32
|
-
const from = tableContext.start + cell.pos + 1;
|
|
33
|
-
const to = tableContext.start + cell.pos + cell.node.nodeSize - 1;
|
|
34
|
-
tr.replaceWith(from, to, paragraph);
|
|
35
|
-
});
|
|
36
|
-
editor.view.dispatch(tr);
|
|
37
|
-
return true;
|
|
38
|
-
};
|
|
39
|
-
const duplicateTable = (editor, target) => {
|
|
40
|
-
if (!editor)
|
|
41
|
-
return false;
|
|
42
|
-
const { tableContext } = target;
|
|
43
|
-
const paragraph = editor.state.schema.nodes.paragraph.createAndFill();
|
|
44
|
-
if (!paragraph)
|
|
45
|
-
return false;
|
|
46
|
-
const insertPosition = tableContext.pos + tableContext.node.nodeSize;
|
|
47
|
-
const duplicatedTable = tableContext.node.copy(tableContext.node.content);
|
|
48
|
-
const tr = editor.state.tr.insert(insertPosition, [
|
|
49
|
-
paragraph,
|
|
50
|
-
duplicatedTable,
|
|
51
|
-
]);
|
|
52
|
-
const firstCellPosition = tableContext.map.positionAt(0, 0, duplicatedTable);
|
|
53
|
-
if (firstCellPosition !== null) {
|
|
54
|
-
const duplicatePosition = insertPosition + paragraph.nodeSize;
|
|
55
|
-
const firstCellContentPosition = duplicatePosition + 1 + firstCellPosition + 1;
|
|
56
|
-
tr.setSelection(TextSelection.near(tr.doc.resolve(firstCellContentPosition)));
|
|
57
|
-
}
|
|
58
|
-
editor.view.dispatch(tr.scrollIntoView());
|
|
59
|
-
return true;
|
|
60
|
-
};
|
|
61
|
-
const deleteTable = (editor, target) => {
|
|
62
|
-
if (!editor)
|
|
63
|
-
return false;
|
|
64
|
-
const { tableContext } = target;
|
|
65
|
-
editor.view.dispatch(editor.state.tr
|
|
66
|
-
.delete(tableContext.pos, tableContext.pos + tableContext.node.nodeSize)
|
|
67
|
-
.scrollIntoView());
|
|
68
|
-
return true;
|
|
69
|
-
};
|
|
70
|
-
const getTableActionGroups = (editor, target) => [
|
|
71
|
-
{
|
|
72
|
-
label: "Content",
|
|
73
|
-
actions: [
|
|
74
|
-
{
|
|
75
|
-
label: "Clear table contents",
|
|
76
|
-
leftSection: _jsx(EraserIcon, { size: 14 }),
|
|
77
|
-
onClick: () => clearTableContents(editor, target),
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
label: "Duplicate table",
|
|
81
|
-
leftSection: _jsx(CopyIcon, { size: 14 }),
|
|
82
|
-
onClick: () => duplicateTable(editor, target),
|
|
83
|
-
},
|
|
84
|
-
],
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
label: "Delete",
|
|
88
|
-
actions: [
|
|
89
|
-
{
|
|
90
|
-
label: "Delete table",
|
|
91
|
-
leftSection: _jsx(Trash2Icon, { size: 14 }),
|
|
92
|
-
danger: true,
|
|
93
|
-
onClick: () => deleteTable(editor, target),
|
|
94
|
-
},
|
|
95
|
-
],
|
|
96
|
-
},
|
|
97
|
-
];
|
|
98
|
-
const getCornerRect = (target) => ({
|
|
99
|
-
top: Math.max(VIEWPORT_PADDING, target.tableRect.top - CORNER_BUTTON_SIZE),
|
|
100
|
-
left: Math.max(VIEWPORT_PADDING, target.tableRect.left - CORNER_BUTTON_SIZE),
|
|
101
|
-
});
|
|
102
|
-
const CornerRoot = styled.div `
|
|
103
|
-
display: flex;
|
|
104
|
-
position: fixed;
|
|
105
|
-
top: ${({ $top }) => `${$top}px`};
|
|
106
|
-
left: ${({ $left }) => `${$left}px`};
|
|
107
|
-
z-index: 1500;
|
|
108
|
-
width: ${CORNER_BUTTON_SIZE}px;
|
|
109
|
-
height: ${CORNER_BUTTON_SIZE}px;
|
|
110
|
-
|
|
111
|
-
button {
|
|
112
|
-
width: 100%;
|
|
113
|
-
height: 100%;
|
|
114
|
-
min-height: 0;
|
|
115
|
-
padding: 0;
|
|
116
|
-
border-radius: 6px;
|
|
117
|
-
background-color: ${({ theme }) => theme.palette.background.paper};
|
|
118
|
-
color: ${({ theme }) => theme.palette.text.secondary};
|
|
119
|
-
|
|
120
|
-
&:hover {
|
|
121
|
-
background-color: ${({ theme }) => theme.palette.primary.main};
|
|
122
|
-
color: white;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
`;
|
|
126
|
-
const TableMenuPanel = styled.div `
|
|
127
|
-
display: flex;
|
|
128
|
-
flex-direction: column;
|
|
129
|
-
min-width: 220px;
|
|
130
|
-
color: ${({ theme }) => theme.palette.text.primary};
|
|
131
|
-
`;
|
|
132
|
-
const TableMenuDropdown = styled(Popover.Dropdown) `
|
|
133
|
-
min-width: 180px;
|
|
134
|
-
border-radius: 5px;
|
|
135
|
-
border: 1px solid ${({ theme }) => theme.palette.divider};
|
|
136
|
-
background-color: ${({ theme }) => theme.palette.input.background};
|
|
137
|
-
box-shadow: none;
|
|
138
|
-
padding: 5px;
|
|
139
|
-
`;
|
|
140
|
-
const TableMenuGroup = styled.div `
|
|
141
|
-
display: flex;
|
|
142
|
-
flex-direction: column;
|
|
143
|
-
gap: 1px;
|
|
144
|
-
padding-top: ${({ $withDivider }) => ($withDivider ? "5px" : 0)};
|
|
145
|
-
margin-top: ${({ $withDivider }) => ($withDivider ? "5px" : 0)};
|
|
146
|
-
border-top: ${({ $withDivider, theme }) => $withDivider ? `1px solid ${theme.palette.divider}` : 0};
|
|
147
|
-
`;
|
|
148
|
-
const TableMenuButton = styled(Button) `
|
|
149
|
-
min-width: 100%;
|
|
150
|
-
height: ${getControlSizeTokens("sm").menuRowHeight}px;
|
|
151
|
-
min-height: ${getControlSizeTokens("sm").menuRowHeight}px;
|
|
152
|
-
padding: 0 ${getControlSizeTokens("sm").menuItemPaddingX}px;
|
|
153
|
-
border: none;
|
|
154
|
-
border-radius: 3px;
|
|
155
|
-
color: ${({ $danger, theme }) => $danger ? theme.palette.error.main : theme.palette.text.primary};
|
|
156
|
-
font-weight: normal;
|
|
157
|
-
justify-content: flex-start;
|
|
158
|
-
width: 100%;
|
|
159
|
-
|
|
160
|
-
.button-label {
|
|
161
|
-
display: inline-block;
|
|
162
|
-
min-width: 0;
|
|
163
|
-
width: 100%;
|
|
164
|
-
overflow: hidden;
|
|
165
|
-
text-align: left;
|
|
166
|
-
text-overflow: ellipsis;
|
|
167
|
-
white-space: nowrap;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
[data-position="left"] {
|
|
171
|
-
color: currentColor;
|
|
172
|
-
opacity: 0.8;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
&:hover {
|
|
176
|
-
background-color: ${({ theme }) => theme.palette.action.hover};
|
|
177
|
-
color: ${({ $danger, theme }) => $danger ? theme.palette.error.main : theme.palette.text.primary};
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
&:active {
|
|
181
|
-
translate: none;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
&:focus {
|
|
185
|
-
text-decoration: none;
|
|
186
|
-
}
|
|
187
|
-
`;
|
|
188
|
-
const TableMenu = ({ groups, onAction, }) => (_jsx(TableMenuPanel, { children: groups.map((group, index) => (_jsx(TableMenuGroup, { "$withDivider": index > 0, children: group.actions.map((action) => (_jsx(TableMenuButton, { "$danger": action.danger, size: "sm", variant: "subtle", leftSection: action.leftSection, justify: "start", onClick: () => {
|
|
189
|
-
action.onClick();
|
|
190
|
-
onAction();
|
|
191
|
-
}, children: action.label }, action.label))) }, group.label))) }));
|
|
192
|
-
export const TableCornerMenu = ({ editor, target, opened, onOpen, onClose, onAction, onMouseEnter, onMouseLeave, onMouseDown, }) => {
|
|
193
|
-
const rect = getCornerRect(target);
|
|
194
|
-
const groups = getTableActionGroups(editor, target);
|
|
195
|
-
return (_jsx(CornerRoot, { "data-monolith-table-rail": true, "$top": rect.top, "$left": rect.left, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, children: _jsxs(Popover, { opened: opened, onChange: (nextOpened) => {
|
|
196
|
-
if (nextOpened) {
|
|
197
|
-
onOpen();
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
onClose();
|
|
201
|
-
}, position: "bottom-start", width: 245, trapFocus: true, children: [_jsx(Popover.Target, { children: _jsx(Button, { type: "button", size: "xs", variant: "outlined", title: "Table options", "aria-label": "Table options", selected: opened, onMouseDown: onMouseDown, children: _jsx(TablePropertiesIcon, { size: 12 }) }) }), _jsx(TableMenuDropdown, { children: _jsx(TableMenu, { groups: groups, onAction: onAction }) })] }) }));
|
|
202
|
-
};
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { Editor } from "@tiptap/react";
|
|
2
|
-
import { Node as ProseMirrorNode } from "@tiptap/pm/model";
|
|
3
|
-
import { TableMap } from "@tiptap/pm/tables";
|
|
4
|
-
type TableToolsContentProps = {
|
|
5
|
-
editor: Editor | null;
|
|
6
|
-
showInsert?: boolean;
|
|
7
|
-
onInsert?: () => void;
|
|
8
|
-
onAction?: () => void;
|
|
9
|
-
};
|
|
10
|
-
type TableToolsPopoverProps = {
|
|
11
|
-
editor: Editor | null;
|
|
12
|
-
};
|
|
13
|
-
type TableRailsProps = {
|
|
14
|
-
editor: Editor | null;
|
|
15
|
-
};
|
|
16
|
-
type RailKind = "row" | "column";
|
|
17
|
-
type RailRect = {
|
|
18
|
-
top: number;
|
|
19
|
-
left: number;
|
|
20
|
-
width: number;
|
|
21
|
-
height: number;
|
|
22
|
-
};
|
|
23
|
-
type TableContext = {
|
|
24
|
-
node: ProseMirrorNode;
|
|
25
|
-
pos: number;
|
|
26
|
-
start: number;
|
|
27
|
-
map: TableMap;
|
|
28
|
-
};
|
|
29
|
-
export type TableRailTarget = {
|
|
30
|
-
kind: RailKind;
|
|
31
|
-
rowIndex: number;
|
|
32
|
-
colIndex: number;
|
|
33
|
-
tableElement: HTMLTableElement;
|
|
34
|
-
tableRect: RailRect;
|
|
35
|
-
tableContext: TableContext;
|
|
36
|
-
rowRect: RailRect;
|
|
37
|
-
columnRect: RailRect;
|
|
38
|
-
};
|
|
39
|
-
export declare const hasTableExtension: (editor: Editor | null) => boolean;
|
|
40
|
-
export declare const isTableActive: (editor: Editor | null) => boolean;
|
|
41
|
-
export declare const TableToolsContent: ({ editor, showInsert, onInsert, onAction, }: TableToolsContentProps) => import("react/jsx-runtime").JSX.Element;
|
|
42
|
-
export declare const TableToolsPopover: ({ editor }: TableToolsPopoverProps) => import("react/jsx-runtime").JSX.Element;
|
|
43
|
-
export declare const TableRails: ({ editor }: TableRailsProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
44
|
-
export {};
|