@designcrowd/library.brand-page 6.0.6-undo-11 → 6.0.6-undo-12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (20) hide show
  1. package/lib/src/{CreatedOnBrandCrowd-de-de-DGLT4mjc.js → CreatedOnBrandCrowd-de-de-BoBmsU5p.js} +1 -1
  2. package/lib/src/{CreatedOnBrandCrowd-en-us-dyPp4NQB.js → CreatedOnBrandCrowd-en-us-VTBk9ZeK.js} +1 -1
  3. package/lib/src/{CreatedOnBrandCrowd-es-es-pxoT8xpT.js → CreatedOnBrandCrowd-es-es-CwYO5ZGB.js} +1 -1
  4. package/lib/src/{CreatedOnBrandCrowd-fr-fr-Bpvv3YSe.js → CreatedOnBrandCrowd-fr-ca-ZNEyNVVj.js} +1 -1
  5. package/lib/src/{CreatedOnBrandCrowd-fr-ca-Bpvv3YSe.js → CreatedOnBrandCrowd-fr-fr-ZNEyNVVj.js} +1 -1
  6. package/lib/src/{CreatedOnBrandCrowd-pt-pt-DqKwinmI.js → CreatedOnBrandCrowd-pt-br-D1q4-n_v.js} +1 -1
  7. package/lib/src/{CreatedOnBrandCrowd-pt-br-DqKwinmI.js → CreatedOnBrandCrowd-pt-pt-D1q4-n_v.js} +1 -1
  8. package/lib/src/{CreatedOnDcom-de-de-DhhAudIO.js → CreatedOnDcom-de-de-CFvvAm2h.js} +1 -1
  9. package/lib/src/{CreatedOnDcom-en-us-DZhMl0Ro.js → CreatedOnDcom-en-us-B5WlETVx.js} +1 -1
  10. package/lib/src/{CreatedOnDcom-es-es-brPE0-Lo.js → CreatedOnDcom-es-es-CatVjoa9.js} +1 -1
  11. package/lib/src/{CreatedOnDcom-fr-ca-CzKZrAVq.js → CreatedOnDcom-fr-ca-uyrRJVf9.js} +1 -1
  12. package/lib/src/{CreatedOnDcom-fr-fr-JLjx-E9X.js → CreatedOnDcom-fr-fr-CKSa6Crw.js} +1 -1
  13. package/lib/src/{CreatedOnDcom-pt-br-B_4Ot1uS.js → CreatedOnDcom-pt-br-BIcGDf-8.js} +1 -1
  14. package/lib/src/{CreatedOnDcom-pt-pt-By5SiPq_.js → CreatedOnDcom-pt-pt-BhKpuziQ.js} +1 -1
  15. package/lib/src/brand-page-maker/stores/history/history-store.js +12 -4
  16. package/lib/src/index.mjs +1 -1
  17. package/lib/src/{lib-C0lwMScz.js → lib-CtSZjhZb.js} +3 -3
  18. package/package.json +1 -1
  19. package/src/brand-page-maker/stores/history/history-store.test.ts +34 -0
  20. package/src/brand-page-maker/stores/history/history-store.ts +12 -4
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-C0lwMScz.js";
2
+ import { _ as t } from "./lib-CtSZjhZb.js";
3
3
  const i = {}, h = {
4
4
  width: "275",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-C0lwMScz.js";
2
+ import { _ as t } from "./lib-CtSZjhZb.js";
3
3
  const i = {}, h = {
4
4
  width: "251",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-C0lwMScz.js";
2
+ import { _ as t } from "./lib-CtSZjhZb.js";
3
3
  const i = {}, h = {
4
4
  width: "250",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-C0lwMScz.js";
2
+ import { _ as t } from "./lib-CtSZjhZb.js";
3
3
  const i = {}, h = {
4
4
  width: "237",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-C0lwMScz.js";
2
+ import { _ as t } from "./lib-CtSZjhZb.js";
3
3
  const i = {}, h = {
4
4
  width: "237",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-C0lwMScz.js";
2
+ import { _ as t } from "./lib-CtSZjhZb.js";
3
3
  const i = {}, h = {
4
4
  width: "263",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-C0lwMScz.js";
2
+ import { _ as t } from "./lib-CtSZjhZb.js";
3
3
  const i = {}, h = {
4
4
  width: "263",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as e } from "./lib-C0lwMScz.js";
2
+ import { _ as e } from "./lib-CtSZjhZb.js";
3
3
  const M = {}, Z = {
4
4
  width: "242",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as e } from "./lib-C0lwMScz.js";
2
+ import { _ as e } from "./lib-CtSZjhZb.js";
3
3
  const i = {}, M = {
4
4
  width: "231",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as e } from "./lib-C0lwMScz.js";
2
+ import { _ as e } from "./lib-CtSZjhZb.js";
3
3
  const M = {}, Z = {
4
4
  width: "230",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as e } from "./lib-C0lwMScz.js";
2
+ import { _ as e } from "./lib-CtSZjhZb.js";
3
3
  const i = {}, l = {
4
4
  width: "216",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as e } from "./lib-C0lwMScz.js";
2
+ import { _ as e } from "./lib-CtSZjhZb.js";
3
3
  const i = {}, l = {
4
4
  width: "216",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as M } from "./lib-C0lwMScz.js";
2
+ import { _ as M } from "./lib-CtSZjhZb.js";
3
3
  const Z = {}, e = {
4
4
  width: "232",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as M } from "./lib-C0lwMScz.js";
2
+ import { _ as M } from "./lib-CtSZjhZb.js";
3
3
  const Z = {}, e = {
4
4
  width: "232",
5
5
  height: "36",
@@ -345,8 +345,12 @@ export const useHistoryStore = defineStore('history', () => {
345
345
  // 1. Diff `cameFromIndex` against target — pages present in target
346
346
  // but absent from source are being restored/added; navigate there
347
347
  // (undo-of-delete, redo-of-add).
348
- // 2. Walk back from targetIndex for the closest entry whose
349
- // activePageId still exists (undo-of-add and non-page edits).
348
+ // 2. Walk back from the NEWER of the two entries: the mutation being
349
+ // applied-or-reverted is always the newer entry's, so its stamp is
350
+ // the page where that change is visible. Undo therefore stays on
351
+ // the page the user just edited instead of teleporting to the
352
+ // previous entry's page; older entries are the fallback when the
353
+ // stamped page doesn't survive the restore (undo-of-add).
350
354
  async function applySnapshotString(snapshotStr, targetIndex, cameFromIndex) {
351
355
  const brandPageMakerStore = useBrandPageMakerStore();
352
356
  let snapshot;
@@ -384,9 +388,13 @@ export const useHistoryStore = defineStore('history', () => {
384
388
  // Source snapshot unparseable — fall through to walk-back.
385
389
  }
386
390
  }
387
- // Step 2: walk-back fallback for non-page-structural edits.
391
+ // Step 2: walk back from the newer entry — for undo that's the entry
392
+ // being undone (stamped with the page the user made that edit on),
393
+ // for redo it's the target. Starting at targetIndex here teleported
394
+ // undo to the PREVIOUS entry's page whenever consecutive entries were
395
+ // captured on different pages.
388
396
  if (!resolvedActivePageId) {
389
- for (let i = targetIndex; i >= 0; i--) {
397
+ for (let i = Math.max(targetIndex, cameFromIndex); i >= 0; i--) {
390
398
  const candidate = entries.value[i]?.activePageId;
391
399
  if (candidate && restoredPageIds.has(candidate)) {
392
400
  resolvedActivePageId = candidate;
package/lib/src/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { A as T, a as E, b as s, c as I, d as S, e as N, f as e, B as A, g as O, h as C, i as t, j as G, k as D, l as P, m as R, n as L, o, p as M, q as r, r as n, s as b, t as l, u as F, v as i, w as c, x as g, y as B, z as Y, C as U, D as d, E as u, F as H, G as p, H as y, I as K, J as m, K as k, L as V, M as X, N as v, O as h, P as f, Q as W, R as x, S as z, T as w, U as Z, V as j, W as q, X as J, Y as Q, Z as $, $ as aa, a0 as _a, a1 as Ta, a2 as Ea, a3 as sa, a4 as Ia, a5 as Sa, a6 as Na, a7 as ea, a8 as Aa, a9 as Oa, aa as Ca, ab as ta, ac as Ga, ad as Da, ae as Pa, af as Ra, ag as La, ah as oa, ai as Ma, aj as ra, ak as na, al as ba, am as la, an as Fa, ao as ia, ap as ca, aq as ga, ar as Ba, as as Ya, at as Ua, au as da, av as ua, aw as Ha, ax as pa, ay as ya, az as Ka, aA as ma, aB as ka, aC as Va, aD as Xa, aE as va, aF as ha, aG as fa, aH as Wa, aI as xa, aJ as za, aK as wa, aL as Za, aM as ja, aN as qa, aO as Ja, aP as Qa, aQ as $a, aR as a_, aS as __, aT as T_, aU as E_, aV as s_, aW as I_, aX as S_, aY as N_, aZ as e_, a_ as A_, a$ as O_, b0 as C_, b1 as t_, b2 as G_, b3 as D_, b4 as P_, b5 as R_, b6 as L_, b7 as o_, b8 as M_, b9 as r_, ba as n_, bb as b_, bc as l_, bd as F_, be as i_, bf as c_, bg as g_, bh as B_, bi as Y_, bj as U_, bk as d_, bl as u_, bm as H_, bn as p_, bo as y_, bp as K_, bq as m_, br as k_, bs as V_, bt as X_, bu as v_, bv as h_, bw as f_, bx as W_, by as x_, bz as z_, bA as w_, bB as Z_, bC as j_, bD as q_, bE as J_, bF as Q_, bG as $_, bH as aT, bI as _T, bJ as TT, bK as ET, bL as sT, bM as IT, bN as ST, bO as NT, bP as eT, bQ as AT, bR as OT, bS as CT, bT as tT, bU as GT, bV as DT, bW as PT, bX as RT, bY as LT, bZ as oT, b_ as MT, b$ as rT, c0 as nT, c1 as bT, c2 as lT, c3 as FT, c4 as iT, c5 as cT, c6 as gT, c7 as BT, c8 as YT, c9 as UT, ca as dT, cb as uT, cc as HT, cd as pT, ce as yT, cf as KT, cg as mT, ch as kT, ci as VT, cj as XT, ck as vT, cl as hT, cm as fT, cn as WT, co as xT, cp as zT, cq as wT, cr as ZT, cs as jT, ct as qT, cu as JT } from "./lib-C0lwMScz.js";
1
+ import { A as T, a as E, b as s, c as I, d as S, e as N, f as e, B as A, g as O, h as C, i as t, j as G, k as D, l as P, m as R, n as L, o, p as M, q as r, r as n, s as b, t as l, u as F, v as i, w as c, x as g, y as B, z as Y, C as U, D as d, E as u, F as H, G as p, H as y, I as K, J as m, K as k, L as V, M as X, N as v, O as h, P as f, Q as W, R as x, S as z, T as w, U as Z, V as j, W as q, X as J, Y as Q, Z as $, $ as aa, a0 as _a, a1 as Ta, a2 as Ea, a3 as sa, a4 as Ia, a5 as Sa, a6 as Na, a7 as ea, a8 as Aa, a9 as Oa, aa as Ca, ab as ta, ac as Ga, ad as Da, ae as Pa, af as Ra, ag as La, ah as oa, ai as Ma, aj as ra, ak as na, al as ba, am as la, an as Fa, ao as ia, ap as ca, aq as ga, ar as Ba, as as Ya, at as Ua, au as da, av as ua, aw as Ha, ax as pa, ay as ya, az as Ka, aA as ma, aB as ka, aC as Va, aD as Xa, aE as va, aF as ha, aG as fa, aH as Wa, aI as xa, aJ as za, aK as wa, aL as Za, aM as ja, aN as qa, aO as Ja, aP as Qa, aQ as $a, aR as a_, aS as __, aT as T_, aU as E_, aV as s_, aW as I_, aX as S_, aY as N_, aZ as e_, a_ as A_, a$ as O_, b0 as C_, b1 as t_, b2 as G_, b3 as D_, b4 as P_, b5 as R_, b6 as L_, b7 as o_, b8 as M_, b9 as r_, ba as n_, bb as b_, bc as l_, bd as F_, be as i_, bf as c_, bg as g_, bh as B_, bi as Y_, bj as U_, bk as d_, bl as u_, bm as H_, bn as p_, bo as y_, bp as K_, bq as m_, br as k_, bs as V_, bt as X_, bu as v_, bv as h_, bw as f_, bx as W_, by as x_, bz as z_, bA as w_, bB as Z_, bC as j_, bD as q_, bE as J_, bF as Q_, bG as $_, bH as aT, bI as _T, bJ as TT, bK as ET, bL as sT, bM as IT, bN as ST, bO as NT, bP as eT, bQ as AT, bR as OT, bS as CT, bT as tT, bU as GT, bV as DT, bW as PT, bX as RT, bY as LT, bZ as oT, b_ as MT, b$ as rT, c0 as nT, c1 as bT, c2 as lT, c3 as FT, c4 as iT, c5 as cT, c6 as gT, c7 as BT, c8 as YT, c9 as UT, ca as dT, cb as uT, cc as HT, cd as pT, ce as yT, cf as KT, cg as mT, ch as kT, ci as VT, cj as XT, ck as vT, cl as hT, cm as fT, cn as WT, co as xT, cp as zT, cq as wT, cr as ZT, cs as jT, ct as qT, cu as JT } from "./lib-CtSZjhZb.js";
2
2
  import { createPinia as $T, setActivePinia as aE } from "pinia";
3
3
  export {
4
4
  T as ABOUT_SECTION_SETTINGS_CONFIG,
@@ -66487,10 +66487,10 @@ const Fi = /* @__PURE__ */ p9(JU1), QU1 = (e, t, n) => {
66487
66487
  D2(() => n.context.isDesignCom, async () => {
66488
66488
  const M = r9().toLowerCase(), S = n.context.isDesignCom ? "Dcom" : "BrandCrowd";
66489
66489
  try {
66490
- const { default: _ } = await PV(/* @__PURE__ */ Object.assign({ "./watermark/CreatedOnBrandCrowd-de-de.vue": () => import("./CreatedOnBrandCrowd-de-de-DGLT4mjc.js"), "./watermark/CreatedOnBrandCrowd-en-us.vue": () => import("./CreatedOnBrandCrowd-en-us-dyPp4NQB.js"), "./watermark/CreatedOnBrandCrowd-es-es.vue": () => import("./CreatedOnBrandCrowd-es-es-pxoT8xpT.js"), "./watermark/CreatedOnBrandCrowd-fr-ca.vue": () => import("./CreatedOnBrandCrowd-fr-ca-Bpvv3YSe.js"), "./watermark/CreatedOnBrandCrowd-fr-fr.vue": () => import("./CreatedOnBrandCrowd-fr-fr-Bpvv3YSe.js"), "./watermark/CreatedOnBrandCrowd-pt-br.vue": () => import("./CreatedOnBrandCrowd-pt-br-DqKwinmI.js"), "./watermark/CreatedOnBrandCrowd-pt-pt.vue": () => import("./CreatedOnBrandCrowd-pt-pt-DqKwinmI.js"), "./watermark/CreatedOnDcom-de-de.vue": () => import("./CreatedOnDcom-de-de-DhhAudIO.js"), "./watermark/CreatedOnDcom-en-us.vue": () => import("./CreatedOnDcom-en-us-DZhMl0Ro.js"), "./watermark/CreatedOnDcom-es-es.vue": () => import("./CreatedOnDcom-es-es-brPE0-Lo.js"), "./watermark/CreatedOnDcom-fr-ca.vue": () => import("./CreatedOnDcom-fr-ca-CzKZrAVq.js"), "./watermark/CreatedOnDcom-fr-fr.vue": () => import("./CreatedOnDcom-fr-fr-JLjx-E9X.js"), "./watermark/CreatedOnDcom-pt-br.vue": () => import("./CreatedOnDcom-pt-br-B_4Ot1uS.js"), "./watermark/CreatedOnDcom-pt-pt.vue": () => import("./CreatedOnDcom-pt-pt-By5SiPq_.js") }), `./watermark/CreatedOn${S}-${M}.vue`, 3);
66490
+ const { default: _ } = await PV(/* @__PURE__ */ Object.assign({ "./watermark/CreatedOnBrandCrowd-de-de.vue": () => import("./CreatedOnBrandCrowd-de-de-BoBmsU5p.js"), "./watermark/CreatedOnBrandCrowd-en-us.vue": () => import("./CreatedOnBrandCrowd-en-us-VTBk9ZeK.js"), "./watermark/CreatedOnBrandCrowd-es-es.vue": () => import("./CreatedOnBrandCrowd-es-es-CwYO5ZGB.js"), "./watermark/CreatedOnBrandCrowd-fr-ca.vue": () => import("./CreatedOnBrandCrowd-fr-ca-ZNEyNVVj.js"), "./watermark/CreatedOnBrandCrowd-fr-fr.vue": () => import("./CreatedOnBrandCrowd-fr-fr-ZNEyNVVj.js"), "./watermark/CreatedOnBrandCrowd-pt-br.vue": () => import("./CreatedOnBrandCrowd-pt-br-D1q4-n_v.js"), "./watermark/CreatedOnBrandCrowd-pt-pt.vue": () => import("./CreatedOnBrandCrowd-pt-pt-D1q4-n_v.js"), "./watermark/CreatedOnDcom-de-de.vue": () => import("./CreatedOnDcom-de-de-CFvvAm2h.js"), "./watermark/CreatedOnDcom-en-us.vue": () => import("./CreatedOnDcom-en-us-B5WlETVx.js"), "./watermark/CreatedOnDcom-es-es.vue": () => import("./CreatedOnDcom-es-es-CatVjoa9.js"), "./watermark/CreatedOnDcom-fr-ca.vue": () => import("./CreatedOnDcom-fr-ca-uyrRJVf9.js"), "./watermark/CreatedOnDcom-fr-fr.vue": () => import("./CreatedOnDcom-fr-fr-CKSa6Crw.js"), "./watermark/CreatedOnDcom-pt-br.vue": () => import("./CreatedOnDcom-pt-br-BIcGDf-8.js"), "./watermark/CreatedOnDcom-pt-pt.vue": () => import("./CreatedOnDcom-pt-pt-BhKpuziQ.js") }), `./watermark/CreatedOn${S}-${M}.vue`, 3);
66491
66491
  i.value = _;
66492
66492
  } catch {
66493
- const { default: x } = await PV(/* @__PURE__ */ Object.assign({ "./watermark/CreatedOnBrandCrowd-en-us.vue": () => import("./CreatedOnBrandCrowd-en-us-dyPp4NQB.js"), "./watermark/CreatedOnDcom-en-us.vue": () => import("./CreatedOnDcom-en-us-DZhMl0Ro.js") }), `./watermark/CreatedOn${S}-en-us.vue`, 3);
66493
+ const { default: x } = await PV(/* @__PURE__ */ Object.assign({ "./watermark/CreatedOnBrandCrowd-en-us.vue": () => import("./CreatedOnBrandCrowd-en-us-VTBk9ZeK.js"), "./watermark/CreatedOnDcom-en-us.vue": () => import("./CreatedOnDcom-en-us-B5WlETVx.js") }), `./watermark/CreatedOn${S}-en-us.vue`, 3);
66494
66494
  i.value = x;
66495
66495
  }
66496
66496
  }, {
@@ -78717,7 +78717,7 @@ const s0 = (e) => {
78717
78717
  }
78718
78718
  }
78719
78719
  if (!F1)
78720
- for (let x1 = q; x1 >= 0; x1--) {
78720
+ for (let x1 = Math.max(q, r1); x1 >= 0; x1--) {
78721
78721
  const O1 = t.value[x1]?.activePageId;
78722
78722
  if (O1 && U1.has(O1)) {
78723
78723
  F1 = O1;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@designcrowd/library.brand-page",
3
3
  "description": "A collection of Maker/Designer applications",
4
- "version": "6.0.6-undo-11",
4
+ "version": "6.0.6-undo-12",
5
5
  "author": "Design.com Eng",
6
6
  "license": "UNLICENSED",
7
7
  "type": "module",
@@ -816,6 +816,40 @@ describe('history-store (single stack + JSON-string snapshots)', () => {
816
816
  );
817
817
  });
818
818
 
819
+ it('undo stays on the page where the undone edit was made (both pages survive the restore)', async () => {
820
+ // Baseline: home + page-2 both exist, user is on home.
821
+ mockPageNavigationStore.activePageId = 'page-home';
822
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
823
+ (mockMakerStore.brandPageData as any).pages = [
824
+ { id: 'page-home', contents: [] },
825
+ { id: 'page-2', contents: [] },
826
+ ];
827
+
828
+ const store = useHistoryStore();
829
+
830
+ await store.captureBaseline();
831
+
832
+ // User navigates to page-2 and edits content there. No page was
833
+ // added or removed, so the structural diff (step 1) finds nothing
834
+ // and resolution falls to the walk-back.
835
+ mockPageNavigationStore.activePageId = 'page-2';
836
+ captureMutated(store);
837
+
838
+ mockMakerStore.applyHistorySnapshot.mockClear();
839
+ await store.undo();
840
+
841
+ // The change being reverted lives on page-2 — the entry being
842
+ // undone is stamped with it and the page survives the restore, so
843
+ // the user stays there instead of teleporting to the baseline's
844
+ // page-home (the pre-fix behavior).
845
+ expect(mockMakerStore.applyHistorySnapshot).toHaveBeenCalledWith(
846
+ expect.anything(),
847
+ 'page-2',
848
+ expect.any(String),
849
+ false,
850
+ );
851
+ });
852
+
819
853
  it('walks back when the captured activePageId no longer exists in the restored snapshot (page-add undo)', async () => {
820
854
  // Baseline: only page-home, user is on page-home.
821
855
  mockPageNavigationStore.activePageId = 'page-home';
@@ -471,8 +471,12 @@ export const useHistoryStore = defineStore('history', () => {
471
471
  // 1. Diff `cameFromIndex` against target — pages present in target
472
472
  // but absent from source are being restored/added; navigate there
473
473
  // (undo-of-delete, redo-of-add).
474
- // 2. Walk back from targetIndex for the closest entry whose
475
- // activePageId still exists (undo-of-add and non-page edits).
474
+ // 2. Walk back from the NEWER of the two entries: the mutation being
475
+ // applied-or-reverted is always the newer entry's, so its stamp is
476
+ // the page where that change is visible. Undo therefore stays on
477
+ // the page the user just edited instead of teleporting to the
478
+ // previous entry's page; older entries are the fallback when the
479
+ // stamped page doesn't survive the restore (undo-of-add).
476
480
  async function applySnapshotString(
477
481
  snapshotStr: string,
478
482
  targetIndex: number,
@@ -522,9 +526,13 @@ export const useHistoryStore = defineStore('history', () => {
522
526
  }
523
527
  }
524
528
 
525
- // Step 2: walk-back fallback for non-page-structural edits.
529
+ // Step 2: walk back from the newer entry — for undo that's the entry
530
+ // being undone (stamped with the page the user made that edit on),
531
+ // for redo it's the target. Starting at targetIndex here teleported
532
+ // undo to the PREVIOUS entry's page whenever consecutive entries were
533
+ // captured on different pages.
526
534
  if (!resolvedActivePageId) {
527
- for (let i = targetIndex; i >= 0; i--) {
535
+ for (let i = Math.max(targetIndex, cameFromIndex); i >= 0; i--) {
528
536
  const candidate = entries.value[i]?.activePageId;
529
537
 
530
538
  if (candidate && restoredPageIds.has(candidate)) {