@atlaskit/editor-plugin-media
Version:
Media plugin for @atlaskit/editor-core
213 lines (212 loc) • 6.54 kB
JavaScript
/** @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;