@atlaskit/editor-plugin-table 7.10.2 → 7.11.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 (48) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/cjs/nodeviews/TableComponent.js +23 -2
  3. package/dist/cjs/plugin.js +6 -0
  4. package/dist/cjs/pm-plugins/table-selection-keymap.js +1 -3
  5. package/dist/cjs/pm-plugins/view-mode-sort/consts.js +9 -0
  6. package/dist/cjs/pm-plugins/view-mode-sort/index.js +304 -0
  7. package/dist/cjs/pm-plugins/view-mode-sort/plugin-key.js +8 -0
  8. package/dist/cjs/pm-plugins/view-mode-sort/types.js +5 -0
  9. package/dist/cjs/pm-plugins/view-mode-sort/utils.js +106 -0
  10. package/dist/cjs/ui/common-styles.js +22 -15
  11. package/dist/es2019/nodeviews/TableComponent.js +24 -2
  12. package/dist/es2019/plugin.js +6 -0
  13. package/dist/es2019/pm-plugins/table-selection-keymap.js +1 -3
  14. package/dist/es2019/pm-plugins/view-mode-sort/consts.js +3 -0
  15. package/dist/es2019/pm-plugins/view-mode-sort/index.js +243 -0
  16. package/dist/es2019/pm-plugins/view-mode-sort/plugin-key.js +2 -0
  17. package/dist/es2019/pm-plugins/view-mode-sort/types.js +1 -0
  18. package/dist/es2019/pm-plugins/view-mode-sort/utils.js +98 -0
  19. package/dist/es2019/ui/common-styles.js +35 -0
  20. package/dist/esm/nodeviews/TableComponent.js +23 -2
  21. package/dist/esm/plugin.js +6 -0
  22. package/dist/esm/pm-plugins/table-selection-keymap.js +1 -3
  23. package/dist/esm/pm-plugins/view-mode-sort/consts.js +3 -0
  24. package/dist/esm/pm-plugins/view-mode-sort/index.js +299 -0
  25. package/dist/esm/pm-plugins/view-mode-sort/plugin-key.js +2 -0
  26. package/dist/esm/pm-plugins/view-mode-sort/types.js +1 -0
  27. package/dist/esm/pm-plugins/view-mode-sort/utils.js +99 -0
  28. package/dist/esm/ui/common-styles.js +15 -8
  29. package/dist/types/pm-plugins/view-mode-sort/consts.d.ts +3 -0
  30. package/dist/types/pm-plugins/view-mode-sort/index.d.ts +10 -0
  31. package/dist/types/pm-plugins/view-mode-sort/plugin-key.d.ts +3 -0
  32. package/dist/types/pm-plugins/view-mode-sort/types.d.ts +17 -0
  33. package/dist/types/pm-plugins/view-mode-sort/utils.d.ts +15 -0
  34. package/dist/types-ts4.5/pm-plugins/view-mode-sort/consts.d.ts +3 -0
  35. package/dist/types-ts4.5/pm-plugins/view-mode-sort/index.d.ts +10 -0
  36. package/dist/types-ts4.5/pm-plugins/view-mode-sort/plugin-key.d.ts +3 -0
  37. package/dist/types-ts4.5/pm-plugins/view-mode-sort/types.d.ts +21 -0
  38. package/dist/types-ts4.5/pm-plugins/view-mode-sort/utils.d.ts +15 -0
  39. package/package.json +7 -7
  40. package/src/nodeviews/TableComponent.tsx +22 -0
  41. package/src/plugin.tsx +11 -0
  42. package/src/pm-plugins/table-selection-keymap.ts +5 -7
  43. package/src/pm-plugins/view-mode-sort/consts.ts +3 -0
  44. package/src/pm-plugins/view-mode-sort/index.ts +257 -0
  45. package/src/pm-plugins/view-mode-sort/plugin-key.ts +6 -0
  46. package/src/pm-plugins/view-mode-sort/types.ts +23 -0
  47. package/src/pm-plugins/view-mode-sort/utils.ts +120 -0
  48. package/src/ui/common-styles.ts +36 -0
@@ -0,0 +1,98 @@
1
+ import { SortOrder } from '@atlaskit/editor-common/types';
2
+ import { IS_DISABLED_CLASS_NAME, SORT_INDEX_DATA_ATTRIBUTE, SORTING_ICON_CLASS_NAME } from './consts';
3
+ export const unsort = (oldOrder, tableElement) => {
4
+ const rows = tableElement.querySelectorAll('tr');
5
+ const tbody = tableElement.querySelector('tbody');
6
+ const sortedOrder = [...oldOrder].sort((a, b) => a.value - b.value);
7
+ sortedOrder.forEach(item => {
8
+ tbody === null || tbody === void 0 ? void 0 : tbody.appendChild(rows[item.index + 1]);
9
+ });
10
+ };
11
+
12
+ // TODO - reuse sort logic from the Renderer and support switching between ASC, DESC and NO_ORDER
13
+ export const getSortOrderFromTable = (tableElement, sortIndex, direction) => {
14
+ const sortOrder = direction === SortOrder.DESC ? -1 : 1;
15
+ const strings = [];
16
+ tableElement.querySelectorAll('tr:not([data-header-row="true"])').forEach(tr => {
17
+ var _tr$querySelectorAll$;
18
+ strings.push(((_tr$querySelectorAll$ = tr.querySelectorAll('td')[sortIndex]) === null || _tr$querySelectorAll$ === void 0 ? void 0 : _tr$querySelectorAll$.textContent) || '');
19
+ });
20
+ const order = Array.from(strings.keys()).sort((a, b) => {
21
+ const string = strings[a] || '';
22
+ return string.localeCompare(strings[b] || '') * sortOrder;
23
+ }).map((value, index) => ({
24
+ value,
25
+ index
26
+ }));
27
+ // TODO - improve this. right now this is a workaround to ensure the first tr is always first in the order
28
+ return [{
29
+ value: -1,
30
+ index: -1
31
+ }, ...order];
32
+ };
33
+ export const toggleSort = (view, event, pluginState) => {
34
+ var _target$closest;
35
+ const target = event.target;
36
+ const widget = target.closest(`.${SORTING_ICON_CLASS_NAME}`);
37
+ if (widget !== null && widget !== void 0 && widget.classList.contains(IS_DISABLED_CLASS_NAME) || !widget) {
38
+ return;
39
+ }
40
+ let datasetortIndex = target === null || target === void 0 ? void 0 : (_target$closest = target.closest('.ProseMirror-widget')) === null || _target$closest === void 0 ? void 0 : _target$closest.getAttribute(SORT_INDEX_DATA_ATTRIBUTE);
41
+ const tr = view.state.tr;
42
+ const tableElement = target.closest('table');
43
+ if (!tableElement || !datasetortIndex) {
44
+ return;
45
+ }
46
+ const tableId = tableElement.getAttribute('data-table-local-id') || '';
47
+ let {
48
+ index,
49
+ direction,
50
+ order: oldOrder
51
+ } = (pluginState === null || pluginState === void 0 ? void 0 : pluginState[tableId]) || {};
52
+
53
+ // Unsort if there was already a sort
54
+ if (direction !== SortOrder.NO_ORDER && oldOrder !== undefined) {
55
+ unsort(oldOrder, tableElement);
56
+ }
57
+ const sortIndex = parseInt(datasetortIndex);
58
+ if (sortIndex === index) {
59
+ switch (direction) {
60
+ case SortOrder.NO_ORDER:
61
+ direction = SortOrder.ASC;
62
+ break;
63
+ case SortOrder.ASC:
64
+ direction = SortOrder.DESC;
65
+ break;
66
+ case SortOrder.DESC:
67
+ direction = SortOrder.NO_ORDER;
68
+ break;
69
+ }
70
+ } else {
71
+ direction = SortOrder.ASC; // default direction when a new index is clicked
72
+ }
73
+ const order = getSortOrderFromTable(tableElement, sortIndex, direction);
74
+ if (direction === SortOrder.NO_ORDER) {
75
+ tr.setMeta('tableSortMeta', {
76
+ [tableId]: {}
77
+ });
78
+ } else {
79
+ tr.setMeta('tableSortMeta', {
80
+ [tableId]: {
81
+ index: sortIndex,
82
+ direction,
83
+ order,
84
+ tableElement
85
+ }
86
+ });
87
+ }
88
+ view.dispatch(tr);
89
+ };
90
+ export const getTableElements = tableId => {
91
+ const tableElement = document.querySelector(`table[data-table-local-id="${tableId}"]`);
92
+ const tbody = tableElement === null || tableElement === void 0 ? void 0 : tableElement.querySelector('tbody');
93
+ const rows = tableElement === null || tableElement === void 0 ? void 0 : tableElement.querySelectorAll('tr');
94
+ return {
95
+ tbody,
96
+ rows
97
+ };
98
+ };
@@ -2,12 +2,14 @@
2
2
 
3
3
  import { css } from '@emotion/react';
4
4
  import { tableMarginTop, tableSharedStyle } from '@atlaskit/editor-common/styles';
5
+ import { SORTABLE_COLUMN_ICON_CLASSNAME } from '@atlaskit/editor-common/table';
5
6
  import { browser } from '@atlaskit/editor-common/utils';
6
7
  import { akEditorSelectedNodeClassName, akEditorSmallZIndex, akEditorStickyHeaderZIndex, akEditorTableCellOnStickyHeaderZIndex, akEditorTableNumberColumnWidth, akEditorTableToolbarSize, akEditorUnitZIndex, getSelectionStyles, MAX_BROWSER_SCROLLBAR_HEIGHT, relativeFontSizeToBase16, SelectionStyle } from '@atlaskit/editor-shared-styles';
7
8
  import { scrollbarStyles } from '@atlaskit/editor-shared-styles/scrollbar';
8
9
  import { getBooleanFF } from '@atlaskit/platform-feature-flags';
9
10
  import { N0, N40A, R500 } from '@atlaskit/theme/colors';
10
11
  import { fontSize } from '@atlaskit/theme/constants';
12
+ import { SORTING_ICON_CLASS_NAME } from '../pm-plugins/view-mode-sort/consts';
11
13
  import { TableCssClassName as ClassName } from '../types';
12
14
  import { columnControlsDecorationHeight, resizeHandlerAreaWidth, resizeHandlerZIndex, resizeLineWidth, rowControlsZIndex, stickyHeaderBorderBottomWidth, stickyRowOffsetTop, tableBorderColor, tableBorderDeleteColor, tableBorderRadiusSize, tableBorderSelectedColor, tableCellBackgroundColor, tableCellDeleteColor, tableCellSelectedColor, tableControlsSpacing, tableHeaderCellBackgroundColor, tableInsertColumnButtonSize, tableOverflowShadowWidth, tablePadding, tableScrollbarOffset, tableTextColor, tableToolbarDeleteColor, tableToolbarSelectedColor, tableToolbarSize } from './consts';
13
15
  import { columnControlsDecoration, columnControlsLineMarker, DeleteButton, dragCornerControlButton, dragInsertButtonWrapper, floatingColumnControls, HeaderButton, HeaderButtonDanger, HeaderButtonHover, hoveredCell, hoveredDeleteButton, hoveredWarningCell, insertColumnButtonWrapper, insertLine, InsertMarker, insertRowButtonWrapper, OverflowShadow, resizeHandle, rowControlsWrapperDotStyle } from './ui-styles';
@@ -123,6 +125,38 @@ const breakoutWidthStyling = () => {
123
125
  }
124
126
  `;
125
127
  };
128
+ const viewModeSortStyles = () => {
129
+ if (getBooleanFF('platform.editor.table.live-pages-sorting_4malx')) {
130
+ return css`
131
+ th {
132
+ .${SORTING_ICON_CLASS_NAME} {
133
+ + p {
134
+ margin-top: 0 !important;
135
+ }
136
+ }
137
+
138
+ &:has(.is-active) {
139
+ .${SORTABLE_COLUMN_ICON_CLASSNAME} {
140
+ opacity: 1;
141
+ }
142
+ }
143
+
144
+ .${SORTABLE_COLUMN_ICON_CLASSNAME} {
145
+ opacity: 0;
146
+ &:focus {
147
+ opacity: 1;
148
+ }
149
+ }
150
+
151
+ &:hover {
152
+ .${SORTABLE_COLUMN_ICON_CLASSNAME} {
153
+ opacity: 1;
154
+ }
155
+ }
156
+ }
157
+ `;
158
+ }
159
+ };
126
160
  const tableBorderStyles = () => {
127
161
  if (getBooleanFF('platform.editor.table.column-controls-styles-updated')) {
128
162
  return `border-color: ${tableBorderDeleteColor}`;
@@ -190,6 +224,7 @@ export const baseTableStyles = props => {
190
224
  ${((_props$featureFlags = props.featureFlags) === null || _props$featureFlags === void 0 ? void 0 : _props$featureFlags.tableDragAndDrop) && insertLine()};
191
225
  ${resizeHandle((_props$featureFlags2 = props.featureFlags) === null || _props$featureFlags2 === void 0 ? void 0 : _props$featureFlags2.tableDragAndDrop)};
192
226
  ${rangeSelectionStyles};
227
+ ${viewModeSortStyles()};
193
228
 
194
229
  .${ClassName.LAST_ITEM_IN_CELL} {
195
230
  margin-bottom: 0;
@@ -66,6 +66,14 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
66
66
  scroll: 0,
67
67
  parentWidth: undefined
68
68
  }, _defineProperty(_defineProperty2, ShadowEvent.SHOW_BEFORE_SHADOW, false), _defineProperty(_defineProperty2, ShadowEvent.SHOW_AFTER_SHADOW, false), _defineProperty(_defineProperty2, "tableWrapperWidth", undefined), _defineProperty(_defineProperty2, "tableWrapperHeight", undefined), _defineProperty2));
69
+ _defineProperty(_assertThisInitialized(_this), "handleMouseEnter", function () {
70
+ var node = _this.props.getNode();
71
+ var pos = _this.props.getPos();
72
+ var tr = _this.props.view.state.tr;
73
+ var tableId = node.attrs.localId;
74
+ tr.setMeta('mouseEnterTable', [tableId, node, pos]);
75
+ _this.props.view.dispatch(tr);
76
+ });
69
77
  _defineProperty(_assertThisInitialized(_this), "updateShadowState", function (shadowKey, value) {
70
78
  if (_this.state[shadowKey] === value) {
71
79
  return;
@@ -331,6 +339,15 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
331
339
  getNode = _this$props7.getNode,
332
340
  getEditorFeatureFlags = _this$props7.getEditorFeatureFlags,
333
341
  isTableScalingEnabled = _this$props7.isTableScalingEnabled;
342
+ if (getBooleanFF('platform.editor.table.live-pages-sorting_4malx')) {
343
+ var _this$props$pluginInj;
344
+ var _ref = ((_this$props$pluginInj = this.props.pluginInjectionApi) === null || _this$props$pluginInj === void 0 || (_this$props$pluginInj = _this$props$pluginInj.editorViewMode) === null || _this$props$pluginInj === void 0 ? void 0 : _this$props$pluginInj.sharedState.currentState()) || {},
345
+ mode = _ref.mode;
346
+ if (mode === 'view') {
347
+ var _this$table;
348
+ this === null || this === void 0 || (_this$table = this.table) === null || _this$table === void 0 || _this$table.addEventListener('mouseenter', this.handleMouseEnter);
349
+ }
350
+ }
334
351
  if (isTableScalingEnabled) {
335
352
  this.handleColgroupUpdates(true);
336
353
  }
@@ -406,6 +423,10 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
406
423
  if (!(options !== null && options !== void 0 && options.isTableResizingEnabled) && allowColumnResizing) {
407
424
  window.removeEventListener('resize', this.handleWindowResizeDebounced);
408
425
  }
426
+ if (getBooleanFF('platform.editor.table.live-pages-sorting_4malx')) {
427
+ var _this$table2;
428
+ this === null || this === void 0 || (_this$table2 = this.table) === null || _this$table2 === void 0 || _this$table2.removeEventListener('mouseenter', this.handleMouseEnter);
429
+ }
409
430
  if (this.overflowShadowsObserver) {
410
431
  this.overflowShadowsObserver.dispose();
411
432
  }
@@ -520,8 +541,8 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
520
541
  var isNoOfColumnsChanged = tablesHaveDifferentNoOfColumns(currentTable, previousTable);
521
542
  var isNoOfRowsChanged = tablesHaveDifferentNoOfRows(currentTable, previousTable);
522
543
  if (isNoOfColumnsChanged || isNoOfRowsChanged) {
523
- var _this$props$pluginInj;
524
- (_this$props$pluginInj = this.props.pluginInjectionApi) === null || _this$props$pluginInj === void 0 || (_this$props$pluginInj = _this$props$pluginInj.accessibilityUtils) === null || _this$props$pluginInj === void 0 || _this$props$pluginInj.actions.ariaNotify(getAssistiveMessage(previousTable, currentTable, this.props.intl), {
544
+ var _this$props$pluginInj2;
545
+ (_this$props$pluginInj2 = this.props.pluginInjectionApi) === null || _this$props$pluginInj2 === void 0 || (_this$props$pluginInj2 = _this$props$pluginInj2.accessibilityUtils) === null || _this$props$pluginInj2 === void 0 || _this$props$pluginInj2.actions.ariaNotify(getAssistiveMessage(previousTable, currentTable, this.props.intl), {
525
546
  priority: 'important'
526
547
  });
527
548
  }
@@ -27,6 +27,7 @@ import { createPlugin as createTableLocalIdPlugin } from './pm-plugins/table-loc
27
27
  import { createPlugin as createFlexiResizingPlugin, getPluginState as getFlexiResizingPlugin, pluginKey as tableResizingPluginKey } from './pm-plugins/table-resizing';
28
28
  import { tableSelectionKeymapPlugin } from './pm-plugins/table-selection-keymap';
29
29
  import { createPlugin as createTableWidthPlugin, pluginKey as tableWidthPluginKey } from './pm-plugins/table-width';
30
+ import { createPlugin as createViewModeSortPlugin } from './pm-plugins/view-mode-sort';
30
31
  import { getToolbarConfig } from './toolbar';
31
32
  import FloatingContextualButton from './ui/FloatingContextualButton';
32
33
  import FloatingContextualMenu from './ui/FloatingContextualMenu';
@@ -219,6 +220,11 @@ var tablesPlugin = function tablesPlugin(_ref) {
219
220
  var dispatch = _ref11.dispatch;
220
221
  return options !== null && options !== void 0 && options.dragAndDropEnabled ? createDragAndDropPlugin(dispatch, editorAnalyticsAPI) : undefined;
221
222
  }
223
+ }, {
224
+ name: 'tableViewModeSort',
225
+ plugin: function plugin() {
226
+ return getBooleanFF('platform.editor.table.live-pages-sorting_4malx') && api !== null && api !== void 0 && api.editorViewMode ? createViewModeSortPlugin(api.editorViewMode) : undefined;
227
+ }
222
228
  }, {
223
229
  name: 'tableLocalId',
224
230
  plugin: function plugin(_ref12) {
@@ -8,9 +8,7 @@ export function tableSelectionKeymapPlugin(editorSelectionAPI) {
8
8
  bindKeymapWithCommand(moveLeft.common, arrowLeftFromTable(editorSelectionAPI)(), list);
9
9
  bindKeymapArrayWithCommand(selectColumn, selectColumns(editorSelectionAPI)(true), list);
10
10
  bindKeymapArrayWithCommand(selectRow, selectRows(editorSelectionAPI)(true), list);
11
- if (getBooleanFF('platform.editor.table.shift-arrowup-fix')) {
12
- bindKeymapWithCommand(shiftArrowUp.common, shiftArrowUpFromTable(editorSelectionAPI)(), list);
13
- }
11
+ bindKeymapWithCommand(shiftArrowUp.common, shiftArrowUpFromTable(editorSelectionAPI)(), list);
14
12
  if (getBooleanFF('platform.editor.table.cmd-a-select-table')) {
15
13
  bindKeymapWithCommand(selectTable.common, modASelectTable(editorSelectionAPI)(), list);
16
14
  }
@@ -0,0 +1,3 @@
1
+ export var SORTING_ICON_CLASS_NAME = 'view-mode-sorting-icon';
2
+ export var IS_DISABLED_CLASS_NAME = 'is-disabled';
3
+ export var SORT_INDEX_DATA_ATTRIBUTE = 'data-sort-index';
@@ -0,0 +1,299 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
4
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
5
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
6
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
7
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
8
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
9
+ /**
10
+ * This plugin allows sorting of table nodes in the Editor without modifying the underlying ProseMirror document.
11
+ * Instead of making changes to the ProseMirror document, the plugin sorts the table rows in the DOM. This allows the sorting to be
12
+ * visible to the user without affecting the document's content.
13
+ */
14
+
15
+ import { createElement } from 'react';
16
+ import ReactDOM from 'react-dom';
17
+ import { RawIntlProvider } from 'react-intl-next';
18
+ import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
19
+ import { SortingIcon } from '@atlaskit/editor-common/table';
20
+ import { SortOrder } from '@atlaskit/editor-common/types';
21
+ import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
22
+ import { TableMap } from '@atlaskit/editor-tables/table-map';
23
+ import { getPluginState } from '../plugin-factory';
24
+ import { IS_DISABLED_CLASS_NAME, SORT_INDEX_DATA_ATTRIBUTE, SORTING_ICON_CLASS_NAME } from './consts';
25
+ import { tableViewModeSortPluginKey as key } from './plugin-key';
26
+ import { getTableElements, toggleSort } from './utils';
27
+ export var createPlugin = function createPlugin(editorViewModeAPI) {
28
+ return new SafePlugin({
29
+ state: {
30
+ init: function init() {
31
+ return {
32
+ decorations: DecorationSet.empty,
33
+ sort: {},
34
+ allTables: []
35
+ };
36
+ },
37
+ apply: function apply(tr, pluginState, oldState) {
38
+ // TODO - move this mode check to plugin creation if possible. Right now it's here because the initial state
39
+ // does not appear correct when the plugin is created.
40
+ var _ref = (editorViewModeAPI === null || editorViewModeAPI === void 0 ? void 0 : editorViewModeAPI.sharedState.currentState()) || {},
41
+ mode = _ref.mode;
42
+ if (mode !== 'view') {
43
+ return pluginState;
44
+ }
45
+ var decorations = pluginState.decorations,
46
+ sort = pluginState.sort,
47
+ allTables = pluginState.allTables;
48
+ var sortMeta = tr.getMeta('tableSortMeta');
49
+ var hoverTableMeta = tr.getMeta('mouseEnterTable');
50
+ var removeTableMeta = tr.getMeta('removeTable');
51
+ var tableId = '';
52
+
53
+ // Remove the table from the state
54
+ if (removeTableMeta) {
55
+ allTables = allTables.filter(function (_ref2) {
56
+ var _ref3 = _slicedToArray(_ref2, 1),
57
+ id = _ref3[0];
58
+ return id !== removeTableMeta;
59
+ });
60
+ } else {
61
+ tableId = hoverTableMeta === null || hoverTableMeta === void 0 ? void 0 : hoverTableMeta[0];
62
+ }
63
+ sort = _objectSpread(_objectSpread({}, sort), sortMeta);
64
+ var isTableInState = allTables.some(function (_ref4) {
65
+ var _ref5 = _slicedToArray(_ref4, 1),
66
+ id = _ref5[0];
67
+ return id === tableId;
68
+ });
69
+
70
+ // Update the table in the state
71
+ if (hoverTableMeta) {
72
+ allTables = allTables.filter(function (_ref6) {
73
+ var _ref7 = _slicedToArray(_ref6, 1),
74
+ id = _ref7[0];
75
+ return id !== hoverTableMeta[0];
76
+ });
77
+ allTables.push(hoverTableMeta);
78
+ }
79
+
80
+ /**
81
+ * Create decorations for the sorting icons
82
+ */
83
+ var decs = [];
84
+
85
+ // TODO - add support for keyboard only users
86
+ if (hoverTableMeta && !isTableInState || sortMeta) {
87
+ allTables.forEach(function (table) {
88
+ var _table = _slicedToArray(table, 3),
89
+ tableId = _table[0],
90
+ _node = _table[1],
91
+ pos = _table[2];
92
+ var tableNode = tr.doc.nodeAt(tr.mapping.map(pos));
93
+ if (!tableNode || tableNode.type.name !== 'table') {
94
+ return pluginState;
95
+ }
96
+ var map = TableMap.get(tableNode);
97
+ var hasMergedCells = new Set(map.map).size !== map.map.length;
98
+ map.mapByRow[0].forEach(function (cell, index) {
99
+ // return pluginState;
100
+ decs.push(Decoration.widget(cell + pos + 2, function () {
101
+ var _sort$tableId;
102
+ var element = document.createElement('div');
103
+ element.setAttribute(SORT_INDEX_DATA_ATTRIBUTE, "".concat(index));
104
+ element.classList.add(SORTING_ICON_CLASS_NAME);
105
+ if (hasMergedCells) {
106
+ element.classList.add(IS_DISABLED_CLASS_NAME);
107
+ }
108
+ var sortOrdered;
109
+ if (index === ((_sort$tableId = sort[tableId]) === null || _sort$tableId === void 0 ? void 0 : _sort$tableId.index)) {
110
+ var _sort$tableId2;
111
+ sortOrdered = (_sort$tableId2 = sort[tableId]) === null || _sort$tableId2 === void 0 ? void 0 : _sort$tableId2.direction;
112
+ } else {
113
+ sortOrdered = SortOrder.NO_ORDER;
114
+ }
115
+ var _getPluginState = getPluginState(oldState),
116
+ getIntl = _getPluginState.getIntl;
117
+ ReactDOM.render( /*#__PURE__*/createElement(RawIntlProvider, {
118
+ value: getIntl()
119
+ }, /*#__PURE__*/createElement(SortingIcon, {
120
+ isSortingAllowed: !hasMergedCells,
121
+ sortOrdered: sortOrdered,
122
+ onClick: function onClick() {},
123
+ onKeyDown: function onKeyDown() {}
124
+ })), element);
125
+ return element;
126
+ }));
127
+ });
128
+ });
129
+ decorations = DecorationSet.create(tr.doc, decs);
130
+ }
131
+
132
+ /**
133
+ * Map the decorations to the new document if there are changes
134
+ */
135
+ if (tr.docChanged) {
136
+ decorations = decorations.map(tr.mapping, tr.doc);
137
+ allTables = allTables.map(function (table) {
138
+ return [table[0], table[1], tr.mapping.map(table[2])];
139
+ });
140
+ }
141
+ return {
142
+ decorations: decorations,
143
+ sort: sort,
144
+ allTables: allTables
145
+ };
146
+ }
147
+ },
148
+ key: key,
149
+ appendTransaction: function appendTransaction(trs, oldState, newState) {
150
+ var _key$getState;
151
+ // return newState.tr;
152
+ var _ref8 = (editorViewModeAPI === null || editorViewModeAPI === void 0 ? void 0 : editorViewModeAPI.sharedState.currentState()) || {},
153
+ mode = _ref8.mode;
154
+ if (mode !== 'view') {
155
+ return newState.tr;
156
+ }
157
+ var allTables = ((_key$getState = key.getState(newState)) === null || _key$getState === void 0 ? void 0 : _key$getState.allTables) || [];
158
+
159
+ /**
160
+ * If incoming changes have affected a table node, remove the sorting. This prevents the
161
+ * table from breaking if changes like merged cells are incoming.
162
+ */
163
+ var _iterator = _createForOfIteratorHelper(trs),
164
+ _step;
165
+ try {
166
+ var _loop = function _loop() {
167
+ var tr = _step.value;
168
+ var hoverTableMeta = tr.getMeta('mouseEnterTable');
169
+ if (hoverTableMeta) {
170
+ allTables = allTables.filter(function (_ref9) {
171
+ var _ref10 = _slicedToArray(_ref9, 1),
172
+ id = _ref10[0];
173
+ return id !== hoverTableMeta[0];
174
+ });
175
+ allTables.push(hoverTableMeta);
176
+ }
177
+ var isRemote = tr.getMeta('isRemote');
178
+ var isDocChanged = tr.docChanged;
179
+ var isChangesIncoming = isRemote && isDocChanged;
180
+ var oldPluginState = key.getState(oldState);
181
+ var newPluginState = key.getState(newState);
182
+ var _iterator2 = _createForOfIteratorHelper(allTables),
183
+ _step2;
184
+ try {
185
+ var _loop2 = function _loop2() {
186
+ var _oldPluginState$sort, _newPluginState$sort;
187
+ var table = _step2.value;
188
+ var _table2 = _slicedToArray(table, 3),
189
+ tableId = _table2[0],
190
+ node = _table2[1],
191
+ pos = _table2[2];
192
+ var _ref11 = (oldPluginState === null || oldPluginState === void 0 || (_oldPluginState$sort = oldPluginState.sort) === null || _oldPluginState$sort === void 0 ? void 0 : _oldPluginState$sort[tableId]) || {},
193
+ oldOrder = _ref11.order,
194
+ oldDirection = _ref11.direction,
195
+ oldIndex = _ref11.index;
196
+ if (isChangesIncoming) {
197
+ var _maybeTableNode$attrs;
198
+ var maybeTableNode = tr.doc.nodeAt(pos);
199
+ var isTableNodeChanged = (maybeTableNode === null || maybeTableNode === void 0 || (_maybeTableNode$attrs = maybeTableNode.attrs) === null || _maybeTableNode$attrs === void 0 ? void 0 : _maybeTableNode$attrs.localId) !== tableId || !node.eq(maybeTableNode);
200
+ if (isTableNodeChanged) {
201
+ var newtr = newState.tr;
202
+ newtr.setMeta('tableSortMeta', _defineProperty({}, tableId, {}));
203
+ newtr.setMeta('removeTable', tableId);
204
+
205
+ // Unsort the table here
206
+ if (oldOrder !== undefined) {
207
+ var _getTableElements = getTableElements(tableId),
208
+ rows = _getTableElements.rows,
209
+ tbody = _getTableElements.tbody;
210
+ if (!rows || !tbody) {
211
+ return {
212
+ v: {
213
+ v: newtr
214
+ }
215
+ };
216
+ }
217
+ var sortedOrder = _toConsumableArray(oldOrder).sort(function (a, b) {
218
+ return a.value - b.value;
219
+ });
220
+ sortedOrder.forEach(function (index, i) {
221
+ tbody.appendChild(rows[index.index + 1]);
222
+ });
223
+ return {
224
+ v: {
225
+ v: newtr
226
+ }
227
+ };
228
+ }
229
+ }
230
+ }
231
+
232
+ /**
233
+ * Sort the table if the sort order has changed
234
+ */
235
+ var _ref12 = (newPluginState === null || newPluginState === void 0 || (_newPluginState$sort = newPluginState.sort) === null || _newPluginState$sort === void 0 ? void 0 : _newPluginState$sort[tableId]) || {},
236
+ newOrder = _ref12.order,
237
+ newDirection = _ref12.direction,
238
+ newIndex = _ref12.index;
239
+ var orderChanged = oldDirection !== newDirection || oldIndex !== newIndex;
240
+ if (orderChanged) {
241
+ if (!isRemote && newDirection !== SortOrder.NO_ORDER) {
242
+ var _getTableElements2 = getTableElements(tableId),
243
+ _rows = _getTableElements2.rows,
244
+ _tbody = _getTableElements2.tbody;
245
+ if (_rows && newOrder) {
246
+ newOrder.forEach(function (index, i) {
247
+ _tbody === null || _tbody === void 0 || _tbody.appendChild(_rows[index.value + 1]);
248
+ });
249
+ }
250
+ }
251
+ }
252
+ },
253
+ _ret2;
254
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
255
+ _ret2 = _loop2();
256
+ if (_ret2) return _ret2.v;
257
+ }
258
+ } catch (err) {
259
+ _iterator2.e(err);
260
+ } finally {
261
+ _iterator2.f();
262
+ }
263
+ },
264
+ _ret;
265
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
266
+ _ret = _loop();
267
+ if (_ret) return _ret.v;
268
+ }
269
+ } catch (err) {
270
+ _iterator.e(err);
271
+ } finally {
272
+ _iterator.f();
273
+ }
274
+ return newState.tr;
275
+ },
276
+ props: {
277
+ handleDOMEvents: {
278
+ keydown: function keydown(view, event) {
279
+ // TODO - fix the focus issue here, where toggling sort with a keypress loses focus
280
+ if (event.key === 'Enter' || event.key === ' ') {
281
+ var _key$getState2;
282
+ var pluginState = ((_key$getState2 = key.getState(view.state)) === null || _key$getState2 === void 0 ? void 0 : _key$getState2.sort) || {};
283
+ toggleSort(view, event, pluginState);
284
+ }
285
+ },
286
+ click: function click(view, event) {
287
+ var _key$getState3;
288
+ var pluginState = ((_key$getState3 = key.getState(view.state)) === null || _key$getState3 === void 0 ? void 0 : _key$getState3.sort) || {};
289
+ toggleSort(view, event, pluginState);
290
+ }
291
+ },
292
+ decorations: function decorations(state) {
293
+ var _key$getState4;
294
+ var decs = ((_key$getState4 = key.getState(state)) === null || _key$getState4 === void 0 ? void 0 : _key$getState4.decorations) || DecorationSet.empty;
295
+ return decs;
296
+ }
297
+ }
298
+ });
299
+ };
@@ -0,0 +1,2 @@
1
+ import { PluginKey } from '@atlaskit/editor-prosemirror/state';
2
+ export var tableViewModeSortPluginKey = new PluginKey('tableViewModeSortPlugin');
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,99 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
3
+ import { SortOrder } from '@atlaskit/editor-common/types';
4
+ import { IS_DISABLED_CLASS_NAME, SORT_INDEX_DATA_ATTRIBUTE, SORTING_ICON_CLASS_NAME } from './consts';
5
+ export var unsort = function unsort(oldOrder, tableElement) {
6
+ var rows = tableElement.querySelectorAll('tr');
7
+ var tbody = tableElement.querySelector('tbody');
8
+ var sortedOrder = _toConsumableArray(oldOrder).sort(function (a, b) {
9
+ return a.value - b.value;
10
+ });
11
+ sortedOrder.forEach(function (item) {
12
+ tbody === null || tbody === void 0 || tbody.appendChild(rows[item.index + 1]);
13
+ });
14
+ };
15
+
16
+ // TODO - reuse sort logic from the Renderer and support switching between ASC, DESC and NO_ORDER
17
+ export var getSortOrderFromTable = function getSortOrderFromTable(tableElement, sortIndex, direction) {
18
+ var sortOrder = direction === SortOrder.DESC ? -1 : 1;
19
+ var strings = [];
20
+ tableElement.querySelectorAll('tr:not([data-header-row="true"])').forEach(function (tr) {
21
+ var _tr$querySelectorAll$;
22
+ strings.push(((_tr$querySelectorAll$ = tr.querySelectorAll('td')[sortIndex]) === null || _tr$querySelectorAll$ === void 0 ? void 0 : _tr$querySelectorAll$.textContent) || '');
23
+ });
24
+ var order = Array.from(strings.keys()).sort(function (a, b) {
25
+ var string = strings[a] || '';
26
+ return string.localeCompare(strings[b] || '') * sortOrder;
27
+ }).map(function (value, index) {
28
+ return {
29
+ value: value,
30
+ index: index
31
+ };
32
+ });
33
+ // TODO - improve this. right now this is a workaround to ensure the first tr is always first in the order
34
+ return [{
35
+ value: -1,
36
+ index: -1
37
+ }].concat(_toConsumableArray(order));
38
+ };
39
+ export var toggleSort = function toggleSort(view, event, pluginState) {
40
+ var _target$closest;
41
+ var target = event.target;
42
+ var widget = target.closest(".".concat(SORTING_ICON_CLASS_NAME));
43
+ if (widget !== null && widget !== void 0 && widget.classList.contains(IS_DISABLED_CLASS_NAME) || !widget) {
44
+ return;
45
+ }
46
+ var datasetortIndex = target === null || target === void 0 || (_target$closest = target.closest('.ProseMirror-widget')) === null || _target$closest === void 0 ? void 0 : _target$closest.getAttribute(SORT_INDEX_DATA_ATTRIBUTE);
47
+ var tr = view.state.tr;
48
+ var tableElement = target.closest('table');
49
+ if (!tableElement || !datasetortIndex) {
50
+ return;
51
+ }
52
+ var tableId = tableElement.getAttribute('data-table-local-id') || '';
53
+ var _ref = (pluginState === null || pluginState === void 0 ? void 0 : pluginState[tableId]) || {},
54
+ index = _ref.index,
55
+ direction = _ref.direction,
56
+ oldOrder = _ref.order;
57
+
58
+ // Unsort if there was already a sort
59
+ if (direction !== SortOrder.NO_ORDER && oldOrder !== undefined) {
60
+ unsort(oldOrder, tableElement);
61
+ }
62
+ var sortIndex = parseInt(datasetortIndex);
63
+ if (sortIndex === index) {
64
+ switch (direction) {
65
+ case SortOrder.NO_ORDER:
66
+ direction = SortOrder.ASC;
67
+ break;
68
+ case SortOrder.ASC:
69
+ direction = SortOrder.DESC;
70
+ break;
71
+ case SortOrder.DESC:
72
+ direction = SortOrder.NO_ORDER;
73
+ break;
74
+ }
75
+ } else {
76
+ direction = SortOrder.ASC; // default direction when a new index is clicked
77
+ }
78
+ var order = getSortOrderFromTable(tableElement, sortIndex, direction);
79
+ if (direction === SortOrder.NO_ORDER) {
80
+ tr.setMeta('tableSortMeta', _defineProperty({}, tableId, {}));
81
+ } else {
82
+ tr.setMeta('tableSortMeta', _defineProperty({}, tableId, {
83
+ index: sortIndex,
84
+ direction: direction,
85
+ order: order,
86
+ tableElement: tableElement
87
+ }));
88
+ }
89
+ view.dispatch(tr);
90
+ };
91
+ export var getTableElements = function getTableElements(tableId) {
92
+ var tableElement = document.querySelector("table[data-table-local-id=\"".concat(tableId, "\"]"));
93
+ var tbody = tableElement === null || tableElement === void 0 ? void 0 : tableElement.querySelector('tbody');
94
+ var rows = tableElement === null || tableElement === void 0 ? void 0 : tableElement.querySelectorAll('tr');
95
+ return {
96
+ tbody: tbody,
97
+ rows: rows
98
+ };
99
+ };