@atlaskit/editor-plugin-table 5.4.24 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/cjs/plugins/table/nodeviews/TableComponent.js +25 -12
- package/dist/cjs/plugins/table/nodeviews/TableResizer.js +150 -10
- package/dist/cjs/plugins/table/toolbar.js +3 -2
- package/dist/cjs/plugins/table/ui/common-styles.js +3 -3
- package/dist/es2019/plugins/table/nodeviews/TableComponent.js +29 -12
- package/dist/es2019/plugins/table/nodeviews/TableResizer.js +143 -5
- package/dist/es2019/plugins/table/toolbar.js +4 -2
- package/dist/es2019/plugins/table/ui/common-styles.js +3 -3
- package/dist/esm/plugins/table/nodeviews/TableComponent.js +25 -12
- package/dist/esm/plugins/table/nodeviews/TableResizer.js +145 -5
- package/dist/esm/plugins/table/toolbar.js +3 -2
- package/dist/esm/plugins/table/ui/common-styles.js +3 -3
- package/package.json +4 -4
- package/src/__tests__/unit/nodeviews/TableContainer.tsx +85 -0
- package/src/plugins/table/nodeviews/TableComponent.tsx +21 -7
- package/src/plugins/table/nodeviews/TableResizer.tsx +232 -26
- package/src/plugins/table/toolbar.tsx +4 -4
- package/src/plugins/table/ui/common-styles.ts +3 -3
|
@@ -81,7 +81,10 @@ class TableComponent extends React.Component {
|
|
|
81
81
|
if (!this.wrapper || event.target !== this.wrapper) {
|
|
82
82
|
return;
|
|
83
83
|
}
|
|
84
|
-
|
|
84
|
+
const {
|
|
85
|
+
stickyScrollbar
|
|
86
|
+
} = this.props.getEditorFeatureFlags();
|
|
87
|
+
if (stickyScrollbar) {
|
|
85
88
|
if (this.stickyScrollbar) {
|
|
86
89
|
this.stickyScrollbar.scrollLeft(this.wrapper.scrollLeft);
|
|
87
90
|
}
|
|
@@ -306,13 +309,17 @@ class TableComponent extends React.Component {
|
|
|
306
309
|
eventDispatcher,
|
|
307
310
|
options,
|
|
308
311
|
isDragAndDropEnabled,
|
|
309
|
-
getNode
|
|
312
|
+
getNode,
|
|
313
|
+
getEditorFeatureFlags
|
|
310
314
|
} = this.props;
|
|
311
315
|
if (allowColumnResizing && this.wrapper && !isIE11) {
|
|
312
316
|
this.wrapper.addEventListener('scroll', this.handleScrollDebounced, {
|
|
313
317
|
passive: true
|
|
314
318
|
});
|
|
315
|
-
|
|
319
|
+
const {
|
|
320
|
+
stickyScrollbar
|
|
321
|
+
} = getEditorFeatureFlags();
|
|
322
|
+
if (stickyScrollbar) {
|
|
316
323
|
if (this.table) {
|
|
317
324
|
this.stickyScrollbar = new TableStickyScrollbar(this.wrapper, this.props.view);
|
|
318
325
|
}
|
|
@@ -398,7 +405,8 @@ class TableComponent extends React.Component {
|
|
|
398
405
|
allowColumnResizing,
|
|
399
406
|
eventDispatcher,
|
|
400
407
|
options,
|
|
401
|
-
isDragAndDropEnabled
|
|
408
|
+
isDragAndDropEnabled,
|
|
409
|
+
getEditorFeatureFlags
|
|
402
410
|
} = this.props;
|
|
403
411
|
if (this.wrapper && !isIE11) {
|
|
404
412
|
this.wrapper.removeEventListener('scroll', this.handleScrollDebounced);
|
|
@@ -406,7 +414,10 @@ class TableComponent extends React.Component {
|
|
|
406
414
|
if (isDragAndDropEnabled && this.dragAndDropCleanupFn) {
|
|
407
415
|
this.dragAndDropCleanupFn();
|
|
408
416
|
}
|
|
409
|
-
|
|
417
|
+
const {
|
|
418
|
+
stickyScrollbar
|
|
419
|
+
} = getEditorFeatureFlags();
|
|
420
|
+
if (stickyScrollbar) {
|
|
410
421
|
if (this.stickyScrollbar) {
|
|
411
422
|
this.stickyScrollbar.dispose();
|
|
412
423
|
}
|
|
@@ -518,7 +529,8 @@ class TableComponent extends React.Component {
|
|
|
518
529
|
getPos,
|
|
519
530
|
pluginInjectionApi,
|
|
520
531
|
isDragAndDropEnabled,
|
|
521
|
-
canDrag
|
|
532
|
+
canDrag,
|
|
533
|
+
getEditorFeatureFlags
|
|
522
534
|
} = this.props;
|
|
523
535
|
const {
|
|
524
536
|
showBeforeShadow,
|
|
@@ -575,8 +587,8 @@ class TableComponent extends React.Component {
|
|
|
575
587
|
selection: view.state.selection,
|
|
576
588
|
headerRowHeight: headerRow ? headerRow.offsetHeight : undefined,
|
|
577
589
|
stickyHeader: this.state.stickyHeader,
|
|
578
|
-
|
|
579
|
-
|
|
590
|
+
canDrag: canDrag,
|
|
591
|
+
getEditorFeatureFlags: getEditorFeatureFlags
|
|
580
592
|
}) : null;
|
|
581
593
|
const shadowPadding = allowControls && tableActive ? -tableToolbarSize : tableMarginSides;
|
|
582
594
|
const shadowStyle = memoizeOne(visible => ({
|
|
@@ -596,6 +608,9 @@ class TableComponent extends React.Component {
|
|
|
596
608
|
}
|
|
597
609
|
const isNested = isTableNested(view.state, tablePos);
|
|
598
610
|
const topStickyShadowPosition = isDragAndDropEnabled ? this.state.stickyHeader && this.state.stickyHeader.top + this.state.stickyHeader.padding + 2 : this.state.stickyHeader && this.state.stickyHeader.top + this.state.stickyHeader.padding + shadowPadding + 2;
|
|
611
|
+
const {
|
|
612
|
+
stickyScrollbar
|
|
613
|
+
} = getEditorFeatureFlags();
|
|
599
614
|
return /*#__PURE__*/React.createElement(TableContainer, {
|
|
600
615
|
className: classnames(ClassName.TABLE_CONTAINER, {
|
|
601
616
|
[ClassName.WITH_CONTROLS]: allowControls && tableActive,
|
|
@@ -616,7 +631,7 @@ class TableComponent extends React.Component {
|
|
|
616
631
|
}, /*#__PURE__*/React.createElement("div", {
|
|
617
632
|
className: ClassName.TABLE_STICKY_SENTINEL_TOP,
|
|
618
633
|
"data-testid": "sticky-sentinel-top"
|
|
619
|
-
}),
|
|
634
|
+
}), stickyScrollbar && /*#__PURE__*/React.createElement("div", {
|
|
620
635
|
className: ClassName.TABLE_STICKY_SCROLLBAR_SENTINEL_TOP,
|
|
621
636
|
"data-testid": "sticky-scrollbar-sentinel-top"
|
|
622
637
|
}), allowControls && rowControls, isDragAndDropEnabled && /*#__PURE__*/React.createElement(ExternalDropTargets, {
|
|
@@ -653,11 +668,13 @@ class TableComponent extends React.Component {
|
|
|
653
668
|
}
|
|
654
669
|
}
|
|
655
670
|
}
|
|
656
|
-
}, allowControls && colControls),
|
|
671
|
+
}, allowControls && colControls), stickyScrollbar && /*#__PURE__*/React.createElement("div", {
|
|
657
672
|
className: ClassName.TABLE_STICKY_SCROLLBAR_CONTAINER,
|
|
658
673
|
style: {
|
|
659
674
|
height: MAX_BROWSER_SCROLLBAR_HEIGHT,
|
|
660
|
-
display: 'none'
|
|
675
|
+
display: 'none',
|
|
676
|
+
// prevent unwanted scroll during table resize without removing scrollbar container from the dom
|
|
677
|
+
width: isResizing ? '0px' : '100%'
|
|
661
678
|
}
|
|
662
679
|
}, /*#__PURE__*/React.createElement("div", {
|
|
663
680
|
style: {
|
|
@@ -682,7 +699,7 @@ class TableComponent extends React.Component {
|
|
|
682
699
|
})), /*#__PURE__*/React.createElement("div", {
|
|
683
700
|
className: ClassName.TABLE_STICKY_SENTINEL_BOTTOM,
|
|
684
701
|
"data-testid": "sticky-sentinel-bottom"
|
|
685
|
-
}),
|
|
702
|
+
}), stickyScrollbar && /*#__PURE__*/React.createElement("div", {
|
|
686
703
|
className: ClassName.TABLE_STICKY_SCROLLBAR_SENTINEL_BOTTOM,
|
|
687
704
|
"data-testid": "sticky-scrollbar-sentinel-bottom"
|
|
688
705
|
}));
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
1
|
+
import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import debounce from 'lodash/debounce';
|
|
2
3
|
import rafSchd from 'raf-schd';
|
|
3
4
|
import { useIntl } from 'react-intl-next';
|
|
4
5
|
import { TABLE_OVERFLOW_CHANGE_TRIGGER } from '@atlaskit/editor-common/analytics';
|
|
5
6
|
import { getGuidelinesWithHighlights } from '@atlaskit/editor-common/guideline';
|
|
7
|
+
import { focusTableResizer, ToolTipContent } from '@atlaskit/editor-common/keymaps';
|
|
6
8
|
import { tableMessages as messages } from '@atlaskit/editor-common/messages';
|
|
7
9
|
import { ResizerNext } from '@atlaskit/editor-common/resizer';
|
|
10
|
+
import { browser } from '@atlaskit/editor-common/utils';
|
|
8
11
|
import { findTable } from '@atlaskit/editor-tables/utils';
|
|
9
12
|
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
10
13
|
import { getPluginState } from '../pm-plugins/plugin-factory';
|
|
@@ -15,6 +18,8 @@ import { TABLE_HIGHLIGHT_GAP, TABLE_HIGHLIGHT_TOLERANCE, TABLE_SNAP_GAP } from '
|
|
|
15
18
|
import { generateResizedPayload, generateResizeFrameRatePayloads, useMeasureFramerate } from '../utils/analytics';
|
|
16
19
|
import { defaultGuidelines } from '../utils/guidelines';
|
|
17
20
|
import { defaultSnappingWidths, findClosestSnap } from '../utils/snapping';
|
|
21
|
+
const DEBOUNCE_TIME_FOR_SCREEN_READER_ANNOUNCER = 1000;
|
|
22
|
+
const RESIZE_STEP_VALUE = 10;
|
|
18
23
|
const handles = {
|
|
19
24
|
right: true
|
|
20
25
|
};
|
|
@@ -83,10 +88,31 @@ export const TableResizer = ({
|
|
|
83
88
|
const currentGap = useRef(0);
|
|
84
89
|
// track resizing state - use ref over state to avoid re-render
|
|
85
90
|
const isResizing = useRef(false);
|
|
91
|
+
const areResizeMetaKeysPressed = useRef(false);
|
|
92
|
+
const resizerRef = useRef(null);
|
|
93
|
+
|
|
94
|
+
// used to reposition tooltip when table is resizing via keyboard
|
|
95
|
+
const updateTooltip = React.useRef();
|
|
86
96
|
const [snappingEnabled, setSnappingEnabled] = useState(false);
|
|
97
|
+
|
|
98
|
+
// we don't want to update aria-live region on each width change, it might provide bad experience for screen reader users
|
|
99
|
+
const [screenReaderResizeInformation, setScreenReaderResizeInformation] = useState({
|
|
100
|
+
type: 'none',
|
|
101
|
+
width
|
|
102
|
+
});
|
|
87
103
|
const {
|
|
88
104
|
formatMessage
|
|
89
105
|
} = useIntl();
|
|
106
|
+
const screenReaderResizeAnnouncerMessages = {
|
|
107
|
+
increase: formatMessage(messages.tableSizeIncreaseScreenReaderInformation, {
|
|
108
|
+
newWidth: screenReaderResizeInformation.width
|
|
109
|
+
}),
|
|
110
|
+
decrease: formatMessage(messages.tableSizeDecreaseScreenReaderInformation, {
|
|
111
|
+
newWidth: screenReaderResizeInformation.width
|
|
112
|
+
}),
|
|
113
|
+
none: ''
|
|
114
|
+
};
|
|
115
|
+
const isTableSelected = ((_findTable = findTable((_editorView$state = editorView.state) === null || _editorView$state === void 0 ? void 0 : _editorView$state.selection)) === null || _findTable === void 0 ? void 0 : _findTable.pos) === getPos();
|
|
90
116
|
const resizerMinWidth = getResizerMinWidth(node);
|
|
91
117
|
const handleSize = getResizerHandleHeight(tableRef);
|
|
92
118
|
const {
|
|
@@ -230,8 +256,109 @@ export const TableResizer = ({
|
|
|
230
256
|
}
|
|
231
257
|
return newWidth;
|
|
232
258
|
}, [displayGapCursor, updateWidth, editorView, getPos, node, tableRef, scheduleResize, displayGuideline, attachAnalyticsEvent, endMeasure, onResizeStop]);
|
|
233
|
-
const
|
|
234
|
-
|
|
259
|
+
const handleTableSizeChangeOnKeypress = useCallback(step => {
|
|
260
|
+
const newWidth = width + step;
|
|
261
|
+
if (newWidth > maxWidth || newWidth < resizerMinWidth) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
handleResizeStop({
|
|
265
|
+
width: width,
|
|
266
|
+
x: 0,
|
|
267
|
+
y: 0,
|
|
268
|
+
height: 0
|
|
269
|
+
}, {
|
|
270
|
+
width: step,
|
|
271
|
+
height: 0
|
|
272
|
+
});
|
|
273
|
+
}, [width, handleResizeStop, maxWidth, resizerMinWidth]);
|
|
274
|
+
const handleEscape = useCallback(() => {
|
|
275
|
+
editorView === null || editorView === void 0 ? void 0 : editorView.focus();
|
|
276
|
+
}, [editorView]);
|
|
277
|
+
const handleKeyDown = useCallback(event => {
|
|
278
|
+
const isBracketKey = event.code === 'BracketRight' || event.code === 'BracketLeft';
|
|
279
|
+
const metaKey = browser.mac ? event.metaKey : event.ctrlKey;
|
|
280
|
+
if (event.altKey || metaKey || event.shiftKey) {
|
|
281
|
+
areResizeMetaKeysPressed.current = true;
|
|
282
|
+
}
|
|
283
|
+
if (event.altKey && metaKey) {
|
|
284
|
+
if (isBracketKey) {
|
|
285
|
+
event.preventDefault();
|
|
286
|
+
handleTableSizeChangeOnKeypress(event.code === 'BracketRight' ? RESIZE_STEP_VALUE : -RESIZE_STEP_VALUE);
|
|
287
|
+
}
|
|
288
|
+
} else if (!areResizeMetaKeysPressed.current) {
|
|
289
|
+
handleEscape();
|
|
290
|
+
}
|
|
291
|
+
}, [handleEscape, handleTableSizeChangeOnKeypress]);
|
|
292
|
+
const handleKeyUp = useCallback(event => {
|
|
293
|
+
if (event.altKey || event.metaKey) {
|
|
294
|
+
areResizeMetaKeysPressed.current = false;
|
|
295
|
+
}
|
|
296
|
+
return;
|
|
297
|
+
}, [areResizeMetaKeysPressed]);
|
|
298
|
+
useLayoutEffect(() => {
|
|
299
|
+
if (getBooleanFF('platform.editor.a11y-table-resizing_uapcv')) {
|
|
300
|
+
if (!resizerRef.current) {
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
const resizeHandleThumbEl = resizerRef.current.getResizerThumbEl();
|
|
304
|
+
const globalKeyDownHandler = event => {
|
|
305
|
+
const metaKey = browser.mac ? event.metaKey : event.ctrlKey;
|
|
306
|
+
if (!isTableSelected) {
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
if (event.altKey && event.shiftKey && metaKey && event.code === 'KeyR') {
|
|
310
|
+
event.preventDefault();
|
|
311
|
+
if (!resizeHandleThumbEl) {
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
resizeHandleThumbEl.focus();
|
|
315
|
+
resizeHandleThumbEl.scrollIntoView({
|
|
316
|
+
behavior: 'smooth',
|
|
317
|
+
block: 'center',
|
|
318
|
+
inline: 'nearest'
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
const editorViewDom = editorView === null || editorView === void 0 ? void 0 : editorView.dom;
|
|
323
|
+
editorViewDom === null || editorViewDom === void 0 ? void 0 : editorViewDom.addEventListener('keydown', globalKeyDownHandler);
|
|
324
|
+
resizeHandleThumbEl === null || resizeHandleThumbEl === void 0 ? void 0 : resizeHandleThumbEl.addEventListener('keydown', handleKeyDown);
|
|
325
|
+
resizeHandleThumbEl === null || resizeHandleThumbEl === void 0 ? void 0 : resizeHandleThumbEl.addEventListener('keyup', handleKeyUp);
|
|
326
|
+
return () => {
|
|
327
|
+
editorViewDom === null || editorViewDom === void 0 ? void 0 : editorViewDom.removeEventListener('keydown', globalKeyDownHandler);
|
|
328
|
+
resizeHandleThumbEl === null || resizeHandleThumbEl === void 0 ? void 0 : resizeHandleThumbEl.removeEventListener('keydown', handleKeyDown);
|
|
329
|
+
resizeHandleThumbEl === null || resizeHandleThumbEl === void 0 ? void 0 : resizeHandleThumbEl.removeEventListener('keyup', handleKeyUp);
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
}, [resizerRef, editorView, handleResizeStop, isTableSelected, handleKeyDown, handleKeyUp]);
|
|
333
|
+
useLayoutEffect(() => {
|
|
334
|
+
if (getBooleanFF('platform.editor.a11y-table-resizing_uapcv')) {
|
|
335
|
+
var _updateTooltip$curren;
|
|
336
|
+
(_updateTooltip$curren = updateTooltip.current) === null || _updateTooltip$curren === void 0 ? void 0 : _updateTooltip$curren.call(updateTooltip);
|
|
337
|
+
}
|
|
338
|
+
}, [width]);
|
|
339
|
+
useEffect(() => {
|
|
340
|
+
if (getBooleanFF('platform.editor.a11y-table-resizing_uapcv')) {
|
|
341
|
+
const debouncedSetWidth = debounce(setScreenReaderResizeInformation, DEBOUNCE_TIME_FOR_SCREEN_READER_ANNOUNCER);
|
|
342
|
+
debouncedSetWidth(prevState => {
|
|
343
|
+
let type = 'none';
|
|
344
|
+
if (prevState.width > width) {
|
|
345
|
+
type = 'decrease';
|
|
346
|
+
}
|
|
347
|
+
if (prevState.width < width) {
|
|
348
|
+
type = 'increase';
|
|
349
|
+
}
|
|
350
|
+
return {
|
|
351
|
+
type,
|
|
352
|
+
width
|
|
353
|
+
};
|
|
354
|
+
});
|
|
355
|
+
return () => {
|
|
356
|
+
debouncedSetWidth.cancel();
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
}, [width]);
|
|
360
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ResizerNext, {
|
|
361
|
+
ref: resizerRef,
|
|
235
362
|
enable: handles,
|
|
236
363
|
width: width,
|
|
237
364
|
handleAlignmentMethod: "sticky",
|
|
@@ -249,6 +376,17 @@ export const TableResizer = ({
|
|
|
249
376
|
isHandleVisible: isTableSelected,
|
|
250
377
|
appearance: isTableSelected && isWholeTableInDanger ? 'danger' : undefined,
|
|
251
378
|
handleHighlight: "shadow",
|
|
252
|
-
handleTooltipContent:
|
|
253
|
-
|
|
379
|
+
handleTooltipContent: getBooleanFF('platform.editor.a11y-table-resizing_uapcv') ? ({
|
|
380
|
+
update
|
|
381
|
+
}) => {
|
|
382
|
+
updateTooltip.current = update;
|
|
383
|
+
return /*#__PURE__*/React.createElement(ToolTipContent, {
|
|
384
|
+
description: formatMessage(messages.resizeTable),
|
|
385
|
+
keymap: focusTableResizer
|
|
386
|
+
});
|
|
387
|
+
} : formatMessage(messages.resizeTable)
|
|
388
|
+
}, children), getBooleanFF('platform.editor.a11y-table-resizing_uapcv') && /*#__PURE__*/React.createElement("div", {
|
|
389
|
+
className: "assistive",
|
|
390
|
+
role: "status"
|
|
391
|
+
}, screenReaderResizeAnnouncerMessages[screenReaderResizeInformation.type]));
|
|
254
392
|
};
|
|
@@ -11,7 +11,6 @@ import { akEditorFloatingPanelZIndex } from '@atlaskit/editor-shared-styles';
|
|
|
11
11
|
import { shortcutStyle } from '@atlaskit/editor-shared-styles/shortcut';
|
|
12
12
|
import { findCellRectClosestToPos, findTable, getSelectionRect, isSelectionType, splitCell } from '@atlaskit/editor-tables/utils';
|
|
13
13
|
import RemoveIcon from '@atlaskit/icon/glyph/editor/remove';
|
|
14
|
-
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
15
14
|
import { clearHoverSelection, hoverColumns, hoverMergedCells, hoverRows, hoverTable, removeDescendantNodes } from './commands';
|
|
16
15
|
import { deleteColumnsWithAnalytics, deleteRowsWithAnalytics, deleteTableWithAnalytics, distributeColumnsWidthsWithAnalytics, emptyMultipleCellsWithAnalytics, insertColumnWithAnalytics, insertRowWithAnalytics, mergeCellsWithAnalytics, setColorWithAnalytics, sortColumnWithAnalytics, splitCellWithAnalytics, toggleHeaderColumnWithAnalytics, toggleHeaderRowWithAnalytics, toggleNumberColumnWithAnalytics, wrapTableInExpandWithAnalytics } from './commands-with-analytics';
|
|
17
16
|
import { getPluginState } from './pm-plugins/plugin-factory';
|
|
@@ -304,12 +303,15 @@ export const getToolbarConfig = (getEditorContainerWidth, editorAnalyticsAPI, ge
|
|
|
304
303
|
}
|
|
305
304
|
return element;
|
|
306
305
|
};
|
|
306
|
+
const {
|
|
307
|
+
stickyScrollbar
|
|
308
|
+
} = getEditorFeatureFlags();
|
|
307
309
|
return {
|
|
308
310
|
title: 'Table floating controls',
|
|
309
311
|
getDomRef,
|
|
310
312
|
nodeType,
|
|
311
313
|
offset: [0, 18],
|
|
312
|
-
absoluteOffset:
|
|
314
|
+
absoluteOffset: stickyScrollbar ? {
|
|
313
315
|
top: -6
|
|
314
316
|
} : {
|
|
315
317
|
top: 0
|
|
@@ -77,8 +77,8 @@ const stickyScrollbarContainerStyles = `.${ClassName.TABLE_CONTAINER} {
|
|
|
77
77
|
bottom: 0;
|
|
78
78
|
}
|
|
79
79
|
}`;
|
|
80
|
-
const stickyScrollbarStyles =
|
|
81
|
-
return
|
|
80
|
+
const stickyScrollbarStyles = featureFlags => {
|
|
81
|
+
return featureFlags !== null && featureFlags !== void 0 && featureFlags.stickyScrollbar ? `${stickyScrollbarContainerStyles} ${stickyScrollbarSentinelStyles}` : '';
|
|
82
82
|
};
|
|
83
83
|
const shadowSentinelStyles = `
|
|
84
84
|
.${ClassName.TABLE_SHADOW_SENTINEL_LEFT},
|
|
@@ -437,7 +437,7 @@ export const tableStyles = props => {
|
|
|
437
437
|
|
|
438
438
|
${sentinelStyles}
|
|
439
439
|
${OverflowShadow(props)}
|
|
440
|
-
${stickyScrollbarStyles()}
|
|
440
|
+
${stickyScrollbarStyles(props.featureFlags)}
|
|
441
441
|
|
|
442
442
|
.${ClassName.TABLE_STICKY} .${ClassName.TABLE_STICKY_SHADOW} {
|
|
443
443
|
height: 0; // stop overflow flash & set correct height in update-overflow-shadows.ts
|
|
@@ -92,7 +92,9 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
|
|
|
92
92
|
if (!_this.wrapper || event.target !== _this.wrapper) {
|
|
93
93
|
return;
|
|
94
94
|
}
|
|
95
|
-
|
|
95
|
+
var _this$props$getEditor = _this.props.getEditorFeatureFlags(),
|
|
96
|
+
stickyScrollbar = _this$props$getEditor.stickyScrollbar;
|
|
97
|
+
if (stickyScrollbar) {
|
|
96
98
|
if (_this.stickyScrollbar) {
|
|
97
99
|
_this.stickyScrollbar.scrollLeft(_this.wrapper.scrollLeft);
|
|
98
100
|
}
|
|
@@ -304,12 +306,15 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
|
|
|
304
306
|
eventDispatcher = _this$props7.eventDispatcher,
|
|
305
307
|
options = _this$props7.options,
|
|
306
308
|
isDragAndDropEnabled = _this$props7.isDragAndDropEnabled,
|
|
307
|
-
getNode = _this$props7.getNode
|
|
309
|
+
getNode = _this$props7.getNode,
|
|
310
|
+
getEditorFeatureFlags = _this$props7.getEditorFeatureFlags;
|
|
308
311
|
if (allowColumnResizing && this.wrapper && !isIE11) {
|
|
309
312
|
this.wrapper.addEventListener('scroll', this.handleScrollDebounced, {
|
|
310
313
|
passive: true
|
|
311
314
|
});
|
|
312
|
-
|
|
315
|
+
var _getEditorFeatureFlag = getEditorFeatureFlags(),
|
|
316
|
+
stickyScrollbar = _getEditorFeatureFlag.stickyScrollbar;
|
|
317
|
+
if (stickyScrollbar) {
|
|
313
318
|
if (this.table) {
|
|
314
319
|
this.stickyScrollbar = new TableStickyScrollbar(this.wrapper, this.props.view);
|
|
315
320
|
}
|
|
@@ -393,14 +398,17 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
|
|
|
393
398
|
allowColumnResizing = _this$props8.allowColumnResizing,
|
|
394
399
|
eventDispatcher = _this$props8.eventDispatcher,
|
|
395
400
|
options = _this$props8.options,
|
|
396
|
-
isDragAndDropEnabled = _this$props8.isDragAndDropEnabled
|
|
401
|
+
isDragAndDropEnabled = _this$props8.isDragAndDropEnabled,
|
|
402
|
+
getEditorFeatureFlags = _this$props8.getEditorFeatureFlags;
|
|
397
403
|
if (this.wrapper && !isIE11) {
|
|
398
404
|
this.wrapper.removeEventListener('scroll', this.handleScrollDebounced);
|
|
399
405
|
}
|
|
400
406
|
if (isDragAndDropEnabled && this.dragAndDropCleanupFn) {
|
|
401
407
|
this.dragAndDropCleanupFn();
|
|
402
408
|
}
|
|
403
|
-
|
|
409
|
+
var _getEditorFeatureFlag2 = getEditorFeatureFlags(),
|
|
410
|
+
stickyScrollbar = _getEditorFeatureFlag2.stickyScrollbar;
|
|
411
|
+
if (stickyScrollbar) {
|
|
404
412
|
if (this.stickyScrollbar) {
|
|
405
413
|
this.stickyScrollbar.dispose();
|
|
406
414
|
}
|
|
@@ -512,7 +520,8 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
|
|
|
512
520
|
getPos = _this$props10.getPos,
|
|
513
521
|
pluginInjectionApi = _this$props10.pluginInjectionApi,
|
|
514
522
|
isDragAndDropEnabled = _this$props10.isDragAndDropEnabled,
|
|
515
|
-
canDrag = _this$props10.canDrag
|
|
523
|
+
canDrag = _this$props10.canDrag,
|
|
524
|
+
getEditorFeatureFlags = _this$props10.getEditorFeatureFlags;
|
|
516
525
|
var _this$state3 = this.state,
|
|
517
526
|
showBeforeShadow = _this$state3.showBeforeShadow,
|
|
518
527
|
showAfterShadow = _this$state3.showAfterShadow;
|
|
@@ -566,8 +575,8 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
|
|
|
566
575
|
selection: view.state.selection,
|
|
567
576
|
headerRowHeight: headerRow ? headerRow.offsetHeight : undefined,
|
|
568
577
|
stickyHeader: this.state.stickyHeader,
|
|
569
|
-
|
|
570
|
-
|
|
578
|
+
canDrag: canDrag,
|
|
579
|
+
getEditorFeatureFlags: getEditorFeatureFlags
|
|
571
580
|
}) : null;
|
|
572
581
|
var shadowPadding = allowControls && tableActive ? -tableToolbarSize : tableMarginSides;
|
|
573
582
|
var shadowStyle = memoizeOne(function (visible) {
|
|
@@ -589,6 +598,8 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
|
|
|
589
598
|
}
|
|
590
599
|
var isNested = isTableNested(view.state, tablePos);
|
|
591
600
|
var topStickyShadowPosition = isDragAndDropEnabled ? this.state.stickyHeader && this.state.stickyHeader.top + this.state.stickyHeader.padding + 2 : this.state.stickyHeader && this.state.stickyHeader.top + this.state.stickyHeader.padding + shadowPadding + 2;
|
|
601
|
+
var _getEditorFeatureFlag3 = getEditorFeatureFlags(),
|
|
602
|
+
stickyScrollbar = _getEditorFeatureFlag3.stickyScrollbar;
|
|
592
603
|
return /*#__PURE__*/React.createElement(TableContainer, {
|
|
593
604
|
className: classnames(ClassName.TABLE_CONTAINER, (_classnames = {}, _defineProperty(_classnames, ClassName.WITH_CONTROLS, allowControls && tableActive), _defineProperty(_classnames, ClassName.TABLE_STICKY, this.state.stickyHeader && hasHeaderRow), _defineProperty(_classnames, ClassName.HOVERED_DELETE_BUTTON, isInDanger), _defineProperty(_classnames, ClassName.TABLE_SELECTED, isTableSelected(view.state.selection)), _classnames)),
|
|
594
605
|
editorView: view,
|
|
@@ -604,7 +615,7 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
|
|
|
604
615
|
}, /*#__PURE__*/React.createElement("div", {
|
|
605
616
|
className: ClassName.TABLE_STICKY_SENTINEL_TOP,
|
|
606
617
|
"data-testid": "sticky-sentinel-top"
|
|
607
|
-
}),
|
|
618
|
+
}), stickyScrollbar && /*#__PURE__*/React.createElement("div", {
|
|
608
619
|
className: ClassName.TABLE_STICKY_SCROLLBAR_SENTINEL_TOP,
|
|
609
620
|
"data-testid": "sticky-scrollbar-sentinel-top"
|
|
610
621
|
}), allowControls && rowControls, isDragAndDropEnabled && /*#__PURE__*/React.createElement(ExternalDropTargets, {
|
|
@@ -641,11 +652,13 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
|
|
|
641
652
|
}
|
|
642
653
|
}
|
|
643
654
|
}
|
|
644
|
-
}, allowControls && colControls),
|
|
655
|
+
}, allowControls && colControls), stickyScrollbar && /*#__PURE__*/React.createElement("div", {
|
|
645
656
|
className: ClassName.TABLE_STICKY_SCROLLBAR_CONTAINER,
|
|
646
657
|
style: {
|
|
647
658
|
height: MAX_BROWSER_SCROLLBAR_HEIGHT,
|
|
648
|
-
display: 'none'
|
|
659
|
+
display: 'none',
|
|
660
|
+
// prevent unwanted scroll during table resize without removing scrollbar container from the dom
|
|
661
|
+
width: isResizing ? '0px' : '100%'
|
|
649
662
|
}
|
|
650
663
|
}, /*#__PURE__*/React.createElement("div", {
|
|
651
664
|
style: {
|
|
@@ -670,7 +683,7 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
|
|
|
670
683
|
})), /*#__PURE__*/React.createElement("div", {
|
|
671
684
|
className: ClassName.TABLE_STICKY_SENTINEL_BOTTOM,
|
|
672
685
|
"data-testid": "sticky-sentinel-bottom"
|
|
673
|
-
}),
|
|
686
|
+
}), stickyScrollbar && /*#__PURE__*/React.createElement("div", {
|
|
674
687
|
className: ClassName.TABLE_STICKY_SCROLLBAR_SENTINEL_BOTTOM,
|
|
675
688
|
"data-testid": "sticky-scrollbar-sentinel-bottom"
|
|
676
689
|
}));
|
|
@@ -2,13 +2,16 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
|
2
2
|
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
3
3
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
4
4
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
5
|
-
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
5
|
+
import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
6
|
+
import debounce from 'lodash/debounce';
|
|
6
7
|
import rafSchd from 'raf-schd';
|
|
7
8
|
import { useIntl } from 'react-intl-next';
|
|
8
9
|
import { TABLE_OVERFLOW_CHANGE_TRIGGER } from '@atlaskit/editor-common/analytics';
|
|
9
10
|
import { getGuidelinesWithHighlights } from '@atlaskit/editor-common/guideline';
|
|
11
|
+
import { focusTableResizer, ToolTipContent } from '@atlaskit/editor-common/keymaps';
|
|
10
12
|
import { tableMessages as messages } from '@atlaskit/editor-common/messages';
|
|
11
13
|
import { ResizerNext } from '@atlaskit/editor-common/resizer';
|
|
14
|
+
import { browser } from '@atlaskit/editor-common/utils';
|
|
12
15
|
import { findTable } from '@atlaskit/editor-tables/utils';
|
|
13
16
|
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
14
17
|
import { getPluginState } from '../pm-plugins/plugin-factory';
|
|
@@ -19,6 +22,8 @@ import { TABLE_HIGHLIGHT_GAP, TABLE_HIGHLIGHT_TOLERANCE, TABLE_SNAP_GAP } from '
|
|
|
19
22
|
import { generateResizedPayload, generateResizeFrameRatePayloads, useMeasureFramerate } from '../utils/analytics';
|
|
20
23
|
import { defaultGuidelines } from '../utils/guidelines';
|
|
21
24
|
import { defaultSnappingWidths, findClosestSnap } from '../utils/snapping';
|
|
25
|
+
var DEBOUNCE_TIME_FOR_SCREEN_READER_ANNOUNCER = 1000;
|
|
26
|
+
var RESIZE_STEP_VALUE = 10;
|
|
22
27
|
var handles = {
|
|
23
28
|
right: true
|
|
24
29
|
};
|
|
@@ -86,12 +91,36 @@ export var TableResizer = function TableResizer(_ref) {
|
|
|
86
91
|
var currentGap = useRef(0);
|
|
87
92
|
// track resizing state - use ref over state to avoid re-render
|
|
88
93
|
var isResizing = useRef(false);
|
|
94
|
+
var areResizeMetaKeysPressed = useRef(false);
|
|
95
|
+
var resizerRef = useRef(null);
|
|
96
|
+
|
|
97
|
+
// used to reposition tooltip when table is resizing via keyboard
|
|
98
|
+
var updateTooltip = React.useRef();
|
|
89
99
|
var _useState = useState(false),
|
|
90
100
|
_useState2 = _slicedToArray(_useState, 2),
|
|
91
101
|
snappingEnabled = _useState2[0],
|
|
92
102
|
setSnappingEnabled = _useState2[1];
|
|
103
|
+
|
|
104
|
+
// we don't want to update aria-live region on each width change, it might provide bad experience for screen reader users
|
|
105
|
+
var _useState3 = useState({
|
|
106
|
+
type: 'none',
|
|
107
|
+
width: width
|
|
108
|
+
}),
|
|
109
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
110
|
+
screenReaderResizeInformation = _useState4[0],
|
|
111
|
+
setScreenReaderResizeInformation = _useState4[1];
|
|
93
112
|
var _useIntl = useIntl(),
|
|
94
113
|
formatMessage = _useIntl.formatMessage;
|
|
114
|
+
var screenReaderResizeAnnouncerMessages = {
|
|
115
|
+
increase: formatMessage(messages.tableSizeIncreaseScreenReaderInformation, {
|
|
116
|
+
newWidth: screenReaderResizeInformation.width
|
|
117
|
+
}),
|
|
118
|
+
decrease: formatMessage(messages.tableSizeDecreaseScreenReaderInformation, {
|
|
119
|
+
newWidth: screenReaderResizeInformation.width
|
|
120
|
+
}),
|
|
121
|
+
none: ''
|
|
122
|
+
};
|
|
123
|
+
var isTableSelected = ((_findTable = findTable((_editorView$state = editorView.state) === null || _editorView$state === void 0 ? void 0 : _editorView$state.selection)) === null || _findTable === void 0 ? void 0 : _findTable.pos) === getPos();
|
|
95
124
|
var resizerMinWidth = getResizerMinWidth(node);
|
|
96
125
|
var handleSize = getResizerHandleHeight(tableRef);
|
|
97
126
|
var _getPluginState = getPluginState(editorView.state),
|
|
@@ -225,8 +254,109 @@ export var TableResizer = function TableResizer(_ref) {
|
|
|
225
254
|
}
|
|
226
255
|
return newWidth;
|
|
227
256
|
}, [displayGapCursor, updateWidth, editorView, getPos, node, tableRef, scheduleResize, displayGuideline, attachAnalyticsEvent, endMeasure, onResizeStop]);
|
|
228
|
-
var
|
|
229
|
-
|
|
257
|
+
var handleTableSizeChangeOnKeypress = useCallback(function (step) {
|
|
258
|
+
var newWidth = width + step;
|
|
259
|
+
if (newWidth > maxWidth || newWidth < resizerMinWidth) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
handleResizeStop({
|
|
263
|
+
width: width,
|
|
264
|
+
x: 0,
|
|
265
|
+
y: 0,
|
|
266
|
+
height: 0
|
|
267
|
+
}, {
|
|
268
|
+
width: step,
|
|
269
|
+
height: 0
|
|
270
|
+
});
|
|
271
|
+
}, [width, handleResizeStop, maxWidth, resizerMinWidth]);
|
|
272
|
+
var handleEscape = useCallback(function () {
|
|
273
|
+
editorView === null || editorView === void 0 || editorView.focus();
|
|
274
|
+
}, [editorView]);
|
|
275
|
+
var handleKeyDown = useCallback(function (event) {
|
|
276
|
+
var isBracketKey = event.code === 'BracketRight' || event.code === 'BracketLeft';
|
|
277
|
+
var metaKey = browser.mac ? event.metaKey : event.ctrlKey;
|
|
278
|
+
if (event.altKey || metaKey || event.shiftKey) {
|
|
279
|
+
areResizeMetaKeysPressed.current = true;
|
|
280
|
+
}
|
|
281
|
+
if (event.altKey && metaKey) {
|
|
282
|
+
if (isBracketKey) {
|
|
283
|
+
event.preventDefault();
|
|
284
|
+
handleTableSizeChangeOnKeypress(event.code === 'BracketRight' ? RESIZE_STEP_VALUE : -RESIZE_STEP_VALUE);
|
|
285
|
+
}
|
|
286
|
+
} else if (!areResizeMetaKeysPressed.current) {
|
|
287
|
+
handleEscape();
|
|
288
|
+
}
|
|
289
|
+
}, [handleEscape, handleTableSizeChangeOnKeypress]);
|
|
290
|
+
var handleKeyUp = useCallback(function (event) {
|
|
291
|
+
if (event.altKey || event.metaKey) {
|
|
292
|
+
areResizeMetaKeysPressed.current = false;
|
|
293
|
+
}
|
|
294
|
+
return;
|
|
295
|
+
}, [areResizeMetaKeysPressed]);
|
|
296
|
+
useLayoutEffect(function () {
|
|
297
|
+
if (getBooleanFF('platform.editor.a11y-table-resizing_uapcv')) {
|
|
298
|
+
if (!resizerRef.current) {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
var resizeHandleThumbEl = resizerRef.current.getResizerThumbEl();
|
|
302
|
+
var globalKeyDownHandler = function globalKeyDownHandler(event) {
|
|
303
|
+
var metaKey = browser.mac ? event.metaKey : event.ctrlKey;
|
|
304
|
+
if (!isTableSelected) {
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
if (event.altKey && event.shiftKey && metaKey && event.code === 'KeyR') {
|
|
308
|
+
event.preventDefault();
|
|
309
|
+
if (!resizeHandleThumbEl) {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
resizeHandleThumbEl.focus();
|
|
313
|
+
resizeHandleThumbEl.scrollIntoView({
|
|
314
|
+
behavior: 'smooth',
|
|
315
|
+
block: 'center',
|
|
316
|
+
inline: 'nearest'
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
var editorViewDom = editorView === null || editorView === void 0 ? void 0 : editorView.dom;
|
|
321
|
+
editorViewDom === null || editorViewDom === void 0 || editorViewDom.addEventListener('keydown', globalKeyDownHandler);
|
|
322
|
+
resizeHandleThumbEl === null || resizeHandleThumbEl === void 0 || resizeHandleThumbEl.addEventListener('keydown', handleKeyDown);
|
|
323
|
+
resizeHandleThumbEl === null || resizeHandleThumbEl === void 0 || resizeHandleThumbEl.addEventListener('keyup', handleKeyUp);
|
|
324
|
+
return function () {
|
|
325
|
+
editorViewDom === null || editorViewDom === void 0 || editorViewDom.removeEventListener('keydown', globalKeyDownHandler);
|
|
326
|
+
resizeHandleThumbEl === null || resizeHandleThumbEl === void 0 || resizeHandleThumbEl.removeEventListener('keydown', handleKeyDown);
|
|
327
|
+
resizeHandleThumbEl === null || resizeHandleThumbEl === void 0 || resizeHandleThumbEl.removeEventListener('keyup', handleKeyUp);
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
}, [resizerRef, editorView, handleResizeStop, isTableSelected, handleKeyDown, handleKeyUp]);
|
|
331
|
+
useLayoutEffect(function () {
|
|
332
|
+
if (getBooleanFF('platform.editor.a11y-table-resizing_uapcv')) {
|
|
333
|
+
var _updateTooltip$curren;
|
|
334
|
+
(_updateTooltip$curren = updateTooltip.current) === null || _updateTooltip$curren === void 0 || _updateTooltip$curren.call(updateTooltip);
|
|
335
|
+
}
|
|
336
|
+
}, [width]);
|
|
337
|
+
useEffect(function () {
|
|
338
|
+
if (getBooleanFF('platform.editor.a11y-table-resizing_uapcv')) {
|
|
339
|
+
var debouncedSetWidth = debounce(setScreenReaderResizeInformation, DEBOUNCE_TIME_FOR_SCREEN_READER_ANNOUNCER);
|
|
340
|
+
debouncedSetWidth(function (prevState) {
|
|
341
|
+
var type = 'none';
|
|
342
|
+
if (prevState.width > width) {
|
|
343
|
+
type = 'decrease';
|
|
344
|
+
}
|
|
345
|
+
if (prevState.width < width) {
|
|
346
|
+
type = 'increase';
|
|
347
|
+
}
|
|
348
|
+
return {
|
|
349
|
+
type: type,
|
|
350
|
+
width: width
|
|
351
|
+
};
|
|
352
|
+
});
|
|
353
|
+
return function () {
|
|
354
|
+
debouncedSetWidth.cancel();
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
}, [width]);
|
|
358
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ResizerNext, {
|
|
359
|
+
ref: resizerRef,
|
|
230
360
|
enable: handles,
|
|
231
361
|
width: width,
|
|
232
362
|
handleAlignmentMethod: "sticky",
|
|
@@ -244,6 +374,16 @@ export var TableResizer = function TableResizer(_ref) {
|
|
|
244
374
|
isHandleVisible: isTableSelected,
|
|
245
375
|
appearance: isTableSelected && isWholeTableInDanger ? 'danger' : undefined,
|
|
246
376
|
handleHighlight: "shadow",
|
|
247
|
-
handleTooltipContent:
|
|
248
|
-
|
|
377
|
+
handleTooltipContent: getBooleanFF('platform.editor.a11y-table-resizing_uapcv') ? function (_ref3) {
|
|
378
|
+
var update = _ref3.update;
|
|
379
|
+
updateTooltip.current = update;
|
|
380
|
+
return /*#__PURE__*/React.createElement(ToolTipContent, {
|
|
381
|
+
description: formatMessage(messages.resizeTable),
|
|
382
|
+
keymap: focusTableResizer
|
|
383
|
+
});
|
|
384
|
+
} : formatMessage(messages.resizeTable)
|
|
385
|
+
}, children), getBooleanFF('platform.editor.a11y-table-resizing_uapcv') && /*#__PURE__*/React.createElement("div", {
|
|
386
|
+
className: "assistive",
|
|
387
|
+
role: "status"
|
|
388
|
+
}, screenReaderResizeAnnouncerMessages[screenReaderResizeInformation.type]));
|
|
249
389
|
};
|