@jackuait/blok 0.10.11 → 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.11", 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-lxerM-Xa.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
@@ -2090,7 +2090,7 @@ var Qt = "outline-hidden py-[7px] mt-[2px] mb-px", $t = "outline-hidden pl-0.5 l
2090
2090
  constructor(e) {
2091
2091
  var t;
2092
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) => {
2093
- if (this.isStructuralOpActive()) {
2093
+ if (this.isStructuralOpActive() && !this.api.blocks.isSyncingFromYjs) {
2094
2094
  this.deferredEvents.push(e);
2095
2095
  return;
2096
2096
  }
@@ -2105,28 +2105,36 @@ var Qt = "outline-hidden py-[7px] mt-[2px] mb-px", $t = "outline-hidden pl-0.5 l
2105
2105
  return;
2106
2106
  }
2107
2107
  if (t !== "block-added" || n.target.id === this.tableBlockId) return;
2108
- let r = n.index;
2109
- if (r === void 0) return;
2110
- let i = this.findRemovedEntryForIndex(r);
2111
- if (i && this.isAdjacentToThisTable(r)) {
2112
- 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);
2113
2121
  return;
2114
2122
  }
2115
- let a = n.target.holder, o = a.closest(`[${z}]`);
2116
- o && this.stripPlaceholders(o);
2117
- let s = o && !this.model.findCellForBlock(n.target.id) ? o.closest(`[${F}]`) : null;
2118
- if (s && this.syncBlockToModel(s, n.target.id), o) return;
2119
- 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)) {
2120
2128
  let e = this.api.blocks.getBlockIndex(this.tableBlockId), t = e === void 0 ? null : this.api.blocks.getBlockByIndex(e);
2121
- if (t && !t.holder.contains(a)) return;
2122
- let i = this.api.blocks.getCurrentBlockIndex(), o = i >= 0 ? this.api.blocks.getBlockByIndex(i) : null;
2123
- if (!(o != null && this.getOwnedCellForBlock(o.id) !== null)) return;
2124
- 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);
2125
2133
  s && (this.claimBlockForCell(s, n.target.id), this.syncBlockToModel(s, n.target.id), this.cellsPendingCheck.delete(s));
2126
2134
  return;
2127
2135
  }
2128
- let c = this.findCellForNewBlock(r);
2129
- 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));
2130
2138
  }, this.handleCellBlankSpaceClick = (e) => {
2131
2139
  let t = e.target;
2132
2140
  if (!t) return;
@@ -2286,6 +2294,24 @@ var Qt = "outline-hidden py-[7px] mt-[2px] mb-px", $t = "outline-hidden pl-0.5 l
2286
2294
  }), n.push(a);
2287
2295
  }), n;
2288
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
+ }
2289
2315
  stripPlaceholders(e) {
2290
2316
  e.querySelectorAll("[data-blok-placeholder-active]").forEach((e) => {
2291
2317
  e.removeAttribute("data-blok-placeholder-active");
@@ -4943,15 +4969,27 @@ var Ir = (e) => {
4943
4969
  }
4944
4970
  save(e) {
4945
4971
  var t;
4946
- let n = this.model.snapshot(), r = (t = this.blockId) == null ? "" : t;
4947
- 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) => {
4948
4974
  if (!R(e)) return e;
4949
- let t = e.blocks.filter((e) => {
4975
+ let a = e.blocks.filter((e) => {
4950
4976
  var t, n, i;
4951
4977
  let a = (t = (n = this.api.blocks).getById) == null ? void 0 : t.call(n, e);
4952
4978
  return a != null && ((i = a.parentId) == null ? "" : i) === r;
4953
4979
  });
4954
- 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 });
4955
4993
  })), n;
4956
4994
  }
4957
4995
  validate(e) {
@@ -4978,7 +5016,9 @@ var Ir = (e) => {
4978
5016
  yi(f, e.content), bi(f, e.content);
4979
5017
  return;
4980
5018
  }
4981
- if (o !== this.setDataGeneration || (this.runStructuralOp(() => {
5019
+ if (o !== this.setDataGeneration) return;
5020
+ let p = this.api.blocks.isSyncingFromYjs;
5021
+ if (this.runStructuralOp(() => {
4982
5022
  var e, t, n, r;
4983
5023
  let i = (e = (t = (n = this.cellBlocks) == null ? void 0 : n.initializeCells((r = this.initialContent) == null ? [] : r)) == null ? this.initialContent : t) == null ? [] : e;
4984
5024
  if (o === this.setDataGeneration) {
@@ -4987,14 +5027,20 @@ var Ir = (e) => {
4987
5027
  let t = e.querySelectorAll(`[${F}]`).length;
4988
5028
  return Array.from({ length: t }, () => ({ blocks: [] }));
4989
5029
  });
4990
- 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 }));
4991
5031
  } else this.model.replaceAll(A(A({}, this.model.snapshot()), {}, { content: i }));
4992
5032
  this.initialContent = null;
4993
5033
  }
4994
- }, !0), o !== this.setDataGeneration)) return;
5034
+ }, !0), o !== this.setDataGeneration) return;
4995
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);
4996
- let p = this.model.snapshot();
4997
- 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
+ }
4998
5044
  }
4999
5045
  onPaste(e) {
5000
5046
  var t, n;
@@ -6332,7 +6378,9 @@ var go = {
6332
6378
  caution: "red"
6333
6379
  }, _o = class {
6334
6380
  constructor({ data: e, api: t, readOnly: n, block: r }) {
6335
- 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);
6336
6384
  }
6337
6385
  normalizeData(e) {
6338
6386
  let t = e;
@@ -6369,8 +6417,10 @@ var go = {
6369
6417
  if (Rt(this._dom.childContainer, e), e.length === 0) {
6370
6418
  let e = this.api.blocks.getBlockIndex(this.blockId);
6371
6419
  if (e !== void 0) {
6372
- let t = this.api.blocks.insertInsideParent(this.blockId, e + 1);
6373
- 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");
6374
6424
  }
6375
6425
  }
6376
6426
  }
@@ -6497,10 +6547,11 @@ var go = {
6497
6547
  };
6498
6548
  }
6499
6549
  static get conversionConfig() {
6500
- return { import: () => ({
6550
+ return { import: (e) => ({
6501
6551
  emoji: Wa,
6502
6552
  textColor: null,
6503
- backgroundColor: null
6553
+ backgroundColor: null,
6554
+ __importedText: e
6504
6555
  }) };
6505
6556
  }
6506
6557
  static get pasteConfig() {
package/dist/full.mjs CHANGED
@@ -1,7 +1,7 @@
1
- import { n as e, t } from "./chunks/blok-CX_pZ_qq.mjs";
2
- import { ur as n } from "./chunks/constants-lxerM-Xa.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-CMNxZqJC.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-CX_pZ_qq.mjs";
2
- import "./chunks/constants-lxerM-Xa.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-lxerM-Xa.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-CMNxZqJC.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.11",
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.