@jackuait/blok 0.10.10 → 0.10.12

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.
@@ -130,7 +130,7 @@ var a = {
130
130
  RIGHT: 2,
131
131
  BACKWARD: 3,
132
132
  FORWARD: 4
133
- }, l = () => "0.10.10", u = /* @__PURE__ */ function(e) {
133
+ }, l = () => "0.10.12", u = /* @__PURE__ */ function(e) {
134
134
  return e.VERBOSE = "VERBOSE", e.INFO = "INFO", e.WARN = "WARN", e.ERROR = "ERROR", e;
135
135
  }({}), d = (e, t, n = "log", r, i = "color: inherit") => {
136
136
  let a = typeof console > "u" ? void 0 : console;
@@ -1,4 +1,4 @@
1
- import { $ as e, $t as t, A as n, At as r, B as i, Bt as a, Ct as o, D as s, Et as c, F as l, Ft as u, G as d, Gt as f, H as p, Ht as m, I as h, It as g, J as _, Jt as v, K as y, Kt as b, L as ee, Lt as x, M as te, Mt as S, Nn as ne, Nt as re, O as ie, Ot as C, P as ae, Pt as oe, Q as se, Qt as ce, R as le, Rn as w, Rt as ue, St as de, Tt as fe, U as pe, Ut as me, V as he, W as ge, Wt as _e, X as ve, Xt as ye, Y as be, Yt as xe, Z as Se, Zt as Ce, _n as we, _t as Te, a as Ee, at as De, bt as Oe, c as ke, cn as T, ct as Ae, d as je, dr as E, dt as Me, en as Ne, et as Pe, f as Fe, ft as Ie, g as Le, gt as Re, h as ze, ht as Be, i as Ve, ir as He, it as Ue, j as We, jt as Ge, k as Ke, kt as qe, l as Je, ln as Ye, lt as Xe, mn as Ze, mt as Qe, n as $e, nt as et, o as tt, ot as nt, p as rt, pn as D, pt as it, q as at, qt as ot, r as st, rn as ct, rt as lt, s as ut, sn as dt, st as ft, t as pt, tt as mt, u as O, un as ht, ur as k, ut as gt, v as _t, vn as vt, vt as yt, wt as bt, xt, z as St, zt as Ct } from "./constants-BYv7qYbw.mjs";
1
+ import { $ as e, $t as t, A as n, At as r, B as i, Bt as a, Ct as o, D as s, Et as c, F as l, Ft as u, G as d, Gt as f, H as p, Ht as m, I as h, It as g, J as _, Jt as v, K as y, Kt as b, L as ee, Lt as x, M as te, Mt as S, Nn as ne, Nt as re, O as ie, Ot as C, P as ae, Pt as oe, Q as se, Qt as ce, R as le, Rn as w, Rt as ue, St as de, Tt as fe, U as pe, Ut as me, V as he, W as ge, Wt as _e, X as ve, Xt as ye, Y as be, Yt as xe, Z as Se, Zt as Ce, _n as we, _t as Te, a as Ee, at as De, bt as Oe, c as ke, cn as T, ct as Ae, d as je, dr as E, dt as Me, en as Ne, et as Pe, f as Fe, ft as Ie, g as Le, gt as Re, h as ze, ht as Be, i as Ve, ir as He, it as Ue, j as We, jt as Ge, k as Ke, kt as qe, l as Je, ln as Ye, lt as Xe, mn as Ze, mt as Qe, n as $e, nt as et, o as tt, ot as nt, p as rt, pn as D, pt as it, q as at, qt as ot, r as st, rn as ct, rt as lt, s as ut, sn as dt, st as ft, t as pt, tt as mt, u as O, un as ht, ur as k, ut as gt, v as _t, vn as vt, vt as yt, wt as bt, xt, z as St, zt as Ct } from "./constants-C0aZXxoO.mjs";
2
2
  import { t as A } from "./objectSpread2-CWwMYL_U.mjs";
3
3
  import { n as j } from "./tw-CqxBf-1Y.mjs";
4
4
  //#region src/components/utils/html.ts
@@ -859,11 +859,27 @@ var Qt = "outline-hidden py-[7px] mt-[2px] mb-px", $t = "outline-hidden pl-0.5 l
859
859
  depth: 0
860
860
  };
861
861
  if (En(e)) {
862
- let t = e.items[0], r = (t == null ? void 0 : t.content) || "", i = (t == null ? void 0 : t.checked) || !1;
862
+ let { text: t, checked: r } = ((e) => {
863
+ if (typeof e == "string") return {
864
+ text: e,
865
+ checked: !1
866
+ };
867
+ if (typeof e == "object" && e) {
868
+ var t, n, r;
869
+ return {
870
+ text: (t = (n = e.content) == null ? e.text : n) == null ? "" : t,
871
+ checked: (r = e.checked) == null ? !1 : r
872
+ };
873
+ }
874
+ return {
875
+ text: "",
876
+ checked: !1
877
+ };
878
+ })(e.items[0]);
863
879
  return A({
864
- text: r,
880
+ text: t,
865
881
  style: e.style || n,
866
- checked: !!i,
882
+ checked: !!r,
867
883
  depth: 0
868
884
  }, e.start !== void 0 && e.start !== 1 ? { start: e.start } : {});
869
885
  }
@@ -2074,7 +2090,7 @@ var Qt = "outline-hidden py-[7px] mt-[2px] mb-px", $t = "outline-hidden pl-0.5 l
2074
2090
  constructor(e) {
2075
2091
  var t;
2076
2092
  this._activeCellWithBlocks = null, this.cellsPendingCheck = /* @__PURE__ */ new Set(), this.pendingCheckScheduled = !1, this.removedBlockCells = /* @__PURE__ */ new Map(), this.deferredEvents = [], this.isExitingTable = !1, this.handleBlockMutation = (e) => {
2077
- if (this.isStructuralOpActive()) {
2093
+ if (this.isStructuralOpActive() && !this.api.blocks.isSyncingFromYjs) {
2078
2094
  this.deferredEvents.push(e);
2079
2095
  return;
2080
2096
  }
@@ -2089,28 +2105,36 @@ var Qt = "outline-hidden py-[7px] mt-[2px] mb-px", $t = "outline-hidden pl-0.5 l
2089
2105
  return;
2090
2106
  }
2091
2107
  if (t !== "block-added" || n.target.id === this.tableBlockId) return;
2092
- let r = n.index;
2093
- if (r === void 0) return;
2094
- let i = this.findRemovedEntryForIndex(r);
2095
- if (i && this.isAdjacentToThisTable(r)) {
2096
- this.claimBlockForCell(i.cell, n.target.id), this.syncBlockToModel(i.cell, n.target.id), this.cellsPendingCheck.delete(i.cell);
2108
+ let r = this.model.findCellForBlock(n.target.id);
2109
+ if (r) {
2110
+ let e = this.gridElement.querySelector(`[${I}="${r.row}"][${L}="${r.col}"]`);
2111
+ if (e) {
2112
+ this.claimBlockForCell(e, n.target.id), this.cellsPendingCheck.delete(e);
2113
+ return;
2114
+ }
2115
+ }
2116
+ let i = n.index;
2117
+ if (i === void 0) return;
2118
+ let a = this.findRemovedEntryForIndex(i);
2119
+ if (a && this.isAdjacentToThisTable(i)) {
2120
+ this.claimBlockForCell(a.cell, n.target.id), this.syncBlockToModel(a.cell, n.target.id), this.cellsPendingCheck.delete(a.cell);
2097
2121
  return;
2098
2122
  }
2099
- let a = n.target.holder, o = a.closest(`[${z}]`);
2100
- o && this.stripPlaceholders(o);
2101
- let s = o && !this.model.findCellForBlock(n.target.id) ? o.closest(`[${F}]`) : null;
2102
- if (s && this.syncBlockToModel(s, n.target.id), o) return;
2103
- if (!this.gridElement.contains(a)) {
2123
+ let o = n.target.holder, s = o.closest(`[${z}]`);
2124
+ s && this.stripPlaceholders(s);
2125
+ let c = s && !this.model.findCellForBlock(n.target.id) ? s.closest(`[${F}]`) : null;
2126
+ if (c && this.syncBlockToModel(c, n.target.id), s) return;
2127
+ if (!this.gridElement.contains(o)) {
2104
2128
  let e = this.api.blocks.getBlockIndex(this.tableBlockId), t = e === void 0 ? null : this.api.blocks.getBlockByIndex(e);
2105
- if (t && !t.holder.contains(a)) return;
2106
- let i = this.api.blocks.getCurrentBlockIndex(), o = i >= 0 ? this.api.blocks.getBlockByIndex(i) : null;
2107
- if (!(o != null && this.getOwnedCellForBlock(o.id) !== null)) return;
2108
- let s = this.findCellForNewBlock(r);
2129
+ if (t && !t.holder.contains(o)) return;
2130
+ let r = this.api.blocks.getCurrentBlockIndex(), a = r >= 0 ? this.api.blocks.getBlockByIndex(r) : null;
2131
+ if (!(a != null && this.getOwnedCellForBlock(a.id) !== null)) return;
2132
+ let s = this.findCellForNewBlock(i);
2109
2133
  s && (this.claimBlockForCell(s, n.target.id), this.syncBlockToModel(s, n.target.id), this.cellsPendingCheck.delete(s));
2110
2134
  return;
2111
2135
  }
2112
- let c = this.findCellForNewBlock(r);
2113
- c && (this.claimBlockForCell(c, n.target.id), this.syncBlockToModel(c, n.target.id), this.cellsPendingCheck.delete(c));
2136
+ let l = this.findCellForNewBlock(i);
2137
+ l && (this.claimBlockForCell(l, n.target.id), this.syncBlockToModel(l, n.target.id), this.cellsPendingCheck.delete(l));
2114
2138
  }, this.handleCellBlankSpaceClick = (e) => {
2115
2139
  let t = e.target;
2116
2140
  if (!t) return;
@@ -2270,6 +2294,24 @@ var Qt = "outline-hidden py-[7px] mt-[2px] mb-px", $t = "outline-hidden pl-0.5 l
2270
2294
  }), n.push(a);
2271
2295
  }), n;
2272
2296
  }
2297
+ reclaimReferencedBlocks() {
2298
+ this.model.snapshot().content.forEach((e, t) => {
2299
+ e.forEach((e, n) => {
2300
+ if (!R(e) || e.blocks.length === 0) return;
2301
+ let r = this.gridElement.querySelector(`[${I}="${t}"][${L}="${n}"]`);
2302
+ if (!r) return;
2303
+ let i = r.querySelector(`[${z}]`);
2304
+ if (i) for (let t of e.blocks) {
2305
+ let e = this.api.blocks.getBlockIndex, n = this.api.blocks.getBlockByIndex;
2306
+ if (typeof e != "function" || typeof n != "function") return;
2307
+ let a = e(t);
2308
+ if (a === void 0) continue;
2309
+ let o = n(a);
2310
+ o && (i.contains(o.holder) || this.claimBlockForCell(r, t));
2311
+ }
2312
+ });
2313
+ });
2314
+ }
2273
2315
  stripPlaceholders(e) {
2274
2316
  e.querySelectorAll("[data-blok-placeholder-active]").forEach((e) => {
2275
2317
  e.removeAttribute("data-blok-placeholder-active");
@@ -4927,15 +4969,27 @@ var Ir = (e) => {
4927
4969
  }
4928
4970
  save(e) {
4929
4971
  var t;
4930
- let n = this.model.snapshot(), r = (t = this.blockId) == null ? "" : t;
4931
- return n.content = n.content.map((e) => e.map((e) => {
4972
+ let n = this.model.snapshot(), r = (t = this.blockId) == null ? "" : t, i = this.gridElement;
4973
+ return n.content = n.content.map((e, t) => e.map((e, n) => {
4932
4974
  if (!R(e)) return e;
4933
- let t = e.blocks.filter((e) => {
4975
+ let a = e.blocks.filter((e) => {
4934
4976
  var t, n, i;
4935
4977
  let a = (t = (n = this.api.blocks).getById) == null ? void 0 : t.call(n, e);
4936
4978
  return a != null && ((i = a.parentId) == null ? "" : i) === r;
4937
4979
  });
4938
- return A(A({}, e), {}, { blocks: t });
4980
+ if (a.length === 0 && i) {
4981
+ let a = i.querySelector(`[${I}="${t}"][${L}="${n}"]`), o = a == null ? void 0 : a.querySelector(`[${z}]`), s = o ? Array.from(o.querySelectorAll("[data-blok-id]")).map((e) => {
4982
+ var t;
4983
+ return (t = e.getAttribute("data-blok-id")) == null ? "" : t;
4984
+ }).filter((e) => {
4985
+ var t, n, i;
4986
+ if (!e) return !1;
4987
+ let a = (t = (n = this.api.blocks).getById) == null ? void 0 : t.call(n, e);
4988
+ return a != null && ((i = a.parentId) == null ? "" : i) === r;
4989
+ }) : [];
4990
+ if (s.length > 0) return A(A({}, e), {}, { blocks: s });
4991
+ }
4992
+ return A(A({}, e), {}, { blocks: a });
4939
4993
  })), n;
4940
4994
  }
4941
4995
  validate(e) {
@@ -4962,7 +5016,9 @@ var Ir = (e) => {
4962
5016
  yi(f, e.content), bi(f, e.content);
4963
5017
  return;
4964
5018
  }
4965
- if (o !== this.setDataGeneration || (this.runStructuralOp(() => {
5019
+ if (o !== this.setDataGeneration) return;
5020
+ let p = this.api.blocks.isSyncingFromYjs;
5021
+ if (this.runStructuralOp(() => {
4966
5022
  var e, t, n, r;
4967
5023
  let i = (e = (t = (n = this.cellBlocks) == null ? void 0 : n.initializeCells((r = this.initialContent) == null ? [] : r)) == null ? this.initialContent : t) == null ? [] : e;
4968
5024
  if (o === this.setDataGeneration) {
@@ -4971,14 +5027,20 @@ var Ir = (e) => {
4971
5027
  let t = e.querySelectorAll(`[${F}]`).length;
4972
5028
  return Array.from({ length: t }, () => ({ blocks: [] }));
4973
5029
  });
4974
- this.model.replaceAll(A(A({}, this.model.snapshot()), {}, { content: e })), U(f, this.cellBlocks);
5030
+ this.model.replaceAll(A(A({}, this.model.snapshot()), {}, { content: e }));
4975
5031
  } else this.model.replaceAll(A(A({}, this.model.snapshot()), {}, { content: i }));
4976
5032
  this.initialContent = null;
4977
5033
  }
4978
- }, !0), o !== this.setDataGeneration)) return;
5034
+ }, !0), o !== this.setDataGeneration) return;
4979
5035
  this.initSubsystems(f), l !== null && this.cellSelection !== null && this.cellSelection.selectRange(l), u !== null && this.rowColControls !== null && this.rowColControls.restoreVisibleGrips(u.col, u.row);
4980
- let p = this.model.snapshot();
4981
- yi(f, p.content), bi(f, p.content);
5036
+ let m = this.model.snapshot();
5037
+ if (yi(f, m.content), bi(f, m.content), p) {
5038
+ var h;
5039
+ (h = this.cellBlocks) == null || h.reclaimReferencedBlocks(), Promise.resolve().then(() => {
5040
+ var e;
5041
+ o === this.setDataGeneration && ((e = this.cellBlocks) == null || e.reclaimReferencedBlocks());
5042
+ });
5043
+ }
4982
5044
  }
4983
5045
  onPaste(e) {
4984
5046
  var t, n;
@@ -6316,7 +6378,9 @@ var go = {
6316
6378
  caution: "red"
6317
6379
  }, _o = class {
6318
6380
  constructor({ data: e, api: t, readOnly: n, block: r }) {
6319
- this._dom = null, this._emojiPicker = null, this._colorPicker = null, this.api = t, this.readOnly = n, this._data = this.normalizeData(e), r && (this.blockId = r.id);
6381
+ this._dom = null, this._emojiPicker = null, this._colorPicker = null, this._pendingChildText = null, this.api = t, this.readOnly = n;
6382
+ let i = typeof e.__importedText == "string" ? e.__importedText : null;
6383
+ i !== null && i.length > 0 && (this._pendingChildText = i), this._data = this.normalizeData(e), r && (this.blockId = r.id);
6320
6384
  }
6321
6385
  normalizeData(e) {
6322
6386
  let t = e;
@@ -6353,8 +6417,10 @@ var go = {
6353
6417
  if (Rt(this._dom.childContainer, e), e.length === 0) {
6354
6418
  let e = this.api.blocks.getBlockIndex(this.blockId);
6355
6419
  if (e !== void 0) {
6356
- let t = this.api.blocks.insertInsideParent(this.blockId, e + 1);
6357
- this._dom.childContainer.appendChild(t.holder), this.api.caret.setToBlock(t.id, "start");
6420
+ let t = this._pendingChildText;
6421
+ this._pendingChildText = null;
6422
+ let n = t !== null && t.length > 0 ? { text: t } : void 0, r = this.api.blocks.insertInsideParent(this.blockId, e + 1, n);
6423
+ this._dom.childContainer.appendChild(r.holder), this.api.caret.setToBlock(r.id, t === null ? "start" : "end");
6358
6424
  }
6359
6425
  }
6360
6426
  }
@@ -6481,10 +6547,11 @@ var go = {
6481
6547
  };
6482
6548
  }
6483
6549
  static get conversionConfig() {
6484
- return { import: () => ({
6550
+ return { import: (e) => ({
6485
6551
  emoji: Wa,
6486
6552
  textColor: null,
6487
- backgroundColor: null
6553
+ backgroundColor: null,
6554
+ __importedText: e
6488
6555
  }) };
6489
6556
  }
6490
6557
  static get pasteConfig() {
package/dist/full.mjs CHANGED
@@ -1,7 +1,7 @@
1
- import { n as e, t } from "./chunks/blok-5Ez9qE7T.mjs";
2
- import { ur as n } from "./chunks/constants-BYv7qYbw.mjs";
1
+ import { n as e, t } from "./chunks/blok-Cb7w54t6.mjs";
2
+ import { ur as n } from "./chunks/constants-C0aZXxoO.mjs";
3
3
  import { t as r } from "./chunks/objectSpread2-CWwMYL_U.mjs";
4
- import { a as i, b as a, c as o, g as s, i as c, l, n as u, o as d, s as f, t as p, v as m, y as h } from "./chunks/tools-CqBnZUYU.mjs";
4
+ import { a as i, b as a, c as o, g as s, i as c, l, n as u, o as d, s as f, t as p, v as m, y as h } from "./chunks/tools-vS7102lG.mjs";
5
5
  //#region src/full.ts
6
6
  var g = {
7
7
  paragraph: {
package/dist/react.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { t as e } from "./chunks/blok-5Ez9qE7T.mjs";
2
- import "./chunks/constants-BYv7qYbw.mjs";
1
+ import { t as e } from "./chunks/blok-Cb7w54t6.mjs";
2
+ import "./chunks/constants-C0aZXxoO.mjs";
3
3
  import { t } from "./chunks/objectSpread2-CWwMYL_U.mjs";
4
4
  import { t as n } from "./chunks/objectWithoutProperties-Dci1-l7D.mjs";
5
5
  import { forwardRef as r, useEffect as i, useMemo as a, useRef as o, useState as s } from "react";
package/dist/tools.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { m as e } from "./chunks/constants-BYv7qYbw.mjs";
2
- import { _ as t, a as n, b as r, c as i, d as a, f as o, g as s, h as c, i as l, l as u, m as d, n as f, o as p, p as m, r as h, s as g, t as _, u as v, v as y, y as b } from "./chunks/tools-CqBnZUYU.mjs";
1
+ import { m as e } from "./chunks/constants-C0aZXxoO.mjs";
2
+ import { _ as t, a as n, b as r, c as i, d as a, f as o, g as s, h as c, i as l, l as u, m as d, n as f, o as p, p as m, r as h, s as g, t as _, u as v, v as y, y as b } from "./chunks/tools-vS7102lG.mjs";
3
3
  export { u as Bold, c as Callout, v as Code, e as Convert, d as Database, m as DatabaseRow, o as Divider, b as Header, h as InlineCode, i as Italic, g as Link, y as List, p as Marker, r as Paragraph, a as Quote, l as Strikethrough, t as Table, s as Toggle, n as Underline, _ as defaultBlockTools, f as defaultInlineTools };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jackuait/blok",
3
- "version": "0.10.10",
3
+ "version": "0.10.12",
4
4
  "description": "Blok — headless, highly extensible rich text editor built for developers who need to implement a block-based editing experience (similar to Notion) without building it from scratch",
5
5
  "module": "dist/blok.mjs",
6
6
  "types": "./types/index.d.ts",
@@ -436,11 +436,16 @@ export class BlocksAPI extends Module {
436
436
  * @param insertIndex - flat block index where the new block should appear
437
437
  * @returns BlockAPI for the newly created child block
438
438
  */
439
- private insertInsideParent = (parentId: string, insertIndex: number): BlockAPIInterface => {
440
- // Force new undo group so this insertion is separate from previous typing.
441
- this.Blok.YjsManager.stopCapturing();
439
+ private insertInsideParent = (parentId: string, insertIndex: number, childData?: BlockToolData): BlockAPIInterface => {
440
+ // Force new undo group so this insertion is separate from previous typing,
441
+ // UNLESS an enclosing atomic operation (e.g. tool conversion) has asked the
442
+ // block manager to suppress stopCapturing so everything merges into a
443
+ // single undo entry.
444
+ if (!this.Blok.BlockManager.suppressStopCapturing) {
445
+ this.Blok.YjsManager.stopCapturing();
446
+ }
442
447
 
443
- const newBlock = this.Blok.BlockManager.insertInsideParent(parentId, insertIndex);
448
+ const newBlock = this.Blok.BlockManager.insertInsideParent(parentId, insertIndex, childData);
444
449
 
445
450
  // NOTE: Do NOT call stopCapturing in a trailing microtask. The operations layer
446
451
  // uses extendThroughRAF on its atomic wrapper to keep isSyncingFromYjs true
@@ -56,6 +56,26 @@ export class KeyboardNavigation extends BlockEventComposer {
56
56
  return Boolean(currentBlock?.holder?.closest('[data-blok-table-cell-blocks]'));
57
57
  }
58
58
 
59
+ /**
60
+ * Resolve the table-cell-blocks container element that owns the given block,
61
+ * or null if the block is not inside a table cell.
62
+ */
63
+ private getTableCellContainer(block: Block | null | undefined): HTMLElement | null {
64
+ return block?.holder?.closest<HTMLElement>('[data-blok-table-cell-blocks]') ?? null;
65
+ }
66
+
67
+ /**
68
+ * True when `a` and `b` live inside the same table cell (same
69
+ * `[data-blok-table-cell-blocks]` container). Used to decide whether
70
+ * a Backspace/Delete merge would cross a cell boundary.
71
+ */
72
+ private areBlocksInSameTableCell(a: Block | null | undefined, b: Block | null | undefined): boolean {
73
+ const cellA = this.getTableCellContainer(a);
74
+ const cellB = this.getTableCellContainer(b);
75
+
76
+ return cellA !== null && cellA === cellB;
77
+ }
78
+
59
79
  /**
60
80
  * Fully close the toolbar if the current block is NOT inside a table cell.
61
81
  * Used for destructive operations (Backspace, Delete, merge) where the
@@ -363,10 +383,12 @@ export class KeyboardNavigation extends BlockEventComposer {
363
383
 
364
384
  /**
365
385
  * Don't merge across table cell boundaries.
366
- * When the caret is at the start of the first input in a table cell, Backspace should be a no-op
367
- * rather than merging the previous cell's last block into the current cell.
386
+ * When the caret is at the start of the FIRST block in a table cell, Backspace
387
+ * must be a no-op rather than merging the previous cell's last block into the
388
+ * current cell. Merges within the same cell (e.g. the user hit Enter to split a
389
+ * paragraph and now wants to undo it) must still work.
368
390
  */
369
- if (this.isCurrentBlockInsideTableCell) {
391
+ if (this.isCurrentBlockInsideTableCell && !this.areBlocksInSameTableCell(currentBlock, previousBlock)) {
370
392
  return;
371
393
  }
372
394
 
@@ -475,10 +497,11 @@ export class KeyboardNavigation extends BlockEventComposer {
475
497
 
476
498
  /**
477
499
  * Don't merge across table cell boundaries.
478
- * When the caret is at the end of the last input in a table cell, Delete should be a no-op
479
- * rather than merging the next cell's first block into the current cell.
500
+ * When the caret is at the end of the LAST block in a table cell, Delete must
501
+ * be a no-op rather than pulling the next cell's first block into the current
502
+ * cell. Merges within the same cell must still work.
480
503
  */
481
- if (this.isCurrentBlockInsideTableCell) {
504
+ if (this.isCurrentBlockInsideTableCell && !this.areBlocksInSameTableCell(currentBlock, nextBlock)) {
482
505
  return;
483
506
  }
484
507
 
@@ -799,13 +799,23 @@ export class BlockManager extends Module {
799
799
  * @param insertIndex - flat block index where the new block should appear
800
800
  * @returns the newly created child block
801
801
  */
802
- public insertInsideParent(parentId: string, insertIndex: number): Block {
802
+ public insertInsideParent(parentId: string, insertIndex: number, childData?: BlockToolData): Block {
803
803
  this._currentBlockIndex = this.operations.currentBlockIndexValue;
804
- const result = this.operations.insertInsideParent(parentId, insertIndex, this.blocksStore);
804
+ const result = this.operations.insertInsideParent(parentId, insertIndex, this.blocksStore, childData);
805
805
  this._currentBlockIndex = this.operations.currentBlockIndexValue;
806
806
  return result;
807
807
  }
808
808
 
809
+ /**
810
+ * True when an atomic operation (convert, split, drag, etc.) is in progress
811
+ * and callers should NOT break the current undo group with `stopCapturing()`.
812
+ * Consumed by api-layer wrappers like `insertInsideParent` that normally
813
+ * force a new undo entry.
814
+ */
815
+ public get suppressStopCapturing(): boolean {
816
+ return this.operations?.suppressStopCapturing ?? false;
817
+ }
818
+
809
819
  /**
810
820
  * Splits a block by updating the current block's data and inserting a new block.
811
821
  * Both operations are grouped into a single undo entry.