@flozy/editor 4.7.8 → 4.7.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -534,7 +534,7 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
534
534
  readOnly: isReadOnly,
535
535
  renderElement: renderElement,
536
536
  renderLeaf: renderLeaf,
537
- decorate: decorators,
537
+ decorate: d => decorators(d, editor),
538
538
  onKeyDown: onKeyDown,
539
539
  onSelect: () => handleCursorScroll(editorWrapper.current)
540
540
  }), !readOnly ? /*#__PURE__*/_jsx(MentionsPopup, {
@@ -584,8 +584,6 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
584
584
  }), htmlAction.showInput && /*#__PURE__*/_jsx(CodeToText, {
585
585
  ...htmlAction,
586
586
  handleCodeToText: handleCodeToText
587
- }), /*#__PURE__*/_jsx(FontLoader, {
588
- ...props
589
587
  })]
590
588
  }, id)
591
589
  })
@@ -90,6 +90,7 @@ function AIInput({
90
90
  children: [/*#__PURE__*/_jsxs(Box, {
91
91
  component: "div",
92
92
  sx: classes.aiContainer,
93
+ ref: refs[0],
93
94
  children: [generatedText ? /*#__PURE__*/_jsx(Typography, {
94
95
  sx: classes.generatedText,
95
96
  style: {
@@ -104,7 +105,6 @@ function AIInput({
104
105
  onSubmit: e => {
105
106
  e.preventDefault();
106
107
  },
107
- ref: refs[0],
108
108
  children: [/*#__PURE__*/_jsx("div", {
109
109
  className: "icon-container icons-elements",
110
110
  ref: inputWrapperRef,
@@ -116,22 +116,21 @@ function AIInput({
116
116
  children: /*#__PURE__*/_jsx(WaveLoading, {})
117
117
  }) : /*#__PURE__*/_jsx(TextareaAutosize, {
118
118
  className: "ai-input",
119
- placeholder: fromToolBar ? "" : "Ask AI to write anything...",
119
+ placeholder: "Ask AI to write anything...",
120
120
  ref: inputRef,
121
121
  value: inputValue,
122
122
  onChange: onInputChange,
123
- disabled: fromToolBar,
124
123
  onKeyDown: event => {
125
124
  if (event.key === "Enter" && !event.shiftKey) {
126
125
  event.preventDefault();
127
126
  handleSendBtnClick();
128
127
  }
129
128
  }
130
- }), fromToolBar ? null : /*#__PURE__*/_jsxs(Box, {
129
+ }), /*#__PURE__*/_jsxs(Box, {
131
130
  component: "div",
132
131
  style: classes.sendIconContainer,
133
132
  className: "icons-elements",
134
- children: [isMobile ? null : /*#__PURE__*/_jsx(IconButton, {
133
+ children: [/*#__PURE__*/_jsx(IconButton, {
135
134
  disabled: loading,
136
135
  onClick: () => startRecording(),
137
136
  children: /*#__PURE__*/_jsx(ChatMicIcon, {})
@@ -40,9 +40,11 @@ const scrollToAIInput = editor => {
40
40
  }, 200);
41
41
  };
42
42
  const insertText = (editor, text, options) => {
43
- const parsed = new DOMParser().parseFromString(text, "text/html");
44
- const fragment = deserialize(parsed.body);
45
- Transforms.insertFragment(editor, fragment, options);
43
+ if (text?.length) {
44
+ const parsed = new DOMParser().parseFromString(text, "text/html");
45
+ const fragment = deserialize(parsed.body);
46
+ Transforms.insertFragment(editor, fragment, options);
47
+ }
46
48
  };
47
49
  const insertAtNextLine = (editor, text) => {
48
50
  const nextLine = getNextLine(editor);
@@ -199,81 +201,95 @@ function PopoverAIInput({
199
201
  useEffect(() => {
200
202
  selectedEleRef.current = selectedElement;
201
203
  }, [selectedElement]);
202
- const onSend = async (type, option) => {
203
- if (type === "close") {
204
- onClickOutside();
205
- return;
206
- }
207
- if (type === "done") {
208
- // Get the current selection point
209
- const {
210
- anchor
211
- } = editor.selection;
212
- const {
213
- path
214
- } = anchor;
215
- const {
216
- text: selectText
217
- } = Node.get(editor, path);
218
- if (selectText?.length) {
219
- insertAtNextLine(editor, generatedText);
220
- } else {
221
- insertText(editor, generatedText);
222
- }
223
- onClickOutside();
224
- return;
225
- }
226
- if (type === "replace_selection") {
227
- // replace generated text
228
- insertText(editor, generatedText);
229
- onClickOutside();
230
- return;
231
- }
232
- if (type === "speech_to_text") {
233
- setGeneratedText(option.text);
234
- return;
235
- }
236
- if (type === "try_again") {
237
- // resetting the previous option and try again
238
- option = selectedOption;
239
- type = selectedOption.value;
240
- } else {
241
- setSelectedOption(option);
242
- }
243
- setLoading(true);
244
- const payload = {
204
+ const framePayload = (type, option) => {
205
+ let payload = {
245
206
  mode: option.mode || 0,
246
207
  query: option?.inputValue || inputValue
247
208
  };
248
209
  if (option.mode === MODES.translate || option.mode === MODES.rephraseTone) {
249
210
  payload.textOptionInput = type;
250
211
  }
212
+ const selectedText = getSelectedText(editor);
213
+ const textData = generatedText || selectedText;
251
214
  if (option.mode) {
252
- payload.textData = generatedText || window.getSelection().toString();
215
+ payload.textData = textData;
216
+ } else if (selectedText && Number(payload.mode) === 0) {
217
+ payload.query = `${selectedText} \n ${payload.query}`;
253
218
  }
254
- const result = await services("infinityAI", payload);
255
- setLoading(false);
256
- setInputValue("");
257
- let {
258
- data: text
259
- } = result || {};
260
- if (!text) {
261
- onClickOutside();
262
- return;
219
+ const tryAgain = type === "try_again";
220
+ if (tryAgain) {
221
+ // resetting previous payload
222
+ const prevPayload = selectedOption?.payload || {};
223
+ payload = prevPayload;
263
224
  }
264
- if (!option.replace) {
225
+ return payload;
226
+ };
227
+ const onSend = async (type, option) => {
228
+ try {
229
+ if (type === "close") {
230
+ onClickOutside();
231
+ return;
232
+ }
233
+ if (type === "done") {
234
+ // Get the current selection point
235
+ const {
236
+ anchor
237
+ } = editor.selection;
238
+ const {
239
+ path
240
+ } = anchor;
241
+ const {
242
+ text: selectText
243
+ } = Node.get(editor, path);
244
+ if (selectText?.length) {
245
+ insertAtNextLine(editor, generatedText);
246
+ } else {
247
+ insertText(editor, generatedText);
248
+ }
249
+ onClickOutside();
250
+ return;
251
+ }
252
+ if (type === "replace_selection") {
253
+ // replace generated text
254
+ insertText(editor, generatedText);
255
+ onClickOutside();
256
+ return;
257
+ }
258
+ setLoading(true);
259
+ const payload = framePayload(type, option);
260
+ setSelectedOption({
261
+ ...option,
262
+ payload
263
+ });
264
+ const result = await services("infinityAI", payload);
265
+ setLoading(false);
266
+ setInputValue("");
267
+ let {
268
+ data: text
269
+ } = result || {};
270
+ if (!text) {
271
+ onClickOutside();
272
+ return;
273
+ }
274
+
275
+ // if (!option.replace) {
265
276
  if (type === "continue_writing") {
266
277
  setGeneratedText(generatedText + text);
267
278
  } else {
268
279
  setGeneratedText(text);
269
280
  }
270
- return;
271
- }
272
- insertText(editor, text);
273
281
 
274
- // scrollToAIInput();
275
- };
282
+ // return;
283
+ // }
276
284
 
285
+ // ** we are not using this insertText right now, AI returned response will not insert into the editor immediately, so option.replace will be false always
286
+ // insertText(editor, text);
287
+
288
+ // scrollToAIInput();
289
+ } catch (err) {
290
+ console.error("Error on sending/inserting text", err);
291
+ }
292
+ };
277
293
  const onInputChange = e => {
278
294
  setInputValue(e.target.value);
279
295
  };
@@ -102,6 +102,7 @@ const Styles = theme => ({
102
102
  customSelectWrapper: {
103
103
  width: "fit-content",
104
104
  marginTop: "4px",
105
+ position: "absolute",
105
106
  "@media only screen and (max-width: 600px)": {
106
107
  marginBottom: "4px"
107
108
  }
@@ -12,13 +12,19 @@ const EmbedPopup = props => {
12
12
  format,
13
13
  onDelete
14
14
  } = props;
15
+ const videoStyles = embedVideoStyle?.filter(f => {
16
+ if (f?.value === "AspectRatio" && format !== "video") {
17
+ return false;
18
+ }
19
+ return true;
20
+ });
15
21
  return /*#__PURE__*/_jsx(StyleBuilder, {
16
22
  title: format === "image" ? "Image" : format === "video" ? "video" : format === "calendly" ? "calendly" : "Embed",
17
23
  type: format === "image" ? "embedImageStyle" : "embedVideoStyle",
18
24
  element: element,
19
25
  onSave: onSave,
20
26
  onClose: onClose,
21
- renderTabs: format === "image" ? embedImageStyle : embedVideoStyle,
27
+ renderTabs: format === "image" ? embedImageStyle : videoStyles,
22
28
  customProps: customProps,
23
29
  onDelete: onDelete
24
30
  });
@@ -286,7 +286,7 @@ const editorStyles = ({
286
286
  }
287
287
  },
288
288
  "& ::selection": {
289
- color: "black",
289
+ color: "inherit",
290
290
  background: "#EAEBFE"
291
291
  }
292
292
  },
@@ -13,6 +13,7 @@ import PopperHeader from "../PopperHeader";
13
13
  import MiniColorPicker from "./MiniColorPicker";
14
14
  import SelectAlignment from "./SelectAlignment";
15
15
  import SelectFontSize from "./SelectFontSize";
16
+ import InfinityAITool from "./InfinityAITool";
16
17
  import { jsx as _jsx } from "react/jsx-runtime";
17
18
  import { jsxs as _jsxs } from "react/jsx-runtime";
18
19
  const DEFAULT_COLOR = {
@@ -49,7 +50,7 @@ const MiniTextFormat = props => {
49
50
  xs: 12,
50
51
  children: /*#__PURE__*/_jsxs("div", {
51
52
  className: "toolWrapper",
52
- children: [/*#__PURE__*/_jsx(SelectTypography, {
53
+ children: [customProps?.hideTools?.includes("infinityAI") ? null : /*#__PURE__*/_jsx(InfinityAITool, {}), /*#__PURE__*/_jsx(SelectTypography, {
53
54
  classes: classes,
54
55
  editor: editor,
55
56
  closeMainPopup: closeMainPopup
@@ -1,5 +1,4 @@
1
1
  import React from "react";
2
- import { Node } from "slate";
3
2
  import { Dialog, DialogContent, DialogTitle, IconButton } from "@mui/material";
4
3
  import SaveAsTemplate from "../../../StyleBuilder/fieldTypes/saveAsTemplate";
5
4
  import { CloseIcon } from "../../../iconslist";
@@ -12,7 +12,7 @@ const Settings = props => {
12
12
  childType,
13
13
  open,
14
14
  anchorEl,
15
- placement,
15
+ // placement,
16
16
  onClose,
17
17
  editor,
18
18
  classes,
@@ -123,8 +123,8 @@ export function onDropItem(props, parentClass) {
123
123
  dragOver,
124
124
  parentPath,
125
125
  path,
126
- diffX,
127
- x: cx,
126
+ // diffX,
127
+ // x: cx,
128
128
  breakpoint
129
129
  // calX,
130
130
  } = props;
@@ -134,7 +134,9 @@ export function onDropItem(props, parentClass) {
134
134
  let newPath = [];
135
135
  newPath = moveTo;
136
136
  const cCalx = isContainerElement(editor, moveTo, props);
137
- const posX = parseInt(cx - window.innerWidth / 2 + MARGIN_OF[breakpoint] - diffX);
137
+ // const posX = parseInt(
138
+ // cx - window.innerWidth / 2 + MARGIN_OF[breakpoint] - diffX
139
+ // );
138
140
  const toSectionNode = Node.get(editor, newPath);
139
141
  const addToSectionDOM = ReactEditor.toDOMNode(editor, toSectionNode);
140
142
  const rect = addToSectionDOM.getBoundingClientRect();
@@ -9,7 +9,7 @@ const embedVideoStyle = [{
9
9
  }]
10
10
  }, {
11
11
  tab: "Aspect Ratio",
12
- value: "Aspect Ratio",
12
+ value: "AspectRatio",
13
13
  hideOnFGS: true,
14
14
  fields: [{
15
15
  label: "Aspect Ratio",
@@ -118,14 +118,14 @@ const SaveAsTemplate = props => {
118
118
  children: "Section"
119
119
  })
120
120
  }), /*#__PURE__*/_jsx(MenuItem, {
121
- value: "Templates",
121
+ value: "Template",
122
122
  children: /*#__PURE__*/_jsx(Typography, {
123
123
  variant: "body1",
124
124
  color: "primary",
125
125
  sx: {
126
126
  fontSize: "14px"
127
127
  },
128
- children: "Templates"
128
+ children: "Template"
129
129
  })
130
130
  })]
131
131
  })
@@ -14,6 +14,19 @@ const withCustomDeleteBackward = editor => {
14
14
  selection
15
15
  } = editor;
16
16
  if (selection) {
17
+ // get the current node
18
+ const [freeGridItemNode] = Editor.nodes(editor, {
19
+ match: n => n.type === "freegridItem" // Adjust based on your list item type
20
+ });
21
+
22
+ // if it is freegrid
23
+ if (freeGridItemNode && freeGridItemNode[0]) {
24
+ const hasText = Node.string(freeGridItemNode[0]);
25
+ if (!hasText) {
26
+ return;
27
+ }
28
+ }
29
+
17
30
  // Check if current node is a list item and is the last one
18
31
  const [node] = Editor.nodes(editor, {
19
32
  match: n => n.type === "list-item" // Adjust based on your list item type
@@ -0,0 +1,22 @@
1
+ import { Editor, Range, Text } from "slate";
2
+ const highlightSelection = ([node, path], editor = {}) => {
3
+ if (Text.isText(node) && editor?.selection) {
4
+ const intersection = Range.intersection(editor.selection, Editor.range(editor, path));
5
+ if (!intersection) {
6
+ return [];
7
+ }
8
+
9
+ // Avoid applying highlight if the range only includes line breaks
10
+ const rangeText = Editor.string(editor, intersection);
11
+ if (!rangeText.trim()) {
12
+ return [];
13
+ }
14
+ const range = {
15
+ highlight: true,
16
+ ...intersection
17
+ };
18
+ return [range];
19
+ }
20
+ return [];
21
+ };
22
+ export default highlightSelection;
@@ -1,5 +1,6 @@
1
+ import highlightSelection from "./highlightSelection";
1
2
  import link from "./link";
2
- const decorators = d => {
3
- return [...link(d)];
3
+ const decorators = (d, editor) => {
4
+ return [...link(d, editor), ...highlightSelection(d, editor)];
4
5
  };
5
6
  export default decorators;
@@ -242,6 +242,15 @@ export const getMarked = (leaf, children, theme) => {
242
242
  })
243
243
  });
244
244
  }
245
+ if (leaf.highlight) {
246
+ children = /*#__PURE__*/_jsx("span", {
247
+ style: {
248
+ background: "#EAEBFE",
249
+ color: "inherit"
250
+ },
251
+ children: children
252
+ });
253
+ }
245
254
  if (leaf.decoration === "link") {
246
255
  children = /*#__PURE__*/_jsx("a", {
247
256
  style: {
@@ -496,7 +496,7 @@ export const isFreeGrid = (nodes, types = ["freegrid", "freegridItem", "freegrid
496
496
  }
497
497
  return false;
498
498
  } catch (err) {
499
- console.log('isFreeGrid error:', err);
499
+ console.log("isFreeGrid error:", err);
500
500
  return false;
501
501
  }
502
502
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flozy/editor",
3
- "version": "4.7.8",
3
+ "version": "4.7.9",
4
4
  "description": "An Editor for flozy app brain",
5
5
  "files": [
6
6
  "dist"