@ctzhian/tiptap 1.13.9 → 2.0.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 (47) hide show
  1. package/dist/Editor/demo.js +1 -1
  2. package/dist/Editor/index.js +17 -0
  3. package/dist/component/CustomBubbleMenu/index.js +1 -1
  4. package/dist/component/CustomDragHandle/index.js +3 -59
  5. package/dist/component/Icons/delete-back-2-line-icon.d.ts +6 -0
  6. package/dist/component/Icons/delete-back-2-line-icon.js +13 -0
  7. package/dist/component/Menu/index.js +5 -1
  8. package/dist/contants/enums.d.ts +9 -0
  9. package/dist/contants/enums.js +61 -1
  10. package/dist/extension/component/TableCellHandleMenu/index.d.ts +9 -0
  11. package/dist/extension/component/TableCellHandleMenu/index.js +443 -0
  12. package/dist/extension/component/TableExtendButton/TableExtendButton.css +30 -0
  13. package/dist/extension/component/TableExtendButton/index.d.ts +23 -0
  14. package/dist/extension/component/TableExtendButton/index.js +201 -0
  15. package/dist/extension/component/TableExtendButton/use-table-extend-row-column.d.ts +15 -0
  16. package/dist/extension/component/TableExtendButton/use-table-extend-row-column.js +87 -0
  17. package/dist/extension/component/TableHandle/TableHandleMenu.css +36 -0
  18. package/dist/extension/component/TableHandle/TableHandleMenu.d.ts +17 -0
  19. package/dist/extension/component/TableHandle/TableHandleMenu.js +685 -0
  20. package/dist/extension/component/TableHandle/index.d.ts +28 -0
  21. package/dist/extension/component/TableHandle/index.js +93 -0
  22. package/dist/extension/component/TableHandle/use-table-handle-positioning.d.ts +40 -0
  23. package/dist/extension/component/TableHandle/use-table-handle-positioning.js +193 -0
  24. package/dist/extension/component/TableHandle/use-table-handle-state.d.ts +22 -0
  25. package/dist/extension/component/TableHandle/use-table-handle-state.js +45 -0
  26. package/dist/extension/component/TableSelectionOverlay/index.d.ts +16 -0
  27. package/dist/extension/component/TableSelectionOverlay/index.js +460 -0
  28. package/dist/extension/component/UploadProgress/index.d.ts +1 -1
  29. package/dist/extension/node/FileHandler.d.ts +1 -1
  30. package/dist/extension/node/Table.js +226 -43
  31. package/dist/extension/node/TableHandler/create-image.d.ts +9 -0
  32. package/dist/extension/node/TableHandler/create-image.js +235 -0
  33. package/dist/extension/node/TableHandler/index.d.ts +15 -0
  34. package/dist/extension/node/TableHandler/index.js +33 -0
  35. package/dist/extension/node/TableHandler/plugin.d.ts +49 -0
  36. package/dist/extension/node/TableHandler/plugin.js +1030 -0
  37. package/dist/index.css +29 -10
  38. package/dist/type/index.d.ts +2 -0
  39. package/dist/util/table-utils.d.ts +161 -0
  40. package/dist/util/table-utils.js +605 -0
  41. package/package.json +2 -1
  42. package/dist/extension/component/Table/ContextMenu.d.ts +0 -11
  43. package/dist/extension/component/Table/ContextMenu.js +0 -186
  44. package/dist/extension/component/Table/TableContextMenuPlugin.d.ts +0 -9
  45. package/dist/extension/component/Table/TableContextMenuPlugin.js +0 -336
  46. package/dist/extension/component/Table/index.d.ts +0 -2
  47. package/dist/extension/component/Table/index.js +0 -2
@@ -0,0 +1,685 @@
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function (_e) { function e(_x) { return _e.apply(this, arguments); } e.toString = function () { return _e.toString(); }; return e; }(function (e) { throw e; }), f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function (_e2) { function e(_x2) { return _e2.apply(this, arguments); } e.toString = function () { return _e2.toString(); }; return e; }(function (e) { didErr = true; err = e; }), f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
3
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
6
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
7
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
8
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
9
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
10
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
11
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
12
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
13
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
14
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
15
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
16
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
17
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
18
+ import { AlignBottomIcon, AlignCenterIcon, AlignJustifyIcon, AlignLeftIcon, AlignRightIcon, AlignTopIcon, ArrowDownSLineIcon, BrushLineIcon, DeleteColumnIcon, DeleteRowIcon, FileCopyLineIcon, InsertColumnLeftIcon, InsertColumnRightIcon, InsertRowBottomIcon, InsertRowTopIcon, LayoutLeft2LineIcon, LayoutTop2LineIcon } from "../../../component/Icons";
19
+ import { DeleteBack2LineIcon } from "../../../component/Icons/delete-back-2-line-icon";
20
+ import { getThemeTextBgColor, getThemeTextColor } from "../../../contants/enums";
21
+ import { Box, Divider, Typography, useTheme } from '@mui/material';
22
+ import { addColumnAfter, addRowAfter, CellSelection, deleteCellSelection, TableMap } from '@tiptap/pm/tables';
23
+ import React, { useCallback, useEffect, useMemo, useState } from 'react';
24
+ import { MoreLineIcon } from "../../../component/Icons/more-line-icon";
25
+ import Menu from "../../../component/Menu";
26
+ import { getColumnCells, getIndexCoordinates, getRowCells, getTable, selectCellsByCoords } from "../../../util/table-utils";
27
+ import { dragEnd } from "../../node/TableHandler/plugin";
28
+ import "./TableHandleMenu.css";
29
+ export var TableHandleMenu = function TableHandleMenu(_ref) {
30
+ var editor = _ref.editor,
31
+ orientation = _ref.orientation,
32
+ index = _ref.index,
33
+ tableNode = _ref.tableNode,
34
+ tablePos = _ref.tablePos,
35
+ onToggleOtherHandle = _ref.onToggleOtherHandle,
36
+ onOpenChange = _ref.onOpenChange,
37
+ dragStart = _ref.dragStart;
38
+ var theme = useTheme();
39
+ var _useState = useState(false),
40
+ _useState2 = _slicedToArray(_useState, 2),
41
+ isDragging = _useState2[0],
42
+ setIsDragging = _useState2[1];
43
+ var selectRowOrColumn = useCallback(function () {
44
+ if (!editor || !tableNode || typeof tablePos !== 'number' || typeof index !== 'number') return;
45
+ try {
46
+ var _TableMap$get = TableMap.get(tableNode),
47
+ width = _TableMap$get.width,
48
+ height = _TableMap$get.height;
49
+ var start = orientation === 'row' ? {
50
+ row: index,
51
+ col: 0
52
+ } : {
53
+ row: 0,
54
+ col: index
55
+ };
56
+ var end = orientation === 'row' ? {
57
+ row: index,
58
+ col: width - 1
59
+ } : {
60
+ row: height - 1,
61
+ col: index
62
+ };
63
+ selectCellsByCoords(editor, tablePos, [start, end], {
64
+ mode: 'dispatch',
65
+ dispatch: editor.view.dispatch.bind(editor.view)
66
+ });
67
+ } catch (error) {
68
+ console.warn('Failed to select row/column:', error);
69
+ }
70
+ }, [editor, tableNode, tablePos, orientation, index]);
71
+ var canDuplicate = useMemo(function () {
72
+ if (!editor || typeof index !== 'number' || typeof tablePos !== 'number') {
73
+ return false;
74
+ }
75
+ try {
76
+ var cells = orientation === 'row' ? getRowCells(editor, index, tablePos) : getColumnCells(editor, index, tablePos);
77
+ return cells.cells.length > 0 && cells.mergedCells.length === 0;
78
+ } catch (_unused) {
79
+ return false;
80
+ }
81
+ }, [editor, index, orientation, tablePos, tableNode, editor === null || editor === void 0 ? void 0 : editor.state.doc]);
82
+ var duplicateRowOrColumn = useCallback(function () {
83
+ if (!editor || typeof index !== 'number' || typeof tablePos !== 'number' || !canDuplicate) {
84
+ return;
85
+ }
86
+ try {
87
+ var originalCells = orientation === 'row' ? getRowCells(editor, index, tablePos) : getColumnCells(editor, index, tablePos);
88
+ if (originalCells.cells.length === 0) return;
89
+ selectRowOrColumn();
90
+ var addSuccess = false;
91
+ if (editor.state.selection instanceof CellSelection) {
92
+ addSuccess = orientation === 'row' ? editor.chain().focus().addRowAfter().run() : editor.chain().focus().addColumnAfter().run();
93
+ } else {
94
+ var sourceCoords = getIndexCoordinates({
95
+ editor: editor,
96
+ index: index,
97
+ orientation: orientation,
98
+ tablePos: tablePos
99
+ });
100
+ if (!sourceCoords) return;
101
+ var stateWithCellSel = selectCellsByCoords(editor, tablePos, sourceCoords, {
102
+ mode: 'state'
103
+ });
104
+ if (!stateWithCellSel) return;
105
+ var dispatch = function dispatch(tr) {
106
+ return editor.view.dispatch(tr);
107
+ };
108
+ if (orientation === 'row') {
109
+ addSuccess = addRowAfter(stateWithCellSel, dispatch);
110
+ } else {
111
+ addSuccess = addColumnAfter(stateWithCellSel, dispatch);
112
+ }
113
+ }
114
+ if (!addSuccess) return;
115
+ var updatedTable = getTable(editor, tablePos);
116
+ if (!updatedTable) return;
117
+ var newCells = orientation === 'row' ? getRowCells(editor, index + 1, updatedTable.pos) : getColumnCells(editor, index + 1, updatedTable.pos);
118
+ if (newCells.cells.length === 0) return;
119
+ var state = editor.state,
120
+ view = editor.view;
121
+ var tr = state.tr;
122
+ var cellsToReplace = _toConsumableArray(newCells.cells).reverse();
123
+ var originalCellsReversed = _toConsumableArray(originalCells.cells).reverse();
124
+ cellsToReplace.forEach(function (newCell, reverseIndex) {
125
+ var originalCell = originalCellsReversed[reverseIndex];
126
+ if (newCell.node && originalCell !== null && originalCell !== void 0 && originalCell.node) {
127
+ var duplicatedCell = newCell.node.type.create(_objectSpread({}, originalCell.node.attrs), originalCell.node.content, originalCell.node.marks);
128
+ var cellEnd = newCell.pos + newCell.node.nodeSize;
129
+ tr.replaceWith(newCell.pos, cellEnd, duplicatedCell);
130
+ }
131
+ });
132
+ if (tr.docChanged) {
133
+ view.dispatch(tr);
134
+ }
135
+ } catch (error) {
136
+ console.error('Error duplicating row/column:', error);
137
+ }
138
+ }, [editor, index, orientation, tablePos, canDuplicate, selectRowOrColumn]);
139
+ var _useState3 = useState(false),
140
+ _useState4 = _slicedToArray(_useState3, 2),
141
+ isHeader = _useState4[0],
142
+ setIsHeader = _useState4[1];
143
+ useEffect(function () {
144
+ if (!editor || typeof index !== 'number' || typeof tablePos !== 'number') {
145
+ setIsHeader(false);
146
+ return;
147
+ }
148
+ try {
149
+ var cells = orientation === 'row' ? getRowCells(editor, index, tablePos) : getColumnCells(editor, index, tablePos);
150
+ if (cells.cells.length === 0) {
151
+ setIsHeader(false);
152
+ return;
153
+ }
154
+ var allHeaders = cells.cells.every(function (cell) {
155
+ var _cell$node;
156
+ return (cell === null || cell === void 0 || (_cell$node = cell.node) === null || _cell$node === void 0 ? void 0 : _cell$node.type.name) === 'tableHeader';
157
+ });
158
+ setIsHeader(allHeaders);
159
+ } catch (_unused2) {
160
+ setIsHeader(false);
161
+ }
162
+ }, [editor, index, orientation, tablePos, tableNode, editor === null || editor === void 0 ? void 0 : editor.state.doc, editor === null || editor === void 0 ? void 0 : editor.state.selection]);
163
+ var isFirstRowOrColumn = typeof index === 'number' && index === 0;
164
+ var menuList = useMemo(function () {
165
+ if (!editor) return [];
166
+ var menuItems = [];
167
+ if (isFirstRowOrColumn) {
168
+ menuItems.push({
169
+ key: 'toggle-header',
170
+ label: isHeader ? orientation === 'row' ? '取消行表头' : '取消列表头' : orientation === 'row' ? '切换行表头' : '切换列表头',
171
+ icon: isHeader ? /*#__PURE__*/React.createElement(LayoutLeft2LineIcon, {
172
+ sx: {
173
+ fontSize: '1rem'
174
+ }
175
+ }) : /*#__PURE__*/React.createElement(LayoutTop2LineIcon, {
176
+ sx: {
177
+ fontSize: '1rem'
178
+ }
179
+ }),
180
+ onClick: function onClick() {
181
+ selectRowOrColumn();
182
+ if (orientation === 'row') {
183
+ editor.chain().focus().toggleHeaderRow().run();
184
+ } else {
185
+ editor.chain().focus().toggleHeaderColumn().run();
186
+ }
187
+ }
188
+ }, {
189
+ customLabel: /*#__PURE__*/React.createElement(Divider, {
190
+ sx: {
191
+ my: 0.5
192
+ }
193
+ }),
194
+ key: 'divider2'
195
+ });
196
+ }
197
+ menuItems.push({
198
+ key: 'add-before',
199
+ label: orientation === 'row' ? '上方插入行' : '左侧插入列',
200
+ icon: orientation === 'row' ? /*#__PURE__*/React.createElement(InsertRowTopIcon, {
201
+ sx: {
202
+ fontSize: '1rem'
203
+ }
204
+ }) : /*#__PURE__*/React.createElement(InsertColumnLeftIcon, {
205
+ sx: {
206
+ fontSize: '1rem'
207
+ }
208
+ }),
209
+ onClick: function onClick() {
210
+ if (orientation === 'row') {
211
+ editor.chain().focus().addRowBefore().run();
212
+ } else {
213
+ editor.chain().focus().addColumnBefore().run();
214
+ }
215
+ }
216
+ }, {
217
+ key: 'add-after',
218
+ label: orientation === 'row' ? '下方插入行' : '右侧插入列',
219
+ icon: orientation === 'row' ? /*#__PURE__*/React.createElement(InsertRowBottomIcon, {
220
+ sx: {
221
+ fontSize: '1rem'
222
+ }
223
+ }) : /*#__PURE__*/React.createElement(InsertColumnRightIcon, {
224
+ sx: {
225
+ fontSize: '1rem'
226
+ }
227
+ }),
228
+ onClick: function onClick() {
229
+ if (orientation === 'row') {
230
+ editor.chain().focus().addRowAfter().run();
231
+ } else {
232
+ editor.chain().focus().addColumnAfter().run();
233
+ }
234
+ }
235
+ }, {
236
+ customLabel: /*#__PURE__*/React.createElement(Divider, {
237
+ sx: {
238
+ my: 0.5
239
+ }
240
+ }),
241
+ key: 'divider1'
242
+ }, {
243
+ key: 'color',
244
+ label: '颜色',
245
+ icon: /*#__PURE__*/React.createElement(BrushLineIcon, {
246
+ sx: {
247
+ fontSize: '1rem'
248
+ }
249
+ }),
250
+ children: [{
251
+ customLabel: /*#__PURE__*/React.createElement(Typography, {
252
+ sx: {
253
+ p: 1,
254
+ fontSize: '0.75rem',
255
+ color: 'text.secondary',
256
+ fontWeight: 'bold'
257
+ }
258
+ }, "\u6587\u5B57\u989C\u8272"),
259
+ key: 'text-color'
260
+ }].concat(_toConsumableArray(getThemeTextColor(theme).map(function (it) {
261
+ return {
262
+ label: it.label,
263
+ key: it.value,
264
+ icon: /*#__PURE__*/React.createElement(Box, {
265
+ sx: {
266
+ color: it.value,
267
+ width: '1rem',
268
+ height: '1rem',
269
+ borderRadius: '50%',
270
+ bgcolor: it.value,
271
+ border: '1px solid',
272
+ borderColor: it.value === theme.palette.common.white ? 'divider' : 'transparent'
273
+ }
274
+ }),
275
+ onClick: function onClick() {
276
+ if (!editor) return;
277
+ selectRowOrColumn();
278
+ setTimeout(function () {
279
+ editor.chain().focus().toggleMark('textStyle', {
280
+ color: it.value
281
+ }).run();
282
+ }, 0);
283
+ }
284
+ };
285
+ })), [{
286
+ customLabel: /*#__PURE__*/React.createElement(Typography, {
287
+ sx: {
288
+ p: 1,
289
+ fontSize: '0.75rem',
290
+ color: 'text.secondary',
291
+ fontWeight: 'bold'
292
+ }
293
+ }, "\u80CC\u666F\u989C\u8272"),
294
+ key: 'background-color'
295
+ }], _toConsumableArray(getThemeTextBgColor(theme).map(function (it) {
296
+ return {
297
+ label: it.label,
298
+ key: it.value,
299
+ icon: /*#__PURE__*/React.createElement(Box, {
300
+ sx: {
301
+ width: '1rem',
302
+ height: '1rem',
303
+ borderRadius: '50%',
304
+ bgcolor: it.value,
305
+ border: '1px solid',
306
+ borderColor: 'divider'
307
+ }
308
+ }),
309
+ onClick: function onClick() {
310
+ if (!editor) return;
311
+ selectRowOrColumn();
312
+ setTimeout(function () {
313
+ var bgColor = it.value === 'transparent' || it.value === 'var(--mui-palette-background-paper)' ? 'transparent' : it.value;
314
+ editor.chain().focus().setCellAttribute('bgcolor', bgColor).run();
315
+ }, 0);
316
+ }
317
+ };
318
+ })))
319
+ }, {
320
+ key: 'align',
321
+ label: '对齐方式',
322
+ icon: /*#__PURE__*/React.createElement(AlignLeftIcon, {
323
+ sx: {
324
+ fontSize: '1rem'
325
+ }
326
+ }),
327
+ children: [{
328
+ customLabel: /*#__PURE__*/React.createElement(Typography, {
329
+ sx: {
330
+ p: 1,
331
+ fontSize: '0.75rem',
332
+ color: 'text.secondary',
333
+ fontWeight: 'bold'
334
+ }
335
+ }, "\u6C34\u5E73\u5BF9\u9F50\u65B9\u5F0F"),
336
+ key: 'align-horizontal'
337
+ }, {
338
+ label: '左侧对齐',
339
+ key: 'align-horizontal-left',
340
+ icon: /*#__PURE__*/React.createElement(AlignLeftIcon, {
341
+ sx: {
342
+ fontSize: '1rem'
343
+ }
344
+ }),
345
+ onClick: function onClick() {
346
+ if (!editor) return;
347
+ selectRowOrColumn();
348
+ setTimeout(function () {
349
+ editor.chain().focus().setCellAttribute('textAlign', 'left').run();
350
+ }, 0);
351
+ }
352
+ }, {
353
+ label: '居中对齐',
354
+ key: 'align-horizontal-center',
355
+ icon: /*#__PURE__*/React.createElement(AlignCenterIcon, {
356
+ sx: {
357
+ fontSize: '1rem'
358
+ }
359
+ }),
360
+ onClick: function onClick() {
361
+ if (!editor) return;
362
+ selectRowOrColumn();
363
+ setTimeout(function () {
364
+ editor.chain().focus().setCellAttribute('textAlign', 'center').run();
365
+ }, 0);
366
+ }
367
+ }, {
368
+ label: '右侧对齐',
369
+ key: 'align-horizontal-right',
370
+ icon: /*#__PURE__*/React.createElement(AlignRightIcon, {
371
+ sx: {
372
+ fontSize: '1rem'
373
+ }
374
+ }),
375
+ onClick: function onClick() {
376
+ if (!editor) return;
377
+ selectRowOrColumn();
378
+ setTimeout(function () {
379
+ editor.chain().focus().setCellAttribute('textAlign', 'right').run();
380
+ }, 0);
381
+ }
382
+ }, {
383
+ label: '两端对齐',
384
+ key: 'align-horizontal-justify',
385
+ icon: /*#__PURE__*/React.createElement(AlignJustifyIcon, {
386
+ sx: {
387
+ fontSize: '1rem'
388
+ }
389
+ }),
390
+ onClick: function onClick() {
391
+ if (!editor) return;
392
+ selectRowOrColumn();
393
+ setTimeout(function () {
394
+ editor.chain().focus().setCellAttribute('textAlign', 'justify').run();
395
+ }, 0);
396
+ }
397
+ }, {
398
+ customLabel: /*#__PURE__*/React.createElement(Typography, {
399
+ sx: {
400
+ p: 1,
401
+ fontSize: '0.75rem',
402
+ color: 'text.secondary',
403
+ fontWeight: 'bold'
404
+ }
405
+ }, "\u5782\u76F4\u5BF9\u9F50\u65B9\u5F0F"),
406
+ key: 'align-vertical'
407
+ }, {
408
+ label: '顶部对齐',
409
+ key: 'align-vertical-top',
410
+ icon: /*#__PURE__*/React.createElement(AlignTopIcon, {
411
+ sx: {
412
+ fontSize: '1rem'
413
+ }
414
+ }),
415
+ onClick: function onClick() {
416
+ if (!editor) return;
417
+ selectRowOrColumn();
418
+ setTimeout(function () {
419
+ editor.chain().focus().setCellAttribute('verticalAlign', 'top').run();
420
+ }, 0);
421
+ }
422
+ }, {
423
+ label: '居中对齐',
424
+ key: 'align-vertical-center',
425
+ icon: /*#__PURE__*/React.createElement(AlignCenterIcon, {
426
+ sx: {
427
+ fontSize: '1rem'
428
+ }
429
+ }),
430
+ onClick: function onClick() {
431
+ if (!editor) return;
432
+ selectRowOrColumn();
433
+ setTimeout(function () {
434
+ editor.chain().focus().setCellAttribute('verticalAlign', 'middle').run();
435
+ }, 0);
436
+ }
437
+ }, {
438
+ label: '底部对齐',
439
+ key: 'align-vertical-bottom',
440
+ icon: /*#__PURE__*/React.createElement(AlignBottomIcon, {
441
+ sx: {
442
+ fontSize: '1rem'
443
+ }
444
+ }),
445
+ onClick: function onClick() {
446
+ if (!editor) return;
447
+ selectRowOrColumn();
448
+ setTimeout(function () {
449
+ editor.chain().focus().setCellAttribute('verticalAlign', 'bottom').run();
450
+ }, 0);
451
+ }
452
+ }]
453
+ }, {
454
+ key: 'clear-content',
455
+ label: orientation === 'row' ? '清空当前行内容' : '清空当前列内容',
456
+ icon: /*#__PURE__*/React.createElement(DeleteBack2LineIcon, {
457
+ sx: {
458
+ fontSize: '1rem'
459
+ }
460
+ }),
461
+ onClick: function onClick() {
462
+ if (!editor || typeof index !== 'number' || typeof tablePos !== 'number' || !tableNode) return;
463
+ var state = editor.state,
464
+ view = editor.view;
465
+ try {
466
+ var _TableMap$get2 = TableMap.get(tableNode),
467
+ width = _TableMap$get2.width,
468
+ height = _TableMap$get2.height;
469
+ var start = orientation === 'row' ? {
470
+ row: index,
471
+ col: 0
472
+ } : {
473
+ row: 0,
474
+ col: index
475
+ };
476
+ var end = orientation === 'row' ? {
477
+ row: index,
478
+ col: width - 1
479
+ } : {
480
+ row: height - 1,
481
+ col: index
482
+ };
483
+ var stateWithSelection = selectCellsByCoords(editor, tablePos, [start, end], {
484
+ mode: 'state'
485
+ });
486
+ if (stateWithSelection && stateWithSelection.selection instanceof CellSelection) {
487
+ deleteCellSelection(stateWithSelection, view.dispatch.bind(view));
488
+ }
489
+ } catch (error) {
490
+ console.warn('Failed to clear row/column content:', error);
491
+ }
492
+ },
493
+ attrs: function () {
494
+ if (!editor || typeof index !== 'number' || typeof tablePos !== 'number') {
495
+ return {
496
+ disabled: true
497
+ };
498
+ }
499
+ try {
500
+ var cells = orientation === 'row' ? getRowCells(editor, index, tablePos) : getColumnCells(editor, index, tablePos);
501
+ if (cells.cells.length === 0) {
502
+ return {
503
+ disabled: true
504
+ };
505
+ }
506
+ var hasContent = false;
507
+ var _iterator = _createForOfIteratorHelper(cells.cells),
508
+ _step;
509
+ try {
510
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
511
+ var cell = _step.value;
512
+ if (cell.node && cell.node.content.size > 0) {
513
+ hasContent = true;
514
+ break;
515
+ }
516
+ }
517
+ } catch (err) {
518
+ _iterator.e(err);
519
+ } finally {
520
+ _iterator.f();
521
+ }
522
+ return hasContent ? {} : {
523
+ disabled: true
524
+ };
525
+ } catch (_unused3) {
526
+ return {
527
+ disabled: true
528
+ };
529
+ }
530
+ }()
531
+ }, {
532
+ customLabel: /*#__PURE__*/React.createElement(Divider, {
533
+ sx: {
534
+ my: 0.5
535
+ }
536
+ }),
537
+ key: 'divider2'
538
+ }, {
539
+ key: 'duplicate',
540
+ label: orientation === 'row' ? '复制当前行' : '复制当前列',
541
+ icon: /*#__PURE__*/React.createElement(FileCopyLineIcon, {
542
+ sx: {
543
+ fontSize: '1rem'
544
+ }
545
+ }),
546
+ onClick: duplicateRowOrColumn,
547
+ attrs: canDuplicate ? {} : {
548
+ disabled: true
549
+ }
550
+ }, {
551
+ key: 'delete',
552
+ label: orientation === 'row' ? '删除当前行' : '删除当前列',
553
+ icon: orientation === 'row' ? /*#__PURE__*/React.createElement(DeleteRowIcon, {
554
+ sx: {
555
+ fontSize: '1rem'
556
+ }
557
+ }) : /*#__PURE__*/React.createElement(DeleteColumnIcon, {
558
+ sx: {
559
+ fontSize: '1rem'
560
+ }
561
+ }),
562
+ onClick: function onClick() {
563
+ if (orientation === 'row') {
564
+ editor.chain().focus().deleteRow().run();
565
+ } else {
566
+ editor.chain().focus().deleteColumn().run();
567
+ }
568
+ }
569
+ });
570
+ return menuItems;
571
+ }, [editor, orientation, isFirstRowOrColumn, isHeader, selectRowOrColumn, canDuplicate, duplicateRowOrColumn]);
572
+ var handleMenuOpen = useCallback(function () {
573
+ if (!editor) return;
574
+ editor.commands.freezeHandles();
575
+ selectRowOrColumn();
576
+ onToggleOtherHandle === null || onToggleOtherHandle === void 0 || onToggleOtherHandle(false);
577
+ onOpenChange === null || onOpenChange === void 0 || onOpenChange(true);
578
+ if (typeof index === 'number' && typeof tablePos === 'number') {
579
+ try {
580
+ var cells = orientation === 'row' ? getRowCells(editor, index, tablePos) : getColumnCells(editor, index, tablePos);
581
+ if (cells.cells.length > 0) {
582
+ var allHeaders = cells.cells.every(function (cell) {
583
+ var _cell$node2;
584
+ return (cell === null || cell === void 0 || (_cell$node2 = cell.node) === null || _cell$node2 === void 0 ? void 0 : _cell$node2.type.name) === 'tableHeader';
585
+ });
586
+ setIsHeader(allHeaders);
587
+ }
588
+ } catch (_unused4) {}
589
+ }
590
+ }, [editor, onOpenChange, onToggleOtherHandle, selectRowOrColumn, index, orientation, tablePos]);
591
+ var handleMenuClose = useCallback(function () {
592
+ if (!editor) return;
593
+ editor.commands.unfreezeHandles();
594
+ onToggleOtherHandle === null || onToggleOtherHandle === void 0 || onToggleOtherHandle(true);
595
+ onOpenChange === null || onOpenChange === void 0 || onOpenChange(false);
596
+ }, [editor, onOpenChange, onToggleOtherHandle]);
597
+ var handleDragStart = useCallback(function (e) {
598
+ setIsDragging(true);
599
+ if (e.currentTarget instanceof HTMLElement) {
600
+ if (typeof index === 'number') {
601
+ e.currentTarget.dataset.tableIndex = String(index);
602
+ }
603
+ if (typeof tablePos === 'number') {
604
+ e.currentTarget.dataset.tablePos = String(tablePos);
605
+ }
606
+ if (tableNode) {
607
+ e.currentTarget.dataset.tableId = tableNode.attrs.id || '';
608
+ }
609
+ }
610
+ dragStart === null || dragStart === void 0 || dragStart(e);
611
+ }, [dragStart, index, tablePos, tableNode]);
612
+ var handleDragEnd = useCallback(function () {
613
+ setIsDragging(false);
614
+ dragEnd();
615
+ }, []);
616
+ var ariaLabel = orientation === 'row' ? 'Row actions' : 'Column actions';
617
+ if (!(editor !== null && editor !== void 0 && editor.isEditable)) return null;
618
+ var handleButton = /*#__PURE__*/React.createElement(Box, {
619
+ component: "button",
620
+ className: "tiptap-table-handle-menu ".concat(isDragging ? 'is-dragging' : '', " ").concat(orientation),
621
+ draggable: true,
622
+ "aria-label": ariaLabel,
623
+ "aria-haspopup": "menu",
624
+ onDragStart: handleDragStart,
625
+ onDragEnd: handleDragEnd,
626
+ sx: _objectSpread(_objectSpread({
627
+ border: 'none',
628
+ display: 'flex',
629
+ alignItems: 'center',
630
+ justifyContent: 'center',
631
+ backgroundColor: 'var(--mui-palette-background-paper3)',
632
+ borderRadius: 'var(--mui-shape-borderRadius)',
633
+ cursor: isDragging ? 'grabbing' : 'pointer',
634
+ padding: 0
635
+ }, orientation === 'row' ? {
636
+ width: '0.75rem',
637
+ height: 'var(--table-handle-ref-height, 40px)'
638
+ } : {
639
+ height: '0.75rem',
640
+ width: 'var(--table-handle-ref-width, 100px)'
641
+ }), {}, {
642
+ '&.is-dragging': {
643
+ backgroundColor: 'var(--mui-palette-primary-main)',
644
+ '& .MuiSvgIcon-root': {
645
+ color: 'var(--mui-palette-common-white)'
646
+ }
647
+ },
648
+ '&:hover': {
649
+ backgroundColor: 'var(--mui-palette-primary-main)',
650
+ '& .MuiSvgIcon-root': {
651
+ color: 'var(--mui-palette-common-white)'
652
+ }
653
+ }
654
+ })
655
+ }, /*#__PURE__*/React.createElement(MoreLineIcon, {
656
+ sx: _objectSpread({
657
+ width: '1rem',
658
+ height: '1rem',
659
+ flexShrink: 0
660
+ }, orientation === 'row' && {
661
+ transform: 'rotate(90deg)'
662
+ })
663
+ }));
664
+ return /*#__PURE__*/React.createElement(Menu, {
665
+ width: 216,
666
+ context: handleButton,
667
+ list: menuList,
668
+ anchorOrigin: {
669
+ vertical: orientation === 'row' ? 'top' : 'bottom',
670
+ horizontal: orientation === 'row' ? 'right' : 'left'
671
+ },
672
+ transformOrigin: {
673
+ vertical: 'top',
674
+ horizontal: 'left'
675
+ },
676
+ onOpen: handleMenuOpen,
677
+ onClose: handleMenuClose,
678
+ arrowIcon: /*#__PURE__*/React.createElement(ArrowDownSLineIcon, {
679
+ sx: {
680
+ fontSize: '1rem',
681
+ transform: 'rotate(-90deg)'
682
+ }
683
+ })
684
+ });
685
+ };