@plone/volto 18.0.0-alpha.17 → 18.0.0-alpha.19

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.
Files changed (95) hide show
  1. package/CHANGELOG.md +48 -2
  2. package/locales/ca/LC_MESSAGES/volto.po +17 -42
  3. package/locales/ca.json +1 -1
  4. package/locales/de/LC_MESSAGES/volto.po +15 -40
  5. package/locales/de.json +1 -1
  6. package/locales/en/LC_MESSAGES/volto.po +14 -39
  7. package/locales/en.json +1 -1
  8. package/locales/es/LC_MESSAGES/volto.po +15 -40
  9. package/locales/es.json +1 -1
  10. package/locales/eu/LC_MESSAGES/volto.po +15 -40
  11. package/locales/eu.json +1 -1
  12. package/locales/fi/LC_MESSAGES/volto.po +15 -40
  13. package/locales/fi.json +1 -1
  14. package/locales/fr/LC_MESSAGES/volto.po +15 -40
  15. package/locales/fr.json +1 -1
  16. package/locales/it/LC_MESSAGES/volto.po +15 -40
  17. package/locales/it.json +1 -1
  18. package/locales/ja/LC_MESSAGES/volto.po +15 -40
  19. package/locales/ja.json +1 -1
  20. package/locales/nl/LC_MESSAGES/volto.po +14 -39
  21. package/locales/nl.json +1 -1
  22. package/locales/pt/LC_MESSAGES/volto.po +15 -40
  23. package/locales/pt.json +1 -1
  24. package/locales/pt_BR/LC_MESSAGES/volto.po +15 -40
  25. package/locales/pt_BR.json +1 -1
  26. package/locales/ro/LC_MESSAGES/volto.po +15 -40
  27. package/locales/ro.json +1 -1
  28. package/locales/volto.pot +15 -40
  29. package/locales/zh_CN/LC_MESSAGES/volto.po +15 -40
  30. package/locales/zh_CN.json +1 -1
  31. package/package.json +11 -21
  32. package/src/components/index.js +0 -6
  33. package/src/components/manage/Add/Add.jsx +1 -1
  34. package/src/components/manage/Blocks/Search/SearchBlockEdit.jsx +8 -2
  35. package/src/components/manage/Blocks/Search/hocs/withSearch.jsx +2 -2
  36. package/src/components/manage/Controlpanels/Groups/GroupsControlpanel.jsx +33 -5
  37. package/src/components/manage/Controlpanels/Groups/GroupsControlpanel.test.jsx +12 -0
  38. package/src/components/manage/Controlpanels/Groups/RenderGroups.jsx +22 -11
  39. package/src/components/manage/Controlpanels/Groups/RenderGroups.test.jsx +21 -0
  40. package/src/components/manage/Controlpanels/Users/RenderUsers.jsx +30 -21
  41. package/src/components/manage/Controlpanels/Users/RenderUsers.test.jsx +27 -1
  42. package/src/components/manage/Controlpanels/Users/UserGroupMembershipListing.jsx +29 -7
  43. package/src/components/manage/Controlpanels/Users/UsersControlpanel.jsx +51 -3
  44. package/src/components/manage/Controlpanels/Users/UsersControlpanel.test.jsx +8 -0
  45. package/src/components/manage/Form/Form.jsx +1 -1
  46. package/src/components/theme/SlotRenderer/SlotRenderer.tsx +8 -1
  47. package/src/config/Blocks.jsx +63 -67
  48. package/src/config/Loadables.jsx +0 -22
  49. package/src/config/Widgets.jsx +0 -2
  50. package/src/config/index.js +0 -13
  51. package/src/helpers/User/User.js +29 -0
  52. package/src/helpers/index.js +6 -1
  53. package/test-setup-config.js +0 -30
  54. package/types/components/index.d.ts +0 -6
  55. package/types/config/Blocks.d.ts +0 -51
  56. package/types/config/Loadables.d.ts +0 -10
  57. package/types/config/Widgets.d.ts +0 -2
  58. package/types/helpers/User/User.d.ts +18 -0
  59. package/types/helpers/index.d.ts +1 -1
  60. package/webpack-plugins/webpack-bundle-analyze-plugin.js +1 -1
  61. package/src/components/manage/AnchorPlugin/components/Link/index.jsx +0 -37
  62. package/src/components/manage/AnchorPlugin/components/LinkButton/index.jsx +0 -126
  63. package/src/components/manage/AnchorPlugin/index.jsx +0 -82
  64. package/src/components/manage/AnchorPlugin/linkStrategy.js +0 -21
  65. package/src/components/manage/AnchorPlugin/utils/EditorUtils.js +0 -47
  66. package/src/components/manage/Blocks/HeroImageLeft/Data.jsx +0 -29
  67. package/src/components/manage/Blocks/HeroImageLeft/Edit.jsx +0 -493
  68. package/src/components/manage/Blocks/HeroImageLeft/Edit.test.jsx +0 -58
  69. package/src/components/manage/Blocks/HeroImageLeft/View.jsx +0 -37
  70. package/src/components/manage/Blocks/HeroImageLeft/View.test.jsx +0 -9
  71. package/src/components/manage/Blocks/HeroImageLeft/schema.js +0 -43
  72. package/src/components/manage/Blocks/Table/Cell.jsx +0 -206
  73. package/src/components/manage/Blocks/Table/Cell.test.jsx +0 -19
  74. package/src/components/manage/Blocks/Table/Edit.jsx +0 -748
  75. package/src/components/manage/Blocks/Table/Edit.test.jsx +0 -44
  76. package/src/components/manage/Blocks/Table/Readme.md +0 -5
  77. package/src/components/manage/Blocks/Table/View.jsx +0 -51
  78. package/src/components/manage/Blocks/Table/View.test.jsx +0 -41
  79. package/src/components/manage/Blocks/Text/Edit.jsx +0 -372
  80. package/src/components/manage/Blocks/Text/Edit.test.jsx +0 -46
  81. package/src/components/manage/Blocks/Text/Readme.md +0 -5
  82. package/src/components/manage/Blocks/Text/Schema.jsx +0 -31
  83. package/src/components/manage/Blocks/Text/View.jsx +0 -26
  84. package/src/components/manage/Blocks/Text/View.test.jsx +0 -28
  85. package/src/components/manage/LinkDetectionPlugin/link-detection-plugin.jsx +0 -227
  86. package/src/components/manage/LinkDetectionPlugin/utils.js +0 -12
  87. package/src/components/manage/Widgets/WysiwygWidget.jsx +0 -350
  88. package/src/components/manage/Widgets/WysiwygWidget.stories.jsx +0 -24
  89. package/src/components/manage/Widgets/WysiwygWidget.test.jsx +0 -37
  90. package/src/config/RichTextEditor/Blocks.jsx +0 -29
  91. package/src/config/RichTextEditor/FromHTML.jsx +0 -8
  92. package/src/config/RichTextEditor/Plugins.jsx +0 -59
  93. package/src/config/RichTextEditor/Styles.jsx +0 -69
  94. package/src/config/RichTextEditor/ToHTML.jsx +0 -262
  95. package/src/config/RichTextEditor/index.js +0 -25
@@ -1,227 +0,0 @@
1
- import * as React from 'react';
2
- import { RichUtils, Modifier, EditorState, SelectionState } from 'draft-js';
3
- import {
4
- isURL,
5
- getUrlFromString,
6
- } from '@plone/volto/components/manage/LinkDetectionPlugin/utils';
7
-
8
- /*
9
- Returns editor state with a link entity created / updated to hold the link @data
10
- for the range specified by @selection
11
- */
12
-
13
- export function editorStateSettingLink(editorState, selection, data) {
14
- const contentState = editorState.getCurrentContent();
15
- const entityKey = getCurrentLinkEntityKey(editorState);
16
-
17
- let nextEditorState = editorState;
18
-
19
- if (!entityKey) {
20
- const contentStateWithEntity = contentState.createEntity(
21
- 'LINK',
22
- 'MUTABLE',
23
- data,
24
- );
25
- const entityKey = contentStateWithEntity.getLastCreatedEntityKey();
26
- nextEditorState = EditorState.set(editorState, {
27
- currentContent: contentStateWithEntity,
28
- });
29
- nextEditorState = RichUtils.toggleLink(
30
- nextEditorState,
31
- selection,
32
- entityKey,
33
- );
34
- } else {
35
- nextEditorState = EditorState.set(editorState, {
36
- currentContent: editorState
37
- .getCurrentContent()
38
- .replaceEntityData(entityKey, data),
39
- });
40
- nextEditorState = EditorState.forceSelection(
41
- nextEditorState,
42
- editorState.getSelection(),
43
- );
44
- }
45
-
46
- return nextEditorState;
47
- }
48
-
49
- /*
50
- Returns the entityKey for the link entity the user is currently within.
51
- */
52
- export function getCurrentLinkEntityKey(editorState) {
53
- const contentState = editorState.getCurrentContent();
54
- const startKey = editorState.getSelection().getStartKey();
55
- const startOffset = editorState.getSelection().getStartOffset();
56
- const block = contentState.getBlockForKey(startKey);
57
-
58
- const linkKey = block.getEntityAt(
59
- Math.min(block.getText().length - 1, startOffset),
60
- );
61
-
62
- if (linkKey) {
63
- const linkInstance = contentState.getEntity(linkKey);
64
- if (linkInstance.getType() === 'LINK') {
65
- return linkKey;
66
- }
67
- }
68
- return null;
69
- }
70
-
71
- /*
72
- Returns the URL for the link entity the user is currently within.
73
- */
74
- export function getCurrentLink(editorState) {
75
- const entityKey = getCurrentLinkEntityKey(editorState);
76
- return (
77
- entityKey &&
78
- editorState.getCurrentContent().getEntity(entityKey).getData().url
79
- );
80
- }
81
-
82
- /* LINK COMPONENT */
83
- const Link = (props) => {
84
- const data = props.contentState.getEntity(props.entityKey).getData();
85
- const { url } = data;
86
- if (!url) {
87
- return <span>{props.children}</span>;
88
- }
89
- return (
90
- <a href={url} title={url}>
91
- {props.children}
92
- </a>
93
- );
94
- };
95
-
96
- const findLinkEntities = (contentBlock, callback, contentState) => {
97
- contentBlock.findEntityRanges((character) => {
98
- const entityKey = character.getEntity();
99
- if (!entityKey) return;
100
- const entity = contentState.getEntity(entityKey);
101
- return entity.getType() === 'LINK' && entity.getData().url;
102
- }, callback);
103
- };
104
-
105
- const createLinkDetectionPlugin = () => {
106
- return {
107
- decorators: [
108
- {
109
- strategy: findLinkEntities,
110
- component: Link,
111
- },
112
- ],
113
- /* The method is always called when we change the data in the editor. */
114
- onChange: (editorState) => {
115
- // Returns the current contents of the editor.
116
- const contentState = editorState.getCurrentContent();
117
-
118
- // Returns the current cursor/selection state of the editor.
119
- const selection = editorState.getSelection();
120
-
121
- if (!selection || !selection.isCollapsed()) {
122
- return editorState;
123
- }
124
-
125
- const cursorOffset = selection.getStartOffset();
126
- const cursorBlockKey = selection.getStartKey();
127
- const cursorBlock = contentState.getBlockForKey(cursorBlockKey);
128
-
129
- if (cursorBlock.getType() !== 'unstyled') {
130
- return editorState;
131
- }
132
-
133
- // Step 1: Get the word around the cursor by splitting the current block's text
134
- const text = cursorBlock.getText();
135
- const currentWordStart = text.lastIndexOf(' ', cursorOffset) + 1;
136
- let currentWordEnd = text.indexOf(' ', cursorOffset);
137
- if (currentWordEnd === -1) {
138
- currentWordEnd = text.length;
139
- }
140
-
141
- const currentWord = text.substr(
142
- currentWordStart,
143
- currentWordEnd - currentWordStart,
144
- );
145
-
146
- const currentWordIsURL = isURL(currentWord);
147
-
148
- // Step 2: Find the existing LINK entity under the user's cursor
149
- let currentLinkEntityKey = cursorBlock.getEntityAt(
150
- Math.min(text.length - 1, cursorOffset),
151
- );
152
- const inst =
153
- currentLinkEntityKey && contentState.getEntity(currentLinkEntityKey);
154
- if (inst && inst.getType() !== 'LINK') {
155
- currentLinkEntityKey = '';
156
- }
157
-
158
- if (currentLinkEntityKey) {
159
- // Note: we don't touch link values added / removed "explicitly" via the link
160
- // toolbar button. This means you can make a link with text that doesn't match the link. Link touched by this plugin, have "autodetected" prop setted to true
161
- const entityExistingData = contentState
162
- .getEntity(currentLinkEntityKey)
163
- .getData();
164
- if (!entityExistingData.autodetected) {
165
- return editorState;
166
- }
167
-
168
- if (currentWordIsURL) {
169
- // We are modifying the URL - update the entity to reflect the current text
170
- const contentState = editorState.getCurrentContent();
171
- return EditorState.set(editorState, {
172
- currentContent: contentState.replaceEntityData(
173
- currentLinkEntityKey,
174
- {
175
- autodetected: true,
176
- url: getUrlFromString(currentWord),
177
- },
178
- ),
179
- });
180
- } else {
181
- // We are no longer in a URL but the entity is still present. Remove it from
182
- // the current character so the linkifying "ends".
183
- const entityRange = new SelectionState({
184
- anchorOffset: currentWordStart - 1,
185
- anchorKey: cursorBlockKey,
186
- focusOffset: currentWordStart,
187
- focusKey: cursorBlockKey,
188
- isBackward: false,
189
- hasFocus: true,
190
- });
191
- return EditorState.set(editorState, {
192
- currentContent: Modifier.applyEntity(
193
- editorState.getCurrentContent(),
194
- entityRange,
195
- null,
196
- ),
197
- });
198
- }
199
- }
200
-
201
- // There is no entity beneath the current word, but it looks like a URL. Linkify it!
202
- if (!currentLinkEntityKey && currentWordIsURL) {
203
- const entityRange = new SelectionState({
204
- anchorOffset: currentWordStart,
205
- anchorKey: cursorBlockKey,
206
- focusOffset: currentWordEnd,
207
- focusKey: cursorBlockKey,
208
- isBackward: false,
209
- hasFocus: false,
210
- });
211
-
212
- let newEditorState = editorStateSettingLink(editorState, entityRange, {
213
- autodetected: true,
214
- url: getUrlFromString(currentWord),
215
- });
216
-
217
- // reset selection to the initial cursor to avoid selecting the entire links
218
- newEditorState = EditorState.acceptSelection(newEditorState, selection);
219
- return newEditorState;
220
- }
221
-
222
- return editorState;
223
- },
224
- };
225
- };
226
-
227
- export default createLinkDetectionPlugin;
@@ -1,12 +0,0 @@
1
- import linkifyIt from 'linkify-it';
2
-
3
- const linkify = linkifyIt();
4
-
5
- export const getUrlFromString = (text) => {
6
- const matchLinkList = linkify.match(text);
7
- return matchLinkList && matchLinkList[0].url;
8
- };
9
-
10
- export const isURL = (text) => {
11
- return !!linkify.match(text);
12
- };
@@ -1,350 +0,0 @@
1
- /**
2
- * WysiwygWidget container.
3
- * @module components/manage/WysiwygWidget/WysiwygWidget
4
- */
5
-
6
- import React, { Component } from 'react';
7
- import ReactDOMServer from 'react-dom/server';
8
- import PropTypes from 'prop-types';
9
- import { connect, Provider } from 'react-redux';
10
- import { compose } from 'redux';
11
- import redraft from 'redraft';
12
- import { Form, Label, TextArea } from 'semantic-ui-react';
13
- import { map } from 'lodash';
14
- import { defineMessages, injectIntl } from 'react-intl';
15
- import configureStore from 'redux-mock-store';
16
- import { MemoryRouter } from 'react-router-dom';
17
- import config from '@plone/volto/registry';
18
-
19
- import { FormFieldWrapper } from '@plone/volto/components';
20
-
21
- import loadable from '@loadable/component';
22
- import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
23
-
24
- const Editor = loadable(() => import('draft-js-plugins-editor'));
25
-
26
- const messages = defineMessages({
27
- default: {
28
- id: 'Default',
29
- defaultMessage: 'Default',
30
- },
31
- idTitle: {
32
- id: 'Short Name',
33
- defaultMessage: 'Short Name',
34
- },
35
- idDescription: {
36
- id: 'Used for programmatic access to the fieldset.',
37
- defaultMessage: 'Used for programmatic access to the fieldset.',
38
- },
39
- title: {
40
- id: 'Title',
41
- defaultMessage: 'Title',
42
- },
43
- description: {
44
- id: 'Description',
45
- defaultMessage: 'Description',
46
- },
47
- required: {
48
- id: 'Required',
49
- defaultMessage: 'Required',
50
- },
51
- delete: {
52
- id: 'Delete',
53
- defaultMessage: 'Delete',
54
- },
55
- });
56
-
57
- /**
58
- * WysiwygWidget HTML richtext editing widget
59
- *
60
- * To use it, in schema properties, declare a field like:
61
- *
62
- * ```jsx
63
- * {
64
- * title: "Rich text",
65
- * widget: 'richtext',
66
- * }
67
- * ```
68
- *
69
- */
70
- class WysiwygWidgetComponent extends Component {
71
- /**
72
- * Property types.
73
- * @property {Object} propTypes Property types.
74
- * @static
75
- */
76
- static propTypes = {
77
- /**
78
- * Id of the field
79
- */
80
- id: PropTypes.string.isRequired,
81
- /**
82
- * Title of the field
83
- */
84
- title: PropTypes.string.isRequired,
85
- /**
86
- * Description of the field
87
- */
88
- description: PropTypes.string,
89
- /**
90
- * True if field is required
91
- */
92
- required: PropTypes.bool,
93
- /**
94
- * Value of the field
95
- */
96
- value: PropTypes.shape({
97
- /**
98
- * Content type of the value
99
- */
100
- 'content-type': PropTypes.string,
101
- /**
102
- * Data of the value
103
- */
104
- data: PropTypes.string,
105
- /**
106
- * Encoding of the value
107
- */
108
- encoding: PropTypes.string,
109
- }),
110
- /**
111
- * Placeholder for the editor
112
- */
113
- placeholder: PropTypes.string,
114
- /**
115
- * List of error messages
116
- */
117
- error: PropTypes.arrayOf(PropTypes.string),
118
- /**
119
- * On change handler
120
- */
121
- onChange: PropTypes.func,
122
- /**
123
- * On delete handler
124
- */
125
- onDelete: PropTypes.func,
126
- /**
127
- * On edit handler
128
- */
129
- onEdit: PropTypes.func,
130
- /**
131
- * Wrapped form component
132
- */
133
- wrapped: PropTypes.bool,
134
- };
135
-
136
- /**
137
- * Default properties
138
- * @property {Object} defaultProps Default properties.
139
- * @static
140
- */
141
- static defaultProps = {
142
- description: null,
143
- required: false,
144
- value: {
145
- 'content-type': 'text/html',
146
- data: '',
147
- encoding: 'utf8',
148
- },
149
- error: [],
150
- onEdit: null,
151
- onDelete: null,
152
- onChange: null,
153
- };
154
-
155
- /**
156
- * Constructor
157
- * @method constructor
158
- * @param {Object} props Component properties
159
- * @constructs WysiwygWidget
160
- */
161
- constructor(props) {
162
- super(props);
163
-
164
- const { stateFromHTML } = props.draftJsImportHtml;
165
- const { EditorState } = props.draftJs;
166
- const createInlineToolbarPlugin = props.draftJsInlineToolbarPlugin.default;
167
-
168
- this.draftConfig = config.settings.richtextEditorSettings(props);
169
-
170
- if (!__SERVER__) {
171
- let editorState;
172
- if (props.value && props.value.data) {
173
- const contentState = stateFromHTML(props.value.data, {
174
- customBlockFn: this.draftConfig.FromHTMLCustomBlockFn,
175
- });
176
- editorState = EditorState.createWithContent(contentState);
177
- } else {
178
- editorState = EditorState.createEmpty();
179
- }
180
-
181
- const inlineToolbarPlugin = createInlineToolbarPlugin({
182
- structure: this.draftConfig.richTextEditorInlineToolbarButtons,
183
- });
184
-
185
- this.state = { editorState, inlineToolbarPlugin };
186
- }
187
-
188
- this.schema = {
189
- fieldsets: [
190
- {
191
- id: 'default',
192
- title: props.intl.formatMessage(messages.default),
193
- fields: ['title', 'id', 'description', 'required'],
194
- },
195
- ],
196
- properties: {
197
- id: {
198
- type: 'string',
199
- title: props.intl.formatMessage(messages.idTitle),
200
- description: props.intl.formatMessage(messages.idDescription),
201
- },
202
- title: {
203
- type: 'string',
204
- title: props.intl.formatMessage(messages.title),
205
- },
206
- description: {
207
- type: 'string',
208
- widget: 'textarea',
209
- title: props.intl.formatMessage(messages.description),
210
- },
211
- required: {
212
- type: 'boolean',
213
- title: props.intl.formatMessage(messages.required),
214
- },
215
- },
216
- required: ['id', 'title'],
217
- };
218
-
219
- this.onChange = this.onChange.bind(this);
220
- }
221
-
222
- /**
223
- * Change handler
224
- * @method onChange
225
- * @param {object} editorState Editor state.
226
- * @returns {undefined}
227
- */
228
- onChange(editorState) {
229
- const { convertToRaw } = this.props.draftJs;
230
- this.setState({ editorState });
231
- const mockStore = configureStore();
232
-
233
- this.props.onChange(this.props.id, {
234
- 'content-type': this.props.value
235
- ? this.props.value['content-type']
236
- : 'text/html',
237
- encoding: this.props.value ? this.props.value.encoding : 'utf8',
238
- data: ReactDOMServer.renderToStaticMarkup(
239
- <Provider
240
- store={mockStore({
241
- userSession: {
242
- token: this.props.token,
243
- },
244
- })}
245
- >
246
- <MemoryRouter>
247
- {redraft(
248
- convertToRaw(editorState.getCurrentContent()),
249
- config.settings.richtextViewSettings.ToHTMLRenderers,
250
- config.settings.richtextViewSettings.ToHTMLOptions,
251
- )}
252
- </MemoryRouter>
253
- </Provider>,
254
- ),
255
- });
256
- }
257
-
258
- /**
259
- * Render method.
260
- * @method render
261
- * @returns {string} Markup for the component.
262
- */
263
- render() {
264
- const { id, title, description, required, value, error, fieldSet } =
265
- this.props;
266
-
267
- if (__SERVER__) {
268
- return (
269
- <Form.Field
270
- inline
271
- required={required}
272
- error={error.length > 0}
273
- className={description ? 'help' : ''}
274
- id={`${fieldSet || 'field'}-${id}`}
275
- >
276
- <div className="wrapper">
277
- <label htmlFor={`field-${id}`}>{title}</label>
278
- <TextArea id={id} name={id} value={value ? value.data : ''} />
279
- {description && <p className="help">{description}</p>}
280
- {map(error, (message) => (
281
- <Label key={message} basic color="red" pointing>
282
- {message}
283
- </Label>
284
- ))}
285
- </div>
286
- </Form.Field>
287
- );
288
- }
289
- const { InlineToolbar } = this.state.inlineToolbarPlugin;
290
-
291
- return (
292
- <FormFieldWrapper {...this.props} className="wysiwyg">
293
- <div style={{ boxSizing: 'initial' }}>
294
- {this.props.onChange ? (
295
- <>
296
- <Editor
297
- id={`field-${id}`}
298
- readOnly={this.props.isDisabled}
299
- onChange={this.onChange}
300
- editorState={this.state.editorState}
301
- plugins={[
302
- this.state.inlineToolbarPlugin,
303
- ...this.draftConfig.richTextEditorPlugins,
304
- ]}
305
- placeholder={this.props.placeholder}
306
- blockRenderMap={this.draftConfig.extendedBlockRenderMap}
307
- blockStyleFn={this.draftConfig.blockStyleFn}
308
- customStyleMap={this.draftConfig.customStyleMap}
309
- />
310
- {this.props.onChange && <InlineToolbar />}
311
- </>
312
- ) : (
313
- <div className="DraftEditor-root" />
314
- )}
315
- </div>
316
- </FormFieldWrapper>
317
- );
318
- }
319
- }
320
-
321
- export const WysiwygWidget = compose(
322
- injectIntl,
323
- injectLazyLibs([
324
- 'draftJs',
325
- 'draftJsBlockBreakoutPlugin',
326
- 'draftJsCreateBlockStyleButton',
327
- 'draftJsCreateInlineStyleButton',
328
- 'draftJsFilters',
329
- 'draftJsImportHtml',
330
- 'draftJsInlineToolbarPlugin',
331
- 'draftJsLibIsSoftNewlineEvent',
332
- 'immutableLib',
333
- ]),
334
- connect(
335
- (state, props) => ({
336
- token: state.userSession.token,
337
- }),
338
- {},
339
- ),
340
- )(WysiwygWidgetComponent);
341
-
342
- const Preloader = (props) => {
343
- const [loaded, setLoaded] = React.useState(false);
344
- React.useEffect(() => {
345
- Editor.load().then(() => setLoaded(true));
346
- }, []);
347
- return loaded ? <WysiwygWidget {...props} /> : null;
348
- };
349
-
350
- export default Preloader;
@@ -1,24 +0,0 @@
1
- import React from 'react';
2
- import WysiwygWidget from './WysiwygWidget';
3
- import WidgetStory from './story';
4
-
5
- export const Wysiwyg = WidgetStory.bind({
6
- props: { id: 'text', title: 'Rich text' },
7
- widget: WysiwygWidget,
8
- });
9
-
10
- export default {
11
- title: 'Edit Widgets/Wysiwyg',
12
- component: WysiwygWidget,
13
- decorators: [
14
- (Story) => (
15
- <div
16
- className="ui segment form attached"
17
- style={{ width: '400px', marginTop: '40px' }}
18
- >
19
- <Story />
20
- </div>
21
- ),
22
- ],
23
- argTypes: {},
24
- };
@@ -1,37 +0,0 @@
1
- import React from 'react';
2
- import renderer from 'react-test-renderer';
3
- import configureStore from 'redux-mock-store';
4
- import { Provider } from 'react-intl-redux';
5
-
6
- import { WysiwygWidget } from './WysiwygWidget';
7
-
8
- global.__SERVER__ = true; // eslint-disable-line no-underscore-dangle
9
-
10
- const mockStore = configureStore();
11
-
12
- jest.mock('@plone/volto/helpers/Loadable/Loadable');
13
- beforeAll(
14
- async () =>
15
- await require('@plone/volto/helpers/Loadable/Loadable').__setLoadables(),
16
- );
17
-
18
- test('renders a wysiwyg widget component', () => {
19
- const store = mockStore({
20
- intl: {
21
- locale: 'en',
22
- messages: {},
23
- },
24
- userSession: {
25
- token:
26
- 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6MTU4MjM0MzcyNSwiZnVsbG5hbWUiOm51bGx9.BxCvhI8qrtSYUbuTCJCe5TYo1jw8LXZC3gwd726O0UI',
27
- },
28
- });
29
-
30
- const component = renderer.create(
31
- <Provider store={store}>
32
- <WysiwygWidget id="my-field" title="My field" onChange={() => {}} />
33
- </Provider>,
34
- );
35
- const json = component.toJSON();
36
- expect(json).toMatchSnapshot();
37
- });
@@ -1,29 +0,0 @@
1
- export default function Blocks(props) {
2
- const { draftJs, immutableLib } = props;
3
- const { DefaultDraftBlockRenderMap } = draftJs;
4
- const { Map } = immutableLib;
5
-
6
- const blockRenderMap = Map({
7
- callout: {
8
- element: 'p',
9
- },
10
- unstyled: {
11
- element: 'div',
12
- },
13
- });
14
-
15
- const extendedBlockRenderMap =
16
- DefaultDraftBlockRenderMap.merge(blockRenderMap);
17
-
18
- const blockStyleFn = (contentBlock) => {
19
- const type = contentBlock.getType();
20
- if (type === 'callout') {
21
- return 'callout';
22
- }
23
- return null;
24
- };
25
-
26
- const listBlockTypes = ['unordered-list-item', 'ordered-list-item'];
27
-
28
- return { extendedBlockRenderMap, blockStyleFn, listBlockTypes };
29
- }
@@ -1,8 +0,0 @@
1
- export default function FromHTMLCustomBlockFn(element) {
2
- if (element.className === 'callout') {
3
- return {
4
- type: 'callout',
5
- };
6
- }
7
- return null;
8
- }