@flozy/editor 4.1.3 → 4.1.5

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.
@@ -426,16 +426,21 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
426
426
  };
427
427
  const handleCursorScroll = container => {
428
428
  try {
429
- const cursorPosition = window.getSelection()?.getRangeAt(0).getBoundingClientRect();
430
- const containerBottom = container.getBoundingClientRect().bottom;
431
- if (cursorPosition?.bottom > containerBottom - 250) {
432
- container.scrollBy({
433
- top: 200,
434
- behavior: "smooth"
435
- });
429
+ const selection = window?.getSelection();
430
+ if (selection && selection.rangeCount > 0) {
431
+ const cursorPosition = selection.getRangeAt(0)?.getBoundingClientRect();
432
+ const containerBottom = container?.getBoundingClientRect()?.bottom;
433
+ if (cursorPosition && cursorPosition.bottom > containerBottom - 250) {
434
+ container?.scrollBy({
435
+ top: 200,
436
+ behavior: "smooth"
437
+ });
438
+ }
439
+ } else {
440
+ console.warn('No valid selection range found');
436
441
  }
437
442
  } catch (err) {
438
- console.log(err);
443
+ console.log('handleCursorScroll', err);
439
444
  }
440
445
  };
441
446
  return /*#__PURE__*/_jsx(EditorProvider, {
@@ -923,7 +923,7 @@ blockquote {
923
923
  }
924
924
 
925
925
  .sliderInput {
926
- width: 30px;
926
+ width: 66px !important;
927
927
  padding: 2px 10px;
928
928
  margin-left: 18px;
929
929
  box-shadow: 0px 4px 16px 0px #0000000d;
@@ -32,6 +32,9 @@ const Styles = theme => ({
32
32
  color: "#000",
33
33
  fontSize: "14px !important",
34
34
  fontFamily: '"Inter", sans-serif',
35
+ "&:focus-visible": {
36
+ border: "none !important"
37
+ },
35
38
  "&::placeholder": {
36
39
  color: "#94A3B8",
37
40
  opacity: 1 /* Firefox */,
@@ -1,12 +1,12 @@
1
1
  import { useEffect, useRef, useState } from "react";
2
- import useDragDom from "../../../hooks/useDragDom";
3
2
  import { IconButton, Popper } from "@mui/material";
4
3
  import Box from "@mui/material/Box";
5
4
  import ContinuousSlider from "./Slider";
6
- import frames from ".";
7
5
  import { useEditorContext } from "../../../hooks/useMouseMove";
8
6
  import { CloseIcon } from "../../../common/iconslist";
7
+ import useDragDom from "../../../hooks/useDragDom";
9
8
  import FramesStyles from "./Styles";
9
+ import frames from ".";
10
10
  import { jsx as _jsx } from "react/jsx-runtime";
11
11
  import { jsxs as _jsxs } from "react/jsx-runtime";
12
12
  import { Fragment as _Fragment } from "react/jsx-runtime";
@@ -48,18 +48,28 @@ const ImageFrame = props => {
48
48
  const SVGFrame = frame ? frames[frame] : null;
49
49
  const {
50
50
  selectedPath,
51
- setSelectedPath
52
- } = useEditorContext();
53
- const open = selectedPath === id && Boolean(anchorEl);
54
- const {
55
- theme
51
+ setSelectedPath,
52
+ selectedElement,
53
+ theme,
54
+ setSelectedElement
56
55
  } = useEditorContext();
56
+ const freeGridItemPath = `${selectedElement?.path?.split("|")?.join(",")},0`;
57
+ const isFreegridSelection = freeGridItemPath === id;
58
+ const open = (selectedPath === id || isFreegridSelection) && Boolean(anchorEl);
57
59
  const classes = FramesStyles(theme);
58
60
  useEffect(() => {
59
61
  if (imageRef?.current && !readOnly) {
60
62
  setDOM(dom);
61
63
  }
62
64
  }, [imageRef]);
65
+ useEffect(() => {
66
+ if (svgRef?.current && selectedElement?.selectedAction === "imageFrame") {
67
+ const imageFrameDom = document.getElementById(`opt_ref_${selectedElement?.path}`);
68
+ setAnchorEl(imageFrameDom);
69
+ } else {
70
+ setAnchorEl(null);
71
+ }
72
+ }, [isFreegridSelection, svgRef?.current, selectedElement?.selectedAction]);
63
73
  useEffect(() => {
64
74
  if (event === "end" && !readOnly) {
65
75
  onChange({
@@ -97,6 +107,11 @@ const ImageFrame = props => {
97
107
  const handleClose = () => {
98
108
  setAnchorEl(null);
99
109
  setSelectedPath(null);
110
+ setSelectedElement({
111
+ ...selectedElement,
112
+ enable: 1,
113
+ selectedAction: null
114
+ });
100
115
  };
101
116
  return /*#__PURE__*/_jsxs(_Fragment, {
102
117
  children: [/*#__PURE__*/_jsx(SVGFrame, {
@@ -118,8 +133,8 @@ const ImageFrame = props => {
118
133
  sx: {
119
134
  zIndex: 100
120
135
  },
121
- placement: "top",
122
- disablePortal: true,
136
+ placement: isFreegridSelection ? "bottom" : "top",
137
+ disablePortal: false,
123
138
  children: /*#__PURE__*/_jsxs(Box, {
124
139
  sx: classes?.sliderContainer,
125
140
  children: [/*#__PURE__*/_jsx(ContinuousSlider, {
@@ -295,6 +295,7 @@ const Image = ({
295
295
  id: path.join(","),
296
296
  onChange: onPosChange,
297
297
  readOnly: readOnly,
298
+ editor: editor,
298
299
  handleImageClick: handleImageClick
299
300
  })
300
301
  }) : null, selected && !readOnly && /*#__PURE__*/_jsx(IconButton, {
@@ -1,7 +1,7 @@
1
1
  const commonOptions = ["drag", "edit", "settings", "saveAsTemplate", "close"];
2
2
  const textOptions = ["edit", "settings", "link", "saveAsTemplate", "close"];
3
3
  const buttonOptions = ["settings", "link", "saveAsTemplate", "close"];
4
- const imageOptions = ["settings", "link", "saveAsTemplate", "close"];
4
+ const imageOptions = ["settings", "link", "imageFrame", "saveAsTemplate", "close"];
5
5
  const boxOptions = ["settings", "link", "saveAsTemplate", "close"];
6
6
  const appHeaderOptions = ["settings", "saveAsTemplate", "close"];
7
7
  const tableOptions = ["drag", "edit", "settings", "saveAsTemplate", "close"];
@@ -96,6 +96,11 @@ const useFreeGridStyles = ({
96
96
  "& .default-toolbar": {
97
97
  display: "block"
98
98
  }
99
+ },
100
+ "& .fgi_type_image": {
101
+ "& .visible-on-hover": {
102
+ display: "none !important"
103
+ }
99
104
  }
100
105
  },
101
106
  /** for element items */
@@ -206,6 +211,11 @@ const useFreeGridStyles = ({
206
211
  backgroundColor: "#FFF",
207
212
  overflow: "hidden"
208
213
  },
214
+ "& .fgi_type_text": {
215
+ "& .edt-headings": {
216
+ margin: "0px"
217
+ }
218
+ },
209
219
  /** element toolbar hide */
210
220
  "& .element-toolbar": {
211
221
  display: "none"
@@ -35,7 +35,7 @@ const FullViewCard = props => {
35
35
  sx: classes.paperOverrides,
36
36
  className: "paperOverrides",
37
37
  children: /*#__PURE__*/_jsx(Box, {
38
- sx: classes.buttonCardMediaWrpr,
38
+ sx: classes.fullViewCardMediaWrpr,
39
39
  onClick: onSelectTemplate(m),
40
40
  children: /*#__PURE__*/_jsx("div", {
41
41
  className: "img-wrapper",
@@ -511,17 +511,17 @@ const usePopupStyle = theme => ({
511
511
  }
512
512
  },
513
513
  buttonCardMediaWrpr: {
514
- padding: "5px",
514
+ padding: '5px',
515
515
  position: "relative",
516
516
  margin: "8px",
517
- marginBottom: "0px",
518
- "& .img-wrapper": {
517
+ height: "50px",
518
+ '& .img-wrapper': {
519
519
  "&:hover": {
520
- padding: "0px 2px 0px 2px",
521
- backgroundColor: "#E9F3FE",
522
- border: "1px solid #2563EB40",
523
- borderRadius: "5px",
524
- height: "100%",
520
+ padding: '0px 2px 0px 2px',
521
+ backgroundColor: '#E9F3FE',
522
+ border: '1px solid #2563EB40',
523
+ borderRadius: '5px',
524
+ // height: "100%",
525
525
  margin: "0px"
526
526
  // "& .template-card-action": {
527
527
  // display: "flex",
@@ -643,6 +643,21 @@ const usePopupStyle = theme => ({
643
643
  "& fieldset": {
644
644
  border: "none !important"
645
645
  }
646
+ },
647
+ fullViewCardMediaWrpr: {
648
+ padding: '5px',
649
+ position: "relative",
650
+ margin: "8px",
651
+ height: "140px",
652
+ '& .img-wrapper': {
653
+ "&:hover": {
654
+ padding: '0px 2px 0px 2px',
655
+ backgroundColor: '#E9F3FE',
656
+ border: '1px solid #2563EB40',
657
+ borderRadius: '5px',
658
+ margin: "0px"
659
+ }
660
+ }
646
661
  }
647
662
  });
648
663
  export default usePopupStyle;
@@ -14,11 +14,11 @@ const FontLoader = props => {
14
14
  let currentIndex = 0;
15
15
  let retryCount = 0;
16
16
  function loadNextBatch() {
17
- if (currentIndex >= families.length) {
17
+ if (currentIndex >= families?.length) {
18
18
  console.log('All fonts have been loaded');
19
19
  return;
20
20
  }
21
- const batch = families.slice(currentIndex, currentIndex + batchSize);
21
+ const batch = families?.slice(currentIndex, currentIndex + batchSize);
22
22
  const batchWithWeights = batch.map(font => `${font}:300,400,600,700`);
23
23
  WebFont.load({
24
24
  google: {
@@ -52,11 +52,11 @@ const FontLoader = props => {
52
52
  return fontFamily.replace(/\\/g, '').replace(/['"]/g, '');
53
53
  };
54
54
  useEffect(() => {
55
- let families = ["PoppinsRegular"];
55
+ let families = [...defaultFonts];
56
56
  if (!readOnly) {
57
- otherProps.services("listGoogleFont", []).then(data => {
58
- families = [...defaultFonts, ...(data?.data || ['PoppinsRegular'])];
59
- const filteredfamilies = families.filter(font => !font.includes("Material"));
57
+ otherProps?.services("listGoogleFont", []).then(data => {
58
+ families = [...families, ...(data?.data || [])];
59
+ const filteredfamilies = families?.filter(font => !font?.includes("Material"));
60
60
  setFontFamilies({
61
61
  id: 1,
62
62
  format: "fontFamily",
@@ -68,11 +68,11 @@ const FontLoader = props => {
68
68
  console.log(err);
69
69
  });
70
70
  } else {
71
- const elements = Array.from(document.querySelectorAll("*"));
71
+ const elements = Array.from(document?.querySelectorAll("*"));
72
72
  const fontSet = new Set();
73
73
  elements.forEach(element => {
74
- const computedStyles = window.getComputedStyle(element);
75
- fontSet.add(sanitizeFontFamily(computedStyles.fontFamily));
74
+ const computedStyles = window?.getComputedStyle(element);
75
+ fontSet.add(sanitizeFontFamily(computedStyles?.fontFamily));
76
76
  });
77
77
  families = Array.from(fontSet);
78
78
  loadFontsInBatches(families);
@@ -11,6 +11,7 @@ import ArrowDownwardIcon from "@mui/icons-material/ArrowDownward";
11
11
  import SaveIcon from "@mui/icons-material/Save";
12
12
  import LinkIcon from "./Icons/LinkIcon";
13
13
  import CodeIcon from "@mui/icons-material/Code";
14
+ import FilterFramesIcon from "@mui/icons-material/FilterFrames";
14
15
  import { GridAddSectionIcon, WorkflowIcon } from "../../iconslist";
15
16
  const Actions = {
16
17
  ai: {
@@ -104,6 +105,12 @@ const Actions = {
104
105
  Button: IconButton,
105
106
  Icon: SaveIcon,
106
107
  title: "Save As Template"
108
+ },
109
+ imageFrame: {
110
+ type: "imageFrame",
111
+ Button: IconButton,
112
+ Icon: FilterFramesIcon,
113
+ title: "Image Frame Settings"
107
114
  }
108
115
  };
109
116
  export default Actions;
@@ -18,43 +18,54 @@ const VirtualElement = props => {
18
18
  useEffect(() => {
19
19
  if (virtualRef?.current) {
20
20
  setTimeout(() => {
21
- calculateProps();
21
+ const allData = calculateProps(path, virtualRef?.current, ROOT_ITEM_CLASS, []);
22
+ console.log(allData);
23
+ // it should trigger by auto alignment or on clicking mobile view change
24
+ updateAutoProps(editor, allData, "xs");
22
25
  }, 0);
23
26
  }
24
27
  }, [updated_at, virtualRef?.current]);
25
- const calculateProps = () => {
26
- const rect = virtualRef?.current?.getBoundingClientRect();
28
+ const calculateProps = (curPath, dom, domClass, allData) => {
29
+ const rect = dom?.getBoundingClientRect();
30
+ const sectionRect = virtualRef?.current?.getBoundingClientRect();
27
31
  const sectionProps = {
28
- path,
32
+ path: curPath,
29
33
  props: {
30
34
  height: rect.height
31
35
  }
32
36
  };
33
37
  const itemsData = [];
34
- const items = virtualRef?.current?.querySelectorAll(ROOT_ITEM_CLASS);
38
+ const items = dom.querySelectorAll(domClass);
35
39
  let sectionHeight = 0;
36
40
  for (let i = 0; i < items.length; i++) {
37
41
  const itemRect = items[i]?.getBoundingClientRect();
38
- const y = Math.abs(rect.top - itemRect?.top);
39
- itemsData.push({
40
- path: items[i]?.dataset.path,
41
- props: {
42
- top: y,
43
- left: 24,
44
- marginTop: 12,
45
- width: itemRect?.width,
46
- height: itemRect?.height,
47
- gridArea: calculateGridArea(y)
48
- }
49
- });
50
- sectionHeight += itemRect?.height;
42
+ if (items[i]?.classList.contains("type_box")) {
43
+ allData = calculateProps(items[i]?.dataset.path, items[i], ".freegrid-item", allData);
44
+ } else {
45
+ const y = Math.abs(rect.top - itemRect?.top);
46
+ itemsData.push({
47
+ path: items[i]?.dataset.path,
48
+ props: {
49
+ top: y,
50
+ left: 24,
51
+ marginTop: 12,
52
+ width: itemRect?.width,
53
+ height: itemRect?.height,
54
+ gridArea: calculateGridArea(y)
55
+ }
56
+ });
57
+ sectionHeight += itemRect?.height;
58
+ }
59
+ }
60
+ if (dom?.classList.contains("type_box")) {
61
+ const y = Math.abs(sectionRect.top - rect?.top);
62
+ sectionProps.props.gridArea = calculateGridArea(y);
51
63
  }
52
64
  if (sectionHeight > sectionProps?.props?.height) {
53
65
  sectionProps.props.height = sectionHeight;
54
66
  }
55
- const allData = [sectionProps, itemsData]?.flat();
56
- // it should trigger by auto alignment or on clicking mobile view change
57
- updateAutoProps(editor, allData, "xs");
67
+ allData = [sectionProps, [...allData, ...itemsData]]?.flat();
68
+ return allData;
58
69
  };
59
70
  const getItems = () => {
60
71
  const items = cloneNode?.querySelectorAll(ROOT_ITEM_CLASS) || [];
@@ -236,6 +236,14 @@ const RnD = props => {
236
236
  selectedActionPath: path
237
237
  });
238
238
  break;
239
+ case "imageFrame":
240
+ setSelectedElement({
241
+ ...selectedElementProps,
242
+ enable: 2,
243
+ selectedAction: actionType,
244
+ selectedActionPath: path
245
+ });
246
+ break;
239
247
  case "saveAsTemplate":
240
248
  const curPath = type === "parent" ? Path.parent(path) : path;
241
249
  const currentNode = Node.get(editor, curPath);
@@ -136,7 +136,7 @@ const BannerSpacing = props => {
136
136
  type: "number",
137
137
  name: "top",
138
138
  value: pro_value?.top,
139
- className: "borderInput",
139
+ className: "borderInput removeScroll",
140
140
  style: {
141
141
  ...squreStyle.topRight
142
142
  },
@@ -149,7 +149,7 @@ const BannerSpacing = props => {
149
149
  type: "number",
150
150
  name: "right",
151
151
  value: pro_value?.right,
152
- className: "borderInput",
152
+ className: "borderInput removeScroll",
153
153
  style: {
154
154
  ...squreStyle.bottomLeft
155
155
  },
@@ -162,7 +162,7 @@ const BannerSpacing = props => {
162
162
  type: "number",
163
163
  name: "bottom",
164
164
  value: pro_value?.bottom,
165
- className: "borderInput",
165
+ className: "borderInput removeScroll",
166
166
  style: {
167
167
  ...squreStyle.bottomRight
168
168
  },
@@ -174,8 +174,8 @@ const BannerSpacing = props => {
174
174
  children: /*#__PURE__*/_jsx("input", {
175
175
  type: "number",
176
176
  name: "left",
177
- className: "borderInput",
178
177
  value: pro_value?.left,
178
+ className: "borderInput removeScroll",
179
179
  style: {
180
180
  ...squreStyle.topLeft
181
181
  },
@@ -257,7 +257,7 @@ export const getBlock = props => {
257
257
  return /*#__PURE__*/_jsx("h1", {
258
258
  ...attributes,
259
259
  ...element.attr,
260
- className: `content-editable ${isEmpty ? "empty" : ""}`,
260
+ className: `edt-headings content-editable ${isEmpty ? "empty" : ""}`,
261
261
  placeholder: "Heading 1",
262
262
  children: children
263
263
  });
@@ -265,7 +265,7 @@ export const getBlock = props => {
265
265
  return /*#__PURE__*/_jsx("h2", {
266
266
  ...attributes,
267
267
  ...element.attr,
268
- className: `content-editable ${isEmpty ? "empty" : ""}`,
268
+ className: `edt-headings content-editable ${isEmpty ? "empty" : ""}`,
269
269
  placeholder: "Heading 2",
270
270
  children: children
271
271
  });
@@ -273,7 +273,7 @@ export const getBlock = props => {
273
273
  return /*#__PURE__*/_jsx("h3", {
274
274
  ...attributes,
275
275
  ...element.attr,
276
- className: `content-editable ${isEmpty ? "empty" : ""}`,
276
+ className: `edt-headings content-editable ${isEmpty ? "empty" : ""}`,
277
277
  placeholder: "Heading 3",
278
278
  children: children
279
279
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flozy/editor",
3
- "version": "4.1.3",
3
+ "version": "4.1.5",
4
4
  "description": "An Editor for flozy app brain",
5
5
  "files": [
6
6
  "dist"