@atlaskit/editor-common 72.4.0 → 72.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.
Files changed (130) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/dist/cjs/analytics/analytics-queue.js +79 -0
  3. package/dist/cjs/analytics/fire-analytics-event.js +36 -0
  4. package/dist/cjs/analytics/index.js +15 -1
  5. package/dist/cjs/analytics/types/enums.js +4 -0
  6. package/dist/cjs/analytics/utils.js +16 -0
  7. package/dist/cjs/hooks/index.js +20 -0
  8. package/dist/cjs/hooks/useConstructor.js +22 -0
  9. package/dist/cjs/hooks/usePreviousState.js +23 -0
  10. package/dist/cjs/keymaps/index.js +1 -1
  11. package/dist/cjs/styles/index.js +6 -0
  12. package/dist/cjs/styles/shared/table.js +3 -1
  13. package/dist/cjs/ui/DropList/index.js +1 -1
  14. package/dist/cjs/ui/index.js +6 -0
  15. package/dist/cjs/ui-color/ColorPalette/Color/index.js +2 -3
  16. package/dist/cjs/ui-color/ColorPalette/Palettes/panelBackgroundPalette.js +1 -1
  17. package/dist/cjs/ui-color/ColorPalette/index.js +9 -11
  18. package/dist/cjs/ui-color/ColorPalette/utils.js +42 -0
  19. package/dist/cjs/ui-color/index.js +25 -0
  20. package/dist/cjs/ui-menu/ArrowKeyNavigationProvider/ColorPaletteArrowKeyNavigationProvider/index.js +141 -0
  21. package/dist/cjs/ui-menu/{MenuArrowKeyNavigationProvider → ArrowKeyNavigationProvider/MenuArrowKeyNavigationProvider}/index.js +15 -0
  22. package/dist/cjs/ui-menu/ArrowKeyNavigationProvider/index.js +29 -0
  23. package/dist/cjs/ui-menu/ArrowKeyNavigationProvider/types.js +12 -0
  24. package/dist/cjs/ui-menu/Dropdown/index.js +5 -7
  25. package/dist/cjs/ui-menu/DropdownMenu/index.js +50 -24
  26. package/dist/cjs/ui-menu/ToolbarButton/index.js +3 -1
  27. package/dist/cjs/ui-menu/index.js +21 -0
  28. package/dist/cjs/utils/analytics.js +5 -1
  29. package/dist/cjs/utils/index.js +6 -0
  30. package/dist/cjs/utils/referentiality.js +29 -15
  31. package/dist/cjs/version.json +1 -1
  32. package/dist/es2019/analytics/analytics-queue.js +53 -0
  33. package/dist/es2019/analytics/fire-analytics-event.js +27 -0
  34. package/dist/es2019/analytics/index.js +3 -1
  35. package/dist/es2019/analytics/types/enums.js +4 -0
  36. package/dist/es2019/analytics/utils.js +4 -0
  37. package/dist/es2019/hooks/index.js +2 -0
  38. package/dist/es2019/hooks/useConstructor.js +17 -0
  39. package/dist/es2019/hooks/usePreviousState.js +18 -0
  40. package/dist/es2019/keymaps/index.js +1 -1
  41. package/dist/es2019/styles/index.js +1 -1
  42. package/dist/es2019/styles/shared/table.js +1 -0
  43. package/dist/es2019/ui/DropList/index.js +1 -1
  44. package/dist/es2019/ui/index.js +1 -1
  45. package/dist/es2019/ui-color/ColorPalette/Color/index.js +7 -4
  46. package/dist/es2019/ui-color/ColorPalette/Palettes/panelBackgroundPalette.js +1 -1
  47. package/dist/es2019/ui-color/ColorPalette/index.js +9 -11
  48. package/dist/es2019/ui-color/ColorPalette/utils.js +31 -0
  49. package/dist/es2019/ui-color/index.js +1 -0
  50. package/dist/es2019/ui-menu/ArrowKeyNavigationProvider/ColorPaletteArrowKeyNavigationProvider/index.js +132 -0
  51. package/dist/es2019/ui-menu/{MenuArrowKeyNavigationProvider → ArrowKeyNavigationProvider/MenuArrowKeyNavigationProvider}/index.js +16 -1
  52. package/dist/es2019/ui-menu/ArrowKeyNavigationProvider/index.js +21 -0
  53. package/dist/es2019/ui-menu/ArrowKeyNavigationProvider/types.js +5 -0
  54. package/dist/es2019/ui-menu/Dropdown/index.js +5 -7
  55. package/dist/es2019/ui-menu/DropdownMenu/index.js +46 -23
  56. package/dist/es2019/ui-menu/ToolbarButton/index.js +3 -1
  57. package/dist/es2019/ui-menu/index.js +3 -0
  58. package/dist/es2019/utils/analytics.js +1 -0
  59. package/dist/es2019/utils/index.js +1 -1
  60. package/dist/es2019/utils/referentiality.js +19 -15
  61. package/dist/es2019/version.json +1 -1
  62. package/dist/esm/analytics/analytics-queue.js +71 -0
  63. package/dist/esm/analytics/fire-analytics-event.js +29 -0
  64. package/dist/esm/analytics/index.js +3 -1
  65. package/dist/esm/analytics/types/enums.js +4 -0
  66. package/dist/esm/analytics/utils.js +9 -0
  67. package/dist/esm/hooks/index.js +2 -0
  68. package/dist/esm/hooks/useConstructor.js +17 -0
  69. package/dist/esm/hooks/usePreviousState.js +18 -0
  70. package/dist/esm/keymaps/index.js +1 -1
  71. package/dist/esm/styles/index.js +1 -1
  72. package/dist/esm/styles/shared/table.js +1 -0
  73. package/dist/esm/ui/DropList/index.js +1 -1
  74. package/dist/esm/ui/index.js +1 -1
  75. package/dist/esm/ui-color/ColorPalette/Color/index.js +2 -3
  76. package/dist/esm/ui-color/ColorPalette/Palettes/panelBackgroundPalette.js +1 -1
  77. package/dist/esm/ui-color/ColorPalette/index.js +9 -11
  78. package/dist/esm/ui-color/ColorPalette/utils.js +32 -0
  79. package/dist/esm/ui-color/index.js +1 -0
  80. package/dist/esm/ui-menu/ArrowKeyNavigationProvider/ColorPaletteArrowKeyNavigationProvider/index.js +131 -0
  81. package/dist/esm/ui-menu/{MenuArrowKeyNavigationProvider → ArrowKeyNavigationProvider/MenuArrowKeyNavigationProvider}/index.js +16 -1
  82. package/dist/esm/ui-menu/ArrowKeyNavigationProvider/index.js +21 -0
  83. package/dist/esm/ui-menu/ArrowKeyNavigationProvider/types.js +5 -0
  84. package/dist/esm/ui-menu/Dropdown/index.js +5 -7
  85. package/dist/esm/ui-menu/DropdownMenu/index.js +50 -24
  86. package/dist/esm/ui-menu/ToolbarButton/index.js +3 -1
  87. package/dist/esm/ui-menu/index.js +3 -0
  88. package/dist/esm/utils/analytics.js +3 -0
  89. package/dist/esm/utils/index.js +1 -1
  90. package/dist/esm/utils/referentiality.js +28 -15
  91. package/dist/esm/version.json +1 -1
  92. package/dist/types/analytics/analytics-queue.d.ts +10 -0
  93. package/dist/types/analytics/fire-analytics-event.d.ts +2 -0
  94. package/dist/types/analytics/index.d.ts +3 -1
  95. package/dist/types/analytics/types/enums.d.ts +4 -0
  96. package/dist/types/analytics/types/events.d.ts +2 -1
  97. package/dist/types/analytics/types/general-events.d.ts +2 -2
  98. package/dist/types/analytics/types/index.d.ts +1 -1
  99. package/dist/types/analytics/utils.d.ts +3 -0
  100. package/dist/types/extensions/types/extension-manifest.d.ts +1 -1
  101. package/dist/types/hooks/index.d.ts +2 -0
  102. package/dist/types/hooks/useConstructor.d.ts +9 -0
  103. package/dist/types/hooks/usePreviousState.d.ts +11 -0
  104. package/dist/types/styles/index.d.ts +1 -1
  105. package/dist/types/styles/shared/table.d.ts +1 -0
  106. package/dist/types/types/editor-actions.d.ts +2 -1
  107. package/dist/types/types/feature-flags.d.ts +11 -0
  108. package/dist/types/types/floating-toolbar.d.ts +1 -1
  109. package/dist/types/types/index.d.ts +2 -2
  110. package/dist/types/types/next-editor-plugin.d.ts +37 -32
  111. package/dist/types/ui/index.d.ts +1 -1
  112. package/dist/types/ui-color/ColorPalette/Color/index.d.ts +1 -5
  113. package/dist/types/ui-color/ColorPalette/index.d.ts +1 -0
  114. package/dist/types/ui-color/ColorPalette/utils.d.ts +11 -0
  115. package/dist/types/ui-color/index.d.ts +1 -0
  116. package/dist/types/ui-menu/ArrowKeyNavigationProvider/ColorPaletteArrowKeyNavigationProvider/index.d.ts +7 -0
  117. package/dist/types/ui-menu/ArrowKeyNavigationProvider/MenuArrowKeyNavigationProvider/index.d.ts +7 -0
  118. package/dist/types/ui-menu/ArrowKeyNavigationProvider/index.d.ts +3 -0
  119. package/dist/types/ui-menu/ArrowKeyNavigationProvider/types.d.ts +33 -0
  120. package/dist/types/ui-menu/Dropdown/index.d.ts +2 -3
  121. package/dist/types/ui-menu/DropdownMenu/index.d.ts +2 -0
  122. package/dist/types/ui-menu/DropdownMenu/types.d.ts +3 -6
  123. package/dist/types/ui-menu/ToolbarButton/index.d.ts +2 -0
  124. package/dist/types/ui-menu/index.d.ts +3 -0
  125. package/dist/types/utils/analytics.d.ts +1 -0
  126. package/dist/types/utils/index.d.ts +1 -1
  127. package/dist/types/utils/referentiality.d.ts +11 -0
  128. package/hooks/package.json +15 -0
  129. package/package.json +18 -14
  130. package/dist/types/ui-menu/MenuArrowKeyNavigationProvider/index.d.ts +0 -16
@@ -0,0 +1,27 @@
1
+ import { FabricChannel } from '@atlaskit/analytics-listeners';
2
+ import { AnalyticsQueue } from './analytics-queue';
3
+ const editorAnalyticsChannel = FabricChannel.editor;
4
+ export const fireAnalyticsEvent = createAnalyticsEvent => ({
5
+ payload,
6
+ channel = editorAnalyticsChannel
7
+ }) => {
8
+ if (!createAnalyticsEvent) {
9
+ return;
10
+ }
11
+
12
+ // START TEMPORARY CODE ED-10584
13
+ // __queueAnalytics property set in ReactEditorView based on featureFlags.queueAnalytics
14
+ const queueAnalytics = Boolean(createAnalyticsEvent.__queueAnalytics);
15
+ // END TEMPORARY CODE ED-10584
16
+
17
+ if (queueAnalytics) {
18
+ const queue = AnalyticsQueue.get();
19
+ queue.schedule(() => {
20
+ var _createAnalyticsEvent;
21
+ return (_createAnalyticsEvent = createAnalyticsEvent(payload)) === null || _createAnalyticsEvent === void 0 ? void 0 : _createAnalyticsEvent.fire(channel);
22
+ });
23
+ } else {
24
+ var _createAnalyticsEvent2;
25
+ (_createAnalyticsEvent2 = createAnalyticsEvent(payload)) === null || _createAnalyticsEvent2 === void 0 ? void 0 : _createAnalyticsEvent2.fire(channel);
26
+ }
27
+ };
@@ -1 +1,3 @@
1
- export { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, BROWSER_FREEZE_INTERACTION_TYPE, CONTENT_COMPONENT, DELETE_DIRECTION, EVENT_TYPE, FLOATING_CONTROLS_TITLE, FULL_WIDTH_MODE, GAP_CURSOR_POSITION, INDENT_DIRECTION, INDENT_TYPE, INPUT_METHOD, LAYOUT_TYPE, LINK_REPRESENTATION, LINK_RESOURCE, LINK_STATUS, LIST_TEXT_SCENARIOS, JOIN_SCENARIOS_WHEN_TYPING_TO_INSERT_LIST, OUTDENT_SCENARIOS, MODE, PLATFORMS, PUNC, PasteContents, PasteSources, PasteTypes, RESOLVE_METHOD, SELECTION_TYPE, SELECTION_POSITION, SMART_LINK_TYPE, SYMBOL, SmartLinkNodeContexts, TABLE_ACTION, TABLE_BREAKOUT, TARGET_SELECTION_SOURCE, TOOLBAR_ACTION_SUBJECT_ID, TRIGGER_METHOD, USER_CONTEXT } from './types';
1
+ export { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, BROWSER_FREEZE_INTERACTION_TYPE, CONTENT_COMPONENT, DELETE_DIRECTION, EVENT_TYPE, FLOATING_CONTROLS_TITLE, FULL_WIDTH_MODE, GAP_CURSOR_POSITION, INDENT_DIRECTION, INDENT_TYPE, INPUT_METHOD, LAYOUT_TYPE, LINK_REPRESENTATION, LINK_RESOURCE, LINK_STATUS, LIST_TEXT_SCENARIOS, JOIN_SCENARIOS_WHEN_TYPING_TO_INSERT_LIST, OUTDENT_SCENARIOS, MODE, PLATFORMS, PUNC, PasteContents, PasteSources, PasteTypes, RESOLVE_METHOD, SELECTION_TYPE, SELECTION_POSITION, SMART_LINK_TYPE, SYMBOL, SmartLinkNodeContexts, TABLE_ACTION, TABLE_BREAKOUT, TARGET_SELECTION_SOURCE, TOOLBAR_ACTION_SUBJECT_ID, TRIGGER_METHOD, USER_CONTEXT } from './types';
2
+ export { fireAnalyticsEvent } from './fire-analytics-event';
3
+ export { getAnalyticsEventsFromTransaction } from './utils';
@@ -57,6 +57,10 @@ export let ACTION;
57
57
  ACTION["INITIALISED_FRAGMENT_MARK"] = "initialisedFragmentMark";
58
58
  ACTION["INPUT_PERF_SAMPLING"] = "inputPerfSampling";
59
59
  ACTION["INPUT_PERF_SAMPLING_AVG"] = "inputPerfSamplingAvg";
60
+ ACTION["INPUT_PERF_SAMPLING_SINGLE_KEYPRESS"] = "inputPerfSamplingSingleKeypress";
61
+ ACTION["INPUT_PERF_SAMPLING_SINGLE_KEYPRESS_AVG"] = "inputPerfSamplingSingleKeypressAvg";
62
+ ACTION["INPUT_PERF_SAMPLING_RENDERED"] = "inputPerfSamplingRendered";
63
+ ACTION["INPUT_PERF_SAMPLING_RENDERED_AVG"] = "inputPerfSamplingRenderedAvg";
60
64
  ACTION["INSERTED"] = "inserted";
61
65
  ACTION["INVALID_DOCUMENT_ENCOUNTERED"] = "invalidDocumentEncountered";
62
66
  ACTION["INVOKED"] = "invoked";
@@ -0,0 +1,4 @@
1
+ import { AnalyticsStep } from '@atlaskit/adf-schema/steps';
2
+ export function getAnalyticsEventsFromTransaction(tr) {
3
+ return tr.steps.filter(step => step instanceof AnalyticsStep).reduce((acc, step) => [...acc, ...step.analyticsEvents], []);
4
+ }
@@ -0,0 +1,2 @@
1
+ export { default as usePreviousState } from './usePreviousState';
2
+ export { default as useConstructor } from './useConstructor';
@@ -0,0 +1,17 @@
1
+ import { useRef } from 'react';
2
+
3
+ /**
4
+ *
5
+ * Hook to run code once in a functional component.
6
+ * Emulates the behaviour of a `constructor` in a class component
7
+ * Place this at the top of your functional component so that it is run first.
8
+ *
9
+ * @param callback Callback function to run once
10
+ */
11
+ export default function useConstructor(callback) {
12
+ const hasRun = useRef(false);
13
+ if (!hasRun.current) {
14
+ callback();
15
+ hasRun.current = true;
16
+ }
17
+ }
@@ -0,0 +1,18 @@
1
+ import { useRef } from 'react';
2
+
3
+ /**
4
+ *
5
+ * Can be used to get the previous state of a prop.
6
+ * This can be helpful when converting class components to functional
7
+ * where we don't have the `prevProps`.
8
+ *
9
+ * @param value New state of the
10
+ * @param initialValue Optional parameter for the inital state of the component
11
+ * @returns
12
+ */
13
+ export default function usePreviousState(value, initialValue) {
14
+ const ref = useRef(initialValue);
15
+ const prevValue = ref.current;
16
+ ref.current = value;
17
+ return prevValue;
18
+ }
@@ -23,7 +23,7 @@ export const toggleHeading6 = makeKeyMapWithCommon('Heading 6', 'Mod-Alt-6');
23
23
  export const toggleOrderedList = makeKeyMapWithCommon('Numbered list', 'Mod-Shift-7');
24
24
  export const ctrlBackSpace = makeKeyMapWithCommon('Cmd + Backspace', 'Mod-Backspace');
25
25
  export const toggleBulletList = makeKeyMapWithCommon('Bullet list', 'Mod-Shift-8');
26
- export const toggleBlockQuote = makeKeymap('Quote', '', 'Cmd-Alt-9');
26
+ export const toggleBlockQuote = makeKeyMapWithCommon('Quote', 'Mod-Shift-9');
27
27
  export const insertNewLine = makeKeyMapWithCommon('Insert new line', 'Shift-Enter');
28
28
  export const shiftBackspace = makeKeyMapWithCommon('Shift Backspace', 'Shift-Backspace');
29
29
  export const splitCodeBlock = makeKeyMapWithCommon('Split code block', 'Enter');
@@ -1,5 +1,5 @@
1
1
  export { textColorStyles } from './shared/text-color';
2
- export { tableSharedStyle, tableMarginTop, tableMarginBottom, tableMarginSides, tableCellMinWidth, tableNewColumnMinWidth, tableCellBorderWidth, calcTableWidth, TableSharedCssClassName, tableResizeHandleWidth, tableCellPadding } from './shared/table';
2
+ export { tableSharedStyle, tableMarginTop, tableMarginBottom, tableMarginSides, tableCellMinWidth, tableNewColumnMinWidth, tableCellBorderWidth, calcTableWidth, TableSharedCssClassName, tableResizeHandleWidth, tableCellPadding, tableMarginTopWithControl } from './shared/table';
3
3
  export { AnnotationSharedClassNames, AnnotationSharedCSSByState, annotationSharedStyles } from './shared/annotation';
4
4
  export { columnLayoutSharedStyle } from './shared/column-layout';
5
5
  export { mediaSingleSharedStyle, richMediaClassName } from './shared/media-single';
@@ -10,6 +10,7 @@ import browser from '../../utils/browser';
10
10
  import { CodeBlockSharedCssClassName } from './code-block';
11
11
  export const tableMarginTop = 24;
12
12
  export const tableMarginBottom = 16;
13
+ export const tableMarginTopWithControl = 14;
13
14
  export const tableMarginSides = 8;
14
15
  export const tableCellMinWidth = 48;
15
16
  export const tableNewColumnMinWidth = 140;
@@ -8,7 +8,7 @@ import { themed } from '@atlaskit/theme/components';
8
8
  import { borderRadius, gridSize } from '@atlaskit/theme/constants';
9
9
  import Layer from '../Layer';
10
10
  const packageName = "@atlaskit/editor-common";
11
- const packageVersion = "72.4.0";
11
+ const packageVersion = "72.5.0";
12
12
  const halfFocusRing = 1;
13
13
  const dropOffset = `0, ${gridSize()}px`;
14
14
  class DropList extends Component {
@@ -8,7 +8,7 @@ export { default as UnsupportedBlock } from './UnsupportedBlock';
8
8
  export { default as UnsupportedInline } from './UnsupportedInline';
9
9
  export { BaseTheme, mapBreakpointToLayoutMaxWidth } from './BaseTheme';
10
10
  export { default as withOuterListeners } from './with-outer-listeners';
11
- export { WidthConsumer, WidthProvider, getBreakpoint } from './WidthProvider';
11
+ export { WidthContext, WidthConsumer, WidthProvider, getBreakpoint } from './WidthProvider';
12
12
  export { default as overflowShadow, shadowClassNames } from './OverflowShadow';
13
13
  export { shadowObserverClassNames, ShadowObserver } from './OverflowShadow/shadowObserver';
14
14
  export { WithCreateAnalyticsEvent } from './WithCreateAnalyticsEvent';
@@ -2,7 +2,6 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  /** @jsx jsx */
3
3
  import React, { PureComponent } from 'react';
4
4
  import { jsx } from '@emotion/react';
5
- import { hexToEditorTextPaletteColor } from '@atlaskit/editor-palette';
6
5
  import EditorDoneIcon from '@atlaskit/icon/glyph/editor/done';
7
6
  import { N0 } from '@atlaskit/theme/colors';
8
7
  import Tooltip from '@atlaskit/tooltip';
@@ -34,10 +33,14 @@ class Color extends PureComponent {
34
33
  /** this is not new usage - old code extracted from editor-core */
35
34
  /* eslint-disable @atlaskit/design-system/ensure-design-token-usage */
36
35
  checkMarkColor = N0,
37
- /* eslint-enable @atlaskit/design-system/ensure-design-token-usage */
38
- useDesignTokens
36
+ /**
37
+ * When hexToPaletteColor prop is set,
38
+ * it will be used to get background color style based on
39
+ * value (which will be hexcode) prop
40
+ */
41
+ hexToPaletteColor
39
42
  } = this.props;
40
- const colorStyle = useDesignTokens ? hexToEditorTextPaletteColor(value) : value;
43
+ const colorStyle = hexToPaletteColor ? hexToPaletteColor(value) : value;
41
44
  return jsx(Tooltip, {
42
45
  content: label
43
46
  }, jsx("span", {
@@ -70,7 +70,7 @@ export const panelBackgroundPalette = [{
70
70
  value: colors.P100
71
71
  }].map(color => ({
72
72
  ...color,
73
- border: DEFAULT_BORDER_COLOR
73
+ border: `var(--ds-border, ${DEFAULT_BORDER_COLOR})`
74
74
  }));
75
75
  /* eslint-enable @atlaskit/design-system/ensure-design-token-usage */
76
76
 
@@ -9,6 +9,7 @@ import Color from './Color';
9
9
  import getColorMessage from './Palettes/getColorMessage';
10
10
  import { newDarkPalette, newLightPalette } from './Palettes/paletteMessagesTokenModeNames';
11
11
  import { colorPaletteWrapper } from './styles';
12
+ import { DEFAULT_COLOR_PICKER_COLUMNS, getColorsPerRowFromPalette } from './utils';
12
13
  /**
13
14
  * For a given color pick the color from a list of colors with
14
15
  * the highest contrast
@@ -16,10 +17,10 @@ import { colorPaletteWrapper } from './styles';
16
17
  * @param color color string, suppports HEX, RGB, RGBA etc.
17
18
  * @return Highest contrast color in pool
18
19
  */
19
- function getCheckMarkColor(color, textPalette) {
20
+ function getCheckMarkColor(color, useIconToken) {
20
21
  // eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage
21
22
  const contrastColor = [N0, N500].sort((a, b) => chromatism.difference(b, color) - chromatism.difference(a, color))[0];
22
- if (!textPalette) {
23
+ if (!useIconToken) {
23
24
  return contrastColor;
24
25
  }
25
26
 
@@ -32,7 +33,7 @@ function getCheckMarkColor(color, textPalette) {
32
33
  const ColorPalette = props => {
33
34
  const {
34
35
  palette,
35
- cols = 7,
36
+ cols = DEFAULT_COLOR_PICKER_COLUMNS,
36
37
  onClick,
37
38
  selectedColor,
38
39
  className,
@@ -40,18 +41,15 @@ const ColorPalette = props => {
40
41
  formatMessage
41
42
  },
42
43
  textPalette = false,
44
+ hexToPaletteColor,
43
45
  useSomewhatSemanticTextColorNames = false
44
46
  } = props;
45
47
  const {
46
48
  colorMode: tokenTheme
47
49
  } = useThemeObserver();
50
+ const useIconToken = !!hexToPaletteColor;
48
51
  const colorsPerRow = React.useMemo(() => {
49
- return palette.reduce((resultArray, item, index) => {
50
- const chunkIndex = Math.floor(index / cols);
51
- resultArray[chunkIndex] = resultArray[chunkIndex] || []; // start a new chunk
52
- resultArray[chunkIndex].push(item);
53
- return resultArray;
54
- }, []);
52
+ return getColorsPerRowFromPalette(palette, cols);
55
53
  }, [palette, cols]);
56
54
  return jsx(React.Fragment, null, colorsPerRow.map((row, rowIdx) => jsx("div", {
57
55
  css: colorPaletteWrapper,
@@ -79,8 +77,8 @@ const ColorPalette = props => {
79
77
  label: message ? formatMessage(message) : label,
80
78
  onClick: onClick,
81
79
  isSelected: value === selectedColor,
82
- checkMarkColor: getCheckMarkColor(value, textPalette),
83
- useDesignTokens: textPalette === true
80
+ checkMarkColor: getCheckMarkColor(value, useIconToken),
81
+ hexToPaletteColor: hexToPaletteColor
84
82
  });
85
83
  }))));
86
84
  };
@@ -0,0 +1,31 @@
1
+ export const DEFAULT_COLOR_PICKER_COLUMNS = 7;
2
+ export function getColorsPerRowFromPalette(palette, cols = DEFAULT_COLOR_PICKER_COLUMNS) {
3
+ return palette.reduce((resultArray, item, index) => {
4
+ const chunkIndex = Math.floor(index / cols);
5
+ resultArray[chunkIndex] = resultArray[chunkIndex] || []; // start a new chunk
6
+ resultArray[chunkIndex].push(item);
7
+ return resultArray;
8
+ }, []);
9
+ }
10
+ export function getSelectedRowAndColumn(colorsPerRow, selectedColor) {
11
+ let selectedRowIndex = -1;
12
+ let selectedColumnIndex = -1;
13
+ colorsPerRow.forEach((row, rowIndex) => {
14
+ row.forEach(({
15
+ value
16
+ }, columnIndex) => {
17
+ if (value === selectedColor) {
18
+ selectedRowIndex = rowIndex;
19
+ selectedColumnIndex = columnIndex;
20
+ }
21
+ });
22
+ });
23
+ return {
24
+ selectedRowIndex,
25
+ selectedColumnIndex
26
+ };
27
+ }
28
+ export function getSelectedRowAndColumnFromPalette(palette, selectedColor, cols = DEFAULT_COLOR_PICKER_COLUMNS) {
29
+ const colorsPerRow = getColorsPerRowFromPalette(palette, cols);
30
+ return getSelectedRowAndColumn(colorsPerRow, selectedColor);
31
+ }
@@ -1,5 +1,6 @@
1
1
  export { default as ColorPalette } from './ColorPalette';
2
2
  export { default as Color } from './ColorPalette/Color';
3
+ export { DEFAULT_COLOR_PICKER_COLUMNS, getColorsPerRowFromPalette, getSelectedRowAndColumn, getSelectedRowAndColumnFromPalette } from './ColorPalette/utils';
3
4
  export { default as cellBackgroundColorPalette } from './ColorPalette/Palettes/cellBackgroundColorPalette';
4
5
  export { default as colorPaletteMessages } from './ColorPalette/Palettes/paletteMessages';
5
6
  export { panelBackgroundPalette, panelDarkModeBackgroundPalette } from './ColorPalette/Palettes/panelBackgroundPalette';
@@ -0,0 +1,132 @@
1
+ import React, { useLayoutEffect, useRef } from 'react';
2
+ /**
3
+ * This component is a wrapper for color picker which listens to keydown events of children
4
+ * and handles arrow key navigation
5
+ */
6
+ export const ColorPaletteArrowKeyNavigationProvider = ({
7
+ children,
8
+ selectedRowIndex,
9
+ selectedColumnIndex,
10
+ isOpenedByKeyboard,
11
+ isPopupPositioned,
12
+ handleClose,
13
+ closeOnTab
14
+ }) => {
15
+ const wrapperRef = useRef(null);
16
+ const currentSelectedColumnIndex = useRef(selectedColumnIndex === -1 ? 0 : selectedColumnIndex);
17
+ const currentSelectedRowIndex = useRef(selectedRowIndex === -1 ? 0 : selectedRowIndex);
18
+ const incrementRowIndex = (rowElements, columnElements) => {
19
+ if (currentSelectedRowIndex.current === rowElements.length - 1) {
20
+ currentSelectedRowIndex.current = 0;
21
+ } else {
22
+ currentSelectedRowIndex.current = currentSelectedRowIndex.current + 1;
23
+ }
24
+ };
25
+ const decrementRowIndex = (rowElements, columnElements) => {
26
+ if (currentSelectedRowIndex.current === 0) {
27
+ currentSelectedRowIndex.current = rowElements.length - 1;
28
+ } else {
29
+ currentSelectedRowIndex.current = currentSelectedRowIndex.current - 1;
30
+ }
31
+ };
32
+ useLayoutEffect(() => {
33
+ const incrementColumnIndex = (rowElements, columnElements) => {
34
+ if (currentSelectedColumnIndex.current === columnElements.length - 1) {
35
+ incrementRowIndex(rowElements, columnElements);
36
+ currentSelectedColumnIndex.current = 0;
37
+ } else {
38
+ currentSelectedColumnIndex.current = currentSelectedColumnIndex.current + 1;
39
+ }
40
+ };
41
+ const decrementColumnIndex = (rowElements, columnElements) => {
42
+ if (currentSelectedColumnIndex.current === 0) {
43
+ decrementRowIndex(rowElements, columnElements);
44
+ currentSelectedColumnIndex.current = columnElements.length - 1;
45
+ } else {
46
+ currentSelectedColumnIndex.current = currentSelectedColumnIndex.current - 1;
47
+ }
48
+ };
49
+ const focusColorSwatch = () => {
50
+ var _focusableElements$cu;
51
+ const colorSwatchesRowElements = getColorSwatchesRows(wrapperRef === null || wrapperRef === void 0 ? void 0 : wrapperRef.current);
52
+ const currentSelectedColorSwatchRowElement = colorSwatchesRowElements[currentSelectedRowIndex.current];
53
+ const focusableElements = getFocusableElements(currentSelectedColorSwatchRowElement);
54
+ if (!focusableElements || (focusableElements === null || focusableElements === void 0 ? void 0 : focusableElements.length) === 0) {
55
+ return;
56
+ }
57
+ (_focusableElements$cu = focusableElements[currentSelectedColumnIndex.current]) === null || _focusableElements$cu === void 0 ? void 0 : _focusableElements$cu.focus();
58
+ };
59
+
60
+ /**
61
+ * To handle the key events on the list
62
+ * @param event
63
+ */
64
+ const handleKeyDown = event => {
65
+ if (event.key === 'Tab' && closeOnTab) {
66
+ handleClose(event);
67
+ return;
68
+ }
69
+ const colorSwatchesRowElements = getColorSwatchesRows(wrapperRef === null || wrapperRef === void 0 ? void 0 : wrapperRef.current);
70
+ const currentSelectedColorSwatchRowElement = colorSwatchesRowElements[currentSelectedRowIndex.current];
71
+ const focusableElements = getFocusableElements(currentSelectedColorSwatchRowElement);
72
+ switch (event.key) {
73
+ case 'ArrowDown':
74
+ incrementRowIndex(colorSwatchesRowElements, focusableElements);
75
+ focusColorSwatch();
76
+ event.preventDefault();
77
+ break;
78
+ case 'ArrowUp':
79
+ decrementRowIndex(colorSwatchesRowElements, focusableElements);
80
+ focusColorSwatch();
81
+ event.preventDefault();
82
+ break;
83
+ case 'ArrowLeft':
84
+ decrementColumnIndex(colorSwatchesRowElements, focusableElements);
85
+ focusColorSwatch();
86
+ event.preventDefault();
87
+ break;
88
+ case 'ArrowRight':
89
+ incrementColumnIndex(colorSwatchesRowElements, focusableElements);
90
+ focusColorSwatch();
91
+ event.preventDefault();
92
+ break;
93
+ case 'Escape':
94
+ handleClose(event);
95
+ break;
96
+ default:
97
+ return;
98
+ }
99
+ };
100
+ document.addEventListener('keydown', handleKeyDown);
101
+ // set focus to current selected color swatch if only opened by keyboard
102
+ if (isOpenedByKeyboard && isPopupPositioned) {
103
+ // Using timeout because, we need to wait till color palette is rendered
104
+ // and visible on screen, then only focus color swatch, otherwise focus will be
105
+ // moved to body
106
+ setTimeout(() => {
107
+ focusColorSwatch();
108
+ });
109
+ }
110
+ return () => {
111
+ document.removeEventListener('keydown', handleKeyDown);
112
+ };
113
+ }, [currentSelectedColumnIndex, isOpenedByKeyboard, isPopupPositioned, wrapperRef, handleClose, closeOnTab]);
114
+ return /*#__PURE__*/React.createElement("div", {
115
+ className: "custom-key-handler-wrapper",
116
+ ref: wrapperRef
117
+ }, children);
118
+ };
119
+ function getColorSwatchesRows(rootNode) {
120
+ if (!rootNode) {
121
+ return [];
122
+ }
123
+ const colorSwatchesRowElements = rootNode.querySelectorAll('div[role=radiogroup]') || [];
124
+ return Array.from(colorSwatchesRowElements);
125
+ }
126
+ function getFocusableElements(rootNode) {
127
+ if (!rootNode) {
128
+ return [];
129
+ }
130
+ const focusableModalElements = rootNode.querySelectorAll('button[role=radio]:not([disabled])') || [];
131
+ return Array.from(focusableModalElements);
132
+ }
@@ -1,4 +1,4 @@
1
- import React, { useCallback, useLayoutEffect, useRef, useState } from 'react';
1
+ import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
2
2
  /**
3
3
  * This component is a wrapper of vertical menus which listens to keydown events of children
4
4
  * and handles up/down arrow key navigation
@@ -33,6 +33,21 @@ export const MenuArrowKeyNavigationProvider = ({
33
33
  setCurrentSelectedItemIndex(nextIndex);
34
34
  return nextIndex;
35
35
  }, [currentSelectedItemIndex]);
36
+
37
+ // this useEffect uses onSelection in it's dependency list which gets
38
+ // changed as a result of the dropdown menu getting re-rendered in it's
39
+ // parent component. Note that if onSelection gets updated to useMemo
40
+ // this will no longer work.
41
+ useEffect(() => {
42
+ const currentIndex = currentSelectedItemIndex;
43
+ const list = getFocusableElements(wrapperRef === null || wrapperRef === void 0 ? void 0 : wrapperRef.current);
44
+ const currentElement = list[currentIndex];
45
+ if (currentElement && currentElement.getAttribute('aria-disabled') === 'true') {
46
+ var _list$focusIndex;
47
+ const focusIndex = incrementIndex(list);
48
+ (_list$focusIndex = list[focusIndex]) === null || _list$focusIndex === void 0 ? void 0 : _list$focusIndex.focus();
49
+ }
50
+ }, [currentSelectedItemIndex, onSelection, incrementIndex, decrementIndex]);
36
51
  useLayoutEffect(() => {
37
52
  if (disableArrowKeyNavigation) {
38
53
  return;
@@ -0,0 +1,21 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import React from 'react';
3
+ import { ColorPaletteArrowKeyNavigationProvider } from './ColorPaletteArrowKeyNavigationProvider';
4
+ import { MenuArrowKeyNavigationProvider } from './MenuArrowKeyNavigationProvider';
5
+ import { ArrowKeyNavigationType } from './types';
6
+ export const ArrowKeyNavigationProvider = props => {
7
+ const {
8
+ children,
9
+ type,
10
+ ...restProps
11
+ } = props;
12
+ if (type === ArrowKeyNavigationType.COLOR) {
13
+ return /*#__PURE__*/React.createElement(ColorPaletteArrowKeyNavigationProvider, _extends({
14
+ selectedRowIndex: props.selectedRowIndex,
15
+ selectedColumnIndex: props.selectedColumnIndex,
16
+ isOpenedByKeyboard: props.isOpenedByKeyboard,
17
+ isPopupPositioned: props.isPopupPositioned
18
+ }, restProps), children);
19
+ }
20
+ return /*#__PURE__*/React.createElement(MenuArrowKeyNavigationProvider, restProps, children);
21
+ };
@@ -0,0 +1,5 @@
1
+ export let ArrowKeyNavigationType;
2
+ (function (ArrowKeyNavigationType) {
3
+ ArrowKeyNavigationType["COLOR"] = "color";
4
+ ArrowKeyNavigationType["MENU"] = "menu";
5
+ })(ArrowKeyNavigationType || (ArrowKeyNavigationType = {}));
@@ -1,9 +1,10 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
1
2
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
3
  import React, { PureComponent } from 'react';
3
4
  import { withReactEditorViewOuterListeners } from '../../ui-react';
4
5
  import DropdownList from '../../ui/DropList';
5
6
  import Popup from '../../ui/Popup';
6
- import { MenuArrowKeyNavigationProvider } from '../MenuArrowKeyNavigationProvider';
7
+ import { ArrowKeyNavigationProvider } from '../ArrowKeyNavigationProvider';
7
8
  /**
8
9
  * Wrapper around @atlaskit/droplist which uses Popup and Portal to render
9
10
  * droplist outside of "overflow: hidden" containers when needed.
@@ -41,8 +42,7 @@ export class Dropdown extends PureComponent {
41
42
  fitHeight,
42
43
  fitWidth,
43
44
  zIndex,
44
- disableArrowKeyNavigation,
45
- keyDownHandlerContext
45
+ arrowKeyNavigationProviderOptions
46
46
  } = this.props;
47
47
  return /*#__PURE__*/React.createElement(Popup, {
48
48
  target: target,
@@ -53,15 +53,13 @@ export class Dropdown extends PureComponent {
53
53
  fitHeight: fitHeight,
54
54
  fitWidth: fitWidth,
55
55
  zIndex: zIndex
56
- }, /*#__PURE__*/React.createElement(MenuArrowKeyNavigationProvider, {
57
- disableArrowKeyNavigation: disableArrowKeyNavigation,
58
- keyDownHandlerContext: keyDownHandlerContext,
56
+ }, /*#__PURE__*/React.createElement(ArrowKeyNavigationProvider, _extends({}, arrowKeyNavigationProviderOptions, {
59
57
  closeOnTab: true,
60
58
  handleClose: event => onOpenChange && onOpenChange({
61
59
  isOpen: false,
62
60
  event
63
61
  })
64
- }, /*#__PURE__*/React.createElement("div", {
62
+ }), /*#__PURE__*/React.createElement("div", {
65
63
  style: {
66
64
  height: 0,
67
65
  minWidth: fitWidth || 0
@@ -12,7 +12,8 @@ import { DropdownMenuSharedCssClassName } from '../../styles';
12
12
  import { withReactEditorViewOuterListeners } from '../../ui-react';
13
13
  import DropList from '../../ui/DropList';
14
14
  import Popup from '../../ui/Popup';
15
- import { MenuArrowKeyNavigationProvider } from '../MenuArrowKeyNavigationProvider';
15
+ import { ArrowKeyNavigationProvider } from '../ArrowKeyNavigationProvider';
16
+ import { ArrowKeyNavigationType } from '../ArrowKeyNavigationProvider/types';
16
17
  const wrapper = css`
17
18
  /* tooltip in ToolbarButton is display:block */
18
19
  & > div > div {
@@ -75,7 +76,7 @@ const buttonStyles = (isActive, submenuActive) => theme => {
75
76
  :focus-visible > span[aria-disabled='false'] {
76
77
  outline: none;
77
78
  }
78
- `; // The deafut focus-visible style is removed to ensure consistency across browsers
79
+ `; // The default focus-visible style is removed to ensure consistency across browsers
79
80
  }
80
81
  };
81
82
 
@@ -94,6 +95,7 @@ export default class DropdownMenuWrapper extends PureComponent {
94
95
  popupPlacement: ['bottom', 'left'],
95
96
  selectionIndex: -1
96
97
  });
98
+ _defineProperty(this, "popupRef", /*#__PURE__*/React.createRef());
97
99
  _defineProperty(this, "handleRef", target => {
98
100
  this.setState({
99
101
  target: target || undefined
@@ -138,24 +140,17 @@ export default class DropdownMenuWrapper extends PureComponent {
138
140
  isOpen,
139
141
  zIndex,
140
142
  shouldUseDefaultRole,
141
- disableArrowKeyNavigation,
142
- keyDownHandlerContext,
143
- onItemActivated
143
+ onItemActivated,
144
+ arrowKeyNavigationProviderOptions
144
145
  } = this.props;
145
- return jsx(Popup, {
146
- target: isOpen ? target : undefined,
147
- mountTo: mountTo,
148
- boundariesElement: boundariesElement,
149
- scrollableElement: scrollableElement,
150
- onPlacementChanged: this.updatePopupPlacement,
151
- fitHeight: fitHeight,
152
- fitWidth: fitWidth,
153
- zIndex: zIndex || akEditorFloatingPanelZIndex,
154
- offset: offset
155
- }, jsx(MenuArrowKeyNavigationProvider, {
156
- disableArrowKeyNavigation: disableArrowKeyNavigation,
157
- handleClose: this.handleCloseAndFocus,
158
- keyDownHandlerContext: keyDownHandlerContext,
146
+
147
+ // Note that this onSelection function can't be refactored to useMemo for
148
+ // performance gains as it is being used as a dependency in a useEffect in
149
+ // MenuArrowKeyNavigationProvider in order to check for re-renders to adjust
150
+ // focus for accessibility. If this needs to be refactored in future refer
151
+ // back to ED-16740 for context.
152
+ const navigationProviderProps = arrowKeyNavigationProviderOptions.type === ArrowKeyNavigationType.COLOR ? arrowKeyNavigationProviderOptions : {
153
+ ...arrowKeyNavigationProviderOptions,
159
154
  onSelection: index => {
160
155
  let result = [];
161
156
  if (typeof onItemActivated === 'function') {
@@ -167,9 +162,22 @@ export default class DropdownMenuWrapper extends PureComponent {
167
162
  shouldCloseMenu: false
168
163
  });
169
164
  }
170
- },
165
+ }
166
+ };
167
+ return jsx(Popup, {
168
+ target: isOpen ? target : undefined,
169
+ mountTo: mountTo,
170
+ boundariesElement: boundariesElement,
171
+ scrollableElement: scrollableElement,
172
+ onPlacementChanged: this.updatePopupPlacement,
173
+ fitHeight: fitHeight,
174
+ fitWidth: fitWidth,
175
+ zIndex: zIndex || akEditorFloatingPanelZIndex,
176
+ offset: offset
177
+ }, jsx(ArrowKeyNavigationProvider, _extends({}, navigationProviderProps, {
178
+ handleClose: this.handleCloseAndFocus,
171
179
  closeOnTab: true
172
- }, jsx(DropListWithOutsideListeners, {
180
+ }), jsx(DropListWithOutsideListeners, {
173
181
  isOpen: true,
174
182
  appearance: "tall",
175
183
  position: popupPlacement.join(' '),
@@ -184,7 +192,9 @@ export default class DropdownMenuWrapper extends PureComponent {
184
192
  height: 0,
185
193
  minWidth: fitWidth || 0
186
194
  }
187
- }), items.map((group, index) => jsx(MenuGroup, {
195
+ }), jsx("div", {
196
+ ref: this.popupRef
197
+ }, items.map((group, index) => jsx(MenuGroup, {
188
198
  key: index,
189
199
  role: shouldUseDefaultRole ? 'group' : 'menu'
190
200
  }, group.items.map(item => {
@@ -197,7 +207,7 @@ export default class DropdownMenuWrapper extends PureComponent {
197
207
  onMouseEnter: this.props.onMouseEnter,
198
208
  onMouseLeave: this.props.onMouseLeave
199
209
  });
200
- }))))));
210
+ })))))));
201
211
  }
202
212
  render() {
203
213
  const {
@@ -210,6 +220,19 @@ export default class DropdownMenuWrapper extends PureComponent {
210
220
  ref: this.handleRef
211
221
  }, children), isOpen ? this.renderDropdownMenu() : null);
212
222
  }
223
+ componentDidUpdate(previousProps) {
224
+ const isOpenToggled = this.props.isOpen !== previousProps.isOpen;
225
+ if (this.props.isOpen && isOpenToggled) {
226
+ if (typeof this.props.shouldFocusFirstItem === 'function' && this.props.shouldFocusFirstItem()) {
227
+ var _this$state$target2;
228
+ const keyboardEvent = new KeyboardEvent('keydown', {
229
+ key: 'ArrowDown',
230
+ bubbles: true
231
+ });
232
+ (_this$state$target2 = this.state.target) === null || _this$state$target2 === void 0 ? void 0 : _this$state$target2.dispatchEvent(keyboardEvent);
233
+ }
234
+ }
235
+ }
213
236
  }
214
237
  const DropdownMenuItemCustomComponent = /*#__PURE__*/React.forwardRef((props, ref) => {
215
238
  const {