@monolith-forensics/monolith-ui 1.9.1-dev.8 → 1.9.3-dev.0

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.
Files changed (93) hide show
  1. package/dist/DropDownMenu/components/MenuItemList.js +32 -12
  2. package/dist/DropDownMenu/components/StyledContent.js +1 -1
  3. package/dist/DropDownMenu/components/StyledInnerItemContainer.js +1 -0
  4. package/dist/FileViewer/FileViewer.js +32 -8
  5. package/dist/FileViewer/viewers/ImageViewer.d.ts +1 -0
  6. package/dist/FileViewer/viewers/ImageViewer.js +36 -15
  7. package/dist/MonolithUIProvider/MonolithUIProvider.d.ts +23 -0
  8. package/dist/RichTextEditor/Components/BubbleMenu.d.ts +8 -8
  9. package/dist/RichTextEditor/Components/BubbleMenu.js +202 -94
  10. package/dist/RichTextEditor/Components/CodeBlockBaseButton.d.ts +18 -0
  11. package/dist/RichTextEditor/Components/CodeBlockBaseButton.js +6 -0
  12. package/dist/RichTextEditor/Components/CodeBlockCopyButton.d.ts +9 -0
  13. package/dist/RichTextEditor/Components/CodeBlockCopyButton.js +42 -0
  14. package/dist/RichTextEditor/Components/CodeBlockFormatButton.d.ts +10 -0
  15. package/dist/RichTextEditor/Components/CodeBlockFormatButton.js +60 -0
  16. package/dist/RichTextEditor/Components/CodeBlockLanguageSelect.d.ts +9 -0
  17. package/dist/RichTextEditor/Components/CodeBlockLanguageSelect.js +30 -0
  18. package/dist/RichTextEditor/Components/CodeBlockNodeView.d.ts +3 -0
  19. package/dist/RichTextEditor/Components/CodeBlockNodeView.js +28 -0
  20. package/dist/RichTextEditor/Components/CodeBlockWrapButton.d.ts +10 -0
  21. package/dist/RichTextEditor/Components/CodeBlockWrapButton.js +17 -0
  22. package/dist/RichTextEditor/Components/LinkEditor.d.ts +8 -0
  23. package/dist/RichTextEditor/Components/LinkEditor.js +94 -0
  24. package/dist/RichTextEditor/Components/TableCornerMenu.d.ts +16 -0
  25. package/dist/RichTextEditor/Components/TableCornerMenu.js +202 -0
  26. package/dist/RichTextEditor/Components/TableTools/TableCornerMenu.d.ts +2 -0
  27. package/dist/RichTextEditor/Components/TableTools/TableCornerMenu.js +19 -0
  28. package/dist/RichTextEditor/Components/TableTools/TableInsertControls.d.ts +2 -0
  29. package/dist/RichTextEditor/Components/TableTools/TableInsertControls.js +24 -0
  30. package/dist/RichTextEditor/Components/TableTools/TableRails.d.ts +2 -0
  31. package/dist/RichTextEditor/Components/TableTools/TableRails.js +180 -0
  32. package/dist/RichTextEditor/Components/TableTools/TableToolMenu.d.ts +5 -0
  33. package/dist/RichTextEditor/Components/TableTools/TableToolMenu.js +6 -0
  34. package/dist/RichTextEditor/Components/TableTools/TableTools.actions.d.ts +5 -0
  35. package/dist/RichTextEditor/Components/TableTools/TableTools.actions.js +183 -0
  36. package/dist/RichTextEditor/Components/TableTools/TableTools.commands.d.ts +16 -0
  37. package/dist/RichTextEditor/Components/TableTools/TableTools.commands.js +217 -0
  38. package/dist/RichTextEditor/Components/TableTools/TableTools.constants.d.ts +8 -0
  39. package/dist/RichTextEditor/Components/TableTools/TableTools.constants.js +11 -0
  40. package/dist/RichTextEditor/Components/TableTools/TableTools.d.ts +3 -0
  41. package/dist/RichTextEditor/Components/TableTools/TableTools.geometry.d.ts +23 -0
  42. package/dist/RichTextEditor/Components/TableTools/TableTools.geometry.js +75 -0
  43. package/dist/RichTextEditor/Components/TableTools/TableTools.js +3 -0
  44. package/dist/RichTextEditor/Components/TableTools/TableTools.selectors.d.ts +16 -0
  45. package/dist/RichTextEditor/Components/TableTools/TableTools.selectors.js +53 -0
  46. package/dist/RichTextEditor/Components/TableTools/TableTools.styled.d.ts +40 -0
  47. package/dist/RichTextEditor/Components/TableTools/TableTools.styled.js +167 -0
  48. package/dist/RichTextEditor/Components/TableTools/TableTools.types.d.ts +76 -0
  49. package/dist/RichTextEditor/Components/TableTools/TableTools.types.js +1 -0
  50. package/dist/RichTextEditor/Components/TableTools/TableTools.utils.d.ts +4 -0
  51. package/dist/RichTextEditor/Components/TableTools/TableTools.utils.js +4 -0
  52. package/dist/RichTextEditor/Components/TableTools/TableToolsPopover.d.ts +2 -0
  53. package/dist/RichTextEditor/Components/TableTools/TableToolsPopover.js +12 -0
  54. package/dist/RichTextEditor/Components/TableTools/index.d.ts +3 -0
  55. package/dist/RichTextEditor/Components/TableTools/index.js +2 -0
  56. package/dist/RichTextEditor/Components/TableTools.d.ts +44 -0
  57. package/dist/RichTextEditor/Components/TableTools.js +790 -0
  58. package/dist/RichTextEditor/Enums/Controls.d.ts +7 -1
  59. package/dist/RichTextEditor/Enums/Controls.js +6 -0
  60. package/dist/RichTextEditor/Enums/Extensions.d.ts +4 -0
  61. package/dist/RichTextEditor/Enums/Extensions.js +4 -0
  62. package/dist/RichTextEditor/Enums/HighlightColors.d.ts +9 -0
  63. package/dist/RichTextEditor/Enums/HighlightColors.js +10 -0
  64. package/dist/RichTextEditor/Enums/SlashCommands.d.ts +4 -1
  65. package/dist/RichTextEditor/Enums/SlashCommands.js +3 -0
  66. package/dist/RichTextEditor/Extensions/SlashCommandList.js +0 -1
  67. package/dist/RichTextEditor/Extensions/getSlashCommand.js +39 -1
  68. package/dist/RichTextEditor/Extensions/getTiptapExtensions.d.ts +10 -2
  69. package/dist/RichTextEditor/Extensions/getTiptapExtensions.js +157 -30
  70. package/dist/RichTextEditor/Plugins/ImageActionsPlugin.js +4 -7
  71. package/dist/RichTextEditor/RichTextEditor.d.ts +4 -2
  72. package/dist/RichTextEditor/RichTextEditor.js +395 -15
  73. package/dist/RichTextEditor/Toolbar/Control.d.ts +6 -2
  74. package/dist/RichTextEditor/Toolbar/Control.js +13 -6
  75. package/dist/RichTextEditor/Toolbar/Controls.d.ts +6 -0
  76. package/dist/RichTextEditor/Toolbar/Controls.js +118 -1
  77. package/dist/RichTextEditor/Toolbar/ControlsGroup.js +17 -6
  78. package/dist/RichTextEditor/Toolbar/Labels.d.ts +1 -0
  79. package/dist/RichTextEditor/Toolbar/Labels.js +1 -0
  80. package/dist/RichTextEditor/Toolbar/Toolbar.d.ts +1 -2
  81. package/dist/RichTextEditor/Toolbar/Toolbar.js +32 -67
  82. package/dist/RichTextEditor/Utils/codeBlockUtils.d.ts +20 -0
  83. package/dist/RichTextEditor/Utils/codeBlockUtils.js +137 -0
  84. package/dist/RichTextEditor/Utils/codeUtils.d.ts +3 -0
  85. package/dist/RichTextEditor/Utils/codeUtils.js +12 -0
  86. package/dist/RichTextEditor/Utils/linkUtils.d.ts +19 -0
  87. package/dist/RichTextEditor/Utils/linkUtils.js +57 -0
  88. package/dist/RichTextEditor/Utils/tableUtils.d.ts +1 -0
  89. package/dist/RichTextEditor/Utils/tableUtils.js +1 -0
  90. package/dist/theme/variants.js +46 -0
  91. package/package.json +8 -1
  92. package/dist/RichTextEditor/Extensions/BubbleMenuExtension.d.ts +0 -7
  93. package/dist/RichTextEditor/Extensions/BubbleMenuExtension.js +0 -157
@@ -0,0 +1,790 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Fragment } from "@tiptap/pm/model";
3
+ import { addColumn, addRow, findCellPos, findTable, removeColumn, removeRow, rowIsHeader, TableMap, } from "@tiptap/pm/tables";
4
+ import { ArrowDownToLineIcon, ArrowLeftToLineIcon, ArrowRightToLineIcon, ArrowUpToLineIcon, CopyIcon, EraserIcon, MoveDownIcon, MoreHorizontalIcon, MoreVerticalIcon, MoveLeftIcon, MoveRightIcon, MoveUpIcon, PanelTopIcon, Table2Icon, Trash2Icon, } from "lucide-react";
5
+ import { useCallback, useEffect, useRef, useState } from "react";
6
+ import styled from "styled-components";
7
+ import { Button } from "../../Button";
8
+ import { getControlSizeTokens } from "../../core";
9
+ import Input from "../../Input";
10
+ import { Switch } from "../../Switch";
11
+ import { Popover } from "../../Popover";
12
+ import { TableCornerMenu } from "./TableCornerMenu";
13
+ import FieldLabel from "../../FieldLabel";
14
+ const DEFAULT_TABLE_OPTIONS = {
15
+ rows: 3,
16
+ cols: 3,
17
+ withHeaderRow: true,
18
+ };
19
+ const MIN_TABLE_SIZE = 1;
20
+ const MAX_TABLE_SIZE = 20;
21
+ const RAIL_THICKNESS = 8;
22
+ const RAIL_HIDE_DELAY = 250;
23
+ const VIEWPORT_PADDING = 8;
24
+ const clampTableSize = (value) => {
25
+ if (Number.isNaN(value))
26
+ return MIN_TABLE_SIZE;
27
+ return Math.min(MAX_TABLE_SIZE, Math.max(MIN_TABLE_SIZE, value));
28
+ };
29
+ export const hasTableExtension = (editor) => Boolean(editor === null || editor === void 0 ? void 0 : editor.extensionManager.extensions.find((extension) => extension.name === "table"));
30
+ export const isTableActive = (editor) => Boolean((editor === null || editor === void 0 ? void 0 : editor.isActive("table")) ||
31
+ (editor === null || editor === void 0 ? void 0 : editor.isActive("tableRow")) ||
32
+ (editor === null || editor === void 0 ? void 0 : editor.isActive("tableCell")) ||
33
+ (editor === null || editor === void 0 ? void 0 : editor.isActive("tableHeader")));
34
+ const runTableCommand = (editor, command, args = []) => {
35
+ const chain = editor === null || editor === void 0 ? void 0 : editor.chain().focus();
36
+ if (!(chain === null || chain === void 0 ? void 0 : chain[command]))
37
+ return;
38
+ chain[command](...args).run();
39
+ };
40
+ const toRect = (rect) => ({
41
+ top: rect.top,
42
+ left: rect.left,
43
+ width: rect.width,
44
+ height: rect.height,
45
+ });
46
+ const clamp = (value, min, max) => Math.max(min, Math.min(max, value));
47
+ const getTableRect = (tableContext) => ({
48
+ left: 0,
49
+ top: 0,
50
+ right: tableContext.map.width,
51
+ bottom: tableContext.map.height,
52
+ tableStart: tableContext.start,
53
+ map: tableContext.map,
54
+ table: tableContext.node,
55
+ });
56
+ const getRowStartOffset = (table, rowIndex) => {
57
+ let offset = 0;
58
+ for (let index = 0; index < rowIndex; index += 1) {
59
+ offset += table.child(index).nodeSize;
60
+ }
61
+ return offset;
62
+ };
63
+ const getCellChildIndex = (table, rowIndex, cellPos) => {
64
+ const row = table.child(rowIndex);
65
+ let offset = getRowStartOffset(table, rowIndex) + 1;
66
+ for (let index = 0; index < row.childCount; index += 1) {
67
+ if (offset === cellPos)
68
+ return index;
69
+ offset += row.child(index).nodeSize;
70
+ }
71
+ return -1;
72
+ };
73
+ const getCellsInTarget = (target) => {
74
+ const { tableContext } = target;
75
+ return tableContext.map
76
+ .cellsInRect(target.kind === "row"
77
+ ? {
78
+ left: 0,
79
+ right: tableContext.map.width,
80
+ top: target.rowIndex,
81
+ bottom: target.rowIndex + 1,
82
+ }
83
+ : {
84
+ left: target.colIndex,
85
+ right: target.colIndex + 1,
86
+ top: 0,
87
+ bottom: tableContext.map.height,
88
+ })
89
+ .map((pos) => ({
90
+ pos,
91
+ node: tableContext.node.nodeAt(pos),
92
+ }))
93
+ .filter((cell) => Boolean(cell.node));
94
+ };
95
+ const getCellsInTableTarget = (target) => {
96
+ const { tableContext } = target;
97
+ return tableContext.map
98
+ .cellsInRect({
99
+ left: 0,
100
+ right: tableContext.map.width,
101
+ top: 0,
102
+ bottom: tableContext.map.height,
103
+ })
104
+ .map((pos) => ({
105
+ pos,
106
+ node: tableContext.node.nodeAt(pos),
107
+ }))
108
+ .filter((cell) => Boolean(cell.node));
109
+ };
110
+ const hasRiskyMergedCells = (target) => {
111
+ return getCellsInTarget(target).some((cell) => cell.node.attrs.rowspan > 1 || cell.node.attrs.colspan > 1);
112
+ };
113
+ const getTopRowIsHeader = (target) => rowIsHeader(target.tableContext.map, target.tableContext.node, 0);
114
+ const insertRowAt = (editor, target, row) => {
115
+ if (!editor)
116
+ return false;
117
+ editor.view.dispatch(addRow(editor.state.tr, getTableRect(target.tableContext), row));
118
+ return true;
119
+ };
120
+ const insertColumnAt = (editor, target, column) => {
121
+ if (!editor)
122
+ return false;
123
+ editor.view.dispatch(addColumn(editor.state.tr, getTableRect(target.tableContext), column));
124
+ return true;
125
+ };
126
+ const deleteRowAt = (editor, target) => {
127
+ if (!editor || target.tableContext.map.height <= 1)
128
+ return false;
129
+ const tr = editor.state.tr;
130
+ removeRow(tr, getTableRect(target.tableContext), target.rowIndex);
131
+ editor.view.dispatch(tr);
132
+ return true;
133
+ };
134
+ const deleteColumnAt = (editor, target) => {
135
+ if (!editor || target.tableContext.map.width <= 1)
136
+ return false;
137
+ const tr = editor.state.tr;
138
+ removeColumn(tr, getTableRect(target.tableContext), target.colIndex);
139
+ editor.view.dispatch(tr);
140
+ return true;
141
+ };
142
+ const clearTargetContents = (editor, target) => {
143
+ if (!editor)
144
+ return false;
145
+ const paragraph = editor.state.schema.nodes.paragraph.createAndFill();
146
+ if (!paragraph)
147
+ return false;
148
+ const tr = editor.state.tr;
149
+ const cells = getCellsInTarget(target).sort((a, b) => b.pos - a.pos);
150
+ cells.forEach((cell) => {
151
+ const from = target.tableContext.start + cell.pos + 1;
152
+ const to = target.tableContext.start + cell.pos + cell.node.nodeSize - 1;
153
+ tr.replaceWith(from, to, paragraph);
154
+ });
155
+ editor.view.dispatch(tr);
156
+ return true;
157
+ };
158
+ const duplicateRow = (editor, target) => {
159
+ if (!editor)
160
+ return false;
161
+ const row = target.tableContext.node.child(target.rowIndex);
162
+ const insertPosition = target.tableContext.start +
163
+ getRowStartOffset(target.tableContext.node, target.rowIndex + 1);
164
+ editor.view.dispatch(editor.state.tr.insert(insertPosition, row.copy(row.content)));
165
+ return true;
166
+ };
167
+ const duplicateColumn = (editor, target) => {
168
+ if (!editor)
169
+ return false;
170
+ const tr = editor.state.tr;
171
+ const inserts = [];
172
+ for (let row = 0; row < target.tableContext.map.height; row += 1) {
173
+ const cellPos = target.tableContext.map.positionAt(row, target.colIndex, target.tableContext.node);
174
+ const cell = target.tableContext.node.nodeAt(cellPos);
175
+ if (cell) {
176
+ inserts.push({
177
+ pos: target.tableContext.start + cellPos + cell.nodeSize,
178
+ node: cell.copy(cell.content),
179
+ });
180
+ }
181
+ }
182
+ inserts
183
+ .sort((a, b) => b.pos - a.pos)
184
+ .forEach((insert) => tr.insert(insert.pos, insert.node));
185
+ editor.view.dispatch(tr);
186
+ return true;
187
+ };
188
+ const moveRow = (editor, target, direction) => {
189
+ if (!editor)
190
+ return false;
191
+ const to = target.rowIndex + direction;
192
+ if (to < 0 || to >= target.tableContext.map.height)
193
+ return false;
194
+ const rows = [];
195
+ target.tableContext.node.forEach((row) => {
196
+ rows.push(row);
197
+ });
198
+ const [row] = rows.splice(target.rowIndex, 1);
199
+ rows.splice(to, 0, row);
200
+ const nextTable = target.tableContext.node.copy(Fragment.from(rows));
201
+ editor.view.dispatch(editor.state.tr.replaceWith(target.tableContext.pos, target.tableContext.pos + target.tableContext.node.nodeSize, nextTable));
202
+ return true;
203
+ };
204
+ const moveColumn = (editor, target, direction) => {
205
+ if (!editor)
206
+ return false;
207
+ const to = target.colIndex + direction;
208
+ if (to < 0 || to >= target.tableContext.map.width)
209
+ return false;
210
+ const rows = [];
211
+ for (let row = 0; row < target.tableContext.map.height; row += 1) {
212
+ const rowNode = target.tableContext.node.child(row);
213
+ const cells = [];
214
+ const cellPos = target.tableContext.map.positionAt(row, target.colIndex, target.tableContext.node);
215
+ const cellIndex = getCellChildIndex(target.tableContext.node, row, cellPos);
216
+ rowNode.forEach((cell) => {
217
+ cells.push(cell);
218
+ });
219
+ if (cellIndex < 0) {
220
+ rows.push(rowNode);
221
+ continue;
222
+ }
223
+ const [cell] = cells.splice(cellIndex, 1);
224
+ const insertIndex = direction > 0 ? cellIndex + 1 : cellIndex - 1;
225
+ cells.splice(insertIndex, 0, cell);
226
+ rows.push(rowNode.copy(Fragment.from(cells)));
227
+ }
228
+ const nextTable = target.tableContext.node.copy(Fragment.from(rows));
229
+ editor.view.dispatch(editor.state.tr.replaceWith(target.tableContext.pos, target.tableContext.pos + target.tableContext.node.nodeSize, nextTable));
230
+ return true;
231
+ };
232
+ const toggleTopHeaderRow = (editor, target) => {
233
+ if (!editor || target.rowIndex !== 0)
234
+ return false;
235
+ const headerType = editor.state.schema.nodes.tableHeader;
236
+ const cellType = editor.state.schema.nodes.tableCell;
237
+ if (!headerType || !cellType)
238
+ return false;
239
+ const makeHeader = !getTopRowIsHeader(target);
240
+ const tr = editor.state.tr;
241
+ const cells = getCellsInTarget(target);
242
+ cells.forEach((cell) => {
243
+ tr.setNodeMarkup(target.tableContext.start + cell.pos, makeHeader ? headerType : cellType, cell.node.attrs);
244
+ });
245
+ editor.view.dispatch(tr);
246
+ return true;
247
+ };
248
+ const TableToolsPanel = styled.div `
249
+ display: flex;
250
+ flex-direction: column;
251
+ gap: 0.75rem;
252
+ min-width: 250px;
253
+ color: ${({ theme }) => theme.palette.text.primary};
254
+ `;
255
+ const TableToolsSection = styled.div `
256
+ display: flex;
257
+ flex-direction: column;
258
+ gap: 0.5rem;
259
+ `;
260
+ const TableToolsSectionTitle = styled(FieldLabel) `
261
+ color: ${({ theme }) => theme.palette.text.secondary};
262
+ font-size: 0.6875rem;
263
+ font-weight: 600;
264
+ line-height: 1rem;
265
+ text-transform: uppercase;
266
+ `;
267
+ const InsertGrid = styled.div `
268
+ display: grid;
269
+ grid-template-columns: repeat(2, minmax(0, 1fr));
270
+ gap: 0.5rem;
271
+ `;
272
+ const Field = styled.label `
273
+ display: flex;
274
+ flex-direction: column;
275
+ gap: 0.25rem;
276
+ color: ${({ theme }) => theme.palette.text.secondary};
277
+ font-size: 0.75rem;
278
+ line-height: 1rem;
279
+ `;
280
+ const SwitchRow = styled.div `
281
+ display: flex;
282
+ align-items: center;
283
+ justify-content: space-between;
284
+ gap: 0.75rem;
285
+ color: ${({ theme }) => theme.palette.text.secondary};
286
+ font-size: 0.75rem;
287
+ line-height: 1rem;
288
+ `;
289
+ const RailRoot = styled.div `
290
+ display: flex;
291
+ position: fixed;
292
+ top: ${({ $rect }) => `${$rect.top}px`};
293
+ left: ${({ $rect }) => `${$rect.left}px`};
294
+ z-index: 1500;
295
+ width: ${({ $rect }) => `${$rect.width}px`};
296
+ height: ${({ $rect }) => `${$rect.height}px`};
297
+
298
+ top: ${({ $rect, $kind }) => $kind === "column" ? `${$rect.top + 5}px` : `${$rect.top}px`};
299
+
300
+ left: ${({ $rect, $kind }) => $kind === "row" ? `${$rect.left + 4}px` : `${$rect.left}px`};
301
+
302
+ button {
303
+ margin: auto;
304
+ width: 100%;
305
+ height: 100%;
306
+
307
+ width: ${({ $kind }) => $kind === "column" ? "30px" : RAIL_THICKNESS + "px"};
308
+
309
+ height: ${({ $kind }) => $kind === "row" ? "30px" : RAIL_THICKNESS + "px"};
310
+
311
+ min-height: 0;
312
+ padding: 0;
313
+ border-radius: 10px;
314
+ background-color: ${({ theme }) => theme.palette.background.paper};
315
+ color: ${({ theme }) => theme.palette.text.secondary};
316
+
317
+ &:hover {
318
+ background-color: ${({ theme }) => theme.palette.primary.main};
319
+ color: white;
320
+ }
321
+ }
322
+ `;
323
+ const RailMenuPanel = styled.div `
324
+ display: flex;
325
+ flex-direction: column;
326
+ min-width: 220px;
327
+ color: ${({ theme }) => theme.palette.text.primary};
328
+ `;
329
+ const RailMenuDropdown = styled(Popover.Dropdown) `
330
+ min-width: 180px;
331
+ border-radius: 5px;
332
+ border: 1px solid ${({ theme }) => theme.palette.divider};
333
+ background-color: ${({ theme }) => theme.palette.input.background};
334
+ box-shadow: none;
335
+ padding: 5px;
336
+ `;
337
+ const RailMenuGroup = styled.div `
338
+ display: flex;
339
+ flex-direction: column;
340
+ gap: 1px;
341
+ padding-top: ${({ $withDivider }) => ($withDivider ? "5px" : 0)};
342
+ margin-top: ${({ $withDivider }) => ($withDivider ? "5px" : 0)};
343
+ border-top: ${({ $withDivider, theme }) => $withDivider ? `1px solid ${theme.palette.divider}` : 0};
344
+ `;
345
+ const RailMenuButton = styled(Button) `
346
+ min-width: 100%;
347
+ height: ${getControlSizeTokens("sm").menuRowHeight}px;
348
+ min-height: ${getControlSizeTokens("sm").menuRowHeight}px;
349
+ padding: 0 ${getControlSizeTokens("sm").menuItemPaddingX}px;
350
+ border: none;
351
+ border-radius: 3px;
352
+ color: ${({ $danger, theme }) => $danger ? theme.palette.error.main : theme.palette.text.primary};
353
+ font-weight: normal;
354
+ justify-content: flex-start;
355
+ width: 100%;
356
+
357
+ .button-label {
358
+ display: inline-block;
359
+ min-width: 0;
360
+ width: 100%;
361
+ overflow: hidden;
362
+ text-align: left;
363
+ text-overflow: ellipsis;
364
+ white-space: nowrap;
365
+ }
366
+
367
+ [data-position="left"] {
368
+ color: currentColor;
369
+ opacity: 0.8;
370
+ }
371
+
372
+ &:hover {
373
+ background-color: ${({ theme }) => theme.palette.action.hover};
374
+ color: ${({ $danger, theme }) => $danger ? theme.palette.error.main : theme.palette.text.primary};
375
+ }
376
+
377
+ &:active {
378
+ translate: none;
379
+ }
380
+
381
+ &:focus {
382
+ text-decoration: none;
383
+ }
384
+ `;
385
+ export const TableToolsContent = ({ editor, showInsert = false, onInsert, onAction, }) => {
386
+ const [insertOptions, setInsertOptions] = useState(DEFAULT_TABLE_OPTIONS);
387
+ const tableAvailable = hasTableExtension(editor) && (editor === null || editor === void 0 ? void 0 : editor.isEditable);
388
+ const updateInsertOption = (key, value) => {
389
+ setInsertOptions((current) => (Object.assign(Object.assign({}, current), { [key]: typeof value === "number" ? clampTableSize(value) : value })));
390
+ };
391
+ const insertTable = () => {
392
+ if (!tableAvailable)
393
+ return;
394
+ runTableCommand(editor, "insertTable", [insertOptions]);
395
+ onInsert === null || onInsert === void 0 ? void 0 : onInsert();
396
+ };
397
+ return (_jsx(TableToolsPanel, { children: showInsert && (_jsxs(TableToolsSection, { children: [_jsx(TableToolsSectionTitle, { description: "Create and insert a table at the current editor position.", children: "Insert Table" }), _jsxs(TableToolsSection, { style: { gap: "1rem" }, children: [_jsxs(InsertGrid, { children: [_jsxs(Field, { children: ["Rows", _jsx(Input, { type: "number", min: MIN_TABLE_SIZE, max: MAX_TABLE_SIZE, size: "xs", value: insertOptions.rows, onChange: (event) => updateInsertOption("rows", Number(event.target.value)) })] }), _jsxs(Field, { children: ["Columns", _jsx(Input, { type: "number", min: MIN_TABLE_SIZE, max: MAX_TABLE_SIZE, size: "xs", value: insertOptions.cols, onChange: (event) => updateInsertOption("cols", Number(event.target.value)) })] })] }), _jsx(SwitchRow, { children: _jsx(Switch, { size: "xs", label: "Include Header Row", description: "The first row will be formatted as a header.", value: insertOptions.withHeaderRow, onChange: (checked) => updateInsertOption("withHeaderRow", checked) }) }), _jsx(Button, { size: "xs", variant: "outlined", fullWidth: true, disabled: !tableAvailable, onClick: insertTable, children: "Insert Table" })] })] })) }));
398
+ };
399
+ export const TableToolsPopover = ({ editor }) => {
400
+ const [opened, setOpened] = useState(false);
401
+ const selected = opened || isTableActive(editor);
402
+ return (_jsxs(Popover, { opened: opened, onChange: setOpened, position: "bottom", width: 285, trapFocus: true, children: [_jsx(Popover.Target, { children: _jsx(Button, { size: "xs", variant: "outlined", title: "Table", "aria-label": "Table", selected: selected, disabled: !hasTableExtension(editor), style: { padding: "1px 6px" }, children: _jsx(Table2Icon, { size: 14 }) }) }), _jsx(Popover.Dropdown, { children: _jsx(TableToolsContent, { editor: editor, showInsert: true, onInsert: () => setOpened(false) }) })] }));
403
+ };
404
+ const RailMenu = ({ groups, onAction, }) => {
405
+ return (_jsx(RailMenuPanel, { children: groups.map((group, index) => (_jsx(RailMenuGroup, { "$withDivider": index > 0, children: group.actions.map((action) => (_jsx(RailMenuButton, { "$danger": action.danger, size: "sm", variant: "subtle", leftSection: action.leftSection, disabled: action.disabled, justify: "start", onClick: () => {
406
+ action.onClick();
407
+ onAction();
408
+ }, children: action.label }, action.label))) }, group.label))) }));
409
+ };
410
+ const getColumnActionGroups = (editor, target) => {
411
+ const risky = hasRiskyMergedCells(target);
412
+ const lastColumn = target.tableContext.map.width - 1;
413
+ return [
414
+ {
415
+ label: "Move",
416
+ actions: [
417
+ {
418
+ label: "Move column left",
419
+ leftSection: _jsx(MoveLeftIcon, { size: 14 }),
420
+ disabled: risky || target.colIndex === 0,
421
+ onClick: () => moveColumn(editor, target, -1),
422
+ },
423
+ {
424
+ label: "Move column right",
425
+ leftSection: _jsx(MoveRightIcon, { size: 14 }),
426
+ disabled: risky || target.colIndex === lastColumn,
427
+ onClick: () => moveColumn(editor, target, 1),
428
+ },
429
+ ],
430
+ },
431
+ {
432
+ label: "Insert",
433
+ actions: [
434
+ {
435
+ label: "Insert column left",
436
+ leftSection: _jsx(ArrowLeftToLineIcon, { size: 14 }),
437
+ onClick: () => insertColumnAt(editor, target, target.colIndex),
438
+ },
439
+ {
440
+ label: "Insert column right",
441
+ leftSection: _jsx(ArrowRightToLineIcon, { size: 14 }),
442
+ onClick: () => insertColumnAt(editor, target, target.colIndex + 1),
443
+ },
444
+ ],
445
+ },
446
+ {
447
+ label: "Content",
448
+ actions: [
449
+ {
450
+ label: "Clear column contents",
451
+ leftSection: _jsx(EraserIcon, { size: 14 }),
452
+ disabled: risky,
453
+ onClick: () => clearTargetContents(editor, target),
454
+ },
455
+ {
456
+ label: "Duplicate column",
457
+ leftSection: _jsx(CopyIcon, { size: 14 }),
458
+ disabled: risky,
459
+ onClick: () => duplicateColumn(editor, target),
460
+ },
461
+ ],
462
+ },
463
+ {
464
+ label: "Delete",
465
+ actions: [
466
+ {
467
+ label: "Delete column",
468
+ leftSection: _jsx(Trash2Icon, { size: 14 }),
469
+ danger: true,
470
+ disabled: risky || target.tableContext.map.width <= 1,
471
+ onClick: () => deleteColumnAt(editor, target),
472
+ },
473
+ ],
474
+ },
475
+ ];
476
+ };
477
+ const getRowActionGroups = (editor, target) => {
478
+ const risky = hasRiskyMergedCells(target);
479
+ const topRowIsHeader = getTopRowIsHeader(target);
480
+ const lastRow = target.tableContext.map.height - 1;
481
+ return [
482
+ {
483
+ label: "Header",
484
+ actions: [
485
+ {
486
+ label: topRowIsHeader ? "Unset header row" : "Set header row",
487
+ leftSection: _jsx(PanelTopIcon, { size: 14 }),
488
+ disabled: target.rowIndex !== 0,
489
+ onClick: () => toggleTopHeaderRow(editor, target),
490
+ },
491
+ ],
492
+ },
493
+ {
494
+ label: "Move",
495
+ actions: [
496
+ {
497
+ label: "Move row up",
498
+ leftSection: _jsx(MoveUpIcon, { size: 14 }),
499
+ disabled: risky ||
500
+ target.rowIndex === 0 ||
501
+ (topRowIsHeader && target.rowIndex === 1),
502
+ onClick: () => moveRow(editor, target, -1),
503
+ },
504
+ {
505
+ label: "Move row down",
506
+ leftSection: _jsx(MoveDownIcon, { size: 14 }),
507
+ disabled: risky ||
508
+ target.rowIndex === lastRow ||
509
+ (topRowIsHeader && target.rowIndex === 0),
510
+ onClick: () => moveRow(editor, target, 1),
511
+ },
512
+ ],
513
+ },
514
+ {
515
+ label: "Insert",
516
+ actions: [
517
+ {
518
+ label: "Insert row above",
519
+ leftSection: _jsx(ArrowUpToLineIcon, { size: 14 }),
520
+ disabled: topRowIsHeader && target.rowIndex === 0,
521
+ onClick: () => insertRowAt(editor, target, target.rowIndex),
522
+ },
523
+ {
524
+ label: "Insert row below",
525
+ leftSection: _jsx(ArrowDownToLineIcon, { size: 14 }),
526
+ onClick: () => insertRowAt(editor, target, target.rowIndex + 1),
527
+ },
528
+ ],
529
+ },
530
+ {
531
+ label: "Content",
532
+ actions: [
533
+ {
534
+ label: "Clear row contents",
535
+ leftSection: _jsx(EraserIcon, { size: 14 }),
536
+ disabled: risky,
537
+ onClick: () => clearTargetContents(editor, target),
538
+ },
539
+ {
540
+ label: "Duplicate row",
541
+ leftSection: _jsx(CopyIcon, { size: 14 }),
542
+ disabled: risky,
543
+ onClick: () => duplicateRow(editor, target),
544
+ },
545
+ ],
546
+ },
547
+ {
548
+ label: "Delete",
549
+ actions: [
550
+ {
551
+ label: "Delete row",
552
+ leftSection: _jsx(Trash2Icon, { size: 14 }),
553
+ danger: true,
554
+ disabled: risky || target.tableContext.map.height <= 1,
555
+ onClick: () => deleteRowAt(editor, target),
556
+ },
557
+ ],
558
+ },
559
+ ];
560
+ };
561
+ const getRailTargetFromCell = (editor, cell) => {
562
+ const tableElement = cell.closest("table");
563
+ const rowElement = cell.closest("tr");
564
+ if (!tableElement || !rowElement || !editor.view.dom.contains(tableElement)) {
565
+ return null;
566
+ }
567
+ const cellPosition = editor.view.posAtDOM(cell, 0);
568
+ const $cell = findCellPos(editor.state.doc, cellPosition);
569
+ if (!$cell)
570
+ return null;
571
+ const table = findTable($cell);
572
+ if (!table)
573
+ return null;
574
+ const map = TableMap.get(table.node);
575
+ const cellRect = map.findCell($cell.pos - table.start);
576
+ const tableRect = toRect(tableElement.getBoundingClientRect());
577
+ const rowRect = toRect(rowElement.getBoundingClientRect());
578
+ const columnRect = toRect(cell.getBoundingClientRect());
579
+ if (tableRect.width <= 0 ||
580
+ tableRect.height <= 0 ||
581
+ rowRect.width <= 0 ||
582
+ rowRect.height <= 0 ||
583
+ columnRect.width <= 0 ||
584
+ columnRect.height <= 0) {
585
+ return null;
586
+ }
587
+ return {
588
+ kind: "column",
589
+ rowIndex: cellRect.top,
590
+ colIndex: cellRect.left,
591
+ tableElement,
592
+ tableRect,
593
+ tableContext: {
594
+ node: table.node,
595
+ pos: table.pos,
596
+ start: table.start,
597
+ map,
598
+ },
599
+ rowRect,
600
+ columnRect,
601
+ };
602
+ };
603
+ const getRailRect = (target, kind) => {
604
+ if (kind === "column") {
605
+ const width = target.columnRect.width;
606
+ const left = clamp(target.columnRect.left, VIEWPORT_PADDING, Math.max(VIEWPORT_PADDING, window.innerWidth - width - VIEWPORT_PADDING));
607
+ return {
608
+ top: Math.max(VIEWPORT_PADDING, target.tableRect.top - RAIL_THICKNESS),
609
+ left,
610
+ width,
611
+ height: RAIL_THICKNESS,
612
+ };
613
+ }
614
+ const height = target.rowRect.height;
615
+ const top = clamp(target.rowRect.top, VIEWPORT_PADDING, Math.max(VIEWPORT_PADDING, window.innerHeight - height - VIEWPORT_PADDING));
616
+ return {
617
+ top,
618
+ left: Math.max(VIEWPORT_PADDING, target.rowRect.left - RAIL_THICKNESS),
619
+ width: RAIL_THICKNESS,
620
+ height,
621
+ };
622
+ };
623
+ export const TableRails = ({ editor }) => {
624
+ const [hoverTarget, setHoverTarget] = useState(null);
625
+ const [lockedTarget, setLockedTarget] = useState(null);
626
+ const [openRail, setOpenRail] = useState(null);
627
+ const hideTimerRef = useRef(null);
628
+ const lastPointerRef = useRef(null);
629
+ const activeTarget = openRail && lockedTarget ? lockedTarget : hoverTarget;
630
+ const clearHideTimer = useCallback(() => {
631
+ if (hideTimerRef.current) {
632
+ clearTimeout(hideTimerRef.current);
633
+ hideTimerRef.current = null;
634
+ }
635
+ }, []);
636
+ const clearTarget = useCallback(() => {
637
+ var _a;
638
+ clearHideTimer();
639
+ if (!openRail) {
640
+ const pointer = lastPointerRef.current;
641
+ const element = pointer
642
+ ? document.elementFromPoint(pointer.x, pointer.y)
643
+ : null;
644
+ if ((_a = element === null || element === void 0 ? void 0 : element.closest) === null || _a === void 0 ? void 0 : _a.call(element, "[data-monolith-table-rail]")) {
645
+ return;
646
+ }
647
+ setHoverTarget(null);
648
+ }
649
+ }, [clearHideTimer, openRail]);
650
+ const scheduleClearTarget = useCallback(() => {
651
+ clearHideTimer();
652
+ hideTimerRef.current = setTimeout(clearTarget, RAIL_HIDE_DELAY);
653
+ }, [clearHideTimer, clearTarget]);
654
+ const refreshTargetFromPoint = useCallback(() => {
655
+ var _a, _b;
656
+ if (!editor || !lastPointerRef.current) {
657
+ setHoverTarget(null);
658
+ return;
659
+ }
660
+ const element = document.elementFromPoint(lastPointerRef.current.x, lastPointerRef.current.y);
661
+ if ((_a = element === null || element === void 0 ? void 0 : element.closest) === null || _a === void 0 ? void 0 : _a.call(element, "[data-monolith-table-rail]")) {
662
+ return;
663
+ }
664
+ const cell = (_b = element === null || element === void 0 ? void 0 : element.closest) === null || _b === void 0 ? void 0 : _b.call(element, "td, th");
665
+ if (cell instanceof HTMLTableCellElement &&
666
+ editor.view.dom.contains(cell)) {
667
+ const target = getRailTargetFromCell(editor, cell);
668
+ setHoverTarget(target);
669
+ return;
670
+ }
671
+ setHoverTarget(null);
672
+ }, [editor]);
673
+ const closeMenu = useCallback(() => {
674
+ setOpenRail(null);
675
+ setLockedTarget(null);
676
+ requestAnimationFrame(refreshTargetFromPoint);
677
+ }, [refreshTargetFromPoint]);
678
+ useEffect(() => {
679
+ if (!editor || !hasTableExtension(editor))
680
+ return;
681
+ const handleMouseMove = (event) => {
682
+ var _a, _b;
683
+ const target = event.target;
684
+ const cell = (_a = target === null || target === void 0 ? void 0 : target.closest) === null || _a === void 0 ? void 0 : _a.call(target, "td, th");
685
+ lastPointerRef.current = { x: event.clientX, y: event.clientY };
686
+ if ((_b = target === null || target === void 0 ? void 0 : target.closest) === null || _b === void 0 ? void 0 : _b.call(target, "[data-monolith-table-rail]")) {
687
+ clearHideTimer();
688
+ return;
689
+ }
690
+ if (openRail) {
691
+ clearHideTimer();
692
+ return;
693
+ }
694
+ if (!(cell instanceof HTMLTableCellElement) ||
695
+ !editor.view.dom.contains(cell)) {
696
+ if (!openRail) {
697
+ scheduleClearTarget();
698
+ }
699
+ return;
700
+ }
701
+ const railTarget = getRailTargetFromCell(editor, cell);
702
+ if (railTarget) {
703
+ clearHideTimer();
704
+ setHoverTarget(railTarget);
705
+ }
706
+ };
707
+ const handleMouseLeave = () => {
708
+ if (!openRail) {
709
+ scheduleClearTarget();
710
+ }
711
+ };
712
+ editor.view.dom.addEventListener("mousemove", handleMouseMove);
713
+ editor.view.dom.addEventListener("mouseleave", handleMouseLeave);
714
+ window.addEventListener("mousemove", handleMouseMove);
715
+ window.addEventListener("scroll", refreshTargetFromPoint, true);
716
+ window.addEventListener("resize", refreshTargetFromPoint);
717
+ return () => {
718
+ editor.view.dom.removeEventListener("mousemove", handleMouseMove);
719
+ editor.view.dom.removeEventListener("mouseleave", handleMouseLeave);
720
+ window.removeEventListener("mousemove", handleMouseMove);
721
+ window.removeEventListener("scroll", refreshTargetFromPoint, true);
722
+ window.removeEventListener("resize", refreshTargetFromPoint);
723
+ clearHideTimer();
724
+ };
725
+ }, [
726
+ clearHideTimer,
727
+ editor,
728
+ openRail,
729
+ refreshTargetFromPoint,
730
+ scheduleClearTarget,
731
+ ]);
732
+ useEffect(() => {
733
+ const highlighted = Array.from(document.querySelectorAll(".monolith-table-rail-target"));
734
+ highlighted.forEach((element) => element.classList.remove("monolith-table-rail-target"));
735
+ if (!activeTarget || !openRail)
736
+ return;
737
+ const cells = openRail === "table"
738
+ ? getCellsInTableTarget(activeTarget)
739
+ : getCellsInTarget(Object.assign(Object.assign({}, activeTarget), { kind: openRail }));
740
+ cells.forEach((cell) => {
741
+ const dom = editor === null || editor === void 0 ? void 0 : editor.view.nodeDOM(activeTarget.tableContext.start + cell.pos);
742
+ if (dom instanceof HTMLElement) {
743
+ dom.classList.add("monolith-table-rail-target");
744
+ }
745
+ });
746
+ return () => {
747
+ cells.forEach((cell) => {
748
+ const dom = editor === null || editor === void 0 ? void 0 : editor.view.nodeDOM(activeTarget.tableContext.start + cell.pos);
749
+ if (dom instanceof HTMLElement) {
750
+ dom.classList.remove("monolith-table-rail-target");
751
+ }
752
+ });
753
+ };
754
+ }, [activeTarget, editor, openRail]);
755
+ const keepEditorSelection = (event) => {
756
+ event.preventDefault();
757
+ };
758
+ if (!activeTarget || !(editor === null || editor === void 0 ? void 0 : editor.isEditable))
759
+ return null;
760
+ const keepTargetVisible = () => {
761
+ clearHideTimer();
762
+ };
763
+ const scheduleTargetClearIfClosed = () => {
764
+ if (!openRail) {
765
+ scheduleClearTarget();
766
+ }
767
+ };
768
+ const renderRail = (kind) => {
769
+ const railTarget = Object.assign(Object.assign({}, activeTarget), { kind });
770
+ const groups = kind === "column"
771
+ ? getColumnActionGroups(editor, railTarget)
772
+ : getRowActionGroups(editor, railTarget);
773
+ return (_jsx(RailRoot, { "data-monolith-table-rail": true, "$kind": kind, "$rect": getRailRect(activeTarget, kind), onMouseEnter: keepTargetVisible, onMouseLeave: scheduleTargetClearIfClosed, children: _jsxs(Popover, { opened: openRail === kind, onChange: (opened) => {
774
+ if (opened) {
775
+ clearHideTimer();
776
+ setLockedTarget(railTarget);
777
+ setOpenRail(kind);
778
+ return;
779
+ }
780
+ setOpenRail(null);
781
+ setLockedTarget(null);
782
+ refreshTargetFromPoint();
783
+ }, position: kind === "column" ? "bottom" : "right", width: 245, trapFocus: true, children: [_jsx(Popover.Target, { children: _jsx(Button, { type: "button", size: "xs", variant: "outlined", title: kind === "column" ? "Column options" : "Row options", "aria-label": kind === "column" ? "Column options" : "Row options", selected: openRail === kind, onMouseDown: keepEditorSelection, children: kind === "column" ? (_jsx(MoreHorizontalIcon, { size: 14 })) : (_jsx(MoreVerticalIcon, { size: 14 })) }) }), _jsx(RailMenuDropdown, { children: _jsx(RailMenu, { groups: groups, onAction: closeMenu }) })] }) }, kind));
784
+ };
785
+ return (_jsxs(_Fragment, { children: [_jsx(TableCornerMenu, { editor: editor, target: activeTarget, opened: openRail === "table", onOpen: () => {
786
+ clearHideTimer();
787
+ setLockedTarget(activeTarget);
788
+ setOpenRail("table");
789
+ }, onClose: closeMenu, onAction: closeMenu, onMouseEnter: keepTargetVisible, onMouseLeave: scheduleTargetClearIfClosed, onMouseDown: keepEditorSelection }), renderRail("column"), renderRail("row")] }));
790
+ };