@vonaffenfels/slate-editor 1.0.41 → 1.0.43
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/dist/BlockEditor.css +1 -1
- package/dist/BlockEditor.js +1 -1
- package/dist/Renderer.js +1 -1
- package/dist/index.css +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/scss/editor.scss +6 -6
- package/src/BlockEditor.js +11 -5
- package/src/SidebarEditor/AssetList.js +1 -1
- package/src/SidebarEditor/SidebarEditorField.js +5 -1
- package/src/Toolbar/Toolbar.js +132 -34
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vonaffenfels/slate-editor",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.43",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"cssnano": "^5.0.1",
|
|
72
72
|
"escape-html": "^1.0.3"
|
|
73
73
|
},
|
|
74
|
-
"gitHead": "
|
|
74
|
+
"gitHead": "2dc1a5a219755f4b1036840f4c1bc9356749eb28",
|
|
75
75
|
"publishConfig": {
|
|
76
76
|
"access": "public"
|
|
77
77
|
}
|
package/scss/editor.scss
CHANGED
|
@@ -390,7 +390,7 @@
|
|
|
390
390
|
}
|
|
391
391
|
}
|
|
392
392
|
|
|
393
|
-
button {
|
|
393
|
+
.button {
|
|
394
394
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !important;
|
|
395
395
|
width: 100%;
|
|
396
396
|
padding: 8px 0.75rem !important;
|
|
@@ -402,15 +402,15 @@ button {
|
|
|
402
402
|
border-radius: 4px !important;
|
|
403
403
|
}
|
|
404
404
|
|
|
405
|
-
button:hover {
|
|
405
|
+
.button:hover {
|
|
406
406
|
background-color: #0275F0 !important;
|
|
407
407
|
}
|
|
408
408
|
|
|
409
|
-
button:active {
|
|
409
|
+
.button:active {
|
|
410
410
|
background-color: #0262C9 !important;
|
|
411
411
|
}
|
|
412
412
|
|
|
413
|
-
button.button--secondary {
|
|
413
|
+
.button.button--secondary {
|
|
414
414
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !important;
|
|
415
415
|
width: 100%;
|
|
416
416
|
padding: 8px 0.75rem !important;
|
|
@@ -422,12 +422,12 @@ button.button--secondary {
|
|
|
422
422
|
border-radius: 4px !important;
|
|
423
423
|
}
|
|
424
424
|
|
|
425
|
-
button.button--secondary:hover {
|
|
425
|
+
.button.button--secondary:hover {
|
|
426
426
|
background-color: #036fe3 !important;
|
|
427
427
|
color: #FFFFFF !important;
|
|
428
428
|
}
|
|
429
429
|
|
|
430
|
-
button.button--secondary:active {
|
|
430
|
+
.button.button--secondary:active {
|
|
431
431
|
background-color: #0262C9 !important;
|
|
432
432
|
color: #FFFFFF !important;
|
|
433
433
|
}
|
package/src/BlockEditor.js
CHANGED
|
@@ -67,14 +67,14 @@ export default function BlockEditor({
|
|
|
67
67
|
];
|
|
68
68
|
|
|
69
69
|
const [loadedStorybookStories, setLoadedStorybookStories] = useState([]);
|
|
70
|
-
const [
|
|
70
|
+
const [isLoadingStories, setIsLoadingStories] = useState(false);
|
|
71
71
|
|
|
72
72
|
const loadStories = async () => {
|
|
73
|
-
|
|
73
|
+
setIsLoadingStories(true);
|
|
74
74
|
|
|
75
75
|
let loadedStories = await storybookStories();
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
setIsLoadingStories(false);
|
|
78
78
|
|
|
79
79
|
setLoadedStorybookStories(loadedStories);
|
|
80
80
|
};
|
|
@@ -252,7 +252,13 @@ export default function BlockEditor({
|
|
|
252
252
|
onChange={onSlateChange}
|
|
253
253
|
>
|
|
254
254
|
<div>
|
|
255
|
-
<Toolbar
|
|
255
|
+
<Toolbar
|
|
256
|
+
hover={false}
|
|
257
|
+
onSaveClick={onSaveClick}
|
|
258
|
+
storybookStories={loadedStorybookStories}
|
|
259
|
+
isLoadingStories={isLoadingStories}
|
|
260
|
+
editor={editor}
|
|
261
|
+
sdk={contentfulSdk}/>
|
|
256
262
|
</div>
|
|
257
263
|
<div className="relative h-full max-h-full overflow-scroll px-8 py-4" ref={scrollContainer}>
|
|
258
264
|
{isLoading && (
|
|
@@ -290,7 +296,7 @@ export default function BlockEditor({
|
|
|
290
296
|
storybookElement={selectedStorybookElement}
|
|
291
297
|
onChange={handleSidebarEditorChange}
|
|
292
298
|
storybookStories={loadedStorybookStories}
|
|
293
|
-
isLoading={
|
|
299
|
+
isLoading={isLoadingStories}
|
|
294
300
|
onClose={handleSidebarClose}
|
|
295
301
|
onDelete={handleSidebarDeleteClick}
|
|
296
302
|
onMove={handleSidebarMoveClick}
|
|
@@ -26,7 +26,7 @@ export const AssetList = ({
|
|
|
26
26
|
onChange={handleChange}
|
|
27
27
|
/>
|
|
28
28
|
<hr className="my-2" style={{borderColor: "#cfd9e0"}}/>
|
|
29
|
-
{onAddClick && index === assets.length - 1 && <button onClick={onAddClick} className="button--secondary">Hinzufügen</button>}
|
|
29
|
+
{onAddClick && index === assets.length - 1 && <button onClick={onAddClick} className="button button--secondary">Hinzufügen</button>}
|
|
30
30
|
</>
|
|
31
31
|
));
|
|
32
32
|
|
|
@@ -243,6 +243,7 @@ export const SidebarEditorField = ({
|
|
|
243
243
|
<>
|
|
244
244
|
{!!value && <div className="mb-2"><Asset sdk={sdk} asset={value} onDeleteClick={() => onChange(fieldKey, null)} onChange={v => onChange(fieldKey, v)} /></div>}
|
|
245
245
|
<button
|
|
246
|
+
className="button"
|
|
246
247
|
onClick={() => {
|
|
247
248
|
sdk.dialogs.selectSingleEntry({contentTypes: field.control.contentTypes}).then(content => {
|
|
248
249
|
onChange(fieldKey, content);
|
|
@@ -271,6 +272,7 @@ export const SidebarEditorField = ({
|
|
|
271
272
|
</details>
|
|
272
273
|
)}
|
|
273
274
|
<button
|
|
275
|
+
className="button"
|
|
274
276
|
onClick={() => {
|
|
275
277
|
sdk.dialogs.selectMultipleEntries({contentTypes: field.control.contentTypes}).then(contents => {
|
|
276
278
|
onChange(fieldKey, contents);
|
|
@@ -284,6 +286,7 @@ export const SidebarEditorField = ({
|
|
|
284
286
|
<>
|
|
285
287
|
{!!value && <div className="mb-2"><Asset cloudinary sdk={sdk} asset={value} onDeleteClick={() => onChange(fieldKey, null)} /></div>}
|
|
286
288
|
<button
|
|
289
|
+
className="button"
|
|
287
290
|
onClick={() => {
|
|
288
291
|
sdk.dialogs.openCurrentApp({
|
|
289
292
|
width: "fullWidth",
|
|
@@ -328,6 +331,7 @@ export const SidebarEditorField = ({
|
|
|
328
331
|
</details>
|
|
329
332
|
)}
|
|
330
333
|
<button
|
|
334
|
+
className="button"
|
|
331
335
|
onClick={() => {
|
|
332
336
|
sdk.dialogs.openCurrentApp({
|
|
333
337
|
width: "fullWidth",
|
|
@@ -384,7 +388,7 @@ export const SidebarEditorField = ({
|
|
|
384
388
|
</div>
|
|
385
389
|
);
|
|
386
390
|
})}
|
|
387
|
-
<button className="button--secondary" onClick={() => onChange(fieldKey, [...(storybookElement.attributes[fieldKey] || []), {}])}>Neue Zeile</button>
|
|
391
|
+
<button className="button button--secondary" onClick={() => onChange(fieldKey, [...(storybookElement.attributes[fieldKey] || []), {}])}>Neue Zeile</button>
|
|
388
392
|
</div>
|
|
389
393
|
</details>
|
|
390
394
|
);
|
package/src/Toolbar/Toolbar.js
CHANGED
|
@@ -21,6 +21,12 @@ import {StorybookButton} from "./Element";
|
|
|
21
21
|
import {LinkButton} from "./Link";
|
|
22
22
|
import {InsertDividerButton} from "./Insert";
|
|
23
23
|
import {InsertGridButton} from "./Layout";
|
|
24
|
+
import {
|
|
25
|
+
Autocomplete, Spinner,
|
|
26
|
+
} from "@contentful/forma-36-react-components";
|
|
27
|
+
import {Transforms} from "slate";
|
|
28
|
+
|
|
29
|
+
const devMode = localStorage.getItem("dev-mode") === "true";
|
|
24
30
|
|
|
25
31
|
export const Portal = ({children}) => {
|
|
26
32
|
return ReactDOM.createPortal(children, window.document.body);
|
|
@@ -29,9 +35,12 @@ export const Portal = ({children}) => {
|
|
|
29
35
|
export const Toolbar = ({
|
|
30
36
|
hover,
|
|
31
37
|
onSaveClick,
|
|
38
|
+
storybookStories,
|
|
39
|
+
isLoadingStories,
|
|
40
|
+
editor,
|
|
41
|
+
sdk,
|
|
32
42
|
}) => {
|
|
33
43
|
const ref = useRef();
|
|
34
|
-
const editor = useSlate();
|
|
35
44
|
|
|
36
45
|
useEffect(() => {
|
|
37
46
|
if (!hover) {
|
|
@@ -93,39 +102,50 @@ export const Toolbar = ({
|
|
|
93
102
|
})}
|
|
94
103
|
>
|
|
95
104
|
<div className="toolbar-btns">
|
|
96
|
-
<div className="flex grow">
|
|
97
|
-
<
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
<
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
<
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
<
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
<
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
105
|
+
<div className="flex grow items-center">
|
|
106
|
+
<div className="flex">
|
|
107
|
+
<FormatButtonBold/>
|
|
108
|
+
<FormatButtonItalic/>
|
|
109
|
+
<FormatButtonUnderline/>
|
|
110
|
+
<FormatButtonStrikethrough/>
|
|
111
|
+
|
|
112
|
+
<LinkButton/>
|
|
113
|
+
|
|
114
|
+
<ToobarHoverExpandButton>
|
|
115
|
+
<BlockButtonHeading level={2}/>
|
|
116
|
+
<BlockButtonHeading level={3}/>
|
|
117
|
+
<BlockButtonHeading level={4}/>
|
|
118
|
+
</ToobarHoverExpandButton>
|
|
119
|
+
|
|
120
|
+
<ToobarHoverExpandButton>
|
|
121
|
+
<BlockButtonUnorderedList/>
|
|
122
|
+
<BlockButtonOrderedList/>
|
|
123
|
+
<BlockButtonArrowList/>
|
|
124
|
+
</ToobarHoverExpandButton>
|
|
125
|
+
|
|
126
|
+
<BlockButtonBlockquote/>
|
|
127
|
+
|
|
128
|
+
<ToobarHoverExpandButton>
|
|
129
|
+
<AlignButtonLeft/>
|
|
130
|
+
<AlignButtonCenter/>
|
|
131
|
+
<AlignButtonRight/>
|
|
132
|
+
</ToobarHoverExpandButton>
|
|
133
|
+
|
|
134
|
+
<ToobarHoverExpandButton>
|
|
135
|
+
<StorybookButton/>
|
|
136
|
+
<InsertDividerButton/>
|
|
137
|
+
<InsertGridButton/>
|
|
138
|
+
</ToobarHoverExpandButton>
|
|
139
|
+
</div>
|
|
140
|
+
|
|
141
|
+
<div>
|
|
142
|
+
<ElementAutocomplete
|
|
143
|
+
isLoading={isLoadingStories}
|
|
144
|
+
storybookStories={storybookStories}
|
|
145
|
+
editor={editor}
|
|
146
|
+
storyContext={sdk.parameters.instance.storyContext}
|
|
147
|
+
/>
|
|
148
|
+
</div>
|
|
129
149
|
</div>
|
|
130
150
|
{!!onSaveClick && <button className="!w-auto !border-0 !bg-green-600 !text-xs font-bold text-white hover:!bg-green-700" onClick={onSaveClick}>Änderungen speichern</button>}
|
|
131
151
|
</div>
|
|
@@ -143,6 +163,84 @@ export const Toolbar = ({
|
|
|
143
163
|
}
|
|
144
164
|
};
|
|
145
165
|
|
|
166
|
+
const ElementAutocomplete = ({
|
|
167
|
+
storybookStories,
|
|
168
|
+
isLoading,
|
|
169
|
+
editor,
|
|
170
|
+
storyContext,
|
|
171
|
+
}) => {
|
|
172
|
+
const [filteredItems, setFilteredItems] = React.useState(items);
|
|
173
|
+
|
|
174
|
+
const items = (storybookStories || []).map(story => {
|
|
175
|
+
let storyTitleSplit = story.title.split("/");
|
|
176
|
+
|
|
177
|
+
if (!story.id) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
let splitStoryContext = storyContext.split(",");
|
|
182
|
+
let isItemInContext = splitStoryContext.find(context => {
|
|
183
|
+
return Array.isArray(story.storyContext) ? story.storyContext.includes(context) : context === story.storyContext;
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
if (!devMode && !isItemInContext) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return {
|
|
191
|
+
value: story.id.toLowerCase(),
|
|
192
|
+
label: storyTitleSplit[storyTitleSplit.length - 1],
|
|
193
|
+
stories: story.stories,
|
|
194
|
+
};
|
|
195
|
+
}).filter(Boolean);
|
|
196
|
+
|
|
197
|
+
useEffect(() => {
|
|
198
|
+
setFilteredItems(items);
|
|
199
|
+
}, [storybookStories]);
|
|
200
|
+
|
|
201
|
+
const handleQueryChange = (query) => {
|
|
202
|
+
setFilteredItems(query ? items.filter((item) => item.label.toLowerCase().includes(query.toLowerCase())) : items);
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
const handleOnChange = (item) => {
|
|
206
|
+
let element = {
|
|
207
|
+
children: [{text: ''}],
|
|
208
|
+
type: "storybook",
|
|
209
|
+
block: item.value,
|
|
210
|
+
attributes: {...(item?.stories?.[0]?.args || item?.stories?.[1]?.args || {})},
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
Transforms.insertNodes(editor, [element]);
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
useEffect(() => {
|
|
217
|
+
let autoCompleteElement = document.getElementsByClassName("element-autocomplete")[0];
|
|
218
|
+
|
|
219
|
+
if (autoCompleteElement) {
|
|
220
|
+
autoCompleteElement.value = "";
|
|
221
|
+
}
|
|
222
|
+
}, []);
|
|
223
|
+
|
|
224
|
+
return (
|
|
225
|
+
<Autocomplete
|
|
226
|
+
items={filteredItems}
|
|
227
|
+
onQueryChange={handleQueryChange}
|
|
228
|
+
isLoading={isLoading}
|
|
229
|
+
placeholder={'Suchen...'}
|
|
230
|
+
emptyListMessage={'Keine Komponenten gefunden'}
|
|
231
|
+
noMatchesMessage={'Keine Ergebnisse gefunden'}
|
|
232
|
+
dropdownProps={{isFullWidth: true}}
|
|
233
|
+
maxHeight={300}
|
|
234
|
+
onChange={handleOnChange}
|
|
235
|
+
width="medium"
|
|
236
|
+
>
|
|
237
|
+
{(options) =>
|
|
238
|
+
options.map((option) => <span key={option.value}>{option.label}</span>)
|
|
239
|
+
}
|
|
240
|
+
</Autocomplete>
|
|
241
|
+
);
|
|
242
|
+
};
|
|
243
|
+
|
|
146
244
|
export const ToobarHoverExpandButton = ({children}) => {
|
|
147
245
|
return <span
|
|
148
246
|
className={
|