@atlaskit/editor-plugin-table 0.2.6 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/cjs/plugins/table/commands/index.js +9 -1
  3. package/dist/cjs/plugins/table/commands/referentiality.js +23 -0
  4. package/dist/cjs/plugins/table/event-handlers.js +5 -1
  5. package/dist/cjs/plugins/table/nodeviews/table.js +10 -1
  6. package/dist/cjs/plugins/table/nodeviews/tableCell.js +5 -1
  7. package/dist/cjs/plugins/table/pm-plugins/decorations/plugin.js +1 -0
  8. package/dist/cjs/plugins/table/pm-plugins/decorations/utils/column-controls.js +1 -3
  9. package/dist/cjs/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +15 -12
  10. package/dist/cjs/plugins/table/toolbar.js +78 -35
  11. package/dist/cjs/plugins/table/ui/common-styles.js +6 -3
  12. package/dist/cjs/plugins/table/ui/messages.js +17 -2
  13. package/dist/cjs/plugins/table/ui/ui-styles.js +2 -7
  14. package/dist/cjs/plugins/table/utils/decoration.js +19 -12
  15. package/dist/cjs/version.json +1 -1
  16. package/dist/es2019/plugins/table/commands/index.js +2 -1
  17. package/dist/es2019/plugins/table/commands/referentiality.js +10 -0
  18. package/dist/es2019/plugins/table/event-handlers.js +3 -1
  19. package/dist/es2019/plugins/table/nodeviews/table.js +13 -1
  20. package/dist/es2019/plugins/table/nodeviews/tableCell.js +5 -1
  21. package/dist/es2019/plugins/table/pm-plugins/decorations/plugin.js +1 -0
  22. package/dist/es2019/plugins/table/pm-plugins/decorations/utils/column-controls.js +1 -2
  23. package/dist/es2019/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +16 -11
  24. package/dist/es2019/plugins/table/toolbar.js +65 -29
  25. package/dist/es2019/plugins/table/ui/common-styles.js +15 -5
  26. package/dist/es2019/plugins/table/ui/messages.js +17 -2
  27. package/dist/es2019/plugins/table/ui/ui-styles.js +24 -16
  28. package/dist/es2019/plugins/table/utils/decoration.js +22 -13
  29. package/dist/es2019/version.json +1 -1
  30. package/dist/esm/plugins/table/commands/index.js +2 -1
  31. package/dist/esm/plugins/table/commands/referentiality.js +12 -0
  32. package/dist/esm/plugins/table/event-handlers.js +5 -1
  33. package/dist/esm/plugins/table/nodeviews/table.js +10 -1
  34. package/dist/esm/plugins/table/nodeviews/tableCell.js +5 -1
  35. package/dist/esm/plugins/table/pm-plugins/decorations/plugin.js +1 -0
  36. package/dist/esm/plugins/table/pm-plugins/decorations/utils/column-controls.js +1 -2
  37. package/dist/esm/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +15 -12
  38. package/dist/esm/plugins/table/toolbar.js +74 -29
  39. package/dist/esm/plugins/table/ui/common-styles.js +6 -3
  40. package/dist/esm/plugins/table/ui/messages.js +17 -2
  41. package/dist/esm/plugins/table/ui/ui-styles.js +2 -6
  42. package/dist/esm/plugins/table/utils/decoration.js +19 -12
  43. package/dist/esm/version.json +1 -1
  44. package/dist/types/plugins/table/commands/index.d.ts +1 -0
  45. package/dist/types/plugins/table/commands/referentiality.d.ts +2 -0
  46. package/dist/types/plugins/table/index.d.ts +2 -3
  47. package/dist/types/plugins/table/nodeviews/table.d.ts +4 -1
  48. package/dist/types/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.d.ts +0 -1
  49. package/dist/types/plugins/table/ui/common-styles.d.ts +4 -1
  50. package/dist/types/plugins/table/ui/messages.d.ts +15 -0
  51. package/package.json +6 -6
  52. package/report.api.md +6 -6
  53. package/src/__tests__/integration/__fixtures__/table-and-paragraph-adf.json +130 -0
  54. package/src/__tests__/integration/floating-toolbar.ts +54 -0
  55. package/src/__tests__/integration/meta-arrowup-cursor-in-first-row.ts +37 -0
  56. package/src/__tests__/unit/color-picker.ts +100 -0
  57. package/src/__tests__/unit/get-toolbar-config.ts +1 -4
  58. package/src/__tests__/unit/keymap.ts +1 -1
  59. package/src/__tests__/unit/nodeviews/cell.ts +52 -57
  60. package/src/__tests__/unit/pm-plugins/sticky-headers/tableRow.tsx +90 -8
  61. package/src/__tests__/unit/transforms/delete-columns.ts +1 -1
  62. package/src/__tests__/unit/transforms/delete-rows.ts +1 -1
  63. package/src/__tests__/unit/utils/collapse.ts +2 -2
  64. package/src/__tests__/visual-regression/__image_snapshots__/cell-options-menu-ts-table-cell-options-menu-delete-row-menu-item-should-remove-the-table-row-on-click-1-snap.png +2 -2
  65. package/src/plugins/table/commands/index.ts +1 -0
  66. package/src/plugins/table/commands/referentiality.ts +14 -0
  67. package/src/plugins/table/event-handlers.ts +7 -1
  68. package/src/plugins/table/index.tsx +6 -1
  69. package/src/plugins/table/nodeviews/table.tsx +16 -1
  70. package/src/plugins/table/nodeviews/tableCell.tsx +3 -1
  71. package/src/plugins/table/pm-plugins/decorations/plugin.ts +1 -0
  72. package/src/plugins/table/pm-plugins/decorations/utils/column-controls.ts +1 -1
  73. package/src/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.ts +12 -10
  74. package/src/plugins/table/toolbar.tsx +84 -28
  75. package/src/plugins/table/ui/common-styles.ts +20 -4
  76. package/src/plugins/table/ui/messages.ts +18 -3
  77. package/src/plugins/table/ui/ui-styles.ts +23 -14
  78. package/src/plugins/table/utils/decoration.ts +36 -20
  79. package/dist/cjs/plugins/table/utils/referentiality.js +0 -29
  80. package/dist/es2019/plugins/table/utils/referentiality.js +0 -18
  81. package/dist/esm/plugins/table/utils/referentiality.js +0 -20
  82. package/dist/types/plugins/table/utils/referentiality.d.ts +0 -2
  83. package/src/plugins/table/utils/referentiality.ts +0 -24
@@ -81,17 +81,12 @@ var columnControlsLineMarker = function columnControlsLineMarker(props) {
81
81
  };
82
82
 
83
83
  exports.columnControlsLineMarker = columnControlsLineMarker;
84
- var DeleteButton = (0, _react.css)(_templateObject13 || (_templateObject13 = (0, _taggedTemplateLiteral2.default)(["\n .", ",\n .", " {\n height: ", "px;\n width: ", "px;\n }\n .", " {\n .", " {\n ", "\n }\n }\n\n .", ":hover {\n background: ", ";\n color: ", ";\n cursor: pointer;\n }\n"])), _types.TableCssClassName.CONTROLS_DELETE_BUTTON_WRAP, _types.TableCssClassName.CONTROLS_DELETE_BUTTON, _consts.tableDeleteButtonSize, _consts.tableDeleteButtonSize, _types.TableCssClassName.CONTROLS_DELETE_BUTTON_WRAP, _types.TableCssClassName.CONTROLS_DELETE_BUTTON, Button("\n background: ".concat((0, _tokens.token)('color.background.neutral', _colors.N20A), ";\n color: ").concat((0, _tokens.token)('color.icon', _colors.N300), ";\n ")), _types.TableCssClassName.CONTROLS_DELETE_BUTTON, (0, _tokens.token)('color.background.danger.bold', _colors.R300), (0, _tokens.token)('color.icon.inverse', 'white')); // TODO: https://product-fabric.atlassian.net/browse/DSP-4451
85
-
86
- /* eslint-disable @atlaskit/design-system/ensure-design-token-usage */
87
-
84
+ var DeleteButton = (0, _react.css)(_templateObject13 || (_templateObject13 = (0, _taggedTemplateLiteral2.default)(["\n .", ",\n .", " {\n height: ", "px;\n width: ", "px;\n }\n .", " {\n .", " {\n ", "\n }\n }\n\n .", ":hover {\n background: ", ";\n color: ", ";\n cursor: pointer;\n }\n"])), _types.TableCssClassName.CONTROLS_DELETE_BUTTON_WRAP, _types.TableCssClassName.CONTROLS_DELETE_BUTTON, _consts.tableDeleteButtonSize, _consts.tableDeleteButtonSize, _types.TableCssClassName.CONTROLS_DELETE_BUTTON_WRAP, _types.TableCssClassName.CONTROLS_DELETE_BUTTON, Button("\n background: ".concat((0, _tokens.token)('color.background.neutral', _colors.N20A), ";\n color: ").concat((0, _tokens.token)('color.icon', _colors.N300), ";\n ")), _types.TableCssClassName.CONTROLS_DELETE_BUTTON, (0, _tokens.token)('color.background.danger.bold', _colors.R300), (0, _tokens.token)('color.icon.inverse', 'white'));
88
85
  exports.DeleteButton = DeleteButton;
89
86
 
90
87
  var OverflowShadow = function OverflowShadow(props) {
91
- return (0, _react.css)(_templateObject14 || (_templateObject14 = (0, _taggedTemplateLiteral2.default)(["\n .", ", .", " {\n display: block;\n height: calc(\n 100% - ", "px\n );\n position: absolute;\n pointer-events: none;\n top: ", "px;\n z-index: ", ";\n width: 8px;\n }\n .", " {\n background: linear-gradient(to left, rgba(99, 114, 130, 0) 0, ", " 100%);\n left: 0px;\n }\n .", "[data-number-column='true'] > :not(.", ").", " {\n left: ", "px;\n }\n .", " {\n background: linear-gradient(\n to right,\n rgba(99, 114, 130, 0) 0,\n ", " 100%\n );\n left: calc(100% + 2px);\n }\n .", " {\n .", ", .", " {\n height: calc(100% - ", "px);\n top: ", "px;\n }\n .", " {\n border-left: 1px solid ", ";\n }\n }\n"])), _types.TableCssClassName.TABLE_RIGHT_SHADOW, _types.TableCssClassName.TABLE_LEFT_SHADOW, _styles.tableMarginTop + _styles.tableMarginBottom + _consts.tableToolbarSize - 2, _styles.tableMarginTop + _consts.tableToolbarSize - 1, _editorSharedStyles.akEditorShadowZIndex, _types.TableCssClassName.TABLE_LEFT_SHADOW, _colors.N40A, _types.TableCssClassName.TABLE_CONTAINER, _types.TableCssClassName.TABLE_STICKY_SHADOW, _types.TableCssClassName.TABLE_LEFT_SHADOW, _editorSharedStyles.akEditorTableNumberColumnWidth - 1, _types.TableCssClassName.TABLE_RIGHT_SHADOW, _colors.N40A, _types.TableCssClassName.WITH_CONTROLS, _types.TableCssClassName.TABLE_RIGHT_SHADOW, _types.TableCssClassName.TABLE_LEFT_SHADOW, _styles.tableMarginTop + _styles.tableMarginBottom - 2, _styles.tableMarginTop - 1, _types.TableCssClassName.TABLE_LEFT_SHADOW, (0, _consts.tableBorderColor)(props));
88
+ return (0, _react.css)(_templateObject14 || (_templateObject14 = (0, _taggedTemplateLiteral2.default)(["\n .", ", .", " {\n display: block;\n height: calc(100% - ", "px);\n position: absolute;\n pointer-events: none;\n top: ", "px;\n z-index: ", ";\n width: 8px;\n }\n .", " {\n background: linear-gradient(\n to left,\n transparent 0,\n ", " 100%\n ),\n linear-gradient(\n to right,\n ", " 0px,\n transparent 1px\n );\n left: 0px;\n }\n .", "[data-number-column='true'] > :not(.", ").", " {\n left: ", "px;\n }\n .", " {\n background: linear-gradient(\n to right,\n transparent 0,\n ", " 100%\n ),\n linear-gradient(\n to left,\n ", " 0px,\n transparent 1px\n );\n left: calc(100% + 2px);\n }\n .", " {\n .", ", .", " {\n height: calc(100% - ", "px);\n top: ", "px;\n }\n .", " {\n border-left: 1px solid ", ";\n }\n }\n"])), _types.TableCssClassName.TABLE_RIGHT_SHADOW, _types.TableCssClassName.TABLE_LEFT_SHADOW, _styles.tableMarginTop + _styles.tableMarginBottom, _styles.tableMarginTop, _editorSharedStyles.akEditorShadowZIndex, _types.TableCssClassName.TABLE_LEFT_SHADOW, (0, _tokens.token)('elevation.shadow.overflow.spread', _colors.N40A), (0, _tokens.token)('elevation.shadow.overflow.perimeter', 'transparent'), _types.TableCssClassName.TABLE_CONTAINER, _types.TableCssClassName.TABLE_STICKY_SHADOW, _types.TableCssClassName.TABLE_LEFT_SHADOW, _editorSharedStyles.akEditorTableNumberColumnWidth - 1, _types.TableCssClassName.TABLE_RIGHT_SHADOW, (0, _tokens.token)('elevation.shadow.overflow.spread', _colors.N40A), (0, _tokens.token)('elevation.shadow.overflow.perimeter', 'transparent'), _types.TableCssClassName.WITH_CONTROLS, _types.TableCssClassName.TABLE_RIGHT_SHADOW, _types.TableCssClassName.TABLE_LEFT_SHADOW, _styles.tableMarginTop + _styles.tableMarginBottom, _styles.tableMarginTop, _types.TableCssClassName.TABLE_LEFT_SHADOW, (0, _consts.tableBorderColor)(props));
92
89
  };
93
- /* eslint-enable @atlaskit/design-system/ensure-design-token-usage */
94
-
95
90
 
96
91
  exports.OverflowShadow = OverflowShadow;
97
92
 
@@ -163,16 +163,21 @@ var createColumnControlsDecoration = function createColumnControlsDecoration(sel
163
163
  var cells = (0, _utils.getCellsInRow)(0)(selection) || [];
164
164
  var index = 0;
165
165
  return cells.map(function (cell) {
166
- var colspan = cell.node.attrs.colspan || 1;
167
- var element = document.createElement('div');
168
- element.classList.add(_types.TableCssClassName.COLUMN_CONTROLS_DECORATIONS);
169
- element.dataset.startIndex = "".concat(index);
170
- index += colspan;
171
- element.dataset.endIndex = "".concat(index);
166
+ var colspan = cell.node.attrs.colspan || 1; // It's important these values are scoped locally as the widget callback could be executed anytime in the future
167
+ // and we want to avoid value leak
168
+
169
+ var startIndex = index;
170
+ var endIndex = startIndex + colspan; // The next cell start index will commence from the current cell end index.
171
+
172
+ index = endIndex;
172
173
  return _prosemirrorView.Decoration.widget(cell.pos + 1, function () {
174
+ var element = document.createElement('div');
175
+ element.classList.add(_types.TableCssClassName.COLUMN_CONTROLS_DECORATIONS);
176
+ element.dataset.startIndex = "".concat(startIndex);
177
+ element.dataset.endIndex = "".concat(endIndex);
173
178
  return element;
174
179
  }, {
175
- key: "".concat(_types.TableDecorations.COLUMN_CONTROLS_DECORATIONS, "_").concat(index),
180
+ key: "".concat(_types.TableDecorations.COLUMN_CONTROLS_DECORATIONS, "_").concat(endIndex),
176
181
  // this decoration should be the first one, even before gap cursor.
177
182
  side: -100
178
183
  });
@@ -288,12 +293,14 @@ var createResizeHandleDecoration = function createResizeHandleDecoration(tr, row
288
293
  }
289
294
 
290
295
  var createResizerHandleDecoration = function createResizerHandleDecoration(cellColumnPositioning, columnIndex, rowIndex, cellPos, cellNode) {
291
- var element = document.createElement('div');
292
- element.classList.add(_types.TableCssClassName.RESIZE_HANDLE_DECORATION);
293
- element.dataset.startIndex = "".concat(cellColumnPositioning.left);
294
- element.dataset.endIndex = "".concat(cellColumnPositioning.right);
295
296
  var position = cellPos + cellNode.nodeSize - 1;
296
- return _prosemirrorView.Decoration.widget(position, element, {
297
+ return _prosemirrorView.Decoration.widget(position, function () {
298
+ var element = document.createElement('div');
299
+ element.classList.add(_types.TableCssClassName.RESIZE_HANDLE_DECORATION);
300
+ element.dataset.startIndex = "".concat(cellColumnPositioning.left);
301
+ element.dataset.endIndex = "".concat(cellColumnPositioning.right);
302
+ return element;
303
+ }, {
297
304
  key: "".concat(_types.TableDecorations.COLUMN_RESIZING_HANDLE, "_").concat(rowIndex, "_").concat(columnIndex)
298
305
  });
299
306
  };
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-table",
3
- "version": "0.2.6",
3
+ "version": "1.0.1",
4
4
  "sideEffects": false
5
5
  }
@@ -4,4 +4,5 @@ export { getNextLayout, toggleContextualMenu, toggleHeaderColumn, toggleHeaderRo
4
4
  export { clearMultipleCells } from './clear';
5
5
  export { autoSizeTable, convertFirstRowToHeader, deleteTable, hideInsertColumnOrRowButton, moveCursorBackward, selectColumn, selectRow, setCellAttr, setEditorFocus, setMultipleCellAttrs, setTableRef, showInsertColumnButton, showInsertRowButton, transformSliceToAddTableHeaders, triggerUnlessTableHeader, addBoldInEmptyHeaderCells, addResizeHandleDecorations } from './misc';
6
6
  export { sortByColumn } from './sort';
7
- export { goToNextCell } from './go-to-next-cell';
7
+ export { goToNextCell } from './go-to-next-cell';
8
+ export { removeDescendantNodes } from './referentiality';
@@ -0,0 +1,10 @@
1
+ import { createCommand } from '../pm-plugins/plugin-factory';
2
+ import { removeConnectedNodes } from '@atlaskit/editor-common/utils';
3
+ export const removeDescendantNodes = sourceNode => createCommand({
4
+ type: 'UPDATE_STATE',
5
+ data: {
6
+ element: undefined
7
+ }
8
+ }, (tr, state) => {
9
+ return sourceNode ? removeConnectedNodes(state, sourceNode) : tr;
10
+ });
@@ -18,6 +18,8 @@ const isFocusingCalendar = event => event instanceof FocusEvent && event.related
18
18
 
19
19
  const isFocusingModal = event => event instanceof FocusEvent && event.relatedTarget instanceof HTMLElement && event.relatedTarget.closest('[role="dialog"]');
20
20
 
21
+ const isFocusingFloatingToolbar = event => event instanceof FocusEvent && event.relatedTarget instanceof HTMLElement && event.relatedTarget.closest('[role="toolbar"]');
22
+
21
23
  export const handleBlur = (view, event) => {
22
24
  const {
23
25
  state,
@@ -25,7 +27,7 @@ export const handleBlur = (view, event) => {
25
27
  } = view; // IE version check for ED-4665
26
28
  // Calendar focus check for ED-10466
27
29
 
28
- if (browser.ie_version !== 11 && !isFocusingCalendar(event) && !isFocusingModal(event)) {
30
+ if (browser.ie_version !== 11 && !isFocusingCalendar(event) && !isFocusingModal(event) && !isFocusingFloatingToolbar(event)) {
29
31
  setEditorFocus(false)(state, dispatch);
30
32
  }
31
33
 
@@ -164,7 +164,19 @@ export default class TableView extends ReactNodeView {
164
164
  return super.viewShouldUpdate(nextNode);
165
165
  }
166
166
 
167
- ignoreMutation() {
167
+ ignoreMutation(mutation) {
168
+ const {
169
+ type,
170
+ target: {
171
+ nodeName,
172
+ firstChild
173
+ }
174
+ } = mutation;
175
+
176
+ if (type === 'selection' && (nodeName === null || nodeName === void 0 ? void 0 : nodeName.toUpperCase()) === 'DIV' && (firstChild === null || firstChild === void 0 ? void 0 : firstChild.nodeName.toUpperCase()) === 'TABLE') {
177
+ return false;
178
+ }
179
+
168
180
  return true;
169
181
  }
170
182
 
@@ -63,7 +63,11 @@ export default class TableCellNodeView {
63
63
 
64
64
  update(node) {
65
65
  const didUpdate = this.updateNodeView(node);
66
- this.node = node;
66
+
67
+ if (didUpdate) {
68
+ this.node = node;
69
+ }
70
+
67
71
  return didUpdate;
68
72
  }
69
73
 
@@ -38,6 +38,7 @@ export const createPlugin = () => {
38
38
  }
39
39
 
40
40
  if (tr.docChanged || tr.selectionSet) {
41
+ pluginState = pluginState.map(tr.mapping, tr.doc);
41
42
  return handleDocOrSelectionChanged(tr, pluginState, oldState);
42
43
  }
43
44
 
@@ -1,6 +1,5 @@
1
1
  import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
2
2
  import { findTable } from '@atlaskit/editor-tables/utils';
3
- import { DecorationSet } from 'prosemirror-view';
4
3
  import { TableDecorations } from '../../../types';
5
4
  import { createColumnControlsDecoration, createColumnSelectedDecoration, findColumnControlSelectedDecoration, findControlsHoverDecoration, updateDecorations } from '../../../utils/decoration';
6
5
  import { composeDecorations } from './compose-decorations';
@@ -61,7 +60,7 @@ export const buildColumnControlsDecorations = ({
61
60
  tr
62
61
  }) => {
63
62
  return composeDecorations([removeColumnControlsSelectedDecoration, removeControlsHoverDecoration, maybeUpdateColumnSelectedDecoration, maybeUpdateColumnControlsDecoration])({
64
- decorationSet: DecorationSet.empty,
63
+ decorationSet,
65
64
  tr
66
65
  });
67
66
  };
@@ -138,14 +138,6 @@ export class TableRowNodeView {
138
138
 
139
139
  if (!tree) {
140
140
  return;
141
- } // make it non-sticky initially to avoid making it look separated
142
-
143
-
144
- if (!this.isTableInit) {
145
- if (this.tree) {
146
- this.makeRowHeaderNotSticky(this.tree.table);
147
- this.isTableInit = true;
148
- }
149
141
  } // when header rows are toggled off - mark sentinels as unobserved
150
142
 
151
143
 
@@ -157,7 +149,11 @@ export class TableRowNodeView {
157
149
  });
158
150
  }
159
151
 
160
- const isCurrentTableSelected = tableRef === tree.table;
152
+ const isCurrentTableSelected = tableRef === tree.table; // If current table selected and header row is toggled off, turn off sticky header
153
+
154
+ if (isCurrentTableSelected && !state.isHeaderRowEnabled && this.tree) {
155
+ this.makeRowHeaderNotSticky(this.tree.table);
156
+ }
161
157
 
162
158
  if (isCurrentTableSelected !== this.focused) {
163
159
  focusChanged = true;
@@ -236,6 +232,8 @@ export class TableRowNodeView {
236
232
  });
237
233
 
238
234
  _defineProperty(this, "makeHeaderRowSticky", tree => {
235
+ var _tbody$firstChild;
236
+
239
237
  // If header row height is more than 50% of viewport height don't do this
240
238
  if (this.stickyRowHeight && this.stickyRowHeight > window.innerHeight / 2) {
241
239
  return;
@@ -243,7 +241,15 @@ export class TableRowNodeView {
243
241
 
244
242
  const {
245
243
  table
246
- } = tree;
244
+ } = tree; // ED-16035 Make sure sticky header is only applied to first row
245
+
246
+ const tbody = this.dom.parentElement;
247
+ const isFirstHeader = tbody === null || tbody === void 0 ? void 0 : (_tbody$firstChild = tbody.firstChild) === null || _tbody$firstChild === void 0 ? void 0 : _tbody$firstChild.isEqualNode(this.dom);
248
+
249
+ if (!isFirstHeader) {
250
+ return;
251
+ }
252
+
247
253
  const currentTableTop = this.getCurrentTableTop(tree);
248
254
  const domTop = currentTableTop > 0 ? this.topPosEditorElement : this.topPosEditorElement + currentTableTop;
249
255
 
@@ -335,7 +341,6 @@ export class TableRowNodeView {
335
341
  this.lastTimePainted = 0;
336
342
  this.isHeaderRow = supportedHeaderRow(node);
337
343
  this.isSticky = false;
338
- this.isTableInit = false;
339
344
 
340
345
  if (this.isHeaderRow) {
341
346
  this.dom.setAttribute('data-header-row', 'true');
@@ -3,13 +3,13 @@ import { jsx } from '@emotion/react';
3
3
  import { defineMessages } from 'react-intl-next';
4
4
  import RemoveIcon from '@atlaskit/icon/glyph/editor/remove';
5
5
  import commonMessages from '@atlaskit/editor-common/messages';
6
- import { clearHoverSelection, hoverTable, hoverColumns, hoverRows } from './commands';
6
+ import { clearHoverSelection, hoverTable, hoverColumns, hoverRows, removeDescendantNodes } from './commands';
7
7
  import { deleteTableWithAnalytics, toggleHeaderColumnWithAnalytics, toggleHeaderRowWithAnalytics, toggleNumberColumnWithAnalytics, insertRowWithAnalytics, deleteRowsWithAnalytics, mergeCellsWithAnalytics, splitCellWithAnalytics, deleteColumnsWithAnalytics, emptyMultipleCellsWithAnalytics, insertColumnWithAnalytics, wrapTableInExpandWithAnalytics, sortColumnWithAnalytics, setColorWithAnalytics, distributeColumnsWidthsWithAnalytics } from './commands-with-analytics';
8
8
  import { getPluginState } from './pm-plugins/plugin-factory';
9
9
  import { pluginKey as tableResizingPluginKey } from './pm-plugins/table-resizing';
10
10
  import { TableCssClassName } from './types';
11
11
  import { getMergedCellsPositions, getSelectedColumnIndexes, getSelectedRowIndexes } from './utils';
12
- import { isReferencedSource } from './utils/referentiality';
12
+ import { isReferencedSource, getChildrenInfo, getNodeName } from '@atlaskit/editor-common/utils';
13
13
  import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
14
14
  import { findCellRectClosestToPos, findTable, getSelectionRect, isSelectionType } from '@atlaskit/editor-tables/utils';
15
15
  import { canMergeCells } from './transforms';
@@ -83,6 +83,7 @@ export const getToolbarMenuConfig = (config, state, {
83
83
  return {
84
84
  id: 'editor.table.tableOptions',
85
85
  type: 'dropdown',
86
+ testId: 'table_options',
86
87
  title: formatMessage(messages.tableOptions),
87
88
  hidden: options.every(option => option.hidden),
88
89
  options
@@ -158,16 +159,9 @@ export const getToolbarCellOptionsConfig = (editorState, editorView, initialSele
158
159
 
159
160
  return true;
160
161
  },
161
- onMouseOver: (state, dispatch) => {
162
- const selectionRect = getClosestSelectionRect(state);
163
-
164
- if (selectionRect) {
165
- hoverColumns(getSelectedColumnIndexes(selectionRect), true)(state, dispatch);
166
- return true;
167
- }
168
-
169
- return false;
170
- },
162
+ onFocus: highlightColumnsHandler,
163
+ onBlur: clearHoverSelection(),
164
+ onMouseOver: highlightColumnsHandler,
171
165
  onMouseLeave: clearHoverSelection(),
172
166
  selected: false,
173
167
  disabled: false
@@ -185,16 +179,9 @@ export const getToolbarCellOptionsConfig = (editorState, editorView, initialSele
185
179
 
186
180
  return true;
187
181
  },
188
- onMouseOver: (state, dispatch) => {
189
- const selectionRect = getClosestSelectionRect(state);
190
-
191
- if (selectionRect) {
192
- hoverRows(getSelectedRowIndexes(selectionRect), true)(state, dispatch);
193
- return true;
194
- }
195
-
196
- return false;
197
- },
182
+ onFocus: highlightRowsHandler,
183
+ onBlur: clearHoverSelection(),
184
+ onMouseOver: highlightRowsHandler,
198
185
  onMouseLeave: clearHoverSelection(),
199
186
  selected: false,
200
187
  disabled: false
@@ -283,6 +270,7 @@ export const getToolbarCellOptionsConfig = (editorState, editorView, initialSele
283
270
  });
284
271
  return {
285
272
  id: 'editor.table.cellOptions',
273
+ testId: 'cell_options',
286
274
  type: 'dropdown',
287
275
  title: formatMessage(tableMessages.cellOptions),
288
276
  options,
@@ -312,13 +300,20 @@ export const getToolbarConfig = (getEditorContainerWidth, editorAnalyticsAPI, ge
312
300
  const colorPicker = getColorPicker(state, menu, intl, getEditorContainerWidth, editorAnalyticsAPI, tableCellOptionsInFloatingToolbar); // Check if we need to show confirm dialog for delete button
313
301
 
314
302
  let confirmDialog;
315
- const localId = tableObject.node.attrs.localId;
316
303
 
317
- if (localId && isReferencedSource(state, localId)) {
318
- confirmDialog = {
304
+ if (isReferencedSource(state, tableObject.node)) {
305
+ confirmDialog = () => ({
306
+ title: intl.formatMessage(tableMessages.deleteElementTitle),
319
307
  okButtonLabel: intl.formatMessage(tableMessages.confirmDeleteLinkedModalOKButton),
320
- message: intl.formatMessage(tableMessages.confirmDeleteLinkedModalMessage)
321
- };
308
+ message: intl.formatMessage(tableMessages.confirmDeleteLinkedModalMessage, {
309
+ nodeName: getNodeName(state, tableObject.node)
310
+ }),
311
+ messagePrefix: intl.formatMessage(tableMessages.confirmDeleteLinkedModalMessagePrefix),
312
+ isReferentialityDialog: true,
313
+ getChildrenInfo: () => getChildrenInfo(state, tableObject.node),
314
+ checkboxLabel: intl.formatMessage(tableMessages.confirmModalCheckboxLabel),
315
+ onConfirm: (isChecked = false) => clickWithCheckboxHandler(isChecked, tableObject.node)
316
+ });
322
317
  }
323
318
 
324
319
  const getDomRef = editorView => {
@@ -354,7 +349,9 @@ export const getToolbarConfig = (getEditorContainerWidth, editorAnalyticsAPI, ge
354
349
  formatMessage: intl.formatMessage,
355
350
  nodeType,
356
351
  onMouseEnter: hoverTable(false, true),
357
- onMouseLeave: clearHoverSelection()
352
+ onMouseLeave: clearHoverSelection(),
353
+ onFocus: hoverTable(false, true),
354
+ onBlur: clearHoverSelection()
358
355
  }, {
359
356
  type: 'separator'
360
357
  }]
@@ -366,8 +363,11 @@ export const getToolbarConfig = (getEditorContainerWidth, editorAnalyticsAPI, ge
366
363
  onClick: deleteTableWithAnalytics(editorAnalyticsAPI),
367
364
  disabled: !!resizeState && !!resizeState.dragging,
368
365
  onMouseEnter: hoverTable(true),
366
+ onFocus: hoverTable(true),
367
+ onBlur: clearHoverSelection(),
369
368
  onMouseLeave: clearHoverSelection(),
370
369
  title: intl.formatMessage(commonMessages.remove),
370
+ focusEditoronEnter: true,
371
371
  confirmDialog
372
372
  }],
373
373
  scrollable: true
@@ -423,7 +423,7 @@ const getColorPicker = (state, menu, {
423
423
  border: DEFAULT_BORDER_COLOR
424
424
  };
425
425
  return [{
426
- id: 'editor.panel.colorPicker',
426
+ id: 'editor.table.colorPicker',
427
427
  title: formatMessage(ContextualMenuMessages.cellBackground),
428
428
  type: 'select',
429
429
  selectType: 'color',
@@ -431,4 +431,40 @@ const getColorPicker = (state, menu, {
431
431
  options: cellBackgroundColorPalette,
432
432
  onChange: option => setColorWithAnalytics(editorAnalyticsAPI)(INPUT_METHOD.FLOATING_TB, option.value, targetCellPosition)
433
433
  }, separator(menu.hidden)];
434
+ };
435
+
436
+ const clickWithCheckboxHandler = (isChecked, node, editorAnalyticsAPI) => (state, dispatch) => {
437
+ if (!node) {
438
+ return false;
439
+ }
440
+
441
+ if (!isChecked) {
442
+ return deleteTableWithAnalytics(editorAnalyticsAPI)(state, dispatch);
443
+ } else {
444
+ removeDescendantNodes(node)(state, dispatch);
445
+ }
446
+
447
+ return true;
448
+ };
449
+
450
+ const highlightRowsHandler = (state, dispatch) => {
451
+ const selectionRect = getClosestSelectionRect(state);
452
+
453
+ if (selectionRect) {
454
+ hoverRows(getSelectedRowIndexes(selectionRect), true)(state, dispatch);
455
+ return true;
456
+ }
457
+
458
+ return false;
459
+ };
460
+
461
+ const highlightColumnsHandler = (state, dispatch) => {
462
+ const selectionRect = getClosestSelectionRect(state);
463
+
464
+ if (selectionRect) {
465
+ hoverColumns(getSelectedColumnIndexes(selectionRect), true)(state, dispatch);
466
+ return true;
467
+ }
468
+
469
+ return false;
434
470
  };
@@ -47,10 +47,17 @@ const sentinelStyles = `.${ClassName.TABLE_CONTAINER} {
47
47
  margin-bottom: ${columnControlsDecorationHeight}px;
48
48
  }
49
49
  }
50
- }`; // TODO: https://product-fabric.atlassian.net/browse/DSP-4139
50
+ }`; // previous styles to add spacing to numbered lists with
51
+ // large item markers (e.g. 101, 102, ...) when nested inside tables
52
+
53
+ const listLargeNumericMarkersOldStyles = `
54
+ .ProseMirror .pm-table-cell-content-wrap ol[data-child-count='100+'] {
55
+ padding-left: revert;
56
+ }
57
+ `; // TODO: https://product-fabric.atlassian.net/browse/DSP-4139
51
58
 
52
59
  export const tableStyles = props => {
53
- var _props$featureFlags;
60
+ var _props$featureFlags, _props$featureFlags2;
54
61
 
55
62
  return css`
56
63
  .${ClassName.LAYOUT_BUTTON} button {
@@ -625,9 +632,12 @@ export const tableStyles = props => {
625
632
  cursor: col-resize;
626
633
  }
627
634
 
628
- .ProseMirror .pm-table-cell-content-wrap ol[data-child-count='100+'] {
629
- padding-left: revert;
630
- }
635
+ /*
636
+ ED-15882: When custom start numbers is enabled for lists, we have
637
+ styles that handle this generally (in editor-common) so we can
638
+ throw away the older table-specific styles here.
639
+ */
640
+ ${props !== null && props !== void 0 && (_props$featureFlags2 = props.featureFlags) !== null && _props$featureFlags2 !== void 0 && _props$featureFlags2.restartNumberedLists ? `` : listLargeNumericMarkersOldStyles}
631
641
  `;
632
642
  };
633
643
  export const tableFullPageEditorStyles = css`
@@ -27,12 +27,27 @@ export default defineMessages({
27
27
  },
28
28
  confirmDeleteLinkedModalOKButton: {
29
29
  id: 'fabric.editor.tables.confirmDeleteLinkedModalOKButton',
30
- defaultMessage: 'Remove table and data',
30
+ defaultMessage: 'Delete',
31
31
  description: 'Action button label for confirm modal when deleting a table linked to an extension.'
32
32
  },
33
33
  confirmDeleteLinkedModalMessage: {
34
34
  id: 'fabric.editor.tables.confirmDeleteLinkedModalMessage',
35
- defaultMessage: 'Removing this table will break all the charts connected to it.',
35
+ defaultMessage: 'Deleting {nodeName} will break anything connected to it.',
36
36
  description: 'Message for confirm modal when deleting a table linked to an extension.'
37
+ },
38
+ confirmDeleteLinkedModalMessagePrefix: {
39
+ id: 'fabric.editor.extension.confirmDeleteLinkedModalMessagePrefix',
40
+ defaultMessage: 'Deleting',
41
+ description: 'prefix for confirmation dialog text'
42
+ },
43
+ confirmModalCheckboxLabel: {
44
+ id: 'fabric.editor.floatingToolbar.confirmModalCheckboxLabel',
45
+ defaultMessage: 'Also delete connected elements',
46
+ description: 'checkbox label text'
47
+ },
48
+ deleteElementTitle: {
49
+ id: 'fabric.editor.extension.deleteElementTitle',
50
+ defaultMessage: 'Delete element',
51
+ description: 'Title text for confirm modal when deleting an extension linked to a data consumer.'
37
52
  }
38
53
  });
@@ -186,24 +186,28 @@ export const DeleteButton = css`
186
186
  color: ${token('color.icon.inverse', 'white')};
187
187
  cursor: pointer;
188
188
  }
189
- `; // TODO: https://product-fabric.atlassian.net/browse/DSP-4451
190
-
191
- /* eslint-disable @atlaskit/design-system/ensure-design-token-usage */
192
-
189
+ `;
193
190
  export const OverflowShadow = props => css`
194
191
  .${ClassName.TABLE_RIGHT_SHADOW}, .${ClassName.TABLE_LEFT_SHADOW} {
195
192
  display: block;
196
- height: calc(
197
- 100% - ${tableMarginTop + tableMarginBottom + tableToolbarSize - 2}px
198
- );
193
+ height: calc(100% - ${tableMarginTop + tableMarginBottom}px);
199
194
  position: absolute;
200
195
  pointer-events: none;
201
- top: ${tableMarginTop + tableToolbarSize - 1}px;
196
+ top: ${tableMarginTop}px;
202
197
  z-index: ${akEditorShadowZIndex};
203
198
  width: 8px;
204
199
  }
205
200
  .${ClassName.TABLE_LEFT_SHADOW} {
206
- background: linear-gradient(to left, rgba(99, 114, 130, 0) 0, ${N40A} 100%);
201
+ background: linear-gradient(
202
+ to left,
203
+ transparent 0,
204
+ ${token('elevation.shadow.overflow.spread', N40A)} 100%
205
+ ),
206
+ linear-gradient(
207
+ to right,
208
+ ${token('elevation.shadow.overflow.perimeter', 'transparent')} 0px,
209
+ transparent 1px
210
+ );
207
211
  left: 0px;
208
212
  }
209
213
  .${ClassName.TABLE_CONTAINER}[data-number-column='true'] > :not(.${ClassName.TABLE_STICKY_SHADOW}).${ClassName.TABLE_LEFT_SHADOW} {
@@ -211,23 +215,27 @@ export const OverflowShadow = props => css`
211
215
  }
212
216
  .${ClassName.TABLE_RIGHT_SHADOW} {
213
217
  background: linear-gradient(
214
- to right,
215
- rgba(99, 114, 130, 0) 0,
216
- ${N40A} 100%
217
- );
218
+ to right,
219
+ transparent 0,
220
+ ${token('elevation.shadow.overflow.spread', N40A)} 100%
221
+ ),
222
+ linear-gradient(
223
+ to left,
224
+ ${token('elevation.shadow.overflow.perimeter', 'transparent')} 0px,
225
+ transparent 1px
226
+ );
218
227
  left: calc(100% + 2px);
219
228
  }
220
229
  .${ClassName.WITH_CONTROLS} {
221
230
  .${ClassName.TABLE_RIGHT_SHADOW}, .${ClassName.TABLE_LEFT_SHADOW} {
222
- height: calc(100% - ${tableMarginTop + tableMarginBottom - 2}px);
223
- top: ${tableMarginTop - 1}px;
231
+ height: calc(100% - ${tableMarginTop + tableMarginBottom}px);
232
+ top: ${tableMarginTop}px;
224
233
  }
225
234
  .${ClassName.TABLE_LEFT_SHADOW} {
226
235
  border-left: 1px solid ${tableBorderColor(props)};
227
236
  }
228
237
  }
229
238
  `;
230
- /* eslint-enable @atlaskit/design-system/ensure-design-token-usage */
231
239
 
232
240
  const columnHeaderButton = (props, cssString) => css`
233
241
  background: ${tableToolbarColor(props)};
@@ -110,14 +110,21 @@ export const createColumnControlsDecoration = selection => {
110
110
  const cells = getCellsInRow(0)(selection) || [];
111
111
  let index = 0;
112
112
  return cells.map(cell => {
113
- const colspan = cell.node.attrs.colspan || 1;
114
- const element = document.createElement('div');
115
- element.classList.add(ClassName.COLUMN_CONTROLS_DECORATIONS);
116
- element.dataset.startIndex = `${index}`;
117
- index += colspan;
118
- element.dataset.endIndex = `${index}`;
119
- return Decoration.widget(cell.pos + 1, () => element, {
120
- key: `${TableDecorations.COLUMN_CONTROLS_DECORATIONS}_${index}`,
113
+ const colspan = cell.node.attrs.colspan || 1; // It's important these values are scoped locally as the widget callback could be executed anytime in the future
114
+ // and we want to avoid value leak
115
+
116
+ const startIndex = index;
117
+ const endIndex = startIndex + colspan; // The next cell start index will commence from the current cell end index.
118
+
119
+ index = endIndex;
120
+ return Decoration.widget(cell.pos + 1, () => {
121
+ const element = document.createElement('div');
122
+ element.classList.add(ClassName.COLUMN_CONTROLS_DECORATIONS);
123
+ element.dataset.startIndex = `${startIndex}`;
124
+ element.dataset.endIndex = `${endIndex}`;
125
+ return element;
126
+ }, {
127
+ key: `${TableDecorations.COLUMN_CONTROLS_DECORATIONS}_${endIndex}`,
121
128
  // this decoration should be the first one, even before gap cursor.
122
129
  side: -100
123
130
  });
@@ -226,12 +233,14 @@ export const createResizeHandleDecoration = (tr, rowIndexTarget, columnEndIndexT
226
233
  }
227
234
 
228
235
  const createResizerHandleDecoration = (cellColumnPositioning, columnIndex, rowIndex, cellPos, cellNode) => {
229
- const element = document.createElement('div');
230
- element.classList.add(ClassName.RESIZE_HANDLE_DECORATION);
231
- element.dataset.startIndex = `${cellColumnPositioning.left}`;
232
- element.dataset.endIndex = `${cellColumnPositioning.right}`;
233
236
  const position = cellPos + cellNode.nodeSize - 1;
234
- return Decoration.widget(position, element, {
237
+ return Decoration.widget(position, () => {
238
+ const element = document.createElement('div');
239
+ element.classList.add(ClassName.RESIZE_HANDLE_DECORATION);
240
+ element.dataset.startIndex = `${cellColumnPositioning.left}`;
241
+ element.dataset.endIndex = `${cellColumnPositioning.right}`;
242
+ return element;
243
+ }, {
235
244
  key: `${TableDecorations.COLUMN_RESIZING_HANDLE}_${rowIndex}_${columnIndex}`
236
245
  });
237
246
  };
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-table",
3
- "version": "0.2.6",
3
+ "version": "1.0.1",
4
4
  "sideEffects": false
5
5
  }
@@ -4,4 +4,5 @@ export { getNextLayout, toggleContextualMenu, toggleHeaderColumn, toggleHeaderRo
4
4
  export { clearMultipleCells } from './clear';
5
5
  export { autoSizeTable, convertFirstRowToHeader, deleteTable, hideInsertColumnOrRowButton, moveCursorBackward, selectColumn, selectRow, setCellAttr, setEditorFocus, setMultipleCellAttrs, setTableRef, showInsertColumnButton, showInsertRowButton, transformSliceToAddTableHeaders, triggerUnlessTableHeader, addBoldInEmptyHeaderCells, addResizeHandleDecorations } from './misc';
6
6
  export { sortByColumn } from './sort';
7
- export { goToNextCell } from './go-to-next-cell';
7
+ export { goToNextCell } from './go-to-next-cell';
8
+ export { removeDescendantNodes } from './referentiality';
@@ -0,0 +1,12 @@
1
+ import { createCommand } from '../pm-plugins/plugin-factory';
2
+ import { removeConnectedNodes } from '@atlaskit/editor-common/utils';
3
+ export var removeDescendantNodes = function removeDescendantNodes(sourceNode) {
4
+ return createCommand({
5
+ type: 'UPDATE_STATE',
6
+ data: {
7
+ element: undefined
8
+ }
9
+ }, function (tr, state) {
10
+ return sourceNode ? removeConnectedNodes(state, sourceNode) : tr;
11
+ });
12
+ };