@plone/volto-slate 18.2.1 → 18.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,16 @@
|
|
|
8
8
|
|
|
9
9
|
<!-- towncrier release notes start -->
|
|
10
10
|
|
|
11
|
+
## 18.2.2 (2025-02-08)
|
|
12
|
+
|
|
13
|
+
### Bugfix
|
|
14
|
+
|
|
15
|
+
- In `RichTextWidget` and `HtmlSlateWidget`, fix breaking a list by typing Enter. @nileshgulia1 [#6570](https://github.com/plone/volto/issues/6570)
|
|
16
|
+
|
|
17
|
+
### Internal
|
|
18
|
+
|
|
19
|
+
- Remove hard dependencies on `react`, move to `peerDependencies` @sneridagh [#6728](https://github.com/plone/volto/issues/6728)
|
|
20
|
+
|
|
11
21
|
## 18.2.1 (2025-01-31)
|
|
12
22
|
|
|
13
23
|
### Bugfix
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plone/volto-slate",
|
|
3
|
-
"version": "18.2.
|
|
3
|
+
"version": "18.2.2",
|
|
4
4
|
"description": "Slate.js integration with Volto",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"author": "European Environment Agency: IDM2 A-Team",
|
|
@@ -25,8 +25,6 @@
|
|
|
25
25
|
"is-url": "1.2.4",
|
|
26
26
|
"jsdom": "^16.6.0",
|
|
27
27
|
"lodash": "4.17.21",
|
|
28
|
-
"react": "18.2.0",
|
|
29
|
-
"react-dom": "18.2.0",
|
|
30
28
|
"react-intersection-observer": "9.1.0",
|
|
31
29
|
"react-intl": "3.12.1",
|
|
32
30
|
"react-redux": "8.1.2",
|
|
@@ -46,6 +44,10 @@
|
|
|
46
44
|
"babel-plugin-transform-class-properties": "^6.24.1",
|
|
47
45
|
"release-it": "^17.0.0"
|
|
48
46
|
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"react": "^18.2.0",
|
|
49
|
+
"react-dom": "^18.2.0"
|
|
50
|
+
},
|
|
49
51
|
"scripts": {
|
|
50
52
|
"dry-release": "release-it --dry-run",
|
|
51
53
|
"release": "release-it",
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Editor, Range, Transforms } from 'slate';
|
|
2
|
+
|
|
3
|
+
import config from '@plone/volto/registry';
|
|
4
|
+
import { isCursorAtBlockEnd } from '@plone/volto-slate/utils/selection';
|
|
5
|
+
import { getCurrentListItem } from '@plone/volto-slate/utils/lists';
|
|
6
|
+
import { createEmptyParagraph } from '@plone/volto-slate/utils/blocks';
|
|
7
|
+
|
|
8
|
+
export const breakListInWidget = (editor) => {
|
|
9
|
+
const { insertBreak } = editor;
|
|
10
|
+
|
|
11
|
+
editor.insertBreak = () => {
|
|
12
|
+
if (!(editor.selection && Range.isCollapsed(editor.selection))) {
|
|
13
|
+
insertBreak();
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const { slate } = config.settings;
|
|
18
|
+
const { anchor } = editor.selection;
|
|
19
|
+
|
|
20
|
+
const ref = Editor.rangeRef(editor, editor.selection, {
|
|
21
|
+
affinity: 'inward',
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const [listItem, listItemPath] = getCurrentListItem(editor);
|
|
25
|
+
if (listItem) {
|
|
26
|
+
if (Editor.string(editor, listItemPath)) {
|
|
27
|
+
Transforms.splitNodes(editor, {
|
|
28
|
+
at: editor.selection,
|
|
29
|
+
match: (node) => node.type === slate.listItemType,
|
|
30
|
+
always: true,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const [parent] = Editor.parent(editor, anchor.path);
|
|
38
|
+
|
|
39
|
+
if (parent.type !== slate.listItemType || anchor.offset > 0) {
|
|
40
|
+
insertBreak();
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
Editor.deleteBackward(editor, { unit: 'line' });
|
|
45
|
+
// also account for empty nodes [{text: ''}]
|
|
46
|
+
if (Editor.isEmpty(editor, parent)) {
|
|
47
|
+
Transforms.removeNodes(editor, { at: ref.current });
|
|
48
|
+
|
|
49
|
+
Transforms.insertNodes(editor, createEmptyParagraph(), {
|
|
50
|
+
at: [editor.children.length],
|
|
51
|
+
});
|
|
52
|
+
Transforms.select(editor, Editor.end(editor, []));
|
|
53
|
+
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
Transforms.removeNodes(editor, { at: ref.current });
|
|
58
|
+
|
|
59
|
+
if (isCursorAtBlockEnd(editor)) {
|
|
60
|
+
Editor.insertNode(editor, createEmptyParagraph());
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
return true;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
return editor;
|
|
67
|
+
};
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
import { withDeleteSelectionOnEnter } from '@plone/volto-slate/editor/extensions';
|
|
23
23
|
import {
|
|
24
24
|
breakList,
|
|
25
|
+
breakListInWidget,
|
|
25
26
|
withDeserializers,
|
|
26
27
|
withLists,
|
|
27
28
|
withSplitBlocksOnBreak,
|
|
@@ -47,6 +48,7 @@ export default function applyConfig(config) {
|
|
|
47
48
|
breakList,
|
|
48
49
|
normalizeExternalData,
|
|
49
50
|
],
|
|
51
|
+
slateWidgetExtensions: [breakListInWidget],
|
|
50
52
|
|
|
51
53
|
// Pluggable handlers for the onKeyDown event of <Editable />
|
|
52
54
|
// Order matters here. A handler can return `true` to stop executing any
|
|
@@ -12,6 +12,7 @@ import { defineMessages, injectIntl } from 'react-intl';
|
|
|
12
12
|
import { FormFieldWrapper } from '@plone/volto/components/manage/Widgets';
|
|
13
13
|
import SlateEditor from '@plone/volto-slate/editor/SlateEditor';
|
|
14
14
|
import { serializeNodes } from '@plone/volto-slate/editor/render';
|
|
15
|
+
import { handleKeyDetached } from '@plone/volto-slate/blocks/Text/keyboard';
|
|
15
16
|
import { makeEditor } from '@plone/volto-slate/utils/editor';
|
|
16
17
|
import deserialize from '@plone/volto-slate/editor/deserialize';
|
|
17
18
|
|
|
@@ -19,6 +20,8 @@ import {
|
|
|
19
20
|
createEmptyParagraph,
|
|
20
21
|
normalizeExternalData,
|
|
21
22
|
} from '@plone/volto-slate/utils';
|
|
23
|
+
import config from '@plone/volto/registry';
|
|
24
|
+
|
|
22
25
|
import { ErrorBoundary } from './ErrorBoundary';
|
|
23
26
|
|
|
24
27
|
import './style.css';
|
|
@@ -44,6 +47,8 @@ const HtmlSlateWidget = (props) => {
|
|
|
44
47
|
intl,
|
|
45
48
|
} = props;
|
|
46
49
|
|
|
50
|
+
const { slateWidgetExtensions } = config.settings.slate;
|
|
51
|
+
|
|
47
52
|
const [selected, setSelected] = React.useState(focus);
|
|
48
53
|
|
|
49
54
|
const editor = React.useMemo(() => makeEditor(), []);
|
|
@@ -127,7 +132,10 @@ const HtmlSlateWidget = (props) => {
|
|
|
127
132
|
block={block}
|
|
128
133
|
selected={selected}
|
|
129
134
|
properties={properties}
|
|
135
|
+
extensions={slateWidgetExtensions}
|
|
136
|
+
onKeyDown={handleKeyDetached}
|
|
130
137
|
placeholder={placeholder}
|
|
138
|
+
editableProps={{ 'aria-multiline': 'true' }}
|
|
131
139
|
/>
|
|
132
140
|
</ErrorBoundary>
|
|
133
141
|
</div>
|
|
@@ -7,7 +7,9 @@ import React from 'react';
|
|
|
7
7
|
import isUndefined from 'lodash/isUndefined';
|
|
8
8
|
import isString from 'lodash/isString';
|
|
9
9
|
import { FormFieldWrapper } from '@plone/volto/components/manage/Widgets';
|
|
10
|
+
import { handleKeyDetached } from '@plone/volto-slate/blocks/Text/keyboard';
|
|
10
11
|
import SlateEditor from '@plone/volto-slate/editor/SlateEditor';
|
|
12
|
+
import config from '@plone/volto/registry';
|
|
11
13
|
|
|
12
14
|
import { createEmptyParagraph, createParagraph } from '../utils/blocks';
|
|
13
15
|
|
|
@@ -37,6 +39,7 @@ const SlateRichTextWidget = (props) => {
|
|
|
37
39
|
readOnly = false,
|
|
38
40
|
} = props;
|
|
39
41
|
const [selected, setSelected] = React.useState(focus);
|
|
42
|
+
const { slateWidgetExtensions } = config.settings.slate;
|
|
40
43
|
|
|
41
44
|
return (
|
|
42
45
|
<FormFieldWrapper {...props} draggable={false} className="slate_wysiwyg">
|
|
@@ -62,7 +65,10 @@ const SlateRichTextWidget = (props) => {
|
|
|
62
65
|
block={block}
|
|
63
66
|
selected={selected}
|
|
64
67
|
properties={properties}
|
|
68
|
+
extensions={slateWidgetExtensions}
|
|
69
|
+
onKeyDown={handleKeyDetached}
|
|
65
70
|
placeholder={placeholder}
|
|
71
|
+
editableProps={{ 'aria-multiline': 'true' }}
|
|
66
72
|
/>
|
|
67
73
|
</div>
|
|
68
74
|
</FormFieldWrapper>
|