@panphora/clayjs 1.25.1 → 1.26.0

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.
Files changed (105) hide show
  1. package/dist/all.js +1 -1
  2. package/dist/clay-dom.js +1 -1
  3. package/dist/clay-events.js +1 -1
  4. package/dist/clay-internals.js +1 -1
  5. package/dist/clay-options.js +1 -1
  6. package/dist/clay-router.js +1 -1
  7. package/dist/clay-ui.js +1 -1
  8. package/dist/clay-utils.js +1 -1
  9. package/dist/clay.js +1 -1
  10. package/dist/clay.standalone.js +1141 -345
  11. package/dist/m/c-2EPHRF47.js +1 -0
  12. package/dist/m/{c-2GB34XL4.js → c-2SUFMUZX.js} +2 -2
  13. package/dist/m/{c-BHLYQGTA.js → c-3S3647J6.js} +1 -1
  14. package/dist/m/{c-QL4NYM2L.js → c-3S5TNRZA.js} +1 -1
  15. package/dist/m/{c-3Y234AUB.js → c-3XGLJAS7.js} +2 -2
  16. package/dist/m/{c-O4YIDULY.js → c-42WBOKFM.js} +1 -1
  17. package/dist/m/{c-42RLKGEY.js → c-4TP3UXBT.js} +1 -1
  18. package/dist/m/{c-ASGHHLFX.js → c-5ELELG2F.js} +1 -1
  19. package/dist/m/{c-T5IWJOMW.js → c-5ZYLTN3Q.js} +1 -1
  20. package/dist/m/{c-DDCYVLGG.js → c-67TBU56I.js} +1 -1
  21. package/dist/m/{c-WNOLMHI2.js → c-6BGJAJ67.js} +1 -1
  22. package/dist/m/{c-XS7G6U3Z.js → c-ABOBD7F3.js} +1 -1
  23. package/dist/m/{c-5IIEOPIV.js → c-ARO6CPMA.js} +1 -1
  24. package/dist/m/{c-XUZMRQ7O.js → c-BCS3AZQZ.js} +1 -1
  25. package/dist/m/c-BOS7GONO.js +1 -0
  26. package/dist/m/{c-NICICT4P.js → c-DEYHCYJB.js} +1 -1
  27. package/dist/m/{c-T7LOTEWO.js → c-DZT6W2NG.js} +1 -1
  28. package/dist/m/c-EHJWIGWN.js +1 -0
  29. package/dist/m/{c-V2V5FKXX.js → c-EIUKME3W.js} +1 -1
  30. package/dist/m/{c-ASMLERFA.js → c-EXZOA6XY.js} +1 -1
  31. package/dist/m/{c-STAPQ2X6.js → c-EYFMAR3M.js} +1 -1
  32. package/dist/m/{c-DVMDYRAE.js → c-FUN6AKFE.js} +1 -1
  33. package/dist/m/{c-XMIDHEKF.js → c-GY36NO7C.js} +1 -1
  34. package/dist/m/{c-TWB5ZQU4.js → c-H47C6PJZ.js} +1 -1
  35. package/dist/m/c-KD2ME5UN.js +2 -0
  36. package/dist/m/{c-GO635CRU.js → c-LAKBBJOU.js} +2 -2
  37. package/dist/m/{c-GNFDX6SU.js → c-LETPPG2F.js} +1 -1
  38. package/dist/m/{c-LS7IVQVW.js → c-MMV5JULA.js} +1 -1
  39. package/dist/m/{c-NEQRFC4O.js → c-MVVEIJUU.js} +1 -1
  40. package/dist/m/{c-XCOQNISP.js → c-N362HNGO.js} +1 -1
  41. package/dist/m/{c-7K4SCQB7.js → c-ND3W7D5U.js} +1 -1
  42. package/dist/m/{c-4NAYDOWH.js → c-NNHNXD6M.js} +1 -1
  43. package/dist/m/{c-DAUQ6JZ3.js → c-NYJ577NL.js} +1 -1
  44. package/dist/m/{c-3AAQJAKJ.js → c-PWILUN4T.js} +1 -1
  45. package/dist/m/{c-7Z2625LX.js → c-QA3Q3MDI.js} +1 -1
  46. package/dist/m/{c-2A2ATCIH.js → c-QKOKMQXA.js} +1 -1
  47. package/dist/m/{c-TGIMBAWE.js → c-RBWVF4N5.js} +1 -1
  48. package/dist/m/{c-A5IYL7JI.js → c-SPOEDIMP.js} +1 -1
  49. package/dist/m/{c-ZJ7726FO.js → c-SRW5OBCF.js} +1 -1
  50. package/dist/m/{c-A3OKSYRI.js → c-SYOA4T7V.js} +1 -1
  51. package/dist/m/{c-MHTO3QAD.js → c-TJ5PFOJ2.js} +1 -1
  52. package/dist/m/{c-NW4ZFKCY.js → c-TKV273YU.js} +1 -1
  53. package/dist/m/{c-D4N4UJCQ.js → c-UEKJWXCB.js} +2 -2
  54. package/dist/m/{c-44WITKWQ.js → c-V4DBV5ZV.js} +1 -1
  55. package/dist/m/c-WHMZCRQD.js +6 -0
  56. package/dist/m/{c-WMRJKQ2V.js → c-WHQUZM2V.js} +1 -1
  57. package/dist/m/{c-C27EVUQ6.js → c-XHD7XJTE.js} +1 -1
  58. package/dist/m/{c-PP3CUF3U.js → c-XONFK3WC.js} +1 -1
  59. package/dist/m/c-YYIN4NAF.js +30 -0
  60. package/dist/m/c-ZFAPQQIB.js +1 -0
  61. package/dist/m/core/{conflict-notice-Y2NTMDGJ.js → conflict-notice-UNDOD4BL.js} +1 -1
  62. package/dist/m/core/site-edits-C22O53GS.js +1 -0
  63. package/dist/m/loader-DCKCZKY6.js +1 -0
  64. package/dist/m/{manifest-A27A4278.js → manifest-7954CBE3.js} +1 -1
  65. package/dist/m/{manifest-edit-E8A61EB4.js → manifest-edit-93AA79D7.js} +1 -1
  66. package/dist/m/manifest.json +442 -441
  67. package/dist/m/page/{editor-HS2CAV3W.js → editor-UF3CIA6V.js} +2 -2
  68. package/dist/m/plugins/{cms-4KET6RZT.js → cms-KG6TCTR3.js} +1 -1
  69. package/dist/m/plugins/{live-CO4VJS46.js → live-DF5YS5AH.js} +1 -1
  70. package/dist/m/plugins/page-GZSU77JS.js +2 -0
  71. package/dist/m/plugins/{page-view-6KNTXABH.js → page-view-7MM3FEAR.js} +1 -1
  72. package/dist/m/plugins/{quickcrop-VNRXGRPC.js → quickcrop-UHURKA2F.js} +2 -2
  73. package/dist/m/plugins/richclay-MXH2GFAZ.js +549 -0
  74. package/dist/m/plugins/undo-KLHAGV75.js +1 -0
  75. package/dist/m/sync/{live-sync-DX4K5GDB.js → live-sync-RZQSDMZW.js} +1 -1
  76. package/dist/offline-manifest.json +360 -360
  77. package/package.json +1 -1
  78. package/src/core/site-edits.js +1 -1
  79. package/src/loader-logic.js +0 -13
  80. package/src/page/boot-pack.js +1 -0
  81. package/src/page/history-intent.js +111 -4
  82. package/src/page/ybind/bridge.js +14 -7
  83. package/src/page/ybind/moves.js +437 -3
  84. package/src/page/ybind/origins.js +1 -1
  85. package/src/page/ybind/recovery.js +1 -1
  86. package/src/plugins/page.js +48 -4
  87. package/src/plugins/richclay.js +136 -0
  88. package/src/plugins/undo.js +169 -7
  89. package/src/recovery/undo.js +14 -7
  90. package/src/sync/live-sync.js +24 -0
  91. package/src/ui/vendor-skin.js +9 -4
  92. package/dist/m/c-3XNTQQEJ.js +0 -1
  93. package/dist/m/c-4OZZ7ENT.js +0 -30
  94. package/dist/m/c-D2OPWOWO.js +0 -2
  95. package/dist/m/c-LUBZU4AZ.js +0 -6
  96. package/dist/m/c-LYNLY3MR.js +0 -1
  97. package/dist/m/c-MLMJUNRV.js +0 -1
  98. package/dist/m/c-V5L6HWVL.js +0 -1
  99. package/dist/m/core/site-edits-TIJDPG6H.js +0 -1
  100. package/dist/m/loader-7ORQVRCK.js +0 -1
  101. package/dist/m/plugins/page-L3VKIQU2.js +0 -2
  102. package/dist/m/plugins/richclay-V6WKJTUF.js +0 -549
  103. package/dist/m/plugins/undo-WUK2NLBA.js +0 -1
  104. /package/dist/m/plugins/{quickcrop-VNRXGRPC.js.LEGAL.txt → quickcrop-UHURKA2F.js.LEGAL.txt} +0 -0
  105. /package/dist/m/plugins/{richclay-V6WKJTUF.js.LEGAL.txt → richclay-MXH2GFAZ.js.LEGAL.txt} +0 -0
@@ -1,4 +1,4 @@
1
- /* clayjs 1.25.1 standalone build: every clayjs module in one file. https://clayjs.com/offline
1
+ /* clayjs 1.26.0 standalone build: every clayjs module in one file. https://clayjs.com/offline
2
2
  Third-party code inside keeps its own license (Sortable MIT, Squire MIT, DOMPurify Apache-2.0 OR MPL-2.0, MicroModal MIT, parse5 MIT, Highlights from Pierre Apache-2.0): https://clayjs.com/THIRD-PARTY-NOTICES.md */
3
3
  (() => {
4
4
  var __create = Object.create;
@@ -884,10 +884,10 @@
884
884
  extension: a2.extension || b7.extension
885
885
  };
886
886
  }
887
- function skipForPolicy(policy, require2, skip) {
887
+ function skipForPolicy(policy, require2, skip2) {
888
888
  if (policy.extension) return true;
889
- if (skip && skip.length) {
890
- return skip.some((tok) => SKIP_TOKEN_PREDICATES[tok]?.(policy) || false);
889
+ if (skip2 && skip2.length) {
890
+ return skip2.some((tok) => SKIP_TOKEN_PREDICATES[tok]?.(policy) || false);
891
891
  }
892
892
  switch (require2) {
893
893
  case "observed":
@@ -1465,13 +1465,13 @@
1465
1465
  this._log(`Notifying ${this._callbacks[type].length} callbacks of type "${type}"`, { changes: changes2 });
1466
1466
  for (const callback of this._callbacks[type]) {
1467
1467
  if (onlyNonPausable && callback.pausable !== false) continue;
1468
- const { fn: fn7, debounce: debounce2 = 0, maxWait = 0, selectorFilter, omitChangeDetails, require: require2, skip } = callback;
1468
+ const { fn: fn7, debounce: debounce2 = 0, maxWait = 0, selectorFilter, omitChangeDetails, require: require2, skip: skip2 } = callback;
1469
1469
  let filteredChanges = changes2.filter(
1470
1470
  (change) => {
1471
1471
  if (require2 !== "observed" && isDerivedChange(change)) return false;
1472
- const currentSkipped = skipForPolicy(this._policyForChange(change), require2, skip);
1472
+ const currentSkipped = skipForPolicy(this._policyForChange(change), require2, skip2);
1473
1473
  if (!change.policyTransition) return !currentSkipped;
1474
- const previousSkipped = skipForPolicy(change.previousPolicy, require2, skip);
1474
+ const previousSkipped = skipForPolicy(change.previousPolicy, require2, skip2);
1475
1475
  return !(currentSkipped && previousSkipped);
1476
1476
  }
1477
1477
  );
@@ -2973,14 +2973,14 @@
2973
2973
  cancelled = () => Object.assign(new Error("clay.modeLifecycle: the import was cancelled"), { name: "AbortError", code: "aborted" });
2974
2974
  DEADLINE_MS = 15e3;
2975
2975
  fault = (message2, code) => Object.assign(new Error(`clayjs: ${message2}`), { code });
2976
- within = (promise, signal) => new Promise((resolve2, reject) => {
2976
+ within = (promise, signal) => new Promise((resolve3, reject) => {
2977
2977
  if (signal?.aborted) return reject(cancelled());
2978
2978
  const abort = () => reject(cancelled());
2979
2979
  signal?.addEventListener?.("abort", abort);
2980
2980
  Promise.resolve(promise).then(
2981
2981
  (value) => {
2982
2982
  signal?.removeEventListener?.("abort", abort);
2983
- resolve2(value);
2983
+ resolve3(value);
2984
2984
  },
2985
2985
  (err) => {
2986
2986
  signal?.removeEventListener?.("abort", abort);
@@ -3019,16 +3019,16 @@
3019
3019
  const ctx = this;
3020
3020
  const now3 = Date.now();
3021
3021
  const remaining = delay - (now3 - lastCall);
3022
- return new Promise((resolve2, reject) => {
3022
+ return new Promise((resolve3, reject) => {
3023
3023
  if (remaining <= 0) {
3024
3024
  clearTimeout(timeoutId);
3025
3025
  timeoutId = null;
3026
3026
  lastCall = now3;
3027
- const waiting = pending8.concat({ resolve: resolve2, reject });
3027
+ const waiting = pending8.concat({ resolve: resolve3, reject });
3028
3028
  pending8 = [];
3029
3029
  settle9(ctx, args, waiting);
3030
3030
  } else {
3031
- pending8.push({ resolve: resolve2, reject });
3031
+ pending8.push({ resolve: resolve3, reject });
3032
3032
  if (!timeoutId) {
3033
3033
  timeoutId = setTimeout(() => {
3034
3034
  lastCall = Date.now();
@@ -10385,7 +10385,7 @@
10385
10385
  if (err.code === "blockeditor-converting" && convertingRetries < PAGE_CONVERTING_MAX_RETRIES) {
10386
10386
  if (currentCaptureId() !== retryGuard) throw err;
10387
10387
  convertingRetries += 1;
10388
- await new Promise((resolve2) => setTimeout(resolve2, Math.max(0, err.retryAfter ?? 1) * 1e3));
10388
+ await new Promise((resolve3) => setTimeout(resolve3, Math.max(0, err.retryAfter ?? 1) * 1e3));
10389
10389
  if (currentCaptureId() !== retryGuard) throw err;
10390
10390
  continue;
10391
10391
  }
@@ -10395,7 +10395,7 @@
10395
10395
  }
10396
10396
  function runSave(html, captureId, callback, conversion, capture = null, blockeditorFormatFloor2 = 0, lane = null, gateToken = null) {
10397
10397
  html = withPageFormatFloor(html, Math.max(knownPageFormatFloor(), blockeditorFormatFloor2));
10398
- return new Promise((resolve2) => {
10398
+ return new Promise((resolve3) => {
10399
10399
  const attempts = [];
10400
10400
  const artifact = captureArtifact(capture);
10401
10401
  const holdsLane = () => lane !== null && laneHolder === lane;
@@ -10412,7 +10412,7 @@
10412
10412
  sent: attempts.length > 0
10413
10413
  });
10414
10414
  if (typeof callback === "function") callback(result2);
10415
- resolve2(result2);
10415
+ resolve3(result2);
10416
10416
  };
10417
10417
  if (!isEditMode && !window.clay?.testMode) {
10418
10418
  return finished(skippedResult("Not in edit mode"));
@@ -10460,12 +10460,12 @@
10460
10460
  }
10461
10461
  function replacePageWith(url, callback = () => {
10462
10462
  }) {
10463
- return new Promise((resolve2) => {
10463
+ return new Promise((resolve3) => {
10464
10464
  let operation = null;
10465
10465
  const done = (result2) => {
10466
10466
  releaseDocumentOperation(operation);
10467
10467
  if (typeof callback === "function") callback(result2);
10468
- resolve2(result2);
10468
+ resolve3(result2);
10469
10469
  };
10470
10470
  if (!isEditMode) return done(skippedResult("Not in edit mode"));
10471
10471
  if (operationKind()) return done(skippedResult("Another document operation is in progress"));
@@ -11320,20 +11320,20 @@
11320
11320
  return JSON.stringify(slot3);
11321
11321
  }
11322
11322
  function request(req) {
11323
- return new Promise((resolve2, reject) => {
11324
- req.onsuccess = () => resolve2(req.result);
11323
+ return new Promise((resolve3, reject) => {
11324
+ req.onsuccess = () => resolve3(req.result);
11325
11325
  req.onerror = () => reject(req.error);
11326
11326
  });
11327
11327
  }
11328
11328
  function cursorAll(source3, key3) {
11329
- return new Promise((resolve2, reject) => {
11329
+ return new Promise((resolve3, reject) => {
11330
11330
  const req = key3 === void 0 ? source3.openCursor() : source3.openCursor(key3);
11331
11331
  const out = [];
11332
11332
  req.onerror = () => reject(req.error);
11333
11333
  req.onsuccess = () => {
11334
11334
  const cursor = req.result;
11335
11335
  if (!cursor) {
11336
- resolve2(out);
11336
+ resolve3(out);
11337
11337
  return;
11338
11338
  }
11339
11339
  out.push(cursor.value);
@@ -11354,16 +11354,16 @@
11354
11354
  }
11355
11355
  }
11356
11356
  function openDatabase(factory = globalThis.indexedDB, { name = DB_NAME, version = DB_VERSION } = {}) {
11357
- return new Promise((resolve2) => {
11357
+ return new Promise((resolve3) => {
11358
11358
  if (!factory || typeof factory.open !== "function") {
11359
- resolve2({ ok: false, code: "unavailable" });
11359
+ resolve3({ ok: false, code: "unavailable" });
11360
11360
  return;
11361
11361
  }
11362
11362
  let req;
11363
11363
  try {
11364
11364
  req = factory.open(name, version);
11365
11365
  } catch (err) {
11366
- resolve2({ ok: false, code: codeFor(err) });
11366
+ resolve3({ ok: false, code: codeFor(err) });
11367
11367
  return;
11368
11368
  }
11369
11369
  let settled3 = false;
@@ -11371,7 +11371,7 @@
11371
11371
  if (settled3) return;
11372
11372
  settled3 = true;
11373
11373
  clearTimeout(timer);
11374
- resolve2(answer);
11374
+ resolve3(answer);
11375
11375
  };
11376
11376
  const timer = setTimeout(() => finish3({ ok: false, code: "blocked" }), OPEN_TIMEOUT_MS);
11377
11377
  req.onupgradeneeded = () => upgrade(req.result);
@@ -11448,16 +11448,16 @@
11448
11448
  return Array.isArray(id2) ? [...scope, ...id2] : id2;
11449
11449
  }
11450
11450
  function runWrite(body3) {
11451
- return new Promise((resolve2) => {
11451
+ return new Promise((resolve3) => {
11452
11452
  if (!db) {
11453
- resolve2({ ok: false, code: openAnswer?.code || "unavailable" });
11453
+ resolve3({ ok: false, code: openAnswer?.code || "unavailable" });
11454
11454
  return;
11455
11455
  }
11456
11456
  let tx;
11457
11457
  try {
11458
11458
  tx = db.transaction([RECORDS, WATERMARKS, META], "readwrite");
11459
11459
  } catch (err) {
11460
- resolve2({ ok: false, code: codeFor(err) });
11460
+ resolve3({ ok: false, code: codeFor(err) });
11461
11461
  return;
11462
11462
  }
11463
11463
  const wasUsage = { ...usage };
@@ -11467,7 +11467,7 @@
11467
11467
  const finish3 = (answer) => {
11468
11468
  if (settled3) return;
11469
11469
  settled3 = true;
11470
- resolve2(answer);
11470
+ resolve3(answer);
11471
11471
  };
11472
11472
  const abort = (code) => {
11473
11473
  if (!failure2) failure2 = code;
@@ -13239,16 +13239,16 @@
13239
13239
  var viaTimer, viaChannel, defaultYieldTask, monotonic;
13240
13240
  var init_slice = __esm({
13241
13241
  "src/lib/slice.js"() {
13242
- viaTimer = () => new Promise((resolve2) => setTimeout(resolve2, 0));
13243
- viaChannel = () => new Promise((resolve2) => {
13242
+ viaTimer = () => new Promise((resolve3) => setTimeout(resolve3, 0));
13243
+ viaChannel = () => new Promise((resolve3) => {
13244
13244
  if (typeof MessageChannel !== "function") {
13245
- viaTimer().then(resolve2);
13245
+ viaTimer().then(resolve3);
13246
13246
  return;
13247
13247
  }
13248
13248
  const channel3 = new MessageChannel();
13249
13249
  channel3.port1.onmessage = () => {
13250
13250
  channel3.port1.close();
13251
- resolve2();
13251
+ resolve3();
13252
13252
  };
13253
13253
  channel3.port2.postMessage(null);
13254
13254
  });
@@ -13795,13 +13795,13 @@
13795
13795
  if (previewHold === 0) return null;
13796
13796
  return holdReasons.keys().next().value || PREVIEW_HOLD_REASON;
13797
13797
  }
13798
- function heldForPreview(callback, resolve2) {
13798
+ function heldForPreview(callback, resolve3) {
13799
13799
  if (previewHold === 0) return false;
13800
13800
  previewMissed = true;
13801
13801
  clearExplicitSave();
13802
13802
  const skipped = skipped_(saveHoldReason());
13803
13803
  callback(skipped);
13804
- resolve2(skipped);
13804
+ resolve3(skipped);
13805
13805
  return skipped;
13806
13806
  }
13807
13807
  function holdForConflict(etag) {
@@ -14009,12 +14009,12 @@
14009
14009
  return null;
14010
14010
  }
14011
14011
  function mergeSettled(quietMs = 150, maxMs = 2e3) {
14012
- return new Promise((resolve2) => {
14012
+ return new Promise((resolve3) => {
14013
14013
  const started5 = monotonic3();
14014
14014
  let timer = null;
14015
14015
  const done = () => {
14016
14016
  document.removeEventListener("clay:sync-applied", bump);
14017
- resolve2();
14017
+ resolve3();
14018
14018
  };
14019
14019
  const bump = () => {
14020
14020
  clearTimeout(timer);
@@ -14089,7 +14089,7 @@
14089
14089
  const comparison = { forComparison, forDirty };
14090
14090
  inFlightComparisons.add(comparison);
14091
14091
  ownSaveOnWire = true;
14092
- return new Promise((resolve2) => {
14092
+ return new Promise((resolve3) => {
14093
14093
  saveCapturedHtml(forSave, captureId, (result2) => {
14094
14094
  ownSaveOnWire = false;
14095
14095
  inFlightComparisons.delete(comparison);
@@ -14097,7 +14097,7 @@
14097
14097
  applySaveResult(result2, comparison.forComparison, comparison.forDirty, forced2 ? "updated after force save" : "updated after save", gateToken, forSave, captureId, quietConflict);
14098
14098
  if (!explicit) autosaveScheduler.noteCost(costMs + (monotonic3() - completedAt));
14099
14099
  if (typeof callback === "function") callback(result2);
14100
- resolve2({ result: result2, dispatched: true });
14100
+ resolve3({ result: result2, dispatched: true });
14101
14101
  if (!laneHeld) drainPendingSave();
14102
14102
  }, { capture, blockeditorFormatFloor: blockeditorFormatFloor2, lane, gateToken });
14103
14103
  });
@@ -14230,20 +14230,20 @@
14230
14230
  function attemptSaveNow({ kind: kind2, permit = null }, callback = () => {
14231
14231
  }) {
14232
14232
  const explicit = kind2 === "explicit";
14233
- return new Promise((resolve2) => {
14233
+ return new Promise((resolve3) => {
14234
14234
  if (!isEditMode && !window.clay?.testMode) {
14235
14235
  if (explicit) clearExplicitSave();
14236
14236
  const skipped = skipped_("Not in edit mode");
14237
14237
  takeSoonQueued().forEach((done) => done(skipped));
14238
14238
  callback(skipped);
14239
- return resolve2(skipped);
14239
+ return resolve3(skipped);
14240
14240
  }
14241
14241
  if (!savesAdmitted(permit)) {
14242
14242
  parkedAutosave = true;
14243
14243
  const skipped = sessionClosed("Save session is quiesced");
14244
14244
  if (explicit) takeSoonQueued().forEach((done) => done(skipped));
14245
14245
  callback(skipped);
14246
- return resolve2(skipped);
14246
+ return resolve3(skipped);
14247
14247
  }
14248
14248
  if (refusesSave()) {
14249
14249
  if (explicit) clearExplicitSave();
@@ -14251,10 +14251,10 @@
14251
14251
  setSaveState("error", refused5.msg, "", { code: refused5.code, status: refused5.status, sent: false });
14252
14252
  takeSoonQueued().forEach((done) => done(refused5));
14253
14253
  callback(refused5);
14254
- return resolve2(refused5);
14254
+ return resolve3(refused5);
14255
14255
  }
14256
14256
  if (explicit) {
14257
- const held = heldForPreview(callback, resolve2);
14257
+ const held = heldForPreview(callback, resolve3);
14258
14258
  if (held) {
14259
14259
  takeSoonQueued().forEach((done) => done(held));
14260
14260
  return;
@@ -14263,37 +14263,37 @@
14263
14263
  pendingSave = true;
14264
14264
  const skipped = skipped_("Save already in progress");
14265
14265
  callback(skipped);
14266
- return resolve2(skipped);
14266
+ return resolve3(skipped);
14267
14267
  }
14268
14268
  } else {
14269
14269
  if (previewHold > 0) {
14270
14270
  previewAutosaveMissed = true;
14271
14271
  const skipped = skipped_(saveHoldReason());
14272
14272
  callback(skipped);
14273
- return resolve2(skipped);
14273
+ return resolve3(skipped);
14274
14274
  }
14275
14275
  if (isSaveInProgress() && !baselineActive && ownSaveOnWire) {
14276
14276
  pendingAutosave = true;
14277
14277
  const skipped = skipped_("Save already in progress");
14278
14278
  callback(skipped);
14279
- return resolve2(skipped);
14279
+ return resolve3(skipped);
14280
14280
  }
14281
14281
  if (preparing) {
14282
14282
  pendingAutosave = true;
14283
14283
  const skipped = skipped_("Save already in progress");
14284
14284
  callback(skipped);
14285
- return resolve2(skipped);
14285
+ return resolve3(skipped);
14286
14286
  }
14287
14287
  if (!baselineActive && !pageMaybeDirty()) {
14288
14288
  const skipped = skipped_("No changes to save");
14289
14289
  callback(skipped);
14290
- return resolve2(skipped);
14290
+ return resolve3(skipped);
14291
14291
  }
14292
14292
  }
14293
14293
  const prepare2 = window.clay?.source?.ensureForSave?.();
14294
- if (prepare2) return resolve2(afterWait(prepare2, () => attemptSaveNow({ kind: kind2, permit }, callback)));
14294
+ if (prepare2) return resolve3(afterWait(prepare2, () => attemptSaveNow({ kind: kind2, permit }, callback)));
14295
14295
  if (preparesSliced() && !prepDriver) {
14296
- resolve2(afterWait(loadPreparer(), () => attemptSaveNow({ kind: kind2, permit }, callback)));
14296
+ resolve3(afterWait(loadPreparer(), () => attemptSaveNow({ kind: kind2, permit }, callback)));
14297
14297
  return;
14298
14298
  }
14299
14299
  const soonQueued = explicit ? takeSoonQueued() : [];
@@ -14311,7 +14311,7 @@
14311
14311
  quietConflict: false,
14312
14312
  settleSoonQueued,
14313
14313
  callback,
14314
- resolve: resolve2
14314
+ resolve: resolve3
14315
14315
  })) return;
14316
14316
  }
14317
14317
  const startedAt = monotonic3();
@@ -14332,7 +14332,7 @@
14332
14332
  if (typeof callback === "function") {
14333
14333
  callback(result2);
14334
14334
  }
14335
- resolve2(result2);
14335
+ resolve3(result2);
14336
14336
  settleSoonQueued(result2);
14337
14337
  return;
14338
14338
  }
@@ -14350,7 +14350,7 @@
14350
14350
  release: () => releaseCaptureArtifact(capture),
14351
14351
  callback
14352
14352
  }).then((outcome2) => {
14353
- resolve2(outcome2.result);
14353
+ resolve3(outcome2.result);
14354
14354
  settleSoonQueued(outcome2.result);
14355
14355
  });
14356
14356
  });
@@ -14366,27 +14366,27 @@
14366
14366
  function savePageForce(callback = () => {
14367
14367
  }, { quietConflict = false, blockeditorFormatFloor: blockeditorFormatFloor2 = 0, permit = null } = {}) {
14368
14368
  if (capabilityPending) return capabilityKnown.then(() => savePageForce(callback, { quietConflict, blockeditorFormatFloor: blockeditorFormatFloor2, permit }));
14369
- return new Promise((resolve2) => {
14369
+ return new Promise((resolve3) => {
14370
14370
  if (!isEditMode && !window.clay?.testMode) {
14371
14371
  const skipped = skipped_("Not in edit mode");
14372
14372
  takeSoonQueued().forEach((done) => done(skipped));
14373
14373
  callback(skipped);
14374
- return resolve2(skipped);
14374
+ return resolve3(skipped);
14375
14375
  }
14376
14376
  if (!savesAdmitted(permit) || permit && !permitHolds(permit)) {
14377
14377
  const skipped = sessionClosed("Save session is quiesced");
14378
14378
  takeSoonQueued().forEach((done) => done(skipped));
14379
14379
  callback(skipped);
14380
- return resolve2(skipped);
14380
+ return resolve3(skipped);
14381
14381
  }
14382
14382
  if (refusesSave()) {
14383
14383
  const refused5 = forbidden_();
14384
14384
  setSaveState("error", refused5.msg, "", { code: refused5.code, status: refused5.status, sent: false });
14385
14385
  takeSoonQueued().forEach((done) => done(refused5));
14386
14386
  callback(refused5);
14387
- return resolve2(refused5);
14387
+ return resolve3(refused5);
14388
14388
  }
14389
- const held = heldForPreview(callback, resolve2);
14389
+ const held = heldForPreview(callback, resolve3);
14390
14390
  if (held) {
14391
14391
  takeSoonQueued().forEach((done) => done(held));
14392
14392
  return;
@@ -14396,16 +14396,16 @@
14396
14396
  const skipped = skipped_("Save already in progress");
14397
14397
  takeSoonQueued().forEach((done) => done(skipped));
14398
14398
  callback(skipped);
14399
- return resolve2(skipped);
14399
+ return resolve3(skipped);
14400
14400
  }
14401
14401
  const prepare2 = window.clay?.source?.ensureForSave?.();
14402
- if (prepare2) return resolve2(afterWait(prepare2, () => savePageForce(callback, { quietConflict, blockeditorFormatFloor: blockeditorFormatFloor2, permit })));
14402
+ if (prepare2) return resolve3(afterWait(prepare2, () => savePageForce(callback, { quietConflict, blockeditorFormatFloor: blockeditorFormatFloor2, permit })));
14403
14403
  const wasOffline = !navigator.onLine;
14404
14404
  if (wasOffline) {
14405
14405
  setOfflineStateQuiet();
14406
14406
  }
14407
14407
  if (preparesSliced() && !prepDriver) {
14408
- resolve2(afterWait(loadPreparer(), () => savePageForce(callback, { quietConflict, blockeditorFormatFloor: blockeditorFormatFloor2, permit })));
14408
+ resolve3(afterWait(loadPreparer(), () => savePageForce(callback, { quietConflict, blockeditorFormatFloor: blockeditorFormatFloor2, permit })));
14409
14409
  return;
14410
14410
  }
14411
14411
  const soonQueued = takeSoonQueued();
@@ -14419,7 +14419,7 @@
14419
14419
  quietConflict,
14420
14420
  settleSoonQueued,
14421
14421
  callback,
14422
- resolve: resolve2
14422
+ resolve: resolve3
14423
14423
  })) return;
14424
14424
  }
14425
14425
  let capture, forSave, forComparison, forDirty, captureId;
@@ -14434,7 +14434,7 @@
14434
14434
  if (typeof callback === "function") {
14435
14435
  callback(result2);
14436
14436
  }
14437
- resolve2(result2);
14437
+ resolve3(result2);
14438
14438
  settleSoonQueued(result2);
14439
14439
  return;
14440
14440
  }
@@ -14454,14 +14454,14 @@
14454
14454
  release: () => releaseCaptureArtifact(capture),
14455
14455
  callback
14456
14456
  }).then((outcome2) => {
14457
- resolve2(outcome2.result);
14457
+ resolve3(outcome2.result);
14458
14458
  settleSoonQueued(outcome2.result);
14459
14459
  });
14460
14460
  });
14461
14461
  }
14462
14462
  function settled(deadline) {
14463
14463
  const events = ["clay:save-saved", "clay:save-error", "clay:save-offline", "clay:save-conflict"];
14464
- return new Promise((resolve2, reject) => {
14464
+ return new Promise((resolve3, reject) => {
14465
14465
  let timer = null;
14466
14466
  const cleanup = () => {
14467
14467
  clearTimeout(timer);
@@ -14469,7 +14469,7 @@
14469
14469
  };
14470
14470
  const onSettle = () => {
14471
14471
  cleanup();
14472
- resolve2();
14472
+ resolve3();
14473
14473
  };
14474
14474
  const remaining = deadline - Date.now();
14475
14475
  if (remaining <= 0) {
@@ -14487,7 +14487,7 @@
14487
14487
  return Object.assign(new Error(message2), { state: state2 });
14488
14488
  }
14489
14489
  function nextEvent(name, deadline) {
14490
- return new Promise((resolve2, reject) => {
14490
+ return new Promise((resolve3, reject) => {
14491
14491
  const remaining = deadline - Date.now();
14492
14492
  if (remaining <= 0) return reject(flushError("Save timed out.", "failed"));
14493
14493
  const timer = setTimeout(() => {
@@ -14496,7 +14496,7 @@
14496
14496
  }, remaining);
14497
14497
  const onEvent = () => {
14498
14498
  clearTimeout(timer);
14499
- resolve2();
14499
+ resolve3();
14500
14500
  };
14501
14501
  document.addEventListener(name, onEvent, { once: true });
14502
14502
  });
@@ -14590,8 +14590,8 @@
14590
14590
  const now3 = Date.now();
14591
14591
  if (soonTimer === null) soonStarted = now3;
14592
14592
  else clearTimeout(soonTimer);
14593
- return new Promise((resolve2) => {
14594
- soonWaiters.push(resolve2);
14593
+ return new Promise((resolve3) => {
14594
+ soonWaiters.push(resolve3);
14595
14595
  soonTimer = setTimeout(fireSoon, Math.max(0, Math.min(SOON_MS, soonStarted + SOON_MAX_MS - now3)));
14596
14596
  });
14597
14597
  }
@@ -15017,8 +15017,8 @@
15017
15017
  });
15018
15018
  async function bounded(pending8, deadline) {
15019
15019
  let timer = null;
15020
- const expired = new Promise((resolve2) => {
15021
- timer = setTimeout(() => resolve2(EXPIRED), Math.max(0, deadline - Date.now()));
15020
+ const expired = new Promise((resolve3) => {
15021
+ timer = setTimeout(() => resolve3(EXPIRED), Math.max(0, deadline - Date.now()));
15022
15022
  });
15023
15023
  try {
15024
15024
  return await Promise.race([Promise.resolve(pending8), expired]);
@@ -15241,10 +15241,10 @@
15241
15241
  }
15242
15242
  })();
15243
15243
  let timer = null;
15244
- const deadline = new Promise((resolve2) => {
15244
+ const deadline = new Promise((resolve3) => {
15245
15245
  timer = setTimeout(() => {
15246
15246
  controller2.abort();
15247
- resolve2(false);
15247
+ resolve3(false);
15248
15248
  }, DEADLINE_MS3);
15249
15249
  });
15250
15250
  let ready11;
@@ -15334,8 +15334,8 @@
15334
15334
  function startDeadline() {
15335
15335
  let timer = null;
15336
15336
  const at8 = Date.now() + DEADLINE_MS3;
15337
- const expired = new Promise((resolve2) => {
15338
- timer = setTimeout(() => resolve2(EXPIRED2), DEADLINE_MS3);
15337
+ const expired = new Promise((resolve3) => {
15338
+ timer = setTimeout(() => resolve3(EXPIRED2), DEADLINE_MS3);
15339
15339
  });
15340
15340
  return { expired, remaining: () => Math.max(0, at8 - Date.now()), clear: () => clearTimeout(timer) };
15341
15341
  }
@@ -16043,10 +16043,10 @@
16043
16043
  const onApplied = (event) => {
16044
16044
  seen.push(event.detail);
16045
16045
  if (!resolvePending || !matchesPending(event.detail)) return;
16046
- const resolve2 = resolvePending;
16046
+ const resolve3 = resolvePending;
16047
16047
  resolvePending = null;
16048
16048
  cleanup();
16049
- resolve2(true);
16049
+ resolve3(true);
16050
16050
  };
16051
16051
  eventTarget.addEventListener("clay:sync-applied", onApplied);
16052
16052
  return {
@@ -16056,12 +16056,12 @@
16056
16056
  cleanup();
16057
16057
  return Promise.resolve(true);
16058
16058
  }
16059
- return new Promise((resolve2) => {
16060
- resolvePending = resolve2;
16059
+ return new Promise((resolve3) => {
16060
+ resolvePending = resolve3;
16061
16061
  timer = setTimeout(() => {
16062
16062
  resolvePending = null;
16063
16063
  cleanup();
16064
- resolve2(false);
16064
+ resolve3(false);
16065
16065
  }, timeoutMs);
16066
16066
  });
16067
16067
  },
@@ -16146,7 +16146,7 @@
16146
16146
  }
16147
16147
  async function waitForBaseline(modules) {
16148
16148
  if (modules.baselineSettled()) return;
16149
- await new Promise((resolve2) => eventTarget.addEventListener("clay:baseline-settled", resolve2, { once: true }));
16149
+ await new Promise((resolve3) => eventTarget.addEventListener("clay:baseline-settled", resolve3, { once: true }));
16150
16150
  }
16151
16151
  async function writeData2(values, { rules, ifMatch } = {}) {
16152
16152
  const draft = await draftRefusal();
@@ -17956,7 +17956,7 @@
17956
17956
  const applied = [];
17957
17957
  for (const [key3, value] of Object.entries(current5)) {
17958
17958
  if (refused5.has(key3) || !rule || !Object.hasOwn(rule, key3) || live3[key3] !== sent[key3]) continue;
17959
- const fields = new Map([...root4.querySelectorAll("[editable]")].map((field) => [field, field.innerHTML]));
17959
+ const fields = new Map([...root4.querySelectorAll("[data-richclay], [richclay], [editable], [clay-editable]")].map((field) => [field, field.innerHTML]));
17960
17960
  mutation_default.pause();
17961
17961
  try {
17962
17962
  engine.applyData(root4, { site: { [key3]: value } }, { site: { [key3]: rule[key3] } });
@@ -28768,7 +28768,7 @@
28768
28768
  lane._handoffHeld = false;
28769
28769
  throw fail("the apply did not settle", "timeout");
28770
28770
  }
28771
- await new Promise((resolve2) => setTimeout(resolve2, 1));
28771
+ await new Promise((resolve3) => setTimeout(resolve3, 1));
28772
28772
  }
28773
28773
  const queued3 = () => lane._pendingHtml != null || lane._pendingExternal != null;
28774
28774
  return {
@@ -28800,7 +28800,7 @@
28800
28800
  if (!lane._handoff || lane.isDestroyed) return;
28801
28801
  for (let pass = 0; pass < 8; pass++) {
28802
28802
  if (lane._morphInFlight) {
28803
- await new Promise((resolve2) => setTimeout(resolve2, 1));
28803
+ await new Promise((resolve3) => setTimeout(resolve3, 1));
28804
28804
  continue;
28805
28805
  }
28806
28806
  if (!queued3()) return;
@@ -28844,7 +28844,7 @@
28844
28844
  morph: () => morph2
28845
28845
  });
28846
28846
  function loadEdit2() {
28847
- editLoad2 ??= new Promise((resolve2) => setTimeout(resolve2, 0)).then(() => Promise.resolve().then(() => (init_live_sync_edit(), live_sync_edit_exports))).then((loaded2) => edit2 = loaded2).catch((error2) => {
28847
+ editLoad2 ??= new Promise((resolve3) => setTimeout(resolve3, 0)).then(() => Promise.resolve().then(() => (init_live_sync_edit(), live_sync_edit_exports))).then((loaded2) => edit2 = loaded2).catch((error2) => {
28848
28848
  editLoad2 = null;
28849
28849
  throw error2;
28850
28850
  });
@@ -28896,6 +28896,14 @@
28896
28896
  emptyScratchpads(doc);
28897
28897
  return doc;
28898
28898
  }
28899
+ function editorFieldsBeforeApply() {
28900
+ const fields = Array.from(document.querySelectorAll(EDITOR_FIELD_SELECTOR), (field) => [field, field.innerHTML]);
28901
+ return () => {
28902
+ for (const [field, before] of fields) {
28903
+ if (field.isConnected && field.innerHTML !== before) field.dispatchEvent(new CustomEvent("clay:external-write"));
28904
+ }
28905
+ };
28906
+ }
28899
28907
  function countAuthored(root4) {
28900
28908
  const counts2 = /* @__PURE__ */ new Map();
28901
28909
  const visit = (el13) => {
@@ -28935,7 +28943,7 @@
28935
28943
  const root4 = (source3) => new DOMParser().parseFromString(source3, "text/html").documentElement;
28936
28944
  return root4(html).isEqualNode(root4(sent)) ? sent : html;
28937
28945
  }
28938
- var edit2, editLoad2, presenceStore, presenceLoad, entering, roster2, rosterLoad, rosterQueue, NO_FILE, notInEditModeResult, SYNC_IGNORE_SELECTOR, FREEZE_SELECTOR2, REMOTE_WINS_SELECTOR, isRootLocalAttr, authoredAttr2, uniqueAuthoredIdentity, isIdMap, RELAY_BODY_BLOB_MIN_BYTES, LiveSync, lastAccepted, acceptedBytesFor, liveSync, morph2, live_sync_default;
28946
+ var edit2, editLoad2, presenceStore, presenceLoad, entering, roster2, rosterLoad, rosterQueue, NO_FILE, notInEditModeResult, SYNC_IGNORE_SELECTOR, FREEZE_SELECTOR2, REMOTE_WINS_SELECTOR, EDITOR_FIELD_SELECTOR, isRootLocalAttr, authoredAttr2, uniqueAuthoredIdentity, isIdMap, RELAY_BODY_BLOB_MIN_BYTES, LiveSync, lastAccepted, acceptedBytesFor, liveSync, morph2, live_sync_default;
28939
28947
  var init_live_sync = __esm({
28940
28948
  "src/sync/live-sync.js"() {
28941
28949
  init_hyper_morph_identity_vendor();
@@ -29005,6 +29013,7 @@
29005
29013
  "[no-watch]",
29006
29014
  "[mutations-ignore]"
29007
29015
  ].join(",");
29016
+ EDITOR_FIELD_SELECTOR = "[data-richclay], [richclay], [editable], [clay-editable]";
29008
29017
  isRootLocalAttr = (el13, name, merged2) => mergeIgnoresAttr(el13, name, merged2) || EXTENSION_ATTR_PATTERN.test(name.toLowerCase());
29009
29018
  authoredAttr2 = (el13) => el13.getAttribute("data-id") || el13.getAttribute("id") || null;
29010
29019
  uniqueAuthoredIdentity = (memo2) => (el13) => {
@@ -30189,6 +30198,7 @@
30189
30198
  let lineageCapture;
30190
30199
  const mergeDocument = (options) => {
30191
30200
  lineageCapture = beginLineageCapture2(conflicts2.list());
30201
+ const tellRewrittenFields = editorFieldsBeforeApply();
30192
30202
  try {
30193
30203
  const pending9 = loadedEngine().HyperMorph.mergeDocument({ ...options, lineage: lineageCapture.lineage });
30194
30204
  lineageCapture.returned();
@@ -30197,6 +30207,8 @@
30197
30207
  lineageCapture.invalidate(conflicts2.list());
30198
30208
  lineageCapture.finish(conflicts2.list());
30199
30209
  throw error2;
30210
+ } finally {
30211
+ tellRewrittenFields();
30200
30212
  }
30201
30213
  };
30202
30214
  const store2 = this.identity;
@@ -30420,7 +30432,7 @@
30420
30432
  this._log("applyUpdate - morph complete, resuming mutations");
30421
30433
  mutation_default.resume();
30422
30434
  resumeGate();
30423
- await new Promise((resolve2) => setTimeout(resolve2, 0));
30435
+ await new Promise((resolve3) => setTimeout(resolve3, 0));
30424
30436
  this.isPaused = false;
30425
30437
  }
30426
30438
  if (stamped) edit2?.conflictResolvedBySync(etag);
@@ -30530,7 +30542,7 @@
30530
30542
  this._log("applyExternal - morph complete, resuming mutations");
30531
30543
  mutation_default.resume();
30532
30544
  resumeGate();
30533
- await new Promise((resolve2) => setTimeout(resolve2, 0));
30545
+ await new Promise((resolve3) => setTimeout(resolve3, 0));
30534
30546
  this.isPaused = false;
30535
30547
  }
30536
30548
  if (stamped) edit2?.conflictResolvedBySync(etag);
@@ -32070,10 +32082,10 @@
32070
32082
  busy = "revert";
32071
32083
  render2();
32072
32084
  let stayed = true;
32073
- const track3 = (e20) => {
32085
+ const track4 = (e20) => {
32074
32086
  stayed = !!root3?.contains(e20.target);
32075
32087
  };
32076
- document.addEventListener("focus", track3, true);
32088
+ document.addEventListener("focus", track4, true);
32077
32089
  let result2;
32078
32090
  try {
32079
32091
  const { revertConflicts: revertConflicts2 } = await Promise.resolve().then(() => (init_conflict_revert(), conflict_revert_exports));
@@ -32082,7 +32094,7 @@
32082
32094
  console.error("[clay] Revert to mine did not finish", err);
32083
32095
  result2 = { revertedIds: [], blockedIds: ids, saveResult: null };
32084
32096
  } finally {
32085
- document.removeEventListener("focus", track3, true);
32097
+ document.removeEventListener("focus", track4, true);
32086
32098
  }
32087
32099
  busy = null;
32088
32100
  for (const id2 of result2.blockedIds) blockedRows.set(id2, ledger2()?.get(id2)?.kind === "json" ? DATA_BLOCKED_ROW : BLOCKED_ROW);
@@ -33683,9 +33695,10 @@ ${entry.now}`;
33683
33695
  for (let node = el13.previousSibling; node; node = node.previousSibling) if (!isSkin(node)) return false;
33684
33696
  return true;
33685
33697
  }
33686
- function schemeRule(roots) {
33698
+ function rootRules(roots) {
33699
+ const scope = `:is(${roots.join(", ")})`;
33687
33700
  return `
33688
- @layer clay-skin{:is(${roots.join(", ")}){color-scheme:${pageScheme()} !important}}`;
33701
+ @layer clay-skin{${scope}{color-scheme:${pageScheme()} !important}${scope}::selection,${scope} ::selection{background-color:light-dark(#B4D5FE, #2F5A8C) !important;color:light-dark(#1A1C24, #F2F4F8) !important}}`;
33689
33702
  }
33690
33703
  function installSkin(name, css, { roots } = {}) {
33691
33704
  installed3.set(name, { css, roots });
@@ -33699,7 +33712,7 @@ ${entry.now}`;
33699
33712
  el13.setAttribute("clay", RUNTIME_ONLY);
33700
33713
  el13.setAttribute("data-clay-skin", name);
33701
33714
  }
33702
- const text6 = roots ? css + schemeRule(roots) : css;
33715
+ const text6 = roots ? css + rootRules(roots) : css;
33703
33716
  if (el13.textContent !== text6) el13.textContent = text6;
33704
33717
  if (!placed(head, el13)) head.insertBefore(el13, firstNonSkin(head));
33705
33718
  return el13;
@@ -38168,14 +38181,113 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
38168
38181
  lease.enable();
38169
38182
  return lease;
38170
38183
  }
38171
- var session2, fault3, isStale, ownership, elements2, ready2, richclay_default;
38184
+ var authoredNoUndo, BLOCK, isBlock, dropLayoutWhitespace, savedForm, UNOWNED, outermost, historyForm, withUnowned, richForm, writeInner, morphNow, pageOwnsTyping, tracked, track, untrackAll, formedFor, followHistory, session2, fault3, isStale, ownership, elements2, ready2, richclay_default;
38172
38185
  var init_richclay2 = __esm({
38173
38186
  "src/plugins/richclay.js"() {
38174
38187
  init_vendor_skin();
38175
38188
  init_richclay();
38176
38189
  init_richclay_vendor();
38177
38190
  init_is_edit_mode();
38191
+ init_ephemeral();
38192
+ init_merge_engine();
38178
38193
  installSkin("richclay", CSS2, { roots: ROOTS });
38194
+ authoredNoUndo = (node) => {
38195
+ if (node.hasAttribute("no-undo") && !node.hasAttribute("data-richclay-runtime-no-undo")) return true;
38196
+ if ((node.getAttribute("clay") || "").split(/\s+/).includes("no-undo")) return true;
38197
+ const parent = node.parentElement;
38198
+ return !!parent && window.clay?.region?.resolveRegionPolicy?.(parent)?.undoable === false;
38199
+ };
38200
+ BLOCK = /^(P|DIV|UL|OL|LI|H[1-6]|BLOCKQUOTE|TABLE|THEAD|TBODY|TR|TD|TH|FIGURE|FIGCAPTION|HR|SECTION|ARTICLE|ASIDE|HEADER|FOOTER|DL|DT|DD)$/;
38201
+ isBlock = (node) => node?.nodeType === 1 && BLOCK.test(node.nodeName);
38202
+ dropLayoutWhitespace = (root4) => {
38203
+ const walker = root4.ownerDocument.createTreeWalker(root4, 4);
38204
+ const blank2 = [];
38205
+ for (let text6 = walker.nextNode(); text6; text6 = walker.nextNode()) {
38206
+ if (/\S/.test(text6.data) || text6.parentElement?.closest("pre")) continue;
38207
+ const parent = text6.parentNode;
38208
+ const edge = !text6.previousSibling || !text6.nextSibling;
38209
+ if (edge && (parent === root4 || isBlock(parent)) || isBlock(text6.previousSibling) || isBlock(text6.nextSibling)) blank2.push(text6);
38210
+ }
38211
+ blank2.forEach((text6) => text6.remove());
38212
+ };
38213
+ savedForm = (node) => {
38214
+ const copy13 = node.cloneNode(true);
38215
+ stripEphemeral(copy13);
38216
+ dropLayoutWhitespace(copy13);
38217
+ return RichClay.savedContent(copy13);
38218
+ };
38219
+ UNOWNED = '[editor-ui], [clay~="editor-ui"], [no-undo]:not([data-richclay-runtime-no-undo]), [clay~="no-undo"]';
38220
+ outermost = (root4) => [...root4.querySelectorAll(UNOWNED)].filter((el13) => {
38221
+ for (let at8 = el13.parentElement; at8 && at8 !== root4; at8 = at8.parentElement) if (at8.matches(UNOWNED)) return false;
38222
+ return true;
38223
+ });
38224
+ historyForm = (node) => {
38225
+ const copy13 = node.cloneNode(true);
38226
+ outermost(copy13).forEach((el13) => el13.replaceWith(copy13.ownerDocument.createElement("clay-kept")));
38227
+ return savedForm(copy13);
38228
+ };
38229
+ withUnowned = (element4, html) => {
38230
+ if (!html.includes("<clay-kept")) return html;
38231
+ const template = element4.ownerDocument.createElement("template");
38232
+ template.innerHTML = html;
38233
+ const live3 = outermost(element4);
38234
+ [...template.content.querySelectorAll("clay-kept")].forEach((slot3, at8) => {
38235
+ if (live3[at8]) slot3.replaceWith(live3[at8].cloneNode(true));
38236
+ else slot3.remove();
38237
+ });
38238
+ return template.innerHTML;
38239
+ };
38240
+ richForm = (node) => !node.matches?.(RichClay.selector) || authoredNoUndo(node) ? void 0 : savedForm(node);
38241
+ writeInner = (root4, html) => {
38242
+ root4.innerHTML = html;
38243
+ };
38244
+ morphNow = (field) => {
38245
+ const engine4 = loadedEngine();
38246
+ if (engine4) return engine4.morph;
38247
+ mergeEngine().catch(() => {
38248
+ });
38249
+ return field.querySelector('[editor-ui], [clay~="editor-ui"]') ? void 0 : writeInner;
38250
+ };
38251
+ pageOwnsTyping = () => window.clay?.undo?.pageHistory === true && window.clay.undo.recordingMode !== "commands";
38252
+ tracked = /* @__PURE__ */ new Map();
38253
+ track = (field) => {
38254
+ const undo2 = window.clay?.undo;
38255
+ if (!pageOwnsTyping() || authoredNoUndo(field)) return;
38256
+ tracked.set(field, undo2.trackContent(field, { read: historyForm, write: (element4, html) => {
38257
+ RichClay.setSavedContent(element4, withUnowned(element4, html), { morph: morphNow(element4) });
38258
+ } }));
38259
+ if (!loadedEngine() && field.querySelector('[editor-ui], [clay~="editor-ui"]') && typeof undo2.hold === "function") {
38260
+ const release3 = undo2.hold();
38261
+ mergeEngine().catch(() => {
38262
+ }).finally(release3);
38263
+ }
38264
+ };
38265
+ untrackAll = () => {
38266
+ for (const dispose2 of tracked.values()) dispose2();
38267
+ tracked.clear();
38268
+ };
38269
+ document.addEventListener("richclay:mount", (event) => track(event.target));
38270
+ formedFor = null;
38271
+ followHistory = () => {
38272
+ const undo2 = window.clay?.undo;
38273
+ if (undo2?.addDurableForm && formedFor !== undo2) {
38274
+ undo2.addDurableForm(richForm);
38275
+ formedFor = undo2;
38276
+ }
38277
+ RichClay.hostHistory = pageOwnsTyping();
38278
+ RichClay.keepsOwnHistory = authoredNoUndo;
38279
+ if (!RichClay.hostHistory) untrackAll();
38280
+ else document.querySelectorAll("[data-richclay-active]").forEach(track);
38281
+ };
38282
+ document.addEventListener("clay:undo-session", followHistory);
38283
+ document.addEventListener("clay:undo-recording", followHistory);
38284
+ document.addEventListener("clay:ready", followHistory);
38285
+ document.addEventListener("richclay:history-exhausted", (event) => {
38286
+ const undo2 = window.clay?.undo;
38287
+ if (!undo2 || window.clay.modeLifecycle?.canWrite?.() === false) return;
38288
+ if (event.detail?.direction === "redo") undo2.redo();
38289
+ else undo2.undo();
38290
+ });
38179
38291
  session2 = null;
38180
38292
  fault3 = (message2, code) => Object.assign(new Error(`clay:richclay: ${message2}`), { code });
38181
38293
  isStale = (context2) => {
@@ -38741,7 +38853,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
38741
38853
  }
38742
38854
  return node;
38743
38855
  }
38744
- function track(root4, ops) {
38856
+ function track2(root4, ops) {
38745
38857
  const done = [];
38746
38858
  try {
38747
38859
  for (const op of ops) {
@@ -38965,8 +39077,8 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
38965
39077
  }
38966
39078
  const data = view3(state2, []);
38967
39079
  let resolveReady;
38968
- const ready11 = new Promise((resolve2) => {
38969
- resolveReady = resolve2;
39080
+ const ready11 = new Promise((resolve3) => {
39081
+ resolveReady = resolve3;
38970
39082
  });
38971
39083
  const handle = Object.freeze({
38972
39084
  name,
@@ -39103,7 +39215,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
39103
39215
  } catch {
39104
39216
  return null;
39105
39217
  }
39106
- const done = track(authoritative, checked);
39218
+ const done = track2(authoritative, checked);
39107
39219
  if (!done) return null;
39108
39220
  untrack(done);
39109
39221
  return checked;
@@ -39116,7 +39228,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
39116
39228
  // for what one path held. next is authoritative itself, changed in place by
39117
39229
  // later frames: a listener copies what it keeps; prev is its own copy.
39118
39230
  rebaseOps(ops, { source: source3 = "remote", confirmed = 0, through, frame = null, room = null, cause = null } = {}) {
39119
- const done = track(authoritative, ops);
39231
+ const done = track2(authoritative, ops);
39120
39232
  if (!done) return false;
39121
39233
  const kept2 = through === void 0 ? pending8.slice(confirmed) : pending8.filter((entry) => entry.id > through);
39122
39234
  const dropped = pending8.length - kept2.length;
@@ -40186,11 +40298,11 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
40186
40298
  const asked2 = { connection, stateCount, read: ++reads };
40187
40299
  let state2 = null;
40188
40300
  const abort = typeof AbortController === "function" ? new AbortController() : null;
40189
- const expired = new Promise((resolve2) => {
40301
+ const expired = new Promise((resolve3) => {
40190
40302
  readTimer = setTimer(() => {
40191
40303
  readTimer = null;
40192
40304
  abort?.abort();
40193
- resolve2(null);
40305
+ resolve3(null);
40194
40306
  }, STATE_TIMEOUT_MS);
40195
40307
  });
40196
40308
  try {
@@ -44680,9 +44792,9 @@ ${n3.toString()}`);
44680
44792
  m7.log.push(entry);
44681
44793
  m7.logBytes += entry.bytes;
44682
44794
  while (m7.log.length > LOG_ENTRIES || m7.logBytes > LOG_BYTES) {
44683
- const gone = m7.log.shift();
44684
- m7.logBytes -= gone.bytes;
44685
- m7.floor = gone.seq;
44795
+ const gone2 = m7.log.shift();
44796
+ m7.logBytes -= gone2.bytes;
44797
+ m7.floor = gone2.seq;
44686
44798
  }
44687
44799
  }
44688
44800
  function advance(data) {
@@ -44839,17 +44951,17 @@ ${n3.toString()}`);
44839
44951
  }
44840
44952
  function closedFor(sequencer) {
44841
44953
  if (mirror.closedBy !== null && (sequencer === null || mirror.closedBy === sequencer)) return Promise.resolve(true);
44842
- return new Promise((resolve2) => {
44954
+ return new Promise((resolve3) => {
44843
44955
  const timer = setTimeout(() => {
44844
44956
  awaitingClose = null;
44845
- resolve2(false);
44957
+ resolve3(false);
44846
44958
  }, CLOSE_WAIT_MS);
44847
44959
  awaitingClose = {
44848
44960
  sequencer,
44849
44961
  resolve(ok) {
44850
44962
  clearTimeout(timer);
44851
44963
  awaitingClose = null;
44852
- resolve2(ok);
44964
+ resolve3(ok);
44853
44965
  }
44854
44966
  };
44855
44967
  });
@@ -44862,8 +44974,8 @@ ${n3.toString()}`);
44862
44974
  const ordered2 = await closedFor(mirror.sequencer);
44863
44975
  if (stopped2) return void 0;
44864
44976
  startRoom({ fresh: mirror.epoch === null || !ordered2 });
44865
- return new Promise((resolve2) => {
44866
- releaseLock = resolve2;
44977
+ return new Promise((resolve3) => {
44978
+ releaseLock = resolve3;
44867
44979
  });
44868
44980
  }).catch(() => {
44869
44981
  }).finally(() => {
@@ -45116,19 +45228,19 @@ ${n3.toString()}`);
45116
45228
  else tellLanded(moved);
45117
45229
  }
45118
45230
  function request4(message2) {
45119
- return new Promise((resolve2) => {
45231
+ return new Promise((resolve3) => {
45120
45232
  const id2 = ++rid;
45121
45233
  const timer = setTimeout(() => {
45122
45234
  waiting.delete(id2);
45123
45235
  ownPosts.delete(id2);
45124
- resolve2(null);
45236
+ resolve3(null);
45125
45237
  }, REQUEST_MS);
45126
45238
  if (message2.type === "post") ownPosts.set(id2, mirror.sequencer);
45127
45239
  waiting.set(id2, (result2) => {
45128
45240
  clearTimeout(timer);
45129
45241
  waiting.delete(id2);
45130
45242
  ownPosts.delete(id2);
45131
- resolve2(result2);
45243
+ resolve3(result2);
45132
45244
  });
45133
45245
  post2({ ...message2, from: clientId, rid: id2 });
45134
45246
  });
@@ -45242,7 +45354,7 @@ ${n3.toString()}`);
45242
45354
  awaitingClose?.resolve(false);
45243
45355
  window.removeEventListener("pagehide", onPageHide);
45244
45356
  window.removeEventListener("pageshow", onPageShow);
45245
- for (const resolve2 of waiting.values()) resolve2(null);
45357
+ for (const resolve3 of waiting.values()) resolve3(null);
45246
45358
  unsubscribe?.();
45247
45359
  unsubscribe = null;
45248
45360
  channel3 = null;
@@ -45653,7 +45765,7 @@ ${n3.toString()}`);
45653
45765
  frame();
45654
45766
  while (liveWriterPending()) {
45655
45767
  if (Date.now() >= deadline) return { ok: false, code: "timeout" };
45656
- await new Promise((resolve2) => setTimeout(resolve2, 5));
45768
+ await new Promise((resolve3) => setTimeout(resolve3, 5));
45657
45769
  frame();
45658
45770
  }
45659
45771
  return { ok: true };
@@ -45728,11 +45840,11 @@ ${n3.toString()}`);
45728
45840
  };
45729
45841
  }
45730
45842
  function freshLaneGates() {
45731
- laneReady = new Promise((resolve2) => {
45732
- settleLane = resolve2;
45843
+ laneReady = new Promise((resolve3) => {
45844
+ settleLane = resolve3;
45733
45845
  });
45734
- writerReady = new Promise((resolve2) => {
45735
- settleWriter = resolve2;
45846
+ writerReady = new Promise((resolve3) => {
45847
+ settleWriter = resolve3;
45736
45848
  });
45737
45849
  }
45738
45850
  function laneGates() {
@@ -46220,11 +46332,11 @@ ${Object.entries(inner).map(([k8, v9]) => `${serializeLive(k8)}:${serializeLive(
46220
46332
  }
46221
46333
  async function requestExitCheckpoint({ name, needsSave, permit, deadline, signal = null, keepalive = false }) {
46222
46334
  const over = () => signal?.aborted || Date.now() >= deadline;
46223
- const pause = () => new Promise((resolve2) => {
46335
+ const pause = () => new Promise((resolve3) => {
46224
46336
  const done = () => {
46225
46337
  clearTimeout(timer);
46226
46338
  signal?.removeEventListener("abort", done);
46227
- resolve2();
46339
+ resolve3();
46228
46340
  };
46229
46341
  const timer = setTimeout(done, 5);
46230
46342
  signal?.addEventListener("abort", done, { once: true });
@@ -46268,11 +46380,11 @@ ${Object.entries(inner).map(([k8, v9]) => `${serializeLive(k8)}:${serializeLive(
46268
46380
  return (entry.landed ?? 0) >= last2;
46269
46381
  });
46270
46382
  if (reached()) return Promise.resolve({ ok: true });
46271
- return new Promise((resolve2) => {
46383
+ return new Promise((resolve3) => {
46272
46384
  const finish3 = (result2) => {
46273
46385
  clearTimeout(timer);
46274
46386
  fileWaiters.delete(check);
46275
- resolve2(result2);
46387
+ resolve3(result2);
46276
46388
  };
46277
46389
  const check = () => {
46278
46390
  if (reached()) finish3({ ok: true });
@@ -54827,14 +54939,14 @@ ${Object.entries(inner).map(([k8, v9]) => `${serializeLive(k8)}:${serializeLive(
54827
54939
  const mapping = new mi2.Mapping();
54828
54940
  for (const t2 of transactions) mapping.appendMapping(t2.mapping);
54829
54941
  const was = /* @__PURE__ */ new Map();
54830
- const track3 = (node, at8) => {
54942
+ const track4 = (node, at8) => {
54831
54943
  if (!node.attrs.id) return;
54832
54944
  const r45 = mapping.mapResult(at8, 1);
54833
54945
  was.set(node.attrs.id, { node, at: r45.deleted ? null : r45.pos });
54834
54946
  };
54835
54947
  old.doc.forEach((node, offset) => {
54836
- track3(node, offset);
54837
- if (node.type.name === "table") node.forEach((row, rowOffset) => track3(row, offset + 1 + rowOffset));
54948
+ track4(node, offset);
54949
+ if (node.type.name === "table") node.forEach((row, rowOffset) => track4(row, offset + 1 + rowOffset));
54838
54950
  });
54839
54951
  const rank = (node, at8) => {
54840
54952
  const w6 = was.get(node.attrs.id);
@@ -55651,12 +55763,12 @@ ${parts.join("\n")}
55651
55763
  const name = tag2 === "mark" ? "highlight" : "text_color";
55652
55764
  return { name, attrs: { color: el13.getAttribute("data-color") } };
55653
55765
  }
55654
- function inlineOfEl(el13, skip = () => false) {
55766
+ function inlineOfEl(el13, skip2 = () => false) {
55655
55767
  let c4 = "";
55656
55768
  const units = [];
55657
55769
  const walk2 = (node, marks, entries3) => {
55658
55770
  for (const child of node.childNodes) {
55659
- if (skip(child)) continue;
55771
+ if (skip2(child)) continue;
55660
55772
  if (child.nodeType === 3) {
55661
55773
  c4 += child.data;
55662
55774
  const key3 = keyOfMarks(safeMarks({ ...marks }), entries3);
@@ -56222,7 +56334,7 @@ ${parts.join("\n")}
56222
56334
  const list3 = aliasClocks.get(client);
56223
56335
  return list3 !== void 0 && list3[lowerClock(list3, clock)] === clock;
56224
56336
  };
56225
- const resolve2 = (id2) => {
56337
+ const resolve3 = (id2) => {
56226
56338
  const alias = hasAlias(id2.client, id2.clock) ? aliases.get(idKey2(id2.client, id2.clock)) : void 0;
56227
56339
  if (alias) return { client: alias.client, clock: alias.clock };
56228
56340
  const list3 = spans.get(id2.client);
@@ -56316,7 +56428,7 @@ ${parts.join("\n")}
56316
56428
  if (!entry?.dest || !entry?.source) throw new Error("Invalid origin destination");
56317
56429
  const dest = entry.dest, source3 = entry.source;
56318
56430
  if (!isClock(dest.client) || !isClock(dest.clock) || !isClock(source3.client) || !isClock(source3.clock)) throw new Error("Invalid origin destination");
56319
- const flat = resolve2(source3);
56431
+ const flat = resolve3(source3);
56320
56432
  const prev = run5[run5.length - 1];
56321
56433
  if (prev && prev.dest.client === dest.client && prev.dest.clock + 1 === dest.clock && prev.source.client === flat.client && prev.source.clock + 1 === flat.clock) run5.push({ dest, source: flat });
56322
56434
  else {
@@ -56328,7 +56440,7 @@ ${parts.join("\n")}
56328
56440
  };
56329
56441
  const recordAlias = (dest, source3) => {
56330
56442
  if (!dest || !source3 || !isClock(dest.client) || !isClock(dest.clock) || !isClock(source3.client) || !isClock(source3.clock)) throw new Error("Invalid origin destination");
56331
- const flat = resolve2(source3);
56443
+ const flat = resolve3(source3);
56332
56444
  const key3 = aliasKey(dest.client, dest.clock);
56333
56445
  const old = origins.get(key3);
56334
56446
  if (old !== void 0 && (old.sourceClient !== flat.client || old.sourceClock !== flat.clock)) throw conflicting(key3);
@@ -56353,7 +56465,7 @@ ${parts.join("\n")}
56353
56465
  };
56354
56466
  return {
56355
56467
  origins,
56356
- resolve: resolve2,
56468
+ resolve: resolve3,
56357
56469
  resolveRange,
56358
56470
  recordSpans,
56359
56471
  recordAlias,
@@ -57035,18 +57147,18 @@ ${parts.join("\n")}
57035
57147
  return norm.get(k8);
57036
57148
  };
57037
57149
  const covered2 = (k8, v9, mk) => coveredBy(k8, v9, mk, normal(mk));
57038
- const gone = /* @__PURE__ */ new Set();
57150
+ const gone2 = /* @__PURE__ */ new Set();
57039
57151
  for (const [k8, v9] of entries3) {
57040
57152
  if (!crowded && k8[0] !== "m") continue;
57041
57153
  for (const [mk] of folds) {
57042
- if (mk === k8 || gone.has(mk) || !covered2(k8, v9, mk)) continue;
57154
+ if (mk === k8 || gone2.has(mk) || !covered2(k8, v9, mk)) continue;
57043
57155
  if (k8[0] === "m" && k8 < mk && covered2(mk, val.get(mk), k8)) continue;
57044
- gone.add(k8);
57156
+ gone2.add(k8);
57045
57157
  break;
57046
57158
  }
57047
57159
  }
57048
- if (!gone.size) return false;
57049
- retire(auth, keysOf(auth, gone));
57160
+ if (!gone2.size) return false;
57161
+ retire(auth, keysOf(auth, gone2));
57050
57162
  return true;
57051
57163
  }
57052
57164
  function maybeCompact() {
@@ -57531,29 +57643,29 @@ ${parts.join("\n")}
57531
57643
  const client = Number(left), clock = Number(right);
57532
57644
  return isClock2(client) && isClock2(clock) ? { client, clock } : null;
57533
57645
  }
57534
- function parseGoneIntents(gone, { strict = false, kept: kept2 = true } = {}) {
57646
+ function parseGoneIntents(gone2, { strict = false, kept: kept2 = true } = {}) {
57535
57647
  const out = emptyIntents();
57536
57648
  if (strict) {
57537
- gone.forEach((value, key3) => recordOf2(value, key3, out));
57649
+ gone2.forEach((value, key3) => recordOf2(value, key3, out));
57538
57650
  return out;
57539
57651
  }
57540
- if (kept2 && gone instanceof se3 && gone.doc) return goneIndexOf(gone).intents();
57652
+ if (kept2 && gone2 instanceof se3 && gone2.doc) return goneIndexOf(gone2).intents();
57541
57653
  if (!kept2) {
57542
- gone.forEach((value, key3) => {
57654
+ gone2.forEach((value, key3) => {
57543
57655
  const record6 = parsedRecord(value, key3);
57544
57656
  if (record6) foldRecord(out, record6);
57545
57657
  });
57546
57658
  return out;
57547
57659
  }
57548
- const previous = parsedGone.get(gone) ?? /* @__PURE__ */ new Map();
57660
+ const previous = parsedGone.get(gone2) ?? /* @__PURE__ */ new Map();
57549
57661
  const parsed2 = /* @__PURE__ */ new Map();
57550
- gone.forEach((value, key3) => {
57662
+ gone2.forEach((value, key3) => {
57551
57663
  const hit = previous.get(key3);
57552
57664
  const entry = hit && hit.value === value ? hit : { value, record: parsedRecord(value, key3) };
57553
57665
  parsed2.set(key3, entry);
57554
57666
  if (entry.record) foldRecord(out, entry.record);
57555
57667
  });
57556
- parsedGone.set(gone, parsed2);
57668
+ parsedGone.set(gone2, parsed2);
57557
57669
  return out;
57558
57670
  }
57559
57671
  function recoveredRoot(sourceKey, removals, intents) {
@@ -57855,15 +57967,15 @@ ${parts.join("\n")}
57855
57967
  }
57856
57968
  };
57857
57969
  goneIndexes = /* @__PURE__ */ new WeakMap();
57858
- goneIndexOf = (gone) => {
57859
- const known3 = goneIndexes.get(gone);
57970
+ goneIndexOf = (gone2) => {
57971
+ const known3 = goneIndexes.get(gone2);
57860
57972
  if (known3) return known3;
57861
57973
  const entries3 = /* @__PURE__ */ new Map();
57862
57974
  let totals = null;
57863
57975
  let added2 = [];
57864
57976
  const update2 = (key3) => {
57865
- const live3 = gone.has(key3);
57866
- const value = live3 ? gone.get(key3) : void 0;
57977
+ const live3 = gone2.has(key3);
57978
+ const value = live3 ? gone2.get(key3) : void 0;
57867
57979
  const entry = entries3.get(key3);
57868
57980
  if (entry && entry.live === live3 && entry.value === value) return;
57869
57981
  const record6 = live3 ? parsedRecord(value, key3) : null;
@@ -57878,13 +57990,13 @@ ${parts.join("\n")}
57878
57990
  entry.record = record6;
57879
57991
  totals = null;
57880
57992
  };
57881
- for (const key3 of gone._map.keys()) update2(key3);
57882
- gone.observe((event) => {
57993
+ for (const key3 of gone2._map.keys()) update2(key3);
57994
+ gone2.observe((event) => {
57883
57995
  for (const key3 of event.keysChanged) update2(key3);
57884
57996
  });
57885
57997
  const index = {
57886
57998
  intents() {
57887
- for (const t2 of gone.doc._transactionCleanups) for (const key3 of t2.changed.get(gone) ?? []) update2(key3);
57999
+ for (const t2 of gone2.doc._transactionCleanups) for (const key3 of t2.changed.get(gone2) ?? []) update2(key3);
57888
58000
  if (!totals) {
57889
58001
  totals = emptyIntents();
57890
58002
  for (const entry of entries3.values()) if (entry.record) foldRecord(totals, entry.record);
@@ -57902,7 +58014,7 @@ ${parts.join("\n")}
57902
58014
  };
57903
58015
  }
57904
58016
  };
57905
- goneIndexes.set(gone, index);
58017
+ goneIndexes.set(gone2, index);
57906
58018
  return index;
57907
58019
  };
57908
58020
  canonical3 = (value) => {
@@ -60549,7 +60661,7 @@ ${parts.join("\n")}
60549
60661
  modal_default.closeHtml = "x";
60550
60662
  modal_default.no = "Cancel";
60551
60663
  modal_default.yes = yesLabel;
60552
- const promise = new Promise((resolve2, reject) => {
60664
+ const promise = new Promise((resolve3, reject) => {
60553
60665
  modal_default.onYes(() => {
60554
60666
  let promptResult;
60555
60667
  if (includeInput) {
@@ -60564,7 +60676,7 @@ ${parts.join("\n")}
60564
60676
  return false;
60565
60677
  }
60566
60678
  }
60567
- setTimeout(() => resolve2(promptResult), 0);
60679
+ setTimeout(() => resolve3(promptResult), 0);
60568
60680
  return true;
60569
60681
  });
60570
60682
  modal_default.onNo = () => {
@@ -60609,9 +60721,9 @@ ${parts.join("\n")}
60609
60721
  modal_default[SURFACE_THEME] = theme3;
60610
60722
  modal_default.closeHtml = "x";
60611
60723
  modal_default.yes = "OK";
60612
- const promise = new Promise((resolve2, reject) => {
60724
+ const promise = new Promise((resolve3, reject) => {
60613
60725
  modal_default.onYes(() => {
60614
- setTimeout(resolve2, 0);
60726
+ setTimeout(resolve3, 0);
60615
60727
  return true;
60616
60728
  });
60617
60729
  modal_default.onNo = () => {
@@ -60658,13 +60770,13 @@ ${parts.join("\n")}
60658
60770
  modal_default[SURFACE_THEME] = theme3;
60659
60771
  modal_default.closeHtml = "x";
60660
60772
  modal_default.yes = "";
60661
- const promise = new Promise((resolve2) => {
60773
+ const promise = new Promise((resolve3) => {
60662
60774
  modal_default.onYes(() => {
60663
- setTimeout(resolve2, 0);
60775
+ setTimeout(resolve3, 0);
60664
60776
  return true;
60665
60777
  });
60666
60778
  modal_default.onNo = () => {
60667
- setTimeout(resolve2, 0);
60779
+ setTimeout(resolve3, 0);
60668
60780
  };
60669
60781
  });
60670
60782
  modal_default.open();
@@ -60862,9 +60974,9 @@ ${parts.join("\n")}
60862
60974
  init_chrome();
60863
60975
  ({ Plugin: Plugin3 } = Oi2);
60864
60976
  inputs = /* @__PURE__ */ new WeakMap();
60865
- readText = (file) => typeof file.text === "function" ? file.text() : new Promise((resolve2, reject) => {
60977
+ readText = (file) => typeof file.text === "function" ? file.text() : new Promise((resolve3, reject) => {
60866
60978
  const reader2 = new FileReader();
60867
- reader2.onload = () => resolve2(reader2.result);
60979
+ reader2.onload = () => resolve3(reader2.result);
60868
60980
  reader2.onerror = () => reject(reader2.error);
60869
60981
  reader2.readAsText(file);
60870
60982
  });
@@ -61581,7 +61693,7 @@ ${parts.join("\n")}
61581
61693
  const tables2 = [...body3.querySelectorAll("table")].filter((table3) => !table3.parentElement.closest("table"));
61582
61694
  if (tables2.length !== 1) return null;
61583
61695
  const rest = body3.cloneNode(true);
61584
- for (const skip of rest.querySelectorAll("table, style, script, template, meta, title")) skip.remove();
61696
+ for (const skip2 of rest.querySelectorAll("table, style, script, template, meta, title")) skip2.remove();
61585
61697
  if (rest.textContent.trim()) return null;
61586
61698
  const table2 = tables2[0];
61587
61699
  const rows2 = [...table2.querySelectorAll("tr")].filter((tr4) => tr4.closest("table") === table2);
@@ -62346,13 +62458,13 @@ ${parts.join("\n")}
62346
62458
 
62347
62459
  // src/page/history-intent.js
62348
62460
  function typingIntent(st10, from, to3, text6) {
62349
- return { kind: "insert", blockId: blockIdAt2(st10.doc, from), from, end: from + text6.length, replaced: from !== to3, text: text6, marks: markKey2(st10), at: Date.now() };
62461
+ return { kind: "insert", blockId: blockIdAt2(st10.doc, from), from, end: from + text6.length, replaced: from !== to3, text: text6, marks: markKey2(st10), breakAfter: endsSentence(st10, from, text6), at: Date.now() };
62350
62462
  }
62351
62463
  function continuesGroup(prev, next) {
62352
62464
  if (!prev || !next || prev.kind !== next.kind) return false;
62353
62465
  if (next.kind === "compose") return prev.id === next.id;
62354
62466
  if (prev.blockId !== next.blockId || next.at - prev.at > GROUP_MS) return false;
62355
- if (next.kind === "insert") return !next.replaced && next.from === prev.end && next.marks === prev.marks && !(/\s$/.test(prev.text) && /^\S/.test(next.text));
62467
+ if (next.kind === "insert") return !prev.breakAfter && !next.replaced && next.from === prev.end && next.marks === prev.marks;
62356
62468
  return next.direction === prev.direction && (next.direction < 0 ? next.to === prev.from : next.from === prev.from);
62357
62469
  }
62358
62470
  function takePendingDelete(view3) {
@@ -62394,7 +62506,97 @@ ${parts.join("\n")}
62394
62506
  }
62395
62507
  });
62396
62508
  }
62397
- var HISTORY_INTENT, GROUP_MS, blockIdAt2, markKey2, DELETES, pendingDeletes, PENDING_MS, DERIVED;
62509
+ function createHistoryBridge({ um, undo: undo2, redo, article, focus }) {
62510
+ const page2 = () => window.clay?.undo;
62511
+ const epoch2 = Math.random().toString(36).slice(2);
62512
+ let next = 0;
62513
+ let running2 = false;
62514
+ let recording2 = false;
62515
+ let disposed = false;
62516
+ const replay = (entry, direction) => {
62517
+ const fromKey = direction === "undo" ? "undoStack" : "redoStack";
62518
+ const toKey = direction === "undo" ? "redoStack" : "undoStack";
62519
+ const source3 = um[fromKey], destination = um[toKey];
62520
+ const index = source3.indexOf(entry.item);
62521
+ if (index < 0) throw new Error("blockeditor: history item is no longer available");
62522
+ const remaining = source3.filter((_7, at8) => at8 !== index);
62523
+ const temporary = [...destination, ...remaining];
62524
+ const boundary3 = temporary.length;
62525
+ um[fromKey] = [entry.item];
62526
+ um[toKey] = temporary;
62527
+ running2 = true;
62528
+ let changed2;
62529
+ let inverse;
62530
+ try {
62531
+ changed2 = direction === "undo" ? undo2() : redo();
62532
+ } finally {
62533
+ inverse = temporary.slice(boundary3);
62534
+ um[fromKey] = remaining;
62535
+ um[toKey] = [...destination, ...inverse];
62536
+ running2 = false;
62537
+ um.stopCapturing();
62538
+ }
62539
+ if (!changed2 || !inverse.length) {
62540
+ entry.item = null;
62541
+ throw new Error("blockeditor: history item was emptied by another edit");
62542
+ }
62543
+ entry.item = inverse[0];
62544
+ entry.applied = direction === "redo";
62545
+ };
62546
+ const onAdded = (event) => {
62547
+ if (running2 || event.origin === um || event.type !== "undo" || page2()?.pageHistory !== true) return;
62548
+ const entry = { item: event.stackItem, applied: true };
62549
+ const id2 = `${epoch2}:${++next}`;
62550
+ const oldValue = `${id2}:undone`, newValue = `${id2}:applied`;
62551
+ const primitive = {
62552
+ kind: "value",
62553
+ target: article,
62554
+ prop: `blockeditor-step:${id2}`,
62555
+ oldValue,
62556
+ newValue,
62557
+ read: () => !disposed && entry.item && (entry.applied ? um.undoStack : um.redoStack).includes(entry.item) ? entry.applied ? newValue : oldValue : null,
62558
+ write: (target, wanted) => {
62559
+ const typing = !!document.activeElement?.closest?.('[contenteditable]:not([contenteditable="false"])');
62560
+ const before = article.textContent;
62561
+ replay(entry, wanted === oldValue ? "undo" : "redo");
62562
+ if (typing && article.textContent !== before && typeof focus === "function") focus();
62563
+ }
62564
+ };
62565
+ recording2 = true;
62566
+ try {
62567
+ try {
62568
+ page2().recordStep("Edit", primitive);
62569
+ } catch {
62570
+ page2().record(primitive);
62571
+ }
62572
+ } finally {
62573
+ recording2 = false;
62574
+ }
62575
+ };
62576
+ const onCommit = () => {
62577
+ if (!recording2) um.stopCapturing();
62578
+ };
62579
+ um.on("stack-item-added", onAdded);
62580
+ let subscribed = null;
62581
+ const subscribe = () => {
62582
+ const current5 = page2()?.pageHistory === true ? page2() : null;
62583
+ if (current5 === subscribed) return;
62584
+ subscribed?.off?.("commit", onCommit);
62585
+ subscribed = current5;
62586
+ subscribed?.on?.("commit", onCommit);
62587
+ };
62588
+ subscribe();
62589
+ document.addEventListener("clay:undo-session", subscribe);
62590
+ return {
62591
+ dispose() {
62592
+ disposed = true;
62593
+ um.off("stack-item-added", onAdded);
62594
+ subscribed?.off?.("commit", onCommit);
62595
+ document.removeEventListener("clay:undo-session", subscribe);
62596
+ }
62597
+ };
62598
+ }
62599
+ var HISTORY_INTENT, GROUP_MS, blockIdAt2, markKey2, SENTENCE_END, endsSentence, DELETES, pendingDeletes, PENDING_MS, DERIVED;
62398
62600
  var init_history_intent = __esm({
62399
62601
  "src/page/history-intent.js"() {
62400
62602
  init_prosemirror_vendor();
@@ -62406,6 +62608,13 @@ ${parts.join("\n")}
62406
62608
  return $pos.depth ? $pos.node(1).attrs.id : null;
62407
62609
  };
62408
62610
  markKey2 = (st10) => (st10.storedMarks ?? st10.selection.$from.marks()).map((m7) => `${m7.type.name}:${JSON.stringify(m7.attrs)}`).sort().join(",");
62611
+ SENTENCE_END = /[.?!]["'\u201D\u2019)\]]*$/;
62612
+ endsSentence = (st10, from, text6) => {
62613
+ if (!/\s$/.test(text6)) return false;
62614
+ const $from = st10.doc.resolve(from);
62615
+ const head = $from.parent.textBetween(0, $from.parentOffset) + text6.replace(/\s+$/, "");
62616
+ return !/\s$/.test(head) && SENTENCE_END.test(head);
62617
+ };
62409
62618
  DELETES = { deleteContentBackward: -1, deleteContentForward: 1 };
62410
62619
  pendingDeletes = /* @__PURE__ */ new WeakMap();
62411
62620
  PENDING_MS = 1e3;
@@ -62526,10 +62735,10 @@ ${parts.join("\n")}
62526
62735
  }
62527
62736
  if (!signal) return shared;
62528
62737
  if (signal.aborted) return Promise.reject(signal.reason);
62529
- return new Promise((resolve2, reject) => {
62738
+ return new Promise((resolve3, reject) => {
62530
62739
  const onAbort = () => reject(signal.reason);
62531
62740
  signal.addEventListener("abort", onAbort, { once: true });
62532
- shared.then(resolve2, reject).finally(() => signal.removeEventListener("abort", onAbort));
62741
+ shared.then(resolve3, reject).finally(() => signal.removeEventListener("abort", onAbort));
62533
62742
  });
62534
62743
  }
62535
62744
  return {
@@ -67970,11 +68179,11 @@ ${INDENTS.map((n3) => `:where(article[data-blockeditor], .blockeditor-editor) .b
67970
68179
  try {
67971
68180
  this.board = boardOf(this.node);
67972
68181
  this.dom.dataset.id = this.blockId ?? "";
67973
- const gone = this.commands?.removed?.(this.blockId) ?? { columns: {}, cards: {} };
67974
- const removed = gone.columns ?? {};
67975
- const deleted = Object.keys(gone.cards ?? {}).filter((id2) => !Object.hasOwn(this.board.cards, id2));
68182
+ const gone2 = this.commands?.removed?.(this.blockId) ?? { columns: {}, cards: {} };
68183
+ const removed = gone2.columns ?? {};
68184
+ const deleted = Object.keys(gone2.cards ?? {}).filter((id2) => !Object.hasOwn(this.board.cards, id2));
67976
68185
  this.trays.replaceChildren(...[...this.board.missing].map(([col, ids], index) => this.tray(col, ids, index, removed[col])));
67977
- if (deleted.length) this.trays.append(this.deletedTray(deleted, gone.cards));
68186
+ if (deleted.length) this.trays.append(this.deletedTray(deleted, gone2.cards));
67978
68187
  else this.showDeleted = false;
67979
68188
  const lanes2 = this.board.columnIds.map((id2, index) => this.lane(id2, index));
67980
68189
  if (this.editing?.kind === "column") lanes2.push(this.newLane());
@@ -71999,7 +72208,7 @@ ${text6}`;
71999
72208
  return answer;
72000
72209
  }
72001
72210
  function pick3(s3) {
72002
- return new Promise((resolve2) => {
72211
+ return new Promise((resolve3) => {
72003
72212
  const input = doc.createElement("input");
72004
72213
  input.type = "file";
72005
72214
  input.accept = "image/*";
@@ -72007,12 +72216,12 @@ ${text6}`;
72007
72216
  input.hidden = true;
72008
72217
  (view3.dom.parentElement ?? doc.body).appendChild(input);
72009
72218
  s3.input = input;
72010
- s3.stopPick = () => resolve2(null);
72219
+ s3.stopPick = () => resolve3(null);
72011
72220
  let done = false;
72012
72221
  const finish3 = (file) => {
72013
72222
  if (done) return;
72014
72223
  done = true;
72015
- resolve2(file);
72224
+ resolve3(file);
72016
72225
  };
72017
72226
  listen3(s3, input, "change", () => finish3([...input.files ?? []][0] ?? null));
72018
72227
  listen3(s3, input, "cancel", () => finish3(null));
@@ -72788,12 +72997,12 @@ ${parsed2.documentElement.outerHTML}`;
72788
72997
  }
72789
72998
  box.append(list3);
72790
72999
  }
72791
- const acts = doc.createElement("div");
72792
- acts.className = "blockeditor-export-acts";
72793
- if (s3.ready) acts.append(button4("download", "Download"), button4("close", "Close"));
72794
- else acts.append(button4("retry", "Try again"), button4("close", "Close"));
72795
- box.append(acts);
72796
- const first = acts.firstChild;
73000
+ const acts2 = doc.createElement("div");
73001
+ acts2.className = "blockeditor-export-acts";
73002
+ if (s3.ready) acts2.append(button4("download", "Download"), button4("close", "Close"));
73003
+ else acts2.append(button4("retry", "Try again"), button4("close", "Close"));
73004
+ box.append(acts2);
73005
+ const first = acts2.firstChild;
72797
73006
  if (!s3.ui) s3.ui = mountEditorUI({ name: "blockeditor-export", content: box, css: [PANEL_CSS], parent: view3.dom.parentElement ?? doc.body });
72798
73007
  (s3.ready ? first : box).focus?.();
72799
73008
  }
@@ -73078,7 +73287,7 @@ ${parsed2.documentElement.outerHTML}`;
73078
73287
  if (typeof type !== "string") throw new MarkdownImportError("malformed-input", "A Markdown token has no type.");
73079
73288
  switch (type) {
73080
73289
  case "text":
73081
- if (Array.isArray(token2.tokens)) walk2(token2.tokens.filter((child) => typeof child?.type === "string" && !BLOCK.has(child.type)), marks);
73290
+ if (Array.isArray(token2.tokens)) walk2(token2.tokens.filter((child) => typeof child?.type === "string" && !BLOCK2.has(child.type)), marks);
73082
73291
  else text6(token2.text, marks);
73083
73292
  break;
73084
73293
  case "escape":
@@ -73242,7 +73451,7 @@ ${parsed2.documentElement.outerHTML}`;
73242
73451
  for (const part2 of inline3(tokens2, { images: false }).parts) {
73243
73452
  own = { c: own.c + part2.c, m: [...own.m, ...part2.m] };
73244
73453
  }
73245
- rest.push(...(child.tokens ?? []).filter((nested) => typeof nested?.type === "string" && BLOCK.has(nested.type) && nested.type !== "space"));
73454
+ rest.push(...(child.tokens ?? []).filter((nested) => typeof nested?.type === "string" && BLOCK2.has(nested.type) && nested.type !== "space"));
73246
73455
  } else rest.push(child);
73247
73456
  }
73248
73457
  const itemKind = item?.task ? "check" : kind2;
@@ -73289,7 +73498,7 @@ ${parsed2.documentElement.outerHTML}`;
73289
73498
  });
73290
73499
  return { blocks: out, unsupported: unsupported2, refused: refused5 };
73291
73500
  }
73292
- var EMBEDS, LOADERS, SCRIPTED, MAX_BYTES, MAX_DEPTH3, MAX_BLOCKS, MarkdownImportError, ATOM7, BREAK5, BLOCK, encoder6, M7, sorted, RELATIVE;
73501
+ var EMBEDS, LOADERS, SCRIPTED, MAX_BYTES, MAX_DEPTH3, MAX_BLOCKS, MarkdownImportError, ATOM7, BREAK5, BLOCK2, encoder6, M7, sorted, RELATIVE;
73293
73502
  var init_import_markdown = __esm({
73294
73503
  "src/page/import-markdown.js"() {
73295
73504
  init_schema();
@@ -73312,7 +73521,7 @@ ${parsed2.documentElement.outerHTML}`;
73312
73521
  };
73313
73522
  ATOM7 = "\uFFFC";
73314
73523
  BREAK5 = { type: "hard_break" };
73315
- BLOCK = /* @__PURE__ */ new Set(["paragraph", "heading", "list", "blockquote", "code", "table", "hr", "html", "def", "space"]);
73524
+ BLOCK2 = /* @__PURE__ */ new Set(["paragraph", "heading", "list", "blockquote", "code", "table", "hr", "html", "def", "space"]);
73316
73525
  encoder6 = new TextEncoder();
73317
73526
  M7 = schema.marks;
73318
73527
  sorted = (marks) => marks.slice().sort((a2, b7) => a2.type.rank - b7.type.rank);
@@ -74825,7 +75034,7 @@ Please report this to https://github.com/markedjs/marked.`, r45) {
74825
75034
  }
74826
75035
  }
74827
75036
  function pick3() {
74828
- return new Promise((resolve2) => {
75037
+ return new Promise((resolve3) => {
74829
75038
  const input = doc.createElement("input");
74830
75039
  input.type = "file";
74831
75040
  input.accept = ".md,.markdown,text/markdown,text/plain";
@@ -74833,7 +75042,7 @@ Please report this to https://github.com/markedjs/marked.`, r45) {
74833
75042
  input.className = "blockeditor-markdown-input";
74834
75043
  const done = (file) => {
74835
75044
  input.remove();
74836
- resolve2(file);
75045
+ resolve3(file);
74837
75046
  };
74838
75047
  input.addEventListener("change", () => done(input.files?.[0] ?? null));
74839
75048
  input.addEventListener("cancel", () => done(null));
@@ -74930,9 +75139,9 @@ Please report this to https://github.com/markedjs/marked.`, r45) {
74930
75139
  const value = String(text6 ?? "").replace(/\s+/g, " ").trim();
74931
75140
  return value.length > 60 ? `${value.slice(0, 60)}\u2026` : value;
74932
75141
  };
74933
- readText2 = (file) => typeof file.text === "function" ? file.text() : new Promise((resolve2, reject) => {
75142
+ readText2 = (file) => typeof file.text === "function" ? file.text() : new Promise((resolve3, reject) => {
74934
75143
  const reader2 = new FileReader();
74935
- reader2.onload = () => resolve2(reader2.result);
75144
+ reader2.onload = () => resolve3(reader2.result);
74936
75145
  reader2.onerror = () => reject(reader2.error);
74937
75146
  reader2.readAsText(file);
74938
75147
  });
@@ -75105,9 +75314,9 @@ ${mark2}`;
75105
75314
  lines.push(text7);
75106
75315
  listOpen2 = true;
75107
75316
  };
75108
- const skip = /* @__PURE__ */ new Set();
75317
+ const skip2 = /* @__PURE__ */ new Set();
75109
75318
  for (const raw of model2) {
75110
- if (!raw || typeof raw.t !== "string" || skip.has(raw.id)) continue;
75319
+ if (!raw || typeof raw.t !== "string" || skip2.has(raw.id)) continue;
75111
75320
  const item = raw;
75112
75321
  const note = noteFor(item);
75113
75322
  const t2 = item.t;
@@ -75141,7 +75350,7 @@ ${mark2}`;
75141
75350
  }
75142
75351
  extension(item, "Toggle");
75143
75352
  const body3 = bodyOf(items, item);
75144
- for (const one of body3) skip.add(one.id);
75353
+ for (const one of body3) skip2.add(one.id);
75145
75354
  push(renderModel([item, ...body3]));
75146
75355
  continue;
75147
75356
  }
@@ -75410,10 +75619,10 @@ ${mark2}`;
75410
75619
  }
75411
75620
  function composed() {
75412
75621
  if (!view3.composing) return Promise.resolve();
75413
- return new Promise((resolve2) => {
75622
+ return new Promise((resolve3) => {
75414
75623
  const done = () => {
75415
75624
  view3.dom.removeEventListener("compositionend", done);
75416
- resolve2();
75625
+ resolve3();
75417
75626
  };
75418
75627
  view3.dom.addEventListener("compositionend", done);
75419
75628
  });
@@ -75710,13 +75919,13 @@ ${mark2}`;
75710
75919
  });
75711
75920
  }
75712
75921
  function settleBranches(inst, branches) {
75713
- return new Promise((resolve2) => {
75922
+ return new Promise((resolve3) => {
75714
75923
  const signal = inst.controller.signal;
75715
75924
  let done = false;
75716
75925
  const finish3 = (outcome2) => {
75717
75926
  if (done) return;
75718
75927
  done = true;
75719
- resolve2(outcome2);
75928
+ resolve3(outcome2);
75720
75929
  };
75721
75930
  if (signal.aborted) return finish3({ cancelled: true });
75722
75931
  signal.addEventListener("abort", () => finish3({ cancelled: true }), { once: true });
@@ -76479,9 +76688,9 @@ ${mark2}`;
76479
76688
  return article ? { article: article.cloneNode(true), tags: pageTags(root4).map((el13) => parseTag(el13.textContent)) } : null;
76480
76689
  }
76481
76690
  function compositionIdle(view3) {
76482
- return new Promise((resolve2) => {
76483
- if (!view3.composing) return resolve2();
76484
- view3.dom.addEventListener("compositionend", () => setTimeout(() => resolve2(compositionIdle(view3)), 0), { once: true });
76691
+ return new Promise((resolve3) => {
76692
+ if (!view3.composing) return resolve3();
76693
+ view3.dom.addEventListener("compositionend", () => setTimeout(() => resolve3(compositionIdle(view3)), 0), { once: true });
76485
76694
  });
76486
76695
  }
76487
76696
  function installAdoption({
@@ -76522,11 +76731,11 @@ ${mark2}`;
76522
76731
  let queue2 = Promise.resolve();
76523
76732
  let disposed = false;
76524
76733
  let cancel2;
76525
- const cancelled3 = new Promise((resolve2) => cancel2 = resolve2);
76734
+ const cancelled3 = new Promise((resolve3) => cancel2 = resolve3);
76526
76735
  async function waitForEditor() {
76527
76736
  let timer;
76528
- const timeout = new Promise((resolve2) => {
76529
- timer = setTimeout(() => resolve2("timeout"), holdMs);
76737
+ const timeout = new Promise((resolve3) => {
76738
+ timer = setTimeout(() => resolve3("timeout"), holdMs);
76530
76739
  });
76531
76740
  try {
76532
76741
  return await Promise.race([Promise.resolve(ready11).then(() => idle2()).then(() => "ready"), cancelled3.then(() => "disposed"), timeout]);
@@ -78021,7 +78230,203 @@ ${mark2}`;
78021
78230
  restoreCaret();
78022
78231
  return { status: "moved", ids: movedIds };
78023
78232
  }
78024
- var refuse6, attrsKey, visibleBlocks, ancestors, isAncestor, inSubtree, setAttr, setParent, MAX_INDENT2, ATTR_RULES, attrChanges, flowUnits, liveRemovals;
78233
+ function carryAcross({ pd, origins, walked, placed: placed2 }, owned2, homes, flip = null, records3 = false) {
78234
+ const entries3 = walked.hidden.filter((entry) => owned2.has(entry.key));
78235
+ if (!entries3.length) return false;
78236
+ const self2 = pd.ydoc.clientID;
78237
+ const deletes = flip !== null || records3 ? parseGoneIntents(pd.gone).textDeletes.filter((record6) => record6.actor !== self2) : [];
78238
+ const removed = /* @__PURE__ */ new Map();
78239
+ const taken2 = /* @__PURE__ */ new Set();
78240
+ const inserts = [];
78241
+ const folds = /* @__PURE__ */ new Map();
78242
+ let visible = null, map = null;
78243
+ for (const entry of entries3) {
78244
+ const owner = owned2.get(entry.key);
78245
+ const { left, past } = owner;
78246
+ const start12 = startOf2(pd, entry.sourceKey);
78247
+ if (!start12) continue;
78248
+ const live3 = new Map(entry.items.map((item) => [item.id, item]));
78249
+ const region = [];
78250
+ for (let it7 = start12.right; it7; it7 = it7.right) {
78251
+ if (it7.countable && !it7.deleted && !live3.has(idKey(it7.id))) break;
78252
+ region.push(it7);
78253
+ }
78254
+ const words3 = new Set(owner.copy ? region.filter((it7) => !it7.deleted && it7.countable && !markerOf2(it7) && !left.has(`${idKey(it7.id)}+${it7.length}`) && homeOf(pd, homes, it7) === start12) : []);
78255
+ const covering = deletes.filter((record6) => region.some((it7) => it7.deleted && it7.countable && it7.id.client === record6.client && record6.clock < it7.id.clock + it7.length && it7.id.clock < record6.clock + record6.length));
78256
+ if (!words3.size && !covering.length) continue;
78257
+ const seen = owner.seen ?? new Map(entry.sv);
78258
+ const fresh = (client, clock) => clock >= (seen.get(client) ?? 0);
78259
+ const formats = words3.size ? formatsBefore(pd, start12) : null;
78260
+ let attrs = null;
78261
+ const units = [];
78262
+ const shown4 = /* @__PURE__ */ new Map();
78263
+ for (const it7 of region) {
78264
+ if (!it7.countable) {
78265
+ if (formats && it7.content instanceof C3 && (!it7.deleted || ae3(past, it7.id))) {
78266
+ if (it7.content.value === null) formats.delete(it7.content.key);
78267
+ else formats.set(it7.content.key, it7.content.value);
78268
+ attrs = null;
78269
+ }
78270
+ continue;
78271
+ }
78272
+ const item = it7.deleted ? null : live3.get(idKey(it7.id));
78273
+ const word = words3.has(it7);
78274
+ for (let offset = 0; offset < it7.length; offset++) {
78275
+ const id2 = { client: it7.id.client, clock: it7.id.clock + offset };
78276
+ const source3 = origins.resolve(id2);
78277
+ const key3 = idKey(source3);
78278
+ if (!(it7.deleted && covering.length && coversOriginal(covering, self2, id2))) shown4.set(key3, true);
78279
+ else if (!shown4.has(key3) && (!owner.alive || fresh(id2.client, id2.clock) || owner.alive.has(idKey(id2)))) shown4.set(key3, false);
78280
+ units.push({ it: it7, item, offset, id: id2, source: source3, key: key3, attrs: word ? attrs ??= Object.fromEntries(formats) : null });
78281
+ }
78282
+ }
78283
+ map ??= createProjectionMap(walked, pd.flow.length);
78284
+ const target = targetOf2(pd, origins, walked, map, entry.blockId);
78285
+ if (!target) {
78286
+ for (const it7 of words3) left.add(`${idKey(it7.id)}+${it7.length}`);
78287
+ continue;
78288
+ }
78289
+ if (covering.length) {
78290
+ for (const [key3, place6] of target.places) if (shown4.get(key3) === false && !removed.has(place6)) removed.set(place6, null);
78291
+ }
78292
+ const groups = /* @__PURE__ */ new Map();
78293
+ let at8 = target.head + 1;
78294
+ for (const unit of units) {
78295
+ const { it: it7, item, offset, id: id2, source: source3 } = unit;
78296
+ if (unit.attrs) {
78297
+ if (!taken2.has(idKey(id2)) && !(visible ??= visibleOriginIndex(pd.flow, walked, origins))(source3.client, source3.clock)) {
78298
+ taken2.add(idKey(id2));
78299
+ removed.set(item.at + offset, owner);
78300
+ if (owner.step && !folds.has(owner)) folds.set(owner, { deleted: [], inserted: [] });
78301
+ const group = groups.get(at8) ?? groups.set(at8, []).get(at8);
78302
+ group.push(item.kind === "text" ? { ch: it7.content.str[offset], attrs: unit.attrs, source: source3 } : { embed: it7.content.embed, attrs: unit.attrs, source: source3 });
78303
+ continue;
78304
+ }
78305
+ left.add(`${idKey(it7.id)}+${it7.length}`);
78306
+ }
78307
+ const place6 = target.places.get(unit.key);
78308
+ if (place6 !== void 0) at8 = place6 + 1;
78309
+ }
78310
+ for (const [place6, list3] of groups) inserts.push({ at: place6, units: list3, owner });
78311
+ }
78312
+ if (!removed.size && !inserts.length) return false;
78313
+ const ops = [...[...removed].map(([at8, owner]) => ({ at: at8, owner })), ...inserts].sort((a2, b7) => b7.at - a2.at || (a2.units ? 1 : 0) - (b7.units ? 1 : 0));
78314
+ pd.ydoc.transact((tr4) => {
78315
+ let run5 = null;
78316
+ const cut2 = () => {
78317
+ if (!run5) return;
78318
+ const fold = folds.get(run5.owner);
78319
+ const sizes = fold ? new Map([...tr4.deleteSet.clients].map(([client, ranges]) => [client, ranges.length])) : null;
78320
+ pd.flow.delete(run5.from, run5.to - run5.from);
78321
+ if (fold) for (const [client, ranges] of tr4.deleteSet.clients) for (const { clock, len } of ranges.slice(sizes.get(client) ?? 0)) {
78322
+ const struct = Zt3(pd.ydoc.store, { client, clock });
78323
+ if (struct instanceof b3) struct.keep = true;
78324
+ fold.deleted.push({ client, clock, len });
78325
+ }
78326
+ run5 = null;
78327
+ };
78328
+ for (const op of ops) {
78329
+ if (!op.units) {
78330
+ if (run5 && op.at === run5.from - 1 && op.owner === run5.owner) run5.from = op.at;
78331
+ else {
78332
+ cut2();
78333
+ run5 = { from: op.at, to: op.at + 1, owner: op.owner };
78334
+ }
78335
+ continue;
78336
+ }
78337
+ cut2();
78338
+ const before = _2(pd.ydoc.store, self2);
78339
+ let cursor = op.at, text6 = "", attrs = null;
78340
+ const put4 = () => {
78341
+ if (!text6) return;
78342
+ const chars = text6;
78343
+ beforeFence(pd, cursor, walked.fences, () => pd.flow.insert(cursor, chars, { ...attrs }));
78344
+ cursor += chars.length;
78345
+ text6 = "";
78346
+ };
78347
+ for (const unit of op.units) {
78348
+ if (unit.ch === void 0) {
78349
+ put4();
78350
+ beforeFence(pd, cursor, walked.fences, () => pd.flow.insertEmbed(cursor, { ...unit.embed }, { ...unit.attrs }));
78351
+ cursor += 1;
78352
+ continue;
78353
+ }
78354
+ if (text6 && attrsKey(unit.attrs) !== attrsKey(attrs)) put4();
78355
+ attrs = unit.attrs;
78356
+ text6 += unit.ch;
78357
+ }
78358
+ put4();
78359
+ folds.get(op.owner)?.inserted.push({ client: self2, clock: before, len: _2(pd.ydoc.store, self2) - before });
78360
+ const dest = unitIds(pd.flow, op.at, cursor);
78361
+ if (dest.length !== op.units.length) throw new Error(`Carried ${dest.length} units instead of ${op.units.length}`);
78362
+ origins.recordSpans(dest.map((id2, i2) => ({ dest: id2, source: op.units[i2].source })));
78363
+ placed2.push({ ids: dest, step: op.owner.step });
78364
+ }
78365
+ cut2();
78366
+ }, CARRY);
78367
+ for (const [{ step }, fold] of folds) {
78368
+ step.deletions = te3([step.deletions, rangesOf2(fold.deleted)]);
78369
+ step.insertions = te3([step.insertions, rangesOf2(fold.inserted)]);
78370
+ }
78371
+ return true;
78372
+ }
78373
+ function createMoveCarry({ pd, origins, um, walked }) {
78374
+ const owned2 = /* @__PURE__ */ new Map();
78375
+ const shown4 = /* @__PURE__ */ new Map();
78376
+ const homes = /* @__PURE__ */ new WeakMap();
78377
+ let flip = null;
78378
+ let placed2 = [];
78379
+ const run5 = (flipped = null, records3 = false) => owned2.size > 0 && carryAcross({ pd, origins, walked: walked(), placed: placed2 }, owned2, homes, flipped, records3);
78380
+ return {
78381
+ note(t2) {
78382
+ const keys2 = [...t2.changed.get(pd.gone) ?? []].filter((key3) => typeof key3 === "string");
78383
+ if (!keys2.some((key3) => key3.startsWith(COPY_ACTIVE_KEYS))) return;
78384
+ const hidden = /* @__PURE__ */ new Set();
78385
+ const past = rangesOf2([...t2.deleteSet.clients].flatMap(([client, ranges]) => ranges.map(({ clock, len }) => ({ client, clock, len }))));
78386
+ for (const key3 of keys2) {
78387
+ const copy13 = key3.startsWith(COPY_ACTIVE_KEYS);
78388
+ if (!copy13 && !key3.startsWith(REMOVE_KEYS)) continue;
78389
+ if (pd.gone.has(key3) === copy13) {
78390
+ owned2.delete(key3);
78391
+ if (!copy13) shown4.set(key3, { seen: t2.afterState, alive: liveIn(pd, JSON.parse(key3)[1]) });
78392
+ continue;
78393
+ }
78394
+ hidden.add(key3);
78395
+ owned2.set(key3, { copy: copy13, left: /* @__PURE__ */ new Set(), past, seen: null, alive: null, step: null, ...copy13 ? null : shown4.get(key3) });
78396
+ }
78397
+ if (hidden.size) flip = hidden;
78398
+ },
78399
+ replay(direction) {
78400
+ const pending8 = direction === "undo" ? um.undoStack : um.redoStack;
78401
+ for (let i2 = pending8.length - 1; i2 >= 0; i2--) {
78402
+ followStep(pd, origins, pending8[i2]);
78403
+ if (acts(pd, pending8[i2])) break;
78404
+ }
78405
+ const inverse = direction === "undo" ? um.redoStack : um.undoStack;
78406
+ const size = inverse.length;
78407
+ flip = null;
78408
+ if (um[direction]() === null) return false;
78409
+ const flipped = flip;
78410
+ flip = null;
78411
+ if (flipped && inverse.length > size) for (const key3 of flipped) owned2.get(key3).step = inverse[inverse.length - 1];
78412
+ run5(flipped);
78413
+ return true;
78414
+ },
78415
+ received(transactions) {
78416
+ if (!owned2.size && !placed2.length) return;
78417
+ let late = false, records3 = false;
78418
+ for (const t2 of transactions) {
78419
+ if (t2.local) continue;
78420
+ late = true;
78421
+ for (const key3 of t2.changed.get(pd.gone) ?? []) if (typeof key3 === "string" && key3.startsWith(TEXT_DELETE_KEYS)) records3 = true;
78422
+ }
78423
+ if (!late) return;
78424
+ run5(null, records3);
78425
+ if (placed2.length) placed2 = reseat(pd, origins, walked(), placed2);
78426
+ }
78427
+ };
78428
+ }
78429
+ var refuse6, attrsKey, visibleBlocks, ancestors, isAncestor, inSubtree, setAttr, setParent, MAX_INDENT2, ATTR_RULES, attrChanges, flowUnits, liveRemovals, CARRY, COPY_ACTIVE_KEYS, REMOVE_KEYS, TEXT_DELETE_KEYS, startOf2, targetOf2, formatsBefore, rangesOf2, markerOf2, homeOf, eachUnit, recorded, gone, followStep, holds3, cutIn, reseat, acts, liveIn;
78025
78430
  var init_moves2 = __esm({
78026
78431
  "src/page/ybind/moves.js"() {
78027
78432
  init_yjs_vendor();
@@ -78131,6 +78536,249 @@ ${mark2}`;
78131
78536
  }
78132
78537
  return out;
78133
78538
  };
78539
+ CARRY = "blockeditor-move-carry";
78540
+ COPY_ACTIVE_KEYS = `["${COPY_ACTIVE}",`;
78541
+ REMOVE_KEYS = `["${REMOVE}",`;
78542
+ TEXT_DELETE_KEYS = `["${TEXT_DELETE}",`;
78543
+ startOf2 = (pd, sourceKey) => {
78544
+ const id2 = parsePhysicalKey(sourceKey);
78545
+ if (!id2) return null;
78546
+ let it7 = null;
78547
+ try {
78548
+ it7 = Zt3(pd.ydoc.store, id2);
78549
+ } catch {
78550
+ return null;
78551
+ }
78552
+ return it7 instanceof b3 && !it7.deleted && it7.parent === pd.flow ? it7 : null;
78553
+ };
78554
+ targetOf2 = (pd, origins, walked, map, blockId) => {
78555
+ let cursor = 0, seg = null;
78556
+ for (const candidate of walked.visible) {
78557
+ if (candidate.id === blockId) {
78558
+ seg = candidate;
78559
+ break;
78560
+ }
78561
+ cursor += candidate.len;
78562
+ }
78563
+ if (!seg || seg.implicit || seg.atom || seg.opaque || !seg.brk) return null;
78564
+ const places = /* @__PURE__ */ new Map();
78565
+ let head = null;
78566
+ for (const [from, to3] of map.physicalRanges(cursor, cursor + seg.len)) {
78567
+ const ids = unitIds(pd.flow, from, to3);
78568
+ for (let i2 = 0; i2 < ids.length; i2++) {
78569
+ if (head === null) head = from;
78570
+ else places.set(idKey(origins.resolve(ids[i2])), from + i2);
78571
+ }
78572
+ }
78573
+ return head === null ? null : { head, places };
78574
+ };
78575
+ formatsBefore = (pd, stop7) => {
78576
+ const out = /* @__PURE__ */ new Map();
78577
+ for (let it7 = pd.flow._start; it7 && it7 !== stop7; it7 = it7.right) {
78578
+ if (it7.deleted || !(it7.content instanceof C3)) continue;
78579
+ if (it7.content.value === null) out.delete(it7.content.key);
78580
+ else out.set(it7.content.key, it7.content.value);
78581
+ }
78582
+ return out;
78583
+ };
78584
+ rangesOf2 = (ranges) => {
78585
+ const set3 = Rr();
78586
+ for (const { client, clock, len } of ranges) (set3.clients.get(client) ?? set3.clients.set(client, []).get(client)).push({ clock, len });
78587
+ return set3;
78588
+ };
78589
+ markerOf2 = (it7) => it7.content instanceof wt2 && it7.content.embed?.b !== void 0;
78590
+ homeOf = (pd, homes, it7) => {
78591
+ const path = [];
78592
+ let at8 = it7, home = null;
78593
+ for (; ; ) {
78594
+ const known3 = homes.get(at8);
78595
+ if (known3 !== void 0) {
78596
+ home = known3;
78597
+ break;
78598
+ }
78599
+ path.push(at8);
78600
+ let next = null;
78601
+ if (at8.origin) try {
78602
+ next = Zt3(pd.ydoc.store, at8.origin);
78603
+ } catch {
78604
+ next = null;
78605
+ }
78606
+ if (!(next instanceof b3)) break;
78607
+ if (markerOf2(next)) {
78608
+ home = next;
78609
+ break;
78610
+ }
78611
+ at8 = next;
78612
+ }
78613
+ for (const item of path) homes.set(item, home);
78614
+ return home;
78615
+ };
78616
+ eachUnit = (pd, set3, f3) => {
78617
+ for (const [client, ranges] of set3.clients) for (const { clock, len } of ranges) {
78618
+ for (let at8 = clock; at8 < clock + len; ) {
78619
+ let it7 = null;
78620
+ try {
78621
+ it7 = Zt3(pd.ydoc.store, { client, clock: at8 });
78622
+ } catch {
78623
+ break;
78624
+ }
78625
+ const end2 = Math.min(clock + len, it7.id.clock + it7.length);
78626
+ if (it7 instanceof b3 && it7.parent === pd.flow && it7.countable) for (let unit = at8; unit < end2; unit++) f3(it7, { client, clock: unit });
78627
+ at8 = end2;
78628
+ }
78629
+ }
78630
+ };
78631
+ recorded = (records3, id2) => records3.some((record6) => record6.client === id2.client && id2.clock >= record6.clock && id2.clock < record6.clock + record6.length);
78632
+ gone = (pd, id2) => {
78633
+ try {
78634
+ return Zt3(pd.ydoc.store, id2).deleted;
78635
+ } catch {
78636
+ return true;
78637
+ }
78638
+ };
78639
+ followStep = (pd, origins, step) => {
78640
+ const dead = [];
78641
+ eachUnit(pd, step.insertions, (it7, id2) => {
78642
+ if (it7.deleted) dead.push(id2);
78643
+ });
78644
+ if (!dead.length) return;
78645
+ const records3 = parseGoneIntents(pd.gone).textDeletes;
78646
+ const words3 = /* @__PURE__ */ new Map();
78647
+ for (const id2 of dead) {
78648
+ const source3 = origins.resolve(id2);
78649
+ const word = words3.get(idKey(source3)) ?? words3.set(idKey(source3), { source: source3, follow: false, redo: [] }).get(idKey(source3));
78650
+ if (!word.follow && !recorded(records3, id2) && gone(pd, source3)) word.follow = true;
78651
+ }
78652
+ eachUnit(pd, step.deletions, (it7, id2) => words3.get(idKey(origins.resolve(id2)))?.redo.push(id2));
78653
+ const wanted = /* @__PURE__ */ new Map();
78654
+ for (const word of words3.values()) {
78655
+ if (!word.follow && !word.redo.length) continue;
78656
+ word.lives = [];
78657
+ (wanted.get(word.source.client) ?? wanted.set(word.source.client, []).get(word.source.client)).push(word);
78658
+ }
78659
+ if (!wanted.size) return;
78660
+ for (let it7 = pd.flow._start; it7; it7 = it7.right) {
78661
+ if (it7.deleted || !it7.countable) continue;
78662
+ let at8 = it7.id.clock;
78663
+ for (const piece of origins.resolveRange(it7.id.client, it7.id.clock, it7.length)) {
78664
+ for (const word of wanted.get(piece.client) ?? []) {
78665
+ const offset = word.source.clock - piece.clock;
78666
+ if (offset >= 0 && offset < piece.length) word.lives.push({ client: it7.id.client, clock: at8 + offset, len: 1 });
78667
+ }
78668
+ at8 += piece.length;
78669
+ }
78670
+ }
78671
+ const adds = [];
78672
+ for (const list3 of wanted.values()) for (const word of list3) {
78673
+ if (word.follow) adds.push(...word.lives);
78674
+ if (!word.lives.length) for (const id2 of word.redo) adds.push({ client: id2.client, clock: id2.clock, len: 1 });
78675
+ }
78676
+ if (adds.length) step.insertions = te3([step.insertions, rangesOf2(adds)]);
78677
+ };
78678
+ holds3 = (it7, id2) => id2 !== null && it7.id.client === id2.client && id2.clock >= it7.id.clock && id2.clock < it7.id.clock + it7.length;
78679
+ cutIn = (pd, ids) => {
78680
+ let item;
78681
+ try {
78682
+ item = Zt3(pd.ydoc.store, ids[0]);
78683
+ } catch {
78684
+ return null;
78685
+ }
78686
+ if (item.id.clock !== ids[0].clock || !item.origin) return null;
78687
+ const between = [item];
78688
+ let edge = null;
78689
+ for (let it7 = item.left; it7 && !holds3(it7, item.origin); it7 = it7.left) {
78690
+ if (markerOf2(it7) && it7.id.client !== pd.ydoc.clientID && !between.some((other) => holds3(other, it7.rightOrigin))) edge = it7;
78691
+ between.push(it7);
78692
+ }
78693
+ return edge;
78694
+ };
78695
+ reseat = (pd, origins, walked, placed2) => {
78696
+ const kept2 = [], moved = [];
78697
+ for (const group of placed2) {
78698
+ const live3 = group.ids.filter((id2) => !gone(pd, id2));
78699
+ if (!live3.length) continue;
78700
+ const edge = cutIn(pd, group.ids);
78701
+ if (edge) moved.push({ group, edge, live: new Set(live3.map(idKey)) });
78702
+ else kept2.push(group);
78703
+ }
78704
+ if (!moved.length) return placed2;
78705
+ const self2 = pd.ydoc.clientID;
78706
+ pd.ydoc.transact(() => {
78707
+ for (const { group, edge, live: live3 } of moved) {
78708
+ const formats = /* @__PURE__ */ new Map();
78709
+ const units = [];
78710
+ let at8 = 0;
78711
+ for (let it7 = pd.flow._start; it7; it7 = it7.right) {
78712
+ if (it7.content instanceof C3) {
78713
+ if (!it7.deleted) {
78714
+ if (it7.content.value === null) formats.delete(it7.content.key);
78715
+ else formats.set(it7.content.key, it7.content.value);
78716
+ }
78717
+ continue;
78718
+ }
78719
+ if (it7.deleted || !it7.countable) continue;
78720
+ for (let offset = 0; offset < it7.length; offset++) {
78721
+ const id2 = { client: it7.id.client, clock: it7.id.clock + offset };
78722
+ if (live3.has(idKey(id2))) units.push({ at: at8 + offset, ch: it7.content instanceof nt3 ? it7.content.str[offset] : void 0, embed: it7.content.embed, attrs: Object.fromEntries(formats), source: origins.resolve(id2) });
78723
+ }
78724
+ at8 += it7.length;
78725
+ }
78726
+ for (let i2 = units.length - 1; i2 >= 0; i2--) pd.flow.delete(units[i2].at, 1);
78727
+ let cursor = 0;
78728
+ for (let it7 = pd.flow._start; it7 && it7 !== edge; it7 = it7.right) if (!it7.deleted && it7.countable) cursor += it7.length;
78729
+ const start12 = cursor;
78730
+ const before = _2(pd.ydoc.store, self2);
78731
+ const fences = [...walked.fences, edge.id];
78732
+ for (const unit of units) {
78733
+ if (unit.ch === void 0) beforeFence(pd, cursor, fences, () => pd.flow.insertEmbed(cursor, { ...unit.embed }, { ...unit.attrs }));
78734
+ else beforeFence(pd, cursor, fences, () => pd.flow.insert(cursor, unit.ch, { ...unit.attrs }));
78735
+ cursor += 1;
78736
+ }
78737
+ const dest = unitIds(pd.flow, start12, cursor);
78738
+ if (dest.length !== units.length) throw new Error(`Moved ${dest.length} carried units instead of ${units.length}`);
78739
+ origins.recordSpans(dest.map((id2, i2) => ({ dest: id2, source: units[i2].source })));
78740
+ if (group.step) group.step.insertions = te3([group.step.insertions, rangesOf2([{ client: self2, clock: before, len: _2(pd.ydoc.store, self2) - before }])]);
78741
+ kept2.push({ ids: dest, step: group.step });
78742
+ }
78743
+ }, CARRY);
78744
+ return kept2;
78745
+ };
78746
+ acts = (pd, step) => {
78747
+ const store2 = pd.ydoc.store;
78748
+ for (const [client, ranges] of step.insertions.clients) for (const { clock, len } of ranges) {
78749
+ for (let at8 = clock; at8 < clock + len; ) {
78750
+ let it7;
78751
+ try {
78752
+ it7 = Zt3(store2, { client, clock: at8 });
78753
+ } catch {
78754
+ break;
78755
+ }
78756
+ let live3 = it7;
78757
+ while (live3 instanceof b3 && live3.redone) {
78758
+ try {
78759
+ live3 = Zt3(store2, live3.redone);
78760
+ } catch {
78761
+ break;
78762
+ }
78763
+ }
78764
+ if (live3 instanceof b3 && !live3.deleted) return true;
78765
+ at8 = it7.id.clock + it7.length;
78766
+ }
78767
+ }
78768
+ for (const [client, ranges] of step.deletions.clients) for (const { clock } of ranges) {
78769
+ if (!ae3(step.insertions, { client, clock })) return true;
78770
+ }
78771
+ return false;
78772
+ };
78773
+ liveIn = (pd, sourceKey) => {
78774
+ const live3 = /* @__PURE__ */ new Set();
78775
+ for (let it7 = startOf2(pd, sourceKey)?.right ?? null; it7; it7 = it7.right) {
78776
+ if (!it7.countable || it7.deleted) continue;
78777
+ if (markerOf2(it7)) break;
78778
+ for (let offset = 0; offset < it7.length; offset++) live3.add(idKey({ client: it7.id.client, clock: it7.id.clock + offset }));
78779
+ }
78780
+ return live3;
78781
+ };
78134
78782
  }
78135
78783
  });
78136
78784
 
@@ -78231,7 +78879,7 @@ ${mark2}`;
78231
78879
  return source3.client !== item.id.client || source3.clock !== item.id.clock || origins.boundaryOf(item.id)?.kind !== "copy";
78232
78880
  }
78233
78881
  });
78234
- const offOrigins = installUndoOrigins(pd, um, origins, (gone) => parseGoneIntents(gone).textDeletes);
78882
+ const offOrigins = installUndoOrigins(pd, um, origins, (gone2) => parseGoneIntents(gone2).textDeletes);
78235
78883
  const notified = /* @__PURE__ */ new Set();
78236
78884
  const localTokens = new Set(authorToken ? [...ownedTokens, authorToken] : ownedTokens);
78237
78885
  let registerAuthor = authorToken ? () => {
@@ -78401,7 +79049,9 @@ ${b7}`);
78401
79049
  }
78402
79050
  const tr4 = view3.state.tr.replace(d2.start, d2.endA, derived2.slice(d2.start, d2.endB)).setMeta(REMOTE_META, true).setMeta("addToHistory", false);
78403
79051
  if (own) tr4.setMeta("yundo", true);
78404
- if (keep4) {
79052
+ if (own && view3.state.doc.textContent !== derived2.textContent && document.activeElement?.closest?.('[contenteditable]:not([contenteditable="false"])')) {
79053
+ tr4.setSelection(Oi2.Selection.near(tr4.doc.resolve(Math.min(d2.endB, tr4.doc.content.size)), -1));
79054
+ } else if (keep4) {
78405
79055
  const hiddenUnit = (y6) => y6 >= 0 && w6.holes.some((hole) => y6 >= yBefore(w6.holes, hole.at) && y6 < yAfter(w6.holes, hole.at));
78406
79056
  const placeIn2 = (id2, offset) => {
78407
79057
  let found = null;
@@ -78442,12 +79092,14 @@ ${b7}`);
78442
79092
  began.set(t2, docVersion);
78443
79093
  docVersion++;
78444
79094
  };
79095
+ const carry = createMoveCarry({ pd, origins, um, walked: () => currentWalk() ?? walk(pd, origins) });
78445
79096
  const onTransaction = (t2) => {
78446
79097
  if (unchanged(t2)) {
78447
79098
  idle2.add(t2);
78448
79099
  if (walkedAt === began.get(t2) && docVersion === walkedAt + 1) walkedAt = docVersion;
78449
79100
  return;
78450
79101
  }
79102
+ if (t2.origin === um) carry.note(t2);
78451
79103
  deltas++;
78452
79104
  delta = deltas === 1 ? captureDelta(pd, t2, w6) : null;
78453
79105
  };
@@ -78471,7 +79123,7 @@ ${b7}`);
78471
79123
  saved2 = { anchor: end2(sel.$anchor), head: end2(sel.$head) };
78472
79124
  };
78473
79125
  const onAfter = (t2) => {
78474
- if (t2.origin !== LOCAL3) {
79126
+ if (t2.origin !== LOCAL3 && !unchanged(t2)) {
78475
79127
  lastIntent = null;
78476
79128
  groupOpen = false;
78477
79129
  }
@@ -78490,6 +79142,7 @@ ${b7}`);
78490
79142
  }
78491
79143
  if (!view3) {
78492
79144
  bumpRecovery();
79145
+ carry.received(transactions);
78493
79146
  return;
78494
79147
  }
78495
79148
  if (local3) {
@@ -78497,6 +79150,7 @@ ${b7}`);
78497
79150
  return;
78498
79151
  }
78499
79152
  render4(own);
79153
+ carry.received(transactions);
78500
79154
  };
78501
79155
  const portMove = (tr4, move2) => {
78502
79156
  const result2 = moveBlocks({ pd, view: view3, um, origins, render: render4, walked: currentWalk() }, move2);
@@ -78595,7 +79249,7 @@ ${b7}`);
78595
79249
  registerAuthor = null;
78596
79250
  const intent = history3 ? intentOf(local3, view3) : null;
78597
79251
  const join = groupOpen && continuesGroup(lastIntent, intent);
78598
- lastIntent = intent;
79252
+ lastIntent = !join && intent?.breakAfter && !intent.text.trim() ? { ...intent, breakAfter: false } : intent;
78599
79253
  joining = join;
78600
79254
  try {
78601
79255
  localGroup(pd, local3, w6, stats2, um, history3, register3, { join, open: intent !== null });
@@ -78656,10 +79310,10 @@ ${b7}`);
78656
79310
  return moveBlocks({ pd, view: view3, um, origins, render: render4, walked: currentWalk() }, args);
78657
79311
  },
78658
79312
  undo() {
78659
- return um.undo() !== null;
79313
+ return carry.replay("undo");
78660
79314
  },
78661
79315
  redo() {
78662
- return um.redo() !== null;
79316
+ return carry.replay("redo");
78663
79317
  }
78664
79318
  };
78665
79319
  }
@@ -78858,7 +79512,7 @@ ${b7}`);
78858
79512
  function flushExit({ permit, deadline, keepalive, signal, timeoutMs }) {
78859
79513
  const end2 = Math.min(deadline ?? Infinity, Date.now() + timeoutMs);
78860
79514
  const over = () => signal?.aborted || Date.now() >= end2;
78861
- return new Promise((resolve2) => {
79515
+ return new Promise((resolve3) => {
78862
79516
  let done = false, timer = null, wake = null;
78863
79517
  const waiter = {
78864
79518
  check() {
@@ -78870,7 +79524,7 @@ ${b7}`);
78870
79524
  waiters.delete(waiter);
78871
79525
  clearTimer(timer);
78872
79526
  signal?.removeEventListener("abort", aborted);
78873
- resolve2(result2);
79527
+ resolve3(result2);
78874
79528
  }
78875
79529
  };
78876
79530
  const aborted = () => waiter.finish({ ok: false, code: "timeout" });
@@ -78919,7 +79573,7 @@ ${b7}`);
78919
79573
  function flush({ permit = null, deadline: exitDeadline = null, keepalive = false, signal = null, timeoutMs = 1e4 } = {}) {
78920
79574
  if (disposed) return Promise.resolve({ ok: false, code: "disposed" });
78921
79575
  if (permit) return flushExit({ permit, deadline: exitDeadline, keepalive, signal, timeoutMs });
78922
- return new Promise((resolve2) => {
79576
+ return new Promise((resolve3) => {
78923
79577
  const deadline = Date.now() + timeoutMs;
78924
79578
  let done = false, checking = false, checkpointing = false, timer = null;
78925
79579
  const waiter = { check, finish: finish3 };
@@ -78928,7 +79582,7 @@ ${b7}`);
78928
79582
  done = true;
78929
79583
  waiters.delete(waiter);
78930
79584
  clearTimer(timer);
78931
- resolve2(result2);
79585
+ resolve3(result2);
78932
79586
  }
78933
79587
  function check() {
78934
79588
  if (done || checking || checkpointing) return;
@@ -79216,6 +79870,7 @@ ${b7}`);
79216
79870
  canon: () => canon,
79217
79871
  classifyFile: () => classifyFile,
79218
79872
  createFeatureLoader: () => createFeatureLoader,
79873
+ createHistoryBridge: () => createHistoryBridge,
79219
79874
  createRecoverList: () => createRecoverList,
79220
79875
  createYPageBinding: () => createYPageBinding,
79221
79876
  focusBlock: () => focusBlock,
@@ -79241,6 +79896,7 @@ ${b7}`);
79241
79896
  init_provider();
79242
79897
  init_migrate();
79243
79898
  init_chrome();
79899
+ init_history_intent();
79244
79900
  init_recover();
79245
79901
  init_document_title_runtime();
79246
79902
  init_feature_loader();
@@ -79515,8 +80171,8 @@ ${b7}`);
79515
80171
  names: names2,
79516
80172
  // The next record this journal commits, or null when the store refuses one or the
79517
80173
  // session closes: the destination a copy names is only real once it is on this device.
79518
- next: () => new Promise((resolve2) => {
79519
- awaiting.push(resolve2);
80174
+ next: () => new Promise((resolve3) => {
80175
+ awaiting.push(resolve3);
79520
80176
  }),
79521
80177
  // Does the work this journal holds carry exactly this block's text? The episode's own
79522
80178
  // base is here, so the answer needs no store and no page.
@@ -79566,7 +80222,7 @@ ${b7}`);
79566
80222
  return resolved;
79567
80223
  });
79568
80224
  function settle9(value) {
79569
- for (const resolve2 of awaiting.splice(0)) resolve2(value);
80225
+ for (const resolve3 of awaiting.splice(0)) resolve3(value);
79570
80226
  }
79571
80227
  function retire(list3) {
79572
80228
  for (const item of list3 || []) {
@@ -81308,8 +81964,8 @@ ${b7}`);
81308
81964
  if (active4) discard(active4);
81309
81965
  const requestId = newId4();
81310
81966
  const candidate = { requestId, discarded: false, done: false };
81311
- candidate.promise = new Promise((resolve2) => {
81312
- candidate.resolve = resolve2;
81967
+ candidate.promise = new Promise((resolve3) => {
81968
+ candidate.resolve = resolve3;
81313
81969
  });
81314
81970
  active4 = candidate;
81315
81971
  const request4 = { protocol: "blockeditor-tool/1", requestId, prompt, context: trimmed, target, current: current5 };
@@ -82238,11 +82894,11 @@ ${b7}`);
82238
82894
  }, LOADING_MS);
82239
82895
  }
82240
82896
  function whenPresent(get5, ms4) {
82241
- return new Promise((resolve2) => {
82897
+ return new Promise((resolve3) => {
82242
82898
  const start12 = Date.now();
82243
82899
  const tick = () => {
82244
82900
  const value = get5();
82245
- if (value || Date.now() - start12 >= ms4) resolve2(value || null);
82901
+ if (value || Date.now() - start12 >= ms4) resolve3(value || null);
82246
82902
  else setTimeout(tick, 50);
82247
82903
  };
82248
82904
  tick();
@@ -82384,6 +83040,19 @@ ${doc.documentElement.outerHTML}`);
82384
83040
  inst.listeners.push([type, handler]);
82385
83041
  }
82386
83042
  function pageHistory(inst) {
83043
+ if (paged()) {
83044
+ const history3 = window.clay.undo;
83045
+ return {
83046
+ undo: () => history3.undo(),
83047
+ redo: () => history3.redo(),
83048
+ get canUndo() {
83049
+ return !!history3.canUndo;
83050
+ },
83051
+ get canRedo() {
83052
+ return !!history3.canRedo;
83053
+ }
83054
+ };
83055
+ }
82387
83056
  const binding = inst?.binding;
82388
83057
  const um = binding?.bridge?.um;
82389
83058
  if (!binding || !um) return null;
@@ -82408,6 +83077,7 @@ ${doc.documentElement.outerHTML}`);
82408
83077
  };
82409
83078
  }
82410
83079
  function notifyHistory(inst) {
83080
+ if (paged()) return;
82411
83081
  const history3 = pageHistory(inst);
82412
83082
  document.dispatchEvent(new CustomEvent("clay:undo-change", {
82413
83083
  detail: { canUndo: !!history3?.canUndo, canRedo: !!history3?.canRedo }
@@ -82722,8 +83392,8 @@ ${doc.documentElement.outerHTML}`);
82722
83392
  let toolsOpening = null;
82723
83393
  let chrome = null;
82724
83394
  let setEditorActive2 = null;
82725
- const editorReady = new Promise((resolve2) => {
82726
- editorReadyResolve = resolve2;
83395
+ const editorReady = new Promise((resolve3) => {
83396
+ editorReadyResolve = resolve3;
82727
83397
  });
82728
83398
  inst.editorReadyResolve = editorReadyResolve;
82729
83399
  addDisposer(inst, () => editorReadyResolve?.());
@@ -82987,7 +83657,9 @@ ${doc.documentElement.outerHTML}`);
82987
83657
  install: async (id2, mod) => {
82988
83658
  if (!editorView) await editorReady;
82989
83659
  if (!isCurrent(inst2) || !editorView) return null;
82990
- const context2 = { view: editorView, upload: isDraftMode ? draftUpload : options.upload, board: binding.board, undo: binding.undo, redo: binding.redo, revise: aiRequested() ? (toolId) => {
83660
+ const undo2 = () => paged() ? window.clay.undo.undo() : binding.undo();
83661
+ const redo = () => paged() ? window.clay.undo.redo() : binding.redo();
83662
+ const context2 = { view: editorView, upload: isDraftMode ? draftUpload : options.upload, board: binding.board, undo: undo2, redo, revise: aiRequested() ? (toolId) => {
82991
83663
  openAi({ target: { toolId } });
82992
83664
  } : null };
82993
83665
  if (id2 === "tool") {
@@ -83163,8 +83835,8 @@ ${doc.documentElement.outerHTML}`);
83163
83835
  doc: binding.doc(),
83164
83836
  dispatch: binding.dispatch,
83165
83837
  history: false,
83166
- undo: binding.undo,
83167
- redo: binding.redo,
83838
+ undo: () => paged() ? window.clay.undo.undo() : binding.undo(),
83839
+ redo: () => paged() ? window.clay.undo.redo() : binding.redo(),
83168
83840
  board: binding.board,
83169
83841
  editable: false,
83170
83842
  features,
@@ -83218,6 +83890,16 @@ ${doc.documentElement.outerHTML}`);
83218
83890
  loaded2.refreshView?.(view3);
83219
83891
  binding.attach(view3);
83220
83892
  const um = binding.bridge?.um;
83893
+ if (um) {
83894
+ const bridge = pageCode.createHistoryBridge({
83895
+ um,
83896
+ undo: () => binding.undo(),
83897
+ redo: () => binding.redo(),
83898
+ article,
83899
+ focus: () => inst2.view?.focus?.()
83900
+ });
83901
+ addDisposer(inst2, bridge.dispose);
83902
+ }
83221
83903
  if (um) {
83222
83904
  const notify = () => notifyHistory(inst2);
83223
83905
  um.on("stack-item-added", notify);
@@ -83236,9 +83918,20 @@ ${doc.documentElement.outerHTML}`);
83236
83918
  const previewIs = previewShown(next.state);
83237
83919
  if (previewIs === previewWas) return;
83238
83920
  previewWas = previewIs;
83921
+ if (paged()) {
83922
+ if (previewIs) inst2.releaseHold = window.clay.undo.hold();
83923
+ else {
83924
+ inst2.releaseHold?.();
83925
+ inst2.releaseHold = null;
83926
+ }
83927
+ }
83239
83928
  notifyHistory(inst2);
83240
83929
  }
83241
83930
  }));
83931
+ addDisposer(inst2, () => {
83932
+ inst2.releaseHold?.();
83933
+ inst2.releaseHold = null;
83934
+ });
83242
83935
  installAwareness(inst2, view3);
83243
83936
  editorReadyResolve();
83244
83937
  featuresReady = Promise.allSettled(loaded2.featureIds.map((id2) => features.ensure(id2)));
@@ -83272,7 +83965,7 @@ ${doc.documentElement.outerHTML}`);
83272
83965
  async function awaitWriterAdoption(inst2, found) {
83273
83966
  const code = await pageCodeReady();
83274
83967
  if (await roomHoldsArticle(inst2, found)) return { ok: true, outcome: "writer-adopts" };
83275
- return new Promise((resolve2) => {
83968
+ return new Promise((resolve3) => {
83276
83969
  let off = null;
83277
83970
  let timer = null;
83278
83971
  let done = false;
@@ -83283,7 +83976,7 @@ ${doc.documentElement.outerHTML}`);
83283
83976
  timer = null;
83284
83977
  off?.();
83285
83978
  off = null;
83286
- resolve2(result2);
83979
+ resolve3(result2);
83287
83980
  };
83288
83981
  addDisposer(inst2, () => finish3({ ok: false, cancelled: true }));
83289
83982
  off = inst2.store.onRebase((event) => {
@@ -83313,8 +84006,8 @@ ${doc.documentElement.outerHTML}`);
83313
84006
  lane.release("blockeditor");
83314
84007
  }
83315
84008
  let timer;
83316
- await Promise.race([pageWriterReady(), new Promise((resolve2) => {
83317
- timer = setTimeout(resolve2, WRITER_WAIT_MS);
84009
+ await Promise.race([pageWriterReady(), new Promise((resolve3) => {
84010
+ timer = setTimeout(resolve3, WRITER_WAIT_MS);
83318
84011
  })]);
83319
84012
  clearTimeout(timer);
83320
84013
  };
@@ -83581,7 +84274,7 @@ ${doc.documentElement.outerHTML}`);
83581
84274
  }
83582
84275
  };
83583
84276
  }
83584
- var ARTICLE_SEL, TAG_SEL, BLOCKED2, STORE_TEXT, RETRY_BOUND_MS, GENERIC_ERROR, GENERIC_OFFLINE, REPLACED_TEXT, TOO_LARGE_TEXT, VISITOR_MEDIA, draftUpload, CLIENT_KEY2, PAGE_FULL_MESSAGE, OVERWRITTEN_TEXT, REPLACED_HOLD, LOADING_MS, LOADING_TEXT, SESSION_HOLD, isPlainObject2, pageCode, pageCodeLoading, generation4, active2, ended2, WRITER_WAIT_MS, AI_EDIT_WAIT_MS, AI_UNAVAILABLE, showReplaced, showTooLarge, showFull, recoveryModules, page, page_default;
84277
+ var ARTICLE_SEL, TAG_SEL, BLOCKED2, STORE_TEXT, RETRY_BOUND_MS, GENERIC_ERROR, GENERIC_OFFLINE, REPLACED_TEXT, TOO_LARGE_TEXT, VISITOR_MEDIA, draftUpload, CLIENT_KEY2, PAGE_FULL_MESSAGE, OVERWRITTEN_TEXT, REPLACED_HOLD, LOADING_MS, LOADING_TEXT, SESSION_HOLD, isPlainObject2, pageCode, pageCodeLoading, generation4, active2, ended2, WRITER_WAIT_MS, AI_EDIT_WAIT_MS, AI_UNAVAILABLE, showReplaced, showTooLarge, showFull, paged, recoveryModules, page, page_default;
83585
84278
  var init_page = __esm({
83586
84279
  "src/plugins/page.js"() {
83587
84280
  init_registry();
@@ -83640,6 +84333,7 @@ ${doc.documentElement.outerHTML}`);
83640
84333
  dispatchState("blocked", code, PAGE_FULL_MESSAGE);
83641
84334
  stopWithNotice(inst, PAGE_FULL_MESSAGE, { reload: false });
83642
84335
  };
84336
+ paged = () => window.clay?.undo?.pageHistory === true;
83643
84337
  recoveryModules = null;
83644
84338
  page = {
83645
84339
  ready: null,
@@ -84226,14 +84920,14 @@ ${doc.documentElement.outerHTML}`);
84226
84920
  }
84227
84921
  return null;
84228
84922
  };
84229
- const syncAttributes = (live3, incoming, skip = null) => {
84923
+ const syncAttributes = (live3, incoming, skip2 = null) => {
84230
84924
  for (const { name, value } of [...incoming.attributes]) {
84231
- if (name === skip || live3.getAttribute(name) === value) continue;
84925
+ if (name === skip2 || live3.getAttribute(name) === value) continue;
84232
84926
  live3.setAttribute(name, value);
84233
84927
  changed2 = true;
84234
84928
  }
84235
84929
  for (const { name } of [...live3.attributes]) {
84236
- if (name === skip || incoming.hasAttribute(name)) continue;
84930
+ if (name === skip2 || incoming.hasAttribute(name)) continue;
84237
84931
  live3.removeAttribute(name);
84238
84932
  changed2 = true;
84239
84933
  }
@@ -84735,8 +85429,8 @@ ${doc.documentElement.outerHTML}`);
84735
85429
  return Promise.resolve(null);
84736
85430
  }
84737
85431
  if (represented2) return Promise.resolve(reader.represented);
84738
- return new Promise((resolve2) => {
84739
- settle5 = resolve2;
85432
+ return new Promise((resolve3) => {
85433
+ settle5 = resolve3;
84740
85434
  });
84741
85435
  }
84742
85436
  function followSync(represented2 = null) {
@@ -85769,7 +86463,7 @@ ${doc.documentElement.outerHTML}`);
85769
86463
  sortable: () => sortable,
85770
86464
  sortableParticipant: () => sortableParticipant
85771
86465
  });
85772
- function track2(record6, target, type, handler, options) {
86466
+ function track3(record6, target, type, handler, options) {
85773
86467
  const entry = { target, type, handler, options };
85774
86468
  target.addEventListener(type, handler, options);
85775
86469
  record6.listeners.push(entry);
@@ -85803,8 +86497,8 @@ ${doc.documentElement.outerHTML}`);
85803
86497
  function recordRuntimeAttrs(item) {
85804
86498
  return [item, ...item.querySelectorAll("*")].filter((el13) => !el13.closest(EDITOR_UI_SELECTOR)).map((el13) => [el13, RUNTIME_ATTRS2.map((name) => el13.getAttribute(name))]);
85805
86499
  }
85806
- function restoreRuntimeAttrs(recorded) {
85807
- for (const [el13, values] of recorded) {
86500
+ function restoreRuntimeAttrs(recorded2) {
86501
+ for (const [el13, values] of recorded2) {
85808
86502
  RUNTIME_ATTRS2.forEach((name, i2) => {
85809
86503
  const before = values[i2];
85810
86504
  const now3 = el13.getAttribute(name);
@@ -85916,7 +86610,7 @@ ${doc.documentElement.outerHTML}`);
85916
86610
  }
85917
86611
  finishMove(result2, onsortedCode);
85918
86612
  };
85919
- let recorded = null;
86613
+ let recorded2 = null;
85920
86614
  let press = null;
85921
86615
  let restoring2 = null;
85922
86616
  let started5 = false;
@@ -85929,8 +86623,8 @@ ${doc.documentElement.outerHTML}`);
85929
86623
  releaseMove(start12);
85930
86624
  };
85931
86625
  const restoreSoon = () => {
85932
- const pending8 = recorded;
85933
- recorded = null;
86626
+ const pending8 = recorded2;
86627
+ recorded2 = null;
85934
86628
  if (pending8) {
85935
86629
  record6.presses.delete(pending8);
85936
86630
  pressed.delete(pending8);
@@ -85953,18 +86647,18 @@ ${doc.documentElement.outerHTML}`);
85953
86647
  restoreSoon();
85954
86648
  later2(record6, endPress);
85955
86649
  };
85956
- track2(record6, sortableElem, "pointerdown", (event) => {
86650
+ track3(record6, sortableElem, "pointerdown", (event) => {
85957
86651
  let item = event.target instanceof Element ? event.target : null;
85958
86652
  while (item && item.parentElement !== sortableElem) item = item.parentElement;
85959
- if (!item || recorded) return;
85960
- recorded = recordRuntimeAttrs(item);
86653
+ if (!item || recorded2) return;
86654
+ recorded2 = recordRuntimeAttrs(item);
85961
86655
  press = beginMove(item);
85962
86656
  started5 = false;
85963
86657
  native = false;
85964
- record6.presses.add(recorded);
85965
- pressed.add(recorded);
85966
- ends = ENDS.map((type) => track2(record6, document, type, settleSoon, true));
85967
- ends.push(track2(record6, document, "dragstart", () => {
86658
+ record6.presses.add(recorded2);
86659
+ pressed.add(recorded2);
86660
+ ends = ENDS.map((type) => track3(record6, document, type, settleSoon, true));
86661
+ ends.push(track3(record6, document, "dragstart", () => {
85968
86662
  native = true;
85969
86663
  }, true));
85970
86664
  }, true);
@@ -87438,11 +88132,13 @@ ${doc.documentElement.outerHTML}`);
87438
88132
  async function keepRefusalNow(engine4, receipt3) {
87439
88133
  const ch = channel2();
87440
88134
  if (!ch) return { ok: false, code: "unavailable" };
87441
- let described = null;
87442
- try {
87443
- described = engine4?.describe?.(receipt3?.entryId) ?? null;
87444
- } catch (_7) {
87445
- described = null;
88135
+ let described = receipt3?.description ?? null;
88136
+ if (!described) {
88137
+ try {
88138
+ described = engine4?.describe?.(receipt3?.entryId) ?? null;
88139
+ } catch (_7) {
88140
+ described = null;
88141
+ }
87446
88142
  }
87447
88143
  if (!described) return { ok: false, code: "unknown-entry" };
87448
88144
  const refused5 = described.refused && typeof described.refused === "object" ? described.refused : {};
@@ -87464,7 +88160,8 @@ ${doc.documentElement.outerHTML}`);
87464
88160
  try {
87465
88161
  staged = ch.stage({ key: key3, kind: UNDO_KIND, baseEtag: representedEtag() ?? null, base: null, payload });
87466
88162
  } catch (err) {
87467
- console.error("clayjs: the refused step could not be kept for a later reload; it is still in this tab's history", err);
88163
+ const message2 = receipt3?.description ? "clayjs: the skipped step could not be kept for a later reload; its text is lost when this tab does" : "clayjs: the refused step could not be kept for a later reload; it is still in this tab's history";
88164
+ console.error(message2, err);
87468
88165
  return { ok: false, code: "error" };
87469
88166
  }
87470
88167
  const written = await ch.flush();
@@ -87538,9 +88235,41 @@ ${doc.documentElement.outerHTML}`);
87538
88235
  undo: () => undo,
87539
88236
  undoParticipant: () => undoParticipant
87540
88237
  });
88238
+ function resolve(root4, textOffset) {
88239
+ let left = Number(textOffset) || 0;
88240
+ if (left < 0) left = 0;
88241
+ const doc = root4.ownerDocument || document;
88242
+ const walker = doc.createTreeWalker(root4, 4);
88243
+ let last2 = null;
88244
+ for (let node = walker.nextNode(); node; node = walker.nextNode()) {
88245
+ if (left <= node.data.length) return { node, offset: left };
88246
+ left -= node.data.length;
88247
+ last2 = node;
88248
+ }
88249
+ return last2 ? { node: last2, offset: last2.data.length } : { node: root4, offset: root4.childNodes.length };
88250
+ }
88251
+ function hostOf3(node) {
88252
+ const element4 = node.nodeType === 1 ? node : node.parentElement;
88253
+ const host2 = element4?.closest?.(EDITABLE2);
88254
+ if (!host2 || !host2.isConnected) return null;
88255
+ if (typeof host2.checkVisibility === "function" && host2.checkVisibility() === false) return null;
88256
+ return host2;
88257
+ }
88258
+ function placeCaret(hint) {
88259
+ if (!hint) return;
88260
+ const at8 = hint.root ? resolve(hint.root, hint.textOffset) : hint;
88261
+ if (!at8?.node) return;
88262
+ const host2 = hostOf3(at8.node);
88263
+ if (!host2) return;
88264
+ if (typeof host2.scrollIntoView === "function") host2.scrollIntoView({ block: "nearest", inline: "nearest" });
88265
+ if (!document.activeElement?.closest?.(EDITABLE2)) return;
88266
+ if (document.activeElement !== host2) host2.focus({ preventScroll: true });
88267
+ document.getSelection()?.collapse(at8.node, at8.offset);
88268
+ }
87541
88269
  function keepsOwnHistory(node) {
87542
88270
  const policy = window.clay?.region?.resolveRegionPolicy;
87543
88271
  if (!policy || node.nodeType !== 1) return false;
88272
+ if (durableFormOf(node) !== void 0) return false;
87544
88273
  const own = policy(node);
87545
88274
  if (own.undoable !== false || own.persist === "none") return false;
87546
88275
  const parent = node.parentElement;
@@ -87606,7 +88335,7 @@ ${doc.documentElement.outerHTML}`);
87606
88335
  function bodyReady() {
87607
88336
  if (typeof document === "undefined") return Promise.resolve();
87608
88337
  if (document.readyState !== "loading") return Promise.resolve();
87609
- return new Promise((resolve2) => document.addEventListener("DOMContentLoaded", resolve2, { once: true }));
88338
+ return new Promise((resolve3) => document.addEventListener("DOMContentLoaded", resolve3, { once: true }));
87610
88339
  }
87611
88340
  function undoLease(record6) {
87612
88341
  return {
@@ -87614,18 +88343,29 @@ ${doc.documentElement.outerHTML}`);
87614
88343
  if (record6.started) return;
87615
88344
  record6.started = true;
87616
88345
  record6.admitted = true;
87617
- undo.start(withTabLocal({ bindKeys: true, ...recording ? { recording } : {} }));
88346
+ undo.start(withTabLocal({
88347
+ bindKeys: true,
88348
+ editableKeys: "page",
88349
+ ownKeysIn: [".blockeditor-editor"],
88350
+ typingBreak: "sentence",
88351
+ refused: "skip",
88352
+ holdReplay: () => holds4.size > 0,
88353
+ ...recording ? { recording } : {}
88354
+ }));
87618
88355
  for (const type of ["undo", "redo"]) {
87619
88356
  undo.on(type, afterReplay);
87620
88357
  record6.subscriptions.push({ type, handler: afterReplay });
87621
88358
  }
87622
88359
  undo.on("refused", refuse7);
87623
88360
  record6.subscriptions.push({ type: "refused", handler: refuse7 });
88361
+ undo.on("skipped", skip);
88362
+ record6.subscriptions.push({ type: "skipped", handler: skip });
87624
88363
  for (const type of HISTORY_EVENTS) {
87625
88364
  undo.on(type, announceChange);
87626
88365
  record6.subscriptions.push({ type, handler: announceChange });
87627
88366
  }
87628
88367
  announceChange();
88368
+ announceSession();
87629
88369
  },
87630
88370
  quiesce() {
87631
88371
  if (!record6.admitted) return;
@@ -87645,6 +88385,7 @@ ${doc.documentElement.outerHTML}`);
87645
88385
  for (const { type, handler } of record6.subscriptions.splice(0)) undo.off(type, handler);
87646
88386
  undo.stop();
87647
88387
  announceChange();
88388
+ announceSession();
87648
88389
  }
87649
88390
  };
87650
88391
  }
@@ -87674,7 +88415,7 @@ ${doc.documentElement.outerHTML}`);
87674
88415
  lease.enable();
87675
88416
  return lease;
87676
88417
  }
87677
- var pageIgnored, withTabLocal, createScope, recording, setRecording, lastEntryId, command, commit, warnedEffectCommit, CONTROLS2, afterReplay, refuse7, recoveryLoad, withRecovery, keepApp, reviewProviders, HISTORY_EVENTS, announceChange, session4, isStale3, ready5, undo_default;
88418
+ var EDITABLE2, pageIgnored, durableForms, durableFormOf, withTabLocal, createScope, recording, setRecording, lastEntryId, command, isBlockStep, commit, warnedEffectCommit, CONTROLS2, afterReplay, refuse7, skip, recoveryLoad, withRecovery, keepApp, reviewProviders, HISTORY_EVENTS, holds4, engineDirection, engineCanUndo, engineCanRedo, announceChange, session4, announceSession, isStale3, ready5, undo_default;
87678
88419
  var init_undo2 = __esm({
87679
88420
  "src/plugins/undo.js"() {
87680
88421
  init_hyper_undo_vendor();
@@ -87684,14 +88425,24 @@ ${doc.documentElement.outerHTML}`);
87684
88425
  init_attr_aliases();
87685
88426
  init_capture_move();
87686
88427
  init_dirty_gate();
88428
+ EDITABLE2 = '[contenteditable]:not([contenteditable="false"])';
87687
88429
  pageIgnored = /* @__PURE__ */ new Set();
88430
+ durableForms = /* @__PURE__ */ new Set();
88431
+ durableFormOf = (node, host2 = null) => {
88432
+ for (const form of durableForms) {
88433
+ const own = form(node, host2);
88434
+ if (typeof own === "string") return own;
88435
+ }
88436
+ return void 0;
88437
+ };
87688
88438
  withTabLocal = (opts = {}) => {
87689
88439
  const own = opts.ignoreAttribute;
87690
88440
  return {
87691
88441
  ...opts,
87692
88442
  ignoreAttribute: (name, target, host2) => pageIgnored.has(name) || isTabLocalAttr(name, target) || isDerivedAttr(target, name, host2) || isRuntimeAttribute(name, target) || (own ? own(name, target, host2) : false),
87693
88443
  isProtected: opts.isProtected || keepsOwnHistory,
87694
- ignoreNode: opts.ignoreNode || isGestureItem
88444
+ ignoreNode: opts.ignoreNode || isGestureItem,
88445
+ durableForm: opts.durableForm || durableFormOf
87695
88446
  };
87696
88447
  };
87697
88448
  createScope = undo.create.bind(undo);
@@ -87700,8 +88451,10 @@ ${doc.documentElement.outerHTML}`);
87700
88451
  setRecording = undo.setRecording.bind(undo);
87701
88452
  undo.setRecording = (mode3) => {
87702
88453
  recording = mode3 ?? null;
88454
+ document.dispatchEvent(new CustomEvent("clay:undo-recording", { detail: { mode: recording } }));
87703
88455
  return setRecording(mode3);
87704
88456
  };
88457
+ Object.defineProperty(undo, "recordingMode", { get: () => recording, configurable: true });
87705
88458
  lastEntryId = () => undo.history.at(-1)?.id ?? null;
87706
88459
  command = undo.command.bind(undo);
87707
88460
  undo.command = (label, fn7) => {
@@ -87709,6 +88462,8 @@ ${doc.documentElement.outerHTML}`);
87709
88462
  if (receipt3) gateMarkDirty();
87710
88463
  return receipt3;
87711
88464
  };
88465
+ undo.recordStep = (label, primitive) => command(label, () => undo.record(primitive));
88466
+ isBlockStep = (entry) => !!entry?.steps?.length && entry.steps.every((step) => step.kind === "value" && /^blockeditor-step(?::|$)/.test(step.prop));
87712
88467
  commit = undo.commit.bind(undo);
87713
88468
  warnedEffectCommit = false;
87714
88469
  undo.commit = (label, fn7) => {
@@ -87724,8 +88479,9 @@ ${doc.documentElement.outerHTML}`);
87724
88479
  CONTROLS2 = `input${PERSIST2}:not([type="password"]):not([type="hidden"]):not([type="file"]), textarea${PERSIST2}, select${PERSIST2}`;
87725
88480
  afterReplay = (receipt3) => {
87726
88481
  if (!receipt3?.ok) return;
87727
- gateMarkDirty();
88482
+ if (!isBlockStep(undo.describe(receipt3.entryId))) gateMarkDirty();
87728
88483
  restoreControls();
88484
+ if (receipt3.caret && undo.pageHistory) placeCaret(receipt3.caret);
87729
88485
  };
87730
88486
  refuse7 = ({ entryId, label, direction, code }) => {
87731
88487
  document.dispatchEvent(new CustomEvent("clay:undo-refused", {
@@ -87733,12 +88489,25 @@ ${doc.documentElement.outerHTML}`);
87733
88489
  }));
87734
88490
  keepRefused({ ok: false, code, entryId, label, direction });
87735
88491
  };
88492
+ skip = ({ entryId, label, direction, code, description }) => {
88493
+ document.dispatchEvent(new CustomEvent("clay:undo-skipped", {
88494
+ detail: { entryId, label, direction, code }
88495
+ }));
88496
+ if (isBlockStep(description)) return;
88497
+ keepRefused({ ok: false, code, entryId, label, direction, description });
88498
+ };
87736
88499
  recoveryLoad = null;
87737
88500
  withRecovery = (call, fallback2) => (...args) => loadRecovery().then(
87738
88501
  (module2) => module2 ? module2[call](...args) : fallback2,
87739
88502
  () => fallback2
87740
88503
  );
87741
88504
  keepApp = withRecovery("keep", { ok: false, code: "unavailable" });
88505
+ undo.addDurableForm = (form) => {
88506
+ durableForms.add(form);
88507
+ return () => {
88508
+ durableForms.delete(form);
88509
+ };
88510
+ };
87742
88511
  undo.ignoreAttribute = (name) => {
87743
88512
  const key3 = String(name || "");
87744
88513
  if (!key3) return () => {
@@ -87782,9 +88551,35 @@ ${doc.documentElement.outerHTML}`);
87782
88551
  }
87783
88552
  return actions;
87784
88553
  };
87785
- HISTORY_EVENTS = ["commit", "undo", "redo", "refused", "discard", "clear"];
88554
+ HISTORY_EVENTS = ["commit", "undo", "redo", "refused", "skipped", "discard", "clear"];
88555
+ holds4 = /* @__PURE__ */ new Set();
88556
+ engineDirection = (name) => {
88557
+ for (let owner = undo; owner; owner = Object.getPrototypeOf(owner)) {
88558
+ const desc = Object.getOwnPropertyDescriptor(owner, name);
88559
+ if (!desc) continue;
88560
+ if (typeof desc.get === "function") return () => desc.get.call(undo);
88561
+ return () => Boolean(desc.value.call(undo));
88562
+ }
88563
+ return () => false;
88564
+ };
88565
+ engineCanUndo = engineDirection("canUndo");
88566
+ engineCanRedo = engineDirection("canRedo");
88567
+ Object.defineProperty(undo, "canUndo", { get: () => holds4.size === 0 && engineCanUndo(), configurable: true });
88568
+ Object.defineProperty(undo, "canRedo", { get: () => holds4.size === 0 && engineCanRedo(), configurable: true });
88569
+ undo.hold = () => {
88570
+ const token2 = /* @__PURE__ */ Symbol("hold");
88571
+ holds4.add(token2);
88572
+ announceChange();
88573
+ let released2 = false;
88574
+ return () => {
88575
+ if (released2) return;
88576
+ released2 = true;
88577
+ holds4.delete(token2);
88578
+ announceChange();
88579
+ };
88580
+ };
87786
88581
  announceChange = () => {
87787
- const live3 = !!session4?.started;
88582
+ const live3 = !!session4?.started && holds4.size === 0;
87788
88583
  document.dispatchEvent(new CustomEvent("clay:undo-change", {
87789
88584
  detail: {
87790
88585
  canUndo: live3 && undo.canUndo,
@@ -87795,6 +88590,16 @@ ${doc.documentElement.outerHTML}`);
87795
88590
  }));
87796
88591
  };
87797
88592
  session4 = null;
88593
+ Object.defineProperty(undo, "pageHistory", {
88594
+ get: () => !!session4?.started,
88595
+ configurable: true
88596
+ });
88597
+ announceSession = () => {
88598
+ if (typeof document === "undefined") return;
88599
+ document.dispatchEvent(new CustomEvent("clay:undo-session", {
88600
+ detail: { started: !!session4?.started, pageHistory: undo.pageHistory }
88601
+ }));
88602
+ };
87798
88603
  isStale3 = (context2) => {
87799
88604
  if (!context2) return false;
87800
88605
  if (context2.signal?.aborted) return true;
@@ -94974,7 +95779,7 @@ tr.hcms-shell.hcms-inline-ghost { display: table-row; }
94974
95779
  const outType = type || (ENCODABLE.includes(file.type) ? file.type : "image/png");
94975
95780
  const url = URL.createObjectURL(file);
94976
95781
  const img = new Image();
94977
- return new Promise((resolve2, reject) => {
95782
+ return new Promise((resolve3, reject) => {
94978
95783
  img.onerror = () => {
94979
95784
  URL.revokeObjectURL(url);
94980
95785
  active3 = false;
@@ -95123,11 +95928,11 @@ tr.hcms-shell.hcms-inline-ghost { display: table-row; }
95123
95928
  reject(new Error("quickcrop: image encoding failed"));
95124
95929
  return;
95125
95930
  }
95126
- resolve2({ blob, dataURL, width: canvas.width, height: canvas.height });
95931
+ resolve3({ blob, dataURL, width: canvas.width, height: canvas.height });
95127
95932
  }, outType, quality);
95128
95933
  },
95129
95934
  onCancel() {
95130
- if (finishOnce()) resolve2(null);
95935
+ if (finishOnce()) resolve3(null);
95131
95936
  }
95132
95937
  });
95133
95938
  }
@@ -95418,7 +96223,7 @@ tr.hcms-shell.hcms-inline-ghost { display: table-row; }
95418
96223
  }
95419
96224
  function postFile(file, { onProgress, signal, taskId, attempt: attempt2, requiredAccess } = {}) {
95420
96225
  const wantedAccess = Array.isArray(requiredAccess) ? requiredAccess : checkRequiredAccess(requiredAccess);
95421
- return new Promise((resolve2) => {
96226
+ return new Promise((resolve3) => {
95422
96227
  const events = { taskId, attempt: attempt2 };
95423
96228
  const token2 = saveToken();
95424
96229
  const path = token2 ? `${UPLOAD_PATH}/${token2}` : UPLOAD_PATH;
@@ -95432,7 +96237,7 @@ tr.hcms-shell.hcms-inline-ghost { display: table-row; }
95432
96237
  if (timeoutId !== null) clearTimeout(timeoutId);
95433
96238
  if (signal) signal.removeEventListener("abort", onAbort);
95434
96239
  if (eventName) emit(eventName, { ...detail, ...events });
95435
- resolve2(value);
96240
+ resolve3(value);
95436
96241
  return true;
95437
96242
  }
95438
96243
  function fail11(msg, msgType, code) {
@@ -96132,7 +96937,7 @@ tr.hcms-shell.hcms-inline-ghost { display: table-row; }
96132
96937
  }
96133
96938
  async function promptForName() {
96134
96939
  const ui9 = await loadDialogUI();
96135
- return new Promise((resolve2) => {
96940
+ return new Promise((resolve3) => {
96136
96941
  const theme3 = ui9.resolveTheme();
96137
96942
  const { root: root4, overlay, panel: panel2, heading, body: body3, footer, close } = ui9.bevelDialog({
96138
96943
  zIndex: "2147483001",
@@ -96226,7 +97031,7 @@ tr.hcms-shell.hcms-inline-ghost { display: table-row; }
96226
97031
  asking = null;
96227
97032
  askingRoot = null;
96228
97033
  cancelAsking = null;
96229
- resolve2(person);
97034
+ resolve3(person);
96230
97035
  }
96231
97036
  ui9.dismissOf.set(root4, () => finish3(null));
96232
97037
  root4.setAttribute("aria-hidden", "false");
@@ -96287,7 +97092,7 @@ tr.hcms-shell.hcms-inline-ghost { display: table-row; }
96287
97092
  }, { signal });
96288
97093
  session6 = { listeners: listeners7, first: refresh(false) };
96289
97094
  }
96290
- return Promise.race([session6.first, new Promise((resolve2) => setTimeout(resolve2, BOOT_WAIT_MS))]);
97095
+ return Promise.race([session6.first, new Promise((resolve3) => setTimeout(resolve3, BOOT_WAIT_MS))]);
96291
97096
  }
96292
97097
  function stopEditing2() {
96293
97098
  session6?.listeners.abort();
@@ -96744,11 +97549,11 @@ tr.hcms-shell.hcms-inline-ghost { display: table-row; }
96744
97549
 
96745
97550
  // src/plugins/menu/actions.js
96746
97551
  function whenPresent2(get5, ms4 = READY_MS) {
96747
- return new Promise((resolve2) => {
97552
+ return new Promise((resolve3) => {
96748
97553
  const start12 = Date.now();
96749
97554
  const tick = () => {
96750
97555
  const value = get5();
96751
- if (value || Date.now() - start12 >= ms4) resolve2(value || null);
97556
+ if (value || Date.now() - start12 >= ms4) resolve3(value || null);
96752
97557
  else setTimeout(tick, 50);
96753
97558
  };
96754
97559
  tick();
@@ -96758,13 +97563,13 @@ tr.hcms-shell.hcms-inline-ghost { display: table-row; }
96758
97563
  const page2 = clay().blockeditor;
96759
97564
  if (!page2) return Promise.resolve(true);
96760
97565
  const start12 = Date.now();
96761
- return new Promise((resolve2) => {
97566
+ return new Promise((resolve3) => {
96762
97567
  let done = false;
96763
97568
  const finish3 = (ok) => {
96764
97569
  if (!done) {
96765
97570
  done = true;
96766
97571
  clearTimeout(timer);
96767
- resolve2(ok);
97572
+ resolve3(ok);
96768
97573
  }
96769
97574
  };
96770
97575
  const tick = () => {
@@ -97271,7 +98076,7 @@ tr.hcms-shell.hcms-inline-ghost { display: table-row; }
97271
98076
  async function afterBaseline() {
97272
98077
  const save2 = await Promise.resolve().then(() => (init_save(), save_exports));
97273
98078
  while (!save2.baselineSettled()) {
97274
- await new Promise((resolve2) => document.addEventListener("clay:baseline-settled", resolve2, { once: true }));
98079
+ await new Promise((resolve3) => document.addEventListener("clay:baseline-settled", resolve3, { once: true }));
97275
98080
  }
97276
98081
  }
97277
98082
  function joinNames(list3) {
@@ -98326,7 +99131,7 @@ tr.hcms-shell.hcms-inline-ghost { display: table-row; }
98326
99131
  const view3 = window.clay && window.clay.blockeditor && window.clay.blockeditor.view;
98327
99132
  return documentTitle(titleItems(view3));
98328
99133
  }
98329
- function hostOf3(value) {
99134
+ function hostOf4(value) {
98330
99135
  const url = parseUrl2(text4(value).trim());
98331
99136
  return url ? url.hostname : "";
98332
99137
  }
@@ -98575,7 +99380,7 @@ tr.hcms-shell.hcms-inline-ghost { display: table-row; }
98575
99380
  const description = text4(readField("ogDescription")).trim() || descriptionValue;
98576
99381
  previewDescription.textContent = description;
98577
99382
  previewDescription.hidden = !description;
98578
- previewHost.textContent = hostOf3(readField("canonical")) || location.host || "";
99383
+ previewHost.textContent = hostOf4(readField("canonical")) || location.host || "";
98579
99384
  previewState.textContent = image ? "Large image card \xB7 1.91:1" : "Summary card";
98580
99385
  cardSize.textContent = image ? "Shared links show the large image." : "Add an image for the large card.";
98581
99386
  derivedButton.hidden = !(isDocumentPage() && FIELDS2.titleMode.read(document) === "custom");
@@ -99229,12 +100034,12 @@ textarea.clay-seo-input.is-short { min-height: 32px; }
99229
100034
  };
99230
100035
  stream.onerror = () => {
99231
100036
  };
99232
- streamReady = new Promise((resolve2) => {
100037
+ streamReady = new Promise((resolve3) => {
99233
100038
  let settled3 = false;
99234
100039
  const finish3 = () => {
99235
100040
  if (settled3) return;
99236
100041
  settled3 = true;
99237
- resolve2();
100042
+ resolve3();
99238
100043
  };
99239
100044
  stream.onopen = finish3;
99240
100045
  setTimeout(finish3, 2e3);
@@ -99432,13 +100237,13 @@ textarea.clay-seo-input.is-short { min-height: 32px; }
99432
100237
  };
99433
100238
  }
99434
100239
  function once(eventName, timeout) {
99435
- return new Promise((resolve2) => {
100240
+ return new Promise((resolve3) => {
99436
100241
  let done = false;
99437
100242
  const settle9 = () => {
99438
100243
  if (done) return;
99439
100244
  done = true;
99440
100245
  document.removeEventListener(eventName, settle9);
99441
- resolve2();
100246
+ resolve3();
99442
100247
  };
99443
100248
  document.addEventListener(eventName, settle9);
99444
100249
  setTimeout(settle9, timeout);
@@ -99538,8 +100343,8 @@ textarea.clay-seo-input.is-short { min-height: 32px; }
99538
100343
  signal: opts.signal && typeof opts.signal.addEventListener === "function" ? opts.signal : null,
99539
100344
  signalHandler: null
99540
100345
  };
99541
- rec.done = new Promise((resolve2) => {
99542
- rec.settle = resolve2;
100346
+ rec.done = new Promise((resolve3) => {
100347
+ rec.settle = resolve3;
99543
100348
  });
99544
100349
  records2.set(id2, rec);
99545
100350
  emit3(rec);
@@ -101351,7 +102156,7 @@ textarea.clay-seo-input.is-short { min-height: 32px; }
101351
102156
  if (pageAi()?.active() && el13 !== document.body) return false;
101352
102157
  if (!canOpenTarget(el13)) return false;
101353
102158
  await init18();
101354
- await new Promise((resolve2) => setTimeout(resolve2, 0));
102159
+ await new Promise((resolve3) => setTimeout(resolve3, 0));
101355
102160
  if (!panel || session9 || barMode) return false;
101356
102161
  const ai5 = pageAi();
101357
102162
  const target = ai5?.active() ? ai5.wholePage() : el13;
@@ -101367,7 +102172,7 @@ textarea.clay-seo-input.is-short { min-height: 32px; }
101367
102172
  async function openTarget(target) {
101368
102173
  if (!target || target.aiTarget !== true) return false;
101369
102174
  await init18();
101370
- await new Promise((resolve2) => setTimeout(resolve2, 0));
102175
+ await new Promise((resolve3) => setTimeout(resolve3, 0));
101371
102176
  if (!panel || session9 || barMode) return false;
101372
102177
  if (!target.isConnected) return false;
101373
102178
  if (!panel.hidden && anchorEl === target) {
@@ -101380,7 +102185,7 @@ textarea.clay-seo-input.is-short { min-height: 32px; }
101380
102185
  async function pick2() {
101381
102186
  await init18();
101382
102187
  if (blockDocWithoutSurface()) return false;
101383
- await new Promise((resolve2) => setTimeout(resolve2, 0));
102188
+ await new Promise((resolve3) => setTimeout(resolve3, 0));
101384
102189
  if (!panel || session9 || barMode) return false;
101385
102190
  if (picker?.picking) return true;
101386
102191
  const ai5 = pageAi();
@@ -101601,11 +102406,11 @@ textarea.clay-seo-input.is-short { min-height: 32px; }
101601
102406
  if (method !== "POST" || !isSaveUrl(url)) {
101602
102407
  return realFetch(url, options);
101603
102408
  }
101604
- return new Promise((resolve2) => {
102409
+ return new Promise((resolve3) => {
101605
102410
  setTimeout(() => {
101606
102411
  if (failNextSave) {
101607
102412
  failNextSave = false;
101608
- resolve2(new Response(JSON.stringify({ msg: "Server not responding", msgType: "error" }), {
102413
+ resolve3(new Response(JSON.stringify({ msg: "Server not responding", msgType: "error" }), {
101609
102414
  status: 503,
101610
102415
  headers: { "Content-Type": "application/json" }
101611
102416
  }));
@@ -101617,13 +102422,13 @@ textarea.clay-seo-input.is-short { min-height: 32px; }
101617
102422
  try {
101618
102423
  localStorage.setItem(KEY3, doc.body.outerHTML);
101619
102424
  } catch {
101620
- resolve2(new Response(JSON.stringify({ msg: "Couldn't save in this browser (storage is full or blocked)", msgType: "error" }), {
102425
+ resolve3(new Response(JSON.stringify({ msg: "Couldn't save in this browser (storage is full or blocked)", msgType: "error" }), {
101621
102426
  status: 507,
101622
102427
  headers: { "Content-Type": "application/json" }
101623
102428
  }));
101624
102429
  return;
101625
102430
  }
101626
- resolve2(new Response(JSON.stringify({ msg: "Saved in your browser", msgType: "success" }), {
102431
+ resolve3(new Response(JSON.stringify({ msg: "Saved in your browser", msgType: "success" }), {
101627
102432
  status: 200,
101628
102433
  headers: { "Content-Type": "application/json" }
101629
102434
  }));
@@ -102496,12 +103301,12 @@ textarea.clay-seo-input.is-short { min-height: 32px; }
102496
103301
  const hits = scope.elementsFromPoint ? scope.elementsFromPoint(x6, y6) : [];
102497
103302
  return hits.filter((hit) => hit.getRootNode() === scope).flatMap((hit) => hit.localName === "clay-editor-ui" && hit.shadowRoot ? hitsAt(hit.shadowRoot, x6, y6) : [hit]);
102498
103303
  }
102499
- function bottomBarHeight(x6, skip) {
103304
+ function bottomBarHeight(x6, skip2) {
102500
103305
  const h = window.innerHeight;
102501
103306
  let raise = 0;
102502
103307
  for (const hit of hitsAt(document, x6, h - 3)) {
102503
103308
  for (let el13 = hit; el13 && el13 !== document.body && el13 !== document.documentElement; el13 = el13.parentElement ?? el13.getRootNode().host) {
102504
- if (skip(el13)) break;
103309
+ if (skip2(el13)) break;
102505
103310
  const position = getComputedStyle(el13).position;
102506
103311
  if (position === "fixed" || position === "sticky") {
102507
103312
  const height = Math.ceil(h - el13.getBoundingClientRect().top);
@@ -103257,11 +104062,11 @@ body:has(> .clay-intro) { height: auto !important; overflow: visible !important;
103257
104062
  }
103258
104063
  function mount4({ memory, template, appName }) {
103259
104064
  const section = buildSection({ template, appName, onClose: () => dismiss5("closed") });
103260
- let gone = false;
104065
+ let gone2 = false;
103261
104066
  let frame = 0;
103262
104067
  function dismiss5(reason) {
103263
- if (gone) return;
103264
- gone = true;
104068
+ if (gone2) return;
104069
+ gone2 = true;
103265
104070
  removeEventListener("scroll", onScroll);
103266
104071
  if (frame) cancelAnimationFrame(frame);
103267
104072
  const height = section.getBoundingClientRect().height;
@@ -103346,20 +104151,20 @@ body:has(> .clay-intro) { height: auto !important; overflow: visible !important;
103346
104151
  return error2;
103347
104152
  }
103348
104153
  function cursorEntries(source3, range) {
103349
- return new Promise((resolve2, reject) => {
104154
+ return new Promise((resolve3, reject) => {
103350
104155
  const out = [];
103351
104156
  const req = source3.openCursor(range);
103352
104157
  req.onerror = () => reject(req.error);
103353
104158
  req.onsuccess = () => {
103354
104159
  const cursor = req.result;
103355
- if (!cursor) return resolve2(out);
104160
+ if (!cursor) return resolve3(out);
103356
104161
  out.push([cursor.key, cursor.value]);
103357
104162
  cursor.continue();
103358
104163
  };
103359
104164
  });
103360
104165
  }
103361
104166
  function openDrafts({ factory = globalThis.indexedDB, keyRange = globalThis.IDBKeyRange, name = DB_NAME2, timeout = OPEN_TIMEOUT_MS2 } = {}) {
103362
- return new Promise((resolve2, reject) => {
104167
+ return new Promise((resolve3, reject) => {
103363
104168
  if (!factory || typeof factory.open !== "function" || !keyRange) return reject(failure("unavailable"));
103364
104169
  let req;
103365
104170
  try {
@@ -103383,7 +104188,7 @@ body:has(> .clay-intro) { height: auto !important; overflow: visible !important;
103383
104188
  };
103384
104189
  req.onsuccess = () => {
103385
104190
  const db = req.result;
103386
- if (!finish3(resolve2, wrap(db, keyRange))) db.close();
104191
+ if (!finish3(resolve3, wrap(db, keyRange))) db.close();
103387
104192
  };
103388
104193
  req.onerror = () => finish3(reject, failure(codeFor2(req.error), req.error));
103389
104194
  req.onblocked = () => finish3(reject, failure("blocked"));
@@ -103427,7 +104232,7 @@ body:has(> .clay-intro) { height: auto !important; overflow: visible !important;
103427
104232
  }
103428
104233
  }
103429
104234
  function change(key3, build6, { timeout = 0, recovery: recovery2 = false } = {}) {
103430
- return new Promise((resolve2, reject) => {
104235
+ return new Promise((resolve3, reject) => {
103431
104236
  let tx;
103432
104237
  try {
103433
104238
  tx = transaction([RECORDS2, PARTS], "readwrite");
@@ -103452,7 +104257,7 @@ body:has(> .clay-intro) { height: auto !important; overflow: visible !important;
103452
104257
  }
103453
104258
  finish3(reject, thrown);
103454
104259
  }, timeout);
103455
- tx.oncomplete = () => finish3(resolve2, result2);
104260
+ tx.oncomplete = () => finish3(resolve3, result2);
103456
104261
  tx.onabort = () => finish3(reject, thrown || failure(tx.error ? codeFor2(tx.error) : "aborted", tx.error));
103457
104262
  try {
103458
104263
  const store2 = tx.objectStore(RECORDS2);
@@ -103495,7 +104300,7 @@ body:has(> .clay-intro) { height: auto !important; overflow: visible !important;
103495
104300
  });
103496
104301
  }
103497
104302
  function putRow(name, value) {
103498
- return new Promise((resolve2, reject) => {
104303
+ return new Promise((resolve3, reject) => {
103499
104304
  if (!/:op:[^:]+$/.test(name)) return reject(failure("bad-op"));
103500
104305
  let tx;
103501
104306
  try {
@@ -103505,7 +104310,7 @@ body:has(> .clay-intro) { height: auto !important; overflow: visible !important;
103505
104310
  } catch (error2) {
103506
104311
  return reject(error2 instanceof Error && error2.code ? error2 : failure(codeFor2(error2), error2));
103507
104312
  }
103508
- tx.oncomplete = () => resolve2();
104313
+ tx.oncomplete = () => resolve3();
103509
104314
  tx.onabort = () => reject(failure(tx.error ? codeFor2(tx.error) : "aborted", tx.error));
103510
104315
  });
103511
104316
  }
@@ -103638,10 +104443,10 @@ body:has(> .clay-intro) { height: auto !important; overflow: visible !important;
103638
104443
  } else if (base2) {
103639
104444
  const merged2 = merge32(base2.data, local3.data, record6.data);
103640
104445
  const page2 = unitOf2(local3);
103641
- const paged = Boolean(page2) && unitMark2(page2) !== unitMark2(unitOf2(base2));
103642
- const pageMoved = paged && unitOf2(record6) && unitMark2(unitOf2(base2)) !== meta.unit;
104446
+ const paged2 = Boolean(page2) && unitMark2(page2) !== unitMark2(unitOf2(base2));
104447
+ const pageMoved = paged2 && unitOf2(record6) && unitMark2(unitOf2(base2)) !== meta.unit;
103643
104448
  if (merged2.conflict || pageMoved) out.conflicts.push(clone(record6));
103644
- const unit = paged ? page2 : unitOf2(record6);
104449
+ const unit = paged2 ? page2 : unitOf2(record6);
103645
104450
  record6 = {
103646
104451
  v: 1,
103647
104452
  savedAt: local3.savedAt ?? new Date(now3).toISOString(),
@@ -103650,7 +104455,7 @@ body:has(> .clay-intro) { height: auto !important; overflow: visible !important;
103650
104455
  data: merged2.value,
103651
104456
  ...unit && { live: unit.live, blockeditor: unit.blockeditor }
103652
104457
  };
103653
- if (paged) meta.unit = unitMark2(unit);
104458
+ if (paged2) meta.unit = unitMark2(unit);
103654
104459
  v1base = clone(local3);
103655
104460
  meta.rev++;
103656
104461
  } else {
@@ -103992,8 +104797,8 @@ body:has(> .clay-intro) { height: auto !important; overflow: visible !important;
103992
104797
  const committed2 = sync();
103993
104798
  if (read4(resetKey) !== next) await committed2;
103994
104799
  else await Promise.race([committed2.catch(() => {
103995
- }), new Promise((resolve2) => {
103996
- timer = setTimeout(resolve2, START_OVER_WAIT_MS);
104800
+ }), new Promise((resolve3) => {
104801
+ timer = setTimeout(resolve3, START_OVER_WAIT_MS);
103997
104802
  })]);
103998
104803
  stop7();
103999
104804
  } catch (error2) {
@@ -104370,8 +105175,8 @@ body:has(> .clay-intro) { height: auto !important; overflow: visible !important;
104370
105175
  if (!store.pending()) return safe ? null : Promise.resolve(false);
104371
105176
  const committed2 = opening.then(() => session10 ? session10.sync().then(() => true) : store.flush()).catch(() => false);
104372
105177
  let timer;
104373
- return Promise.race([committed2, new Promise((resolve2) => {
104374
- timer = setTimeout(() => resolve2(false), DOWNLOAD_WAIT_MS);
105178
+ return Promise.race([committed2, new Promise((resolve3) => {
105179
+ timer = setTimeout(() => resolve3(false), DOWNLOAD_WAIT_MS);
104375
105180
  })]).finally(() => clearTimeout(timer));
104376
105181
  };
104377
105182
  document.addEventListener("visibilitychange", () => {
@@ -104392,8 +105197,8 @@ body:has(> .clay-intro) { height: auto !important; overflow: visible !important;
104392
105197
  event.preventDefault();
104393
105198
  leaving2 = true;
104394
105199
  let timer;
104395
- await Promise.race([waiting, new Promise((resolve2) => {
104396
- timer = setTimeout(resolve2, DOWNLOAD_WAIT_MS);
105200
+ await Promise.race([waiting, new Promise((resolve3) => {
105201
+ timer = setTimeout(resolve3, DOWNLOAD_WAIT_MS);
104397
105202
  })]);
104398
105203
  clearTimeout(timer);
104399
105204
  leaving2 = false;
@@ -105412,10 +106217,10 @@ body:has(> .clay-intro) { height: auto !important; overflow: visible !important;
105412
106217
  if (l2.kind === "comment") return "#comment";
105413
106218
  return "<" + l2.tag + l2.attrs.map((a2) => " " + a2.name + '="' + a2.value.slice(0, 30) + '"').join("") + ">";
105414
106219
  }
105415
- function pair(root4, m7, resolve2 = (n3) => n3) {
105416
- return drain(pairSteps(root4, m7, resolve2));
106220
+ function pair(root4, m7, resolve3 = (n3) => n3) {
106221
+ return drain(pairSteps(root4, m7, resolve3));
105417
106222
  }
105418
- function* pairSteps(root4, m7, resolve2 = (n3) => n3) {
106223
+ function* pairSteps(root4, m7, resolve3 = (n3) => n3) {
105419
106224
  const map = /* @__PURE__ */ new WeakMap();
105420
106225
  const keyMap = /* @__PURE__ */ new Map();
105421
106226
  const walked = { n: 0 };
@@ -105424,12 +106229,12 @@ body:has(> .clay-intro) { height: auto !important; overflow: visible !important;
105424
106229
  const stats2 = { paired: 0, unmatchedLive: [], unmatchedSource: [], attrDiffs: [], textDiffs: 0, unresolved: 0 };
105425
106230
  const gen = {};
105426
106231
  m7.gen = gen;
105427
- yield* bindSteps(root4, m7.root, map, keyMap, stats2, "html", resolve2, gen, walked);
106232
+ yield* bindSteps(root4, m7.root, map, keyMap, stats2, "html", resolve3, gen, walked);
105428
106233
  return { map, stats: stats2 };
105429
106234
  }
105430
- function* bindSteps(node, loc, map, keyMap, stats2, path, resolve2, gen, walked) {
106235
+ function* bindSteps(node, loc, map, keyMap, stats2, path, resolve3, gen, walked) {
105431
106236
  if (++walked.n % YIELD_EVERY === 0) yield;
105432
- const key3 = resolve2(node);
106237
+ const key3 = resolve3(node);
105433
106238
  if (key3) {
105434
106239
  map.set(key3, loc);
105435
106240
  loc.gen = gen;
@@ -105446,7 +106251,7 @@ body:has(> .clay-intro) { height: auto !important; overflow: visible !important;
105446
106251
  for (const [i2, j10] of pairs) {
105447
106252
  usedL.add(i2);
105448
106253
  usedS.add(j10);
105449
- yield* bindSteps(L9[i2], S8[j10], map, keyMap, stats2, path + ">" + (L9[i2].nodeType === 1 ? L9[i2].localName : "#") + "[" + i2 + "]", resolve2, gen, walked);
106254
+ yield* bindSteps(L9[i2], S8[j10], map, keyMap, stats2, path + ">" + (L9[i2].nodeType === 1 ? L9[i2].localName : "#") + "[" + i2 + "]", resolve3, gen, walked);
105450
106255
  }
105451
106256
  for (let i2 = 0; i2 < L9.length; i2++) if (!usedL.has(i2)) stats2.unmatchedLive.push({ path, node: describe(L9[i2]) });
105452
106257
  for (let j10 = 0; j10 < S8.length; j10++) if (!usedS.has(j10)) stats2.unmatchedSource.push({ path, node: describeLoc(S8[j10]) });
@@ -108233,8 +109038,8 @@ body:has(> .clay-intro) { height: auto !important; overflow: visible !important;
108233
109038
  }
108234
109039
  cancel2.addEventListener("click", close);
108235
109040
  let resolveDone;
108236
- const done = new Promise((resolve2) => {
108237
- resolveDone = resolve2;
109041
+ const done = new Promise((resolve3) => {
109042
+ resolveDone = resolve3;
108238
109043
  });
108239
109044
  agree.addEventListener("click", async () => {
108240
109045
  agree.disabled = true;
@@ -108418,12 +109223,12 @@ body:has(> .clay-intro) { height: auto !important; overflow: visible !important;
108418
109223
  }
108419
109224
  function whenMenuReady(clay6) {
108420
109225
  if (menuReady(clay6) || !menuPlanned(clay6)) return Promise.resolve();
108421
- return new Promise((resolve2) => {
109226
+ return new Promise((resolve3) => {
108422
109227
  const onSettled = (event) => {
108423
109228
  if (!event.detail || event.detail.plugin !== "menu") return;
108424
109229
  document.removeEventListener("clay:plugin-ready", onSettled);
108425
109230
  document.removeEventListener("clay:plugin-failed", onSettled);
108426
- resolve2();
109231
+ resolve3();
108427
109232
  };
108428
109233
  document.addEventListener("clay:plugin-ready", onSettled);
108429
109234
  document.addEventListener("clay:plugin-failed", onSettled);
@@ -112962,7 +113767,7 @@ https://github.com/highlightjs/highlight.js/issues/2277`), x6 = n3, E5 = a2), h
112962
113767
  while (i2 < keys2.length - 1 && keys2[i2 + 1].t === keys2[0].t) i2++;
112963
113768
  return keys2[i2].v;
112964
113769
  }
112965
- function resolve(tweens, resets = []) {
113770
+ function resolve2(tweens, resets = []) {
112966
113771
  if (!tweens.length) return [];
112967
113772
  const firstStart = Math.min(...tweens.map((t2) => t2.start));
112968
113773
  const list3 = [
@@ -113034,7 +113839,7 @@ https://github.com/highlightjs/highlight.js/issues/2277`), x6 = n3, E5 = a2), h
113034
113839
  }
113035
113840
  for (const [el13, props] of groups) {
113036
113841
  for (const [prop, list3] of props) {
113037
- const keys2 = resolve(list3, s3.resets);
113842
+ const keys2 = resolve2(list3, s3.resets);
113038
113843
  const v9 = initialValue(keys2);
113039
113844
  if (!same8(valueAt(keys2, start12, prop), v9)) s3.add(el13, prop, start12, 0, v9, { ease: "linear" });
113040
113845
  }
@@ -113232,7 +114037,7 @@ https://github.com/highlightjs/highlight.js/issues/2277`), x6 = n3, E5 = a2), h
113232
114037
  });
113233
114038
  }
113234
114039
  current(el13, prop, t2) {
113235
- const keys2 = resolve(this.tweens.filter((tw) => tw.el === el13 && tw.prop === prop), this.resets);
114040
+ const keys2 = resolve2(this.tweens.filter((tw) => tw.el === el13 && tw.prop === prop), this.resets);
113236
114041
  return valueAt(keys2, t2, prop);
113237
114042
  }
113238
114043
  rect(el13) {
@@ -113568,7 +114373,7 @@ https://github.com/highlightjs/highlight.js/issues/2277`), x6 = n3, E5 = a2), h
113568
114373
  try {
113569
114374
  for (const [el13, props] of groups) {
113570
114375
  for (const [prop, list3] of props) {
113571
- const keys2 = resolve(list3, this.resets);
114376
+ const keys2 = resolve2(list3, this.resets);
113572
114377
  if (this.loop && this.resets.length && !same8(keys2[keys2.length - 1].v, initialValue(keys2))) {
113573
114378
  const late = list3.reduce((a2, b7) => b7.start > a2.start ? b7 : a2);
113574
114379
  throw new Error(`uimotion: ${prop} on an element still changes after the last reset() (${late.source}), so the loop jumps. Move reset() to the end, or return it to its start value.`);
@@ -117694,8 +118499,8 @@ ${t2}` : `"use strict"; return (${t2});`;
117694
118499
  return function(...args) {
117695
118500
  const ctx = this;
117696
118501
  clearTimeout(timeoutId);
117697
- return new Promise((resolve2, reject) => {
117698
- pending8.push({ resolve: resolve2, reject });
118502
+ return new Promise((resolve3, reject) => {
118503
+ pending8.push({ resolve: resolve3, reject });
117699
118504
  timeoutId = setTimeout(() => {
117700
118505
  const waiting = pending8;
117701
118506
  pending8 = [];
@@ -118871,7 +119676,6 @@ ${t2}` : `"use strict"; return (${t2});`;
118871
119676
  var PLUGIN_ORDER = ["visitor-drafts", "visitor-menu", "richclay", "indicator", "sortable", "undo", "unsent", "quickcrop", "upload", "people", "menu", "upgrade", "cms", "blockeditor-view", "sync", "live", "blockeditor", "message", "like", "wire", "ai-edit", "demo", "derive", "bind-text", "source"];
118872
119677
  var IMPLIES = { cms: ["quickcrop", "upload", "menu"], "ai-edit": ["wire"], blockeditor: ["live", "sync", "upload", "wire", "ai-edit"] };
118873
119678
  var DISPLACES = { blockeditor: ["richclay"] };
118874
- var CANNOT_RUN_WITH = { blockeditor: ["undo"] };
118875
119679
  var LATE = /* @__PURE__ */ new Set(["source", "sortable", "menu", "upgrade"]);
118876
119680
  var LATE_WITH_PAGE = /* @__PURE__ */ new Set(["wire", "ai-edit"]);
118877
119681
  function parseCsv2(params, key3, enabled, apply3) {
@@ -118930,14 +119734,6 @@ ${t2}` : `"use strict"; return (${t2});`;
118930
119734
  for (const name of names2) if (!explicit.has(name)) enabled.delete(name);
118931
119735
  }
118932
119736
  }
118933
- for (const [owner, names2] of Object.entries(CANNOT_RUN_WITH)) {
118934
- if (!enabled.has(owner)) continue;
118935
- for (const name of names2) {
118936
- if (!enabled.has(name)) continue;
118937
- enabled.delete(name);
118938
- console.warn(`clayjs: plugin "${name}" cannot run with "${owner}" and was left out`);
118939
- }
118940
- }
118941
119737
  const plugins = [];
118942
119738
  const late = [];
118943
119739
  for (const name of PLUGIN_ORDER) {
@@ -118995,12 +119791,12 @@ ${t2}` : `"use strict"; return (${t2});`;
118995
119791
  function savedWrite(records3) {
118996
119792
  const policy = window.clay?.region?.resolveRegionPolicy;
118997
119793
  if (!policy) return null;
118998
- const tracked = (el13) => !!el13 && !el13.closest(NO_SNAPSHOT) && policy(el13).dirtyTracked;
119794
+ const tracked2 = (el13) => !!el13 && !el13.closest(NO_SNAPSHOT) && policy(el13).dirtyTracked;
118999
119795
  for (const r45 of records3) {
119000
119796
  if (r45.type === "attributes" && isTabLocalAttr(r45.attributeName, r45.target)) continue;
119001
119797
  const el13 = r45.target.nodeType === 1 ? r45.target : r45.target.parentElement;
119002
- if (!tracked(el13)) continue;
119003
- if (r45.type === "childList" && ![...r45.addedNodes, ...r45.removedNodes].some((n3) => n3.nodeType !== 1 || tracked(n3))) continue;
119798
+ if (!tracked2(el13)) continue;
119799
+ if (r45.type === "childList" && ![...r45.addedNodes, ...r45.removedNodes].some((n3) => n3.nodeType !== 1 || tracked2(n3))) continue;
119004
119800
  return r45.target;
119005
119801
  }
119006
119802
  return null;
@@ -119192,7 +119988,7 @@ ${t2}` : `"use strict"; return (${t2});`;
119192
119988
  return hints;
119193
119989
  });
119194
119990
  function domReady() {
119195
- return new Promise((resolve2) => dom_ready_default(resolve2));
119991
+ return new Promise((resolve3) => dom_ready_default(resolve3));
119196
119992
  }
119197
119993
  function templateSource() {
119198
119994
  const meta = document.querySelector('meta[name="hyper-source"]');
@@ -119222,8 +120018,8 @@ ${t2}` : `"use strict"; return (${t2});`;
119222
120018
  });
119223
120019
  }
119224
120020
  let settleLate;
119225
- const lateDone = new Promise((resolve2) => {
119226
- settleLate = resolve2;
120021
+ const lateDone = new Promise((resolve3) => {
120022
+ settleLate = resolve3;
119227
120023
  });
119228
120024
  const readerOptions = { sync: plan.plugins.includes("sync/live-sync.js") };
119229
120025
  for (const path of plan.core) {