@atlaskit/editor-plugin-table 12.2.6 → 12.2.7

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 (204) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/package.json +4 -4
  3. package/afm-cc/tsconfig.json +0 -123
  4. package/afm-dev-agents/tsconfig.json +0 -123
  5. package/afm-jira/tsconfig.json +0 -123
  6. package/afm-passionfruit/tsconfig.json +0 -123
  7. package/afm-post-office/tsconfig.json +0 -123
  8. package/afm-rovo-extension/tsconfig.json +0 -123
  9. package/afm-townsquare/tsconfig.json +0 -123
  10. package/afm-volt/tsconfig.json +0 -114
  11. package/build/tsconfig.json +0 -23
  12. package/docs/0-intro.tsx +0 -57
  13. package/src/index.ts +0 -21
  14. package/src/nodeviews/ExternalDropTargets.tsx +0 -91
  15. package/src/nodeviews/OverflowShadowsObserver.ts +0 -156
  16. package/src/nodeviews/TableCell.ts +0 -134
  17. package/src/nodeviews/TableComponent.tsx +0 -1590
  18. package/src/nodeviews/TableComponentWithSharedState.tsx +0 -278
  19. package/src/nodeviews/TableContainer.tsx +0 -926
  20. package/src/nodeviews/TableNodeViewBase.ts +0 -29
  21. package/src/nodeviews/TableResizer.tsx +0 -884
  22. package/src/nodeviews/TableRow.ts +0 -830
  23. package/src/nodeviews/TableStickyScrollbar.ts +0 -211
  24. package/src/nodeviews/__mocks__/OverflowShadowsObserver.ts +0 -15
  25. package/src/nodeviews/__mocks__/OverridableMock.ts +0 -26
  26. package/src/nodeviews/table-container-styles.ts +0 -9
  27. package/src/nodeviews/table-node-views.ts +0 -76
  28. package/src/nodeviews/table.tsx +0 -530
  29. package/src/nodeviews/toDOM.ts +0 -244
  30. package/src/nodeviews/types.ts +0 -36
  31. package/src/nodeviews/update-overflow-shadows.ts +0 -11
  32. package/src/pm-plugins/analytics/actions.ts +0 -21
  33. package/src/pm-plugins/analytics/commands.ts +0 -47
  34. package/src/pm-plugins/analytics/plugin-factory.ts +0 -9
  35. package/src/pm-plugins/analytics/plugin-key.ts +0 -5
  36. package/src/pm-plugins/analytics/plugin.ts +0 -80
  37. package/src/pm-plugins/analytics/reducer.ts +0 -27
  38. package/src/pm-plugins/analytics/types.ts +0 -20
  39. package/src/pm-plugins/analytics/utils/moved-event.ts +0 -51
  40. package/src/pm-plugins/commands/clear.ts +0 -43
  41. package/src/pm-plugins/commands/collapse.ts +0 -17
  42. package/src/pm-plugins/commands/column-resize.ts +0 -478
  43. package/src/pm-plugins/commands/commands-with-analytics.ts +0 -715
  44. package/src/pm-plugins/commands/delete.ts +0 -42
  45. package/src/pm-plugins/commands/display-mode.ts +0 -18
  46. package/src/pm-plugins/commands/go-to-next-cell.ts +0 -198
  47. package/src/pm-plugins/commands/hover.ts +0 -242
  48. package/src/pm-plugins/commands/index.ts +0 -51
  49. package/src/pm-plugins/commands/insert.ts +0 -438
  50. package/src/pm-plugins/commands/misc.ts +0 -811
  51. package/src/pm-plugins/commands/referentiality.ts +0 -15
  52. package/src/pm-plugins/commands/selection.ts +0 -537
  53. package/src/pm-plugins/commands/sort.ts +0 -102
  54. package/src/pm-plugins/commands/split-cell.ts +0 -28
  55. package/src/pm-plugins/commands/toggle.ts +0 -109
  56. package/src/pm-plugins/create-plugin-config.ts +0 -17
  57. package/src/pm-plugins/decorations/plugin.ts +0 -107
  58. package/src/pm-plugins/decorations/utils/column-controls.ts +0 -91
  59. package/src/pm-plugins/decorations/utils/column-resizing.ts +0 -71
  60. package/src/pm-plugins/decorations/utils/compose-decorations.ts +0 -9
  61. package/src/pm-plugins/decorations/utils/types.ts +0 -16
  62. package/src/pm-plugins/default-table-selection.ts +0 -14
  63. package/src/pm-plugins/drag-and-drop/actions.ts +0 -48
  64. package/src/pm-plugins/drag-and-drop/commands-with-analytics.ts +0 -222
  65. package/src/pm-plugins/drag-and-drop/commands.ts +0 -194
  66. package/src/pm-plugins/drag-and-drop/consts.ts +0 -7
  67. package/src/pm-plugins/drag-and-drop/plugin-factory.ts +0 -33
  68. package/src/pm-plugins/drag-and-drop/plugin-key.ts +0 -5
  69. package/src/pm-plugins/drag-and-drop/plugin.ts +0 -398
  70. package/src/pm-plugins/drag-and-drop/reducer.ts +0 -38
  71. package/src/pm-plugins/drag-and-drop/types.ts +0 -18
  72. package/src/pm-plugins/drag-and-drop/utils/autoscrollers.ts +0 -49
  73. package/src/pm-plugins/drag-and-drop/utils/getDragBehaviour.ts +0 -9
  74. package/src/pm-plugins/drag-and-drop/utils/monitor.ts +0 -73
  75. package/src/pm-plugins/handlers.ts +0 -161
  76. package/src/pm-plugins/keymap.ts +0 -436
  77. package/src/pm-plugins/main.ts +0 -433
  78. package/src/pm-plugins/plugin-factory.ts +0 -42
  79. package/src/pm-plugins/plugin-key.ts +0 -8
  80. package/src/pm-plugins/reducer.ts +0 -145
  81. package/src/pm-plugins/safari-delete-composition-text-issue-workaround.ts +0 -102
  82. package/src/pm-plugins/sticky-headers/commands.ts +0 -8
  83. package/src/pm-plugins/sticky-headers/plugin-key.ts +0 -5
  84. package/src/pm-plugins/sticky-headers/plugin-state.ts +0 -52
  85. package/src/pm-plugins/sticky-headers/plugin.ts +0 -12
  86. package/src/pm-plugins/sticky-headers/types.ts +0 -20
  87. package/src/pm-plugins/sticky-headers/util.ts +0 -18
  88. package/src/pm-plugins/table-analytics.ts +0 -100
  89. package/src/pm-plugins/table-local-id.ts +0 -213
  90. package/src/pm-plugins/table-resizing/commands.ts +0 -116
  91. package/src/pm-plugins/table-resizing/event-handlers.ts +0 -352
  92. package/src/pm-plugins/table-resizing/plugin-factory.ts +0 -29
  93. package/src/pm-plugins/table-resizing/plugin-key.ts +0 -5
  94. package/src/pm-plugins/table-resizing/plugin.ts +0 -94
  95. package/src/pm-plugins/table-resizing/reducer.ts +0 -37
  96. package/src/pm-plugins/table-resizing/utils/colgroup.ts +0 -306
  97. package/src/pm-plugins/table-resizing/utils/column-state.ts +0 -120
  98. package/src/pm-plugins/table-resizing/utils/consts.ts +0 -11
  99. package/src/pm-plugins/table-resizing/utils/content-width.ts +0 -118
  100. package/src/pm-plugins/table-resizing/utils/dom.ts +0 -132
  101. package/src/pm-plugins/table-resizing/utils/misc.ts +0 -282
  102. package/src/pm-plugins/table-resizing/utils/resize-column.ts +0 -34
  103. package/src/pm-plugins/table-resizing/utils/resize-logic.ts +0 -289
  104. package/src/pm-plugins/table-resizing/utils/resize-state.ts +0 -417
  105. package/src/pm-plugins/table-resizing/utils/scale-table.ts +0 -290
  106. package/src/pm-plugins/table-resizing/utils/types.ts +0 -25
  107. package/src/pm-plugins/table-resizing/utils/unit-to-number.ts +0 -1
  108. package/src/pm-plugins/table-selection-keymap.ts +0 -64
  109. package/src/pm-plugins/table-size-selector.ts +0 -39
  110. package/src/pm-plugins/table-width-in-comment-fix.ts +0 -113
  111. package/src/pm-plugins/table-width.ts +0 -153
  112. package/src/pm-plugins/transforms/column-width.ts +0 -249
  113. package/src/pm-plugins/transforms/delete-columns.ts +0 -281
  114. package/src/pm-plugins/transforms/delete-rows.ts +0 -154
  115. package/src/pm-plugins/transforms/fix-tables.ts +0 -249
  116. package/src/pm-plugins/transforms/merge.ts +0 -301
  117. package/src/pm-plugins/transforms/replace-table.ts +0 -38
  118. package/src/pm-plugins/transforms/split.ts +0 -90
  119. package/src/pm-plugins/utils/alignment.ts +0 -33
  120. package/src/pm-plugins/utils/analytics.ts +0 -238
  121. package/src/pm-plugins/utils/collapse.ts +0 -93
  122. package/src/pm-plugins/utils/column-controls.ts +0 -250
  123. package/src/pm-plugins/utils/create.ts +0 -64
  124. package/src/pm-plugins/utils/decoration.ts +0 -672
  125. package/src/pm-plugins/utils/dom.ts +0 -251
  126. package/src/pm-plugins/utils/drag-menu.tsx +0 -491
  127. package/src/pm-plugins/utils/get-allow-add-column-custom-step.ts +0 -10
  128. package/src/pm-plugins/utils/guidelines.ts +0 -30
  129. package/src/pm-plugins/utils/merged-cells.ts +0 -239
  130. package/src/pm-plugins/utils/nodes.ts +0 -162
  131. package/src/pm-plugins/utils/paste.ts +0 -386
  132. package/src/pm-plugins/utils/row-controls.ts +0 -211
  133. package/src/pm-plugins/utils/selection.ts +0 -17
  134. package/src/pm-plugins/utils/snapping.ts +0 -136
  135. package/src/pm-plugins/utils/table.ts +0 -60
  136. package/src/pm-plugins/utils/update-plugin-state-decorations.ts +0 -13
  137. package/src/pm-plugins/view-mode-sort/consts.ts +0 -3
  138. package/src/pm-plugins/view-mode-sort/index.ts +0 -291
  139. package/src/pm-plugins/view-mode-sort/plugin-key.ts +0 -7
  140. package/src/pm-plugins/view-mode-sort/types.ts +0 -23
  141. package/src/pm-plugins/view-mode-sort/utils.ts +0 -136
  142. package/src/tablePlugin.tsx +0 -971
  143. package/src/tablePluginType.ts +0 -102
  144. package/src/types/index.ts +0 -592
  145. package/src/ui/ColumnResizeWidget/index.tsx +0 -61
  146. package/src/ui/ContentComponent.tsx +0 -311
  147. package/src/ui/DragHandle/HandleIconComponent.tsx +0 -21
  148. package/src/ui/DragHandle/index.tsx +0 -391
  149. package/src/ui/DragPreview/index.tsx +0 -51
  150. package/src/ui/FloatingAlignmentButtons/FloatingAlignmentButtons.tsx +0 -59
  151. package/src/ui/FloatingContextualButton/FixedButton.tsx +0 -203
  152. package/src/ui/FloatingContextualButton/index.tsx +0 -168
  153. package/src/ui/FloatingContextualButton/styles.ts +0 -69
  154. package/src/ui/FloatingContextualMenu/ContextualMenu.tsx +0 -931
  155. package/src/ui/FloatingContextualMenu/index.tsx +0 -141
  156. package/src/ui/FloatingContextualMenu/styles.ts +0 -77
  157. package/src/ui/FloatingDeleteButton/DeleteButton.tsx +0 -54
  158. package/src/ui/FloatingDeleteButton/getPopUpOptions.ts +0 -65
  159. package/src/ui/FloatingDeleteButton/index.tsx +0 -383
  160. package/src/ui/FloatingDeleteButton/types.ts +0 -3
  161. package/src/ui/FloatingDragMenu/DragMenu.tsx +0 -668
  162. package/src/ui/FloatingDragMenu/DropdownMenu.tsx +0 -221
  163. package/src/ui/FloatingDragMenu/index.tsx +0 -136
  164. package/src/ui/FloatingDragMenu/styles.ts +0 -83
  165. package/src/ui/FloatingInsertButton/InsertButton.tsx +0 -263
  166. package/src/ui/FloatingInsertButton/getPopupOptions.ts +0 -131
  167. package/src/ui/FloatingInsertButton/index.tsx +0 -314
  168. package/src/ui/FloatingToolbarLabel/FloatingToolbarLabel.tsx +0 -31
  169. package/src/ui/SizeSelector/index.tsx +0 -74
  170. package/src/ui/TableFloatingColumnControls/ColumnControls/index.tsx +0 -397
  171. package/src/ui/TableFloatingColumnControls/ColumnDropTargets/ColumnDropTarget.tsx +0 -105
  172. package/src/ui/TableFloatingColumnControls/ColumnDropTargets/index.tsx +0 -63
  173. package/src/ui/TableFloatingColumnControls/index.tsx +0 -151
  174. package/src/ui/TableFloatingControls/CornerControls/ClassicCornerControls.tsx +0 -106
  175. package/src/ui/TableFloatingControls/CornerControls/DragCornerControls.tsx +0 -143
  176. package/src/ui/TableFloatingControls/CornerControls/types.ts +0 -12
  177. package/src/ui/TableFloatingControls/FloatingControlsWithSelection.tsx +0 -88
  178. package/src/ui/TableFloatingControls/NumberColumn/index.tsx +0 -175
  179. package/src/ui/TableFloatingControls/RowControls/ClassicControls.tsx +0 -131
  180. package/src/ui/TableFloatingControls/RowControls/DragControls.tsx +0 -429
  181. package/src/ui/TableFloatingControls/RowDropTarget/index.tsx +0 -96
  182. package/src/ui/TableFloatingControls/index.tsx +0 -275
  183. package/src/ui/TableFullWidthLabel/index.tsx +0 -38
  184. package/src/ui/common-styles.ts +0 -1218
  185. package/src/ui/consts.ts +0 -109
  186. package/src/ui/event-handlers.ts +0 -662
  187. package/src/ui/global-styles.tsx +0 -55
  188. package/src/ui/hooks/useInternalTablePluginStateSelector.ts +0 -38
  189. package/src/ui/icons/AddColLeftIcon.tsx +0 -37
  190. package/src/ui/icons/AddColRightIcon.tsx +0 -37
  191. package/src/ui/icons/AddRowAboveIcon.tsx +0 -22
  192. package/src/ui/icons/AddRowBelowIcon.tsx +0 -39
  193. package/src/ui/icons/DragHandleDisabledIcon.tsx +0 -25
  194. package/src/ui/icons/DragHandleIcon.tsx +0 -16
  195. package/src/ui/icons/DragInMotionIcon.tsx +0 -54
  196. package/src/ui/icons/MergeCellsIcon.tsx +0 -26
  197. package/src/ui/icons/MinimisedHandle.tsx +0 -15
  198. package/src/ui/icons/SortingIconWrapper.tsx +0 -43
  199. package/src/ui/icons/SplitCellIcon.tsx +0 -34
  200. package/src/ui/toolbar.tsx +0 -1153
  201. package/src/ui/ui-styles.ts +0 -960
  202. package/tsconfig.app.json +0 -135
  203. package/tsconfig.dev.json +0 -54
  204. package/tsconfig.json +0 -18
@@ -1,1590 +0,0 @@
1
- import type { CSSProperties } from 'react';
2
- import React from 'react';
3
-
4
- import classnames from 'classnames';
5
- import memoizeOne from 'memoize-one';
6
- import rafSchedule from 'raf-schd';
7
- import type { IntlShape } from 'react-intl-next';
8
- import { injectIntl } from 'react-intl-next';
9
-
10
- import type { TableColumnOrdering } from '@atlaskit/custom-steps';
11
- import { ACTION_SUBJECT, EVENT_TYPE, TABLE_ACTION } from '@atlaskit/editor-common/analytics';
12
- import type { DispatchAnalyticsEvent } from '@atlaskit/editor-common/analytics';
13
- import { tintDirtyTransaction } from '@atlaskit/editor-common/collab';
14
- import type { EventDispatcher } from '@atlaskit/editor-common/event-dispatcher';
15
- import { getParentOfTypeCount } from '@atlaskit/editor-common/nesting';
16
- import { nodeVisibilityManager } from '@atlaskit/editor-common/node-visibility';
17
- import { getParentNodeWidth, getTableContainerWidth } from '@atlaskit/editor-common/node-width';
18
- import { tableMarginSides } from '@atlaskit/editor-common/styles';
19
- import type { EditorContainerWidth, GetEditorFeatureFlags } from '@atlaskit/editor-common/types';
20
- import { browser, isValidPosition } from '@atlaskit/editor-common/utils';
21
- import type { Node as PmNode } from '@atlaskit/editor-prosemirror/model';
22
- import type { Selection } from '@atlaskit/editor-prosemirror/state';
23
- import type { EditorView } from '@atlaskit/editor-prosemirror/view';
24
- import {
25
- akEditorTableNumberColumnWidth,
26
- akEditorTableToolbarSize as tableToolbarSize,
27
- } from '@atlaskit/editor-shared-styles';
28
- import { findTable, isTableSelected } from '@atlaskit/editor-tables/utils';
29
- import { fg } from '@atlaskit/platform-feature-flags';
30
- import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
31
- import type { CleanupFn } from '@atlaskit/pragmatic-drag-and-drop/types';
32
- import UFOLoadHold from '@atlaskit/react-ufo/load-hold';
33
- import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
34
- import { token } from '@atlaskit/tokens';
35
-
36
- import { autoSizeTable, clearHoverSelection } from '../pm-plugins/commands';
37
- import { autoScrollerFactory } from '../pm-plugins/drag-and-drop/utils/autoscrollers';
38
- import { getPluginState } from '../pm-plugins/plugin-factory';
39
- import { pluginKey as stickyHeadersPluginKey } from '../pm-plugins/sticky-headers/plugin-key';
40
- import type { RowStickyState, StickyPluginState } from '../pm-plugins/sticky-headers/types';
41
- import { findStickyHeaderForTable } from '../pm-plugins/sticky-headers/util';
42
- import { META_KEYS } from '../pm-plugins/table-analytics';
43
- import {
44
- insertColgroupFromNode,
45
- hasTableBeenResized,
46
- } from '../pm-plugins/table-resizing/utils/colgroup';
47
- import {
48
- COLUMN_MIN_WIDTH,
49
- TABLE_EDITOR_MARGIN,
50
- TABLE_OFFSET_IN_COMMENT_EDITOR,
51
- } from '../pm-plugins/table-resizing/utils/consts';
52
- import { updateControls } from '../pm-plugins/table-resizing/utils/dom';
53
- import {
54
- getLayoutSize,
55
- getScalingPercentForTableWithoutWidth,
56
- getTableScalingPercent,
57
- } from '../pm-plugins/table-resizing/utils/misc';
58
- import { getResizeState, updateColgroup } from '../pm-plugins/table-resizing/utils/resize-state';
59
- import { scaleTable } from '../pm-plugins/table-resizing/utils/scale-table';
60
- import {
61
- containsHeaderRow,
62
- isTableNested,
63
- isTableNestedInMoreThanOneNode,
64
- tablesHaveDifferentColumnWidths,
65
- tablesHaveDifferentNoOfColumns,
66
- tablesHaveDifferentNoOfRows,
67
- } from '../pm-plugins/utils/nodes';
68
- import { getAssistiveMessage } from '../pm-plugins/utils/table';
69
- import type { CellHoverMeta, PluginInjectionAPI } from '../types';
70
- import { TableCssClassName as ClassName, ShadowEvent } from '../types';
71
- import {
72
- handleMouseOut,
73
- handleMouseOver,
74
- isTableInFocus,
75
- withCellTracking,
76
- } from '../ui/event-handlers';
77
- import TableFloatingColumnControls from '../ui/TableFloatingColumnControls';
78
- // Ignored via go/ees005
79
- // eslint-disable-next-line import/no-named-as-default
80
- import TableFloatingControls from '../ui/TableFloatingControls';
81
-
82
- import { ExternalDropTargets } from './ExternalDropTargets';
83
- import { OverflowShadowsObserver } from './OverflowShadowsObserver';
84
- import { TableContainer } from './TableContainer';
85
- import { TableStickyScrollbar } from './TableStickyScrollbar';
86
- import type { TableOptions } from './types';
87
-
88
- const isIE11 = browser.ie_version === 11;
89
- // When table is inserted via paste, keyboard shortcut or quickInsert,
90
- // componentDidUpdate is called multiple times. The isOverflowing value is correct only on the last update.
91
- // To make sure we capture the last update, we use setTimeout.
92
- const initialOverflowCaptureTimeroutDelay = 300;
93
-
94
- // This is a hard switch for controlling whether the overflow analytics should be dispatched. There has been 6months of data
95
- // already collected which we could use but have not. This has been disabled rather then removed entirely in the event that
96
- // the current collected data becomes stale and we want to start collecting fresh data again in future.
97
- // PLEASE NOTE: that the current way this alaytics has been configured WILL cause reflows to occur. This is why the has been disabled.
98
- const isOverflowAnalyticsEnabled = false;
99
-
100
- // Prevent unnecessary parentWidth updates when table is nested inside of a node that is nested itself.
101
- const NESTED_TABLE_IN_NESTED_PARENT_WIDTH_DIFF_MIN_THRESHOLD = 2;
102
- const NESTED_TABLE_IN_NESTED_PARENT_WIDTH_DIFF_MAX_THRESHOLD = 20;
103
-
104
- interface ComponentProps {
105
- view: EditorView;
106
- getNode: () => PmNode;
107
- allowColumnResizing?: boolean;
108
- eventDispatcher: EventDispatcher;
109
- getPos: () => number | undefined;
110
- options?: TableOptions;
111
-
112
- contentDOM: (node: HTMLElement | null) => void;
113
- containerWidth: EditorContainerWidth;
114
- allowControls?: boolean;
115
-
116
- allowTableResizing?: boolean;
117
- allowTableAlignment?: boolean;
118
-
119
- isHeaderRowEnabled: boolean;
120
- isHeaderColumnEnabled: boolean;
121
- isMediaFullscreen?: boolean;
122
- isDragAndDropEnabled?: boolean;
123
- isTableScalingEnabled?: boolean;
124
- tableActive: boolean;
125
- ordering?: TableColumnOrdering;
126
- isResizing?: boolean;
127
- getEditorFeatureFlags: GetEditorFeatureFlags;
128
- dispatchAnalyticsEvent: DispatchAnalyticsEvent;
129
- pluginInjectionApi?: PluginInjectionAPI;
130
- intl: IntlShape;
131
-
132
- // marking props as optional to ensure backward compatibility when platform_editor_table_use_shared_state_hook_fg disabled
133
- isInDanger?: boolean;
134
- hoveredRows?: number[];
135
- hoveredCell?: CellHoverMeta;
136
- isTableHovered?: boolean;
137
- isWholeTableInDanger?: boolean;
138
- selection?: Selection;
139
- limitedMode?: boolean;
140
- }
141
-
142
- interface TableState {
143
- scroll: number;
144
- parentWidth?: number;
145
- stickyHeader?: RowStickyState;
146
- [ShadowEvent.SHOW_BEFORE_SHADOW]: boolean;
147
- [ShadowEvent.SHOW_AFTER_SHADOW]: boolean;
148
- tableWrapperWidth?: number;
149
- tableWrapperHeight?: number;
150
- windowResized?: boolean;
151
- }
152
-
153
- // Generate a unique ID to prevent collisions when multiple plugin versions exist on the same page
154
- const generateUniqueTableId = () => {
155
- // Use crypto.randomUUID() if available, fallback to Math.random() based approach
156
- if (!globalThis.crypto || typeof globalThis.crypto.randomUUID !== 'function') {
157
- // Fallback: for older environments (IE).
158
- // Not the best fallback, but the crypto.randomUUID is widely available
159
- return (Math.random() + 1).toString(36).substring(20);
160
- }
161
- return crypto.randomUUID();
162
- };
163
-
164
- // Ignored via go/ees005
165
- // eslint-disable-next-line @repo/internal/react/no-class-components
166
- class TableComponent extends React.Component<ComponentProps, TableState> {
167
- static displayName = 'TableComponent';
168
-
169
- state: TableState = {
170
- scroll: 0,
171
- parentWidth: undefined,
172
- [ShadowEvent.SHOW_BEFORE_SHADOW]: false,
173
- [ShadowEvent.SHOW_AFTER_SHADOW]: false,
174
- tableWrapperWidth: undefined,
175
- tableWrapperHeight: undefined,
176
- windowResized: false,
177
- };
178
-
179
- private wrapper?: HTMLDivElement | null;
180
- private table?: HTMLTableElement | null;
181
- private node: PmNode;
182
- private containerWidth?: EditorContainerWidth;
183
- private wasResizing?: boolean;
184
- private tableNodeWidth?: number;
185
- private layoutSize?: number;
186
- private overflowShadowsObserver?: OverflowShadowsObserver;
187
- private stickyScrollbar?: TableStickyScrollbar;
188
-
189
- private isInitialOverflowSent: boolean;
190
- private isNestedInTable: boolean;
191
- private initialOverflowCaptureTimerId?: ReturnType<typeof setTimeout>;
192
- private resizeObserver?: ResizeObserver;
193
-
194
- private wrapperWidth?: number;
195
- private wrapperReisizeObserver?: ResizeObserver;
196
-
197
- private updateColGroupFromFullWidthChange?: boolean;
198
-
199
- private dragAndDropCleanupFn?: CleanupFn;
200
- private nodeVisibilityObserverCleanupFn?: CleanupFn;
201
- private holdCompleted = false;
202
- private dispatchEventName = `tableResized-${generateUniqueTableId()}`;
203
-
204
- constructor(props: ComponentProps) {
205
- super(props);
206
- const { options, containerWidth, getNode } = props;
207
- this.node = getNode();
208
- this.containerWidth = containerWidth;
209
-
210
- const tablePos = props.getPos();
211
-
212
- this.isNestedInTable = tablePos
213
- ? getParentOfTypeCount(props.view.state.schema.nodes.table)(
214
- props.view.state.doc.resolve(tablePos),
215
- ) > 0
216
- : false;
217
-
218
- this.isInitialOverflowSent = false;
219
-
220
- if (!this.updateColGroupFromFullWidthChange) {
221
- this.updateColGroupFromFullWidthChange =
222
- options?.isFullWidthModeEnabled && !options?.wasFullWidthModeEnabled;
223
- }
224
-
225
- // store table size using previous full-width mode so can detect if it has changed.
226
- const isFullWidthModeEnabled = options ? options.wasFullWidthModeEnabled : false;
227
- this.layoutSize = this.tableNodeLayoutSize(this.node, containerWidth.width, {
228
- isFullWidthModeEnabled,
229
- });
230
-
231
- this.resizeObserver = new ResizeObserver((entries) => {
232
- for (const entry of entries) {
233
- this.setState((prev) => {
234
- return prev?.tableWrapperWidth === entry.contentRect?.width &&
235
- prev?.tableWrapperHeight === entry.contentRect?.height
236
- ? prev
237
- : {
238
- ...prev,
239
- tableWrapperWidth: entry.contentRect.width,
240
- tableWrapperHeight: entry.contentRect.height,
241
- };
242
- });
243
- }
244
- });
245
-
246
- // Disable inline table editing and resizing controls in Firefox
247
- // https://github.com/ProseMirror/prosemirror/issues/432
248
- if ('execCommand' in document) {
249
- ['enableObjectResizing', 'enableInlineTableEditing'].forEach((cmd) => {
250
- if (document.queryCommandSupported(cmd)) {
251
- document.execCommand(cmd, false, 'false');
252
- }
253
- });
254
- }
255
- }
256
-
257
- private handleMouseOut = (event: Event) => {
258
- if (!isTableInFocus(this.props.view)) {
259
- return false;
260
- }
261
- return handleMouseOut(this.props.view, event);
262
- };
263
-
264
- private handleMouseOver = (event: Event) => {
265
- if (!isTableInFocus(this.props.view)) {
266
- return false;
267
- }
268
- return withCellTracking(handleMouseOver)(this.props.view, event);
269
- };
270
-
271
- componentDidMount() {
272
- const { observe } = nodeVisibilityManager(this.props.view.dom);
273
- if (this.table) {
274
- this.nodeVisibilityObserverCleanupFn = observe({
275
- element: this.table,
276
- onFirstVisible: () => {
277
- this.initialiseEventListenersAfterMount();
278
- // force width calculcation - missed resize event under firefox when
279
- // table is nested within bodied extension
280
- if (this.wrapper && fg('platform_editor_nodevisibility_resize_sync')) {
281
- this.wrapperWidth = this.wrapper?.clientWidth;
282
- }
283
- },
284
- });
285
- }
286
- }
287
-
288
- initialiseEventListenersAfterMount() {
289
- const {
290
- allowColumnResizing,
291
- allowTableResizing,
292
- eventDispatcher,
293
- isDragAndDropEnabled,
294
- getNode,
295
- getEditorFeatureFlags,
296
- isTableScalingEnabled,
297
- } = this.props;
298
-
299
- // Ignored via go/ees005
300
- // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
301
- this?.table?.addEventListener('mouseenter', this.handleMouseEnter);
302
-
303
- // Ignored via go/ees005
304
- // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
305
- this?.table?.addEventListener('mouseout', this.handleMouseOut);
306
-
307
- // Ignored via go/ees005
308
- // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
309
- this?.table?.addEventListener('mouseover', this.handleMouseOver);
310
-
311
- const { tableWithFixedColumnWidthsOption = false } = getEditorFeatureFlags();
312
-
313
- if (!expValEquals('platform_editor_tables_scaling_css', 'isEnabled', true)) {
314
- if (isTableScalingEnabled && !tableWithFixedColumnWidthsOption) {
315
- this.handleColgroupUpdates(true);
316
- }
317
-
318
- if (
319
- isTableScalingEnabled &&
320
- tableWithFixedColumnWidthsOption &&
321
- getNode().attrs.displayMode !== 'fixed'
322
- ) {
323
- this.handleColgroupUpdates(true);
324
- }
325
- }
326
-
327
- if (this.wrapper) {
328
- this.wrapperReisizeObserver = new ResizeObserver((entries) => {
329
- for (const entry of entries) {
330
- this.wrapperWidth = entry.contentRect?.width;
331
- }
332
- });
333
-
334
- this.wrapperReisizeObserver.observe(this.wrapper);
335
- }
336
-
337
- if (allowColumnResizing && this.wrapper && !isIE11) {
338
- // Ignored via go/ees005
339
- // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
340
- this.wrapper.addEventListener('scroll', this.handleScrollDebounced, {
341
- passive: true,
342
- });
343
-
344
- if (fg('disable-sticky-scrollbar-for-nested-tables')) {
345
- if (this.table && !this.isNestedInTable) {
346
- this.stickyScrollbar = new TableStickyScrollbar(this.wrapper, this.props.view);
347
- }
348
- } else {
349
- if (this.table) {
350
- this.stickyScrollbar = new TableStickyScrollbar(this.wrapper, this.props.view);
351
- }
352
- }
353
-
354
- if (isDragAndDropEnabled) {
355
- this.dragAndDropCleanupFn = combine(
356
- ...autoScrollerFactory({
357
- tableWrapper: this.wrapper,
358
- getNode,
359
- }),
360
- );
361
- }
362
- }
363
-
364
- if (allowColumnResizing) {
365
- /**
366
- * We no longer use `containerWidth` as a variable to determine an update for table resizing (avoids unnecessary updates).
367
- * Instead we use the resize event to only trigger updates when necessary.
368
- */
369
- if (!allowTableResizing) {
370
- // Ignored via go/ees005
371
- // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
372
- window.addEventListener('resize', this.handleWindowResizeDebounced);
373
- }
374
- // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
375
- window.addEventListener('resize', this.handleWindowResizeNewDebounced);
376
- this.handleTableResizingDebounced();
377
- }
378
-
379
- const currentStickyState = stickyHeadersPluginKey.getState(this.props.view.state);
380
-
381
- if (currentStickyState) {
382
- this.onStickyState(currentStickyState);
383
- }
384
-
385
- // Ignored via go/ees005
386
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
387
- eventDispatcher.on((stickyHeadersPluginKey as any).key, this.onStickyState);
388
-
389
- if (isOverflowAnalyticsEnabled) {
390
- const initialIsOveflowing =
391
- this.state[ShadowEvent.SHOW_BEFORE_SHADOW] || this.state[ShadowEvent.SHOW_AFTER_SHADOW];
392
-
393
- this.setTimerToSendInitialOverflowCaptured(initialIsOveflowing);
394
- }
395
- }
396
-
397
- componentWillUnmount() {
398
- const { allowColumnResizing, allowTableResizing, eventDispatcher, isDragAndDropEnabled } =
399
- this.props;
400
- if (this.wrapper && !isIE11) {
401
- // Ignored via go/ees005
402
- // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
403
- this.wrapper.removeEventListener('scroll', this.handleScrollDebounced);
404
- }
405
-
406
- if (isDragAndDropEnabled && this.dragAndDropCleanupFn) {
407
- this.dragAndDropCleanupFn();
408
- }
409
-
410
- if (this.nodeVisibilityObserverCleanupFn) {
411
- this.nodeVisibilityObserverCleanupFn();
412
- }
413
-
414
- this.resizeObserver?.disconnect();
415
- this.wrapperReisizeObserver?.disconnect();
416
-
417
- if (this.stickyScrollbar) {
418
- this.stickyScrollbar.dispose();
419
- }
420
-
421
- this.handleScrollDebounced.cancel();
422
- this.scaleTableDebounced.cancel();
423
- this.handleTableResizingDebounced.cancel();
424
- this.handleAutoSizeDebounced.cancel();
425
- if (!allowTableResizing) {
426
- this.handleWindowResizeDebounced.cancel();
427
- }
428
- this.handleWindowResizeNewDebounced.cancel();
429
-
430
- if (!allowTableResizing && allowColumnResizing) {
431
- // Ignored via go/ees005
432
- // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
433
- window.removeEventListener('resize', this.handleWindowResizeDebounced);
434
- }
435
-
436
- if (allowColumnResizing) {
437
- // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
438
- window.removeEventListener('resize', this.handleWindowResizeNewDebounced);
439
- }
440
-
441
- // Ignored via go/ees005
442
- // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
443
- this?.table?.removeEventListener('mouseenter', this.handleMouseEnter);
444
-
445
- // Ignored via go/ees005
446
- // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
447
- this?.table?.removeEventListener('mouseout', this.handleMouseOut);
448
-
449
- // Ignored via go/ees005
450
- // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
451
- this?.table?.removeEventListener('mouseover', this.handleMouseOver);
452
-
453
- if (this.overflowShadowsObserver) {
454
- this.overflowShadowsObserver.dispose();
455
- }
456
-
457
- // Ignored via go/ees005
458
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
459
- eventDispatcher.off((stickyHeadersPluginKey as any).key, this.onStickyState);
460
-
461
- if (this.initialOverflowCaptureTimerId) {
462
- clearTimeout(this.initialOverflowCaptureTimerId);
463
- }
464
- }
465
-
466
- handleMouseEnter = () => {
467
- const node = this.props.getNode();
468
- const pos = this.props.getPos();
469
- const tr = this.props.view.state.tr;
470
- const tableId = node.attrs.localId;
471
- tr.setMeta('mouseEnterTable', [tableId, node, pos]);
472
- this.props.view.dispatch(tr);
473
- };
474
-
475
- // Should be called only when table node width is reset to undefined in Comment Editor
476
- // Maybe replaced by handleColgroupUpdates as we implement new table's support in Comment Editor.
477
- removeInlineTableWidth() {
478
- const { isResizing, getNode, view, getPos } = this.props;
479
- if (!this.table) {
480
- return;
481
- }
482
-
483
- const tableNode = getNode();
484
- const newTableWidth = tableNode.attrs.width;
485
-
486
- const start = getPos() || 0;
487
- const depth = view.state.doc.resolve(start).depth;
488
- if (depth !== 0) {
489
- return;
490
- }
491
-
492
- if (!isResizing && newTableWidth === null) {
493
- this.table.style.width = '';
494
- }
495
- }
496
-
497
- handleColgroupUpdates(force = false) {
498
- const { getNode, containerWidth, isResizing, view, getPos, getEditorFeatureFlags, options } =
499
- this.props;
500
-
501
- if (!this.table) {
502
- return;
503
- }
504
-
505
- // Remove any widths styles after resizing preview is completed
506
- this.table.style.width = '';
507
- const tableNode = getNode();
508
- const start = getPos() || 0;
509
- const depth = view.state.doc.resolve(start).depth;
510
-
511
- if (depth !== 0) {
512
- return;
513
- }
514
-
515
- let tableNodeWidth = getTableContainerWidth(tableNode);
516
- const isTableResizedFullWidth = tableNodeWidth === 1800 && this.wasResizing && !isResizing;
517
-
518
- // Needed for undo / redo
519
- const isTableWidthChanged = tableNodeWidth !== this.tableNodeWidth;
520
-
521
- const tableRenderWidth = options?.isCommentEditor
522
- ? containerWidth.width - (TABLE_OFFSET_IN_COMMENT_EDITOR + 1) // should be the same as this.table.parentElement?.clientWidth - 1, subtract 1 to avoid overflow
523
- : containerWidth.width - TABLE_EDITOR_MARGIN;
524
-
525
- tableNodeWidth =
526
- options?.isCommentEditor && !tableNode.attrs.width ? tableRenderWidth : tableNodeWidth;
527
-
528
- const isTableSquashed = tableRenderWidth < tableNodeWidth;
529
- const isNumberColumnChanged =
530
- tableNode.attrs.isNumberColumnEnabled !== this.node.attrs.isNumberColumnEnabled;
531
- const isNumberOfColumnsChanged = tablesHaveDifferentNoOfColumns(tableNode, this.node);
532
-
533
- const { width: containerWidthValue, lineLength: containerLineLength } = containerWidth;
534
- const isLineLengthChanged = this.containerWidth?.lineLength !== containerLineLength;
535
-
536
- const isFullWidthModeAndLineLengthChanged =
537
- this.updateColGroupFromFullWidthChange &&
538
- isLineLengthChanged &&
539
- fg('platform_editor_table_overflow_in_full_width_fix');
540
-
541
- const maybeScale =
542
- isTableSquashed ||
543
- isTableWidthChanged ||
544
- (isTableResizedFullWidth && !options?.isCommentEditor) ||
545
- isNumberColumnChanged ||
546
- isNumberOfColumnsChanged ||
547
- (expValEquals('platform_editor_tables_scaling_css', 'isEnabled', true) &&
548
- this.state.windowResized);
549
-
550
- if (force || maybeScale || isFullWidthModeAndLineLengthChanged) {
551
- const isWidthChanged = this.containerWidth?.width !== containerWidthValue;
552
- const wasTableResized = hasTableBeenResized(this.node);
553
- const isTableResized = hasTableBeenResized(tableNode);
554
- const isColumnsDistributed = wasTableResized && !isTableResized;
555
- const isTableDisplayModeChanged = this.node.attrs.displayMode !== tableNode.attrs.displayMode;
556
-
557
- const shouldUpdateColgroup = this.shouldUpdateColgroup({
558
- isWindowResized: this.state.windowResized,
559
- isWidthChanged,
560
- isTableWidthChanged,
561
- isColumnsDistributed,
562
- isTableResizedFullWidth,
563
- isTableDisplayModeChanged,
564
- isNumberColumnChanged,
565
- isNumberOfColumnsChanged,
566
- isFullWidthModeAndLineLengthChanged,
567
- });
568
-
569
- const { tableWithFixedColumnWidthsOption = false } = getEditorFeatureFlags();
570
-
571
- const isTableScalingWithFixedColumnWidthsOptionEnabled =
572
- !!this.props.options?.isTableScalingEnabled && tableWithFixedColumnWidthsOption;
573
-
574
- const shouldUseIncreasedScalingPercent =
575
- isTableScalingWithFixedColumnWidthsOptionEnabled ||
576
- (!!this.props.options?.isTableScalingEnabled && !!this.props.options?.isCommentEditor);
577
-
578
- if (force || (!isResizing && shouldUpdateColgroup)) {
579
- const resizeState = getResizeState({
580
- minWidth: COLUMN_MIN_WIDTH,
581
- // When numbered column enabled, we need to subtract the width of the numbered column
582
- maxSize: tableNode.attrs.isNumberColumnEnabled
583
- ? tableRenderWidth - akEditorTableNumberColumnWidth
584
- : tableRenderWidth,
585
- table: tableNode,
586
- tableRef: this.table,
587
- start,
588
- domAtPos: view.domAtPos.bind(view),
589
- isTableScalingEnabled: true,
590
- shouldUseIncreasedScalingPercent,
591
- isCommentEditor: !!this.props.options?.isCommentEditor,
592
- });
593
-
594
- let shouldScaleOnColgroupUpdate = false;
595
- if (this.props.options?.isTableScalingEnabled && !tableWithFixedColumnWidthsOption) {
596
- shouldScaleOnColgroupUpdate = true;
597
- }
598
-
599
- if (
600
- isTableScalingWithFixedColumnWidthsOptionEnabled &&
601
- tableNode.attrs.displayMode !== 'fixed'
602
- ) {
603
- shouldScaleOnColgroupUpdate = true;
604
- }
605
-
606
- if (this.props.options?.isTableScalingEnabled && this.props.options?.isCommentEditor) {
607
- shouldScaleOnColgroupUpdate = true;
608
- }
609
-
610
- let scalePercent = 1;
611
- requestAnimationFrame(() => {
612
- // Scaling percent has to be calculated inside requestAnimationFrame, otherwise
613
- // renderWidth calculated as `tableRef?.parentElement?.clientWidth`
614
- // inside of getTableScalingPercent returns 0.
615
- if (
616
- !this.props.options?.isCommentEditor ||
617
- (this.props.options?.isCommentEditor && tableNode.attrs.width)
618
- ) {
619
- scalePercent = getTableScalingPercent(
620
- tableNode,
621
- // Ignored via go/ees005
622
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
623
- this.table!,
624
- shouldUseIncreasedScalingPercent,
625
- );
626
- } else {
627
- // Ignored via go/ees005
628
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
629
- scalePercent = getScalingPercentForTableWithoutWidth(tableNode, this.table!);
630
- }
631
-
632
- // Request animation frame required for Firefox
633
- updateColgroup(
634
- resizeState,
635
- // Ignored via go/ees005
636
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
637
- this.table!,
638
- tableNode,
639
- shouldScaleOnColgroupUpdate,
640
- scalePercent,
641
- );
642
-
643
- if (expValEquals('cc_editor_ufo_hold_table_till_resize_complete', 'isEnabled', true)) {
644
- // Mark table as updated for TableHold component (if no table exists yet, the colgroup update will not have done anything)
645
- if (this.table && !this.holdCompleted) {
646
- const customTableResizedEvent = new CustomEvent(this.dispatchEventName);
647
-
648
- document.dispatchEvent(customTableResizedEvent);
649
- this.holdCompleted = true;
650
- }
651
- }
652
- });
653
- }
654
- }
655
-
656
- if (isFullWidthModeAndLineLengthChanged) {
657
- this.updateColGroupFromFullWidthChange = false;
658
- }
659
-
660
- this.tableNodeWidth = tableNodeWidth;
661
- this.wasResizing = isResizing;
662
- this.containerWidth = containerWidth;
663
- }
664
-
665
- // Ignored via go/ees005
666
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
667
- componentDidUpdate(_: any, prevState: TableState) {
668
- const {
669
- view,
670
- getNode,
671
- isMediaFullscreen,
672
- allowColumnResizing,
673
- allowTableResizing,
674
- isResizing,
675
- options,
676
- isTableScalingEnabled, // we could use options.isTableScalingEnabled here
677
- getPos,
678
- getEditorFeatureFlags,
679
- } = this.props;
680
- let { isInDanger } = this.props;
681
-
682
- const table = findTable(view.state.selection);
683
-
684
- if (!fg('platform_editor_table_use_shared_state_hook_fg')) {
685
- const pluginState = getPluginState(view.state);
686
- isInDanger = pluginState.isInDanger;
687
- }
688
-
689
- let shouldScale = false;
690
- let shouldHandleColgroupUpdates = false;
691
- const { tableWithFixedColumnWidthsOption = false } = getEditorFeatureFlags();
692
-
693
- if (isTableScalingEnabled && !tableWithFixedColumnWidthsOption) {
694
- shouldScale = true;
695
- shouldHandleColgroupUpdates = true;
696
- }
697
-
698
- const isTableScalingWithFixedColumnWidthsOptionEnabled =
699
- !!isTableScalingEnabled && tableWithFixedColumnWidthsOption;
700
- const shouldUseIncreasedScalingPercent =
701
- isTableScalingWithFixedColumnWidthsOptionEnabled ||
702
- (!!isTableScalingEnabled && !!this.props.options?.isCommentEditor);
703
-
704
- if (
705
- isTableScalingWithFixedColumnWidthsOptionEnabled &&
706
- getNode().attrs.displayMode !== 'fixed'
707
- ) {
708
- shouldScale = true;
709
- shouldHandleColgroupUpdates = true;
710
- }
711
-
712
- if (
713
- expValEquals('platform_editor_tables_scaling_css', 'isEnabled', true) &&
714
- this.state.windowResized
715
- ) {
716
- shouldHandleColgroupUpdates = true;
717
- }
718
-
719
- if (shouldHandleColgroupUpdates) {
720
- this.handleColgroupUpdates();
721
- }
722
-
723
- if (isInDanger && !table) {
724
- clearHoverSelection()(view.state, view.dispatch);
725
- }
726
-
727
- if (
728
- this.props.options?.isCommentEditor &&
729
- allowTableResizing &&
730
- !options?.isTableScalingEnabled
731
- ) {
732
- this.removeInlineTableWidth();
733
- }
734
-
735
- if (this.wrapper?.parentElement && this.table && !this.overflowShadowsObserver) {
736
- if (this.props.isDragAndDropEnabled) {
737
- // requestAnimationFrame is used here to fix a race condition issue
738
- // that happens when a table is nested in expand and expand's width is
739
- // changed via breakout button
740
- window.requestAnimationFrame(() => {
741
- this.overflowShadowsObserver = new OverflowShadowsObserver(
742
- this.updateShadowStateDebounced,
743
- // Ignored via go/ees005
744
- // eslint-disable-next-line @atlaskit/editor/no-as-casting
745
- this.table as HTMLElement,
746
- this.wrapper as HTMLDivElement,
747
- );
748
- });
749
- } else {
750
- this.overflowShadowsObserver = new OverflowShadowsObserver(
751
- this.updateShadowState,
752
- this.table,
753
- this.wrapper,
754
- );
755
- }
756
- }
757
-
758
- if (this.overflowShadowsObserver) {
759
- this.overflowShadowsObserver.observeShadowSentinels(this.state.stickyHeader?.sticky);
760
- }
761
-
762
- const currentTable = getNode();
763
- const previousTable = this.node;
764
- const isNoOfColumnsChanged = tablesHaveDifferentNoOfColumns(currentTable, previousTable);
765
- const isNoOfRowsChanged = tablesHaveDifferentNoOfRows(currentTable, previousTable);
766
- if (isNoOfColumnsChanged || isNoOfRowsChanged) {
767
- this.props.pluginInjectionApi?.accessibilityUtils?.actions.ariaNotify(
768
- getAssistiveMessage(previousTable, currentTable, this.props.intl),
769
- { priority: 'important' },
770
- );
771
- }
772
-
773
- if (currentTable.attrs.__autoSize) {
774
- // Wait for next tick to handle auto sizing, gives the browser time to do layout calc etc.
775
- this.handleAutoSizeDebounced();
776
- }
777
- // re-drawing will cause media component get unmounted that will exit fullscreen mode if media is in fullscreen mode
778
- // see https://product-fabric.atlassian.net/browse/MEX-1290
779
- else if (allowColumnResizing && this.table && !isMediaFullscreen) {
780
- // If col widths (e.g. via collab) or number of columns (e.g. delete a column) have changed,
781
- // re-draw colgroup.
782
- if (tablesHaveDifferentColumnWidths(currentTable, previousTable) || isNoOfColumnsChanged) {
783
- const { view } = this.props;
784
- const shouldRecreateResizeCols =
785
- !allowTableResizing || !isResizing || (isNoOfColumnsChanged && isResizing);
786
-
787
- if (shouldRecreateResizeCols) {
788
- const start = getPos() || 0;
789
- const depth = view.state.doc.resolve(start).depth;
790
- shouldScale = depth === 0 && shouldScale;
791
- insertColgroupFromNode(
792
- this.table,
793
- currentTable,
794
- shouldScale,
795
- undefined,
796
- shouldUseIncreasedScalingPercent,
797
- options?.isCommentEditor,
798
- );
799
- }
800
-
801
- updateControls()(view.state);
802
- }
803
-
804
- this.handleTableResizingDebounced();
805
- }
806
-
807
- if (isOverflowAnalyticsEnabled) {
808
- const newIsOverflowing =
809
- this.state[ShadowEvent.SHOW_BEFORE_SHADOW] || this.state[ShadowEvent.SHOW_AFTER_SHADOW];
810
-
811
- const prevIsOverflowing =
812
- prevState[ShadowEvent.SHOW_BEFORE_SHADOW] || prevState[ShadowEvent.SHOW_AFTER_SHADOW];
813
-
814
- if (this.initialOverflowCaptureTimerId) {
815
- clearTimeout(this.initialOverflowCaptureTimerId);
816
- }
817
-
818
- if (!this.isInitialOverflowSent) {
819
- this.setTimerToSendInitialOverflowCaptured(newIsOverflowing);
820
- }
821
-
822
- if (this.isInitialOverflowSent && prevIsOverflowing !== newIsOverflowing) {
823
- const {
824
- dispatch,
825
- state: { tr },
826
- } = this.props.view;
827
-
828
- dispatch(
829
- tr.setMeta(META_KEYS.OVERFLOW_STATE_CHANGED, {
830
- isOverflowing: newIsOverflowing,
831
- wasOverflowing: prevIsOverflowing,
832
- editorWidth: this.props.containerWidth.width || 0,
833
- width: this.node.attrs.width || 0,
834
- parentWidth: this.state?.parentWidth || 0,
835
- }),
836
- );
837
- }
838
- }
839
- }
840
-
841
- private updateShadowState = (shadowKey: ShadowEvent, value: boolean) => {
842
- if (this.state[shadowKey] === value) {
843
- return;
844
- }
845
- this.setState({ [shadowKey]: value } as Pick<TableState, typeof shadowKey>);
846
- };
847
-
848
- private createShadowSentinels = (table: HTMLTableElement | null) => {
849
- if (table) {
850
- const shadowSentinelLeft = document.createElement('span');
851
- shadowSentinelLeft.className = ClassName.TABLE_SHADOW_SENTINEL_LEFT;
852
- const shadowSentinelRight = document.createElement('span');
853
- shadowSentinelRight.className = ClassName.TABLE_SHADOW_SENTINEL_RIGHT;
854
- table.prepend(shadowSentinelLeft);
855
- table.prepend(shadowSentinelRight);
856
- }
857
- };
858
-
859
- private observeTable(table: HTMLTableElement | null) {
860
- if (table) {
861
- this.resizeObserver?.observe(table);
862
- }
863
- }
864
-
865
- onStickyState = (state: StickyPluginState) => {
866
- const pos = this.props.getPos();
867
- if (!isValidPosition(pos, this.props.view.state)) {
868
- return;
869
- }
870
- const stickyHeader = findStickyHeaderForTable(state, pos);
871
- if (stickyHeader !== this.state.stickyHeader) {
872
- this.setState({ stickyHeader });
873
- if (this.overflowShadowsObserver) {
874
- this.overflowShadowsObserver.updateStickyShadows();
875
- }
876
- }
877
- };
878
-
879
- // Ignored via go/ees005
880
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
881
- prevTableState: any = null;
882
-
883
- render() {
884
- const {
885
- view,
886
- getNode,
887
- isResizing,
888
- allowControls = true,
889
- isHeaderRowEnabled,
890
- ordering,
891
- isHeaderColumnEnabled,
892
- tableActive,
893
- containerWidth,
894
- options,
895
- getPos,
896
- pluginInjectionApi,
897
- isDragAndDropEnabled,
898
- getEditorFeatureFlags,
899
- isTableScalingEnabled, // here we can use options.isTableScalingEnabled
900
- allowTableResizing,
901
- allowTableAlignment,
902
- selection,
903
- } = this.props;
904
-
905
- let { isInDanger, hoveredRows, hoveredCell, isTableHovered, isWholeTableInDanger } = this.props;
906
-
907
- const { showBeforeShadow, showAfterShadow } = this.state;
908
- const node = getNode();
909
-
910
- if (!fg('platform_editor_table_use_shared_state_hook_fg')) {
911
- const pluginState = getPluginState(view.state);
912
- isInDanger = pluginState.isInDanger;
913
- hoveredRows = pluginState.hoveredRows;
914
- hoveredCell = pluginState.hoveredCell;
915
- isTableHovered = pluginState.isTableHovered;
916
- isWholeTableInDanger = pluginState.isWholeTableInDanger;
917
- }
918
-
919
- const tableRef = this.table || undefined;
920
- const headerRow = tableRef
921
- ? tableRef.querySelector<HTMLTableRowElement>('tr[data-header-row]')
922
- : undefined;
923
-
924
- const hasHeaderRow = containsHeaderRow(node);
925
- const rowControls = (
926
- <TableFloatingControls
927
- editorView={view}
928
- tableRef={tableRef}
929
- tableNode={node}
930
- tableActive={tableActive}
931
- hoveredRows={hoveredRows}
932
- hoveredCell={hoveredCell}
933
- isTableHovered={isTableHovered}
934
- isInDanger={isInDanger}
935
- isResizing={isResizing}
936
- isNumberColumnEnabled={node.attrs.isNumberColumnEnabled}
937
- isHeaderRowEnabled={isHeaderRowEnabled}
938
- isDragAndDropEnabled={isDragAndDropEnabled}
939
- ordering={ordering}
940
- isHeaderColumnEnabled={isHeaderColumnEnabled}
941
- hasHeaderRow={hasHeaderRow}
942
- // pass `selection` and `tableHeight` to control re-render
943
- selection={view.state.selection}
944
- headerRowHeight={headerRow ? headerRow.offsetHeight : undefined}
945
- stickyHeader={!this.props.limitedMode ? this.state.stickyHeader : undefined}
946
- tableWrapperWidth={this.state.tableWrapperWidth}
947
- api={pluginInjectionApi}
948
- isChromelessEditor={options?.isChromelessEditor}
949
- />
950
- );
951
- const tableContainerWidth = getTableContainerWidth(node);
952
- const colControls = isDragAndDropEnabled ? (
953
- <TableFloatingColumnControls
954
- editorView={view}
955
- tableRef={tableRef}
956
- getNode={getNode}
957
- tableActive={tableActive}
958
- isInDanger={isInDanger}
959
- hoveredRows={hoveredRows}
960
- hoveredCell={hoveredCell}
961
- isTableHovered={isTableHovered}
962
- isResizing={isResizing}
963
- ordering={ordering}
964
- hasHeaderRow={hasHeaderRow}
965
- // pass `selection` to control re-render
966
- selection={view.state.selection}
967
- headerRowHeight={headerRow ? headerRow.offsetHeight : undefined}
968
- stickyHeader={!this.props.limitedMode ? this.state.stickyHeader : undefined}
969
- getEditorFeatureFlags={getEditorFeatureFlags}
970
- tableContainerWidth={tableContainerWidth}
971
- isNumberColumnEnabled={node.attrs.isNumberColumnEnabled}
972
- getScrollOffset={() => this.wrapper?.scrollLeft || 0}
973
- tableWrapperHeight={this.state.tableWrapperHeight}
974
- api={pluginInjectionApi}
975
- isChromelessEditor={options?.isChromelessEditor}
976
- />
977
- ) : null;
978
-
979
- const shadowPadding = allowControls && tableActive ? -tableToolbarSize : tableMarginSides;
980
-
981
- const shadowStyle = memoizeOne(
982
- (visible) => ({ visibility: visible ? 'visible' : 'hidden' }) as CSSProperties,
983
- );
984
-
985
- /**
986
- * ED-19838
987
- * There is a getPos issue coming from this code. We need to apply this workaround for now and apply a patch
988
- * before CR6 lands in production
989
- */
990
- let tablePos: number | undefined;
991
- try {
992
- tablePos = getPos ? getPos() : undefined;
993
- } catch (e) {
994
- tablePos = undefined;
995
- }
996
-
997
- const isNested = isTableNested(view.state, tablePos);
998
-
999
- const topShadowPadding = isDragAndDropEnabled ? 0 : shadowPadding;
1000
- const topOffset = 0;
1001
-
1002
- const topStickyShadowPosition =
1003
- !this.props.limitedMode &&
1004
- this.state.stickyHeader &&
1005
- topOffset + this.state.stickyHeader.padding + topShadowPadding + 2;
1006
-
1007
- const { tableWithFixedColumnWidthsOption = false } = getEditorFeatureFlags();
1008
-
1009
- const shouldUseIncreasedScalingPercent =
1010
- !!isTableScalingEnabled &&
1011
- (tableWithFixedColumnWidthsOption || !!this.props.options?.isCommentEditor);
1012
-
1013
- return (
1014
- <TableContainer
1015
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
1016
- className={classnames(ClassName.TABLE_CONTAINER, {
1017
- [ClassName.WITH_CONTROLS]: allowControls && tableActive,
1018
- [ClassName.TABLE_STICKY]:
1019
- !this.props.limitedMode && this.state.stickyHeader && hasHeaderRow,
1020
- [ClassName.HOVERED_DELETE_BUTTON]: isInDanger,
1021
- [ClassName.TABLE_SELECTED]: isTableSelected(selection ?? view.state.selection),
1022
- [ClassName.NESTED_TABLE_WITH_CONTROLS]:
1023
- tableActive && allowControls && this.isNestedInTable,
1024
- })}
1025
- editorView={view}
1026
- getPos={getPos}
1027
- node={node}
1028
- // Ignored via go/ees005
1029
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1030
- tableRef={tableRef!}
1031
- containerWidth={containerWidth}
1032
- isNested={isNested}
1033
- pluginInjectionApi={pluginInjectionApi}
1034
- tableWrapperHeight={this.state.tableWrapperHeight}
1035
- isTableResizingEnabled={allowTableResizing}
1036
- isResizing={isResizing}
1037
- isWindowResized={this.state.windowResized}
1038
- isTableScalingEnabled={isTableScalingEnabled}
1039
- isTableWithFixedColumnWidthsOptionEnabled={tableWithFixedColumnWidthsOption}
1040
- isWholeTableInDanger={isWholeTableInDanger}
1041
- isTableAlignmentEnabled={allowTableAlignment}
1042
- shouldUseIncreasedScalingPercent={shouldUseIncreasedScalingPercent}
1043
- isCommentEditor={options?.isCommentEditor}
1044
- isChromelessEditor={options?.isChromelessEditor}
1045
- >
1046
- {expValEquals('cc_editor_ufo_hold_table_till_resize_complete', 'isEnabled', true) ? (
1047
- <TableHold dispatchEventName={this.dispatchEventName} />
1048
- ) : null}
1049
- <div
1050
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
1051
- className={ClassName.TABLE_STICKY_SENTINEL_TOP}
1052
- data-testid="sticky-sentinel-top"
1053
- />
1054
- {fg('disable-sticky-scrollbar-for-nested-tables') ? (
1055
- !this.isNestedInTable && (
1056
- <div
1057
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
1058
- className={ClassName.TABLE_STICKY_SCROLLBAR_SENTINEL_TOP}
1059
- data-testid="sticky-scrollbar-sentinel-top"
1060
- />
1061
- )
1062
- ) : (
1063
- <div
1064
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
1065
- className={ClassName.TABLE_STICKY_SCROLLBAR_SENTINEL_TOP}
1066
- data-testid="sticky-scrollbar-sentinel-top"
1067
- />
1068
- )}
1069
-
1070
- {allowControls && rowControls}
1071
- {isDragAndDropEnabled && (
1072
- <ExternalDropTargets
1073
- editorView={view}
1074
- node={node}
1075
- getScrollOffset={() => {
1076
- return this.wrapper?.scrollLeft || 0;
1077
- }}
1078
- getTableWrapperWidth={() => {
1079
- return this.wrapper?.clientWidth || 760;
1080
- }}
1081
- />
1082
- )}
1083
- <div
1084
- contentEditable={false}
1085
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
1086
- style={shadowStyle(showBeforeShadow)}
1087
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
1088
- className={
1089
- options?.isChromelessEditor && !isDragAndDropEnabled
1090
- ? ClassName.TABLE_LEFT_SHADOW + ' ' + ClassName.TABLE_CHROMELESS
1091
- : ClassName.TABLE_LEFT_SHADOW
1092
- }
1093
- />
1094
- {this.state.stickyHeader && (
1095
- <div
1096
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
1097
- className={`${ClassName.TABLE_LEFT_SHADOW} ${ClassName.TABLE_STICKY_SHADOW}`}
1098
- style={{
1099
- visibility: showBeforeShadow && hasHeaderRow ? 'visible' : 'hidden',
1100
- top: `${topStickyShadowPosition}px`,
1101
- paddingBottom: `${isDragAndDropEnabled && token('space.025', '2px')}`,
1102
- }}
1103
- />
1104
- )}
1105
- <div
1106
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
1107
- className={classnames(ClassName.TABLE_NODE_WRAPPER)}
1108
- ref={(elem) => {
1109
- this.wrapper = elem;
1110
- if (elem) {
1111
- this.props.contentDOM(elem);
1112
- const tableElement = elem.querySelector('table');
1113
-
1114
- if (tableElement !== this.table) {
1115
- this.table = tableElement;
1116
- this.createShadowSentinels(this.table);
1117
- this.observeTable(this.table);
1118
- }
1119
- }
1120
- }}
1121
- >
1122
- {allowControls && colControls}
1123
- </div>
1124
- {fg('disable-sticky-scrollbar-for-nested-tables') ? (
1125
- !this.isNestedInTable ? (
1126
- <div
1127
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
1128
- className={ClassName.TABLE_STICKY_SCROLLBAR_CONTAINER}
1129
- data-vc-nvs="true"
1130
- style={{
1131
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
1132
- height: token('space.250', '20px'), // MAX_BROWSER_SCROLLBAR_HEIGHT
1133
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
1134
- display: 'none',
1135
- // prevent unwanted scroll during table resize without removing scrollbar container from the dom
1136
- width: isResizing ? token('space.0', '0px') : '100%',
1137
- }}
1138
- >
1139
- <div
1140
- style={{
1141
- width: tableRef?.clientWidth,
1142
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
1143
- height: '100%',
1144
- }}
1145
- data-vc-nvs="true"
1146
- ></div>
1147
- </div>
1148
- ) : (
1149
- <div
1150
- style={{
1151
- width: tableRef?.clientWidth,
1152
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
1153
- height: '100%',
1154
- }}
1155
- data-vc-nvs="true"
1156
- ></div>
1157
- )
1158
- ) : (
1159
- <div
1160
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
1161
- className={ClassName.TABLE_STICKY_SCROLLBAR_CONTAINER}
1162
- style={{
1163
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
1164
- height: token('space.250', '20px'), // MAX_BROWSER_SCROLLBAR_HEIGHT
1165
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
1166
- display: 'none',
1167
- // prevent unwanted scroll during table resize without removing scrollbar container from the dom
1168
- width: isResizing ? token('space.0', '0px') : '100%',
1169
- }}
1170
- data-vc-nvs="true"
1171
- >
1172
- <div
1173
- style={{
1174
- width: tableRef?.clientWidth,
1175
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
1176
- height: '100%',
1177
- }}
1178
- data-vc-nvs="true"
1179
- ></div>
1180
- </div>
1181
- )}
1182
- <div
1183
- contentEditable={false}
1184
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
1185
- style={shadowStyle(showAfterShadow)}
1186
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
1187
- className={
1188
- options?.isChromelessEditor && !isDragAndDropEnabled
1189
- ? ClassName.TABLE_RIGHT_SHADOW + ' ' + ClassName.TABLE_CHROMELESS
1190
- : ClassName.TABLE_RIGHT_SHADOW
1191
- }
1192
- />
1193
- {this.state.stickyHeader && (
1194
- <div
1195
- style={{
1196
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
1197
- position: 'absolute',
1198
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
1199
- right: token('space.400', '32px'), // tableOverflowShadowWidthWide
1200
- }}
1201
- >
1202
- <div
1203
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
1204
- className={`${ClassName.TABLE_RIGHT_SHADOW} ${ClassName.TABLE_STICKY_SHADOW}`}
1205
- style={{
1206
- visibility: showAfterShadow && hasHeaderRow ? 'visible' : 'hidden',
1207
- top: `${topStickyShadowPosition}px`,
1208
- paddingBottom: `${isDragAndDropEnabled && token('space.025', '2px')}`,
1209
- }}
1210
- />
1211
- </div>
1212
- )}
1213
-
1214
- <div
1215
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
1216
- className={ClassName.TABLE_STICKY_SENTINEL_BOTTOM}
1217
- data-testid="sticky-sentinel-bottom"
1218
- />
1219
- {fg('disable-sticky-scrollbar-for-nested-tables') ? (
1220
- !this.isNestedInTable && (
1221
- <div
1222
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
1223
- className={ClassName.TABLE_STICKY_SCROLLBAR_SENTINEL_BOTTOM}
1224
- data-testid="sticky-scrollbar-sentinel-bottom"
1225
- />
1226
- )
1227
- ) : (
1228
- <div
1229
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
1230
- className={ClassName.TABLE_STICKY_SCROLLBAR_SENTINEL_BOTTOM}
1231
- data-testid="sticky-scrollbar-sentinel-bottom"
1232
- />
1233
- )}
1234
- </TableContainer>
1235
- );
1236
- }
1237
-
1238
- private handleScroll = (event: Event) => {
1239
- if (!this.wrapper || event.target !== this.wrapper) {
1240
- return;
1241
- }
1242
-
1243
- if (this.stickyScrollbar) {
1244
- this.stickyScrollbar.scrollLeft(this.wrapper.scrollLeft);
1245
- }
1246
-
1247
- if (this.table) {
1248
- // sync sticky header row to table scroll
1249
- const headers = this.table.querySelectorAll('tr[data-header-row]');
1250
- for (let i = 0; i < headers.length; i++) {
1251
- // Ignored via go/ees005
1252
- // eslint-disable-next-line @atlaskit/editor/no-as-casting
1253
- const header = headers[i] as HTMLElement;
1254
-
1255
- header.scrollLeft = this.wrapper.scrollLeft;
1256
- header.style.marginRight = '2px';
1257
- }
1258
- }
1259
-
1260
- this.setState({
1261
- [ShadowEvent.SHOW_BEFORE_SHADOW]: this.wrapper.scrollLeft !== 0,
1262
- });
1263
- };
1264
-
1265
- private handleTableResizing = () => {
1266
- const { getNode, containerWidth, options, allowTableResizing } = this.props;
1267
- // Ignored via go/ees005
1268
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1269
- const prevNode = this.node!;
1270
- const node = getNode();
1271
- const prevAttrs = prevNode.attrs;
1272
-
1273
- const isNested = isTableNested(this.props.view.state, this.props.getPos());
1274
-
1275
- let parentWidth = this.getParentNodeWidth();
1276
-
1277
- if (isNested && isTableNestedInMoreThanOneNode(this.props.view.state, this.props.getPos())) {
1278
- const resizeObsWrapperWidth = this.wrapperWidth || 0;
1279
-
1280
- const wrapperWidthDiffBetweenRerenders = Math.abs(
1281
- resizeObsWrapperWidth - (this.state.parentWidth || 0),
1282
- );
1283
- const isOusideOfThreshold =
1284
- wrapperWidthDiffBetweenRerenders <=
1285
- NESTED_TABLE_IN_NESTED_PARENT_WIDTH_DIFF_MIN_THRESHOLD ||
1286
- wrapperWidthDiffBetweenRerenders > NESTED_TABLE_IN_NESTED_PARENT_WIDTH_DIFF_MAX_THRESHOLD;
1287
- // 1. Check isOusideOfThreshold is added to prevent undersired state update.
1288
- // When table is nested in the extenstion and the table column is being resized,
1289
- // space available within extension can change and cause undesirable state update.
1290
- // MIN_THRESNESTED_TABLE_IN_NESTED_PARENT_WIDTH_DIFF_MIN_THRESHOLDHOLD value is required
1291
- // as the resizeObsWrapperWidth can differ between page reloads by 2px.
1292
-
1293
- // 2. Check resizeObsWrapperWidth > 1 is added to prevent parentWidth update when table unmounts.
1294
- // When a is nested table in a nested expand and the expand collabses, the table unmounts and
1295
- // resizeObsWrapperWidth becomes 1.
1296
- parentWidth =
1297
- isOusideOfThreshold && resizeObsWrapperWidth > 1
1298
- ? resizeObsWrapperWidth
1299
- : this.state.parentWidth;
1300
- }
1301
-
1302
- const parentWidthChanged = parentWidth && parentWidth !== this.state.parentWidth;
1303
-
1304
- const layoutSize = this.tableNodeLayoutSize(node, containerWidth.width, options);
1305
-
1306
- const hasNumberedColumnChanged =
1307
- prevAttrs.isNumberColumnEnabled !== node.attrs.isNumberColumnEnabled;
1308
-
1309
- const noOfColumnsChanged = tablesHaveDifferentNoOfColumns(node, prevNode);
1310
-
1311
- if (
1312
- // We need to react if our parent changes
1313
- // Scales the cols widths relative to the new parent width.
1314
- parentWidthChanged ||
1315
- // Enabling / disabling this feature reduces or adds size to the table.
1316
- hasNumberedColumnChanged ||
1317
- // This last check is also to cater for dynamic text sizing changing the 'default' layout width
1318
- // Usually happens on window resize.
1319
- layoutSize !== this.layoutSize ||
1320
- noOfColumnsChanged
1321
- ) {
1322
- const shouldScaleTable =
1323
- (!allowTableResizing || (allowTableResizing && isNested)) &&
1324
- !hasNumberedColumnChanged &&
1325
- !noOfColumnsChanged;
1326
-
1327
- // If column has been inserted/deleted avoid multi dispatch
1328
- if (shouldScaleTable) {
1329
- this.scaleTable(
1330
- {
1331
- parentWidth,
1332
- },
1333
- hasNumberedColumnChanged,
1334
- );
1335
- }
1336
-
1337
- // only when table resizing is enabled and toggle numbered column to run scaleTable
1338
- if (allowTableResizing && hasNumberedColumnChanged) {
1339
- if (!hasTableBeenResized(prevNode)) {
1340
- this.scaleTable(
1341
- {
1342
- parentWidth: node.attrs.width,
1343
- },
1344
- true,
1345
- );
1346
- }
1347
- }
1348
-
1349
- this.updateParentWidth(parentWidth);
1350
- }
1351
-
1352
- this.node = node;
1353
- this.containerWidth = containerWidth;
1354
- this.layoutSize = layoutSize;
1355
- };
1356
-
1357
- // Function gets called when table is nested.
1358
- private scaleTable = (scaleOptions: { parentWidth?: number }, isUserTriggered = false) => {
1359
- const { view, getNode, getPos, containerWidth, options } = this.props;
1360
- const node = getNode();
1361
- const { state, dispatch } = view;
1362
- const pos = getPos();
1363
-
1364
- if (typeof pos !== 'number' || !isValidPosition(pos, state)) {
1365
- return;
1366
- }
1367
- const domAtPos = view.domAtPos.bind(view);
1368
- const { width } = containerWidth;
1369
-
1370
- this.scaleTableDebounced.cancel();
1371
-
1372
- const tr = scaleTable(
1373
- this.table,
1374
- {
1375
- ...scaleOptions,
1376
- node,
1377
- prevNode: this.node || node,
1378
- start: pos + 1,
1379
- containerWidth: width,
1380
- // Ignored via go/ees005
1381
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1382
- previousContainerWidth: this.containerWidth!.width || width,
1383
- ...options,
1384
- },
1385
- domAtPos,
1386
- this.props.pluginInjectionApi,
1387
- false, // isTableScalingEnabled doesn't change the behavior of nested tables
1388
- false, // shouldUseIncreasedScalingPercent set to false for nested tables
1389
- )(state.tr);
1390
-
1391
- if (!isUserTriggered) {
1392
- tintDirtyTransaction(tr);
1393
- if (fg('platform_editor_fix_table_resizing_undo')) {
1394
- // Avoid adding this transaction separately to the history as these are automatic updates
1395
- // as a consequence of another action
1396
- tr.setMeta('addToHistory', false);
1397
- }
1398
- }
1399
-
1400
- dispatch(tr);
1401
- };
1402
-
1403
- private setTimerToSendInitialOverflowCaptured = (isOverflowing: boolean) => {
1404
- const { dispatchAnalyticsEvent, containerWidth, allowTableResizing } = this.props;
1405
- const parentWidth = this.state?.parentWidth || 0;
1406
-
1407
- this.initialOverflowCaptureTimerId = setTimeout(() => {
1408
- dispatchAnalyticsEvent({
1409
- action: TABLE_ACTION.INITIAL_OVERFLOW_CAPTURED,
1410
- actionSubject: ACTION_SUBJECT.TABLE,
1411
- actionSubjectId: null,
1412
- eventType: EVENT_TYPE.TRACK,
1413
- attributes: {
1414
- editorWidth: containerWidth.width || 0,
1415
- isOverflowing,
1416
- tableResizingEnabled: allowTableResizing || false,
1417
- width: this.node.attrs.width || 0,
1418
- parentWidth,
1419
- },
1420
- });
1421
-
1422
- this.isInitialOverflowSent = true;
1423
- }, initialOverflowCaptureTimeroutDelay);
1424
- };
1425
-
1426
- private handleAutoSize = () => {
1427
- if (this.table) {
1428
- const { view, getNode, getPos, containerWidth } = this.props;
1429
- const node = getNode();
1430
- const pos = getPos();
1431
- if (!isValidPosition(pos, view.state)) {
1432
- return;
1433
- }
1434
- autoSizeTable(view, node, this.table, pos, {
1435
- containerWidth: containerWidth.width,
1436
- });
1437
- }
1438
- };
1439
-
1440
- private handleWindowResize = () => {
1441
- const { getNode, containerWidth } = this.props;
1442
- const node = getNode();
1443
- const layoutSize = this.tableNodeLayoutSize(node);
1444
-
1445
- if (containerWidth.width > layoutSize) {
1446
- return;
1447
- }
1448
-
1449
- const parentWidth = this.getParentNodeWidth();
1450
- this.scaleTableDebounced({
1451
- parentWidth: parentWidth,
1452
- });
1453
- };
1454
-
1455
- // This is a new handler for window resize events that sets the windowResized state immediately
1456
- // This is needed to update colgroup on window resize, to enforce the table scaling
1457
- private handleWindowResizeNew = () => {
1458
- // Set resizing to true immediately
1459
- if (!this.state.windowResized) {
1460
- this.setState({
1461
- windowResized: true,
1462
- });
1463
- }
1464
- };
1465
-
1466
- private getParentNodeWidth = () => {
1467
- const {
1468
- getPos,
1469
- containerWidth,
1470
- options,
1471
- view: { state },
1472
- } = this.props;
1473
- const pos = getPos();
1474
- if (!isValidPosition(pos, state)) {
1475
- return;
1476
- }
1477
- const parentNodeWith = getParentNodeWidth(
1478
- pos,
1479
- state,
1480
- containerWidth,
1481
- options && options.isFullWidthModeEnabled,
1482
- );
1483
-
1484
- return parentNodeWith;
1485
- };
1486
-
1487
- private updateParentWidth = (width?: number) => {
1488
- this.setState({ parentWidth: width });
1489
- };
1490
-
1491
- private tableNodeLayoutSize = (node: PmNode, containerWidth?: number, options?: TableOptions) =>
1492
- getLayoutSize(
1493
- node.attrs.layout,
1494
- containerWidth || this.props.containerWidth.width,
1495
- options || this.props.options || {},
1496
- );
1497
-
1498
- private shouldUpdateColgroup = (params: {
1499
- isWindowResized: boolean | undefined;
1500
- isWidthChanged: boolean;
1501
- isTableWidthChanged: boolean;
1502
- isColumnsDistributed: boolean;
1503
- isTableResizedFullWidth: boolean | undefined;
1504
- isTableDisplayModeChanged: boolean;
1505
- isNumberColumnChanged: boolean;
1506
- isNumberOfColumnsChanged: boolean;
1507
- isFullWidthModeAndLineLengthChanged: boolean | undefined;
1508
- }): boolean => {
1509
- const {
1510
- isWindowResized,
1511
- isWidthChanged,
1512
- isTableWidthChanged,
1513
- isColumnsDistributed,
1514
- isTableResizedFullWidth,
1515
- isTableDisplayModeChanged,
1516
- isNumberColumnChanged,
1517
- isNumberOfColumnsChanged,
1518
- isFullWidthModeAndLineLengthChanged,
1519
- } = params;
1520
-
1521
- const isFullPageEditor =
1522
- !this.props.options?.isCommentEditor && !this.props.options?.isChromelessEditor;
1523
-
1524
- if (expValEquals('platform_editor_tables_scaling_css', 'isEnabled', true) && isFullPageEditor) {
1525
- return (
1526
- !!isWindowResized ||
1527
- isColumnsDistributed ||
1528
- !!isTableResizedFullWidth ||
1529
- isTableDisplayModeChanged ||
1530
- isNumberColumnChanged ||
1531
- isNumberOfColumnsChanged ||
1532
- !!isFullWidthModeAndLineLengthChanged
1533
- );
1534
- }
1535
- return (
1536
- isWidthChanged ||
1537
- isTableWidthChanged ||
1538
- isColumnsDistributed ||
1539
- !!isTableResizedFullWidth ||
1540
- isTableDisplayModeChanged ||
1541
- isNumberColumnChanged ||
1542
- isNumberOfColumnsChanged ||
1543
- !!isFullWidthModeAndLineLengthChanged
1544
- );
1545
- };
1546
-
1547
- private scaleTableDebounced = rafSchedule(this.scaleTable);
1548
- private handleTableResizingDebounced = rafSchedule(this.handleTableResizing);
1549
- private handleScrollDebounced = rafSchedule(this.handleScroll);
1550
- private handleAutoSizeDebounced = rafSchedule(this.handleAutoSize);
1551
- private handleWindowResizeDebounced = rafSchedule(this.handleWindowResize);
1552
- private handleWindowResizeNewDebounced = rafSchedule(this.handleWindowResizeNew);
1553
- private updateShadowStateDebounced = rafSchedule(this.updateShadowState);
1554
- }
1555
-
1556
- export default injectIntl(TableComponent);
1557
-
1558
- /**
1559
- * This is needed because of how currently the table is resized post client boot up with code that exists outside react
1560
- *
1561
- * This can be deleted once https://home.atlassian.com/o/2346a038-3c8c-498b-a79b-e7847859868d/s/a436116f-02ce-4520-8fbb-7301462a1674/project/ATLAS-97756/updates
1562
- * is rolled out (and doesn't need to be used in the test arm of that change).
1563
- */
1564
- const TableHold = React.memo(function TableHold({
1565
- dispatchEventName,
1566
- }: {
1567
- dispatchEventName: string;
1568
- }) {
1569
- const [tableUpdateConfirmed, setTableUpdateConfirmed] = React.useState(false);
1570
-
1571
- React.useEffect(() => {
1572
- const customEventListener = () => {
1573
- setTableUpdateConfirmed(true);
1574
- };
1575
-
1576
- // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
1577
- document.addEventListener(dispatchEventName, customEventListener);
1578
-
1579
- return () => {
1580
- // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
1581
- document.removeEventListener(dispatchEventName, customEventListener);
1582
- };
1583
- }, [dispatchEventName]);
1584
-
1585
- if (tableUpdateConfirmed === false) {
1586
- return <UFOLoadHold name="editor_table_resize" />;
1587
- }
1588
-
1589
- return null;
1590
- });