@designcrowd/library.brand-page 6.0.6-tracker-1 → 6.0.6-undo-2

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 (64) hide show
  1. package/lib/src/{CreatedOnBrandCrowd-de-de-DD0OBnij.js → CreatedOnBrandCrowd-de-de-BSFTp6yl.js} +1 -1
  2. package/lib/src/{CreatedOnBrandCrowd-en-us-DysrpsmM.js → CreatedOnBrandCrowd-en-us-rPQrOY1L.js} +1 -1
  3. package/lib/src/{CreatedOnBrandCrowd-es-es-B6twGr9h.js → CreatedOnBrandCrowd-es-es-awd8-QFa.js} +1 -1
  4. package/lib/src/{CreatedOnBrandCrowd-fr-fr-yxl0ih_4.js → CreatedOnBrandCrowd-fr-ca-CwJ4J7Ow.js} +1 -1
  5. package/lib/src/{CreatedOnBrandCrowd-fr-ca-yxl0ih_4.js → CreatedOnBrandCrowd-fr-fr-CwJ4J7Ow.js} +1 -1
  6. package/lib/src/{CreatedOnBrandCrowd-pt-pt-BtXDrIcx.js → CreatedOnBrandCrowd-pt-br-BXYfTLlD.js} +1 -1
  7. package/lib/src/{CreatedOnBrandCrowd-pt-br-BtXDrIcx.js → CreatedOnBrandCrowd-pt-pt-BXYfTLlD.js} +1 -1
  8. package/lib/src/{CreatedOnDcom-de-de-ho_ROy1L.js → CreatedOnDcom-de-de-kX6u1lNK.js} +1 -1
  9. package/lib/src/{CreatedOnDcom-en-us-C91p9kls.js → CreatedOnDcom-en-us-Bkq5sgFs.js} +1 -1
  10. package/lib/src/{CreatedOnDcom-es-es-B3FYmObE.js → CreatedOnDcom-es-es-zCAC9ujj.js} +1 -1
  11. package/lib/src/{CreatedOnDcom-fr-ca-D40m7fPx.js → CreatedOnDcom-fr-ca-BYz6Wzg5.js} +1 -1
  12. package/lib/src/{CreatedOnDcom-fr-fr-Cd57oYyc.js → CreatedOnDcom-fr-fr-CN-wAaSH.js} +1 -1
  13. package/lib/src/{CreatedOnDcom-pt-br-Du57mWxG.js → CreatedOnDcom-pt-br-BrK4Ngg-.js} +1 -1
  14. package/lib/src/{CreatedOnDcom-pt-pt-fYoPZWwr.js → CreatedOnDcom-pt-pt-AfI_g7xJ.js} +1 -1
  15. package/lib/src/brand-page/utils/logo.util.d.ts +14 -0
  16. package/lib/src/brand-page/utils/logo.util.js +19 -0
  17. package/lib/src/brand-page-maker/components/action-bar/ActionBar.mixin.d.ts +1 -1
  18. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +1 -1
  19. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.js +1 -1
  20. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMakerTemplateSettings.mixin.d.ts +1 -1
  21. package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +1 -1
  22. package/lib/src/brand-page-maker/components/brandpage-settings/ReplaceImageSettingsForBrandPageSettings.mixin.d.ts +1 -1
  23. package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.d.ts +1 -1
  24. package/lib/src/brand-page-maker/components/seo-settings/UrlSettings.mixin.d.ts +1 -1
  25. package/lib/src/brand-page-maker/components/social-share/SocialShare.mixin.d.ts +1 -1
  26. package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.d.ts +1 -1
  27. package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.js +16 -0
  28. package/lib/src/brand-page-maker/composables/useUndoRedoFlag.d.ts +6 -7
  29. package/lib/src/brand-page-maker/composables/useUndoRedoFlag.js +7 -12
  30. package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.d.ts +1 -1
  31. package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.js +12 -7
  32. package/lib/src/brand-page-maker/stores/history/history-store.d.ts +6 -0
  33. package/lib/src/brand-page-maker/stores/history/history-store.js +11 -1
  34. package/lib/src/index.mjs +83 -84
  35. package/lib/src/{lib-lMNy66QO.js → lib-BYFWAvIq.js} +22625 -22276
  36. package/lib/src/metadata-builder/builders/reorder-pages-builder.d.ts +13 -0
  37. package/lib/src/metadata-builder/builders/reorder-pages-builder.js +49 -0
  38. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +1 -1
  39. package/lib/src/shared/content-settings/components/content-settings/ReplaceImageSettingsForContent.mixin.d.ts +1 -1
  40. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.d.ts +1 -1
  41. package/lib/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.d.ts +1 -0
  42. package/lib/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.js +18 -7
  43. package/lib/src/shared/logo-settings/components/LogoSettings.mixin.d.ts +1 -1
  44. package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +1 -1
  45. package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +1 -1
  46. package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +1 -1
  47. package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +1 -1
  48. package/package.json +1 -16
  49. package/src/brand-page/utils/logo.util.test.ts +54 -1
  50. package/src/brand-page/utils/logo.util.ts +23 -0
  51. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.ts +1 -1
  52. package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.ts +17 -0
  53. package/src/brand-page-maker/composables/useUndoRedoFlag.ts +7 -13
  54. package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.test.ts +53 -0
  55. package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.ts +13 -16
  56. package/src/brand-page-maker/stores/history/history-store.test.ts +51 -0
  57. package/src/brand-page-maker/stores/history/history-store.ts +19 -0
  58. package/src/metadata-builder/builders/reorder-pages-builder.ts +80 -0
  59. package/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.ts +19 -11
  60. package/lib/src/tracker.d.ts +0 -2
  61. package/lib/src/tracker.js +0 -12
  62. package/lib/src/tracker.mjs +0 -12
  63. package/lib/src/useEventTracker-DmQ6AkNn.js +0 -356
  64. package/src/tracker.ts +0 -28
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-lMNy66QO.js";
2
+ import { _ as t } from "./lib-BYFWAvIq.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-lMNy66QO.js";
2
+ import { _ as t } from "./lib-BYFWAvIq.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-lMNy66QO.js";
2
+ import { _ as t } from "./lib-BYFWAvIq.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-lMNy66QO.js";
2
+ import { _ as t } from "./lib-BYFWAvIq.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-lMNy66QO.js";
2
+ import { _ as t } from "./lib-BYFWAvIq.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-lMNy66QO.js";
2
+ import { _ as t } from "./lib-BYFWAvIq.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-lMNy66QO.js";
2
+ import { _ as t } from "./lib-BYFWAvIq.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-lMNy66QO.js";
2
+ import { _ as e } from "./lib-BYFWAvIq.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-lMNy66QO.js";
2
+ import { _ as e } from "./lib-BYFWAvIq.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-lMNy66QO.js";
2
+ import { _ as e } from "./lib-BYFWAvIq.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-lMNy66QO.js";
2
+ import { _ as e } from "./lib-BYFWAvIq.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-lMNy66QO.js";
2
+ import { _ as e } from "./lib-BYFWAvIq.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-lMNy66QO.js";
2
+ import { _ as M } from "./lib-BYFWAvIq.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-lMNy66QO.js";
2
+ import { _ as M } from "./lib-BYFWAvIq.js";
3
3
  const Z = {}, e = {
4
4
  width: "232",
5
5
  height: "36",
@@ -30,6 +30,20 @@ export declare const calculateOptimizedLogoDimensions: (logoData: {
30
30
  width: string;
31
31
  height: string;
32
32
  };
33
+ /**
34
+ * Resolves the "current" logo image from a brand-page MODEL (the raw,
35
+ * deserialized shape — not the live stores, whose contents are wrapped in
36
+ * `settings.content`).
37
+ *
38
+ * Brand-site keeps its logo in the page header; brand-page and brand-contact
39
+ * keep it as a logo CONTENT block on the home page — the same `isBrandSite ?
40
+ * header : content` split the logo-settings store getters/setter use. This is
41
+ * the single source of truth for model-level logo reads: initial load and
42
+ * history-restore both call it so the two paths can't drift. They previously
43
+ * hard-coded `=== brandPage`, which silently excluded brand-contact and read a
44
+ * stale header logo on undo.
45
+ */
46
+ export declare const getLogoImageFromModel: (model: BrandPageModel) => LogoImageModel | undefined;
33
47
  export declare const recalculateLogoContentDimensions: (pageData: any, editableLogoVariations: {
34
48
  variationId: number;
35
49
  width: number;
@@ -225,6 +225,25 @@ export const calculateOptimizedLogoDimensions = (logoData, currentWidth, current
225
225
  }
226
226
  return { width: currentWidth, height: currentHeight };
227
227
  };
228
+ /**
229
+ * Resolves the "current" logo image from a brand-page MODEL (the raw,
230
+ * deserialized shape — not the live stores, whose contents are wrapped in
231
+ * `settings.content`).
232
+ *
233
+ * Brand-site keeps its logo in the page header; brand-page and brand-contact
234
+ * keep it as a logo CONTENT block on the home page — the same `isBrandSite ?
235
+ * header : content` split the logo-settings store getters/setter use. This is
236
+ * the single source of truth for model-level logo reads: initial load and
237
+ * history-restore both call it so the two paths can't drift. They previously
238
+ * hard-coded `=== brandPage`, which silently excluded brand-contact and read a
239
+ * stale header logo on undo.
240
+ */
241
+ export const getLogoImageFromModel = (model) => {
242
+ if (model.brandPageType === BRAND_PAGE_TYPES.brandSite) {
243
+ return model.pageHeaderDesktop?.logoImage;
244
+ }
245
+ return model.pages?.[0]?.contents?.find(isLogoContent)?.logoImage;
246
+ };
228
247
  export const recalculateLogoContentDimensions = async (pageData, editableLogoVariations, logoImage, isPrePurchase) => {
229
248
  try {
230
249
  let logoData;
@@ -118,7 +118,7 @@ declare const _default: import("vue").DefineComponent<{}, {
118
118
  content: TContent;
119
119
  }>(payload: P): Promise<void>;
120
120
  _captureTemplateSwitchIfEnabled(): void;
121
- applyHistorySnapshot(snapshot: import("@brand-page/models").BrandPageModel, activePageId?: string, logoEditsStr?: string): Promise<void>;
121
+ applyHistorySnapshot(snapshot: import("@brand-page/models").BrandPageModel, activePageId?: string, logoEditsStr?: string, selectedTemplateId?: string | false): Promise<void>;
122
122
  _syncLogoSettingsFromSnapshot(snapshot: import("@brand-page/models").BrandPageModel, logoEditsStr?: string): Promise<void>;
123
123
  _navigateToActivePage(activePageId?: string): void;
124
124
  _fallbackSidebarIfSelectedContentMissing(snapshot: import("@brand-page/models").BrandPageModel): void;
@@ -163,7 +163,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
163
163
  content: TContent;
164
164
  }>(payload: P): Promise<void>;
165
165
  _captureTemplateSwitchIfEnabled(): void;
166
- applyHistorySnapshot(snapshot: import("@brand-page").BrandPageModel, activePageId?: string, logoEditsStr?: string): Promise<void>;
166
+ applyHistorySnapshot(snapshot: import("@brand-page").BrandPageModel, activePageId?: string, logoEditsStr?: string, selectedTemplateId?: string | false): Promise<void>;
167
167
  _syncLogoSettingsFromSnapshot(snapshot: import("@brand-page").BrandPageModel, logoEditsStr?: string): Promise<void>;
168
168
  _navigateToActivePage(activePageId?: string): void;
169
169
  _fallbackSidebarIfSelectedContentMissing(snapshot: import("@brand-page").BrandPageModel): void;
@@ -196,7 +196,7 @@ export default defineComponent({
196
196
  this.brandPageMakerStore.setIsBrandPageLoaded(true);
197
197
  // Capture baseline for undo/redo when the feature is active for this
198
198
  // session — see useUndoRedoFlag.ts for the gate (LaunchDarkly flag +
199
- // brand-site + non-admin maker).
199
+ // non-admin maker; all three brands).
200
200
  if (useUndoRedoFlag().value) {
201
201
  useHistoryStore().captureBaseline();
202
202
  }
@@ -107,7 +107,7 @@ declare const _default: import("vue").DefineComponent<{}, {
107
107
  content: TContent;
108
108
  }>(payload: P): Promise<void>;
109
109
  _captureTemplateSwitchIfEnabled(): void;
110
- applyHistorySnapshot(snapshot: import("../../../lib").BrandPageModel, activePageId?: string, logoEditsStr?: string): Promise<void>;
110
+ applyHistorySnapshot(snapshot: import("../../../lib").BrandPageModel, activePageId?: string, logoEditsStr?: string, selectedTemplateId?: string | false): Promise<void>;
111
111
  _syncLogoSettingsFromSnapshot(snapshot: import("../../../lib").BrandPageModel, logoEditsStr?: string): Promise<void>;
112
112
  _navigateToActivePage(activePageId?: string): void;
113
113
  _fallbackSidebarIfSelectedContentMissing(snapshot: import("../../../lib").BrandPageModel): void;
@@ -626,7 +626,7 @@ declare const _default: import("vue").DefineComponent<{}, {
626
626
  content: TContent;
627
627
  }>(payload: P): Promise<void>;
628
628
  _captureTemplateSwitchIfEnabled(): void;
629
- applyHistorySnapshot(snapshot: import("@brand-page").BrandPageModel, activePageId?: string, logoEditsStr?: string): Promise<void>;
629
+ applyHistorySnapshot(snapshot: import("@brand-page").BrandPageModel, activePageId?: string, logoEditsStr?: string, selectedTemplateId?: string | false): Promise<void>;
630
630
  _syncLogoSettingsFromSnapshot(snapshot: import("@brand-page").BrandPageModel, logoEditsStr?: string): Promise<void>;
631
631
  _navigateToActivePage(activePageId?: string): void;
632
632
  _fallbackSidebarIfSelectedContentMissing(snapshot: import("@brand-page").BrandPageModel): void;
@@ -113,7 +113,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
113
113
  content: TContent;
114
114
  }>(payload: P): Promise<void>;
115
115
  _captureTemplateSwitchIfEnabled(): void;
116
- applyHistorySnapshot(snapshot: import("../../../brand-page").BrandPageModel, activePageId?: string, logoEditsStr?: string): Promise<void>;
116
+ applyHistorySnapshot(snapshot: import("../../../brand-page").BrandPageModel, activePageId?: string, logoEditsStr?: string, selectedTemplateId?: string | false): Promise<void>;
117
117
  _syncLogoSettingsFromSnapshot(snapshot: import("../../../brand-page").BrandPageModel, logoEditsStr?: string): Promise<void>;
118
118
  _navigateToActivePage(activePageId?: string): void;
119
119
  _fallbackSidebarIfSelectedContentMissing(snapshot: import("../../../brand-page").BrandPageModel): void;
@@ -391,7 +391,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
391
391
  content: TContent;
392
392
  }>(payload: P): Promise<void>;
393
393
  _captureTemplateSwitchIfEnabled(): void;
394
- applyHistorySnapshot(snapshot: import("../../../brand-page").BrandPageModel, activePageId?: string, logoEditsStr?: string): Promise<void>;
394
+ applyHistorySnapshot(snapshot: import("../../../brand-page").BrandPageModel, activePageId?: string, logoEditsStr?: string, selectedTemplateId?: string | false): Promise<void>;
395
395
  _syncLogoSettingsFromSnapshot(snapshot: import("../../../brand-page").BrandPageModel, logoEditsStr?: string): Promise<void>;
396
396
  _navigateToActivePage(activePageId?: string): void;
397
397
  _fallbackSidebarIfSelectedContentMissing(snapshot: import("../../../brand-page").BrandPageModel): void;
@@ -392,7 +392,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
392
392
  content: TContent;
393
393
  }>(payload: P): Promise<void>;
394
394
  _captureTemplateSwitchIfEnabled(): void;
395
- applyHistorySnapshot(snapshot: import("../../../brand-page").BrandPageModel, activePageId?: string, logoEditsStr?: string): Promise<void>;
395
+ applyHistorySnapshot(snapshot: import("../../../brand-page").BrandPageModel, activePageId?: string, logoEditsStr?: string, selectedTemplateId?: string | false): Promise<void>;
396
396
  _syncLogoSettingsFromSnapshot(snapshot: import("../../../brand-page").BrandPageModel, logoEditsStr?: string): Promise<void>;
397
397
  _navigateToActivePage(activePageId?: string): void;
398
398
  _fallbackSidebarIfSelectedContentMissing(snapshot: import("../../../brand-page").BrandPageModel): void;
@@ -123,7 +123,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
123
123
  content: TContent;
124
124
  }>(payload: P): Promise<void>;
125
125
  _captureTemplateSwitchIfEnabled(): void;
126
- applyHistorySnapshot(snapshot: import("../../../brand-page").BrandPageModel, activePageId?: string, logoEditsStr?: string): Promise<void>;
126
+ applyHistorySnapshot(snapshot: import("../../../brand-page").BrandPageModel, activePageId?: string, logoEditsStr?: string, selectedTemplateId?: string | false): Promise<void>;
127
127
  _syncLogoSettingsFromSnapshot(snapshot: import("../../../brand-page").BrandPageModel, logoEditsStr?: string): Promise<void>;
128
128
  _navigateToActivePage(activePageId?: string): void;
129
129
  _fallbackSidebarIfSelectedContentMissing(snapshot: import("../../../brand-page").BrandPageModel): void;
@@ -441,7 +441,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
441
441
  content: TContent;
442
442
  }>(payload: P): Promise<void>;
443
443
  _captureTemplateSwitchIfEnabled(): void;
444
- applyHistorySnapshot(snapshot: import("@brand-page").BrandPageModel, activePageId?: string, logoEditsStr?: string): Promise<void>;
444
+ applyHistorySnapshot(snapshot: import("@brand-page").BrandPageModel, activePageId?: string, logoEditsStr?: string, selectedTemplateId?: string | false): Promise<void>;
445
445
  _syncLogoSettingsFromSnapshot(snapshot: import("@brand-page").BrandPageModel, logoEditsStr?: string): Promise<void>;
446
446
  _navigateToActivePage(activePageId?: string): void;
447
447
  _fallbackSidebarIfSelectedContentMissing(snapshot: import("@brand-page").BrandPageModel): void;
@@ -266,6 +266,22 @@ export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDro
266
266
  // Update model when editor content changes
267
267
  editor.on('update', () => {
268
268
  const sanitizedData = sanitiseClientSideRTE(editor.getHTML());
269
+ // An update fired while the editor is unfocused is TipTap rewriting the
270
+ // model back into its canonical HTML during mount rehydration or a
271
+ // programmatic setContent — not a user edit. Fold it into the current
272
+ // head so merely selecting a section doesn't push a phantom undo entry
273
+ // (BP-5810). The construction-time arm above lapses before this async
274
+ // write-back fires, so re-arm here. Genuine edits happen while focused and
275
+ // still push a new entry.
276
+ //
277
+ // Known limitation: a programmatic toolbar command run on an editor the
278
+ // user hasn't focused yet would also merge (losing that undo step). Today
279
+ // the RTE only mounts inside an already-open settings drawer and the user
280
+ // focuses it before formatting, so this doesn't occur — revisit if a
281
+ // consumer ever drives toolbar actions on an unfocused editor.
282
+ if (!editor.isFocused && !historyStore.isApplyingSnapshot) {
283
+ historyStore.mergeNextMutation();
284
+ }
269
285
  emit('update:modelValue', sanitizedData.sanitizedHtml);
270
286
  });
271
287
  editor.on('selectionUpdate', () => {
@@ -1,16 +1,15 @@
1
1
  import { type ComputedRef } from 'vue';
2
2
  /**
3
- * Returns whether undo/redo is active for the current maker session. All
4
- * three conditions must hold:
3
+ * Returns whether undo/redo is active for the current maker session. Both
4
+ * conditions must hold:
5
5
  *
6
6
  * 1. `userStore.features.canUseUndoRedo` is true. The flag is populated by
7
7
  * the consumer (BrandCrowd.Net / web-renderer) via the
8
8
  * `WebsiteDesignUserFeatures.CanUseUndoRedo` boolean on the ViewModel —
9
- * same precedent as RichTextEditor / GettyVideos / AITextGenerator.
10
- * 2. The maker is a brand-site (Website Maker). V1 scope is brand-site
11
- * only; brand-page (single-page profile) and brand-contact (vCard) are
12
- * out of scope.
13
- * 3. The session is NOT in admin-maker mode (`userStore.isAdmin`). The
9
+ * same precedent as RichTextEditor / GettyVideos / AITextGenerator. The
10
+ * one flag governs all three brands (brand-site, brand-page,
11
+ * brand-contact) there is no per-brand gating.
12
+ * 2. The session is NOT in admin-maker mode (`userStore.isAdmin`). The
14
13
  * admin maker uses the same components but a different editing flow
15
14
  * (template authoring) where undo/redo is out of scope.
16
15
  */
@@ -1,25 +1,20 @@
1
1
  import { computed } from 'vue';
2
2
  import { useBrandPageMakerUserStore } from '@brand-page-maker/stores/user';
3
- import { useBrandPageMakerStore } from '@brand-page-maker/stores/brandpage-maker/brandpage-maker-store';
4
3
  /**
5
- * Returns whether undo/redo is active for the current maker session. All
6
- * three conditions must hold:
4
+ * Returns whether undo/redo is active for the current maker session. Both
5
+ * conditions must hold:
7
6
  *
8
7
  * 1. `userStore.features.canUseUndoRedo` is true. The flag is populated by
9
8
  * the consumer (BrandCrowd.Net / web-renderer) via the
10
9
  * `WebsiteDesignUserFeatures.CanUseUndoRedo` boolean on the ViewModel —
11
- * same precedent as RichTextEditor / GettyVideos / AITextGenerator.
12
- * 2. The maker is a brand-site (Website Maker). V1 scope is brand-site
13
- * only; brand-page (single-page profile) and brand-contact (vCard) are
14
- * out of scope.
15
- * 3. The session is NOT in admin-maker mode (`userStore.isAdmin`). The
10
+ * same precedent as RichTextEditor / GettyVideos / AITextGenerator. The
11
+ * one flag governs all three brands (brand-site, brand-page,
12
+ * brand-contact) there is no per-brand gating.
13
+ * 2. The session is NOT in admin-maker mode (`userStore.isAdmin`). The
16
14
  * admin maker uses the same components but a different editing flow
17
15
  * (template authoring) where undo/redo is out of scope.
18
16
  */
19
17
  export function useUndoRedoFlag() {
20
18
  const userStore = useBrandPageMakerUserStore();
21
- const brandPageMakerStore = useBrandPageMakerStore();
22
- return computed(() => userStore.features.canUseUndoRedo &&
23
- brandPageMakerStore.isBrandSite &&
24
- !userStore.isAdmin);
19
+ return computed(() => userStore.features.canUseUndoRedo && !userStore.isAdmin);
25
20
  }
@@ -211,7 +211,7 @@ export declare const useBrandPageMakerStore: import("pinia").StoreDefinition<"br
211
211
  * feature flag is on — see `BrandPageMaker.mixin.ts`).
212
212
  */
213
213
  _captureTemplateSwitchIfEnabled(): void;
214
- applyHistorySnapshot(snapshot: BrandPageModel, activePageId?: string, logoEditsStr?: string): Promise<void>;
214
+ applyHistorySnapshot(snapshot: BrandPageModel, activePageId?: string, logoEditsStr?: string, selectedTemplateId?: string | false): Promise<void>;
215
215
  _syncLogoSettingsFromSnapshot(snapshot: BrandPageModel, logoEditsStr?: string): Promise<void>;
216
216
  /**
217
217
  * Restore the active page after a history apply. The id passed in is
@@ -494,7 +494,7 @@ export const useBrandPageMakerStore = defineStore('brandPageMaker', {
494
494
  return;
495
495
  historyStore.captureTemplateSwitch();
496
496
  },
497
- async applyHistorySnapshot(snapshot, activePageId, logoEditsStr) {
497
+ async applyHistorySnapshot(snapshot, activePageId, logoEditsStr, selectedTemplateId) {
498
498
  const styleSettingsStore = useUiStyleSettingsStore();
499
499
  const navigationStyleSettingsStore = useUiNavigationStyleSettingsStore();
500
500
  const backgroundSettingsStore = useUiBackgroundSettingsStore();
@@ -574,6 +574,15 @@ export const useBrandPageMakerStore = defineStore('brandPageMaker', {
574
574
  this.ogDescription = snapshot.ogDescription;
575
575
  this.cookieOptions = snapshot.cookieOptions;
576
576
  this.saveContactSettings = snapshot.saveContactSettings;
577
+ // 7b. Restore the selected-template pointer that drives the templates
578
+ // sidebar highlight. It's a UI pointer, not part of the persisted
579
+ // model, so it rides along as a history-entry sidecar (like
580
+ // `activePageId`). Its watchers only reset scroll position (no
581
+ // template re-application), so setting it here is safe during apply.
582
+ // (BP-5813)
583
+ if (selectedTemplateId !== undefined) {
584
+ this.setSelectedTemplateId({ templateId: selectedTemplateId });
585
+ }
577
586
  // 8. Re-sync the logo-settings sidebar's `selectedLogoImage` from the
578
587
  // restored header logo. The preview rehydrates via the page contents,
579
588
  // but `uiLogoSettings` holds its own copy that drives the sidebar
@@ -622,9 +631,7 @@ export const useBrandPageMakerStore = defineStore('brandPageMaker', {
622
631
  console.error('brandpage-maker-store: failed to restore logoEdits', error);
623
632
  }
624
633
  }
625
- const logoImage = snapshot.brandPageType === BRAND_PAGE_TYPES.default
626
- ? snapshot.pages?.[0]?.contents?.find((c) => c.type === 'logo')?.logoImage
627
- : snapshot.pageHeaderDesktop?.logoImage;
634
+ const logoImage = logoUtil.getLogoImageFromModel(snapshot);
628
635
  if (!logoImage)
629
636
  return;
630
637
  logoSettingsStore.setState({
@@ -848,9 +855,7 @@ export const useBrandPageMakerStore = defineStore('brandPageMaker', {
848
855
  this.setBrandPageType({
849
856
  brandPageType: _brandPageType,
850
857
  });
851
- let logoImage = brandPageModel.brandPageType === BRAND_PAGE_TYPES.default
852
- ? brandPageModel.pages?.[0].contents.find((c) => c.type === 'logo')?.logoImage
853
- : brandPageModel.pageHeaderDesktop?.logoImage;
858
+ let logoImage = logoUtil.getLogoImageFromModel(brandPageModel);
854
859
  if (!logoImage?.logoDraftToken) {
855
860
  logoImage = logoUtil.safeGetLogoImageFromLogoImageUrl(logoVariationImageUrls[0]);
856
861
  }
@@ -16,6 +16,12 @@ export interface HistoryEntry {
16
16
  activePageId: string;
17
17
  /** JSON-stringified `editableLogoStore.logoEdits`. Undefined if logo tab never opened. */
18
18
  logoEdits?: string;
19
+ /**
20
+ * Selected template id at capture time — drives the templates sidebar
21
+ * highlight. `false` when no template is selected. Sidecar to
22
+ * `brandPageData` (not part of the persisted model), like `activePageId`.
23
+ */
24
+ selectedTemplateId?: string | false;
19
25
  }
20
26
  export declare const useHistoryStore: import("pinia").StoreDefinition<"history", Pick<{
21
27
  entries: import("vue").ShallowRef<HistoryEntry[], HistoryEntry[]>;
@@ -97,6 +97,9 @@ export const useHistoryStore = defineStore('history', () => {
97
97
  function getCurrentActivePageId() {
98
98
  return usePageNavigationStore().activePageId ?? '';
99
99
  }
100
+ function getCurrentSelectedTemplateId() {
101
+ return useBrandPageMakerStore().selectedTemplateId;
102
+ }
100
103
  function serializeCurrentLogoEdits() {
101
104
  try {
102
105
  const editableLogoStore = useUiEditableLogoStore();
@@ -150,6 +153,7 @@ export const useHistoryStore = defineStore('history', () => {
150
153
  sizeBytes: args.snapshot.length,
151
154
  activePageId: args.activePageId,
152
155
  logoEdits: args.logoEdits,
156
+ selectedTemplateId: args.selectedTemplateId,
153
157
  };
154
158
  // FR-11: truncate redo tail, then append.
155
159
  const next = entries.value.slice(0, currentIndex.value + 1);
@@ -209,6 +213,7 @@ export const useHistoryStore = defineStore('history', () => {
209
213
  return;
210
214
  const activePageId = getCurrentActivePageId();
211
215
  const logoEdits = serializeCurrentLogoEdits();
216
+ const selectedTemplateId = getCurrentSelectedTemplateId();
212
217
  // Settle window: fold post-init reactive cascades back into the
213
218
  // baseline so undo doesn't light up before the user has done
214
219
  // anything.
@@ -228,6 +233,7 @@ export const useHistoryStore = defineStore('history', () => {
228
233
  sizeBytes: snapshot.length,
229
234
  activePageId,
230
235
  logoEdits,
236
+ selectedTemplateId,
231
237
  },
232
238
  ];
233
239
  return;
@@ -241,6 +247,7 @@ export const useHistoryStore = defineStore('history', () => {
241
247
  sizeBytes: snapshot.length,
242
248
  activePageId,
243
249
  logoEdits,
250
+ selectedTemplateId,
244
251
  };
245
252
  entries.value = next;
246
253
  return;
@@ -251,6 +258,7 @@ export const useHistoryStore = defineStore('history', () => {
251
258
  actor: 'user',
252
259
  activePageId,
253
260
  logoEdits,
261
+ selectedTemplateId,
254
262
  });
255
263
  };
256
264
  // Monotonic — first mutation arms; subsequent ones inside the window
@@ -299,6 +307,7 @@ export const useHistoryStore = defineStore('history', () => {
299
307
  sizeBytes: snapshot.length,
300
308
  activePageId: getCurrentActivePageId(),
301
309
  logoEdits: serializeCurrentLogoEdits(),
310
+ selectedTemplateId: getCurrentSelectedTemplateId(),
302
311
  },
303
312
  ];
304
313
  currentIndex.value = 0;
@@ -318,6 +327,7 @@ export const useHistoryStore = defineStore('history', () => {
318
327
  snapshot,
319
328
  activePageId: getCurrentActivePageId(),
320
329
  logoEdits: serializeCurrentLogoEdits(),
330
+ selectedTemplateId: getCurrentSelectedTemplateId(),
321
331
  ...args,
322
332
  });
323
333
  }
@@ -393,7 +403,7 @@ export const useHistoryStore = defineStore('history', () => {
393
403
  pendingTimerIsMerge = false;
394
404
  cancelPendingAutoCapture();
395
405
  try {
396
- await brandPageMakerStore.applyHistorySnapshot(snapshot, resolvedActivePageId, targetEntry?.logoEdits);
406
+ await brandPageMakerStore.applyHistorySnapshot(snapshot, resolvedActivePageId, targetEntry?.logoEdits, targetEntry?.selectedTemplateId);
397
407
  }
398
408
  finally {
399
409
  isApplyingSnapshot.value = false;