@zhenliang/sheet 0.2.5-beta.1 → 0.2.5-beta.10
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.
- package/dist/core/editor/InputOptionsEditor/index.d.ts +2 -11
- package/dist/core/editor/InputOptionsEditor/index.js +293 -164
- package/dist/core/editor/InputOptionsEditor/index.less +2 -1
- package/dist/core/editor/InputOptionsEditor/utils.d.ts +17 -1
- package/dist/core/editor/InputOptionsEditor/utils.js +34 -6
- package/dist/core/editor/InputOptionsEditor/vaildFormula.js +14 -2
- package/dist/core/editor/numberEditor/index.d.ts +1 -0
- package/dist/core/editor/numberEditor/index.js +2 -2
- package/dist/core/sheet/Cell.js +1 -1
- package/dist/core/table/useRowSelection.d.ts +1 -1
- package/dist/example/basic.js +8 -0
- package/package.json +1 -1
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
import type { SheetType } from "../../../type";
|
|
2
2
|
import './index.less';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
value: string;
|
|
6
|
-
info?: string;
|
|
7
|
-
children?: OptionItem[];
|
|
8
|
-
}
|
|
9
|
-
export interface FormulaInputProps {
|
|
10
|
-
options: OptionItem[];
|
|
11
|
-
value?: string;
|
|
12
|
-
}
|
|
13
|
-
export declare const getFormulaInputEditor: (options: OptionItem[], replaceIndex?: string) => SheetType.CellEditor;
|
|
3
|
+
import { OptionItem, inputProps } from './utils';
|
|
4
|
+
export declare const getFormulaInputEditor: (options: OptionItem[], replaceIndex?: string, extraProps?: inputProps, getExtraProps?: ((props: SheetType.CellEditorProps) => inputProps) | undefined, choseEditor?: ((record: any) => boolean) | undefined) => SheetType.CellEditor;
|
|
14
5
|
export default getFormulaInputEditor;
|
|
@@ -11,34 +11,54 @@ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o =
|
|
|
11
11
|
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
12
|
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
13
|
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
14
|
-
|
|
15
|
-
import { head, isEmpty, isNil } from 'lodash';
|
|
16
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
14
|
+
function _objectDestructuringEmpty(obj) { if (obj == null) throw new TypeError("Cannot destructure " + obj); }
|
|
17
15
|
import { InfoCircleOutlined } from '@ant-design/icons';
|
|
18
|
-
import {
|
|
19
|
-
import
|
|
16
|
+
import { Dropdown, Input, Menu, Tooltip } from 'antd';
|
|
17
|
+
import { get, head, isEmpty, isNil } from 'lodash';
|
|
18
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
19
|
+
import { formulaString } from "../numberEditor";
|
|
20
20
|
import "./index.less";
|
|
21
|
+
import { flattenOptions, getCursorPositionInSpan, getSpanAtCursor, getStringDiff, moveCursorToSpan, replaceLabelsWithValues, replaceLongestDiff, replaceValuesWithLabels, tokenize, validateVariables } from "./utils";
|
|
22
|
+
import validateCalculationExpr from "./vaildFormula";
|
|
21
23
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
22
24
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
23
|
-
var OPERATORS = ['=', '+', '-', '*', '/'];
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
25
|
+
var OPERATORS = ['=', '+', '-', '*', '/', '('];
|
|
26
|
+
|
|
27
|
+
// // 创建 label span
|
|
28
|
+
// const createLabelSpan = (label: string): HTMLElement => {
|
|
29
|
+
// const span = document.createElement('span');
|
|
30
|
+
// span.className = 'formula-editor-token-label';
|
|
31
|
+
// span.textContent = label;
|
|
32
|
+
// return span;
|
|
33
|
+
// };
|
|
34
|
+
|
|
35
|
+
// // 创建 empty other span
|
|
36
|
+
// const createEmptyOtherSpan = (): HTMLElement => {
|
|
37
|
+
// const span = document.createElement('span');
|
|
38
|
+
// span.className = 'formula-editor-token-other';
|
|
39
|
+
// span.textContent = '';
|
|
40
|
+
// return span;
|
|
41
|
+
// };
|
|
42
|
+
|
|
43
|
+
export var getFormulaInputEditor = function getFormulaInputEditor(options, replaceIndex, extraProps, getExtraProps, choseEditor) {
|
|
44
|
+
var _ref = extraProps || {},
|
|
45
|
+
warnMethod = _ref.warnMethod,
|
|
46
|
+
rangeMethod = _ref.rangeMethod,
|
|
47
|
+
precision = _ref.precision,
|
|
48
|
+
max = _ref.max,
|
|
49
|
+
min = _ref.min;
|
|
36
50
|
var FormulaInputEditor = function FormulaInputEditor(props) {
|
|
51
|
+
var _get;
|
|
37
52
|
var originValue = props.value,
|
|
38
53
|
onChange = props.onChange,
|
|
39
54
|
isEditing = props.isEditing,
|
|
40
55
|
record = props.record;
|
|
41
|
-
|
|
56
|
+
// 兼容number
|
|
57
|
+
var inputNumberRef = useRef(null);
|
|
58
|
+
var _ref2 = getExtraProps ? getExtraProps(props) : extraProps !== null && extraProps !== void 0 ? extraProps : {},
|
|
59
|
+
inputArgs = Object.assign({}, (_objectDestructuringEmpty(_ref2), _ref2));
|
|
60
|
+
var replaceValue = replaceIndex ? (_get = get(record, [replaceIndex])) !== null && _get !== void 0 ? _get : '' : originValue;
|
|
61
|
+
var calcValue = replaceValue.startsWith('=') ? replaceValue : "=".concat(replaceValue);
|
|
42
62
|
var _useState = useState(calcValue),
|
|
43
63
|
_useState2 = _slicedToArray(_useState, 1),
|
|
44
64
|
inputValue = _useState2[0];
|
|
@@ -47,7 +67,7 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
|
|
|
47
67
|
offsetX = _useState4[0],
|
|
48
68
|
setOffsetX = _useState4[1];
|
|
49
69
|
// 为了不重新render,再写一个
|
|
50
|
-
var _useState5 = useState(
|
|
70
|
+
var _useState5 = useState(replaceValue),
|
|
51
71
|
_useState6 = _slicedToArray(_useState5, 2),
|
|
52
72
|
containerValue = _useState6[0],
|
|
53
73
|
setContainerValue = _useState6[1];
|
|
@@ -60,6 +80,7 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
|
|
|
60
80
|
_useState10 = _slicedToArray(_useState9, 2),
|
|
61
81
|
inputAfterDropDownShow = _useState10[0],
|
|
62
82
|
setInputAfterDropDownShow = _useState10[1];
|
|
83
|
+
var tempSpanRef = useRef(null);
|
|
63
84
|
var containerRef = useRef(null);
|
|
64
85
|
var inputOperatorPosition = useRef(0);
|
|
65
86
|
|
|
@@ -74,7 +95,7 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
|
|
|
74
95
|
}, [inputValue, flatOptions]);
|
|
75
96
|
// 根据搜索文本获取筛选后的层级选项(保持层级结构)
|
|
76
97
|
var filteredHierarchyOptions = useMemo(function () {
|
|
77
|
-
var searchText = inputAfterDropDownShow;
|
|
98
|
+
var searchText = inputAfterDropDownShow.trim();
|
|
78
99
|
// 如果搜索文本为空,显示所有选项(保持层级)
|
|
79
100
|
if (!searchText) {
|
|
80
101
|
return options;
|
|
@@ -109,25 +130,55 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
|
|
|
109
130
|
useEffect(function () {
|
|
110
131
|
if (!open) {
|
|
111
132
|
containerValueSnapShot.current = '';
|
|
133
|
+
tempSpanRef.current = null;
|
|
112
134
|
}
|
|
113
135
|
setInputAfterDropDownShow('');
|
|
114
136
|
}, [open]);
|
|
137
|
+
var closeDorpDown = useCallback(function () {
|
|
138
|
+
setInputAfterDropDownShow('');
|
|
139
|
+
tempSpanRef.current = null;
|
|
140
|
+
// 点击div内直接关闭
|
|
141
|
+
setOpen(false);
|
|
142
|
+
}, []);
|
|
115
143
|
|
|
116
|
-
//
|
|
144
|
+
// 处理选项点击
|
|
117
145
|
var handleOptionClick = useCallback(function (opt) {
|
|
118
146
|
var container = containerRef.current;
|
|
119
147
|
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
148
|
var selection = window.getSelection();
|
|
130
149
|
if (!selection || selection.rangeCount === 0) return;
|
|
150
|
+
|
|
151
|
+
// 如果有 tempSpanRef,用新逻辑:直接替换该 span 的内容
|
|
152
|
+
if (tempSpanRef.current) {
|
|
153
|
+
tempSpanRef.current.textContent = opt.label;
|
|
154
|
+
var replacedSpan = tempSpanRef.current;
|
|
155
|
+
tempSpanRef.current = null;
|
|
156
|
+
|
|
157
|
+
// 光标移到替换后的 span 后面
|
|
158
|
+
var _allSpans = Array.from(container.querySelectorAll('span'));
|
|
159
|
+
var replacedIndex = _allSpans.indexOf(replacedSpan);
|
|
160
|
+
var _targetSpan = _allSpans[replacedIndex + 1];
|
|
161
|
+
if (!_targetSpan || _targetSpan.classList.contains('formula-editor-token-label')) {
|
|
162
|
+
_targetSpan = document.createElement('span');
|
|
163
|
+
_targetSpan.className = 'formula-editor-token-other';
|
|
164
|
+
_targetSpan.textContent = '';
|
|
165
|
+
replacedSpan.after(_targetSpan);
|
|
166
|
+
}
|
|
167
|
+
moveCursorToSpan(_targetSpan, true, selection);
|
|
168
|
+
// 更新 containerValue
|
|
169
|
+
var newValue = container.textContent || '';
|
|
170
|
+
var valueExpr = replaceLabelsWithValues(newValue, flatOptions);
|
|
171
|
+
setContainerValue(valueExpr);
|
|
172
|
+
onChange(valueExpr);
|
|
173
|
+
setOpen(false);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
// 原逻辑:删除 inputAfterDropDownShow,插入新 label
|
|
177
|
+
var newValueUser = replaceLongestDiff(containerValueSnapShot.current, opt.label, inputOperatorPosition.current);
|
|
178
|
+
var expr = newValueUser;
|
|
179
|
+
var valueExprUser = replaceLabelsWithValues(expr, flatOptions);
|
|
180
|
+
setContainerValue(valueExprUser);
|
|
181
|
+
onChange(valueExprUser);
|
|
131
182
|
var range = selection.getRangeAt(0);
|
|
132
183
|
var startContainer = range.startContainer;
|
|
133
184
|
var currentSpan = startContainer.nodeType === Node.TEXT_NODE ? startContainer.parentElement : startContainer;
|
|
@@ -180,19 +231,17 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
|
|
|
180
231
|
targetSpan.textContent = '';
|
|
181
232
|
labelSpan.after(targetSpan);
|
|
182
233
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
var newRange = document.createRange();
|
|
186
|
-
newRange.selectNodeContents(targetSpan);
|
|
187
|
-
newRange.collapse(true);
|
|
188
|
-
selection.removeAllRanges();
|
|
189
|
-
selection.addRange(newRange);
|
|
234
|
+
moveCursorToSpan(targetSpan, true, selection);
|
|
235
|
+
setOpen(false);
|
|
190
236
|
}, [inputAfterDropDownShow]);
|
|
191
237
|
|
|
192
238
|
// 处理输入变化
|
|
193
239
|
var handleInput = useCallback(function () {
|
|
194
240
|
var container = containerRef.current;
|
|
195
241
|
if (!container) return;
|
|
242
|
+
if (tempSpanRef.current) {
|
|
243
|
+
closeDorpDown();
|
|
244
|
+
}
|
|
196
245
|
var newValue = container.textContent || '';
|
|
197
246
|
var processedValue = newValue;
|
|
198
247
|
var expr = processedValue;
|
|
@@ -216,7 +265,7 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
|
|
|
216
265
|
if (open) {
|
|
217
266
|
var _getStringDiff2 = getStringDiff(containerValueSnapShot.current, newValue),
|
|
218
267
|
addedOnSnapShot = _getStringDiff2.added;
|
|
219
|
-
isBeginWithNumber = /^\d$/.test(head(addedOnSnapShot));
|
|
268
|
+
isBeginWithNumber = /^\d$/.test(head(addedOnSnapShot.join('').trim()));
|
|
220
269
|
inputStringAfterDropDownShow = addedOnSnapShot.join('');
|
|
221
270
|
}
|
|
222
271
|
if (pressAOperator) {
|
|
@@ -253,12 +302,8 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
|
|
|
253
302
|
(_containerRef$current2 = containerRef.current) === null || _containerRef$current2 === void 0 || _containerRef$current2.focus();
|
|
254
303
|
}
|
|
255
304
|
}, [isEditing]);
|
|
256
|
-
var closeDorpDown = useCallback(function () {
|
|
257
|
-
// 点击div内直接关闭
|
|
258
|
-
setOpen(false);
|
|
259
|
-
}, []);
|
|
260
305
|
|
|
261
|
-
// 鼠标释放时,如果光标在 label span
|
|
306
|
+
// 鼠标释放时,如果光标在 label span 内,打开下拉框并记录 tempSpan
|
|
262
307
|
var handleMouseUp = useCallback(function () {
|
|
263
308
|
var div = containerRef.current;
|
|
264
309
|
if (!div) return;
|
|
@@ -271,8 +316,20 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
|
|
|
271
316
|
if (!currentSpan || currentSpan === div) return;
|
|
272
317
|
var isLabelSpan = currentSpan.classList.contains('formula-editor-token-label');
|
|
273
318
|
|
|
274
|
-
// 如果在 label span
|
|
319
|
+
// 如果在 label span 内,打开下拉框并记录 tempSpan
|
|
275
320
|
if (isLabelSpan) {
|
|
321
|
+
// 更新 offsetX 位置
|
|
322
|
+
var containerRect = div.getBoundingClientRect();
|
|
323
|
+
var cursorRect = range.getBoundingClientRect();
|
|
324
|
+
var cursorDistance = cursorRect ? cursorRect.left - containerRect.left : 0;
|
|
325
|
+
setOffsetX(cursorDistance < 150 ? 0 : cursorDistance - 8);
|
|
326
|
+
|
|
327
|
+
// 记录当前 label span 作为 tempSpan
|
|
328
|
+
tempSpanRef.current = currentSpan;
|
|
329
|
+
|
|
330
|
+
// 打开下拉框
|
|
331
|
+
setOpen(true);
|
|
332
|
+
// 移动到下一个 span 的开头
|
|
276
333
|
var allSpans = Array.from(div.querySelectorAll('span'));
|
|
277
334
|
var currentIndex = allSpans.indexOf(currentSpan);
|
|
278
335
|
if (currentIndex < allSpans.length - 1) {
|
|
@@ -284,10 +341,10 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
|
|
|
284
341
|
selection.addRange(newRange);
|
|
285
342
|
}
|
|
286
343
|
}
|
|
287
|
-
}, [closeDorpDown]);
|
|
344
|
+
}, [closeDorpDown, setOffsetX, setOpen]);
|
|
288
345
|
var handleKeyDown = useCallback(function (e) {
|
|
289
346
|
var _currentSpan$textCont, _currentSpan$textCont2;
|
|
290
|
-
if (e.key === 'ArrowUp' || e.key ===
|
|
347
|
+
if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
|
|
291
348
|
e.preventDefault();
|
|
292
349
|
e.stopPropagation();
|
|
293
350
|
return;
|
|
@@ -307,13 +364,13 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
|
|
|
307
364
|
|
|
308
365
|
// 方向键:跳过 label span
|
|
309
366
|
if (e.key === 'ArrowRight' || e.key === 'ArrowLeft') {
|
|
310
|
-
closeDorpDown();
|
|
311
367
|
var position = getCursorPositionInSpan(currentSpan);
|
|
312
368
|
var isAtEnd = startOffset >= textLen;
|
|
313
369
|
var isAtStart = startOffset === 0;
|
|
314
370
|
var isAlmostEnd = startOffset >= textLen - 1;
|
|
315
371
|
var isAlmostStart = position === 1;
|
|
316
372
|
if (e.key === 'ArrowRight' && isAtEnd) {
|
|
373
|
+
closeDorpDown();
|
|
317
374
|
// 向右 + 在末尾 -> 跳到下一个 span 的开头(跳过 label span)
|
|
318
375
|
var targetIndex = currentIndex + 1;
|
|
319
376
|
while (targetIndex < allSpans.length && allSpans[targetIndex].classList.contains('formula-editor-token-label')) {
|
|
@@ -322,48 +379,35 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
|
|
|
322
379
|
if (targetIndex < allSpans.length && targetIndex !== currentIndex + 1) {
|
|
323
380
|
e.preventDefault();
|
|
324
381
|
var targetSpan = allSpans[targetIndex];
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
382
|
+
moveCursorToSpan(targetSpan, true, selection);
|
|
383
|
+
}
|
|
384
|
+
} else if (e.key === 'ArrowRight' && isAlmostEnd) {
|
|
385
|
+
closeDorpDown();
|
|
386
|
+
var _targetIndex = currentIndex + 1;
|
|
387
|
+
if (_targetIndex < allSpans.length && !allSpans[_targetIndex].classList.contains('formula-editor-token-label')) {
|
|
388
|
+
e.preventDefault();
|
|
389
|
+
var _targetSpan2 = allSpans[_targetIndex];
|
|
390
|
+
moveCursorToSpan(_targetSpan2, true, selection);
|
|
330
391
|
}
|
|
331
392
|
} else if (e.key === 'ArrowLeft' && isAtStart) {
|
|
393
|
+
closeDorpDown();
|
|
332
394
|
// 向左 + 在开头 -> 跳到上一个 span 的末尾(跳过 label span)
|
|
333
|
-
var
|
|
334
|
-
while (
|
|
335
|
-
|
|
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);
|
|
395
|
+
var _targetIndex2 = currentIndex - 1;
|
|
396
|
+
while (_targetIndex2 >= 0 && allSpans[_targetIndex2].classList.contains('formula-editor-token-label')) {
|
|
397
|
+
_targetIndex2--;
|
|
345
398
|
}
|
|
346
|
-
|
|
347
|
-
var _targetIndex2 = currentIndex + 1;
|
|
348
|
-
if (_targetIndex2 < allSpans.length && !allSpans[_targetIndex2].classList.contains('formula-editor-token-label')) {
|
|
399
|
+
if (_targetIndex2 >= 0 && _targetIndex2 !== currentIndex - 1) {
|
|
349
400
|
e.preventDefault();
|
|
350
|
-
var
|
|
351
|
-
|
|
352
|
-
_newRange2.selectNodeContents(_targetSpan2);
|
|
353
|
-
_newRange2.collapse(true);
|
|
354
|
-
selection.removeAllRanges();
|
|
355
|
-
selection.addRange(_newRange2);
|
|
401
|
+
var _targetSpan3 = allSpans[_targetIndex2];
|
|
402
|
+
moveCursorToSpan(_targetSpan3, false, selection);
|
|
356
403
|
}
|
|
357
404
|
} else if (e.key === 'ArrowLeft' && isAlmostStart) {
|
|
405
|
+
closeDorpDown();
|
|
358
406
|
var _targetIndex3 = currentIndex - 1;
|
|
359
407
|
if (_targetIndex3 >= 0 && !allSpans[_targetIndex3].classList.contains('formula-editor-token-label')) {
|
|
360
408
|
e.preventDefault();
|
|
361
|
-
var
|
|
362
|
-
|
|
363
|
-
_newRange3.selectNodeContents(_targetSpan3);
|
|
364
|
-
_newRange3.collapse(false);
|
|
365
|
-
selection.removeAllRanges();
|
|
366
|
-
selection.addRange(_newRange3);
|
|
409
|
+
var _targetSpan4 = allSpans[_targetIndex3];
|
|
410
|
+
moveCursorToSpan(_targetSpan4, false, selection);
|
|
367
411
|
}
|
|
368
412
|
}
|
|
369
413
|
return;
|
|
@@ -371,6 +415,19 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
|
|
|
371
415
|
|
|
372
416
|
// 删除键逻辑
|
|
373
417
|
if (e.key !== 'Delete' && e.key !== 'Backspace') return;
|
|
418
|
+
if (e.key === 'Backspace' || e.key === 'Delete') {
|
|
419
|
+
if (tempSpanRef.current) {
|
|
420
|
+
closeDorpDown();
|
|
421
|
+
}
|
|
422
|
+
// 检查删除后是否只剩一个空的 span
|
|
423
|
+
var allSpansNow = Array.from(div.querySelectorAll('span'));
|
|
424
|
+
var isOnlyOneEmptySpan = allSpansNow.length === 1 && allSpansNow[0].textContent === '';
|
|
425
|
+
if (isOnlyOneEmptySpan) {
|
|
426
|
+
e.preventDefault();
|
|
427
|
+
e.stopPropagation();
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
374
431
|
|
|
375
432
|
// 不在 label span 内,在 span 开头且前一个是 label 时,删除整个 label span
|
|
376
433
|
if (startOffset === 0 && e.key === 'Backspace' && currentIndex > 0) {
|
|
@@ -379,31 +436,31 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
|
|
|
379
436
|
e.preventDefault();
|
|
380
437
|
e.stopPropagation();
|
|
381
438
|
prevSpan.remove();
|
|
382
|
-
var
|
|
439
|
+
var newRange = document.createRange();
|
|
383
440
|
|
|
384
441
|
// 如果当前 span 有内容,光标放在开头;否则找最近的有内容的 span
|
|
385
442
|
if (currentSpan.textContent !== '') {
|
|
386
|
-
|
|
387
|
-
|
|
443
|
+
newRange.selectNodeContents(currentSpan);
|
|
444
|
+
newRange.collapse(true);
|
|
388
445
|
} else {
|
|
389
446
|
// 找前一个最近的有内容的 span
|
|
390
|
-
var
|
|
447
|
+
var _targetSpan5;
|
|
391
448
|
for (var i = currentIndex - 2; i >= 0; i--) {
|
|
392
449
|
if (allSpans[i].textContent !== '') {
|
|
393
|
-
|
|
450
|
+
_targetSpan5 = allSpans[i];
|
|
394
451
|
break;
|
|
395
452
|
}
|
|
396
453
|
}
|
|
397
|
-
if (
|
|
398
|
-
|
|
399
|
-
|
|
454
|
+
if (_targetSpan5) {
|
|
455
|
+
newRange.selectNodeContents(_targetSpan5);
|
|
456
|
+
newRange.collapse(false);
|
|
400
457
|
} else {
|
|
401
|
-
|
|
402
|
-
|
|
458
|
+
newRange.selectNodeContents(div);
|
|
459
|
+
newRange.collapse(true);
|
|
403
460
|
}
|
|
404
461
|
}
|
|
405
462
|
selection.removeAllRanges();
|
|
406
|
-
selection.addRange(
|
|
463
|
+
selection.addRange(newRange);
|
|
407
464
|
return;
|
|
408
465
|
}
|
|
409
466
|
}
|
|
@@ -419,11 +476,11 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
|
|
|
419
476
|
if (prevText.length > 0) {
|
|
420
477
|
_prevSpan.textContent = prevText.slice(0, -1);
|
|
421
478
|
}
|
|
422
|
-
var
|
|
423
|
-
|
|
424
|
-
|
|
479
|
+
var _newRange = document.createRange();
|
|
480
|
+
_newRange.selectNodeContents(_prevSpan);
|
|
481
|
+
_newRange.collapse(false);
|
|
425
482
|
selection.removeAllRanges();
|
|
426
|
-
selection.addRange(
|
|
483
|
+
selection.addRange(_newRange);
|
|
427
484
|
}
|
|
428
485
|
}
|
|
429
486
|
|
|
@@ -438,76 +495,104 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
|
|
|
438
495
|
// 如果光标在 span 开头 + Delete 键,currentIndex 指向的是被删 span 的后一个,所以要 -1
|
|
439
496
|
var searchIndex = startOffset === 0 ? currentIndex - 1 : currentIndex;
|
|
440
497
|
// 从 searchIndex 位置往前找
|
|
441
|
-
var
|
|
498
|
+
var _targetSpan6;
|
|
442
499
|
for (var _i = searchIndex; _i >= 0; _i--) {
|
|
443
500
|
var span = allSpansNow[_i];
|
|
444
501
|
if (span.textContent !== '') {
|
|
445
|
-
|
|
502
|
+
_targetSpan6 = span;
|
|
446
503
|
break;
|
|
447
504
|
}
|
|
448
505
|
}
|
|
449
506
|
// 如果找到的有内容 span 是 label,则把光标放在 label span 的后一个 span 的开头
|
|
450
|
-
if (
|
|
451
|
-
var labelIndex = allSpansNow.indexOf(
|
|
507
|
+
if (_targetSpan6 && _targetSpan6.classList.contains('formula-editor-token-label')) {
|
|
508
|
+
var labelIndex = allSpansNow.indexOf(_targetSpan6);
|
|
452
509
|
if (labelIndex < allSpansNow.length - 1) {
|
|
453
510
|
var nextSpan = allSpansNow[labelIndex + 1];
|
|
454
|
-
var
|
|
455
|
-
|
|
456
|
-
|
|
511
|
+
var _newRange2 = document.createRange();
|
|
512
|
+
_newRange2.selectNodeContents(nextSpan);
|
|
513
|
+
_newRange2.collapse(true);
|
|
457
514
|
selection.removeAllRanges();
|
|
458
|
-
selection.addRange(
|
|
515
|
+
selection.addRange(_newRange2);
|
|
459
516
|
return;
|
|
460
517
|
}
|
|
461
518
|
}
|
|
462
519
|
|
|
463
520
|
// 否则把光标放在找到的 span 的末尾
|
|
464
|
-
if (
|
|
465
|
-
var
|
|
466
|
-
|
|
467
|
-
|
|
521
|
+
if (_targetSpan6) {
|
|
522
|
+
var _newRange3 = document.createRange();
|
|
523
|
+
_newRange3.selectNodeContents(_targetSpan6);
|
|
524
|
+
_newRange3.collapse(false);
|
|
468
525
|
selection.removeAllRanges();
|
|
469
|
-
selection.addRange(
|
|
526
|
+
selection.addRange(_newRange3);
|
|
470
527
|
return;
|
|
471
528
|
}
|
|
472
529
|
}
|
|
473
530
|
if (!currentSpanNow || currentSpanNow === div) return;
|
|
474
531
|
if (currentSpanNow.textContent === '') {
|
|
475
532
|
var currentIndexNow = allSpansNow.indexOf(currentSpanNow);
|
|
476
|
-
var
|
|
533
|
+
var _newRange4 = document.createRange();
|
|
477
534
|
if (currentIndexNow > 0) {
|
|
478
535
|
// 移到前一个 span 的末尾,但如果前一个 span 是 label,则移到后一个 span 的开头
|
|
479
|
-
var
|
|
480
|
-
if (
|
|
536
|
+
var _targetSpan7 = allSpansNow[currentIndexNow - 1];
|
|
537
|
+
if (_targetSpan7.classList.contains('formula-editor-token-label')) {
|
|
481
538
|
// 移到 label span 的后一个 span 的开头
|
|
482
539
|
if (currentIndexNow < allSpansNow.length - 1) {
|
|
483
540
|
var _nextSpan = allSpansNow[currentIndexNow + 1];
|
|
484
|
-
|
|
485
|
-
|
|
541
|
+
_newRange4.selectNodeContents(_nextSpan);
|
|
542
|
+
_newRange4.collapse(true);
|
|
486
543
|
} else {
|
|
487
|
-
|
|
488
|
-
|
|
544
|
+
_newRange4.selectNodeContents(div);
|
|
545
|
+
_newRange4.collapse(false);
|
|
489
546
|
}
|
|
490
547
|
} else {
|
|
491
|
-
|
|
492
|
-
|
|
548
|
+
_newRange4.selectNodeContents(_targetSpan7);
|
|
549
|
+
_newRange4.collapse(false);
|
|
493
550
|
}
|
|
494
551
|
currentSpanNow.remove();
|
|
495
552
|
} else if (allSpansNow.length > 1) {
|
|
496
553
|
// 第一个 span 为空,移到下一个 span 的开头
|
|
497
554
|
var _nextSpan2 = allSpansNow[currentIndexNow + 1];
|
|
498
|
-
|
|
499
|
-
|
|
555
|
+
_newRange4.selectNodeContents(_nextSpan2);
|
|
556
|
+
_newRange4.collapse(true);
|
|
500
557
|
currentSpanNow.remove();
|
|
501
558
|
} else {
|
|
502
559
|
// 只有一个空 span,保持空
|
|
503
|
-
|
|
504
|
-
|
|
560
|
+
_newRange4.selectNodeContents(div);
|
|
561
|
+
_newRange4.collapse(true);
|
|
505
562
|
}
|
|
506
563
|
selection.removeAllRanges();
|
|
507
|
-
selection.addRange(
|
|
564
|
+
selection.addRange(_newRange4);
|
|
508
565
|
}
|
|
509
566
|
}, 0);
|
|
510
567
|
}, []);
|
|
568
|
+
|
|
569
|
+
// 递归渲染多级菜单
|
|
570
|
+
var renderMenuItems = function renderMenuItems(items) {
|
|
571
|
+
return items.map(function (opt) {
|
|
572
|
+
if (opt.children && opt.children.length > 0) {
|
|
573
|
+
return /*#__PURE__*/_jsx(Menu.SubMenu, {
|
|
574
|
+
title: opt.label,
|
|
575
|
+
className: "formula-editor-dropdown-submenu",
|
|
576
|
+
children: renderMenuItems(opt.children)
|
|
577
|
+
}, opt.value);
|
|
578
|
+
}
|
|
579
|
+
return /*#__PURE__*/_jsxs(Menu.Item, {
|
|
580
|
+
className: "formula-editor-dropdown-item",
|
|
581
|
+
onClick: function onClick() {
|
|
582
|
+
return handleOptionClick(opt);
|
|
583
|
+
},
|
|
584
|
+
children: [opt.label, opt.info ? /*#__PURE__*/_jsx(Tooltip, {
|
|
585
|
+
title: opt.info,
|
|
586
|
+
children: /*#__PURE__*/_jsx(InfoCircleOutlined, {
|
|
587
|
+
style: {
|
|
588
|
+
color: '#FF9900',
|
|
589
|
+
marginLeft: 4
|
|
590
|
+
}
|
|
591
|
+
})
|
|
592
|
+
}) : null]
|
|
593
|
+
}, opt.value);
|
|
594
|
+
});
|
|
595
|
+
};
|
|
511
596
|
var dropdownContent = /*#__PURE__*/_jsx(Menu, {
|
|
512
597
|
className: "formula-editor-dropdown",
|
|
513
598
|
style: {
|
|
@@ -523,36 +608,39 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
|
|
|
523
608
|
className: "formula-editor-dropdown-no-data",
|
|
524
609
|
children: "\u6682\u65E0\u6570\u636E"
|
|
525
610
|
})
|
|
526
|
-
}, "no-data") : filteredHierarchyOptions
|
|
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
|
-
})
|
|
611
|
+
}, "no-data") : renderMenuItems(filteredHierarchyOptions)
|
|
555
612
|
});
|
|
613
|
+
var handleChange = useCallback(function (value) {
|
|
614
|
+
onChange(!isNil(value) ? value : null);
|
|
615
|
+
}, [onChange]);
|
|
616
|
+
useEffect(function () {
|
|
617
|
+
if (isEditing) {
|
|
618
|
+
var _inputNumberRef$curre;
|
|
619
|
+
inputNumberRef === null || inputNumberRef === void 0 || (_inputNumberRef$curre = inputNumberRef.current) === null || _inputNumberRef$curre === void 0 || _inputNumberRef$curre.focus();
|
|
620
|
+
}
|
|
621
|
+
}, [isEditing]);
|
|
622
|
+
var reFocus = useCallback(function () {
|
|
623
|
+
if (isEditing) {
|
|
624
|
+
var _inputNumberRef$curre2;
|
|
625
|
+
inputNumberRef === null || inputNumberRef === void 0 || (_inputNumberRef$curre2 = inputNumberRef.current) === null || _inputNumberRef$curre2 === void 0 || _inputNumberRef$curre2.focus();
|
|
626
|
+
}
|
|
627
|
+
}, [isEditing]);
|
|
628
|
+
if (choseEditor && choseEditor(record)) {
|
|
629
|
+
var _ref3;
|
|
630
|
+
return /*#__PURE__*/_jsx(Input, _objectSpread(_objectSpread({
|
|
631
|
+
ref: inputNumberRef,
|
|
632
|
+
onBlur: reFocus
|
|
633
|
+
}, inputArgs), {}, {
|
|
634
|
+
className: "number-editor",
|
|
635
|
+
onMouseDown: function onMouseDown(e) {
|
|
636
|
+
return e.stopPropagation();
|
|
637
|
+
},
|
|
638
|
+
value: (_ref3 = originValue) !== null && _ref3 !== void 0 ? _ref3 : '',
|
|
639
|
+
onChange: function onChange(e) {
|
|
640
|
+
handleChange(e.target.value);
|
|
641
|
+
}
|
|
642
|
+
}));
|
|
643
|
+
}
|
|
556
644
|
return /*#__PURE__*/_jsx(Dropdown, {
|
|
557
645
|
overlayClassName: "dropDownOffset",
|
|
558
646
|
overlay: dropdownContent,
|
|
@@ -571,13 +659,13 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
|
|
|
571
659
|
spellCheck: false,
|
|
572
660
|
children: isEmpty(tokens) ? /*#__PURE__*/_jsx("span", {
|
|
573
661
|
style: {
|
|
574
|
-
minWidth:
|
|
662
|
+
minWidth: 1,
|
|
575
663
|
height: 40
|
|
576
664
|
}
|
|
577
665
|
}) : tokens.map(function (token, index) {
|
|
578
666
|
return token.type === 'end' ? /*#__PURE__*/_jsx("span", {
|
|
579
667
|
style: {
|
|
580
|
-
minWidth:
|
|
668
|
+
minWidth: 1,
|
|
581
669
|
height: 40
|
|
582
670
|
}
|
|
583
671
|
}, index) : /*#__PURE__*/_jsx("span", {
|
|
@@ -593,22 +681,40 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
|
|
|
593
681
|
var flatOptions = flattenOptions(options);
|
|
594
682
|
|
|
595
683
|
// checker:使用 validateCalculationExpr 校验语法 + 校验变量是否都在 options 中
|
|
596
|
-
FormulaInputEditor.checker = function (value) {
|
|
684
|
+
FormulaInputEditor.checker = function (value, record, currentValue) {
|
|
597
685
|
if (isNil(value)) return true;
|
|
686
|
+
if (choseEditor && choseEditor(record)) {
|
|
687
|
+
var _String;
|
|
688
|
+
var result = (_String = String(value)) === null || _String === void 0 ? void 0 : _String.replace(/,/g, '');
|
|
689
|
+
result = formulaString(result, currentValue, precision);
|
|
690
|
+
// parse number with thousands separator
|
|
691
|
+
var range = rangeMethod === null || rangeMethod === void 0 ? void 0 : rangeMethod(record);
|
|
692
|
+
if (!isNil(range === null || range === void 0 ? void 0 : range.max) && !isNil(range === null || range === void 0 ? void 0 : range.min)) {
|
|
693
|
+
var _ref4 = range || {},
|
|
694
|
+
_ref4$max = _ref4.max,
|
|
695
|
+
_max = _ref4$max === void 0 ? 0 : _ref4$max,
|
|
696
|
+
_ref4$min = _ref4.min,
|
|
697
|
+
_min = _ref4$min === void 0 ? 0 : _ref4$min;
|
|
698
|
+
if (result < _min || result > _max) {
|
|
699
|
+
warnMethod === null || warnMethod === void 0 || warnMethod(record);
|
|
700
|
+
return false;
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
if (isNaN(result)) {
|
|
704
|
+
return false;
|
|
705
|
+
}
|
|
706
|
+
return true;
|
|
707
|
+
}
|
|
598
708
|
var strValue = String(value);
|
|
599
|
-
|
|
600
709
|
// 如果以 = 开头,去掉 = 后校验
|
|
601
710
|
var expr = strValue.startsWith('=') ? strValue.slice(1) : strValue;
|
|
602
711
|
var parsedExpr = replaceLabelsWithValues(expr, flatOptions);
|
|
603
|
-
|
|
604
712
|
// 空表达式不校验
|
|
605
713
|
if (!parsedExpr.trim()) return true;
|
|
606
|
-
|
|
607
714
|
// 1. 语法校验
|
|
608
715
|
if (!validateCalculationExpr(parsedExpr)) {
|
|
609
716
|
return false;
|
|
610
717
|
}
|
|
611
|
-
|
|
612
718
|
// 2. 变量校验:所有变量必须在 options 中
|
|
613
719
|
if (!validateVariables(parsedExpr, flatOptions)) {
|
|
614
720
|
return false;
|
|
@@ -617,10 +723,15 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
|
|
|
617
723
|
};
|
|
618
724
|
|
|
619
725
|
// formula:校验公式,校验成功返回 currentValue
|
|
620
|
-
FormulaInputEditor.formula = function (value, currentValue) {
|
|
726
|
+
FormulaInputEditor.formula = function (value, record, currentValue) {
|
|
621
727
|
if (isNil(value)) {
|
|
622
728
|
return null;
|
|
623
729
|
}
|
|
730
|
+
if (choseEditor && choseEditor(record)) {
|
|
731
|
+
var _String2;
|
|
732
|
+
var formatValue = (_String2 = String(value)) === null || _String2 === void 0 ? void 0 : _String2.replace(/,/g, '');
|
|
733
|
+
return formulaString(formatValue, currentValue, precision, max, min, true);
|
|
734
|
+
}
|
|
624
735
|
var strValue = String(value);
|
|
625
736
|
var hasEqualSign = strValue.startsWith('=');
|
|
626
737
|
var expr = hasEqualSign ? strValue.slice(1) : strValue;
|
|
@@ -645,8 +756,17 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
|
|
|
645
756
|
};
|
|
646
757
|
|
|
647
758
|
// parser:粘贴时处理,将 label 转换为 value
|
|
648
|
-
FormulaInputEditor.parser = function (value) {
|
|
759
|
+
FormulaInputEditor.parser = function (value, record, currentValue) {
|
|
649
760
|
if (isNil(value)) return null;
|
|
761
|
+
if (choseEditor && choseEditor(record)) {
|
|
762
|
+
var _String3;
|
|
763
|
+
var result = (_String3 = String(value)) === null || _String3 === void 0 ? void 0 : _String3.replace(/[,|%]/g, '');
|
|
764
|
+
result = formulaString(result, currentValue, precision);
|
|
765
|
+
if (isNil(result) || isNaN(result)) {
|
|
766
|
+
return null;
|
|
767
|
+
}
|
|
768
|
+
return result;
|
|
769
|
+
}
|
|
650
770
|
var strValue = String(value);
|
|
651
771
|
var hasEqualSign = strValue.startsWith('=');
|
|
652
772
|
var expr = hasEqualSign ? strValue.slice(1) : strValue;
|
|
@@ -657,15 +777,24 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
|
|
|
657
777
|
};
|
|
658
778
|
|
|
659
779
|
// formatter:复制时触发,将 value 转换为 label
|
|
660
|
-
FormulaInputEditor.formatter = function (value) {
|
|
661
|
-
if (
|
|
662
|
-
|
|
780
|
+
FormulaInputEditor.formatter = function (value, record) {
|
|
781
|
+
if (choseEditor && choseEditor(record)) {
|
|
782
|
+
var _String4;
|
|
783
|
+
if (isNil(value) || isNaN(value)) {
|
|
784
|
+
return null;
|
|
785
|
+
}
|
|
786
|
+
var result = parseFloat((_String4 = String(value)) === null || _String4 === void 0 ? void 0 : _String4.replace(/,/g, ''));
|
|
787
|
+
return result;
|
|
788
|
+
}
|
|
789
|
+
var replaceValue = replaceIndex ? get(record, [replaceIndex]) : value;
|
|
790
|
+
if (isNil(replaceValue)) return null;
|
|
791
|
+
var strValue = String(replaceValue);
|
|
663
792
|
var hasEqualSign = strValue.startsWith('=');
|
|
664
793
|
var expr = hasEqualSign ? strValue.slice(1) : strValue;
|
|
665
794
|
|
|
666
795
|
// 将 value 替换为 label
|
|
667
796
|
var displayExpr = replaceValuesWithLabels(expr, flatOptions);
|
|
668
|
-
return hasEqualSign ? '=' + displayExpr
|
|
797
|
+
return hasEqualSign ? displayExpr : '=' + displayExpr;
|
|
669
798
|
};
|
|
670
799
|
return FormulaInputEditor;
|
|
671
800
|
};
|
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
white-space: nowrap;
|
|
5
5
|
overflow: hidden;
|
|
6
6
|
outline: none;
|
|
7
|
-
min-width:
|
|
7
|
+
min-width: 90%;
|
|
8
8
|
max-height: 100%;
|
|
9
9
|
box-shadow: inset 0 -100px 0 rgba(33, 133, 208, 15%);
|
|
10
10
|
position: absolute;
|
|
11
11
|
top: 0;
|
|
12
12
|
background: #fff;
|
|
13
|
+
padding-right: 8px;
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
.formula-editor-equal {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { InputNumberProps } from "antd";
|
|
1
2
|
export declare const OPERATORS: string[];
|
|
2
3
|
export declare const VARIABLE_REGEX: RegExp;
|
|
3
4
|
export declare const NUMBER_REGEX: RegExp;
|
|
@@ -40,7 +41,7 @@ export declare const validateVariables: (expr: string, flatOptions: {
|
|
|
40
41
|
value: string;
|
|
41
42
|
}[]) => boolean;
|
|
42
43
|
/**
|
|
43
|
-
*
|
|
44
|
+
* 扁平化选项列表(只获取叶子节点)
|
|
44
45
|
*/
|
|
45
46
|
export declare const flattenOptions: (options: {
|
|
46
47
|
label: string;
|
|
@@ -57,3 +58,18 @@ export declare const longestCommonSubsequence: (arr1: string, arr2: string) => s
|
|
|
57
58
|
export declare const getStringDiff: (str1: any, str2: any, mode?: string) => any;
|
|
58
59
|
export declare const replaceLongestDiff: (a: string, str: string, position: number) => string;
|
|
59
60
|
export declare const getCursorPositionInSpan: (span: any) => any;
|
|
61
|
+
export interface OptionItem {
|
|
62
|
+
label: string;
|
|
63
|
+
value: string;
|
|
64
|
+
info?: string;
|
|
65
|
+
children?: OptionItem[];
|
|
66
|
+
}
|
|
67
|
+
export type inputProps = Partial<Pick<InputNumberProps, 'max' | 'min' | 'addonBefore' | 'addonAfter' | 'precision'> & {
|
|
68
|
+
warnMethod?: (record: any) => void;
|
|
69
|
+
rangeMethod?: (record: any) => {
|
|
70
|
+
max?: number;
|
|
71
|
+
min?: number;
|
|
72
|
+
};
|
|
73
|
+
}>;
|
|
74
|
+
export declare const getSpanAtCursor: (startContainer: any) => HTMLElement | null;
|
|
75
|
+
export declare const moveCursorToSpan: (targetSpan: HTMLElement, atStart: boolean | undefined, selection: any) => void;
|
|
@@ -38,7 +38,7 @@ export var replaceValuesWithLabels = function replaceValuesWithLabels(expr, flat
|
|
|
38
38
|
} finally {
|
|
39
39
|
_iterator.f();
|
|
40
40
|
}
|
|
41
|
-
return result.
|
|
41
|
+
return result.trim();
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
/**
|
|
@@ -115,6 +115,9 @@ var splitSegmentByLabels = function splitSegmentByLabels(segment, sortedLabels)
|
|
|
115
115
|
* 有效 label 为 type 'label',其他为 'other'
|
|
116
116
|
*/
|
|
117
117
|
export var tokenize = function tokenize(text, flatOptions) {
|
|
118
|
+
if (!text) {
|
|
119
|
+
return [];
|
|
120
|
+
}
|
|
118
121
|
var tokens = [];
|
|
119
122
|
|
|
120
123
|
// 将 value 转换为 label
|
|
@@ -204,7 +207,7 @@ export var validateVariables = function validateVariables(expr, flatOptions) {
|
|
|
204
207
|
};
|
|
205
208
|
|
|
206
209
|
/**
|
|
207
|
-
*
|
|
210
|
+
* 扁平化选项列表(只获取叶子节点)
|
|
208
211
|
*/
|
|
209
212
|
export var flattenOptions = function flattenOptions(options) {
|
|
210
213
|
var result = [];
|
|
@@ -213,12 +216,15 @@ export var flattenOptions = function flattenOptions(options) {
|
|
|
213
216
|
try {
|
|
214
217
|
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
215
218
|
var opt = _step5.value;
|
|
216
|
-
result.push({
|
|
217
|
-
label: opt.label,
|
|
218
|
-
value: opt.value
|
|
219
|
-
});
|
|
220
219
|
if (opt.children && opt.children.length > 0) {
|
|
220
|
+
// 有 children,递归获取叶子节点,不添加当前节点
|
|
221
221
|
result.push.apply(result, _toConsumableArray(flattenOptions(opt.children)));
|
|
222
|
+
} else {
|
|
223
|
+
// 没有 children,是叶子节点,添加到结果
|
|
224
|
+
result.push({
|
|
225
|
+
label: opt.label,
|
|
226
|
+
value: opt.value
|
|
227
|
+
});
|
|
222
228
|
}
|
|
223
229
|
}
|
|
224
230
|
} catch (err) {
|
|
@@ -332,4 +338,26 @@ export var getCursorPositionInSpan = function getCursorPositionInSpan(span) {
|
|
|
332
338
|
preCaretRange.selectNodeContents(span);
|
|
333
339
|
preCaretRange.setEnd(range.startContainer, range.startOffset);
|
|
334
340
|
return preCaretRange.toString().length;
|
|
341
|
+
};
|
|
342
|
+
// 获取光标所在的 span
|
|
343
|
+
export var getSpanAtCursor = function getSpanAtCursor(startContainer) {
|
|
344
|
+
if (startContainer.nodeType === Node.TEXT_NODE) {
|
|
345
|
+
return startContainer.parentElement;
|
|
346
|
+
}
|
|
347
|
+
if (startContainer.nodeType === Node.ELEMENT_NODE) {
|
|
348
|
+
return startContainer;
|
|
349
|
+
}
|
|
350
|
+
return null;
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
// 将光标移到目标 span 的开头或末尾
|
|
354
|
+
export var moveCursorToSpan = function moveCursorToSpan(targetSpan) {
|
|
355
|
+
var atStart = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
|
356
|
+
var selection = arguments.length > 2 ? arguments[2] : undefined;
|
|
357
|
+
if (!selection) return;
|
|
358
|
+
var newRange = document.createRange();
|
|
359
|
+
newRange.selectNodeContents(targetSpan);
|
|
360
|
+
newRange.collapse(atStart);
|
|
361
|
+
selection.removeAllRanges();
|
|
362
|
+
selection.addRange(newRange);
|
|
335
363
|
};
|
|
@@ -257,14 +257,26 @@ var Parser = /*#__PURE__*/function () {
|
|
|
257
257
|
return true;
|
|
258
258
|
}
|
|
259
259
|
|
|
260
|
-
//
|
|
261
|
-
// factor: '(' expr ')' | NUMBER | PERCENT | REFVAR
|
|
260
|
+
// 解析基本表达式(括号、数字、百分比、变量、带符号的数字)
|
|
261
|
+
// factor: '(' expr ')' | NUMBER | PERCENT | REFVAR | ('+' | '-') factor
|
|
262
|
+
// 注意:一元正负号后不能紧跟另一个一元正负号
|
|
262
263
|
}, {
|
|
263
264
|
key: "parseFactor",
|
|
264
265
|
value: function parseFactor() {
|
|
265
266
|
var token = this.currentToken();
|
|
266
267
|
if (!token) return false;
|
|
267
268
|
|
|
269
|
+
// 处理一元正负号
|
|
270
|
+
if (token.type === 'ADD' || token.type === 'SUB') {
|
|
271
|
+
this.pos++;
|
|
272
|
+
var nextToken = this.currentToken();
|
|
273
|
+
// 一元正负号后不能是另一个一元正负号
|
|
274
|
+
if (nextToken && (nextToken.type === 'ADD' || nextToken.type === 'SUB')) {
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
return this.parseFactor();
|
|
278
|
+
}
|
|
279
|
+
|
|
268
280
|
// 处理括号表达式
|
|
269
281
|
if (token.type === 'LPAREN') {
|
|
270
282
|
this.pos++;
|
|
@@ -9,6 +9,7 @@ type inputProps = Partial<Pick<InputNumberProps, 'max' | 'min' | 'addonBefore' |
|
|
|
9
9
|
min?: number;
|
|
10
10
|
};
|
|
11
11
|
}>;
|
|
12
|
+
export declare const formulaString: (value: unknown, currentValue: unknown, precision?: number, max?: number, min?: number, isEdit?: boolean) => unknown;
|
|
12
13
|
export declare const NumberEditor: SheetType.CellEditor;
|
|
13
14
|
export declare const getNumberEditor: (extraProps?: inputProps, getExtraProps?: ((props: SheetType.CellEditorProps) => inputProps) | undefined) => SheetType.CellEditor;
|
|
14
15
|
export {};
|
|
@@ -13,7 +13,7 @@ import { evaluate } from 'mathjs';
|
|
|
13
13
|
import { useCallback, useEffect, useRef } from 'react';
|
|
14
14
|
import "./index.less";
|
|
15
15
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
16
|
-
var formulaString = function formulaString(value, currentValue, precision, max, min, isEdit) {
|
|
16
|
+
export var formulaString = function formulaString(value, currentValue, precision, max, min, isEdit) {
|
|
17
17
|
var curNumber = currentValue !== null && currentValue !== void 0 ? currentValue : 0;
|
|
18
18
|
var headStr = head(String(value).trim());
|
|
19
19
|
var formula = String(value).replace('=', '');
|
|
@@ -106,7 +106,7 @@ export var getNumberEditor = function getNumberEditor(extraProps, getExtraProps)
|
|
|
106
106
|
}
|
|
107
107
|
}));
|
|
108
108
|
};
|
|
109
|
-
NumberEditor.formula = function (value, currentValue) {
|
|
109
|
+
NumberEditor.formula = function (value, record, currentValue) {
|
|
110
110
|
var _String;
|
|
111
111
|
if (isNil(value)) {
|
|
112
112
|
return null;
|
package/dist/core/sheet/Cell.js
CHANGED
|
@@ -89,7 +89,7 @@ var Cell = function Cell(props) {
|
|
|
89
89
|
// 转化一下公式
|
|
90
90
|
if (cell !== null && cell !== void 0 && (_cell$dataEditor3 = cell.dataEditor) !== null && _cell$dataEditor3 !== void 0 && _cell$dataEditor3.formula) {
|
|
91
91
|
var _cell$dataEditor4;
|
|
92
|
-
newValue = cell === null || cell === void 0 || (_cell$dataEditor4 = cell.dataEditor) === null || _cell$dataEditor4 === void 0 ? void 0 : _cell$dataEditor4.formula(value, valueRef.current);
|
|
92
|
+
newValue = cell === null || cell === void 0 || (_cell$dataEditor4 = cell.dataEditor) === null || _cell$dataEditor4 === void 0 ? void 0 : _cell$dataEditor4.formula(value, cell.record, valueRef.current);
|
|
93
93
|
if (newValue === Infinity) {
|
|
94
94
|
antConfirm({
|
|
95
95
|
title: '公式有误',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SheetTableType } from "../..";
|
|
2
2
|
export declare const useRowSelection: (dataSource: Record<string, unknown>[], rowSelection?: SheetTableType.TableRowSelection, hasChildren?: boolean) => [boolean[], (value: boolean[]) => void];
|
|
3
|
-
export declare const formatSelectionData: (param: Pick<SheetTableType.TableProps, "columns" | "
|
|
3
|
+
export declare const formatSelectionData: (param: Pick<SheetTableType.TableProps, "columns" | "showRemark" | "rowSelection" | "dataSource" | "rowKey"> & {
|
|
4
4
|
checked: boolean[];
|
|
5
5
|
}) => any[][];
|
package/dist/example/basic.js
CHANGED
|
@@ -175,6 +175,14 @@ var data = [{
|
|
|
175
175
|
tags: ['cool', 'teacher'],
|
|
176
176
|
formula: '=(123 + 456) * price + 888',
|
|
177
177
|
amount: 100
|
|
178
|
+
}, {
|
|
179
|
+
key: '6',
|
|
180
|
+
name: 'Joe 23',
|
|
181
|
+
age: 41,
|
|
182
|
+
address: 'Sidney No. 1 Lake Park',
|
|
183
|
+
tags: ['cool', 'teacher'],
|
|
184
|
+
formula: '=(123 + -456) * price *-discount',
|
|
185
|
+
amount: 100
|
|
178
186
|
}];
|
|
179
187
|
var App = function App() {
|
|
180
188
|
var _useState = useState(data),
|