@flozy/editor 3.1.8 → 3.1.9

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.
@@ -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"