@atlaskit/editor-plugin-media 1.23.2 → 1.24.1

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.
@@ -1,5 +1,5 @@
1
1
  /** @jsx jsx */
2
- import { useRef, useState } from 'react';
2
+ import { useCallback, useEffect, useRef, useState } from 'react';
3
3
 
4
4
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
5
5
  import { jsx } from '@emotion/react';
@@ -8,11 +8,12 @@ import { imageBorderMessages as messages } from '@atlaskit/editor-common/media';
8
8
  import { DropdownMenuSharedCssClassName } from '@atlaskit/editor-common/styles';
9
9
  import { Popup } from '@atlaskit/editor-common/ui';
10
10
  import { borderColorPalette, borderPaletteTooltipMessages, ColorPalette } from '@atlaskit/editor-common/ui-color';
11
- import { ArrowKeyNavigationType, DropdownMenu, ToolbarButton } from '@atlaskit/editor-common/ui-menu';
11
+ import { ArrowKeyNavigationProvider, ArrowKeyNavigationType, DropdownMenu, ToolbarButton } from '@atlaskit/editor-common/ui-menu';
12
12
  import { hexToEditorBorderPaletteColor } from '@atlaskit/editor-palette';
13
13
  import ExpandIcon from '@atlaskit/icon/glyph/chevron-down';
14
+ import { fg } from '@atlaskit/platform-feature-flags';
14
15
  import Tooltip from '@atlaskit/tooltip';
15
- import { buttonStyle, buttonWrapperStyle, contextualMenuArrow, contextualMenuColorIcon, contextualSubMenu, itemSpacing, line, menuItemDimensions, toolbarButtonWrapper } from './styles';
16
+ import { buttonStyle, buttonWrapperStyle, contextualMenuArrow, contextualMenuColorIcon, contextualSubMenu, dropdownOptionButton, dropdownWrapper, itemSpacing, line, menuItemDimensions, toolbarButtonWrapper } from './styles';
16
17
  const ImageBorder = ({
17
18
  intl: {
18
19
  formatMessage
@@ -22,12 +23,30 @@ const ImageBorder = ({
22
23
  setBorder
23
24
  }) => {
24
25
  const popupTarget = useRef(null);
26
+ const dropDownColorOptionButton = useRef(null);
27
+ const dropDownSizeOptionButton = useRef(null);
28
+ const colorSubmenuRef = useRef(null);
29
+ const sizeSubmenuRef = useRef(null);
30
+ const openDropdownButtonRef = useRef(null);
25
31
  const enabled = !!borderMark;
26
32
  const color = borderMark === null || borderMark === void 0 ? void 0 : borderMark.color;
27
33
  const size = borderMark === null || borderMark === void 0 ? void 0 : borderMark.size;
28
34
  const [isOpen, setIsOpen] = useState(false);
35
+ const [isOpenByKeyboard, setIsOpenedByKeyboard] = useState(false);
29
36
  const [isColorSubmenuOpen, setIsColorSubmenuOpen] = useState(false);
30
37
  const [isSizeSubmenuOpen, setIsSizeSubmenuOpen] = useState(false);
38
+ const handleColorSubmenuEsc = useCallback(() => {
39
+ var _dropDownColorOptionB;
40
+ setIsOpenedByKeyboard(false);
41
+ setIsColorSubmenuOpen(false);
42
+ dropDownColorOptionButton === null || dropDownColorOptionButton === void 0 ? void 0 : (_dropDownColorOptionB = dropDownColorOptionButton.current) === null || _dropDownColorOptionB === void 0 ? void 0 : _dropDownColorOptionB.focus();
43
+ }, []);
44
+ const handleSizeSubmenuEsc = useCallback(() => {
45
+ var _dropDownSizeOptionBu;
46
+ setIsOpenedByKeyboard(false);
47
+ setIsSizeSubmenuOpen(false);
48
+ dropDownSizeOptionButton === null || dropDownSizeOptionButton === void 0 ? void 0 : (_dropDownSizeOptionBu = dropDownSizeOptionButton.current) === null || _dropDownSizeOptionBu === void 0 ? void 0 : _dropDownSizeOptionBu.focus();
49
+ }, []);
31
50
  const handleSubMenuRef = ref => {
32
51
  if (!ref) {
33
52
  return;
@@ -37,6 +56,38 @@ const ImageBorder = ({
37
56
  ref.style.left = `-${rect.width}px`;
38
57
  }
39
58
  };
59
+ const handleTriggerByKeyboard = (event, callback) => {
60
+ if (fg('platform-editor-a11y-image-border-options-dropdown')) {
61
+ if (event.key === 'Enter' || event.key === ' ') {
62
+ event.preventDefault();
63
+ callback();
64
+ setIsOpenedByKeyboard(true);
65
+ }
66
+ }
67
+ };
68
+ useEffect(() => {
69
+ if (fg('platform-editor-a11y-image-border-options-dropdown')) {
70
+ const focusFirstOption = (submenuRef, isOpen) => {
71
+ if (!isOpenByKeyboard) {
72
+ return;
73
+ }
74
+ if (isOpen && submenuRef.current) {
75
+ const firstOption = submenuRef.current.querySelector('button');
76
+ if (!firstOption) {
77
+ return;
78
+ }
79
+ firstOption.focus();
80
+ const keyboardEvent = new KeyboardEvent('keydown', {
81
+ key: 'ArrowDown',
82
+ bubbles: true
83
+ });
84
+ firstOption.dispatchEvent(keyboardEvent);
85
+ }
86
+ };
87
+ focusFirstOption(colorSubmenuRef, isColorSubmenuOpen);
88
+ focusFirstOption(sizeSubmenuRef, isSizeSubmenuOpen);
89
+ }
90
+ }, [isColorSubmenuOpen, isSizeSubmenuOpen, isOpenByKeyboard]);
40
91
  const borderSizeOptions = [{
41
92
  name: formatMessage(messages.borderSizeSubtle),
42
93
  value: 1
@@ -47,7 +98,144 @@ const ImageBorder = ({
47
98
  name: formatMessage(messages.borderSizeBold),
48
99
  value: 3
49
100
  }];
50
- const items = [{
101
+ const items = fg('platform-editor-a11y-image-border-options-dropdown') ? [{
102
+ content: jsx("div", null, jsx("button", {
103
+ ref: dropDownColorOptionButton,
104
+ type: "button",
105
+ "aria-label": "Image border options Color dropdown button",
106
+ "data-testid": "image-border-dropdown-button-color"
107
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766
108
+ ,
109
+ css: [dropdownOptionButton],
110
+ "aria-expanded": isColorSubmenuOpen,
111
+ onKeyDown: e => handleTriggerByKeyboard(e, () => setIsColorSubmenuOpen(!isColorSubmenuOpen))
112
+ }, jsx("span", null, formatMessage(messages.borderColor)), jsx("div", {
113
+ css: contextualMenuColorIcon(color && hexToEditorBorderPaletteColor(color))
114
+ })), jsx("div", {
115
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
116
+ className: DropdownMenuSharedCssClassName.SUBMENU,
117
+ ref: colorSubmenuRef
118
+ }, isColorSubmenuOpen &&
119
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766
120
+ jsx("div", {
121
+ css: contextualSubMenu(0),
122
+ ref: handleSubMenuRef
123
+ }, jsx(ArrowKeyNavigationProvider, {
124
+ type: ArrowKeyNavigationType.MENU,
125
+ handleClose: e => {
126
+ e.preventDefault();
127
+ e.stopPropagation();
128
+ handleColorSubmenuEsc();
129
+ },
130
+ disableCloseOnArrowClick: true
131
+ }, jsx(ColorPalette, {
132
+ onClick: color => {
133
+ setBorder({
134
+ color
135
+ });
136
+ setIsOpen(!isOpen);
137
+ },
138
+ onKeyDown: (color, _, event) => {
139
+ if (event.key === 'Enter' || event.key === ' ') {
140
+ var _openDropdownButtonRe;
141
+ setBorder({
142
+ color
143
+ });
144
+ setIsOpen(!isOpen);
145
+ setIsColorSubmenuOpen(false);
146
+ setIsSizeSubmenuOpen(false);
147
+ (_openDropdownButtonRe = openDropdownButtonRef.current) === null || _openDropdownButtonRe === void 0 ? void 0 : _openDropdownButtonRe.focus();
148
+ }
149
+ },
150
+ selectedColor: color !== null && color !== void 0 ? color : null,
151
+ paletteOptions: {
152
+ palette: borderColorPalette,
153
+ paletteColorTooltipMessages: borderPaletteTooltipMessages,
154
+ hexToPaletteColor: hexToEditorBorderPaletteColor
155
+ }
156
+ }))))),
157
+ 'data-testid': 'dropdown-item__Color',
158
+ key: 'dropdown-menu-image-border-color-button',
159
+ value: {
160
+ name: 'color'
161
+ },
162
+ 'aria-label': '',
163
+ wrapperTabIndex: null
164
+ }, {
165
+ content: jsx("div", null, jsx("button", {
166
+ type: "button",
167
+ "aria-label": "Image border options Size dropdown button",
168
+ "data-testid": "image-border-dropdown-button-size"
169
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766
170
+ ,
171
+ css: [dropdownOptionButton],
172
+ "aria-expanded": isSizeSubmenuOpen,
173
+ ref: dropDownSizeOptionButton,
174
+ onKeyDown: e => handleTriggerByKeyboard(e, () => setIsSizeSubmenuOpen(!isSizeSubmenuOpen))
175
+ }, jsx("span", null, formatMessage(messages.borderSize)), jsx("div", {
176
+ css: contextualMenuArrow
177
+ })), jsx("div", {
178
+ //eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
179
+ className: DropdownMenuSharedCssClassName.SUBMENU,
180
+ ref: sizeSubmenuRef
181
+ }, isSizeSubmenuOpen && jsx(ArrowKeyNavigationProvider, {
182
+ type: ArrowKeyNavigationType.MENU,
183
+ handleClose: e => {
184
+ e.preventDefault();
185
+ handleSizeSubmenuEsc();
186
+ },
187
+ disableCloseOnArrowClick: true
188
+ }, jsx("div", {
189
+ css: contextualSubMenu(1),
190
+ ref: handleSubMenuRef
191
+ }, borderSizeOptions.map(({
192
+ name,
193
+ value
194
+ }, idx) => jsx(Tooltip, {
195
+ key: idx,
196
+ content: name
197
+ }, jsx("span", {
198
+ css: buttonWrapperStyle
199
+ }, jsx("button", {
200
+ type: "button"
201
+ /* eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766 */,
202
+ css: buttonStyle(value === size),
203
+ "aria-label": name,
204
+ role: "radio",
205
+ "aria-checked": value === size,
206
+ onClick: () => {
207
+ setBorder({
208
+ size: value
209
+ });
210
+ setIsOpen(false);
211
+ },
212
+ onKeyDown: event => {
213
+ if (event.key === 'Enter' || event.key === ' ') {
214
+ var _openDropdownButtonRe2;
215
+ setBorder({
216
+ size: value
217
+ });
218
+ setIsOpen(false);
219
+ setIsColorSubmenuOpen(false);
220
+ setIsSizeSubmenuOpen(false);
221
+ (_openDropdownButtonRe2 = openDropdownButtonRef.current) === null || _openDropdownButtonRe2 === void 0 ? void 0 : _openDropdownButtonRe2.focus();
222
+ }
223
+ },
224
+ onMouseDown: e => {
225
+ e.preventDefault();
226
+ }
227
+ }, jsx("div", {
228
+ css: line(value, value === size),
229
+ role: "presentation"
230
+ }))))))))),
231
+ 'data-testid': 'dropdown-item__Size',
232
+ key: 'dropdown-menu-image-border-size-button',
233
+ value: {
234
+ name: 'size'
235
+ },
236
+ 'aria-label': '',
237
+ wrapperTabIndex: null
238
+ }] : [{
51
239
  content: formatMessage(messages.borderColor),
52
240
  value: {
53
241
  name: 'color'
@@ -123,7 +311,6 @@ const ImageBorder = ({
123
311
  role: "presentation"
124
312
  })))))))
125
313
  }];
126
-
127
314
  /**
128
315
  * We want to change direction of our dropdowns a bit early,
129
316
  * not exactly when it hits the boundary.
@@ -131,6 +318,7 @@ const ImageBorder = ({
131
318
  const fitTolerance = 10;
132
319
  const fitWidth = menuItemDimensions.width;
133
320
  const fitHeight = items.length * (menuItemDimensions.height + itemSpacing);
321
+ const isAnySubMenuOpen = isSizeSubmenuOpen || isColorSubmenuOpen;
134
322
  return jsx("div", null, jsx("div", {
135
323
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766
136
324
  css: toolbarButtonWrapper({
@@ -155,7 +343,9 @@ const ImageBorder = ({
155
343
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
156
344
  , {
157
345
  className: "image-border-toolbar-dropdown",
346
+ ref: openDropdownButtonRef,
158
347
  selected: enabled || isOpen,
348
+ "aria-expanded": fg('platform-editor-a11y-image-border-options-dropdown') ? isOpen : undefined,
159
349
  "aria-label": formatMessage(messages.borderOptions),
160
350
  title: formatMessage(messages.borderOptions),
161
351
  spacing: "compact",
@@ -164,7 +354,11 @@ const ImageBorder = ({
164
354
  }),
165
355
  onClick: () => {
166
356
  setIsOpen(!isOpen);
167
- }
357
+ if (fg('platform-editor-a11y-image-border-options-dropdown')) {
358
+ setIsOpenedByKeyboard(false);
359
+ }
360
+ },
361
+ onKeyDown: fg('platform-editor-a11y-image-border-options-dropdown') ? e => handleTriggerByKeyboard(e, () => setIsOpen(!isOpen)) : undefined
168
362
  }))), jsx(Popup, {
169
363
  target: popupTarget.current ? popupTarget.current : undefined,
170
364
  fitWidth: fitWidth + fitTolerance,
@@ -175,7 +369,9 @@ const ImageBorder = ({
175
369
  onMouseLeave: () => {
176
370
  setIsColorSubmenuOpen(false);
177
371
  setIsSizeSubmenuOpen(false);
178
- }
372
+ },
373
+ css: fg('platform-editor-a11y-image-border-options-dropdown') ? /* eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766 */
374
+ dropdownWrapper : undefined
179
375
  }, jsx(DropdownMenu
180
376
  //This needs be removed when the a11y is completely handled
181
377
  //Disabling key navigation now as it works only partially
@@ -183,16 +379,27 @@ const ImageBorder = ({
183
379
  , {
184
380
  arrowKeyNavigationProviderOptions: {
185
381
  type: ArrowKeyNavigationType.MENU,
186
- disableArrowKeyNavigation: true
382
+ disableArrowKeyNavigation: fg('platform-editor-a11y-image-border-options-dropdown') ? isAnySubMenuOpen ? true : false : true
187
383
  },
384
+ allowEnterDefaultBehavior: fg('platform-editor-a11y-image-border-options-dropdown') ? isAnySubMenuOpen ? true : false : undefined,
385
+ handleEscapeKeydown: fg('platform-editor-a11y-image-border-options-dropdown') ? isAnySubMenuOpen ? () => {
386
+ return;
387
+ } : () => {
388
+ var _openDropdownButtonRe3;
389
+ (_openDropdownButtonRe3 = openDropdownButtonRef.current) === null || _openDropdownButtonRe3 === void 0 ? void 0 : _openDropdownButtonRe3.focus();
390
+ } : undefined,
188
391
  items: [{
189
392
  items
190
393
  }],
191
394
  isOpen: isOpen,
395
+ shouldFocusFirstItem: fg('platform-editor-a11y-image-border-options-dropdown') ? () => isOpenByKeyboard : undefined,
192
396
  onOpenChange: () => {
193
397
  setIsOpen(false);
194
398
  setIsColorSubmenuOpen(false);
195
399
  setIsSizeSubmenuOpen(false);
400
+ if (fg('platform-editor-a11y-image-border-options-dropdown')) {
401
+ setIsOpenedByKeyboard(false);
402
+ }
196
403
  },
197
404
  onItemActivated: ({
198
405
  item
@@ -209,9 +416,15 @@ const ImageBorder = ({
209
416
  }) => {
210
417
  if (item.value.name === 'color') {
211
418
  setIsColorSubmenuOpen(true);
419
+ if (fg('platform-editor-a11y-image-border-options-dropdown')) {
420
+ setIsOpenedByKeyboard(false);
421
+ }
212
422
  }
213
423
  if (item.value.name === 'size') {
214
424
  setIsSizeSubmenuOpen(true);
425
+ if (fg('platform-editor-a11y-image-border-options-dropdown')) {
426
+ setIsOpenedByKeyboard(false);
427
+ }
215
428
  }
216
429
  },
217
430
  onMouseLeave: ({
@@ -129,4 +129,27 @@ export const toolbarButtonWrapper = ({
129
129
 
130
130
  ${!enabled && getHoverStyles('.image-border-toolbar-btn')}
131
131
  ${!isOpen && !enabled && getHoverStyles('.image-border-toolbar-dropdown')}
132
+ `;
133
+
134
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-exported-styles
135
+ export const dropdownOptionButton = css`
136
+ background: transparent;
137
+ border: 2px solid transparent;
138
+ display: flex;
139
+ width: 100%;
140
+ align-items: center;
141
+ justify-content: space-between;
142
+ padding: 8px 16px;
143
+
144
+ &:focus {
145
+ background-color: ${"var(--ds-background-neutral-subtle-hovered, rgb(244, 245, 247))"};
146
+ border: 2px solid ${"var(--ds-border-focused, #2684FF)"};
147
+ }
148
+ `;
149
+
150
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-exported-styles
151
+ export const dropdownWrapper = css`
152
+ span[role='menuitem'] {
153
+ padding: 0;
154
+ }
132
155
  `;
@@ -365,11 +365,10 @@ export var ReactMediaGroupNode = function ReactMediaGroupNode(portalProviderAPI,
365
365
  var mediaOptions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
366
366
  var pluginInjectionApi = arguments.length > 4 ? arguments[4] : undefined;
367
367
  return function (node, view, getPos) {
368
- var hasIntlContext = true;
369
368
  return new MediaGroupNodeView(node, view, getPos, portalProviderAPI, eventDispatcher, {
370
369
  providerFactory: providerFactory,
371
370
  mediaOptions: mediaOptions,
372
371
  pluginInjectionApi: pluginInjectionApi
373
- }, undefined, undefined, undefined, hasIntlContext).init();
372
+ }).init();
374
373
  };
375
374
  };
@@ -183,12 +183,11 @@ export var ReactMediaNode = function ReactMediaNode(portalProviderAPI, eventDisp
183
183
  var mediaOptions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
184
184
  var pluginInjectionApi = arguments.length > 4 ? arguments[4] : undefined;
185
185
  return function (node, view, getPos) {
186
- var hasIntlContext = true;
187
186
  return new MediaNodeView(node, view, getPos, portalProviderAPI, eventDispatcher, {
188
187
  eventDispatcher: eventDispatcher,
189
188
  providerFactory: providerFactory,
190
189
  mediaOptions: mediaOptions,
191
190
  pluginInjectionApi: pluginInjectionApi
192
- }, undefined, undefined, undefined, hasIntlContext).init();
191
+ }).init();
193
192
  };
194
193
  };
@@ -693,7 +693,6 @@ var MediaSingleNodeView = /*#__PURE__*/function (_ReactNodeView) {
693
693
  export var ReactMediaSingleNode = function ReactMediaSingleNode(portalProviderAPI, eventDispatcher, providerFactory, pluginInjectionApi, dispatchAnalyticsEvent) {
694
694
  var mediaOptions = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
695
695
  return function (node, view, getPos) {
696
- var hasIntlContext = true;
697
696
  return new MediaSingleNodeView(node, view, getPos, portalProviderAPI, eventDispatcher, {
698
697
  eventDispatcher: eventDispatcher,
699
698
  fullWidthMode: mediaOptions.fullWidthEnabled,
@@ -703,6 +702,6 @@ export var ReactMediaSingleNode = function ReactMediaSingleNode(portalProviderAP
703
702
  isCopyPasteEnabled: mediaOptions.isCopyPasteEnabled,
704
703
  pluginInjectionApi: pluginInjectionApi,
705
704
  editorAppearance: mediaOptions.editorAppearance
706
- }, undefined, undefined, undefined, hasIntlContext).init();
705
+ }).init();
707
706
  };
708
707
  };