@atlaskit/editor-plugin-table 19.0.0 → 20.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/cjs/nodeviews/TableResizer.js +1 -1
  3. package/dist/cjs/nodeviews/table.js +18 -2
  4. package/dist/cjs/nodeviews/toDOM.js +18 -4
  5. package/dist/cjs/pm-plugins/keymap.js +12 -12
  6. package/dist/cjs/pm-plugins/main.js +41 -7
  7. package/dist/cjs/pm-plugins/table-width.js +10 -0
  8. package/dist/cjs/pm-plugins/transforms/content-mode.js +48 -0
  9. package/dist/cjs/pm-plugins/transforms/fix-tables.js +4 -35
  10. package/dist/cjs/pm-plugins/transforms/table-transform-utils.js +62 -0
  11. package/dist/cjs/pm-plugins/utils/tableMode.js +149 -0
  12. package/dist/cjs/tablePlugin.js +45 -40
  13. package/dist/cjs/ui/ContentComponent.js +1 -0
  14. package/dist/cjs/ui/event-handlers.js +3 -2
  15. package/dist/cjs/ui/global-styles.js +2 -1
  16. package/dist/cjs/ui/toolbar.js +36 -7
  17. package/dist/es2019/nodeviews/TableResizer.js +1 -1
  18. package/dist/es2019/nodeviews/table.js +18 -2
  19. package/dist/es2019/nodeviews/toDOM.js +18 -4
  20. package/dist/es2019/pm-plugins/keymap.js +2 -2
  21. package/dist/es2019/pm-plugins/main.js +41 -7
  22. package/dist/es2019/pm-plugins/table-width.js +10 -0
  23. package/dist/es2019/pm-plugins/transforms/content-mode.js +39 -0
  24. package/dist/es2019/pm-plugins/transforms/fix-tables.js +2 -33
  25. package/dist/es2019/pm-plugins/transforms/table-transform-utils.js +56 -0
  26. package/dist/es2019/pm-plugins/utils/tableMode.js +148 -0
  27. package/dist/es2019/tablePlugin.js +10 -4
  28. package/dist/es2019/ui/ContentComponent.js +1 -0
  29. package/dist/es2019/ui/event-handlers.js +4 -3
  30. package/dist/es2019/ui/global-styles.js +2 -1
  31. package/dist/es2019/ui/toolbar.js +33 -6
  32. package/dist/esm/nodeviews/TableResizer.js +1 -1
  33. package/dist/esm/nodeviews/table.js +18 -2
  34. package/dist/esm/nodeviews/toDOM.js +18 -4
  35. package/dist/esm/pm-plugins/keymap.js +12 -12
  36. package/dist/esm/pm-plugins/main.js +41 -7
  37. package/dist/esm/pm-plugins/table-width.js +10 -0
  38. package/dist/esm/pm-plugins/transforms/content-mode.js +41 -0
  39. package/dist/esm/pm-plugins/transforms/fix-tables.js +2 -33
  40. package/dist/esm/pm-plugins/transforms/table-transform-utils.js +56 -0
  41. package/dist/esm/pm-plugins/utils/tableMode.js +143 -0
  42. package/dist/esm/tablePlugin.js +45 -40
  43. package/dist/esm/ui/ContentComponent.js +1 -0
  44. package/dist/esm/ui/event-handlers.js +4 -3
  45. package/dist/esm/ui/global-styles.js +2 -1
  46. package/dist/esm/ui/toolbar.js +36 -7
  47. package/dist/types/pm-plugins/keymap.d.ts +1 -1
  48. package/dist/types/pm-plugins/main.d.ts +1 -1
  49. package/dist/types/pm-plugins/transforms/content-mode.d.ts +8 -0
  50. package/dist/types/pm-plugins/transforms/table-transform-utils.d.ts +11 -0
  51. package/dist/types/pm-plugins/utils/tableMode.d.ts +22 -0
  52. package/dist/types/tablePluginType.d.ts +6 -0
  53. package/dist/types/types/index.d.ts +3 -0
  54. package/dist/types/ui/global-styles.d.ts +2 -1
  55. package/dist/types-ts4.5/pm-plugins/keymap.d.ts +1 -1
  56. package/dist/types-ts4.5/pm-plugins/main.d.ts +1 -1
  57. package/dist/types-ts4.5/pm-plugins/transforms/content-mode.d.ts +8 -0
  58. package/dist/types-ts4.5/pm-plugins/transforms/table-transform-utils.d.ts +11 -0
  59. package/dist/types-ts4.5/pm-plugins/utils/tableMode.d.ts +22 -0
  60. package/dist/types-ts4.5/tablePluginType.d.ts +6 -0
  61. package/dist/types-ts4.5/types/index.d.ts +3 -0
  62. package/dist/types-ts4.5/ui/global-styles.d.ts +2 -1
  63. package/package.json +21 -20
@@ -18,10 +18,12 @@ import { akEditorTableNumberColumnWidth } from '@atlaskit/editor-shared-styles';
18
18
  import { TableMap } from '@atlaskit/editor-tables/table-map';
19
19
  import { fg } from '@atlaskit/platform-feature-flags';
20
20
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
21
+ import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
21
22
  import { pluginConfig as getPluginConfig } from '../pm-plugins/create-plugin-config';
22
23
  import { getPluginState } from '../pm-plugins/plugin-factory';
23
24
  import { pluginKey as tableWidthPluginKey } from '../pm-plugins/table-width';
24
25
  import { isTableNested, tablesHaveDifferentColumnWidths } from '../pm-plugins/utils/nodes';
26
+ import { isTableInContentMode } from '../pm-plugins/utils/tableMode';
25
27
  import { TableComponentWithSharedState } from './TableComponentWithSharedState';
26
28
  import { tableNodeSpecWithFixedToDOM } from './toDOM';
27
29
  var tableAttributes = function tableAttributes(node) {
@@ -198,7 +200,7 @@ var TableView = /*#__PURE__*/function (_ReactNodeView) {
198
200
  key: "setDomAttrs",
199
201
  value: function setDomAttrs(node) {
200
202
  var _this3 = this,
201
- _this$reactComponentP6,
203
+ _this$reactComponentP8,
202
204
  _this$getEditorFeatur2,
203
205
  _this$options3,
204
206
  _this$options4;
@@ -206,12 +208,26 @@ var TableView = /*#__PURE__*/function (_ReactNodeView) {
206
208
  return; // width / attribute application to actual table will happen later when table is set
207
209
  }
208
210
  var attrs = tableAttributes(node);
211
+ if (expValEqualsNoExposure('platform_editor_table_fit_to_content_auto_convert', 'isEnabled', true)) {
212
+ var _this$reactComponentP6, _this$reactComponentP7;
213
+ if (isTableInContentMode({
214
+ node: node,
215
+ allowColumnResizing: !!this.reactComponentProps.allowColumnResizing,
216
+ allowTableResizing: !!this.reactComponentProps.allowTableResizing,
217
+ isFullPageEditor: !((_this$reactComponentP6 = this.reactComponentProps.options) !== null && _this$reactComponentP6 !== void 0 && _this$reactComponentP6.isCommentEditor) && !((_this$reactComponentP7 = this.reactComponentProps.options) !== null && _this$reactComponentP7 !== void 0 && _this$reactComponentP7.isChromelessEditor),
218
+ isTableNested: isTableNested(this.view.state, this.getPos())
219
+ }) && expValEquals('platform_editor_table_fit_to_content_auto_convert', 'isEnabled', true)) {
220
+ attrs['data-initial-width-mode'] = 'content';
221
+ } else {
222
+ this.table.removeAttribute('data-initial-width-mode');
223
+ }
224
+ }
209
225
  Object.keys(attrs).forEach(function (attr) {
210
226
  // Ignored via go/ees005
211
227
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
212
228
  _this3.table.setAttribute(attr, attrs[attr]);
213
229
  });
214
- var isTableFixedColumnWidthsOptionEnabled = (fg('platform_editor_table_fixed_column_width_prop') ? (_this$reactComponentP6 = this.reactComponentProps) === null || _this$reactComponentP6 === void 0 ? void 0 : _this$reactComponentP6.allowFixedColumnWidthOption : (_this$getEditorFeatur2 = this.getEditorFeatureFlags) === null || _this$getEditorFeatur2 === void 0 ? void 0 : _this$getEditorFeatur2.call(this).tableWithFixedColumnWidthsOption) || false;
230
+ var isTableFixedColumnWidthsOptionEnabled = (fg('platform_editor_table_fixed_column_width_prop') ? (_this$reactComponentP8 = this.reactComponentProps) === null || _this$reactComponentP8 === void 0 ? void 0 : _this$reactComponentP8.allowFixedColumnWidthOption : (_this$getEditorFeatur2 = this.getEditorFeatureFlags) === null || _this$getEditorFeatur2 === void 0 ? void 0 : _this$getEditorFeatur2.call(this).tableWithFixedColumnWidthsOption) || false;
215
231
  // Preserve Table Width cannot have inline width set on the table
216
232
  if (!((_this$options3 = this.options) !== null && _this$options3 !== void 0 && _this$options3.isTableScalingEnabled) || (_this$options4 = this.options) !== null && _this$options4 !== void 0 && _this$options4.isTableScalingEnabled && isTableFixedColumnWidthsOptionEnabled && node.attrs.displayMode === 'fixed') {
217
233
  var _tableWidthPluginKey$;
@@ -3,6 +3,7 @@ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
3
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
4
4
  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; }
5
5
  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; }
6
+ import classNames from 'classnames';
6
7
  import kebabCase from 'lodash/kebabCase';
7
8
  import { table, tableWithNestedTable } from '@atlaskit/adf-schema';
8
9
  import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
@@ -10,11 +11,20 @@ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
10
11
  import { generateColgroupFromNode, getResizerMinWidth } from '../pm-plugins/table-resizing/utils/colgroup';
11
12
  import { TABLE_MAX_WIDTH, TABLE_FULL_WIDTH } from '../pm-plugins/table-resizing/utils/consts';
12
13
  import { getTableResizerContainerMaxWidthInCSS, getTableResizerContainerForFullPageWidthInCSS, getTableResizerItemWidthInCSS } from '../pm-plugins/table-resizing/utils/misc';
14
+ import { isTableInContentMode } from '../pm-plugins/utils/tableMode';
13
15
  import { getAlignmentStyle } from './table-container-styles';
14
16
  export var tableNodeSpecWithFixedToDOM = function tableNodeSpecWithFixedToDOM(config) {
15
17
  var tableNode = config.isNestingSupported ? tableWithNestedTable : table;
16
18
  return _objectSpread(_objectSpread({}, tableNode), {}, {
17
19
  toDOM: function toDOM(node) {
20
+ var isFullPageEditor = !config.isChromelessEditor && !config.isCommentEditor;
21
+ var isInContentMode = isTableInContentMode({
22
+ node: node,
23
+ allowColumnResizing: config.allowColumnResizing,
24
+ allowTableResizing: config.tableResizingEnabled,
25
+ isFullPageEditor: isFullPageEditor,
26
+ isTableNested: config.isNested
27
+ }) && expValEquals('platform_editor_table_fit_to_content_auto_convert', 'isEnabled', true);
18
28
  var alignmentStyle = Object.entries(getAlignmentStyle(node.attrs.layout)).map(function (_ref) {
19
29
  var _ref2 = _slicedToArray(_ref, 2),
20
30
  k = _ref2[0],
@@ -22,7 +32,6 @@ export var tableNodeSpecWithFixedToDOM = function tableNodeSpecWithFixedToDOM(co
22
32
  return "".concat(kebabCase(k), ": ").concat(kebabCase(v));
23
33
  }).join(';');
24
34
  var tableMinWidth = getResizerMinWidth(node);
25
- var isFullPageEditor = !config.isChromelessEditor && !config.isCommentEditor;
26
35
  var attrs = {
27
36
  'data-number-column': node.attrs.isNumberColumnEnabled,
28
37
  'data-layout': node.attrs.layout,
@@ -32,6 +41,9 @@ export var tableNodeSpecWithFixedToDOM = function tableNodeSpecWithFixedToDOM(co
32
41
  'data-ssr-placeholder': "table-".concat(node.attrs.localId),
33
42
  'data-ssr-placeholder-replace': "table-".concat(node.attrs.localId)
34
43
  };
44
+ if (isInContentMode) {
45
+ attrs['data-initial-width-mode'] = 'content';
46
+ }
35
47
  if (expValEquals('platform_editor_table_display_mode_in_to_dom', 'isEnabled', true)) {
36
48
  attrs['data-table-display-mode'] = node.attrs.displayMode;
37
49
  }
@@ -84,11 +96,13 @@ export var tableNodeSpecWithFixedToDOM = function tableNodeSpecWithFixedToDOM(co
84
96
  class: 'pm-table-resizer-container',
85
97
  style: convertToInlineCss({
86
98
  '--ak-editor-table-gutter-padding': config.isTableScalingEnabled ? 'calc(var(--ak-editor--large-gutter-padding) * 2)' : 'calc(var(--ak-editor--large-gutter-padding) * 2 - var(--ak-editor-resizer-handle-spacing))',
87
- '--ak-editor-table-width': resizableTableWidth,
99
+ '--ak-editor-table-width': isInContentMode ? 'max-content' : resizableTableWidth,
88
100
  width: "var(--ak-editor-table-width)"
89
101
  })
90
102
  }, ['div', {
91
- class: 'resizer-item display-handle',
103
+ class: expValEquals('platform_editor_table_fit_to_content_auto_convert', 'isEnabled', true) ? 'resizer-item display-handle' : classNames('resizer-item', {
104
+ 'display-handle': !isInContentMode
105
+ }),
92
106
  style: convertToInlineCss({
93
107
  position: 'relative',
94
108
  userSelect: 'auto',
@@ -97,7 +111,7 @@ export var tableNodeSpecWithFixedToDOM = function tableNodeSpecWithFixedToDOM(co
97
111
  '--ak-editor-table-min-width': "".concat(tableMinWidth, "px"),
98
112
  minWidth: 'var(--ak-editor-table-min-width)',
99
113
  maxWidth: getTableResizerContainerMaxWidthInCSS(config.isCommentEditor, config.isChromelessEditor, config.isTableScalingEnabled),
100
- width: getTableResizerItemWidthInCSS(node, config.isCommentEditor, config.isChromelessEditor)
114
+ width: isInContentMode ? 'auto' : getTableResizerItemWidthInCSS(node, config.isCommentEditor, config.isChromelessEditor)
101
115
  })
102
116
  }, ['span', {
103
117
  class: 'resizer-hover-zone'
@@ -10,18 +10,18 @@ import { activateNextResizeArea, initiateKeyboardColumnResizing, stopKeyboardCol
10
10
  import { addRowAroundSelection, changeColumnWidthByStepWithAnalytics, deleteSelectedRowsOrColumnsWithAnalyticsViaShortcut, deleteTableIfSelectedWithAnalytics, emptyMultipleCellsWithAnalytics } from './commands/commands-with-analytics';
11
11
  import { goToNextCellVertical } from './commands/go-to-next-cell';
12
12
  import { addColumnAfter as addColumnAfterCommand, addColumnBefore as addColumnBeforeCommand, insertTableWithNestingSupport } from './commands/insert';
13
- export function keymapPlugin(getEditorContainerWidth, api, nodeViewPortalProviderAPI, editorAnalyticsAPI) {
13
+ export function keymapPlugin(getEditorContainerWidth, api, nodeViewPortalProviderAPI, editorAnalyticsAPI, dragAndDropEnabled) {
14
14
  var _pluginInjectionApi$a;
15
- var isTableScalingEnabled = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
16
- var isTableAlignmentEnabled = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
17
- var isFullWidthEnabled = arguments.length > 6 ? arguments[6] : undefined;
18
- var pluginInjectionApi = arguments.length > 7 ? arguments[7] : undefined;
19
- var getIntl = arguments.length > 8 ? arguments[8] : undefined;
20
- var isTableFixedColumnWidthsOptionEnabled = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : false;
21
- var shouldUseIncreasedScalingPercent = arguments.length > 10 ? arguments[10] : undefined;
22
- var isCommentEditor = arguments.length > 11 ? arguments[11] : undefined;
23
- var isChromelessEditor = arguments.length > 12 ? arguments[12] : undefined;
24
- var isTableResizingEnabled = arguments.length > 13 ? arguments[13] : undefined;
15
+ var isTableScalingEnabled = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
16
+ var isTableAlignmentEnabled = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false;
17
+ var isFullWidthEnabled = arguments.length > 7 ? arguments[7] : undefined;
18
+ var pluginInjectionApi = arguments.length > 8 ? arguments[8] : undefined;
19
+ var getIntl = arguments.length > 9 ? arguments[9] : undefined;
20
+ var isTableFixedColumnWidthsOptionEnabled = arguments.length > 10 && arguments[10] !== undefined ? arguments[10] : false;
21
+ var shouldUseIncreasedScalingPercent = arguments.length > 11 ? arguments[11] : undefined;
22
+ var isCommentEditor = arguments.length > 12 ? arguments[12] : undefined;
23
+ var isChromelessEditor = arguments.length > 13 ? arguments[13] : undefined;
24
+ var isTableResizingEnabled = arguments.length > 14 ? arguments[14] : undefined;
25
25
  var list = {};
26
26
  var ariaNotifyPlugin = pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$a = pluginInjectionApi.accessibilityUtils) === null || _pluginInjectionApi$a === void 0 ? void 0 : _pluginInjectionApi$a.actions.ariaNotify;
27
27
  bindKeymapWithCommand(
@@ -92,7 +92,7 @@ export function keymapPlugin(getEditorContainerWidth, api, nodeViewPortalProvide
92
92
  // Ignored via go/ees005
93
93
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
94
94
  addColumnAfterVO.common, addColumnAfterCommand(api, isTableScalingEnabled, isTableFixedColumnWidthsOptionEnabled, shouldUseIncreasedScalingPercent), list);
95
- if (moveRowDown.common && moveRowUp.common && moveColumnLeft.common && moveColumnRight.common) {
95
+ if (dragAndDropEnabled && moveRowDown.common && moveRowUp.common && moveColumnLeft.common && moveColumnRight.common) {
96
96
  var isNewKeyMapExperiment = expValEquals('editor-a11y-fy26-keyboard-move-row-column', 'isEnabled', true);
97
97
  // Move row/column shortcuts
98
98
  /**
@@ -1,6 +1,7 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  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; }
3
3
  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; }
4
+ import { bind } from 'bind-event-listener';
4
5
  import { ACTION, ACTION_SUBJECT, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
5
6
  import { getBrowserInfo } from '@atlaskit/editor-common/browser';
6
7
  import { insideTable } from '@atlaskit/editor-common/core-utils';
@@ -27,10 +28,13 @@ import { fixTables } from './transforms/fix-tables';
27
28
  import { replaceSelectedTable } from './transforms/replace-table';
28
29
  import { findControlsHoverDecoration } from './utils/decoration';
29
30
  import { transformSliceToCorrectEmptyTableCells, transformSliceToFixHardBreakProblemOnCopyFromCell, transformSliceToRemoveOpenTable, transformSliceToRemoveNestedTables, isHeaderRowRequired, transformSliceTableLayoutDefaultToCenter } from './utils/paste';
30
- export var createPlugin = function createPlugin(dispatchAnalyticsEvent, dispatch, portalProviderAPI, nodeViewPortalProviderAPI, eventDispatcher, pluginConfig, getEditorContainerWidth, getEditorFeatureFlags, getIntl, fullWidthModeEnabled, previousFullWidthModeEnabled, editorAnalyticsAPI, pluginInjectionApi, isTableScalingEnabled, shouldUseIncreasedScalingPercent, isCommentEditor, isChromelessEditor, allowFixedColumnWidthOption) {
31
+ import { applyMeasuredWidthToAllTables, isContentModeSupported } from './utils/tableMode';
32
+ export var createPlugin = function createPlugin(dispatchAnalyticsEvent, dispatch, portalProviderAPI, nodeViewPortalProviderAPI, eventDispatcher, pluginConfig, getEditorContainerWidth, getEditorFeatureFlags, getIntl, fullWidthModeEnabled, previousFullWidthModeEnabled, dragAndDropEnabled, editorAnalyticsAPI, pluginInjectionApi, isTableScalingEnabled, shouldUseIncreasedScalingPercent, isCommentEditor, isChromelessEditor, allowFixedColumnWidthOption) {
31
33
  var _accessibilityUtils;
32
34
  var state = createPluginState(dispatch, _objectSpread(_objectSpread(_objectSpread({
33
35
  pluginConfig: pluginConfig,
36
+ isCommentEditor: isCommentEditor,
37
+ isChromelessEditor: isChromelessEditor,
34
38
  isTableHovered: false,
35
39
  insertColumnButtonIndex: undefined,
36
40
  insertRowButtonIndex: undefined,
@@ -38,7 +42,7 @@ export var createPlugin = function createPlugin(dispatchAnalyticsEvent, dispatch
38
42
  wasFullWidthModeEnabled: previousFullWidthModeEnabled,
39
43
  isHeaderRowEnabled: !!pluginConfig.allowHeaderRow,
40
44
  isHeaderColumnEnabled: false,
41
- isDragAndDropEnabled: true,
45
+ isDragAndDropEnabled: dragAndDropEnabled,
42
46
  isTableScalingEnabled: isTableScalingEnabled
43
47
  }, defaultHoveredCell), defaultTableSelection), {}, {
44
48
  getIntl: getIntl
@@ -71,7 +75,7 @@ export var createPlugin = function createPlugin(dispatchAnalyticsEvent, dispatch
71
75
  tableRow: tableRowView({
72
76
  eventDispatcher: eventDispatcher,
73
77
  pluginInjectionApi: pluginInjectionApi,
74
- isDragAndDropEnabled: true
78
+ isDragAndDropEnabled: dragAndDropEnabled
75
79
  }),
76
80
  tableCell: tableCellView({
77
81
  eventDispatcher: eventDispatcher,
@@ -125,8 +129,34 @@ export var createPlugin = function createPlugin(dispatchAnalyticsEvent, dispatch
125
129
  }
126
130
  },
127
131
  view: function view(editorView) {
132
+ var _pluginInjectionApi$e;
128
133
  var domAtPos = editorView.domAtPos.bind(editorView);
129
134
  editorViewRef = editorView;
135
+ var contentModeSizeTableId = null;
136
+ var focusListenerBinding = null;
137
+ if ((pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$e = pluginInjectionApi.editorViewMode) === null || _pluginInjectionApi$e === void 0 || (_pluginInjectionApi$e = _pluginInjectionApi$e.sharedState.currentState()) === null || _pluginInjectionApi$e === void 0 ? void 0 : _pluginInjectionApi$e.mode) !== 'view' && isContentModeSupported({
138
+ allowColumnResizing: !!pluginConfig.allowColumnResizing,
139
+ allowTableResizing: !!pluginConfig.allowTableResizing,
140
+ isFullPageEditor: !isChromelessEditor && !isCommentEditor
141
+ }) && expValEquals('platform_editor_table_fit_to_content_auto_convert', 'isEnabled', true)) {
142
+ focusListenerBinding = bind(editorView.dom, {
143
+ type: 'focus',
144
+ listener: function listener() {
145
+ if (contentModeSizeTableId) {
146
+ return;
147
+ }
148
+ contentModeSizeTableId = requestAnimationFrame(function () {
149
+ if (!editorViewRef) {
150
+ return;
151
+ }
152
+ applyMeasuredWidthToAllTables(editorViewRef, pluginInjectionApi);
153
+ });
154
+ },
155
+ options: {
156
+ once: true
157
+ }
158
+ });
159
+ }
130
160
  return {
131
161
  update: function update(view, prevState) {
132
162
  var state = view.state,
@@ -135,12 +165,12 @@ export var createPlugin = function createPlugin(dispatchAnalyticsEvent, dispatch
135
165
  var pluginState = getPluginState(state);
136
166
  var tableRef;
137
167
  if (fg('platform_editor_enable_table_dnd')) {
138
- var _pluginInjectionApi$e;
168
+ var _pluginInjectionApi$e2;
139
169
  var parent = findParentDomRefOfType(state.schema.nodes.table, domAtPos)(selection);
140
- var shouldSetTableRef = fg('platform_editor_enable_table_dnd_patch_1') ? parent && (pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$e = pluginInjectionApi.editorViewMode) === null || _pluginInjectionApi$e === void 0 || (_pluginInjectionApi$e = _pluginInjectionApi$e.sharedState.currentState()) === null || _pluginInjectionApi$e === void 0 ? void 0 : _pluginInjectionApi$e.mode) !== 'view' : parent;
170
+ var shouldSetTableRef = fg('platform_editor_enable_table_dnd_patch_1') ? parent && (pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$e2 = pluginInjectionApi.editorViewMode) === null || _pluginInjectionApi$e2 === void 0 || (_pluginInjectionApi$e2 = _pluginInjectionApi$e2.sharedState.currentState()) === null || _pluginInjectionApi$e2 === void 0 ? void 0 : _pluginInjectionApi$e2.mode) !== 'view' : parent;
141
171
  if (expValEquals('platform_editor_table_update_table_ref', 'isEnabled', true) && fg('platform_editor_update_table_ref_fix')) {
142
- var _pluginInjectionApi$e2, _pluginInjectionApi$i;
143
- shouldSetTableRef = parent && (pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$e2 = pluginInjectionApi.editorViewMode) === null || _pluginInjectionApi$e2 === void 0 || (_pluginInjectionApi$e2 = _pluginInjectionApi$e2.sharedState.currentState()) === null || _pluginInjectionApi$e2 === void 0 ? void 0 : _pluginInjectionApi$e2.mode) !== 'view' && (pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$i = pluginInjectionApi.interaction) === null || _pluginInjectionApi$i === void 0 || (_pluginInjectionApi$i = _pluginInjectionApi$i.sharedState.currentState()) === null || _pluginInjectionApi$i === void 0 ? void 0 : _pluginInjectionApi$i.interactionState) !== 'hasNotHadInteraction';
172
+ var _pluginInjectionApi$e3, _pluginInjectionApi$i;
173
+ shouldSetTableRef = parent && (pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$e3 = pluginInjectionApi.editorViewMode) === null || _pluginInjectionApi$e3 === void 0 || (_pluginInjectionApi$e3 = _pluginInjectionApi$e3.sharedState.currentState()) === null || _pluginInjectionApi$e3 === void 0 ? void 0 : _pluginInjectionApi$e3.mode) !== 'view' && (pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$i = pluginInjectionApi.interaction) === null || _pluginInjectionApi$i === void 0 || (_pluginInjectionApi$i = _pluginInjectionApi$i.sharedState.currentState()) === null || _pluginInjectionApi$i === void 0 ? void 0 : _pluginInjectionApi$i.interactionState) !== 'hasNotHadInteraction';
144
174
  }
145
175
  if (shouldSetTableRef) {
146
176
  tableRef =
@@ -202,6 +232,10 @@ export var createPlugin = function createPlugin(dispatchAnalyticsEvent, dispatch
202
232
  } else if (pluginState.isResizeHandleWidgetAdded) {
203
233
  removeResizeHandleDecorations()(state, dispatch);
204
234
  }
235
+ },
236
+ destroy: function destroy() {
237
+ contentModeSizeTableId && cancelAnimationFrame(contentModeSizeTableId);
238
+ focusListenerBinding && focusListenerBinding();
205
239
  }
206
240
  };
207
241
  },
@@ -17,6 +17,7 @@ import { akEditorDefaultLayoutWidth, akEditorFullWidthLayoutWidth, akEditorMaxWi
17
17
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
18
18
  import { TABLE_MAX_WIDTH, TABLE_FULL_WIDTH } from './table-resizing/utils/consts';
19
19
  import { ALIGN_START } from './utils/alignment';
20
+ import { isTableInContentMode } from './utils/tableMode';
20
21
  export var pluginKey = new PluginKey('tableWidthPlugin');
21
22
  var createPlugin = function createPlugin(dispatch, dispatchAnalyticsEvent, fullWidthEnabled, maxWidthEnabled, isTableScalingEnabled, isTableAlignmentEnabled, isCommentEditor) {
22
23
  return new SafePlugin({
@@ -63,6 +64,15 @@ var createPlugin = function createPlugin(dispatch, dispatchAnalyticsEvent, fullW
63
64
  var tr = newState.tr;
64
65
  if (isReplaceDocumentOperation && !isCommentEditor) {
65
66
  newState.doc.forEach(function (node, offset) {
67
+ if (isTableInContentMode({
68
+ node: node,
69
+ allowColumnResizing: true,
70
+ allowTableResizing: true,
71
+ isFullPageEditor: true,
72
+ isTableNested: false
73
+ })) {
74
+ return;
75
+ }
66
76
  if (node.type === table) {
67
77
  var width = node.attrs.width;
68
78
  var layout = node.attrs.layout;
@@ -0,0 +1,41 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ 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; }
3
+ 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; }
4
+ import { tableCellMinWidth } from '@atlaskit/editor-common/styles';
5
+ import { akEditorFullWidthLayoutWidth, akEditorMaxLayoutWidth } from '@atlaskit/editor-shared-styles';
6
+ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
7
+ import { updateCellsMarkup } from './table-transform-utils';
8
+ var tableWidth = function tableWidth(contentWidth) {
9
+ var maxEditorWidth = expValEquals('editor_tinymce_full_width_mode', 'isEnabled', true) || expValEquals('confluence_max_width_content_appearance', 'isEnabled', true) ? akEditorMaxLayoutWidth : akEditorFullWidthLayoutWidth;
10
+ return Math.min(maxEditorWidth, contentWidth);
11
+ };
12
+ export var getTableMeasurement = function getTableMeasurement(tableRef) {
13
+ var colWidths = getRenderedColgroupColumnWidths(tableRef);
14
+ var totalContentWidth = colWidths.reduce(function (acc, current) {
15
+ return acc + current;
16
+ }, 0);
17
+ return {
18
+ colWidths: colWidths,
19
+ tableWidth: tableWidth(totalContentWidth)
20
+ };
21
+ };
22
+ export var applyTableMeasurement = function applyTableMeasurement(tr, tableNode, _ref, tablePos) {
23
+ var colWidths = _ref.colWidths,
24
+ tableWidth = _ref.tableWidth;
25
+ tr = updateCellsMarkup(tr, tableNode, tablePos, function (cell, _rowIndex, colIndex) {
26
+ var newColWidths = colWidths.slice(colIndex, colIndex + cell.attrs.colspan);
27
+ return cell.type.createChecked(_objectSpread(_objectSpread({}, cell.attrs), {}, {
28
+ colwidth: newColWidths.length ? newColWidths : null
29
+ }), cell.content, cell.marks);
30
+ });
31
+ return tr.setNodeMarkup(tablePos, undefined, _objectSpread(_objectSpread({}, tableNode.attrs), {}, {
32
+ width: tableWidth
33
+ }));
34
+ };
35
+ function getRenderedColgroupColumnWidths(tableRef) {
36
+ var cols = Array.from(tableRef.querySelectorAll(':scope > colgroup > col'));
37
+ return cols.map(function (col) {
38
+ var width = col.getBoundingClientRect().width;
39
+ return Math.max(Math.round(width), tableCellMinWidth);
40
+ });
41
+ }
@@ -6,6 +6,7 @@ import { akEditorDefaultLayoutWidth, akEditorWideLayoutWidth } from '@atlaskit/e
6
6
  import { calculateColumnWidth, getCellsRefsInColumn } from '../table-resizing/utils/column-state';
7
7
  import { contentWidth } from '../table-resizing/utils/content-width';
8
8
  import { getLayoutSize } from '../table-resizing/utils/misc';
9
+ import { replaceCells } from './table-transform-utils';
9
10
  var validateTableCellNodeAttrs = function validateTableCellNodeAttrs(_ref, reportInvalidTableCellSpanAttrs) {
10
11
  var colspan = _ref.colspan,
11
12
  rowspan = _ref.rowspan,
@@ -153,36 +154,4 @@ function parseDOMColumnWidths(domAtPos, tableNode, tableStart, tableRef) {
153
154
  }
154
155
  }
155
156
  return cols;
156
- }
157
-
158
- // TODO: ED-26961 - move to prosemirror-utils
159
- var replaceCells = function replaceCells(tr, table, tablePos, modifyCell) {
160
- var rows = [];
161
- var modifiedCells = 0;
162
- for (var rowIndex = 0; rowIndex < table.childCount; rowIndex++) {
163
- var row = table.child(rowIndex);
164
- var cells = [];
165
- for (var colIndex = 0; colIndex < row.childCount; colIndex++) {
166
- var cell = row.child(colIndex);
167
-
168
- // TODO: ED-26961 - The rowIndex and colIndex are not accurate in a merged cell scenario
169
- // e.g. table with 5 columns might have only one cell in a row, colIndex will be 1, where it should be 4
170
- var node = modifyCell(cell, rowIndex, colIndex);
171
- if (node.sameMarkup(cell) === false) {
172
- modifiedCells++;
173
- }
174
- cells.push(node);
175
- }
176
- if (cells.length) {
177
- rows.push(row.type.createChecked(row.attrs, cells, row.marks));
178
- }
179
- }
180
-
181
- // Check if the table has changed before replacing.
182
- // If no cells are modified our counter will be zero.
183
- if (rows.length && modifiedCells !== 0) {
184
- var newTable = table.type.createChecked(table.attrs, rows, table.marks);
185
- return tr.replaceWith(tablePos, tablePos + table.nodeSize, newTable);
186
- }
187
- return tr;
188
- };
157
+ }
@@ -0,0 +1,56 @@
1
+ // TODO: ED-26961 - move to prosemirror-utils
2
+ export var replaceCells = function replaceCells(tr, table, tablePos, modifyCell) {
3
+ var rows = [];
4
+ var modifiedCells = 0;
5
+ for (var rowIndex = 0; rowIndex < table.childCount; rowIndex++) {
6
+ var row = table.child(rowIndex);
7
+ var cells = [];
8
+ for (var colIndex = 0; colIndex < row.childCount; colIndex++) {
9
+ var cell = row.child(colIndex);
10
+
11
+ // TODO: ED-26961 - The rowIndex and colIndex are not accurate in a merged cell scenario
12
+ // e.g. table with 5 columns might have only one cell in a row, colIndex will be 1, where it should be 4
13
+ var node = modifyCell(cell, rowIndex, colIndex);
14
+ if (node.sameMarkup(cell) === false) {
15
+ modifiedCells++;
16
+ }
17
+ cells.push(node);
18
+ }
19
+ if (cells.length) {
20
+ rows.push(row.type.createChecked(row.attrs, cells, row.marks));
21
+ }
22
+ }
23
+
24
+ // Check if the table has changed before replacing.
25
+ // If no cells are modified our counter will be zero.
26
+ if (rows.length && modifiedCells !== 0) {
27
+ var newTable = table.type.createChecked(table.attrs, rows, table.marks);
28
+ return tr.replaceWith(tablePos, tablePos + table.nodeSize, newTable);
29
+ }
30
+ return tr;
31
+ };
32
+
33
+ /**
34
+ * Position-preserving alternative to `replaceCells`.
35
+ *
36
+ * Uses `setNodeMarkup` per cell instead of rebuilding the whole table with
37
+ * `replaceWith`, so document positions inside cells are never invalidated.
38
+ * This preserves any existing selection through `tr.mapping`.
39
+ */
40
+ export var updateCellsMarkup = function updateCellsMarkup(tr, table, tablePos, modifyCell) {
41
+ var rowOffset = tablePos + 1;
42
+ for (var rowIndex = 0; rowIndex < table.childCount; rowIndex++) {
43
+ var row = table.child(rowIndex);
44
+ var cellOffset = rowOffset + 1;
45
+ for (var colIndex = 0; colIndex < row.childCount; colIndex++) {
46
+ var cell = row.child(colIndex);
47
+ var modified = modifyCell(cell, rowIndex, colIndex);
48
+ if (!modified.sameMarkup(cell)) {
49
+ tr.setNodeMarkup(cellOffset, modified.type, modified.attrs, modified.marks);
50
+ }
51
+ cellOffset += cell.nodeSize;
52
+ }
53
+ rowOffset += row.nodeSize;
54
+ }
55
+ return tr;
56
+ };
@@ -0,0 +1,143 @@
1
+ import { ACTION_SUBJECT, EVENT_TYPE, TABLE_ACTION } from '@atlaskit/editor-common/analytics';
2
+ import { TableSharedCssClassName } from '@atlaskit/editor-common/styles';
3
+ import { findTable } from '@atlaskit/editor-tables/utils';
4
+ import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
5
+ import { hasTableColumnBeenResized } from '../table-resizing/utils/colgroup';
6
+ import { applyTableMeasurement, getTableMeasurement } from '../transforms/content-mode';
7
+ import { ALIGN_START } from './alignment';
8
+ export var isTableInContentMode = function isTableInContentMode(_ref) {
9
+ var allowColumnResizing = _ref.allowColumnResizing,
10
+ allowTableResizing = _ref.allowTableResizing,
11
+ isFullPageEditor = _ref.isFullPageEditor,
12
+ isTableNested = _ref.isTableNested,
13
+ node = _ref.node;
14
+ if (!expValEqualsNoExposure('platform_editor_table_fit_to_content_auto_convert', 'isEnabled', true)) {
15
+ return false;
16
+ }
17
+ if (!node || isTableNested) {
18
+ return false;
19
+ }
20
+ return isContentModeSupported({
21
+ allowColumnResizing: allowColumnResizing,
22
+ allowTableResizing: allowTableResizing,
23
+ isFullPageEditor: isFullPageEditor
24
+ }) && !hasTableBeenResized(node) && node.attrs.layout === ALIGN_START;
25
+ };
26
+ export var isContentModeSupported = function isContentModeSupported(_ref2) {
27
+ var allowColumnResizing = _ref2.allowColumnResizing,
28
+ allowTableResizing = _ref2.allowTableResizing,
29
+ isFullPageEditor = _ref2.isFullPageEditor;
30
+ return allowColumnResizing && allowTableResizing && isFullPageEditor;
31
+ };
32
+ export var hasTableBeenResized = function hasTableBeenResized(node) {
33
+ return node.attrs.width !== null || hasTableColumnBeenResized(node);
34
+ };
35
+
36
+ /**
37
+ * Iterates all top-level tables in the document, and for those in content mode,
38
+ * measures rendered column widths and sets colwidth + table width attributes
39
+ * in a single batched transaction.
40
+ */
41
+ export var applyMeasuredWidthToAllTables = function applyMeasuredWidthToAllTables(view, pluginInjectionApi) {
42
+ var _view$state = view.state,
43
+ doc = _view$state.doc,
44
+ schema = _view$state.schema;
45
+ var tr = view.state.tr;
46
+ var table = schema.nodes.table;
47
+ var modified = false;
48
+ var measuredTables = [];
49
+
50
+ // modify only top-level tables
51
+ doc.forEach(function (node, offset) {
52
+ if (node.type !== table || hasTableBeenResized(node) && node.attrs.layout !== ALIGN_START) {
53
+ return;
54
+ }
55
+ var domNode = view.domAtPos(offset + 1).node;
56
+ var tableWrapper = domNode instanceof HTMLElement ? domNode.closest(".".concat(TableSharedCssClassName.TABLE_VIEW_CONTENT_WRAP)) : null;
57
+ var tableRef = tableWrapper === null || tableWrapper === void 0 ? void 0 : tableWrapper.querySelector('table');
58
+ if (!tableRef) {
59
+ return;
60
+ }
61
+ measuredTables.push({
62
+ node: node,
63
+ offset: offset,
64
+ measurement: getTableMeasurement(tableRef)
65
+ });
66
+ });
67
+ measuredTables.forEach(function (_ref3) {
68
+ var node = _ref3.node,
69
+ offset = _ref3.offset,
70
+ measurement = _ref3.measurement;
71
+ tr = applyTableMeasurement(tr, node, measurement, offset);
72
+ modified = true;
73
+ });
74
+ if (modified) {
75
+ var _pluginInjectionApi$a, _pluginInjectionApi$w, _pluginInjectionApi$w2;
76
+ pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$a = pluginInjectionApi.analytics) === null || _pluginInjectionApi$a === void 0 || (_pluginInjectionApi$a = _pluginInjectionApi$a.actions) === null || _pluginInjectionApi$a === void 0 || _pluginInjectionApi$a.attachAnalyticsEvent({
77
+ action: TABLE_ACTION.FIT_TO_CONTENT_AUTO_CONVERTED,
78
+ actionSubject: ACTION_SUBJECT.TABLE,
79
+ actionSubjectId: null,
80
+ eventType: EVENT_TYPE.TRACK,
81
+ attributes: {
82
+ editorContainerWidth: (_pluginInjectionApi$w = pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$w2 = pluginInjectionApi.width) === null || _pluginInjectionApi$w2 === void 0 || (_pluginInjectionApi$w2 = _pluginInjectionApi$w2.sharedState.currentState()) === null || _pluginInjectionApi$w2 === void 0 ? void 0 : _pluginInjectionApi$w2.width) !== null && _pluginInjectionApi$w !== void 0 ? _pluginInjectionApi$w : 0,
83
+ totalTablesResized: measuredTables.length,
84
+ measurements: measuredTables.map(function (_ref4) {
85
+ var measurement = _ref4.measurement;
86
+ return {
87
+ tableWidth: measurement.tableWidth,
88
+ totalColumnCount: measurement.colWidths.length
89
+ };
90
+ })
91
+ }
92
+ })(tr);
93
+ view.dispatch(tr.setMeta('addToHistory', false));
94
+ }
95
+ };
96
+ export var applyMeasuredWidthToSelectedTable = function applyMeasuredWidthToSelectedTable(view, api) {
97
+ var _api$analytics, _api$width$sharedStat, _api$width;
98
+ var tableObject = findTable(view.state.selection);
99
+ if (!tableObject) {
100
+ return;
101
+ }
102
+ var node = tableObject.node,
103
+ pos = tableObject.pos;
104
+ var tableState = api === null || api === void 0 ? void 0 : api.table.sharedState.currentState();
105
+ if (!(tableState !== null && tableState !== void 0 && tableState.tableRef)) {
106
+ return;
107
+ }
108
+ var tableRef = tableState.tableRef;
109
+
110
+ // Instead of dispatching a transaction to "strip widths" and then waiting
111
+ // for a rAF to measure natural column widths, instea directly update the DOM elements and
112
+ // take a measurement.
113
+ var cols = Array.from(tableRef.querySelectorAll(':scope > colgroup > col'));
114
+ var contentWrap = tableRef.closest(".".concat(TableSharedCssClassName.TABLE_VIEW_CONTENT_WRAP));
115
+ var resizerContainer = contentWrap === null || contentWrap === void 0 ? void 0 : contentWrap.querySelector(".".concat(TableSharedCssClassName.TABLE_RESIZER_CONTAINER));
116
+ var resizerItem = resizerContainer === null || resizerContainer === void 0 ? void 0 : resizerContainer.querySelector('.resizer-item.display-handle');
117
+ tableRef.style.width = '';
118
+ tableRef.style.tableLayout = 'auto';
119
+ cols.forEach(function (col) {
120
+ return col.style.width = '';
121
+ });
122
+ if (resizerContainer) {
123
+ resizerContainer.style.width = 'max-content';
124
+ resizerContainer.style.setProperty('--ak-editor-table-width', 'max-content');
125
+ }
126
+ if (resizerItem) {
127
+ resizerItem.style.width = 'max-content';
128
+ }
129
+ var measurement = getTableMeasurement(tableRef);
130
+ var tr = applyTableMeasurement(view.state.tr, node, measurement, pos);
131
+ api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || (_api$analytics = _api$analytics.actions) === null || _api$analytics === void 0 || _api$analytics.attachAnalyticsEvent({
132
+ action: TABLE_ACTION.FIT_TO_CONTENT_ON_DEMAND,
133
+ actionSubject: ACTION_SUBJECT.TABLE,
134
+ actionSubjectId: null,
135
+ eventType: EVENT_TYPE.TRACK,
136
+ attributes: {
137
+ editorContainerWidth: (_api$width$sharedStat = api === null || api === void 0 || (_api$width = api.width) === null || _api$width === void 0 || (_api$width = _api$width.sharedState.currentState()) === null || _api$width === void 0 ? void 0 : _api$width.width) !== null && _api$width$sharedStat !== void 0 ? _api$width$sharedStat : 0,
138
+ tableWidth: measurement.tableWidth,
139
+ totalColumnCount: measurement.colWidths.length
140
+ }
141
+ })(tr);
142
+ view.dispatch(tr);
143
+ };