@flozy/editor 3.1.8 → 3.1.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -28,13 +28,11 @@ import DragAndDrop from "./common/DnD";
28
28
  import Section from "./common/Section";
29
29
  import "animate.css";
30
30
  import decorators from "./utils/Decorators";
31
- import useElement from "./utils/customHooks/useElement";
32
31
  import { getTRBLBreakPoints } from "./helper/theme";
33
32
  import { handleInsertLastElement, outsideEditorClickLabel } from "./utils/helper";
34
33
  import useWindowResize from "./hooks/useWindowResize";
35
34
  import { jsx as _jsx } from "react/jsx-runtime";
36
35
  import { jsxs as _jsxs } from "react/jsx-runtime";
37
- const PREVIEW_IMAGE_HIDE_CLASS = ["grid-container-toolbar", "grid-item-toolbar", "element-toolbar"];
38
36
  const Item = /*#__PURE__*/forwardRef(({
39
37
  children,
40
38
  ...props
@@ -166,19 +164,7 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
166
164
  const dom = needBackground ? editorWrapper?.current : editorWrapper?.current.getElementsByClassName("innert-editor-textbox")[0];
167
165
  const c = await getThumbnailImage(dom, {
168
166
  ...options,
169
- allowTaint: true,
170
- backgroundColor: null,
171
- proxy: "anonymous",
172
- useCORS: true,
173
- onclone: document => {
174
- // hide class
175
- for (let hidedeClass of PREVIEW_IMAGE_HIDE_CLASS) {
176
- for (let element of document.getElementsByClassName(hidedeClass)) {
177
- element.style.display = "none";
178
- }
179
- }
180
- return document;
181
- }
167
+ proxy: `${otherProps?.PAGES_API_HOST}/page/2canvas`
182
168
  });
183
169
  return c;
184
170
  };
@@ -372,7 +358,7 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
372
358
  }
373
359
  }, [readOnly, isTextSelected]);
374
360
  const handleFooterClick = () => {
375
- window.open('https://www.flozy.com', '_blank');
361
+ window.open("https://www.flozy.com", "_blank");
376
362
  };
377
363
  const editorWrapperStyle = useMemo(() => {
378
364
  const style = {
@@ -381,6 +367,7 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
381
367
  if (pageBgImage && pageBgImage !== "none") {
382
368
  style.backgroundImage = `url(${pageBgImage})`;
383
369
  style.backgroundSize = `cover`;
370
+ style.backgroundRepeat = "repeat";
384
371
  } else {
385
372
  style.background = pageColor || "";
386
373
  }
@@ -406,12 +393,13 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
406
393
  initialValue: value,
407
394
  onChange: handleEditorChange,
408
395
  children: [/*#__PURE__*/_jsx(DragAndDrop, {
409
- children: /*#__PURE__*/_jsx(Overlay, {
410
- children: /*#__PURE__*/_jsx(Box, {
396
+ children: /*#__PURE__*/_jsxs(Overlay, {
397
+ children: [/*#__PURE__*/_jsx(Box, {
411
398
  className: `${hasTopBanner() ? "has-topbanner" : ""} ${!pageColor ? "no-color" : ""} ${isScrolling ? "" : "hideScroll"} scrollable-content scrollSmooth`,
412
399
  sx: classes.slateWrapper,
413
400
  id: "slate-wrapper-scroll-container",
414
401
  style: editorWrapperStyle,
402
+ ref: editorWrapper,
415
403
  onClick: e => {
416
404
  handleInsertLastElement(e, editor);
417
405
  },
@@ -425,7 +413,6 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
425
413
  "data-info": outsideEditorClickLabel,
426
414
  children: /*#__PURE__*/_jsxs(Box, {
427
415
  component: "div",
428
- ref: editorWrapper,
429
416
  className: `editor-wrapper ${pageWidth === "fixed" ? "fixed" : "full"}`,
430
417
  sx: {
431
418
  backgroundColor: "transparent",
@@ -441,11 +428,7 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
441
428
  maxWidth: pageMaxWidth ? `${parseInt(pageMaxWidth)}px !important` : "auto"
442
429
  },
443
430
  "data-info": outsideEditorClickLabel,
444
- children: [!readOnly ? /*#__PURE__*/_jsx(PopupTool, {
445
- onDrawerOpen: onDrawerOpen,
446
- theme: theme,
447
- setIsTextSelected: setIsTextSelected
448
- }) : null, /*#__PURE__*/_jsx(Editable, {
431
+ children: [/*#__PURE__*/_jsx(Editable, {
449
432
  className: "innert-editor-textbox",
450
433
  readOnly: isReadOnly,
451
434
  renderElement: renderElement,
@@ -473,7 +456,7 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
473
456
  color: "rgb(100, 116, 139)",
474
457
  fontSize: "13px",
475
458
  paddingBottom: hideMiniToolBar ? "0px" : "12px",
476
- cursor: 'pointer'
459
+ cursor: "pointer"
477
460
  },
478
461
  align: "center",
479
462
  "data-info": outsideEditorClickLabel,
@@ -481,7 +464,11 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
481
464
  children: footer
482
465
  })]
483
466
  })
484
- })
467
+ }), !readOnly ? /*#__PURE__*/_jsx(PopupTool, {
468
+ onDrawerOpen: onDrawerOpen,
469
+ theme: theme,
470
+ setIsTextSelected: setIsTextSelected
471
+ }) : null]
485
472
  })
486
473
  }), htmlAction.showInput && /*#__PURE__*/_jsx(CodeToText, {
487
474
  ...htmlAction,
@@ -17,8 +17,10 @@ import Typography from "@mui/material/Typography";
17
17
  import Button from "@mui/material/Button";
18
18
  import AppHeaderPopup from "./AppHeaderPopup";
19
19
  import { getTRBLBreakPoints } from "../../helper/theme";
20
+ import { handleLinkType } from "../../utils/helper";
20
21
  import { jsx as _jsx } from "react/jsx-runtime";
21
22
  import { jsxs as _jsxs } from "react/jsx-runtime";
23
+ import { createElement as _createElement } from "react";
22
24
  import { Fragment as _Fragment } from "react/jsx-runtime";
23
25
  const drawerWidth = 240;
24
26
  function AppHeader(props) {
@@ -263,38 +265,40 @@ function AppHeader(props) {
263
265
  color: textColor
264
266
  },
265
267
  children: /*#__PURE__*/_jsx(MenuIcon, {})
266
- }) : null, !isDrawer ? menus.map((item, i) => /*#__PURE__*/_jsx(Button, {
267
- component: "a",
268
- href: item.url,
269
- sx: {
270
- position: "relative",
271
- fontFamily: fontFamily,
272
- textTransform: "none",
273
- fontSize: fontSize || "16px",
274
- color: textColor || "#FFF",
275
- background: bgColor || "none",
276
- "& .m-settings": {
277
- display: "none",
278
- position: "absolute",
279
- top: 0,
280
- bottom: 0,
281
- left: 0,
282
- right: 0,
283
- margin: "auto",
284
- width: "42px",
285
- height: "42px",
286
- background: "#FFF"
287
- },
288
- "&:hover": {
289
- color: textColorHover || textColor || "#FFF",
290
- background: bgColorHover || bgColor || "none",
268
+ }) : null, !isDrawer ? menus.map((item, i) => {
269
+ const buttonProps = handleLinkType(item.url, item.linkType, true, item.target === "_blank");
270
+ return /*#__PURE__*/_createElement(Button, {
271
+ ...buttonProps,
272
+ key: `${item.url}_${i}_no_drawer`,
273
+ sx: {
274
+ position: "relative",
275
+ fontFamily: fontFamily,
276
+ textTransform: "none",
277
+ fontSize: fontSize || "16px",
278
+ color: textColor || "#FFF",
279
+ background: bgColor || "none",
291
280
  "& .m-settings": {
292
- display: "block"
281
+ display: "none",
282
+ position: "absolute",
283
+ top: 0,
284
+ bottom: 0,
285
+ left: 0,
286
+ right: 0,
287
+ margin: "auto",
288
+ width: "42px",
289
+ height: "42px",
290
+ background: "#FFF"
291
+ },
292
+ "&:hover": {
293
+ color: textColorHover || textColor || "#FFF",
294
+ background: bgColorHover || bgColor || "none",
295
+ "& .m-settings": {
296
+ display: "block"
297
+ }
293
298
  }
294
299
  }
295
- },
296
- children: item.text
297
- }, `${item.url}_${i}_no_drawer`)) : null]
300
+ }, item.text);
301
+ }) : null]
298
302
  })]
299
303
  })
300
304
  }), /*#__PURE__*/_jsx("nav", {
@@ -10,8 +10,8 @@ import ButtonPopup from "./ButtonPopup";
10
10
  import { actionButtonRedirect } from "../../service/actionTrigger";
11
11
  import { WorkflowIcon } from "../../common/iconslist";
12
12
  import { getTRBLBreakPoints, getBreakPointsValue } from "../../helper/theme";
13
- import { windowVar } from "../../utils/helper";
14
- import ButtonNavSettings from "./ButtonNavSettings";
13
+ import { handleLinkType, windowVar } from "../../utils/helper";
14
+ import LinkSettings from "../../common/LinkSettings";
15
15
  import { jsx as _jsx } from "react/jsx-runtime";
16
16
  import { jsxs as _jsxs } from "react/jsx-runtime";
17
17
  const EditorButton = props => {
@@ -53,9 +53,16 @@ const EditorButton = props => {
53
53
  } = element;
54
54
  const {
55
55
  linkType,
56
- redirectOnURLResult
56
+ redirectOnURLResult,
57
+ actionTrigger
57
58
  } = buttonLink || {};
59
+ const {
60
+ onClick
61
+ } = actionTrigger || {
62
+ options: []
63
+ };
58
64
  const isTrigger = linkType === "actionTrigger";
65
+ const refURl = isTrigger ? buttonLink?.url : url;
59
66
  const BtnIcon = buttonIcon ? fIcons[buttonIcon] : null;
60
67
  windowVar.lastButtonProps = element;
61
68
  const handleTrigger = async () => {
@@ -72,82 +79,7 @@ const EditorButton = props => {
72
79
  window.open(refUrl, "_blank").focus();
73
80
  }
74
81
  };
75
- const handleLinkType = (readOnly, openInNewTab) => {
76
- const props = {};
77
- if (!readOnly) {
78
- return {
79
- component: "button"
80
- };
81
- }
82
- switch (linkType) {
83
- case "webAddress":
84
- const refUrl = url ? url.includes("http") ? url : `//${url}` : "Link";
85
- props.component = "a";
86
- if (refUrl !== "Link") {
87
- props.href = refUrl;
88
- }
89
- if (openInNewTab) {
90
- props.target = "_blank";
91
- }
92
- break;
93
- case "actionTrigger":
94
- if (!readOnly) {
95
- props.component = "button";
96
- props.onClick = () => {};
97
- } else {
98
- props.component = "button";
99
- props.onClick = handleTrigger;
100
- }
101
- break;
102
- case "page":
103
- props.component = "a";
104
- const [page, section] = url.split("#");
105
- props.href = page === "home" ? `#${section}` : `/${url}`;
106
- if (openInNewTab) {
107
- props.target = "_blank";
108
- }
109
- break;
110
- case "email":
111
- props.component = "a";
112
- props.href = `mailto:${url}`;
113
- break;
114
- case "phone":
115
- props.component = "a";
116
- props.href = `tel:${url}`;
117
- break;
118
- case "scrollTopOrBottom":
119
- props.component = "button";
120
- props.onClick = () => {
121
- const scrollEle = document.getElementById("slate-wrapper-scroll-container");
122
- if (scrollEle) {
123
- if (url === "top") {
124
- // top of the page
125
- scrollEle.scrollTo(0, 0);
126
- } else if (url === "bottom") {
127
- // bottom of the page
128
- scrollEle.scrollTo(0, scrollEle.scrollHeight);
129
- }
130
- }
131
- };
132
- break;
133
- default:
134
- return {};
135
- }
136
-
137
- // for iphone fix
138
- if (props.component === "a") {
139
- props.onTouchEnd = e => {
140
- e.preventDefault();
141
- e.stopPropagation();
142
- window.open(props.href, props.target);
143
- };
144
- props.onClick = () => {
145
- return false;
146
- };
147
- }
148
- return props;
149
- };
150
- const buttonProps = handleLinkType(readOnly, openInNewTab);
82
+ const buttonProps = handleLinkType(refURl, linkType, readOnly, openInNewTab, handleTrigger);
151
83
  const onMenuClick = val => () => {
152
84
  switch (val) {
153
85
  case "edit":
@@ -166,7 +98,7 @@ const EditorButton = props => {
166
98
  }
167
99
  };
168
100
  const Toolbar = () => {
169
- const btnProps = handleLinkType(true, true);
101
+ const btnProps = handleLinkType(refURl, linkType, true, true, handleTrigger);
170
102
  return !readOnly ? /*#__PURE__*/_jsxs("div", {
171
103
  className: "element-toolbar hr",
172
104
  style: {
@@ -307,13 +239,27 @@ const EditorButton = props => {
307
239
  onClose: onClose,
308
240
  onDelete: onMenuClick("delete"),
309
241
  customProps: customProps
310
- }), openNav ? /*#__PURE__*/_jsx(ButtonNavSettings, {
311
- open: openNav,
242
+ }), openNav ? /*#__PURE__*/_jsx(LinkSettings, {
312
243
  handleClose: () => setOpenNav(false),
313
- onSave: onSave,
314
- customProps: customProps,
315
- element: element,
316
- editor: editor
244
+ onSave: ({
245
+ linkType,
246
+ navValue,
247
+ openInNewTab
248
+ }) => {
249
+ onSave({
250
+ buttonLink: {
251
+ linkType,
252
+ onClick
253
+ },
254
+ url: navValue,
255
+ openInNewTab
256
+ });
257
+ setOpenNav(false);
258
+ },
259
+ navType: element?.buttonLink?.linkType,
260
+ navValue: element?.url,
261
+ openInNewTab: element?.openInNewTab,
262
+ customProps: customProps
317
263
  }) : null]
318
264
  });
319
265
  };
@@ -14,7 +14,10 @@ const ColorPickerStyles = theme => ({
14
14
  },
15
15
  colorPopper: {
16
16
  "& .MuiPaper-root": {
17
- backgroundColor: theme?.palette?.editor?.background
17
+ backgroundColor: theme?.palette?.editor?.background,
18
+ '@media only screen and (max-width: 600px)': {
19
+ marginTop: "-40px"
20
+ }
18
21
  }
19
22
  },
20
23
  colorButtonSingle: {
@@ -5,12 +5,14 @@ import AspectRatioIcon from "@mui/icons-material/AspectRatio";
5
5
  import useResize from "../../utils/customHooks/useResize";
6
6
  import EmbedPopup from "./EmbedPopup";
7
7
  import { IconButton, Tooltip, Box } from "@mui/material";
8
- import { GridSettingsIcon } from "../../common/iconslist";
8
+ import { GridSettingsIcon, LinkIcon } from "../../common/iconslist";
9
9
  import { useEditorContext, useEditorSelection } from "../../hooks/useMouseMove";
10
10
  import { getTRBLBreakPoints, getBreakPointsValue } from "../../helper/theme";
11
11
  import Icon from "../../common/Icon";
12
12
  import frames from "./Frames";
13
13
  import ImageFrame from "./Frames/ImageFrame";
14
+ import LinkSettings from "../../common/LinkSettings";
15
+ import { handleLinkType } from "../../utils/helper";
14
16
  import { jsx as _jsx } from "react/jsx-runtime";
15
17
  import { jsxs as _jsxs } from "react/jsx-runtime";
16
18
  const Image = ({
@@ -35,6 +37,7 @@ const Image = ({
35
37
  frame = null,
36
38
  webAddress,
37
39
  isNewTab,
40
+ linkType,
38
41
  framePos
39
42
  } = element;
40
43
  const {
@@ -52,6 +55,7 @@ const Image = ({
52
55
  const [openSetttings, setOpenSettings] = useState(false);
53
56
  const path = ReactEditor.findPath(editor, element);
54
57
  const [showTool] = useEditorSelection(editor);
58
+ const [openNav, setOpenNav] = useState(false);
55
59
  const getSize = () => {
56
60
  if (element?.size === undefined) {
57
61
  return {
@@ -86,20 +90,6 @@ const Image = ({
86
90
  onLoad(getSize());
87
91
  }
88
92
  }, []);
89
- const handleImageClick = () => {
90
- Transforms.select(editor, {
91
- anchor: Editor.start(editor, path),
92
- focus: Editor.end(editor, path)
93
- });
94
- if (webAddress) {
95
- const refUrl = webAddress ? webAddress.includes("http") ? webAddress : `//${webAddress}` : "Link";
96
- if (isNewTab) {
97
- window.open(refUrl, "_blank").focus();
98
- } else {
99
- window.location.href = refUrl;
100
- }
101
- }
102
- };
103
93
  const onSettings = () => {
104
94
  setOpenSettings(true);
105
95
  };
@@ -127,7 +117,7 @@ const Image = ({
127
117
  onSave(data);
128
118
  };
129
119
  const ToolBar = () => {
130
- return selected && !showTool ? /*#__PURE__*/_jsx("div", {
120
+ return /*#__PURE__*/_jsxs("div", {
131
121
  className: "element-toolbar visible-on-hover",
132
122
  contentEditable: false,
133
123
  style: {
@@ -136,21 +126,43 @@ const Image = ({
136
126
  left: "auto",
137
127
  margin: "0px"
138
128
  },
139
- children: /*#__PURE__*/_jsx(Tooltip, {
129
+ children: [/*#__PURE__*/_jsx(Tooltip, {
140
130
  title: "Image Settings",
141
131
  arrow: true,
142
132
  children: /*#__PURE__*/_jsx(IconButton, {
143
133
  onClick: onSettings,
144
134
  children: /*#__PURE__*/_jsx(GridSettingsIcon, {})
145
135
  })
146
- })
147
- }) : null;
136
+ }), /*#__PURE__*/_jsx(Tooltip, {
137
+ title: "Link Settings",
138
+ arrow: true,
139
+ children: /*#__PURE__*/_jsx(IconButton, {
140
+ onClick: () => setOpenNav(true),
141
+ children: /*#__PURE__*/_jsx(LinkIcon, {})
142
+ })
143
+ })]
144
+ });
148
145
  };
149
146
  const ImageContent = () => {
147
+ const {
148
+ onClick,
149
+ onTouchEnd
150
+ } = handleLinkType(webAddress, linkType, readOnly, isNewTab);
151
+ const handleImageClick = () => {
152
+ Transforms.select(editor, {
153
+ anchor: Editor.start(editor, path),
154
+ focus: Editor.end(editor, path)
155
+ });
156
+ if (onClick) {
157
+ onClick();
158
+ }
159
+ if (onTouchEnd) {
160
+ onTouchEnd();
161
+ }
162
+ };
150
163
  return !url && !readOnly ? /*#__PURE__*/_jsxs(Box, {
151
164
  component: "button",
152
165
  className: "element-empty-btn",
153
- onClick: onSettings,
154
166
  contentEditable: false,
155
167
  children: [/*#__PURE__*/_jsx(Icon, {
156
168
  icon: "image"
@@ -173,6 +185,7 @@ const Image = ({
173
185
  alt: alt,
174
186
  src: url,
175
187
  onClick: handleImageClick,
188
+ onTouchEnd: onTouchEnd,
176
189
  "data-path": path.join(","),
177
190
  draggable: false
178
191
  });
@@ -254,7 +267,25 @@ const Image = ({
254
267
  }), /*#__PURE__*/_jsx("span", {
255
268
  contentEditable: false,
256
269
  children: children
257
- })]
270
+ }), openNav ? /*#__PURE__*/_jsx(LinkSettings, {
271
+ handleClose: () => setOpenNav(false),
272
+ onSave: ({
273
+ linkType,
274
+ navValue,
275
+ openInNewTab
276
+ }) => {
277
+ onSave({
278
+ linkType,
279
+ webAddress: navValue,
280
+ isNewTab: openInNewTab
281
+ });
282
+ setOpenNav(false);
283
+ },
284
+ navType: linkType,
285
+ navValue: webAddress,
286
+ openInNewTab: isNewTab,
287
+ customProps: customProps
288
+ }) : null]
258
289
  });
259
290
  };
260
291
  export default Image;
@@ -300,7 +300,7 @@ const Form = props => {
300
300
  children: formTitle
301
301
  }), children, /*#__PURE__*/_jsx(Grid, {
302
302
  item: true,
303
- xs: buttonProps?.grid || 6,
303
+ ...buttonProps?.grid,
304
304
  className: "form-btn-wrpr",
305
305
  contentEditable: false,
306
306
  style: {
@@ -20,11 +20,15 @@ const editorStyles = ({
20
20
  "& .mobileMiniTextWrapper": {
21
21
  boxShadow: "0px 0px 10px 0px rgba(0, 0, 0, 0.16)",
22
22
  position: "fixed",
23
- bottom: 0,
23
+ bottom: "env(safe-area-inset-bottom)",
24
24
  left: 0,
25
25
  width: "100%",
26
26
  zIndex: 99999,
27
- background: "white"
27
+ backgroundColor: theme?.palette?.editor?.background,
28
+ color: theme?.palette?.editor?.textColor,
29
+ "& .MuiOutlinedInput-input": {
30
+ color: theme?.palette?.editor?.textColor
31
+ }
28
32
  }
29
33
  },
30
34
  slateWrapper: {
@@ -7,7 +7,7 @@ import { BREAKPOINTS_DEVICES, getBreakPointsValue } from "../../../helper/theme"
7
7
  import { headingMap, sizeMap } from "../../../utils/font";
8
8
  import { jsx as _jsx } from "react/jsx-runtime";
9
9
  import { jsxs as _jsxs } from "react/jsx-runtime";
10
- const fontSizeOptions = [16, 18, 20, 22, 26, 32, 36, 40, 48, 64, 96, 128];
10
+ const fontSizeOptions = [8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 26, 32, 36, 40, 48, 64, 96, 128];
11
11
  function SelectFontSize({
12
12
  editor,
13
13
  classes
@@ -103,7 +103,7 @@ const MiniTextFormat = props => {
103
103
  transition: true,
104
104
  placement: "bottom-end",
105
105
  sx: classes.popupWrapper,
106
- className: `tools-drawer ${size?.device}`,
106
+ className: `tools-drawer ${size?.device} textSettings`,
107
107
  children: ({
108
108
  TransitionProps
109
109
  }) => /*#__PURE__*/_jsx(Fade, {
@@ -18,6 +18,12 @@ const usePopupStyle = theme => ({
18
18
  "& .MuiPaper-root": {
19
19
  backgroundColor: theme?.palette?.editor?.background
20
20
  },
21
+ "&.textSettings": {
22
+ '@media only screen and (max-width: 600px)': {
23
+ margin: "4px !important",
24
+ marginBottom: "54px !important"
25
+ }
26
+ },
21
27
  "& .MuiTypography-root": {
22
28
  color: theme?.palette?.editor?.textColor
23
29
  },
@@ -391,7 +397,10 @@ const usePopupStyle = theme => ({
391
397
  },
392
398
  colorPopper: {
393
399
  "& .MuiPaper-root": {
394
- backgroundColor: theme?.palette?.editor?.background
400
+ backgroundColor: theme?.palette?.editor?.background,
401
+ '@media only screen and (max-width: 600px)': {
402
+ marginTop: "-40px"
403
+ }
395
404
  }
396
405
  },
397
406
  fullViewCardMedia: {
@@ -459,7 +468,7 @@ const usePopupStyle = theme => ({
459
468
  gap: "4px"
460
469
  },
461
470
  "& .verticalLine": {
462
- borderLeft: "1px solid #E0E0E0",
471
+ borderLeft: `1px solid ${theme?.palette?.primary?.border8}`,
463
472
  minHeight: "20px",
464
473
  height: "100%"
465
474
  },
@@ -500,10 +509,14 @@ const usePopupStyle = theme => ({
500
509
  },
501
510
  customSelectPopoverWrapper: {
502
511
  "& .MuiPopover-paper": {
503
- maxHeight: '140px'
512
+ maxHeight: '140px',
513
+ background: theme?.palette?.editor?.background,
514
+ '@media only screen and (max-width: 600px)': {
515
+ marginTop: "-40px"
516
+ }
504
517
  },
505
518
  "& .customSelectOptionLabel": {
506
- color: "black",
519
+ color: theme?.palette?.editor?.textColor,
507
520
  margin: "0px",
508
521
  width: "100%",
509
522
  justifyContent: "start",
@@ -511,11 +524,13 @@ const usePopupStyle = theme => ({
511
524
  fontSize: "14px",
512
525
  lineHeight: "1.75 !important",
513
526
  fontWeight: 400,
527
+ background: theme?.palette?.editor?.background,
514
528
  "& :hover": {
515
- background: "#F0F5FA !important"
529
+ background: `${theme?.palette?.action?.selected} !important`
516
530
  },
517
531
  "&.selected": {
518
- background: "#F0F5FA !important"
532
+ color: `${theme?.palette?.primary?.main} !important`,
533
+ background: `${theme?.palette?.action?.selected} !important`
519
534
  }
520
535
  },
521
536
  "& .menuOptions": {
@@ -528,13 +543,13 @@ const usePopupStyle = theme => ({
528
543
  textTransform: "none"
529
544
  }
530
545
  },
531
- mobileMiniTextWrapper: {
532
- boxShadow: "0px 0px 10px 0px rgba(0, 0, 0, 0.16)",
533
- position: "fixed",
534
- bottom: "env(safe-area-inset-bottom)",
535
- left: 0,
536
- width: "100%"
537
- },
546
+ // mobileMiniTextWrapper: {
547
+ // boxShadow: "0px 0px 10px 0px rgba(0, 0, 0, 0.16)",
548
+ // position: "fixed",
549
+ // bottom: "env(safe-area-inset-bottom)",
550
+ // left: 0,
551
+ // width: "100%",
552
+ // },
538
553
  miniFontSizeInput: {
539
554
  "& input": {
540
555
  fontSize: "14px",
@@ -7,7 +7,7 @@ import IconButton from '@mui/material/IconButton';
7
7
  import CloseIcon from '@mui/icons-material/Close';
8
8
  import { FormControl, FormControlLabel, Grid, Radio, RadioGroup } from '@mui/material';
9
9
  import { useState } from 'react';
10
- import ButtonNavSettingsStyles from './style';
10
+ import LinkSettingsStyles from './style';
11
11
  import { getNavOptions } from './navOptions';
12
12
  import { ScrollTopBottom, SelectPage, TextInput, Trigger } from './NavComponents';
13
13
  import { jsx as _jsx } from "react/jsx-runtime";
@@ -20,49 +20,28 @@ const MAP_COMPONENT = {
20
20
  scrollTopOrBottom: ScrollTopBottom,
21
21
  page: SelectPage
22
22
  };
23
- export default function ButtonNavSettings(props) {
23
+ export default function LinkSettings(props) {
24
24
  const {
25
- open,
26
25
  handleClose,
27
26
  onSave,
28
27
  customProps,
29
- element,
30
- editor
28
+ navType
31
29
  } = props;
32
30
  const navOptions = getNavOptions(customProps.hideTools);
33
- const prevNavType = element?.buttonLink?.linkType;
34
- const classes = ButtonNavSettingsStyles();
35
- const [nav, setNav] = useState(prevNavType ? navOptions.find(n => n.value === prevNavType) : {
31
+ const classes = LinkSettingsStyles();
32
+ const [nav, setNav] = useState(navType ? navOptions.find(n => n.value === navType) : {
36
33
  label: "None",
37
34
  value: ""
38
35
  });
39
- const [navValue, setNavValue] = useState(element?.url || "");
40
- const [openInNewTab, setOpenInNewTab] = useState(element.openInNewTab || false);
41
- const {
42
- metadata
43
- } = customProps || {
44
- metadata: {}
45
- };
46
- const {
47
- buttonLink
48
- } = metadata || {
49
- actionTrigger: {}
50
- };
51
- const {
52
- actionTrigger
53
- } = buttonLink || {};
54
- const {
55
- onClick
56
- } = actionTrigger || {
57
- options: []
58
- };
36
+ const [navValue, setNavValue] = useState(props?.navValue || "");
37
+ const [openInNewTab, setOpenInNewTab] = useState(props.openInNewTab || false);
59
38
  const NavSettings = MAP_COMPONENT[nav?.value];
60
39
  const onChange = value => {
61
40
  setNavValue(value);
62
41
  };
63
42
  return /*#__PURE__*/_jsxs(Dialog, {
64
43
  onClose: handleClose,
65
- open: open,
44
+ open: true,
66
45
  sx: classes.dialogContainer,
67
46
  fullWidth: true,
68
47
  maxWidth: "sm",
@@ -106,7 +85,6 @@ export default function ButtonNavSettings(props) {
106
85
  nav: nav,
107
86
  onChange: onChange,
108
87
  value: navValue,
109
- editor: editor,
110
88
  openInNewTab: openInNewTab,
111
89
  onNewTabChange: () => setOpenInNewTab(prev => !prev),
112
90
  services: customProps.services
@@ -121,14 +99,10 @@ export default function ButtonNavSettings(props) {
121
99
  }), /*#__PURE__*/_jsx(Button, {
122
100
  onClick: () => {
123
101
  onSave({
124
- buttonLink: {
125
- linkType: nav?.value,
126
- onClick
127
- },
128
- url: navValue,
102
+ linkType: nav?.value,
103
+ navValue,
129
104
  openInNewTab
130
105
  });
131
- handleClose();
132
106
  },
133
107
  sx: classes.saveBtn,
134
108
  children: "Save"
@@ -39,17 +39,20 @@ const embedImageStyle = [{
39
39
  value: "RoundedLightB2",
40
40
  label: "Rounded Light B2 Frame"
41
41
  }]
42
- }, {
43
- label: "Add web address here",
44
- key: "webAddress",
45
- type: "text",
46
- placeholder: "https://"
47
- }, {
48
- label: "Open in new tab",
49
- key: "isNewTab",
50
- type: "selectBox",
51
- placeholder: "Open in new tab"
52
- }]
42
+ }
43
+ // {
44
+ // label: "Add web address here",
45
+ // key: "webAddress",
46
+ // type: "text",
47
+ // placeholder: "https://",
48
+ // },
49
+ // {
50
+ // label: "Open in new tab",
51
+ // key: "isNewTab",
52
+ // type: "selectBox",
53
+ // placeholder: "Open in new tab",
54
+ // },
55
+ ]
53
56
  }, {
54
57
  tab: "Banner Spacing",
55
58
  value: "bannerSpacing",
@@ -1,6 +1,8 @@
1
- import React from "react";
1
+ import React, { useState } from "react";
2
2
  import { Button, Grid, Radio, RadioGroup, TextField, FormControl, FormLabel, FormControlLabel, Typography, Tooltip, IconButton } from "@mui/material";
3
3
  import DeleteIcon from "@mui/icons-material/Delete";
4
+ import Settings from "@mui/icons-material/Settings";
5
+ import LinkSettings from "../../LinkSettings";
4
6
  import { jsx as _jsx } from "react/jsx-runtime";
5
7
  import { jsxs as _jsxs } from "react/jsx-runtime";
6
8
  const MenusArray = props => {
@@ -8,7 +10,8 @@ const MenusArray = props => {
8
10
  value,
9
11
  data,
10
12
  elementProps,
11
- onChange
13
+ onChange,
14
+ customProps
12
15
  } = props;
13
16
  const {
14
17
  key
@@ -18,6 +21,7 @@ const MenusArray = props => {
18
21
  } = elementProps || {
19
22
  menuStyle: "stacked"
20
23
  };
24
+ const [openNav, setOpenNav] = useState(false);
21
25
  const handleChange = index => e => {
22
26
  const upValue = [...(value || [])];
23
27
  upValue[index] = {
@@ -47,6 +51,17 @@ const MenusArray = props => {
47
51
  [e.target.name]: e.target.value
48
52
  });
49
53
  };
54
+ const selectedMenu = openNav?.menu || {};
55
+ const onSave = update => {
56
+ const upValue = [...(value || [])];
57
+ upValue[openNav?.index] = {
58
+ ...(upValue[openNav?.index] || {}),
59
+ ...update
60
+ };
61
+ onChange({
62
+ [key]: upValue
63
+ });
64
+ };
50
65
  return /*#__PURE__*/_jsxs(Grid, {
51
66
  item: true,
52
67
  xs: 12,
@@ -123,6 +138,16 @@ const MenusArray = props => {
123
138
  onChange: handleChange(i),
124
139
  size: "small",
125
140
  fullWidth: true
141
+ }), /*#__PURE__*/_jsx(Tooltip, {
142
+ title: "Link Settings",
143
+ arrow: true,
144
+ children: /*#__PURE__*/_jsx(IconButton, {
145
+ onClick: () => setOpenNav({
146
+ menu: m,
147
+ index: i
148
+ }),
149
+ children: /*#__PURE__*/_jsx(Settings, {})
150
+ })
126
151
  }), /*#__PURE__*/_jsx(Tooltip, {
127
152
  title: "Delete Menu",
128
153
  arrow: true,
@@ -142,7 +167,25 @@ const MenusArray = props => {
142
167
  },
143
168
  children: "+ Add"
144
169
  })
145
- })]
170
+ }), openNav ? /*#__PURE__*/_jsx(LinkSettings, {
171
+ handleClose: () => setOpenNav(null),
172
+ onSave: ({
173
+ linkType,
174
+ navValue,
175
+ openInNewTab
176
+ }) => {
177
+ onSave({
178
+ linkType,
179
+ url: navValue,
180
+ target: openInNewTab ? "_blank" : ""
181
+ });
182
+ setOpenNav(false);
183
+ },
184
+ navType: selectedMenu?.linkType,
185
+ navValue: selectedMenu?.url,
186
+ openInNewTab: selectedMenu?.target === "_blank",
187
+ customProps: customProps
188
+ }) : null]
146
189
  });
147
190
  };
148
191
  export default MenusArray;
@@ -1,4 +1,22 @@
1
1
  import { jsx } from "slate-hyperscript";
2
+ const handleTableCell = (el, children) => {
3
+ const wrapChild = children?.map(c => {
4
+ if (typeof c === "string") {
5
+ return {
6
+ type: "paragraph",
7
+ children: [{
8
+ text: c
9
+ }],
10
+ cellBgColor: "#FFFFFF"
11
+ };
12
+ }
13
+ return c;
14
+ });
15
+ return {
16
+ type: "table-cell",
17
+ overwriteChild: wrapChild
18
+ };
19
+ };
2
20
  const ELEMENT_TAGS = {
3
21
  A: el => ({
4
22
  type: "link",
@@ -53,11 +71,15 @@ const ELEMENT_TAGS = {
53
71
  "GOOGLE-SHEETS-HTML-ORIGIN": () => ({
54
72
  type: "paragraph"
55
73
  }),
56
- TABLE: (el, bodyChildren = []) => {
74
+ TABLE: (el, children = []) => {
75
+ const bodyChild = children[0]?.children || [];
76
+ const firstRowChildren = bodyChild[0]?.children || [];
57
77
  return {
58
78
  type: "table",
59
- rows: bodyChildren?.length,
60
- columns: bodyChildren[0]?.children?.length
79
+ overwriteChild: bodyChild,
80
+ // we are not having table-body in our json format, just we are wrapping table-row's inside the table
81
+ rows: bodyChild?.length,
82
+ columns: firstRowChildren?.length
61
83
  };
62
84
  },
63
85
  THEAD: () => ({
@@ -66,15 +88,11 @@ const ELEMENT_TAGS = {
66
88
  TBODY: () => ({
67
89
  type: "table-body"
68
90
  }),
69
- TH: () => ({
70
- type: "table-cell"
71
- }),
91
+ TH: handleTableCell,
72
92
  TR: () => ({
73
93
  type: "table-row"
74
94
  }),
75
- TD: () => ({
76
- type: "table-cell"
77
- }),
95
+ TD: handleTableCell,
78
96
  COLGROUP: () => ({
79
97
  type: "paragraph"
80
98
  }),
@@ -133,8 +151,11 @@ const deserialize = el => {
133
151
  return jsx("fragment", {}, children);
134
152
  }
135
153
  if (ELEMENT_TAGS[nodeName]) {
136
- const attrs = ELEMENT_TAGS[nodeName](el, children);
137
- return jsx("element", attrs, children);
154
+ const {
155
+ overwriteChild,
156
+ ...attrs
157
+ } = ELEMENT_TAGS[nodeName](el, children);
158
+ return jsx("element", attrs, overwriteChild || children);
138
159
  }
139
160
  if (TEXT_TAGS[nodeName]) {
140
161
  const attrs = TEXT_TAGS[nodeName](el);
@@ -3,10 +3,42 @@ import { rectIntersection, closestCenter } from "@dnd-kit/core";
3
3
  import { getQueryStrings } from "../utils/SlateUtilityFunctions";
4
4
  import { Node } from "slate";
5
5
  const HIDE_PLACHOLDERS = ["grid", "grid-item", "table"];
6
+ const PREVIEW_IMAGE_HIDE_CLASS = ["grid-container-toolbar", "grid-item-toolbar", "element-toolbar", "mini-tool-wrpr-ei", "element-selector", "element-selector-ctrl"];
6
7
  export const getThumbnailImage = async (dom, options = {}) => {
7
8
  try {
8
- const canvas = await html2canvas(dom, options);
9
- return canvas.toDataURL();
9
+ const canvas = await html2canvas(dom, {
10
+ windowWidth: 1440,
11
+ windowHeight: 768,
12
+ ...options,
13
+ backgroundColor: null,
14
+ allowTaint: true,
15
+ useCORS: false,
16
+ scale: 0.5,
17
+ imageTimeout: 0,
18
+ onclone: document => {
19
+ // hide class
20
+ const sw = document.getElementById("slate-wrapper-scroll-container");
21
+ sw.style.minHeight = "2000px";
22
+ const svgFrames = document.querySelectorAll(".image-frame svg");
23
+ for (let i = 0; i < svgFrames.length; i++) {
24
+ svgFrames[i].style.width = "100%";
25
+ }
26
+ const rectFills = document.getElementsByTagName("rect");
27
+ for (let i = 0; i < rectFills.length; i++) {
28
+ const hasURL = rectFills[i]?.getAttribute("fill")?.indexOf("url") > -1;
29
+ if (hasURL) {
30
+ rectFills[i].style.fill = "#CCC";
31
+ }
32
+ }
33
+ for (let hidedeClass of PREVIEW_IMAGE_HIDE_CLASS) {
34
+ for (let element of document.getElementsByClassName(hidedeClass)) {
35
+ element.style.display = "none";
36
+ }
37
+ }
38
+ return document;
39
+ }
40
+ });
41
+ return canvas.toDataURL("image/jpeg", 0.5);
10
42
  } catch (err) {
11
43
  console.log(err);
12
44
  return null;
@@ -11,7 +11,7 @@ const withTable = editor => {
11
11
  if (arg.reverse) {
12
12
  const table = new TableUtil(editor);
13
13
  const cellsSelected = table.isCellSelected(editor.selection);
14
- if (cellsSelected) {
14
+ if (cellsSelected && cellsSelected.length > 1) {
15
15
  cellsSelected.forEach(cellPath => {
16
16
  Transforms.removeNodes(editor, {
17
17
  at: cellPath
@@ -125,7 +125,9 @@ export const escapeEvent = props => {
125
125
  const parentNodes = parentPath.filter(m => m.length).map(m => Node.get(editor, m));
126
126
  const ele = isListItem(editor);
127
127
  const eleType = ele[0]?.type;
128
- if (parentNodes.length === 2 && parentNodes[1]?.type === "list-item") {
128
+ const parentLists = parentNodes.filter(p => p.type === "orderedList" || p.type === "unorderedList");
129
+ if (parentLists?.length === 1) {
130
+ // if not in nested list
129
131
  toggleBlock(editor, "list-item", editor.selection);
130
132
  } else if (eleType === "check-list-item") {
131
133
  checkListEnterEvent(editor, eleType);
@@ -1,6 +1,7 @@
1
1
  import { Editor, Node, Transforms, Element } from "slate";
2
2
  import { ReactEditor } from "slate-react";
3
3
  import insertNewLine from "./insertNewLine";
4
+ import { getDevice } from "../helper/theme";
4
5
  export const windowVar = {};
5
6
  export const formatDate = (date, format = "MM/DD/YYYY") => {
6
7
  if (!date) return "";
@@ -100,10 +101,10 @@ export const getSelectedText = editor => {
100
101
  export const isEmptyNode = (editor, children, path) => {
101
102
  try {
102
103
  const isEmptyText = Node.string(Node.get(editor, path))?.length === 0;
103
- const emptyNode = children?.length === 1 && children[0]?.children[0]?.type === undefined && children[0]?.type === "paragraph";
104
+ const emptyNode = children?.length === 1 && children && children[0]?.children[0]?.type === undefined && children[0]?.type === "paragraph";
104
105
  return isEmptyText && emptyNode;
105
106
  } catch (err) {
106
- console.log(err);
107
+ // console.log(err);
107
108
  return "";
108
109
  }
109
110
  };
@@ -123,7 +124,7 @@ export const handleInsertLastElement = (event, editor) => {
123
124
  offset: 0
124
125
  };
125
126
  Transforms.insertNodes(editor, {
126
- text: ''
127
+ text: ""
127
128
  }, {
128
129
  at: path
129
130
  });
@@ -202,4 +203,88 @@ export const decodeAndParseBase64 = encodedString => {
202
203
  const decodedURLString = decodeURIComponent(decodedString);
203
204
  const jsonData = JSON.parse(decodedURLString);
204
205
  return jsonData;
206
+ };
207
+ export const handleLinkType = (url, linkType, readOnly, openInNewTab, onClick = () => {}) => {
208
+ const props = {};
209
+ if (!readOnly) {
210
+ return {
211
+ component: "button"
212
+ };
213
+ }
214
+ switch (linkType) {
215
+ case "webAddress":
216
+ const refUrl = url ? url.includes("http") ? url : `//${url}` : "Link";
217
+ props.component = "a";
218
+ if (refUrl !== "Link") {
219
+ props.href = refUrl;
220
+ }
221
+ if (openInNewTab) {
222
+ props.target = "_blank";
223
+ }
224
+ break;
225
+ case "actionTrigger":
226
+ if (!readOnly) {
227
+ props.component = "button";
228
+ props.onClick = () => {};
229
+ } else {
230
+ props.component = "button";
231
+ props.onClick = onClick;
232
+ }
233
+ break;
234
+ case "page":
235
+ props.component = "a";
236
+ const [page, section] = url.split("#");
237
+ const sec = section ? `#${section}` : "";
238
+ props.href = page === "home" ? sec : `/${url}`;
239
+ if (openInNewTab) {
240
+ props.target = "_blank";
241
+ }
242
+ break;
243
+ case "email":
244
+ props.component = "a";
245
+ props.href = `mailto:${url}`;
246
+ break;
247
+ case "phone":
248
+ props.component = "a";
249
+ props.href = `tel:${url}`;
250
+ break;
251
+ case "scrollTopOrBottom":
252
+ props.component = "button";
253
+ props.onClick = () => {
254
+ const scrollEle = document.getElementById("slate-wrapper-scroll-container");
255
+ if (scrollEle) {
256
+ if (url === "top") {
257
+ // top of the page
258
+ scrollEle.scrollTo(0, 0);
259
+ } else if (url === "bottom") {
260
+ // bottom of the page
261
+ scrollEle.scrollTo(0, scrollEle.scrollHeight);
262
+ }
263
+ }
264
+ };
265
+ break;
266
+ default:
267
+ return {};
268
+ }
269
+
270
+ // for iphone fix
271
+ if (props.component === "a" && props.href) {
272
+ if (getDevice(window.innerWidth) === "xs") {
273
+ props.component = "button"; // iphone is opening two tabs, on open in new tab because of a tag.
274
+ }
275
+
276
+ props.onTouchEnd = e => {
277
+ e.preventDefault();
278
+ e.stopPropagation();
279
+ if (props.target) {
280
+ window.open(props.href);
281
+ } else {
282
+ window.location.href = props.href;
283
+ }
284
+ };
285
+ props.onClick = () => {
286
+ return false;
287
+ };
288
+ }
289
+ return props;
205
290
  };
@@ -13,24 +13,28 @@ export const createAppHeaderNode = ({
13
13
  appLogo: "none",
14
14
  menus: menus || [{
15
15
  type: "menu",
16
- url: "/",
17
- target: "_blank",
18
- text: "Home"
16
+ url: "home",
17
+ target: "",
18
+ text: "Home",
19
+ linkType: "page"
19
20
  }, {
20
21
  type: "menu",
21
- url: "/wireframe2",
22
- target: "_blank",
23
- text: "Wireframe"
22
+ url: "wireframe2",
23
+ target: "",
24
+ text: "Wireframe",
25
+ linkType: "page"
24
26
  }, {
25
27
  type: "menu",
26
28
  url: "https://www.google.com",
27
- target: "_blank",
28
- text: "Work"
29
+ target: "",
30
+ text: "Work",
31
+ linkType: "webAddress"
29
32
  }, {
30
33
  type: "menu",
31
34
  url: "https://www.google.com",
32
- target: "_blank",
33
- text: "Contact"
35
+ target: "",
36
+ text: "Contact",
37
+ linkType: "webAddress"
34
38
  }],
35
39
  menuStyle: "stacked",
36
40
  children: [{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flozy/editor",
3
- "version": "3.1.8",
3
+ "version": "3.1.9",
4
4
  "description": "An Editor for flozy app brain",
5
5
  "files": [
6
6
  "dist"