@vonaffenfels/slate-editor 1.0.41 → 1.0.44
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 +2 -2
- package/dist/BlockEditor.js +1 -1
- package/dist/Renderer.js +1 -1
- package/dist/index.css +2 -2
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/scss/editor.scss +6 -6
- package/scss/sidebarEditor.scss +1 -1
- package/src/BlockEditor.js +22 -5
- package/src/SidebarEditor/AssetList.js +1 -1
- package/src/SidebarEditor/SidebarEditorField.js +7 -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.44",
|
|
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": "9bcbf3b9b1002d4d41a6d23fb3ab6b567fc1de4f",
|
|
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/scss/sidebarEditor.scss
CHANGED
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
|
};
|
|
@@ -218,6 +218,17 @@ export default function BlockEditor({
|
|
|
218
218
|
}
|
|
219
219
|
|
|
220
220
|
try {
|
|
221
|
+
editor.selection = {
|
|
222
|
+
anchor: {
|
|
223
|
+
offset: 0,
|
|
224
|
+
path,
|
|
225
|
+
},
|
|
226
|
+
focus: {
|
|
227
|
+
offset: 0,
|
|
228
|
+
path,
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
|
|
221
232
|
Transforms.moveNodes(editor, {
|
|
222
233
|
from: [path[0]],
|
|
223
234
|
match: node => {
|
|
@@ -252,7 +263,13 @@ export default function BlockEditor({
|
|
|
252
263
|
onChange={onSlateChange}
|
|
253
264
|
>
|
|
254
265
|
<div>
|
|
255
|
-
<Toolbar
|
|
266
|
+
<Toolbar
|
|
267
|
+
hover={false}
|
|
268
|
+
onSaveClick={onSaveClick}
|
|
269
|
+
storybookStories={loadedStorybookStories}
|
|
270
|
+
isLoadingStories={isLoadingStories}
|
|
271
|
+
editor={editor}
|
|
272
|
+
sdk={contentfulSdk}/>
|
|
256
273
|
</div>
|
|
257
274
|
<div className="relative h-full max-h-full overflow-scroll px-8 py-4" ref={scrollContainer}>
|
|
258
275
|
{isLoading && (
|
|
@@ -290,7 +307,7 @@ export default function BlockEditor({
|
|
|
290
307
|
storybookElement={selectedStorybookElement}
|
|
291
308
|
onChange={handleSidebarEditorChange}
|
|
292
309
|
storybookStories={loadedStorybookStories}
|
|
293
|
-
isLoading={
|
|
310
|
+
isLoading={isLoadingStories}
|
|
294
311
|
onClose={handleSidebarClose}
|
|
295
312
|
onDelete={handleSidebarDeleteClick}
|
|
296
313
|
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
|
|
|
@@ -88,9 +88,11 @@ export const SidebarEditorField = ({
|
|
|
88
88
|
return (
|
|
89
89
|
<div>
|
|
90
90
|
<input
|
|
91
|
+
id={fieldKey}
|
|
91
92
|
type="checkbox"
|
|
92
93
|
checked={value}
|
|
93
94
|
onChange={e => onChange(fieldKey, e.target.checked)} />
|
|
95
|
+
<label htmlFor={fieldKey}>{value ? "Ja" : "Nein"}</label>
|
|
94
96
|
</div>
|
|
95
97
|
);
|
|
96
98
|
case "select":
|
|
@@ -243,6 +245,7 @@ export const SidebarEditorField = ({
|
|
|
243
245
|
<>
|
|
244
246
|
{!!value && <div className="mb-2"><Asset sdk={sdk} asset={value} onDeleteClick={() => onChange(fieldKey, null)} onChange={v => onChange(fieldKey, v)} /></div>}
|
|
245
247
|
<button
|
|
248
|
+
className="button"
|
|
246
249
|
onClick={() => {
|
|
247
250
|
sdk.dialogs.selectSingleEntry({contentTypes: field.control.contentTypes}).then(content => {
|
|
248
251
|
onChange(fieldKey, content);
|
|
@@ -271,6 +274,7 @@ export const SidebarEditorField = ({
|
|
|
271
274
|
</details>
|
|
272
275
|
)}
|
|
273
276
|
<button
|
|
277
|
+
className="button"
|
|
274
278
|
onClick={() => {
|
|
275
279
|
sdk.dialogs.selectMultipleEntries({contentTypes: field.control.contentTypes}).then(contents => {
|
|
276
280
|
onChange(fieldKey, contents);
|
|
@@ -284,6 +288,7 @@ export const SidebarEditorField = ({
|
|
|
284
288
|
<>
|
|
285
289
|
{!!value && <div className="mb-2"><Asset cloudinary sdk={sdk} asset={value} onDeleteClick={() => onChange(fieldKey, null)} /></div>}
|
|
286
290
|
<button
|
|
291
|
+
className="button"
|
|
287
292
|
onClick={() => {
|
|
288
293
|
sdk.dialogs.openCurrentApp({
|
|
289
294
|
width: "fullWidth",
|
|
@@ -328,6 +333,7 @@ export const SidebarEditorField = ({
|
|
|
328
333
|
</details>
|
|
329
334
|
)}
|
|
330
335
|
<button
|
|
336
|
+
className="button"
|
|
331
337
|
onClick={() => {
|
|
332
338
|
sdk.dialogs.openCurrentApp({
|
|
333
339
|
width: "fullWidth",
|
|
@@ -384,7 +390,7 @@ export const SidebarEditorField = ({
|
|
|
384
390
|
</div>
|
|
385
391
|
);
|
|
386
392
|
})}
|
|
387
|
-
<button className="button--secondary" onClick={() => onChange(fieldKey, [...(storybookElement.attributes[fieldKey] || []), {}])}>Neue Zeile</button>
|
|
393
|
+
<button className="button button--secondary" onClick={() => onChange(fieldKey, [...(storybookElement.attributes[fieldKey] || []), {}])}>Neue Zeile</button>
|
|
388
394
|
</div>
|
|
389
395
|
</details>
|
|
390
396
|
);
|
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={
|