@atlaskit/editor-plugin-table 7.18.2 → 7.18.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 (47) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/cjs/commands/index.js +6 -0
  3. package/dist/cjs/commands/misc.js +15 -1
  4. package/dist/cjs/plugin.js +7 -4
  5. package/dist/cjs/pm-plugins/keymap.js +3 -0
  6. package/dist/cjs/reducer.js +1 -0
  7. package/dist/cjs/ui/FloatingContextualButton/index.js +18 -2
  8. package/dist/cjs/ui/FloatingContextualMenu/ContextualMenu.js +170 -35
  9. package/dist/cjs/ui/FloatingContextualMenu/index.js +4 -2
  10. package/dist/es2019/commands/index.js +1 -1
  11. package/dist/es2019/commands/misc.js +9 -1
  12. package/dist/es2019/plugin.js +7 -4
  13. package/dist/es2019/pm-plugins/keymap.js +5 -2
  14. package/dist/es2019/reducer.js +1 -0
  15. package/dist/es2019/ui/FloatingContextualButton/index.js +17 -2
  16. package/dist/es2019/ui/FloatingContextualMenu/ContextualMenu.js +159 -24
  17. package/dist/es2019/ui/FloatingContextualMenu/index.js +4 -2
  18. package/dist/esm/commands/index.js +1 -1
  19. package/dist/esm/commands/misc.js +14 -0
  20. package/dist/esm/plugin.js +7 -4
  21. package/dist/esm/pm-plugins/keymap.js +5 -2
  22. package/dist/esm/reducer.js +1 -0
  23. package/dist/esm/ui/FloatingContextualButton/index.js +15 -2
  24. package/dist/esm/ui/FloatingContextualMenu/ContextualMenu.js +171 -40
  25. package/dist/esm/ui/FloatingContextualMenu/index.js +4 -2
  26. package/dist/types/commands/index.d.ts +1 -1
  27. package/dist/types/commands/misc.d.ts +1 -0
  28. package/dist/types/types.d.ts +6 -0
  29. package/dist/types/ui/FloatingContextualButton/index.d.ts +1 -0
  30. package/dist/types/ui/FloatingContextualMenu/ContextualMenu.d.ts +7 -3
  31. package/dist/types/ui/FloatingContextualMenu/index.d.ts +2 -1
  32. package/dist/types-ts4.5/commands/index.d.ts +1 -1
  33. package/dist/types-ts4.5/commands/misc.d.ts +1 -0
  34. package/dist/types-ts4.5/types.d.ts +6 -0
  35. package/dist/types-ts4.5/ui/FloatingContextualButton/index.d.ts +1 -0
  36. package/dist/types-ts4.5/ui/FloatingContextualMenu/ContextualMenu.d.ts +7 -3
  37. package/dist/types-ts4.5/ui/FloatingContextualMenu/index.d.ts +2 -1
  38. package/package.json +4 -1
  39. package/src/commands/index.ts +1 -0
  40. package/src/commands/misc.ts +13 -0
  41. package/src/plugin.tsx +6 -1
  42. package/src/pm-plugins/keymap.ts +6 -1
  43. package/src/reducer.ts +1 -0
  44. package/src/types.ts +27 -20
  45. package/src/ui/FloatingContextualButton/index.tsx +19 -1
  46. package/src/ui/FloatingContextualMenu/ContextualMenu.tsx +209 -30
  47. package/src/ui/FloatingContextualMenu/index.tsx +3 -0
@@ -116,6 +116,7 @@ export default ((pluginState, action) => {
116
116
  case 'HOVER_CELL':
117
117
  case 'SHOW_RESIZE_HANDLE_LINE':
118
118
  case 'SET_EDITOR_FOCUS':
119
+ case 'SET_CELL_MENU_OPEN':
119
120
  return {
120
121
  ...pluginState,
121
122
  ...action.data
@@ -1,5 +1,5 @@
1
1
  /** @jsx jsx */
2
- import React from 'react';
2
+ import React, { useEffect } from 'react';
3
3
 
4
4
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
5
5
  import { jsx } from '@emotion/react';
@@ -12,6 +12,7 @@ import { ToolbarButton } from '@atlaskit/editor-common/ui-menu';
12
12
  import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
13
13
  import { akEditorSmallZIndex } from '@atlaskit/editor-shared-styles';
14
14
  import ExpandIcon from '@atlaskit/icon/glyph/chevron-down';
15
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
15
16
  import { toggleContextualMenu } from '../../commands';
16
17
  import { TableCssClassName as ClassName } from '../../types';
17
18
  import FixedButton from './FixedButton';
@@ -26,6 +27,7 @@ const FloatingContextualButtonInner = /*#__PURE__*/React.memo(props => {
26
27
  stickyHeader,
27
28
  tableWrapper,
28
29
  targetCellPosition,
30
+ isCellMenuOpenByKeyboard,
29
31
  intl: {
30
32
  formatMessage
31
33
  }
@@ -48,6 +50,18 @@ const FloatingContextualButtonInner = /*#__PURE__*/React.memo(props => {
48
50
  const domAtPos = editorView.domAtPos.bind(editorView);
49
51
  let targetCellRef;
50
52
  targetCellRef = findDomRefAtPos(targetCellPosition, domAtPos);
53
+ useEffect(() => {
54
+ if (getBooleanFF('platform.editor.a11y-table-context-menu_y4c9c')) {
55
+ if (isCellMenuOpenByKeyboard && !isContextualMenuOpen) {
56
+ const {
57
+ state,
58
+ dispatch
59
+ } = editorView;
60
+ // open the menu when the keyboard shortcut is pressed
61
+ toggleContextualMenu()(state, dispatch);
62
+ }
63
+ }
64
+ }, [isCellMenuOpenByKeyboard, isContextualMenuOpen, editorView]);
51
65
  if (!targetCellRef || !(targetCellRef instanceof HTMLElement)) {
52
66
  return null;
53
67
  }
@@ -68,7 +82,8 @@ const FloatingContextualButtonInner = /*#__PURE__*/React.memo(props => {
68
82
  iconBefore: jsx(ExpandIcon, {
69
83
  label: ""
70
84
  }),
71
- "aria-label": labelCellOptions
85
+ "aria-label": labelCellOptions,
86
+ "aria-expanded": getBooleanFF('platform.editor.a11y-table-context-menu_y4c9c') ? isContextualMenuOpen : undefined
72
87
  }));
73
88
  const parentSticky = targetCellRef.parentElement && targetCellRef.parentElement.className.indexOf('sticky') > -1;
74
89
  if (stickyHeader && parentSticky && tableWrapper) {
@@ -1,8 +1,7 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  /* eslint-disable @atlaskit/design-system/prefer-primitives */
3
3
  /** @jsx jsx */
4
- import { Component } from 'react';
5
-
4
+ import React, { Component } from 'react';
6
5
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
7
6
  import { jsx } from '@emotion/react';
8
7
  import { injectIntl } from 'react-intl-next';
@@ -11,8 +10,8 @@ import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
11
10
  import { addColumnAfter, addRowAfter, backspace, tooltip } from '@atlaskit/editor-common/keymaps';
12
11
  import { tableMessages as messages } from '@atlaskit/editor-common/messages';
13
12
  import { DropdownMenuSharedCssClassName } from '@atlaskit/editor-common/styles';
14
- import { backgroundPaletteTooltipMessages, cellBackgroundColorPalette, ColorPalette } from '@atlaskit/editor-common/ui-color';
15
- import { ArrowKeyNavigationType, DropdownMenu } from '@atlaskit/editor-common/ui-menu';
13
+ import { backgroundPaletteTooltipMessages, cellBackgroundColorPalette, ColorPalette, getSelectedRowAndColumnFromPalette } from '@atlaskit/editor-common/ui-color';
14
+ import { ArrowKeyNavigationProvider, ArrowKeyNavigationType, DropdownMenu } from '@atlaskit/editor-common/ui-menu';
16
15
  import { closestElement } from '@atlaskit/editor-common/utils';
17
16
  import { hexToEditorBackgroundPaletteColor } from '@atlaskit/editor-palette';
18
17
  import { shortcutStyle } from '@atlaskit/editor-shared-styles/shortcut';
@@ -21,22 +20,26 @@ import CrossCircleIcon from '@atlaskit/icon/glyph/cross-circle';
21
20
  import EditorBackgroundColorIcon from '@atlaskit/icon/glyph/editor/background-color';
22
21
  import RemoveIcon from '@atlaskit/icon/glyph/editor/remove';
23
22
  import { getBooleanFF } from '@atlaskit/platform-feature-flags';
24
- import { clearHoverSelection, hoverColumns, hoverMergedCells, hoverRows, toggleContextualMenu } from '../../commands';
23
+ import { clearHoverSelection, hoverColumns, hoverMergedCells, hoverRows, setFocusToCellMenu, toggleContextualMenu } from '../../commands';
25
24
  import { deleteColumnsWithAnalytics, deleteRowsWithAnalytics, distributeColumnsWidthsWithAnalytics, emptyMultipleCellsWithAnalytics, insertColumnWithAnalytics, insertRowWithAnalytics, mergeCellsWithAnalytics, setColorWithAnalytics, sortColumnWithAnalytics, splitCellWithAnalytics } from '../../commands-with-analytics';
26
25
  import { getPluginState } from '../../pm-plugins/plugin-factory';
26
+ import { pluginKey as tablePluginKey } from '../../pm-plugins/plugin-key';
27
27
  import { getNewResizeStateFromSelectedColumns } from '../../pm-plugins/table-resizing/utils/resize-state';
28
28
  import { canMergeCells } from '../../transforms';
29
29
  import { TableCssClassName as ClassName } from '../../types';
30
30
  import { getMergedCellsPositions, getSelectedColumnIndexes, getSelectedRowIndexes } from '../../utils';
31
- import { contextualMenuDropdownWidth, contextualMenuDropdownWidthDnD } from '../consts';
31
+ import { colorPalletteColumns, contextualMenuDropdownWidth, contextualMenuDropdownWidthDnD } from '../consts';
32
32
  import { AddColRightIcon, AddRowBelowIcon, MergeCellsIcon, SplitCellIcon } from '../icons';
33
33
  import { cellColourPreviewStyles, elementBeforeIconStyles } from './styles';
34
+ const arrowsList = new Set(['ArrowRight', 'ArrowLeft']);
34
35
  export class ContextualMenu extends Component {
35
36
  constructor(...args) {
36
37
  super(...args);
37
38
  _defineProperty(this, "state", {
38
- isSubmenuOpen: false
39
+ isSubmenuOpen: false,
40
+ isOpenAllowed: false
39
41
  });
42
+ _defineProperty(this, "dropdownMenuRef", /*#__PURE__*/React.createRef());
40
43
  _defineProperty(this, "handleSubMenuRef", ref => {
41
44
  const parent = closestElement(this.props.editorView.dom, '.fabric-editor-popup-scroll-parent');
42
45
  if (!(parent && ref)) {
@@ -58,7 +61,8 @@ export class ContextualMenu extends Component {
58
61
  intl: {
59
62
  formatMessage
60
63
  },
61
- editorView
64
+ editorView,
65
+ isCellMenuOpenByKeyboard
62
66
  } = this.props;
63
67
  const {
64
68
  isSubmenuOpen
@@ -68,9 +72,16 @@ export class ContextualMenu extends Component {
68
72
  isDragAndDropEnabled
69
73
  } = getPluginState(editorView.state);
70
74
  if (allowBackgroundColor) {
71
- var _node$attrs, _node$attrs2;
75
+ var _node$attrs, _node$attrs2, _node$attrs3;
72
76
  const node = isOpen && targetCellPosition ? state.doc.nodeAt(targetCellPosition) : null;
73
77
  const background = hexToEditorBackgroundPaletteColor((node === null || node === void 0 ? void 0 : (_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.background) || '#ffffff');
78
+ let selectedRowIndex;
79
+ let selectedColumnIndex;
80
+ if (getBooleanFF('platform.editor.a11y-table-context-menu_y4c9c')) {
81
+ const selectedRowAndColumnFromPalette = getSelectedRowAndColumnFromPalette(cellBackgroundColorPalette, background, colorPalletteColumns);
82
+ selectedRowIndex = selectedRowAndColumnFromPalette.selectedRowIndex;
83
+ selectedColumnIndex = selectedRowAndColumnFromPalette.selectedColumnIndex;
84
+ }
74
85
  return {
75
86
  content: isDragAndDropEnabled ? formatMessage(messages.backgroundColor) : formatMessage(messages.cellBackground),
76
87
  value: {
@@ -94,10 +105,27 @@ export class ContextualMenu extends Component {
94
105
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
95
106
  ,
96
107
  className: isDragAndDropEnabled ? ClassName.CONTEXTUAL_MENU_ICON_SMALL : ClassName.CONTEXTUAL_MENU_ICON
97
- }), isSubmenuOpen && jsx("div", {
108
+ }), getBooleanFF('platform.editor.a11y-table-context-menu_y4c9c') ? isSubmenuOpen && jsx("div", {
98
109
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
99
110
  className: ClassName.CONTEXTUAL_SUBMENU,
100
111
  ref: this.handleSubMenuRef
112
+ }, jsx(ArrowKeyNavigationProvider, {
113
+ type: ArrowKeyNavigationType.COLOR,
114
+ selectedRowIndex: selectedRowIndex || 0,
115
+ selectedColumnIndex: selectedColumnIndex || 0,
116
+ handleClose: () => {
117
+ this.setState({
118
+ isSubmenuOpen: false
119
+ });
120
+ if (this.dropdownMenuRef && this.dropdownMenuRef.current) {
121
+ const focusableItems = this.dropdownMenuRef.current.querySelectorAll('div[tabindex="-1"]:not([disabled])');
122
+ if (focusableItems && focusableItems.length) {
123
+ focusableItems[0].focus();
124
+ }
125
+ }
126
+ },
127
+ isPopupPositioned: true,
128
+ isOpenedByKeyboard: isCellMenuOpenByKeyboard
101
129
  }, jsx(ColorPalette, {
102
130
  cols: 7,
103
131
  onClick: this.setColor,
@@ -107,7 +135,22 @@ export class ContextualMenu extends Component {
107
135
  paletteColorTooltipMessages: backgroundPaletteTooltipMessages,
108
136
  hexToPaletteColor: hexToEditorBackgroundPaletteColor
109
137
  }
110
- })))
138
+ }))) : isSubmenuOpen &&
139
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
140
+ jsx("div", {
141
+ className: ClassName.CONTEXTUAL_SUBMENU,
142
+ ref: this.handleSubMenuRef
143
+ }, jsx(ColorPalette, {
144
+ cols: 7,
145
+ onClick: this.setColor,
146
+ selectedColor: (node === null || node === void 0 ? void 0 : (_node$attrs3 = node.attrs) === null || _node$attrs3 === void 0 ? void 0 : _node$attrs3.background) || '#ffffff',
147
+ paletteOptions: {
148
+ palette: cellBackgroundColorPalette,
149
+ paletteColorTooltipMessages: backgroundPaletteTooltipMessages,
150
+ hexToPaletteColor: hexToEditorBackgroundPaletteColor
151
+ }
152
+ }))),
153
+ 'aria-expanded': getBooleanFF('platform.editor.a11y-table-context-menu_y4c9c') ? isSubmenuOpen : undefined
111
154
  };
112
155
  }
113
156
  });
@@ -439,7 +482,8 @@ export class ContextualMenu extends Component {
439
482
  selectionRect,
440
483
  editorAnalyticsAPI,
441
484
  getEditorContainerWidth,
442
- getEditorFeatureFlags
485
+ getEditorFeatureFlags,
486
+ isCellMenuOpenByKeyboard
443
487
  } = this.props;
444
488
  // TargetCellPosition could be outdated: https://product-fabric.atlassian.net/browse/ED-8129
445
489
  const {
@@ -454,6 +498,21 @@ export class ContextualMenu extends Component {
454
498
  tableDuplicateCellColouring = false,
455
499
  tableWithFixedColumnWidthsOption = false
456
500
  } = getEditorFeatureFlags ? getEditorFeatureFlags() : {};
501
+ // context menu opened by keyboard and any item except 'background' activated
502
+ // or color has been chosen from color palette
503
+ if (getBooleanFF('platform.editor.a11y-table-context-menu_y4c9c') && isCellMenuOpenByKeyboard && (item.value.name !== 'background' || item.value.name === 'background' && this.state.isSubmenuOpen)) {
504
+ const {
505
+ tr
506
+ } = state;
507
+ tr.setMeta(tablePluginKey, {
508
+ type: 'SET_CELL_MENU_OPEN',
509
+ data: {
510
+ isCellMenuOpenByKeyboard: false
511
+ }
512
+ });
513
+ dispatch(tr);
514
+ editorView.dom.focus(); // otherwise cursor disappears from cell
515
+ }
457
516
  const shouldUseIncreasedScalingPercent = isTableScalingEnabled && tableWithFixedColumnWidthsOption && getBooleanFF('platform.editor.table.use-increased-scaling-percent');
458
517
  switch (item.value.name) {
459
518
  case 'sort_column_desc':
@@ -507,6 +566,19 @@ export class ContextualMenu extends Component {
507
566
  deleteRowsWithAnalytics(editorAnalyticsAPI)(INPUT_METHOD.CONTEXT_MENU, selectionRect, !!isHeaderRowRequired)(state, dispatch);
508
567
  this.toggleOpen();
509
568
  break;
569
+ case 'background':
570
+ {
571
+ // This is called twice.
572
+ // 1st time when user chooses the background color item.
573
+ // 2nd when color has been chosen from color palette.
574
+ // here we are handling the 1st call relying on the isSubmenuOpen state value
575
+ if (getBooleanFF('platform.editor.a11y-table-context-menu_y4c9c') && isCellMenuOpenByKeyboard && !this.state.isSubmenuOpen) {
576
+ this.setState({
577
+ isSubmenuOpen: true
578
+ });
579
+ }
580
+ break;
581
+ }
510
582
  }
511
583
  });
512
584
  _defineProperty(this, "toggleOpen", () => {
@@ -524,17 +596,51 @@ export class ContextualMenu extends Component {
524
596
  });
525
597
  }
526
598
  });
527
- _defineProperty(this, "handleOpenChange", () => {
599
+ _defineProperty(this, "handleOpenChange", payload => {
528
600
  const {
529
601
  editorView: {
530
602
  state,
531
- dispatch
532
- }
603
+ dispatch,
604
+ dom
605
+ },
606
+ isCellMenuOpenByKeyboard
533
607
  } = this.props;
534
- toggleContextualMenu()(state, dispatch);
535
- this.setState({
536
- isSubmenuOpen: false
537
- });
608
+ if (getBooleanFF('platform.editor.a11y-table-context-menu_y4c9c')) {
609
+ if (payload) {
610
+ const {
611
+ event
612
+ } = payload;
613
+ if (event && event instanceof KeyboardEvent) {
614
+ if (!this.state.isSubmenuOpen) {
615
+ if (arrowsList.has(event.key)) {
616
+ // preventing default behavior for avoiding cursor jump to next/previous table column
617
+ // when left/right arrow pressed.
618
+ event.preventDefault();
619
+ }
620
+ toggleContextualMenu()(state, dispatch);
621
+ this.setState({
622
+ isSubmenuOpen: false
623
+ });
624
+ setFocusToCellMenu(false)(state, dispatch);
625
+ dom.focus();
626
+ }
627
+ } else {
628
+ // mouse click outside
629
+ toggleContextualMenu()(state, dispatch);
630
+ this.setState({
631
+ isSubmenuOpen: false
632
+ });
633
+ if (isCellMenuOpenByKeyboard) {
634
+ setFocusToCellMenu(false)(state, dispatch);
635
+ }
636
+ }
637
+ }
638
+ } else {
639
+ toggleContextualMenu()(state, dispatch);
640
+ this.setState({
641
+ isSubmenuOpen: false
642
+ });
643
+ }
538
644
  });
539
645
  _defineProperty(this, "handleItemMouseEnter", ({
540
646
  item
@@ -601,21 +707,46 @@ export class ContextualMenu extends Component {
601
707
  this.toggleOpen();
602
708
  });
603
709
  }
710
+ componentDidMount() {
711
+ if (getBooleanFF('platform.editor.a11y-table-context-menu_y4c9c')) {
712
+ // ArrowKeyNavigationProvider in DropdownMenu expects that menu handle will stay focused
713
+ // until user pressed ArrowDown.
714
+ // Behavior above fails the A11Y requirement about first item in menu should be focused immediately.
715
+ // so here is triggering componentDidUpdate inside dropdown to set focus on first element
716
+ const {
717
+ isCellMenuOpenByKeyboard
718
+ } = this.props;
719
+ if (isCellMenuOpenByKeyboard) {
720
+ this.setState({
721
+ ...this.state,
722
+ isOpenAllowed: isCellMenuOpenByKeyboard
723
+ });
724
+ }
725
+ }
726
+ }
604
727
  render() {
605
728
  const {
606
729
  isOpen,
607
730
  mountPoint,
608
731
  offset,
609
732
  boundariesElement,
610
- editorView
733
+ editorView,
734
+ isCellMenuOpenByKeyboard
611
735
  } = this.props;
612
736
  const {
613
737
  isDragAndDropEnabled
614
738
  } = getPluginState(editorView.state);
615
739
  const items = isDragAndDropEnabled ? this.createNewContextMenuItems() : this.createOriginalContextMenuItems();
740
+ let isOpenAllowed = false;
741
+ if (getBooleanFF('platform.editor.a11y-table-context-menu_y4c9c')) {
742
+ isOpenAllowed = isCellMenuOpenByKeyboard ? this.state.isOpenAllowed : isOpen;
743
+ } else {
744
+ isOpenAllowed = isOpen;
745
+ }
616
746
  return jsx("div", {
617
747
  "data-testid": "table-cell-contextual-menu",
618
- onMouseLeave: this.closeSubmenu
748
+ onMouseLeave: this.closeSubmenu,
749
+ ref: this.dropdownMenuRef
619
750
  }, jsx(DropdownMenu, {
620
751
  mountTo: mountPoint
621
752
  //This needs be removed when the a11y is completely handled
@@ -623,21 +754,25 @@ export class ContextualMenu extends Component {
623
754
  ,
624
755
  arrowKeyNavigationProviderOptions: {
625
756
  type: ArrowKeyNavigationType.MENU,
626
- disableArrowKeyNavigation: true
757
+ disableArrowKeyNavigation: getBooleanFF('platform.editor.a11y-table-context-menu_y4c9c') && isCellMenuOpenByKeyboard && !this.state.isSubmenuOpen ? false : true
627
758
  },
628
759
  items: items,
629
- isOpen: isOpen,
760
+ isOpen: isOpenAllowed,
630
761
  onOpenChange: this.handleOpenChange,
631
762
  onItemActivated: this.onMenuItemActivated,
632
763
  onMouseEnter: this.handleItemMouseEnter,
633
764
  onMouseLeave: this.handleItemMouseLeave,
634
765
  fitHeight: 188,
635
766
  fitWidth: isDragAndDropEnabled ? contextualMenuDropdownWidthDnD : contextualMenuDropdownWidth,
767
+ shouldFocusFirstItem: getBooleanFF('platform.editor.a11y-table-context-menu_y4c9c') ? () => {
768
+ return Boolean(isCellMenuOpenByKeyboard);
769
+ } : undefined,
636
770
  boundariesElement: boundariesElement,
637
771
  offset: offset,
638
772
  section: isDragAndDropEnabled ? {
639
773
  hasSeparator: true
640
- } : undefined
774
+ } : undefined,
775
+ isAllowEnterDefaultBehavior: getBooleanFF('platform.editor.a11y-table-context-menu_y4c9c') ? this.state.isSubmenuOpen : false
641
776
  }));
642
777
  }
643
778
  }
@@ -18,7 +18,8 @@ const FloatingContextualMenu = ({
18
18
  pluginConfig,
19
19
  editorAnalyticsAPI,
20
20
  getEditorContainerWidth,
21
- getEditorFeatureFlags
21
+ getEditorFeatureFlags,
22
+ isCellMenuOpenByKeyboard
22
23
  }) => {
23
24
  // TargetCellPosition could be outdated: https://product-fabric.atlassian.net/browse/ED-8129
24
25
  const {
@@ -71,7 +72,8 @@ const FloatingContextualMenu = ({
71
72
  boundariesElement: boundariesElement,
72
73
  editorAnalyticsAPI: editorAnalyticsAPI,
73
74
  getEditorContainerWidth: getEditorContainerWidth,
74
- getEditorFeatureFlags: getEditorFeatureFlags
75
+ getEditorFeatureFlags: getEditorFeatureFlags,
76
+ isCellMenuOpenByKeyboard: isCellMenuOpenByKeyboard
75
77
  })));
76
78
  };
77
79
  FloatingContextualMenu.displayName = 'FloatingContextualMenu';
@@ -2,7 +2,7 @@ export { hoverColumns, hoverRows, hoverTable, hoverCell, hoverMergedCells, clear
2
2
  export { insertColumn, insertRow, createTable } from './insert';
3
3
  export { getNextLayout, toggleContextualMenu, toggleHeaderColumn, toggleHeaderRow, toggleNumberColumn, toggleTableLayout } from './toggle';
4
4
  export { clearMultipleCells } from './clear';
5
- export { autoSizeTable, convertFirstRowToHeader, deleteTable, hideInsertColumnOrRowButton, moveCursorBackward, selectColumn, selectColumns, selectRow, selectRows, setCellAttr, setEditorFocus, setMultipleCellAttrs, setTableRef, showInsertColumnButton, showInsertRowButton, transformSliceToAddTableHeaders, triggerUnlessTableHeader, addBoldInEmptyHeaderCells, addResizeHandleDecorations, updateWidthToWidest } from './misc';
5
+ export { autoSizeTable, convertFirstRowToHeader, deleteTable, hideInsertColumnOrRowButton, moveCursorBackward, selectColumn, selectColumns, selectRow, selectRows, setCellAttr, setEditorFocus, setMultipleCellAttrs, setTableRef, showInsertColumnButton, showInsertRowButton, transformSliceToAddTableHeaders, triggerUnlessTableHeader, addBoldInEmptyHeaderCells, addResizeHandleDecorations, updateWidthToWidest, setFocusToCellMenu } from './misc';
6
6
  export { sortByColumn } from './sort';
7
7
  export { goToNextCell } from './go-to-next-cell';
8
8
  export { removeDescendantNodes } from './referentiality';
@@ -619,4 +619,18 @@ export var setTableAlignmentWithTableContentWithPos = function setTableAlignment
619
619
  tr.setNodeMarkup(tableNodeWithPos.pos, undefined, nextTableAttrs).setMeta('scrollIntoView', false);
620
620
  return tr;
621
621
  };
622
+ };
623
+ export var setFocusToCellMenu = function setFocusToCellMenu() {
624
+ var isCellMenuOpenByKeyboard = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
625
+ var originalTr = arguments.length > 1 ? arguments[1] : undefined;
626
+ return createCommand(function () {
627
+ return {
628
+ type: 'SET_CELL_MENU_OPEN',
629
+ data: {
630
+ isCellMenuOpenByKeyboard: isCellMenuOpenByKeyboard
631
+ }
632
+ };
633
+ }, function (tr) {
634
+ return (originalTr || tr).setMeta('addToHistory', false);
635
+ });
622
636
  };
@@ -349,10 +349,11 @@ var tablesPlugin = function tablesPlugin(_ref) {
349
349
  isHeaderColumnEnabled = _ref18.isHeaderColumnEnabled,
350
350
  isHeaderRowEnabled = _ref18.isHeaderRowEnabled,
351
351
  isDragAndDropEnabled = _ref18.isDragAndDropEnabled,
352
- tableWrapperTarget = _ref18.tableWrapperTarget;
352
+ tableWrapperTarget = _ref18.tableWrapperTarget,
353
+ isCellMenuOpenByKeyboard = _ref18.isCellMenuOpenByKeyboard;
353
354
  var allowControls = pluginConfig.allowControls;
354
355
  var stickyHeader = stickyHeadersState ? findStickyHeaderForTable(stickyHeadersState, tablePos) : undefined;
355
- return /*#__PURE__*/React.createElement(React.Fragment, null, targetCellPosition && tableRef && !isResizing && options && options.allowContextualMenu && /*#__PURE__*/React.createElement(FloatingContextualButton, {
356
+ return /*#__PURE__*/React.createElement(React.Fragment, null, targetCellPosition && (tableRef || getBooleanFF('platform.editor.a11y-table-context-menu_y4c9c') && isCellMenuOpenByKeyboard) && !isResizing && options && options.allowContextualMenu && /*#__PURE__*/React.createElement(FloatingContextualButton, {
356
357
  isNumberColumnEnabled: tableNode && tableNode.attrs.isNumberColumnEnabled,
357
358
  editorView: editorView,
358
359
  tableNode: tableNode,
@@ -362,7 +363,8 @@ var tablesPlugin = function tablesPlugin(_ref) {
362
363
  dispatchAnalyticsEvent: dispatchAnalyticsEvent,
363
364
  isContextualMenuOpen: isContextualMenuOpen,
364
365
  stickyHeader: stickyHeader,
365
- tableWrapper: tableWrapperTarget
366
+ tableWrapper: tableWrapperTarget,
367
+ isCellMenuOpenByKeyboard: isCellMenuOpenByKeyboard
366
368
  }), allowControls && /*#__PURE__*/React.createElement(FloatingInsertButton, {
367
369
  tableNode: tableNode,
368
370
  tableRef: tableRef,
@@ -390,7 +392,8 @@ var tablesPlugin = function tablesPlugin(_ref) {
390
392
  pluginConfig: pluginConfig,
391
393
  editorAnalyticsAPI: editorAnalyticsAPI,
392
394
  getEditorContainerWidth: defaultGetEditorContainerWidth,
393
- getEditorFeatureFlags: (options === null || options === void 0 ? void 0 : options.getEditorFeatureFlags) || defaultGetEditorFeatureFlags
395
+ getEditorFeatureFlags: (options === null || options === void 0 ? void 0 : options.getEditorFeatureFlags) || defaultGetEditorFeatureFlags,
396
+ isCellMenuOpenByKeyboard: isCellMenuOpenByKeyboard
394
397
  }), isDragAndDropEnabled && /*#__PURE__*/React.createElement(FloatingDragMenu, {
395
398
  editorView: editorView,
396
399
  mountPoint: popupsMountPoint,
@@ -1,9 +1,9 @@
1
1
  import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
2
- import { addColumnAfter, addColumnAfterVO, addColumnBefore, addColumnBeforeVO, addRowAfter, addRowAfterVO, addRowBefore, addRowBeforeVO, backspace, bindKeymapWithCommand, decreaseMediaSize, deleteColumn, deleteRow, escape, increaseMediaSize, moveColumnLeft, moveColumnRight, moveLeft, moveRight, moveRowDown, moveRowUp, nextCell, previousCell, startColumnResizing, toggleTable } from '@atlaskit/editor-common/keymaps';
2
+ import { addColumnAfter, addColumnAfterVO, addColumnBefore, addColumnBeforeVO, addRowAfter, addRowAfterVO, addRowBefore, addRowBeforeVO, backspace, bindKeymapWithCommand, decreaseMediaSize, deleteColumn, deleteRow, escape, focusToContextMenuTrigger, increaseMediaSize, moveColumnLeft, moveColumnRight, moveLeft, moveRight, moveRowDown, moveRowUp, nextCell, previousCell, startColumnResizing, toggleTable } from '@atlaskit/editor-common/keymaps';
3
3
  import { chainCommands } from '@atlaskit/editor-prosemirror/commands';
4
4
  import { keymap } from '@atlaskit/editor-prosemirror/keymap';
5
5
  import { getBooleanFF } from '@atlaskit/platform-feature-flags';
6
- import { goToNextCell, moveCursorBackward } from '../commands';
6
+ import { goToNextCell, moveCursorBackward, setFocusToCellMenu } from '../commands';
7
7
  import { addRowAroundSelection, changeColumnWidthByStepWithAnalytics, deleteSelectedRowsOrColumnsWithAnalyticsViaShortcut, deleteTableIfSelectedWithAnalytics, emptyMultipleCellsWithAnalytics } from '../commands-with-analytics';
8
8
  import { activateNextResizeArea, initiateKeyboardColumnResizing, stopKeyboardColumnResizing } from '../commands/column-resize';
9
9
  import { addColumnAfter as addColumnAfterCommand, addColumnBefore as addColumnBeforeCommand, createTable } from '../commands/insert';
@@ -77,6 +77,9 @@ export function keymapPlugin(getEditorContainerWidth, editorAnalyticsAPI, dragAn
77
77
  getIntl: getIntl
78
78
  }), list);
79
79
  }
80
+ if (getBooleanFF('platform.editor.a11y-table-context-menu_y4c9c')) {
81
+ bindKeymapWithCommand(focusToContextMenuTrigger.common, setFocusToCellMenu(), list);
82
+ }
80
83
  return keymap(list);
81
84
  }
82
85
  export default keymapPlugin;
@@ -95,6 +95,7 @@ export default (function (pluginState, action) {
95
95
  case 'HOVER_CELL':
96
96
  case 'SHOW_RESIZE_HANDLE_LINE':
97
97
  case 'SET_EDITOR_FOCUS':
98
+ case 'SET_CELL_MENU_OPEN':
98
99
  return _objectSpread(_objectSpread({}, pluginState), action.data);
99
100
  default:
100
101
  return pluginState;
@@ -1,5 +1,5 @@
1
1
  /** @jsx jsx */
2
- import React from 'react';
2
+ import React, { useEffect } from 'react';
3
3
 
4
4
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
5
5
  import { jsx } from '@emotion/react';
@@ -12,6 +12,7 @@ import { ToolbarButton } from '@atlaskit/editor-common/ui-menu';
12
12
  import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
13
13
  import { akEditorSmallZIndex } from '@atlaskit/editor-shared-styles';
14
14
  import ExpandIcon from '@atlaskit/icon/glyph/chevron-down';
15
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
15
16
  import { toggleContextualMenu } from '../../commands';
16
17
  import { TableCssClassName as ClassName } from '../../types';
17
18
  import FixedButton from './FixedButton';
@@ -25,6 +26,7 @@ var FloatingContextualButtonInner = /*#__PURE__*/React.memo(function (props) {
25
26
  stickyHeader = props.stickyHeader,
26
27
  tableWrapper = props.tableWrapper,
27
28
  targetCellPosition = props.targetCellPosition,
29
+ isCellMenuOpenByKeyboard = props.isCellMenuOpenByKeyboard,
28
30
  formatMessage = props.intl.formatMessage; // : Props & WrappedComponentProps
29
31
 
30
32
  var handleClick = function handleClick() {
@@ -42,6 +44,16 @@ var FloatingContextualButtonInner = /*#__PURE__*/React.memo(function (props) {
42
44
  var domAtPos = editorView.domAtPos.bind(editorView);
43
45
  var targetCellRef;
44
46
  targetCellRef = findDomRefAtPos(targetCellPosition, domAtPos);
47
+ useEffect(function () {
48
+ if (getBooleanFF('platform.editor.a11y-table-context-menu_y4c9c')) {
49
+ if (isCellMenuOpenByKeyboard && !isContextualMenuOpen) {
50
+ var state = editorView.state,
51
+ dispatch = editorView.dispatch;
52
+ // open the menu when the keyboard shortcut is pressed
53
+ toggleContextualMenu()(state, dispatch);
54
+ }
55
+ }
56
+ }, [isCellMenuOpenByKeyboard, isContextualMenuOpen, editorView]);
45
57
  if (!targetCellRef || !(targetCellRef instanceof HTMLElement)) {
46
58
  return null;
47
59
  }
@@ -62,7 +74,8 @@ var FloatingContextualButtonInner = /*#__PURE__*/React.memo(function (props) {
62
74
  iconBefore: jsx(ExpandIcon, {
63
75
  label: ""
64
76
  }),
65
- "aria-label": labelCellOptions
77
+ "aria-label": labelCellOptions,
78
+ "aria-expanded": getBooleanFF('platform.editor.a11y-table-context-menu_y4c9c') ? isContextualMenuOpen : undefined
66
79
  }));
67
80
  var parentSticky = targetCellRef.parentElement && targetCellRef.parentElement.className.indexOf('sticky') > -1;
68
81
  if (stickyHeader && parentSticky && tableWrapper) {