@vonaffenfels/slate-editor 1.1.3 → 1.1.6

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.1.3",
3
+ "version": "1.1.6",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -25,6 +25,7 @@
25
25
  "@babel/plugin-syntax-dynamic-import": "^7.8.3",
26
26
  "@babel/preset-env": "^7.13.15",
27
27
  "@babel/preset-react": "^7.13.13",
28
+ "@contentful/f36-components": "^4.53.0",
28
29
  "@contentful/forma-36-react-components": "^3.100.7",
29
30
  "@fortawesome/fontawesome-svg-core": "^1.2.35",
30
31
  "@fortawesome/free-solid-svg-icons": "^5.15.3",
@@ -71,7 +72,7 @@
71
72
  "cssnano": "^5.0.1",
72
73
  "escape-html": "^1.0.3"
73
74
  },
74
- "gitHead": "9bb577c35e6bd63588821abb46c9a3d4d400bda2",
75
+ "gitHead": "c68ecbde3a3285867c999004130e18b5f2949a58",
75
76
  "publishConfig": {
76
77
  "access": "public"
77
78
  }
package/scss/editor.scss CHANGED
@@ -56,6 +56,10 @@
56
56
  padding: 45px 0 0 0;
57
57
  position: relative;
58
58
 
59
+ .editor-empty-element {
60
+ display: block!important;
61
+ }
62
+
59
63
  p[data-slate-node="element"] {
60
64
  position: relative;
61
65
  //outline: #CECECE dashed;
@@ -26,8 +26,7 @@
26
26
  }
27
27
 
28
28
  &.storybook-inline {
29
- display: inline-flex;
30
- flex-direction: row-reverse;
29
+ display: inline-block;
31
30
 
32
31
  .options-toolbar {
33
32
  display: inline-block;
@@ -341,10 +341,7 @@ export default function BlockEditor({
341
341
  Transforms.insertNodes(editor, [
342
342
  {
343
343
  children: [{text: ''}],
344
- block: "Blocks/Empty",
345
- attributes: {blockWidth: "site"},
346
- isEmpty: true,
347
- type: "storybook",
344
+ type: "paragraph",
348
345
  },
349
346
  ], {at});
350
347
  };
@@ -1,8 +1,7 @@
1
- import {Autocomplete} from "@contentful/forma-36-react-components";
1
+ import {Autocomplete} from "@contentful/f36-components";
2
2
  import {
3
3
  useEffect, useState,
4
4
  } from "react";
5
- import {Transforms} from "slate";
6
5
 
7
6
  const devMode = localStorage.getItem("dev-mode") === "true";
8
7
 
@@ -21,6 +20,8 @@ export const ElementAutocomplete = ({
21
20
  type: "storybook",
22
21
  })) || []), ...customStories]).map(story => {
23
22
  let storyTitleSplit = String(story.title || "").split("/");
23
+ let storyName = story.label || storyTitleSplit.at(-1);
24
+ let storyGroup = storyTitleSplit.length > 1 ? storyTitleSplit.slice(0, -1).join("/") : null;
24
25
 
25
26
  if (story.type === "storybook") {
26
27
  if (!story.id) {
@@ -38,10 +39,10 @@ export const ElementAutocomplete = ({
38
39
  }
39
40
  }
40
41
 
41
-
42
42
  return {
43
43
  value: story.id?.toLowerCase(),
44
- label: story.label || storyTitleSplit[storyTitleSplit.length - 1],
44
+ group: storyGroup,
45
+ label: (storyName || "NameFehlerhaft").replace(/([^A-Z]*)([A-Z]+)([^A-Z]*)/g, '$1 $2$3').trim(),
45
46
  attributes: story?.stories?.[0]?.args || story?.stories?.[1]?.args || {},
46
47
  type: story.type,
47
48
  };
@@ -77,24 +78,52 @@ export const ElementAutocomplete = ({
77
78
  }
78
79
  }, []);
79
80
 
81
+
82
+ const groupedItemsObj = filteredItems.reduce((acc, item) => {
83
+ if (!acc[item.group]) {
84
+ acc[item.group] = [];
85
+ }
86
+
87
+ acc[item.group].push(item);
88
+
89
+ return acc;
90
+ }, {});
91
+ const groupedItemsArr = Object.keys(groupedItemsObj).reduce((acc, key) => {
92
+ const group = {
93
+ groupTitle: key || "#",
94
+ options: groupedItemsObj[key],
95
+ };
96
+
97
+ group.options.sort((a, b) => {
98
+ return a.label.localeCompare(b.label);
99
+ });
100
+
101
+ acc.push(group);
102
+
103
+ return acc;
104
+ }, []);
105
+
106
+ groupedItemsArr.sort((a, b) => {
107
+ return a.groupTitle.localeCompare(b.groupTitle);
108
+ });
109
+
80
110
  return (
81
111
  <Autocomplete
82
- items={filteredItems}
83
- onQueryChange={handleQueryChange}
112
+ items={groupedItemsArr}
113
+ isGrouped={true}
114
+ onInputValueChange={handleQueryChange}
84
115
  isLoading={isLoading}
85
116
  placeholder={'Element hinzufügen'}
86
- emptyListMessage={'Keine Komponenten gefunden'}
87
- noMatchesMessage={'Keine Ergebnisse gefunden'}
117
+ emptyListMessage={'Keine Elemente gefunden'}
118
+ noMatchesMessage={'Keine Elemente gefunden'}
88
119
  dropdownProps={{isFullWidth: true}}
89
120
  maxHeight={300}
90
- onChange={handleOnChange}
121
+ onSelectItem={handleOnChange}
91
122
  width="medium"
123
+ itemToString={(item) => ""}
124
+ renderItem={(item) => `${item.label}`}
92
125
  {...props}
93
- >
94
- {(options) =>
95
- options.map((option) => <span key={option.value}>{option.label}</span>)
96
- }
97
- </Autocomplete>
126
+ />
98
127
  );
99
128
  };
100
129
 
@@ -5,7 +5,6 @@ import {SidebarEditorField} from "./SidebarEditor/SidebarEditorField";
5
5
  import {ToolMargin} from "./Tools/Margin";
6
6
  import "../scss/sidebarEditor.scss";
7
7
  import {Spinner} from "@contentful/forma-36-react-components";
8
- import {ElementAutocomplete} from "./ElementAutocomplete";
9
8
  import {
10
9
  CollapsableMenu, CollapsableMenuItem,
11
10
  } from "./CollapsableMenu/CollapsableMenu";
@@ -198,7 +197,7 @@ const SidebarEditor = ({
198
197
 
199
198
  let storyTitleSplit = String(story.title || "").split("/");
200
199
 
201
- return <h2 className="mb-2 text-lg font-bold">{storyTitleSplit[storyTitleSplit.length - 1]}</h2>;
200
+ return <h2 className="mb-2 text-lg font-bold text-black">{storyTitleSplit[storyTitleSplit.length - 1]}</h2>;
202
201
  };
203
202
 
204
203
  const renderFields = () => {
@@ -291,7 +290,7 @@ const SidebarEditor = ({
291
290
  <div id="sidebar-editor">
292
291
  {isLoading ? (
293
292
  <div className="flex h-full flex-col items-center justify-center">
294
- <Spinner />
293
+ <Spinner/>
295
294
  <span className="mt-2">Elemente werden geladen</span>
296
295
  </div>
297
296
  ) : (
@@ -304,32 +303,62 @@ const SidebarEditor = ({
304
303
  <div className="mr-1 flex items-center">
305
304
  <ToolMargin
306
305
  margin={storybookElement.attributes.margin}
307
- onChange={value => handleFieldValueChange("margin", value)} />
306
+ onChange={value => handleFieldValueChange("margin", value)}/>
308
307
  </div>
309
308
  <div className="icon-button-group mr-1">
310
- <IconButton title="Rückgängig" onClick={undo} disabled={currentVersion <= 1}>↺</IconButton>
311
- <IconButton title="Wiederherstellen" onClick={redo} disabled={currentVersion >= versionCount || versionCount === 0}>↻</IconButton>
309
+ <IconButton
310
+ title="Rückgängig"
311
+ onClick={undo}
312
+ disabled={currentVersion <= 1}>↺</IconButton>
313
+ <IconButton
314
+ title="Wiederherstellen"
315
+ onClick={redo}
316
+ disabled={currentVersion >= versionCount || versionCount === 0}>↻</IconButton>
312
317
  </div>
313
318
  <div className="icon-button-group mr-1">
314
- <IconButton title="Nach oben verschieben" onClick={() => onMove && onMove(storybookElement, "up")} disabled={storybookElement.path[0] === 0}>
315
-
319
+ <IconButton
320
+ title="Nach oben verschieben"
321
+ onClick={() => onMove && onMove(storybookElement, "up")}
322
+ disabled={storybookElement.path[0] === 0}>
323
+
316
324
  </IconButton>
317
- <IconButton title="Nach unten verschieben" onClick={() => onMove && onMove(storybookElement, "down")} disabled={storybookElement.path[0] === editor.children.length - 1}>
318
-
325
+ <IconButton
326
+ title="Nach unten verschieben"
327
+ onClick={() => onMove && onMove(storybookElement, "down")}
328
+ disabled={storybookElement.path[0] === editor.children.length - 1}>
329
+
319
330
  </IconButton>
320
331
  </div>
321
- <IconButton title="Löschen" className="mr-1" onClick={() => onDelete && onDelete(storybookElement)}>
322
- 🗑
332
+ <IconButton
333
+ title="Löschen"
334
+ className="mr-1"
335
+ onClick={() => onDelete && onDelete(storybookElement)}>
336
+ 🗑
323
337
  </IconButton>
324
338
  <CollapsableMenu button={<IconButton title="Funktionen">…</IconButton>}>
325
- <CollapsableMenuItem onClick={onDuplicate}>Duplizieren</CollapsableMenuItem>
326
- <CollapsableMenuItem onClick={() => onInsert("above")}>Davor hinzufügen</CollapsableMenuItem>
327
- <CollapsableMenuItem onClick={() => onInsert("below")}>Danach hinzufügen</CollapsableMenuItem>
339
+ <CollapsableMenuItem
340
+ onClick={onDuplicate}>Duplizieren</CollapsableMenuItem>
341
+ <CollapsableMenuItem onClick={() => onInsert("above")}>Davor
342
+ hinzufügen</CollapsableMenuItem>
343
+ <CollapsableMenuItem onClick={() => onInsert("below")}>Danach
344
+ hinzufügen</CollapsableMenuItem>
328
345
  <div className="px-4 pb-2 pt-1">
329
346
  <b className="mb-1 block text-sm">Sichtbar auf:</b>
330
- <Switch value={!storybookElement.attributes.hideOnDesktop} label="Desktop" className="mb-2" onClick={() => handleFieldValueChange("hideOnDesktop", !storybookElement.attributes.hideOnDesktop)} />
331
- <Switch value={!storybookElement.attributes.hideOnTablet} label="Tablet" className="mb-2" onClick={() => handleFieldValueChange("hideOnTablet", !storybookElement.attributes.hideOnTablet)} />
332
- <Switch value={!storybookElement.attributes.hideOnSmartphone} label="Smartphone" className="mb-2" onClick={() => handleFieldValueChange("hideOnSmartphone", !storybookElement.attributes.hideOnSmartphone)} />
347
+ <Switch
348
+ value={!storybookElement.attributes.hideOnDesktop}
349
+ label="Desktop"
350
+ className="mb-2"
351
+ onClick={() => handleFieldValueChange("hideOnDesktop", !storybookElement.attributes.hideOnDesktop)}/>
352
+ <Switch
353
+ value={!storybookElement.attributes.hideOnTablet}
354
+ label="Tablet"
355
+ className="mb-2"
356
+ onClick={() => handleFieldValueChange("hideOnTablet", !storybookElement.attributes.hideOnTablet)}/>
357
+ <Switch
358
+ value={!storybookElement.attributes.hideOnSmartphone}
359
+ label="Smartphone"
360
+ className="mb-2"
361
+ onClick={() => handleFieldValueChange("hideOnSmartphone", !storybookElement.attributes.hideOnSmartphone)}/>
333
362
  </div>
334
363
  </CollapsableMenu>
335
364
  </div>
@@ -339,29 +368,25 @@ const SidebarEditor = ({
339
368
  </div>
340
369
  <hr className="mt-2" style={{borderColor: "#cfd9e0"}}/>
341
370
  </div>
342
- <div className="grow overflow-y-auto pr-2 pt-2">
343
- {renderTitle()}
344
- <div className="mb-2">
345
- <ElementAutocomplete
346
- isLoading={isLoading}
347
- storybookStories={storybookStories}
348
- editor={editor}
349
- storyContext={sdk.parameters.instance.storyContext}
350
- portal={portal}
351
- lastSelection={lastSelection}
352
- onChange={handleAutocompleteChange}
353
- placeholder="Element wählen"
354
- width="full"
355
- />
371
+ <div className="flex grow flex-col gap-2 overflow-y-auto pr-2 pt-2" >
372
+ <div>
373
+ {renderTitle()}
356
374
  </div>
357
375
  {storybookElement?.block && (
358
- <div>
359
- <div className="mb-2 grid grid-flow-col grid-cols-2 gap-2">
360
- <VariantSelect className="w-full" story={story} onChange={handleVariantSelectChange} />
361
- <BlockWidthSelect className="w-full" value={storybookElement.attributes.blockWidth} onChange={e => handleFieldValueChange("blockWidth", e.target.value)} />
376
+ <>
377
+ <div className="mb-2 flex flex-col gap-2">
378
+ <VariantSelect
379
+ sdk={sdk}
380
+ className="w-full"
381
+ story={story}
382
+ onChange={handleVariantSelectChange}/>
383
+ <BlockWidthSelect
384
+ className="w-full"
385
+ value={storybookElement.attributes.blockWidth}
386
+ onChange={e => handleFieldValueChange("blockWidth", e.target.value)}/>
362
387
  </div>
363
388
  <hr className="my-4" style={{borderColor: "#cfd9e0"}}/>
364
- </div>
389
+ </>
365
390
  )}
366
391
  {renderFields()}
367
392
  </div>
@@ -377,7 +402,8 @@ export const IconButton = ({
377
402
  disabled,
378
403
  size = "medium",
379
404
  className,
380
- onClick = () => {},
405
+ onClick = () => {
406
+ },
381
407
  ...props
382
408
  }) => {
383
409
  let classNames = "icon-button cursor-pointer select-none !p-1";
@@ -416,7 +442,6 @@ const BlockWidthSelect = ({
416
442
  }) => {
417
443
  return (
418
444
  <div>
419
- <label className="block">Breite</label>
420
445
  <select
421
446
  value={value || ""}
422
447
  onChange={onChange}
@@ -435,24 +460,35 @@ const VariantSelect = ({
435
460
  story,
436
461
  onChange,
437
462
  className,
463
+ sdk,
438
464
  }) => {
439
465
  const stories = story?.stories?.filter(s => s.title !== story.title) || [];
440
466
 
441
- if (!onChange) {
467
+ if (!onChange || stories?.length < 2) {
442
468
  return null;
443
469
  }
444
470
 
445
471
  return (
446
472
  <div className={className}>
447
- <label className="block">Preset</label>
448
473
  <select
449
- disabled={stories.length <= 1}
450
- onChange={e => onChange && onChange({
451
- block: story.id,
452
- attributes: {...stories.find(s => s.title === e.target.value)?.args || {}},
453
- type: "storybook",
454
- })}>
455
- <option>Preset wählen</option>
474
+ onChange={e => {
475
+ sdk.dialogs
476
+ .openConfirm({
477
+ title: 'Einstellungen überschreiben',
478
+ message: 'Alle Einstellungen werden überschrieben?',
479
+ intent: 'negative',
480
+ confirmLabel: 'Überschreiben',
481
+ cancelLabel: 'Abbrechen',
482
+ })
483
+ .then((result) => {
484
+ onChange({
485
+ block: story.id,
486
+ attributes: {...stories.find(s => s.title === e.target.value)?.args || {}},
487
+ type: "storybook",
488
+ });
489
+ });
490
+ }}>
491
+ <option>Einstellungen überschreiben</option>
456
492
  {stories.map(s => (
457
493
  <option key={`variant-option-${s.title}`} value={s.title}>{s.title}</option>
458
494
  ))}
@@ -100,7 +100,10 @@ export const Toolbar = ({
100
100
  children: [{text: ''}],
101
101
  type: item.type,
102
102
  block: item.value,
103
- attributes: item.attributes,
103
+ attributes: {
104
+ ...(item.attributes || {}),
105
+ blockWidth: "site",
106
+ },
104
107
  };
105
108
 
106
109
  Transforms.insertNodes(editor, [element], {at: [lastSelection?.anchor?.path?.[0]]});