@atlaskit/editor-common 84.5.1 → 85.1.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 (84) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/cjs/analytics/types/enums.js +2 -0
  3. package/dist/cjs/extensibility/extensionNodeView.js +1 -2
  4. package/dist/cjs/keymaps/index.js +3 -2
  5. package/dist/cjs/keymaps/keymap.js +25 -43
  6. package/dist/cjs/link/ConfigureLinkOverlay/Dropdown.js +34 -9
  7. package/dist/cjs/link/ConfigureLinkOverlay/index.js +15 -5
  8. package/dist/cjs/link/ConfigureLinkOverlay/useLinkOverlayAnalyticsEvents.js +46 -0
  9. package/dist/cjs/monitoring/error.js +1 -1
  10. package/dist/cjs/react-node-view/getInlineNodeViewProducer.js +2 -4
  11. package/dist/cjs/react-node-view/index.js +4 -10
  12. package/dist/cjs/selection-based-node-view/SelectionBasedNodeView.js +2 -5
  13. package/dist/cjs/ui/DropList/index.js +1 -1
  14. package/dist/cjs/ui-color/ColorPalette/Color/index.js +11 -0
  15. package/dist/cjs/ui-color/ColorPalette/index.js +2 -0
  16. package/dist/cjs/ui-menu/ArrowKeyNavigationProvider/MenuArrowKeyNavigationProvider/index.js +18 -5
  17. package/dist/cjs/ui-menu/DropdownMenu/index.js +33 -11
  18. package/dist/es2019/analytics/types/enums.js +2 -0
  19. package/dist/es2019/extensibility/extensionNodeView.js +1 -2
  20. package/dist/es2019/keymaps/index.js +1 -0
  21. package/dist/es2019/keymaps/keymap.js +25 -43
  22. package/dist/es2019/link/ConfigureLinkOverlay/Dropdown.js +33 -7
  23. package/dist/es2019/link/ConfigureLinkOverlay/index.js +16 -5
  24. package/dist/es2019/link/ConfigureLinkOverlay/useLinkOverlayAnalyticsEvents.js +39 -0
  25. package/dist/es2019/monitoring/error.js +1 -1
  26. package/dist/es2019/react-node-view/getInlineNodeViewProducer.js +2 -4
  27. package/dist/es2019/react-node-view/index.js +5 -7
  28. package/dist/es2019/selection-based-node-view/SelectionBasedNodeView.js +3 -2
  29. package/dist/es2019/ui/DropList/index.js +1 -1
  30. package/dist/es2019/ui-color/ColorPalette/Color/index.js +13 -0
  31. package/dist/es2019/ui-color/ColorPalette/index.js +2 -0
  32. package/dist/es2019/ui-menu/ArrowKeyNavigationProvider/MenuArrowKeyNavigationProvider/index.js +19 -6
  33. package/dist/es2019/ui-menu/DropdownMenu/index.js +34 -12
  34. package/dist/esm/analytics/types/enums.js +2 -0
  35. package/dist/esm/extensibility/extensionNodeView.js +1 -2
  36. package/dist/esm/keymaps/index.js +1 -0
  37. package/dist/esm/keymaps/keymap.js +25 -43
  38. package/dist/esm/link/ConfigureLinkOverlay/Dropdown.js +34 -9
  39. package/dist/esm/link/ConfigureLinkOverlay/index.js +15 -5
  40. package/dist/esm/link/ConfigureLinkOverlay/useLinkOverlayAnalyticsEvents.js +40 -0
  41. package/dist/esm/monitoring/error.js +1 -1
  42. package/dist/esm/react-node-view/getInlineNodeViewProducer.js +2 -4
  43. package/dist/esm/react-node-view/index.js +4 -10
  44. package/dist/esm/selection-based-node-view/SelectionBasedNodeView.js +3 -5
  45. package/dist/esm/ui/DropList/index.js +1 -1
  46. package/dist/esm/ui-color/ColorPalette/Color/index.js +11 -0
  47. package/dist/esm/ui-color/ColorPalette/index.js +2 -0
  48. package/dist/esm/ui-menu/ArrowKeyNavigationProvider/MenuArrowKeyNavigationProvider/index.js +19 -6
  49. package/dist/esm/ui-menu/DropdownMenu/index.js +34 -12
  50. package/dist/types/analytics/types/enums.d.ts +3 -1
  51. package/dist/types/extensibility/extensionNodeView.d.ts +1 -2
  52. package/dist/types/keymaps/index.d.ts +1 -0
  53. package/dist/types/link/ConfigureLinkOverlay/Dropdown.d.ts +5 -4
  54. package/dist/types/link/ConfigureLinkOverlay/index.d.ts +2 -2
  55. package/dist/types/link/ConfigureLinkOverlay/useLinkOverlayAnalyticsEvents.d.ts +5 -0
  56. package/dist/types/react-node-view/index.d.ts +2 -5
  57. package/dist/types/selection-based-node-view/SelectionBasedNodeView.d.ts +1 -2
  58. package/dist/types/types/plugin-factory.d.ts +1 -2
  59. package/dist/types/ui-color/ColorPalette/Color/index.d.ts +2 -1
  60. package/dist/types/ui-color/ColorPalette/index.d.ts +1 -0
  61. package/dist/types/ui-menu/ArrowKeyNavigationProvider/MenuArrowKeyNavigationProvider/index.d.ts +1 -1
  62. package/dist/types/ui-menu/ArrowKeyNavigationProvider/types.d.ts +1 -0
  63. package/dist/types/ui-menu/DropdownMenu/types.d.ts +4 -1
  64. package/dist/types-ts4.5/analytics/types/enums.d.ts +3 -1
  65. package/dist/types-ts4.5/extensibility/extensionNodeView.d.ts +1 -2
  66. package/dist/types-ts4.5/keymaps/index.d.ts +1 -0
  67. package/dist/types-ts4.5/link/ConfigureLinkOverlay/Dropdown.d.ts +5 -4
  68. package/dist/types-ts4.5/link/ConfigureLinkOverlay/index.d.ts +2 -2
  69. package/dist/types-ts4.5/link/ConfigureLinkOverlay/useLinkOverlayAnalyticsEvents.d.ts +5 -0
  70. package/dist/types-ts4.5/react-node-view/index.d.ts +2 -5
  71. package/dist/types-ts4.5/selection-based-node-view/SelectionBasedNodeView.d.ts +1 -2
  72. package/dist/types-ts4.5/types/plugin-factory.d.ts +1 -2
  73. package/dist/types-ts4.5/ui-color/ColorPalette/Color/index.d.ts +2 -1
  74. package/dist/types-ts4.5/ui-color/ColorPalette/index.d.ts +1 -0
  75. package/dist/types-ts4.5/ui-menu/ArrowKeyNavigationProvider/MenuArrowKeyNavigationProvider/index.d.ts +1 -1
  76. package/dist/types-ts4.5/ui-menu/ArrowKeyNavigationProvider/types.d.ts +1 -0
  77. package/dist/types-ts4.5/ui-menu/DropdownMenu/types.d.ts +4 -1
  78. package/package.json +4 -6
  79. package/dist/cjs/ui/PortalProvider/index.js +0 -235
  80. package/dist/es2019/ui/PortalProvider/index.js +0 -171
  81. package/dist/esm/ui/PortalProvider/index.js +0 -229
  82. package/dist/types/ui/PortalProvider/index.d.ts +0 -48
  83. package/dist/types-ts4.5/ui/PortalProvider/index.d.ts +0 -48
  84. package/portal-provider/package.json +0 -15
@@ -105,7 +105,7 @@ var DropdownMenuWrapper = exports.default = /*#__PURE__*/function (_PureComponen
105
105
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "handleCloseAndFocus", function (event) {
106
106
  var _this$state$target;
107
107
  (_this$state$target = _this.state.target) === null || _this$state$target === void 0 || (_this$state$target = _this$state$target.querySelector('button')) === null || _this$state$target === void 0 || _this$state$target.focus();
108
- if ((0, _platformFeatureFlags.getBooleanFF)('platform.editor.a11y-table-context-menu_y4c9c')) {
108
+ if ((0, _platformFeatureFlags.fg)('platform.editor.a11y-table-context-menu_y4c9c')) {
109
109
  _this.handleClose(event);
110
110
  } else {
111
111
  _this.handleClose();
@@ -114,7 +114,7 @@ var DropdownMenuWrapper = exports.default = /*#__PURE__*/function (_PureComponen
114
114
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "handleClose", function (event) {
115
115
  var onOpenChange = _this.props.onOpenChange;
116
116
  if (onOpenChange) {
117
- if ((0, _platformFeatureFlags.getBooleanFF)('platform.editor.a11y-table-context-menu_y4c9c')) {
117
+ if ((0, _platformFeatureFlags.fg)('platform.editor.a11y-table-context-menu_y4c9c')) {
118
118
  onOpenChange({
119
119
  isOpen: false,
120
120
  event: event
@@ -149,7 +149,8 @@ var DropdownMenuWrapper = exports.default = /*#__PURE__*/function (_PureComponen
149
149
  onItemActivated = _this$props.onItemActivated,
150
150
  arrowKeyNavigationProviderOptions = _this$props.arrowKeyNavigationProviderOptions,
151
151
  section = _this$props.section,
152
- isAllowEnterDefaultBehavior = _this$props.isAllowEnterDefaultBehavior;
152
+ allowEnterDefaultBehavior = _this$props.allowEnterDefaultBehavior,
153
+ handleEscapeKeydown = _this$props.handleEscapeKeydown;
153
154
  // Note that this onSelection function can't be refactored to useMemo for
154
155
  // performance gains as it is being used as a dependency in a useEffect in
155
156
  // MenuArrowKeyNavigationProvider in order to check for re-renders to adjust
@@ -190,10 +191,10 @@ var DropdownMenuWrapper = exports.default = /*#__PURE__*/function (_PureComponen
190
191
  shouldFitContainer: true,
191
192
  isTriggerNotTabbable: true,
192
193
  handleClickOutside: this.handleClose,
193
- handleEscapeKeydown: this.handleCloseAndFocus,
194
+ handleEscapeKeydown: (0, _platformFeatureFlags.fg)('platform-editor-a11y-image-border-options-dropdown') ? handleEscapeKeydown || this.handleCloseAndFocus : this.handleCloseAndFocus,
194
195
  handleEnterKeydown: function handleEnterKeydown(e) {
195
- if ((0, _platformFeatureFlags.getBooleanFF)('platform.editor.a11y-table-context-menu_y4c9c')) {
196
- if (!isAllowEnterDefaultBehavior) {
196
+ if ((0, _platformFeatureFlags.fg)('platform.editor.a11y-table-context-menu_y4c9c') || (0, _platformFeatureFlags.fg)('platform-editor-a11y-image-border-options-dropdown')) {
197
+ if (!allowEnterDefaultBehavior) {
197
198
  e.preventDefault();
198
199
  }
199
200
  } else {
@@ -255,7 +256,7 @@ var DropdownMenuWrapper = exports.default = /*#__PURE__*/function (_PureComponen
255
256
  key: 'ArrowDown',
256
257
  bubbles: true
257
258
  });
258
- if (mountTo && (0, _platformFeatureFlags.getBooleanFF)('platform.editor.a11y-main-toolbar-navigation_osrty')) {
259
+ if (mountTo && (0, _platformFeatureFlags.fg)('platform.editor.a11y-main-toolbar-navigation_osrty')) {
259
260
  mountTo.dispatchEvent(keyboardEvent);
260
261
  return;
261
262
  }
@@ -306,17 +307,38 @@ function DropdownMenuItem(_ref) {
306
307
  var _handleSubmenuActive = function _handleSubmenuActive(event) {
307
308
  setSubmenuActive(Boolean(event.target instanceof HTMLElement && event.target.closest(".".concat(_styles.DropdownMenuSharedCssClassName.SUBMENU))));
308
309
  };
310
+ var ariaLabel;
311
+ if ((0, _platformFeatureFlags.fg)('platform-editor-a11y-image-border-options-dropdown')) {
312
+ ariaLabel = item['aria-label'] === '' ? undefined : item['aria-label'] || String(item.content);
313
+ } else {
314
+ ariaLabel = item['aria-label'] || String(item.content);
315
+ }
316
+ var testId;
317
+ if ((0, _platformFeatureFlags.fg)('platform-editor-a11y-image-border-options-dropdown')) {
318
+ testId = item['data-testid'] || "dropdown-item__".concat(item.content);
319
+ } else {
320
+ testId = "dropdown-item__".concat(String(item.content));
321
+ }
322
+
323
+ // From time to time we don't want to have any tabIndex on item wrapper
324
+ // especially when we pass any interactive element as a item.content
325
+ var tabIndex;
326
+ if ((0, _platformFeatureFlags.fg)('platform-editor-a11y-image-border-options-dropdown')) {
327
+ tabIndex = item.wrapperTabIndex === null ? undefined : item.wrapperTabIndex || -1;
328
+ } else {
329
+ tabIndex = -1;
330
+ }
309
331
  var dropListItem = (0, _react2.jsx)("div", {
310
332
  css: function css() {
311
333
  return buttonStyles(item.isActive, submenuActive);
312
334
  },
313
- tabIndex: -1,
335
+ tabIndex: tabIndex,
314
336
  "aria-disabled": item.isDisabled ? 'true' : 'false',
315
337
  onMouseDown: _handleSubmenuActive
316
338
  }, (0, _react2.jsx)(_menu.CustomItem, {
317
339
  item: item,
318
340
  key: (_item$key2 = item.key) !== null && _item$key2 !== void 0 ? _item$key2 : String(item.content),
319
- testId: "dropdown-item__".concat(String(item.content)),
341
+ testId: testId,
320
342
  role: shouldUseDefaultRole ? 'button' : 'menuitem',
321
343
  iconBefore: item.elemBefore,
322
344
  iconAfter: item.elemAfter,
@@ -326,7 +348,7 @@ function DropdownMenuItem(_ref) {
326
348
  item: item
327
349
  });
328
350
  },
329
- "aria-label": item['aria-label'] || String(item.content),
351
+ "aria-label": ariaLabel,
330
352
  "aria-pressed": shouldUseDefaultRole ? item.isActive : undefined,
331
353
  "aria-keyshortcuts": item['aria-keyshortcuts'],
332
354
  onMouseDown: function onMouseDown(e) {
@@ -343,7 +365,7 @@ function DropdownMenuItem(_ref) {
343
365
  item: item
344
366
  });
345
367
  },
346
- "aria-expanded": (0, _platformFeatureFlags.getBooleanFF)('platform.editor.a11y-table-context-menu_y4c9c') ? item['aria-expanded'] : undefined
368
+ "aria-expanded": (0, _platformFeatureFlags.fg)('platform.editor.a11y-table-context-menu_y4c9c') ? item['aria-expanded'] : undefined
347
369
  }, item.content));
348
370
  if (item.tooltipDescription) {
349
371
  var _item$key3;
@@ -235,6 +235,7 @@ export let ACTION_SUBJECT = /*#__PURE__*/function (ACTION_SUBJECT) {
235
235
  ACTION_SUBJECT["DRAG"] = "drag";
236
236
  ACTION_SUBJECT["ELEMENT"] = "element";
237
237
  ACTION_SUBJECT["CONTEXT_MENU"] = "contextMenu";
238
+ ACTION_SUBJECT["INLINE_DIALOG"] = "inlineDialog";
238
239
  return ACTION_SUBJECT;
239
240
  }({});
240
241
  export let ACTION_SUBJECT_ID = /*#__PURE__*/function (ACTION_SUBJECT_ID) {
@@ -349,6 +350,7 @@ export let ACTION_SUBJECT_ID = /*#__PURE__*/function (ACTION_SUBJECT_ID) {
349
350
  ACTION_SUBJECT_ID["SAVE"] = "save";
350
351
  ACTION_SUBJECT_ID["SECTION"] = "section";
351
352
  ACTION_SUBJECT_ID["SMART_LINK"] = "smartLink";
353
+ ACTION_SUBJECT_ID["SMART_LINK_TOOLBAR"] = "smartLinkToolbar";
352
354
  ACTION_SUBJECT_ID["STATUS"] = "status";
353
355
  ACTION_SUBJECT_ID["SYMBOL"] = "symbol";
354
356
  ACTION_SUBJECT_ID["TABLE"] = "table";
@@ -53,13 +53,12 @@ export class ExtensionNode extends ReactNodeView {
53
53
  }
54
54
  export default function ExtensionNodeView(portalProviderAPI, eventDispatcher, providerFactory, extensionHandlers, extensionNodeViewOptions, pluginInjectionApi, macroInteractionDesignFeatureFlags) {
55
55
  return (node, view, getPos) => {
56
- const hasIntlContext = true;
57
56
  return new ExtensionNode(node, view, getPos, portalProviderAPI, eventDispatcher, {
58
57
  providerFactory,
59
58
  extensionHandlers,
60
59
  extensionNodeViewOptions,
61
60
  pluginInjectionApi,
62
61
  macroInteractionDesignFeatureFlags
63
- }, undefined, undefined, undefined, hasIntlContext).init();
62
+ }).init();
64
63
  };
65
64
  }
@@ -98,6 +98,7 @@ export const toggleHighlightPalette = makeKeyMapWithCommon('Toggle Highlight Pal
98
98
  export const focusToContextMenuTrigger = makeKeyMapWithCommon('Focus table context menu trigger', 'Shift-F10');
99
99
  export const dragToMoveUp = makeKeyMapWithCommon('Move node up in the document', 'Ctrl-Alt-Shift-ArrowUp');
100
100
  export const dragToMoveDown = makeKeyMapWithCommon('Move node down in the document', 'Ctrl-Alt-Shift-ArrowDown');
101
+ export const showElementDragHandle = makeKeyMapWithCommon('Show drag handle for editor element', 'Ctrl-Alt-Shift-a');
101
102
  const arrowKeysMap = {
102
103
  // for reference: https://wincent.com/wiki/Unicode_representations_of_modifier_keys
103
104
  ARROWLEFT: '\u2190',
@@ -1,6 +1,5 @@
1
1
  import { base, keyName } from 'w3c-keyname';
2
2
  import { keydownHandler } from '@atlaskit/editor-prosemirror/keymap';
3
- import { getBooleanFF } from '@atlaskit/platform-feature-flags';
4
3
  import { SafePlugin } from '../safe-plugin';
5
4
 
6
5
  /**
@@ -14,52 +13,35 @@ export function keymap(bindings) {
14
13
  return new SafePlugin({
15
14
  props: {
16
15
  handleKeyDown(view, event) {
17
- if (getBooleanFF('platform.editor.text-alignment-keyboard-shortcuts')) {
18
- const name = keyName(event);
19
- let keyboardEvent = event;
16
+ const name = keyName(event);
17
+ let keyboardEvent = event;
20
18
 
21
- // We will try to bypass the keycode only if any of mod keys are pressed,
22
- // to allow users to use non-latin and Dead characters.
23
- const isModKeyPressed = event.ctrlKey || event.metaKey;
19
+ // We will try to bypass the keycode only if any of mod keys are pressed,
20
+ // to allow users to use non-latin and Dead characters.
21
+ const isModKeyPressed = event.ctrlKey || event.metaKey;
24
22
 
25
- // Check the unicode of the character to assert that it's not an ASCII character.
26
- // These are characters outside latin's range.
27
- const isNonLatinKey = name.length === 1 && /[^\u0000-\u007f]/.test(name);
23
+ // Check the unicode of the character to assert that it's not an ASCII character.
24
+ // These are characters outside latin's range.
25
+ const isNonLatinKey = name.length === 1 && /[^\u0000-\u007f]/.test(name);
28
26
 
29
- // The `Dead` key is a key that combines with a following key to produce a combined character.
30
- // It will have `even.key === 'Dead'` in some browsers but the `keyCode` will be the same as in a qwerty-keyboard.
31
- // See https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key and https://en.wikipedia.org/wiki/Dead_key
32
- const isDeadKey = name === 'Dead';
33
- if (isModKeyPressed && (isNonLatinKey || isDeadKey)) {
34
- keyboardEvent = new KeyboardEvent(event.type, {
35
- // FIXME: The event.keyCode is deprecated (see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode),
36
- // and could be removed in any time, but the w3c-keyname library doesn't provide a way to get
37
- // a key by event.code.
38
- key: base[event.keyCode],
39
- code: event.code,
40
- ctrlKey: event.ctrlKey,
41
- altKey: event.altKey,
42
- metaKey: event.metaKey,
43
- shiftKey: event.shiftKey
44
- });
45
- }
46
- return keydownHandler(bindings)(view, keyboardEvent);
47
- } else {
48
- const name = keyName(event);
49
- let keyboardEvent = event;
50
- if (event.ctrlKey && name.length === 1 &&
51
- // Check the unicode of the character to
52
- // assert that its not an ASCII character.
53
- // These are characters outside Latin's range.
54
- /[^\u0000-\u007f]/.test(name)) {
55
- keyboardEvent = new KeyboardEvent('keydown', {
56
- key: base[event.keyCode],
57
- code: event.code,
58
- ctrlKey: true
59
- });
60
- }
61
- return keydownHandler(bindings)(view, keyboardEvent);
27
+ // The `Dead` key is a key that combines with a following key to produce a combined character.
28
+ // It will have `even.key === 'Dead'` in some browsers but the `keyCode` will be the same as in a qwerty-keyboard.
29
+ // See https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key and https://en.wikipedia.org/wiki/Dead_key
30
+ const isDeadKey = name === 'Dead';
31
+ if (isModKeyPressed && (isNonLatinKey || isDeadKey)) {
32
+ keyboardEvent = new KeyboardEvent(event.type, {
33
+ // FIXME: The event.keyCode is deprecated (see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode),
34
+ // and could be removed in any time, but the w3c-keyname library doesn't provide a way to get
35
+ // a key by event.code.
36
+ key: base[event.keyCode],
37
+ code: event.code,
38
+ ctrlKey: event.ctrlKey,
39
+ altKey: event.altKey,
40
+ metaKey: event.metaKey,
41
+ shiftKey: event.shiftKey
42
+ });
62
43
  }
44
+ return keydownHandler(bindings)(view, keyboardEvent);
63
45
  }
64
46
  }
65
47
  });
@@ -5,28 +5,46 @@ import { useCallback } from 'react';
5
5
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
6
6
  import { jsx } from '@emotion/react';
7
7
  import { useIntl } from 'react-intl-next';
8
+ import { withAnalyticsContext } from '@atlaskit/analytics-next';
8
9
  import DropdownMenu, { DropdownItem, DropdownItemGroup } from '@atlaskit/dropdown-menu';
9
10
  import ChevronDownIcon from '@atlaskit/icon/glyph/chevron-down';
10
11
  import PreferencesIcon from '@atlaskit/icon/glyph/preferences';
11
12
  import ShortcutIcon from '@atlaskit/icon/glyph/shortcut';
12
13
  import { cardMessages as messages } from '../../messages';
13
14
  import { StyledButton } from './StyledButton';
15
+ import { useLinkOverlayAnalyticsEvents } from './useLinkOverlayAnalyticsEvents';
16
+ const SMALL_LINK_TOOLBAR_ANALYTICS_SOURCE = 'smallLinkToolbar';
14
17
  const Dropdown = ({
15
- testId,
16
- onDropdownChange
18
+ onDropdownChange,
19
+ testId
17
20
  }) => {
18
21
  const {
19
22
  formatMessage
20
23
  } = useIntl();
21
24
  const configureLinkLabel = formatMessage(messages.inlineConfigureLink);
22
25
  const goToLinkLabel = formatMessage(messages.inlineGoToLink);
26
+ const {
27
+ fireActionClickEvent,
28
+ fireLinkClickEvent,
29
+ fireToolbarViewEvent
30
+ } = useLinkOverlayAnalyticsEvents();
23
31
  const onOpenChange = useCallback(({
24
32
  isOpen
25
33
  }) => {
26
34
  onDropdownChange === null || onDropdownChange === void 0 ? void 0 : onDropdownChange(isOpen);
27
- }, [onDropdownChange]);
35
+ if (isOpen) {
36
+ fireToolbarViewEvent();
37
+ }
38
+ }, [fireToolbarViewEvent, onDropdownChange]);
39
+ const onGoToLinkClick = useCallback(() => {
40
+ fireActionClickEvent('goToLink');
41
+ }, [fireActionClickEvent]);
42
+ const onConfigureClick = useCallback(() => {
43
+ fireActionClickEvent('configureLink');
44
+ }, [fireActionClickEvent]);
28
45
  return jsx(DropdownMenu, {
29
46
  trigger: ({
47
+ onClick,
30
48
  triggerRef,
31
49
  ...props
32
50
  }) => jsx(StyledButton, _extends({
@@ -35,7 +53,11 @@ const Dropdown = ({
35
53
  iconBefore: jsx(ChevronDownIcon, {
36
54
  label: configureLinkLabel,
37
55
  size: 'small'
38
- })
56
+ }),
57
+ onClick: e => {
58
+ onClick === null || onClick === void 0 ? void 0 : onClick(e);
59
+ fireLinkClickEvent();
60
+ }
39
61
  })),
40
62
  testId: `${testId}-dropdown`,
41
63
  onOpenChange: onOpenChange
@@ -43,12 +65,16 @@ const Dropdown = ({
43
65
  elemBefore: jsx(ShortcutIcon, {
44
66
  label: goToLinkLabel,
45
67
  size: 'medium'
46
- })
68
+ }),
69
+ onClick: onGoToLinkClick
47
70
  }, goToLinkLabel), jsx(DropdownItem, {
48
71
  elemBefore: jsx(PreferencesIcon, {
49
72
  label: configureLinkLabel,
50
73
  size: 'medium'
51
- })
74
+ }),
75
+ onClick: onConfigureClick
52
76
  }, configureLinkLabel)));
53
77
  };
54
- export default Dropdown;
78
+ export default withAnalyticsContext({
79
+ source: SMALL_LINK_TOOLBAR_ANALYTICS_SOURCE
80
+ })(Dropdown);
@@ -4,6 +4,7 @@ import { useCallback, useLayoutEffect, useState } from 'react';
4
4
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
5
5
  import { css, jsx } from '@emotion/react';
6
6
  import { useIntl } from 'react-intl-next';
7
+ import { withAnalyticsContext } from '@atlaskit/analytics-next';
7
8
  import { NodeSelection, TextSelection } from '@atlaskit/editor-prosemirror/state';
8
9
  import PreferencesIcon from '@atlaskit/icon/glyph/preferences';
9
10
  import { N0 } from '@atlaskit/theme/colors';
@@ -12,6 +13,7 @@ import Tooltip from '@atlaskit/tooltip';
12
13
  import { cardMessages } from '../../messages';
13
14
  import Dropdown from './Dropdown';
14
15
  import { StyledButton } from './StyledButton';
16
+ import { useLinkOverlayAnalyticsEvents } from './useLinkOverlayAnalyticsEvents';
15
17
  const buttonWrapperStyles = css({
16
18
  position: 'absolute',
17
19
  zIndex: layers.card(),
@@ -22,7 +24,7 @@ const buttonWrapperStyles = css({
22
24
  borderRadius: "var(--ds-border-radius, 3px)"
23
25
  });
24
26
  const showDropdownThresholdPx = 50;
25
- export const OverlayButton = ({
27
+ export const OverlayButton = withAnalyticsContext()(({
26
28
  editorView,
27
29
  testId = 'link-configure-overlay-button',
28
30
  targetElementPos = 0,
@@ -34,6 +36,10 @@ export const OverlayButton = ({
34
36
  } = useIntl();
35
37
  const configureLinkLabel = formatMessage(cardMessages.inlineConfigureLink);
36
38
  const [showDropdown, setShowDropdown] = useState(false);
39
+ const {
40
+ fireLinkClickEvent,
41
+ fireActionClickEvent
42
+ } = useLinkOverlayAnalyticsEvents();
37
43
  useLayoutEffect(() => {
38
44
  var _domNode;
39
45
  let domNode = editorView.nodeDOM(targetElementPos);
@@ -52,7 +58,7 @@ export const OverlayButton = ({
52
58
  const docNode = editorView.state.doc.nodeAt(targetElementPos);
53
59
  const nodeEnd = targetElementPos + ((_docNode$nodeSize = docNode === null || docNode === void 0 ? void 0 : docNode.nodeSize) !== null && _docNode$nodeSize !== void 0 ? _docNode$nodeSize : 0);
54
60
  const isText = docNode === null || docNode === void 0 ? void 0 : docNode.isText;
55
- const handleClick = useCallback(() => {
61
+ const handleConfigureClick = useCallback(() => {
56
62
  const tr = editorView.state.tr;
57
63
  if (isText) {
58
64
  tr.setSelection(TextSelection.create(tr.doc, targetElementPos, Math.min(nodeEnd, tr.doc.nodeSize)));
@@ -60,7 +66,12 @@ export const OverlayButton = ({
60
66
  tr.setSelection(NodeSelection.create(tr.doc, targetElementPos));
61
67
  }
62
68
  editorView.dispatch(tr);
63
- }, [isText, editorView, nodeEnd, targetElementPos]);
69
+ }, [editorView, isText, targetElementPos, nodeEnd]);
70
+ const handleConfigureClickWithAnalytics = useCallback(() => {
71
+ fireLinkClickEvent();
72
+ fireActionClickEvent('configureLink');
73
+ handleConfigureClick();
74
+ }, [fireActionClickEvent, fireLinkClickEvent, handleConfigureClick]);
64
75
  const {
65
76
  from,
66
77
  to
@@ -80,11 +91,11 @@ export const OverlayButton = ({
80
91
  hideTooltipOnClick: true,
81
92
  testId: `${testId}-tooltip`
82
93
  }, jsx(StyledButton, {
83
- onClick: handleClick,
94
+ onClick: handleConfigureClickWithAnalytics,
84
95
  iconBefore: jsx(PreferencesIcon, {
85
96
  label: configureLinkLabel,
86
97
  size: "small",
87
98
  testId: `${testId}-configure-icon`
88
99
  })
89
100
  })));
90
- };
101
+ });
@@ -0,0 +1,39 @@
1
+ import { useMemo } from 'react';
2
+ import { FabricChannel } from '@atlaskit/analytics-listeners';
3
+ import { useAnalyticsEvents } from '@atlaskit/analytics-next';
4
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '../../analytics';
5
+ export const useLinkOverlayAnalyticsEvents = () => {
6
+ const {
7
+ createAnalyticsEvent
8
+ } = useAnalyticsEvents();
9
+ return useMemo(() => ({
10
+ fireActionClickEvent: linkAction => {
11
+ createAnalyticsEvent({
12
+ action: ACTION.CLICKED,
13
+ actionSubject: ACTION_SUBJECT.BUTTON,
14
+ eventType: EVENT_TYPE.UI,
15
+ attributes: {
16
+ action: linkAction
17
+ }
18
+ }).fire(FabricChannel.media);
19
+ },
20
+ fireLinkClickEvent: () => {
21
+ createAnalyticsEvent({
22
+ action: ACTION.CLICKED,
23
+ actionSubject: ACTION_SUBJECT.LINK,
24
+ eventType: EVENT_TYPE.UI
25
+ }).fire(FabricChannel.media);
26
+ },
27
+ fireToolbarViewEvent: () => {
28
+ createAnalyticsEvent({
29
+ action: ACTION.VIEWED,
30
+ actionSubject: ACTION_SUBJECT.INLINE_DIALOG,
31
+ actionSubjectId: ACTION_SUBJECT_ID.SMART_LINK_TOOLBAR,
32
+ eventType: EVENT_TYPE.SCREEN,
33
+ attributes: {
34
+ linkType: 'smallLink'
35
+ }
36
+ }).fire(FabricChannel.media);
37
+ }
38
+ }), [createAnalyticsEvent]);
39
+ };
@@ -1,7 +1,7 @@
1
1
  import { isFedRamp } from './environment';
2
2
  const SENTRY_DSN = 'https://0b10c8e02fb44d8796c047b102c9bee8@o55978.ingest.sentry.io/4505129224110080';
3
3
  const packageName = 'editor-common'; // Sentry doesn't accept '/' in its releases https://docs.sentry.io/platforms/javascript/configuration/releases/
4
- const packageVersion = "84.5.1";
4
+ const packageVersion = "85.1.0";
5
5
  const sanitiseSentryEvents = (data, _hint) => {
6
6
  // Remove URL as it has UGC
7
7
  // TODO: Sanitise the URL instead of just removing it
@@ -58,9 +58,7 @@ function createNodeView({
58
58
  nodeViewParams,
59
59
  Component,
60
60
  extraComponentProps
61
- }), domRef, key, false,
62
- // node views should be rendered with intl context
63
- true);
61
+ }), domRef, key);
64
62
  }
65
63
  const {
66
64
  samplingRate,
@@ -117,7 +115,7 @@ function createNodeView({
117
115
  // When prosemirror destroys the node view, we need to clean up
118
116
  // what we have previously rendered using the editor portal
119
117
  // provider api.
120
- pmPluginFactoryParams.portalProviderAPI.remove(key, domRef);
118
+ pmPluginFactoryParams.portalProviderAPI.remove(key);
121
119
  // @ts-expect-error Expect an error as domRef is expected to be
122
120
  // of HTMLSpanElement type however once the node view has
123
121
  // been destroyed no other consumers should still be using it.
@@ -9,7 +9,7 @@ import { analyticsEventKey } from '../utils/analytics';
9
9
  import { generateUniqueNodeKey } from './generateUniqueNodeKey';
10
10
  export { getInlineNodeViewProducer, inlineNodeViewClassname } from './getInlineNodeViewProducer';
11
11
  export default class ReactNodeView {
12
- constructor(_node, view, getPos, portalProviderAPI, eventDispatcher, reactComponentProps, reactComponent, hasAnalyticsContext = false, viewShouldUpdate, hasIntlContext = false) {
12
+ constructor(_node, view, getPos, portalProviderAPI, eventDispatcher, reactComponentProps, reactComponent, viewShouldUpdate) {
13
13
  _defineProperty(this, "decorations", []);
14
14
  _defineProperty(this, "handleRef", node => this._handleRef(node));
15
15
  _defineProperty(this, "dispatchAnalyticsEvent", payload => {
@@ -26,10 +26,8 @@ export default class ReactNodeView {
26
26
  this.portalProviderAPI = portalProviderAPI;
27
27
  this.reactComponentProps = reactComponentProps || {};
28
28
  this.reactComponent = reactComponent;
29
- this.hasAnalyticsContext = hasAnalyticsContext;
30
29
  this._viewShouldUpdate = viewShouldUpdate;
31
30
  this.eventDispatcher = eventDispatcher;
32
- this.hasIntlContext = hasIntlContext;
33
31
  this.key = generateUniqueNodeKey();
34
32
  }
35
33
 
@@ -92,7 +90,7 @@ export default class ReactNodeView {
92
90
  dispatchAnalyticsEvent: this.dispatchAnalyticsEvent
93
91
  }, component());
94
92
  };
95
- this.portalProviderAPI.render(componentWithErrorBoundary, this.domRef, this.key, this.hasAnalyticsContext, this.hasIntlContext);
93
+ this.portalProviderAPI.render(componentWithErrorBoundary, this.domRef, this.key);
96
94
  }
97
95
  createDomRef() {
98
96
  if (!this.node.isInline) {
@@ -165,11 +163,11 @@ export default class ReactNodeView {
165
163
  if (!this.domRef) {
166
164
  return;
167
165
  }
168
- this.portalProviderAPI.remove(this.key, this.domRef);
166
+ this.portalProviderAPI.remove(this.key);
169
167
  this.domRef = undefined;
170
168
  this.contentDOM = undefined;
171
169
  }
172
- static fromComponent(component, portalProviderAPI, eventDispatcher, props, viewShouldUpdate, hasIntlContext = false) {
173
- return (node, view, getPos) => new ReactNodeView(node, view, getPos, portalProviderAPI, eventDispatcher, props, component, false, viewShouldUpdate, hasIntlContext).init();
170
+ static fromComponent(component, portalProviderAPI, eventDispatcher, props, viewShouldUpdate) {
171
+ return (node, view, getPos) => new ReactNodeView(node, view, getPos, portalProviderAPI, eventDispatcher, props, component, viewShouldUpdate).init();
174
172
  }
175
173
  }
@@ -1,5 +1,6 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import ReactNodeView from '../react-node-view';
3
+
3
4
  /**
4
5
  * A ReactNodeView that handles React components sensitive
5
6
  * to selection changes.
@@ -25,8 +26,8 @@ import ReactNodeView from '../react-node-view';
25
26
  */
26
27
 
27
28
  export class SelectionBasedNodeView extends ReactNodeView {
28
- constructor(node, view, getPos, portalProviderAPI, eventDispatcher, reactComponentProps, reactComponent, hasContext = false, viewShouldUpdate, hasIntlContext = false) {
29
- super(node, view, getPos, portalProviderAPI, eventDispatcher, reactComponentProps, reactComponent, hasContext, viewShouldUpdate, hasIntlContext);
29
+ constructor(node, view, getPos, portalProviderAPI, eventDispatcher, reactComponentProps, reactComponent, viewShouldUpdate) {
30
+ super(node, view, getPos, portalProviderAPI, eventDispatcher, reactComponentProps, reactComponent, viewShouldUpdate);
30
31
  _defineProperty(this, "isSelectedNode", false);
31
32
  _defineProperty(this, "isNodeInsideSelection", (from, to, pos, posEnd) => {
32
33
  ({
@@ -9,7 +9,7 @@ import { createAndFireEvent, withAnalyticsContext, withAnalyticsEvents } from '@
9
9
  import { N0, N50A, N60A, N900 } from '@atlaskit/theme/colors';
10
10
  import Layer from '../Layer';
11
11
  const packageName = "@atlaskit/editor-common";
12
- const packageVersion = "84.5.1";
12
+ const packageVersion = "85.1.0";
13
13
  const halfFocusRing = 1;
14
14
  const dropOffset = '0, 8';
15
15
  class DropList extends Component {
@@ -39,6 +39,18 @@ const Color = props => {
39
39
  e.preventDefault();
40
40
  onClick(value, label);
41
41
  };
42
+ const onKeyDown = e => {
43
+ const {
44
+ onKeyDown,
45
+ value,
46
+ label
47
+ } = props;
48
+ if (!onKeyDown) {
49
+ return undefined;
50
+ }
51
+ e.preventDefault();
52
+ onKeyDown(value, label, e);
53
+ };
42
54
  return jsx(Tooltip, {
43
55
  content: label
44
56
  }, jsx("span", {
@@ -52,6 +64,7 @@ const Color = props => {
52
64
  role: "radio",
53
65
  "aria-checked": isSelected,
54
66
  onClick: onClick,
67
+ onKeyDown: onKeyDown,
55
68
  onMouseDown: onMouseDown,
56
69
  tabIndex: tabIndex
57
70
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
@@ -39,6 +39,7 @@ const ColorPalette = props => {
39
39
  const {
40
40
  cols = DEFAULT_COLOR_PICKER_COLUMNS,
41
41
  onClick,
42
+ onKeyDown,
42
43
  selectedColor,
43
44
  className,
44
45
  intl: {
@@ -87,6 +88,7 @@ const ColorPalette = props => {
87
88
  borderColor: border,
88
89
  label: message ? formatMessage(message) : label,
89
90
  onClick: onClick,
91
+ onKeyDown: onKeyDown,
90
92
  isSelected: value === selectedColor,
91
93
  checkMarkColor: getCheckMarkColor(value, useIconToken),
92
94
  hexToPaletteColor: hexToPaletteColor,
@@ -1,5 +1,5 @@
1
1
  import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
2
- import { getBooleanFF } from '@atlaskit/platform-feature-flags';
2
+ import { fg } from '@atlaskit/platform-feature-flags';
3
3
  const hasEnabledItems = list => list.some(item => item.getAttribute('aria-disabled') !== 'true');
4
4
 
5
5
  /**
@@ -14,11 +14,12 @@ export const MenuArrowKeyNavigationProvider = ({
14
14
  closeOnTab,
15
15
  onSelection,
16
16
  editorRef,
17
- popupsMountPoint
17
+ popupsMountPoint,
18
+ disableCloseOnArrowClick
18
19
  }) => {
19
20
  const wrapperRef = useRef(null);
20
21
  const [currentSelectedItemIndex, setCurrentSelectedItemIndex] = useState(-1);
21
- const element = getBooleanFF('platform.editor.a11y-main-toolbar-navigation_osrty') && popupsMountPoint ? [popupsMountPoint, editorRef.current] : [editorRef.current];
22
+ const element = popupsMountPoint && fg('platform.editor.a11y-main-toolbar-navigation_osrty') ? [popupsMountPoint, editorRef.current] : [editorRef.current];
22
23
  const [listenerTargetElement] = useState(element);
23
24
  const incrementIndex = useCallback(list => {
24
25
  const currentIndex = currentSelectedItemIndex;
@@ -111,7 +112,13 @@ export const MenuArrowKeyNavigationProvider = ({
111
112
  if (targetElement instanceof HTMLElement && !targetElement.closest('.custom-key-handler-wrapper')) {
112
113
  return;
113
114
  }
114
- handleClose(event);
115
+ if (fg('platform-editor-a11y-image-border-options-dropdown')) {
116
+ if (!disableCloseOnArrowClick) {
117
+ handleClose(event);
118
+ }
119
+ } else {
120
+ handleClose(event);
121
+ }
115
122
  if (targetElement instanceof HTMLElement && !targetElement.closest('[data-testid="editor-floating-toolbar"]')) {
116
123
  keyDownHandlerContext === null || keyDownHandlerContext === void 0 ? void 0 : keyDownHandlerContext.handleArrowLeft();
117
124
  }
@@ -120,7 +127,13 @@ export const MenuArrowKeyNavigationProvider = ({
120
127
  if (targetElement instanceof HTMLElement && !targetElement.closest('.custom-key-handler-wrapper')) {
121
128
  return;
122
129
  }
123
- handleClose(event);
130
+ if (fg('platform-editor-a11y-image-border-options-dropdown')) {
131
+ if (!disableCloseOnArrowClick) {
132
+ handleClose(event);
133
+ }
134
+ } else {
135
+ handleClose(event);
136
+ }
124
137
  if (targetElement instanceof HTMLElement && !targetElement.closest('[data-testid="editor-floating-toolbar"]')) {
125
138
  keyDownHandlerContext === null || keyDownHandlerContext === void 0 ? void 0 : keyDownHandlerContext.handleArrowRight();
126
139
  }
@@ -145,7 +158,7 @@ export const MenuArrowKeyNavigationProvider = ({
145
158
  elem && elem.removeEventListener('keydown', handleKeyDown);
146
159
  });
147
160
  };
148
- }, [currentSelectedItemIndex, wrapperRef, handleClose, disableArrowKeyNavigation, keyDownHandlerContext, closeOnTab, onSelection, incrementIndex, decrementIndex, listenerTargetElement]);
161
+ }, [currentSelectedItemIndex, wrapperRef, handleClose, disableArrowKeyNavigation, keyDownHandlerContext, closeOnTab, onSelection, incrementIndex, decrementIndex, listenerTargetElement, disableCloseOnArrowClick]);
149
162
  return /*#__PURE__*/React.createElement("div", {
150
163
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
151
164
  className: "menu-key-handler-wrapper custom-key-handler-wrapper",