@vonaffenfels/slate-editor 1.1.36 → 1.1.39

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.36",
3
+ "version": "1.1.39",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -72,7 +72,7 @@
72
72
  "cssnano": "^5.0.1",
73
73
  "escape-html": "^1.0.3"
74
74
  },
75
- "gitHead": "c55640e4184996f5503928a6e1f990c3b4420a52",
75
+ "gitHead": "5039c3a8ae4e6e90f31a2e832f55dc3e02fcb190",
76
76
  "publishConfig": {
77
77
  "access": "public"
78
78
  }
@@ -28,6 +28,7 @@
28
28
 
29
29
  input[type="text"],
30
30
  input[type="time"],
31
+ input[type="date"],
31
32
  input[type="number"],
32
33
  input[type="color"],
33
34
  input[type="datetime-local"],
@@ -37,6 +37,7 @@ export const Element = ({
37
37
  switch (props.element.type) {
38
38
  case 'storybook':
39
39
  return <div
40
+ id={props?.element?.attributes?.id}
40
41
  onClick={e => e.stopPropagation()}
41
42
  className={"storybook-element-wrapper"}>
42
43
  <StorybookNode
@@ -144,6 +144,9 @@ const StorybookNodeComponent = ({
144
144
  title="Klicken, um das Element zu konfigurieren"
145
145
  onClick={onEditClick}>
146
146
  <div className="absolute right-0 top-0 m-2">
147
+ <span className="mr-2">
148
+ {[element?.attributes?.visibleFromDate, element?.attributes?.visibleToDate].filter(Boolean).map((date) => new Date(date).toLocaleString?.()).join(" - ")}
149
+ </span>
147
150
  <FontAwesomeIcon
148
151
  icon={faDesktop}
149
152
  color={element?.attributes?.hideOnDesktop ? "lightgray" : "black"}
@@ -36,6 +36,16 @@ export const StorybookDisplay = (props) => {
36
36
  };
37
37
  }, [elRef.current]);
38
38
 
39
+ let currentDate = new Date();
40
+
41
+ if (!isEditor && element?.attributes?.visibleFromDate && new Date(element?.attributes?.visibleFromDate) > currentDate) {
42
+ return;
43
+ }
44
+
45
+ if (!isEditor && element?.attributes?.visibleToDate && new Date(element?.attributes?.visibleToDate) < currentDate) {
46
+ return;
47
+ }
48
+
39
49
  if (element.isEmpty || !element.block) {
40
50
  return <EmptyBlock {...element.attributes} />;
41
51
  }
@@ -0,0 +1,55 @@
1
+ import classNames from "classnames";
2
+
3
+ export const DateTime = ({
4
+ value,
5
+ onChange,
6
+ className,
7
+ inline,
8
+ ...props
9
+ }) => {
10
+ // Separate date and time values
11
+ const dateValue = value ? value.split("T")[0] : "";
12
+ const timeValue = value ? value.split("T")[1] : "";
13
+
14
+ // Handle changes for date and time inputs
15
+ const handleDateChange = (e) => {
16
+ const newDate = e.target.value;
17
+ const newDateTime = `${newDate}T${timeValue || "00:00"}`;
18
+ onChange(newDateTime);
19
+ };
20
+
21
+ const handleTimeChange = (e) => {
22
+ const newTime = e.target.value;
23
+ const newDateTime = `${dateValue || "1970-01-01"}T${newTime}`;
24
+ onChange(newDateTime);
25
+ };
26
+
27
+ return (
28
+ <div className={classNames(className, "grid gap-2", {
29
+ "grid-cols-2": inline,
30
+ "grid-cols-1": !inline,
31
+ })}>
32
+ {/* Date input */}
33
+ <input
34
+ type="date"
35
+ className="w-full"
36
+ value={dateValue}
37
+ onChange={handleDateChange}
38
+ {...props}
39
+ />
40
+
41
+ {/* Time input */}
42
+ <input
43
+ type="time"
44
+ className="w-full"
45
+ value={timeValue}
46
+ onChange={handleTimeChange}
47
+ {...props}
48
+ />
49
+
50
+ {!!value && (
51
+ <button className="button button--tertiary" onClick={() => onChange(undefined)}>Zurücksetzen</button>
52
+ )}
53
+ </div>
54
+ );
55
+ };
@@ -9,6 +9,7 @@ import {
9
9
  CollapsableMenu, CollapsableMenuItem,
10
10
  } from "./CollapsableMenu/CollapsableMenu";
11
11
  import {Switch} from "./SidebarEditor/Fields/Switch";
12
+ import {DateTime} from "./SidebarEditor/Fields/DateTime";
12
13
 
13
14
  const SidebarEditor = ({
14
15
  sdk,
@@ -379,7 +380,7 @@ const SidebarEditor = ({
379
380
  hinzufügen</CollapsableMenuItem>
380
381
  <CollapsableMenuItem onClick={handleInfoClick}>Info</CollapsableMenuItem>
381
382
  <div className="px-4 pb-2 pt-1">
382
- <b className="mb-1 block text-sm">Sichtbar auf:</b>
383
+ <b className="mb-1 block text-sm">Sichtbarkeit</b>
383
384
  <Switch
384
385
  value={!storybookElement.attributes.hideOnDesktop}
385
386
  label="Desktop"
@@ -395,6 +396,10 @@ const SidebarEditor = ({
395
396
  label="Smartphone"
396
397
  className="mb-2"
397
398
  onClick={() => handleFieldValueChange("hideOnSmartphone", !storybookElement.attributes.hideOnSmartphone)}/>
399
+ <label className="mb-1 block">Sichtbar von</label>
400
+ <DateTime className="mb-2" value={storybookElement.attributes.visibleFromDate} onChange={v => handleFieldValueChange("visibleFromDate", v)} />
401
+ <label className="mb-1 block">Sichtbar bis</label>
402
+ <DateTime className="mb-2" value={storybookElement.attributes.visibleToDate} onChange={v => handleFieldValueChange("visibleToDate", v)} />
398
403
  </div>
399
404
  </CollapsableMenu>
400
405
  </div>
@@ -0,0 +1,95 @@
1
+ import {
2
+ ReactEditor, useSlate,
3
+ } from "slate-react";
4
+ import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
5
+ import React, {
6
+ useEffect, useState,
7
+ } from "react";
8
+ import classNames from "classnames";
9
+ import {
10
+ Editor, Transforms, Element as SlateElement, Range, Node,
11
+ } from "slate";
12
+ import {
13
+ faAnchor, faLink,
14
+ } from "@fortawesome/free-solid-svg-icons";
15
+
16
+ export const AnchorButtonElement = ({
17
+ icon,
18
+ children,
19
+ }) => {
20
+ const editor = useSlate();
21
+
22
+ const [anchor, setAnchor] = useState("");
23
+ const [node, setNode] = useState(undefined);
24
+
25
+ useEffect(() => {
26
+ if (editor?.selection?.anchor?.path?.[0] !== undefined) {
27
+ let node = Node.get(editor, [editor?.selection?.anchor?.path?.[0]]);
28
+
29
+ setAnchor(node?.attributes?.id || "");
30
+ setNode(node);
31
+ }
32
+ }, [editor?.selection?.anchor?.path?.[0], editor]);
33
+
34
+ const apply = (value) => {
35
+ // Node.get could return editor itself
36
+ if (!node?.type) {
37
+ return;
38
+ }
39
+
40
+ let path = ReactEditor.findPath(editor, node);
41
+
42
+ let newNode = {
43
+ ...node,
44
+ attributes: {
45
+ ...node.attributes,
46
+ id: anchor,
47
+ },
48
+ };
49
+
50
+ setNode(newNode);
51
+
52
+ Transforms.setNodes(editor, newNode, {at: path});
53
+ };
54
+
55
+ const reset = () => {
56
+ apply("");
57
+
58
+ return;
59
+ };
60
+
61
+ return (
62
+ <span
63
+ className={
64
+ classNames({
65
+ "toolbar-btn": true,
66
+ "active": node?.attributes?.id,
67
+ })
68
+ }
69
+ >
70
+ {!!icon && <FontAwesomeIcon icon={icon} />}
71
+ {children}
72
+ <span className="toolbar-btn-config">
73
+ <span className="toolbar-btn-config-inner">
74
+ <span className="toolbar-btn-config-row">
75
+ <label className="toolbar-form-label">
76
+ Ankername
77
+ </label>
78
+ <span className="toolbar-form-input">
79
+ <input type="text" value={anchor} onChange={(e) => setAnchor(e.target.value)}/>
80
+ </span>
81
+ </span>
82
+ <span className="toolbar-btn-config-row">
83
+ <span className="toolbar-btn" onMouseDown={() => apply(anchor)}>Apply</span>
84
+ {node?.attributes?.id && <span className="toolbar-btn" onMouseDown={reset}>Remove</span>}
85
+ </span>
86
+ </span>
87
+ </span>
88
+ </span>
89
+ );
90
+ };
91
+
92
+
93
+ export const AnchorButton = () => {
94
+ return <AnchorButtonElement icon={faAnchor}/>;
95
+ };
@@ -25,6 +25,7 @@ import {
25
25
  } from "@contentful/forma-36-react-components";
26
26
  import {Transforms} from "slate";
27
27
  import {ElementAutocomplete} from "../ElementAutocomplete";
28
+ import {AnchorButton} from "./Anchor";
28
29
 
29
30
  export const Portal = ({children}) => {
30
31
  return ReactDOM.createPortal(children, window.document.body);
@@ -166,6 +167,8 @@ export const Toolbar = ({
166
167
  <AlignButtonRight/>
167
168
  </ToobarHoverExpandButton>
168
169
 
170
+ <AnchorButton />
171
+
169
172
  <ToobarHoverExpandButton>
170
173
  <InsertDividerButton/>
171
174
  <InsertGridButton/>