@flozy/editor 1.7.8 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. package/dist/Editor/CommonEditor.js +12 -11
  2. package/dist/Editor/Editor.css +2 -2
  3. package/dist/Editor/Elements/Attachments/Attachments.js +95 -0
  4. package/dist/Editor/Elements/Attachments/AttachmentsButton.js +46 -0
  5. package/dist/Editor/Elements/Carousel/Carousel.js +2 -3
  6. package/dist/Editor/Elements/Carousel/CarouselItem.js +16 -7
  7. package/dist/Editor/Elements/Color Picker/Styles.js +2 -2
  8. package/dist/Editor/Elements/Embed/Image.js +1 -1
  9. package/dist/Editor/Elements/Grid/templates/carousel_item.js +60 -0
  10. package/dist/Editor/Elements/Link/Link.js +5 -3
  11. package/dist/Editor/Elements/SimpleText.js +4 -2
  12. package/dist/Editor/Elements/Table/TableCell.js +3 -2
  13. package/dist/Editor/MiniEditor.js +14 -12
  14. package/dist/Editor/Toolbar/Basic/index.js +53 -0
  15. package/dist/Editor/Toolbar/Toolbar.js +7 -0
  16. package/dist/Editor/Toolbar/toolbarGroups.js +9 -2
  17. package/dist/Editor/common/ColorPickerButton.js +14 -7
  18. package/dist/Editor/common/Icon.js +3 -2
  19. package/dist/Editor/common/ImageSelector/ImageSelector.js +12 -4
  20. package/dist/Editor/common/ImageSelector/Options/Upload.js +4 -2
  21. package/dist/Editor/common/Shorthands/elements.js +1 -1
  22. package/dist/Editor/common/Uploader.js +48 -10
  23. package/dist/Editor/common/iconslist.js +10 -10
  24. package/dist/Editor/helper/index.js +5 -2
  25. package/dist/Editor/service/fileupload.js +0 -1
  26. package/dist/Editor/utils/SlateUtilityFunctions.js +7 -1
  27. package/dist/Editor/utils/attachments.js +34 -0
  28. package/dist/Editor/utils/carouselItem.js +2 -4
  29. package/dist/Editor/utils/helper.js +30 -0
  30. package/dist/Editor/utils/serializeToHTML.js +19 -2
  31. package/dist/Editor/utils/table.js +19 -2
  32. package/package.json +1 -1
@@ -346,11 +346,11 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
346
346
  onChange: handleEditorChange,
347
347
  children: [/*#__PURE__*/_jsx(DragAndDrop, {
348
348
  children: /*#__PURE__*/_jsx(Overlay, {
349
- children: /*#__PURE__*/_jsxs(Box, {
349
+ children: /*#__PURE__*/_jsx(Box, {
350
350
  className: `${hasTopBanner() ? "has-topbanner" : ""}`,
351
351
  sx: classes.slateWrapper,
352
352
  id: "slate-wrapper-scroll-container",
353
- children: [/*#__PURE__*/_jsxs(Box, {
353
+ children: /*#__PURE__*/_jsxs(Box, {
354
354
  component: "div",
355
355
  className: "max-content",
356
356
  children: [renderTopBanner(), /*#__PURE__*/_jsx("div", {
@@ -397,15 +397,16 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
397
397
  }), !readOnly ? /*#__PURE__*/_jsx(MiniToolbar, {
398
398
  customProps: customProps,
399
399
  toolbarOptions: toolbarOptions
400
- }) : null]
401
- }), readOnly && /*#__PURE__*/_jsx(Typography, {
402
- sx: {
403
- color: "rgb(100, 116, 139)",
404
- fontSize: "13px"
405
- },
406
- align: "center",
407
- children: footer
408
- })]
400
+ }) : null, footer && /*#__PURE__*/_jsx(Typography, {
401
+ sx: {
402
+ color: "rgb(100, 116, 139)",
403
+ fontSize: "13px",
404
+ paddingBottom: "12px"
405
+ },
406
+ align: "center",
407
+ children: footer
408
+ })]
409
+ })
409
410
  })
410
411
  })
411
412
  }), htmlAction.showInput && /*#__PURE__*/_jsx(CodeToText, {
@@ -32,11 +32,11 @@ blockquote {
32
32
  .editor-wrapper table,
33
33
  .editor-wrapperth,
34
34
  .editor-wrapper td {
35
- border: 1px solid black;
35
+ border: 1px solid transparent;
36
36
  }
37
37
 
38
38
  .editor-wrapper table {
39
- border-collapse: collapse;
39
+ border-collapse: separate;
40
40
  }
41
41
 
42
42
  .editor-wrapper .editor-wrapperbutton {
@@ -0,0 +1,95 @@
1
+ import React from "react";
2
+ import { Box, Card, CardMedia, CardContent, Typography } from "@mui/material";
3
+ import PictureAsPdfIcon from "@mui/icons-material/PictureAsPdf";
4
+ import TextSnippetIcon from "@mui/icons-material/TextSnippet";
5
+ import { formatDate } from "../../utils/helper";
6
+ import { jsx as _jsx } from "react/jsx-runtime";
7
+ import { jsxs as _jsxs } from "react/jsx-runtime";
8
+ const Attachments = props => {
9
+ const {
10
+ attributes,
11
+ element,
12
+ children
13
+ } = props;
14
+ const {
15
+ url,
16
+ type,
17
+ date
18
+ } = element;
19
+ const getLastName = url?.split("/").pop();
20
+ const fileName = `${decodeURI(getLastName)}`;
21
+ return /*#__PURE__*/_jsxs(Box, {
22
+ component: "div",
23
+ className: "attachment-wrpr-ev2",
24
+ ...attributes,
25
+ contentEditable: false,
26
+ style: {
27
+ display: "inline-flex"
28
+ },
29
+ children: [/*#__PURE__*/_jsxs(Card, {
30
+ style: {
31
+ display: "flex",
32
+ justifyContent: "center",
33
+ alignItems: "center",
34
+ width: "100%",
35
+ padding: "8px",
36
+ boxShadow: "none",
37
+ border: "1px solid #eae9e9",
38
+ backgroundColor: "#F7F7F7"
39
+ },
40
+ children: [/*#__PURE__*/_jsx(CardMedia, {
41
+ sx: {
42
+ "& svg": {
43
+ width: 32,
44
+ height: 32,
45
+ "&.pdf-i": {
46
+ fill: "#e5252a"
47
+ },
48
+ "&.doc-i": {
49
+ fill: "#0263d1"
50
+ }
51
+ }
52
+ },
53
+ children: type === "pdf" ? /*#__PURE__*/_jsx(PictureAsPdfIcon, {
54
+ className: "pdf-i"
55
+ }) : /*#__PURE__*/_jsx(TextSnippetIcon, {
56
+ className: "doc-i"
57
+ })
58
+ }), /*#__PURE__*/_jsxs(CardContent, {
59
+ component: "a",
60
+ href: url,
61
+ target: "_blank",
62
+ style: {
63
+ display: "flex",
64
+ justifyContent: "center",
65
+ alignItems: "start",
66
+ padding: "8px",
67
+ textDecoration: "none",
68
+ flexDirection: "column",
69
+ color: "#0F172A"
70
+ },
71
+ children: [/*#__PURE__*/_jsx(Typography, {
72
+ style: {
73
+ fontWeight: "bold",
74
+ color: "#0F172A",
75
+ fontSize: "14px"
76
+ },
77
+ component: "div",
78
+ children: fileName
79
+ }), /*#__PURE__*/_jsx(Typography, {
80
+ style: {
81
+ fontWeight: "normal",
82
+ color: "#64748b",
83
+ fontSize: "11px"
84
+ },
85
+ component: "div",
86
+ children: formatDate(date)
87
+ })]
88
+ })]
89
+ }), /*#__PURE__*/_jsx("span", {
90
+ contentEditable: false,
91
+ children: children
92
+ })]
93
+ });
94
+ };
95
+ export default Attachments;
@@ -0,0 +1,46 @@
1
+ import React, { useState } from "react";
2
+ import { useSlateStatic } from "slate-react";
3
+ import ToolbarIcon from "../../common/ToolbarIcon";
4
+ import Icon from "../../common/Icon";
5
+ import ImageSelector from "../../common/ImageSelector/ImageSelector";
6
+ import { insertAttachments } from "../../utils/attachments";
7
+ import { jsx as _jsx } from "react/jsx-runtime";
8
+ import { Fragment as _Fragment } from "react/jsx-runtime";
9
+ import { jsxs as _jsxs } from "react/jsx-runtime";
10
+ const AttachmentsButton = props => {
11
+ const editor = useSlateStatic();
12
+ const {
13
+ customProps,
14
+ icoBtnType
15
+ } = props;
16
+ const [open, SetOpen] = useState(false);
17
+ const handleClick = () => {
18
+ SetOpen(true);
19
+ };
20
+ const onSelectImage = url => {
21
+ insertAttachments(editor, {
22
+ url
23
+ });
24
+ handleClose();
25
+ };
26
+ const handleClose = () => {
27
+ SetOpen(false);
28
+ };
29
+ return /*#__PURE__*/_jsxs(_Fragment, {
30
+ children: [/*#__PURE__*/_jsx(ToolbarIcon, {
31
+ title: "Doc Upload",
32
+ onClick: handleClick,
33
+ icon: /*#__PURE__*/_jsx(Icon, {
34
+ icon: "docsUpload"
35
+ }),
36
+ icoBtnType: icoBtnType
37
+ }), /*#__PURE__*/_jsx(ImageSelector, {
38
+ open: open,
39
+ onClose: handleClose,
40
+ customProps: customProps,
41
+ onSelectImage: onSelectImage,
42
+ title: "Document"
43
+ })]
44
+ });
45
+ };
46
+ export default AttachmentsButton;
@@ -113,8 +113,7 @@ const Carousel = props => {
113
113
  className: "sliderBg",
114
114
  style: {
115
115
  backgroundColor: "transparent",
116
- position: "relative",
117
- minHeight: "300px"
116
+ position: "relative"
118
117
  },
119
118
  contentEditable: edit,
120
119
  onMouseOver: onMouseOver,
@@ -135,7 +134,7 @@ const Carousel = props => {
135
134
  }, i);
136
135
  })
137
136
  })
138
- }, `slider_${children.length}`), !readOnly && /*#__PURE__*/_jsx(ToolBar, {})]
137
+ }, `slider_${children.length}_${new Date().getTime()}`), !readOnly && /*#__PURE__*/_jsx(ToolBar, {})]
139
138
  });
140
139
  };
141
140
  export default Carousel;
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { Transforms } from "slate";
2
+ import { Node, Transforms } from "slate";
3
3
  import { useSlateStatic, ReactEditor } from "slate-react";
4
4
  import { Tooltip, IconButton } from "@mui/material";
5
5
  import DeleteIcon from "@mui/icons-material/Delete";
@@ -16,13 +16,17 @@ const CarouselItem = props => {
16
16
  readOnly
17
17
  } = customProps;
18
18
  const editor = useSlateStatic();
19
- const path = ReactEditor.findPath(editor, element);
20
19
  const onMenuClick = val => () => {
21
20
  switch (val) {
22
21
  case "delete":
23
- Transforms.removeNodes(editor, {
24
- at: [...path]
25
- });
22
+ const path = ReactEditor.findPath(editor, element);
23
+ const parentSlide = Node.get(editor, [path[0]]);
24
+ const canDelete = parentSlide?.children?.length > 1;
25
+ if (canDelete) {
26
+ Transforms.removeNodes(editor, {
27
+ at: [...path]
28
+ });
29
+ }
26
30
  return;
27
31
  default:
28
32
  return;
@@ -32,8 +36,10 @@ const CarouselItem = props => {
32
36
  return !readOnly ? /*#__PURE__*/_jsx("div", {
33
37
  className: "element-toolbar hr",
34
38
  style: {
35
- top: "0px"
39
+ top: "0px",
40
+ right: "28px"
36
41
  },
42
+ contentEditable: false,
37
43
  children: /*#__PURE__*/_jsx(Tooltip, {
38
44
  title: "Delete Slide",
39
45
  arrow: true,
@@ -50,7 +56,10 @@ const CarouselItem = props => {
50
56
  children: /*#__PURE__*/_jsxs("div", {
51
57
  className: "carousel-item-inner",
52
58
  style: {
53
- minHeight: "50px"
59
+ minHeight: "50px",
60
+ display: "block",
61
+ justifyContent: "center",
62
+ alignItems: "center"
54
63
  },
55
64
  children: [children, /*#__PURE__*/_jsx(Toolbar, {})]
56
65
  })
@@ -19,8 +19,8 @@ const ColorPickerStyles = () => ({
19
19
  position: "absolute",
20
20
  top: "-4px",
21
21
  left: "-4px",
22
- width: "calc(100% + 4px)",
23
- height: "calc(100% + 4px)",
22
+ width: "calc(100% + 8px)",
23
+ height: "calc(100% + 8px)",
24
24
  border: "2px solid #2563EB",
25
25
  borderRadius: "50%"
26
26
  }
@@ -123,7 +123,7 @@ const Image = ({
123
123
  onClick: onSettings,
124
124
  contentEditable: false,
125
125
  children: [/*#__PURE__*/_jsx(Icon, {
126
- icon: "video"
126
+ icon: "image"
127
127
  }), "Add Image"]
128
128
  }) : /*#__PURE__*/_jsx("img", {
129
129
  style: {
@@ -0,0 +1,60 @@
1
+ const carousel_item = itemNo => ({
2
+ type: "paragraph",
3
+ children: [{
4
+ type: "grid",
5
+ grid: "container",
6
+ children: [{
7
+ type: "grid-item",
8
+ grid: 12,
9
+ children: [{
10
+ type: "alignLeft",
11
+ children: [{
12
+ type: "paragraph",
13
+ children: [{
14
+ text: `Slide ${itemNo}`,
15
+ fontSize: "huge",
16
+ fontFamily: "PoppinsBold"
17
+ }]
18
+ }, {
19
+ type: "paragraph",
20
+ children: [{
21
+ fontSize: "16px",
22
+ fontFamily: "PoppinsRegular",
23
+ text: ""
24
+ }]
25
+ }, {
26
+ type: "paragraph",
27
+ children: [{
28
+ fontSize: "16px",
29
+ fontFamily: "PoppinsRegular",
30
+ text: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."
31
+ }]
32
+ }]
33
+ }],
34
+ bgColor: "rgba(185, 179, 179, 0)",
35
+ lockSpacing: true,
36
+ bannerSpacing: {
37
+ top: 16,
38
+ left: 16,
39
+ right: 16,
40
+ bottom: 16,
41
+ undefined: 16
42
+ },
43
+ alignment: {
44
+ horizantal: "center"
45
+ }
46
+ }],
47
+ alignment: {
48
+ flexDirection: "row"
49
+ },
50
+ lockSpacing: true,
51
+ bannerSpacing: {
52
+ top: "16",
53
+ left: "16",
54
+ right: "16",
55
+ bottom: "16"
56
+ },
57
+ bgColor: "rgb(102, 102, 102)"
58
+ }]
59
+ });
60
+ export default carousel_item;
@@ -8,6 +8,7 @@ import LinkOffIcon from "@mui/icons-material/LinkOff";
8
8
  import { removeLink } from "../../utils/link";
9
9
  import LinkPopup from "./LinkPopup";
10
10
  import "./styles.css";
11
+ import { absoluteLink } from "../../utils/helper";
11
12
  import { jsx as _jsx } from "react/jsx-runtime";
12
13
  import { jsxs as _jsxs } from "react/jsx-runtime";
13
14
  const Link = ({
@@ -25,6 +26,7 @@ const Link = ({
25
26
  showInNewTab: true
26
27
  });
27
28
  const path = ReactEditor.findPath(editor, element);
29
+ const absLink = absoluteLink(element.href);
28
30
  const updateLink = () => {
29
31
  Transforms.setNodes(editor, {
30
32
  href: linkData?.url,
@@ -71,8 +73,8 @@ const Link = ({
71
73
  children: [/*#__PURE__*/_jsx(Tooltip, {
72
74
  title: "Open",
73
75
  children: /*#__PURE__*/_jsx(IconButton, {
74
- href: element.href,
75
- target: element.target,
76
+ href: absLink,
77
+ target: "_blank",
76
78
  children: /*#__PURE__*/_jsx(OpenInNewIcon, {})
77
79
  })
78
80
  }), /*#__PURE__*/_jsx(Tooltip, {
@@ -93,7 +95,7 @@ const Link = ({
93
95
  return /*#__PURE__*/_jsxs("div", {
94
96
  className: "link",
95
97
  children: [/*#__PURE__*/_jsx("a", {
96
- href: element.href,
98
+ href: absLink,
97
99
  ...attributes,
98
100
  ...element.attr,
99
101
  target: element.target,
@@ -3,6 +3,7 @@ import { useSlateStatic, useSelected, ReactEditor } from "slate-react";
3
3
  import { Box } from "@mui/material";
4
4
  import { getPageSettings } from "../utils/pageSettings";
5
5
  import { invertColor } from "../helper";
6
+ import { isTextSelected } from "../utils/helper";
6
7
  import { jsx as _jsx } from "react/jsx-runtime";
7
8
  import { jsxs as _jsxs } from "react/jsx-runtime";
8
9
  const SimpleTextStyle = ({
@@ -68,8 +69,9 @@ const SimpleText = props => {
68
69
  });
69
70
  const selected = useSelected();
70
71
  const path = ReactEditor.findPath(editor, element);
71
- const showPlaceHolder = !readOnly && path.length === 1 && isEmpty && selected;
72
+ const showPlaceHolder = !readOnly && path.length === 1 && isEmpty;
72
73
  const isEmptyEditor = !readOnly && isEmpty && editor.children.length === 1 && !selected;
74
+ const opacity = !isTextSelected(editor?.selection);
73
75
  return /*#__PURE__*/_jsxs(Box, {
74
76
  ...element.attr,
75
77
  ...attributes,
@@ -77,7 +79,7 @@ const SimpleText = props => {
77
79
  sx: classes.root,
78
80
  children: [children, /*#__PURE__*/_jsx("span", {
79
81
  className: "placeholder-simple-text",
80
- children: isEmptyEditor ? editorPlaceholder || "Write Something..." : showPlaceHolder ? "Type / to browse elements" : ""
82
+ children: isEmptyEditor ? editorPlaceholder || "Write Something..." : showPlaceHolder ? opacity && selected ? "Type / to browse elements" : "" : ""
81
83
  })]
82
84
  });
83
85
  };
@@ -40,7 +40,8 @@ const TableCell = props => {
40
40
  const {
41
41
  bgColor,
42
42
  borderColor,
43
- entireBgColor
43
+ entireBgColor,
44
+ entireBorderColor
44
45
  } = element;
45
46
  const [parentDOM, setParentDOM] = useState(null);
46
47
  const editor = useSlateStatic();
@@ -107,7 +108,7 @@ const TableCell = props => {
107
108
  const sizeProps = isHeader ? {
108
109
  width: size?.width || tableSize?.cellWidth
109
110
  } : {};
110
- const cellBorderColor = borderColor || rowProps?.borderColor || parentProps?.borderColor;
111
+ const cellBorderColor = borderColor || rowProps?.borderColor || parentProps?.borderColor || entireBorderColor;
111
112
  return /*#__PURE__*/_jsxs("td", {
112
113
  ...element.attr,
113
114
  ...attributes,
@@ -1,12 +1,15 @@
1
1
  import React, { useCallback, useRef, useState } from "react";
2
2
  import { createEditor } from "slate";
3
- import { Slate, Editable, withReact } from "slate-react";
3
+ import { Slate, Editable } from "slate-react";
4
4
  import { getBlock, getMarked } from "./utils/SlateUtilityFunctions";
5
5
  import { commands, mentionsEvent } from "./utils/events";
6
6
  import useMentions from "./hooks/useMentions";
7
7
  import Shorthands from "./common/Shorthands";
8
- // import withCommon from "./hooks/withCommon";
8
+ import BasicToolbar from "./Toolbar/Basic";
9
+ import withCommon from "./hooks/withCommon";
10
+ import "./Editor.css";
9
11
  import { jsx as _jsx } from "react/jsx-runtime";
12
+ import { jsxs as _jsxs } from "react/jsx-runtime";
10
13
  const initialValue = [{
11
14
  type: "paragraph",
12
15
  children: [{
@@ -21,6 +24,7 @@ const MiniEditor = props => {
21
24
  // editor: collaborativeEditor,
22
25
  readOnly,
23
26
  miniEditorPlaceholder,
27
+ toolbars,
24
28
  otherProps
25
29
  } = props;
26
30
  const {
@@ -28,13 +32,9 @@ const MiniEditor = props => {
28
32
  // needLayout = true,
29
33
  } = otherProps || {};
30
34
  const mentionsRef = useRef();
31
- const [editor] = useState(() => withReact(createEditor()));
32
-
33
- // const editor = useMemo(() => {
34
- // if (collaborativeEditor) return collaborativeEditor;
35
- // return withCommon(createEditor(), { needLayout });
36
- // }, [collaborativeEditor]);
37
-
35
+ const [editor] = useState(() => withCommon(createEditor(), {
36
+ needLayout: false
37
+ }));
38
38
  const isReadOnly = readOnly === "readonly";
39
39
  const customProps = {
40
40
  ...(otherProps || {}),
@@ -102,14 +102,16 @@ const MiniEditor = props => {
102
102
  customProps: customProps
103
103
  });
104
104
  }, []);
105
- return /*#__PURE__*/_jsx(Slate, {
105
+ return /*#__PURE__*/_jsxs(Slate, {
106
106
  editor: editor,
107
107
  initialValue: initialValue,
108
- children: /*#__PURE__*/_jsx(Editable, {
108
+ children: [/*#__PURE__*/_jsx(BasicToolbar, {
109
+ toolbars: toolbars || []
110
+ }), /*#__PURE__*/_jsx(Editable, {
109
111
  renderElement: renderElement,
110
112
  renderLeaf: renderLeaf,
111
113
  onKeyDown: onKeyDown
112
- })
114
+ })]
113
115
  });
114
116
  };
115
117
  MiniEditor.displayName = "MiniEditor";
@@ -0,0 +1,53 @@
1
+ import React, { useState } from "react";
2
+ import { useSlateStatic } from "slate-react";
3
+ import { Box, Tooltip } from "@mui/material";
4
+ import { toolbarGroups } from "../toolbarGroups";
5
+ import { MarkButton } from "../FormatTools";
6
+ import LinkButton from "../../Elements/Link/LinkButton";
7
+ import { addMarkData, isBlockActive } from "../../utils/SlateUtilityFunctions";
8
+ import ColorPickerButton from "../../common/ColorPickerButton";
9
+ import { colors } from "../../Elements/Color Picker/defaultColors";
10
+ import { jsx as _jsx } from "react/jsx-runtime";
11
+ import { jsxs as _jsxs } from "react/jsx-runtime";
12
+ const allTools = toolbarGroups.flat();
13
+ const BasicToolbar = ({
14
+ toolbars
15
+ }) => {
16
+ const editor = useSlateStatic();
17
+
18
+ // state
19
+ const [activeColor, setActiveColor] = useState("#000000");
20
+ const fontStyle = allTools.filter(f => f.basic);
21
+ const link = allTools.find(f => f.format?.indexOf("link") >= 0);
22
+ const handleTextColor = color => {
23
+ setActiveColor(color);
24
+ addMarkData(editor, {
25
+ format: 'color',
26
+ value: color
27
+ });
28
+ };
29
+ return /*#__PURE__*/_jsxs(Box, {
30
+ component: 'div',
31
+ className: "basic-toolbar",
32
+ children: [fontStyle?.map((m, i) => {
33
+ return /*#__PURE__*/_jsx(MarkButton, {
34
+ editor: editor,
35
+ ...m
36
+ }, `pptool_mark_${i}_${m.id}`);
37
+ }), /*#__PURE__*/_jsx(LinkButton, {
38
+ active: isBlockActive(editor, link.format),
39
+ editor: editor
40
+ }, link.id), /*#__PURE__*/_jsx(Tooltip, {
41
+ arrow: true,
42
+ title: "Current Color",
43
+ children: /*#__PURE__*/_jsx(ColorPickerButton, {
44
+ value: activeColor || "#0000",
45
+ onSave: color => {
46
+ handleTextColor(color);
47
+ },
48
+ defaultColors: colors
49
+ })
50
+ })]
51
+ });
52
+ };
53
+ export default BasicToolbar;
@@ -27,6 +27,7 @@ import InlineIconButton from "../Elements/InlineIcon/InlineIconButton";
27
27
  import EmojiButton from "../Elements/Emoji/EmojiButton.js";
28
28
  import "./styles.css";
29
29
  import TopBannerButton from "../Elements/TopBanner/TopBannerButton.js";
30
+ import AttachmentsButton from "../Elements/Attachments/AttachmentsButton";
30
31
  import { jsx as _jsx } from "react/jsx-runtime";
31
32
  import { jsxs as _jsxs } from "react/jsx-runtime";
32
33
  export const RenderToolbarIcon = props => {
@@ -193,6 +194,12 @@ export const RenderToolbarIcon = props => {
193
194
  customProps: customProps,
194
195
  icoBtnType: icoBtnType
195
196
  }, element.id);
197
+ case "docsUpload":
198
+ return /*#__PURE__*/_jsx(AttachmentsButton, {
199
+ editor: editor,
200
+ customProps: customProps,
201
+ icoBtnType: icoBtnType
202
+ }, element.id);
196
203
  default:
197
204
  return null;
198
205
  }
@@ -45,12 +45,14 @@ export const toolbarGroups = [[{
45
45
  id: 3,
46
46
  format: "bold",
47
47
  type: "mark",
48
- title: "Bold"
48
+ title: "Bold",
49
+ basic: true
49
50
  }, {
50
51
  id: 4,
51
52
  format: "italic",
52
53
  type: "mark",
53
- title: "Italic"
54
+ title: "Italic",
55
+ basic: true
54
56
  }, {
55
57
  id: 5,
56
58
  format: "underline",
@@ -152,6 +154,11 @@ export const toolbarGroups = [[{
152
154
  format: "video",
153
155
  type: "embed",
154
156
  group: "elements"
157
+ }, {
158
+ id: 46,
159
+ format: "docsUpload",
160
+ type: "docsUpload",
161
+ group: "elements"
155
162
  }, {
156
163
  id: 44,
157
164
  lbT: "embed",
@@ -1,14 +1,15 @@
1
1
  import React, { useState } from "react";
2
2
  import { Grid, Button, Popover } from "@mui/material";
3
- // import ColorPicker from "react-best-gradient-color-picker";
4
3
  import ColorPickerTool from "react-gcolor-picker";
4
+ import { colors } from "../Elements/Color Picker/defaultColors";
5
5
  import { jsx as _jsx } from "react/jsx-runtime";
6
6
  import { jsxs as _jsxs } from "react/jsx-runtime";
7
7
  import { Fragment as _Fragment } from "react/jsx-runtime";
8
8
  const ColorPickerButton = props => {
9
9
  const {
10
10
  value,
11
- onSave
11
+ onSave,
12
+ defaultColors = []
12
13
  } = props;
13
14
  const [anchorEl, setAnchorEl] = useState(null);
14
15
  const [color, setColor] = useState(value);
@@ -47,7 +48,7 @@ const ColorPickerButton = props => {
47
48
  onClose: handleClose,
48
49
  sx: {
49
50
  "& .MuiPaper-root": {
50
- overflow: "hidden"
51
+ overflow: "auto"
51
52
  }
52
53
  },
53
54
  children: /*#__PURE__*/_jsx(Grid, {
@@ -56,10 +57,13 @@ const ColorPickerButton = props => {
56
57
  children: /*#__PURE__*/_jsxs(Grid, {
57
58
  item: true,
58
59
  xs: 12,
59
- children: [/*#__PURE__*/_jsx(ColorPickerTool, {
60
- gradient: true,
61
- value: color,
62
- onChange: setColor
60
+ children: [/*#__PURE__*/_jsx("div", {
61
+ children: /*#__PURE__*/_jsx(ColorPickerTool, {
62
+ gradient: true,
63
+ value: color,
64
+ onChange: setColor,
65
+ defaultColors: defaultColors || []
66
+ })
63
67
  }), /*#__PURE__*/_jsxs("div", {
64
68
  style: {
65
69
  display: "flex",
@@ -81,4 +85,7 @@ const ColorPickerButton = props => {
81
85
  })]
82
86
  });
83
87
  };
88
+ ColorPickerButton.defaultProps = {
89
+ defaultColors: [...colors]
90
+ };
84
91
  export default ColorPickerButton;
@@ -7,7 +7,7 @@ import { AiFillEdit, AiOutlineInsertRowBelow, AiOutlineInsertRowRight, AiOutline
7
7
  import { SiLatex } from "react-icons/si";
8
8
  import { RiDeleteColumn, RiDeleteRow } from "react-icons/ri";
9
9
  import { IoIosImage, IoMdArrowDroprightCircle, IoMdArrowDropdownCircle } from "react-icons/io";
10
- import { GridIcon, AccordionIcon, SignatureIcon, ButtonIcon, Carousal, FormIcon, BoldIcon, FontFamilyIcon, FontSizeIcon, ImageIcon, ItalicIcon, LinkIcon, StrikethroughIcon, TableIcon, UnderLineIcon, VideoIcon, CheckboxIcon, AppHeader, MoreHorizontal, UploadImage } from "./iconslist";
10
+ import { GridIcon, AccordionIcon, SignatureIcon, ButtonIcon, Carousal, FormIcon, BoldIcon, FontFamilyIcon, FontSizeIcon, ImageIcon, ItalicIcon, LinkIcon, StrikethroughIcon, TableIcon, UnderLineIcon, VideoIcon, CheckboxIcon, AppHeader, MoreHorizontal, UploadImage, DocsUpload } from "./iconslist";
11
11
  import { jsx as _jsx } from "react/jsx-runtime";
12
12
  import { jsxs as _jsxs } from "react/jsx-runtime";
13
13
  const iconList = {
@@ -182,7 +182,8 @@ const iconList = {
182
182
  size: 20
183
183
  }),
184
184
  appHeader: /*#__PURE__*/_jsx(AppHeader, {}),
185
- moreHorizantal: /*#__PURE__*/_jsx(MoreHorizontal, {})
185
+ moreHorizantal: /*#__PURE__*/_jsx(MoreHorizontal, {}),
186
+ docsUpload: /*#__PURE__*/_jsx(DocsUpload, {})
186
187
  };
187
188
  const Icon = props => {
188
189
  const {
@@ -13,6 +13,12 @@ const IMAGE_SLECTOR_OPTIONS = {
13
13
  choose: ChooseAssets,
14
14
  addLink: AddLink
15
15
  };
16
+ const TAB_SHOW = {
17
+ Image: ["upload", "choose", "addLink"],
18
+ Video: ["addLink"],
19
+ Embed: ["addLink"],
20
+ Document: ["addLink", "upload"]
21
+ };
16
22
  const ImageSelector = props => {
17
23
  const classes = ImageSelectorStyles();
18
24
  const {
@@ -25,6 +31,7 @@ const ImageSelector = props => {
25
31
  const [tabValue, setTabValue] = useState(title === "Image" ? "choose" : "addLink");
26
32
  const [image, setImage] = useState(value || "");
27
33
  const handleTabChange = (e, newValue) => {
34
+ setImage("");
28
35
  setTabValue(newValue);
29
36
  };
30
37
  const onUploaded = url => {
@@ -60,7 +67,7 @@ const ImageSelector = props => {
60
67
  orientation: "vertical",
61
68
  value: tabValue,
62
69
  children: [/*#__PURE__*/_jsx(Tab, {
63
- className: `${isActive("upload")} ${title !== "Image" ? "hidden" : ""}`,
70
+ className: `${isActive("upload")} ${TAB_SHOW[title].indexOf("upload") === -1 ? "hidden" : ""}`,
64
71
  sx: classes.tab,
65
72
  icon: /*#__PURE__*/_jsx(Icon, {
66
73
  icon: "fileUpload"
@@ -69,7 +76,7 @@ const ImageSelector = props => {
69
76
  value: "upload",
70
77
  label: "Upload Media"
71
78
  }), /*#__PURE__*/_jsx(Tab, {
72
- className: `${isActive("choose")} ${title !== "Image" ? "hidden" : ""}`,
79
+ className: `${isActive("choose")} ${TAB_SHOW[title].indexOf("choose") === -1 ? "hidden" : ""}`,
73
80
  sx: classes.tab,
74
81
  icon: /*#__PURE__*/_jsx(Icon, {
75
82
  icon: "media"
@@ -78,7 +85,7 @@ const ImageSelector = props => {
78
85
  value: "choose",
79
86
  label: "Choose Media"
80
87
  }), /*#__PURE__*/_jsx(Tab, {
81
- className: `${isActive("addLink")}`,
88
+ className: `${isActive("addLink")} ${TAB_SHOW[title].indexOf("addLink") === -1 ? "hidden" : ""}`,
82
89
  sx: classes.tab,
83
90
  icon: /*#__PURE__*/_jsx(Icon, {
84
91
  icon: "link"
@@ -109,8 +116,9 @@ const ImageSelector = props => {
109
116
  sx: classes.closeBtn,
110
117
  children: "Cancel"
111
118
  }), /*#__PURE__*/_jsx(Button, {
119
+ disabled: !image,
112
120
  onClick: onSave,
113
- className: "primaryBtn",
121
+ className: `primaryBtn ${!image ? "disabled" : ""}`,
114
122
  sx: classes.saveBtn,
115
123
  children: "Save"
116
124
  })]
@@ -8,7 +8,8 @@ const Upload = props => {
8
8
  value,
9
9
  onUploaded,
10
10
  customProps,
11
- disableUpload = false
11
+ disableUpload = false,
12
+ title
12
13
  } = props;
13
14
  const onDone = img => {
14
15
  onUploaded(img);
@@ -28,7 +29,8 @@ const Upload = props => {
28
29
  },
29
30
  customProps: customProps,
30
31
  onUploaded: onDone,
31
- disableUpload: disableUpload
32
+ disableUpload: disableUpload,
33
+ title: title
32
34
  })
33
35
  });
34
36
  };
@@ -101,7 +101,7 @@ const ELEMENTS_LIST = [{
101
101
  icon: /*#__PURE__*/_jsx(Icon, {
102
102
  icon: "embed"
103
103
  }),
104
- onInsert: editor => insertDefaultEmbed(editor, "video", "https://calendly.com/agenciflow/1-1-agency-scale-clone?hide_event_type_details=1&month=2024-03")
104
+ onInsert: editor => insertDefaultEmbed(editor, "video", "")
105
105
  }, {
106
106
  name: "Emoji",
107
107
  group: "Elements",
@@ -1,24 +1,28 @@
1
1
  import React, { useState } from "react";
2
- import { Grid, Button } from "@mui/material";
2
+ import { Grid, Button, Typography } from "@mui/material";
3
3
  import { convertBase64 } from "../utils/helper";
4
4
  import { uploadFile } from "../service/fileupload";
5
5
  import Icon from "./Icon";
6
6
  import UploadStyles from "../common/ImageSelector/UploadStyles";
7
7
  import { jsx as _jsx } from "react/jsx-runtime";
8
+ import { Fragment as _Fragment } from "react/jsx-runtime";
8
9
  import { jsxs as _jsxs } from "react/jsx-runtime";
9
10
  const Uploader = props => {
10
11
  const {
11
12
  value,
12
13
  onUploaded,
13
- customProps
14
+ customProps,
15
+ title
14
16
  } = props;
15
17
  const classes = UploadStyles();
16
18
  const [base64, setBase64] = useState(value?.url);
19
+ const [fileName, setFileName] = useState("");
17
20
  const [uploading, setUploading] = useState(false);
18
21
  const handleChange = async e => {
19
22
  const uFile = e.target.files[0];
20
23
  const strImage = await convertBase64(uFile);
21
24
  setBase64(strImage);
25
+ setFileName(uFile?.name);
22
26
  doUpload(strImage, e.target.files[0]);
23
27
  };
24
28
  const doUpload = async (strImage, file) => {
@@ -38,6 +42,44 @@ const Uploader = props => {
38
42
  setBase64(null);
39
43
  onUploaded("none");
40
44
  };
45
+ const getBackground = () => {
46
+ switch (title) {
47
+ case "Document":
48
+ return {
49
+ backgroundImage: `url()`
50
+ };
51
+ default:
52
+ return {
53
+ backgroundImage: base64 ? `url(${base64})` : "none"
54
+ };
55
+ }
56
+ };
57
+ const renderThumb = () => {
58
+ switch (title) {
59
+ case "Document":
60
+ return /*#__PURE__*/_jsxs(_Fragment, {
61
+ children: [/*#__PURE__*/_jsx(Typography, {
62
+ style: {
63
+ padding: "8px",
64
+ fontSize: "12px",
65
+ color: "#2563eb",
66
+ textAlign: "center"
67
+ },
68
+ children: fileName
69
+ }), /*#__PURE__*/_jsx(Grid, {
70
+ className: "removeImageText",
71
+ onClick: onRemoveBG,
72
+ children: "REMOVE"
73
+ })]
74
+ });
75
+ default:
76
+ return /*#__PURE__*/_jsx(Grid, {
77
+ className: "removeImageText",
78
+ onClick: onRemoveBG,
79
+ children: "REMOVE"
80
+ });
81
+ }
82
+ };
41
83
  return /*#__PURE__*/_jsxs(Grid, {
42
84
  container: true,
43
85
  sx: classes.uploadContainer,
@@ -50,16 +92,12 @@ const Uploader = props => {
50
92
  xs: 12,
51
93
  className: "btn--wrpr",
52
94
  style: {
53
- backgroundImage: base64 ? `url(${base64})` : "none"
95
+ ...getBackground()
54
96
  },
55
97
  sx: classes.uploadField,
56
98
  children: !uploading ? /*#__PURE__*/_jsx(Grid, {
57
99
  className: "uploadImageSection",
58
- children: base64 ? /*#__PURE__*/_jsx(Grid, {
59
- className: "removeImageText",
60
- onClick: onRemoveBG,
61
- children: "REMOVE"
62
- }) : /*#__PURE__*/_jsx(Grid, {
100
+ children: base64 ? renderThumb() : /*#__PURE__*/_jsx(Grid, {
63
101
  className: "uploadImageText",
64
102
  children: /*#__PURE__*/_jsxs(Button, {
65
103
  component: "label",
@@ -77,11 +115,11 @@ const Uploader = props => {
77
115
  onChange: handleChange
78
116
  }), /*#__PURE__*/_jsx(Icon, {
79
117
  icon: "fileUpload"
80
- }), /*#__PURE__*/_jsx("span", {
118
+ }), /*#__PURE__*/_jsxs("span", {
81
119
  style: {
82
120
  paddingLeft: "8px"
83
121
  },
84
- children: "upload your image"
122
+ children: ["upload ", title || "image"]
85
123
  })]
86
124
  })
87
125
  })
@@ -765,32 +765,32 @@ export const DocsUpload = props => /*#__PURE__*/_jsxs("svg", {
765
765
  fill: "none",
766
766
  children: [/*#__PURE__*/_jsx("path", {
767
767
  d: "M6.14453 0.855469V3.14118C6.14453 3.29274 6.20474 3.43808 6.3119 3.54524C6.41906 3.65241 6.56441 3.71261 6.71596 3.71261H9.00167",
768
- stroke: "#828282",
769
- strokeWidth: "0.7",
768
+ stroke: "#64748B",
769
+ strokeWidth: "1",
770
770
  strokeLinecap: "round",
771
771
  strokeLinejoin: "round"
772
772
  }), /*#__PURE__*/_jsx("path", {
773
773
  d: "M7.85714 11.1412H2.14286C1.83975 11.1412 1.54906 11.0208 1.33474 10.8064C1.12041 10.5921 1 10.3014 1 9.99833V1.99833C1 1.69522 1.12041 1.40453 1.33474 1.1902C1.54906 0.975877 1.83975 0.855469 2.14286 0.855469H6.14286L9 3.71261V9.99833C9 10.3014 8.87959 10.5921 8.66527 10.8064C8.45094 11.0208 8.16025 11.1412 7.85714 11.1412Z",
774
- stroke: "#828282",
775
- strokeWidth: "0.7",
774
+ stroke: "#64748B",
775
+ strokeWidth: "1",
776
776
  strokeLinecap: "round",
777
777
  strokeLinejoin: "round"
778
778
  }), /*#__PURE__*/_jsx("path", {
779
779
  d: "M3.28516 4.28516H3.85658",
780
- stroke: "#828282",
781
- strokeWidth: "0.7",
780
+ stroke: "#64748B",
781
+ strokeWidth: "1",
782
782
  strokeLinecap: "round",
783
783
  strokeLinejoin: "round"
784
784
  }), /*#__PURE__*/_jsx("path", {
785
785
  d: "M3.28516 6.57031H6.71373",
786
- stroke: "#828282",
787
- strokeWidth: "0.7",
786
+ stroke: "#64748B",
787
+ strokeWidth: "1",
788
788
  strokeLinecap: "round",
789
789
  strokeLinejoin: "round"
790
790
  }), /*#__PURE__*/_jsx("path", {
791
791
  d: "M3.28516 8.85547H6.71373",
792
- stroke: "#828282",
793
- strokeWidth: "0.7",
792
+ stroke: "#64748B",
793
+ strokeWidth: "1",
794
794
  strokeLinecap: "round",
795
795
  strokeLinejoin: "round"
796
796
  })]
@@ -76,8 +76,11 @@ export function getEmbedURL(element) {
76
76
  }
77
77
  export const isEmptyTextNode = element => {
78
78
  try {
79
- const showPlaceholder = element?.children?.filter(f => HIDE_PLACHOLDERS.indexOf(f.type) > -1).length === 0;
80
- return Node.string(element)?.length === 0 && showPlaceholder;
79
+ if (element) {
80
+ const showPlaceholder = element?.children?.filter(f => HIDE_PLACHOLDERS.indexOf(f.type) > -1).length === 0;
81
+ return Node.string(element)?.length === 0 && showPlaceholder;
82
+ }
83
+ return false;
81
84
  } catch (err) {
82
85
  console.log(err);
83
86
  return false;
@@ -3,7 +3,6 @@ export const uploadFile = async (formData, props) => {
3
3
  const response = await fetch(`${props.API_HOST}/general/notes/file_upload`, {
4
4
  method: "POST",
5
5
  headers: {
6
- // "Content-Type": "application/json",
7
6
  Authorization: `Bearer ${props.token}`
8
7
  },
9
8
  body: formData
@@ -33,6 +33,7 @@ import EmbedLink from "../Elements/Embed/link";
33
33
  import SimpleText from "../Elements/SimpleText";
34
34
  import CheckList from "../Elements/List/CheckList";
35
35
  import { isEmptyTextNode } from "../helper";
36
+ import Attachments from "../Elements/Attachments/Attachments";
36
37
  import { jsx as _jsx } from "react/jsx-runtime";
37
38
  const alignment = ["alignLeft", "alignRight", "alignCenter"];
38
39
  const list_types = ["orderedList", "unorderedList"];
@@ -472,6 +473,11 @@ export const getBlock = props => {
472
473
  return /*#__PURE__*/_jsx(EmbedLink, {
473
474
  ...props
474
475
  });
476
+ case "docs":
477
+ case "pdf":
478
+ return /*#__PURE__*/_jsx(Attachments, {
479
+ ...props
480
+ });
475
481
  default:
476
482
  return /*#__PURE__*/_jsx(SimpleText, {
477
483
  ...props,
@@ -481,7 +487,7 @@ export const getBlock = props => {
481
487
  };
482
488
  export const getQueryStrings = urlString => {
483
489
  try {
484
- if (urlString) {
490
+ if (urlString && urlString?.indexOf("/embed") === -1) {
485
491
  const newUrl = new URL(urlString);
486
492
  var youCode = newUrl.searchParams.get("v");
487
493
  if (!youCode) {
@@ -0,0 +1,34 @@
1
+ import { Transforms } from "slate";
2
+ import insertNewLine from "./insertNewLine";
3
+ const createAttachmentsNode = ({
4
+ type,
5
+ url
6
+ }) => {
7
+ return {
8
+ type: type || "docs",
9
+ url,
10
+ date: new Date().getTime(),
11
+ width: "100%",
12
+ height: "300px",
13
+ children: [{
14
+ text: ""
15
+ }]
16
+ };
17
+ };
18
+ export const insertAttachments = (editor, data) => {
19
+ try {
20
+ const {
21
+ url
22
+ } = data;
23
+ if (url) {
24
+ const attachmentsNode = createAttachmentsNode({
25
+ ...data,
26
+ type: url?.split(".").pop() === "pdf" ? "pdf" : "docs"
27
+ });
28
+ Transforms.insertNodes(editor, [attachmentsNode]);
29
+ insertNewLine(editor);
30
+ }
31
+ } catch (err) {
32
+ console.log(err);
33
+ }
34
+ };
@@ -1,13 +1,11 @@
1
1
  import { Transforms } from "slate";
2
+ import carousel_item from "../Elements/Grid/templates/carousel_item";
2
3
  export const carouselItem = (itemNo = "") => {
3
4
  return {
4
5
  type: "carousel-item",
5
6
  image: null,
6
7
  children: [{
7
- type: "paragraph",
8
- children: [{
9
- text: `Slide ${itemNo}`
10
- }]
8
+ ...carousel_item(itemNo)
11
9
  }]
12
10
  };
13
11
  };
@@ -41,4 +41,34 @@ export const gradientBorder = color => {
41
41
  borderColor: color || "transparent"
42
42
  };
43
43
  }
44
+ };
45
+ export const absoluteLink = url => {
46
+ try {
47
+ if (url?.indexOf("://") === -1) {
48
+ return `//${url}`;
49
+ }
50
+ return url;
51
+ } catch (err) {
52
+ console.log(err);
53
+ return url;
54
+ }
55
+ };
56
+ export const isTextSelected = selection => {
57
+ try {
58
+ const {
59
+ anchor,
60
+ focus
61
+ } = selection || {};
62
+ if (anchor && focus) {
63
+ if (JSON.stringify(anchor?.path) !== JSON.stringify(focus?.path)) {
64
+ return true;
65
+ }
66
+ return false;
67
+ } else {
68
+ return false;
69
+ }
70
+ } catch (err) {
71
+ console.log(err);
72
+ return false;
73
+ }
44
74
  };
@@ -1,5 +1,22 @@
1
- import { Node } from "slate";
1
+ import { renderToString } from "react-dom/server";
2
+ import { getBlock } from "./SlateUtilityFunctions";
2
3
  const serializeToHTML = nodes => {
3
- return nodes.map(n => Node.string(n)).join("\n");
4
+ try {
5
+ const htmlString = nodes.map(n => {
6
+ if (n) {
7
+ const props = {
8
+ element: n,
9
+ children: n?.children
10
+ };
11
+ const reactString = renderToString(getBlock(props));
12
+ return reactString;
13
+ } else {
14
+ return "";
15
+ }
16
+ });
17
+ console.log(htmlString);
18
+ } catch (err) {
19
+ console.log(err);
20
+ }
4
21
  };
5
22
  export default serializeToHTML;
@@ -219,19 +219,36 @@ export class TableUtil {
219
219
  });
220
220
 
221
221
  // cell bg entire
222
- if (cellProps?.entireBgColor) {
222
+ if (cellProps?.entireBgColor || tableProps?.borderColor || rowProps?.borderColor) {
223
223
  const {
224
224
  rows
225
225
  } = tableProps;
226
226
  for (let r = 0; r < rows; r++) {
227
227
  Transforms.setNodes(this.editor, {
228
- ...cellProps,
229
228
  entireBgColor: cellProps?.entireBgColor
230
229
  }, {
231
230
  at: [currentCellPath[0], r, currentCellPath[2]]
232
231
  });
233
232
  }
234
233
  }
234
+
235
+ // cell border all
236
+ if (tableProps?.borderColor || rowProps?.borderColor) {
237
+ const {
238
+ rows,
239
+ columns
240
+ } = tableProps;
241
+ for (let r = 0; r < rows; r++) {
242
+ for (let c = 0; c < columns; c++) {
243
+ Transforms.setNodes(this.editor, {
244
+ entireBorderColor: tableProps?.borderColor,
245
+ rowBorder: rowProps?.borderColor
246
+ }, {
247
+ at: [currentCellPath[0], r, c]
248
+ });
249
+ }
250
+ }
251
+ }
235
252
  }
236
253
  } catch (err) {
237
254
  console.log(err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flozy/editor",
3
- "version": "1.7.8",
3
+ "version": "1.8.0",
4
4
  "description": "An Editor for flozy app brain",
5
5
  "files": [
6
6
  "dist"