@vonaffenfels/slate-editor 1.0.26 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vonaffenfels/slate-editor",
3
- "version": "1.0.26",
3
+ "version": "1.0.30",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -62,7 +62,7 @@
62
62
  "url-loader": "^4.1.1",
63
63
  "util": "^0.12.5",
64
64
  "walk-sync": "^3.0.0",
65
- "webpack": "5.73.0",
65
+ "webpack": "5.88.2",
66
66
  "webpack-cli": "^4.6.0",
67
67
  "webpack-dev-server": "4.7.4"
68
68
  },
@@ -71,7 +71,7 @@
71
71
  "cssnano": "^5.0.1",
72
72
  "escape-html": "^1.0.3"
73
73
  },
74
- "gitHead": "7089b60e41691c2c382e25c8447f74d0bd031aaa",
74
+ "gitHead": "fe88a0b3ce82331fa3d7193a4cd62b8e2c8ecfb9",
75
75
  "publishConfig": {
76
76
  "access": "public"
77
77
  }
@@ -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,
@@ -17,6 +17,8 @@ import "../scss/editor.scss";
17
17
  import {ListItemPlugin} from "./plugins/ListItem";
18
18
  import ErrorBoundary from "../src/Blocks/ErrorBoundary";
19
19
  import SidebarEditor from './SidebarEditor';
20
+ import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
21
+ import {faSpinner} from '@fortawesome/free-solid-svg-icons';
20
22
 
21
23
  export default function BlockEditor({
22
24
  onChange,
@@ -27,6 +29,7 @@ export default function BlockEditor({
27
29
  storybookComponentDataLoader,
28
30
  storybookStories,
29
31
  onSaveClick,
32
+ isLoading,
30
33
  }) {
31
34
  const scrollContainer = useRef(null);
32
35
  const [selectedStorybookElement, setSelectedStorybookElement] = useState(null);
@@ -61,6 +64,24 @@ export default function BlockEditor({
61
64
  ],
62
65
  },
63
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
+
64
85
  const resetEditor = () => {
65
86
  if (confirm("This action will delete all data in the editor, are you sure?")) {
66
87
  onChange(emptyValue);
@@ -231,7 +252,12 @@ export default function BlockEditor({
231
252
  <div>
232
253
  <Toolbar hover={false} onSaveClick={onSaveClick}/>
233
254
  </div>
234
- <div className="h-full max-h-full overflow-scroll px-8 py-4" ref={scrollContainer}>
255
+ <div className="relative h-full max-h-full overflow-scroll px-8 py-4" ref={scrollContainer}>
256
+ {isLoading && (
257
+ <div className='pointer-events-none fixed left-0 top-0 z-50 text-black dark:text-white' style={{padding: "61px 0 0 16px"}}>
258
+ <FontAwesomeIcon icon={faSpinner} pulse />
259
+ </div>
260
+ )}
235
261
  <ErrorBoundary
236
262
  name="editor"
237
263
  fallback={(
@@ -261,7 +287,8 @@ export default function BlockEditor({
261
287
  sdk={contentfulSdk}
262
288
  storybookElement={selectedStorybookElement}
263
289
  onChange={handleSidebarEditorChange}
264
- storybookStories={storybookStories}
290
+ storybookStories={loadedStorybookStories}
291
+ isLoading={isSidebarLoading}
265
292
  onClose={handleSidebarClose}
266
293
  onDelete={handleSidebarDeleteClick}
267
294
  onMove={handleSidebarMoveClick}
@@ -1,6 +1,7 @@
1
1
  import React from "react";
2
2
  import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
3
3
  import {
4
+ faAlignCenter,
4
5
  faArrowDown, faArrowUp, faBorderAll, faBorderNone, faCompress, faTimes,
5
6
  } from "@fortawesome/free-solid-svg-icons";
6
7
  import {Transforms} from "slate";
@@ -119,6 +120,44 @@ export const LayoutBlock = ({
119
120
  }, {at: fromPath});
120
121
  };
121
122
 
123
+ const switchCenter = (e) => {
124
+ let node = ReactEditor.toSlateNode(editor, attributes.ref.current);
125
+ let fromPath = ReactEditor.findPath(editor, node);
126
+
127
+ if (!fromPath) {
128
+ return;
129
+ }
130
+
131
+ let justifyCenter = !(element?.attributes?.justifyCenter);
132
+
133
+ Transforms.setNodes(editor, {
134
+ type: "layout",
135
+ attributes: {
136
+ ...(element.attributes || {}),
137
+ justifyCenter,
138
+ },
139
+ }, {at: fromPath});
140
+ };
141
+
142
+ const switchBorder = (e) => {
143
+ let node = ReactEditor.toSlateNode(editor, attributes.ref.current);
144
+ let fromPath = ReactEditor.findPath(editor, node);
145
+
146
+ if (!fromPath) {
147
+ return;
148
+ }
149
+
150
+ let tableBorder = !(element?.attributes?.tableBorder);
151
+
152
+ Transforms.setNodes(editor, {
153
+ type: "layout",
154
+ attributes: {
155
+ ...(element.attributes || {}),
156
+ tableBorder,
157
+ },
158
+ }, {at: fromPath});
159
+ };
160
+
122
161
  const onMarginChange = (value) => {
123
162
  let node = ReactEditor.toSlateNode(editor, attributes.ref.current);
124
163
  let path = ReactEditor.findPath(editor, node);
@@ -159,12 +198,28 @@ export const LayoutBlock = ({
159
198
  <FontAwesomeIcon icon={faBorderAll} size="lg"/>
160
199
  )}
161
200
  </span>
201
+ <span className="options-container-option options-container-option-expand" onClick={switchCenter}>
202
+ {!element?.attributes?.justifyCenter ? (
203
+ <FontAwesomeIcon icon={faAlignCenter} size="lg"/>
204
+ ) : (
205
+ <FontAwesomeIcon icon={faAlignCenter} color="#3490f3" size="lg"/>
206
+ )}
207
+ </span>
208
+ <span className="options-container-option options-container-option-expand-text mx-2" onClick={switchBorder}>
209
+ {!element?.attributes?.tableBorder ? (
210
+ <span>Kein Rahmen</span>
211
+ ) : (
212
+ <span>Rahmen</span>
213
+ )}
214
+ </span>
162
215
  <ToolMargin margin={element?.attributes?.margin} onChange={onMarginChange}/>
163
216
  </div>
164
217
  <div
165
218
  className={`layout-block layout-grid layout-grid-cols-${children.length} ` + classNames({
166
219
  [classNameArticle + " article-width"]: element?.attributes?.width === "article" || !element?.attributes?.width,
167
220
  [classNameSite + " site-width"]: element?.attributes?.width === "full",
221
+ "block-editor-table-border-wrapper": element?.attributes?.tableBorder,
222
+ "justify-center": element?.attributes?.justifyCenter,
168
223
  "space-x-4": element?.attributes?.spacing,
169
224
  "editor-mt-large": element?.attributes?.margin?.top,
170
225
  "editor-mr-large": element?.attributes?.margin?.right,
@@ -137,6 +137,8 @@ export function Serializer({
137
137
  "mr-16": props?.attributes?.margin?.right,
138
138
  "mb-16": props?.attributes?.margin?.bottom,
139
139
  "ml-16": props?.attributes?.margin?.left,
140
+ "block-editor-table-border-wrapper": props?.attributes?.tableBorder,
141
+ "justify-center": props?.attributes?.justifyCenter,
140
142
  [typeProps.classNameSite + " site-width"]: !isInSlot && (props.attributes?.width === "site" || props.attributes?.width === "full"),
141
143
  [typeProps.classNameArticle + " article-width"]: !isInSlot && (props.attributes?.width === "article" || !props.attributes?.width),
142
144
  })}
@@ -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
 
@@ -107,6 +132,22 @@ export const Asset = ({
107
132
  return null;
108
133
  }
109
134
 
135
+ let assetType = "image";
136
+
137
+ if (title?.endsWith(".mp3")) {
138
+ assetType = "audio";
139
+ }
140
+
141
+ const renderMedia = () => {
142
+ switch (assetType) {
143
+ case "audio":
144
+ return <audio src={mediaUrl} className="mt-2 w-full" controls />;
145
+ case "image":
146
+ default:
147
+ return <img src={mediaUrl} width="100%" className="mt-2 rounded-md" />;
148
+ }
149
+ };
150
+
110
151
  return (
111
152
  <div className="flex flex-col">
112
153
  <div className="flex">
@@ -120,13 +161,20 @@ export const Asset = ({
120
161
  <IconButton size="small" onClick={() => onMoveClick("down")} disabled={index === assetsLength - 1}>↓</IconButton>
121
162
  </div>
122
163
  )}
123
- <a className="mr-1" target="_blank" href={href} rel="noreferrer">
124
- <IconButton size="small">Asset</IconButton>
125
- </a>
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>
126
174
  <IconButton size="small" onClick={onDeleteClick}>⨯</IconButton>
127
175
  </div>
128
176
  </div>
129
- {!!mediaUrl && <img src={mediaUrl} width="100%" className="mt-2 rounded-md" />}
177
+ {!!mediaUrl && renderMedia()}
130
178
  </div>
131
179
  );
132
180
  };
@@ -122,8 +122,8 @@ export const SidebarEditorField = ({
122
122
  case "object":
123
123
  return (
124
124
  <textarea
125
- value={value || ""}
126
- onChange={e => onChange(fieldKey, e.target.value)} />
125
+ value={typeof value === "object" ? JSON.stringify(value, null, 2) || "" : value}
126
+ onChange={e => onChange(fieldKey, isJson(e.target.value) ? JSON.parse(e.target.value) : e.target.value)} />
127
127
  );
128
128
  case "radio":
129
129
  return (
@@ -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 => {
@@ -379,8 +379,17 @@ export const SidebarEditorField = ({
379
379
 
380
380
  return (
381
381
  <div key={`${field.name}`} className="mb-2">
382
- <label className="block">{field.name}</label>
382
+ <label className="block">{field.name || fieldKey}</label>
383
383
  {inputField}
384
384
  </div>
385
385
  );
386
+ };
387
+
388
+ const isJson = (str) => {
389
+ try {
390
+ JSON.parse(str);
391
+ } catch (e) {
392
+ return false;
393
+ }
394
+ return true;
386
395
  };
@@ -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
- <div>
169
- <div className="flex items-center justify-end">
170
- <div className="grow">
171
- {storybookElement?.block && (
172
- <div className="flex items-center">
173
- <div className="icon-button-group mr-1">
174
- <IconButton title="Rückgängig" onClick={undo} disabled={currentVersion <= 1}>↺</IconButton>
175
- <IconButton title="Wiederherstellen" onClick={redo} disabled={currentVersion >= versionCount || versionCount === 0}>↻</IconButton>
176
- </div>
177
- <div className="icon-button-group mr-1">
178
- <IconButton title="Nach oben verschieben" onClick={() => onMove && onMove(storybookElement, "up")} disabled={storybookElement.path[0] === 0}>
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
- </IconButton>
181
- <IconButton title="Nach unten verschieben" onClick={() => onMove && onMove(storybookElement, "down")} disabled={storybookElement.path[0] === editor.children.length - 1}>
189
+ </IconButton>
190
+ <IconButton title="Nach unten verschieben" onClick={() => onMove && onMove(storybookElement, "down")} disabled={storybookElement.path[0] === editor.children.length - 1}>
182
191
 
183
- </IconButton>
184
- </div>
185
- <IconButton title="Löschen" onClick={() => onDelete && onDelete(storybookElement)}>
192
+ </IconButton>
193
+ </div>
194
+ <IconButton title="Löschen" onClick={() => onDelete && onDelete(storybookElement)}>
186
195
  🗑
187
- </IconButton>
188
- <div className="ml-1 flex items-center">
189
- <ToolMargin
190
- margin={storybookElement.attributes.margin}
191
- onChange={value => handleFieldValueChange("margin", value)} />
192
- </div>
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
- {!!onClose && <IconButton onClick={onClose} title="Schließen">⨯</IconButton>}
197
- </div>
198
- <hr className="mt-2" style={{borderColor: "#cfd9e0"}}/>
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
- <hr className="my-4" style={{borderColor: "#cfd9e0"}}/>
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
- {!!story && (
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>
@@ -73,8 +73,23 @@ export const toggleBlock = (editor, format, attributes) => {
73
73
 
74
74
  export const isBlockActive = (editor, format, attributes) => {
75
75
  const {selection} = editor;
76
+
76
77
  if (selection) {
77
- const selectedNodes = [editor.children[selection.anchor.path[0]]];
78
+ let selected = editor;
79
+
80
+ let reducedPath = selection.anchor.path.slice(0, -1);
81
+
82
+ for (let i = 0; i < reducedPath.length; i++) {
83
+ let path = reducedPath[i];
84
+
85
+ selected = selected.children[path];
86
+
87
+ if (LIST_TYPES.includes(selected.type)) {
88
+ break;
89
+ }
90
+ }
91
+
92
+ const selectedNodes = [selected];
78
93
 
79
94
  return !!selectedNodes.find(v => {
80
95
  if (Editor.isEditor(v)) {