@atlaskit/editor-plugin-table 22.4.2 → 22.4.4

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,22 @@
1
1
  # @atlaskit/editor-plugin-table
2
2
 
3
+ ## 22.4.4
4
+
5
+ ### Patch Changes
6
+
7
+ - [`4c459a2718b67`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/4c459a2718b67) -
8
+ Clean up synced block feature gates
9
+ - Updated dependencies
10
+
11
+ ## 22.4.3
12
+
13
+ ### Patch Changes
14
+
15
+ - [`3a69722c61c6a`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/3a69722c61c6a) -
16
+ Add rounded corners to table node in editor. This works by hiding the actual table border and
17
+ adding a pseudo element with rounded corners.
18
+ - Updated dependencies
19
+
3
20
  ## 22.4.2
4
21
 
5
22
  ### Patch Changes
@@ -14,6 +14,8 @@ var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits
14
14
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
15
15
  var _adfSchema = require("@atlaskit/adf-schema");
16
16
  var _analytics = require("@atlaskit/editor-common/analytics");
17
+ var _editorTables = require("@atlaskit/editor-tables");
18
+ var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
17
19
  var _TableNodeViewBase = _interopRequireDefault(require("./TableNodeViewBase"));
18
20
  function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2.default)(o), (0, _possibleConstructorReturn2.default)(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2.default)(t).constructor) : o.apply(t, e)); }
19
21
  function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
@@ -49,6 +51,22 @@ var TableCell = exports.default = /*#__PURE__*/function (_TableNodeView) {
49
51
  var _this;
50
52
  (0, _classCallCheck2.default)(this, TableCell);
51
53
  _this = _callSuper(this, TableCell, [node, view, getPos, eventDispatcher]);
54
+ /** Cached edge state to avoid redundant DOM writes. */
55
+ (0, _defineProperty2.default)(_this, "prevReachesTop", false);
56
+ (0, _defineProperty2.default)(_this, "prevReachesBottom", false);
57
+ (0, _defineProperty2.default)(_this, "prevReachesLeft", false);
58
+ (0, _defineProperty2.default)(_this, "prevReachesRight", false);
59
+ (0, _defineProperty2.default)(_this, "destroy", function () {
60
+ if (_this.delayHandle && typeof window !== 'undefined') {
61
+ var _window, _window$cancelIdleCal, _window2, _window2$cancelAnimat;
62
+ // eslint-disable-next-line compat/compat
63
+ (_window = window) === null || _window === void 0 || (_window$cancelIdleCal = _window.cancelIdleCallback) === null || _window$cancelIdleCal === void 0 || _window$cancelIdleCal.call(_window, _this.delayHandle);
64
+ (_window2 = window) === null || _window2 === void 0 || (_window2$cancelAnimat = _window2.cancelAnimationFrame) === null || _window2$cancelAnimat === void 0 || _window2$cancelAnimat.call(_window2, _this.delayHandle);
65
+ }
66
+ });
67
+ if ((0, _expValEquals.expValEquals)('platform_editor_table_q4_loveability', 'isEnabled', true)) {
68
+ _this.updateTableEdgeAttrs(node);
69
+ }
52
70
 
53
71
  // CONFCLOUD-78239: Previously we had a bug which tried to invert the heading colour of a table
54
72
  // Obviously design tokens can't be inverted and so it would result in `VAR(--DS-BACKGROUND-ACCENT-GRAY-SUBTLEST, #F4F5F7)`
@@ -60,14 +78,6 @@ var TableCell = exports.default = /*#__PURE__*/function (_TableNodeView) {
60
78
  // This is a workaround to fix those cases on the fly. Note it is super specific on purpose
61
79
  // so that it just fixes the heading token (other tokens should be unaffected)
62
80
  // At some point in the future
63
- (0, _defineProperty2.default)(_this, "destroy", function () {
64
- if (_this.delayHandle && typeof window !== 'undefined') {
65
- var _window, _window$cancelIdleCal, _window2, _window2$cancelAnimat;
66
- // eslint-disable-next-line compat/compat
67
- (_window = window) === null || _window === void 0 || (_window$cancelIdleCal = _window.cancelIdleCallback) === null || _window$cancelIdleCal === void 0 || _window$cancelIdleCal.call(_window, _this.delayHandle);
68
- (_window2 = window) === null || _window2 === void 0 || (_window2$cancelAnimat = _window2.cancelAnimationFrame) === null || _window2$cancelAnimat === void 0 || _window2$cancelAnimat.call(_window2, _this.delayHandle);
69
- }
70
- });
71
81
  if (cssVariablePattern.test(node.attrs.background)) {
72
82
  _this.delayHandle = delayUntilIdle(function () {
73
83
  var pos = getPos();
@@ -98,6 +108,70 @@ var TableCell = exports.default = /*#__PURE__*/function (_TableNodeView) {
98
108
  }
99
109
  return didUpdate;
100
110
  }
111
+
112
+ /**
113
+ * Detects whether this cell visually reaches the bottom or right edge of the table
114
+ * (accounting for rowspan/colspan) and sets data attributes so CSS can apply
115
+ * rounded corners and transparent borders to merged cells that span to the table edges.
116
+ */
117
+ }, {
118
+ key: "updateTableEdgeAttrs",
119
+ value: function updateTableEdgeAttrs(node) {
120
+ var pos = this.getPos();
121
+ if (pos === undefined) {
122
+ return;
123
+ }
124
+ try {
125
+ var resolvedPos = this.view.state.doc.resolve(pos);
126
+
127
+ // Cell → row → table: depth-1 is the table, depth is the row
128
+ var tableDepth = resolvedPos.depth - 1;
129
+ var rowDepth = resolvedPos.depth;
130
+ if (tableDepth < 0 || rowDepth < 0) {
131
+ return;
132
+ }
133
+ var tableNode = resolvedPos.node(tableDepth);
134
+ if (tableNode.type.name !== 'table') {
135
+ return;
136
+ }
137
+ var tableMap = _editorTables.TableMap.get(tableNode);
138
+ var cellStartInTable = pos - resolvedPos.start(tableDepth);
139
+ var cellRect = tableMap.findCell(cellStartInTable);
140
+ var reachesTop = cellRect.top === 0;
141
+ var reachesBottom = cellRect.bottom >= tableMap.height;
142
+ var reachesLeft = cellRect.left === 0;
143
+ var reachesRight = cellRect.right >= tableMap.width;
144
+
145
+ // Only touch DOM attributes that actually changed
146
+ if (reachesTop !== this.prevReachesTop) {
147
+ this.prevReachesTop = reachesTop;
148
+ this.setDataAttr('data-reaches-top', reachesTop);
149
+ }
150
+ if (reachesBottom !== this.prevReachesBottom) {
151
+ this.prevReachesBottom = reachesBottom;
152
+ this.setDataAttr('data-reaches-bottom', reachesBottom);
153
+ }
154
+ if (reachesLeft !== this.prevReachesLeft) {
155
+ this.prevReachesLeft = reachesLeft;
156
+ this.setDataAttr('data-reaches-left', reachesLeft);
157
+ }
158
+ if (reachesRight !== this.prevReachesRight) {
159
+ this.prevReachesRight = reachesRight;
160
+ this.setDataAttr('data-reaches-right', reachesRight);
161
+ }
162
+ } catch (_unused) {
163
+ // Position may be stale during document mutations; silently ignore.
164
+ }
165
+ }
166
+ }, {
167
+ key: "setDataAttr",
168
+ value: function setDataAttr(attr, value) {
169
+ if (value) {
170
+ this.dom.setAttribute(attr, 'true');
171
+ } else {
172
+ this.dom.removeAttribute(attr);
173
+ }
174
+ }
101
175
  }, {
102
176
  key: "updateNodeView",
103
177
  value: function updateNodeView(node) {
@@ -137,6 +211,9 @@ var TableCell = exports.default = /*#__PURE__*/function (_TableNodeView) {
137
211
  removedAttrs.forEach(function (key) {
138
212
  return _this2.dom.removeAttribute(key);
139
213
  });
214
+ if ((0, _expValEquals.expValEquals)('platform_editor_table_q4_loveability', 'isEnabled', true)) {
215
+ this.updateTableEdgeAttrs(node);
216
+ }
140
217
  return true;
141
218
  }
142
219
 
@@ -143,7 +143,7 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
143
143
  var tablePos = _this.props.getPos();
144
144
  var isNested = (0, _nodes.isTableNested)(_this.props.view.state, tablePos);
145
145
  var parentWidth = _this.getParentNodeWidth();
146
- var useMeasuredWidthForBodiedSyncBlock = isNested && typeof tablePos === 'number' && (0, _nodes.isTableNestedUnderBodiedSyncBlock)(_this.props.view.state, tablePos) && (0, _platformFeatureFlags.fg)('platform_synced_block_patch_9');
146
+ var useMeasuredWidthForBodiedSyncBlock = isNested && typeof tablePos === 'number' && (0, _nodes.isTableNestedUnderBodiedSyncBlock)(_this.props.view.state, tablePos);
147
147
  if (useMeasuredWidthForBodiedSyncBlock) {
148
148
  // Prefer the live DOM measurement (`clientWidth`) over the ResizeObserver-cached
149
149
  // value (`wrapperWidth`) because clientWidth is synchronous and more up-to-date
@@ -64,6 +64,37 @@ var handleInlineTableWidth = function handleInlineTableWidth(table, width) {
64
64
  }
65
65
  table.style.setProperty('width', "".concat(width, "px"));
66
66
  };
67
+ var setDataAttr = function setDataAttr(cell, attr, value) {
68
+ var hasAttr = cell.hasAttribute(attr);
69
+ if (value && !hasAttr) {
70
+ cell.setAttribute(attr, 'true');
71
+ } else if (!value && hasAttr) {
72
+ cell.removeAttribute(attr);
73
+ }
74
+ };
75
+ var refreshRoundedTableEdgeAttrs = function refreshRoundedTableEdgeAttrs(table, tableNode) {
76
+ try {
77
+ var tableMap = _tableMap.TableMap.get(tableNode);
78
+ var cells = Array.from(table.rows).flatMap(function (row) {
79
+ return Array.from(row.cells);
80
+ });
81
+ var cellOffsets = Array.from(new Set(tableMap.map));
82
+ cellOffsets.forEach(function (cellOffset, cellIndex) {
83
+ var cell = cells[cellIndex];
84
+ if (!cell) {
85
+ return;
86
+ }
87
+ var cellRect = tableMap.findCell(cellOffset);
88
+ setDataAttr(cell, 'data-reaches-top', cellRect.top === 0);
89
+ setDataAttr(cell, 'data-reaches-bottom', cellRect.bottom >= tableMap.height);
90
+ setDataAttr(cell, 'data-reaches-left', cellRect.left === 0);
91
+ setDataAttr(cell, 'data-reaches-right', cellRect.right >= tableMap.width);
92
+ });
93
+ } catch (_unused) {
94
+ // Table structure can be transient while ProseMirror normalises transactions.
95
+ // Keep existing edge attrs if the current shape cannot be mapped safely.
96
+ }
97
+ };
67
98
  var TableView = exports.default = /*#__PURE__*/function (_ReactNodeView) {
68
99
  function TableView(props) {
69
100
  var _this;
@@ -248,6 +279,46 @@ var TableView = exports.default = /*#__PURE__*/function (_ReactNodeView) {
248
279
  }
249
280
  }
250
281
  }
282
+ }, {
283
+ key: "scheduleRoundedTableEdgeRefresh",
284
+ value:
285
+ // Each TableCell node view refreshes its own edge attrs when its cell attrs change.
286
+ // However, when the table's shape changes (e.g. a new row is inserted below the
287
+ // last row), ProseMirror may reuse the existing neighbouring cells as-is, so those
288
+ // cells never get a chance to update their edge attrs on their own.
289
+ //
290
+ // To cover those cases, we refresh edge attrs from the table node view here.
291
+ //
292
+ // The refresh runs on the next animation frame because ReactNodeView.update()
293
+ // schedules the table's React render via the portal provider. If we read
294
+ // `this.table.rows` synchronously, we'd still see the previous DOM.
295
+ function scheduleRoundedTableEdgeRefresh(node) {
296
+ var _this4 = this;
297
+ if (this.roundedTableEdgeRefreshHandle !== undefined) {
298
+ cancelAnimationFrame(this.roundedTableEdgeRefreshHandle);
299
+ }
300
+ this.roundedTableEdgeRefreshHandle = requestAnimationFrame(function () {
301
+ _this4.roundedTableEdgeRefreshHandle = undefined;
302
+ if (_this4.table instanceof HTMLTableElement) {
303
+ refreshRoundedTableEdgeAttrs(_this4.table, node);
304
+ }
305
+ });
306
+ }
307
+ }, {
308
+ key: "update",
309
+ value: function update(node, decorations, innerDecorations, validUpdate) {
310
+ if (!(0, _expValEquals.expValEquals)('platform_editor_table_q4_loveability', 'isEnabled', true)) {
311
+ return _superPropGet(TableView, "update", this, 3)([node, decorations, innerDecorations, validUpdate]);
312
+ }
313
+ var currentTableMap = _tableMap.TableMap.get(this.node);
314
+ var nextTableMap = _tableMap.TableMap.get(node);
315
+ var tableGeometryChanged = currentTableMap.width !== nextTableMap.width || currentTableMap.height !== nextTableMap.height;
316
+ var didUpdate = _superPropGet(TableView, "update", this, 3)([node, decorations, innerDecorations, validUpdate]);
317
+ if (didUpdate && tableGeometryChanged) {
318
+ this.scheduleRoundedTableEdgeRefresh(node);
319
+ }
320
+ return didUpdate;
321
+ }
251
322
  }, {
252
323
  key: "render",
253
324
  value: function render(props, forwardRef) {
@@ -325,6 +396,10 @@ var TableView = exports.default = /*#__PURE__*/function (_ReactNodeView) {
325
396
  key: "destroy",
326
397
  value: function destroy() {
327
398
  var _this$eventDispatcher;
399
+ if (this.roundedTableEdgeRefreshHandle !== undefined) {
400
+ cancelAnimationFrame(this.roundedTableEdgeRefreshHandle);
401
+ this.roundedTableEdgeRefreshHandle = undefined;
402
+ }
328
403
  if (this.resizeObserver) {
329
404
  this.resizeObserver.disconnect();
330
405
  }
@@ -11,7 +11,6 @@ var _nodeWidth = require("@atlaskit/editor-common/node-width");
11
11
  var _styles = require("@atlaskit/editor-common/styles");
12
12
  var _syncBlock = require("@atlaskit/editor-common/sync-block");
13
13
  var _editorSharedStyles = require("@atlaskit/editor-shared-styles");
14
- var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
15
14
  var _columnWidth = require("../../transforms/column-width");
16
15
  var _nodes = require("../../utils/nodes");
17
16
  var _misc = require("../utils/misc");
@@ -179,7 +178,7 @@ var scaleTable = exports.scaleTable = function scaleTable(tableRef, options, dom
179
178
  // table's outer width to exceed the colgroup width by 1px. Subtract 1px from the
180
179
  // parentWidth here so that the scaled colgroup fits within the sync-block
181
180
  // container without overflowing.
182
- var isNestedInBodiedSyncBlock = !!((_tableRef$closest = tableRef.closest) !== null && _tableRef$closest !== void 0 && _tableRef$closest.call(tableRef, ".".concat(_syncBlock.BodiedSyncBlockSharedCssClassName.content))) && (0, _platformFeatureFlags.fg)('platform_synced_block_patch_9');
181
+ var isNestedInBodiedSyncBlock = !!((_tableRef$closest = tableRef.closest) !== null && _tableRef$closest !== void 0 && _tableRef$closest.call(tableRef, ".".concat(_syncBlock.BodiedSyncBlockSharedCssClassName.content)));
183
182
  var BORDER_COLLAPSE_WIDTH_PX = 1;
184
183
  var adjustedParentWidth = isNestedInBodiedSyncBlock ? parentWidth - BORDER_COLLAPSE_WIDTH_PX : parentWidth;
185
184
  resizeState = scaleWithParent(tableRef, adjustedParentWidth, node, start, domAtPos, isTableScalingEnabledOnCurrentTable, shouldUseIncreasedScalingPercent);
@@ -80,9 +80,8 @@ var NumberColumn = exports.default = /*#__PURE__*/function (_Component) {
80
80
  style: {
81
81
  // eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage/preview
82
82
  marginTop: hasHeaderRow && this.props.stickyTop !== undefined ? rowHeights[0] : undefined,
83
- borderLeft:
84
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
85
- isDragAndDropEnabled && tableActive ? "1px solid ".concat(_consts.tableBorderColor) : undefined,
83
+ borderLeft: isDragAndDropEnabled && tableActive && !(0, _expValEquals.expValEquals)('platform_editor_table_q4_loveability', 'isEnabled', true) ? // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
84
+ "1px solid ".concat(_consts.tableBorderColor) : undefined,
86
85
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
87
86
  visibility: 'hidden' // Ensure the column is not visible during SSR
88
87
  },
@@ -95,9 +94,8 @@ var NumberColumn = exports.default = /*#__PURE__*/function (_Component) {
95
94
  style: {
96
95
  // eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage/preview
97
96
  marginTop: hasHeaderRow && this.props.stickyTop !== undefined ? rowHeights[0] : undefined,
98
- borderLeft:
99
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
100
- isDragAndDropEnabled && tableActive ? "1px solid ".concat(_consts.tableBorderColor) : undefined,
97
+ borderLeft: isDragAndDropEnabled && tableActive && !(0, _expValEquals.expValEquals)('platform_editor_table_q4_loveability', 'isEnabled', true) ? // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
98
+ "1px solid ".concat(_consts.tableBorderColor) : undefined,
101
99
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
102
100
  visibility: 'visible'
103
101
  },