@flozy/editor 4.4.9 → 4.5.0

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.
@@ -27,7 +27,7 @@ import DragAndDrop from "./common/DnD";
27
27
  import Section from "./common/Section";
28
28
  import decorators from "./utils/Decorators";
29
29
  import { getTRBLBreakPoints } from "./helper/theme";
30
- import { handleInsertLastElement, isFreeGridFragment, outsideEditorClickLabel } from "./utils/helper";
30
+ import { handleInsertLastElement, isFreeGrid, isFreeGridFragment, outsideEditorClickLabel } from "./utils/helper";
31
31
  import useWindowResize from "./hooks/useWindowResize";
32
32
  import PopoverAIInput from "./Elements/AI/PopoverAIInput";
33
33
  import RnDCopy from "./common/RnD/RnDCopy";
@@ -82,7 +82,6 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
82
82
  onSave,
83
83
  editor: collaborativeEditor,
84
84
  readOnly,
85
- toolbarOptions,
86
85
  otherProps,
87
86
  isIframe,
88
87
  theme,
@@ -288,10 +287,11 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
288
287
  index,
289
288
  type
290
289
  } = mentions;
291
- const chars = type ? Shorthands[type]({
290
+ const updatedHideTools = !isFreeGrid(content) ? [...hideTools, "freegrid"] : hideTools;
291
+ const chars = type && !isFreeGrid(content) ? Shorthands[type]({
292
292
  ...mentions,
293
293
  CHARACTERS,
294
- hideTools: hideTools || []
294
+ hideTools: updatedHideTools || []
295
295
  }) : [];
296
296
  const handleEditorChange = newValue => {
297
297
  setValue(newValue);
@@ -370,7 +370,7 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
370
370
  } else if (event.key === "ArrowDown" && otherProps?.tagName !== 'Pages') {
371
371
  upDownArrowKeyEvents(event, editor);
372
372
  }
373
- }, [chars, editor, target, mentions, setMentions, search, type, mentionsRef]);
373
+ }, [chars, target, mentions, setMentions, search, type, mentionsRef]);
374
374
  const Overlay = collaborativeEditor && !isReadOnly ? RemoteCursorOverlay : React.Fragment;
375
375
  const dotBg = needDotsBG ? {
376
376
  background: "white",
@@ -499,6 +499,8 @@ const FreeGrid = props => {
499
499
  backgroundSize: "cover"
500
500
  },
501
501
  "data-path": path.join("|"),
502
+ "data-dragOverId": path.join("|"),
503
+ "data-dragOverType": "parent",
502
504
  style: {
503
505
  "--cols": `100%`,
504
506
  "--rows": `repeat(${repeatTimes}, ${ROW_HEIGHT}px)`
@@ -190,6 +190,8 @@ const FreeGridBox = props => {
190
190
  ...attributes,
191
191
  className: "fgi_type_box freegrid-container-parent",
192
192
  "data-path": path.join("|"),
193
+ "data-dragOverId": path.join("|"),
194
+ "data-dragOverType": "parent",
193
195
  style: {
194
196
  "--height": `${height}px`,
195
197
  "--cols": `100%`,
@@ -20,6 +20,9 @@ const useFreeGridStyles = ({
20
20
  marginLeft: `calc((100% - ${MAX_DEVICE_WIDTH}px) * 0.5)`,
21
21
  "&.active-drag": {
22
22
  pointerEvents: "none",
23
+ "& *": {
24
+ pointerEvents: "none"
25
+ },
23
26
  zIndex: "9999 !important"
24
27
  },
25
28
  "&.inactive-drag": {
@@ -206,9 +209,26 @@ const useFreeGridStyles = ({
206
209
  "& .freegrid-item": {
207
210
  marginLeft: "0px"
208
211
  // pointerEvents: "none",
212
+ },
213
+
214
+ "&.rnd-dragOver": {
215
+ outline: "2px solid #116dff",
216
+ "&:before": {
217
+ content: '"Attach to Box"',
218
+ position: "absolute",
219
+ top: "-36px",
220
+ left: 0,
221
+ right: 0,
222
+ margin: "0px auto",
223
+ width: "fit-content",
224
+ background: "#116dff",
225
+ padding: "8px 12px",
226
+ color: "#FFF",
227
+ fontSize: "14px",
228
+ borderRadius: "7px"
229
+ }
209
230
  }
210
231
  },
211
-
212
232
  "& .fgi_type_form": {
213
233
  "& .form-field": {
214
234
  "& input": {
@@ -289,6 +309,22 @@ const useFreeGridStyles = ({
289
309
  [theme.breakpoints.between("xs", "md")]: {
290
310
  marginLeft: `calc((100% - 320px) * 0.5)`
291
311
  }
312
+ },
313
+ "&.rnd-dragOver": {
314
+ "&:before": {
315
+ content: '"Attact to this Section"',
316
+ position: "absolute",
317
+ top: 0,
318
+ left: 0,
319
+ right: 0,
320
+ margin: "0px auto",
321
+ width: "fit-content",
322
+ background: "#116dff",
323
+ padding: "8px 12px",
324
+ color: "#FFF",
325
+ fontSize: "14px",
326
+ borderRadius: "7px"
327
+ }
292
328
  }
293
329
  }
294
330
  },
@@ -17,7 +17,6 @@ const DragOver = props => {
17
17
  const open = Boolean(anchorEl);
18
18
  const isSectionHover = status && type === "parent";
19
19
  const isContainerHover = hover_on === path && type === "parent-container";
20
- console.log(isSectionHover, isContainerHover);
21
20
  useEffect(() => {
22
21
  if (ref?.current) {
23
22
  const getBoundingClientRect = () => ref?.current?.getBoundingClientRect();
@@ -11,13 +11,14 @@ import DragInfo from "./DragInfo";
11
11
  import GuideLines from "./GuideLines";
12
12
  import ShadowElement from "./ShadowElement";
13
13
  import BoundaryLine from "./GuideLines/BoundaryLine";
14
- import DragOver from "./DragOver";
15
14
  import ContextMenu from "./ContextMenu";
16
15
  import VirtualElement from "./VirtualElement";
17
16
  import { ItemTypes } from "./ElementSettings/settingsConstants";
18
17
  import { focusSelection, clearSelection } from "../../helper";
19
18
  import { selectText } from "../../utils/helper";
20
19
  import { removeSign } from "./ElementSettings/OtherSettings";
20
+ import useDragging from "../../hooks/useDragging";
21
+ import { dragOverOn } from "../../helper/RnD/focusNode";
21
22
  import { jsx as _jsx } from "react/jsx-runtime";
22
23
  import { jsxs as _jsxs } from "react/jsx-runtime";
23
24
  import { Fragment as _Fragment } from "react/jsx-runtime";
@@ -58,7 +59,6 @@ const RnD = props => {
58
59
  const {
59
60
  isSelectedElement,
60
61
  setSelectedElement,
61
- dragging,
62
62
  updateDragging,
63
63
  contextMenu,
64
64
  setContextMenu,
@@ -76,21 +76,25 @@ const RnD = props => {
76
76
  const open = Boolean(enable);
77
77
  const currentAction = str_path === sp ? selectedAction : null;
78
78
  const positionRef = useRef();
79
+ const {
80
+ draggingRef,
81
+ startDragging,
82
+ stopDragging,
83
+ setDragOver
84
+ } = useDragging();
85
+ const dragging = draggingRef?.current;
79
86
  const {
80
87
  active,
81
88
  id,
82
- parentPath,
83
- dragOver
89
+ parentPath
84
90
  } = dragging;
85
91
  const dragInfoOpen = id === str_path;
86
- const dragOverStatus = dragOver === str_path && parentPath !== str_path;
87
92
  const [absPosition, setAbsPosition] = useState({});
88
93
  const openContextMenu = contextMenu?.path === str_path;
89
94
  const [position, setPosition] = useState({
90
95
  x: 0,
91
96
  y: 0
92
97
  });
93
- const pathIsDragging = dragOver === str_path && dragging?.isDragging;
94
98
  const parentSectionPath = str_path?.split("|").slice(0, 2).join("_");
95
99
  useEffect(() => {
96
100
  if (ITEM_TYPES.includes(type)) {
@@ -156,7 +160,6 @@ const RnD = props => {
156
160
  switch (e.detail) {
157
161
  case 1:
158
162
  if (!enable) {
159
- // focusSelection(editor, { path });
160
163
  setSelectedElement({
161
164
  path: str_path,
162
165
  enable: 1,
@@ -164,6 +167,7 @@ const RnD = props => {
164
167
  anchorEl: rndRef?.current
165
168
  });
166
169
  }
170
+ // ReactEditor.focus(editor);
167
171
  break;
168
172
  case 2:
169
173
  focusSelection(editor, {
@@ -281,9 +285,8 @@ const RnD = props => {
281
285
  dragOver: null
282
286
  }, null);
283
287
  }
284
- // focusSelection(editor, { path: updated_at });
288
+ stopDragging();
285
289
  };
286
-
287
290
  const onDragStart = e => {
288
291
  e.preventDefault();
289
292
  if (e?.target?.dataset?.path?.split(",").join("|") === sp) {
@@ -301,6 +304,9 @@ const RnD = props => {
301
304
  diffX: parseInt(Math.abs(Math.floor(left - e.clientX))),
302
305
  diffY: parseInt(Math.abs(Math.floor(top - e.clientY)))
303
306
  };
307
+ const parentPath = getParentSectionPath({
308
+ ref
309
+ }, ".freegrid-container-parent");
304
310
  updateDragging({
305
311
  ...dragging,
306
312
  active: true,
@@ -312,17 +318,24 @@ const RnD = props => {
312
318
  width,
313
319
  height
314
320
  },
315
- isDragging: true,
316
- parentPath: getParentSectionPath({
317
- ref
318
- }, ".freegrid-container-parent")
321
+ isDragging: 1,
322
+ parentPath
319
323
  });
320
324
  setPosition({
321
325
  ...updatedPosition
322
326
  });
327
+ startDragging({
328
+ active: true,
329
+ id: str_path,
330
+ position: {
331
+ ...updatedPosition
332
+ },
333
+ isDragging: 1,
334
+ parentPath
335
+ });
323
336
  }
324
337
  };
325
- const onDrag = (e, d) => {
338
+ const onDrag = e => {
326
339
  e.preventDefault();
327
340
  const lines = getClosestDraggable(e.clientX, e.clientY, `.freegrid-section_${parentSectionPath} .freegrid-container .freegrid-item.inactive-drag`.replace(/\|/g, "\\|"), ".freegrid-item.active-drag:not(.exclude-virtual)");
328
341
  setAbsPosition({
@@ -330,7 +343,7 @@ const RnD = props => {
330
343
  "--zIndex": 2000
331
344
  });
332
345
  updateDragging({
333
- isDragging: true,
346
+ isDragging: 2,
334
347
  position: {
335
348
  ...dragging.position,
336
349
  x: e.clientX,
@@ -344,16 +357,34 @@ const RnD = props => {
344
357
  y: e.clientY,
345
358
  lines: lines
346
359
  });
360
+ const isDragOverOnParent = {};
361
+ let dragOverEle = e?.toElement?.dataset?.dragovertype !== "child" ? e?.toElement : e?.toElement?.closest(".freegrid-container-parent");
362
+
363
+ // some cases
364
+ if (dragOverEle?.dataset?.dragovertype === undefined) {
365
+ // means check for parent element
366
+ dragOverEle = e?.toElement?.parentElement;
367
+ }
368
+ if (dragOverEle?.dataset?.dragovertype !== "child") {
369
+ const oldPath = dragging.dragOver;
370
+ isDragOverOnParent.dragOver = dragOverEle?.dataset?.dragoverid;
371
+ isDragOverOnParent.dragOverType = dragOverEle?.dataset?.dragovertype;
372
+ dragOverOn(oldPath, dragOverEle?.dataset?.dragoverid);
373
+ }
374
+ startDragging({
375
+ isDragging: 2,
376
+ ...isDragOverOnParent
377
+ });
347
378
  };
348
379
  const onDragStop = (e, d) => {
349
380
  e.preventDefault();
350
381
  e.stopPropagation();
351
- if (dragging?.isDragging && dragging?.position?.strXY) {
382
+ if (dragging?.isDragging === 2 && dragging?.position?.strXY && dragging?.dragOver) {
352
383
  d.x = e.x;
353
384
  d.y = e.y;
354
385
  d.offsetX = e.offsetX;
355
386
  d.offsetY = e.offsetY;
356
- d.dragOver = dragOver;
387
+ d.dragOver = dragging?.dragOver;
357
388
  d.parentPath = parentPath;
358
389
  d.diffX = position?.diffX;
359
390
  d.diffY = position?.diffY;
@@ -381,6 +412,11 @@ const RnD = props => {
381
412
  setAbsPosition({
382
413
  ...ud
383
414
  });
415
+ stopDragging();
416
+ } else {
417
+ // invalid drags
418
+ // found in dev mode and in safari browser
419
+ onAfterDrop(path);
384
420
  }
385
421
  };
386
422
  const onResizeStop = (e, direction, ref, d, position) => {
@@ -431,6 +467,9 @@ const RnD = props => {
431
467
  e.stopPropagation();
432
468
  }
433
469
  if (type !== "child") {
470
+ setDragOver({
471
+ dragOver: str_path
472
+ });
434
473
  updateDragging({
435
474
  dragOver: str_path
436
475
  }, str_path);
@@ -504,14 +543,9 @@ const RnD = props => {
504
543
  "data-event": "rnd-click",
505
544
  className: "editor-blocker",
506
545
  "data-path": path,
507
- contentEditable: false
508
- }) : null, pathIsDragging ? /*#__PURE__*/_jsx(DragOver, {
509
- status: dragOverStatus,
510
- hover_on: dragOver,
511
- path: str_path,
512
- parentPath: parentPath,
513
- type: type,
514
- childType: childType
546
+ contentEditable: false,
547
+ "data-dragOverId": str_path,
548
+ "data-dragOverType": type
515
549
  }) : null]
516
550
  }, eId), !active && rndRef?.current && open ? /*#__PURE__*/_jsx(ElementOptions, {
517
551
  id: `opt_ref_${str_path}`,
@@ -55,15 +55,17 @@ const SectionStyle = theme => ({
55
55
  },
56
56
  "&.is-temp": {
57
57
  position: "fixed",
58
- background: "red",
58
+ background: "transparent",
59
59
  padding: "12px",
60
60
  width: "10px",
61
61
  height: "10px",
62
- // left: 0,
63
- // top: 0,
62
+ left: 0,
63
+ top: 0,
64
+ bottom: 0,
65
+ right: 0,
64
66
  margin: "auto",
65
- left: "var(--left)",
66
- top: "var(--top)",
67
+ // left: "var(--left)",
68
+ // top: "var(--top)",
67
69
  zIndex: 1000,
68
70
  pointerEvents: "none"
69
71
  }
@@ -17,6 +17,7 @@ const ensureTemporaryFocusNode = (editor, selectedDOM) => {
17
17
  type: "temp",
18
18
  temp: TEMP_NODE_ID,
19
19
  children: [{
20
+ type: "restrictedType",
20
21
  text: ""
21
22
  }],
22
23
  left,
@@ -24,22 +25,9 @@ const ensureTemporaryFocusNode = (editor, selectedDOM) => {
24
25
  }, {
25
26
  at: [editor.children.length]
26
27
  });
27
- } else {
28
- Transforms.setNodes(editor, {
29
- type: "temp",
30
- temp: TEMP_NODE_ID,
31
- children: [{
32
- text: ""
33
- }],
34
- left,
35
- top
36
- }, {
37
- at: tempNodeEntry[1]
38
- });
39
28
  }
40
29
  };
41
30
  export const focusUsingTemporaryNode = (editor, selectedDOM) => {
42
- // de-select and select
43
31
  Transforms.deselect(editor);
44
32
 
45
33
  // Ensure the temporary node exists
@@ -52,9 +40,8 @@ export const focusUsingTemporaryNode = (editor, selectedDOM) => {
52
40
  });
53
41
  if (tempNodeEntry) {
54
42
  const [, path] = tempNodeEntry;
55
- Transforms.select(editor, path); // Move selection to the temp node
43
+ Transforms.select(editor, path);
56
44
  }
57
-
58
45
  ReactEditor.focus(editor);
59
46
  };
60
47
  export const cleanupTemporaryFocusNode = editor => {
@@ -67,4 +54,21 @@ export const cleanupTemporaryFocusNode = editor => {
67
54
  at: path
68
55
  });
69
56
  }
57
+ };
58
+ export const dragOverOn = (previousPath, currentPath) => {
59
+ try {
60
+ const previousElement = document.querySelector(`[data-dragoverid="${previousPath}"]`);
61
+ const currentElement = document.querySelector(`[data-dragoverid="${currentPath}"]`);
62
+ // Remove 'dragOver' class from the current element, if it exists
63
+ if (previousElement && previousElement.classList.contains("rnd-dragOver")) {
64
+ previousElement.classList.remove("rnd-dragOver");
65
+ }
66
+
67
+ // Add 'dragOver' class to the new element
68
+ if (currentElement) {
69
+ currentElement.classList.add("rnd-dragOver");
70
+ }
71
+ } catch (err) {
72
+ console.log(err);
73
+ }
70
74
  };
@@ -0,0 +1,51 @@
1
+ import { useState, useCallback, useRef } from "react";
2
+ const initialState = {
3
+ id: null,
4
+ active: false,
5
+ isDragging: 0,
6
+ dragOver: false,
7
+ dragOverType: null
8
+ };
9
+ const useDragging = () => {
10
+ const [dragging, setDragging] = useState({
11
+ ...initialState
12
+ });
13
+
14
+ // Ref to keep the latest draggingStatus
15
+ const draggingRef = useRef(dragging);
16
+ const updateDragging = newStatus => {
17
+ setDragging(prevStatus => {
18
+ const updatedStatus = {
19
+ ...prevStatus,
20
+ ...newStatus
21
+ };
22
+ draggingRef.current = updatedStatus; // Update the ref to hold latest status
23
+ return updatedStatus;
24
+ });
25
+ };
26
+ const startDragging = useCallback(data => {
27
+ // console.log("dragissue", "startDragging");
28
+ updateDragging({
29
+ ...data
30
+ });
31
+ }, []);
32
+ const stopDragging = useCallback(() => {
33
+ // console.log("dragissue", "stopDragging");
34
+ updateDragging({
35
+ ...initialState
36
+ });
37
+ }, []);
38
+ const setDragOver = useCallback(isOver => {
39
+ updateDragging({
40
+ dragOver: isOver
41
+ });
42
+ }, []);
43
+ return {
44
+ dragging,
45
+ draggingRef,
46
+ startDragging,
47
+ stopDragging,
48
+ setDragOver
49
+ };
50
+ };
51
+ export default useDragging;
@@ -98,7 +98,11 @@ export const EditorProvider = ({
98
98
  updateDragging,
99
99
  fontFamilies,
100
100
  setFontFamilies
101
- }), [path, editor?.selection, selectedPath, selectedElement, dragging.active, dragging.isDragging, dragging.dragOver, contextMenu, openAI, popupType, drop, fontFamilies]);
101
+ }), [path, editor?.selection, selectedPath, selectedElement,
102
+ // dragging.active,
103
+ // dragging.isDragging,
104
+ // dragging.dragOver,
105
+ contextMenu, openAI, popupType, drop]);
102
106
  return /*#__PURE__*/_jsx(EditorContext.Provider, {
103
107
  value: otherValues,
104
108
  children: children
@@ -9,6 +9,7 @@ import withLayout from "../plugins/withLayout";
9
9
  import withHtml from "../plugins/withHTML";
10
10
  import withErrorHandling from "./withErrorHandling";
11
11
  import withCustomDeleteBackward from "../plugins/withCustomDeleteBackward";
12
+ import withRestrictedNodes from "./withRestrictedNodes";
12
13
  const withCommon = (props, rest = {}) => {
13
14
  return rest.needLayout ? withErrorHandling(withHtml(withEquation(withLayout(withHistory(withEmbeds(withTables(withLinks(withMentions(withCustomDeleteBackward(withReact(props))))))))))) : withErrorHandling(withHtml(withEquation(withHistory(withEmbeds(withTables(withLinks(withMentions(withCustomDeleteBackward(withReact(props))))))))));
14
15
  };
@@ -0,0 +1,48 @@
1
+ import { Editor } from "slate";
2
+
3
+ // Custom insertText that prevents updates in specific node types
4
+ const withRestrictedNodes = editor => {
5
+ const {
6
+ insertText,
7
+ deleteBackward
8
+ } = editor;
9
+
10
+ // Override insertText
11
+ editor.insertText = text => {
12
+ const {
13
+ selection
14
+ } = editor;
15
+ if (selection) {
16
+ const [node] = Editor.node(editor, selection);
17
+ console.log(node);
18
+
19
+ // Prevent insertText if node type matches
20
+ if (node && node.type === "restrictedType") {
21
+ return; // Skip inserting text
22
+ }
23
+ }
24
+
25
+ // Call the original insertText if node type does not match
26
+ insertText(text);
27
+ };
28
+
29
+ // Similarly override deleteBackward if needed
30
+ editor.deleteBackward = (...args) => {
31
+ const {
32
+ selection
33
+ } = editor;
34
+ if (selection) {
35
+ const [node] = Editor.node(editor, selection);
36
+
37
+ // Prevent deletion if node type matches
38
+ if (node && node.type === "restrictedType") {
39
+ return; // Skip deleting text
40
+ }
41
+ }
42
+
43
+ // Call the original deleteBackward if node type does not match
44
+ deleteBackward(...args);
45
+ };
46
+ return editor;
47
+ };
48
+ export default withRestrictedNodes;
@@ -157,7 +157,7 @@ const onBringBack = (event, {
157
157
  console.log(err);
158
158
  }
159
159
  };
160
- export const onInsertFragment = async ({
160
+ export const onInsertFragment = ({
161
161
  editor,
162
162
  slateNodes
163
163
  }) => {
@@ -181,6 +181,18 @@ export const onInsertFragment = async ({
181
181
  setSelectedElement: window.updateSelectedItem
182
182
  });
183
183
  }
184
+ } else {
185
+ // if no selection place items at last
186
+ const np = onPasteRnDNode(editor, {
187
+ path: [editor.children.length - 1, 0],
188
+ children: [],
189
+ slateNodes: slateNodes
190
+ });
191
+ if (np && window.updateSelectedItem) {
192
+ focusOnNewItem(editor, np, {
193
+ setSelectedElement: window.updateSelectedItem
194
+ });
195
+ }
184
196
  }
185
197
  } catch (err) {
186
198
  console.log(err);
@@ -543,8 +543,8 @@ export const getBlock = props => {
543
543
  return /*#__PURE__*/_jsx("span", {
544
544
  ...attributes,
545
545
  ...element.attr,
546
- contentEditable: false,
547
546
  className: "temp-focus-node",
547
+ contentEditable: false,
548
548
  children: children
549
549
  });
550
550
  default:
@@ -1,4 +1,4 @@
1
- import { Editor, Node, Transforms, Element } from "slate";
1
+ import { Editor, Node, Transforms, Element, Path } from "slate";
2
2
  import { ReactEditor } from "slate-react";
3
3
  import insertNewLine from "./insertNewLine";
4
4
  import { getDevice } from "../helper/theme";
@@ -470,4 +470,20 @@ export const editorThemeStyle = {
470
470
  };
471
471
  export const getEditorTheme = (themeType = "light") => {
472
472
  return editorThemeStyle[themeType] || {};
473
+ };
474
+ export const isFreeGrid = (nodes, types = ["freegrid", "freegridItem", "freegridBox"]) => {
475
+ try {
476
+ for (const node of nodes) {
477
+ if (types.includes(node.type)) {
478
+ return true;
479
+ }
480
+ if (node.children && isFreeGrid(node.children, types)) {
481
+ return true;
482
+ }
483
+ }
484
+ return false;
485
+ } catch (err) {
486
+ console.log('isFreeGrid error:', err);
487
+ return false;
488
+ }
473
489
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flozy/editor",
3
- "version": "4.4.9",
3
+ "version": "4.5.0",
4
4
  "description": "An Editor for flozy app brain",
5
5
  "files": [
6
6
  "dist"