@atlaskit/editor-common 70.2.1 → 71.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/dist/cjs/analytics/types/enums.js +10 -1
  3. package/dist/cjs/keymaps/index.js +5 -8
  4. package/dist/cjs/messages/insert-block.js +12 -7
  5. package/dist/cjs/panel.js +6 -0
  6. package/dist/cjs/styles/shared/code-block.js +5 -5
  7. package/dist/cjs/styles/shared/panel.js +54 -17
  8. package/dist/cjs/styles/shared/table.js +12 -7
  9. package/dist/cjs/styles/shared/text-color.js +1 -1
  10. package/dist/cjs/ui/DropList/index.js +1 -1
  11. package/dist/cjs/ui-color/ColorPalette/Color/index.js +6 -2
  12. package/dist/cjs/ui-color/ColorPalette/index.js +21 -11
  13. package/dist/cjs/ui-menu/Dropdown/index.js +16 -2
  14. package/dist/cjs/ui-menu/DropdownMenu/index.js +27 -8
  15. package/dist/cjs/ui-menu/MenuArrowKeyNavigationProvider/index.js +162 -0
  16. package/dist/cjs/ui-react/with-react-editor-view-outer-listeners.js +22 -13
  17. package/dist/cjs/utils/index.js +6 -0
  18. package/dist/cjs/utils/performance/measure-render.js +44 -23
  19. package/dist/cjs/version.json +1 -1
  20. package/dist/es2019/analytics/types/enums.js +10 -1
  21. package/dist/es2019/keymaps/index.js +4 -6
  22. package/dist/es2019/messages/insert-block.js +12 -7
  23. package/dist/es2019/panel.js +1 -1
  24. package/dist/es2019/styles/shared/code-block.js +39 -25
  25. package/dist/es2019/styles/shared/panel.js +48 -18
  26. package/dist/es2019/styles/shared/table.js +24 -13
  27. package/dist/es2019/styles/shared/text-color.js +1 -1
  28. package/dist/es2019/ui/DropList/index.js +1 -1
  29. package/dist/es2019/ui-color/ColorPalette/Color/index.js +6 -3
  30. package/dist/es2019/ui-color/ColorPalette/index.js +19 -11
  31. package/dist/es2019/ui-menu/Dropdown/index.js +13 -2
  32. package/dist/es2019/ui-menu/DropdownMenu/index.js +41 -6
  33. package/dist/es2019/ui-menu/MenuArrowKeyNavigationProvider/index.js +146 -0
  34. package/dist/es2019/ui-react/with-react-editor-view-outer-listeners.js +20 -13
  35. package/dist/es2019/utils/index.js +1 -1
  36. package/dist/es2019/utils/performance/measure-render.js +43 -23
  37. package/dist/es2019/version.json +1 -1
  38. package/dist/esm/analytics/types/enums.js +10 -1
  39. package/dist/esm/keymaps/index.js +3 -6
  40. package/dist/esm/messages/insert-block.js +12 -7
  41. package/dist/esm/panel.js +1 -1
  42. package/dist/esm/styles/shared/code-block.js +5 -5
  43. package/dist/esm/styles/shared/panel.js +49 -18
  44. package/dist/esm/styles/shared/table.js +12 -9
  45. package/dist/esm/styles/shared/text-color.js +1 -1
  46. package/dist/esm/ui/DropList/index.js +1 -1
  47. package/dist/esm/ui-color/ColorPalette/Color/index.js +5 -2
  48. package/dist/esm/ui-color/ColorPalette/index.js +20 -11
  49. package/dist/esm/ui-menu/Dropdown/index.js +15 -2
  50. package/dist/esm/ui-menu/DropdownMenu/index.js +28 -9
  51. package/dist/esm/ui-menu/MenuArrowKeyNavigationProvider/index.js +147 -0
  52. package/dist/esm/ui-react/with-react-editor-view-outer-listeners.js +22 -13
  53. package/dist/esm/utils/index.js +1 -1
  54. package/dist/esm/utils/performance/measure-render.js +42 -23
  55. package/dist/esm/version.json +1 -1
  56. package/dist/types/analytics/index.d.ts +1 -1
  57. package/dist/types/analytics/types/enums.d.ts +18 -1
  58. package/dist/types/analytics/types/general-events.d.ts +2 -1
  59. package/dist/types/analytics/types/index.d.ts +1 -0
  60. package/dist/types/analytics/types/referentiality-events.d.ts +47 -4
  61. package/dist/types/keymaps/index.d.ts +0 -1
  62. package/dist/types/messages/insert-block.d.ts +7 -2
  63. package/dist/types/panel.d.ts +1 -1
  64. package/dist/types/styles/shared/code-block.d.ts +1 -0
  65. package/dist/types/styles/shared/panel.d.ts +1 -0
  66. package/dist/types/types/feature-flags.d.ts +27 -6
  67. package/dist/types/types/floating-toolbar.d.ts +4 -0
  68. package/dist/types/ui-color/ColorPalette/Color/index.d.ts +5 -0
  69. package/dist/types/ui-color/ColorPalette/index.d.ts +8 -0
  70. package/dist/types/ui-menu/Dropdown/index.d.ts +3 -0
  71. package/dist/types/ui-menu/DropdownMenu/index.d.ts +1 -0
  72. package/dist/types/ui-menu/DropdownMenu/types.d.ts +7 -0
  73. package/dist/types/ui-menu/MenuArrowKeyNavigationProvider/index.d.ts +15 -0
  74. package/dist/types/ui-react/with-react-editor-view-outer-listeners.d.ts +2 -0
  75. package/dist/types/utils/index.d.ts +1 -1
  76. package/dist/types/utils/performance/measure-render.d.ts +12 -0
  77. package/package.json +8 -7
  78. package/report.api.md +12 -5
@@ -4,15 +4,15 @@ var _templateObject;
4
4
 
5
5
  /* eslint-disable @atlaskit/design-system/ensure-design-token-usage */
6
6
  // TODO: https://product-fabric.atlassian.net/browse/DSP-4118
7
- // TODO: https://product-fabric.atlassian.net/browse/DSP-4153
8
7
  import { css } from '@emotion/react';
9
8
  import { tableCellContentDomSelector, tableCellSelector, tableHeaderSelector, tablePrefixSelector } from '@atlaskit/adf-schema';
10
- import { akEditorBreakoutPadding, akEditorFullWidthLayoutWidth, akEditorTableBorder, akEditorTableBorderDark, akEditorTableNumberColumnWidth, akEditorTableToolbar, akEditorTableToolbarDark, akEditorWideLayoutWidth, getTableCellBackgroundDarkModeColors, overflowShadow } from '@atlaskit/editor-shared-styles';
9
+ import { akEditorBreakoutPadding, akEditorFullWidthLayoutWidth, akEditorSelectedNodeClassName, akEditorTableBorder, akEditorTableBorderDark, akEditorTableNumberColumnWidth, akEditorTableToolbar, akEditorTableToolbarDark, akEditorWideLayoutWidth, getTableCellBackgroundDarkModeColors, overflowShadow } from '@atlaskit/editor-shared-styles';
11
10
  import { DN20 } from '@atlaskit/theme/colors';
12
11
  import { themed } from '@atlaskit/theme/components';
13
12
  import { gridSize } from '@atlaskit/theme/constants';
14
13
  import { token } from '@atlaskit/tokens';
15
14
  import browser from '../../utils/browser';
15
+ import { CodeBlockSharedCssClassName } from './code-block';
16
16
  export var tableMarginTop = 24;
17
17
  export var tableMarginBottom = 16;
18
18
  export var tableMarginSides = 8;
@@ -38,7 +38,7 @@ export var TableSharedCssClassName = {
38
38
  };
39
39
 
40
40
  var tableSharedStyle = function tableSharedStyle(props) {
41
- return css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n .", " {\n position: relative;\n margin: 0 auto ", "px;\n box-sizing: border-box;\n\n /**\n * Fix block top alignment inside table cells.\n */\n .decisionItemView-content-wrap:first-of-type > div {\n margin-top: 0;\n }\n }\n .", "[data-number-column='true'] {\n padding-left: ", "px;\n clear: both;\n }\n .", " > table {\n margin: ", "px 0 0 0;\n }\n\n .", " > table,\n .", " > table {\n margin: ", "px ", "px 0 0;\n }\n\n /* avoid applying styles to nested tables (possible via extensions) */\n .", " > table,\n .", " > table,\n .", " > table {\n border-collapse: collapse;\n border: ", "px solid\n ", ";\n table-layout: fixed;\n font-size: 1em;\n width: 100%;\n\n &[data-autosize='true'] {\n table-layout: auto;\n }\n\n & {\n * {\n box-sizing: border-box;\n }\n hr {\n box-sizing: content-box;\n }\n\n tbody {\n border-bottom: none;\n }\n th td {\n background-color: ", ";\n }\n th,\n td {\n min-width: ", "px;\n font-weight: normal;\n vertical-align: top;\n border: 1px solid\n ", ";\n border-right-width: 0;\n border-bottom-width: 0;\n padding: ", "px;\n /* https://stackoverflow.com/questions/7517127/borders-not-shown-in-firefox-with-border-collapse-on-table-position-relative-o */\n ", "\n\n ", ";\n\n > :first-child:not(style),\n > style:first-child + * {\n margin-top: 0;\n }\n\n > .ProseMirror-gapcursor:first-child + *,\n > style:first-child + .ProseMirror-gapcursor + * {\n margin-top: 0;\n }\n\n > .ProseMirror-gapcursor:first-child + span + *,\n > style:first-child + .ProseMirror-gapcursor + span + * {\n margin-top: 0;\n }\n\n th p:not(:first-of-type),\n td p:not(:first-of-type) {\n margin-top: 12px;\n }\n }\n th {\n background-color: ", ";\n text-align: left;\n\n /* only apply this styling to codeblocks in default background headercells */\n /* TODO this needs to be overhauled as it relies on unsafe selectors */\n &:not([style]) {\n .code-block {\n background-image: ", ";\n background-attachment: local, scroll, scroll;\n background-position: 100% 0, 100% 0, 0 0;\n background-color: ", ";\n\n .line-number-gutter {\n background-color: ", ";\n }\n\n /* this is only relevant to the element taken care of by renderer */\n > [data-ds--code--code-block] {\n background-image: ", "!important;\n\n background-color: ", "!important;\n\n // selector lives inside @atlaskit/code\n --ds--code--line-number-bg-color: ", ";\n }\n }\n }\n }\n }\n }\n"])), TableSharedCssClassName.TABLE_CONTAINER, tableMarginBottom, TableSharedCssClassName.TABLE_CONTAINER, akEditorTableNumberColumnWidth - 1, TableSharedCssClassName.TABLE_NODE_WRAPPER, tableMarginTop, TableSharedCssClassName.TABLE_CONTAINER, TableSharedCssClassName.TABLE_STICKY_WRAPPER, tableMarginTop, tableMarginSides, TableSharedCssClassName.TABLE_CONTAINER, TableSharedCssClassName.TABLE_NODE_WRAPPER, TableSharedCssClassName.TABLE_STICKY_WRAPPER, tableCellBorderWidth, themed({
41
+ return css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n .", " {\n position: relative;\n margin: 0 auto ", "px;\n box-sizing: border-box;\n\n /**\n * Fix block top alignment inside table cells.\n */\n .decisionItemView-content-wrap:first-of-type > div {\n margin-top: 0;\n }\n }\n .", "[data-number-column='true'] {\n padding-left: ", "px;\n clear: both;\n }\n .", " > table {\n margin: ", "px 0 0 0;\n }\n\n .", " > table,\n .", " > table {\n margin: ", "px ", "px 0 0;\n }\n\n /* avoid applying styles to nested tables (possible via extensions) */\n .", " > table,\n .", " > table,\n .", " > table {\n border-collapse: collapse;\n border: ", "px solid\n ", ";\n table-layout: fixed;\n font-size: 1em;\n width: 100%;\n\n &[data-autosize='true'] {\n table-layout: auto;\n }\n\n & {\n * {\n box-sizing: border-box;\n }\n hr {\n box-sizing: content-box;\n }\n\n tbody {\n border-bottom: none;\n }\n th td {\n background-color: ", ";\n }\n th,\n td {\n min-width: ", "px;\n font-weight: normal;\n vertical-align: top;\n border: 1px solid\n ", ";\n border-right-width: 0;\n border-bottom-width: 0;\n padding: ", "px;\n /* https://stackoverflow.com/questions/7517127/borders-not-shown-in-firefox-with-border-collapse-on-table-position-relative-o */\n ", "\n\n ", ";\n\n > :first-child:not(style),\n > style:first-child + * {\n margin-top: 0;\n }\n\n > .ProseMirror-gapcursor:first-child + *,\n > style:first-child + .ProseMirror-gapcursor + * {\n margin-top: 0;\n }\n\n > .ProseMirror-gapcursor:first-child + span + *,\n > style:first-child + .ProseMirror-gapcursor + span + * {\n margin-top: 0;\n }\n\n th p:not(:first-of-type),\n td p:not(:first-of-type) {\n margin-top: 12px;\n }\n }\n th {\n background-color: ", ";\n text-align: left;\n\n /* only apply this styling to codeblocks in default background headercells */\n /* TODO this needs to be overhauled as it relies on unsafe selectors */\n &:not([style]):not(.danger) {\n .", ":not(.danger) {\n background-color: ", ";\n\n :not(.", ") {\n box-shadow: 0px 0px 0px 1px\n ", ";\n }\n\n .", " {\n background-image: ", ";\n\n background-color: ", ";\n }\n\n .", " {\n background-color: ", ";\n }\n\n /* this is only relevant to the element taken care of by renderer */\n > [data-ds--code--code-block] {\n background-image: ", "!important;\n\n background-color: ", "!important;\n\n // selector lives inside @atlaskit/code\n --ds--code--line-number-bg-color: ", ";\n }\n }\n }\n }\n }\n }\n"])), TableSharedCssClassName.TABLE_CONTAINER, tableMarginBottom, TableSharedCssClassName.TABLE_CONTAINER, akEditorTableNumberColumnWidth - 1, TableSharedCssClassName.TABLE_NODE_WRAPPER, tableMarginTop, TableSharedCssClassName.TABLE_CONTAINER, TableSharedCssClassName.TABLE_STICKY_WRAPPER, tableMarginTop, tableMarginSides, TableSharedCssClassName.TABLE_CONTAINER, TableSharedCssClassName.TABLE_NODE_WRAPPER, TableSharedCssClassName.TABLE_STICKY_WRAPPER, tableCellBorderWidth, themed({
42
42
  light: token('color.border', akEditorTableBorder),
43
43
  dark: token('color.border', akEditorTableBorderDark)
44
44
  })(props), token('color.background.neutral.subtle', 'white'), tableCellMinWidth, themed({
@@ -49,22 +49,25 @@ var tableSharedStyle = function tableSharedStyle(props) {
49
49
  })(props), themed({
50
50
  light: token('color.background.neutral', akEditorTableToolbar),
51
51
  dark: token('color.background.neutral', akEditorTableToolbarDark)
52
- })(props), overflowShadow({
52
+ })(props), CodeBlockSharedCssClassName.CODEBLOCK_CONTAINER, themed({
53
+ light: token('elevation.surface.raised', 'rgb(235, 237, 240)'),
54
+ dark: token('elevation.surface.raised', 'rgb(36, 47, 66)')
55
+ })(props), akEditorSelectedNodeClassName, token('color.border', 'transparent'), CodeBlockSharedCssClassName.CODEBLOCK_CONTENT_WRAPPER, overflowShadow({
53
56
  background: themed({
54
- light: 'rgb(235, 237, 240)',
55
- dark: 'rgb(36, 47, 66)'
57
+ light: token('color.background.neutral', 'rgb(235, 237, 240)'),
58
+ dark: token('color.background.neutral', 'rgb(36, 47, 66)')
56
59
  })(props),
57
60
  width: "".concat(gridSize(), "px")
58
61
  }), themed({
59
62
  light: token('color.background.neutral', 'rgb(235, 237, 240)'),
60
63
  dark: token('color.background.neutral', 'rgb(36, 47, 66)')
61
- })(props), themed({
64
+ })(props), CodeBlockSharedCssClassName.CODEBLOCK_LINE_NUMBER_GUTTER, themed({
62
65
  light: token('color.background.neutral', 'rgb(226, 229, 233)'),
63
66
  dark: token('color.background.neutral', DN20)
64
67
  })(props), overflowShadow({
65
68
  background: themed({
66
- light: 'rgb(235, 237, 240)',
67
- dark: 'rgb(36, 47, 66)'
69
+ light: token('color.background.neutral', 'rgb(235, 237, 240)'),
70
+ dark: token('color.background.neutral', 'rgb(36, 47, 66)')
68
71
  })(props),
69
72
  width: "".concat(gridSize(), "px")
70
73
  }), themed({
@@ -3,4 +3,4 @@ import _taggedTemplateLiteral from "@babel/runtime/helpers/taggedTemplateLiteral
3
3
  var _templateObject;
4
4
 
5
5
  import { css } from '@emotion/react';
6
- export var textColorStyles = css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n .fabric-text-color-mark {\n color: var(--custom-text-color, inherit);\n }\n\n a .fabric-text-color-mark {\n color: unset;\n }\n"])));
6
+ export var textColorStyles = css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n .fabric-text-color-mark {\n color: var(--custom-palette-color, inherit);\n }\n\n a .fabric-text-color-mark {\n color: unset;\n }\n"])));
@@ -23,7 +23,7 @@ import { borderRadius, gridSize } from '@atlaskit/theme/constants';
23
23
  import { token } from '@atlaskit/tokens';
24
24
  import Layer from '../Layer';
25
25
  var packageName = "@atlaskit/editor-common";
26
- var packageVersion = "70.2.1";
26
+ var packageVersion = "71.0.0";
27
27
  var halfFocusRing = 1;
28
28
  var dropOffset = "0, ".concat(gridSize(), "px");
29
29
 
@@ -13,6 +13,7 @@ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Re
13
13
  /** @jsx jsx */
14
14
  import React, { PureComponent } from 'react';
15
15
  import { jsx } from '@emotion/react';
16
+ import { hexToEditorTextPaletteColor } from '@atlaskit/editor-palette';
16
17
  import EditorDoneIcon from '@atlaskit/icon/glyph/editor/done';
17
18
  import { N0 } from '@atlaskit/theme/colors';
18
19
  import Tooltip from '@atlaskit/tooltip';
@@ -61,7 +62,9 @@ var Color = /*#__PURE__*/function (_PureComponent) {
61
62
  isSelected = _this$props2.isSelected,
62
63
  borderColor = _this$props2.borderColor,
63
64
  _this$props2$checkMar = _this$props2.checkMarkColor,
64
- checkMarkColor = _this$props2$checkMar === void 0 ? N0 : _this$props2$checkMar;
65
+ checkMarkColor = _this$props2$checkMar === void 0 ? N0 : _this$props2$checkMar,
66
+ useDesignTokens = _this$props2.useDesignTokens;
67
+ var colorStyle = useDesignTokens ? hexToEditorTextPaletteColor(value) : value;
65
68
  return jsx(Tooltip, {
66
69
  content: label
67
70
  }, jsx("span", {
@@ -76,7 +79,7 @@ var Color = /*#__PURE__*/function (_PureComponent) {
76
79
  tabIndex: tabIndex,
77
80
  className: "".concat(isSelected ? 'selected' : ''),
78
81
  style: {
79
- backgroundColor: value || 'transparent',
82
+ backgroundColor: colorStyle || 'transparent',
80
83
  border: "1px solid ".concat(borderColor)
81
84
  },
82
85
  autoFocus: autoFocus
@@ -4,6 +4,7 @@ import { jsx } from '@emotion/react';
4
4
  import chromatism from 'chromatism';
5
5
  import { injectIntl } from 'react-intl-next';
6
6
  import { N0, N500 } from '@atlaskit/theme/colors';
7
+ import { token } from '@atlaskit/tokens';
7
8
  import Color from './Color';
8
9
  import { colorPaletteWrapper } from './styles';
9
10
 
@@ -14,10 +15,21 @@ import { colorPaletteWrapper } from './styles';
14
15
  * @param color color string, suppports HEX, RGB, RGBA etc.
15
16
  * @return Highest contrast color in pool
16
17
  */
17
- function getContrastColor(color, pool) {
18
- return pool.sort(function (a, b) {
18
+ function getCheckMarkColor(color, textPalette) {
19
+ // eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage
20
+ var contrastColor = [N0, N500].sort(function (a, b) {
19
21
  return chromatism.difference(b, color) - chromatism.difference(a, color);
20
22
  })[0];
23
+
24
+ if (!textPalette) {
25
+ return contrastColor;
26
+ } // Use of these token comes from guidance from designers in the Design System team
27
+ // they are only intended for use with text colors (and there are different tokens
28
+ // planned to be used when this extended to be used with other palettes).
29
+ // eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage
30
+
31
+
32
+ return contrastColor === N0 ? token('color.icon.inverse', N0) : token('color.icon', N500);
21
33
  }
22
34
 
23
35
  var ColorPalette = function ColorPalette(props) {
@@ -27,7 +39,9 @@ var ColorPalette = function ColorPalette(props) {
27
39
  onClick = props.onClick,
28
40
  selectedColor = props.selectedColor,
29
41
  className = props.className,
30
- formatMessage = props.intl.formatMessage;
42
+ formatMessage = props.intl.formatMessage,
43
+ _props$textPalette = props.textPalette,
44
+ textPalette = _props$textPalette === void 0 ? false : _props$textPalette;
31
45
  var colorsPerRow = React.useMemo(function () {
32
46
  return palette.reduce(function (resultArray, item, index) {
33
47
  var chunkIndex = Math.floor(index / cols);
@@ -54,14 +68,9 @@ var ColorPalette = function ColorPalette(props) {
54
68
  borderColor: border,
55
69
  label: message ? formatMessage(message) : label,
56
70
  onClick: onClick,
57
- isSelected: value === selectedColor
58
- /** this is not new usage - old code extracted from editor-core */
59
-
60
- /* eslint-disable @atlaskit/design-system/ensure-design-token-usage */
61
- ,
62
- checkMarkColor: getContrastColor(value, [N0, N500])
63
- /* eslint-enable @atlaskit/design-system/ensure-design-token-usage */
64
-
71
+ isSelected: value === selectedColor,
72
+ checkMarkColor: getCheckMarkColor(value, textPalette),
73
+ useDesignTokens: textPalette === true
65
74
  });
66
75
  }));
67
76
  }));
@@ -14,6 +14,7 @@ import React, { PureComponent } from 'react';
14
14
  import { withReactEditorViewOuterListeners } from '../../ui-react';
15
15
  import DropdownList from '../../ui/DropList';
16
16
  import Popup from '../../ui/Popup';
17
+ import { MenuArrowKeyNavigationProvider } from '../MenuArrowKeyNavigationProvider';
17
18
 
18
19
  /**
19
20
  * Wrapper around @atlaskit/droplist which uses Popup and Portal to render
@@ -65,7 +66,9 @@ export var Dropdown = /*#__PURE__*/function (_PureComponent) {
65
66
  onOpenChange = _this$props.onOpenChange,
66
67
  fitHeight = _this$props.fitHeight,
67
68
  fitWidth = _this$props.fitWidth,
68
- zIndex = _this$props.zIndex;
69
+ zIndex = _this$props.zIndex,
70
+ disableArrowKeyNavigation = _this$props.disableArrowKeyNavigation,
71
+ keyDownHandlerContext = _this$props.keyDownHandlerContext;
69
72
  return /*#__PURE__*/React.createElement(Popup, {
70
73
  target: target,
71
74
  mountTo: mountTo,
@@ -75,6 +78,16 @@ export var Dropdown = /*#__PURE__*/function (_PureComponent) {
75
78
  fitHeight: fitHeight,
76
79
  fitWidth: fitWidth,
77
80
  zIndex: zIndex
81
+ }, /*#__PURE__*/React.createElement(MenuArrowKeyNavigationProvider, {
82
+ disableArrowKeyNavigation: disableArrowKeyNavigation,
83
+ keyDownHandlerContext: keyDownHandlerContext,
84
+ closeonTab: true,
85
+ handleClose: function handleClose(event) {
86
+ return onOpenChange && onOpenChange({
87
+ isOpen: false,
88
+ event: event
89
+ });
90
+ }
78
91
  }, /*#__PURE__*/React.createElement("div", {
79
92
  style: {
80
93
  height: 0,
@@ -85,7 +98,7 @@ export var Dropdown = /*#__PURE__*/function (_PureComponent) {
85
98
  onOpenChange: onOpenChange,
86
99
  position: popupPlacement.join(' '),
87
100
  shouldFitContainer: true
88
- }, children)));
101
+ }, children))));
89
102
  }
90
103
  }, {
91
104
  key: "render",
@@ -10,7 +10,7 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
10
10
  import _taggedTemplateLiteral from "@babel/runtime/helpers/taggedTemplateLiteral";
11
11
  var _excluded = ["children"];
12
12
 
13
- var _templateObject, _templateObject2, _templateObject3;
13
+ var _templateObject, _templateObject2, _templateObject3, _templateObject4;
14
14
 
15
15
  function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
16
16
 
@@ -21,14 +21,16 @@ import React, { PureComponent } from 'react';
21
21
  import { css, jsx } from '@emotion/react';
22
22
  import { akEditorFloatingPanelZIndex } from '@atlaskit/editor-shared-styles';
23
23
  import { CustomItem, MenuGroup } from '@atlaskit/menu';
24
- import { DN600, DN80, N70, N900 } from '@atlaskit/theme/colors';
24
+ import { B100, DN600, DN80, N70, N900 } from '@atlaskit/theme/colors';
25
25
  import { themed } from '@atlaskit/theme/components';
26
26
  import { token } from '@atlaskit/tokens';
27
27
  import Tooltip from '@atlaskit/tooltip';
28
28
  import { withReactEditorViewOuterListeners } from '../../ui-react';
29
29
  import DropList from '../../ui/DropList';
30
30
  import Popup from '../../ui/Popup';
31
+ import { MenuArrowKeyNavigationProvider } from '../MenuArrowKeyNavigationProvider';
31
32
  var wrapper = css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n /* tooltip in ToolbarButton is display:block */\n & > div > div {\n display: flex;\n }\n"])));
33
+ var focusedMenuItemStyle = css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n box-shadow: inset 0px 0px 0px 2px ", ";\n outline: none;\n"])), token('color.border.focused', B100));
32
34
 
33
35
  var buttonStyles = function buttonStyles(isActive) {
34
36
  return function (theme) {
@@ -36,9 +38,9 @@ var buttonStyles = function buttonStyles(isActive) {
36
38
  /**
37
39
  * Hack for item to imitate old dropdown-menu selected styles
38
40
  */
39
- return css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n > span,\n > span:hover,\n > span:active {\n background: ", ";\n color: ", ";\n }\n "])), token('color.background.selected', '#6c798f'), token('color.text', '#fff'));
41
+ return css(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n > span,\n > span:hover,\n > span:active {\n background: ", ";\n color: ", ";\n }\n :focus > span[aria-disabled='false'] {\n ", ";\n }\n :focus-visible,\n :focus-visible > span[aria-disabled='false'] {\n outline: none;\n }\n "])), token('color.background.selected', '#6c798f'), token('color.text', '#fff'), focusedMenuItemStyle);
40
42
  } else {
41
- return css(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n > span:hover[aria-disabled='false'] {\n color: ", ";\n background-color: ", ";\n }\n > span:active[aria-disabled='false'] {\n background-color: ", ";\n }\n > span[aria-disabled='true'] {\n color: ", ";\n }\n "])), themed({
43
+ return css(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral(["\n > span:hover[aria-disabled='false'] {\n color: ", ";\n background-color: ", ";\n }\n > span:active[aria-disabled='false'] {\n background-color: ", ";\n }\n > span[aria-disabled='true'] {\n color: ", ";\n }\n :focus > span[aria-disabled='false'] {\n ", ";\n }\n :focus-visible,\n :focus-visible > span[aria-disabled='false'] {\n outline: none;\n }\n "])), themed({
42
44
  light: token('color.text', N900),
43
45
  dark: token('color.text', DN600)
44
46
  })(theme), themed({
@@ -50,7 +52,7 @@ var buttonStyles = function buttonStyles(isActive) {
50
52
  })(theme), themed({
51
53
  light: token('color.text.disabled', N70),
52
54
  dark: token('color.text.disabled', DN80)
53
- })(theme));
55
+ })(theme), focusedMenuItemStyle); // The deafut focus-visible style is removed to ensure consistency across browsers
54
56
  }
55
57
  };
56
58
  };
@@ -99,6 +101,14 @@ var DropdownMenuWrapper = /*#__PURE__*/function (_PureComponent) {
99
101
  }
100
102
  });
101
103
 
104
+ _defineProperty(_assertThisInitialized(_this), "handleCloseandFocus", function () {
105
+ var _this$state$target, _this$state$target$qu;
106
+
107
+ _this.handleClose();
108
+
109
+ (_this$state$target = _this.state.target) === null || _this$state$target === void 0 ? void 0 : (_this$state$target$qu = _this$state$target.querySelector('button')) === null || _this$state$target$qu === void 0 ? void 0 : _this$state$target$qu.focus();
110
+ });
111
+
102
112
  _defineProperty(_assertThisInitialized(_this), "handleClose", function () {
103
113
  if (_this.props.onOpenChange) {
104
114
  _this.props.onOpenChange({
@@ -128,7 +138,9 @@ var DropdownMenuWrapper = /*#__PURE__*/function (_PureComponent) {
128
138
  fitWidth = _this$props.fitWidth,
129
139
  isOpen = _this$props.isOpen,
130
140
  zIndex = _this$props.zIndex,
131
- shouldUseDefaultRole = _this$props.shouldUseDefaultRole;
141
+ shouldUseDefaultRole = _this$props.shouldUseDefaultRole,
142
+ disableArrowKeyNavigation = _this$props.disableArrowKeyNavigation,
143
+ keyDownHandlerContext = _this$props.keyDownHandlerContext;
132
144
  return jsx(Popup, {
133
145
  target: isOpen ? target : undefined,
134
146
  mountTo: mountTo,
@@ -139,6 +151,11 @@ var DropdownMenuWrapper = /*#__PURE__*/function (_PureComponent) {
139
151
  fitWidth: fitWidth,
140
152
  zIndex: zIndex || akEditorFloatingPanelZIndex,
141
153
  offset: offset
154
+ }, jsx(MenuArrowKeyNavigationProvider, {
155
+ disableArrowKeyNavigation: disableArrowKeyNavigation,
156
+ handleClose: this.handleCloseandFocus,
157
+ keyDownHandlerContext: keyDownHandlerContext,
158
+ closeonTab: true
142
159
  }, jsx(DropListWithOutsideListeners, {
143
160
  isOpen: true,
144
161
  appearance: "tall",
@@ -147,7 +164,8 @@ var DropdownMenuWrapper = /*#__PURE__*/function (_PureComponent) {
147
164
  shouldFitContainer: true,
148
165
  isTriggerNotTabbable: true,
149
166
  handleClickOutside: this.handleClose,
150
- handleEscapeKeydown: this.handleClose
167
+ handleEscapeKeydown: this.handleCloseandFocus,
168
+ targetRef: this.state.target
151
169
  }, jsx("div", {
152
170
  style: {
153
171
  height: 0,
@@ -169,7 +187,7 @@ var DropdownMenuWrapper = /*#__PURE__*/function (_PureComponent) {
169
187
  onMouseLeave: _this2.props.onMouseLeave
170
188
  });
171
189
  }));
172
- })));
190
+ }))));
173
191
  }
174
192
  }, {
175
193
  key: "render",
@@ -220,7 +238,8 @@ function DropdownMenuItem(_ref) {
220
238
  return buttonStyles(item.isActive)({
221
239
  theme: theme
222
240
  });
223
- }
241
+ },
242
+ tabIndex: -1
224
243
  }, jsx(CustomItem, {
225
244
  item: item,
226
245
  key: (_item$key2 = item.key) !== null && _item$key2 !== void 0 ? _item$key2 : String(item.content),
@@ -0,0 +1,147 @@
1
+ import React, { useLayoutEffect, useRef } from 'react';
2
+
3
+ /**
4
+ * This component is a wrapper of vertical menus which listens to keydown events of children
5
+ * and handles up/down arrow key navigation
6
+ */
7
+ export var MenuArrowKeyNavigationProvider = function MenuArrowKeyNavigationProvider(_ref) {
8
+ var children = _ref.children,
9
+ handleClose = _ref.handleClose,
10
+ disableArrowKeyNavigation = _ref.disableArrowKeyNavigation,
11
+ keyDownHandlerContext = _ref.keyDownHandlerContext,
12
+ closeonTab = _ref.closeonTab;
13
+ var wrapperRef = useRef(null);
14
+ var currentSelectedItemIndex = useRef(-1);
15
+
16
+ var incrementIndex = function incrementIndex(list) {
17
+ if (currentSelectedItemIndex.current === list.length - 1 || currentSelectedItemIndex.current === -1) {
18
+ currentSelectedItemIndex.current = 0;
19
+ } else {
20
+ currentSelectedItemIndex.current = currentSelectedItemIndex.current + 1;
21
+ }
22
+ };
23
+
24
+ var decrementIndex = function decrementIndex(list) {
25
+ if (currentSelectedItemIndex.current === 0 || currentSelectedItemIndex.current === -1) {
26
+ currentSelectedItemIndex.current = list.length - 1;
27
+ } else {
28
+ currentSelectedItemIndex.current = currentSelectedItemIndex.current - 1;
29
+ }
30
+ };
31
+
32
+ useLayoutEffect(function () {
33
+ if (disableArrowKeyNavigation) {
34
+ return;
35
+ }
36
+ /**
37
+ * To handle the key events on the list
38
+ * @param event
39
+ */
40
+
41
+
42
+ var handleKeyDown = function handleKeyDown(event) {
43
+ var _wrapperRef$current, _focusableElements$cu, _focusableElements$cu2;
44
+
45
+ var targetElement = event.target; //Tab key on menu items can be handled in the parent components of dropdown menus with KeydownHandlerContext
46
+
47
+ if (event.key === 'Tab' && closeonTab) {
48
+ handleClose(event);
49
+ keyDownHandlerContext === null || keyDownHandlerContext === void 0 ? void 0 : keyDownHandlerContext.handleTab();
50
+ return;
51
+ } //To trap the focus inside the toolbar using left and right arrow keys
52
+
53
+
54
+ var focusableElements = getEnabledElements(wrapperRef === null || wrapperRef === void 0 ? void 0 : wrapperRef.current);
55
+
56
+ if (!focusableElements || (focusableElements === null || focusableElements === void 0 ? void 0 : focusableElements.length) === 0) {
57
+ return;
58
+ }
59
+
60
+ if (!((_wrapperRef$current = wrapperRef.current) !== null && _wrapperRef$current !== void 0 && _wrapperRef$current.contains(targetElement))) {
61
+ currentSelectedItemIndex.current = -1;
62
+ }
63
+
64
+ switch (event.key) {
65
+ case 'ArrowDown':
66
+ //If ArrowDown pressed
67
+ //If on last item
68
+ // Focus last item
69
+ //Else
70
+ // Focus next item
71
+ incrementIndex(focusableElements);
72
+ (_focusableElements$cu = focusableElements[currentSelectedItemIndex.current]) === null || _focusableElements$cu === void 0 ? void 0 : _focusableElements$cu.focus();
73
+ event.preventDefault();
74
+ break;
75
+
76
+ case 'ArrowUp':
77
+ //ArrowUP pressed
78
+ //If on First item
79
+ // Focus last item
80
+ //Else
81
+ // Focus previous item
82
+ decrementIndex(focusableElements);
83
+ (_focusableElements$cu2 = focusableElements[currentSelectedItemIndex.current]) === null || _focusableElements$cu2 === void 0 ? void 0 : _focusableElements$cu2.focus();
84
+ event.preventDefault();
85
+ break;
86
+ //ArrowLeft/Right on the menu should close the menus
87
+ //then logic to retain the focus can be handled in the parent components with KeydownHandlerContext
88
+
89
+ case 'ArrowLeft':
90
+ //Filter out the events from outside the menu
91
+ if (!targetElement.closest('.custom-key-handler-wrapper')) {
92
+ return;
93
+ }
94
+
95
+ handleClose(event);
96
+ keyDownHandlerContext === null || keyDownHandlerContext === void 0 ? void 0 : keyDownHandlerContext.handleArrowLeft();
97
+ break;
98
+
99
+ case 'ArrowRight':
100
+ //Filter out the events from outside the menu
101
+ if (!targetElement.closest('.custom-key-handler-wrapper')) {
102
+ return;
103
+ }
104
+
105
+ handleClose(event);
106
+ keyDownHandlerContext === null || keyDownHandlerContext === void 0 ? void 0 : keyDownHandlerContext.handleArrowRight();
107
+ break;
108
+
109
+ case 'Escape':
110
+ handleClose(event);
111
+ break;
112
+
113
+ default:
114
+ return;
115
+ }
116
+ };
117
+
118
+ document.addEventListener('keydown', handleKeyDown);
119
+ return function () {
120
+ document.removeEventListener('keydown', handleKeyDown);
121
+ };
122
+ }, [currentSelectedItemIndex, wrapperRef, handleClose, disableArrowKeyNavigation, keyDownHandlerContext, closeonTab]);
123
+ return /*#__PURE__*/React.createElement("div", {
124
+ className: "custom-key-handler-wrapper",
125
+ ref: wrapperRef
126
+ }, children);
127
+ };
128
+
129
+ function getFocusableElements(rootNode) {
130
+ if (!rootNode) {
131
+ return [];
132
+ }
133
+
134
+ var focusableModalElements = rootNode.querySelectorAll('a[href], button:not([disabled]), textarea, input, select, div[tabindex="-1"]') || [];
135
+ return Array.from(focusableModalElements);
136
+ }
137
+ /**
138
+ * This method filters out all the disabled menu items
139
+ */
140
+
141
+
142
+ function getEnabledElements(rootNode) {
143
+ var focusableElements = getFocusableElements(rootNode);
144
+ return focusableElements.filter(function (element) {
145
+ return !element.querySelector('[role="button"][aria-disabled="true"]') && !element.querySelector('[role="menuitem"][aria-disabled="true"]');
146
+ });
147
+ }
@@ -6,7 +6,7 @@ import _inherits from "@babel/runtime/helpers/inherits";
6
6
  import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
7
7
  import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
8
8
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
9
- var _excluded = ["handleClickOutside", "handleEnterKeydown", "handleEscapeKeydown"];
9
+ var _excluded = ["handleClickOutside", "handleEnterKeydown", "handleEscapeKeydown", "closeonTab"];
10
10
 
11
11
  function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
12
12
 
@@ -41,7 +41,16 @@ var WithOutsideClick = /*#__PURE__*/function (_PureComponent) {
41
41
 
42
42
  if (!domNode || evt.target instanceof Node && !domNode.contains(evt.target)) {
43
43
  if (_this.props.handleClickOutside) {
44
- _this.props.handleClickOutside(evt);
44
+ var _this$props$editorVie;
45
+
46
+ _this.props.handleClickOutside(evt); //When the menus are closed by clicking outside the focus is set on editor.
47
+
48
+
49
+ if (!((_this$props$editorVie = _this.props.editorView) !== null && _this$props$editorVie !== void 0 && _this$props$editorVie.hasFocus())) {
50
+ var _this$props$editorVie2;
51
+
52
+ (_this$props$editorVie2 = _this.props.editorView) === null || _this$props$editorVie2 === void 0 ? void 0 : _this$props$editorVie2.focus();
53
+ }
45
54
  }
46
55
  }
47
56
  });
@@ -52,22 +61,18 @@ var WithOutsideClick = /*#__PURE__*/function (_PureComponent) {
52
61
  }
53
62
 
54
63
  if (evt.code === 'Escape' && _this.props.handleEscapeKeydown) {
55
- var _this$props$editorVie;
56
-
57
64
  evt.preventDefault();
58
65
  evt.stopPropagation();
59
66
 
60
- _this.props.handleEscapeKeydown(evt);
61
-
62
- if (!((_this$props$editorVie = _this.props.editorView) !== null && _this$props$editorVie !== void 0 && _this$props$editorVie.hasFocus())) {
63
- var _this$props$editorVie2;
67
+ _this.props.handleEscapeKeydown(evt); //on 'Esc', Focus is handled in 'handleEscapeKeydown'.
64
68
 
65
- (_this$props$editorVie2 = _this.props.editorView) === null || _this$props$editorVie2 === void 0 ? void 0 : _this$props$editorVie2.focus();
66
- }
67
69
 
68
70
  return false;
69
71
  } else if (evt.code === 'Enter' && _this.props.handleEnterKeydown) {
70
72
  _this.props.handleEnterKeydown(evt);
73
+ } else if (evt.code === 'Tab' && _this.props.handleEscapeKeydown && _this.props.closeonTab) {
74
+ //The menus should be closed when the tab is pressed as it takes the focus out of the menu
75
+ _this.props.handleEscapeKeydown(evt);
71
76
  }
72
77
  });
73
78
 
@@ -84,7 +89,8 @@ var WithOutsideClick = /*#__PURE__*/function (_PureComponent) {
84
89
  if (this.props.handleEscapeKeydown) {
85
90
  var _this$props$editorRef;
86
91
 
87
- (((_this$props$editorRef = this.props.editorRef) === null || _this$props$editorRef === void 0 ? void 0 : _this$props$editorRef.current) || document).addEventListener('keydown', this.handleKeydown, false);
92
+ //Attached event to the menu so that 'ESC' events from the opened menu also will be handled.
93
+ (((_this$props$editorRef = this.props.editorRef) === null || _this$props$editorRef === void 0 ? void 0 : _this$props$editorRef.current) || this.props.targetRef || document).addEventListener('keydown', this.handleKeydown, false);
88
94
  }
89
95
  }
90
96
  }, {
@@ -97,7 +103,7 @@ var WithOutsideClick = /*#__PURE__*/function (_PureComponent) {
97
103
  if (this.props.handleEscapeKeydown) {
98
104
  var _this$props$editorRef2;
99
105
 
100
- (((_this$props$editorRef2 = this.props.editorRef) === null || _this$props$editorRef2 === void 0 ? void 0 : _this$props$editorRef2.current) || document).removeEventListener('keydown', this.handleKeydown, false);
106
+ (((_this$props$editorRef2 = this.props.editorRef) === null || _this$props$editorRef2 === void 0 ? void 0 : _this$props$editorRef2.current) || this.props.targetRef || document).removeEventListener('keydown', this.handleKeydown, false);
101
107
  }
102
108
  }
103
109
  }, {
@@ -119,6 +125,7 @@ export default function withReactEditorViewOuterListeners(Component) {
119
125
  var handleClickOutside = _ref.handleClickOutside,
120
126
  handleEnterKeydown = _ref.handleEnterKeydown,
121
127
  handleEscapeKeydown = _ref.handleEscapeKeydown,
128
+ closeonTab = _ref.closeonTab,
122
129
  props = _objectWithoutProperties(_ref, _excluded);
123
130
 
124
131
  var isActiveComponent = hasIsOpen(props) ? props.isOpen : true;
@@ -128,10 +135,12 @@ export default function withReactEditorViewOuterListeners(Component) {
128
135
  return /*#__PURE__*/React.createElement(WithOutsideClick, {
129
136
  editorView: editorView,
130
137
  editorRef: editorRef,
138
+ targetRef: props.targetRef,
131
139
  isActiveComponent: isActiveComponent,
132
140
  handleClickOutside: handleClickOutside,
133
141
  handleEnterKeydown: handleEnterKeydown,
134
- handleEscapeKeydown: handleEscapeKeydown
142
+ handleEscapeKeydown: handleEscapeKeydown,
143
+ closeonTab: closeonTab
135
144
  }, /*#__PURE__*/React.createElement(Component, props));
136
145
  });
137
146
  };
@@ -13,7 +13,7 @@ export { walkUpTreeUntil, unwrap, removeNestedEmptyEls, containsClassName, close
13
13
  export { default as ADFTraversor } from './traversor';
14
14
  export { analyticsEventKey, getAnalyticsAppearance, getAnalyticsEventSeverity, SEVERITY, getUnsupportedContentLevelData, UNSUPPORTED_CONTENT_LEVEL_SEVERITY, UNSUPPORTED_CONTENT_LEVEL_SEVERITY_THRESHOLD_DEFAULTS } from './analytics';
15
15
  export { findAndTrackUnsupportedContentNodes } from './track-unsupported-content';
16
- export { measureRender } from './performance/measure-render';
16
+ export { getDistortedDurationMonitor, measureRender } from './performance/measure-render';
17
17
  export { startMeasure, stopMeasure, clearMeasure } from './performance/measure';
18
18
  export { measureTTI, getTTISeverity, TTI_SEVERITY_THRESHOLD_DEFAULTS, TTI_FROM_INVOCATION_SEVERITY_THRESHOLD_DEFAULTS } from './performance/measure-tti';
19
19
  export { isPerformanceAPIAvailable, isPerformanceObserverAvailable } from './performance/is-performance-api-available';