@flozy/editor 4.2.0 → 4.2.2

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