@lumir-company/editor 0.4.17 → 0.4.18

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/index.mjs CHANGED
@@ -4901,6 +4901,9 @@ function LumirTableHandlesController() {
4901
4901
  const frozenRef = useRef11(false);
4902
4902
  const menuOpenRef = useRef11(false);
4903
4903
  const draggingRef = useRef11(false);
4904
+ useEffect10(() => {
4905
+ editor.__lumirActiveTableId = focused?.block?.id ?? null;
4906
+ }, [editor, focused]);
4904
4907
  const recompute = useCallback20(() => {
4905
4908
  if (frozenRef.current) {
4906
4909
  return;
@@ -5443,6 +5446,140 @@ function liftFontSize(blocks) {
5443
5446
  return mapPreservingRef(blocks, (b) => mapBlock(b, "lift"));
5444
5447
  }
5445
5448
 
5449
+ // src/utils/table-delete.ts
5450
+ import { CellSelection, TableMap as TableMap2, deleteRow } from "prosemirror-tables";
5451
+ function measureRowHeights(view, tablePos) {
5452
+ try {
5453
+ const at = view?.domAtPos?.(tablePos + 1);
5454
+ let el = at?.node;
5455
+ if (el && el.nodeType === 3) el = el.parentElement;
5456
+ const tableEl = el?.closest?.("table") ?? null;
5457
+ const body = tableEl?.tBodies?.[0];
5458
+ if (!body) return null;
5459
+ return Array.from(body.rows).map(
5460
+ (tr) => Math.round(tr.getBoundingClientRect().height)
5461
+ );
5462
+ } catch {
5463
+ return null;
5464
+ }
5465
+ }
5466
+ function buildDeleteColumnTr(state, tablePos, col, rowPx) {
5467
+ const table = state.doc.nodeAt(tablePos);
5468
+ if (!table || table.type.name !== "table") return null;
5469
+ const map = TableMap2.get(table);
5470
+ const W = map.width;
5471
+ const H = map.height;
5472
+ if (col < 0 || col >= W || W <= 1) return null;
5473
+ const cells = [];
5474
+ const seen = /* @__PURE__ */ new Set();
5475
+ for (let r = 0; r < H; r++) {
5476
+ for (let c = 0; c < W; c++) {
5477
+ const pos = map.map[r * W + c];
5478
+ if (seen.has(pos)) continue;
5479
+ seen.add(pos);
5480
+ const node = table.nodeAt(pos);
5481
+ if (!node) continue;
5482
+ cells.push({
5483
+ node,
5484
+ top: r,
5485
+ left: c,
5486
+ rowspan: node.attrs.rowspan ?? 1,
5487
+ colspan: node.attrs.colspan ?? 1
5488
+ });
5489
+ }
5490
+ }
5491
+ const spansCol = (c) => c.left <= col && col < c.left + c.colspan;
5492
+ const isDropped = (c) => spansCol(c) && c.colspan === 1;
5493
+ const survivingByRow = new Array(H).fill(0);
5494
+ for (const c of cells) if (!isDropped(c)) survivingByRow[c.top]++;
5495
+ const rowDies = survivingByRow.map((n) => n === 0);
5496
+ const newRowIndex = [];
5497
+ let ni = 0;
5498
+ for (let r = 0; r < H; r++) newRowIndex[r] = rowDies[r] ? -1 : ni++;
5499
+ const newH = ni;
5500
+ if (newH === 0) return null;
5501
+ const newRows = Array.from({ length: newH }, () => []);
5502
+ for (const c of cells) {
5503
+ if (isDropped(c)) continue;
5504
+ const newColspan = c.colspan - (spansCol(c) ? 1 : 0);
5505
+ let dyingWithin = 0;
5506
+ for (let r = c.top; r < c.top + c.rowspan; r++) if (rowDies[r]) dyingWithin++;
5507
+ const newRowspan = Math.max(1, c.rowspan - dyingWithin);
5508
+ const attrs = { ...c.node.attrs, colspan: newColspan, rowspan: newRowspan };
5509
+ if (spansCol(c) && Array.isArray(attrs.colwidth) && attrs.colwidth.length) {
5510
+ const cw = attrs.colwidth.slice();
5511
+ cw.splice(col - c.left, 1);
5512
+ attrs.colwidth = cw.some((w) => w > 0) ? cw : null;
5513
+ }
5514
+ if (dyingWithin > 0 && rowPx) {
5515
+ let sum = 0;
5516
+ let ok = true;
5517
+ for (let r = c.top; r < c.top + c.rowspan; r++) {
5518
+ if (typeof rowPx[r] !== "number") {
5519
+ ok = false;
5520
+ break;
5521
+ }
5522
+ sum += rowPx[r];
5523
+ }
5524
+ if (ok && sum > 0) attrs.rowHeight = Math.round(sum);
5525
+ }
5526
+ const target = newRowIndex[c.top];
5527
+ if (target >= 0) newRows[target].push(c.node.type.create(attrs, c.node.content));
5528
+ }
5529
+ const rowType = table.child(0)?.type;
5530
+ if (!rowType) return null;
5531
+ const rowNodes = newRows.map((rowCells) => rowType.create(null, rowCells));
5532
+ const newTable = table.type.create(table.attrs, rowNodes);
5533
+ const tr = state.tr;
5534
+ tr.replaceWith(tablePos, tablePos + table.nodeSize, newTable);
5535
+ return tr.docChanged ? tr : null;
5536
+ }
5537
+ function removeFocusedRowOrColumn(editor, index, direction) {
5538
+ const tiptap = editor?._tiptapEditor;
5539
+ if (!tiptap) return false;
5540
+ const { state } = tiptap;
5541
+ let tablePos = -1;
5542
+ const activeId = editor?.__lumirActiveTableId;
5543
+ if (activeId) {
5544
+ const p = findTableNodePos(tiptap, activeId);
5545
+ if (p >= 0 && state.doc.nodeAt(p)?.type.name === "table") tablePos = p;
5546
+ }
5547
+ if (tablePos < 0) {
5548
+ const $from = state.selection.$from;
5549
+ for (let d = $from.depth; d > 0; d--) {
5550
+ if ($from.node(d).type.name === "table") {
5551
+ tablePos = $from.before(d);
5552
+ break;
5553
+ }
5554
+ }
5555
+ }
5556
+ if (tablePos < 0) {
5557
+ const vp = editor?.tableHandles?.view?.tablePos;
5558
+ if (typeof vp === "number" && state.doc.nodeAt(vp)?.type.name === "table") {
5559
+ tablePos = vp;
5560
+ }
5561
+ }
5562
+ if (tablePos < 0) return false;
5563
+ try {
5564
+ if (direction === "column") {
5565
+ const rowPx = measureRowHeights(tiptap.view, tablePos);
5566
+ const tr = buildDeleteColumnTr(state, tablePos, index, rowPx);
5567
+ if (!tr) return false;
5568
+ tiptap.view.dispatch(tr);
5569
+ return true;
5570
+ }
5571
+ const tableInside = state.doc.resolve(tablePos + 1);
5572
+ const rowStart = state.doc.resolve(tableInside.posAtIndex(index) + 1);
5573
+ const cellPos = state.doc.resolve(rowStart.posAtIndex(0));
5574
+ const selState = state.apply(
5575
+ state.tr.setSelection(new CellSelection(cellPos))
5576
+ );
5577
+ return deleteRow(selState, (tr) => tiptap.view.dispatch(tr));
5578
+ } catch {
5579
+ return false;
5580
+ }
5581
+ }
5582
+
5446
5583
  // src/utils/excel-paste.ts
5447
5584
  var NAMED_COLORS = {
5448
5585
  black: "#000000",
@@ -6296,6 +6433,18 @@ function LumirEditor({
6296
6433
  editor.isEditable = editable;
6297
6434
  }
6298
6435
  }, [editor, editable]);
6436
+ useEffect11(() => {
6437
+ if (!editor) return;
6438
+ const th = editor.tableHandles;
6439
+ if (!th || th.__lumirColDelPatched || typeof th.removeRowOrColumn !== "function")
6440
+ return;
6441
+ const orig = th.removeRowOrColumn.bind(th);
6442
+ th.removeRowOrColumn = (index, dir) => {
6443
+ if (removeFocusedRowOrColumn(editor, index, dir)) return;
6444
+ return orig(index, dir);
6445
+ };
6446
+ th.__lumirColDelPatched = true;
6447
+ }, [editor]);
6299
6448
  useEffect11(() => {
6300
6449
  if (!editor || !floatingMenu) return;
6301
6450
  const ft = editor.formattingToolbar;