@flozy/editor 1.7.8 → 1.8.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.
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"