@designcrowd/library.brand-page 5.18.1-undo-29 → 5.18.1-undo-32
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-BxL6mTJW.js → CreatedOnBrandCrowd-de-de-DUgkmx89.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-en-us-BPbjqfkj.js → CreatedOnBrandCrowd-en-us-C5dQGLuA.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-es-es-DDsoe143.js → CreatedOnBrandCrowd-es-es-CjPcnNlq.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-fr-Dak7ppy_.js → CreatedOnBrandCrowd-fr-ca-D2wnZOOE.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-ca-Dak7ppy_.js → CreatedOnBrandCrowd-fr-fr-D2wnZOOE.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-pt-BUAneEVD.js → CreatedOnBrandCrowd-pt-br-OQj-IBh_.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-br-BUAneEVD.js → CreatedOnBrandCrowd-pt-pt-OQj-IBh_.js} +1 -1
- package/lib/src/{CreatedOnDcom-de-de-BJ00bTz_.js → CreatedOnDcom-de-de-DLijuIaL.js} +1 -1
- package/lib/src/{CreatedOnDcom-en-us-B0V1M9Hs.js → CreatedOnDcom-en-us-D9M_heGE.js} +1 -1
- package/lib/src/{CreatedOnDcom-es-es-YDMLB7u6.js → CreatedOnDcom-es-es-PgWwbBLA.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-ca-DppQ26s1.js → CreatedOnDcom-fr-ca-BXiB-abj.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-fr-0Xi-3slB.js → CreatedOnDcom-fr-fr-BXhTmu7F.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-br-De-wHqSu.js → CreatedOnDcom-pt-br-3e6y567w.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-pt-CQGAsn5D.js → CreatedOnDcom-pt-pt-GojOtHmO.js} +1 -1
- package/lib/src/brand-page-maker/components/action-bar/ActionBar.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMakerTemplateSettings.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/brandpage-settings/ReplaceImageSettingsForBrandPageSettings.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/seo-settings/UrlSettings.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/social-share/SocialShare.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.d.ts +1 -1
- package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.js +46 -22
- package/lib/src/brand-page-maker/stores/history/history-store.js +66 -66
- package/lib/src/index.mjs +1 -1
- package/lib/src/{lib-YRlMax_i.js → lib-DVs3jUit.js} +18674 -18654
- package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +65 -1
- package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.js +12 -0
- package/lib/src/shared/content-settings/components/content-settings/ReplaceImageSettingsForContent.mixin.d.ts +1 -1
- package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.d.ts +1 -1
- package/lib/src/shared/logo-settings/components/EditLogoSettings.mixin.d.ts +1 -0
- package/lib/src/shared/logo-settings/components/LogoSettings.mixin.d.ts +2 -1
- package/lib/src/shared/logo-settings/store/editable-logo-store.d.ts +14 -0
- package/lib/src/shared/logo-settings/store/editable-logo-store.js +26 -10
- package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +1 -1
- package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +2 -1
- package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +1 -1
- package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +1 -1
- package/package.json +1 -1
- package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.ts +53 -23
- package/src/brand-page-maker/stores/history/history-store.test.ts +29 -135
- package/src/brand-page-maker/stores/history/history-store.ts +85 -76
- package/src/shared/content-settings/components/content-settings/ContentSettings.mixin.ts +12 -0
- package/src/shared/logo-settings/store/editable-logo-store.ts +28 -11
package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts
CHANGED
|
@@ -146,7 +146,7 @@ declare const _default: import("vue").DefineComponent<{}, {
|
|
|
146
146
|
}>(payload: P): Promise<void>;
|
|
147
147
|
_captureTemplateSwitchIfEnabled(): void;
|
|
148
148
|
applyHistorySnapshot(snapshot: import("@brand-page").BrandPageModel, activePageId?: string | undefined, logoEditsStr?: string | undefined): Promise<void>;
|
|
149
|
-
_syncLogoSettingsFromSnapshot(snapshot: import("@brand-page").BrandPageModel, logoEditsStr?: string | undefined): void
|
|
149
|
+
_syncLogoSettingsFromSnapshot(snapshot: import("@brand-page").BrandPageModel, logoEditsStr?: string | undefined): Promise<void>;
|
|
150
150
|
_navigateToActivePage(activePageId?: string | undefined): void;
|
|
151
151
|
_fallbackSidebarIfSelectedContentMissing(snapshot: import("@brand-page").BrandPageModel): void;
|
|
152
152
|
export(): import("@brand-page").BrandPageModel;
|
|
@@ -844,6 +844,70 @@ declare const _default: import("vue").DefineComponent<{}, {
|
|
|
844
844
|
sendAiSendPromptEvent: (ctaLocation: string) => void;
|
|
845
845
|
sendAiStopGenerationEvent: (ctaLocation: string) => void;
|
|
846
846
|
};
|
|
847
|
+
historyStore: import("pinia").Store<"history", Pick<{
|
|
848
|
+
entries: import("vue").ShallowRef<import("@brand-page-maker/stores/history/history-store").HistoryEntry[], import("@brand-page-maker/stores/history/history-store").HistoryEntry[]>;
|
|
849
|
+
currentIndex: import("vue").Ref<number, number>;
|
|
850
|
+
isApplyingSnapshot: import("vue").Ref<boolean, boolean>;
|
|
851
|
+
baselineCaptured: import("vue").Ref<boolean, boolean>;
|
|
852
|
+
canUndo: import("vue").ComputedRef<boolean>;
|
|
853
|
+
canRedo: import("vue").ComputedRef<boolean>;
|
|
854
|
+
captureBaseline: () => void;
|
|
855
|
+
capture: (args: {
|
|
856
|
+
source: "manual_edit" | "template_switch" | "ai_changeset" | "rich_text";
|
|
857
|
+
actor: "user" | "ai_builder";
|
|
858
|
+
label?: string | undefined;
|
|
859
|
+
}) => "committed" | "oversized" | "noop" | "skipped";
|
|
860
|
+
captureTemplateSwitch: (label?: string | undefined) => "committed" | "oversized" | "noop" | "skipped";
|
|
861
|
+
captureAiChangeset: (label?: string | undefined) => "committed" | "oversized" | "noop" | "skipped";
|
|
862
|
+
mergeNextMutation: () => void;
|
|
863
|
+
undo: () => Promise<void>;
|
|
864
|
+
redo: () => Promise<void>;
|
|
865
|
+
reset: () => void;
|
|
866
|
+
getCurrentSizeBytes: () => number;
|
|
867
|
+
getCurrentEntryCount: () => number;
|
|
868
|
+
}, "entries" | "currentIndex" | "isApplyingSnapshot" | "baselineCaptured">, Pick<{
|
|
869
|
+
entries: import("vue").ShallowRef<import("@brand-page-maker/stores/history/history-store").HistoryEntry[], import("@brand-page-maker/stores/history/history-store").HistoryEntry[]>;
|
|
870
|
+
currentIndex: import("vue").Ref<number, number>;
|
|
871
|
+
isApplyingSnapshot: import("vue").Ref<boolean, boolean>;
|
|
872
|
+
baselineCaptured: import("vue").Ref<boolean, boolean>;
|
|
873
|
+
canUndo: import("vue").ComputedRef<boolean>;
|
|
874
|
+
canRedo: import("vue").ComputedRef<boolean>;
|
|
875
|
+
captureBaseline: () => void;
|
|
876
|
+
capture: (args: {
|
|
877
|
+
source: "manual_edit" | "template_switch" | "ai_changeset" | "rich_text";
|
|
878
|
+
actor: "user" | "ai_builder";
|
|
879
|
+
label?: string | undefined;
|
|
880
|
+
}) => "committed" | "oversized" | "noop" | "skipped";
|
|
881
|
+
captureTemplateSwitch: (label?: string | undefined) => "committed" | "oversized" | "noop" | "skipped";
|
|
882
|
+
captureAiChangeset: (label?: string | undefined) => "committed" | "oversized" | "noop" | "skipped";
|
|
883
|
+
mergeNextMutation: () => void;
|
|
884
|
+
undo: () => Promise<void>;
|
|
885
|
+
redo: () => Promise<void>;
|
|
886
|
+
reset: () => void;
|
|
887
|
+
getCurrentSizeBytes: () => number;
|
|
888
|
+
getCurrentEntryCount: () => number;
|
|
889
|
+
}, "canUndo" | "canRedo">, Pick<{
|
|
890
|
+
entries: import("vue").ShallowRef<import("@brand-page-maker/stores/history/history-store").HistoryEntry[], import("@brand-page-maker/stores/history/history-store").HistoryEntry[]>;
|
|
891
|
+
currentIndex: import("vue").Ref<number, number>;
|
|
892
|
+
isApplyingSnapshot: import("vue").Ref<boolean, boolean>;
|
|
893
|
+
baselineCaptured: import("vue").Ref<boolean, boolean>;
|
|
894
|
+
canUndo: import("vue").ComputedRef<boolean>;
|
|
895
|
+
canRedo: import("vue").ComputedRef<boolean>;
|
|
896
|
+
captureBaseline: () => void;
|
|
897
|
+
capture: (args: {
|
|
898
|
+
source: "manual_edit" | "template_switch" | "ai_changeset" | "rich_text";
|
|
899
|
+
actor: "user" | "ai_builder";
|
|
900
|
+
label?: string | undefined;
|
|
901
|
+
}) => "committed" | "oversized" | "noop" | "skipped";
|
|
902
|
+
captureTemplateSwitch: (label?: string | undefined) => "committed" | "oversized" | "noop" | "skipped";
|
|
903
|
+
captureAiChangeset: (label?: string | undefined) => "committed" | "oversized" | "noop" | "skipped";
|
|
904
|
+
mergeNextMutation: () => void;
|
|
905
|
+
undo: () => Promise<void>;
|
|
906
|
+
redo: () => Promise<void>;
|
|
907
|
+
reset: () => void;
|
|
908
|
+
getCurrentSizeBytes: () => number;
|
|
909
|
+
getCurrentEntryCount: () => number;
|
|
910
|
+
}, "reset" | "undo" | "redo" | "captureBaseline" | "capture" | "captureTemplateSwitch" | "captureAiChangeset" | "mergeNextMutation" | "getCurrentSizeBytes" | "getCurrentEntryCount">>;
|
|
847
911
|
externalEditor: import("@tiptap/vue-3").Editor;
|
|
848
912
|
}, {
|
|
849
913
|
categoryTabs: CategoryTab[];
|
package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.js
CHANGED
|
@@ -11,6 +11,7 @@ import { useExternalRichTextEditor } from '@brand-page-maker/composables/rich-te
|
|
|
11
11
|
import { switchAllContentToRTE, transformToRTE, RTE_ALLOWED_SECTION_TYPES, } from '@brand-page-maker/utils';
|
|
12
12
|
import { useUiStyleSettingsStore } from '../../../style-settings/store';
|
|
13
13
|
import { usePageNavigationStore } from '../../../../shared/page-navigation/store/page-navigation-store';
|
|
14
|
+
import { useHistoryStore } from '@brand-page-maker/stores/history/history-store';
|
|
14
15
|
export default defineComponent({
|
|
15
16
|
setup() {
|
|
16
17
|
const brandPageMakerStore = useBrandPageMakerStore();
|
|
@@ -20,6 +21,7 @@ export default defineComponent({
|
|
|
20
21
|
const styleSettingsStore = useUiStyleSettingsStore();
|
|
21
22
|
const userStore = useBrandPageMakerUserStore();
|
|
22
23
|
const eventTracker = useEventTracker();
|
|
24
|
+
const historyStore = useHistoryStore();
|
|
23
25
|
const { externalEditor } = useExternalRichTextEditor();
|
|
24
26
|
return {
|
|
25
27
|
mode: computed(() => contentSettingsStore.mode),
|
|
@@ -36,6 +38,7 @@ export default defineComponent({
|
|
|
36
38
|
pageSettingsStore,
|
|
37
39
|
styleSettingsStore,
|
|
38
40
|
eventTracker,
|
|
41
|
+
historyStore,
|
|
39
42
|
externalEditor,
|
|
40
43
|
};
|
|
41
44
|
},
|
|
@@ -52,6 +55,15 @@ export default defineComponent({
|
|
|
52
55
|
},
|
|
53
56
|
mounted() {
|
|
54
57
|
if (this.canUseRichTextEditor) {
|
|
58
|
+
// `switchAllContentToRTE` walks every content item on every page
|
|
59
|
+
// and rewraps plain-text titles/paragraphs in TipTap HTML so they
|
|
60
|
+
// render through the inline RTE. That's a hydration write — it
|
|
61
|
+
// happens whenever the Content sidebar tab mounts (incl. when the
|
|
62
|
+
// user clicks the header in the canvas) and produces no
|
|
63
|
+
// user-visible change. Arm the merge flag so the watcher folds
|
|
64
|
+
// the resulting flush into the current head entry instead of
|
|
65
|
+
// pushing a phantom undo step.
|
|
66
|
+
this.historyStore.mergeNextMutation();
|
|
55
67
|
switchAllContentToRTE(this.pageSettingsStore, this.externalEditor, this.styleSettingsStore);
|
|
56
68
|
}
|
|
57
69
|
},
|
|
@@ -662,7 +662,7 @@ declare const _default: import("vue").DefineComponent<{}, {
|
|
|
662
662
|
}>(payload: P): Promise<void>;
|
|
663
663
|
_captureTemplateSwitchIfEnabled(): void;
|
|
664
664
|
applyHistorySnapshot(snapshot: import("@brand-page").BrandPageModel, activePageId?: string | undefined, logoEditsStr?: string | undefined): Promise<void>;
|
|
665
|
-
_syncLogoSettingsFromSnapshot(snapshot: import("@brand-page").BrandPageModel, logoEditsStr?: string | undefined): void
|
|
665
|
+
_syncLogoSettingsFromSnapshot(snapshot: import("@brand-page").BrandPageModel, logoEditsStr?: string | undefined): Promise<void>;
|
|
666
666
|
_navigateToActivePage(activePageId?: string | undefined): void;
|
|
667
667
|
_fallbackSidebarIfSelectedContentMissing(snapshot: import("@brand-page").BrandPageModel): void;
|
|
668
668
|
export(): import("@brand-page").BrandPageModel;
|
|
@@ -609,7 +609,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
609
609
|
}>(payload: P): Promise<void>;
|
|
610
610
|
_captureTemplateSwitchIfEnabled(): void;
|
|
611
611
|
applyHistorySnapshot(snapshot: import("@brand-page").BrandPageModel, activePageId?: string | undefined, logoEditsStr?: string | undefined): Promise<void>;
|
|
612
|
-
_syncLogoSettingsFromSnapshot(snapshot: import("@brand-page").BrandPageModel, logoEditsStr?: string | undefined): void
|
|
612
|
+
_syncLogoSettingsFromSnapshot(snapshot: import("@brand-page").BrandPageModel, logoEditsStr?: string | undefined): Promise<void>;
|
|
613
613
|
_navigateToActivePage(activePageId?: string | undefined): void;
|
|
614
614
|
_fallbackSidebarIfSelectedContentMissing(snapshot: import("@brand-page").BrandPageModel): void;
|
|
615
615
|
export(): import("@brand-page").BrandPageModel;
|
|
@@ -111,6 +111,7 @@ declare const _default: import("vue").DefineComponent<{}, {
|
|
|
111
111
|
getEditableLogoVariationByVariationId(id: number): any;
|
|
112
112
|
getEditableLogoVariationByBase64(base64: string): any;
|
|
113
113
|
updateEditableLogoImageUrlAsync(defaultPrimaryText?: string | undefined, overrideLogoVariation?: number | undefined, layout?: string | undefined): Promise<void>;
|
|
114
|
+
stampLogoBase64IntoBrandPageData(overrideLogoVariation?: number | undefined): void;
|
|
114
115
|
restoreVariationsForDraftToken(logoDraftToken: string): boolean;
|
|
115
116
|
updateMetadataAsync(defaultPrimaryText?: string | undefined, resetLogoTemplateMetadata?: boolean, layout?: string | undefined): Promise<void>;
|
|
116
117
|
updateEditableLogoImageByVariationAsync(editableLogoVariation: import("../store/editable-logo-store").EditableLogoVariation, defaultPrimaryText?: string | undefined, layout?: string | undefined): Promise<import("../../../clients/fabric-render-client").ModifyLogoDataResponse | null>;
|
|
@@ -136,7 +136,7 @@ declare const _default: import("vue").DefineComponent<{}, {
|
|
|
136
136
|
}>(payload: P): Promise<void>;
|
|
137
137
|
_captureTemplateSwitchIfEnabled(): void;
|
|
138
138
|
applyHistorySnapshot(snapshot: import("../../../brand-page").BrandPageModel, activePageId?: string | undefined, logoEditsStr?: string | undefined): Promise<void>;
|
|
139
|
-
_syncLogoSettingsFromSnapshot(snapshot: import("../../../brand-page").BrandPageModel, logoEditsStr?: string | undefined): void
|
|
139
|
+
_syncLogoSettingsFromSnapshot(snapshot: import("../../../brand-page").BrandPageModel, logoEditsStr?: string | undefined): Promise<void>;
|
|
140
140
|
_navigateToActivePage(activePageId?: string | undefined): void;
|
|
141
141
|
_fallbackSidebarIfSelectedContentMissing(snapshot: import("../../../brand-page").BrandPageModel): void;
|
|
142
142
|
export(): import("../../../brand-page").BrandPageModel;
|
|
@@ -300,6 +300,7 @@ declare const _default: import("vue").DefineComponent<{}, {
|
|
|
300
300
|
getEditableLogoVariationByVariationId(id: number): any;
|
|
301
301
|
getEditableLogoVariationByBase64(base64: string): any;
|
|
302
302
|
updateEditableLogoImageUrlAsync(defaultPrimaryText?: string | undefined, overrideLogoVariation?: number | undefined, layout?: string | undefined): Promise<void>;
|
|
303
|
+
stampLogoBase64IntoBrandPageData(overrideLogoVariation?: number | undefined): void;
|
|
303
304
|
restoreVariationsForDraftToken(logoDraftToken: string): boolean;
|
|
304
305
|
updateMetadataAsync(defaultPrimaryText?: string | undefined, resetLogoTemplateMetadata?: boolean, layout?: string | undefined): Promise<void>;
|
|
305
306
|
updateEditableLogoImageByVariationAsync(editableLogoVariation: import("../store").EditableLogoVariation, defaultPrimaryText?: string | undefined, layout?: string | undefined): Promise<import("../../../clients/fabric-render-client").ModifyLogoDataResponse | null>;
|
|
@@ -186,6 +186,20 @@ export declare const useUiEditableLogoStore: import("pinia").StoreDefinition<"ui
|
|
|
186
186
|
getEditableLogoVariationByVariationId(id: number): any;
|
|
187
187
|
getEditableLogoVariationByBase64(base64: string): any;
|
|
188
188
|
updateEditableLogoImageUrlAsync(defaultPrimaryText?: string, overrideLogoVariation?: number | undefined, layout?: string): Promise<void>;
|
|
189
|
+
/**
|
|
190
|
+
* Stamp `editableLogoVariations[*].base64` across every consumer in
|
|
191
|
+
* `brandPageData`: header/footer logo sections (desktop + mobile)
|
|
192
|
+
* and every `LogoContent` block on every page. Used by the live edit
|
|
193
|
+
* path after a fabric-render POST AND by the undo/redo BYO branch
|
|
194
|
+
* after `restoreVariationsForDraftToken` has rehydrated the cache.
|
|
195
|
+
*
|
|
196
|
+
* The history store strips `logoImageBase64Url` from snapshots to
|
|
197
|
+
* keep them under the 25 MB per-entry cap, so something has to
|
|
198
|
+
* write the base64 back into `brandPageData` after restore — for
|
|
199
|
+
* designed logos it's the awaited fabric-render call; for BYO it's
|
|
200
|
+
* this method.
|
|
201
|
+
*/
|
|
202
|
+
stampLogoBase64IntoBrandPageData(overrideLogoVariation?: number): void;
|
|
189
203
|
/**
|
|
190
204
|
* Restore the variations grid for `logoDraftToken` from the per-token
|
|
191
205
|
* cache. Called by `_syncLogoSettingsFromSnapshot` during undo/redo.
|
|
@@ -218,6 +218,32 @@ export const useUiEditableLogoStore = defineStore('uiEditableLogo', {
|
|
|
218
218
|
async updateEditableLogoImageUrlAsync(defaultPrimaryText, overrideLogoVariation, layout) {
|
|
219
219
|
const tasks = this.editableLogoVariations.map((x) => this.updateEditableLogoImageByVariationAsync(x, defaultPrimaryText, layout));
|
|
220
220
|
await Promise.all(tasks);
|
|
221
|
+
this.stampLogoBase64IntoBrandPageData(overrideLogoVariation);
|
|
222
|
+
// Stash the freshly rendered variation set under the active draft
|
|
223
|
+
// token so undo can restore it later without re-rendering. This is
|
|
224
|
+
// the only place in production that meaningfully populates
|
|
225
|
+
// `editableLogoVariations` (BYO upload + designed-logo setStateAsync
|
|
226
|
+
// both funnel here), so caching here keeps every distinct draft's
|
|
227
|
+
// grid available for the lifetime of the session.
|
|
228
|
+
if (this.logoDraftToken) {
|
|
229
|
+
this.variationsByDraftToken[this.logoDraftToken] =
|
|
230
|
+
this.editableLogoVariations.map((v) => ({ ...v }));
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
/**
|
|
234
|
+
* Stamp `editableLogoVariations[*].base64` across every consumer in
|
|
235
|
+
* `brandPageData`: header/footer logo sections (desktop + mobile)
|
|
236
|
+
* and every `LogoContent` block on every page. Used by the live edit
|
|
237
|
+
* path after a fabric-render POST AND by the undo/redo BYO branch
|
|
238
|
+
* after `restoreVariationsForDraftToken` has rehydrated the cache.
|
|
239
|
+
*
|
|
240
|
+
* The history store strips `logoImageBase64Url` from snapshots to
|
|
241
|
+
* keep them under the 25 MB per-entry cap, so something has to
|
|
242
|
+
* write the base64 back into `brandPageData` after restore — for
|
|
243
|
+
* designed logos it's the awaited fabric-render call; for BYO it's
|
|
244
|
+
* this method.
|
|
245
|
+
*/
|
|
246
|
+
stampLogoBase64IntoBrandPageData(overrideLogoVariation) {
|
|
221
247
|
const pageSettingStore = useUiPageSettingsStore();
|
|
222
248
|
[PAGE_SECTIONS.header, PAGE_SECTIONS.footer].forEach((section) => {
|
|
223
249
|
[VIEWPORTS.desktop, VIEWPORTS.mobile].forEach((viewport) => {
|
|
@@ -243,16 +269,6 @@ export const useUiEditableLogoStore = defineStore('uiEditableLogo', {
|
|
|
243
269
|
}
|
|
244
270
|
});
|
|
245
271
|
});
|
|
246
|
-
// Stash the freshly rendered variation set under the active draft
|
|
247
|
-
// token so undo can restore it later without re-rendering. This is
|
|
248
|
-
// the only place in production that meaningfully populates
|
|
249
|
-
// `editableLogoVariations` (BYO upload + designed-logo setStateAsync
|
|
250
|
-
// both funnel here), so caching here keeps every distinct draft's
|
|
251
|
-
// grid available for the lifetime of the session.
|
|
252
|
-
if (this.logoDraftToken) {
|
|
253
|
-
this.variationsByDraftToken[this.logoDraftToken] =
|
|
254
|
-
this.editableLogoVariations.map((v) => ({ ...v }));
|
|
255
|
-
}
|
|
256
272
|
},
|
|
257
273
|
/**
|
|
258
274
|
* Restore the variations grid for `logoDraftToken` from the per-token
|
|
@@ -3848,7 +3848,7 @@ declare const _default: import("vue").DefineComponent<{}, {
|
|
|
3848
3848
|
}>(payload: P): Promise<void>;
|
|
3849
3849
|
_captureTemplateSwitchIfEnabled(): void;
|
|
3850
3850
|
applyHistorySnapshot(snapshot: import("@brand-page").BrandPageModel, activePageId?: string | undefined, logoEditsStr?: string | undefined): Promise<void>;
|
|
3851
|
-
_syncLogoSettingsFromSnapshot(snapshot: import("@brand-page").BrandPageModel, logoEditsStr?: string | undefined): void
|
|
3851
|
+
_syncLogoSettingsFromSnapshot(snapshot: import("@brand-page").BrandPageModel, logoEditsStr?: string | undefined): Promise<void>;
|
|
3852
3852
|
_navigateToActivePage(activePageId?: string | undefined): void;
|
|
3853
3853
|
_fallbackSidebarIfSelectedContentMissing(snapshot: import("@brand-page").BrandPageModel): void;
|
|
3854
3854
|
export(): import("@brand-page").BrandPageModel;
|
|
@@ -4287,6 +4287,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
4287
4287
|
getEditableLogoVariationByVariationId(id: number): any;
|
|
4288
4288
|
getEditableLogoVariationByBase64(base64: string): any;
|
|
4289
4289
|
updateEditableLogoImageUrlAsync(defaultPrimaryText?: string | undefined, overrideLogoVariation?: number | undefined, layout?: string | undefined): Promise<void>;
|
|
4290
|
+
stampLogoBase64IntoBrandPageData(overrideLogoVariation?: number | undefined): void;
|
|
4290
4291
|
restoreVariationsForDraftToken(logoDraftToken: string): boolean;
|
|
4291
4292
|
updateMetadataAsync(defaultPrimaryText?: string | undefined, resetLogoTemplateMetadata?: boolean, layout?: string | undefined): Promise<void>;
|
|
4292
4293
|
updateEditableLogoImageByVariationAsync(editableLogoVariation: import("@shared/logo-settings/store").EditableLogoVariation, defaultPrimaryText?: string | undefined, layout?: string | undefined): Promise<import("../../../../clients/fabric-render-client").ModifyLogoDataResponse | null>;
|
|
@@ -4407,7 +4408,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
4407
4408
|
}>(payload: P): Promise<void>;
|
|
4408
4409
|
_captureTemplateSwitchIfEnabled(): void;
|
|
4409
4410
|
applyHistorySnapshot(snapshot: import("@brand-page").BrandPageModel, activePageId?: string | undefined, logoEditsStr?: string | undefined): Promise<void>;
|
|
4410
|
-
_syncLogoSettingsFromSnapshot(snapshot: import("@brand-page").BrandPageModel, logoEditsStr?: string | undefined): void
|
|
4411
|
+
_syncLogoSettingsFromSnapshot(snapshot: import("@brand-page").BrandPageModel, logoEditsStr?: string | undefined): Promise<void>;
|
|
4411
4412
|
_navigateToActivePage(activePageId?: string | undefined): void;
|
|
4412
4413
|
_fallbackSidebarIfSelectedContentMissing(snapshot: import("@brand-page").BrandPageModel): void;
|
|
4413
4414
|
export(): import("@brand-page").BrandPageModel;
|
package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts
CHANGED
|
@@ -185,7 +185,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
185
185
|
}>(payload: P): Promise<void>;
|
|
186
186
|
_captureTemplateSwitchIfEnabled(): void;
|
|
187
187
|
applyHistorySnapshot(snapshot: import("@brand-page/models").BrandPageModel, activePageId?: string | undefined, logoEditsStr?: string | undefined): Promise<void>;
|
|
188
|
-
_syncLogoSettingsFromSnapshot(snapshot: import("@brand-page/models").BrandPageModel, logoEditsStr?: string | undefined): void
|
|
188
|
+
_syncLogoSettingsFromSnapshot(snapshot: import("@brand-page/models").BrandPageModel, logoEditsStr?: string | undefined): Promise<void>;
|
|
189
189
|
_navigateToActivePage(activePageId?: string | undefined): void;
|
|
190
190
|
_fallbackSidebarIfSelectedContentMissing(snapshot: import("@brand-page/models").BrandPageModel): void;
|
|
191
191
|
export(): import("@brand-page/models").BrandPageModel;
|
|
@@ -577,7 +577,7 @@ declare const _default: import("vue").DefineComponent<{}, {
|
|
|
577
577
|
}>(payload: P): Promise<void>;
|
|
578
578
|
_captureTemplateSwitchIfEnabled(): void;
|
|
579
579
|
applyHistorySnapshot(snapshot: import("@brand-page").BrandPageModel, activePageId?: string | undefined, logoEditsStr?: string | undefined): Promise<void>;
|
|
580
|
-
_syncLogoSettingsFromSnapshot(snapshot: import("@brand-page").BrandPageModel, logoEditsStr?: string | undefined): void
|
|
580
|
+
_syncLogoSettingsFromSnapshot(snapshot: import("@brand-page").BrandPageModel, logoEditsStr?: string | undefined): Promise<void>;
|
|
581
581
|
_navigateToActivePage(activePageId?: string | undefined): void;
|
|
582
582
|
_fallbackSidebarIfSelectedContentMissing(snapshot: import("@brand-page").BrandPageModel): void;
|
|
583
583
|
export(): import("@brand-page").BrandPageModel;
|
package/package.json
CHANGED
|
@@ -33,6 +33,7 @@ import type {
|
|
|
33
33
|
import type { UserFeatures } from '../user';
|
|
34
34
|
import { useBrandPageMakerUserStore } from '../user';
|
|
35
35
|
import { defineStore } from 'pinia';
|
|
36
|
+
import { toRaw } from 'vue';
|
|
36
37
|
import { useUiStore } from '../ui';
|
|
37
38
|
import type { LogoSettingsState } from '@shared/logo-settings/store';
|
|
38
39
|
import {
|
|
@@ -894,7 +895,7 @@ export const useBrandPageMakerStore = defineStore('brandPageMaker', {
|
|
|
894
895
|
// text, support text, logo colors, fonts), `editableLogoStore.logoEdits`
|
|
895
896
|
// is restored from that string so the sidebar form fields and the
|
|
896
897
|
// save-time fabric-render POST both pick up the pre-edit state.
|
|
897
|
-
this._syncLogoSettingsFromSnapshot(snapshot, logoEditsStr);
|
|
898
|
+
await this._syncLogoSettingsFromSnapshot(snapshot, logoEditsStr);
|
|
898
899
|
|
|
899
900
|
// 9. If the sidebar is editing a content item that no longer exists in
|
|
900
901
|
// the restored page, fall back to the Content tab so the user doesn't
|
|
@@ -914,15 +915,24 @@ export const useBrandPageMakerStore = defineStore('brandPageMaker', {
|
|
|
914
915
|
this._navigateToActivePage(activePageId);
|
|
915
916
|
},
|
|
916
917
|
|
|
917
|
-
_syncLogoSettingsFromSnapshot(
|
|
918
|
+
async _syncLogoSettingsFromSnapshot(
|
|
918
919
|
snapshot: BrandPageModel,
|
|
919
920
|
logoEditsStr?: string,
|
|
920
|
-
): void {
|
|
921
|
+
): Promise<void> {
|
|
921
922
|
const logoSettingsStore = useUiLogoSettingsStore();
|
|
922
923
|
const editableLogoStore = useUiEditableLogoStore();
|
|
923
924
|
const logoStore = useLogoStore();
|
|
924
925
|
const containerStore = useBrandPageContainerStore();
|
|
925
926
|
|
|
927
|
+
// Snapshot the pre-restore logo identity BEFORE we $patch logoEdits.
|
|
928
|
+
// Used below to short-circuit the fabric-render call when the entry
|
|
929
|
+
// we're restoring has the same logoEdits + draft token as the live
|
|
930
|
+
// state — i.e. only non-logo state changed between the two entries.
|
|
931
|
+
const prevLogoEditsStr = JSON.stringify(
|
|
932
|
+
toRaw(editableLogoStore.logoEdits),
|
|
933
|
+
);
|
|
934
|
+
const prevDraftToken = editableLogoStore.logoDraftToken;
|
|
935
|
+
|
|
926
936
|
// Restore `editableLogoStore.logoEdits` first — sidecar to `brandPageData`,
|
|
927
937
|
// captured per-entry. Wholesale-replace via `$patch` so a previous
|
|
928
938
|
// entry's textObjects/colors don't leak through (e.g. switching
|
|
@@ -981,6 +991,22 @@ export const useBrandPageMakerStore = defineStore('brandPageMaker', {
|
|
|
981
991
|
|
|
982
992
|
editableLogoStore.setLogoDraftToken(draftToken);
|
|
983
993
|
|
|
994
|
+
// Did the logo identity actually change between the two entries?
|
|
995
|
+
// If both `logoEdits` and the draft token match what was already
|
|
996
|
+
// live, the cached `editableLogoVariations` is still the right
|
|
997
|
+
// render and we just need to stamp it back into `brandPageData`
|
|
998
|
+
// (history-store strips `logoImageBase64Url` from snapshots, so
|
|
999
|
+
// the page-level base64 fields are now empty).
|
|
1000
|
+
const logoUnchanged =
|
|
1001
|
+
prevDraftToken === draftToken &&
|
|
1002
|
+
(logoEditsStr === undefined || logoEditsStr === prevLogoEditsStr);
|
|
1003
|
+
|
|
1004
|
+
if (logoUnchanged) {
|
|
1005
|
+
editableLogoStore.stampLogoBase64IntoBrandPageData();
|
|
1006
|
+
|
|
1007
|
+
return;
|
|
1008
|
+
}
|
|
1009
|
+
|
|
984
1010
|
const isByo = !!draft?.isByo;
|
|
985
1011
|
|
|
986
1012
|
if (isByo) {
|
|
@@ -988,41 +1014,45 @@ export const useBrandPageMakerStore = defineStore('brandPageMaker', {
|
|
|
988
1014
|
// `variationsByDraftToken` keyed off that token always matches the
|
|
989
1015
|
// base64 the user saw at capture. No re-render — the uploaded
|
|
990
1016
|
// image bytes are the source of truth and there's nothing for
|
|
991
|
-
// fabric-render to derive.
|
|
992
|
-
|
|
1017
|
+
// fabric-render to derive. After restoring the variations cache,
|
|
1018
|
+
// stamp the base64 back across header/footer/per-page logo
|
|
1019
|
+
// content; the snapshot itself doesn't carry `logoImageBase64Url`.
|
|
1020
|
+
if (editableLogoStore.restoreVariationsForDraftToken(draftToken)) {
|
|
1021
|
+
editableLogoStore.stampLogoBase64IntoBrandPageData();
|
|
1022
|
+
}
|
|
993
1023
|
|
|
994
1024
|
return;
|
|
995
1025
|
}
|
|
996
1026
|
|
|
997
|
-
// Designed (non-BYO) logo
|
|
998
|
-
//
|
|
999
|
-
//
|
|
1000
|
-
//
|
|
1001
|
-
// canvas, post-undo save metadata, recalculateLogoSizes) showing
|
|
1002
|
-
// the post-edit base64 while the form fields show pre-edit state.
|
|
1003
|
-
//
|
|
1004
|
-
// Fire-and-forget the same render the live edit path runs:
|
|
1027
|
+
// Designed (non-BYO) logo whose form state actually differs from
|
|
1028
|
+
// the live state. The draft token is reused across every form-field
|
|
1029
|
+
// edit, so the per-token cache only holds the latest render —
|
|
1030
|
+
// re-issue the same fabric-render call the live edit path runs.
|
|
1005
1031
|
// `updateEditableLogoImageUrlAsync` POSTs the freshly-restored
|
|
1006
|
-
// `logoEdits
|
|
1007
|
-
//
|
|
1008
|
-
// The undo/redo apply itself stays synchronous; the canvas updates
|
|
1009
|
-
// a moment later when fabric-render responds.
|
|
1032
|
+
// `logoEdits`, writes the returned base64 across every header/footer
|
|
1033
|
+
// + per-page logo content + `editableLogoVariations`.
|
|
1010
1034
|
//
|
|
1011
|
-
//
|
|
1012
|
-
//
|
|
1013
|
-
//
|
|
1035
|
+
// Awaited (not fire-and-forget): two undos in quick succession would
|
|
1036
|
+
// otherwise kick off two parallel render bursts whose `Promise.all`
|
|
1037
|
+
// tasks interleave, leaving each variation showing whichever request
|
|
1038
|
+
// happened to win the race rather than the variation that belongs
|
|
1039
|
+
// to the snapshot the user landed on. Awaiting also keeps the call
|
|
1040
|
+
// inside the `applyHistorySnapshot`/`isApplyingSnapshot` window, so
|
|
1041
|
+
// the post-render writeback is naturally suppressed by the existing
|
|
1042
|
+
// watcher guard — no `mergeNextMutation()` needed.
|
|
1014
1043
|
if (
|
|
1015
1044
|
containerStore.isPrePurchase &&
|
|
1016
1045
|
logoEditsStr &&
|
|
1017
1046
|
logoStore.logoTemplateAsset
|
|
1018
1047
|
) {
|
|
1019
|
-
|
|
1020
|
-
|
|
1048
|
+
try {
|
|
1049
|
+
await editableLogoStore.updateEditableLogoImageUrlAsync();
|
|
1050
|
+
} catch (error) {
|
|
1021
1051
|
console.error(
|
|
1022
1052
|
'brandpage-maker-store: failed to re-render logo on history apply',
|
|
1023
1053
|
error,
|
|
1024
1054
|
);
|
|
1025
|
-
}
|
|
1055
|
+
}
|
|
1026
1056
|
}
|
|
1027
1057
|
},
|
|
1028
1058
|
|
|
@@ -22,16 +22,6 @@ const mockPageNavigationStore = {
|
|
|
22
22
|
activePageId: '',
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
const mockShopConfigStore: { paymentConfig: unknown } = {
|
|
26
|
-
paymentConfig: undefined,
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const mockPageSettingsStore: {
|
|
30
|
-
pages: { contents: { settings: { content: Record<string, unknown> } }[] }[];
|
|
31
|
-
} = {
|
|
32
|
-
pages: [],
|
|
33
|
-
};
|
|
34
|
-
|
|
35
25
|
vi.mock('../brandpage-maker/brandpage-maker-store', () => ({
|
|
36
26
|
useBrandPageMakerStore: vi.fn(() => mockMakerStore),
|
|
37
27
|
}));
|
|
@@ -46,14 +36,6 @@ vi.mock('@shared/page-navigation/store/page-navigation-store', () => ({
|
|
|
46
36
|
usePageNavigationStore: vi.fn(() => mockPageNavigationStore),
|
|
47
37
|
}));
|
|
48
38
|
|
|
49
|
-
vi.mock('@shared/ecommerce-settings/store/shop-settings-store', () => ({
|
|
50
|
-
useShopConfigStore: vi.fn(() => mockShopConfigStore),
|
|
51
|
-
}));
|
|
52
|
-
|
|
53
|
-
vi.mock('@shared/page-settings/store', () => ({
|
|
54
|
-
useUiPageSettingsStore: vi.fn(() => mockPageSettingsStore),
|
|
55
|
-
}));
|
|
56
|
-
|
|
57
39
|
// Mutate the mock between captures so each capture produces a distinct
|
|
58
40
|
// snapshot. The store now drops byte-identical captures (BP-5506: prevents
|
|
59
41
|
// undo/redo steps that do nothing visible), so tests that previously relied
|
|
@@ -86,8 +68,6 @@ describe('history-store (single stack + JSON-string snapshots)', () => {
|
|
|
86
68
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
87
69
|
(mockMakerStore.brandPageData as any).v = 1;
|
|
88
70
|
mockPageNavigationStore.activePageId = '';
|
|
89
|
-
mockShopConfigStore.paymentConfig = undefined;
|
|
90
|
-
mockPageSettingsStore.pages = [];
|
|
91
71
|
});
|
|
92
72
|
|
|
93
73
|
it('captures baseline and initialises the pointer to 0', async () => {
|
|
@@ -187,6 +167,35 @@ describe('history-store (single stack + JSON-string snapshots)', () => {
|
|
|
187
167
|
expect(store.currentIndex).toBe(1);
|
|
188
168
|
});
|
|
189
169
|
|
|
170
|
+
it('captures pre-purchase logo edits even when brandPageData is byte-identical', async () => {
|
|
171
|
+
// Pre-purchase logo-tab edits (text/color/font) live on
|
|
172
|
+
// `editableLogoStore.logoEdits` (sidecar) and the rendered base64 is
|
|
173
|
+
// stripped from snapshots to stay under the 25 MB cap. Two
|
|
174
|
+
// consecutive logo edits therefore produce identical snapshot bytes
|
|
175
|
+
// — without comparing the sidecar, every logo edit would dedup as
|
|
176
|
+
// a no-op and history would silently stop growing.
|
|
177
|
+
const editableLogoStore = useUiEditableLogoStore();
|
|
178
|
+
|
|
179
|
+
editableLogoStore.logoEdits.textObjects = [
|
|
180
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
181
|
+
{ id: 't1', role: 'primary-text', text: 'Acme' } as any,
|
|
182
|
+
];
|
|
183
|
+
|
|
184
|
+
const store = useHistoryStore();
|
|
185
|
+
|
|
186
|
+
await store.captureBaseline();
|
|
187
|
+
expect(store.entries.length).toBe(1);
|
|
188
|
+
|
|
189
|
+
// User changes the logo text — only the sidecar mutates. Snapshot
|
|
190
|
+
// bytes are identical (no brandPageData diff). Must still commit.
|
|
191
|
+
editableLogoStore.logoEdits.textObjects[0].text = 'AcmeCo';
|
|
192
|
+
|
|
193
|
+
const r = store.capture({ source: 'manual_edit', actor: 'user' });
|
|
194
|
+
|
|
195
|
+
expect(r).toBe('committed');
|
|
196
|
+
expect(store.entries.length).toBe(2);
|
|
197
|
+
});
|
|
198
|
+
|
|
190
199
|
// BP-5506 phantom-undo prevention via the `mergeNextMutation()` flag.
|
|
191
200
|
// Hydration write sites (TipTap mount, lazy paymentConfig fill,
|
|
192
201
|
// stale-page-ref clear) call this immediately before the imperative
|
|
@@ -402,121 +411,6 @@ describe('history-store (single stack + JSON-string snapshots)', () => {
|
|
|
402
411
|
});
|
|
403
412
|
});
|
|
404
413
|
|
|
405
|
-
// BP-5506 follow-up: paymentConfig is the user's Stripe Connect linkage
|
|
406
|
-
// (backend-confirmed, per project guardrails). It must be invariant
|
|
407
|
-
// under undo/redo regardless of what other edits the user makes — the
|
|
408
|
-
// restore-time re-stamp in `applySnapshotString` re-derives every live
|
|
409
|
-
// wrapper's `paymentConfig` from `shopConfigStore.paymentConfig` after
|
|
410
|
-
// each undo / redo apply. Snapshot bytes themselves can carry whatever
|
|
411
|
-
// value `brandPageData` happened to have at capture time (including
|
|
412
|
-
// undefined for sections the user never opened); the re-stamp is what
|
|
413
|
-
// makes the contract hold.
|
|
414
|
-
describe('paymentConfig invariance under undo/redo', () => {
|
|
415
|
-
it('re-stamps wrapper.paymentConfig from shopStore on undo', async () => {
|
|
416
|
-
const store = useHistoryStore();
|
|
417
|
-
|
|
418
|
-
// Live shop store has the user's Stripe linkage.
|
|
419
|
-
mockShopConfigStore.paymentConfig = {
|
|
420
|
-
id: 'live-stripe',
|
|
421
|
-
name: 'Stripe',
|
|
422
|
-
status: 'Active',
|
|
423
|
-
};
|
|
424
|
-
|
|
425
|
-
// Live page settings has a tipping section whose wrapper holds
|
|
426
|
-
// paymentConfig = undefined (e.g. the user has just undone past the
|
|
427
|
-
// baseline and `applyHistorySnapshot` rebuilt content from a
|
|
428
|
-
// paymentConfig-free snapshot).
|
|
429
|
-
mockPageSettingsStore.pages = [
|
|
430
|
-
{
|
|
431
|
-
contents: [
|
|
432
|
-
{
|
|
433
|
-
settings: {
|
|
434
|
-
content: {
|
|
435
|
-
type: 'support-me',
|
|
436
|
-
supportMeConfig: {
|
|
437
|
-
paymentOptions: [],
|
|
438
|
-
paymentConfig: undefined,
|
|
439
|
-
},
|
|
440
|
-
},
|
|
441
|
-
},
|
|
442
|
-
},
|
|
443
|
-
],
|
|
444
|
-
},
|
|
445
|
-
];
|
|
446
|
-
|
|
447
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
448
|
-
(mockMakerStore.brandPageData as any).pages = [
|
|
449
|
-
{
|
|
450
|
-
id: 'p',
|
|
451
|
-
contents: [{ type: 'support-me', supportMeConfig: {} }],
|
|
452
|
-
},
|
|
453
|
-
];
|
|
454
|
-
await store.captureBaseline();
|
|
455
|
-
captureMutated(store);
|
|
456
|
-
|
|
457
|
-
// Undo back to baseline. The mock applyHistorySnapshot is a no-op,
|
|
458
|
-
// but the restore-side re-stamp inside `applySnapshotString` should
|
|
459
|
-
// still run after it resolves.
|
|
460
|
-
await store.undo();
|
|
461
|
-
|
|
462
|
-
// Live wrapper now reflects shopStore.paymentConfig.
|
|
463
|
-
const wrapper =
|
|
464
|
-
mockPageSettingsStore.pages[0].contents[0].settings.content
|
|
465
|
-
.supportMeConfig;
|
|
466
|
-
|
|
467
|
-
expect((wrapper as { paymentConfig: unknown }).paymentConfig).toEqual({
|
|
468
|
-
id: 'live-stripe',
|
|
469
|
-
name: 'Stripe',
|
|
470
|
-
status: 'Active',
|
|
471
|
-
});
|
|
472
|
-
});
|
|
473
|
-
|
|
474
|
-
it('re-stamps to undefined when shopStore has no paymentConfig', async () => {
|
|
475
|
-
const store = useHistoryStore();
|
|
476
|
-
|
|
477
|
-
// No Stripe linkage in the shop store.
|
|
478
|
-
mockShopConfigStore.paymentConfig = undefined;
|
|
479
|
-
|
|
480
|
-
mockPageSettingsStore.pages = [
|
|
481
|
-
{
|
|
482
|
-
contents: [
|
|
483
|
-
{
|
|
484
|
-
settings: {
|
|
485
|
-
content: {
|
|
486
|
-
type: 'support-me',
|
|
487
|
-
supportMeConfig: {
|
|
488
|
-
paymentConfig: { id: 'stale', name: 'Stripe' },
|
|
489
|
-
},
|
|
490
|
-
},
|
|
491
|
-
},
|
|
492
|
-
},
|
|
493
|
-
],
|
|
494
|
-
},
|
|
495
|
-
];
|
|
496
|
-
|
|
497
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
498
|
-
(mockMakerStore.brandPageData as any).pages = [
|
|
499
|
-
{
|
|
500
|
-
id: 'p',
|
|
501
|
-
contents: [{ type: 'support-me', supportMeConfig: {} }],
|
|
502
|
-
},
|
|
503
|
-
];
|
|
504
|
-
await store.captureBaseline();
|
|
505
|
-
captureMutated(store);
|
|
506
|
-
|
|
507
|
-
await store.undo();
|
|
508
|
-
|
|
509
|
-
const wrapper =
|
|
510
|
-
mockPageSettingsStore.pages[0].contents[0].settings.content
|
|
511
|
-
.supportMeConfig;
|
|
512
|
-
|
|
513
|
-
// Stale value cleared; live wrapper now matches shopStore (undefined).
|
|
514
|
-
expect(
|
|
515
|
-
(wrapper as { paymentConfig: unknown }).paymentConfig,
|
|
516
|
-
).toBeUndefined();
|
|
517
|
-
});
|
|
518
|
-
});
|
|
519
|
-
|
|
520
414
|
it('reentrancy guard: capture no-ops when isApplyingSnapshot is true', async () => {
|
|
521
415
|
const store = useHistoryStore();
|
|
522
416
|
|