@fileverse-dev/fortune-react 1.3.13-create-3 → 1.3.13-create-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.
Files changed (35) hide show
  1. package/es/components/FxEditor/index.js +73 -18
  2. package/es/components/SheetOverlay/ContentEditable.js +4 -3
  3. package/es/components/SheetOverlay/InputBox.js +193 -44
  4. package/es/components/SheetOverlay/drag_and_drop/column-helpers.js +4 -27
  5. package/es/components/SheetOverlay/drag_and_drop/row-helpers.js +4 -25
  6. package/es/components/SheetOverlay/formula-segment-boundary.js +1 -1
  7. package/es/components/SheetOverlay/helper.d.ts +7 -0
  8. package/es/components/SheetOverlay/helper.js +75 -0
  9. package/es/components/SheetOverlay/index.css +10 -83
  10. package/es/components/SheetOverlay/index.js +1 -26
  11. package/es/components/Toolbar/ColorPicker.js +3 -2
  12. package/es/components/Toolbar/CustomColor.js +7 -3
  13. package/es/components/Toolbar/index.js +11 -2
  14. package/es/hooks/useFormulaEditorHistory.d.ts +4 -4
  15. package/es/hooks/useFormulaEditorHistory.js +87 -59
  16. package/es/hooks/useRerenderOnFormulaCaret.d.ts +1 -1
  17. package/es/hooks/useRerenderOnFormulaCaret.js +6 -3
  18. package/lib/components/FxEditor/index.js +72 -17
  19. package/lib/components/SheetOverlay/ContentEditable.js +4 -3
  20. package/lib/components/SheetOverlay/InputBox.js +192 -43
  21. package/lib/components/SheetOverlay/drag_and_drop/column-helpers.js +3 -26
  22. package/lib/components/SheetOverlay/drag_and_drop/row-helpers.js +3 -24
  23. package/lib/components/SheetOverlay/formula-segment-boundary.js +1 -1
  24. package/lib/components/SheetOverlay/helper.d.ts +7 -0
  25. package/lib/components/SheetOverlay/helper.js +79 -0
  26. package/lib/components/SheetOverlay/index.css +10 -83
  27. package/lib/components/SheetOverlay/index.js +1 -26
  28. package/lib/components/Toolbar/ColorPicker.js +3 -2
  29. package/lib/components/Toolbar/CustomColor.js +7 -3
  30. package/lib/components/Toolbar/index.js +10 -1
  31. package/lib/hooks/useFormulaEditorHistory.d.ts +4 -4
  32. package/lib/hooks/useFormulaEditorHistory.js +85 -58
  33. package/lib/hooks/useRerenderOnFormulaCaret.d.ts +1 -1
  34. package/lib/hooks/useRerenderOnFormulaCaret.js +5 -2
  35. package/package.json +2 -2
@@ -1,6 +1,13 @@
1
1
  export declare function moveCursorToEnd(editableDiv: HTMLDivElement): void;
2
2
  export declare function getCursorPosition(editableDiv: HTMLDivElement): number;
3
+ export declare function getSelectionOffsets(editableDiv: HTMLDivElement): {
4
+ start: number;
5
+ end: number;
6
+ };
7
+ export declare function isEditorUndoRedoKeyEvent(e: KeyboardEvent): boolean;
8
+ export declare function shouldUseCustomEditorHistory(editorInnerTextTrimmed: string, historyActive: boolean): boolean;
3
9
  export declare function setCursorPosition(editableDiv: HTMLDivElement, targetOffset: number): void;
10
+ export declare function setSelectionOffsets(editableDiv: HTMLDivElement, startOffset: number, endOffset: number): void;
4
11
  export declare function buildFormulaSuggestionText(editableDiv: HTMLDivElement, formulaName: string): {
5
12
  text: string;
6
13
  caretOffset: number;
@@ -18,6 +18,44 @@ export function getCursorPosition(editableDiv) {
18
18
  preRange.setEnd(range.endContainer, range.endOffset);
19
19
  return preRange.toString().length;
20
20
  }
21
+ export function getSelectionOffsets(editableDiv) {
22
+ var selection = window.getSelection();
23
+ if (!selection || selection.rangeCount === 0) {
24
+ var caret = getCursorPosition(editableDiv);
25
+ return {
26
+ start: caret,
27
+ end: caret
28
+ };
29
+ }
30
+ var range = selection.getRangeAt(0);
31
+ if (!editableDiv.contains(range.startContainer) || !editableDiv.contains(range.endContainer)) {
32
+ var caret = getCursorPosition(editableDiv);
33
+ return {
34
+ start: caret,
35
+ end: caret
36
+ };
37
+ }
38
+ var startRange = range.cloneRange();
39
+ startRange.selectNodeContents(editableDiv);
40
+ startRange.setEnd(range.startContainer, range.startOffset);
41
+ var start = startRange.toString().length;
42
+ var endRange = range.cloneRange();
43
+ endRange.selectNodeContents(editableDiv);
44
+ endRange.setEnd(range.endContainer, range.endOffset);
45
+ var end = endRange.toString().length;
46
+ return {
47
+ start: Math.max(0, Math.min(start, end)),
48
+ end: Math.max(start, end)
49
+ };
50
+ }
51
+ export function isEditorUndoRedoKeyEvent(e) {
52
+ if (!e.metaKey && !e.ctrlKey) return false;
53
+ if (e.code === "KeyZ" || e.code === "KeyY") return true;
54
+ return e.keyCode === 90 || e.keyCode === 89;
55
+ }
56
+ export function shouldUseCustomEditorHistory(editorInnerTextTrimmed, historyActive) {
57
+ return historyActive || editorInnerTextTrimmed.length > 0;
58
+ }
21
59
  export function setCursorPosition(editableDiv, targetOffset) {
22
60
  var _a, _b;
23
61
  editableDiv.focus();
@@ -44,6 +82,43 @@ export function setCursorPosition(editableDiv, targetOffset) {
44
82
  selection.removeAllRanges();
45
83
  selection.addRange(range);
46
84
  }
85
+ export function setSelectionOffsets(editableDiv, startOffset, endOffset) {
86
+ editableDiv.focus();
87
+ var selection = window.getSelection();
88
+ if (!selection) return;
89
+ var startTarget = Math.max(0, Math.min(startOffset, endOffset));
90
+ var endTarget = Math.max(startTarget, endOffset);
91
+ var walker = document.createTreeWalker(editableDiv, NodeFilter.SHOW_TEXT);
92
+ var resolve = function resolve(target) {
93
+ var _a, _b;
94
+ var remaining = target;
95
+ var node = walker.nextNode();
96
+ while (node) {
97
+ var len = (_b = (_a = node.textContent) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
98
+ if (remaining <= len) return {
99
+ node: node,
100
+ offset: remaining
101
+ };
102
+ remaining -= len;
103
+ node = walker.nextNode();
104
+ }
105
+ return null;
106
+ };
107
+ walker.currentNode = editableDiv;
108
+ var startPos = resolve(startTarget);
109
+ walker.currentNode = editableDiv;
110
+ var endPos = resolve(endTarget);
111
+ var range = document.createRange();
112
+ if (startPos && endPos) {
113
+ range.setStart(startPos.node, startPos.offset);
114
+ range.setEnd(endPos.node, endPos.offset);
115
+ } else {
116
+ range.selectNodeContents(editableDiv);
117
+ range.collapse(false);
118
+ }
119
+ selection.removeAllRanges();
120
+ selection.addRange(range);
121
+ }
47
122
  export function buildFormulaSuggestionText(editableDiv, formulaName) {
48
123
  var fullText = editableDiv.innerText || "";
49
124
  var selection = window.getSelection();
@@ -145,12 +145,6 @@
145
145
  margin: 0px 0 0 0px;
146
146
  }
147
147
 
148
- .fortune-selection-copy .fortune-copy {
149
- position: absolute;
150
- z-index: 18;
151
- background-color: transparent;
152
- }
153
-
154
148
  .fortune-selection-copy-hc {
155
149
  position: absolute;
156
150
  top: 0;
@@ -330,7 +324,7 @@
330
324
  max-height: 9900px;
331
325
  max-width: 9900px;
332
326
  border: 2px #efc703 solid;
333
- padding: 0 2px;
327
+ padding: 2px 2px;
334
328
  margin: 0;
335
329
  resize: none;
336
330
  overflow: hidden;
@@ -363,6 +357,14 @@
363
357
  color: forestgreen;
364
358
  }
365
359
 
360
+ .luckysheet-formula-text-calc,
361
+ .luckysheet-formula-text-lpar,
362
+ .luckysheet-formula-text-comma,
363
+ .luckysheet-formula-text-rpar {
364
+ padding-left: 2px;
365
+ padding-right: 2px;
366
+ }
367
+
366
368
  .luckysheet-cell-flow {
367
369
  margin: 0;
368
370
  padding: 0;
@@ -647,50 +649,6 @@
647
649
  cursor: se-resize;
648
650
  }
649
651
 
650
- .fortune-selection-copy-top {
651
- left: 0;
652
- right: 0;
653
- height: 2px;
654
- top: 0;
655
- background-position: bottom;
656
- /* background-image: url("EwaAntH.gif"); */
657
- }
658
-
659
- .fortune-selection-copy-right {
660
- top: 0;
661
- bottom: 0;
662
- width: 2px;
663
- right: 0;
664
- /* background-image: url("EwaAntV.gif"); */
665
- }
666
-
667
- .fortune-selection-copy-bottom {
668
- left: 0;
669
- right: 0;
670
- height: 2px;
671
- bottom: 0;
672
- /* background-image: url("EwaAntH.gif"); */
673
- }
674
-
675
- .fortune-selection-copy-left {
676
- top: 0;
677
- bottom: 0;
678
- width: 2px;
679
- left: 0;
680
- background-position: right;
681
- /* background-image: url("EwaAntV.gif"); */
682
- }
683
-
684
- .fortune-selection-copy-hc {
685
- position: absolute;
686
- top: 0;
687
- right: 0;
688
- bottom: 0;
689
- left: 0;
690
- border: 2px dashed #12a5ff;
691
- z-index: 8;
692
- }
693
-
694
652
  .luckysheet-modal-dialog-resize {
695
653
  position: absolute;
696
654
  border: 2px solid #0188fb;
@@ -765,39 +723,8 @@
765
723
  cursor: se-resize;
766
724
  }
767
725
 
768
- .fortune-formula-functionrange-highlight .fortune-copy {
769
- background-image: none;
770
- background: #0188fb;
771
- position: absolute;
772
- z-index: 18;
726
+ .fortune-formula-functionrange-highlight {
773
727
  cursor: move;
774
- opacity: 0.9;
775
- box-sizing: content-box;
776
- /*border: 1px solid #fff;*/
777
- }
778
-
779
- .fortune-formula-functionrange-highlight .fortune-selection-copy-top {
780
- top: -2px;
781
- border-top: 2px solid #fff;
782
- border-bottom: 2px solid #fff;
783
- }
784
-
785
- .fortune-formula-functionrange-highlight .fortune-selection-copy-right {
786
- right: -2px;
787
- border-left: 2px solid #fff;
788
- border-right: 2px solid #fff;
789
- }
790
-
791
- .fortune-formula-functionrange-highlight .fortune-selection-copy-bottom {
792
- bottom: -2px;
793
- border-top: 2px solid #fff;
794
- border-bottom: 2px solid #fff;
795
- }
796
-
797
- .fortune-formula-functionrange-highlight .fortune-selection-copy-left {
798
- left: -2px;
799
- border-left: 2px solid #fff;
800
- border-right: 2px solid #fff;
801
728
  }
802
729
 
803
730
  .fortune-formula-functionrange-highlight .fortune-selection-copy-hc {
@@ -285,14 +285,6 @@ var SheetOverlay = function SheetOverlay() {
285
285
  className: "fortune-selection-copy fortune-formula-functionrange-select",
286
286
  style: context.formulaRangeSelect
287
287
  }, /*#__PURE__*/React.createElement("div", {
288
- className: "fortune-selection-copy-top fortune-copy"
289
- }), /*#__PURE__*/React.createElement("div", {
290
- className: "fortune-selection-copy-right fortune-copy"
291
- }), /*#__PURE__*/React.createElement("div", {
292
- className: "fortune-selection-copy-bottom fortune-copy"
293
- }), /*#__PURE__*/React.createElement("div", {
294
- className: "fortune-selection-copy-left fortune-copy"
295
- }), /*#__PURE__*/React.createElement("div", {
296
288
  className: "fortune-selection-copy-hc"
297
289
  }))), context.formulaRangeHighlight.map(function (v) {
298
290
  var rangeIndex = v.rangeIndex,
@@ -302,16 +294,7 @@ var SheetOverlay = function SheetOverlay() {
302
294
  id: "fortune-formula-functionrange-highlight",
303
295
  className: "fortune-selection-highlight fortune-formula-functionrange-highlight",
304
296
  style: _.omit(v, "backgroundColor")
305
- }, ["top", "right", "bottom", "left"].map(function (d) {
306
- return /*#__PURE__*/React.createElement("div", {
307
- key: d,
308
- "data-type": d,
309
- className: "fortune-selection-copy-".concat(d, " fortune-copy"),
310
- style: {
311
- backgroundColor: backgroundColor
312
- }
313
- });
314
- }), /*#__PURE__*/React.createElement("div", {
297
+ }, /*#__PURE__*/React.createElement("div", {
315
298
  className: "fortune-selection-copy-hc",
316
299
  style: formulaRangeHighlightHcStyle(backgroundColor)
317
300
  }));
@@ -364,14 +347,6 @@ var SheetOverlay = function SheetOverlay() {
364
347
  height: row - row_pre - 1
365
348
  }
366
349
  }, /*#__PURE__*/React.createElement("div", {
367
- className: "fortune-selection-copy-top fortune-copy"
368
- }), /*#__PURE__*/React.createElement("div", {
369
- className: "fortune-selection-copy-right fortune-copy"
370
- }), /*#__PURE__*/React.createElement("div", {
371
- className: "fortune-selection-copy-bottom fortune-copy"
372
- }), /*#__PURE__*/React.createElement("div", {
373
- className: "fortune-selection-copy-left fortune-copy"
374
- }), /*#__PURE__*/React.createElement("div", {
375
350
  className: "fortune-selection-copy-hc"
376
351
  }));
377
352
  }))), /*#__PURE__*/React.createElement("div", {
@@ -12,8 +12,9 @@ var ColorPicker = function ColorPicker(_a) {
12
12
  return /*#__PURE__*/React.createElement("div", {
13
13
  key: c,
14
14
  className: "fortune-toolbar-color-picker-item",
15
- onClick: function onClick() {
16
- return onPick(c);
15
+ onMouseDown: function onMouseDown(e) {
16
+ e.preventDefault();
17
+ onPick(c);
17
18
  },
18
19
  tabIndex: 0,
19
20
  style: {
@@ -6,11 +6,15 @@ export var CustomColor = function CustomColor(_a) {
6
6
  var onCustomPick = _a.onCustomPick,
7
7
  onColorPick = _a.onColorPick;
8
8
  return /*#__PURE__*/React.createElement("div", {
9
- id: "fortune-custom-color"
9
+ id: "fortune-custom-color",
10
+ onMouseDown: function onMouseDown(e) {
11
+ e.preventDefault();
12
+ }
10
13
  }, /*#__PURE__*/React.createElement("div", {
11
14
  className: "color-reset",
12
- onClick: function onClick() {
13
- return onCustomPick(undefined);
15
+ onMouseDown: function onMouseDown(e) {
16
+ e.preventDefault();
17
+ onCustomPick(undefined);
14
18
  },
15
19
  tabIndex: 0
16
20
  }, /*#__PURE__*/React.createElement(SVGIcon, {
@@ -123,7 +123,7 @@ var __spreadArray = this && this.__spreadArray || function (to, from, pack) {
123
123
  return to.concat(ar || Array.prototype.slice.call(from));
124
124
  };
125
125
  import React, { useContext, useCallback, useRef, useEffect, useState } from "react";
126
- import { toolbarItemClickHandler, handleTextBackground, handleTextColor, handleTextSize, normalizedCellAttr, getFlowdata, newComment, editComment, deleteComment, showHideComment, showHideAllComments, autoSelectionFormula, handleSum, locale, handleMerge, handleBorder, toolbarItemSelectedFunc, handleFreeze, insertImage, showImgChooser, updateFormat, handleSort, handleHorizontalAlign, handleVerticalAlign, handleScreenShot, createFilter, clearFilter, applyLocation, insertDuneChart, api, getSheetIndex, is_date } from "@fileverse-dev/fortune-core";
126
+ import { toolbarItemClickHandler, handleTextBackground, handleTextColor, handleTextSize, normalizedCellAttr, getFlowdata, newComment, editComment, deleteComment, showHideComment, showHideAllComments, autoSelectionFormula, handleSum, locale, handleMerge, handleBorder, toolbarItemSelectedFunc, handleFreeze, insertImage, showImgChooser, updateFormat, handleSort, handleHorizontalAlign, handleVerticalAlign, handleScreenShot, createFilter, clearFilter, applyLocation, insertDuneChart, getFormulaEditorOwner, api, getSheetIndex, is_date } from "@fileverse-dev/fortune-core";
127
127
  import _ from "lodash";
128
128
  import { IconButton, LucideIcon, Tooltip, Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from "@fileverse/ui";
129
129
  import DataVerificationPortal from "./dataVerificationPortal";
@@ -463,6 +463,14 @@ var Toolbar = function Toolbar(_a) {
463
463
  settings = _f.settings,
464
464
  handleUndo = _f.handleUndo,
465
465
  handleRedo = _f.handleRedo;
466
+ var restoreEditorFocusAfterToolbarAction = useCallback(function () {
467
+ if (context.luckysheetCellUpdate.length === 0) return;
468
+ requestAnimationFrame(function () {
469
+ var owner = getFormulaEditorOwner(context);
470
+ var target = owner === "fx" ? refs.fxInput.current : refs.cellInput.current;
471
+ target === null || target === void 0 ? void 0 : target.focus();
472
+ });
473
+ }, [context, refs.cellInput, refs.fxInput]);
466
474
  var contextRef = useRef(context);
467
475
  var containerRef = useRef(null);
468
476
  var _g = useState(-1),
@@ -1712,7 +1720,8 @@ var Toolbar = function Toolbar(_a) {
1712
1720
  return /*#__PURE__*/React.createElement("div", {
1713
1721
  ref: containerRef,
1714
1722
  className: "fortune-toolbar",
1715
- "aria-label": toolbar.toolbar
1723
+ "aria-label": toolbar.toolbar,
1724
+ onMouseUpCapture: restoreEditorFocusAfterToolbarAction
1716
1725
  }, /*#__PURE__*/React.createElement(DataVerificationPortal, {
1717
1726
  visible: showDataValidation
1718
1727
  }), /*#__PURE__*/React.createElement(ConditionalFormatPortal, {
@@ -2,22 +2,22 @@ import { type RefObject } from "react";
2
2
  import { type Context } from "@fileverse-dev/fortune-core";
3
3
  import type { SetContextOptions } from "../context";
4
4
  export type FormulaHistoryEntry = {
5
- text: string;
5
+ html: string;
6
6
  caret: number;
7
- spanValues: string[];
8
7
  };
9
8
  export type FormulaEditorHistoryPrimary = "cell" | "fx";
10
9
  type SetContext = (recipe: (ctx: Context) => void, options?: SetContextOptions) => void;
11
- export declare function useFormulaEditorHistory(primaryRef: RefObject<HTMLDivElement | null>, cellInputRef: RefObject<HTMLDivElement | null>, fxInputRef: RefObject<HTMLDivElement | null>, setContext: SetContext, primary: FormulaEditorHistoryPrimary): {
10
+ export declare function useFormulaEditorHistory(primaryRef: RefObject<HTMLDivElement | null>, cellInputRef: RefObject<HTMLDivElement | null>, fxInputRef: RefObject<HTMLDivElement | null>, _setContext: SetContext, primary: FormulaEditorHistoryPrimary): {
12
11
  formulaHistoryRef: RefObject<{
13
12
  active: boolean;
14
13
  entries: FormulaHistoryEntry[];
15
14
  index: number;
16
15
  }>;
17
16
  preTextRef: RefObject<string>;
18
- preFormulaSpanValuesRef: RefObject<string[] | null>;
19
17
  resetFormulaHistory: () => void;
20
18
  handleFormulaHistoryUndoRedo: (isRedo: boolean) => boolean;
19
+ capturePreEditorHistoryState: () => void;
20
+ appendEditorHistoryFromPrimaryEditor: (getCaret: () => number) => void;
21
21
  capturePreFormulaState: () => void;
22
22
  appendFormulaHistoryFromPrimaryEditor: (getCaret: () => number) => void;
23
23
  };
@@ -1,47 +1,54 @@
1
1
  import { useCallback, useRef } from "react";
2
- import _ from "lodash";
3
- import { escapeScriptTag, functionHTMLGenerate, escapeHTMLTag, handleFormulaInput } from "@fileverse-dev/fortune-core";
4
- import { setCursorPosition } from "../components/SheetOverlay/helper";
2
+ import { escapeScriptTag } from "@fileverse-dev/fortune-core";
3
+ import { getCursorPosition, getSelectionOffsets, setSelectionOffsets, setCursorPosition } from "../components/SheetOverlay/helper";
5
4
  var MAX_FORMULA_HISTORY = 100;
6
- export function useFormulaEditorHistory(primaryRef, cellInputRef, fxInputRef, setContext, primary) {
5
+ function normalizeEditorHtmlSnapshot(html) {
6
+ var stripped = (html !== null && html !== void 0 ? html : "").replace(/\u200B/g, "").trim();
7
+ if (stripped === "" || stripped === "<br>" || stripped === "<div><br></div>" || stripped === "<div></div>") {
8
+ return "";
9
+ }
10
+ return html !== null && html !== void 0 ? html : "";
11
+ }
12
+ export function useFormulaEditorHistory(primaryRef, cellInputRef, fxInputRef, _setContext, primary) {
7
13
  var preTextRef = useRef("");
8
- var preFormulaSpanValuesRef = useRef(null);
14
+ var preHtmlRef = useRef("");
15
+ var preCaretRef = useRef(0);
16
+ var startedFromEmptyRef = useRef(true);
9
17
  var formulaHistoryRef = useRef({
10
18
  active: false,
11
19
  entries: [],
12
20
  index: -1
13
21
  });
22
+ var isApplyingHistoryRef = useRef(false);
14
23
  var resetFormulaHistory = useCallback(function () {
15
24
  formulaHistoryRef.current = {
16
25
  active: false,
17
26
  entries: [],
18
27
  index: -1
19
28
  };
20
- preFormulaSpanValuesRef.current = null;
29
+ preHtmlRef.current = "";
30
+ preCaretRef.current = 0;
31
+ startedFromEmptyRef.current = true;
21
32
  }, []);
22
33
  var pushFormulaHistoryEntry = useCallback(function (entry) {
23
34
  var history = formulaHistoryRef.current;
24
35
  var current = history.entries[history.index];
25
- if (current && current.spanValues.length > 0 && entry.spanValues.length > 0 && _.isEqual(current.spanValues, entry.spanValues)) {
26
- return;
27
- }
28
- if (current && current.spanValues.length === 0 && entry.spanValues.length === 0 && current.text === entry.text && current.caret === entry.caret) {
36
+ if (current && current.html === entry.html) {
29
37
  return;
30
38
  }
31
39
  var nextEntries = history.entries.slice(0, history.index + 1);
32
40
  nextEntries.push(entry);
33
- if (nextEntries.length > MAX_FORMULA_HISTORY) {
34
- nextEntries.shift();
35
- }
41
+ if (nextEntries.length > MAX_FORMULA_HISTORY) nextEntries.shift();
36
42
  history.entries = nextEntries;
37
43
  history.index = nextEntries.length - 1;
38
44
  history.active = true;
39
45
  }, []);
40
- var applyFormulaHistoryEntry = useCallback(function (entry) {
46
+ var applyFormulaHistoryEntry = useCallback(function (entry, preserveSelection) {
47
+ var _a, _b, _c;
41
48
  var primaryEl = primaryRef.current;
42
49
  if (!primaryEl) return;
43
- var safeText = escapeScriptTag(entry.text || "");
44
- var html = safeText.startsWith("=") ? functionHTMLGenerate(safeText) : escapeHTMLTag(safeText);
50
+ isApplyingHistoryRef.current = true;
51
+ var html = escapeScriptTag((_a = entry.html) !== null && _a !== void 0 ? _a : "");
45
52
  var cell = cellInputRef.current;
46
53
  var fx = fxInputRef.current;
47
54
  primaryEl.innerHTML = html;
@@ -50,70 +57,91 @@ export function useFormulaEditorHistory(primaryRef, cellInputRef, fxInputRef, se
50
57
  } else if (cell) {
51
58
  cell.innerHTML = html;
52
59
  }
53
- setCursorPosition(primaryEl, Math.min(entry.caret, entry.text.length));
54
- setContext(function (draftCtx) {
55
- if (primary === "cell") {
56
- if (!cellInputRef.current) return;
57
- handleFormulaInput(draftCtx, fxInputRef.current, cellInputRef.current, 0);
58
- } else {
59
- if (!fxInputRef.current) return;
60
- handleFormulaInput(draftCtx, cellInputRef.current, fxInputRef.current, 0);
61
- }
60
+ var textLen = (_c = (_b = primaryEl.innerText) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0;
61
+ if (preserveSelection && preserveSelection.end > preserveSelection.start && textLen > 0) {
62
+ var start = Math.max(0, Math.min(preserveSelection.start, textLen));
63
+ var end = Math.max(start, Math.min(preserveSelection.end, textLen));
64
+ setSelectionOffsets(primaryEl, start, end);
65
+ } else {
66
+ setCursorPosition(primaryEl, Math.max(0, textLen));
67
+ }
68
+ requestAnimationFrame(function () {
69
+ requestAnimationFrame(function () {
70
+ setTimeout(function () {
71
+ isApplyingHistoryRef.current = false;
72
+ }, 120);
73
+ });
62
74
  });
63
- }, [cellInputRef, fxInputRef, primary, primaryRef, setContext]);
75
+ }, [cellInputRef, fxInputRef, primary, primaryRef]);
64
76
  var handleFormulaHistoryUndoRedo = useCallback(function (isRedo) {
77
+ var _a, _b;
65
78
  var history = formulaHistoryRef.current;
66
79
  if (!history.active || history.entries.length === 0) return false;
67
80
  var nextIndex = isRedo ? history.index + 1 : history.index - 1;
68
- if (nextIndex < 0 || nextIndex >= history.entries.length) return true;
81
+ if (nextIndex < 0 || nextIndex >= history.entries.length) {
82
+ if (!isRedo && nextIndex < 0 && startedFromEmptyRef.current) {
83
+ var liveHtml = normalizeEditorHtmlSnapshot((_b = (_a = primaryRef.current) === null || _a === void 0 ? void 0 : _a.innerHTML) !== null && _b !== void 0 ? _b : "");
84
+ if (liveHtml !== "") {
85
+ history.entries[0] = {
86
+ html: "",
87
+ caret: 0
88
+ };
89
+ history.index = 0;
90
+ var currentSelection_1 = primaryRef.current ? getSelectionOffsets(primaryRef.current) : undefined;
91
+ applyFormulaHistoryEntry(history.entries[0], currentSelection_1);
92
+ return true;
93
+ }
94
+ }
95
+ return false;
96
+ }
69
97
  history.index = nextIndex;
70
- applyFormulaHistoryEntry(history.entries[nextIndex]);
98
+ var entry = history.entries[nextIndex];
99
+ var currentSelection = primaryRef.current ? getSelectionOffsets(primaryRef.current) : undefined;
100
+ applyFormulaHistoryEntry(entry, currentSelection);
71
101
  return true;
72
- }, [applyFormulaHistoryEntry]);
73
- var capturePreFormulaState = useCallback(function () {
102
+ }, [applyFormulaHistoryEntry, primaryRef]);
103
+ var capturePreEditorHistoryState = useCallback(function () {
104
+ var _a;
74
105
  var el = primaryRef.current;
75
106
  if (!el) return;
76
107
  preTextRef.current = el.innerText;
77
- preFormulaSpanValuesRef.current = Array.from(el.querySelectorAll("span.fortune-formula-functionrange-cell")).map(function (node) {
78
- var _a;
79
- return (_a = node.textContent) !== null && _a !== void 0 ? _a : "";
80
- });
108
+ preHtmlRef.current = el.innerHTML;
109
+ preCaretRef.current = getCursorPosition(el);
110
+ if (!formulaHistoryRef.current.active) {
111
+ startedFromEmptyRef.current = normalizeEditorHtmlSnapshot((_a = preHtmlRef.current) !== null && _a !== void 0 ? _a : "") === "";
112
+ }
81
113
  }, [primaryRef]);
82
- var appendFormulaHistoryFromPrimaryEditor = useCallback(function (getCaret) {
114
+ var appendEditorHistoryFromPrimaryEditor = useCallback(function (getCaret) {
83
115
  var _a, _b;
116
+ if (isApplyingHistoryRef.current) return;
84
117
  var el = primaryRef.current;
85
118
  if (!el) return;
86
- var currentText = el.innerText || "";
87
- if (currentText.startsWith("=")) {
88
- var caret = getCaret();
89
- var spanValues = Array.from(el.querySelectorAll("span.fortune-formula-functionrange-cell")).map(function (node) {
90
- var _a;
91
- return (_a = node.textContent) !== null && _a !== void 0 ? _a : "";
92
- });
93
- if (!formulaHistoryRef.current.active) {
94
- var seedText = preTextRef.current || "";
95
- pushFormulaHistoryEntry({
96
- text: seedText,
97
- caret: Math.min(caret, seedText.length),
98
- spanValues: (_b = (_a = preFormulaSpanValuesRef.current) !== null && _a !== void 0 ? _a : spanValues) !== null && _b !== void 0 ? _b : []
99
- });
100
- }
119
+ var preHtmlSnapshot = normalizeEditorHtmlSnapshot((_a = preHtmlRef.current) !== null && _a !== void 0 ? _a : "");
120
+ var snapshotHtml = normalizeEditorHtmlSnapshot((_b = el.innerHTML) !== null && _b !== void 0 ? _b : "");
121
+ var caret = getCaret();
122
+ var history = formulaHistoryRef.current;
123
+ var wasInactive = !history.active || history.entries.length === 0;
124
+ if (wasInactive) {
125
+ startedFromEmptyRef.current = preHtmlSnapshot === "";
126
+ var seedHtml = preHtmlSnapshot === snapshotHtml ? "" : preHtmlSnapshot !== null && preHtmlSnapshot !== void 0 ? preHtmlSnapshot : "";
101
127
  pushFormulaHistoryEntry({
102
- text: currentText,
103
- caret: caret,
104
- spanValues: spanValues
128
+ html: seedHtml,
129
+ caret: preCaretRef.current
105
130
  });
106
- } else if (formulaHistoryRef.current.active) {
107
- resetFormulaHistory();
108
131
  }
109
- }, [primaryRef, pushFormulaHistoryEntry, resetFormulaHistory]);
132
+ pushFormulaHistoryEntry({
133
+ html: snapshotHtml,
134
+ caret: caret
135
+ });
136
+ }, [primaryRef, pushFormulaHistoryEntry]);
110
137
  return {
111
138
  formulaHistoryRef: formulaHistoryRef,
112
139
  preTextRef: preTextRef,
113
- preFormulaSpanValuesRef: preFormulaSpanValuesRef,
114
140
  resetFormulaHistory: resetFormulaHistory,
115
141
  handleFormulaHistoryUndoRedo: handleFormulaHistoryUndoRedo,
116
- capturePreFormulaState: capturePreFormulaState,
117
- appendFormulaHistoryFromPrimaryEditor: appendFormulaHistoryFromPrimaryEditor
142
+ capturePreEditorHistoryState: capturePreEditorHistoryState,
143
+ appendEditorHistoryFromPrimaryEditor: appendEditorHistoryFromPrimaryEditor,
144
+ capturePreFormulaState: capturePreEditorHistoryState,
145
+ appendFormulaHistoryFromPrimaryEditor: appendEditorHistoryFromPrimaryEditor
118
146
  };
119
147
  }
@@ -1,2 +1,2 @@
1
1
  import { type RefObject } from "react";
2
- export declare function useRerenderOnFormulaCaret(editorRef: RefObject<HTMLDivElement | null>, editSessionActive: boolean): void;
2
+ export declare function useRerenderOnFormulaCaret(editorRef: RefObject<HTMLDivElement | null>, editSessionActive: boolean, onAfterCaretMove?: () => void): void;
@@ -1,13 +1,15 @@
1
- import { useEffect, useState } from "react";
2
- export function useRerenderOnFormulaCaret(editorRef, editSessionActive) {
1
+ import { useEffect, useRef, useState } from "react";
2
+ export function useRerenderOnFormulaCaret(editorRef, editSessionActive, onAfterCaretMove) {
3
3
  var _a = useState(0),
4
4
  bump = _a[1];
5
+ var onAfterCaretMoveRef = useRef(onAfterCaretMove);
6
+ onAfterCaretMoveRef.current = onAfterCaretMove;
5
7
  useEffect(function () {
6
8
  if (!editSessionActive) {
7
9
  return function () {};
8
10
  }
9
11
  var onSelectionChange = function onSelectionChange() {
10
- var _a, _b;
12
+ var _a, _b, _c;
11
13
  var el = editorRef.current;
12
14
  if (!el) return;
13
15
  var text = (_b = (_a = el.innerText) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : "";
@@ -19,6 +21,7 @@ export function useRerenderOnFormulaCaret(editorRef, editSessionActive) {
19
21
  bump(function (n) {
20
22
  return n + 1;
21
23
  });
24
+ (_c = onAfterCaretMoveRef.current) === null || _c === void 0 ? void 0 : _c.call(onAfterCaretMoveRef);
22
25
  };
23
26
  document.addEventListener("selectionchange", onSelectionChange);
24
27
  return function () {