@designcrowd/library.brand-page 5.18.3-button-fix-1 → 5.18.3-undo-35

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 (112) hide show
  1. package/lib/src/{CreatedOnBrandCrowd-de-de-DQLtpdLe.js → CreatedOnBrandCrowd-de-de-nGPiEkaH.js} +1 -1
  2. package/lib/src/{CreatedOnBrandCrowd-en-us-CvEhlADd.js → CreatedOnBrandCrowd-en-us-D3ibxOrN.js} +1 -1
  3. package/lib/src/{CreatedOnBrandCrowd-es-es-pYQeTTC0.js → CreatedOnBrandCrowd-es-es-BAq0PV5c.js} +1 -1
  4. package/lib/src/{CreatedOnBrandCrowd-fr-fr-CcE-iCEq.js → CreatedOnBrandCrowd-fr-ca-9foHt2a-.js} +1 -1
  5. package/lib/src/{CreatedOnBrandCrowd-fr-ca-CcE-iCEq.js → CreatedOnBrandCrowd-fr-fr-9foHt2a-.js} +1 -1
  6. package/lib/src/{CreatedOnBrandCrowd-pt-pt-OyhWWWyO.js → CreatedOnBrandCrowd-pt-br-DO739Uxl.js} +1 -1
  7. package/lib/src/{CreatedOnBrandCrowd-pt-br-OyhWWWyO.js → CreatedOnBrandCrowd-pt-pt-DO739Uxl.js} +1 -1
  8. package/lib/src/{CreatedOnDcom-de-de-DH98FFLS.js → CreatedOnDcom-de-de-CFbNW8tl.js} +1 -1
  9. package/lib/src/{CreatedOnDcom-en-us-DK67NN1r.js → CreatedOnDcom-en-us-BL34V8eu.js} +1 -1
  10. package/lib/src/{CreatedOnDcom-es-es-9-QU4BU6.js → CreatedOnDcom-es-es-BKXWvHkV.js} +1 -1
  11. package/lib/src/{CreatedOnDcom-fr-ca-U9J9H9VB.js → CreatedOnDcom-fr-ca-DCyU-m6J.js} +1 -1
  12. package/lib/src/{CreatedOnDcom-fr-fr-DqdzB1DJ.js → CreatedOnDcom-fr-fr-DEciA_zh.js} +1 -1
  13. package/lib/src/{CreatedOnDcom-pt-br-c4UiWtkB.js → CreatedOnDcom-pt-br-BVB2zdvU.js} +1 -1
  14. package/lib/src/{CreatedOnDcom-pt-pt-Do2qJsYp.js → CreatedOnDcom-pt-pt-DatUuIK6.js} +1 -1
  15. package/lib/src/brand-page-maker/components/action-bar/ActionBar.mixin.d.ts +7 -2
  16. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +7 -2
  17. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.js +10 -0
  18. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMakerTemplateSettings.mixin.d.ts +7 -2
  19. package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.js +1 -0
  20. package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +23 -2
  21. package/lib/src/brand-page-maker/components/brandpage-settings/ReplaceImageSettingsForBrandPageSettings.mixin.d.ts +7 -2
  22. package/lib/src/brand-page-maker/components/quick-link-bar/QuickLinkBar.mixin.d.ts +3 -0
  23. package/lib/src/brand-page-maker/components/quick-link-bar/QuickLinkBar.mixin.js +11 -0
  24. package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.d.ts +7 -2
  25. package/lib/src/brand-page-maker/components/seo-settings/UrlSettings.mixin.d.ts +7 -2
  26. package/lib/src/brand-page-maker/components/social-share/SocialShare.mixin.d.ts +7 -2
  27. package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.d.ts +7 -2
  28. package/lib/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.js +9 -0
  29. package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.js +20 -1
  30. package/lib/src/brand-page-maker/composables/useEventTracker.d.ts +20 -0
  31. package/lib/src/brand-page-maker/composables/useEventTracker.js +17 -0
  32. package/lib/src/brand-page-maker/composables/useUndoRedoFlag.d.ts +16 -0
  33. package/lib/src/brand-page-maker/composables/useUndoRedoFlag.js +22 -0
  34. package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.d.ts +41 -2
  35. package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.js +307 -5
  36. package/lib/src/brand-page-maker/stores/history/history-store.d.ts +83 -0
  37. package/lib/src/brand-page-maker/stores/history/history-store.js +488 -0
  38. package/lib/src/brand-page-maker/stores/logo-store/logo-store.d.ts +1 -0
  39. package/lib/src/brand-page-maker/stores/user/user-store.js +1 -0
  40. package/lib/src/bundled-translations-D1q3rSEz.js +175 -0
  41. package/lib/src/bundles/bundled-translations.json +3 -1
  42. package/lib/src/constants/ui.d.ts +1 -0
  43. package/lib/src/css/library.brand-page-brandCrowd.min.css +50 -54
  44. package/lib/src/css/library.brand-page-brandPage.min.css +50 -55
  45. package/lib/src/css/library.brand-page-designCom.min.css +50 -54
  46. package/lib/src/css/library.brand-page-preview.min.css +50 -54
  47. package/lib/src/index.mjs +1 -1
  48. package/lib/src/{lib-BI3J4Mbk.js → lib-C_Pc-5bF.js} +34307 -33712
  49. package/lib/src/metadata-builder/builders/reorder-pages-builder.d.ts +13 -0
  50. package/lib/src/metadata-builder/builders/reorder-pages-builder.js +49 -0
  51. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +87 -2
  52. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.js +5 -0
  53. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.stories.js +1 -0
  54. package/lib/src/shared/content-settings/components/content-settings/ReplaceImageSettingsForContent.mixin.d.ts +23 -2
  55. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.d.ts +16 -0
  56. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.d.ts +7 -2
  57. package/lib/src/shared/content-settings/components/draggable-item-list/DraggableItemList.mixin.d.ts +3 -0
  58. package/lib/src/shared/content-settings/components/draggable-item-list/DraggableItemList.mixin.js +19 -2
  59. package/lib/src/shared/content-settings/components/form-fields-field/FormFieldsField.mixin.js +18 -8
  60. package/lib/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.d.ts +64 -0
  61. package/lib/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.js +6 -0
  62. package/lib/src/shared/logo-settings/components/EditLogoSettings.mixin.d.ts +19 -0
  63. package/lib/src/shared/logo-settings/components/EditLogoSettings.mixin.js +11 -0
  64. package/lib/src/shared/logo-settings/components/LogoSettings.mixin.d.ts +10 -2
  65. package/lib/src/shared/logo-settings/store/editable-logo-store.d.ts +5 -1
  66. package/lib/src/shared/logo-settings/store/editable-logo-store.js +31 -0
  67. package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +24 -2
  68. package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +10 -2
  69. package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +23 -2
  70. package/lib/src/shared/side-bar/components/SideBarTabButton.mixin.d.ts +16 -0
  71. package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +23 -2
  72. package/lib/src/shared/template-settings/components/TemplatesSettings.mixin.d.ts +16 -0
  73. package/package.json +1 -1
  74. package/src/brand-page/components/button/Button.vue +2 -10
  75. package/src/brand-page/components/contact-form/ContactForm.vue +2 -2
  76. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.ts +11 -0
  77. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.vue +2 -3
  78. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.ts +1 -0
  79. package/src/brand-page-maker/components/cookie-collection/CookieSettings.vue +18 -17
  80. package/src/brand-page-maker/components/quick-link-bar/QuickLinkBar.mixin.ts +13 -0
  81. package/src/brand-page-maker/components/quick-link-bar/QuickLinkBar.vue +26 -3
  82. package/src/brand-page-maker/components/quick-link-bar/RedoButton.vue +66 -0
  83. package/src/brand-page-maker/components/quick-link-bar/UndoButton.vue +66 -0
  84. package/src/brand-page-maker/components/quick-link-bar/i18n/quick-link-bar.json +3 -1
  85. package/src/brand-page-maker/components/quick-link-bar/undo-redo-buttons.test.ts +116 -0
  86. package/src/brand-page-maker/components/save-contact/SaveContact.vue +12 -19
  87. package/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.ts +10 -0
  88. package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.ts +24 -1
  89. package/src/brand-page-maker/composables/useEventTracker.ts +29 -0
  90. package/src/brand-page-maker/composables/useUndoRedoFlag.ts +26 -0
  91. package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.test.ts +335 -0
  92. package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.ts +371 -4
  93. package/src/brand-page-maker/stores/history/history-store.test.ts +1120 -0
  94. package/src/brand-page-maker/stores/history/history-store.ts +651 -0
  95. package/src/brand-page-maker/stores/logo-store/logo-store.ts +5 -0
  96. package/src/brand-page-maker/stores/user/user-store.ts +1 -0
  97. package/src/bundles/bundled-translations.json +3 -1
  98. package/src/constants/ui.ts +1 -0
  99. package/src/metadata-builder/builders/reorder-pages-builder.ts +80 -0
  100. package/src/shared/content-settings/components/content-settings/ContentSettings.mixin.ts +5 -0
  101. package/src/shared/content-settings/components/content-settings/ContentSettings.stories.ts +1 -0
  102. package/src/shared/content-settings/components/draggable-item-list/DraggableItemList.mixin.ts +19 -2
  103. package/src/shared/content-settings/components/draggable-item-list/DraggableItemList.vue +1 -1
  104. package/src/shared/content-settings/components/form-fields-field/FormFieldsField.mixin.ts +26 -10
  105. package/src/shared/content-settings/components/logo-selection-field/LogoSelection.vue +63 -48
  106. package/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.vue +4 -0
  107. package/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.ts +7 -0
  108. package/src/shared/content-settings/components/text-field/TextField.vue +1 -0
  109. package/src/shared/content-settings/components/text-image-field/TextImageField.vue +33 -4
  110. package/src/shared/logo-settings/components/EditLogoSettings.mixin.ts +11 -0
  111. package/src/shared/logo-settings/store/editable-logo-store.ts +42 -1
  112. package/lib/src/bundled-translations-B5Fkt3qd.js +0 -175
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-BI3J4Mbk.js";
2
+ import { _ as t } from "./lib-C_Pc-5bF.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-BI3J4Mbk.js";
2
+ import { _ as t } from "./lib-C_Pc-5bF.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-BI3J4Mbk.js";
2
+ import { _ as t } from "./lib-C_Pc-5bF.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-BI3J4Mbk.js";
2
+ import { _ as t } from "./lib-C_Pc-5bF.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-BI3J4Mbk.js";
2
+ import { _ as t } from "./lib-C_Pc-5bF.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-BI3J4Mbk.js";
2
+ import { _ as t } from "./lib-C_Pc-5bF.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-BI3J4Mbk.js";
2
+ import { _ as t } from "./lib-C_Pc-5bF.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-BI3J4Mbk.js";
2
+ import { _ as e } from "./lib-C_Pc-5bF.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-BI3J4Mbk.js";
2
+ import { _ as e } from "./lib-C_Pc-5bF.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-BI3J4Mbk.js";
2
+ import { _ as e } from "./lib-C_Pc-5bF.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-BI3J4Mbk.js";
2
+ import { _ as e } from "./lib-C_Pc-5bF.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-BI3J4Mbk.js";
2
+ import { _ as e } from "./lib-C_Pc-5bF.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-BI3J4Mbk.js";
2
+ import { _ as M } from "./lib-C_Pc-5bF.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-BI3J4Mbk.js";
2
+ import { _ as M } from "./lib-C_Pc-5bF.js";
3
3
  const Z = {}, e = {
4
4
  width: "232",
5
5
  height: "36",
@@ -107,16 +107,21 @@ declare const _default: import("vue").DefineComponent<{}, {
107
107
  hideChangeTemplateConfirmModal(): void;
108
108
  onBackgroundChanged(): void;
109
109
  onChangeTemplateConfirmModalCancel(): void;
110
- onChangeTemplateConfirmModalConfirm(): void;
110
+ onChangeTemplateConfirmModalConfirm(): Promise<void>;
111
111
  onContentChanged(): void;
112
112
  onStyleChanged(): void;
113
- onTemplateSelected(payload: import("@brand-page-maker/stores").OnTemplateSelectedPayload): void;
113
+ onTemplateSelected(payload: import("@brand-page-maker/stores").OnTemplateSelectedPayload): Promise<void>;
114
114
  setSelectedTabName(payload: any): void;
115
115
  showNextNotificationMessage(): Promise<void>;
116
116
  updateContent<TContent extends import("@brand-page/models").Content, P extends {
117
117
  id: string;
118
118
  content: TContent;
119
119
  }>(payload: P): Promise<void>;
120
+ _captureTemplateSwitchIfEnabled(): void;
121
+ applyHistorySnapshot(snapshot: import("@brand-page/models").BrandPageModel, activePageId?: string | undefined, logoEditsStr?: string | undefined): Promise<void>;
122
+ _syncLogoSettingsFromSnapshot(snapshot: import("@brand-page/models").BrandPageModel, logoEditsStr?: string | undefined): Promise<void>;
123
+ _navigateToActivePage(activePageId?: string | undefined): void;
124
+ _fallbackSidebarIfSelectedContentMissing(snapshot: import("@brand-page/models").BrandPageModel): void;
120
125
  export(): import("@brand-page/models").BrandPageModel;
121
126
  setBrandPageType({ brandPageType }: {
122
127
  brandPageType: "default" | "brandSite" | "brandContact";
@@ -152,16 +152,21 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
152
152
  hideChangeTemplateConfirmModal(): void;
153
153
  onBackgroundChanged(): void;
154
154
  onChangeTemplateConfirmModalCancel(): void;
155
- onChangeTemplateConfirmModalConfirm(): void;
155
+ onChangeTemplateConfirmModalConfirm(): Promise<void>;
156
156
  onContentChanged(): void;
157
157
  onStyleChanged(): void;
158
- onTemplateSelected(payload: import("@brand-page-maker/stores").OnTemplateSelectedPayload): void;
158
+ onTemplateSelected(payload: import("@brand-page-maker/stores").OnTemplateSelectedPayload): Promise<void>;
159
159
  setSelectedTabName(payload: any): void;
160
160
  showNextNotificationMessage(): Promise<void>;
161
161
  updateContent<TContent extends import("@brand-page").Content, P extends {
162
162
  id: string;
163
163
  content: TContent;
164
164
  }>(payload: P): Promise<void>;
165
+ _captureTemplateSwitchIfEnabled(): void;
166
+ applyHistorySnapshot(snapshot: import("@brand-page").BrandPageModel, activePageId?: string | undefined, logoEditsStr?: string | undefined): Promise<void>;
167
+ _syncLogoSettingsFromSnapshot(snapshot: import("@brand-page").BrandPageModel, logoEditsStr?: string | undefined): Promise<void>;
168
+ _navigateToActivePage(activePageId?: string | undefined): void;
169
+ _fallbackSidebarIfSelectedContentMissing(snapshot: import("@brand-page").BrandPageModel): void;
165
170
  export(): import("@brand-page").BrandPageModel;
166
171
  setBrandPageType({ brandPageType }: {
167
172
  brandPageType: "default" | "brandSite" | "brandContact";
@@ -11,6 +11,8 @@ import { navigateToPageByPageId } from '../../routing';
11
11
  import { useBrandPageContainerStore } from '@brand-page-maker/stores';
12
12
  import { UI_DEVICE_MODES, UI_SCREENSIZE_MODES, } from '@shared/models';
13
13
  import { useBrandPageMakerStore, useBrandPageMakerUserStore, useLocalisedRouteStore, useUiStore, useSnapshotStore, useVideoStore, } from '@brand-page-maker/stores';
14
+ import { useHistoryStore } from '@brand-page-maker/stores/history/history-store';
15
+ import { useUndoRedoFlag } from '@brand-page-maker/composables/useUndoRedoFlag';
14
16
  import { useUiContentSettingsStore } from '@shared/content-settings/store';
15
17
  import { useUiTemplateSettingsStore } from '@shared/template-settings/store';
16
18
  import { useUiPageSettingsStore } from '@shared/page-settings/store';
@@ -189,6 +191,14 @@ export default defineComponent({
189
191
  }
190
192
  // Mark brand page as fully loaded
191
193
  this.brandPageMakerStore.setIsBrandPageLoaded(true);
194
+ // Capture baseline for undo/redo when the feature is active for this
195
+ // session. `useUndoRedoFlag` requires both the LaunchDarkly feature
196
+ // (`userStore.features.canUseUndoRedo`) AND the maker being a brand-site
197
+ // — V1 scope is brand-site only; brand-page and brand-contact don't get
198
+ // undo/redo. See useUndoRedoFlag.ts for the rationale.
199
+ if (useUndoRedoFlag().value) {
200
+ useHistoryStore().captureBaseline();
201
+ }
192
202
  this.$emit(EVENTS.Initialised);
193
203
  },
194
204
  mounted() {
@@ -96,16 +96,21 @@ declare const _default: import("vue").DefineComponent<{}, {
96
96
  hideChangeTemplateConfirmModal(): void;
97
97
  onBackgroundChanged(): void;
98
98
  onChangeTemplateConfirmModalCancel(): void;
99
- onChangeTemplateConfirmModalConfirm(): void;
99
+ onChangeTemplateConfirmModalConfirm(): Promise<void>;
100
100
  onContentChanged(): void;
101
101
  onStyleChanged(): void;
102
- onTemplateSelected(payload: import("../../stores").OnTemplateSelectedPayload): void;
102
+ onTemplateSelected(payload: import("../../stores").OnTemplateSelectedPayload): Promise<void>;
103
103
  setSelectedTabName(payload: any): void;
104
104
  showNextNotificationMessage(): Promise<void>;
105
105
  updateContent<TContent extends import("../../../lib").Content, P extends {
106
106
  id: string;
107
107
  content: TContent;
108
108
  }>(payload: P): Promise<void>;
109
+ _captureTemplateSwitchIfEnabled(): void;
110
+ applyHistorySnapshot(snapshot: import("../../../lib").BrandPageModel, activePageId?: string | undefined, logoEditsStr?: string | undefined): Promise<void>;
111
+ _syncLogoSettingsFromSnapshot(snapshot: import("../../../lib").BrandPageModel, logoEditsStr?: string | undefined): Promise<void>;
112
+ _navigateToActivePage(activePageId?: string | undefined): void;
113
+ _fallbackSidebarIfSelectedContentMissing(snapshot: import("../../../lib").BrandPageModel): void;
109
114
  export(): import("../../../lib").BrandPageModel;
110
115
  setBrandPageType({ brandPageType }: {
111
116
  brandPageType: "default" | "brandSite" | "brandContact";
@@ -53,6 +53,7 @@ export const userFeatures = {
53
53
  canUseGettyVideos: false,
54
54
  canUseGoogleAdsense: false,
55
55
  googleAdsenseEnabled: false,
56
+ canUseUndoRedo: false,
56
57
  };
57
58
  export const BRAND_PAGE = {
58
59
  styles: {
@@ -602,16 +602,21 @@ declare const _default: import("vue").DefineComponent<{}, {
602
602
  hideChangeTemplateConfirmModal(): void;
603
603
  onBackgroundChanged(): void;
604
604
  onChangeTemplateConfirmModalCancel(): void;
605
- onChangeTemplateConfirmModalConfirm(): void;
605
+ onChangeTemplateConfirmModalConfirm(): Promise<void>;
606
606
  onContentChanged(): void;
607
607
  onStyleChanged(): void;
608
- onTemplateSelected(payload: import("@brand-page-maker/stores").OnTemplateSelectedPayload): void;
608
+ onTemplateSelected(payload: import("@brand-page-maker/stores").OnTemplateSelectedPayload): Promise<void>;
609
609
  setSelectedTabName(payload: any): void;
610
610
  showNextNotificationMessage(): Promise<void>;
611
611
  updateContent<TContent extends Content, P extends {
612
612
  id: string;
613
613
  content: TContent;
614
614
  }>(payload: P): Promise<void>;
615
+ _captureTemplateSwitchIfEnabled(): void;
616
+ applyHistorySnapshot(snapshot: import("@brand-page").BrandPageModel, activePageId?: string | undefined, logoEditsStr?: string | undefined): Promise<void>;
617
+ _syncLogoSettingsFromSnapshot(snapshot: import("@brand-page").BrandPageModel, logoEditsStr?: string | undefined): Promise<void>;
618
+ _navigateToActivePage(activePageId?: string | undefined): void;
619
+ _fallbackSidebarIfSelectedContentMissing(snapshot: import("@brand-page").BrandPageModel): void;
615
620
  export(): import("@brand-page").BrandPageModel;
616
621
  setBrandPageType({ brandPageType }: {
617
622
  brandPageType: "default" | "brandSite" | "brandContact";
@@ -1046,6 +1051,22 @@ declare const _default: import("vue").DefineComponent<{}, {
1046
1051
  }>;
1047
1052
  eventTracker: {
1048
1053
  sendShippingToggleEvent: (isEnabled: boolean) => void;
1054
+ sendUndoEvent: (props: {
1055
+ entries_count: number;
1056
+ actor: string | undefined;
1057
+ }) => void;
1058
+ sendRedoEvent: (props: {
1059
+ entries_count: number;
1060
+ actor: string | undefined;
1061
+ }) => void;
1062
+ sendHistoryCappedEvent: (props: {
1063
+ entries_count: number;
1064
+ size_bytes: number;
1065
+ }) => void;
1066
+ sendHistoryOversizedEvent: (props: {
1067
+ attempted_bytes: number;
1068
+ source: string;
1069
+ }) => void;
1049
1070
  sendSaveContactEvent: () => void;
1050
1071
  sendStartForFreeEvent: () => void;
1051
1072
  sendFooterLinkClickEvent: (linkType: "watermark_logo" | "create_your_website") => void;
@@ -102,16 +102,21 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
102
102
  hideChangeTemplateConfirmModal(): void;
103
103
  onBackgroundChanged(): void;
104
104
  onChangeTemplateConfirmModalCancel(): void;
105
- onChangeTemplateConfirmModalConfirm(): void;
105
+ onChangeTemplateConfirmModalConfirm(): Promise<void>;
106
106
  onContentChanged(): void;
107
107
  onStyleChanged(): void;
108
- onTemplateSelected(payload: import("@brand-page-maker/stores").OnTemplateSelectedPayload): void;
108
+ onTemplateSelected(payload: import("@brand-page-maker/stores").OnTemplateSelectedPayload): Promise<void>;
109
109
  setSelectedTabName(payload: any): void;
110
110
  showNextNotificationMessage(): Promise<void>;
111
111
  updateContent<TContent extends import("../../../brand-page").Content, P extends {
112
112
  id: string;
113
113
  content: TContent;
114
114
  }>(payload: P): Promise<void>;
115
+ _captureTemplateSwitchIfEnabled(): void;
116
+ applyHistorySnapshot(snapshot: import("../../../brand-page").BrandPageModel, activePageId?: string | undefined, logoEditsStr?: string | undefined): Promise<void>;
117
+ _syncLogoSettingsFromSnapshot(snapshot: import("../../../brand-page").BrandPageModel, logoEditsStr?: string | undefined): Promise<void>;
118
+ _navigateToActivePage(activePageId?: string | undefined): void;
119
+ _fallbackSidebarIfSelectedContentMissing(snapshot: import("../../../brand-page").BrandPageModel): void;
115
120
  export(): import("../../../brand-page").BrandPageModel;
116
121
  setBrandPageType({ brandPageType }: {
117
122
  brandPageType: "default" | "brandSite" | "brandContact";
@@ -291,9 +291,12 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
291
291
  pushManageWebPageUpdateSensitiveContentClickEvent(): Promise<void>;
292
292
  pushManageWebPageUnpublishClickEvent(): Promise<void>;
293
293
  }>;
294
+ undoRedoEnabled: import("vue").ComputedRef<boolean>;
294
295
  }, {
295
296
  copied: boolean;
296
297
  }, {
298
+ isPublished(): boolean;
299
+ shouldShowBar(): boolean;
297
300
  brandPageUrl(): string;
298
301
  copyButtonLabel(): string;
299
302
  }, {
@@ -1,6 +1,7 @@
1
1
  import { defineComponent } from 'vue';
2
2
  import { CUSTOM_DOMAIN_STATUSES } from '@brand-page-maker/constants';
3
3
  import { useBrandPageContainerStore, useEventManagerStore, } from '@brand-page-maker/stores';
4
+ import { useUndoRedoFlag } from '@brand-page-maker/composables/useUndoRedoFlag';
4
5
  import { quickLinkBarTr } from '@src/composables/useTranslate';
5
6
  export default defineComponent({
6
7
  props: {
@@ -17,6 +18,7 @@ export default defineComponent({
17
18
  return {
18
19
  brandPageContainerStore: useBrandPageContainerStore(),
19
20
  eventManagerStore: useEventManagerStore(),
21
+ undoRedoEnabled: useUndoRedoFlag(),
20
22
  };
21
23
  },
22
24
  data() {
@@ -25,6 +27,15 @@ export default defineComponent({
25
27
  };
26
28
  },
27
29
  computed: {
30
+ isPublished() {
31
+ return this.brandPageContainerStore.isPublished;
32
+ },
33
+ // Only render the bar when at least one inner cluster has something to
34
+ // show. Otherwise we'd render an empty white strip — e.g. on an
35
+ // unpublished page with the undo flag off.
36
+ shouldShowBar() {
37
+ return Boolean(this.undoRedoEnabled) || this.isPublished;
38
+ },
28
39
  brandPageUrl() {
29
40
  if (this.brandPageContainerStore.isCustomDomainEnabled &&
30
41
  this.brandPageContainerStore.customDomain &&
@@ -380,16 +380,21 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
380
380
  hideChangeTemplateConfirmModal(): void;
381
381
  onBackgroundChanged(): void;
382
382
  onChangeTemplateConfirmModalCancel(): void;
383
- onChangeTemplateConfirmModalConfirm(): void;
383
+ onChangeTemplateConfirmModalConfirm(): Promise<void>;
384
384
  onContentChanged(): void;
385
385
  onStyleChanged(): void;
386
- onTemplateSelected(payload: import("@brand-page-maker/stores").OnTemplateSelectedPayload): void;
386
+ onTemplateSelected(payload: import("@brand-page-maker/stores").OnTemplateSelectedPayload): Promise<void>;
387
387
  setSelectedTabName(payload: any): void;
388
388
  showNextNotificationMessage(): Promise<void>;
389
389
  updateContent<TContent extends import("../../../brand-page").Content, P extends {
390
390
  id: string;
391
391
  content: TContent;
392
392
  }>(payload: P): Promise<void>;
393
+ _captureTemplateSwitchIfEnabled(): void;
394
+ applyHistorySnapshot(snapshot: import("../../../brand-page").BrandPageModel, activePageId?: string | undefined, logoEditsStr?: string | undefined): Promise<void>;
395
+ _syncLogoSettingsFromSnapshot(snapshot: import("../../../brand-page").BrandPageModel, logoEditsStr?: string | undefined): Promise<void>;
396
+ _navigateToActivePage(activePageId?: string | undefined): void;
397
+ _fallbackSidebarIfSelectedContentMissing(snapshot: import("../../../brand-page").BrandPageModel): void;
393
398
  export(): import("../../../brand-page").BrandPageModel;
394
399
  setBrandPageType({ brandPageType }: {
395
400
  brandPageType: "default" | "brandSite" | "brandContact";
@@ -381,16 +381,21 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
381
381
  hideChangeTemplateConfirmModal(): void;
382
382
  onBackgroundChanged(): void;
383
383
  onChangeTemplateConfirmModalCancel(): void;
384
- onChangeTemplateConfirmModalConfirm(): void;
384
+ onChangeTemplateConfirmModalConfirm(): Promise<void>;
385
385
  onContentChanged(): void;
386
386
  onStyleChanged(): void;
387
- onTemplateSelected(payload: import("@brand-page-maker/stores").OnTemplateSelectedPayload): void;
387
+ onTemplateSelected(payload: import("@brand-page-maker/stores").OnTemplateSelectedPayload): Promise<void>;
388
388
  setSelectedTabName(payload: any): void;
389
389
  showNextNotificationMessage(): Promise<void>;
390
390
  updateContent<TContent extends import("../../../brand-page").Content, P extends {
391
391
  id: string;
392
392
  content: TContent;
393
393
  }>(payload: P): Promise<void>;
394
+ _captureTemplateSwitchIfEnabled(): void;
395
+ applyHistorySnapshot(snapshot: import("../../../brand-page").BrandPageModel, activePageId?: string | undefined, logoEditsStr?: string | undefined): Promise<void>;
396
+ _syncLogoSettingsFromSnapshot(snapshot: import("../../../brand-page").BrandPageModel, logoEditsStr?: string | undefined): Promise<void>;
397
+ _navigateToActivePage(activePageId?: string | undefined): void;
398
+ _fallbackSidebarIfSelectedContentMissing(snapshot: import("../../../brand-page").BrandPageModel): void;
394
399
  export(): import("../../../brand-page").BrandPageModel;
395
400
  setBrandPageType({ brandPageType }: {
396
401
  brandPageType: "default" | "brandSite" | "brandContact";
@@ -112,16 +112,21 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
112
112
  hideChangeTemplateConfirmModal(): void;
113
113
  onBackgroundChanged(): void;
114
114
  onChangeTemplateConfirmModalCancel(): void;
115
- onChangeTemplateConfirmModalConfirm(): void;
115
+ onChangeTemplateConfirmModalConfirm(): Promise<void>;
116
116
  onContentChanged(): void;
117
117
  onStyleChanged(): void;
118
- onTemplateSelected(payload: import("@brand-page-maker/stores").OnTemplateSelectedPayload): void;
118
+ onTemplateSelected(payload: import("@brand-page-maker/stores").OnTemplateSelectedPayload): Promise<void>;
119
119
  setSelectedTabName(payload: any): void;
120
120
  showNextNotificationMessage(): Promise<void>;
121
121
  updateContent<TContent extends import("../../../brand-page").Content, P extends {
122
122
  id: string;
123
123
  content: TContent;
124
124
  }>(payload: P): Promise<void>;
125
+ _captureTemplateSwitchIfEnabled(): void;
126
+ applyHistorySnapshot(snapshot: import("../../../brand-page").BrandPageModel, activePageId?: string | undefined, logoEditsStr?: string | undefined): Promise<void>;
127
+ _syncLogoSettingsFromSnapshot(snapshot: import("../../../brand-page").BrandPageModel, logoEditsStr?: string | undefined): Promise<void>;
128
+ _navigateToActivePage(activePageId?: string | undefined): void;
129
+ _fallbackSidebarIfSelectedContentMissing(snapshot: import("../../../brand-page").BrandPageModel): void;
125
130
  export(): import("../../../brand-page").BrandPageModel;
126
131
  setBrandPageType({ brandPageType }: {
127
132
  brandPageType: "default" | "brandSite" | "brandContact";
@@ -432,16 +432,21 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
432
432
  hideChangeTemplateConfirmModal(): void;
433
433
  onBackgroundChanged(): void;
434
434
  onChangeTemplateConfirmModalCancel(): void;
435
- onChangeTemplateConfirmModalConfirm(): void;
435
+ onChangeTemplateConfirmModalConfirm(): Promise<void>;
436
436
  onContentChanged(): void;
437
437
  onStyleChanged(): void;
438
- onTemplateSelected(payload: import("@brand-page-maker/stores").OnTemplateSelectedPayload): void;
438
+ onTemplateSelected(payload: import("@brand-page-maker/stores").OnTemplateSelectedPayload): Promise<void>;
439
439
  setSelectedTabName(payload: any): void;
440
440
  showNextNotificationMessage(): Promise<void>;
441
441
  updateContent<TContent extends import("@brand-page").Content, P extends {
442
442
  id: string;
443
443
  content: TContent;
444
444
  }>(payload: P): Promise<void>;
445
+ _captureTemplateSwitchIfEnabled(): void;
446
+ applyHistorySnapshot(snapshot: import("@brand-page").BrandPageModel, activePageId?: string | undefined, logoEditsStr?: string | undefined): Promise<void>;
447
+ _syncLogoSettingsFromSnapshot(snapshot: import("@brand-page").BrandPageModel, logoEditsStr?: string | undefined): Promise<void>;
448
+ _navigateToActivePage(activePageId?: string | undefined): void;
449
+ _fallbackSidebarIfSelectedContentMissing(snapshot: import("@brand-page").BrandPageModel): void;
445
450
  export(): import("@brand-page").BrandPageModel;
446
451
  setBrandPageType({ brandPageType }: {
447
452
  brandPageType: "default" | "brandSite" | "brandContact";
@@ -10,6 +10,8 @@ import { usePageNavigationStore } from '../../../shared/page-navigation/store/pa
10
10
  import { navigateToPageByPageId } from '../../routing';
11
11
  import { useSnapshotStore, useAiWebsiteBuilderThreadStore, useAiCheckpointStore, useBrandPageContainerStore, useUiStore, } from '../../stores';
12
12
  import { useBrandPageMakerStore } from '../../stores';
13
+ import { useHistoryStore } from '../../stores/history/history-store';
14
+ import { useUndoRedoFlag } from '../useUndoRedoFlag';
13
15
  import { useBrandPageMakerUserStore } from '../../stores/user/user-store';
14
16
  import { useAiMetadataBuilder } from './useAiMetadataBuilder';
15
17
  import { pickErrorMessage, pickWsErrorMessage, buildSubmitErrorReport, } from './aiErrorCopy';
@@ -23,6 +25,8 @@ export function useAiWebsiteBuilderChat() {
23
25
  const aiThreadStore = useAiWebsiteBuilderThreadStore();
24
26
  const snapshotStore = useSnapshotStore();
25
27
  const brandPageMakerStore = useBrandPageMakerStore();
28
+ const historyStore = useHistoryStore();
29
+ const undoRedoEnabled = useUndoRedoFlag();
26
30
  const containerStore = useBrandPageContainerStore();
27
31
  const userStore = useBrandPageMakerUserStore();
28
32
  const uiStore = useUiStore();
@@ -298,6 +302,11 @@ export function useAiWebsiteBuilderChat() {
298
302
  navigateToPageByPageId(pageNavigationStore.activePageId);
299
303
  }
300
304
  await nextTick();
305
+ // One history entry per AI prompt (US-E1). `captureAiChangeset` cancels
306
+ // the auto-watcher's pending flush so the apply doesn't double-capture.
307
+ if (undoRedoEnabled.value) {
308
+ historyStore.captureAiChangeset();
309
+ }
301
310
  // Re-capture snapshot so subsequent messages reflect the updated page
302
311
  await snapshotStore.refreshSnapshotAsync();
303
312
  return {
@@ -21,6 +21,7 @@ import { buildInitialMarks, emToPx, isStyleChanged, pxToEm, sanitiseClientSideRT
21
21
  import { HYPERLINK_TYPE, } from '@brand-page';
22
22
  import { letterSpacingValueConvertor, colorConvertor, backgroundColorConvertor, } from '@brand-page-maker/convertors';
23
23
  import { useUiContentSettingsStore } from '@shared/content-settings/store';
24
+ import { useHistoryStore } from '@brand-page-maker/stores/history/history-store';
24
25
  import { AllSelection } from 'prosemirror-state';
25
26
  import { MaxLength } from './extensions/MaxLength';
26
27
  import { AutoLink } from './extensions/AutoLink';
@@ -72,6 +73,10 @@ export const useExternalRichTextEditor = () => {
72
73
  };
73
74
  };
74
75
  export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDropdownRef, selectedGlobalTextStyles, onSelectTextStyleType, updateRichTextEditor, textStyleTypeOptions, markedText, isHyperlinkPopupOpen, selectedLinkTypeValue) => {
76
+ const historyStore = useHistoryStore();
77
+ // TipTap rehydrates and writes back canonical HTML on mount — fold
78
+ // that into the current head instead of pushing a phantom entry.
79
+ historyStore.mergeNextMutation();
75
80
  const editor = new Editor({
76
81
  content: model.value ?? '',
77
82
  editable: !props.readOnly,
@@ -229,7 +234,14 @@ export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDro
229
234
  }
230
235
  });
231
236
  watch(() => model.value, (newValue) => {
232
- if (updateRichTextEditor.value && editor.getHTML() !== newValue) {
237
+ // Re-seed the editor when the model has been mutated from outside
238
+ // (history undo/redo, template switch, reorder). `!editor.isFocused`
239
+ // distinguishes "external mutation" from "user is typing in me" — the
240
+ // latter would wipe the user's cursor if we called setContent.
241
+ // `updateRichTextEditor.value` is retained as an explicit override for
242
+ // callers (reorder) that need to force a re-seed while focused.
243
+ const isExternalMutation = updateRichTextEditor.value || !editor.isFocused;
244
+ if (isExternalMutation && editor.getHTML() !== newValue) {
233
245
  editor.commands.setContent(newValue, false);
234
246
  updateRichTextEditor.value = false;
235
247
  //text style type is not switching when reordering
@@ -256,6 +268,13 @@ export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDro
256
268
  emit('update:modelValue', sanitizedData.sanitizedHtml);
257
269
  });
258
270
  editor.on('selectionUpdate', () => {
271
+ // Skip while a history snapshot is being applied — `setContent` fires
272
+ // selectionUpdate before the editor has fully rehydrated, which causes
273
+ // toolbar buttons (alignment, letter-spacing) to flash through bogus
274
+ // active states before settling. The editor emits a final selectionUpdate
275
+ // after apply completes, which lands the correct values (BP-5506).
276
+ if (historyStore.isApplyingSnapshot)
277
+ return;
259
278
  const textStyleAttributes = editor.getAttributes('textStyle');
260
279
  const highlightAttributes = editor.getAttributes('highlight');
261
280
  const focusedAlignment = editor.getAttributes(editor.state.selection.$anchor.node().type.name);
@@ -55,6 +55,10 @@ export declare const EVENTS: {
55
55
  WEBSITE_MAKER_DIGITAL_BUSINESS_CARDS_HIDE_POPUP: string;
56
56
  WEBSITE_MAKER_GETTY_VIDEO: string;
57
57
  WEBSITE_MAKER_SHIPPING_TOGGLE: string;
58
+ WEBSITE_MAKER_UNDO: string;
59
+ WEBSITE_MAKER_REDO: string;
60
+ WEBSITE_MAKER_HISTORY_CAPPED: string;
61
+ WEBSITE_MAKER_HISTORY_OVERSIZED: string;
58
62
  };
59
63
  export declare const SELECT_LOCATIONS: {
60
64
  MAKER_PREVIEW: string;
@@ -107,6 +111,22 @@ export declare const PUBLISH_OPTION_MODAL_CONTINUATION_EVENTS: {
107
111
  };
108
112
  declare const useEventTracker: () => {
109
113
  sendShippingToggleEvent: (isEnabled: boolean) => void;
114
+ sendUndoEvent: (props: {
115
+ entries_count: number;
116
+ actor: string | undefined;
117
+ }) => void;
118
+ sendRedoEvent: (props: {
119
+ entries_count: number;
120
+ actor: string | undefined;
121
+ }) => void;
122
+ sendHistoryCappedEvent: (props: {
123
+ entries_count: number;
124
+ size_bytes: number;
125
+ }) => void;
126
+ sendHistoryOversizedEvent: (props: {
127
+ attempted_bytes: number;
128
+ source: string;
129
+ }) => void;
110
130
  sendSaveContactEvent: () => void;
111
131
  sendStartForFreeEvent: () => void;
112
132
  sendFooterLinkClickEvent: (linkType: 'watermark_logo' | 'create_your_website') => void;
@@ -36,6 +36,10 @@ export const EVENTS = {
36
36
  WEBSITE_MAKER_DIGITAL_BUSINESS_CARDS_HIDE_POPUP: 'website_maker_digital_business_cards_hide_popup',
37
37
  WEBSITE_MAKER_GETTY_VIDEO: 'website_maker_getty_video',
38
38
  WEBSITE_MAKER_SHIPPING_TOGGLE: 'website_maker_shipping_toggle',
39
+ WEBSITE_MAKER_UNDO: 'website_maker_undo',
40
+ WEBSITE_MAKER_REDO: 'website_maker_redo',
41
+ WEBSITE_MAKER_HISTORY_CAPPED: 'website_maker_history_capped',
42
+ WEBSITE_MAKER_HISTORY_OVERSIZED: 'website_maker_history_oversized',
39
43
  };
40
44
  export const SELECT_LOCATIONS = {
41
45
  MAKER_PREVIEW: 'maker_preview',
@@ -321,6 +325,19 @@ const useEventTracker = () => {
321
325
  is_enabled: isEnabled,
322
326
  });
323
327
  },
328
+ // Undo / Redo (BP-5506)
329
+ sendUndoEvent: (props) => {
330
+ _publishEvent(EVENTS.WEBSITE_MAKER_UNDO, props);
331
+ },
332
+ sendRedoEvent: (props) => {
333
+ _publishEvent(EVENTS.WEBSITE_MAKER_REDO, props);
334
+ },
335
+ sendHistoryCappedEvent: (props) => {
336
+ _publishEvent(EVENTS.WEBSITE_MAKER_HISTORY_CAPPED, props);
337
+ },
338
+ sendHistoryOversizedEvent: (props) => {
339
+ _publishEvent(EVENTS.WEBSITE_MAKER_HISTORY_OVERSIZED, props);
340
+ },
324
341
  };
325
342
  };
326
343
  export { useEventTracker };
@@ -0,0 +1,16 @@
1
+ import { type ComputedRef } from 'vue';
2
+ /**
3
+ * Returns whether undo/redo is active for the current maker session. Two
4
+ * conditions must hold:
5
+ *
6
+ * 1. `userStore.features.canUseUndoRedo` is true. The flag is populated by
7
+ * the consumer (BrandCrowd.Net / web-renderer) via the
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. The flag itself is global on LaunchDarkly so it can't
13
+ * gate this on its own — `isBrandSite` is the per-session
14
+ * discriminator.
15
+ */
16
+ export declare function useUndoRedoFlag(): ComputedRef<boolean>;