From c2076176f07fc75c21d481e7e53ffbce936647cf Mon Sep 17 00:00:00 2001
From: Giulia Ghisini
Date: Fri, 22 Sep 2023 15:11:26 +0200
Subject: [PATCH 001/353] BREAKING CHANGE: use slate editor
---
src/config/Widgets/widgets.js | 2 +-
src/config/italiaConfig.js | 18 +++++++++---------
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/config/Widgets/widgets.js b/src/config/Widgets/widgets.js
index 43bdcc925..ccb04c4d9 100644
--- a/src/config/Widgets/widgets.js
+++ b/src/config/Widgets/widgets.js
@@ -82,7 +82,7 @@ const getItaliaWidgets = (config) => {
},
widget: {
...config.widgets.widget,
- richtext: WysiwygWidget,
+ //richtext: WysiwygWidget,
color_list: ColorListWidget,
path_filters: PathFiltersWidget,
location_filter: LocationFiltersWidget,
diff --git a/src/config/italiaConfig.js b/src/config/italiaConfig.js
index a3ebafa65..4d67d298d 100644
--- a/src/config/italiaConfig.js
+++ b/src/config/italiaConfig.js
@@ -180,7 +180,7 @@ export default function applyConfig(voltoConfig) {
'social-settings': shareSVG,
'release-log': logSVG,
},
- defaultBlockType: 'text',
+ //defaultBlockType: 'text',
defaultExcludedFromSearch: {
portalTypes: ['Image', 'File'],
},
@@ -402,14 +402,14 @@ export default function applyConfig(voltoConfig) {
...config.blocks.blocksConfig.slate,
restricted: true,
},
- table: {
- ...config.blocks.blocksConfig.table,
- restricted: false,
- },
- slateTable: {
- ...config.blocks.blocksConfig.slateTable,
- restricted: true,
- },
+ // table: {
+ // ...config.blocks.blocksConfig.table,
+ // restricted: false,
+ // },
+ // slateTable: {
+ // ...config.blocks.blocksConfig.slateTable,
+ // restricted: true,
+ // },
maps: {
...config.blocks.blocksConfig.maps,
restricted: true,
From d4e4a71dc380166c71edfdc28384e8f1e75e6eb2 Mon Sep 17 00:00:00 2001
From: Giulia Ghisini
Date: Fri, 22 Sep 2023 15:11:57 +0200
Subject: [PATCH 002/353] fix: fix font-style when adding new page
---
src/theme/_cms-ui.scss | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/src/theme/_cms-ui.scss b/src/theme/_cms-ui.scss
index 167967a92..9e5698382 100644
--- a/src/theme/_cms-ui.scss
+++ b/src/theme/_cms-ui.scss
@@ -84,12 +84,10 @@ body.cms-ui {
&.contenttype-argomento,
&.contenttype-pagina-argomento,
&.contenttype-cartellamodulistica {
- &:not(.section-add) {
- .block {
- font-family: $font-family-sans-serif;
- font-weight: 300;
- line-height: 1.555;
- }
+ .block {
+ font-family: $font-family-sans-serif;
+ font-weight: 300;
+ line-height: 1.555;
}
}
From 5018988eea0e7440a48fdc8321a4e47fce642eae Mon Sep 17 00:00:00 2001
From: Giulia Ghisini
Date: Tue, 26 Sep 2023 10:12:16 +0200
Subject: [PATCH 003/353] 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
From 4fc6d8acab86e08554876ae3797a7f122f140fab Mon Sep 17 00:00:00 2001
From: Giulia Ghisini
Date: Tue, 26 Sep 2023 16:05:44 +0200
Subject: [PATCH 004/353] feat: added Align, Headings, Underline and Blockquote
styles in slate editor
---
src/config/Slate/Alignment/AlignMenu.jsx | 13 +-
src/config/Slate/Alignment/index.js | 15 +-
.../Slate/Blockquote/BlockquoteMenu.jsx | 138 ++++++++++++++++++
src/config/Slate/Blockquote/index.js | 12 ++
src/config/Slate/Headings/HeadingsMenu.jsx | 135 +++++++++++++++++
src/config/Slate/Headings/headingsMenu.scss | 44 ++++++
src/config/Slate/Headings/index.js | 36 +++++
src/config/Slate/Underline/index.js | 10 ++
src/config/Slate/config.js | 17 +++
.../{Alignment/utils.js => dropdownUtils.js} | 29 ++--
src/config/Slate/utils.js | 30 ++++
src/theme/ItaliaTheme/_main.scss | 15 +-
12 files changed, 460 insertions(+), 34 deletions(-)
create mode 100644 src/config/Slate/Blockquote/BlockquoteMenu.jsx
create mode 100644 src/config/Slate/Blockquote/index.js
create mode 100644 src/config/Slate/Headings/HeadingsMenu.jsx
create mode 100644 src/config/Slate/Headings/headingsMenu.scss
create mode 100644 src/config/Slate/Headings/index.js
create mode 100644 src/config/Slate/Underline/index.js
rename src/config/Slate/{Alignment/utils.js => dropdownUtils.js} (86%)
create mode 100644 src/config/Slate/utils.js
diff --git a/src/config/Slate/Alignment/AlignMenu.jsx b/src/config/Slate/Alignment/AlignMenu.jsx
index d7307ca4f..ded0e0117 100644
--- a/src/config/Slate/Alignment/AlignMenu.jsx
+++ b/src/config/Slate/Alignment/AlignMenu.jsx
@@ -4,7 +4,10 @@ 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 {
+ isBlockStyleActive,
+ toggleStyle,
+} from 'design-comuni-plone-theme/config/Slate/dropdownUtils';
import { Icon } from '@plone/volto/components';
import { ToolbarButton } from '@plone/volto-slate/editor/ui';
@@ -14,7 +17,7 @@ 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';
+import 'design-comuni-plone-theme/config/Slate/dropdownStyle.scss';
const ALIGN_OPTIONS = [
{
@@ -28,7 +31,7 @@ const ALIGN_OPTIONS = [
icon: alignCenterSVG,
},
{
- cssClass: 'text-right',
+ cssClass: 'text-end',
text: 'Allinea a destra',
icon: alignRightSVG,
},
@@ -63,8 +66,8 @@ const MenuOpts = ({ editor, toSelect, option, type }) => {
onClick={(event, selItem) => {
toggleStyle(editor, {
cssClass: selItem.value,
- isBlock: selItem.isBlock,
- oneOfType: 'align',
+ isBlock: true,
+ oneOf: ALIGN_OPTIONS.reduce((acc, o) => [...acc, o.cssClass], []),
});
}}
/>
diff --git a/src/config/Slate/Alignment/index.js b/src/config/Slate/Alignment/index.js
index 9606f2ee0..0084df04d 100644
--- a/src/config/Slate/Alignment/index.js
+++ b/src/config/Slate/Alignment/index.js
@@ -1,10 +1,8 @@
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};
+ return {children}
;
};
export default function install(config) {
@@ -15,9 +13,14 @@ export default function install(config) {
);
slate.elements['align'] = AlignElement;
- slate.toolbarButtons.push('align');
- slate.expandedToolbarButtons.push('align');
- console.log(slate);
+
+ //lo metto come primo elemento della toolbar
+ slate.toolbarButtons = ['align', 'separator', ...slate.toolbarButtons];
+ slate.expandedToolbarButtons = [
+ 'align',
+ 'separator',
+ ...slate.expandedToolbarButtons,
+ ];
return config;
}
diff --git a/src/config/Slate/Blockquote/BlockquoteMenu.jsx b/src/config/Slate/Blockquote/BlockquoteMenu.jsx
new file mode 100644
index 000000000..fa2831189
--- /dev/null
+++ b/src/config/Slate/Blockquote/BlockquoteMenu.jsx
@@ -0,0 +1,138 @@
+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 quoteIcon from '@plone/volto/icons/quote.svg';
+
+import 'design-comuni-plone-theme/config/Slate/dropdownStyle.scss';
+
+const OPTIONS = [
+ {
+ title: 'Blockquote semplice',
+ format: 'blockquote',
+ icon: quoteIcon,
+ },
+ {
+ title: 'Blockquote card',
+ format: 'blockquote',
+ icon: quoteIcon,
+ className: 'blockquote-card',
+ },
+ {
+ title: 'Blockquote card scuro',
+ format: 'blockquote',
+ icon: quoteIcon,
+ className: 'blockquote-card dark',
+ },
+];
+
+const messages = defineMessages({
+ blockquote: {
+ id: 'Blockquote',
+ defaultMessage: 'Blockquote',
+ },
+});
+
+const BlockquoteMenuButton = ({ icon, active, ...props }) => (
+
+);
+
+const MenuOpts = ({ editor, toSelect, option, type }) => {
+ const isActive = toSelect.includes(option);
+
+ return (
+ {
+ toggleStyle(editor, {
+ cssClass: selItem.value,
+ isBlock: true,
+ oneOf: OPTIONS.reduce((acc, o) => [...acc, o.cssClass], []),
+ });
+ }}
+ />
+ );
+};
+
+const BlockquoteButton = (props) => {
+ const editor = useSlate();
+ const intl = useIntl();
+
+ const blockOpts = 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 = 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 BlockquoteButton;
diff --git a/src/config/Slate/Blockquote/index.js b/src/config/Slate/Blockquote/index.js
new file mode 100644
index 000000000..becd912d4
--- /dev/null
+++ b/src/config/Slate/Blockquote/index.js
@@ -0,0 +1,12 @@
+import React from 'react';
+import BlockquoteMenu from './BlockquoteMenu';
+
+export default function install(config) {
+ const { slate } = config.settings;
+
+ slate.buttons.blockquote = (props) => (
+
+ );
+
+ return config;
+}
diff --git a/src/config/Slate/Headings/HeadingsMenu.jsx b/src/config/Slate/Headings/HeadingsMenu.jsx
new file mode 100644
index 000000000..f1cdcc573
--- /dev/null
+++ b/src/config/Slate/Headings/HeadingsMenu.jsx
@@ -0,0 +1,135 @@
+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 config from '@plone/volto/registry';
+import { isBlockActive } from '@plone/volto-slate/utils';
+
+import { ToolbarButton, BlockButton } from '@plone/volto-slate/editor/ui';
+
+import headingIcon from '@plone/volto/icons/heading.svg';
+
+import 'design-comuni-plone-theme/config/Slate/dropdownStyle.scss';
+import 'design-comuni-plone-theme/config/Slate/Headings/headingsMenu.scss';
+
+const OPTIONS = [
+ {
+ title: 'h2',
+ format: 'h2',
+ content: 'h2',
+ className: 'headings-h2',
+ },
+ {
+ title: 'h3',
+ format: 'h3',
+ content: 'h3',
+ className: 'headings-h3',
+ },
+ {
+ title: 'h4',
+ format: 'h4',
+ content: 'h4',
+ className: 'headings-h4',
+ },
+ {
+ title: 'h5',
+ format: 'h5',
+ content: 'h5',
+ className: 'headings-h5',
+ },
+ {
+ title: 'h6',
+ format: 'h6',
+ content: 'h6',
+ className: 'headings-h6',
+ },
+];
+
+const messages = defineMessages({
+ title: {
+ id: 'Titolo',
+ defaultMessage: 'Titolo',
+ },
+});
+
+const HeadingsMenuButton = ({ icon, active, ...props }) => (
+
+);
+
+const MenuOpts = ({ editor, toSelect, option, type }) => {
+ const isActive = toSelect.includes(option);
+ return (
+
+
+
+ );
+};
+
+const HeadingsButton = (props) => {
+ const editor = useSlate();
+ const intl = useIntl();
+
+ // Calculating the initial selection.
+ const toSelect = [];
+
+ // block styles
+ for (const opt of OPTIONS) {
+ const ia = isBlockActive(editor, opt.format);
+
+ if (ia) {
+ toSelect.push(opt);
+ }
+ }
+
+ const menuItemProps = {
+ toSelect,
+ editor,
+ };
+
+ const showMenu = OPTIONS.length;
+
+ return showMenu ? (
+
+ ) : (
+ ''
+ );
+};
+
+export default HeadingsButton;
diff --git a/src/config/Slate/Headings/headingsMenu.scss b/src/config/Slate/Headings/headingsMenu.scss
new file mode 100644
index 000000000..ac898bdb5
--- /dev/null
+++ b/src/config/Slate/Headings/headingsMenu.scss
@@ -0,0 +1,44 @@
+.slate-toolbar .ui.dropdown#headings-menu .menu {
+ .item {
+ padding: 0 !important;
+ text-align: center;
+ .button-wrapper {
+ margin: 0;
+ .ui.button {
+ border: none;
+ border-radius: 0;
+ padding: 0.78571429rem 1.14285714rem !important;
+
+ &,
+ &.active {
+ background-color: transparent !important;
+ color: rgba(0, 0, 0, 0.6) !important;
+ }
+
+ &.headings-h2 {
+ font-size: 2.222rem;
+ font-family: 'Titillium Web', Geneva, Tahoma, sans-serif;
+ }
+ &.headings-h3 {
+ font-size: 1.777rem;
+ font-family: 'Titillium Web', Geneva, Tahoma, sans-serif;
+ }
+ &.headings-h4 {
+ font-size: 1.555rem;
+ font-weight: 600;
+ font-family: 'Titillium Web', Geneva, Tahoma, sans-serif;
+ }
+ &.headings-h5 {
+ font-size: 1.333rem;
+ font-weight: 400;
+ font-family: 'Titillium Web', Geneva, Tahoma, sans-serif;
+ }
+ &.headings-h6 {
+ font-size: 1rem;
+ font-weight: 600;
+ font-family: 'Titillium Web', Geneva, Tahoma, sans-serif;
+ }
+ }
+ }
+ }
+}
diff --git a/src/config/Slate/Headings/index.js b/src/config/Slate/Headings/index.js
new file mode 100644
index 000000000..5d121aaa9
--- /dev/null
+++ b/src/config/Slate/Headings/index.js
@@ -0,0 +1,36 @@
+import React from 'react';
+import HeadingsMenu from './HeadingsMenu';
+import { insertToolbarButtons } from 'design-comuni-plone-theme/config/Slate/utils';
+
+export default function install(config) {
+ const { slate } = config.settings;
+
+ slate.buttons.headings = (props) => (
+
+ );
+
+ //aggiungo gli elements h5, h6 perchè non previsti da volto
+ slate.elements['h5'] = ({ attributes, children }) => (
+ {children}
+ );
+ slate.elements['h6'] = ({ attributes, children }) => (
+ {children}
+ );
+
+ // rimuovo i bottoni di heading di volto
+ slate.toolbarButtons = slate.toolbarButtons.filter(
+ (b) => b !== 'heading-two' && b !== 'heading-three',
+ );
+ slate.expandedToolbarButtons = slate.expandedToolbarButtons.filter(
+ (b) => b !== 'heading-two' && b !== 'heading-three',
+ );
+
+ //aggiungo il bottone di headings alla toolbar, dopo strikethrough
+ insertToolbarButtons(
+ ['separator', 'headings', 'separator'],
+ 'strikethrough',
+ slate,
+ );
+
+ return config;
+}
diff --git a/src/config/Slate/Underline/index.js b/src/config/Slate/Underline/index.js
new file mode 100644
index 000000000..eb5b9efba
--- /dev/null
+++ b/src/config/Slate/Underline/index.js
@@ -0,0 +1,10 @@
+import { insertToolbarButtons } from 'design-comuni-plone-theme/config/Slate/utils';
+
+export default function install(config) {
+ const { slate } = config.settings;
+
+ //aggiungo il bottone di underline alla toolbar, dopo bold
+ insertToolbarButtons(['underline'], 'italic', slate);
+
+ return config;
+}
diff --git a/src/config/Slate/config.js b/src/config/Slate/config.js
index b55fb2283..24f665ad3 100644
--- a/src/config/Slate/config.js
+++ b/src/config/Slate/config.js
@@ -1,6 +1,23 @@
//config.settings.slate.contextToolbarButtons
import installAlignment from 'design-comuni-plone-theme/config/Slate/Alignment';
+import installHeadings from 'design-comuni-plone-theme/config/Slate/Headings';
+import installUnderline from 'design-comuni-plone-theme/config/Slate/Underline';
+import installBlockquote from 'design-comuni-plone-theme/config/Slate/Blockquote';
export default function applyItaliaSlateConfig(config) {
installAlignment(config);
+ installHeadings(config);
+ installUnderline(config);
+
+ installBlockquote(config);
+
+ //remove callout because there's a Volto's block for it
+ delete config.settings.slate.elements.callout;
+ delete config.settings.slate.buttons.callout;
+ config.settings.slate.toolbarButtons = config.settings.slate.toolbarButtons.filter(
+ (b) => b !== 'callout',
+ );
+ config.settings.slate.expandedToolbarButtons = config.settings.slate.toolbarButtons.filter(
+ (b) => b !== 'callout',
+ );
}
diff --git a/src/config/Slate/Alignment/utils.js b/src/config/Slate/dropdownUtils.js
similarity index 86%
rename from src/config/Slate/Alignment/utils.js
rename to src/config/Slate/dropdownUtils.js
index ce42c5aab..dd485a851 100644
--- a/src/config/Slate/Alignment/utils.js
+++ b/src/config/Slate/dropdownUtils.js
@@ -9,15 +9,15 @@ import config from '@plone/volto/registry';
* @param {object} options
* @param {boolean} options.oneOfType Whether the given type is admitted once
*/
-export const toggleStyle = (editor, { cssClass, isBlock, oneOfType }) => {
+export const toggleStyle = (editor, { cssClass, isBlock, oneOf }) => {
if (isBlock) {
- toggleBlockStyle(editor, cssClass, oneOfType);
+ toggleBlockStyle(editor, cssClass, oneOf);
} else {
toggleInlineStyle(editor, cssClass);
}
};
-export const toggleBlockStyle = (editor, style, oneOfType) => {
+export const toggleBlockStyle = (editor, style, oneOf) => {
// 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;
@@ -33,7 +33,7 @@ export const toggleBlockStyle = (editor, style, oneOfType) => {
} else if (!isListItem && wantsList) {
// changeBlockToList(editor, format);
} else if (!isListItem && !wantsList) {
- internalToggleBlockStyle(editor, style);
+ internalToggleBlockStyle(editor, style, oneOf);
} else {
console.warn('toggleBlockStyle case not covered, please examine:', {
wantsList,
@@ -104,8 +104,8 @@ export const isInlineStyleActive = (editor, style) => {
return false;
};
-export const internalToggleBlockStyle = (editor, style) => {
- toggleBlockStyleInSelection(editor, style);
+export const internalToggleBlockStyle = (editor, style, oneOf) => {
+ toggleBlockStyleInSelection(editor, style, oneOf);
};
export const internalToggleInlineStyle = (editor, style) => {
@@ -138,7 +138,7 @@ function toggleInlineStyleInSelection(editor, style) {
}
}
-function toggleBlockStyleInSelection(editor, style) {
+function toggleBlockStyleInSelection(editor, style, oneOf) {
const sn = Array.from(
Editor.nodes(editor, {
mode: 'highest',
@@ -155,11 +155,22 @@ function toggleBlockStyleInSelection(editor, style) {
} else if (n.styleName.split(' ').filter((x) => x === style).length > 0) {
cn = cn
.split(' ')
- .filter((x) => x !== style)
+ .filter((x) => x !== style && x !== '')
.join(' ');
} else {
+ if (oneOf?.length > 0) {
+ cn = cn
+ .split(' ')
+ .filter((c) => !oneOf.includes(c))
+ .join(' ');
+ }
+
// the style is not set but other styles are set
- cn = cn.split(' ').concat(style).join(' ');
+ cn = cn
+ .split(' ')
+ .filter((c) => c !== '')
+ .concat(style)
+ .join(' ');
}
Transforms.setNodes(editor, { styleName: cn }, { at: p });
}
diff --git a/src/config/Slate/utils.js b/src/config/Slate/utils.js
new file mode 100644
index 000000000..9dfc962d2
--- /dev/null
+++ b/src/config/Slate/utils.js
@@ -0,0 +1,30 @@
+export const insertToolbarButtons = (buttons = [], insertAfter = '', slate) => {
+ const insertAtToolbarButtons = slate.toolbarButtons.indexOf(insertAfter) + 1;
+ slate.toolbarButtons = [
+ ...slate.toolbarButtons.slice(0, insertAtToolbarButtons),
+ ...buttons,
+ ...slate.toolbarButtons.slice(insertAtToolbarButtons),
+ ].filter((el, index, array) => {
+ if (index > 0) {
+ //rimuovo i separatori consecutivi nel caso se ne siano creati
+ if (el === 'separator' && array[index - 1] === 'separator') return false;
+ }
+ return true;
+ });
+
+ const insertAtExpandedToolbarButtons =
+ slate.toolbarButtons.indexOf(insertAfter) + 1;
+ slate.expandedToolbarButtons = [
+ ...slate.expandedToolbarButtons.slice(0, insertAtExpandedToolbarButtons),
+ ...buttons,
+ ...slate.expandedToolbarButtons.slice(insertAtExpandedToolbarButtons),
+ ].filter((el, index, array) => {
+ if (index > 0) {
+ //rimuovo i separatori consecutivi nel caso se ne siano creati
+ if (el === 'separator' && array[index - 1] === 'separator') return false;
+ }
+ return true;
+ });
+
+ //rimuovo doppi separator
+};
diff --git a/src/theme/ItaliaTheme/_main.scss b/src/theme/ItaliaTheme/_main.scss
index 432e2f3db..762b0c360 100644
--- a/src/theme/ItaliaTheme/_main.scss
+++ b/src/theme/ItaliaTheme/_main.scss
@@ -89,20 +89,7 @@ iframe {
.public-ui,
.cms-ui {
blockquote {
- position: relative;
- margin: 1.5rem 2rem;
- font-family: $font-family-serif;
-
- &:before {
- position: absolute;
- top: -1.8rem;
- left: -2rem;
- display: block;
- height: 0;
- color: $neutral-2-b2;
- content: '“';
- font-size: 400%;
- }
+ border-color: $primary !important;
}
.callout {
From f084598dfb80b75238901667f7a20bd7ced94fce Mon Sep 17 00:00:00 2001
From: Giulia Ghisini
Date: Thu, 28 Sep 2023 16:02:44 +0200
Subject: [PATCH 005/353] chore: blockquote slate
---
src/config/Slate/Alignment/AlignMenu.jsx | 11 ++-
.../Slate/Blockquote/BlockquoteMenu.jsx | 32 ++++---
src/config/Slate/dropdownUtils.js | 93 ++++++++++++++++---
src/icons/Group.svg | 1 +
src/icons/blockquote-card-dark.svg | 1 +
src/icons/blockquote-card.svg | 1 +
src/icons/blockquote-simple.svg | 1 +
7 files changed, 113 insertions(+), 27 deletions(-)
create mode 100644 src/icons/Group.svg
create mode 100644 src/icons/blockquote-card-dark.svg
create mode 100644 src/icons/blockquote-card.svg
create mode 100644 src/icons/blockquote-simple.svg
diff --git a/src/config/Slate/Alignment/AlignMenu.jsx b/src/config/Slate/Alignment/AlignMenu.jsx
index ded0e0117..774460ebe 100644
--- a/src/config/Slate/Alignment/AlignMenu.jsx
+++ b/src/config/Slate/Alignment/AlignMenu.jsx
@@ -22,22 +22,22 @@ import 'design-comuni-plone-theme/config/Slate/dropdownStyle.scss';
const ALIGN_OPTIONS = [
{
cssClass: 'text-left',
- text: 'Allinea a sinistra',
+ title: 'Allinea a sinistra',
icon: alignLeftSVG,
},
{
cssClass: 'text-center',
- text: 'Allinea al centro',
+ title: 'Allinea al centro',
icon: alignCenterSVG,
},
{
cssClass: 'text-end',
- text: 'Allinea a destra',
+ title: 'Allinea a destra',
icon: alignRightSVG,
},
{
cssClass: 'text-justify',
- text: 'Allinea il testo giustificato',
+ title: 'Allinea il testo giustificato',
icon: alignJustifySVG,
},
];
@@ -81,7 +81,8 @@ const AlignButton = (props) => {
const blockOpts = ALIGN_OPTIONS.map((def) => {
return {
value: def.cssClass,
- text: def.label,
+ text: def.text,
+ title: def.title,
icon: (props) => ,
isBlock: true,
originalIcon: def.icon,
diff --git a/src/config/Slate/Blockquote/BlockquoteMenu.jsx b/src/config/Slate/Blockquote/BlockquoteMenu.jsx
index fa2831189..62f87c211 100644
--- a/src/config/Slate/Blockquote/BlockquoteMenu.jsx
+++ b/src/config/Slate/Blockquote/BlockquoteMenu.jsx
@@ -13,6 +13,9 @@ import { Icon } from '@plone/volto/components';
import { ToolbarButton } from '@plone/volto-slate/editor/ui';
import quoteIcon from '@plone/volto/icons/quote.svg';
+import blockquoteSimpleIcon from 'design-comuni-plone-theme/icons/blockquote-simple.svg';
+import blockquoteCardIcon from 'design-comuni-plone-theme/icons/blockquote-card.svg';
+import blockquoteCardDarkIcon from 'design-comuni-plone-theme/icons/blockquote-card-dark.svg';
import 'design-comuni-plone-theme/config/Slate/dropdownStyle.scss';
@@ -20,19 +23,20 @@ const OPTIONS = [
{
title: 'Blockquote semplice',
format: 'blockquote',
- icon: quoteIcon,
+ icon: blockquoteSimpleIcon,
+ cssClass: 'blockquote',
},
{
title: 'Blockquote card',
format: 'blockquote',
- icon: quoteIcon,
- className: 'blockquote-card',
+ icon: blockquoteCardIcon,
+ cssClass: 'blockquote-card',
},
{
title: 'Blockquote card scuro',
format: 'blockquote',
- icon: quoteIcon,
- className: 'blockquote-card dark',
+ icon: blockquoteCardDarkIcon,
+ cssClass: 'blockquote-card dark',
},
];
@@ -47,7 +51,7 @@ const BlockquoteMenuButton = ({ icon, active, ...props }) => (
);
-const MenuOpts = ({ editor, toSelect, option, type }) => {
+const MenuOpts = ({ editor, toSelect, option, type, ...props }) => {
const isActive = toSelect.includes(option);
return (
@@ -61,6 +65,8 @@ const MenuOpts = ({ editor, toSelect, option, type }) => {
toggleStyle(editor, {
cssClass: selItem.value,
isBlock: true,
+ format: selItem.format,
+ allowedChildren: props.allowedChildren,
oneOf: OPTIONS.reduce((acc, o) => [...acc, o.cssClass], []),
});
}}
@@ -75,7 +81,9 @@ const BlockquoteButton = (props) => {
const blockOpts = OPTIONS.map((def) => {
return {
value: def.cssClass,
- text: def.label,
+ text: def.text,
+ title: def.title,
+ format: def.format,
icon: (props) => ,
isBlock: true,
originalIcon: def.icon,
@@ -84,11 +92,12 @@ const BlockquoteButton = (props) => {
// Calculating the initial selection.
const toSelect = [];
- let selectedIcon = OPTIONS[0].icon;
+ let selectedIcon = quoteIcon;
+ const oneOf = OPTIONS.reduce((acc, o) => [...acc, o.cssClass], []);
// block styles
for (const val of blockOpts) {
- const ia = isBlockStyleActive(editor, val.value);
+ const ia = isBlockStyleActive(editor, val.value, oneOf);
if (ia) {
toSelect.push(val);
@@ -99,13 +108,14 @@ const BlockquoteButton = (props) => {
const menuItemProps = {
toSelect,
editor,
+ ...props,
};
const showMenu = blockOpts.length;
return showMenu ? (