@vonaffenfels/slate-editor 1.0.80 → 1.1.0

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.80",
3
+ "version": "1.1.0",
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": "4fb98b27f14958fc2d5c99f8d95c5010da0c266e",
74
+ "gitHead": "d768183ee1ab268e8c52315f91176ff8d610b81b",
75
75
  "publishConfig": {
76
76
  "access": "public"
77
77
  }
@@ -1,5 +1,12 @@
1
+ .storybook-element-wrapper {
2
+ width: 100%;
3
+ margin-left: auto;
4
+ margin-right: auto;
5
+ }
6
+
1
7
  .storybook-element {
2
- display: inline;
8
+ display: inline-block;
9
+ width: 100%;
3
10
 
4
11
  .storybook-element-component-overlay {
5
12
  display: none;
@@ -8,6 +15,7 @@
8
15
  position: absolute;
9
16
  z-index: 20;
10
17
  background-color: rgba(255, 255, 255, 0.7);
18
+ backdrop-filter: blur(4px);
11
19
  color: black;
12
20
  font-size: 1em;
13
21
  align-items: center;
@@ -20,6 +20,7 @@ import SidebarEditor from './SidebarEditor';
20
20
  import {Spinner} from '@contentful/forma-36-react-components';
21
21
  import {ObjectId} from "./ObjectId";
22
22
  import {Resizable} from "./SidebarEditor/Resizable";
23
+ import {Loader} from "./Loader";
23
24
 
24
25
  export default function BlockEditor({
25
26
  onChange,
@@ -31,6 +32,7 @@ export default function BlockEditor({
31
32
  storybookStories,
32
33
  onSaveClick,
33
34
  isLoading,
35
+ activeConfig,
34
36
  }) {
35
37
  const scrollContainer = useRef(null);
36
38
  const [selectedStorybookElement, setSelectedStorybookElement] = useState(null);
@@ -85,7 +87,6 @@ export default function BlockEditor({
85
87
  let loadedStories = await storybookStories();
86
88
 
87
89
  setIsLoadingStories(false);
88
-
89
90
  setLoadedStorybookStories(loadedStories);
90
91
  };
91
92
 
@@ -99,13 +100,46 @@ export default function BlockEditor({
99
100
  }
100
101
  };
101
102
 
103
+ const fixValue = (newValue) => {
104
+ const fixedValue = [...(newValue || [])];
105
+
106
+ return fixedValue.map(node => {
107
+ // unwrap elements that are inside of a paragraph (that has no text content) so they have been inserted "inline" by mistake
108
+ // this helps preventing a lot of hydration errors!
109
+ if (node?.type === "paragraph") {
110
+ const textContent = node.children.find(v => !v?.type && v?.text);
111
+ if (!textContent) {
112
+ const storybookNodes = node.children.filter(v => v?.type === "storybook");
113
+ // only unwrap if we only have exactly 1 node
114
+ if (storybookNodes.length === 1) {
115
+ const storyNode = storybookNodes.at(0);
116
+ storyNode.isInline = false;
117
+ return storyNode;
118
+ }
119
+ }
120
+ } else if (node?.type === "storybook") {
121
+ if (node.isInline) {
122
+ // we need to copy the node since its readOnly
123
+ return {
124
+ ...node,
125
+ isInline: undefined,
126
+ };
127
+ }
128
+ }
129
+
130
+ return node;
131
+ });
132
+ };
133
+
102
134
  const onSlateChange = (newValue) => {
103
135
  if (editor.selection) {
104
136
  setLastSelection(editor.selection);
105
137
  }
106
138
 
107
- if (newValue.length > 0) {
108
- onChange(newValue);
139
+ const newValueFixed = fixValue(newValue);
140
+
141
+ if (newValueFixed.length > 0) {
142
+ onChange(newValueFixed);
109
143
  } else {
110
144
  onChange(emptyValue);
111
145
  }
@@ -319,6 +353,20 @@ export default function BlockEditor({
319
353
  setSelectedStorybookElement(null);
320
354
  };
321
355
 
356
+ const slug = contentfulSdk?.entry?.fields?.slug?.getValue();
357
+
358
+ if (isLoadingStories) {
359
+ return <div style={{
360
+ display: "flex",
361
+ justifyContent: "center",
362
+ alignItems: "center",
363
+ width: "100%",
364
+ height: "100%",
365
+ }}>
366
+ <Loader/>
367
+ </div>;
368
+ }
369
+
322
370
  return (
323
371
  <div className={classNames({"block-editor-wrapper h-full": true})}>
324
372
  <Resizable
@@ -336,7 +384,12 @@ export default function BlockEditor({
336
384
  isLoadingStories={isLoadingStories}
337
385
  editor={editor}
338
386
  sdk={contentfulSdk}
339
- lastSelection={lastSelection}/>
387
+ lastSelection={lastSelection}
388
+ buttons={activeConfig?.domain && slug && (
389
+ <a href={`${activeConfig.domain}/${slug}`} target="_blank" rel="noreferrer">
390
+ <button className='button button--secondary'>Live-Seite öffnen</button>
391
+ </a>
392
+ )}/>
340
393
  </div>
341
394
  <div className="relative h-full max-h-full overflow-scroll px-8 py-4" ref={scrollContainer}>
342
395
  {isLoading && (
@@ -384,7 +437,7 @@ export default function BlockEditor({
384
437
  onDuplicate={handleSidebarDuplicateClick}
385
438
  onInsert={handleSidebarInsertClick}
386
439
  editor={editor}
387
- lastSelection={lastSelection} />
440
+ lastSelection={lastSelection}/>
388
441
  }
389
442
  />
390
443
  </div>
package/src/Loader.js ADDED
@@ -0,0 +1,138 @@
1
+ export const Loader = ({
2
+ width = "240px",
3
+ height = "240px",
4
+ }) => {
5
+ return <svg
6
+ style={{
7
+ margin: "auto",
8
+ background: "none",
9
+ display: "block",
10
+ shapeRendering: "auto",
11
+ }}
12
+ width={width}
13
+ height={height}
14
+ viewBox="0 0 100 100"
15
+ preserveAspectRatio="xMidYMid">
16
+ <g transform="rotate(0 50 50)">
17
+ <rect x="46.5" y="17.5" rx="3.5" ry="1.5" width="7" height="3" fill="#000000">
18
+ <animate
19
+ attributeName="opacity"
20
+ values="1;0"
21
+ keyTimes="0;1"
22
+ dur="0.9174311926605504s"
23
+ begin="-0.8340283569641368s"
24
+ repeatCount="indefinite" />
25
+ </rect>
26
+ </g>
27
+ <g transform="rotate(32.72727272727273 50 50)">
28
+ <rect x="46.5" y="17.5" rx="3.5" ry="1.5" width="7" height="3" fill="#000000">
29
+ <animate
30
+ attributeName="opacity"
31
+ values="1;0"
32
+ keyTimes="0;1"
33
+ dur="0.9174311926605504s"
34
+ begin="-0.7506255212677231s"
35
+ repeatCount="indefinite" />
36
+ </rect>
37
+ </g>
38
+ <g transform="rotate(65.45454545454545 50 50)">
39
+ <rect x="46.5" y="17.5" rx="3.5" ry="1.5" width="7" height="3" fill="#000000">
40
+ <animate
41
+ attributeName="opacity"
42
+ values="1;0"
43
+ keyTimes="0;1"
44
+ dur="0.9174311926605504s"
45
+ begin="-0.6672226855713094s"
46
+ repeatCount="indefinite" />
47
+ </rect>
48
+ </g>
49
+ <g transform="rotate(98.18181818181819 50 50)">
50
+ <rect x="46.5" y="17.5" rx="3.5" ry="1.5" width="7" height="3" fill="#000000">
51
+ <animate
52
+ attributeName="opacity"
53
+ values="1;0"
54
+ keyTimes="0;1"
55
+ dur="0.9174311926605504s"
56
+ begin="-0.5838198498748958s"
57
+ repeatCount="indefinite" />
58
+ </rect>
59
+ </g>
60
+ <g transform="rotate(130.9090909090909 50 50)">
61
+ <rect x="46.5" y="17.5" rx="3.5" ry="1.5" width="7" height="3" fill="#000000">
62
+ <animate
63
+ attributeName="opacity"
64
+ values="1;0"
65
+ keyTimes="0;1"
66
+ dur="0.9174311926605504s"
67
+ begin="-0.5004170141784821s"
68
+ repeatCount="indefinite" />
69
+ </rect>
70
+ </g>
71
+ <g transform="rotate(163.63636363636363 50 50)">
72
+ <rect x="46.5" y="17.5" rx="3.5" ry="1.5" width="7" height="3" fill="#000000">
73
+ <animate
74
+ attributeName="opacity"
75
+ values="1;0"
76
+ keyTimes="0;1"
77
+ dur="0.9174311926605504s"
78
+ begin="-0.4170141784820684s"
79
+ repeatCount="indefinite" />
80
+ </rect>
81
+ </g>
82
+ <g transform="rotate(196.36363636363637 50 50)">
83
+ <rect x="46.5" y="17.5" rx="3.5" ry="1.5" width="7" height="3" fill="#000000">
84
+ <animate
85
+ attributeName="opacity"
86
+ values="1;0"
87
+ keyTimes="0;1"
88
+ dur="0.9174311926605504s"
89
+ begin="-0.3336113427856547s"
90
+ repeatCount="indefinite" />
91
+ </rect>
92
+ </g>
93
+ <g transform="rotate(229.0909090909091 50 50)">
94
+ <rect x="46.5" y="17.5" rx="3.5" ry="1.5" width="7" height="3" fill="#000000">
95
+ <animate
96
+ attributeName="opacity"
97
+ values="1;0"
98
+ keyTimes="0;1"
99
+ dur="0.9174311926605504s"
100
+ begin="-0.25020850708924103s"
101
+ repeatCount="indefinite" />
102
+ </rect>
103
+ </g>
104
+ <g transform="rotate(261.8181818181818 50 50)">
105
+ <rect x="46.5" y="17.5" rx="3.5" ry="1.5" width="7" height="3" fill="#000000">
106
+ <animate
107
+ attributeName="opacity"
108
+ values="1;0"
109
+ keyTimes="0;1"
110
+ dur="0.9174311926605504s"
111
+ begin="-0.16680567139282734s"
112
+ repeatCount="indefinite" />
113
+ </rect>
114
+ </g>
115
+ <g transform="rotate(294.54545454545456 50 50)">
116
+ <rect x="46.5" y="17.5" rx="3.5" ry="1.5" width="7" height="3" fill="#000000">
117
+ <animate
118
+ attributeName="opacity"
119
+ values="1;0"
120
+ keyTimes="0;1"
121
+ dur="0.9174311926605504s"
122
+ begin="-0.08340283569641367s"
123
+ repeatCount="indefinite" />
124
+ </rect>
125
+ </g>
126
+ <g transform="rotate(327.27272727272725 50 50)">
127
+ <rect x="46.5" y="17.5" rx="3.5" ry="1.5" width="7" height="3" fill="#000000">
128
+ <animate
129
+ attributeName="opacity"
130
+ values="1;0"
131
+ keyTimes="0;1"
132
+ dur="0.9174311926605504s"
133
+ begin="0s"
134
+ repeatCount="indefinite" />
135
+ </rect>
136
+ </g>
137
+ </svg>;
138
+ };
@@ -11,7 +11,8 @@ export const Default = ({
11
11
  isRenderer,
12
12
  isInSlot = false,
13
13
  defaultComponentReplacement,
14
- onElementClick = () => {},
14
+ onElementClick = () => {
15
+ },
15
16
  ...props
16
17
  }) => {
17
18
  const getPropsForType = (type) => {
@@ -54,56 +55,52 @@ export const Default = ({
54
55
  }
55
56
 
56
57
  attributes.onClick = () => onElementClick(element);
58
+ attributes.className = alignedClassname.trim() || undefined;
57
59
 
58
60
  switch (type) {
59
61
  case "blockquote":
60
- return <Wrapper>
61
- <blockquote {...attributes} className={alignedClassname.trim()}>{children}</blockquote>
62
+ return <Wrapper type={type}>
63
+ <blockquote {...attributes}>{children}</blockquote>
62
64
  </Wrapper>;
63
65
  case "list-item":
64
- return <Wrapper>
65
- <li {...attributes} className={alignedClassname.trim()}>{children}</li>
66
+ return <Wrapper type={type}>
67
+ <li {...attributes}>{children}</li>
66
68
  </Wrapper>;
67
69
  case "unordered-list":
68
- return <Wrapper>
69
- <ul {...attributes} className={alignedClassname.trim()}>{children}</ul>
70
+ return <Wrapper type={type}>
71
+ <ul {...attributes}>{children}</ul>
70
72
  </Wrapper>;
71
73
  case "ordered-list":
72
- return <Wrapper>
73
- <ol {...attributes} className={alignedClassname.trim()}>{children}</ol>
74
+ return <Wrapper type={type}>
75
+ <ol {...attributes}>{children}</ol>
74
76
  </Wrapper>;
75
77
  case "arrow-list":
76
- return <Wrapper>
78
+ return <Wrapper type={type}>
77
79
  <ul
78
80
  {...attributes}
79
- className={classNames({
80
- ...alignedClassname.trim(),
81
- "arrow-list": true,
82
- })}>{children}</ul>
81
+ className={classNames("arrow-list", attributes.className)}>{children}</ul>
83
82
  </Wrapper>;
84
83
  case "code":
85
84
  if (isRenderer) {
86
- return <Wrapper code={element?.attributes?.code} />;
85
+ return <Wrapper code={element?.attributes?.code} type={type}/>;
87
86
  } else {
88
- return <Wrapper><div {...attributes} className={alignedClassname.trim()}><div dangerouslySetInnerHTML={{__html: element?.attributes?.code}} /></div></Wrapper>;
89
- }
90
- case "heading":
91
- switch (element.attributes.level) {
92
- case 1:
93
- return <Wrapper level={element.attributes.level}><h1 {...attributes} id={element?.attributes?.id || undefined} className={alignedClassname.trim() || undefined}>{children}</h1></Wrapper>;
94
- case 2:
95
- return <Wrapper level={element.attributes.level}><h2 {...attributes} id={element?.attributes?.id || undefined} className={alignedClassname.trim() || undefined}>{children}</h2></Wrapper>;
96
- case 3:
97
- return <Wrapper level={element.attributes.level}><h3 {...attributes} id={element?.attributes?.id || undefined} className={alignedClassname.trim() || undefined}>{children}</h3></Wrapper>;
98
- case 4:
99
- return <Wrapper level={element.attributes.level}><h4 {...attributes} id={element?.attributes?.id || undefined} className={alignedClassname.trim() || undefined}>{children}</h4></Wrapper>;
100
- case 5:
101
- return <Wrapper level={element.attributes.level}><h5 {...attributes} id={element?.attributes?.id || undefined} className={alignedClassname.trim() || undefined}>{children}</h5></Wrapper>;
102
- case 6:
103
- return <Wrapper level={element.attributes.level}><h6 {...attributes} id={element?.attributes?.id || undefined} className={alignedClassname.trim() || undefined}>{children}</h6></Wrapper>;
104
- default:
105
- return null;
87
+ return <Wrapper type={type}>
88
+ <div {...attributes} >
89
+ <div dangerouslySetInnerHTML={{__html: element?.attributes?.code}}/>
90
+ </div>
91
+ </Wrapper>;
106
92
  }
93
+ case "heading": {
94
+ const HeadingTag = `h${element.attributes.level || 1}`;
95
+ return <Wrapper level={element.attributes.level} type={type}>
96
+ <HeadingTag
97
+ {...attributes}
98
+ id={element?.attributes?.id || undefined}
99
+ >
100
+ {children}
101
+ </HeadingTag>
102
+ </Wrapper>;
103
+ }
107
104
  case "link": {
108
105
  let relProp = `noopener noreferrer`;
109
106
  let {
@@ -121,29 +118,40 @@ export const Default = ({
121
118
  let CustomLink = typeof defaultComponentReplacement === "function" ? defaultComponentReplacement(type) : null;
122
119
 
123
120
  if (CustomLink) {
124
- return <Wrapper><CustomLink {...linkAttributes} {...attributes} rel={relProp} className={alignedClassname.trim()}>{children}</CustomLink></Wrapper>;
121
+ return <Wrapper type={type}><CustomLink
122
+ {...linkAttributes}
123
+ {...attributes}
124
+ rel={relProp}
125
+ className={alignedClassname.trim()}>{children}</CustomLink></Wrapper>;
125
126
  } else {
126
- return <Wrapper><a {...linkAttributes} {...attributes} rel={relProp} className={alignedClassname.trim()}>{children}</a></Wrapper>;
127
+ return <Wrapper type={type}><a
128
+ {...linkAttributes}
129
+ {...attributes}
130
+ rel={relProp}
131
+ className={alignedClassname.trim()}>{children}</a></Wrapper>;
127
132
  }
128
133
  }
129
134
  case "paragraph":
130
- return <Wrapper><p {...element.attributes} {...attributes} className={alignedClassname.trim()}>{children}</p></Wrapper>;
135
+ return <Wrapper type={type}><p
136
+ {...element.attributes}
137
+ {...attributes}
138
+ className={alignedClassname.trim()}>{children}</p></Wrapper>;
131
139
  case "divider":
132
- return <Wrapper>
140
+ return <Wrapper type={type}>
133
141
  <hr {...attributes} />
134
142
  {children}
135
143
  </Wrapper>;
136
144
  case "div":
137
- return <Wrapper>
145
+ return <Wrapper type={type}>
138
146
  <div {...element.attributes} {...attributes}>{children}</div>
139
147
  </Wrapper>;
140
148
  case "span":
141
- return <Wrapper>
149
+ return <Wrapper type={type}>
142
150
  <span {...element.attributes} {...attributes}>{children}</span>
143
151
  </Wrapper>;
144
152
  default:
145
153
  if (isRenderer) {
146
- return <Wrapper>{children}</Wrapper>;
154
+ return <Wrapper type={type}>{children}</Wrapper>;
147
155
  } else {
148
156
  return <span {...attributes} className={alignedClassname.trim()}>{children}</span>;
149
157
  }
@@ -37,7 +37,8 @@ export const Element = ({
37
37
  switch (props.element.type) {
38
38
  case 'storybook':
39
39
  return <div
40
- onClick={e => e.stopPropagation()}>
40
+ onClick={e => e.stopPropagation()}
41
+ className={"storybook-element-wrapper"}>
41
42
  <StorybookNode
42
43
  {...props}
43
44
  {...typeProps}
@@ -124,25 +124,66 @@ const StorybookNodeComponent = ({
124
124
  })}>
125
125
  <span className="options-container">
126
126
  {!element.isInline && (<>
127
- <span className="options-container-option options-container-option-move-up" title="Move up" onClick={moveUp}>
127
+ <span
128
+ className="options-container-option options-container-option-move-up"
129
+ title="Move up"
130
+ onClick={moveUp}>
128
131
  <FontAwesomeIcon icon={faArrowUp} size="lg"/>
129
132
  </span>
130
- <span className="options-container-option options-container-option-move-down" title="Move down" onClick={moveDown}>
133
+ <span
134
+ className="options-container-option options-container-option-move-down"
135
+ title="Move down"
136
+ onClick={moveDown}>
131
137
  <FontAwesomeIcon icon={faArrowDown} size="lg"/>
132
138
  </span>
133
139
  </>)}
134
140
  </span>
135
141
  <span className={classNames({"storybook-element-component": true})}>
136
- <span className="storybook-element-component-overlay" title="Klicken, um das Element zu konfigurieren" onClick={onEditClick}>
142
+ <span
143
+ className="storybook-element-component-overlay"
144
+ title="Klicken, um das Element zu konfigurieren"
145
+ onClick={onEditClick}>
137
146
  <div className="absolute right-0 top-0 m-2">
138
147
  <FontAwesomeIcon
139
148
  icon={faDesktop}
140
149
  color={element?.attributes?.hideOnDesktop ? "lightgray" : "black"}
141
- className="mr-2" />
142
- <FontAwesomeIcon icon={faTablet} color={element?.attributes?.hideOnTablet ? "lightgray" : "black"} className="mr-2" />
143
- <FontAwesomeIcon icon={faMobile} color={element?.attributes?.hideOnSmartphone ? "lightgray" : "black"} />
150
+ className="mr-2"/>
151
+ <FontAwesomeIcon
152
+ icon={faTablet}
153
+ color={element?.attributes?.hideOnTablet ? "lightgray" : "black"}
154
+ className="mr-2"/>
155
+ <FontAwesomeIcon
156
+ icon={faMobile}
157
+ color={element?.attributes?.hideOnSmartphone ? "lightgray" : "black"}/>
144
158
  </div>
145
- Klicken, um das Element zu konfigurieren</span>
159
+ <svg
160
+ width="30%"
161
+ height="30%"
162
+ style={{
163
+ minWidth: "20px",
164
+ minHeight: "20px",
165
+ }}
166
+ viewBox="0 0 48 48"
167
+ xmlns="http://www.w3.org/2000/svg">
168
+ <path d="M0 0h48v48H0z" fill="none"/>
169
+ <style dangerouslySetInnerHTML={{
170
+ __html: `
171
+ g { mix-blend-mode: multiply; }
172
+ `,
173
+ }}/>
174
+ <g>
175
+ <path d="M8.706,37.027c2.363-0.585,4.798-1.243,6.545-1.243c0.683,0,1.261,0.101,1.688,0.345c1.474,0.845,2.318,4.268,3.245,7.502
176
+ C21.421,43.866,22.694,44,24,44c1.306,0,2.579-0.134,3.816-0.368c0.926-3.234,1.771-6.657,3.244-7.501
177
+ c0.427-0.245,1.005-0.345,1.688-0.345c1.747,0,4.183,0.658,6.545,1.243c1.605-1.848,2.865-3.99,3.706-6.333
178
+ c-2.344-2.406-4.872-4.891-4.872-6.694c0-1.804,2.528-4.288,4.872-6.694c-0.841-2.343-2.101-4.485-3.706-6.333
179
+ c-2.363,0.585-4.798,1.243-6.545,1.243c-0.683,0-1.261-0.101-1.688-0.345c-1.474-0.845-2.318-4.268-3.245-7.502
180
+ C26.579,4.134,25.306,4,24,4c-1.306,0-2.579,0.134-3.816,0.368c-0.926,3.234-1.771,6.657-3.245,7.501
181
+ c-0.427,0.245-1.005,0.345-1.688,0.345c-1.747,0-4.183-0.658-6.545-1.243C7.101,12.821,5.841,14.962,5,17.306
182
+ C7.344,19.712,9.872,22.196,9.872,24c0,1.804-2.527,4.288-4.872,6.694C5.841,33.037,7.101,35.179,8.706,37.027z M18,24
183
+ c0-3.314,2.686-6,6-6s6,2.686,6,6s-2.686,6-6,6S18,27.314,18,24z"/>
184
+ </g>
185
+ </svg>
186
+ </span>
146
187
  <div onClick={onEditClick}>
147
188
  <StorybookDisplay
148
189
  {...element.attributes}
@@ -121,20 +121,23 @@ const BlockComponent = ({
121
121
  }
122
122
  }
123
123
 
124
- if (loadedAttributes.blockWidth || loadedAttributes.margin) {
125
- return <span className={classNames({
126
- "block-article-width": loadedAttributes.blockWidth === "article",
127
- "block-site-width": loadedAttributes.blockWidth === "site",
128
- "block-small-width": loadedAttributes.blockWidth === "small",
129
- "editor-mt-large": loadedAttributes?.margin?.top,
130
- "editor-mr-large": loadedAttributes?.margin?.right,
131
- "editor-mb-large": loadedAttributes?.margin?.bottom,
132
- "editor-ml-large": loadedAttributes?.margin?.left,
133
- "lg:hidden": loadedAttributes?.hideOnDesktop && !isEditor,
134
- "sm:max-lg:hidden": loadedAttributes?.hideOnTablet && !isEditor,
135
- "max-sm:hidden": loadedAttributes?.hideOnSmartphone && !isEditor,
136
- })}><LoadedComponent {...loadedAttributes} /></span>;
137
- } else {
124
+ const WrapperTag = loadedAttributes.isInline ? "span" : "div";
125
+ const wrapperClassName = classNames({
126
+ "block-article-width": loadedAttributes.blockWidth === "article",
127
+ "block-site-width": loadedAttributes.blockWidth === "site",
128
+ "block-small-width": loadedAttributes.blockWidth === "small",
129
+ "editor-mt-large": loadedAttributes?.margin?.top,
130
+ "editor-mr-large": loadedAttributes?.margin?.right,
131
+ "editor-mb-large": loadedAttributes?.margin?.bottom,
132
+ "editor-ml-large": loadedAttributes?.margin?.left,
133
+ "lg:hidden": loadedAttributes?.hideOnDesktop && !isEditor,
134
+ "sm:max-lg:hidden": loadedAttributes?.hideOnTablet && !isEditor,
135
+ "max-sm:hidden": loadedAttributes?.hideOnSmartphone && !isEditor,
136
+ });
137
+
138
+ if (!wrapperClassName) {
138
139
  return <LoadedComponent {...loadedAttributes} />;
139
140
  }
141
+
142
+ return <WrapperTag className={wrapperClassName}><LoadedComponent {...loadedAttributes} /></WrapperTag>;
140
143
  };
@@ -124,7 +124,7 @@ export function Serializer({
124
124
  storybookComponentDataLoader: storybookComponentDataLoader,
125
125
  };
126
126
 
127
- return <Wrapper><StorybookDisplay {...storyProps} /></Wrapper>;
127
+ return <Wrapper type={props.type} block={props.block}><StorybookDisplay {...storyProps} /></Wrapper>;
128
128
  }
129
129
  case 'layout': {
130
130
  let isGrid = true;
@@ -137,7 +137,7 @@ export function Serializer({
137
137
  });
138
138
  }
139
139
 
140
- return <Wrapper>
140
+ return <Wrapper type={props.type}>
141
141
  <div
142
142
  data-cols={props.children.length}
143
143
  className={classNames("block-editor-layout", {
@@ -167,7 +167,7 @@ export function Serializer({
167
167
  </Wrapper>;
168
168
  }
169
169
  case 'layout-slot':
170
- return <Wrapper>
170
+ return <Wrapper type={props.type}>
171
171
  <div
172
172
  className={classNames({
173
173
  ["block-editor-layout-" + props.attributes.name]: true,
@@ -40,6 +40,14 @@ const SidebarEditor = ({
40
40
 
41
41
  const story = storybookStories?.find(v => storybookElement.block?.toLowerCase() === v.id?.toLowerCase());
42
42
 
43
+ useEffect(() => {
44
+ const selectedHtmlNode = document.querySelector(".slate-editor-element-selected");
45
+
46
+ if (selectedHtmlNode) {
47
+ selectedHtmlNode.scrollIntoView();
48
+ }
49
+ }, [storybookElement]);
50
+
43
51
  if (story?.argTypes) {
44
52
  Object.keys(story.argTypes).forEach(key => {
45
53
  const argType = story.argTypes[key];
@@ -41,9 +41,5 @@ export const StorybookButton = () => {
41
41
  <FontAwesomeIcon icon={faPlus} />
42
42
  <span> Element hinzufügen</span>
43
43
  </span>
44
- <span className={"toolbar-btn"} onMouseDown={onClickInline}>
45
- <FontAwesomeIcon icon={faPlus} />
46
- <span> Inline Element hinzufügen</span>
47
- </span>
48
44
  </>;
49
45
  };
@@ -39,6 +39,7 @@ export const Toolbar = ({
39
39
  editor,
40
40
  sdk,
41
41
  lastSelection,
42
+ buttons,
42
43
  }) => {
43
44
  const ref = useRef();
44
45
 
@@ -145,7 +146,6 @@ export const Toolbar = ({
145
146
  </ToobarHoverExpandButton>
146
147
 
147
148
  <ToobarHoverExpandButton>
148
- <StorybookButton/>
149
149
  <InsertDividerButton/>
150
150
  <InsertGridButton/>
151
151
  </ToobarHoverExpandButton>
@@ -166,6 +166,9 @@ export const Toolbar = ({
166
166
  {!!onSaveClick && <button
167
167
  className="!w-auto !border-0 !bg-green-600 !text-xs font-bold text-white hover:!bg-green-700"
168
168
  onClick={onSaveClick}>Änderungen speichern</button>}
169
+ {buttons && (
170
+ <div>{buttons}</div>
171
+ )}
169
172
  </div>
170
173
  </Menu>;
171
174
  }