@flozy/editor 4.2.0 → 4.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable no-unused-vars */
2
2
  import React, { useRef, useCallback, useEffect, useMemo, useState, forwardRef, useImperativeHandle } from "react";
3
3
  import PropTypes from "prop-types";
4
- import { createEditor, Transforms } from "slate";
4
+ import { createEditor, Transforms, Range } from "slate";
5
5
  import { Slate, Editable, ReactEditor } from "slate-react";
6
6
  import { useDebounce, useDebouncedCallback } from "use-debounce";
7
7
  import { getMarked, getBlock } from "./utils/SlateUtilityFunctions";
@@ -365,6 +365,20 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
365
365
  });
366
366
  } else if (event.key === "Enter") {
367
367
  enterEvent(event, editor, customProps?.isMobile);
368
+ } else if (event.key === 'Backspace') {
369
+ const {
370
+ selection
371
+ } = editor;
372
+ event.preventDefault();
373
+ if (selection) {
374
+ if (!Range.isCollapsed(selection)) {
375
+ editor.deleteFragment();
376
+ } else {
377
+ editor.deleteBackward({
378
+ unit: 'character'
379
+ });
380
+ }
381
+ }
368
382
  }
369
383
  }, [chars, editor, target, mentions, setMentions, search, type, mentionsRef]);
370
384
  const Overlay = collaborativeEditor && !isReadOnly ? RemoteCursorOverlay : React.Fragment;
@@ -425,18 +439,20 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
425
439
  };
426
440
  const handleCursorScroll = container => {
427
441
  try {
428
- const selection = window?.getSelection();
429
- if (selection && selection.rangeCount > 0) {
430
- const cursorPosition = selection.getRangeAt(0)?.getBoundingClientRect();
431
- const containerBottom = container?.getBoundingClientRect()?.bottom;
432
- if (cursorPosition && cursorPosition.bottom > containerBottom - 250) {
433
- container?.scrollBy({
434
- top: 200,
435
- behavior: "smooth"
436
- });
442
+ if (!customProps?.isMobile) {
443
+ const selection = window?.getSelection();
444
+ if (selection && selection.rangeCount > 0) {
445
+ const cursorPosition = selection.getRangeAt(0)?.getBoundingClientRect();
446
+ const containerBottom = container?.getBoundingClientRect()?.bottom;
447
+ if (cursorPosition && cursorPosition.bottom > containerBottom - 250) {
448
+ container?.scrollBy({
449
+ top: 200,
450
+ behavior: "smooth"
451
+ });
452
+ }
453
+ } else {
454
+ console.warn('No valid selection range found');
437
455
  }
438
- } else {
439
- console.warn('No valid selection range found');
440
456
  }
441
457
  } catch (err) {
442
458
  console.log('handleCursorScroll', err);
@@ -10,7 +10,7 @@ import EmbedPopup from "./EmbedPopup";
10
10
  import { GridSettingsIcon } from "../../common/iconslist";
11
11
  import { gradientBorder } from "../../utils/helper";
12
12
  import { getEmbedURL } from "../../helper";
13
- import { getBreakPointsValue, groupByBreakpoint } from "../../helper/theme";
13
+ import { getBreakPointsValue, getTRBLBreakPoints, groupByBreakpoint } from "../../helper/theme";
14
14
  import { jsx as _jsx } from "react/jsx-runtime";
15
15
  import { jsxs as _jsxs } from "react/jsx-runtime";
16
16
  const Video = ({
@@ -29,7 +29,9 @@ const Video = ({
29
29
  borderStyle,
30
30
  url,
31
31
  xsHidden,
32
- width: oldWidth
32
+ width: oldWidth,
33
+ bannerSpacing,
34
+ bgColor
33
35
  } = element;
34
36
  const editor = useSlateStatic();
35
37
  const [openSetttings, setOpenSettings] = useState(false);
@@ -139,6 +141,14 @@ const Video = ({
139
141
  }
140
142
  };
141
143
  const embedURL = getEmbedURL(element);
144
+ const videoSX = groupByBreakpoint({
145
+ borderRadius: {
146
+ ...getBreakPointsValue(borderRadius || {}, null, "overrideBorderRadius", true)
147
+ },
148
+ padding: {
149
+ ...getTRBLBreakPoints(bannerSpacing)
150
+ }
151
+ }, theme);
142
152
  const VideoContent = () => {
143
153
  return resizing ? /*#__PURE__*/_jsx("div", {
144
154
  style: {
@@ -164,10 +174,9 @@ const Video = ({
164
174
  left: "0px",
165
175
  ...(gradientBorder(borderColor) || {}),
166
176
  borderWidth: borderWidth || "1px",
167
- borderRadius: {
168
- ...getBreakPointsValue(borderRadius || {}, null, "overrideBorderRadius", true)
169
- },
170
- borderStyle: borderStyle || "solid"
177
+ borderStyle: borderStyle || "solid",
178
+ background: bgColor || "transparent",
179
+ ...videoSX
171
180
  },
172
181
  src: embedURL,
173
182
  title: alt
@@ -262,6 +262,7 @@ const Form = props => {
262
262
  };
263
263
  const handleCloseMessage = () => {
264
264
  setSubmittedSuccessfully(false);
265
+ formEle.current.reset();
265
266
  };
266
267
  const onMouseLeave = () => {
267
268
  setShowOptions(false);
@@ -449,7 +449,8 @@ const FreeGrid = props => {
449
449
  props: {
450
450
  editor,
451
451
  path,
452
- classes
452
+ classes,
453
+ customProps
453
454
  }
454
455
  }
455
456
  },
@@ -471,7 +472,7 @@ const FreeGrid = props => {
471
472
  "--cols": `100%`,
472
473
  "--rows": `repeat(${repeatTimes}, ${ROW_HEIGHT}px)`,
473
474
  background: sectionBgColor,
474
- backgroundImage: `url('${sectionBackgroundImage}')`,
475
+ backgroundImage: sectionBackgroundImage ? `url('${sectionBackgroundImage}')` : "",
475
476
  backgroundSize: "cover"
476
477
  },
477
478
  children: [children, !readOnly ? /*#__PURE__*/_jsx("span", {
@@ -200,10 +200,11 @@ const FreeGridBox = props => {
200
200
  ...getBreakPointsValue(sectionBorderRadius || {}, null, "overrideBorderRadius", true)
201
201
  },
202
202
  background: sectionBgColor,
203
- backgroundImage: `url(${sectionBackgroundImage})`,
203
+ backgroundImage: sectionBackgroundImage ? `url('${sectionBackgroundImage}')` : "",
204
204
  borderColor: borderColor || "transparent",
205
205
  borderWidth: borderWidth || "1px",
206
- borderStyle: borderStyle || "solid"
206
+ borderStyle: borderStyle || "solid",
207
+ backgroundSize: "cover"
207
208
  },
208
209
  children: children
209
210
  })
@@ -1,51 +1,65 @@
1
1
  import React from "react";
2
- import { Box, List, ListItemButton } from "@mui/material";
2
+ import { Box, List, ListItemButton, ListItemIcon, ListItemText } from "@mui/material";
3
+ import Icon from "../../../common/Icon";
3
4
  import { jsx as _jsx } from "react/jsx-runtime";
4
5
  import { jsxs as _jsxs } from "react/jsx-runtime";
6
+ const FREE_GRID_ELEMENTS = [{
7
+ actionType: "addText",
8
+ label: "Text",
9
+ icon: "text"
10
+ }, {
11
+ actionType: "addButton",
12
+ label: "Button",
13
+ icon: "button"
14
+ }, {
15
+ actionType: "addImage",
16
+ label: "Image",
17
+ icon: "image"
18
+ }, {
19
+ actionType: "addVideo",
20
+ label: "Embed or Video",
21
+ icon: "embed"
22
+ }, {
23
+ actionType: "addBox",
24
+ label: "Box",
25
+ icon: "colorbox"
26
+ }, {
27
+ actionType: "addTable",
28
+ label: "Table",
29
+ icon: "table"
30
+ }, {
31
+ actionType: "addCode",
32
+ label: "Code",
33
+ icon: "embedScript"
34
+ }, {
35
+ actionType: "addForm",
36
+ label: "Form",
37
+ icon: "form"
38
+ }, {
39
+ actionType: "addAppHeader",
40
+ label: "App Header",
41
+ icon: "appHeader"
42
+ }];
5
43
  const AddElement = props => {
6
44
  const {
7
45
  handleClick
8
46
  } = props;
9
47
  return /*#__PURE__*/_jsx(Box, {
10
- children: /*#__PURE__*/_jsxs(List, {
48
+ children: /*#__PURE__*/_jsx(List, {
11
49
  className: "item-list-wrpr",
12
- children: [/*#__PURE__*/_jsx(ListItemButton, {
13
- className: "item-wrapper",
14
- onClick: handleClick("addText"),
15
- children: "Text"
16
- }), /*#__PURE__*/_jsx(ListItemButton, {
17
- className: "item-wrapper",
18
- onClick: handleClick("addButton"),
19
- children: "Button"
20
- }), /*#__PURE__*/_jsx(ListItemButton, {
21
- className: "item-wrapper",
22
- onClick: handleClick("addImage"),
23
- children: "Image"
24
- }), /*#__PURE__*/_jsx(ListItemButton, {
25
- className: "item-wrapper",
26
- onClick: handleClick("addVideo"),
27
- children: "Embed or Video"
28
- }), /*#__PURE__*/_jsx(ListItemButton, {
29
- className: "item-wrapper",
30
- onClick: handleClick("addTable"),
31
- children: "Table"
32
- }), /*#__PURE__*/_jsx(ListItemButton, {
33
- className: "item-wrapper",
34
- onClick: handleClick("addCode"),
35
- children: "Code"
36
- }), /*#__PURE__*/_jsx(ListItemButton, {
37
- className: "item-wrapper",
38
- onClick: handleClick("addBox"),
39
- children: "Box"
40
- }), /*#__PURE__*/_jsx(ListItemButton, {
41
- className: "item-wrapper",
42
- onClick: handleClick("addForm"),
43
- children: "Form"
44
- }), /*#__PURE__*/_jsx(ListItemButton, {
45
- className: "item-wrapper",
46
- onClick: handleClick("addAppHeader"),
47
- children: "App Header"
48
- })]
50
+ children: FREE_GRID_ELEMENTS.map(m => {
51
+ return /*#__PURE__*/_jsxs(ListItemButton, {
52
+ className: "item-wrapper",
53
+ onClick: handleClick(m.actionType),
54
+ children: [/*#__PURE__*/_jsx(ListItemIcon, {
55
+ children: /*#__PURE__*/_jsx(Icon, {
56
+ icon: m.icon
57
+ })
58
+ }), /*#__PURE__*/_jsx(ListItemText, {
59
+ children: m.label
60
+ })]
61
+ }, m.actionType);
62
+ })
49
63
  })
50
64
  });
51
65
  };
@@ -8,7 +8,8 @@ const SectionSettings = props => {
8
8
  const {
9
9
  editor,
10
10
  path,
11
- classes
11
+ classes,
12
+ customProps
12
13
  } = props;
13
14
  const element = Node.get(editor, path);
14
15
  const styleMaps = sectionStyle?.filter(f => !f?.hideOnFGS);
@@ -38,7 +39,7 @@ const SectionSettings = props => {
38
39
  value: m.value,
39
40
  element: element,
40
41
  onChange: onChange,
41
- customProps: {},
42
+ customProps: customProps,
42
43
  handleClose: handleClose
43
44
  }, `tab_${m.value}_$${i}`);
44
45
  })
@@ -194,6 +194,13 @@ const useFreeGridStyles = ({
194
194
  }
195
195
  },
196
196
  "& .fgi_type_table": {
197
+ overflowX: "auto",
198
+ "& table": {
199
+ "&.readOnly": {
200
+ tableLayout: "fixed",
201
+ width: "100% !important"
202
+ }
203
+ },
197
204
  "& .tableToolBar": {
198
205
  right: "0px",
199
206
  left: "auto",
@@ -1,7 +1,7 @@
1
1
  import React, { useState } from "react";
2
2
  import { Transforms } from "slate";
3
3
  import { useSelected, useSlateStatic } from "slate-react";
4
- import { Box, IconButton, Tooltip, Table as TableComp, TableBody } from "@mui/material";
4
+ import { Box, IconButton, Tooltip, Table as TableComp, TableBody, useTheme } from "@mui/material";
5
5
  import AlignHorizontalLeftIcon from "@mui/icons-material/AlignHorizontalLeft";
6
6
  import AlignHorizontalRightIcon from "@mui/icons-material/AlignHorizontalRight";
7
7
  import AlignVerticalTopIcon from "@mui/icons-material/AlignVerticalTop";
@@ -16,6 +16,7 @@ import TablePopup from "./TablePopup";
16
16
  import { useEditorSelection } from "../../hooks/useMouseMove";
17
17
  import TableStyles from "./Styles";
18
18
  import "./table.css";
19
+ import { groupByBreakpoint } from "../../helper/theme";
19
20
  import { jsx as _jsx } from "react/jsx-runtime";
20
21
  import { jsxs as _jsxs } from "react/jsx-runtime";
21
22
  const TABLE_MENUS = [{
@@ -72,6 +73,7 @@ const TABLE_MENUS = [{
72
73
  }
73
74
  }];
74
75
  const Table = props => {
76
+ const theme = useTheme();
75
77
  const {
76
78
  element,
77
79
  attributes,
@@ -86,7 +88,8 @@ const Table = props => {
86
88
  const [exandTools, setExpandTools] = useState(false);
87
89
  const {
88
90
  bgColor,
89
- borderColor
91
+ borderColor,
92
+ xsHidden
90
93
  } = element;
91
94
  const editor = useSlateStatic();
92
95
  const selected = useSelected();
@@ -174,6 +177,12 @@ const Table = props => {
174
177
  const onClose = () => {
175
178
  setOpenSettings(false);
176
179
  };
180
+ const tableSX = groupByBreakpoint({
181
+ display: {
182
+ xs: xsHidden ? "none" : "inline-block",
183
+ lg: "inline-block"
184
+ }
185
+ }, theme);
177
186
  return /*#__PURE__*/_jsxs("div", {
178
187
  style: {
179
188
  minWidth: "100%",
@@ -181,7 +190,11 @@ const Table = props => {
181
190
  position: "relative"
182
191
  },
183
192
  children: [/*#__PURE__*/_jsx(TableComp, {
184
- sx: classes.table,
193
+ className: readOnly ? "readOnly" : "",
194
+ sx: {
195
+ ...classes.table,
196
+ ...tableSX
197
+ },
185
198
  style: {
186
199
  background: bgColor,
187
200
  border: borderColor ? `1px solid ${borderColor}` : "",
@@ -289,6 +289,7 @@ const editorStyles = ({
289
289
  fullScreenWrapper: {
290
290
  "& .MuiPaper-root": {
291
291
  borderRadius: "0px !important",
292
+ paddingTop: '20px',
292
293
  "& .MuiDialogTitle-root": {
293
294
  position: "absolute",
294
295
  top: 0,
@@ -25,6 +25,7 @@ const FontLoader = props => {
25
25
  families: [...batchWithWeights]
26
26
  },
27
27
  classes: false,
28
+ timeout: 2000,
28
29
  active: () => {
29
30
  console.log(`Fonts loaded successfully: ${batch}`);
30
31
  currentIndex += batchSize;
@@ -78,7 +79,7 @@ const FontLoader = props => {
78
79
  families = Array.from(fontSet);
79
80
  loadFontsInBatches(families);
80
81
  }
81
- }, [readOnly, otherProps, setFontFamilies]);
82
+ }, []);
82
83
  return null;
83
84
  };
84
85
  export default FontLoader;
@@ -42,7 +42,7 @@ const DragOver = props => {
42
42
  horizontal: "center"
43
43
  },
44
44
  transformOrigin: {
45
- vertical: "top",
45
+ vertical: "bottom",
46
46
  horizontal: "center"
47
47
  },
48
48
  children: /*#__PURE__*/_jsx(Paper, {
@@ -25,8 +25,11 @@ const useOptionsPopupStyle = () => ({
25
25
  }
26
26
  },
27
27
  "& .item-wrapper": {
28
- padding: "12px",
28
+ padding: "8px",
29
29
  fontFamily: "sans-serif",
30
+ "& .MuiListItemIcon-root": {
31
+ minWidth: "30px"
32
+ },
30
33
  "&.title": {
31
34
  display: "flex",
32
35
  fontWeight: "bold",
@@ -5,6 +5,64 @@ import updateAutoProps from "./updateAutoProps";
5
5
  import { calculateGridArea } from "../Utils/gridDropItem";
6
6
  import { jsx as _jsx } from "react/jsx-runtime";
7
7
  const ROOT_ITEM_CLASS = ".freegrid-item.path-3";
8
+
9
+ // Function to group items by path and calculate heights
10
+ function groupByPathAndCalculateHeight(data) {
11
+ const root = {};
12
+ const heightData = {};
13
+
14
+ // Step 1: Group items based on their path
15
+ data.forEach(item => {
16
+ const segments = item.path.split("|");
17
+ let current = root;
18
+ segments.forEach((segment, index) => {
19
+ if (!current[segment]) {
20
+ current[segment] = {
21
+ children: {},
22
+ props: {
23
+ height: 0
24
+ }
25
+ };
26
+ }
27
+ if (index === segments.length - 1) {
28
+ // Assign the properties of the item including height
29
+ current[segment] = {
30
+ ...item,
31
+ children: current[segment].children
32
+ };
33
+ }
34
+ current = current[segment].children;
35
+ });
36
+ });
37
+
38
+ // Step 2: Recursively calculate the height of each parent based on children
39
+ const calculateHeight = node => {
40
+ if (!node.children || Object.keys(node.children).length === 0) {
41
+ // Base case: If there are no children, return the node's height
42
+ return node.props.height;
43
+ }
44
+
45
+ // Calculate the height by summing the heights of all children
46
+ let totalHeight = 0;
47
+ Object.values(node.children).forEach(child => {
48
+ totalHeight += calculateHeight(child);
49
+ });
50
+
51
+ // Update the parent's height to be the total height of its children
52
+ node.props.height = totalHeight;
53
+ if (node?.path) {
54
+ heightData[node.path] = totalHeight;
55
+ }
56
+ return totalHeight;
57
+ };
58
+
59
+ // Start calculation from the root
60
+ Object.values(root).forEach(node => calculateHeight(node));
61
+ return {
62
+ root,
63
+ heightData
64
+ };
65
+ }
8
66
  const VirtualElement = props => {
9
67
  const classes = useVirtualElementStyles();
10
68
  const {
@@ -19,9 +77,10 @@ const VirtualElement = props => {
19
77
  if (virtualRef?.current) {
20
78
  setTimeout(() => {
21
79
  const allData = calculateProps(path, virtualRef?.current, ROOT_ITEM_CLASS, []);
80
+ const groupData = groupByPathAndCalculateHeight(allData);
22
81
  // it should trigger by auto alignment or on clicking mobile view change
23
- updateAutoProps(editor, allData, "xs");
24
- }, 0);
82
+ updateAutoProps(editor, allData, "xs", groupData);
83
+ }, 100);
25
84
  }
26
85
  }, [updated_at, virtualRef?.current]);
27
86
  const calculateProps = (curPath, dom, domClass, allData) => {
@@ -35,11 +94,12 @@ const VirtualElement = props => {
35
94
  };
36
95
  const itemsData = [];
37
96
  const items = dom.querySelectorAll(domClass);
38
- let sectionHeight = 0;
97
+ const nextItemPathLength = curPath?.split("|").length + 2;
98
+ let sectionHeight = 12;
39
99
  for (let i = 0; i < items.length; i++) {
40
100
  const itemRect = items[i]?.getBoundingClientRect();
41
101
  if (items[i]?.classList.contains("type_box")) {
42
- allData = calculateProps(items[i]?.dataset.path, items[i], ".freegrid-item", allData);
102
+ allData = calculateProps(items[i]?.dataset.path, items[i], `.freegrid-item.path-${nextItemPathLength}`, allData);
43
103
  } else {
44
104
  const y = Math.abs(rect.top - itemRect?.top);
45
105
  itemsData.push({
@@ -10,6 +10,7 @@ const useVirtualElementStyles = () => ({
10
10
  right: 0,
11
11
  top: 0,
12
12
  "& .freegrid-item": {
13
+ position: "relative !important",
13
14
  gridArea: "none !important",
14
15
  width: "calc(100% - 48px) !important",
15
16
  height: "auto !important",
@@ -1,6 +1,7 @@
1
1
  import { Node, Transforms } from "slate";
2
- const updateAutoProps = (editor, datas = [], breakpoint = "") => {
2
+ const updateAutoProps = (editor, datas = [], breakpoint = "", groupData) => {
3
3
  try {
4
+ // const { heightData } = groupData;
4
5
  for (let i = 0; i < datas.length; i++) {
5
6
  const {
6
7
  path,
@@ -22,7 +22,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
22
22
  import { jsxs as _jsxs } from "react/jsx-runtime";
23
23
  import { Fragment as _Fragment } from "react/jsx-runtime";
24
24
  const ITEM_TYPES = ["child", "parent-container"];
25
- const EDIT_MODES = ["text", "form"];
25
+ const EDIT_MODES = ["text", "form", "table"];
26
26
  let hover_on = new Set();
27
27
  const RnD = props => {
28
28
  const rndRef = useRef(null);
@@ -24,6 +24,10 @@ const embedVideoStyle = [{
24
24
  tab: "Border",
25
25
  value: "border",
26
26
  fields: [{
27
+ label: "Background Color",
28
+ key: "bgColor",
29
+ type: "color"
30
+ }, {
27
31
  label: "Border Color",
28
32
  key: "borderColor",
29
33
  type: "color"
@@ -56,5 +60,13 @@ const embedVideoStyle = [{
56
60
  });
57
61
  }
58
62
  }]
63
+ }, {
64
+ tab: "Banner Spacing",
65
+ value: "bannerSpacing",
66
+ fields: [{
67
+ label: "Banner Spacing",
68
+ key: "bannerSpacing",
69
+ type: "bannerSpacing"
70
+ }]
59
71
  }];
60
72
  export default embedVideoStyle;
@@ -38,5 +38,14 @@ const tableStyle = [{
38
38
  key: "col.borderColor",
39
39
  type: "color"
40
40
  }]
41
+ }, {
42
+ tab: "Visibility",
43
+ value: "visibility",
44
+ fields: [{
45
+ label: "Hide on Mobile",
46
+ key: "table.xsHidden",
47
+ type: "selectBox",
48
+ placeholder: "Hide on Mobile"
49
+ }]
41
50
  }];
42
51
  export default tableStyle;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flozy/editor",
3
- "version": "4.2.0",
3
+ "version": "4.2.2",
4
4
  "description": "An Editor for flozy app brain",
5
5
  "files": [
6
6
  "dist"