design-comuni-plone-theme
Version:
Volto Theme for Italia design guidelines
170 lines (152 loc) • 3.99 kB
JSX
import React from 'react';
import { useSlate } from 'slate-react';
import { Dropdown } from 'semantic-ui-react';
import { useIntl, defineMessages } from 'react-intl';
import cx from 'classnames';
import { omit } from 'lodash';
import {
isBlockStyleActive,
toggleStyle,
} from 'design-comuni-plone-theme/config/Slate/dropdownUtils';
import { Icon } from '@plone/volto/components';
import { ToolbarButton } from '@plone/volto-slate/editor/ui';
import alignCenterSVG from '@plone/volto/icons/align-center.svg';
import alignLeftSVG from '@plone/volto/icons/align-left.svg';
import alignRightSVG from '@plone/volto/icons/align-right.svg';
import alignJustifySVG from '@plone/volto/icons/align-justify.svg';
import 'design-comuni-plone-theme/config/Slate/dropdownStyle.scss';
const messages = defineMessages({
align: {
id: 'Allineamento',
defaultMessage: 'Allineamento',
},
align_left: {
id: 'Allinea a sinistra',
defaultMessage: 'Allinea a sinistra',
},
align_center: {
id: 'Allinea al centro',
defaultMessage: 'Allinea al centro',
},
align_right: {
id: 'Allinea a destra',
defaultMessage: 'Allinea a destra',
},
align_justify: {
id: 'Allinea il testo giustificato',
defaultMessage: 'Allinea il testo giustificato',
},
});
const ALIGN_OPTIONS = [
{
cssClass: 'text-left',
title: messages.align_left,
icon: alignLeftSVG,
},
{
cssClass: 'text-center',
title: messages.align_center,
icon: alignCenterSVG,
},
{
cssClass: 'text-end',
title: messages.align_right,
icon: alignRightSVG,
},
{
cssClass: 'text-justify',
title: messages.align_justify,
icon: alignJustifySVG,
},
];
const AlignMenuButton = ({ icon, active, ...props }) => {
return (
<ToolbarButton
{...props}
icon={icon}
active={active}
onMouseDown={() => {}}
/>
);
};
const MenuOpts = ({ editor, toSelect, option, type }) => {
const isActive = toSelect.includes(option);
return (
<Dropdown.Item
as="span"
active={isActive}
className={cx(`${type}-${option.value}`, { active: isActive })}
{...omit(option, ['isBlock', 'originalIcon'])}
data-isblock={option.isBlock}
onClick={(event, selItem) => {
toggleStyle(editor, {
cssClass: selItem.value,
isBlock: true,
oneOf: ALIGN_OPTIONS.reduce((acc, o) => [...acc, o.cssClass], []),
});
}}
/>
);
};
const AlignButton = (props) => {
const editor = useSlate();
const intl = useIntl();
const blockOpts = ALIGN_OPTIONS.map((def) => {
return {
value: def.cssClass,
text: def.text,
title: intl.formatMessage(def.title),
icon: (props) => <Icon name={def.icon} size="24px" />,
isBlock: true,
originalIcon: def.icon,
};
});
// Calculating the initial selection.
const toSelect = [];
let selectedIcon = ALIGN_OPTIONS[0].icon;
// block styles
for (const val of blockOpts) {
const ia = isBlockStyleActive(editor, val.value);
if (ia) {
toSelect.push(val);
selectedIcon = val.originalIcon;
}
}
const menuItemProps = {
toSelect,
editor,
};
return (
<Dropdown
id="align-menu"
pointing="top left"
multiple
value={toSelect}
additionLabel={intl.formatMessage(messages.align)}
trigger={
<AlignMenuButton
title={intl.formatMessage(messages.align)}
icon={selectedIcon}
active={toSelect.length > 0}
/>
}
onMouseDown={(e) => {
e.preventDefault();
e.stopPropagation();
}}
>
<Dropdown.Menu>
{blockOpts.length &&
blockOpts.map((option, index) => (
<MenuOpts
{...menuItemProps}
type="block-align"
option={option}
key={index}
/>
))}
</Dropdown.Menu>
</Dropdown>
);
};
export default AlignButton;