@atlaskit/editor-plugin-table 5.7.1 → 5.7.3

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 (77) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cjs/nodeviews/TableComponent.js +4 -1
  3. package/dist/cjs/plugin.js +2 -1
  4. package/dist/cjs/pm-plugins/main.js +5 -16
  5. package/dist/cjs/pm-plugins/table-resizing/event-handlers.js +0 -4
  6. package/dist/cjs/toolbar.js +87 -14
  7. package/dist/cjs/types.js +0 -2
  8. package/dist/cjs/ui/FloatingDragMenu/index.js +5 -2
  9. package/dist/cjs/ui/FloatingInsertButton/InsertButton.js +3 -3
  10. package/dist/cjs/ui/FloatingInsertButton/index.js +1 -1
  11. package/dist/cjs/ui/TableFloatingColumnControls/ColumnControls/index.js +49 -18
  12. package/dist/cjs/ui/TableFloatingColumnControls/index.js +17 -8
  13. package/dist/cjs/ui/common-styles.js +1 -1
  14. package/dist/cjs/utils/decoration.js +48 -34
  15. package/dist/cjs/utils/dom.js +1 -19
  16. package/dist/cjs/utils/index.js +0 -6
  17. package/dist/es2019/nodeviews/TableComponent.js +5 -2
  18. package/dist/es2019/plugin.js +2 -1
  19. package/dist/es2019/pm-plugins/main.js +1 -12
  20. package/dist/es2019/pm-plugins/table-resizing/event-handlers.js +1 -5
  21. package/dist/es2019/toolbar.js +77 -9
  22. package/dist/es2019/types.js +0 -2
  23. package/dist/es2019/ui/FloatingDragMenu/index.js +6 -3
  24. package/dist/es2019/ui/FloatingInsertButton/InsertButton.js +3 -3
  25. package/dist/es2019/ui/FloatingInsertButton/index.js +2 -2
  26. package/dist/es2019/ui/TableFloatingColumnControls/ColumnControls/index.js +42 -12
  27. package/dist/es2019/ui/TableFloatingColumnControls/index.js +18 -9
  28. package/dist/es2019/ui/common-styles.js +6 -1
  29. package/dist/es2019/utils/decoration.js +47 -33
  30. package/dist/es2019/utils/dom.js +0 -18
  31. package/dist/es2019/utils/index.js +1 -1
  32. package/dist/esm/nodeviews/TableComponent.js +5 -2
  33. package/dist/esm/plugin.js +2 -1
  34. package/dist/esm/pm-plugins/main.js +1 -12
  35. package/dist/esm/pm-plugins/table-resizing/event-handlers.js +1 -5
  36. package/dist/esm/toolbar.js +86 -13
  37. package/dist/esm/types.js +0 -2
  38. package/dist/esm/ui/FloatingDragMenu/index.js +6 -3
  39. package/dist/esm/ui/FloatingInsertButton/InsertButton.js +3 -3
  40. package/dist/esm/ui/FloatingInsertButton/index.js +2 -2
  41. package/dist/esm/ui/TableFloatingColumnControls/ColumnControls/index.js +45 -14
  42. package/dist/esm/ui/TableFloatingColumnControls/index.js +18 -9
  43. package/dist/esm/ui/common-styles.js +2 -2
  44. package/dist/esm/utils/decoration.js +48 -34
  45. package/dist/esm/utils/dom.js +0 -18
  46. package/dist/esm/utils/index.js +1 -1
  47. package/dist/types/toolbar.d.ts +3 -1
  48. package/dist/types/types.d.ts +1 -1
  49. package/dist/types/ui/FloatingDragMenu/index.d.ts +3 -1
  50. package/dist/types/ui/TableFloatingColumnControls/ColumnControls/index.d.ts +3 -1
  51. package/dist/types/ui/TableFloatingColumnControls/index.d.ts +2 -0
  52. package/dist/types/utils/dom.d.ts +0 -1
  53. package/dist/types/utils/index.d.ts +1 -1
  54. package/dist/types-ts4.5/toolbar.d.ts +3 -1
  55. package/dist/types-ts4.5/types.d.ts +1 -1
  56. package/dist/types-ts4.5/ui/FloatingDragMenu/index.d.ts +3 -1
  57. package/dist/types-ts4.5/ui/TableFloatingColumnControls/ColumnControls/index.d.ts +3 -1
  58. package/dist/types-ts4.5/ui/TableFloatingColumnControls/index.d.ts +2 -0
  59. package/dist/types-ts4.5/utils/dom.d.ts +0 -1
  60. package/dist/types-ts4.5/utils/index.d.ts +1 -1
  61. package/package.json +8 -8
  62. package/src/nodeviews/TableComponent.tsx +7 -2
  63. package/src/plugin.tsx +1 -0
  64. package/src/pm-plugins/main.ts +0 -18
  65. package/src/pm-plugins/table-resizing/event-handlers.ts +1 -8
  66. package/src/toolbar.tsx +135 -9
  67. package/src/types.ts +1 -2
  68. package/src/ui/FloatingDragMenu/index.tsx +14 -2
  69. package/src/ui/FloatingInsertButton/InsertButton.tsx +6 -2
  70. package/src/ui/FloatingInsertButton/index.tsx +4 -2
  71. package/src/ui/TableFloatingColumnControls/ColumnControls/index.tsx +53 -19
  72. package/src/ui/TableFloatingColumnControls/index.tsx +23 -11
  73. package/src/ui/TableFloatingControls/RowControls/DragControls.tsx +0 -10
  74. package/src/ui/common-styles.ts +6 -0
  75. package/src/utils/decoration.ts +41 -28
  76. package/src/utils/dom.ts +0 -23
  77. package/src/utils/index.ts +0 -1
@@ -1,10 +1,12 @@
1
1
  /* eslint-disable @atlaskit/design-system/prefer-primitives */
2
2
  import type { MouseEvent } from 'react';
3
- import React, { useCallback, useMemo } from 'react';
3
+ import React, { useCallback, useEffect, useMemo, useRef } from 'react';
4
4
 
5
5
  import { tableCellMinWidth } from '@atlaskit/editor-common/styles';
6
+ import { closestElement } from '@atlaskit/editor-common/utils';
6
7
  import type { Selection } from '@atlaskit/editor-prosemirror/state';
7
8
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
9
+ import { akEditorTableNumberColumnWidth } from '@atlaskit/editor-shared-styles';
8
10
  import { CellSelection } from '@atlaskit/editor-tables';
9
11
  import { getSelectionRect } from '@atlaskit/editor-tables/utils';
10
12
 
@@ -35,6 +37,8 @@ export interface ColumnControlsProps {
35
37
  hasHeaderColumn?: boolean;
36
38
  isTableHovered?: boolean;
37
39
  canDrag?: boolean;
40
+ tableContainerWidth?: number;
41
+ isNumberColumnEnabled?: boolean;
38
42
  }
39
43
 
40
44
  const getSelectedColumns = (selection: Selection) => {
@@ -62,10 +66,18 @@ export const ColumnControls = ({
62
66
  hasHeaderColumn,
63
67
  isTableHovered,
64
68
  canDrag,
69
+ tableContainerWidth,
70
+ isNumberColumnEnabled,
65
71
  }: ColumnControlsProps) => {
72
+ const columnControlsRef = useRef<HTMLDivElement>(null);
66
73
  const widths =
67
- colWidths?.map((width) => (width ? `${width - 1}px` : '0px')).join(' ') ??
68
- '0px';
74
+ colWidths
75
+ ?.map((width) =>
76
+ // when there is sticky header, a `margin-right: -1px` applied to `tr.sticky th` so it causes colWidths to be 1px wider
77
+ // we need to reduce the width by 1px to avoid misalignment of column controls.
78
+ width ? (stickyTop ? `${width - 2}px` : `${width - 1}px`) : '0px',
79
+ )
80
+ .join(' ') ?? '0px';
69
81
  // TODO: reusing getRowsParams here because it's generic enough to work for columns -> rename
70
82
  const columnParams = getRowsParams(colWidths ?? []);
71
83
  const colIndex = hoveredCell?.colIndex;
@@ -153,8 +165,32 @@ export const ColumnControls = ({
153
165
  const colIndexes = useMemo(() => {
154
166
  return [colIndex!];
155
167
  }, [colIndex]);
168
+ const tableWrapper = closestElement(
169
+ tableRef,
170
+ `.${ClassName.TABLE_NODE_WRAPPER}`,
171
+ );
172
+ const handleScroll = useCallback(
173
+ (event?: Event) => {
174
+ if (stickyTop) {
175
+ if (columnControlsRef && columnControlsRef.current) {
176
+ columnControlsRef.current.scrollLeft = tableWrapper?.scrollLeft ?? 0;
177
+ }
178
+ }
179
+ },
180
+ [stickyTop, tableWrapper],
181
+ );
182
+
183
+ useEffect(() => {
184
+ handleScroll();
185
+ }, [handleScroll]);
186
+
187
+ useEffect(() => {
188
+ tableWrapper?.addEventListener('scroll', handleScroll);
156
189
 
157
- const previewHeight = rowHeights?.reduce((sum, cur) => sum + cur, 0) ?? 0;
190
+ return () => {
191
+ tableWrapper?.removeEventListener('scroll', handleScroll);
192
+ };
193
+ }, [tableWrapper, handleScroll]);
158
194
 
159
195
  const generateHandleByType = (type: HandleTypes): JSX.Element | null => {
160
196
  if (!hoveredCell || !colWidths?.length) {
@@ -163,6 +199,7 @@ export const ColumnControls = ({
163
199
  const isHover = type === 'hover';
164
200
 
165
201
  const isColumnsSelected = selectedColIndexes.length > 0;
202
+ const previewHeight = rowHeights?.reduce((sum, cur) => sum + cur, 0) ?? 0;
166
203
 
167
204
  const showCondition = isHover
168
205
  ? isColumnsSelected &&
@@ -186,13 +223,13 @@ export const ColumnControls = ({
186
223
  : 'selected'
187
224
  : 'default';
188
225
 
189
- const currentSelectionApprearance = isColumnsSelected
226
+ const currentSelectionAppearance = isColumnsSelected
190
227
  ? isInDanger
191
228
  ? 'danger'
192
229
  : 'selected'
193
230
  : hoveredAppearance;
194
231
 
195
- const istSelecting = isColumnsSelected && !isHover;
232
+ const isSelecting = isColumnsSelected && !isHover;
196
233
 
197
234
  // this indexes are used to calculate the drag and drop source
198
235
  const indexes = isColumnsSelected
@@ -206,7 +243,7 @@ export const ColumnControls = ({
206
243
  <div
207
244
  key={type}
208
245
  style={{
209
- gridColumn: istSelecting
246
+ gridColumn: isSelecting
210
247
  ? selectedColumnPosition
211
248
  : gridColumnPosition,
212
249
  display: 'flex',
@@ -228,7 +265,7 @@ export const ColumnControls = ({
228
265
  previewWidth={colWidths?.[colIndex!] ?? tableCellMinWidth}
229
266
  previewHeight={previewHeight}
230
267
  appearance={
231
- istSelecting ? currentSelectionApprearance : hoveredAppearance
268
+ isSelecting ? currentSelectionAppearance : hoveredAppearance
232
269
  }
233
270
  onClick={handleClick}
234
271
  onMouseOver={handleMouseOver}
@@ -261,24 +298,31 @@ export const ColumnControls = ({
261
298
  : sortedHandles.reverse();
262
299
  };
263
300
 
301
+ const containerWidth =
302
+ isNumberColumnEnabled && tableContainerWidth
303
+ ? tableContainerWidth - akEditorTableNumberColumnWidth
304
+ : tableContainerWidth;
264
305
  return (
265
306
  <div
266
307
  className={ClassName.DRAG_COLUMN_CONTROLS}
267
308
  onMouseMove={handleMouseMove}
268
309
  >
269
310
  <div
311
+ ref={columnControlsRef}
270
312
  className={ClassName.DRAG_COLUMN_CONTROLS_INNER}
271
313
  data-testid="table-floating-column-controls"
272
314
  style={{
273
315
  gridTemplateColumns: widths,
274
316
  marginTop,
317
+ width: stickyTop ? containerWidth : undefined,
318
+ overflowX: stickyTop ? 'hidden' : 'visible',
275
319
  }}
276
320
  >
277
321
  {!isResizing &&
278
322
  columnParams.map(({ startIndex, endIndex }, index) => (
279
323
  <div
280
324
  style={{
281
- gridColumn: `${index + 1} / span 1`,
325
+ gridColumn: `${startIndex + 1} / span 1`,
282
326
  }}
283
327
  data-start-index={startIndex}
284
328
  data-end-index={endIndex}
@@ -286,16 +330,6 @@ export const ColumnControls = ({
286
330
  contentEditable={false}
287
331
  key={index}
288
332
  >
289
- {/* TODO: Disabling first column insert button https://atlassian.slack.com/archives/C05U8HRQM50/p1698363744682219?thread_ts=1698209039.104909&cid=C05U8HRQM50 */}
290
- {/* {!hasHeaderColumn && index === 0 && (
291
- <div
292
- style={{
293
- left: '0px',
294
- right: 'unset',
295
- }}
296
- className={ClassName.DRAG_COLUMN_FLOATING_INSERT_DOT}
297
- />
298
- )} */}
299
333
  <div
300
334
  className={ClassName.DRAG_COLUMN_FLOATING_INSERT_DOT}
301
335
  style={columnParams.length - 1 === index ? { right: '0' } : {}}
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useMemo, useState } from 'react';
1
+ import React, { useEffect, useMemo, useRef, useState } from 'react';
2
2
 
3
3
  import type { TableColumnOrdering } from '@atlaskit/custom-steps';
4
4
  import type { GetEditorFeatureFlags } from '@atlaskit/editor-common/types';
@@ -36,6 +36,8 @@ export interface Props {
36
36
  stickyHeader?: RowStickyState;
37
37
  isTableHovered?: boolean;
38
38
  canDrag?: boolean;
39
+ tableContainerWidth?: number;
40
+ isNumberColumnEnabled?: boolean;
39
41
  }
40
42
 
41
43
  export const TableFloatingColumnControls: React.FC<Props> = ({
@@ -51,15 +53,22 @@ export const TableFloatingColumnControls: React.FC<Props> = ({
51
53
  isInDanger,
52
54
  isTableHovered,
53
55
  canDrag,
56
+ tableContainerWidth,
57
+ isNumberColumnEnabled,
54
58
  }) => {
55
59
  const [tableRect, setTableRect] = useState<{ width: number; height: number }>(
56
60
  { width: 0, height: 0 },
57
61
  );
58
-
59
62
  const [hasDropTargets, setHasDropTargets] = useState(false);
63
+ const containerRef = useRef<HTMLDivElement>(null);
64
+
60
65
  const node = getNode();
61
66
  const currentNodeLocalId = node?.attrs.localId;
62
67
  const hasHeaderColumn = containsHeaderColumn(node);
68
+ const stickyTop =
69
+ stickyHeader && stickyHeader.sticky && hasHeaderRow
70
+ ? stickyHeader.top
71
+ : undefined;
63
72
 
64
73
  useEffect(() => {
65
74
  if (tableRef && window?.ResizeObserver) {
@@ -118,19 +127,20 @@ export const TableFloatingColumnControls: React.FC<Props> = ({
118
127
 
119
128
  const colWidths = getColumnsWidths(editorView);
120
129
 
121
- const stickyTop =
122
- stickyHeader && stickyHeader.sticky && hasHeaderRow
123
- ? stickyHeader.top
124
- : undefined;
125
-
126
- // TODO - Removing column controls for now because they are causing the table
127
- // to overflow and scroll. Update this when sticky header support is added ED-21088
128
- if (stickyHeader && stickyHeader.sticky) {
129
- return null;
130
+ if (stickyTop) {
131
+ const headerRowHeight =
132
+ hasHeaderRow && stickyTop !== undefined ? rowHeights?.[0] ?? 0 : 0;
133
+ containerRef?.current?.style.setProperty(
134
+ 'top',
135
+ `${stickyTop! - headerRowHeight + 33}px`, // 33px is padding and margin applied on tr.sticky
136
+ );
137
+ } else {
138
+ containerRef?.current?.style.removeProperty('top');
130
139
  }
131
140
 
132
141
  return (
133
142
  <div
143
+ ref={containerRef}
134
144
  className={ClassName.DRAG_COLUMN_CONTROLS_WRAPPER}
135
145
  data-testid="table-floating-column-controls-wrapper"
136
146
  >
@@ -148,6 +158,8 @@ export const TableFloatingColumnControls: React.FC<Props> = ({
148
158
  colWidths={colWidths}
149
159
  hasHeaderColumn={hasHeaderColumn}
150
160
  canDrag={canDrag}
161
+ tableContainerWidth={tableContainerWidth}
162
+ isNumberColumnEnabled={isNumberColumnEnabled}
151
163
  />
152
164
  {hasDropTargets && (
153
165
  <ColumnDropTargets
@@ -310,16 +310,6 @@ const DragControlsComponent = ({
310
310
  contentEditable={false}
311
311
  key={`insert-dot-${index}`}
312
312
  >
313
- {/* TODO: Disabling first column insert button https://atlassian.slack.com/archives/C05U8HRQM50/p1698363744682219?thread_ts=1698209039.104909&cid=C05U8HRQM50 */}
314
- {/* {!hasHeaderRow && index === 0 && (
315
- <div
316
- style={{
317
- top: '0px',
318
- left: token('space.075', '6px'),
319
- }}
320
- className={ClassName.DRAG_ROW_FLOATING_INSERT_DOT}
321
- />
322
- )} */}
323
313
  <div className={ClassName.DRAG_ROW_FLOATING_INSERT_DOT} />
324
314
  </div>
325
315
  {isDragging && (
@@ -7,6 +7,7 @@ import {
7
7
  import type { FeatureFlags } from '@atlaskit/editor-common/types';
8
8
  import { browser } from '@atlaskit/editor-common/utils';
9
9
  import {
10
+ akEditorFloatingDialogZIndex,
10
11
  akEditorSelectedNodeClassName,
11
12
  akEditorSmallZIndex,
12
13
  akEditorStickyHeaderZIndex,
@@ -1049,6 +1050,11 @@ export const tableStyles = (props: { featureFlags?: FeatureFlags }) => css`
1049
1050
  top: ${tableMarginTop}px;
1050
1051
  }
1051
1052
 
1053
+ .${ClassName.TABLE_STICKY} .${ClassName.DRAG_COLUMN_CONTROLS_WRAPPER} {
1054
+ position: fixed;
1055
+ z-index: ${akEditorFloatingDialogZIndex};
1056
+ }
1057
+
1052
1058
  ${tableWrapperStyles()}
1053
1059
  }
1054
1060
 
@@ -22,6 +22,7 @@ import {
22
22
  getCellsInRow,
23
23
  getSelectionRect,
24
24
  } from '@atlaskit/editor-tables/utils';
25
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
25
26
 
26
27
  import type { Cell, CellColumnPositioning } from '../types';
27
28
  import { TableCssClassName as ClassName, TableDecorations } from '../types';
@@ -101,34 +102,46 @@ export const createControlsHoverDecoration = (
101
102
  // So If the table cells are in danger we want to create a "rectangle" selection
102
103
  // to match the "clicked" selection
103
104
 
104
- if (danger) {
105
- // Find the bounding rectangle of all the given cells, also considering
106
- // merged cells.
107
- const { recLeft, recTop, recRight, recBottom } = cells.reduce(
108
- (acc, cell) => {
109
- const { left, right, bottom, top } = map.findCell(
110
- cell.pos - table.start,
111
- );
112
- // Finding the bounding rect requires finding the min left and top positions,
113
- // and the max right and bottom positions of the cells
114
- return {
115
- recLeft: Math.min(acc.recLeft, left),
116
- recTop: Math.min(acc.recTop, top),
117
- recRight: Math.max(acc.recRight, right),
118
- recBottom: Math.max(acc.recBottom, bottom),
119
- };
120
- },
121
- // +-Infinity as initialisation vars which will always be overwritten
122
- // by smaller/larger values respectively
123
- {
124
- recLeft: Infinity,
125
- recTop: Infinity,
126
- recRight: -Infinity,
127
- recBottom: -Infinity,
128
- },
129
- );
130
- const rect = new Rect(recLeft, recTop, recRight, recBottom);
131
- updatedCells = map.cellsInRect(rect).map((x) => x + table.start);
105
+ if (getBooleanFF('platform.editor.table.in-danger-hover-merged-cells-fix')) {
106
+ if (danger && type !== 'table') {
107
+ const { selection } = tr;
108
+ const table = findTable(selection);
109
+ const rect = getSelectionRect(selection);
110
+
111
+ if (table && rect) {
112
+ updatedCells = map.cellsInRect(rect).map((x) => x + table.start);
113
+ }
114
+ }
115
+ } else {
116
+ if (danger) {
117
+ // Find the bounding rectangle of all the given cells, also considering
118
+ // merged cells.
119
+ const { recLeft, recTop, recRight, recBottom } = cells.reduce(
120
+ (acc, cell) => {
121
+ const { left, right, bottom, top } = map.findCell(
122
+ cell.pos - table.start,
123
+ );
124
+ // Finding the bounding rect requires finding the min left and top positions,
125
+ // and the max right and bottom positions of the cells
126
+ return {
127
+ recLeft: Math.min(acc.recLeft, left),
128
+ recTop: Math.min(acc.recTop, top),
129
+ recRight: Math.max(acc.recRight, right),
130
+ recBottom: Math.max(acc.recBottom, bottom),
131
+ };
132
+ },
133
+ // +-Infinity as initialisation vars which will always be overwritten
134
+ // by smaller/larger values respectively
135
+ {
136
+ recLeft: Infinity,
137
+ recTop: Infinity,
138
+ recRight: -Infinity,
139
+ recBottom: -Infinity,
140
+ },
141
+ );
142
+ const rect = new Rect(recLeft, recTop, recRight, recBottom);
143
+ updatedCells = map.cellsInRect(rect).map((x) => x + table.start);
144
+ }
132
145
  }
133
146
 
134
147
  return updatedCells.map((pos) => {
package/src/utils/dom.ts CHANGED
@@ -5,7 +5,6 @@ import {
5
5
 
6
6
  import { TableCssClassName as ClassName } from '../types';
7
7
  import type { ElementContentRects } from '../types';
8
- import { tableToolbarSize } from '../ui/consts';
9
8
 
10
9
  const SELECTOR_TABLE_LEAFS = `.${ClassName.TABLE_CELL}, .${ClassName.TABLE_HEADER_CELL}`;
11
10
 
@@ -178,28 +177,6 @@ export const getMousePositionVerticalRelativeByElement = (
178
177
  return null;
179
178
  };
180
179
 
181
- // This function is deprecated
182
- export const updateResizeHandles = (tableRef?: HTMLElement) => {
183
- if (!tableRef) {
184
- return;
185
- }
186
-
187
- // see ED-7600
188
- const nodes = Array.from(
189
- tableRef.querySelectorAll(
190
- `.${ClassName.RESIZE_HANDLE}`,
191
- ) as NodeListOf<HTMLElement>,
192
- );
193
- if (!nodes || !nodes.length) {
194
- return;
195
- }
196
-
197
- const height = tableRef.offsetHeight + tableToolbarSize;
198
- nodes.forEach((node) => {
199
- node.style.height = `${height}px`;
200
- });
201
- };
202
-
203
180
  export const hasResizeHandler = ({
204
181
  columnEndIndexTarget,
205
182
  target,
@@ -54,7 +54,6 @@ export {
54
54
  getColumnOrRowIndex,
55
55
  getMousePositionHorizontalRelativeByElement,
56
56
  getMousePositionVerticalRelativeByElement,
57
- updateResizeHandles,
58
57
  isResizeHandleDecoration,
59
58
  hasResizeHandler,
60
59
  findNearestCellIndexToPoint,