UNPKG

@atlaskit/editor-plugin-media

Version:

Media plugin for @atlaskit/editor-core

213 lines (212 loc) 6.54 kB
/** @jsx jsx */ import { useRef, useState } from 'react'; import { jsx } from '@emotion/react'; import { BorderIcon } from '@atlaskit/editor-common/icons'; 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 { ArrowKeyNavigationType, DropdownMenu, ToolbarButton } from '@atlaskit/editor-common/ui-menu'; import { hexToEditorBorderPaletteColor } from '@atlaskit/editor-palette'; import ExpandIcon from '@atlaskit/icon/glyph/chevron-down'; import Tooltip from '@atlaskit/tooltip'; import { messages } from './messages'; import { buttonStyle, buttonWrapperStyle, contextualMenuArrow, contextualMenuColorIcon, contextualSubMenu, itemSpacing, line, menuItemDimensions, toolbarButtonWrapper } from './styles'; const ImageBorder = ({ intl: { formatMessage }, toggleBorder, borderMark, setBorder }) => { const popupTarget = useRef(null); const enabled = !!borderMark; const color = borderMark === null || borderMark === void 0 ? void 0 : borderMark.color; const size = borderMark === null || borderMark === void 0 ? void 0 : borderMark.size; const [isOpen, setIsOpen] = useState(false); const [isColorSubmenuOpen, setIsColorSubmenuOpen] = useState(false); const [isSizeSubmenuOpen, setIsSizeSubmenuOpen] = useState(false); const handleSubMenuRef = ref => { if (!ref) { return; } const rect = ref.getBoundingClientRect(); if (rect.left + rect.width > window.innerWidth) { ref.style.left = `-${rect.width}px`; } }; const borderSizeOptions = [{ name: formatMessage(messages.borderSizeSubtle), value: 1 }, { name: formatMessage(messages.borderSizeMedium), value: 2 }, { name: formatMessage(messages.borderSizeBold), value: 3 }]; const items = [{ content: formatMessage(messages.borderColor), value: { name: 'color' }, elemAfter: jsx("div", { className: DropdownMenuSharedCssClassName.SUBMENU }, jsx("div", { css: contextualMenuColorIcon(color && hexToEditorBorderPaletteColor(color)) }), isColorSubmenuOpen && jsx("div", { css: contextualSubMenu(0), ref: handleSubMenuRef }, jsx(ColorPalette, { onClick: color => { setBorder({ color }); setIsOpen(!isOpen); }, selectedColor: color !== null && color !== void 0 ? color : null, paletteOptions: { palette: borderColorPalette, paletteColorTooltipMessages: borderPaletteTooltipMessages, hexToPaletteColor: hexToEditorBorderPaletteColor } }))) }, { content: formatMessage(messages.borderSize), value: { name: 'size' }, elemAfter: jsx("div", { className: DropdownMenuSharedCssClassName.SUBMENU }, jsx("div", { css: contextualMenuArrow }), isSizeSubmenuOpen && jsx("div", { css: contextualSubMenu(1), ref: handleSubMenuRef }, borderSizeOptions.map(({ name, value }, idx) => jsx(Tooltip, { key: idx, content: name }, jsx("span", { css: buttonWrapperStyle }, jsx("button", { css: buttonStyle(value === size), "aria-label": name, role: "radio", "aria-checked": value === size, onClick: () => { setBorder({ size: value }); setIsOpen(false); }, onMouseDown: e => { e.preventDefault(); } }, jsx("div", { css: line(value, value === size), role: "presentation" }))))))) }]; /** * We want to change direction of our dropdowns a bit early, * not exactly when it hits the boundary. */ const fitTolerance = 10; const fitWidth = menuItemDimensions.width; const fitHeight = items.length * (menuItemDimensions.height + itemSpacing); return jsx("div", null, jsx("div", { css: toolbarButtonWrapper({ enabled, isOpen }) }, jsx(ToolbarButton, { className: "image-border-toolbar-btn", selected: enabled, onClick: toggleBorder, spacing: "compact", "aria-label": enabled ? formatMessage(messages.removeBorder) : formatMessage(messages.addBorder), iconBefore: jsx(BorderIcon, { label: "" }), title: enabled ? formatMessage(messages.removeBorder) : formatMessage(messages.addBorder) }), jsx("div", { ref: popupTarget }, jsx(ToolbarButton, { className: "image-border-toolbar-dropdown", selected: enabled || isOpen, "aria-label": formatMessage(messages.borderOptions), title: formatMessage(messages.borderOptions), spacing: "compact", iconBefore: jsx(ExpandIcon, { label: "" }), onClick: () => { setIsOpen(!isOpen); } }))), jsx(Popup, { target: popupTarget.current ? popupTarget.current : undefined, fitWidth: fitWidth + fitTolerance, fitHeight: fitHeight + fitTolerance, forcePlacement: true, stick: true }, jsx("div", { onMouseLeave: () => { setIsColorSubmenuOpen(false); setIsSizeSubmenuOpen(false); } }, 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 , { arrowKeyNavigationProviderOptions: { type: ArrowKeyNavigationType.MENU, disableArrowKeyNavigation: true }, items: [{ items }], isOpen: isOpen, onOpenChange: () => { setIsOpen(false); setIsColorSubmenuOpen(false); setIsSizeSubmenuOpen(false); }, onItemActivated: ({ item }) => { if (item.value.name === 'color') { setIsColorSubmenuOpen(!isColorSubmenuOpen); } if (item.value.name === 'size') { setIsSizeSubmenuOpen(!isSizeSubmenuOpen); } }, onMouseEnter: ({ item }) => { if (item.value.name === 'color') { setIsColorSubmenuOpen(true); } if (item.value.name === 'size') { setIsSizeSubmenuOpen(true); } }, onMouseLeave: ({ item }) => { if (item.value.name === 'color') { setIsColorSubmenuOpen(false); } if (item.value.name === 'size') { setIsSizeSubmenuOpen(false); } }, fitWidth: fitWidth + fitTolerance, fitHeight: fitHeight + fitTolerance })))); }; export default ImageBorder;