@plone/volto-slate 18.0.0-alpha.8 → 18.0.0
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/.stylelintrc +14 -0
- package/CHANGELOG.md +106 -0
- package/locales/pt_BR/LC_MESSAGES/volto.po +205 -0
- package/package.json +13 -2
- package/src/blocks/Table/TableBlockEdit.jsx +2 -1
- package/src/blocks/Table/TableBlockView.jsx +2 -2
- package/src/blocks/Table/index.js +0 -1
- package/src/blocks/Text/DefaultTextBlockEditor.jsx +2 -5
- package/src/blocks/Text/DetachedTextBlockEditor.jsx +12 -1
- package/src/blocks/Text/SlashMenu.jsx +16 -2
- package/src/blocks/Text/extensions/breakList.js +24 -9
- package/src/blocks/Text/extensions/insertBreak.js +1 -1
- package/src/blocks/Text/extensions/withDeserializers.js +1 -4
- package/src/blocks/Text/{index.js → index.jsx} +6 -22
- package/src/blocks/Text/keyboard/indentListItems.js +2 -2
- package/src/constants.js +3 -0
- package/src/editor/less/editor.less +14 -5
- package/src/editor/less/slate.less +3 -1
- package/src/editor/plugins/Markdown/constants.js +9 -9
- package/src/editor/plugins/Markdown/extensions.js +2 -2
- package/src/editor/ui/PositionedToolbar.jsx +9 -2
- package/src/elementEditor/PluginEditor.jsx +2 -1
- package/src/elementEditor/utils.js +24 -5
- package/src/utils/blocks.js +16 -1
- package/src/utils/volto-blocks.js +15 -2
- package/src/widgets/HtmlSlateWidget.jsx +1 -1
- package/src/widgets/ObjectByTypeWidget.jsx +2 -1
- package/src/widgets/RichTextWidget.jsx +1 -1
- /package/src/editor/plugins/Blockquote/{index.js → index.jsx} +0 -0
- /package/src/editor/plugins/Callout/{index.js → index.jsx} +0 -0
- /package/src/editor/plugins/Link/{index.js → index.jsx} +0 -0
- /package/src/editor/plugins/StyleMenu/{index.js → index.jsx} +0 -0
- /package/src/editor/plugins/Table/{index.js → index.jsx} +0 -0
package/.stylelintrc
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": ["stylelint-config-idiomatic-order"],
|
|
3
|
+
"plugins": ["stylelint-prettier"],
|
|
4
|
+
"overrides": [
|
|
5
|
+
{
|
|
6
|
+
"files": ["**/*.less"],
|
|
7
|
+
"customSyntax": "postcss-less"
|
|
8
|
+
}
|
|
9
|
+
],
|
|
10
|
+
"rules": {
|
|
11
|
+
"prettier/prettier": true,
|
|
12
|
+
"order/properties-alphabetical-order": null
|
|
13
|
+
}
|
|
14
|
+
}
|
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,112 @@
|
|
|
8
8
|
|
|
9
9
|
<!-- towncrier release notes start -->
|
|
10
10
|
|
|
11
|
+
## 18.0.0 (2024-10-31)
|
|
12
|
+
|
|
13
|
+
### Internal
|
|
14
|
+
|
|
15
|
+
- Release 18.0.0 final @sneridagh
|
|
16
|
+
|
|
17
|
+
## 18.0.0-alpha.20 (2024-10-30)
|
|
18
|
+
|
|
19
|
+
### Bugfix
|
|
20
|
+
|
|
21
|
+
- Fix slight CSS lint violation in volto-slate @sneridagh [#6444](https://github.com/plone/volto/issues/6444)
|
|
22
|
+
|
|
23
|
+
## 18.0.0-alpha.19 (2024-10-03)
|
|
24
|
+
|
|
25
|
+
### Feature
|
|
26
|
+
|
|
27
|
+
- Update Brazilian Portuguese translations. @ericof [#6292](https://github.com/plone/volto/issues/6292)
|
|
28
|
+
|
|
29
|
+
### Bugfix
|
|
30
|
+
|
|
31
|
+
- Fetch `user` before pass it to the `restricted` function of the block settings. @wesleybl [#6293](https://github.com/plone/volto/issues/6293)
|
|
32
|
+
|
|
33
|
+
## 18.0.0-alpha.18 (2024-09-13)
|
|
34
|
+
|
|
35
|
+
### Feature
|
|
36
|
+
|
|
37
|
+
- Pass `user`, `navRoot` and `contentType` objects to the `restricted` function of the block settings. @wesleybl [#6264](https://github.com/plone/volto/issues/6264)
|
|
38
|
+
|
|
39
|
+
## 18.0.0-alpha.17 (2024-07-05)
|
|
40
|
+
|
|
41
|
+
### Feature
|
|
42
|
+
|
|
43
|
+
- Use the unused `toggleButton` prop in `PositionedToolbar` to render the toolbar in a different `portal` target falling back to `document.body` if `toggleButton` is not provided. @ichim-david
|
|
44
|
+
|
|
45
|
+
When `toggleButton` is provided as a `portal` target, allow negative left positioning except when the target is `document.body` to prevent the toolbar going off-screen and avoid breaking changes. @ichim-david [#6159](https://github.com/plone/volto/issues/6159)
|
|
46
|
+
|
|
47
|
+
## 18.0.0-alpha.16 (2024-07-03)
|
|
48
|
+
|
|
49
|
+
### Internal
|
|
50
|
+
|
|
51
|
+
- Fix dependencies for the package @sneridagh [#6148](https://github.com/plone/volto/issues/6148)
|
|
52
|
+
|
|
53
|
+
## 18.0.0-alpha.15 (2024-06-28)
|
|
54
|
+
|
|
55
|
+
### Internal
|
|
56
|
+
|
|
57
|
+
- Add proper dependencies to `volto-slate`. @sneridagh [#6130](https://github.com/plone/volto/issues/6130)
|
|
58
|
+
|
|
59
|
+
## 18.0.0-alpha.14 (2024-06-26)
|
|
60
|
+
|
|
61
|
+
### Feature
|
|
62
|
+
|
|
63
|
+
- Added `link-form-container` styles for `AddLinkForm` component. @ichim-david [#5607](https://github.com/plone/volto/issues/5607)
|
|
64
|
+
- Handle breakList in DetachedTextBlockEditor. @giuliaghisini [#6106](https://github.com/plone/volto/issues/6106)
|
|
65
|
+
|
|
66
|
+
### Bugfix
|
|
67
|
+
|
|
68
|
+
- In the Slate text block, the markup shortcuts for heading and blockquote work again. @kHAPPY2004 [#5452](https://github.com/plone/volto/issues/5452)
|
|
69
|
+
- When pasting an image into a Slate block, now only an image block is created, instead of both a Slate block and an image block. @aryan7081 [#5818](https://github.com/plone/volto/issues/5818)
|
|
70
|
+
|
|
71
|
+
### Internal
|
|
72
|
+
|
|
73
|
+
- Rename files with wrong extension `js->jsx` when they contain JSX. @sneridagh [#6114](https://github.com/plone/volto/issues/6114)
|
|
74
|
+
|
|
75
|
+
## 18.0.0-alpha.13 (2024-06-13)
|
|
76
|
+
|
|
77
|
+
### Bugfix
|
|
78
|
+
|
|
79
|
+
- Fix removal of slate formatting applied to text when toggling the list buttons @robgietema [#6080](https://github.com/plone/volto/issues/6080)
|
|
80
|
+
|
|
81
|
+
## 18.0.0-alpha.12 (2024-04-23)
|
|
82
|
+
|
|
83
|
+
### Bugfix
|
|
84
|
+
|
|
85
|
+
- In the Slate text block, the markup shortcuts for bold, italic and strikethrough work again. @kHAPPY2004 [#5605](https://github.com/plone/volto/issues/5605)
|
|
86
|
+
|
|
87
|
+
### Internal
|
|
88
|
+
|
|
89
|
+
- Update imports to work with the new code split components in Volto. @pnicolli [#5295](https://github.com/plone/volto/issues/5295)
|
|
90
|
+
|
|
91
|
+
## 18.0.0-alpha.11 (2024-04-03)
|
|
92
|
+
|
|
93
|
+
### Bugfix
|
|
94
|
+
|
|
95
|
+
- Fix removing an element in slate when cursor is at the end of the element to be removed; Fix losing selection when adding an element. @razvanMiu [#5928](https://github.com/plone/volto/issues/5928)
|
|
96
|
+
|
|
97
|
+
## 18.0.0-alpha.10 (2024-03-14)
|
|
98
|
+
|
|
99
|
+
### Breaking
|
|
100
|
+
|
|
101
|
+
- Remove legacy `text`, `table` and `hero` blocks based in `draftJS` @sneridagh [#5846](https://github.com/plone/volto/issues/5846)
|
|
102
|
+
|
|
103
|
+
### Bugfix
|
|
104
|
+
|
|
105
|
+
- Fix other occurrences of mutable (referenced) objects when assigning the default inner `blocksConfig` object for the `grid` block, pass by value instead. sneridagh [#5859](https://github.com/plone/volto/issues/5859)
|
|
106
|
+
|
|
107
|
+
### Internal
|
|
108
|
+
|
|
109
|
+
- Fix CSS lint @sneridagh [#5849](https://github.com/plone/volto/issues/5849)
|
|
110
|
+
|
|
111
|
+
## 18.0.0-alpha.9 (2024-03-02)
|
|
112
|
+
|
|
113
|
+
### Internal
|
|
114
|
+
|
|
115
|
+
- Update dependencies @sneridagh [#5815](https://github.com/plone/volto/issues/5815)
|
|
116
|
+
|
|
11
117
|
## 18.0.0-alpha.8 (2024-03-01)
|
|
12
118
|
|
|
13
119
|
### Feature
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
msgid ""
|
|
2
|
+
msgstr ""
|
|
3
|
+
"Project-Id-Version: Plone\n"
|
|
4
|
+
"POT-Creation-Date: 2022-07-20T12:45:09.681Z\n"
|
|
5
|
+
"PO-Revision-Date: \n"
|
|
6
|
+
"Last-Translator: Érico Andrei <ericof@plone.org>\n"
|
|
7
|
+
"Language-Team: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
|
|
8
|
+
"Language: pt_BR\n"
|
|
9
|
+
"MIME-Version: 1.0\n"
|
|
10
|
+
"Content-Type: text/plain; charset=utf-8\n"
|
|
11
|
+
"Content-Transfer-Encoding: 8bit\n"
|
|
12
|
+
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
|
13
|
+
"Language-Code: en\n"
|
|
14
|
+
"Language-Name: English\n"
|
|
15
|
+
"Preferred-Encodings: utf-8\n"
|
|
16
|
+
"Domain: volto\n"
|
|
17
|
+
"X-Generator: Poedit 3.5\n"
|
|
18
|
+
|
|
19
|
+
# defaultMessage: Add link
|
|
20
|
+
#: editor/plugins/Link/index
|
|
21
|
+
msgid "Add link"
|
|
22
|
+
msgstr "Adicionar link"
|
|
23
|
+
|
|
24
|
+
# defaultMessage: An error has occurred while editing "{name}" field. We have been notified and we are looking into it. Please save your work and retry. If the issue persists please contact the site administrator.
|
|
25
|
+
#: widgets/HtmlSlateWidget
|
|
26
|
+
#, fuzzy
|
|
27
|
+
msgid "An error has occurred while editing \"{name}\" field. We have been notified and we are looking into it. Please save your work and retry. If the issue persists please contact the site administrator."
|
|
28
|
+
msgstr "Ocorreu um erro ao editar o campo \"{name}\". Fomos notificados e estamos analisando o problema. Salve seu trabalho e tente novamente. Se o problema persistir, entre em contato com o administrador do site."
|
|
29
|
+
|
|
30
|
+
# defaultMessage: An error has occurred while rendering "{name}" field. We have been notified and we are looking into it. If the issue persists please contact the site administrator.
|
|
31
|
+
#: widgets/RichTextWidgetView
|
|
32
|
+
#, fuzzy
|
|
33
|
+
msgid "An error has occurred while rendering \"{name}\" field. We have been notified and we are looking into it. If the issue persists please contact the site administrator."
|
|
34
|
+
msgstr "Ocorreu um erro ao renderizar o campo \"{name}\". Fomos notificados e estamos analisando o problema. Se o problema persistir, entre em contato com o administrador do site."
|
|
35
|
+
|
|
36
|
+
# defaultMessage: Bottom
|
|
37
|
+
#: blocks/Table/TableBlockEdit
|
|
38
|
+
msgid "Bottom"
|
|
39
|
+
msgstr "Base"
|
|
40
|
+
|
|
41
|
+
# defaultMessage: Center
|
|
42
|
+
#: blocks/Table/TableBlockEdit
|
|
43
|
+
#, fuzzy
|
|
44
|
+
msgid "Center"
|
|
45
|
+
msgstr "Centro"
|
|
46
|
+
|
|
47
|
+
# defaultMessage: Delete col
|
|
48
|
+
#: blocks/Table/TableBlockEdit editor/plugins/Table/index
|
|
49
|
+
#, fuzzy
|
|
50
|
+
msgid "Delete col"
|
|
51
|
+
msgstr "Excluir coluna"
|
|
52
|
+
|
|
53
|
+
# defaultMessage: Delete row
|
|
54
|
+
#: blocks/Table/TableBlockEdit editor/plugins/Table/index
|
|
55
|
+
#, fuzzy
|
|
56
|
+
msgid "Delete row"
|
|
57
|
+
msgstr "Excluir linha"
|
|
58
|
+
|
|
59
|
+
# defaultMessage: Delete table
|
|
60
|
+
#: editor/plugins/Table/index
|
|
61
|
+
#, fuzzy
|
|
62
|
+
msgid "Delete table"
|
|
63
|
+
msgstr "Excluir tabela"
|
|
64
|
+
|
|
65
|
+
# defaultMessage: Divide each row into separate cells
|
|
66
|
+
#: blocks/Table/TableBlockEdit
|
|
67
|
+
#, fuzzy
|
|
68
|
+
msgid "Divide each row into separate cells"
|
|
69
|
+
msgstr "Dividir cada linha em células separadas"
|
|
70
|
+
|
|
71
|
+
# defaultMessage: Edit element
|
|
72
|
+
#: elementEditor/messages
|
|
73
|
+
#, fuzzy
|
|
74
|
+
msgid "Edit element"
|
|
75
|
+
msgstr "Editar elemento"
|
|
76
|
+
|
|
77
|
+
# defaultMessage: Edit link
|
|
78
|
+
#: editor/plugins/AdvancedLink/index editor/plugins/Link/index
|
|
79
|
+
#, fuzzy
|
|
80
|
+
msgid "Edit link"
|
|
81
|
+
msgstr "Editar link"
|
|
82
|
+
|
|
83
|
+
# defaultMessage: Fixed width table cells
|
|
84
|
+
#: blocks/Table/TableBlockEdit
|
|
85
|
+
#, fuzzy
|
|
86
|
+
msgid "Fixed width table cells"
|
|
87
|
+
msgstr "Células de tabela de largura fixa"
|
|
88
|
+
|
|
89
|
+
# defaultMessage: Hide headers
|
|
90
|
+
#: blocks/Table/TableBlockEdit
|
|
91
|
+
#, fuzzy
|
|
92
|
+
msgid "Hide headers"
|
|
93
|
+
msgstr "Ocultar cabeçalhos"
|
|
94
|
+
|
|
95
|
+
# defaultMessage: Insert col after
|
|
96
|
+
#: blocks/Table/TableBlockEdit editor/plugins/Table/index
|
|
97
|
+
#, fuzzy
|
|
98
|
+
msgid "Insert col after"
|
|
99
|
+
msgstr "Inserir coluna após"
|
|
100
|
+
|
|
101
|
+
# defaultMessage: Insert col before
|
|
102
|
+
#: blocks/Table/TableBlockEdit editor/plugins/Table/index
|
|
103
|
+
#, fuzzy
|
|
104
|
+
msgid "Insert col before"
|
|
105
|
+
msgstr "Inserir coluna antes"
|
|
106
|
+
|
|
107
|
+
# defaultMessage: Insert row after
|
|
108
|
+
#: blocks/Table/TableBlockEdit editor/plugins/Table/index
|
|
109
|
+
#, fuzzy
|
|
110
|
+
msgid "Insert row after"
|
|
111
|
+
msgstr "Inserir linha após"
|
|
112
|
+
|
|
113
|
+
# defaultMessage: Insert row before
|
|
114
|
+
#: blocks/Table/TableBlockEdit editor/plugins/Table/index
|
|
115
|
+
#, fuzzy
|
|
116
|
+
msgid "Insert row before"
|
|
117
|
+
msgstr "Inserir linha antes"
|
|
118
|
+
|
|
119
|
+
# defaultMessage: Left
|
|
120
|
+
#: blocks/Table/TableBlockEdit
|
|
121
|
+
#, fuzzy
|
|
122
|
+
msgid "Left"
|
|
123
|
+
msgstr "Esquerda"
|
|
124
|
+
|
|
125
|
+
# defaultMessage: Make the table compact
|
|
126
|
+
#: blocks/Table/TableBlockEdit
|
|
127
|
+
#, fuzzy
|
|
128
|
+
msgid "Make the table compact"
|
|
129
|
+
msgstr "Compactar a tabela"
|
|
130
|
+
|
|
131
|
+
# defaultMessage: Make the table sortable
|
|
132
|
+
#: blocks/Table/TableBlockEdit
|
|
133
|
+
msgid "Make the table sortable"
|
|
134
|
+
msgstr "Tornar a tabela ordenável"
|
|
135
|
+
|
|
136
|
+
# defaultMessage: Middle
|
|
137
|
+
#: blocks/Table/TableBlockEdit
|
|
138
|
+
msgid "Middle"
|
|
139
|
+
msgstr "Meio"
|
|
140
|
+
|
|
141
|
+
# defaultMessage: No matching blocks
|
|
142
|
+
#: blocks/Text/SlashMenu
|
|
143
|
+
#, fuzzy
|
|
144
|
+
msgid "No matching blocks"
|
|
145
|
+
msgstr "Não há blocos correspondentes"
|
|
146
|
+
|
|
147
|
+
# defaultMessage: Reduce complexity
|
|
148
|
+
#: blocks/Table/TableBlockEdit
|
|
149
|
+
#, fuzzy
|
|
150
|
+
msgid "Reduce complexity"
|
|
151
|
+
msgstr "Reduzir complexidade"
|
|
152
|
+
|
|
153
|
+
# defaultMessage: Remove element
|
|
154
|
+
#: elementEditor/messages
|
|
155
|
+
#, fuzzy
|
|
156
|
+
msgid "Remove element"
|
|
157
|
+
msgstr "Remover elemento"
|
|
158
|
+
|
|
159
|
+
# defaultMessage: Remove link
|
|
160
|
+
#: editor/plugins/AdvancedLink/index
|
|
161
|
+
#, fuzzy
|
|
162
|
+
msgid "Remove link"
|
|
163
|
+
msgstr "Remover link"
|
|
164
|
+
|
|
165
|
+
# defaultMessage: Right
|
|
166
|
+
#: blocks/Table/TableBlockEdit
|
|
167
|
+
#, fuzzy
|
|
168
|
+
msgid "Right"
|
|
169
|
+
msgstr "Direita"
|
|
170
|
+
|
|
171
|
+
# defaultMessage: Stripe alternate rows with color
|
|
172
|
+
#: blocks/Table/TableBlockEdit
|
|
173
|
+
#, fuzzy
|
|
174
|
+
msgid "Stripe alternate rows with color"
|
|
175
|
+
msgstr "Alternar cores das linhas"
|
|
176
|
+
|
|
177
|
+
# defaultMessage: Table
|
|
178
|
+
#: blocks/Table/TableBlockEdit
|
|
179
|
+
#, fuzzy
|
|
180
|
+
msgid "Table"
|
|
181
|
+
msgstr "Tabela"
|
|
182
|
+
|
|
183
|
+
# defaultMessage: Table color inverted
|
|
184
|
+
#: blocks/Table/TableBlockEdit
|
|
185
|
+
#, fuzzy
|
|
186
|
+
msgid "Table color inverted"
|
|
187
|
+
msgstr "Cor da tabela invertida"
|
|
188
|
+
|
|
189
|
+
# defaultMessage: Top
|
|
190
|
+
#: blocks/Table/TableBlockEdit
|
|
191
|
+
#, fuzzy
|
|
192
|
+
msgid "Top"
|
|
193
|
+
msgstr "Topo"
|
|
194
|
+
|
|
195
|
+
# defaultMessage: Type text…
|
|
196
|
+
#: blocks/Text/DefaultTextBlockEditor blocks/Text/DetachedTextBlockEditor
|
|
197
|
+
#, fuzzy
|
|
198
|
+
msgid "Type text…"
|
|
199
|
+
msgstr "Digite texto…"
|
|
200
|
+
|
|
201
|
+
# defaultMessage: Visible only in view mode
|
|
202
|
+
#: blocks/Table/TableBlockEdit
|
|
203
|
+
#, fuzzy
|
|
204
|
+
msgid "Visible only in view mode"
|
|
205
|
+
msgstr "Visível apenas no modo de visualização"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plone/volto-slate",
|
|
3
|
-
"version": "18.0.0
|
|
3
|
+
"version": "18.0.0",
|
|
4
4
|
"description": "Slate.js integration with Volto",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"author": "European Environment Agency: IDM2 A-Team",
|
|
@@ -18,16 +18,27 @@
|
|
|
18
18
|
"access": "public"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
+
"classnames": "2.2.6",
|
|
22
|
+
"github-slugger": "1.4.0",
|
|
21
23
|
"image-extensions": "1.1.0",
|
|
24
|
+
"is-hotkey": "0.2.0",
|
|
22
25
|
"is-url": "1.2.4",
|
|
23
26
|
"jsdom": "^16.6.0",
|
|
27
|
+
"lodash": "4.17.21",
|
|
24
28
|
"react": "18.2.0",
|
|
25
|
-
"react-intersection-observer": "9.1.0",
|
|
26
29
|
"react-dom": "18.2.0",
|
|
30
|
+
"react-intersection-observer": "9.1.0",
|
|
31
|
+
"react-intl": "3.12.1",
|
|
32
|
+
"react-redux": "8.1.2",
|
|
33
|
+
"react-router-dom": "5.2.0",
|
|
34
|
+
"react-toastify": "5.5.0",
|
|
35
|
+
"redux-mock-store": "1.5.4",
|
|
36
|
+
"semantic-ui-react": "2.1.5",
|
|
27
37
|
"slate": "0.100.0",
|
|
28
38
|
"slate-history": "0.100.0",
|
|
29
39
|
"slate-hyperscript": "0.100.0",
|
|
30
40
|
"slate-react": "0.98.4",
|
|
41
|
+
"uuid": "^9.0.1",
|
|
31
42
|
"weak-key": "^1.0.2"
|
|
32
43
|
},
|
|
33
44
|
"devDependencies": {
|
|
@@ -11,7 +11,8 @@ import cx from 'classnames';
|
|
|
11
11
|
import { defineMessages, injectIntl } from 'react-intl';
|
|
12
12
|
|
|
13
13
|
import Cell from './Cell';
|
|
14
|
-
import {
|
|
14
|
+
import { Icon, SidebarPortal } from '@plone/volto/components';
|
|
15
|
+
import { BlockDataForm } from '@plone/volto/components/manage/Form';
|
|
15
16
|
import TableSchema from './schema';
|
|
16
17
|
|
|
17
18
|
import rowBeforeSVG from '@plone/volto/icons/row-before.svg';
|
|
@@ -12,11 +12,8 @@ import {
|
|
|
12
12
|
validateFileUploadSize,
|
|
13
13
|
} from '@plone/volto/helpers';
|
|
14
14
|
import config from '@plone/volto/registry';
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
SidebarPortal,
|
|
18
|
-
BlockChooserButton,
|
|
19
|
-
} from '@plone/volto/components';
|
|
15
|
+
import { SidebarPortal, BlockChooserButton } from '@plone/volto/components';
|
|
16
|
+
import { BlockDataForm } from '@plone/volto/components/manage/Form';
|
|
20
17
|
|
|
21
18
|
import { SlateEditor } from '@plone/volto-slate/editor';
|
|
22
19
|
import { serializeNodesToText } from '@plone/volto-slate/editor/render';
|
|
@@ -4,6 +4,7 @@ import { useInView } from 'react-intersection-observer';
|
|
|
4
4
|
import { SlateEditor } from '@plone/volto-slate/editor';
|
|
5
5
|
import { serializeNodesToText } from '@plone/volto-slate/editor/render';
|
|
6
6
|
import { handleKeyDetached } from './keyboard';
|
|
7
|
+
import config from '@plone/volto/registry';
|
|
7
8
|
|
|
8
9
|
const DEBUG = false;
|
|
9
10
|
|
|
@@ -29,6 +30,7 @@ export const DetachedTextBlockEditor = (props) => {
|
|
|
29
30
|
const { value } = data;
|
|
30
31
|
|
|
31
32
|
const intl = useIntl();
|
|
33
|
+
const { textblockExtensions } = config.settings.slate;
|
|
32
34
|
const placeholder =
|
|
33
35
|
data.placeholder || formTitle || intl.formatMessage(messages.text);
|
|
34
36
|
let instructions = data?.instructions?.data || data?.instructions;
|
|
@@ -41,13 +43,22 @@ export const DetachedTextBlockEditor = (props) => {
|
|
|
41
43
|
rootMargin: '0px 0px 200px 0px',
|
|
42
44
|
});
|
|
43
45
|
|
|
46
|
+
const withBlockProperties = React.useCallback(
|
|
47
|
+
(editor) => {
|
|
48
|
+
editor.getBlockProps = () => props;
|
|
49
|
+
return editor;
|
|
50
|
+
},
|
|
51
|
+
[props],
|
|
52
|
+
);
|
|
53
|
+
|
|
44
54
|
return (
|
|
45
55
|
<div className="text-slate-editor-inner detached-slate-editor" ref={ref}>
|
|
46
56
|
<SlateEditor
|
|
47
57
|
index={index}
|
|
48
58
|
readOnly={!inView}
|
|
49
59
|
properties={properties}
|
|
50
|
-
|
|
60
|
+
extensions={textblockExtensions}
|
|
61
|
+
renderExtensions={[withBlockProperties]}
|
|
51
62
|
value={value}
|
|
52
63
|
block={block /* is this needed? */}
|
|
53
64
|
debug={DEBUG}
|
|
@@ -4,6 +4,7 @@ import { filter, isEmpty } from 'lodash';
|
|
|
4
4
|
import { Menu } from 'semantic-ui-react';
|
|
5
5
|
import { useIntl, FormattedMessage } from 'react-intl';
|
|
6
6
|
import { Icon } from '@plone/volto/components';
|
|
7
|
+
import { useUser } from '@plone/volto/hooks';
|
|
7
8
|
|
|
8
9
|
const emptySlateBlock = () => ({
|
|
9
10
|
value: [
|
|
@@ -105,9 +106,13 @@ const PersistentSlashMenu = ({ editor }) => {
|
|
|
105
106
|
selected,
|
|
106
107
|
allowedBlocks,
|
|
107
108
|
detached,
|
|
109
|
+
navRoot,
|
|
110
|
+
contentType,
|
|
108
111
|
} = props;
|
|
109
112
|
const disableNewBlocks = data?.disableNewBlocks || detached;
|
|
110
113
|
|
|
114
|
+
const user = useUser();
|
|
115
|
+
|
|
111
116
|
const [slashMenuSelected, setSlashMenuSelected] = React.useState(0);
|
|
112
117
|
|
|
113
118
|
const hasAllowedBlocks = !isEmpty(allowedBlocks);
|
|
@@ -122,8 +127,14 @@ const PersistentSlashMenu = ({ editor }) => {
|
|
|
122
127
|
hasAllowedBlocks
|
|
123
128
|
? allowedBlocks.includes(item.id)
|
|
124
129
|
: typeof item.restricted === 'function'
|
|
125
|
-
|
|
126
|
-
|
|
130
|
+
? !item.restricted({
|
|
131
|
+
properties,
|
|
132
|
+
block: item,
|
|
133
|
+
navRoot,
|
|
134
|
+
contentType,
|
|
135
|
+
user,
|
|
136
|
+
})
|
|
137
|
+
: !item.restricted,
|
|
127
138
|
)
|
|
128
139
|
.filter((block) => Boolean(block.title && block.id))
|
|
129
140
|
.filter((block) => {
|
|
@@ -152,6 +163,9 @@ const PersistentSlashMenu = ({ editor }) => {
|
|
|
152
163
|
properties,
|
|
153
164
|
slashCommand,
|
|
154
165
|
hasAllowedBlocks,
|
|
166
|
+
navRoot,
|
|
167
|
+
contentType,
|
|
168
|
+
user,
|
|
155
169
|
],
|
|
156
170
|
);
|
|
157
171
|
|
|
@@ -35,6 +35,8 @@ export const breakList = (editor) => {
|
|
|
35
35
|
|
|
36
36
|
const { slate } = config.settings;
|
|
37
37
|
const { anchor } = editor.selection;
|
|
38
|
+
const blockProps = editor.getBlockProps();
|
|
39
|
+
const detached = blockProps.detached;
|
|
38
40
|
|
|
39
41
|
const ref = Editor.rangeRef(editor, editor.selection, {
|
|
40
42
|
affinity: 'inward',
|
|
@@ -65,8 +67,7 @@ export const breakList = (editor) => {
|
|
|
65
67
|
return; // applies default behaviour, as defined in insertBreak.js extension
|
|
66
68
|
}
|
|
67
69
|
|
|
68
|
-
if (parent) {
|
|
69
|
-
const blockProps = editor.getBlockProps();
|
|
70
|
+
if (parent && !detached) {
|
|
70
71
|
const { data } = blockProps;
|
|
71
72
|
// Don't add new block if not allowed
|
|
72
73
|
if (data?.disableNewBlocks) {
|
|
@@ -77,22 +78,36 @@ export const breakList = (editor) => {
|
|
|
77
78
|
Editor.deleteBackward(editor, { unit: 'line' });
|
|
78
79
|
// also account for empty nodes [{text: ''}]
|
|
79
80
|
if (Editor.isEmpty(editor, parent)) {
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
if (detached) {
|
|
82
|
+
Transforms.removeNodes(editor, { at: ref.current });
|
|
83
|
+
|
|
84
|
+
Transforms.insertNodes(editor, createEmptyParagraph(), {
|
|
85
|
+
at: [editor.children.length],
|
|
86
|
+
});
|
|
87
|
+
Transforms.select(editor, Editor.end(editor, []));
|
|
88
|
+
} else {
|
|
89
|
+
createAndSelectNewBlockAfter(editor, [createEmptyParagraph()]);
|
|
90
|
+
Transforms.removeNodes(editor, { at: ref.current });
|
|
91
|
+
}
|
|
82
92
|
return true;
|
|
83
93
|
}
|
|
84
94
|
|
|
85
95
|
Transforms.removeNodes(editor, { at: ref.current });
|
|
86
96
|
|
|
87
97
|
if (isCursorAtBlockEnd(editor)) {
|
|
88
|
-
|
|
98
|
+
if (detached) {
|
|
99
|
+
Editor.insertNode(editor, createEmptyParagraph());
|
|
100
|
+
} else {
|
|
101
|
+
createAndSelectNewBlockAfter(editor, [createEmptyParagraph()]);
|
|
102
|
+
}
|
|
89
103
|
return true;
|
|
90
104
|
}
|
|
91
105
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
106
|
+
if (!detached) {
|
|
107
|
+
const [top, bottom] = splitEditorInTwoFragments(editor, ref.current);
|
|
108
|
+
setEditorContent(editor, top);
|
|
109
|
+
createAndSelectNewBlockAfter(editor, bottom);
|
|
110
|
+
}
|
|
96
111
|
return true;
|
|
97
112
|
};
|
|
98
113
|
|
|
@@ -46,10 +46,7 @@ export const onImageLoad = (editor, reader) => () => {
|
|
|
46
46
|
},
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
-
uploadContent(url, content, block)
|
|
50
|
-
const dlUrl = data.image.download;
|
|
51
|
-
insertImage(editor, dlUrl);
|
|
52
|
-
});
|
|
49
|
+
uploadContent(url, content, block);
|
|
53
50
|
};
|
|
54
51
|
|
|
55
52
|
export const withDeserializers = (editor) => {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import redraft from 'redraft';
|
|
3
2
|
import TextBlockView from './TextBlockView';
|
|
4
3
|
import TextBlockEdit from './TextBlockEdit';
|
|
5
4
|
import TextBlockSchema from './TextBlockSchema';
|
|
5
|
+
import { cloneDeep } from 'lodash';
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
8
|
goDown,
|
|
@@ -128,26 +128,8 @@ export default function applyConfig(config) {
|
|
|
128
128
|
return override_toc && level
|
|
129
129
|
? [parseInt(level.slice(1)), entry_text]
|
|
130
130
|
: config.settings.slate.topLevelTargetElements.includes(type)
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
},
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
// Make draft js compatible with ToC
|
|
137
|
-
config.blocks.blocksConfig.text = {
|
|
138
|
-
...config.blocks.blocksConfig.text,
|
|
139
|
-
restricted: true,
|
|
140
|
-
tocEntry: (block = {}) => {
|
|
141
|
-
const draft = redraft(
|
|
142
|
-
block.text,
|
|
143
|
-
config.settings.richtextViewSettings.ToHTMLRenderers,
|
|
144
|
-
config.settings.richtextViewSettings.ToHTMLOptions,
|
|
145
|
-
);
|
|
146
|
-
const type = draft?.[0]?.[0]?.type;
|
|
147
|
-
|
|
148
|
-
return config.settings.slate.topLevelTargetElements.includes(type)
|
|
149
|
-
? [parseInt(type.slice(1)), block.text.blocks[0].text]
|
|
150
|
-
: null;
|
|
131
|
+
? [parseInt(type.slice(1)), plaintext]
|
|
132
|
+
: null;
|
|
151
133
|
},
|
|
152
134
|
};
|
|
153
135
|
|
|
@@ -164,7 +146,9 @@ export default function applyConfig(config) {
|
|
|
164
146
|
// This is required in order to initialize the inner blocksConfig
|
|
165
147
|
// for the grid block, since the slate block lives in an add-on
|
|
166
148
|
// it should be responsible to fill itself into the grid configuration
|
|
167
|
-
|
|
149
|
+
// The cloneDeep is mandatory in order to not mess with pass by reference problems
|
|
150
|
+
config.blocks.blocksConfig.gridBlock.blocksConfig.slate =
|
|
151
|
+
cloneDeep(slateBlockConfig);
|
|
168
152
|
}
|
|
169
153
|
|
|
170
154
|
return config;
|
|
@@ -55,8 +55,8 @@ export function indentListItems({ editor, event }) {
|
|
|
55
55
|
? decreaseMultipleItemsDepth(editor, event)
|
|
56
56
|
: decreaseItemDepth(editor, event)
|
|
57
57
|
: event.ctrlKey
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
? increaseMultipleItemDepth(editor, event)
|
|
59
|
+
: increaseItemDepth(editor, event);
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
package/src/constants.js
CHANGED
|
@@ -22,6 +22,9 @@ export const P = 'p';
|
|
|
22
22
|
export const LI = 'li';
|
|
23
23
|
export const UL = 'ul';
|
|
24
24
|
export const OL = 'ol';
|
|
25
|
+
export const H2 = 'h2';
|
|
26
|
+
export const H3 = 'h3';
|
|
27
|
+
export const BLOCKQUOTE = 'blockquote';
|
|
25
28
|
|
|
26
29
|
// dom parsing node information
|
|
27
30
|
export const TEXT_NODE = 3;
|
|
@@ -25,6 +25,12 @@
|
|
|
25
25
|
&.upper {
|
|
26
26
|
transform: translateY(-100%);
|
|
27
27
|
}
|
|
28
|
+
|
|
29
|
+
.link-form-container {
|
|
30
|
+
margin-left: 2px;
|
|
31
|
+
display: flex;
|
|
32
|
+
align-items: center;
|
|
33
|
+
}
|
|
28
34
|
}
|
|
29
35
|
|
|
30
36
|
.toolbar-wrapper.active {
|
|
@@ -41,12 +47,13 @@
|
|
|
41
47
|
box-sizing: border-box;
|
|
42
48
|
padding: 3px;
|
|
43
49
|
border: none;
|
|
44
|
-
background: #fff;
|
|
45
50
|
border-radius: 2px;
|
|
51
|
+
background: #fff;
|
|
46
52
|
box-shadow: 0 0 8px rgba(0, 0, 0, 0.1);
|
|
47
53
|
font-family: 'Poppins', 'Helvetica Neue', Arial, Helvetica, sans-serif;
|
|
48
54
|
font-size: 1rem;
|
|
49
55
|
font-weight: normal;
|
|
56
|
+
min-width: 300px; // needed for image widget slate toolbar
|
|
50
57
|
|
|
51
58
|
.expando {
|
|
52
59
|
flex-grow: 1;
|
|
@@ -74,8 +81,8 @@
|
|
|
74
81
|
box-sizing: border-box;
|
|
75
82
|
padding: 4px !important;
|
|
76
83
|
border: 0;
|
|
77
|
-
background: rgba(255, 255, 255, 0.975);
|
|
78
84
|
border-radius: 1px;
|
|
85
|
+
background: rgba(255, 255, 255, 0.975);
|
|
79
86
|
color: @brown;
|
|
80
87
|
font-size: 18px;
|
|
81
88
|
vertical-align: bottom;
|
|
@@ -91,9 +98,9 @@
|
|
|
91
98
|
}
|
|
92
99
|
|
|
93
100
|
&.active {
|
|
101
|
+
border-radius: 3px;
|
|
94
102
|
// TODO: stop using !important, use smth better
|
|
95
103
|
background: #efefef !important;
|
|
96
|
-
border-radius: 3px;
|
|
97
104
|
box-shadow: inset 0 0 0 1px @blue !important;
|
|
98
105
|
color: @blue !important;
|
|
99
106
|
|
|
@@ -151,9 +158,11 @@
|
|
|
151
158
|
top: 29px;
|
|
152
159
|
left: -9px;
|
|
153
160
|
width: 210px;
|
|
154
|
-
background-color: rgba(255, 255, 255, 0.975);
|
|
155
161
|
border-radius: 2px;
|
|
156
|
-
|
|
162
|
+
background-color: rgba(255, 255, 255, 0.975);
|
|
163
|
+
box-shadow:
|
|
164
|
+
0 0 8px rgba(0, 0, 0, 0.1),
|
|
165
|
+
0 2px 4px rgba(0, 0, 0, 0.05);
|
|
157
166
|
|
|
158
167
|
.ui.menu {
|
|
159
168
|
border: 0;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { toggleList } from './utils';
|
|
2
2
|
import { isBlockActive } from '@plone/volto-slate/utils';
|
|
3
|
-
import { UL, OL, LI } from '@plone/volto-slate/constants';
|
|
3
|
+
import { UL, OL, LI, H2, H3, BLOCKQUOTE } from '@plone/volto-slate/constants';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Uses the old toggleList function to toggle lists on or off or from a type to another.
|
|
@@ -22,11 +22,11 @@ export const localToggleList = (editor, format) => {
|
|
|
22
22
|
*/
|
|
23
23
|
export const autoformatRules = [
|
|
24
24
|
{
|
|
25
|
-
type:
|
|
25
|
+
type: H2,
|
|
26
26
|
markup: '#',
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
|
-
type:
|
|
29
|
+
type: H3,
|
|
30
30
|
markup: '##',
|
|
31
31
|
},
|
|
32
32
|
{
|
|
@@ -44,36 +44,36 @@ export const autoformatRules = [
|
|
|
44
44
|
},
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
|
-
type:
|
|
47
|
+
type: BLOCKQUOTE,
|
|
48
48
|
markup: ['>'],
|
|
49
49
|
// preFormat,
|
|
50
50
|
},
|
|
51
51
|
{
|
|
52
|
-
type: '
|
|
52
|
+
type: 'strong',
|
|
53
53
|
between: ['**', '**'],
|
|
54
54
|
mode: 'inline',
|
|
55
55
|
insertTrigger: true,
|
|
56
56
|
},
|
|
57
57
|
{
|
|
58
|
-
type: '
|
|
58
|
+
type: 'strong',
|
|
59
59
|
between: ['__', '__'],
|
|
60
60
|
mode: 'inline',
|
|
61
61
|
insertTrigger: true,
|
|
62
62
|
},
|
|
63
63
|
{
|
|
64
|
-
type: '
|
|
64
|
+
type: 'em',
|
|
65
65
|
between: ['*', '*'],
|
|
66
66
|
mode: 'inline',
|
|
67
67
|
insertTrigger: true,
|
|
68
68
|
},
|
|
69
69
|
{
|
|
70
|
-
type: '
|
|
70
|
+
type: 'em',
|
|
71
71
|
between: ['_', '_'],
|
|
72
72
|
mode: 'inline',
|
|
73
73
|
insertTrigger: true,
|
|
74
74
|
},
|
|
75
75
|
{
|
|
76
|
-
type: '
|
|
76
|
+
type: 'del',
|
|
77
77
|
between: ['~~', '~~'],
|
|
78
78
|
mode: 'inline',
|
|
79
79
|
insertTrigger: true,
|
|
@@ -170,9 +170,8 @@ export const autoformatInline = (
|
|
|
170
170
|
|
|
171
171
|
// add mark to the text between the markups
|
|
172
172
|
Transforms.select(editor, markupRange);
|
|
173
|
-
|
|
173
|
+
Transforms.wrapNodes(editor, { type, children: [] }, { split: true });
|
|
174
174
|
Transforms.collapse(editor, { edge: 'end' });
|
|
175
|
-
editor.removeMark(type);
|
|
176
175
|
|
|
177
176
|
// delete start markup
|
|
178
177
|
const startMarkupPointBefore = getPointBefore(editor, selection, {
|
|
@@ -200,6 +199,7 @@ export const autoformatBlock = (editor, type, at, { preFormat, format }) => {
|
|
|
200
199
|
Transforms.setNodes(
|
|
201
200
|
editor,
|
|
202
201
|
{ type },
|
|
202
|
+
{ at },
|
|
203
203
|
{ match: (n) => Editor.isBlock(editor, n) },
|
|
204
204
|
);
|
|
205
205
|
} else {
|
|
@@ -7,12 +7,19 @@ const PositionedToolbar = ({ toggleButton, className, children, position }) => {
|
|
|
7
7
|
// TODO: "position" is actually an object like `{ style: {} }`
|
|
8
8
|
// To be renamed as "attributes" or "attrs"
|
|
9
9
|
const ref = React.useRef();
|
|
10
|
+
const portalTarget = toggleButton || document.body;
|
|
10
11
|
|
|
11
12
|
React.useEffect(() => {
|
|
12
13
|
const el = ref.current;
|
|
13
14
|
|
|
14
15
|
const { style } = position || {};
|
|
15
|
-
|
|
16
|
+
// allow negative left positioning when portal isn't document.body
|
|
17
|
+
// we need to use Math.max to avoid Slate AddLink popup going off screen
|
|
18
|
+
// and it adds the toolbar to the body
|
|
19
|
+
const left =
|
|
20
|
+
portalTarget === document.body
|
|
21
|
+
? `${Math.max(style.left - el.offsetWidth / 2, 0)}px`
|
|
22
|
+
: `${style.left - el.offsetWidth / 2}px`;
|
|
16
23
|
const top = `${style.top - el.offsetHeight}px`;
|
|
17
24
|
|
|
18
25
|
el.style.opacity = style.opacity;
|
|
@@ -24,7 +31,7 @@ const PositionedToolbar = ({ toggleButton, className, children, position }) => {
|
|
|
24
31
|
<BasicToolbar className={`slate-inline-toolbar ${className}`} ref={ref}>
|
|
25
32
|
{children}
|
|
26
33
|
</BasicToolbar>,
|
|
27
|
-
|
|
34
|
+
portalTarget,
|
|
28
35
|
);
|
|
29
36
|
};
|
|
30
37
|
|
|
@@ -3,7 +3,8 @@ import { isEqual } from 'lodash';
|
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { useDispatch } from 'react-redux';
|
|
5
5
|
import { ReactEditor } from 'slate-react';
|
|
6
|
-
import { Icon as VoltoIcon
|
|
6
|
+
import { Icon as VoltoIcon } from '@plone/volto/components';
|
|
7
|
+
import { BlockDataForm } from '@plone/volto/components/manage/Form';
|
|
7
8
|
import { setPluginOptions } from '@plone/volto-slate/actions';
|
|
8
9
|
import BaseSchemaProvider from './SchemaProvider';
|
|
9
10
|
|
|
@@ -45,13 +45,16 @@ export const _insertElement = (elementType) => (editor, data) => {
|
|
|
45
45
|
match: (node) => {
|
|
46
46
|
return Node.string(node).length !== 0;
|
|
47
47
|
},
|
|
48
|
-
},
|
|
48
|
+
},
|
|
49
49
|
);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
const sel = JSON.parse(JSON.stringify(rangeRef.current));
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
|
|
54
|
+
setTimeout(() => {
|
|
55
|
+
Transforms.select(editor, sel);
|
|
56
|
+
editor.setSavedSelection(sel);
|
|
57
|
+
});
|
|
55
58
|
|
|
56
59
|
return true;
|
|
57
60
|
}
|
|
@@ -69,10 +72,26 @@ export const _insertElement = (elementType) => (editor, data) => {
|
|
|
69
72
|
* @returns {Object|null} - current node
|
|
70
73
|
*/
|
|
71
74
|
export const _unwrapElement = (elementType) => (editor) => {
|
|
72
|
-
const
|
|
73
|
-
|
|
75
|
+
const selection = editor.selection || editor.getSavedSelection();
|
|
76
|
+
let [link] = Editor.nodes(editor, {
|
|
77
|
+
at: selection,
|
|
74
78
|
match: (node) => node?.type === elementType,
|
|
75
79
|
});
|
|
80
|
+
const isAtStart =
|
|
81
|
+
selection.anchor.offset === 0 && selection.focus.offset === 0;
|
|
82
|
+
|
|
83
|
+
if (!link && !isAtStart) return false;
|
|
84
|
+
|
|
85
|
+
if (!link) {
|
|
86
|
+
try {
|
|
87
|
+
link = Editor.previous(editor, {
|
|
88
|
+
at: selection.anchor.path,
|
|
89
|
+
});
|
|
90
|
+
} catch (ex) {
|
|
91
|
+
link = [];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
76
95
|
const [, path] = link;
|
|
77
96
|
const [start, end] = Editor.edges(editor, path);
|
|
78
97
|
const range = { anchor: start, focus: end };
|
package/src/utils/blocks.js
CHANGED
|
@@ -264,7 +264,7 @@ export const toggleBlock = (editor, format, allowedChildren) => {
|
|
|
264
264
|
} else if (!isListItem && !wantsList) {
|
|
265
265
|
toggleFormat(editor, format, allowedChildren);
|
|
266
266
|
} else if (isListItem && wantsList && isActive) {
|
|
267
|
-
|
|
267
|
+
clearList(editor);
|
|
268
268
|
} else {
|
|
269
269
|
console.warn('toggleBlock case not covered, please examine:', {
|
|
270
270
|
wantsList,
|
|
@@ -298,6 +298,21 @@ export const switchListType = (editor, format) => {
|
|
|
298
298
|
Transforms.wrapNodes(editor, block);
|
|
299
299
|
};
|
|
300
300
|
|
|
301
|
+
/*
|
|
302
|
+
* Clear list by exploding the block
|
|
303
|
+
*/
|
|
304
|
+
export const clearList = (editor) => {
|
|
305
|
+
const { slate } = config.settings;
|
|
306
|
+
Transforms.unwrapNodes(editor, {
|
|
307
|
+
match: (n) => slate.listTypes.includes(n.type),
|
|
308
|
+
split: true,
|
|
309
|
+
});
|
|
310
|
+
Transforms.setNodes(editor, {
|
|
311
|
+
type: 'p',
|
|
312
|
+
});
|
|
313
|
+
Editor.normalize(editor);
|
|
314
|
+
};
|
|
315
|
+
|
|
301
316
|
export const changeBlockToList = (editor, format) => {
|
|
302
317
|
const { slate } = config.settings;
|
|
303
318
|
const [match] = Editor.nodes(editor, {
|
|
@@ -3,6 +3,8 @@ import { v4 as uuid } from 'uuid';
|
|
|
3
3
|
import {
|
|
4
4
|
addBlock,
|
|
5
5
|
changeBlock,
|
|
6
|
+
insertBlock,
|
|
7
|
+
blockHasValue,
|
|
6
8
|
getBlocksFieldname,
|
|
7
9
|
getBlocksLayoutFieldname,
|
|
8
10
|
} from '@plone/volto/helpers';
|
|
@@ -121,8 +123,19 @@ export function createImageBlock(url, index, props) {
|
|
|
121
123
|
const blocksFieldname = getBlocksFieldname(properties);
|
|
122
124
|
const blocksLayoutFieldname = getBlocksLayoutFieldname(properties);
|
|
123
125
|
|
|
124
|
-
const
|
|
125
|
-
const
|
|
126
|
+
const currBlockId = properties.blocks_layout.items[index];
|
|
127
|
+
const currBlockHasValue = blockHasValue(properties.blocks[currBlockId]);
|
|
128
|
+
let id, newFormData;
|
|
129
|
+
|
|
130
|
+
if (currBlockHasValue) {
|
|
131
|
+
[id, newFormData] = addBlock(properties, 'image', index + 1);
|
|
132
|
+
newFormData = changeBlock(newFormData, id, { '@type': 'image', url });
|
|
133
|
+
} else {
|
|
134
|
+
[id, newFormData] = insertBlock(properties, currBlockId, {
|
|
135
|
+
'@type': 'image',
|
|
136
|
+
url,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
126
139
|
|
|
127
140
|
ReactDOM.unstable_batchedUpdates(() => {
|
|
128
141
|
onChangeField(blocksFieldname, newFormData[blocksFieldname]);
|
|
@@ -9,7 +9,7 @@ import { MemoryRouter } from 'react-router-dom';
|
|
|
9
9
|
import { Provider, useSelector } from 'react-redux';
|
|
10
10
|
import { defineMessages, injectIntl } from 'react-intl';
|
|
11
11
|
|
|
12
|
-
import { FormFieldWrapper } from '@plone/volto/components';
|
|
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
15
|
import { makeEditor } from '@plone/volto-slate/utils';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Menu, Tab } from 'semantic-ui-react';
|
|
3
|
-
import { Icon
|
|
3
|
+
import { Icon } from '@plone/volto/components';
|
|
4
|
+
import { ObjectWidget } from '@plone/volto/components/manage/Widgets';
|
|
4
5
|
|
|
5
6
|
export const ObjectByTypeWidget = (props) => {
|
|
6
7
|
const { schemas, value = {}, onChange, errors = {}, id } = props;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import React from 'react';
|
|
7
7
|
import isUndefined from 'lodash/isUndefined';
|
|
8
8
|
import isString from 'lodash/isString';
|
|
9
|
-
import { FormFieldWrapper } from '@plone/volto/components';
|
|
9
|
+
import { FormFieldWrapper } from '@plone/volto/components/manage/Widgets';
|
|
10
10
|
import SlateEditor from '@plone/volto-slate/editor/SlateEditor';
|
|
11
11
|
|
|
12
12
|
import { createEmptyParagraph, createParagraph } from '../utils/blocks';
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|