@zhenliang/sheet 0.2.5-beta.6 → 0.2.5-beta.8

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.
@@ -74,6 +74,7 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
74
74
  _useState10 = _slicedToArray(_useState9, 2),
75
75
  inputAfterDropDownShow = _useState10[0],
76
76
  setInputAfterDropDownShow = _useState10[1];
77
+ var tempSpanRef = useRef(null);
77
78
  var containerRef = useRef(null);
78
79
  var inputOperatorPosition = useRef(0);
79
80
 
@@ -123,23 +124,63 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
123
124
  useEffect(function () {
124
125
  if (!open) {
125
126
  containerValueSnapShot.current = '';
127
+ tempSpanRef.current = null;
126
128
  }
127
129
  setInputAfterDropDownShow('');
128
130
  }, [open]);
131
+ var closeDorpDown = useCallback(function () {
132
+ setInputAfterDropDownShow('');
133
+ tempSpanRef.current = null;
134
+ // 点击div内直接关闭
135
+ setOpen(false);
136
+ }, []);
129
137
 
130
- // 处理选项点击:删除用户刚输入的值,将选中的 label 放到运算符后面
138
+ // 处理选项点击
131
139
  var handleOptionClick = useCallback(function (opt) {
132
140
  var container = containerRef.current;
133
141
  if (!container) return;
134
- var newValue = replaceLongestDiff(containerValueSnapShot.current, opt.label, inputOperatorPosition.current);
135
142
  setOpen(false);
136
143
  containerValueSnapShot.current = '';
137
- var expr = newValue;
138
- var valueExpr = replaceLabelsWithValues(expr, flatOptions);
139
- setContainerValue(valueExpr);
140
- onChange(valueExpr);
141
144
 
142
- // 获取当前光标所在的 span
145
+ // 如果有 tempSpanRef,用新逻辑:直接替换该 span 的内容
146
+ if (tempSpanRef.current) {
147
+ tempSpanRef.current.textContent = opt.label;
148
+ var replacedSpan = tempSpanRef.current;
149
+ tempSpanRef.current = null;
150
+
151
+ // 光标移到替换后的 span 后面
152
+ var _allSpans = Array.from(container.querySelectorAll('span'));
153
+ var replacedIndex = _allSpans.indexOf(replacedSpan);
154
+ var _targetSpan = _allSpans[replacedIndex + 1];
155
+ if (!_targetSpan || _targetSpan.classList.contains('formula-editor-token-label')) {
156
+ _targetSpan = document.createElement('span');
157
+ _targetSpan.className = 'formula-editor-token-other';
158
+ _targetSpan.textContent = '';
159
+ replacedSpan.after(_targetSpan);
160
+ }
161
+ var _selection = window.getSelection();
162
+ if (_selection && _selection.rangeCount > 0) {
163
+ var _newRange = document.createRange();
164
+ _newRange.selectNodeContents(_targetSpan);
165
+ _newRange.collapse(true);
166
+ _selection.removeAllRanges();
167
+ _selection.addRange(_newRange);
168
+ }
169
+
170
+ // 更新 containerValue
171
+ var newValue = container.textContent || '';
172
+ var valueExpr = replaceLabelsWithValues(newValue, flatOptions);
173
+ setContainerValue(valueExpr);
174
+ onChange(valueExpr);
175
+ return;
176
+ }
177
+
178
+ // 原逻辑:删除 inputAfterDropDownShow,插入新 label
179
+ var newValueUser = replaceLongestDiff(containerValueSnapShot.current, opt.label, inputOperatorPosition.current);
180
+ var expr = newValueUser;
181
+ var valueExprUser = replaceLabelsWithValues(expr, flatOptions);
182
+ setContainerValue(valueExprUser);
183
+ onChange(valueExprUser);
143
184
  var selection = window.getSelection();
144
185
  if (!selection || selection.rangeCount === 0) return;
145
186
  var range = selection.getRangeAt(0);
@@ -207,6 +248,9 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
207
248
  var handleInput = useCallback(function () {
208
249
  var container = containerRef.current;
209
250
  if (!container) return;
251
+ if (tempSpanRef.current) {
252
+ closeDorpDown();
253
+ }
210
254
  var newValue = container.textContent || '';
211
255
  var processedValue = newValue;
212
256
  var expr = processedValue;
@@ -267,12 +311,8 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
267
311
  (_containerRef$current2 = containerRef.current) === null || _containerRef$current2 === void 0 || _containerRef$current2.focus();
268
312
  }
269
313
  }, [isEditing]);
270
- var closeDorpDown = useCallback(function () {
271
- // 点击div内直接关闭
272
- setOpen(false);
273
- }, []);
274
314
 
275
- // 鼠标释放时,如果光标在 label span 内,移动到后一个 span 的开头
315
+ // 鼠标释放时,如果光标在 label span 内,打开下拉框并记录 tempSpan
276
316
  var handleMouseUp = useCallback(function () {
277
317
  var div = containerRef.current;
278
318
  if (!div) return;
@@ -285,8 +325,20 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
285
325
  if (!currentSpan || currentSpan === div) return;
286
326
  var isLabelSpan = currentSpan.classList.contains('formula-editor-token-label');
287
327
 
288
- // 如果在 label span 内,移动到下一个 span 的开头
328
+ // 如果在 label span 内,打开下拉框并记录 tempSpan
289
329
  if (isLabelSpan) {
330
+ // 更新 offsetX 位置
331
+ var containerRect = div.getBoundingClientRect();
332
+ var cursorRect = range.getBoundingClientRect();
333
+ var cursorDistance = cursorRect ? cursorRect.left - containerRect.left : 0;
334
+ setOffsetX(cursorDistance < 150 ? 0 : cursorDistance - 8);
335
+
336
+ // 记录当前 label span 作为 tempSpan
337
+ tempSpanRef.current = currentSpan;
338
+
339
+ // 打开下拉框
340
+ setOpen(true);
341
+ // 移动到下一个 span 的开头
290
342
  var allSpans = Array.from(div.querySelectorAll('span'));
291
343
  var currentIndex = allSpans.indexOf(currentSpan);
292
344
  if (currentIndex < allSpans.length - 1) {
@@ -321,13 +373,13 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
321
373
 
322
374
  // 方向键:跳过 label span
323
375
  if (e.key === 'ArrowRight' || e.key === 'ArrowLeft') {
324
- closeDorpDown();
325
376
  var position = getCursorPositionInSpan(currentSpan);
326
377
  var isAtEnd = startOffset >= textLen;
327
378
  var isAtStart = startOffset === 0;
328
379
  var isAlmostEnd = startOffset >= textLen - 1;
329
380
  var isAlmostStart = position === 1;
330
381
  if (e.key === 'ArrowRight' && isAtEnd) {
382
+ closeDorpDown();
331
383
  // 向右 + 在末尾 -> 跳到下一个 span 的开头(跳过 label span)
332
384
  var targetIndex = currentIndex + 1;
333
385
  while (targetIndex < allSpans.length && allSpans[targetIndex].classList.contains('formula-editor-token-label')) {
@@ -343,6 +395,7 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
343
395
  selection.addRange(newRange);
344
396
  }
345
397
  } else if (e.key === 'ArrowLeft' && isAtStart) {
398
+ closeDorpDown();
346
399
  // 向左 + 在开头 -> 跳到上一个 span 的末尾(跳过 label span)
347
400
  var _targetIndex = currentIndex - 1;
348
401
  while (_targetIndex >= 0 && allSpans[_targetIndex].classList.contains('formula-editor-token-label')) {
@@ -350,34 +403,36 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
350
403
  }
351
404
  if (_targetIndex >= 0 && _targetIndex !== currentIndex - 1) {
352
405
  e.preventDefault();
353
- var _targetSpan = allSpans[_targetIndex];
354
- var _newRange = document.createRange();
355
- _newRange.selectNodeContents(_targetSpan);
356
- _newRange.collapse(false);
406
+ var _targetSpan2 = allSpans[_targetIndex];
407
+ var _newRange2 = document.createRange();
408
+ _newRange2.selectNodeContents(_targetSpan2);
409
+ _newRange2.collapse(false);
357
410
  selection.removeAllRanges();
358
- selection.addRange(_newRange);
411
+ selection.addRange(_newRange2);
359
412
  }
360
413
  } else if (e.key === 'ArrowRight' && isAlmostEnd) {
414
+ closeDorpDown();
361
415
  var _targetIndex2 = currentIndex + 1;
362
416
  if (_targetIndex2 < allSpans.length && !allSpans[_targetIndex2].classList.contains('formula-editor-token-label')) {
363
417
  e.preventDefault();
364
- var _targetSpan2 = allSpans[_targetIndex2];
365
- var _newRange2 = document.createRange();
366
- _newRange2.selectNodeContents(_targetSpan2);
367
- _newRange2.collapse(true);
418
+ var _targetSpan3 = allSpans[_targetIndex2];
419
+ var _newRange3 = document.createRange();
420
+ _newRange3.selectNodeContents(_targetSpan3);
421
+ _newRange3.collapse(true);
368
422
  selection.removeAllRanges();
369
- selection.addRange(_newRange2);
423
+ selection.addRange(_newRange3);
370
424
  }
371
425
  } else if (e.key === 'ArrowLeft' && isAlmostStart) {
426
+ closeDorpDown();
372
427
  var _targetIndex3 = currentIndex - 1;
373
428
  if (_targetIndex3 >= 0 && !allSpans[_targetIndex3].classList.contains('formula-editor-token-label')) {
374
429
  e.preventDefault();
375
- var _targetSpan3 = allSpans[_targetIndex3];
376
- var _newRange3 = document.createRange();
377
- _newRange3.selectNodeContents(_targetSpan3);
378
- _newRange3.collapse(false);
430
+ var _targetSpan4 = allSpans[_targetIndex3];
431
+ var _newRange4 = document.createRange();
432
+ _newRange4.selectNodeContents(_targetSpan4);
433
+ _newRange4.collapse(false);
379
434
  selection.removeAllRanges();
380
- selection.addRange(_newRange3);
435
+ selection.addRange(_newRange4);
381
436
  }
382
437
  }
383
438
  return;
@@ -385,7 +440,10 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
385
440
 
386
441
  // 删除键逻辑
387
442
  if (e.key !== 'Delete' && e.key !== 'Backspace') return;
388
- if (e.key === 'Backspace') {
443
+ if (e.key === 'Backspace' || e.key === 'Delete') {
444
+ if (tempSpanRef.current) {
445
+ closeDorpDown();
446
+ }
389
447
  // 检查删除后是否只剩一个空的 span
390
448
  var allSpansNow = Array.from(div.querySelectorAll('span'));
391
449
  var isOnlyOneEmptySpan = allSpansNow.length === 1 && allSpansNow[0].textContent === '';
@@ -403,31 +461,31 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
403
461
  e.preventDefault();
404
462
  e.stopPropagation();
405
463
  prevSpan.remove();
406
- var _newRange4 = document.createRange();
464
+ var _newRange5 = document.createRange();
407
465
 
408
466
  // 如果当前 span 有内容,光标放在开头;否则找最近的有内容的 span
409
467
  if (currentSpan.textContent !== '') {
410
- _newRange4.selectNodeContents(currentSpan);
411
- _newRange4.collapse(true);
468
+ _newRange5.selectNodeContents(currentSpan);
469
+ _newRange5.collapse(true);
412
470
  } else {
413
471
  // 找前一个最近的有内容的 span
414
- var _targetSpan4;
472
+ var _targetSpan5;
415
473
  for (var i = currentIndex - 2; i >= 0; i--) {
416
474
  if (allSpans[i].textContent !== '') {
417
- _targetSpan4 = allSpans[i];
475
+ _targetSpan5 = allSpans[i];
418
476
  break;
419
477
  }
420
478
  }
421
- if (_targetSpan4) {
422
- _newRange4.selectNodeContents(_targetSpan4);
423
- _newRange4.collapse(false);
479
+ if (_targetSpan5) {
480
+ _newRange5.selectNodeContents(_targetSpan5);
481
+ _newRange5.collapse(false);
424
482
  } else {
425
- _newRange4.selectNodeContents(div);
426
- _newRange4.collapse(true);
483
+ _newRange5.selectNodeContents(div);
484
+ _newRange5.collapse(true);
427
485
  }
428
486
  }
429
487
  selection.removeAllRanges();
430
- selection.addRange(_newRange4);
488
+ selection.addRange(_newRange5);
431
489
  return;
432
490
  }
433
491
  }
@@ -443,11 +501,11 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
443
501
  if (prevText.length > 0) {
444
502
  _prevSpan.textContent = prevText.slice(0, -1);
445
503
  }
446
- var _newRange5 = document.createRange();
447
- _newRange5.selectNodeContents(_prevSpan);
448
- _newRange5.collapse(false);
504
+ var _newRange6 = document.createRange();
505
+ _newRange6.selectNodeContents(_prevSpan);
506
+ _newRange6.collapse(false);
449
507
  selection.removeAllRanges();
450
- selection.addRange(_newRange5);
508
+ selection.addRange(_newRange6);
451
509
  }
452
510
  }
453
511
 
@@ -462,73 +520,73 @@ export var getFormulaInputEditor = function getFormulaInputEditor(options, repla
462
520
  // 如果光标在 span 开头 + Delete 键,currentIndex 指向的是被删 span 的后一个,所以要 -1
463
521
  var searchIndex = startOffset === 0 ? currentIndex - 1 : currentIndex;
464
522
  // 从 searchIndex 位置往前找
465
- var _targetSpan5;
523
+ var _targetSpan6;
466
524
  for (var _i = searchIndex; _i >= 0; _i--) {
467
525
  var span = allSpansNow[_i];
468
526
  if (span.textContent !== '') {
469
- _targetSpan5 = span;
527
+ _targetSpan6 = span;
470
528
  break;
471
529
  }
472
530
  }
473
531
  // 如果找到的有内容 span 是 label,则把光标放在 label span 的后一个 span 的开头
474
- if (_targetSpan5 && _targetSpan5.classList.contains('formula-editor-token-label')) {
475
- var labelIndex = allSpansNow.indexOf(_targetSpan5);
532
+ if (_targetSpan6 && _targetSpan6.classList.contains('formula-editor-token-label')) {
533
+ var labelIndex = allSpansNow.indexOf(_targetSpan6);
476
534
  if (labelIndex < allSpansNow.length - 1) {
477
535
  var nextSpan = allSpansNow[labelIndex + 1];
478
- var _newRange6 = document.createRange();
479
- _newRange6.selectNodeContents(nextSpan);
480
- _newRange6.collapse(true);
536
+ var _newRange7 = document.createRange();
537
+ _newRange7.selectNodeContents(nextSpan);
538
+ _newRange7.collapse(true);
481
539
  selection.removeAllRanges();
482
- selection.addRange(_newRange6);
540
+ selection.addRange(_newRange7);
483
541
  return;
484
542
  }
485
543
  }
486
544
 
487
545
  // 否则把光标放在找到的 span 的末尾
488
- if (_targetSpan5) {
489
- var _newRange7 = document.createRange();
490
- _newRange7.selectNodeContents(_targetSpan5);
491
- _newRange7.collapse(false);
546
+ if (_targetSpan6) {
547
+ var _newRange8 = document.createRange();
548
+ _newRange8.selectNodeContents(_targetSpan6);
549
+ _newRange8.collapse(false);
492
550
  selection.removeAllRanges();
493
- selection.addRange(_newRange7);
551
+ selection.addRange(_newRange8);
494
552
  return;
495
553
  }
496
554
  }
497
555
  if (!currentSpanNow || currentSpanNow === div) return;
498
556
  if (currentSpanNow.textContent === '') {
499
557
  var currentIndexNow = allSpansNow.indexOf(currentSpanNow);
500
- var _newRange8 = document.createRange();
558
+ var _newRange9 = document.createRange();
501
559
  if (currentIndexNow > 0) {
502
560
  // 移到前一个 span 的末尾,但如果前一个 span 是 label,则移到后一个 span 的开头
503
- var _targetSpan6 = allSpansNow[currentIndexNow - 1];
504
- if (_targetSpan6.classList.contains('formula-editor-token-label')) {
561
+ var _targetSpan7 = allSpansNow[currentIndexNow - 1];
562
+ if (_targetSpan7.classList.contains('formula-editor-token-label')) {
505
563
  // 移到 label span 的后一个 span 的开头
506
564
  if (currentIndexNow < allSpansNow.length - 1) {
507
565
  var _nextSpan = allSpansNow[currentIndexNow + 1];
508
- _newRange8.selectNodeContents(_nextSpan);
509
- _newRange8.collapse(true);
566
+ _newRange9.selectNodeContents(_nextSpan);
567
+ _newRange9.collapse(true);
510
568
  } else {
511
- _newRange8.selectNodeContents(div);
512
- _newRange8.collapse(false);
569
+ _newRange9.selectNodeContents(div);
570
+ _newRange9.collapse(false);
513
571
  }
514
572
  } else {
515
- _newRange8.selectNodeContents(_targetSpan6);
516
- _newRange8.collapse(false);
573
+ _newRange9.selectNodeContents(_targetSpan7);
574
+ _newRange9.collapse(false);
517
575
  }
518
576
  currentSpanNow.remove();
519
577
  } else if (allSpansNow.length > 1) {
520
578
  // 第一个 span 为空,移到下一个 span 的开头
521
579
  var _nextSpan2 = allSpansNow[currentIndexNow + 1];
522
- _newRange8.selectNodeContents(_nextSpan2);
523
- _newRange8.collapse(true);
580
+ _newRange9.selectNodeContents(_nextSpan2);
581
+ _newRange9.collapse(true);
524
582
  currentSpanNow.remove();
525
583
  } else {
526
584
  // 只有一个空 span,保持空
527
- _newRange8.selectNodeContents(div);
528
- _newRange8.collapse(true);
585
+ _newRange9.selectNodeContents(div);
586
+ _newRange9.collapse(true);
529
587
  }
530
588
  selection.removeAllRanges();
531
- selection.addRange(_newRange8);
589
+ selection.addRange(_newRange9);
532
590
  }
533
591
  }, 0);
534
592
  }, []);
@@ -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++;
@@ -181,7 +181,7 @@ var data = [{
181
181
  age: 41,
182
182
  address: 'Sidney No. 1 Lake Park',
183
183
  tags: ['cool', 'teacher'],
184
- formula: null,
184
+ formula: '=(123 + -456) * price *-discount',
185
185
  amount: 100
186
186
  }];
187
187
  var App = function App() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhenliang/sheet",
3
- "version": "0.2.5-beta.6",
3
+ "version": "0.2.5-beta.8",
4
4
  "description": "A react library developed with dumi",
5
5
  "license": "MIT",
6
6
  "module": "dist/index.js",