@designcrowd/library.brand-page 5.18.1-undo-26 → 5.18.1-undo-27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/src/{CreatedOnBrandCrowd-de-de-DWzLegt3.js → CreatedOnBrandCrowd-de-de-COk1RbBS.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-en-us-Dr6isTH_.js → CreatedOnBrandCrowd-en-us-CB3iIEMt.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-es-es-hPCTaL-A.js → CreatedOnBrandCrowd-es-es-CRU0kUB6.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-fr-BNDUTNc_.js → CreatedOnBrandCrowd-fr-ca-C5DdVGnT.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-ca-BNDUTNc_.js → CreatedOnBrandCrowd-fr-fr-C5DdVGnT.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-pt-DKn5U0m5.js → CreatedOnBrandCrowd-pt-br-2L9tw0-m.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-br-DKn5U0m5.js → CreatedOnBrandCrowd-pt-pt-2L9tw0-m.js} +1 -1
- package/lib/src/{CreatedOnDcom-de-de-Cxe0RSmZ.js → CreatedOnDcom-de-de-BDHBukLE.js} +1 -1
- package/lib/src/{CreatedOnDcom-en-us-D1D6h8b6.js → CreatedOnDcom-en-us-D0vKhTnI.js} +1 -1
- package/lib/src/{CreatedOnDcom-es-es-4k5Jz225.js → CreatedOnDcom-es-es-CCYUHgfO.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-ca-CeB-CL-1.js → CreatedOnDcom-fr-ca-DnPc5h-w.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-fr-D7PCXxYg.js → CreatedOnDcom-fr-fr-CvWbnzbp.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-br-D89FAdoN.js → CreatedOnDcom-pt-br-DdMZYZog.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-pt-CtJ0lm4O.js → CreatedOnDcom-pt-pt-BPvriH9Y.js} +1 -1
- package/lib/src/brand-page-maker/stores/history/history-store.js +105 -68
- package/lib/src/index.mjs +1 -1
- package/lib/src/{lib-D_xnR4VH.js → lib-CcYKXNUY.js} +7695 -7675
- package/package.json +1 -1
- package/src/brand-page-maker/stores/history/history-store.test.ts +167 -95
- package/src/brand-page-maker/stores/history/history-store.ts +139 -75
|
@@ -5,7 +5,6 @@ import { useAiWebsiteBuilderThreadStore } from '../ai-thread/ai-website-builder-
|
|
|
5
5
|
import { useEventTracker } from '../../composables/useEventTracker';
|
|
6
6
|
import { usePageNavigationStore } from '@shared/page-navigation/store/page-navigation-store';
|
|
7
7
|
import { useUiEditableLogoStore } from '@shared/logo-settings/store/editable-logo-store';
|
|
8
|
-
import { useShopConfigStore } from '@shared/ecommerce-settings/store/shop-settings-store';
|
|
9
8
|
import { useUiPageSettingsStore } from '@shared/page-settings/store';
|
|
10
9
|
import { ESCAPED_NEWLINE_CHARACTER } from '@src/constants/ui';
|
|
11
10
|
/**
|
|
@@ -50,54 +49,33 @@ const MAX_ENTRY_BYTES = 25 * 1024 * 1024;
|
|
|
50
49
|
// reactive cascades (template loadPageNo, router afterEach, layout settle)
|
|
51
50
|
// that would otherwise make undo light up before the user has done anything.
|
|
52
51
|
const BASELINE_SETTLE_MS = 2000;
|
|
53
|
-
// Content-level wrapper keys whose `paymentConfig` child is
|
|
54
|
-
//
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
// these sections — that hydration is not user authoring intent, and Stripe
|
|
58
|
-
// Connect linkage state is backend-confirmed (per `project-guardrails.md`).
|
|
52
|
+
// Content-level wrapper keys whose `paymentConfig` child is the user's
|
|
53
|
+
// Stripe Connect linkage — backend-confirmed state, not native authoring
|
|
54
|
+
// intent (per `project-guardrails.md`). It must be invariant under undo /
|
|
55
|
+
// redo regardless of what other edits the user makes.
|
|
59
56
|
//
|
|
60
|
-
// paymentConfig is kept
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
//
|
|
66
|
-
//
|
|
67
|
-
//
|
|
57
|
+
// paymentConfig is kept invariant by `applySnapshotString`:
|
|
58
|
+
// - Before applying the target snapshot, harvest each live
|
|
59
|
+
// wrapper.paymentConfig keyed by content id.
|
|
60
|
+
// - applyHistorySnapshot rebuilds page contents from the snapshot
|
|
61
|
+
// (which may carry a stale or absent paymentConfig).
|
|
62
|
+
// - After the apply resolves, walk the rebuilt live pages and re-stamp
|
|
63
|
+
// wrapper.paymentConfig from the harvest, so each wrapper holds the
|
|
64
|
+
// same paymentConfig it had immediately before the apply.
|
|
68
65
|
//
|
|
69
|
-
//
|
|
70
|
-
//
|
|
66
|
+
// Snapshots themselves still carry paymentConfig (we don't strip at
|
|
67
|
+
// capture time) — there's nothing to gain from stripping when the live
|
|
68
|
+
// value is preserved across the apply, and keeping snapshots whole avoids
|
|
69
|
+
// any data-loss risk for any future code path that might read paymentConfig
|
|
70
|
+
// from a snapshot directly. The dedup-side strip below ignores
|
|
71
|
+
// `paymentConfig` for the byte-compare so a click-without-edit doesn't
|
|
72
|
+
// generate a phantom entry.
|
|
71
73
|
const PAYMENT_CONFIG_WRAPPER_KEYS = [
|
|
72
74
|
'supportMeConfig',
|
|
73
75
|
'requestPaymentConfig',
|
|
74
76
|
'shopPaymentConfig',
|
|
75
77
|
];
|
|
76
|
-
|
|
77
|
-
* Walk a `pages` array and remove the `paymentConfig` key from every
|
|
78
|
-
* payment-config wrapper found inside `pages[*].contents[*]`. Mutates in
|
|
79
|
-
* place — caller is responsible for passing a clone if the source must
|
|
80
|
-
* remain untouched.
|
|
81
|
-
*/
|
|
82
|
-
function stripPaymentConfigsFromPages(pages) {
|
|
83
|
-
if (!Array.isArray(pages))
|
|
84
|
-
return;
|
|
85
|
-
for (const page of pages) {
|
|
86
|
-
const contents = page?.contents;
|
|
87
|
-
if (!Array.isArray(contents))
|
|
88
|
-
continue;
|
|
89
|
-
for (const content of contents) {
|
|
90
|
-
if (!content || typeof content !== 'object')
|
|
91
|
-
continue;
|
|
92
|
-
for (const key of PAYMENT_CONFIG_WRAPPER_KEYS) {
|
|
93
|
-
const wrapper = content[key];
|
|
94
|
-
if (wrapper && typeof wrapper === 'object' && !Array.isArray(wrapper)) {
|
|
95
|
-
delete wrapper.paymentConfig;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
78
|
+
const PAYMENT_CONFIG_WRAPPER_KEY_SET = new Set(PAYMENT_CONFIG_WRAPPER_KEYS);
|
|
101
79
|
export const useHistoryStore = defineStore('history', () => {
|
|
102
80
|
const eventTracker = useEventTracker();
|
|
103
81
|
// --- State ---
|
|
@@ -131,15 +109,7 @@ export const useHistoryStore = defineStore('history', () => {
|
|
|
131
109
|
if (!cachedMakerStore)
|
|
132
110
|
return null;
|
|
133
111
|
try {
|
|
134
|
-
|
|
135
|
-
// `paymentConfig` from every payment-config wrapper before re-
|
|
136
|
-
// stringifying. paymentConfig is the user's Stripe Connect linkage
|
|
137
|
-
// (backend-confirmed) and must not enter the undo stack — see
|
|
138
|
-
// `PAYMENT_CONFIG_WRAPPER_KEYS` above. The live store is never
|
|
139
|
-
// mutated; the strip operates on the detached clone only.
|
|
140
|
-
const cloned = JSON.parse(JSON.stringify(toRaw(cachedMakerStore.brandPageData)));
|
|
141
|
-
stripPaymentConfigsFromPages(cloned.pages);
|
|
142
|
-
return JSON.stringify(cloned);
|
|
112
|
+
return JSON.stringify(toRaw(cachedMakerStore.brandPageData));
|
|
143
113
|
}
|
|
144
114
|
catch (error) {
|
|
145
115
|
console.error('history-store: failed to serialize snapshot', error);
|
|
@@ -427,6 +397,29 @@ export const useHistoryStore = defineStore('history', () => {
|
|
|
427
397
|
// represent a user-visible change.
|
|
428
398
|
if (key === 'isModifiedAfterTemplateApplied')
|
|
429
399
|
continue;
|
|
400
|
+
// Strip lazily-hydrated `paymentConfig` from payment-config wrappers
|
|
401
|
+
// (`supportMeConfig` / `requestPaymentConfig` / `shopPaymentConfig`)
|
|
402
|
+
// for the dedup byte-compare. paymentConfig is preserved across
|
|
403
|
+
// every undo/redo by `applySnapshotString`'s harvest+re-stamp pair,
|
|
404
|
+
// so capturing a wrapper-only diff (e.g. lazy hydration on first
|
|
405
|
+
// section click) would generate a phantom undo entry that, on
|
|
406
|
+
// playback, has no user-visible effect. Same reasoning as the
|
|
407
|
+
// `*Style` / RTE hydration carve-outs above. See
|
|
408
|
+
// `PAYMENT_CONFIG_WRAPPER_KEYS`.
|
|
409
|
+
if (PAYMENT_CONFIG_WRAPPER_KEY_SET.has(key) &&
|
|
410
|
+
v !== null &&
|
|
411
|
+
typeof v === 'object' &&
|
|
412
|
+
!Array.isArray(v) &&
|
|
413
|
+
'paymentConfig' in v) {
|
|
414
|
+
const wrapper = v;
|
|
415
|
+
const stripped = {};
|
|
416
|
+
for (const k of Object.keys(wrapper)) {
|
|
417
|
+
if (k === 'paymentConfig')
|
|
418
|
+
continue;
|
|
419
|
+
stripped[k] = wrapper[k];
|
|
420
|
+
}
|
|
421
|
+
v = stripped;
|
|
422
|
+
}
|
|
430
423
|
// Collapse RTE default-hydration wrappers down to the plain text
|
|
431
424
|
// they wrap. Plain "X" and `<p style="..."><span ...><mark ...>X
|
|
432
425
|
// </mark></span></p>` share the same canonical "X" so a sidebar
|
|
@@ -827,51 +820,95 @@ export const useHistoryStore = defineStore('history', () => {
|
|
|
827
820
|
}
|
|
828
821
|
}
|
|
829
822
|
const targetEntry = entries.value[targetIndex];
|
|
823
|
+
// Harvest the LIVE `wrapper.paymentConfig` from every payment-config
|
|
824
|
+
// wrapper BEFORE applying the snapshot. The snapshot may carry a
|
|
825
|
+
// stale or absent paymentConfig (e.g. baseline captured before the
|
|
826
|
+
// wrapper was hydrated), but the live value reflects the current
|
|
827
|
+
// truth — wherever it came from (server bootstrap, Stripe Connect
|
|
828
|
+
// onboarding via PaymentConfigField, or the shop store's lazy hydration).
|
|
829
|
+
// We re-stamp this harvest onto the rebuilt live wrappers after the
|
|
830
|
+
// apply so paymentConfig is invariant under undo/redo regardless of
|
|
831
|
+
// what other content edits the user made. See `PAYMENT_CONFIG_WRAPPER_KEYS`.
|
|
832
|
+
const paymentConfigHarvest = harvestLivePaymentConfigsByContentId();
|
|
830
833
|
isApplyingSnapshot.value = true;
|
|
831
834
|
try {
|
|
832
835
|
await brandPageMakerStore.applyHistorySnapshot(snapshot, resolvedActivePageId, targetEntry?.logoEdits);
|
|
833
836
|
await nextTick();
|
|
834
|
-
|
|
835
|
-
// the freshly-restored content tree from the live shop store. The
|
|
836
|
-
// snapshot is paymentConfig-free (capture-time strip in
|
|
837
|
-
// `serializeCurrentSnapshot`), so without this step every wrapper
|
|
838
|
-
// would be left with `paymentConfig: undefined` after restore. The
|
|
839
|
-
// shop store's value is itself never undoable (see `project-
|
|
840
|
-
// guardrails.md` — Stripe Connect linkage is backend-confirmed).
|
|
841
|
-
restorePaymentConfigsOnLivePages();
|
|
837
|
+
restorePaymentConfigsFromHarvest(paymentConfigHarvest);
|
|
842
838
|
}
|
|
843
839
|
finally {
|
|
844
840
|
isApplyingSnapshot.value = false;
|
|
845
841
|
}
|
|
846
842
|
}
|
|
843
|
+
function harvestLivePaymentConfigsByContentId() {
|
|
844
|
+
const out = new Map();
|
|
845
|
+
try {
|
|
846
|
+
const pageSettingsStore = useUiPageSettingsStore();
|
|
847
|
+
for (const page of pageSettingsStore.pages) {
|
|
848
|
+
for (const item of page.contents) {
|
|
849
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
850
|
+
const content = item.settings.content;
|
|
851
|
+
const id = content?.id;
|
|
852
|
+
if (!id)
|
|
853
|
+
continue;
|
|
854
|
+
let entryRecord = undefined;
|
|
855
|
+
for (const key of PAYMENT_CONFIG_WRAPPER_KEYS) {
|
|
856
|
+
const wrapper = content?.[key];
|
|
857
|
+
if (wrapper &&
|
|
858
|
+
typeof wrapper === 'object' &&
|
|
859
|
+
!Array.isArray(wrapper) &&
|
|
860
|
+
'paymentConfig' in wrapper) {
|
|
861
|
+
if (!entryRecord)
|
|
862
|
+
entryRecord = {};
|
|
863
|
+
entryRecord[key] = wrapper.paymentConfig;
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
if (entryRecord)
|
|
867
|
+
out.set(id, entryRecord);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
catch (error) {
|
|
872
|
+
console.error('history-store: failed to harvest live paymentConfig before apply', error);
|
|
873
|
+
}
|
|
874
|
+
return out;
|
|
875
|
+
}
|
|
847
876
|
/**
|
|
848
|
-
*
|
|
849
|
-
*
|
|
850
|
-
*
|
|
851
|
-
*
|
|
877
|
+
* Re-stamp `wrapper.paymentConfig` onto every matching live wrapper from
|
|
878
|
+
* the pre-apply harvest. Wrappers whose content id is missing from the
|
|
879
|
+
* harvest are left as-is (e.g. a content item that didn't exist before
|
|
880
|
+
* this restore — there's nothing to preserve).
|
|
852
881
|
*/
|
|
853
|
-
function
|
|
882
|
+
function restorePaymentConfigsFromHarvest(harvest) {
|
|
883
|
+
if (harvest.size === 0)
|
|
884
|
+
return;
|
|
854
885
|
try {
|
|
855
|
-
const shopStore = useShopConfigStore();
|
|
856
886
|
const pageSettingsStore = useUiPageSettingsStore();
|
|
857
|
-
const livePaymentConfig = shopStore.paymentConfig;
|
|
858
887
|
for (const page of pageSettingsStore.pages) {
|
|
859
888
|
for (const item of page.contents) {
|
|
860
889
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
861
890
|
const content = item.settings.content;
|
|
891
|
+
const id = content?.id;
|
|
892
|
+
if (!id)
|
|
893
|
+
continue;
|
|
894
|
+
const harvestedRecord = harvest.get(id);
|
|
895
|
+
if (!harvestedRecord)
|
|
896
|
+
continue;
|
|
862
897
|
for (const key of PAYMENT_CONFIG_WRAPPER_KEYS) {
|
|
898
|
+
if (!(key in harvestedRecord))
|
|
899
|
+
continue;
|
|
863
900
|
const wrapper = content?.[key];
|
|
864
901
|
if (wrapper &&
|
|
865
902
|
typeof wrapper === 'object' &&
|
|
866
903
|
!Array.isArray(wrapper)) {
|
|
867
|
-
wrapper.paymentConfig =
|
|
904
|
+
wrapper.paymentConfig = harvestedRecord[key];
|
|
868
905
|
}
|
|
869
906
|
}
|
|
870
907
|
}
|
|
871
908
|
}
|
|
872
909
|
}
|
|
873
910
|
catch (error) {
|
|
874
|
-
console.error('history-store: failed to restore paymentConfig
|
|
911
|
+
console.error('history-store: failed to restore paymentConfig from harvest', error);
|
|
875
912
|
}
|
|
876
913
|
}
|
|
877
914
|
/** Move the pointer back one step and apply the entry at the new position. */
|
package/lib/src/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as E, a as T, 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 G, j as D, k as P, l as t, m as R, n as L, o as M, p as o, q as r, r as b, s as n, t as F, u as i, v as l, w as g, x as B, y as c, 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 k, K as m, L as V, M as X, N as h, O as v, P as W, Q as f, R as x, S as z, T as w, U as Z, V as j, W as Q, X as q, Y as J, Z as $, $ as aa, a0 as _a, a1 as Ea, a2 as Ta, 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 Ga, ac as Da, ad as Pa, ae as ta, af as Ra, ag as La, ah as Ma, ai as oa, aj as ra, ak as ba, al as na, am as Fa, an as ia, ao as la, ap as ga, aq as Ba, ar as ca, 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 ka, aB as ma, aC as Va, aD as Xa, aE as ha, aF as va, aG as Wa, aH as fa, aI as xa, aJ as za, aK as wa, aL as Za, aM as ja, aN as Qa, aO as qa, aP as Ja, aQ as $a, aR as a_, aS as __, aT as E_, aU as T_, 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 G_, b2 as D_, b3 as P_, b4 as t_, b5 as R_, b6 as L_, b7 as M_, b8 as o_, b9 as r_, ba as b_, bb as n_, bc as F_, bd as i_, be as l_, bf as g_, bg as B_, bh as c_, 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 k_, br as m_, bs as V_, bt as X_, bu as h_, bv as v_, bw as W_, bx as f_, by as x_, bz as z_, bA as w_, bB as Z_, bC as j_, bD as Q_, bE as q_, bF as J_, bG as $_, bH as aE, bI as _E, bJ as EE, bK as TE, bL as sE, bM as IE, bN as SE, bO as NE, bP as eE, bQ as AE, bR as OE, bS as CE, bT as GE, bU as DE, bV as PE, bW as tE, bX as RE, bY as LE, bZ as ME, b_ as oE, b$ as rE, c0 as bE, c1 as nE, c2 as FE, c3 as iE, c4 as lE, c5 as gE, c6 as BE, c7 as cE, c8 as YE, c9 as UE, ca as dE, cb as uE, cc as HE, cd as pE, ce as yE, cf as KE, cg as kE, ch as mE, ci as VE, cj as XE, ck as hE, cl as vE, cm as WE, cn as fE, co as xE } from "./lib-
|
|
1
|
+
import { A as E, a as T, 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 G, j as D, k as P, l as t, m as R, n as L, o as M, p as o, q as r, r as b, s as n, t as F, u as i, v as l, w as g, x as B, y as c, 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 k, K as m, L as V, M as X, N as h, O as v, P as W, Q as f, R as x, S as z, T as w, U as Z, V as j, W as Q, X as q, Y as J, Z as $, $ as aa, a0 as _a, a1 as Ea, a2 as Ta, 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 Ga, ac as Da, ad as Pa, ae as ta, af as Ra, ag as La, ah as Ma, ai as oa, aj as ra, ak as ba, al as na, am as Fa, an as ia, ao as la, ap as ga, aq as Ba, ar as ca, 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 ka, aB as ma, aC as Va, aD as Xa, aE as ha, aF as va, aG as Wa, aH as fa, aI as xa, aJ as za, aK as wa, aL as Za, aM as ja, aN as Qa, aO as qa, aP as Ja, aQ as $a, aR as a_, aS as __, aT as E_, aU as T_, 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 G_, b2 as D_, b3 as P_, b4 as t_, b5 as R_, b6 as L_, b7 as M_, b8 as o_, b9 as r_, ba as b_, bb as n_, bc as F_, bd as i_, be as l_, bf as g_, bg as B_, bh as c_, 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 k_, br as m_, bs as V_, bt as X_, bu as h_, bv as v_, bw as W_, bx as f_, by as x_, bz as z_, bA as w_, bB as Z_, bC as j_, bD as Q_, bE as q_, bF as J_, bG as $_, bH as aE, bI as _E, bJ as EE, bK as TE, bL as sE, bM as IE, bN as SE, bO as NE, bP as eE, bQ as AE, bR as OE, bS as CE, bT as GE, bU as DE, bV as PE, bW as tE, bX as RE, bY as LE, bZ as ME, b_ as oE, b$ as rE, c0 as bE, c1 as nE, c2 as FE, c3 as iE, c4 as lE, c5 as gE, c6 as BE, c7 as cE, c8 as YE, c9 as UE, ca as dE, cb as uE, cc as HE, cd as pE, ce as yE, cf as KE, cg as kE, ch as mE, ci as VE, cj as XE, ck as hE, cl as vE, cm as WE, cn as fE, co as xE } from "./lib-CcYKXNUY.js";
|
|
2
2
|
import { createPinia as wE, setActivePinia as ZE } from "pinia";
|
|
3
3
|
export {
|
|
4
4
|
E as ABOUT_SECTION_SETTINGS_CONFIG,
|