@flozy/editor 4.1.3 → 4.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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"