From 5018988eea0e7440a48fdc8321a4e47fce642eae Mon Sep 17 00:00:00 2001
From: Giulia Ghisini
Date: Tue, 26 Sep 2023 10:12:16 +0200
Subject: [PATCH] chore: slate config
---
src/config/Slate/Alignment/AlignMenu.jsx | 141 +++++++++++++++++++
src/config/Slate/Alignment/index.js | 23 ++++
src/config/Slate/Alignment/utils.js | 166 +++++++++++++++++++++++
src/config/Slate/config.js | 6 +
src/config/Slate/dropdownStyle.scss | 9 ++
src/config/italiaConfig.js | 4 +-
6 files changed, 348 insertions(+), 1 deletion(-)
create mode 100644 src/config/Slate/Alignment/AlignMenu.jsx
create mode 100644 src/config/Slate/Alignment/index.js
create mode 100644 src/config/Slate/Alignment/utils.js
create mode 100644 src/config/Slate/config.js
create mode 100644 src/config/Slate/dropdownStyle.scss
diff --git a/src/config/Slate/Alignment/AlignMenu.jsx b/src/config/Slate/Alignment/AlignMenu.jsx
new file mode 100644
index 000000000..d7307ca4f
--- /dev/null
+++ b/src/config/Slate/Alignment/AlignMenu.jsx
@@ -0,0 +1,141 @@
+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 './utils';
+
+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 '../dropdownStyle.scss';
+
+const ALIGN_OPTIONS = [
+ {
+ cssClass: 'text-left',
+ text: 'Allinea a sinistra',
+ icon: alignLeftSVG,
+ },
+ {
+ cssClass: 'text-center',
+ text: 'Allinea al centro',
+ icon: alignCenterSVG,
+ },
+ {
+ cssClass: 'text-right',
+ text: 'Allinea a destra',
+ icon: alignRightSVG,
+ },
+ {
+ cssClass: 'text-justify',
+ text: 'Allinea il testo giustificato',
+ icon: alignJustifySVG,
+ },
+];
+
+const messages = defineMessages({
+ align: {
+ id: 'Allineamento',
+ defaultMessage: 'Allineamento',
+ },
+});
+
+const AlignMenuButton = ({ icon, active, ...props }) => (
+
+);
+
+const MenuOpts = ({ editor, toSelect, option, type }) => {
+ const isActive = toSelect.includes(option);
+
+ return (
+ {
+ toggleStyle(editor, {
+ cssClass: selItem.value,
+ isBlock: selItem.isBlock,
+ oneOfType: 'align',
+ });
+ }}
+ />
+ );
+};
+
+const AlignButton = (props) => {
+ const editor = useSlate();
+ const intl = useIntl();
+
+ const blockOpts = ALIGN_OPTIONS.map((def) => {
+ return {
+ value: def.cssClass,
+ text: def.label,
+ icon: (props) => ,
+ 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,
+ };
+
+ const showMenu = blockOpts.length;
+
+ return showMenu ? (
+
+ ) : (
+ ''
+ );
+};
+
+export default AlignButton;
diff --git a/src/config/Slate/Alignment/index.js b/src/config/Slate/Alignment/index.js
new file mode 100644
index 000000000..9606f2ee0
--- /dev/null
+++ b/src/config/Slate/Alignment/index.js
@@ -0,0 +1,23 @@
+import React from 'react';
+import AlignMenu from './AlignMenu';
+//import '@plone/volto-slate/editor/plugins/StyleMenu/style.less';
+
+export const AlignElement = ({ attributes, children, element }) => {
+ console.log(attributes, element);
+ return aaaa{children}
;
+};
+
+export default function install(config) {
+ const { slate } = config.settings;
+
+ slate.buttons.align = (props) => (
+
+ );
+
+ slate.elements['align'] = AlignElement;
+ slate.toolbarButtons.push('align');
+ slate.expandedToolbarButtons.push('align');
+ console.log(slate);
+
+ return config;
+}
diff --git a/src/config/Slate/Alignment/utils.js b/src/config/Slate/Alignment/utils.js
new file mode 100644
index 000000000..ce42c5aab
--- /dev/null
+++ b/src/config/Slate/Alignment/utils.js
@@ -0,0 +1,166 @@
+/* eslint no-console: ["error", { allow: ["warn", "error"] }] */
+import { Editor, Transforms } from 'slate';
+import { isBlockActive } from '@plone/volto-slate/utils';
+import config from '@plone/volto/registry';
+
+/**
+ * Toggles a style (e.g. in the StyleMenu plugin).
+ * @param {Editor} editor
+ * @param {object} options
+ * @param {boolean} options.oneOfType Whether the given type is admitted once
+ */
+export const toggleStyle = (editor, { cssClass, isBlock, oneOfType }) => {
+ if (isBlock) {
+ toggleBlockStyle(editor, cssClass, oneOfType);
+ } else {
+ toggleInlineStyle(editor, cssClass);
+ }
+};
+
+export const toggleBlockStyle = (editor, style, oneOfType) => {
+ // We have 6 boolean variables which need to be accounted for.
+ // See https://docs.google.com/spreadsheets/d/1mVeMuqSTMABV2BhoHPrPAFjn7zUksbNgZ9AQK_dcd3U/edit?usp=sharing
+ const { slate } = config.settings;
+
+ const isListItem = isBlockActive(editor, slate.listItemType);
+ const isActive = isBlockStyleActive(editor, style);
+ const wantsList = false;
+
+ if (isListItem && !wantsList) {
+ toggleBlockStyleAsListItem(editor, style);
+ } else if (isListItem && wantsList && !isActive) {
+ // switchListType(editor, format); // this will deconstruct to Volto blocks
+ } else if (!isListItem && wantsList) {
+ // changeBlockToList(editor, format);
+ } else if (!isListItem && !wantsList) {
+ internalToggleBlockStyle(editor, style);
+ } else {
+ console.warn('toggleBlockStyle case not covered, please examine:', {
+ wantsList,
+ isActive,
+ isListItem,
+ });
+ }
+};
+
+export const toggleInlineStyle = (editor, style) => {
+ // We have 6 boolean variables which need to be accounted for.
+ // See https://docs.google.com/spreadsheets/d/1mVeMuqSTMABV2BhoHPrPAFjn7zUksbNgZ9AQK_dcd3U/edit?usp=sharing
+ const { slate } = config.settings;
+
+ const isListItem = isBlockActive(editor, slate.listItemType);
+ const isActive = isInlineStyleActive(editor, style);
+ const wantsList = false;
+
+ if (isListItem && !wantsList) {
+ toggleInlineStyleAsListItem(editor, style);
+ } else if (isListItem && wantsList && !isActive) {
+ // switchListType(editor, format); // this will deconstruct to Volto blocks
+ } else if (!isListItem && wantsList) {
+ // changeBlockToList(editor, format);
+ } else if (!isListItem && !wantsList) {
+ internalToggleInlineStyle(editor, style);
+ } else {
+ console.warn('toggleInlineStyle case not covered, please examine:', {
+ wantsList,
+ isActive,
+ isListItem,
+ });
+ }
+};
+
+export const isBlockStyleActive = (editor, style) => {
+ const keyName = `style-${style}`;
+ const sn = Array.from(
+ Editor.nodes(editor, {
+ match: (n) => {
+ const isStyle = typeof n.styleName === 'string' || n[keyName];
+ return !Editor.isEditor(n) && isStyle;
+ },
+ mode: 'all',
+ }),
+ );
+
+ for (const [n] of sn) {
+ if (typeof n.styleName === 'string') {
+ if (n.styleName.split(' ').filter((x) => x === style).length > 0) {
+ return true;
+ }
+ } else if (
+ n[keyName] &&
+ keyName.split('style-').filter((x) => x === style).length > 0
+ )
+ return true;
+ }
+ return false;
+};
+
+export const isInlineStyleActive = (editor, style) => {
+ const m = Editor.marks(editor);
+ const keyName = `style-${style}`;
+ if (m && m[keyName]) {
+ return true;
+ }
+ return false;
+};
+
+export const internalToggleBlockStyle = (editor, style) => {
+ toggleBlockStyleInSelection(editor, style);
+};
+
+export const internalToggleInlineStyle = (editor, style) => {
+ toggleInlineStyleInSelection(editor, style);
+};
+
+/*
+ * Applies a block format unto a list item. Will split the list and deconstruct the
+ * block
+ */
+export const toggleBlockStyleAsListItem = (editor, style) => {
+ toggleBlockStyleInSelection(editor, style);
+};
+
+/*
+ * Applies an inline style unto a list item.
+ */
+export const toggleInlineStyleAsListItem = (editor, style) => {
+ toggleInlineStyleInSelection(editor, style);
+};
+
+function toggleInlineStyleInSelection(editor, style) {
+ const m = Editor.marks(editor);
+ const keyName = 'style-' + style;
+
+ if (m && m[keyName]) {
+ Editor.removeMark(editor, keyName);
+ } else {
+ Editor.addMark(editor, keyName, true);
+ }
+}
+
+function toggleBlockStyleInSelection(editor, style) {
+ const sn = Array.from(
+ Editor.nodes(editor, {
+ mode: 'highest',
+ match: (n) => {
+ return !Editor.isEditor(n);
+ },
+ }),
+ );
+
+ for (const [n, p] of sn) {
+ let cn = n.styleName;
+ if (typeof n.styleName !== 'string') {
+ cn = style;
+ } else if (n.styleName.split(' ').filter((x) => x === style).length > 0) {
+ cn = cn
+ .split(' ')
+ .filter((x) => x !== style)
+ .join(' ');
+ } else {
+ // the style is not set but other styles are set
+ cn = cn.split(' ').concat(style).join(' ');
+ }
+ Transforms.setNodes(editor, { styleName: cn }, { at: p });
+ }
+}
diff --git a/src/config/Slate/config.js b/src/config/Slate/config.js
new file mode 100644
index 000000000..b55fb2283
--- /dev/null
+++ b/src/config/Slate/config.js
@@ -0,0 +1,6 @@
+//config.settings.slate.contextToolbarButtons
+import installAlignment from 'design-comuni-plone-theme/config/Slate/Alignment';
+
+export default function applyItaliaSlateConfig(config) {
+ installAlignment(config);
+}
diff --git a/src/config/Slate/dropdownStyle.scss b/src/config/Slate/dropdownStyle.scss
new file mode 100644
index 000000000..fb47383d4
--- /dev/null
+++ b/src/config/Slate/dropdownStyle.scss
@@ -0,0 +1,9 @@
+.cms-ui .slate-inline-toolbar .ui.dropdown .menu > .item {
+ &.active {
+ color: #007eb1;
+ background-color: lighten(#007eb1, 60);
+ }
+ > .icon {
+ margin-right: 0;
+ }
+}
diff --git a/src/config/italiaConfig.js b/src/config/italiaConfig.js
index 4d67d298d..7f6612b77 100644
--- a/src/config/italiaConfig.js
+++ b/src/config/italiaConfig.js
@@ -58,6 +58,7 @@ import bandoSVG from 'design-comuni-plone-theme/icons/bando.svg';
import logSVG from 'design-comuni-plone-theme/icons/log.svg';
import applyRichTextConfig from 'design-comuni-plone-theme/config/RichTextEditor/config';
+import applyItaliaSlateConfig from 'design-comuni-plone-theme/config/Slate/config';
import gdprPrivacyPanelConfig from 'design-comuni-plone-theme/config/volto-gdpr-privacy-defaultPanelConfig.js';
@@ -70,7 +71,8 @@ const ReleaseLog = loadable(() =>
);
export default function applyConfig(voltoConfig) {
- let config = applyRichTextConfig(voltoConfig);
+ let config = applyRichTextConfig(voltoConfig); //[ToDO]: da rimuovere in favore di slate?
+ applyItaliaSlateConfig(config);
/******************************************************************************
* SETTINGS