@flozy/editor 10.6.0 → 10.6.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.
@@ -462,10 +462,11 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
462
462
  } else if (event.key === "ArrowDown" && otherProps?.tagName !== "Pages") {
463
463
  upDownArrowKeyEvents(event, editor);
464
464
  } else if (event.key === "Backspace") {
465
- const isAccordion = handleAccordionOnBackspace(event, editor);
466
- if (isAccordion) {
467
- return;
468
- }
465
+ // const isAccordion = handleAccordionOnBackspace(event, editor);
466
+ // if (isAccordion) {
467
+ // return;
468
+ // }
469
+
469
470
  const isNodeRestricted = isRestrictedNode(event, editor);
470
471
  if (isNodeRestricted) {
471
472
  return;
@@ -95,14 +95,13 @@ const Accordion = props => {
95
95
  } = useEditorContext();
96
96
  const classes = useCommonStyle(theme);
97
97
  useEffect(() => {
98
- if (!editor.selection || !children[1]) return;
98
+ if (!editor.selection) return;
99
99
  try {
100
- const accordionDetailsElement = element.children?.[1];
101
- const detailsPath = ReactEditor.findPath(editor, accordionDetailsElement);
100
+ const detailsPath = [...path, 1];
102
101
  const detailsRange = Editor.range(editor, detailsPath);
103
102
  const isInside = Range.intersection(detailsRange, editor.selection);
104
103
  if (isInside && !toggle) {
105
- setToggle(true);
104
+ setToggle(!toggle);
106
105
  }
107
106
  } catch (e) {
108
107
  console.error(e);
@@ -164,7 +164,10 @@ export default function LinkSettings(props) {
164
164
  setNav(navOption);
165
165
  setNavValue("");
166
166
  },
167
- translation: translation
167
+ translation: translation,
168
+ radioProps: {
169
+ disableRipple: true
170
+ }
168
171
  })
169
172
  })
170
173
  }), /*#__PURE__*/_jsx(Grid, {
@@ -124,14 +124,39 @@ const isOverLapLine = ({
124
124
  export function getClosestDraggable(x, y, className, activeClassName) {
125
125
  const draggables = document.querySelectorAll(className);
126
126
  const activeDragEle = document.querySelectorAll(activeClassName)[0];
127
+ const container = document.querySelector("#slate-wrapper-scroll-container");
128
+ if (!activeDragEle || !container) return [];
129
+ const containerRect = container.getBoundingClientRect();
127
130
  const {
128
131
  left: aLeft,
129
132
  top: aTop,
130
133
  width: aWidth,
131
134
  height: aHeight
132
135
  } = activeDragEle?.getBoundingClientRect() || {};
133
- let lines = [];
136
+ const lines = [];
137
+ const clampLine = ({
138
+ x,
139
+ y,
140
+ width,
141
+ height
142
+ }) => {
143
+ if (width > 1) {
144
+ if (x < containerRect.left) x = containerRect.left;
145
+ if (x + width > containerRect.right) width = containerRect.right - x;
146
+ }
147
+ if (height > 1) {
148
+ if (y < containerRect.top) y = containerRect.top;
149
+ if (y + height > containerRect.bottom) height = containerRect.bottom - y;
150
+ }
151
+ return {
152
+ x,
153
+ y,
154
+ width,
155
+ height
156
+ };
157
+ };
134
158
  draggables.forEach(draggable => {
159
+ if (draggable === activeDragEle) return;
135
160
  const {
136
161
  left,
137
162
  top,
@@ -148,42 +173,45 @@ export function getClosestDraggable(x, y, className, activeClassName) {
148
173
  x: xVal,
149
174
  y: yVal
150
175
  }, lines)) {
151
- lines.push({
152
- y: top,
176
+ const line = {
153
177
  x: xVal,
178
+ y: yVal,
154
179
  width: x > left ? Math.abs(aLeft + aWidth - left) : Math.abs(aLeft - (left + width)),
155
180
  height: 1
156
- });
181
+ };
182
+ lines.push(clampLine(line));
157
183
  }
158
184
 
159
185
  // bottom match
160
186
  xVal = x < left ? aLeft : left;
161
187
  yVal = top + height;
162
- if (Math.abs(top + height - (aTop + aHeight)) <= GUIDE_LINE_THRESHOLD && !isOverLapLine({
188
+ if (Math.abs(yVal - (aTop + aHeight)) <= GUIDE_LINE_THRESHOLD && !isOverLapLine({
163
189
  x: xVal,
164
190
  y: yVal
165
191
  }, lines)) {
166
- lines.push({
167
- y: yVal,
192
+ const line = {
168
193
  x: xVal,
194
+ y: yVal,
169
195
  width: x > left ? Math.abs(aLeft + aWidth - left) : Math.abs(aLeft - (left + width)),
170
196
  height: 1
171
- });
197
+ };
198
+ lines.push(clampLine(line));
172
199
  }
173
200
 
174
- // center match
201
+ // center match (horizontal)
175
202
  xVal = x < left ? aLeft : left;
176
203
  yVal = top + height / 2;
177
- if (Math.abs(top + height / 2 - (aTop + aHeight / 2)) <= GUIDE_LINE_THRESHOLD && !isOverLapLine({
204
+ if (Math.abs(yVal - (aTop + aHeight / 2)) <= GUIDE_LINE_THRESHOLD && !isOverLapLine({
178
205
  x: xVal,
179
206
  y: yVal
180
207
  }, lines, "y")) {
181
- lines.push({
182
- y: yVal,
208
+ const line = {
183
209
  x: xVal,
210
+ y: yVal,
184
211
  width: x > left ? Math.abs(aLeft + aWidth - left) : Math.abs(aLeft - (left + width)),
185
212
  height: 1
186
- });
213
+ };
214
+ lines.push(clampLine(line));
187
215
  }
188
216
 
189
217
  // right match
@@ -193,12 +221,13 @@ export function getClosestDraggable(x, y, className, activeClassName) {
193
221
  x: xVal,
194
222
  y: yVal
195
223
  }, lines)) {
196
- lines.push({
197
- y: yVal,
224
+ const line = {
198
225
  x: xVal,
226
+ y: yVal,
199
227
  width: 1,
200
228
  height: Math.abs(aTop - top)
201
- });
229
+ };
230
+ lines.push(clampLine(line));
202
231
  }
203
232
 
204
233
  // left match
@@ -208,27 +237,29 @@ export function getClosestDraggable(x, y, className, activeClassName) {
208
237
  x: xVal,
209
238
  y: yVal
210
239
  }, lines)) {
211
- lines.push({
212
- y: yVal,
240
+ const line = {
213
241
  x: xVal,
242
+ y: yVal,
214
243
  width: 1,
215
244
  height: Math.abs(aTop - top)
216
- });
245
+ };
246
+ lines.push(clampLine(line));
217
247
  }
218
248
 
219
- // middle match
249
+ // middle match (vertical)
220
250
  xVal = left + width / 2;
221
251
  yVal = top < aTop ? top : aTop;
222
- if (Math.abs(aLeft + aWidth / 2 - (left + width / 2)) <= GUIDE_LINE_THRESHOLD && !isOverLapLine({
252
+ if (Math.abs(aLeft + aWidth / 2 - xVal) <= GUIDE_LINE_THRESHOLD && !isOverLapLine({
223
253
  x: xVal,
224
254
  y: yVal
225
255
  }, lines)) {
226
- lines.push({
227
- y: yVal,
256
+ const line = {
228
257
  x: xVal,
258
+ y: yVal,
229
259
  width: 1,
230
260
  height: Math.abs(aTop - top)
231
- });
261
+ };
262
+ lines.push(clampLine(line));
232
263
  }
233
264
  });
234
265
  return lines;
@@ -158,8 +158,11 @@ const RnD = props => {
158
158
  const textElement = currElement?.querySelector(".fgi_type_text");
159
159
  if (breakpoint && textElement && childType === "text" && !enable) {
160
160
  timerId.current = setTimeout(() => {
161
- // const { clientHeight } = textElement;
162
- const clientHeight = getTextElementHeight(textElement);
161
+ const {
162
+ clientHeight
163
+ } = textElement;
164
+ // const clientHeight = getTextElementHeight(textElement);
165
+
163
166
  const {
164
167
  height
165
168
  } = delta || {};
@@ -1,5 +1,6 @@
1
1
  import { Editor, Node, Path, Point, Range, Transforms } from "slate";
2
2
  import { containsSurrogatePair, getNextNode } from "../utils/helper";
3
+ import { onDeleteBackwardAccordion } from "../utils/accordion";
3
4
  const BACKWARD_BLOCKS = ["list-item", "signature"];
4
5
  const isNodeTextEmpty = node => {
5
6
  const nodeText = Node.string(node);
@@ -32,7 +33,7 @@ const withCustomDeleteBackward = editor => {
32
33
  }
33
34
  if (selection && Range.isCollapsed(selection)) {
34
35
  const [currentNode, path] = Editor.node(editor, selection);
35
- if (currentNode && typeof currentNode.text === 'string') {
36
+ if (currentNode && typeof currentNode.text === "string") {
36
37
  const text = currentNode.text;
37
38
  if (containsSurrogatePair(text)) {
38
39
  // Check if the cursor is at the end of a surrogate pair
@@ -60,6 +61,10 @@ const withCustomDeleteBackward = editor => {
60
61
  }
61
62
  }
62
63
  }
64
+ const preventDefaultAccordion = onDeleteBackwardAccordion(editor);
65
+ if (preventDefaultAccordion) {
66
+ return;
67
+ }
63
68
  }
64
69
 
65
70
  // Check if current node is a list item and is the last one, signature node
@@ -1,6 +1,9 @@
1
- import { Editor, Element, Transforms } from "slate";
1
+ import { Editor, Element, Path, Transforms } from "slate";
2
2
  import insertNewLine from "./insertNewLine";
3
+ import { ALLOWED_TEXT_NODES, getNode, getNodeText, getNodeWithType } from "./helper";
3
4
  import { isMobileWindow } from "../helper";
5
+ import { removeAccordion } from "./events";
6
+ import { ReactEditor } from "slate-react";
4
7
  const focusAccordion = (editor, upPath) => {
5
8
  Transforms.select(editor, {
6
9
  path: upPath,
@@ -56,4 +59,80 @@ export const insertAccordion = (editor, path) => {
56
59
  } catch (err) {
57
60
  console.log(err);
58
61
  }
62
+ };
63
+ export const onDeleteBackwardAccordion = editor => {
64
+ try {
65
+ let preventDefault = false;
66
+ const {
67
+ selection
68
+ } = editor;
69
+ const {
70
+ path: currentPath,
71
+ offset
72
+ } = selection.anchor || {};
73
+ const isCursorAtStart = offset === 0;
74
+ if (isCursorAtStart) {
75
+ // If the cursor is at the start of the accordion-summary and backspace is pressed,
76
+ // unwrap the accordion by removing both the summary and details,
77
+ // and insert their contents as regular nodes without the accordion wrapper.
78
+ const [accordionSummary] = getNodeWithType(editor, "accordion-summary");
79
+ const [accordionTitle, accordionTitlePath] = accordionSummary || [];
80
+ if (accordionTitle) {
81
+ const accordionPath = Path.parent(accordionTitlePath);
82
+ removeAccordion(editor, accordionPath);
83
+ preventDefault = true;
84
+ return;
85
+ }
86
+ const parentPath = Path.parent(currentPath);
87
+ const parentNode = getNode(editor, parentPath);
88
+ const isTextNode = ALLOWED_TEXT_NODES.includes(parentNode?.type);
89
+ if (isTextNode) {
90
+ const prevEntry = Editor.previous(editor, {
91
+ at: parentPath,
92
+ match: n => n.type === "accordion"
93
+ });
94
+ if (prevEntry) {
95
+ const [accordionNode, accordionPath] = prevEntry;
96
+ const dom = ReactEditor.toDOMNode(editor, accordionNode);
97
+ const aContent = dom.querySelector(".accordion-content");
98
+ const isContentVisible = aContent.style.display !== "none";
99
+ if (!isContentVisible) {
100
+ // If the accordion content is not visible and backspace is pressed,
101
+ // the content from the current node should be merged with the accordion title,
102
+ // and the cursor should move to the title.
103
+ // Otherwise, Slate will by default merge the current node into the hidden details section,
104
+ // which makes the content invisible.
105
+
106
+ let targetPath = [...accordionPath, 0, 0];
107
+ const targetNodeEntry = getNode(editor, targetPath);
108
+ if (targetNodeEntry) {
109
+ const nodeText = getNodeText(parentNode);
110
+ const endPath = Editor.end(editor, targetPath);
111
+
112
+ // Move current paragraph text into the end of the target block
113
+ Transforms.select(editor, Editor.start(editor, parentPath));
114
+ Transforms.delete(editor, {
115
+ at: parentPath
116
+ });
117
+ Transforms.insertText(editor, nodeText, {
118
+ at: endPath
119
+ });
120
+
121
+ // move the focus and cursor to the inserted node
122
+ Transforms.select(editor, {
123
+ anchor: endPath,
124
+ focus: endPath
125
+ });
126
+ ReactEditor.focus(editor);
127
+ preventDefault = true;
128
+ return;
129
+ }
130
+ }
131
+ }
132
+ }
133
+ }
134
+ return preventDefault;
135
+ } catch (err) {
136
+ console.log(err);
137
+ }
59
138
  };
@@ -2,10 +2,9 @@ import { Editor, Transforms, Element, Node, Path, Range, Point } from "slate";
2
2
  import { toggleBlock } from "./SlateUtilityFunctions";
3
3
  import insertNewLine from "./insertNewLine";
4
4
  import { insertAccordion } from "./accordion";
5
- import { getNodeWithType, isListItem } from "./helper";
5
+ import { getNode, isListItem } from "./helper";
6
6
  import RnDCtrlCmds from "./RnD/RnDCtrlCmds";
7
7
  import EDITORCMDS from "../common/EditorCmds";
8
- import { ReactEditor } from "slate-react";
9
8
  const HOTKEYS = {
10
9
  b: "bold",
11
10
  i: "italic",
@@ -184,16 +183,16 @@ const checkListEnterEvent = (editor, type) => {
184
183
  insertNewLine(editor);
185
184
  }
186
185
  };
187
- const removeAccordion = (editor, accordionPath) => {
186
+ export const removeAccordion = (editor, accordionPath) => {
187
+ const accordion = getNode(editor, accordionPath);
188
188
  Transforms.removeNodes(editor, {
189
189
  at: accordionPath
190
190
  });
191
- Transforms.insertNodes(editor, {
192
- type: "paragraph",
193
- children: [{
194
- text: ""
195
- }]
196
- }, {
191
+ const insertNodes = [];
192
+ accordion.children.forEach(a => {
193
+ a.children.forEach(n => insertNodes.push(n));
194
+ });
195
+ Transforms.insertNodes(editor, insertNodes, {
197
196
  at: accordionPath,
198
197
  select: true
199
198
  });
@@ -342,37 +341,48 @@ export const enterEvent = (e, editor, isMobile) => {
342
341
  console.log(err);
343
342
  }
344
343
  };
345
- export const handleAccordionOnBackspace = (e, editor) => {
346
- try {
347
- let isAccordion = false;
348
- const [accordionDetails] = getNodeWithType(editor, "accordion-details");
349
- const [accordionDetailsNode] = accordionDetails || [];
350
- if (accordionDetailsNode) {
351
- const dom = ReactEditor.toDOMNode(editor, accordionDetailsNode);
352
- if (dom?.parentElement) {
353
- dom.parentElement.style.display = "block";
354
- }
355
- }
356
- const [accordionSummary] = getNodeWithType(editor, "accordion-summary");
357
- const [accordionTitle, accordionTitlePath] = accordionSummary || [];
358
- if (accordionTitle) {
359
- // no selection
360
- if (Range.isCollapsed(editor.selection)) {
361
- const start = Editor.start(editor, accordionTitlePath);
362
- const isCursorAtStart = Point.equals(editor.selection.focus, start);
363
- if (isCursorAtStart) {
364
- e.preventDefault();
365
- const parentPath = Path.parent(accordionTitlePath);
366
- removeAccordion(editor, parentPath);
367
- isAccordion = true;
368
- }
369
- }
370
- }
371
- return isAccordion;
372
- } catch (err) {
373
- console.log(err);
374
- }
375
- };
344
+
345
+ // not using now
346
+ // export const handleAccordionOnBackspace = (e, editor) => {
347
+ // try {
348
+ // let isAccordion = false;
349
+
350
+ // const [accordionDetails] = getNodeWithType(editor, "accordion-details");
351
+ // const [accordionDetailsNode] = accordionDetails || [];
352
+
353
+ // if (accordionDetailsNode) {
354
+ // const dom = ReactEditor.toDOMNode(editor, accordionDetailsNode);
355
+
356
+ // if (dom?.parentElement) {
357
+ // dom.parentElement.style.display = "block";
358
+ // }
359
+ // }
360
+
361
+ // const [accordionSummary] = getNodeWithType(editor, "accordion-summary");
362
+
363
+ // const [accordionTitle, accordionTitlePath] = accordionSummary || [];
364
+
365
+ // if (accordionTitle) {
366
+ // // no selection
367
+ // if (Range.isCollapsed(editor.selection)) {
368
+ // const start = Editor.start(editor, accordionTitlePath);
369
+ // const isCursorAtStart = Point.equals(editor.selection.focus, start);
370
+
371
+ // if (isCursorAtStart) {
372
+ // e.preventDefault();
373
+ // const parentPath = Path.parent(accordionTitlePath);
374
+ // removeAccordion(editor, parentPath);
375
+ // isAccordion = true;
376
+ // }
377
+ // }
378
+ // }
379
+
380
+ // return isAccordion;
381
+ // } catch (err) {
382
+ // console.log(err);
383
+ // }
384
+ // };
385
+
376
386
  export const upDownArrowKeyEvents = (e, editor) => {
377
387
  try {
378
388
  const {
@@ -1053,4 +1053,5 @@ export const handleCopy = (event, editor) => {
1053
1053
  event.clipboardData?.setData("text/html", html);
1054
1054
  event.clipboardData?.setData("text/plain", text);
1055
1055
  event.clipboardData?.setData("application/x-slate-fragment", encodedFragment);
1056
- };
1056
+ };
1057
+ export const ALLOWED_TEXT_NODES = ["paragraph", "title", "headingOne", "headingTwo", "headingThree", "headingFour", "headingFive", "headingSix", "blockquote"];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flozy/editor",
3
- "version": "10.6.0",
3
+ "version": "10.6.2",
4
4
  "description": "An Editor for flozy app brain",
5
5
  "files": [
6
6
  "dist"