@vonaffenfels/slate-editor 1.0.28 → 1.0.30
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/src/BlockEditor.js +21 -2
- package/src/SidebarEditor/AssetList.js +40 -8
- package/src/SidebarEditor/SidebarEditorField.js +1 -1
- package/src/SidebarEditor.js +101 -90
- package/src/dev/App.js +1 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vonaffenfels/slate-editor",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.30",
|
|
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": "fe88a0b3ce82331fa3d7193a4cd62b8e2c8ecfb9",
|
|
75
75
|
"publishConfig": {
|
|
76
76
|
"access": "public"
|
|
77
77
|
}
|
package/src/BlockEditor.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, {
|
|
2
|
-
useCallback, useMemo, useState, useRef,
|
|
2
|
+
useCallback, useMemo, useState, useRef, useEffect,
|
|
3
3
|
} from 'react';
|
|
4
4
|
import {
|
|
5
5
|
Slate, Editable, withReact, ReactEditor,
|
|
@@ -64,6 +64,24 @@ export default function BlockEditor({
|
|
|
64
64
|
],
|
|
65
65
|
},
|
|
66
66
|
];
|
|
67
|
+
|
|
68
|
+
const [loadedStorybookStories, setLoadedStorybookStories] = useState([]);
|
|
69
|
+
const [isSidebarLoading, setIsSidebarLoading] = useState(false);
|
|
70
|
+
|
|
71
|
+
const loadStories = async () => {
|
|
72
|
+
setIsSidebarLoading(true);
|
|
73
|
+
|
|
74
|
+
let loadedStories = await storybookStories();
|
|
75
|
+
|
|
76
|
+
setIsSidebarLoading(false);
|
|
77
|
+
|
|
78
|
+
setLoadedStorybookStories(loadedStories);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
loadStories();
|
|
83
|
+
}, []);
|
|
84
|
+
|
|
67
85
|
const resetEditor = () => {
|
|
68
86
|
if (confirm("This action will delete all data in the editor, are you sure?")) {
|
|
69
87
|
onChange(emptyValue);
|
|
@@ -269,7 +287,8 @@ export default function BlockEditor({
|
|
|
269
287
|
sdk={contentfulSdk}
|
|
270
288
|
storybookElement={selectedStorybookElement}
|
|
271
289
|
onChange={handleSidebarEditorChange}
|
|
272
|
-
storybookStories={
|
|
290
|
+
storybookStories={loadedStorybookStories}
|
|
291
|
+
isLoading={isSidebarLoading}
|
|
273
292
|
onClose={handleSidebarClose}
|
|
274
293
|
onDelete={handleSidebarDeleteClick}
|
|
275
294
|
onMove={handleSidebarMoveClick}
|
|
@@ -23,6 +23,7 @@ export const AssetList = ({
|
|
|
23
23
|
assetsLength={assets.length}
|
|
24
24
|
onMoveClick={(direction) => handleMoveClick(direction, index)}
|
|
25
25
|
onDeleteClick={() => handleDeleteClick(index)}
|
|
26
|
+
onChange={handleChange}
|
|
26
27
|
/>
|
|
27
28
|
<hr className="my-2" style={{borderColor: "#cfd9e0"}}/>
|
|
28
29
|
{onAddClick && index === assets.length - 1 && <button onClick={onAddClick} className="button--secondary">Hinzufügen</button>}
|
|
@@ -49,6 +50,24 @@ export const AssetList = ({
|
|
|
49
50
|
onChange(newAssets);
|
|
50
51
|
};
|
|
51
52
|
|
|
53
|
+
const handleChange = (newAsset) => {
|
|
54
|
+
let newAssets = assets.map(asset => {
|
|
55
|
+
if (asset?.sys?.id === newAsset?.sys?.id) {
|
|
56
|
+
return newAsset;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return asset;
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
console.log({
|
|
63
|
+
newAssets,
|
|
64
|
+
newAsset,
|
|
65
|
+
assets,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
onChange(newAssets);
|
|
69
|
+
};
|
|
70
|
+
|
|
52
71
|
return (
|
|
53
72
|
<div>{renderAssets}</div>
|
|
54
73
|
);
|
|
@@ -60,21 +79,18 @@ export const Asset = ({
|
|
|
60
79
|
assetsLength,
|
|
61
80
|
onDeleteClick,
|
|
62
81
|
onMoveClick,
|
|
82
|
+
onChange,
|
|
63
83
|
sdk,
|
|
64
84
|
cloudinary = false,
|
|
65
85
|
}) => {
|
|
66
86
|
const [mediaUrl, setMediaUrl] = useState(null);
|
|
67
87
|
|
|
68
88
|
let id = asset?.sys?.id;
|
|
69
|
-
let title = asset?.fields?.title?.["en-US"] || asset?.fields?.title?.["de"] || asset?.fields?.title?.toString();
|
|
70
|
-
let space = asset?.sys?.space?.sys?.id;
|
|
71
|
-
let environment = asset?.sys?.environment?.sys?.id;
|
|
89
|
+
let title = asset?.fields?.title?.["en-US"] || asset?.fields?.title?.["de"] || asset?.fields?.title?.toString() || asset?.title?.toString();
|
|
72
90
|
let mediaAssetId = asset?.fields?.media?.["en-US"]?.sys?.id || asset?.fields?.media?.["de"]?.sys?.id || asset?.fields?.media?.sys?.id;
|
|
73
|
-
let href = `https://app.contentful.com/spaces/${space}/environments/${environment}/entries/${id}`;
|
|
74
91
|
|
|
75
92
|
if (cloudinary) {
|
|
76
93
|
title = asset.public_id;
|
|
77
|
-
href = asset.url;
|
|
78
94
|
}
|
|
79
95
|
|
|
80
96
|
useEffect(() => {
|
|
@@ -85,6 +101,15 @@ export const Asset = ({
|
|
|
85
101
|
}
|
|
86
102
|
|
|
87
103
|
if (!mediaAssetId) {
|
|
104
|
+
if (asset?.media?.url) {
|
|
105
|
+
let params = new URLSearchParams({
|
|
106
|
+
w: "512",
|
|
107
|
+
q: "80",
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
setMediaUrl(`${asset?.media?.url}?${params}`);
|
|
111
|
+
}
|
|
112
|
+
|
|
88
113
|
return;
|
|
89
114
|
}
|
|
90
115
|
|
|
@@ -136,9 +161,16 @@ export const Asset = ({
|
|
|
136
161
|
<IconButton size="small" onClick={() => onMoveClick("down")} disabled={index === assetsLength - 1}>↓</IconButton>
|
|
137
162
|
</div>
|
|
138
163
|
)}
|
|
139
|
-
<
|
|
140
|
-
|
|
141
|
-
|
|
164
|
+
<IconButton
|
|
165
|
+
size="small"
|
|
166
|
+
className="mr-1"
|
|
167
|
+
onClick={() => {
|
|
168
|
+
sdk.navigator.openEntry(id, {slideIn: {waitForClose: true}}).then(({entity}) => {
|
|
169
|
+
if (onChange) {
|
|
170
|
+
onChange(entity);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
}}>✎</IconButton>
|
|
142
174
|
<IconButton size="small" onClick={onDeleteClick}>⨯</IconButton>
|
|
143
175
|
</div>
|
|
144
176
|
</div>
|
|
@@ -219,7 +219,7 @@ export const SidebarEditorField = ({
|
|
|
219
219
|
case "contentful-content":
|
|
220
220
|
return (
|
|
221
221
|
<>
|
|
222
|
-
{!!value && <div className="mb-2"><Asset sdk={sdk} asset={value} onDeleteClick={() => onChange(fieldKey, null)} /></div>}
|
|
222
|
+
{!!value && <div className="mb-2"><Asset sdk={sdk} asset={value} onDeleteClick={() => onChange(fieldKey, null)} onChange={v => onChange(fieldKey, v)} /></div>}
|
|
223
223
|
<button
|
|
224
224
|
onClick={() => {
|
|
225
225
|
sdk.dialogs.selectSingleEntry({contentTypes: field.control.contentTypes}).then(content => {
|
package/src/SidebarEditor.js
CHANGED
|
@@ -5,6 +5,8 @@ import {SidebarEditorField} from "./SidebarEditor/SidebarEditorField";
|
|
|
5
5
|
import {ToolMargin} from "./Tools/Margin";
|
|
6
6
|
|
|
7
7
|
import "../scss/sidebarEditor.scss";
|
|
8
|
+
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
|
9
|
+
import {faSpinner} from "@fortawesome/free-solid-svg-icons";
|
|
8
10
|
|
|
9
11
|
const SidebarEditor = ({
|
|
10
12
|
sdk,
|
|
@@ -15,6 +17,7 @@ const SidebarEditor = ({
|
|
|
15
17
|
onDelete,
|
|
16
18
|
onMove,
|
|
17
19
|
editor,
|
|
20
|
+
isLoading,
|
|
18
21
|
}) => {
|
|
19
22
|
const [versions, setVersions] = useState([]);
|
|
20
23
|
const [lastChangedProperty, setLastChangedProperty] = useState(null);
|
|
@@ -26,7 +29,7 @@ const SidebarEditor = ({
|
|
|
26
29
|
tables: {},
|
|
27
30
|
};
|
|
28
31
|
|
|
29
|
-
const story = storybookStories?.find(v => storybookElement.block === v.id);
|
|
32
|
+
const story = storybookStories?.find(v => storybookElement.block?.toLowerCase() === v.id?.toLowerCase());
|
|
30
33
|
|
|
31
34
|
if (story) {
|
|
32
35
|
Object.keys(story.argTypes).forEach(key => {
|
|
@@ -165,99 +168,107 @@ const SidebarEditor = ({
|
|
|
165
168
|
|
|
166
169
|
return (
|
|
167
170
|
<div id="sidebar-editor">
|
|
168
|
-
|
|
169
|
-
<div className="
|
|
170
|
-
<
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
<
|
|
171
|
+
{isLoading ? (
|
|
172
|
+
<div className="text-center">
|
|
173
|
+
<FontAwesomeIcon icon={faSpinner} pulse />
|
|
174
|
+
</div>
|
|
175
|
+
) : (
|
|
176
|
+
<>
|
|
177
|
+
<div>
|
|
178
|
+
<div className="flex items-center justify-end">
|
|
179
|
+
<div className="grow">
|
|
180
|
+
{storybookElement?.block && (
|
|
181
|
+
<div className="flex items-center">
|
|
182
|
+
<div className="icon-button-group mr-1">
|
|
183
|
+
<IconButton title="Rückgängig" onClick={undo} disabled={currentVersion <= 1}>↺</IconButton>
|
|
184
|
+
<IconButton title="Wiederherstellen" onClick={redo} disabled={currentVersion >= versionCount || versionCount === 0}>↻</IconButton>
|
|
185
|
+
</div>
|
|
186
|
+
<div className="icon-button-group mr-1">
|
|
187
|
+
<IconButton title="Nach oben verschieben" onClick={() => onMove && onMove(storybookElement, "up")} disabled={storybookElement.path[0] === 0}>
|
|
179
188
|
↑
|
|
180
|
-
|
|
181
|
-
|
|
189
|
+
</IconButton>
|
|
190
|
+
<IconButton title="Nach unten verschieben" onClick={() => onMove && onMove(storybookElement, "down")} disabled={storybookElement.path[0] === editor.children.length - 1}>
|
|
182
191
|
↓
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
192
|
+
</IconButton>
|
|
193
|
+
</div>
|
|
194
|
+
<IconButton title="Löschen" onClick={() => onDelete && onDelete(storybookElement)}>
|
|
186
195
|
🗑
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
196
|
+
</IconButton>
|
|
197
|
+
<div className="ml-1 flex items-center">
|
|
198
|
+
<ToolMargin
|
|
199
|
+
margin={storybookElement.attributes.margin}
|
|
200
|
+
onChange={value => handleFieldValueChange("margin", value)} />
|
|
201
|
+
</div>
|
|
202
|
+
</div>
|
|
203
|
+
)}
|
|
193
204
|
</div>
|
|
194
|
-
|
|
205
|
+
{!!onClose && <IconButton onClick={onClose} title="Schließen">⨯</IconButton>}
|
|
206
|
+
</div>
|
|
207
|
+
<hr className="mt-2" style={{borderColor: "#cfd9e0"}}/>
|
|
195
208
|
</div>
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
</div>
|
|
200
|
-
<div className="grow overflow-y-auto pr-2 pt-2">
|
|
201
|
-
<div className="mb-2">
|
|
202
|
-
<BlockSelect stories={storybookStories} active={storybookElement} onChange={handleBlockSelectChange} />
|
|
203
|
-
</div>
|
|
204
|
-
{storybookElement?.block && (
|
|
205
|
-
<div>
|
|
206
|
-
<div className="mb-2 grid grid-flow-col grid-cols-2 gap-2">
|
|
207
|
-
<VariantSelect className="w-full" story={story} onChange={handleVariantSelectChange} />
|
|
208
|
-
<BlockWidthSelect className="w-full" value={storybookElement.attributes.blockWidth} onChange={e => handleFieldValueChange("blockWidth", e.target.value)} />
|
|
209
|
+
<div className="grow overflow-y-auto pr-2 pt-2">
|
|
210
|
+
<div className="mb-2">
|
|
211
|
+
<BlockSelect stories={storybookStories} active={storybookElement} onChange={handleBlockSelectChange} />
|
|
209
212
|
</div>
|
|
210
|
-
|
|
213
|
+
{storybookElement?.block && (
|
|
214
|
+
<div>
|
|
215
|
+
<div className="mb-2 grid grid-flow-col grid-cols-2 gap-2">
|
|
216
|
+
<VariantSelect className="w-full" story={story} onChange={handleVariantSelectChange} />
|
|
217
|
+
<BlockWidthSelect className="w-full" value={storybookElement.attributes.blockWidth} onChange={e => handleFieldValueChange("blockWidth", e.target.value)} />
|
|
218
|
+
</div>
|
|
219
|
+
<hr className="my-4" style={{borderColor: "#cfd9e0"}}/>
|
|
220
|
+
</div>
|
|
221
|
+
)}
|
|
222
|
+
{!!story && (
|
|
223
|
+
<>
|
|
224
|
+
{Object.keys(fields.fields).map(key => {
|
|
225
|
+
const field = fields.fields[key];
|
|
226
|
+
|
|
227
|
+
return <SidebarEditorField
|
|
228
|
+
sdk={sdk}
|
|
229
|
+
value={storybookElement?.attributes?.[key]}
|
|
230
|
+
key={key}
|
|
231
|
+
storybookElement={storybookElement}
|
|
232
|
+
fieldKey={key}
|
|
233
|
+
field={field}
|
|
234
|
+
onChange={(
|
|
235
|
+
key, value, mvpField, mvpIndex,
|
|
236
|
+
) => handleFieldValueChange(
|
|
237
|
+
key, value, mvpField, mvpIndex,
|
|
238
|
+
)}
|
|
239
|
+
/>;
|
|
240
|
+
})}
|
|
241
|
+
{Object.keys(fields.tables).map(tableKey => {
|
|
242
|
+
return (
|
|
243
|
+
<details key={`accordion-item-${tableKey}`} className="mb-2">
|
|
244
|
+
<summary>{tableKey}</summary>
|
|
245
|
+
<div className="mt-4">
|
|
246
|
+
{Object.keys(fields.tables[tableKey]).map(key => {
|
|
247
|
+
const field = fields.tables[tableKey][key];
|
|
248
|
+
|
|
249
|
+
return <SidebarEditorField
|
|
250
|
+
sdk={sdk}
|
|
251
|
+
value={storybookElement?.attributes?.[key]}
|
|
252
|
+
key={key}
|
|
253
|
+
fieldKey={key}
|
|
254
|
+
story={storybookElement}
|
|
255
|
+
field={field}
|
|
256
|
+
onChange={(
|
|
257
|
+
key, value, mvpField, mvpIndex,
|
|
258
|
+
) => handleFieldValueChange(
|
|
259
|
+
key, value, mvpField, mvpIndex,
|
|
260
|
+
)}
|
|
261
|
+
/>;
|
|
262
|
+
})}
|
|
263
|
+
</div>
|
|
264
|
+
</details>
|
|
265
|
+
);
|
|
266
|
+
})}
|
|
267
|
+
</>
|
|
268
|
+
)}
|
|
211
269
|
</div>
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
<>
|
|
215
|
-
{Object.keys(fields.fields).map(key => {
|
|
216
|
-
const field = fields.fields[key];
|
|
217
|
-
|
|
218
|
-
return <SidebarEditorField
|
|
219
|
-
sdk={sdk}
|
|
220
|
-
value={storybookElement?.attributes?.[key]}
|
|
221
|
-
key={key}
|
|
222
|
-
storybookElement={storybookElement}
|
|
223
|
-
fieldKey={key}
|
|
224
|
-
field={field}
|
|
225
|
-
onChange={(
|
|
226
|
-
key, value, mvpField, mvpIndex,
|
|
227
|
-
) => handleFieldValueChange(
|
|
228
|
-
key, value, mvpField, mvpIndex,
|
|
229
|
-
)}
|
|
230
|
-
/>;
|
|
231
|
-
})}
|
|
232
|
-
{Object.keys(fields.tables).map(tableKey => {
|
|
233
|
-
return (
|
|
234
|
-
<details key={`accordion-item-${tableKey}`} className="mb-2">
|
|
235
|
-
<summary>{tableKey}</summary>
|
|
236
|
-
<div className="mt-4">
|
|
237
|
-
{Object.keys(fields.tables[tableKey]).map(key => {
|
|
238
|
-
const field = fields.tables[tableKey][key];
|
|
239
|
-
|
|
240
|
-
return <SidebarEditorField
|
|
241
|
-
sdk={sdk}
|
|
242
|
-
value={storybookElement?.attributes?.[key]}
|
|
243
|
-
key={key}
|
|
244
|
-
fieldKey={key}
|
|
245
|
-
story={storybookElement}
|
|
246
|
-
field={field}
|
|
247
|
-
onChange={(
|
|
248
|
-
key, value, mvpField, mvpIndex,
|
|
249
|
-
) => handleFieldValueChange(
|
|
250
|
-
key, value, mvpField, mvpIndex,
|
|
251
|
-
)}
|
|
252
|
-
/>;
|
|
253
|
-
})}
|
|
254
|
-
</div>
|
|
255
|
-
</details>
|
|
256
|
-
);
|
|
257
|
-
})}
|
|
258
|
-
</>
|
|
259
|
-
)}
|
|
260
|
-
</div>
|
|
270
|
+
</>
|
|
271
|
+
)}
|
|
261
272
|
</div>
|
|
262
273
|
);
|
|
263
274
|
};
|
|
@@ -410,7 +421,7 @@ const BlockSelect = ({
|
|
|
410
421
|
|
|
411
422
|
if (option.title && option.id) {
|
|
412
423
|
return (
|
|
413
|
-
<option key={option.id} value={option.id}>
|
|
424
|
+
<option key={option.id} value={option.id.toLowerCase()}>
|
|
414
425
|
{option.shortTitle}
|
|
415
426
|
</option>
|
|
416
427
|
);
|
|
@@ -433,8 +444,8 @@ const BlockSelect = ({
|
|
|
433
444
|
<div className={className}>
|
|
434
445
|
<label className="block">Element</label>
|
|
435
446
|
<select
|
|
436
|
-
onChange={e => onSelectChange(stories.find(s => s.id === e.target.value))}
|
|
437
|
-
value={active?.block}
|
|
447
|
+
onChange={e => onSelectChange(stories.find(s => s.id?.toLowerCase() === e.target.value))}
|
|
448
|
+
value={active?.block?.toLowerCase()}
|
|
438
449
|
className="font-bold"
|
|
439
450
|
>
|
|
440
451
|
<option>Element wählen</option>
|
package/src/dev/App.js
CHANGED
|
@@ -23,22 +23,13 @@ function App() {
|
|
|
23
23
|
},
|
|
24
24
|
];
|
|
25
25
|
const [value, setValue] = useState(SampleValue);
|
|
26
|
-
const [loadedStorybookStories, setLoadedStorybookStories] = useState([]);
|
|
27
|
-
|
|
28
|
-
const loadStories = async () => {
|
|
29
|
-
setLoadedStorybookStories(await storybookStories());
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
useEffect(() => {
|
|
33
|
-
loadStories();
|
|
34
|
-
}, []);
|
|
35
26
|
|
|
36
27
|
return (
|
|
37
28
|
<div className="editor-demo-wrapper">
|
|
38
29
|
<div className="editor-demo block-editor-content">
|
|
39
30
|
<div className="editor-demo-editor container">
|
|
40
31
|
<BlockEditor
|
|
41
|
-
storybookStories={
|
|
32
|
+
storybookStories={storybookStories}
|
|
42
33
|
onChange={setValue}
|
|
43
34
|
elementPropsMap={{}}
|
|
44
35
|
value={value}
|