UNPKG

@atlaskit/editor-plugin-media

Version:

Media plugin for @atlaskit/editor-core

499 lines (497 loc) 20.4 kB
import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; /** * @jsxRuntime classic * @jsx jsx */ import { useCallback, useEffect, useRef, useState } from 'react'; // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled, @typescript-eslint/consistent-type-imports import { css, jsx } from '@emotion/react'; import { imageBorderMessages as messages } from '@atlaskit/editor-common/media'; import { DropdownMenuSharedCssClassName } from '@atlaskit/editor-common/styles'; import { Popup } from '@atlaskit/editor-common/ui'; import { borderColorPalette, borderPaletteTooltipMessages, ColorPalette } from '@atlaskit/editor-common/ui-color'; import { ArrowKeyNavigationProvider, ArrowKeyNavigationType, DropdownMenu, ToolbarButton } from '@atlaskit/editor-common/ui-menu'; import { hexToEditorBorderPaletteColor } from '@atlaskit/editor-palette'; import BorderIcon from '@atlaskit/icon/core/border'; import ChevronDownIcon from '@atlaskit/icon/core/chevron-down'; import StrokeWeightLargeIcon from '@atlaskit/icon/core/stroke-weight-large'; import StrokeWeightMediumIcon from '@atlaskit/icon/core/stroke-weight-medium'; import StrokeWeightSmallIcon from '@atlaskit/icon/core/stroke-weight-small'; import { Text } from '@atlaskit/primitives/compiled'; import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals'; import Tooltip from '@atlaskit/tooltip'; import { buttonStyle, buttonWrapperStyle, contextualMenuArrow, contextualSubMenu, dropdownOptionButton, dropdownWrapper, itemSpacing, menuItemDimensions, toolbarButtonWrapper } from './styles'; // New padding for border options drop down var dropdownOptionButtonNew = css({ background: 'transparent', borderWidth: "var(--ds-border-width-selected, 2px)", borderStyle: 'solid', borderColor: 'transparent', display: 'flex', width: '100%', alignItems: 'center', justifyContent: 'space-between', padding: 0, '&:focus': { backgroundColor: "var(--ds-background-neutral-subtle-hovered, #0515240F)", borderColor: "var(--ds-border-focused, #4688EC)" } }); var ImageBorder = function ImageBorder(_ref) { var formatMessage = _ref.intl.formatMessage, toggleBorder = _ref.toggleBorder, borderMark = _ref.borderMark, setBorder = _ref.setBorder; var popupTarget = useRef(null); var dropDownColorOptionButton = useRef(null); var dropDownSizeOptionButton = useRef(null); var colorSubmenuRef = useRef(null); var sizeSubmenuRef = useRef(null); var openDropdownButtonRef = useRef(null); var enabled = !!borderMark; var color = borderMark === null || borderMark === void 0 ? void 0 : borderMark.color; var size = borderMark === null || borderMark === void 0 ? void 0 : borderMark.size; var _useState = useState(false), _useState2 = _slicedToArray(_useState, 2), isOpen = _useState2[0], setIsOpen = _useState2[1]; var _useState3 = useState(false), _useState4 = _slicedToArray(_useState3, 2), isOpenByKeyboard = _useState4[0], setIsOpenedByKeyboard = _useState4[1]; var _useState5 = useState(false), _useState6 = _slicedToArray(_useState5, 2), isColorSubmenuOpen = _useState6[0], setIsColorSubmenuOpen = _useState6[1]; var _useState7 = useState(false), _useState8 = _slicedToArray(_useState7, 2), isSizeSubmenuOpen = _useState8[0], setIsSizeSubmenuOpen = _useState8[1]; var handleColorSubmenuEsc = useCallback(function () { var _dropDownColorOptionB; setIsOpenedByKeyboard(false); setIsColorSubmenuOpen(false); dropDownColorOptionButton === null || dropDownColorOptionButton === void 0 || (_dropDownColorOptionB = dropDownColorOptionButton.current) === null || _dropDownColorOptionB === void 0 || _dropDownColorOptionB.focus(); }, []); var handleSizeSubmenuEsc = useCallback(function () { var _dropDownSizeOptionBu; setIsOpenedByKeyboard(false); setIsSizeSubmenuOpen(false); dropDownSizeOptionButton === null || dropDownSizeOptionButton === void 0 || (_dropDownSizeOptionBu = dropDownSizeOptionButton.current) === null || _dropDownSizeOptionBu === void 0 || _dropDownSizeOptionBu.focus(); }, []); var handleSubMenuRef = function handleSubMenuRef(ref) { if (!ref) { return; } var rect = ref.getBoundingClientRect(); if (rect.left + rect.width > window.innerWidth) { ref.style.left = "-".concat(rect.width, "px"); } }; var handleTriggerByKeyboard = function handleTriggerByKeyboard(event, allowedKeys, callback) { if (!allowedKeys.includes(event.key)) { return; } event.preventDefault(); callback(); setIsOpenedByKeyboard(true); }; var handleTriggerToolbarByKeyboard = function handleTriggerToolbarByKeyboard(event, callback) { handleTriggerByKeyboard(event, ['Enter', ' '], callback); }; var handleTriggerSubmenuByKeyboard = function handleTriggerSubmenuByKeyboard(event, callback) { var keys = expValEquals('platform_editor_toolbar_submenu_open_click', 'isEnabled', true) ? ['Enter', 'ArrowRight'] : ['Enter', ' ']; handleTriggerByKeyboard(event, keys, callback); }; useEffect(function () { var focusFirstOption = function focusFirstOption(submenuRef, isOpen) { if (!isOpenByKeyboard) { return; } if (isOpen && submenuRef.current) { var firstOption = submenuRef.current.querySelector('button'); if (!firstOption) { return; } firstOption.focus(); var keyboardEvent = new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }); firstOption.dispatchEvent(keyboardEvent); } }; focusFirstOption(colorSubmenuRef, isColorSubmenuOpen); focusFirstOption(sizeSubmenuRef, isSizeSubmenuOpen); }, [isColorSubmenuOpen, isSizeSubmenuOpen, isOpenByKeyboard]); var borderSizeOptions = [{ name: formatMessage(messages.borderSizeSubtle), value: 1, icon: StrokeWeightSmallIcon }, { name: formatMessage(messages.borderSizeMedium), value: 2, icon: StrokeWeightMediumIcon }, { name: formatMessage(messages.borderSizeBold), value: 3, icon: StrokeWeightLargeIcon }]; var items = [{ content: jsx("div", null, jsx("button", { ref: dropDownColorOptionButton, type: "button", "aria-label": formatMessage(messages.borderColorDropdownAriaLabel), "data-testid": "image-border-dropdown-button-color", css: expValEquals('platform_editor_fix_media_toolbar_border_dropdown', 'isEnabled', true, false) ? dropdownOptionButtonNew : // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766 dropdownOptionButton, "aria-expanded": isColorSubmenuOpen, onKeyDown: function onKeyDown(e) { return handleTriggerSubmenuByKeyboard(e, function () { if (expValEquals('platform_editor_toolbar_submenu_open_click', 'isEnabled', true)) { setIsColorSubmenuOpen(function (prev) { var next = !prev; if (next) { setIsSizeSubmenuOpen(false); } return next; }); } else { setIsColorSubmenuOpen(!isColorSubmenuOpen); } }); } }, jsx(Text, null, formatMessage(messages.borderColor)), jsx("div", { css: contextualMenuArrow })), jsx("div", { // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766 className: DropdownMenuSharedCssClassName.SUBMENU, ref: colorSubmenuRef }, isColorSubmenuOpen && // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766 jsx("div", { css: contextualSubMenu(0), ref: handleSubMenuRef }, jsx(ArrowKeyNavigationProvider, { type: ArrowKeyNavigationType.MENU // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , handleClose: function handleClose(e) { e.preventDefault(); e.stopPropagation(); handleColorSubmenuEsc(); }, disableCloseOnArrowClick: true }, jsx(ColorPalette // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , { onClick: function onClick(color) { setBorder({ color: color }); setIsOpen(!isOpen); } // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onKeyDown: function onKeyDown(color, _, event) { if (event.key === 'Enter' || event.key === ' ') { var _openDropdownButtonRe; setBorder({ color: color }); setIsOpen(!isOpen); setIsColorSubmenuOpen(false); setIsSizeSubmenuOpen(false); (_openDropdownButtonRe = openDropdownButtonRef.current) === null || _openDropdownButtonRe === void 0 || _openDropdownButtonRe.focus(); } }, selectedColor: color !== null && color !== void 0 ? color : null // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , paletteOptions: { palette: borderColorPalette, paletteColorTooltipMessages: borderPaletteTooltipMessages, hexToPaletteColor: hexToEditorBorderPaletteColor } }))))), 'data-testid': 'dropdown-item__Color', key: 'dropdown-menu-image-border-color-button', value: { name: 'color' }, 'aria-label': '', wrapperTabIndex: null }, { content: jsx("div", null, jsx("button", { type: "button", "aria-label": formatMessage(messages.borderSizeDropdownAriaLabel), "data-testid": "image-border-dropdown-button-size", css: expValEquals('platform_editor_fix_media_toolbar_border_dropdown', 'isEnabled', true, false) ? dropdownOptionButtonNew : // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766 dropdownOptionButton, "aria-expanded": isSizeSubmenuOpen, ref: dropDownSizeOptionButton, onKeyDown: function onKeyDown(e) { return handleTriggerSubmenuByKeyboard(e, function () { if (expValEquals('platform_editor_toolbar_submenu_open_click', 'isEnabled', true)) { setIsSizeSubmenuOpen(function (prev) { var next = !prev; if (next) { setIsColorSubmenuOpen(false); } return next; }); } else { setIsSizeSubmenuOpen(!isSizeSubmenuOpen); } }); } }, jsx(Text, null, formatMessage(messages.borderSize)), jsx("div", { css: contextualMenuArrow })), jsx("div", { //eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766 className: DropdownMenuSharedCssClassName.SUBMENU, ref: sizeSubmenuRef }, isSizeSubmenuOpen && jsx(ArrowKeyNavigationProvider, { type: ArrowKeyNavigationType.MENU // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , handleClose: function handleClose(e) { e.preventDefault(); handleSizeSubmenuEsc(); }, disableCloseOnArrowClick: true }, jsx("div", { css: contextualSubMenu(1), ref: handleSubMenuRef }, borderSizeOptions.map(function (_ref2, idx) { var name = _ref2.name, value = _ref2.value, icon = _ref2.icon; // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-explicit-any var ButtonIcon = icon; return ( // Ignored via go/ees005 // eslint-disable-next-line react/no-array-index-key jsx(Tooltip, { key: idx, content: name }, jsx("span", { css: buttonWrapperStyle }, jsx("button", { type: "button" /* eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766 */, css: buttonStyle(value === size), "aria-label": name, role: "radio", "aria-checked": value === size, onClick: function onClick() { setBorder({ size: value }); setIsOpen(false); }, onKeyDown: function onKeyDown(event) { if (event.key === 'Enter' || event.key === ' ') { var _openDropdownButtonRe2; setBorder({ size: value }); setIsOpen(false); setIsColorSubmenuOpen(false); setIsSizeSubmenuOpen(false); (_openDropdownButtonRe2 = openDropdownButtonRef.current) === null || _openDropdownButtonRe2 === void 0 || _openDropdownButtonRe2.focus(); } }, onMouseDown: function onMouseDown(e) { e.preventDefault(); } }, jsx(ButtonIcon, { color: value === size ? "var(--ds-icon-inverse, #FFFFFF)" : 'currentColor', spacing: "spacious", label: "" })))) ); }))))), 'data-testid': 'dropdown-item__Size', key: 'dropdown-menu-image-border-size-button', value: { name: 'size' }, 'aria-label': '', wrapperTabIndex: null }]; /** * We want to change direction of our dropdowns a bit early, * not exactly when it hits the boundary. */ var fitTolerance = 10; var fitWidth = menuItemDimensions.width; var fitHeight = items.length * (menuItemDimensions.height + itemSpacing); var isAnySubMenuOpen = isSizeSubmenuOpen || isColorSubmenuOpen; return jsx("div", null, jsx("div", { // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766 css: toolbarButtonWrapper({ enabled: enabled, isOpen: isOpen }) }, jsx(ToolbarButton // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766 , { className: "image-border-toolbar-btn", selected: enabled, onClick: toggleBorder, spacing: "compact", "aria-label": enabled ? formatMessage(messages.removeBorder) : formatMessage(messages.addBorder), iconBefore: jsx(BorderIcon, { color: "currentColor", label: "", spacing: "spacious" }), title: enabled ? formatMessage(messages.removeBorder) : formatMessage(messages.addBorder) }), jsx("div", { ref: popupTarget }, jsx(ToolbarButton // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766 , { className: "image-border-toolbar-dropdown", ref: openDropdownButtonRef, selected: enabled || isOpen, "aria-expanded": isOpen, "aria-label": formatMessage(messages.borderOptions), title: formatMessage(messages.borderOptions), spacing: "compact", iconBefore: jsx(ChevronDownIcon, { color: "currentColor", spacing: "spacious", label: "", size: "small" }) // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onClick: function onClick() { setIsOpen(!isOpen); setIsOpenedByKeyboard(false); } // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onKeyDown: function onKeyDown(e) { return handleTriggerToolbarByKeyboard(e, function () { return setIsOpen(!isOpen); }); } }))), jsx(Popup, { target: popupTarget.current ? popupTarget.current : undefined, fitWidth: fitWidth + fitTolerance, fitHeight: fitHeight + fitTolerance, forcePlacement: true, stick: true }, jsx("div", { onMouseLeave: expValEquals('platform_editor_toolbar_submenu_open_click', 'isEnabled', true) ? undefined : function () { setIsColorSubmenuOpen(false); setIsSizeSubmenuOpen(false); } /* eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766 */, css: dropdownWrapper }, jsx(DropdownMenu //This needs be removed when the a11y is completely handled //Disabling key navigation now as it works only partially //Same with packages/editor/editor-plugin-table/src/plugins/table/ui/FloatingContextualMenu/ContextualMenu.tsx // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , { arrowKeyNavigationProviderOptions: { type: ArrowKeyNavigationType.MENU, disableArrowKeyNavigation: isAnySubMenuOpen }, allowEnterDefaultBehavior: isAnySubMenuOpen, handleEscapeKeydown: isAnySubMenuOpen ? function () { return; } : function () { var _openDropdownButtonRe3; (_openDropdownButtonRe3 = openDropdownButtonRef.current) === null || _openDropdownButtonRe3 === void 0 || _openDropdownButtonRe3.focus(); } // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , items: [{ items: items }], isOpen: isOpen // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , shouldFocusFirstItem: function shouldFocusFirstItem() { return isOpenByKeyboard; } // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onOpenChange: function onOpenChange() { setIsOpen(false); setIsColorSubmenuOpen(false); setIsSizeSubmenuOpen(false); setIsOpenedByKeyboard(false); } // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onItemActivated: function onItemActivated(_ref3) { var item = _ref3.item; if (item.value.name === 'color') { if (expValEquals('platform_editor_toolbar_submenu_open_click', 'isEnabled', true)) { setIsColorSubmenuOpen(function (prev) { var next = !prev; if (next) { setIsSizeSubmenuOpen(false); } return next; }); } else { setIsColorSubmenuOpen(!isColorSubmenuOpen); } } if (item.value.name === 'size') { if (expValEquals('platform_editor_toolbar_submenu_open_click', 'isEnabled', true)) { setIsSizeSubmenuOpen(function (prev) { var next = !prev; if (next) { setIsColorSubmenuOpen(false); } return next; }); } else { setIsSizeSubmenuOpen(!isSizeSubmenuOpen); } } } // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onMouseEnter: function onMouseEnter(_ref4) { var item = _ref4.item; if (!expValEquals('platform_editor_toolbar_submenu_open_click', 'isEnabled', true)) { if (item.value.name === 'color') { setIsColorSubmenuOpen(true); setIsOpenedByKeyboard(false); } if (item.value.name === 'size') { setIsSizeSubmenuOpen(true); setIsOpenedByKeyboard(false); } } } // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onMouseLeave: function onMouseLeave(_ref5) { var item = _ref5.item; if (!expValEquals('platform_editor_toolbar_submenu_open_click', 'isEnabled', true)) { if (item.value.name === 'color') { setIsColorSubmenuOpen(false); } if (item.value.name === 'size') { setIsSizeSubmenuOpen(false); } } }, fitWidth: fitWidth + fitTolerance, fitHeight: fitHeight + fitTolerance })))); }; export default ImageBorder;