@underverse-ui/underverse 1.0.185 → 1.0.186

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "package": "@underverse-ui/underverse",
3
- "version": "1.0.185",
3
+ "version": "1.0.186",
4
4
  "sourceEntry": "src/index.ts",
5
5
  "totalExports": 248,
6
6
  "exports": [
package/dist/index.cjs CHANGED
@@ -42461,6 +42461,9 @@ function getFormulaEditingTableContext(view) {
42461
42461
  if (!tableNode || tableNode.type.name !== "table") return null;
42462
42462
  const tableDom = cellDom.closest("table");
42463
42463
  if (!(tableDom instanceof HTMLTableElement)) return null;
42464
+ const tableMap = import_tables7.TableMap.get(tableNode);
42465
+ const tableStart = $from.start(tableDepth);
42466
+ const formulaCellRect = tableMap.findCell(cellPos - tableStart);
42464
42467
  return {
42465
42468
  cellContentEnd: $from.end(depth),
42466
42469
  cellContentStart: $from.start(depth),
@@ -42468,11 +42471,50 @@ function getFormulaEditingTableContext(view) {
42468
42471
  formula: getCellText2(node),
42469
42472
  tableDom,
42470
42473
  tableNode,
42471
- tablePos: $from.before(tableDepth)
42474
+ tablePos: $from.before(tableDepth),
42475
+ formulaCellLabel: `${indexToColumnName(formulaCellRect.left)}${formulaCellRect.top + 1}`
42472
42476
  };
42473
42477
  }
42474
42478
  return null;
42475
42479
  }
42480
+ function collectTableFormulaCells(tableNode) {
42481
+ const tableMap = import_tables7.TableMap.get(tableNode);
42482
+ const formulas = [];
42483
+ tableNode.forEach((rowNode, rowOffset) => {
42484
+ rowNode.forEach((cellNode, cellOffset) => {
42485
+ const formula = typeof cellNode.attrs.formula === "string" ? cellNode.attrs.formula.trim() : "";
42486
+ if (!formula) return;
42487
+ const rect = tableMap.findCell(rowOffset + 1 + cellOffset);
42488
+ formulas.push({
42489
+ label: `${indexToColumnName(rect.left)}${rect.top + 1}`,
42490
+ formula
42491
+ });
42492
+ });
42493
+ });
42494
+ return formulas;
42495
+ }
42496
+ function getFormulaCycleBlockedLabels(tableNode, formulaCellLabel) {
42497
+ const graph = buildTableFormulaDependencyGraph(collectTableFormulaCells(tableNode));
42498
+ const blocked = /* @__PURE__ */ new Set();
42499
+ const queue = [formulaCellLabel.toUpperCase()];
42500
+ for (let index = 0; index < queue.length; index += 1) {
42501
+ const label = queue[index];
42502
+ if (!label || blocked.has(label)) continue;
42503
+ blocked.add(label);
42504
+ for (const dependent of graph.dependents.get(label) ?? []) {
42505
+ if (!blocked.has(dependent)) queue.push(dependent);
42506
+ }
42507
+ }
42508
+ return blocked;
42509
+ }
42510
+ function getReferenceLabels(reference) {
42511
+ const range = parseTableCellRange(reference);
42512
+ return range ? getTableCellRangeLabels(range) : [reference.toUpperCase()];
42513
+ }
42514
+ function isBlockedFormulaReference(tableNode, formulaCellLabel, reference) {
42515
+ const blockedLabels = getFormulaCycleBlockedLabels(tableNode, formulaCellLabel);
42516
+ return getReferenceLabels(reference).some((label) => blockedLabels.has(label));
42517
+ }
42476
42518
  function cancelFormulaEditing(view) {
42477
42519
  const context = getFormulaEditingTableContext(view);
42478
42520
  if (!context) return false;
@@ -42536,10 +42578,20 @@ function normalizeFormulaRangeLabel(fromLabel, toLabel) {
42536
42578
  return fromLabel === toLabel ? fromLabel : `${fromLabel}:${toLabel}`;
42537
42579
  }
42538
42580
  function replacePickedLabel(view, pickState, nextLabel, currentCell) {
42539
- if (nextLabel === pickState.currentLabel && currentCell === pickState.currentCell) return pickState;
42581
+ const formulaContext = getFormulaEditingTableContext(view);
42582
+ const blocked = formulaContext ? isBlockedFormulaReference(formulaContext.tableNode, pickState.formulaCellLabel, nextLabel) : false;
42583
+ if (blocked) {
42584
+ return {
42585
+ ...pickState,
42586
+ blocked: true,
42587
+ currentCell
42588
+ };
42589
+ }
42590
+ if (nextLabel === pickState.currentLabel && currentCell === pickState.currentCell && !pickState.blocked) return pickState;
42540
42591
  if (nextLabel === pickState.currentLabel) {
42541
42592
  return {
42542
42593
  ...pickState,
42594
+ blocked: false,
42543
42595
  currentCell
42544
42596
  };
42545
42597
  }
@@ -42549,6 +42601,7 @@ function replacePickedLabel(view, pickState, nextLabel, currentCell) {
42549
42601
  view.dispatch(tr);
42550
42602
  return {
42551
42603
  ...pickState,
42604
+ blocked: false,
42552
42605
  insertedTo: nextTo,
42553
42606
  currentLabel: nextLabel,
42554
42607
  currentCell
@@ -42560,6 +42613,22 @@ function beginFormulaRangePick(view, event) {
42560
42613
  if (!formulaCell) return null;
42561
42614
  const picked = getFormulaTableCellInfo(view, event.target, formulaCell.tablePos);
42562
42615
  if (!picked || picked.cell === formulaCell.cellDom) return null;
42616
+ const blocked = isBlockedFormulaReference(formulaCell.tableNode, formulaCell.formulaCellLabel, picked.label);
42617
+ if (blocked) {
42618
+ event.preventDefault();
42619
+ event.stopPropagation();
42620
+ return {
42621
+ anchorLabel: picked.label,
42622
+ anchorCell: picked.cell,
42623
+ tablePos: formulaCell.tablePos,
42624
+ insertedFrom: view.state.selection.from,
42625
+ insertedTo: view.state.selection.from,
42626
+ currentLabel: "",
42627
+ currentCell: picked.cell,
42628
+ blocked: true,
42629
+ formulaCellLabel: formulaCell.formulaCellLabel
42630
+ };
42631
+ }
42563
42632
  const { from, to } = view.state.selection;
42564
42633
  const prefix = from === to ? getReferenceInsertionPrefix(view, formulaCell.cellContentStart, from) : "";
42565
42634
  const insertedText = `${prefix}${picked.label}`;
@@ -42577,7 +42646,9 @@ function beginFormulaRangePick(view, event) {
42577
42646
  insertedFrom,
42578
42647
  insertedTo: insertedFrom + picked.label.length,
42579
42648
  currentLabel: picked.label,
42580
- currentCell: picked.cell
42649
+ currentCell: picked.cell,
42650
+ blocked: false,
42651
+ formulaCellLabel: formulaCell.formulaCellLabel
42581
42652
  };
42582
42653
  }
42583
42654
  function updateFormulaRangePick(view, pickState, event) {
@@ -42605,7 +42676,8 @@ function getFormulaRangePickHighlight(container, pickState) {
42605
42676
  left,
42606
42677
  top,
42607
42678
  width: Math.max(0, right - left),
42608
- height: Math.max(0, bottom - top)
42679
+ height: Math.max(0, bottom - top),
42680
+ blocked: pickState.blocked
42609
42681
  };
42610
42682
  }
42611
42683
 
@@ -42629,6 +42701,12 @@ function createReferenceHighlight(label) {
42629
42701
  element.className = "pointer-events-none absolute z-[21] rounded-[2px] border-2 border-emerald-500 bg-emerald-500/15";
42630
42702
  return element;
42631
42703
  }
42704
+ function createBlockedReferenceHighlight(label) {
42705
+ const element = document.createElement("span");
42706
+ element.dataset.ueditorFormulaBlockedReference = label;
42707
+ element.className = "pointer-events-none absolute z-[22] rounded-[2px] border-2 border-destructive/80 bg-destructive/10";
42708
+ return element;
42709
+ }
42632
42710
  function useFormulaCoordinateOverlay(editor, containerRef, labels) {
42633
42711
  const overlayRef = (0, import_react77.useRef)(null);
42634
42712
  (0, import_react77.useEffect)(() => {
@@ -42640,6 +42718,7 @@ function useFormulaCoordinateOverlay(editor, containerRef, labels) {
42640
42718
  let activeTable = null;
42641
42719
  let activeTablePos = null;
42642
42720
  let hoverLabel = null;
42721
+ const scrollListenerOptions = { passive: true, capture: true };
42643
42722
  const clearOverlay = () => {
42644
42723
  activeTable = null;
42645
42724
  activeTablePos = null;
@@ -42699,10 +42778,12 @@ function useFormulaCoordinateOverlay(editor, containerRef, labels) {
42699
42778
  actions.dataset.ueditorFormulaActions = "";
42700
42779
  actions.className = "pointer-events-auto absolute z-50 flex items-center gap-1 rounded-md border border-border bg-background p-1 shadow-md";
42701
42780
  const formulaCellRect = context.cellDom.getBoundingClientRect();
42781
+ const formulaActionsHeight = 34;
42782
+ const formulaActionsTop = formulaCellRect.bottom + 4 + formulaActionsHeight > tableRect.bottom ? Math.max(containerRect.top + 4, formulaCellRect.top - formulaActionsHeight - 4) : formulaCellRect.bottom + 4;
42702
42783
  setPosition(
42703
42784
  actions,
42704
42785
  formulaCellRect.left - containerRect.left + container.scrollLeft,
42705
- formulaCellRect.bottom - containerRect.top + container.scrollTop + 4
42786
+ formulaActionsTop - containerRect.top + container.scrollTop
42706
42787
  );
42707
42788
  const applyButton = document.createElement("button");
42708
42789
  applyButton.type = "button";
@@ -42754,10 +42835,12 @@ function useFormulaCoordinateOverlay(editor, containerRef, labels) {
42754
42835
  children.push(label);
42755
42836
  }
42756
42837
  const references = new Set(getTableFormulaReferences(context.formula));
42838
+ const blockedReferences = getFormulaCycleBlockedLabels(context.tableNode, context.formulaCellLabel);
42757
42839
  for (const info of cellInfos) {
42758
- if (!info || !references.has(info.label)) continue;
42840
+ if (!info) continue;
42759
42841
  const cellRect = info.cell.getBoundingClientRect();
42760
- const highlight = createReferenceHighlight(info.label);
42842
+ const highlight = info.label !== context.formulaCellLabel && blockedReferences.has(info.label) ? createBlockedReferenceHighlight(info.label) : references.has(info.label) ? createReferenceHighlight(info.label) : null;
42843
+ if (!highlight) continue;
42761
42844
  setPosition(
42762
42845
  highlight,
42763
42846
  cellRect.left - containerRect.left + container.scrollLeft + 2,
@@ -42812,6 +42895,7 @@ function useFormulaCoordinateOverlay(editor, containerRef, labels) {
42812
42895
  editor.view.dom.addEventListener("mousemove", handleMouseMove2);
42813
42896
  editor.view.dom.addEventListener("mouseleave", handleMouseLeave2);
42814
42897
  container.addEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, scheduleSync);
42898
+ container.addEventListener("scroll", scheduleSync, scrollListenerOptions);
42815
42899
  window.addEventListener("resize", scheduleSync);
42816
42900
  scheduleSync();
42817
42901
  return () => {
@@ -42822,6 +42906,7 @@ function useFormulaCoordinateOverlay(editor, containerRef, labels) {
42822
42906
  editor.view.dom.removeEventListener("mousemove", handleMouseMove2);
42823
42907
  editor.view.dom.removeEventListener("mouseleave", handleMouseLeave2);
42824
42908
  container.removeEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, scheduleSync);
42909
+ container.removeEventListener("scroll", scheduleSync, scrollListenerOptions);
42825
42910
  window.removeEventListener("resize", scheduleSync);
42826
42911
  if (animationFrame != null) window.cancelAnimationFrame(animationFrame);
42827
42912
  clearOverlay();
@@ -44238,7 +44323,7 @@ var UEditor = import_react82.default.forwardRef(({
44238
44323
  {
44239
44324
  ref: formulaCoordinateOverlayRef,
44240
44325
  "data-ueditor-formula-coordinate-overlay": "",
44241
- className: "pointer-events-none absolute inset-0 z-[21] hidden overflow-visible"
44326
+ className: "pointer-events-none absolute inset-0 z-[35] hidden overflow-visible"
44242
44327
  }
44243
44328
  ),
44244
44329
  formulaRangeHighlight && /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
@@ -44246,7 +44331,11 @@ var UEditor = import_react82.default.forwardRef(({
44246
44331
  {
44247
44332
  "aria-hidden": "true",
44248
44333
  "data-ueditor-formula-range-highlight": "",
44249
- className: "pointer-events-none absolute z-20 rounded-[2px] border-2 border-primary bg-primary/10",
44334
+ "data-ueditor-formula-range-blocked": formulaRangeHighlight.blocked ? "true" : void 0,
44335
+ className: cn(
44336
+ "pointer-events-none absolute z-20 rounded-[2px] border-2",
44337
+ formulaRangeHighlight.blocked ? "border-destructive bg-destructive/15" : "border-primary bg-primary/10"
44338
+ ),
44250
44339
  style: {
44251
44340
  left: formulaRangeHighlight.left,
44252
44341
  top: formulaRangeHighlight.top,