@atlaskit/editor-plugin-table 2.5.4 → 2.6.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @atlaskit/editor-plugin-table
2
2
 
3
+ ## 2.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`0ae6f70038a`](https://bitbucket.org/atlassian/atlassian-frontend/commits/0ae6f70038a) - [ED-17635] Add analytics event for table width resizing
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies
12
+
13
+ ## 2.5.5
14
+
15
+ ### Patch Changes
16
+
17
+ - [`d55db921de3`](https://bitbucket.org/atlassian/atlassian-frontend/commits/d55db921de3) - improve performance when adding a new column in table
18
+
3
19
  ## 2.5.4
4
20
 
5
21
  ### Patch Changes
@@ -71,8 +71,11 @@ var ResizableTableContainer = function ResizableTableContainer(_ref2) {
71
71
  guidelines: guidelines
72
72
  })) !== null && _pluginInjectionApi$d !== void 0 ? _pluginInjectionApi$d : false;
73
73
  }, [pluginInjectionApi, editorView]);
74
+ var attachAnalyticsEvent = (0, _react.useCallback)(function (payload) {
75
+ var _pluginInjectionApi$d5;
76
+ return pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$d5 = pluginInjectionApi.dependencies) === null || _pluginInjectionApi$d5 === void 0 ? void 0 : _pluginInjectionApi$d5.analytics.actions.attachAnalyticsEvent(payload);
77
+ }, [pluginInjectionApi]);
74
78
  var tableWidth = (0, _nodeWidth.getTableContainerWidth)(node);
75
-
76
79
  // 76 is currently an accepted padding value considering the spacing for resizer handle
77
80
  var responsiveContainerWidth = containerWidth - 76;
78
81
  var width = Math.min(tableWidth, responsiveContainerWidth);
@@ -93,7 +96,8 @@ var ResizableTableContainer = function ResizableTableContainer(_ref2) {
93
96
  getPos: getPos,
94
97
  node: node,
95
98
  tableRef: tableRef,
96
- displayGuideline: displayGuideline
99
+ displayGuideline: displayGuideline,
100
+ attachAnalyticsEvent: attachAnalyticsEvent
97
101
  }, /*#__PURE__*/_react.default.createElement(InnerContainer, {
98
102
  className: className,
99
103
  node: node
@@ -10,11 +10,14 @@ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/de
10
10
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
11
11
  var _react = _interopRequireWildcard(require("react"));
12
12
  var _rafSchd = _interopRequireDefault(require("raf-schd"));
13
+ var _analytics = require("@atlaskit/editor-common/analytics");
13
14
  var _guideline = require("@atlaskit/editor-common/guideline");
14
15
  var _resizer = require("@atlaskit/editor-common/resizer");
16
+ var _editorTables = require("@atlaskit/editor-tables");
15
17
  var _utils = require("../pm-plugins/table-resizing/utils");
16
18
  var _tableWidth = require("../pm-plugins/table-width");
17
19
  var _consts = require("../ui/consts");
20
+ var _utils2 = require("../utils");
18
21
  var _guidelines = require("../utils/guidelines");
19
22
  var _snapping = require("../utils/snapping");
20
23
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
@@ -25,6 +28,23 @@ var handles = {
25
28
  right: true
26
29
  };
27
30
  var tableHandleMarginTop = 11;
31
+ var generateResizedPayload = function generateResizedPayload(props) {
32
+ var _props$originalNode$a;
33
+ var tableMap = _editorTables.TableMap.get(props.resizedNode);
34
+ return {
35
+ action: _analytics.TABLE_ACTION.RESIZED,
36
+ actionSubject: _analytics.ACTION_SUBJECT.TABLE,
37
+ eventType: _analytics.EVENT_TYPE.TRACK,
38
+ attributes: {
39
+ newWidth: props.resizedNode.attrs.width,
40
+ prevWidth: (_props$originalNode$a = props.originalNode.attrs.width) !== null && _props$originalNode$a !== void 0 ? _props$originalNode$a : null,
41
+ nodeSize: props.resizedNode.nodeSize,
42
+ totalTableWidth: (0, _utils.hasTableBeenResized)(props.resizedNode) ? (0, _utils2.getTableWidth)(props.resizedNode) : null,
43
+ totalRowCount: tableMap.height,
44
+ totalColumnCount: tableMap.width
45
+ }
46
+ };
47
+ };
28
48
  var TableResizer = function TableResizer(_ref) {
29
49
  var children = _ref.children,
30
50
  width = _ref.width,
@@ -34,7 +54,8 @@ var TableResizer = function TableResizer(_ref) {
34
54
  getPos = _ref.getPos,
35
55
  node = _ref.node,
36
56
  tableRef = _ref.tableRef,
37
- displayGuideline = _ref.displayGuideline;
57
+ displayGuideline = _ref.displayGuideline,
58
+ attachAnalyticsEvent = _ref.attachAnalyticsEvent;
38
59
  var currentColumnCount = (0, _utils.getColgroupChildrenLength)(node);
39
60
  var minColumnWidth = currentColumnCount <= 3 ? currentColumnCount * _utils.COLUMN_MIN_WIDTH : 3 * _utils.COLUMN_MIN_WIDTH;
40
61
  var tableHeight = tableRef === null || tableRef === void 0 ? void 0 : tableRef.clientHeight;
@@ -88,6 +109,7 @@ var TableResizer = function TableResizer(_ref) {
88
109
  resizing: false
89
110
  });
90
111
  if (typeof pos === 'number') {
112
+ var _attachAnalyticsEvent;
91
113
  tr = tr.setNodeMarkup(pos, undefined, _objectSpread(_objectSpread({}, node.attrs), {}, {
92
114
  width: newWidth
93
115
  }));
@@ -98,6 +120,11 @@ var TableResizer = function TableResizer(_ref) {
98
120
  start: pos + 1,
99
121
  parentWidth: newWidth
100
122
  }, editorView.domAtPos.bind(editorView))(tr);
123
+ var scaledNode = tr.doc.nodeAt(pos);
124
+ (_attachAnalyticsEvent = attachAnalyticsEvent(generateResizedPayload({
125
+ originalNode: node,
126
+ resizedNode: scaledNode
127
+ }))) === null || _attachAnalyticsEvent === void 0 ? void 0 : _attachAnalyticsEvent(tr);
101
128
  }
102
129
  dispatch(tr);
103
130
 
@@ -105,7 +132,26 @@ var TableResizer = function TableResizer(_ref) {
105
132
  displayGuideline([]);
106
133
  updateWidth(newWidth);
107
134
  return newWidth;
108
- }, [updateWidth, editorView, getPos, node, tableRef, displayGuideline]);
135
+ }, [updateWidth, editorView, getPos, node, tableRef, displayGuideline, attachAnalyticsEvent]);
136
+ var handleResize = (0, _react.useCallback)(function (originalState, delta) {
137
+ var newWidth = originalState.width + delta.width;
138
+ var pos = getPos();
139
+ if (typeof pos !== 'number') {
140
+ return;
141
+ }
142
+ (0, _utils.previewScaleTable)(tableRef, {
143
+ node: node,
144
+ prevNode: node,
145
+ start: pos + 1,
146
+ parentWidth: newWidth
147
+ }, editorView.domAtPos.bind(editorView));
148
+ updateActiveGuidelines((0, _snapping.findClosestSnap)(newWidth, _guidelines.defaultGuidelineWidths, _guidelines.defaultGuidelines, _consts.TABLE_HIGHLIGHT_GAP));
149
+ updateWidth(newWidth);
150
+ return newWidth;
151
+ }, [editorView, getPos, node, tableRef, updateWidth, updateActiveGuidelines]);
152
+ var scheduleResize = (0, _react.useMemo)(function () {
153
+ return (0, _rafSchd.default)(handleResize);
154
+ }, [handleResize]);
109
155
  return /*#__PURE__*/_react.default.createElement(_resizer.ResizerNext, {
110
156
  enable: handles,
111
157
  width: width,
@@ -113,22 +159,7 @@ var TableResizer = function TableResizer(_ref) {
113
159
  handleHeightSize: handleHeightSize,
114
160
  handleMarginTop: tableHandleMarginTop,
115
161
  handleResizeStart: handleResizeStart,
116
- handleResize: (0, _rafSchd.default)(function (originalState, delta) {
117
- var newWidth = originalState.width + delta.width;
118
- var pos = getPos();
119
- if (typeof pos !== 'number') {
120
- return;
121
- }
122
- (0, _utils.previewScaleTable)(tableRef, {
123
- node: node,
124
- prevNode: node,
125
- start: pos + 1,
126
- parentWidth: newWidth
127
- }, editorView.domAtPos.bind(editorView));
128
- updateActiveGuidelines((0, _snapping.findClosestSnap)(newWidth, _guidelines.defaultGuidelineWidths, _guidelines.defaultGuidelines, _consts.TABLE_HIGHLIGHT_GAP));
129
- updateWidth(newWidth);
130
- return newWidth;
131
- }),
162
+ handleResize: scheduleResize,
132
163
  handleResizeStop: handleResizeStop,
133
164
  resizeRatio: 2,
134
165
  minWidth: minColumnWidth,
@@ -32,22 +32,6 @@ var anyChildCellMergedAcrossRow = function anyChildCellMergedAcrossRow(node) {
32
32
  });
33
33
  };
34
34
 
35
- /**
36
- * Compare two table row nodes and return true if the two table rows have a
37
- * different number of table cells or if table cell row spans are different
38
- */
39
- var rowHasDifferentMergedCells = function rowHasDifferentMergedCells(prevNode, incomingNode) {
40
- var incomingNodeChildrenRowSpan = (0, _utils.mapChildren)(prevNode, function (child) {
41
- return child.attrs.rowspan || 0;
42
- });
43
- var currentNodeChildrenRowSpan = (0, _utils.mapChildren)(incomingNode, function (child) {
44
- return child.attrs.rowspan || 0;
45
- });
46
- return incomingNodeChildrenRowSpan.length !== currentNodeChildrenRowSpan.length || currentNodeChildrenRowSpan.some(function (child, index) {
47
- return child !== incomingNodeChildrenRowSpan[index];
48
- });
49
- };
50
-
51
35
  /**
52
36
  * Check if a given node is a header row with this definition:
53
37
  * - all children are tableHeader cells
@@ -512,10 +496,6 @@ var TableRowNodeView = /*#__PURE__*/function () {
512
496
  return false; // re-create nodeview
513
497
  }
514
498
 
515
- if (rowHasDifferentMergedCells(this.node, node)) {
516
- return false;
517
- }
518
-
519
499
  // node is different but no need to re-create nodeview
520
500
  this.node = node;
521
501
 
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-table",
3
- "version": "2.5.4",
3
+ "version": "2.6.0",
4
4
  "sideEffects": false
5
5
  }
@@ -62,8 +62,11 @@ export const ResizableTableContainer = ({
62
62
  guidelines
63
63
  })) !== null && _pluginInjectionApi$d !== void 0 ? _pluginInjectionApi$d : false;
64
64
  }, [pluginInjectionApi, editorView]);
65
+ const attachAnalyticsEvent = useCallback(payload => {
66
+ var _pluginInjectionApi$d5;
67
+ return pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$d5 = pluginInjectionApi.dependencies) === null || _pluginInjectionApi$d5 === void 0 ? void 0 : _pluginInjectionApi$d5.analytics.actions.attachAnalyticsEvent(payload);
68
+ }, [pluginInjectionApi]);
65
69
  const tableWidth = getTableContainerWidth(node);
66
-
67
70
  // 76 is currently an accepted padding value considering the spacing for resizer handle
68
71
  const responsiveContainerWidth = containerWidth - 76;
69
72
  const width = Math.min(tableWidth, responsiveContainerWidth);
@@ -84,7 +87,8 @@ export const ResizableTableContainer = ({
84
87
  getPos: getPos,
85
88
  node: node,
86
89
  tableRef: tableRef,
87
- displayGuideline: displayGuideline
90
+ displayGuideline: displayGuideline,
91
+ attachAnalyticsEvent: attachAnalyticsEvent
88
92
  }, /*#__PURE__*/React.createElement(InnerContainer, {
89
93
  className: className,
90
94
  node: node
@@ -1,16 +1,36 @@
1
1
  import React, { useCallback, useMemo, useRef, useState } from 'react';
2
2
  import rafSchd from 'raf-schd';
3
+ import { ACTION_SUBJECT, EVENT_TYPE, TABLE_ACTION } from '@atlaskit/editor-common/analytics';
3
4
  import { getGuidelinesWithHighlights } from '@atlaskit/editor-common/guideline';
4
5
  import { ResizerNext } from '@atlaskit/editor-common/resizer';
5
- import { COLUMN_MIN_WIDTH, getColgroupChildrenLength, previewScaleTable, scaleTable } from '../pm-plugins/table-resizing/utils';
6
+ import { TableMap } from '@atlaskit/editor-tables';
7
+ import { COLUMN_MIN_WIDTH, getColgroupChildrenLength, hasTableBeenResized, previewScaleTable, scaleTable } from '../pm-plugins/table-resizing/utils';
6
8
  import { pluginKey as tableWidthPluginKey } from '../pm-plugins/table-width';
7
9
  import { TABLE_HIGHLIGHT_GAP, TABLE_SNAP_GAP } from '../ui/consts';
10
+ import { getTableWidth } from '../utils';
8
11
  import { defaultGuidelines, defaultGuidelineWidths } from '../utils/guidelines';
9
12
  import { findClosestSnap } from '../utils/snapping';
10
13
  const handles = {
11
14
  right: true
12
15
  };
13
16
  const tableHandleMarginTop = 11;
17
+ const generateResizedPayload = props => {
18
+ var _props$originalNode$a;
19
+ const tableMap = TableMap.get(props.resizedNode);
20
+ return {
21
+ action: TABLE_ACTION.RESIZED,
22
+ actionSubject: ACTION_SUBJECT.TABLE,
23
+ eventType: EVENT_TYPE.TRACK,
24
+ attributes: {
25
+ newWidth: props.resizedNode.attrs.width,
26
+ prevWidth: (_props$originalNode$a = props.originalNode.attrs.width) !== null && _props$originalNode$a !== void 0 ? _props$originalNode$a : null,
27
+ nodeSize: props.resizedNode.nodeSize,
28
+ totalTableWidth: hasTableBeenResized(props.resizedNode) ? getTableWidth(props.resizedNode) : null,
29
+ totalRowCount: tableMap.height,
30
+ totalColumnCount: tableMap.width
31
+ }
32
+ };
33
+ };
14
34
  export const TableResizer = ({
15
35
  children,
16
36
  width,
@@ -20,7 +40,8 @@ export const TableResizer = ({
20
40
  getPos,
21
41
  node,
22
42
  tableRef,
23
- displayGuideline
43
+ displayGuideline,
44
+ attachAnalyticsEvent
24
45
  }) => {
25
46
  const currentColumnCount = getColgroupChildrenLength(node);
26
47
  const minColumnWidth = currentColumnCount <= 3 ? currentColumnCount * COLUMN_MIN_WIDTH : 3 * COLUMN_MIN_WIDTH;
@@ -77,6 +98,7 @@ export const TableResizer = ({
77
98
  resizing: false
78
99
  });
79
100
  if (typeof pos === 'number') {
101
+ var _attachAnalyticsEvent;
80
102
  tr = tr.setNodeMarkup(pos, undefined, {
81
103
  ...node.attrs,
82
104
  width: newWidth
@@ -88,6 +110,11 @@ export const TableResizer = ({
88
110
  start: pos + 1,
89
111
  parentWidth: newWidth
90
112
  }, editorView.domAtPos.bind(editorView))(tr);
113
+ const scaledNode = tr.doc.nodeAt(pos);
114
+ (_attachAnalyticsEvent = attachAnalyticsEvent(generateResizedPayload({
115
+ originalNode: node,
116
+ resizedNode: scaledNode
117
+ }))) === null || _attachAnalyticsEvent === void 0 ? void 0 : _attachAnalyticsEvent(tr);
91
118
  }
92
119
  dispatch(tr);
93
120
 
@@ -95,7 +122,24 @@ export const TableResizer = ({
95
122
  displayGuideline([]);
96
123
  updateWidth(newWidth);
97
124
  return newWidth;
98
- }, [updateWidth, editorView, getPos, node, tableRef, displayGuideline]);
125
+ }, [updateWidth, editorView, getPos, node, tableRef, displayGuideline, attachAnalyticsEvent]);
126
+ const handleResize = useCallback((originalState, delta) => {
127
+ const newWidth = originalState.width + delta.width;
128
+ const pos = getPos();
129
+ if (typeof pos !== 'number') {
130
+ return;
131
+ }
132
+ previewScaleTable(tableRef, {
133
+ node,
134
+ prevNode: node,
135
+ start: pos + 1,
136
+ parentWidth: newWidth
137
+ }, editorView.domAtPos.bind(editorView));
138
+ updateActiveGuidelines(findClosestSnap(newWidth, defaultGuidelineWidths, defaultGuidelines, TABLE_HIGHLIGHT_GAP));
139
+ updateWidth(newWidth);
140
+ return newWidth;
141
+ }, [editorView, getPos, node, tableRef, updateWidth, updateActiveGuidelines]);
142
+ const scheduleResize = useMemo(() => rafSchd(handleResize), [handleResize]);
99
143
  return /*#__PURE__*/React.createElement(ResizerNext, {
100
144
  enable: handles,
101
145
  width: width,
@@ -103,22 +147,7 @@ export const TableResizer = ({
103
147
  handleHeightSize: handleHeightSize,
104
148
  handleMarginTop: tableHandleMarginTop,
105
149
  handleResizeStart: handleResizeStart,
106
- handleResize: rafSchd((originalState, delta) => {
107
- const newWidth = originalState.width + delta.width;
108
- const pos = getPos();
109
- if (typeof pos !== 'number') {
110
- return;
111
- }
112
- previewScaleTable(tableRef, {
113
- node,
114
- prevNode: node,
115
- start: pos + 1,
116
- parentWidth: newWidth
117
- }, editorView.domAtPos.bind(editorView));
118
- updateActiveGuidelines(findClosestSnap(newWidth, defaultGuidelineWidths, defaultGuidelines, TABLE_HIGHLIGHT_GAP));
119
- updateWidth(newWidth);
120
- return newWidth;
121
- }),
150
+ handleResize: scheduleResize,
122
151
  handleResizeStop: handleResizeStop,
123
152
  resizeRatio: 2,
124
153
  minWidth: minColumnWidth,
@@ -18,16 +18,6 @@ const HEADER_ROW_SCROLL_THROTTLE_TIMEOUT = 200;
18
18
  const HEADER_ROW_SCROLL_RESET_DEBOUNCE_TIMEOUT = 400;
19
19
  const anyChildCellMergedAcrossRow = node => mapChildren(node, child => child.attrs.rowspan || 0).some(rowspan => rowspan > 1);
20
20
 
21
- /**
22
- * Compare two table row nodes and return true if the two table rows have a
23
- * different number of table cells or if table cell row spans are different
24
- */
25
- const rowHasDifferentMergedCells = (prevNode, incomingNode) => {
26
- const incomingNodeChildrenRowSpan = mapChildren(prevNode, child => child.attrs.rowspan || 0);
27
- const currentNodeChildrenRowSpan = mapChildren(incomingNode, child => child.attrs.rowspan || 0);
28
- return incomingNodeChildrenRowSpan.length !== currentNodeChildrenRowSpan.length || currentNodeChildrenRowSpan.some((child, index) => child !== incomingNodeChildrenRowSpan[index]);
29
- };
30
-
31
21
  /**
32
22
  * Check if a given node is a header row with this definition:
33
23
  * - all children are tableHeader cells
@@ -477,10 +467,6 @@ export class TableRowNodeView {
477
467
  return false; // re-create nodeview
478
468
  }
479
469
 
480
- if (rowHasDifferentMergedCells(this.node, node)) {
481
- return false;
482
- }
483
-
484
470
  // node is different but no need to re-create nodeview
485
471
  this.node = node;
486
472
 
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-table",
3
- "version": "2.5.4",
3
+ "version": "2.6.0",
4
4
  "sideEffects": false
5
5
  }
@@ -60,8 +60,11 @@ export var ResizableTableContainer = function ResizableTableContainer(_ref2) {
60
60
  guidelines: guidelines
61
61
  })) !== null && _pluginInjectionApi$d !== void 0 ? _pluginInjectionApi$d : false;
62
62
  }, [pluginInjectionApi, editorView]);
63
+ var attachAnalyticsEvent = useCallback(function (payload) {
64
+ var _pluginInjectionApi$d5;
65
+ return pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$d5 = pluginInjectionApi.dependencies) === null || _pluginInjectionApi$d5 === void 0 ? void 0 : _pluginInjectionApi$d5.analytics.actions.attachAnalyticsEvent(payload);
66
+ }, [pluginInjectionApi]);
63
67
  var tableWidth = getTableContainerWidth(node);
64
-
65
68
  // 76 is currently an accepted padding value considering the spacing for resizer handle
66
69
  var responsiveContainerWidth = containerWidth - 76;
67
70
  var width = Math.min(tableWidth, responsiveContainerWidth);
@@ -82,7 +85,8 @@ export var ResizableTableContainer = function ResizableTableContainer(_ref2) {
82
85
  getPos: getPos,
83
86
  node: node,
84
87
  tableRef: tableRef,
85
- displayGuideline: displayGuideline
88
+ displayGuideline: displayGuideline,
89
+ attachAnalyticsEvent: attachAnalyticsEvent
86
90
  }, /*#__PURE__*/React.createElement(InnerContainer, {
87
91
  className: className,
88
92
  node: node
@@ -4,17 +4,37 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
4
4
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
5
5
  import React, { useCallback, useMemo, useRef, useState } from 'react';
6
6
  import rafSchd from 'raf-schd';
7
+ import { ACTION_SUBJECT, EVENT_TYPE, TABLE_ACTION } from '@atlaskit/editor-common/analytics';
7
8
  import { getGuidelinesWithHighlights } from '@atlaskit/editor-common/guideline';
8
9
  import { ResizerNext } from '@atlaskit/editor-common/resizer';
9
- import { COLUMN_MIN_WIDTH, getColgroupChildrenLength, previewScaleTable, scaleTable } from '../pm-plugins/table-resizing/utils';
10
+ import { TableMap } from '@atlaskit/editor-tables';
11
+ import { COLUMN_MIN_WIDTH, getColgroupChildrenLength, hasTableBeenResized, previewScaleTable, scaleTable } from '../pm-plugins/table-resizing/utils';
10
12
  import { pluginKey as tableWidthPluginKey } from '../pm-plugins/table-width';
11
13
  import { TABLE_HIGHLIGHT_GAP, TABLE_SNAP_GAP } from '../ui/consts';
14
+ import { getTableWidth } from '../utils';
12
15
  import { defaultGuidelines, defaultGuidelineWidths } from '../utils/guidelines';
13
16
  import { findClosestSnap } from '../utils/snapping';
14
17
  var handles = {
15
18
  right: true
16
19
  };
17
20
  var tableHandleMarginTop = 11;
21
+ var generateResizedPayload = function generateResizedPayload(props) {
22
+ var _props$originalNode$a;
23
+ var tableMap = TableMap.get(props.resizedNode);
24
+ return {
25
+ action: TABLE_ACTION.RESIZED,
26
+ actionSubject: ACTION_SUBJECT.TABLE,
27
+ eventType: EVENT_TYPE.TRACK,
28
+ attributes: {
29
+ newWidth: props.resizedNode.attrs.width,
30
+ prevWidth: (_props$originalNode$a = props.originalNode.attrs.width) !== null && _props$originalNode$a !== void 0 ? _props$originalNode$a : null,
31
+ nodeSize: props.resizedNode.nodeSize,
32
+ totalTableWidth: hasTableBeenResized(props.resizedNode) ? getTableWidth(props.resizedNode) : null,
33
+ totalRowCount: tableMap.height,
34
+ totalColumnCount: tableMap.width
35
+ }
36
+ };
37
+ };
18
38
  export var TableResizer = function TableResizer(_ref) {
19
39
  var children = _ref.children,
20
40
  width = _ref.width,
@@ -24,7 +44,8 @@ export var TableResizer = function TableResizer(_ref) {
24
44
  getPos = _ref.getPos,
25
45
  node = _ref.node,
26
46
  tableRef = _ref.tableRef,
27
- displayGuideline = _ref.displayGuideline;
47
+ displayGuideline = _ref.displayGuideline,
48
+ attachAnalyticsEvent = _ref.attachAnalyticsEvent;
28
49
  var currentColumnCount = getColgroupChildrenLength(node);
29
50
  var minColumnWidth = currentColumnCount <= 3 ? currentColumnCount * COLUMN_MIN_WIDTH : 3 * COLUMN_MIN_WIDTH;
30
51
  var tableHeight = tableRef === null || tableRef === void 0 ? void 0 : tableRef.clientHeight;
@@ -78,6 +99,7 @@ export var TableResizer = function TableResizer(_ref) {
78
99
  resizing: false
79
100
  });
80
101
  if (typeof pos === 'number') {
102
+ var _attachAnalyticsEvent;
81
103
  tr = tr.setNodeMarkup(pos, undefined, _objectSpread(_objectSpread({}, node.attrs), {}, {
82
104
  width: newWidth
83
105
  }));
@@ -88,6 +110,11 @@ export var TableResizer = function TableResizer(_ref) {
88
110
  start: pos + 1,
89
111
  parentWidth: newWidth
90
112
  }, editorView.domAtPos.bind(editorView))(tr);
113
+ var scaledNode = tr.doc.nodeAt(pos);
114
+ (_attachAnalyticsEvent = attachAnalyticsEvent(generateResizedPayload({
115
+ originalNode: node,
116
+ resizedNode: scaledNode
117
+ }))) === null || _attachAnalyticsEvent === void 0 ? void 0 : _attachAnalyticsEvent(tr);
91
118
  }
92
119
  dispatch(tr);
93
120
 
@@ -95,7 +122,26 @@ export var TableResizer = function TableResizer(_ref) {
95
122
  displayGuideline([]);
96
123
  updateWidth(newWidth);
97
124
  return newWidth;
98
- }, [updateWidth, editorView, getPos, node, tableRef, displayGuideline]);
125
+ }, [updateWidth, editorView, getPos, node, tableRef, displayGuideline, attachAnalyticsEvent]);
126
+ var handleResize = useCallback(function (originalState, delta) {
127
+ var newWidth = originalState.width + delta.width;
128
+ var pos = getPos();
129
+ if (typeof pos !== 'number') {
130
+ return;
131
+ }
132
+ previewScaleTable(tableRef, {
133
+ node: node,
134
+ prevNode: node,
135
+ start: pos + 1,
136
+ parentWidth: newWidth
137
+ }, editorView.domAtPos.bind(editorView));
138
+ updateActiveGuidelines(findClosestSnap(newWidth, defaultGuidelineWidths, defaultGuidelines, TABLE_HIGHLIGHT_GAP));
139
+ updateWidth(newWidth);
140
+ return newWidth;
141
+ }, [editorView, getPos, node, tableRef, updateWidth, updateActiveGuidelines]);
142
+ var scheduleResize = useMemo(function () {
143
+ return rafSchd(handleResize);
144
+ }, [handleResize]);
99
145
  return /*#__PURE__*/React.createElement(ResizerNext, {
100
146
  enable: handles,
101
147
  width: width,
@@ -103,22 +149,7 @@ export var TableResizer = function TableResizer(_ref) {
103
149
  handleHeightSize: handleHeightSize,
104
150
  handleMarginTop: tableHandleMarginTop,
105
151
  handleResizeStart: handleResizeStart,
106
- handleResize: rafSchd(function (originalState, delta) {
107
- var newWidth = originalState.width + delta.width;
108
- var pos = getPos();
109
- if (typeof pos !== 'number') {
110
- return;
111
- }
112
- previewScaleTable(tableRef, {
113
- node: node,
114
- prevNode: node,
115
- start: pos + 1,
116
- parentWidth: newWidth
117
- }, editorView.domAtPos.bind(editorView));
118
- updateActiveGuidelines(findClosestSnap(newWidth, defaultGuidelineWidths, defaultGuidelines, TABLE_HIGHLIGHT_GAP));
119
- updateWidth(newWidth);
120
- return newWidth;
121
- }),
152
+ handleResize: scheduleResize,
122
153
  handleResizeStop: handleResizeStop,
123
154
  resizeRatio: 2,
124
155
  minWidth: minColumnWidth,
@@ -26,22 +26,6 @@ var anyChildCellMergedAcrossRow = function anyChildCellMergedAcrossRow(node) {
26
26
  });
27
27
  };
28
28
 
29
- /**
30
- * Compare two table row nodes and return true if the two table rows have a
31
- * different number of table cells or if table cell row spans are different
32
- */
33
- var rowHasDifferentMergedCells = function rowHasDifferentMergedCells(prevNode, incomingNode) {
34
- var incomingNodeChildrenRowSpan = mapChildren(prevNode, function (child) {
35
- return child.attrs.rowspan || 0;
36
- });
37
- var currentNodeChildrenRowSpan = mapChildren(incomingNode, function (child) {
38
- return child.attrs.rowspan || 0;
39
- });
40
- return incomingNodeChildrenRowSpan.length !== currentNodeChildrenRowSpan.length || currentNodeChildrenRowSpan.some(function (child, index) {
41
- return child !== incomingNodeChildrenRowSpan[index];
42
- });
43
- };
44
-
45
29
  /**
46
30
  * Check if a given node is a header row with this definition:
47
31
  * - all children are tableHeader cells
@@ -505,10 +489,6 @@ export var TableRowNodeView = /*#__PURE__*/function () {
505
489
  return false; // re-create nodeview
506
490
  }
507
491
 
508
- if (rowHasDifferentMergedCells(this.node, node)) {
509
- return false;
510
- }
511
-
512
492
  // node is different but no need to re-create nodeview
513
493
  this.node = node;
514
494
 
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-table",
3
- "version": "2.5.4",
3
+ "version": "2.6.0",
4
4
  "sideEffects": false
5
5
  }
@@ -1,6 +1,8 @@
1
1
  import { PropsWithChildren } from 'react';
2
2
  import { Node as PMNode } from 'prosemirror-model';
3
+ import { Transaction } from 'prosemirror-state';
3
4
  import { EditorView } from 'prosemirror-view';
5
+ import { TableEventPayload } from '@atlaskit/editor-common/analytics';
4
6
  import type { GuidelineConfig } from '@atlaskit/editor-plugin-guideline';
5
7
  interface TableResizerProps {
6
8
  width: number;
@@ -11,6 +13,7 @@ interface TableResizerProps {
11
13
  node: PMNode;
12
14
  tableRef: HTMLTableElement;
13
15
  displayGuideline: (guideline: GuidelineConfig[]) => boolean;
16
+ attachAnalyticsEvent: (payload: TableEventPayload) => ((tr: Transaction) => boolean) | undefined;
14
17
  }
15
- export declare const TableResizer: ({ children, width, maxWidth, updateWidth, editorView, getPos, node, tableRef, displayGuideline, }: PropsWithChildren<TableResizerProps>) => JSX.Element;
18
+ export declare const TableResizer: ({ children, width, maxWidth, updateWidth, editorView, getPos, node, tableRef, displayGuideline, attachAnalyticsEvent, }: PropsWithChildren<TableResizerProps>) => JSX.Element;
16
19
  export {};
@@ -1,6 +1,8 @@
1
1
  import { PropsWithChildren } from 'react';
2
2
  import { Node as PMNode } from 'prosemirror-model';
3
+ import { Transaction } from 'prosemirror-state';
3
4
  import { EditorView } from 'prosemirror-view';
5
+ import { TableEventPayload } from '@atlaskit/editor-common/analytics';
4
6
  import type { GuidelineConfig } from '@atlaskit/editor-plugin-guideline';
5
7
  interface TableResizerProps {
6
8
  width: number;
@@ -11,6 +13,7 @@ interface TableResizerProps {
11
13
  node: PMNode;
12
14
  tableRef: HTMLTableElement;
13
15
  displayGuideline: (guideline: GuidelineConfig[]) => boolean;
16
+ attachAnalyticsEvent: (payload: TableEventPayload) => ((tr: Transaction) => boolean) | undefined;
14
17
  }
15
- export declare const TableResizer: ({ children, width, maxWidth, updateWidth, editorView, getPos, node, tableRef, displayGuideline, }: PropsWithChildren<TableResizerProps>) => JSX.Element;
18
+ export declare const TableResizer: ({ children, width, maxWidth, updateWidth, editorView, getPos, node, tableRef, displayGuideline, attachAnalyticsEvent, }: PropsWithChildren<TableResizerProps>) => JSX.Element;
16
19
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-table",
3
- "version": "2.5.4",
3
+ "version": "2.6.0",
4
4
  "description": "Table plugin for the @atlaskit/editor",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -27,8 +27,8 @@
27
27
  "releaseModel": "continuous"
28
28
  },
29
29
  "dependencies": {
30
- "@atlaskit/adf-schema": "^26.2.0",
31
- "@atlaskit/editor-common": "^74.26.0",
30
+ "@atlaskit/adf-schema": "^26.3.0",
31
+ "@atlaskit/editor-common": "^74.27.0",
32
32
  "@atlaskit/editor-palette": "1.5.1",
33
33
  "@atlaskit/editor-plugin-analytics": "^0.1.0",
34
34
  "@atlaskit/editor-plugin-content-insertion": "^0.0.6",
@@ -1,8 +1,13 @@
1
1
  import React from 'react';
2
2
 
3
- import { render } from '@testing-library/react';
3
+ import { fireEvent, render } from '@testing-library/react';
4
4
 
5
5
  import { TableAttributes } from '@atlaskit/adf-schema';
6
+ import {
7
+ ACTION_SUBJECT,
8
+ EVENT_TYPE,
9
+ TABLE_ACTION,
10
+ } from '@atlaskit/editor-common/analytics';
6
11
  import { akEditorWideLayoutWidth } from '@atlaskit/editor-shared-styles';
7
12
  import { findTable } from '@atlaskit/editor-tables/utils';
8
13
  import { createEditorFactory } from '@atlaskit/editor-test-helpers/create-editor';
@@ -43,12 +48,12 @@ describe('table -> nodeviews -> TableContainer.tsx', () => {
43
48
  });
44
49
  };
45
50
  const createNode = (attrs?: TableAttributes) => {
46
- const { editorView: view } = editor(
47
- doc(p('text'), table(attrs)(tr(td()(p('{<>}text')), tdEmpty, tdEmpty))),
51
+ const { editorView } = editor(
52
+ doc(table(attrs)(tr(td()(p('{<>}text')), tdEmpty, tdEmpty))),
48
53
  );
49
- const resolvedTable = findTable(view.state.selection);
54
+ const resolvedTable = findTable(editorView.state.selection);
50
55
 
51
- return resolvedTable!.node;
56
+ return { editorView, node: resolvedTable!.node };
52
57
  };
53
58
 
54
59
  describe('show correct container for FF and options', () => {
@@ -56,7 +61,7 @@ describe('table -> nodeviews -> TableContainer.tsx', () => {
56
61
  isTableResizingEnabled: boolean,
57
62
  isBreakoutEnabled: boolean = true,
58
63
  ) => {
59
- const node = createNode();
64
+ const { node, editorView } = createNode();
60
65
 
61
66
  const { container } = render(
62
67
  <TableContainer
@@ -68,7 +73,7 @@ describe('table -> nodeviews -> TableContainer.tsx', () => {
68
73
  isTableResizingEnabled={isTableResizingEnabled}
69
74
  isBreakoutEnabled={isBreakoutEnabled}
70
75
  className={''}
71
- editorView={{} as any}
76
+ editorView={editorView}
72
77
  getPos={() => 1}
73
78
  tableRef={{} as any}
74
79
  isNested={false}
@@ -94,7 +99,7 @@ describe('table -> nodeviews -> TableContainer.tsx', () => {
94
99
  isTableResizingEnabled: boolean,
95
100
  isBreakoutEnabled: boolean = true,
96
101
  ) => {
97
- const node = createNode();
102
+ const { node, editorView } = createNode();
98
103
 
99
104
  const { container } = render(
100
105
  <TableContainer
@@ -106,7 +111,7 @@ describe('table -> nodeviews -> TableContainer.tsx', () => {
106
111
  isTableResizingEnabled={isTableResizingEnabled}
107
112
  isBreakoutEnabled={isBreakoutEnabled}
108
113
  className={''}
109
- editorView={{} as any}
114
+ editorView={editorView}
110
115
  getPos={() => 1}
111
116
  tableRef={{} as any}
112
117
  isNested={true}
@@ -129,7 +134,7 @@ describe('table -> nodeviews -> TableContainer.tsx', () => {
129
134
 
130
135
  describe('sets width and margin correctly for resizable container', () => {
131
136
  const buildContainer = (attrs: TableAttributes) => {
132
- const node = createNode(attrs);
137
+ const { node, editorView } = createNode(attrs);
133
138
 
134
139
  const { container } = render(
135
140
  <ResizableTableContainer
@@ -137,7 +142,7 @@ describe('table -> nodeviews -> TableContainer.tsx', () => {
137
142
  lineLength={720}
138
143
  node={node}
139
144
  className={''}
140
- editorView={{} as any}
145
+ editorView={editorView}
141
146
  getPos={() => 1}
142
147
  tableRef={{} as any}
143
148
  />,
@@ -154,4 +159,62 @@ describe('table -> nodeviews -> TableContainer.tsx', () => {
154
159
  expect(style.marginLeft).toBe('-120px');
155
160
  });
156
161
  });
162
+
163
+ describe('analytics', () => {
164
+ const buildContainer = (attrs: TableAttributes) => {
165
+ const { node, editorView } = createNode(attrs);
166
+ const analyticsMock = jest.fn();
167
+
168
+ const { container } = render(
169
+ <ResizableTableContainer
170
+ containerWidth={1800}
171
+ lineLength={720}
172
+ node={node}
173
+ className={''}
174
+ editorView={editorView}
175
+ getPos={() => 0}
176
+ tableRef={
177
+ {
178
+ querySelector: () => null,
179
+ insertBefore: () => {},
180
+ style: {},
181
+ } as any
182
+ }
183
+ pluginInjectionApi={
184
+ {
185
+ dependencies: {
186
+ analytics: { actions: { attachAnalyticsEvent: analyticsMock } },
187
+ },
188
+ } as any
189
+ }
190
+ />,
191
+ );
192
+
193
+ return { container, analyticsMock };
194
+ };
195
+
196
+ test('fires when resizing is finished', async () => {
197
+ const { container, analyticsMock } = buildContainer({ layout: 'wide' });
198
+
199
+ fireEvent.mouseDown(container.querySelector('.resizer-handle-right')!);
200
+ fireEvent.mouseMove(container.querySelector('.resizer-handle-right')!);
201
+ fireEvent.mouseMove(container.querySelector('.resizer-handle-right')!);
202
+ fireEvent.mouseMove(container.querySelector('.resizer-handle-right')!);
203
+ fireEvent.mouseUp(container.querySelector('.resizer-handle-right')!);
204
+
205
+ expect(analyticsMock).toHaveBeenLastCalledWith({
206
+ action: TABLE_ACTION.RESIZED,
207
+ actionSubject: ACTION_SUBJECT.TABLE,
208
+ eventType: EVENT_TYPE.TRACK,
209
+ attributes: {
210
+ width: undefined, // Can't get the events right to trigger re-resizeable
211
+ prevWidth: null,
212
+ nodeSize: 20,
213
+ totalTableWidth: null,
214
+ totalRowCount: 1,
215
+ totalColumnCount: 3,
216
+ },
217
+ });
218
+ });
219
+ });
157
220
  });
@@ -39,7 +39,8 @@ describe('Snapshot Test: Table', () => {
39
39
  });
40
40
 
41
41
  describe('sticky header', () => {
42
- it('should align with table cell when active', async () => {
42
+ // FIXME: This test was automatically skipped due to failure on 26/07/2023: https://product-fabric.atlassian.net/browse/ED-19223
43
+ it.skip('should align with table cell when active', async () => {
43
44
  await initEditor(page, stickyHeaderWithHorizontalScroll);
44
45
 
45
46
  await clickFirstCell(page, true);
@@ -9,6 +9,7 @@ import classNames from 'classnames';
9
9
  import { Node as PMNode } from 'prosemirror-model';
10
10
  import { EditorView } from 'prosemirror-view';
11
11
 
12
+ import { TableEventPayload } from '@atlaskit/editor-common/analytics';
12
13
  import { getTableContainerWidth } from '@atlaskit/editor-common/node-width';
13
14
  import { calcTableWidth } from '@atlaskit/editor-common/styles';
14
15
  import { EditorContainerWidth } from '@atlaskit/editor-common/types';
@@ -115,15 +116,20 @@ export const ResizableTableContainer = ({
115
116
  [pluginInjectionApi, editorView],
116
117
  );
117
118
 
118
- const tableWidth = getTableContainerWidth(node);
119
+ const attachAnalyticsEvent = useCallback(
120
+ (payload: TableEventPayload) => {
121
+ return pluginInjectionApi?.dependencies?.analytics.actions.attachAnalyticsEvent(
122
+ payload,
123
+ );
124
+ },
125
+ [pluginInjectionApi],
126
+ );
119
127
 
128
+ const tableWidth = getTableContainerWidth(node);
120
129
  // 76 is currently an accepted padding value considering the spacing for resizer handle
121
130
  const responsiveContainerWidth = containerWidth - 76;
122
-
123
131
  const width = Math.min(tableWidth, responsiveContainerWidth);
124
-
125
132
  marginLeftRef.current = getMarginLeft(lineLength, width);
126
-
127
133
  const maxResizerWidth = Math.min(responsiveContainerWidth, TABLE_MAX_WIDTH);
128
134
 
129
135
  return (
@@ -141,6 +147,7 @@ export const ResizableTableContainer = ({
141
147
  node={node}
142
148
  tableRef={tableRef}
143
149
  displayGuideline={displayGuideline}
150
+ attachAnalyticsEvent={attachAnalyticsEvent}
144
151
  >
145
152
  <InnerContainer className={className} node={node}>
146
153
  {children}
@@ -7,9 +7,16 @@ import React, {
7
7
  } from 'react';
8
8
 
9
9
  import { Node as PMNode } from 'prosemirror-model';
10
+ import { Transaction } from 'prosemirror-state';
10
11
  import { EditorView } from 'prosemirror-view';
11
12
  import rafSchd from 'raf-schd';
12
13
 
14
+ import {
15
+ ACTION_SUBJECT,
16
+ EVENT_TYPE,
17
+ TABLE_ACTION,
18
+ TableEventPayload,
19
+ } from '@atlaskit/editor-common/analytics';
13
20
  import { getGuidelinesWithHighlights } from '@atlaskit/editor-common/guideline';
14
21
  import {
15
22
  HandleHeightSizeType,
@@ -17,15 +24,18 @@ import {
17
24
  ResizerNext,
18
25
  } from '@atlaskit/editor-common/resizer';
19
26
  import type { GuidelineConfig } from '@atlaskit/editor-plugin-guideline';
27
+ import { TableMap } from '@atlaskit/editor-tables';
20
28
 
21
29
  import {
22
30
  COLUMN_MIN_WIDTH,
23
31
  getColgroupChildrenLength,
32
+ hasTableBeenResized,
24
33
  previewScaleTable,
25
34
  scaleTable,
26
35
  } from '../pm-plugins/table-resizing/utils';
27
36
  import { pluginKey as tableWidthPluginKey } from '../pm-plugins/table-width';
28
37
  import { TABLE_HIGHLIGHT_GAP, TABLE_SNAP_GAP } from '../ui/consts';
38
+ import { getTableWidth } from '../utils';
29
39
  import { defaultGuidelines, defaultGuidelineWidths } from '../utils/guidelines';
30
40
  import { findClosestSnap } from '../utils/snapping';
31
41
 
@@ -38,11 +48,37 @@ interface TableResizerProps {
38
48
  node: PMNode;
39
49
  tableRef: HTMLTableElement;
40
50
  displayGuideline: (guideline: GuidelineConfig[]) => boolean;
51
+ attachAnalyticsEvent: (
52
+ payload: TableEventPayload,
53
+ ) => ((tr: Transaction) => boolean) | undefined;
41
54
  }
42
55
 
43
56
  const handles = { right: true };
44
57
  const tableHandleMarginTop = 11;
45
58
 
59
+ const generateResizedPayload = (props: {
60
+ originalNode: PMNode;
61
+ resizedNode: PMNode;
62
+ }): TableEventPayload => {
63
+ const tableMap = TableMap.get(props.resizedNode);
64
+
65
+ return {
66
+ action: TABLE_ACTION.RESIZED,
67
+ actionSubject: ACTION_SUBJECT.TABLE,
68
+ eventType: EVENT_TYPE.TRACK,
69
+ attributes: {
70
+ newWidth: props.resizedNode.attrs.width,
71
+ prevWidth: props.originalNode.attrs.width ?? null,
72
+ nodeSize: props.resizedNode.nodeSize,
73
+ totalTableWidth: hasTableBeenResized(props.resizedNode)
74
+ ? getTableWidth(props.resizedNode)
75
+ : null,
76
+ totalRowCount: tableMap.height,
77
+ totalColumnCount: tableMap.width,
78
+ },
79
+ };
80
+ };
81
+
46
82
  export const TableResizer = ({
47
83
  children,
48
84
  width,
@@ -53,6 +89,7 @@ export const TableResizer = ({
53
89
  node,
54
90
  tableRef,
55
91
  displayGuideline,
92
+ attachAnalyticsEvent,
56
93
  }: PropsWithChildren<TableResizerProps>) => {
57
94
  const currentColumnCount = getColgroupChildrenLength(node);
58
95
  const minColumnWidth =
@@ -111,6 +148,7 @@ export const TableResizer = ({
111
148
  dispatch,
112
149
  state: { tr },
113
150
  } = editorView;
151
+
114
152
  dispatch(tr.setMeta(tableWidthPluginKey, { resizing: true }));
115
153
 
116
154
  setSnappingEnabled(displayGuideline(defaultGuidelines));
@@ -142,19 +180,73 @@ export const TableResizer = ({
142
180
  },
143
181
  editorView.domAtPos.bind(editorView),
144
182
  )(tr);
183
+
184
+ const scaledNode = tr.doc.nodeAt(pos)!;
185
+
186
+ attachAnalyticsEvent(
187
+ generateResizedPayload({
188
+ originalNode: node,
189
+ resizedNode: scaledNode,
190
+ }),
191
+ )?.(tr);
145
192
  }
146
193
 
147
194
  dispatch(tr);
148
195
 
149
196
  // Hide guidelines when resizing stops
150
197
  displayGuideline([]);
198
+ updateWidth(newWidth);
199
+
200
+ return newWidth;
201
+ },
202
+ [
203
+ updateWidth,
204
+ editorView,
205
+ getPos,
206
+ node,
207
+ tableRef,
208
+ displayGuideline,
209
+ attachAnalyticsEvent,
210
+ ],
211
+ );
212
+
213
+ const handleResize = useCallback(
214
+ (originalState, delta) => {
215
+ const newWidth = originalState.width + delta.width;
216
+ const pos = getPos();
217
+ if (typeof pos !== 'number') {
218
+ return;
219
+ }
220
+
221
+ previewScaleTable(
222
+ tableRef,
223
+ {
224
+ node,
225
+ prevNode: node,
226
+ start: pos + 1,
227
+ parentWidth: newWidth,
228
+ },
229
+ editorView.domAtPos.bind(editorView),
230
+ );
231
+
232
+ updateActiveGuidelines(
233
+ findClosestSnap(
234
+ newWidth,
235
+ defaultGuidelineWidths,
236
+ defaultGuidelines,
237
+ TABLE_HIGHLIGHT_GAP,
238
+ ),
239
+ );
151
240
 
152
241
  updateWidth(newWidth);
242
+
153
243
  return newWidth;
154
244
  },
155
- [updateWidth, editorView, getPos, node, tableRef, displayGuideline],
245
+ [editorView, getPos, node, tableRef, updateWidth, updateActiveGuidelines],
156
246
  );
157
247
 
248
+ const scheduleResize = useMemo(() => rafSchd(handleResize), [handleResize]);
249
+
158
250
  return (
159
251
  <ResizerNext
160
252
  enable={handles}
@@ -163,36 +255,7 @@ export const TableResizer = ({
163
255
  handleHeightSize={handleHeightSize}
164
256
  handleMarginTop={tableHandleMarginTop}
165
257
  handleResizeStart={handleResizeStart}
166
- handleResize={rafSchd((originalState, delta) => {
167
- const newWidth = originalState.width + delta.width;
168
- const pos = getPos();
169
- if (typeof pos !== 'number') {
170
- return;
171
- }
172
-
173
- previewScaleTable(
174
- tableRef,
175
- {
176
- node,
177
- prevNode: node,
178
- start: pos + 1,
179
- parentWidth: newWidth,
180
- },
181
- editorView.domAtPos.bind(editorView),
182
- );
183
-
184
- updateActiveGuidelines(
185
- findClosestSnap(
186
- newWidth,
187
- defaultGuidelineWidths,
188
- defaultGuidelines,
189
- TABLE_HIGHLIGHT_GAP,
190
- ),
191
- );
192
-
193
- updateWidth(newWidth);
194
- return newWidth;
195
- })}
258
+ handleResize={scheduleResize}
196
259
  handleResizeStop={handleResizeStop}
197
260
  resizeRatio={2}
198
261
  minWidth={minColumnWidth}
@@ -40,28 +40,6 @@ const anyChildCellMergedAcrossRow = (node: PmNode) =>
40
40
  (rowspan) => rowspan > 1,
41
41
  );
42
42
 
43
- /**
44
- * Compare two table row nodes and return true if the two table rows have a
45
- * different number of table cells or if table cell row spans are different
46
- */
47
- const rowHasDifferentMergedCells = (prevNode: PmNode, incomingNode: PmNode) => {
48
- const incomingNodeChildrenRowSpan = mapChildren(
49
- prevNode,
50
- (child) => child.attrs.rowspan || 0,
51
- );
52
- const currentNodeChildrenRowSpan = mapChildren(
53
- incomingNode,
54
- (child) => child.attrs.rowspan || 0,
55
- );
56
-
57
- return (
58
- incomingNodeChildrenRowSpan.length !== currentNodeChildrenRowSpan.length ||
59
- currentNodeChildrenRowSpan.some(
60
- (child, index) => child !== incomingNodeChildrenRowSpan[index],
61
- )
62
- );
63
- };
64
-
65
43
  /**
66
44
  * Check if a given node is a header row with this definition:
67
45
  * - all children are tableHeader cells
@@ -429,10 +407,6 @@ export class TableRowNodeView implements NodeView {
429
407
  return false; // re-create nodeview
430
408
  }
431
409
 
432
- if (rowHasDifferentMergedCells(this.node, node)) {
433
- return false;
434
- }
435
-
436
410
  // node is different but no need to re-create nodeview
437
411
  this.node = node;
438
412