@zhenliang/sheet 0.2.5-beta.1 → 0.2.5-beta.11

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.
@@ -4,41 +4,45 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
4
4
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
5
5
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
6
6
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
7
- function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
8
7
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
9
8
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
10
9
  function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
11
10
  function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
12
11
  function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
13
12
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
14
- import { Dropdown, Menu, Tooltip } from 'antd';
15
- import { head, isEmpty, isNil } from 'lodash';
13
+ function _objectDestructuringEmpty(obj) { if (obj == null) throw new TypeError("Cannot destructure " + obj); }
14
+ import { Dropdown, Input } from 'antd';
15
+ import { get, head, isEmpty, isNil } from 'lodash';
16
16
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
17
- import { InfoCircleOutlined } from '@ant-design/icons';
18
- import { flattenOptions, getStringDiff, replaceLabelsWithValues, replaceLongestDiff, replaceValuesWithLabels, tokenize, validateVariables, getCursorPositionInSpan } from "./utils";
19
- import validateCalculationExpr from "./vaildFormula";
17
+ import { formulaString } from "../numberEditor";
18
+ import DropMenu from "./DropMenu";
20
19
  import "./index.less";
20
+ import { useKeyEventEffect } from "./keyEventEffect";
21
+ import { createSpan, flattenOptions, getStringDiff, moveCursorToSpan, replaceLabelsWithValues, replaceLongestDiff, replaceValuesWithLabels, SpanType, tokenize, validateVariables } from "./utils";
22
+ import validateCalculationExpr from "./vaildFormula";
21
23
  import { jsx as _jsx } from "react/jsx-runtime";
22
- import { jsxs as _jsxs } from "react/jsx-runtime";
23
- var OPERATORS = ['=', '+', '-', '*', '/'];
24
-
25
- // 获取光标所在的 span
26
- var getSpanAtCursor = function getSpanAtCursor(startContainer) {
27
- if (startContainer.nodeType === Node.TEXT_NODE) {
28
- return startContainer.parentElement;
29
- }
30
- if (startContainer.nodeType === Node.ELEMENT_NODE) {
31
- return startContainer;
32
- }
33
- return null;
34
- };
35
- export var getFormulaInputEditor = function getFormulaInputEditor(options, replaceIndex) {
24
+ var OPERATORS = ['=', '+', '-', '*', '/', '('];
25
+ var LABEL = SpanType.LABEL,
26
+ OTHER = SpanType.OTHER;
27
+ export var getFormulaInputEditor = function getFormulaInputEditor(options, replaceIndex, extraProps, getExtraProps, choseEditor) {
28
+ var _ref = extraProps || {},
29
+ warnMethod = _ref.warnMethod,
30
+ rangeMethod = _ref.rangeMethod,
31
+ precision = _ref.precision,
32
+ max = _ref.max,
33
+ min = _ref.min;
36
34
  var FormulaInputEditor = function FormulaInputEditor(props) {
35
+ var _get;
37
36
  var originValue = props.value,
38
37
  onChange = props.onChange,
39
38
  isEditing = props.isEditing,
40
39
  record = props.record;
41
- var calcValue = replaceIndex ? record === null || record === void 0 ? void 0 : record[replaceIndex] : originValue;
40
+ // 兼容number
41
+ var inputNumberRef = useRef(null);
42
+ var _ref2 = getExtraProps ? getExtraProps(props) : extraProps !== null && extraProps !== void 0 ? extraProps : {},
43
+ inputArgs = Object.assign({}, (_objectDestructuringEmpty(_ref2), _ref2));
44
+ var replaceValue = replaceIndex ? (_get = get(record, [replaceIndex])) !== null && _get !== void 0 ? _get : '' : originValue;
45
+ var calcValue = replaceValue.startsWith('=') ? replaceValue : "=".concat(replaceValue);
42
46
  var _useState = useState(calcValue),
43
47
  _useState2 = _slicedToArray(_useState, 1),
44
48
  inputValue = _useState2[0];
@@ -47,7 +51,7 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
47
51
  offsetX = _useState4[0],
48
52
  setOffsetX = _useState4[1];
49
53
  // 为了不重新render,再写一个
50
- var _useState5 = useState(calcValue),
54
+ var _useState5 = useState(replaceValue),
51
55
  _useState6 = _slicedToArray(_useState5, 2),
52
56
  containerValue = _useState6[0],
53
57
  setContainerValue = _useState6[1];
@@ -60,6 +64,7 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
60
64
  _useState10 = _slicedToArray(_useState9, 2),
61
65
  inputAfterDropDownShow = _useState10[0],
62
66
  setInputAfterDropDownShow = _useState10[1];
67
+ var tempSpanRef = useRef(null);
63
68
  var containerRef = useRef(null);
64
69
  var inputOperatorPosition = useRef(0);
65
70
 
@@ -73,61 +78,57 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
73
78
  return tokenize(inputValue, flatOptions);
74
79
  }, [inputValue, flatOptions]);
75
80
  // 根据搜索文本获取筛选后的层级选项(保持层级结构)
76
- var filteredHierarchyOptions = useMemo(function () {
77
- var searchText = inputAfterDropDownShow;
78
- // 如果搜索文本为空,显示所有选项(保持层级)
79
- if (!searchText) {
80
- return options;
81
- }
82
81
 
83
- // 根据搜索文本筛选,保持层级结构
84
- var filterWithHierarchy = function filterWithHierarchy(items) {
85
- var result = [];
86
- var _iterator = _createForOfIteratorHelper(items),
87
- _step;
88
- try {
89
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
90
- var item = _step.value;
91
- var labelMatch = item.label.includes(searchText);
92
- // 筛选 children
93
- var filteredChildren = item.children ? filterWithHierarchy(item.children) : [];
94
- if (labelMatch || filteredChildren.length > 0) {
95
- result.push(_objectSpread(_objectSpread({}, item), {}, {
96
- children: filteredChildren.length > 0 ? filteredChildren : item.children
97
- }));
98
- }
99
- }
100
- } catch (err) {
101
- _iterator.e(err);
102
- } finally {
103
- _iterator.f();
104
- }
105
- return result;
106
- };
107
- return filterWithHierarchy(options);
108
- }, [inputAfterDropDownShow]);
109
82
  useEffect(function () {
110
83
  if (!open) {
111
84
  containerValueSnapShot.current = '';
85
+ tempSpanRef.current = null;
112
86
  }
113
87
  setInputAfterDropDownShow('');
114
88
  }, [open]);
89
+ var closeDorpDown = useCallback(function () {
90
+ setInputAfterDropDownShow('');
91
+ tempSpanRef.current = null;
92
+ // 点击div内直接关闭
93
+ setOpen(false);
94
+ }, []);
115
95
 
116
- // 处理选项点击:删除用户刚输入的值,将选中的 label 放到运算符后面
96
+ // 处理选项点击
117
97
  var handleOptionClick = useCallback(function (opt) {
118
98
  var container = containerRef.current;
119
99
  if (!container) return;
120
- var newValue = replaceLongestDiff(containerValueSnapShot.current, opt.label, inputOperatorPosition.current);
121
- setOpen(false);
122
- containerValueSnapShot.current = '';
123
- var expr = newValue;
124
- var valueExpr = replaceLabelsWithValues(expr, flatOptions);
125
- setContainerValue(valueExpr);
126
- onChange(valueExpr);
127
-
128
- // 获取当前光标所在的 span
129
100
  var selection = window.getSelection();
130
101
  if (!selection || selection.rangeCount === 0) return;
102
+
103
+ // 如果有 tempSpanRef,用新逻辑:直接替换该 span 的内容
104
+ if (tempSpanRef.current) {
105
+ tempSpanRef.current.textContent = opt.label;
106
+ var replacedSpan = tempSpanRef.current;
107
+ tempSpanRef.current = null;
108
+
109
+ // 光标移到替换后的 span 后面
110
+ var _allSpans = Array.from(container.querySelectorAll('span'));
111
+ var replacedIndex = _allSpans.indexOf(replacedSpan);
112
+ var _targetSpan = _allSpans[replacedIndex + 1];
113
+ if (!_targetSpan || _targetSpan.classList.contains('formula-editor-token-label')) {
114
+ _targetSpan = createSpan(OTHER, '');
115
+ replacedSpan.after(_targetSpan);
116
+ }
117
+ moveCursorToSpan(_targetSpan, true, selection);
118
+ // 更新 containerValue
119
+ var newValue = container.textContent || '';
120
+ var valueExpr = replaceLabelsWithValues(newValue, flatOptions);
121
+ setContainerValue(valueExpr);
122
+ onChange(valueExpr);
123
+ setOpen(false);
124
+ return;
125
+ }
126
+ // 原逻辑:删除 inputAfterDropDownShow,插入新 label
127
+ var newValueUser = replaceLongestDiff(containerValueSnapShot.current, opt.label, inputOperatorPosition.current);
128
+ var expr = newValueUser;
129
+ var valueExprUser = replaceLabelsWithValues(expr, flatOptions);
130
+ setContainerValue(valueExprUser);
131
+ onChange(valueExprUser);
131
132
  var range = selection.getRangeAt(0);
132
133
  var startContainer = range.startContainer;
133
134
  var currentSpan = startContainer.nodeType === Node.TEXT_NODE ? startContainer.parentElement : startContainer;
@@ -145,23 +146,17 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
145
146
  var afterPart = spanText.slice(deleteIndex + deleteText.length);
146
147
 
147
148
  // 删除当前 span,用三个 span 替换:other(前)、label、other(后)
148
- var labelSpan = document.createElement('span');
149
- labelSpan.className = 'formula-editor-token-label';
150
- labelSpan.textContent = opt.label;
149
+ var labelSpan = createSpan(LABEL, opt.label);
151
150
 
152
151
  // 创建待插入的 span 列表
153
152
  var spansToInsert = [];
154
153
  if (beforePart) {
155
- var beforeSpan = document.createElement('span');
156
- beforeSpan.className = 'formula-editor-token-other';
157
- beforeSpan.textContent = beforePart;
154
+ var beforeSpan = createSpan(OTHER, beforePart);
158
155
  spansToInsert.push(beforeSpan);
159
156
  }
160
157
  spansToInsert.push(labelSpan);
161
158
  if (afterPart) {
162
- var afterSpan = document.createElement('span');
163
- afterSpan.className = 'formula-editor-token-other';
164
- afterSpan.textContent = afterPart;
159
+ var afterSpan = createSpan(OTHER, afterPart);
165
160
  spansToInsert.push(afterSpan);
166
161
  }
167
162
  // 插入所有 span
@@ -175,24 +170,20 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
175
170
 
176
171
  // 如果下一个 span 是 label 类型或没有下一个 span,则插入一个空 span
177
172
  if (!targetSpan || targetSpan.classList.contains('formula-editor-token-label')) {
178
- targetSpan = document.createElement('span');
179
- targetSpan.className = 'formula-editor-token-other';
180
- targetSpan.textContent = '';
173
+ targetSpan = createSpan(OTHER, '');
181
174
  labelSpan.after(targetSpan);
182
175
  }
183
-
184
- // 将光标移到目标 span 的开头
185
- var newRange = document.createRange();
186
- newRange.selectNodeContents(targetSpan);
187
- newRange.collapse(true);
188
- selection.removeAllRanges();
189
- selection.addRange(newRange);
176
+ moveCursorToSpan(targetSpan, true, selection);
177
+ setOpen(false);
190
178
  }, [inputAfterDropDownShow]);
191
179
 
192
180
  // 处理输入变化
193
181
  var handleInput = useCallback(function () {
194
182
  var container = containerRef.current;
195
183
  if (!container) return;
184
+ if (tempSpanRef.current) {
185
+ closeDorpDown();
186
+ }
196
187
  var newValue = container.textContent || '';
197
188
  var processedValue = newValue;
198
189
  var expr = processedValue;
@@ -216,7 +207,7 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
216
207
  if (open) {
217
208
  var _getStringDiff2 = getStringDiff(containerValueSnapShot.current, newValue),
218
209
  addedOnSnapShot = _getStringDiff2.added;
219
- isBeginWithNumber = /^\d$/.test(head(addedOnSnapShot));
210
+ isBeginWithNumber = /^\d$/.test(head(addedOnSnapShot.join('').trim()));
220
211
  inputStringAfterDropDownShow = addedOnSnapShot.join('');
221
212
  }
222
213
  if (pressAOperator) {
@@ -245,6 +236,18 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
245
236
  setInputAfterDropDownShow(inputStringAfterDropDownShow);
246
237
  onChange(valueExpr);
247
238
  }, [containerValue, open]);
239
+ var _useKeyEventEffect = useKeyEventEffect({
240
+ closeDorpDown: closeDorpDown,
241
+ setOffsetX: setOffsetX,
242
+ setOpen: setOpen,
243
+ containerRef: containerRef,
244
+ tempSpanRef: tempSpanRef,
245
+ inputAfterDropDownShow: inputAfterDropDownShow,
246
+ options: options
247
+ }),
248
+ handleMouseUp = _useKeyEventEffect.handleMouseUp,
249
+ handleKeyDown = _useKeyEventEffect.handleKeyDown,
250
+ filteredHierarchyOptions = _useKeyEventEffect.filteredHierarchyOptions;
248
251
 
249
252
  // 编辑状态时自动聚焦
250
253
  useEffect(function () {
@@ -253,309 +256,46 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
253
256
  (_containerRef$current2 = containerRef.current) === null || _containerRef$current2 === void 0 || _containerRef$current2.focus();
254
257
  }
255
258
  }, [isEditing]);
256
- var closeDorpDown = useCallback(function () {
257
- // 点击div内直接关闭
258
- setOpen(false);
259
- }, []);
260
-
261
- // 鼠标释放时,如果光标在 label span 内,移动到后一个 span 的开头
262
- var handleMouseUp = useCallback(function () {
263
- var div = containerRef.current;
264
- if (!div) return;
265
- closeDorpDown();
266
- var selection = window.getSelection();
267
- if (!selection || selection.rangeCount === 0) return;
268
- var range = selection.getRangeAt(0);
269
- var startContainer = range.startContainer;
270
- var currentSpan = getSpanAtCursor(startContainer);
271
- if (!currentSpan || currentSpan === div) return;
272
- var isLabelSpan = currentSpan.classList.contains('formula-editor-token-label');
273
-
274
- // 如果在 label span 内,移动到下一个 span 的开头
275
- if (isLabelSpan) {
276
- var allSpans = Array.from(div.querySelectorAll('span'));
277
- var currentIndex = allSpans.indexOf(currentSpan);
278
- if (currentIndex < allSpans.length - 1) {
279
- var nextSpan = allSpans[currentIndex + 1];
280
- var newRange = document.createRange();
281
- newRange.selectNodeContents(nextSpan);
282
- newRange.collapse(true);
283
- selection.removeAllRanges();
284
- selection.addRange(newRange);
285
- }
286
- }
287
- }, [closeDorpDown]);
288
- var handleKeyDown = useCallback(function (e) {
289
- var _currentSpan$textCont, _currentSpan$textCont2;
290
- if (e.key === 'ArrowUp' || e.key === "ArrowDown") {
291
- e.preventDefault();
292
- e.stopPropagation();
293
- return;
294
- }
295
- var div = containerRef.current;
296
- if (!div) return;
297
- var selection = window.getSelection();
298
- if (!selection || selection.rangeCount === 0) return;
299
- var range = selection.getRangeAt(0);
300
- var startContainer = range.startContainer,
301
- startOffset = range.startOffset;
302
- var currentSpan = getSpanAtCursor(startContainer);
303
- if (!currentSpan || currentSpan === div) return;
304
- var allSpans = Array.from(div.querySelectorAll('span'));
305
- var currentIndex = allSpans.indexOf(currentSpan);
306
- var textLen = (_currentSpan$textCont = (_currentSpan$textCont2 = currentSpan.textContent) === null || _currentSpan$textCont2 === void 0 ? void 0 : _currentSpan$textCont2.length) !== null && _currentSpan$textCont !== void 0 ? _currentSpan$textCont : 0;
307
-
308
- // 方向键:跳过 label span
309
- if (e.key === 'ArrowRight' || e.key === 'ArrowLeft') {
310
- closeDorpDown();
311
- var position = getCursorPositionInSpan(currentSpan);
312
- var isAtEnd = startOffset >= textLen;
313
- var isAtStart = startOffset === 0;
314
- var isAlmostEnd = startOffset >= textLen - 1;
315
- var isAlmostStart = position === 1;
316
- if (e.key === 'ArrowRight' && isAtEnd) {
317
- // 向右 + 在末尾 -> 跳到下一个 span 的开头(跳过 label span)
318
- var targetIndex = currentIndex + 1;
319
- while (targetIndex < allSpans.length && allSpans[targetIndex].classList.contains('formula-editor-token-label')) {
320
- targetIndex++;
321
- }
322
- if (targetIndex < allSpans.length && targetIndex !== currentIndex + 1) {
323
- e.preventDefault();
324
- var targetSpan = allSpans[targetIndex];
325
- var newRange = document.createRange();
326
- newRange.selectNodeContents(targetSpan);
327
- newRange.collapse(true);
328
- selection.removeAllRanges();
329
- selection.addRange(newRange);
330
- }
331
- } else if (e.key === 'ArrowLeft' && isAtStart) {
332
- // 向左 + 在开头 -> 跳到上一个 span 的末尾(跳过 label span)
333
- var _targetIndex = currentIndex - 1;
334
- while (_targetIndex >= 0 && allSpans[_targetIndex].classList.contains('formula-editor-token-label')) {
335
- _targetIndex--;
336
- }
337
- if (_targetIndex >= 0 && _targetIndex !== currentIndex - 1) {
338
- e.preventDefault();
339
- var _targetSpan = allSpans[_targetIndex];
340
- var _newRange = document.createRange();
341
- _newRange.selectNodeContents(_targetSpan);
342
- _newRange.collapse(false);
343
- selection.removeAllRanges();
344
- selection.addRange(_newRange);
345
- }
346
- } else if (e.key === 'ArrowRight' && isAlmostEnd) {
347
- var _targetIndex2 = currentIndex + 1;
348
- if (_targetIndex2 < allSpans.length && !allSpans[_targetIndex2].classList.contains('formula-editor-token-label')) {
349
- e.preventDefault();
350
- var _targetSpan2 = allSpans[_targetIndex2];
351
- var _newRange2 = document.createRange();
352
- _newRange2.selectNodeContents(_targetSpan2);
353
- _newRange2.collapse(true);
354
- selection.removeAllRanges();
355
- selection.addRange(_newRange2);
356
- }
357
- } else if (e.key === 'ArrowLeft' && isAlmostStart) {
358
- var _targetIndex3 = currentIndex - 1;
359
- if (_targetIndex3 >= 0 && !allSpans[_targetIndex3].classList.contains('formula-editor-token-label')) {
360
- e.preventDefault();
361
- var _targetSpan3 = allSpans[_targetIndex3];
362
- var _newRange3 = document.createRange();
363
- _newRange3.selectNodeContents(_targetSpan3);
364
- _newRange3.collapse(false);
365
- selection.removeAllRanges();
366
- selection.addRange(_newRange3);
367
- }
368
- }
369
- return;
370
- }
371
-
372
- // 删除键逻辑
373
- if (e.key !== 'Delete' && e.key !== 'Backspace') return;
374
-
375
- // 不在 label span 内,在 span 开头且前一个是 label 时,删除整个 label span
376
- if (startOffset === 0 && e.key === 'Backspace' && currentIndex > 0) {
377
- var prevSpan = allSpans[currentIndex - 1];
378
- if (prevSpan.classList.contains('formula-editor-token-label')) {
379
- e.preventDefault();
380
- e.stopPropagation();
381
- prevSpan.remove();
382
- var _newRange4 = document.createRange();
383
-
384
- // 如果当前 span 有内容,光标放在开头;否则找最近的有内容的 span
385
- if (currentSpan.textContent !== '') {
386
- _newRange4.selectNodeContents(currentSpan);
387
- _newRange4.collapse(true);
388
- } else {
389
- // 找前一个最近的有内容的 span
390
- var _targetSpan4;
391
- for (var i = currentIndex - 2; i >= 0; i--) {
392
- if (allSpans[i].textContent !== '') {
393
- _targetSpan4 = allSpans[i];
394
- break;
395
- }
396
- }
397
- if (_targetSpan4) {
398
- _newRange4.selectNodeContents(_targetSpan4);
399
- _newRange4.collapse(false);
400
- } else {
401
- _newRange4.selectNodeContents(div);
402
- _newRange4.collapse(true);
403
- }
404
- }
405
- selection.removeAllRanges();
406
- selection.addRange(_newRange4);
407
- return;
408
- }
259
+ var handleChange = useCallback(function (value) {
260
+ onChange(!isNil(value) ? value : null);
261
+ }, [onChange]);
262
+ useEffect(function () {
263
+ if (isEditing) {
264
+ var _inputNumberRef$curre;
265
+ inputNumberRef === null || inputNumberRef === void 0 || (_inputNumberRef$curre = inputNumberRef.current) === null || _inputNumberRef$curre === void 0 || _inputNumberRef$curre.focus();
409
266
  }
410
-
411
- // span 开头 + Delete 键,光标移到前一个 span 的末尾
412
- if (startOffset === 0 && e.key === 'Backspace' && currentIndex > 0) {
413
- var _prevSpan = allSpans[currentIndex - 1];
414
- // 前一个 span 是非 label span 时,光标移到其末尾
415
- if (!_prevSpan.classList.contains('formula-editor-token-label')) {
416
- e.preventDefault();
417
- e.stopPropagation();
418
- var prevText = _prevSpan.textContent || '';
419
- if (prevText.length > 0) {
420
- _prevSpan.textContent = prevText.slice(0, -1);
421
- }
422
- var _newRange5 = document.createRange();
423
- _newRange5.selectNodeContents(_prevSpan);
424
- _newRange5.collapse(false);
425
- selection.removeAllRanges();
426
- selection.addRange(_newRange5);
427
- }
267
+ }, [isEditing]);
268
+ var reFocus = useCallback(function () {
269
+ if (isEditing) {
270
+ var _inputNumberRef$curre2;
271
+ inputNumberRef === null || inputNumberRef === void 0 || (_inputNumberRef$curre2 = inputNumberRef.current) === null || _inputNumberRef$curre2 === void 0 || _inputNumberRef$curre2.focus();
428
272
  }
429
-
430
- // 其他情况:等待浏览器完成默认删除后,检查当前 span 是否为空
431
- setTimeout(function () {
432
- var currentSpanNow = getSpanAtCursor(startContainer);
433
- var allSpansNow = Array.from(div.querySelectorAll('span'));
434
-
435
- // 如果 currentSpanNow 不在 allSpansNow 里(被浏览器删除了)
436
- // 且还有 span 存在,用按下删除键时的 currentSpan 位置往前找
437
- if (allSpansNow.length > 0 && !allSpansNow.includes(currentSpanNow)) {
438
- // 如果光标在 span 开头 + Delete 键,currentIndex 指向的是被删 span 的后一个,所以要 -1
439
- var searchIndex = startOffset === 0 ? currentIndex - 1 : currentIndex;
440
- // searchIndex 位置往前找
441
- var _targetSpan5;
442
- for (var _i = searchIndex; _i >= 0; _i--) {
443
- var span = allSpansNow[_i];
444
- if (span.textContent !== '') {
445
- _targetSpan5 = span;
446
- break;
447
- }
448
- }
449
- // 如果找到的有内容 span 是 label,则把光标放在 label span 的后一个 span 的开头
450
- if (_targetSpan5 && _targetSpan5.classList.contains('formula-editor-token-label')) {
451
- var labelIndex = allSpansNow.indexOf(_targetSpan5);
452
- if (labelIndex < allSpansNow.length - 1) {
453
- var nextSpan = allSpansNow[labelIndex + 1];
454
- var _newRange6 = document.createRange();
455
- _newRange6.selectNodeContents(nextSpan);
456
- _newRange6.collapse(true);
457
- selection.removeAllRanges();
458
- selection.addRange(_newRange6);
459
- return;
460
- }
461
- }
462
-
463
- // 否则把光标放在找到的 span 的末尾
464
- if (_targetSpan5) {
465
- var _newRange7 = document.createRange();
466
- _newRange7.selectNodeContents(_targetSpan5);
467
- _newRange7.collapse(false);
468
- selection.removeAllRanges();
469
- selection.addRange(_newRange7);
470
- return;
471
- }
472
- }
473
- if (!currentSpanNow || currentSpanNow === div) return;
474
- if (currentSpanNow.textContent === '') {
475
- var currentIndexNow = allSpansNow.indexOf(currentSpanNow);
476
- var _newRange8 = document.createRange();
477
- if (currentIndexNow > 0) {
478
- // 移到前一个 span 的末尾,但如果前一个 span 是 label,则移到后一个 span 的开头
479
- var _targetSpan6 = allSpansNow[currentIndexNow - 1];
480
- if (_targetSpan6.classList.contains('formula-editor-token-label')) {
481
- // 移到 label span 的后一个 span 的开头
482
- if (currentIndexNow < allSpansNow.length - 1) {
483
- var _nextSpan = allSpansNow[currentIndexNow + 1];
484
- _newRange8.selectNodeContents(_nextSpan);
485
- _newRange8.collapse(true);
486
- } else {
487
- _newRange8.selectNodeContents(div);
488
- _newRange8.collapse(false);
489
- }
490
- } else {
491
- _newRange8.selectNodeContents(_targetSpan6);
492
- _newRange8.collapse(false);
493
- }
494
- currentSpanNow.remove();
495
- } else if (allSpansNow.length > 1) {
496
- // 第一个 span 为空,移到下一个 span 的开头
497
- var _nextSpan2 = allSpansNow[currentIndexNow + 1];
498
- _newRange8.selectNodeContents(_nextSpan2);
499
- _newRange8.collapse(true);
500
- currentSpanNow.remove();
501
- } else {
502
- // 只有一个空 span,保持空
503
- _newRange8.selectNodeContents(div);
504
- _newRange8.collapse(true);
505
- }
506
- selection.removeAllRanges();
507
- selection.addRange(_newRange8);
273
+ }, [isEditing]);
274
+ if (choseEditor && choseEditor(record)) {
275
+ var _ref3;
276
+ return /*#__PURE__*/_jsx(Input, _objectSpread(_objectSpread({
277
+ ref: inputNumberRef,
278
+ onBlur: reFocus
279
+ }, inputArgs), {}, {
280
+ className: "number-editor",
281
+ onMouseDown: function onMouseDown(e) {
282
+ return e.stopPropagation();
283
+ },
284
+ value: (_ref3 = originValue) !== null && _ref3 !== void 0 ? _ref3 : '',
285
+ onChange: function onChange(e) {
286
+ handleChange(e.target.value);
508
287
  }
509
- }, 0);
510
- }, []);
511
- var dropdownContent = /*#__PURE__*/_jsx(Menu, {
512
- className: "formula-editor-dropdown",
513
- style: {
514
- transform: "translateX(".concat(offsetX, "px)")
515
- },
516
- onMouseDown: function onMouseDown(e) {
517
- e.preventDefault();
518
- e.stopPropagation();
519
- },
520
- children: filteredHierarchyOptions.length === 0 ? /*#__PURE__*/_jsx(Menu.Item, {
521
- disabled: true,
522
- children: /*#__PURE__*/_jsx("span", {
523
- className: "formula-editor-dropdown-no-data",
524
- children: "\u6682\u65E0\u6570\u636E"
525
- })
526
- }, "no-data") : filteredHierarchyOptions.map(function (opt) {
527
- return opt.children && opt.children.length > 0 ? /*#__PURE__*/_jsx(Menu.SubMenu, {
528
- title: opt.label,
529
- className: "formula-editor-dropdown-submenu",
530
- children: opt.children.map(function (child) {
531
- return /*#__PURE__*/_jsx(Menu.Item, {
532
- className: "formula-editor-dropdown-item",
533
- onClick: function onClick() {
534
- return handleOptionClick(child);
535
- },
536
- children: child.label
537
- }, child.value);
538
- })
539
- }, opt.value) : /*#__PURE__*/_jsxs(Menu.Item, {
540
- className: "formula-editor-dropdown-item",
541
- onClick: function onClick() {
542
- return handleOptionClick(opt);
543
- },
544
- children: [opt.label, opt.info ? /*#__PURE__*/_jsx(Tooltip, {
545
- title: opt.info,
546
- children: /*#__PURE__*/_jsx(InfoCircleOutlined, {
547
- style: {
548
- color: '#FF9900',
549
- marginLeft: 4
550
- }
551
- })
552
- }) : null]
553
- }, opt.value);
554
- })
555
- });
288
+ }));
289
+ }
556
290
  return /*#__PURE__*/_jsx(Dropdown, {
557
291
  overlayClassName: "dropDownOffset",
558
- overlay: dropdownContent,
292
+ overlay: /*#__PURE__*/_jsx(DropMenu, {
293
+ options: filteredHierarchyOptions,
294
+ onOptionClick: handleOptionClick,
295
+ style: {
296
+ transform: "translateX(".concat(offsetX, "px)")
297
+ }
298
+ }),
559
299
  open: open,
560
300
  children: /*#__PURE__*/_jsx("div", {
561
301
  ref: containerRef,
@@ -571,13 +311,13 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
571
311
  spellCheck: false,
572
312
  children: isEmpty(tokens) ? /*#__PURE__*/_jsx("span", {
573
313
  style: {
574
- minWidth: 8,
314
+ minWidth: 1,
575
315
  height: 40
576
316
  }
577
317
  }) : tokens.map(function (token, index) {
578
318
  return token.type === 'end' ? /*#__PURE__*/_jsx("span", {
579
319
  style: {
580
- minWidth: 8,
320
+ minWidth: 1,
581
321
  height: 40
582
322
  }
583
323
  }, index) : /*#__PURE__*/_jsx("span", {
@@ -593,22 +333,40 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
593
333
  var flatOptions = flattenOptions(options);
594
334
 
595
335
  // checker:使用 validateCalculationExpr 校验语法 + 校验变量是否都在 options 中
596
- FormulaInputEditor.checker = function (value) {
336
+ FormulaInputEditor.checker = function (value, record, currentValue) {
597
337
  if (isNil(value)) return true;
338
+ if (choseEditor && choseEditor(record)) {
339
+ var _String;
340
+ var result = (_String = String(value)) === null || _String === void 0 ? void 0 : _String.replace(/,/g, '');
341
+ result = formulaString(result, currentValue, precision);
342
+ // parse number with thousands separator
343
+ var range = rangeMethod === null || rangeMethod === void 0 ? void 0 : rangeMethod(record);
344
+ if (!isNil(range === null || range === void 0 ? void 0 : range.max) && !isNil(range === null || range === void 0 ? void 0 : range.min)) {
345
+ var _ref4 = range || {},
346
+ _ref4$max = _ref4.max,
347
+ _max = _ref4$max === void 0 ? 0 : _ref4$max,
348
+ _ref4$min = _ref4.min,
349
+ _min = _ref4$min === void 0 ? 0 : _ref4$min;
350
+ if (result < _min || result > _max) {
351
+ warnMethod === null || warnMethod === void 0 || warnMethod(record);
352
+ return false;
353
+ }
354
+ }
355
+ if (isNaN(result)) {
356
+ return false;
357
+ }
358
+ return true;
359
+ }
598
360
  var strValue = String(value);
599
-
600
361
  // 如果以 = 开头,去掉 = 后校验
601
362
  var expr = strValue.startsWith('=') ? strValue.slice(1) : strValue;
602
363
  var parsedExpr = replaceLabelsWithValues(expr, flatOptions);
603
-
604
364
  // 空表达式不校验
605
365
  if (!parsedExpr.trim()) return true;
606
-
607
366
  // 1. 语法校验
608
367
  if (!validateCalculationExpr(parsedExpr)) {
609
368
  return false;
610
369
  }
611
-
612
370
  // 2. 变量校验:所有变量必须在 options 中
613
371
  if (!validateVariables(parsedExpr, flatOptions)) {
614
372
  return false;
@@ -617,10 +375,15 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
617
375
  };
618
376
 
619
377
  // formula:校验公式,校验成功返回 currentValue
620
- FormulaInputEditor.formula = function (value, currentValue) {
378
+ FormulaInputEditor.formula = function (value, record, currentValue) {
621
379
  if (isNil(value)) {
622
380
  return null;
623
381
  }
382
+ if (choseEditor && choseEditor(record)) {
383
+ var _String2;
384
+ var formatValue = (_String2 = String(value)) === null || _String2 === void 0 ? void 0 : _String2.replace(/,/g, '');
385
+ return formulaString(formatValue, currentValue, precision, max, min, true);
386
+ }
624
387
  var strValue = String(value);
625
388
  var hasEqualSign = strValue.startsWith('=');
626
389
  var expr = hasEqualSign ? strValue.slice(1) : strValue;
@@ -645,8 +408,17 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
645
408
  };
646
409
 
647
410
  // parser:粘贴时处理,将 label 转换为 value
648
- FormulaInputEditor.parser = function (value) {
411
+ FormulaInputEditor.parser = function (value, record, currentValue) {
649
412
  if (isNil(value)) return null;
413
+ if (choseEditor && choseEditor(record)) {
414
+ var _String3;
415
+ var result = (_String3 = String(value)) === null || _String3 === void 0 ? void 0 : _String3.replace(/[,|%]/g, '');
416
+ result = formulaString(result, currentValue, precision);
417
+ if (isNil(result) || isNaN(result)) {
418
+ return null;
419
+ }
420
+ return result;
421
+ }
650
422
  var strValue = String(value);
651
423
  var hasEqualSign = strValue.startsWith('=');
652
424
  var expr = hasEqualSign ? strValue.slice(1) : strValue;
@@ -657,15 +429,24 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
657
429
  };
658
430
 
659
431
  // formatter:复制时触发,将 value 转换为 label
660
- FormulaInputEditor.formatter = function (value) {
661
- if (isNil(value)) return null;
662
- var strValue = String(value);
432
+ FormulaInputEditor.formatter = function (value, record) {
433
+ if (choseEditor && choseEditor(record)) {
434
+ var _String4;
435
+ if (isNil(value) || isNaN(value)) {
436
+ return null;
437
+ }
438
+ var result = parseFloat((_String4 = String(value)) === null || _String4 === void 0 ? void 0 : _String4.replace(/,/g, ''));
439
+ return result;
440
+ }
441
+ var replaceValue = replaceIndex ? get(record, [replaceIndex]) : value;
442
+ if (isNil(replaceValue)) return null;
443
+ var strValue = String(replaceValue);
663
444
  var hasEqualSign = strValue.startsWith('=');
664
445
  var expr = hasEqualSign ? strValue.slice(1) : strValue;
665
446
 
666
447
  // 将 value 替换为 label
667
448
  var displayExpr = replaceValuesWithLabels(expr, flatOptions);
668
- return hasEqualSign ? '=' + displayExpr : displayExpr;
449
+ return hasEqualSign ? displayExpr : '=' + displayExpr;
669
450
  };
670
451
  return FormulaInputEditor;
671
452
  };