@vonaffenfels/slate-editor 1.1.28 → 1.1.31

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.
@@ -1,13 +1,14 @@
1
- import {IconButton} from "../SidebarEditor";
2
1
  import {swapArrayElements} from "../helper/array";
3
- import {reduceContentfulResponse} from "../util/reduceContentfulResponse";
4
- import {
5
- Asset, AssetList,
6
- } from "./AssetList";
7
- import {Switch} from "./Switch";
2
+ import {Switch} from "./Fields/Switch";
8
3
  import {Select} from "./Fields/Select";
9
4
  import {RemoteSelect} from "./Fields/RemoteSelect";
10
5
  import {MultiSelect} from "./Fields/MultiSelect";
6
+ import {StreamSelect} from "./Fields/StreamSelect";
7
+ import {Textarea} from "./Fields/Textarea";
8
+ import {ContentfulContentSelect} from "./Fields/ContentfulContentSelect";
9
+ import {CloudinaryContentSelect} from "./Fields/CloudinaryContentSelect";
10
+ import {MVP} from "./Fields/MVP";
11
+ import {ColorPicker} from "./Fields/ColorPicker";
11
12
 
12
13
  export const SidebarEditorField = ({
13
14
  field,
@@ -60,21 +61,7 @@ export const SidebarEditorField = ({
60
61
 
61
62
  switch (field?.control?.type) {
62
63
  case "text":
63
- return <textarea
64
- type="text"
65
- value={value || ""}
66
- onChange={e => {
67
- onChange(fieldKey, e.target.value);
68
- e.target.style.height = "5px";
69
- e.target.style.height = e.target.scrollHeight + 2 + "px";
70
- }}
71
- onBlur={(e) => {
72
- e.target.style.height = "42px";
73
- }}
74
- onFocus={e => {
75
- e.target.style.height = "5px";
76
- e.target.style.height = e.target.scrollHeight + 2 + "px";
77
- }}/>;
64
+ return <Textarea onChange={e => onChange(fieldKey, e.target.value)} value={value} />;
78
65
  case "boolean":
79
66
  return (
80
67
  <div className="flex items-center">
@@ -90,16 +77,7 @@ export const SidebarEditorField = ({
90
77
  case "remote-select":
91
78
  return <RemoteSelect onChange={e => onChange(fieldKey, e.target.value)} field={field} value={value} />;
92
79
  case "data-stream":
93
- return (
94
- <select
95
- value={value || ""}
96
- onChange={e => onChange(fieldKey, e.target.value)}>
97
- <option value="">Auswählen</option>
98
- {(field?.control?.streams || []).map(stream => (
99
- <option key={`select-option-${stream.value}`} value={`$$_STREAM__${stream.value}__`}>{stream.label}</option>
100
- ))}
101
- </select>
102
- );
80
+ return <StreamSelect onChange={e => onChange(fieldKey, e.target.value)} field={field} value={value} />;
103
81
  case "number":
104
82
  return (
105
83
  <input
@@ -118,22 +96,7 @@ export const SidebarEditorField = ({
118
96
  onChange={e => onChange(fieldKey, Number(e.target.value))}/>
119
97
  );
120
98
  case "object":
121
- return (
122
- <textarea
123
- value={typeof value === "object" ? JSON.stringify(value, null, 2) || "" : value}
124
- onChange={e => {
125
- onChange(fieldKey, isJson(e.target.value) ? JSON.parse(e.target.value) : e.target.value);
126
- e.target.style.height = "5px";
127
- e.target.style.height = e.target.scrollHeight + 2 + "px";
128
- }}
129
- onBlur={(e) => {
130
- e.target.style.height = "42px";
131
- }}
132
- onFocus={e => {
133
- e.target.style.height = "5px";
134
- e.target.style.height = e.target.scrollHeight + 2 + "px";
135
- }}/>
136
- );
99
+ return <Textarea onChange={e => onChange(fieldKey, isJson(e.target.value) ? JSON.parse(e.target.value) : e.target.value)} />;
137
100
  case "radio":
138
101
  return (
139
102
  <div>
@@ -210,15 +173,7 @@ export const SidebarEditorField = ({
210
173
  );
211
174
  case "color":
212
175
  return (
213
- <div className="flex flex-col">
214
- <input
215
- type="color"
216
- value={value || ""}
217
- onChange={e => onChange(fieldKey, e.target.value)}/>
218
- {!!value && (
219
- <button className="button button--tertiary mt-1" onClick={() => onChange(fieldKey, undefined)}>Zurücksetzen</button>
220
- )}
221
- </div>
176
+ <ColorPicker value={value} onChange={c => onChange(fieldKey, c)} />
222
177
  );
223
178
  case "date":
224
179
  return (
@@ -244,188 +199,28 @@ export const SidebarEditorField = ({
244
199
  onChange(fieldKey, v);
245
200
  }} />;
246
201
  case "contentful-content":
247
- return (
248
- <>
249
- {!!value && <div className="mb-2"><Asset
250
- sdk={sdk}
251
- asset={value}
252
- onDeleteClick={() => onChange(fieldKey, null)}
253
- onChange={v => onChange(fieldKey, v)}/></div>}
254
- <button
255
- className="button"
256
- onClick={() => {
257
- sdk.dialogs.selectSingleEntry({contentTypes: field.control.contentTypes}).then(content => {
258
- onChange(fieldKey, reduceContentfulResponse(content, field.control.paths));
259
- });
260
- }}
261
- >Auswählen
262
- </button>
263
- </>
264
- );
202
+ return <ContentfulContentSelect value={value} onChange={v => onChange(fieldKey, v)} field={field} sdk={sdk} />;
265
203
  case "contentful-contents":
266
- return (
267
- <>
268
- {value && value.length > 0 && (
269
- <details className="mb-2">
270
- <summary>{value.length || 0} {value.length === 1 ? "Element" : "Elemente"}</summary>
271
- <div className="mt-4">
272
- <AssetList
273
- assets={value}
274
- sdk={sdk}
275
- onChange={v => onChange(fieldKey, v)}
276
- onAddClick={() => {
277
- sdk.dialogs.selectMultipleEntries({contentTypes: field.control.contentTypes}).then(contents => {
278
- onChange(fieldKey, reduceContentfulResponse([...value, ...contents], field.control.paths));
279
- });
280
- }}/>
281
- </div>
282
- </details>
283
- )}
284
- <button
285
- className="button"
286
- onClick={() => {
287
- sdk.dialogs.selectMultipleEntries({contentTypes: field.control.contentTypes}).then(contents => {
288
- onChange(fieldKey, reduceContentfulResponse(contents, field.control.paths));
289
- });
290
- }}
291
- >Auswählen
292
- </button>
293
- </>
294
- );
204
+ return <ContentfulContentSelect value={value} onChange={v => onChange(fieldKey, v)} field={field} sdk={sdk} multiple />;
295
205
  case "cloudinary-image":
296
- return (
297
- <>
298
- {!!value && <div className="mb-2"><Asset
299
- cloudinary
300
- sdk={sdk}
301
- asset={value}
302
- onDeleteClick={() => onChange(fieldKey, null)}/></div>}
303
- <button
304
- className="button"
305
- onClick={() => {
306
- sdk.dialogs.openCurrentApp({
307
- width: "fullWidth",
308
- title: "Select Image",
309
- shouldCloseOnOverlayClick: true,
310
- shouldCloseOnEscapePress: true,
311
- parameters: {
312
- type: "cloudinary",
313
- portal: sdk?.entry?.fields?.portal?.getValue(),
314
- },
315
- }).then((data) => {
316
- onChange(fieldKey, data?.assets?.[0]);
317
- });
318
- }}
319
- >Auswählen
320
- </button>
321
- </>
322
- );
206
+ return <CloudinaryContentSelect value={value} onChange={v => onChange(fieldKey, v)} field={field} sdk={sdk} />;
323
207
  case "cloudinary-images":
324
- return (
325
- <>
326
- {value && value.length > 0 && (
327
- <details className="mb-2">
328
- <summary>{value.length || 0} {value.length === 1 ? "Element" : "Elemente"}</summary>
329
- <div className="mt-4">
330
- <AssetList
331
- cloudinary
332
- assets={value}
333
- sdk={sdk}
334
- onChange={v => onChange(fieldKey, v)}
335
- onAddClick={() => {
336
- sdk.dialogs.openCurrentApp({
337
- width: "fullWidth",
338
- title: "Select Images",
339
- shouldCloseOnOverlayClick: true,
340
- shouldCloseOnEscapePress: true,
341
- parameters: {
342
- type: "cloudinary",
343
- multiple: true,
344
- portal: sdk?.entry?.fields?.portal?.getValue(),
345
- },
346
- }).then((data) => {
347
- onChange(fieldKey, [...value, ...(data?.assets || [])]);
348
- });
349
- }}/>
350
- </div>
351
- </details>
352
- )}
353
- <button
354
- className="button"
355
- onClick={() => {
356
- sdk.dialogs.openCurrentApp({
357
- width: "fullWidth",
358
- title: "Select Images",
359
- shouldCloseOnOverlayClick: true,
360
- shouldCloseOnEscapePress: true,
361
- parameters: {
362
- type: "cloudinary",
363
- multiple: true,
364
- portal: sdk?.entry?.fields?.portal?.getValue(),
365
- },
366
- }).then((data) => {
367
- onChange(fieldKey, data?.assets);
368
- });
369
- }}
370
- >Auswählen
371
- </button>
372
- </>
373
- );
208
+ return <CloudinaryContentSelect value={value} onChange={v => onChange(fieldKey, v)} field={field} sdk={sdk} multiple />;
374
209
  case "mvp":
375
- return (
376
- <details>
377
- <summary>{storybookElement?.attributes?.[fieldKey]?.length || 0} {storybookElement?.attributes?.[fieldKey]?.length === 1 ? "Element" : "Elemente"}</summary>
378
- <div className="mt-4">
379
- {storybookElement?.attributes?.[fieldKey]?.map((f, index) => {
380
- return (
381
- <div className="mb-4" key={`mvp-${index}`}>
382
- <div className="mb-2 flex items-center">
383
- <b className="grow">{field.name} [{index.toString()}]</b>
384
- <div className="icon-button-group mr-1">
385
- <IconButton
386
- size="small"
387
- onClick={() => handleMVPMoveClick(fieldKey, "up", index)}
388
- disabled={index === 0}>↑</IconButton>
389
- <IconButton
390
- size="small"
391
- onClick={() => handleMVPMoveClick(fieldKey, "down", index)}
392
- disabled={index === storybookElement.attributes?.[fieldKey]?.length - 1}>↓</IconButton>
393
- </div>
394
- <IconButton
395
- size="small"
396
- onClick={() => deleteMVPEntry(fieldKey, index)}>🗑</IconButton>
397
- </div>
398
- {Object.keys(field.control.fields).map((key, mvpIndex) => {
399
- let mvpField = field.control.fields[key];
400
-
401
- value = storybookElement.attributes?.[fieldKey]?.[index]?.[key];
402
-
403
- return (
404
- <div key={`mvp-field-${key}`}>
405
- <SidebarEditorField
406
- field={mvpField}
407
- fieldKey={fieldKey}
408
- value={value}
409
- storybookElement={storybookElement}
410
- sdk={sdk}
411
- onChange={(fK, value) => onChange(
412
- fK, value, key, index,
413
- )}/>
414
- </div>
415
- );
416
- })}
417
- <hr className="my-4" style={{borderColor: "rgb(174, 193, 204)"}}/>
418
- </div>
419
- );
420
- })}
421
- <button
422
- className="button button--secondary"
423
- onClick={() => onChange(fieldKey, [...(storybookElement.attributes[fieldKey] || []), {}])}>Neue
424
- Zeile
425
- </button>
426
- </div>
427
- </details>
428
- );
210
+ return <MVP
211
+ value={value}
212
+ onMove={(direction, index) => handleMVPMoveClick(fieldKey, direction, index)}
213
+ onDelete={(index) => deleteMVPEntry(fieldKey, index)}
214
+ field={field}
215
+ onChange={(
216
+ fK, value, key, index,
217
+ ) => onChange(
218
+ fK, value, key, index,
219
+ )}
220
+ fieldKey={fieldKey}
221
+ sdk={sdk}
222
+ storybookElement={storybookElement}
223
+ />;
429
224
  default:
430
225
  return <div className="message message--negative">Keine Konfiguration zu Feldtyp "{field?.control?.type}"
431
226
  gefunden</div>;
@@ -8,7 +8,7 @@ import {Spinner} from "@contentful/forma-36-react-components";
8
8
  import {
9
9
  CollapsableMenu, CollapsableMenuItem,
10
10
  } from "./CollapsableMenu/CollapsableMenu";
11
- import {Switch} from "./SidebarEditor/Switch";
11
+ import {Switch} from "./SidebarEditor/Fields/Switch";
12
12
 
13
13
  const SidebarEditor = ({
14
14
  sdk,
@@ -24,8 +24,6 @@ const SidebarEditor = ({
24
24
  isLoading,
25
25
  lastSelection,
26
26
  }) => {
27
- const portal = sdk?.entry?.fields?.portal.getValue();
28
-
29
27
  const [versions, setVersions] = useState([]);
30
28
  const [lastChangedProperty, setLastChangedProperty] = useState(null);
31
29
  const [versionCount, setVersionCount] = useState(0);
@@ -172,20 +170,6 @@ const SidebarEditor = ({
172
170
  }
173
171
  };
174
172
 
175
- const handleAutocompleteChange = (item) => {
176
- if (!item) {
177
- return onChange({}); // reset to empty
178
- }
179
-
180
- // reset to the first or second story
181
- onChange({
182
- ...storybookElement,
183
- block: item.value,
184
- attributes: item.attributes,
185
- type: item.type,
186
- });
187
- };
188
-
189
173
  useEffect(() => resetVersions, [storybookElement?.editorAttributes?.ref]);
190
174
 
191
175
  const renderTitle = () => {
@@ -122,6 +122,8 @@ export const Toolbar = ({
122
122
  Transforms.insertNodes(editor, [element], {at: slicedPath});
123
123
  }
124
124
  });
125
+ } else {
126
+ Transforms.insertNodes(editor, [element], {at: [0]});
125
127
  }
126
128
  };
127
129
 
@@ -13,17 +13,9 @@ export const TranslationToolbarButton = ({
13
13
  setLocale,
14
14
  translateFromLocale = "de",
15
15
  }) => {
16
- const [enabled, setEnabled] = useState(false);
17
16
  const [loading, setLoading] = useState(false);
18
17
  const [error, setError] = useState(null);
19
-
20
- useEffect(() => {
21
- if (sdk) {
22
- if (sdk?.parameters?.installation?.usersWithTranslation?.includes(sdk?.user?.email) && sdk?.parameters?.installation?.translationService) {
23
- setEnabled(true);
24
- }
25
- }
26
- }, [sdk]);
18
+ const enabled = sdk?.parameters?.installation?.usersWithTranslation?.includes(sdk?.user?.email) && sdk?.parameters?.installation?.translationService;
27
19
 
28
20
  if (sdk.locales.available.length < 2 || !enabled) {
29
21
  return null;