@designcrowd/library.brand-page 5.18.5 → 5.18.6

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 (142) hide show
  1. package/lib/src/{CreatedOnBrandCrowd-de-de-ciKpCAd9.js → CreatedOnBrandCrowd-de-de-DlYq1LAT.js} +1 -1
  2. package/lib/src/{CreatedOnBrandCrowd-en-us-CZbTS1AZ.js → CreatedOnBrandCrowd-en-us-BssRIQqn.js} +1 -1
  3. package/lib/src/{CreatedOnBrandCrowd-es-es-C8MExng5.js → CreatedOnBrandCrowd-es-es-BGF9pptH.js} +1 -1
  4. package/lib/src/{CreatedOnBrandCrowd-fr-fr-CO0L9NK2.js → CreatedOnBrandCrowd-fr-ca-Caupqu2Z.js} +1 -1
  5. package/lib/src/{CreatedOnBrandCrowd-fr-ca-CO0L9NK2.js → CreatedOnBrandCrowd-fr-fr-Caupqu2Z.js} +1 -1
  6. package/lib/src/{CreatedOnBrandCrowd-pt-pt-zVDvBF2H.js → CreatedOnBrandCrowd-pt-br-s9q4uJ4u.js} +1 -1
  7. package/lib/src/{CreatedOnBrandCrowd-pt-br-zVDvBF2H.js → CreatedOnBrandCrowd-pt-pt-s9q4uJ4u.js} +1 -1
  8. package/lib/src/{CreatedOnDcom-de-de-WrUSQdjf.js → CreatedOnDcom-de-de-UnYnZbA7.js} +1 -1
  9. package/lib/src/{CreatedOnDcom-en-us-BqC9YtkL.js → CreatedOnDcom-en-us-rDv6H12L.js} +1 -1
  10. package/lib/src/{CreatedOnDcom-es-es-BzH32Oya.js → CreatedOnDcom-es-es-DKPLaT6o.js} +1 -1
  11. package/lib/src/{CreatedOnDcom-fr-ca-D7TYfCW0.js → CreatedOnDcom-fr-ca-DAv34bG7.js} +1 -1
  12. package/lib/src/{CreatedOnDcom-fr-fr-DVlyfBtb.js → CreatedOnDcom-fr-fr-DsOHnS8q.js} +1 -1
  13. package/lib/src/{CreatedOnDcom-pt-br-CSRB91ey.js → CreatedOnDcom-pt-br-DpjDBCLj.js} +1 -1
  14. package/lib/src/{CreatedOnDcom-pt-pt-9KMj5gpc.js → CreatedOnDcom-pt-pt-rFG0unf1.js} +1 -1
  15. package/lib/src/brand-page-maker/components/action-bar/ActionBar.mixin.d.ts +2 -7
  16. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +2 -7
  17. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.js +0 -8
  18. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMakerTemplateSettings.mixin.d.ts +2 -7
  19. package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.js +0 -1
  20. package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +2 -87
  21. package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.js +0 -5
  22. package/lib/src/brand-page-maker/components/brandpage-settings/ReplaceImageSettingsForBrandPageSettings.mixin.d.ts +2 -7
  23. package/lib/src/brand-page-maker/components/quick-link-bar/QuickLinkBar.mixin.d.ts +0 -3
  24. package/lib/src/brand-page-maker/components/quick-link-bar/QuickLinkBar.mixin.js +0 -11
  25. package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.d.ts +2 -7
  26. package/lib/src/brand-page-maker/components/seo-settings/UrlSettings.mixin.d.ts +2 -7
  27. package/lib/src/brand-page-maker/components/social-share/SocialShare.mixin.d.ts +2 -7
  28. package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.d.ts +2 -7
  29. package/lib/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.js +0 -9
  30. package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.js +1 -20
  31. package/lib/src/brand-page-maker/composables/useEventTracker.d.ts +0 -20
  32. package/lib/src/brand-page-maker/composables/useEventTracker.js +0 -17
  33. package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.d.ts +2 -41
  34. package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.js +5 -307
  35. package/lib/src/brand-page-maker/stores/logo-store/logo-store.d.ts +0 -1
  36. package/lib/src/brand-page-maker/stores/user/user-store.js +0 -1
  37. package/lib/src/bundled-translations-B5Fkt3qd.js +175 -0
  38. package/lib/src/bundled-translations.de-DE-DpdVePM9.js +175 -0
  39. package/lib/src/bundled-translations.es-ES-BsIcrzZF.js +175 -0
  40. package/lib/src/bundled-translations.fr-CA-G1XCp2Qh.js +175 -0
  41. package/lib/src/bundled-translations.fr-FR-BdwLXOnB.js +175 -0
  42. package/lib/src/bundled-translations.pt-BR-Bvn5ePe7.js +175 -0
  43. package/lib/src/bundled-translations.pt-PT-CDtkb2k1.js +175 -0
  44. package/lib/src/bundles/bundled-translations.de-DE.json +1 -3
  45. package/lib/src/bundles/bundled-translations.es-ES.json +1 -3
  46. package/lib/src/bundles/bundled-translations.fr-CA.json +1 -3
  47. package/lib/src/bundles/bundled-translations.fr-FR.json +1 -3
  48. package/lib/src/bundles/bundled-translations.json +1 -3
  49. package/lib/src/bundles/bundled-translations.pt-BR.json +1 -3
  50. package/lib/src/bundles/bundled-translations.pt-PT.json +1 -3
  51. package/lib/src/constants/ui.d.ts +0 -1
  52. package/lib/src/css/library.brand-page-brandCrowd.min.css +15 -20
  53. package/lib/src/css/library.brand-page-brandPage.min.css +16 -20
  54. package/lib/src/css/library.brand-page-designCom.min.css +15 -20
  55. package/lib/src/css/library.brand-page-preview.min.css +15 -20
  56. package/lib/src/index.mjs +1 -1
  57. package/lib/src/{lib-BXbo_N88.js → lib-ngdDRkSL.js} +27318 -27915
  58. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +2 -87
  59. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.js +0 -5
  60. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.stories.js +0 -1
  61. package/lib/src/shared/content-settings/components/content-settings/ReplaceImageSettingsForContent.mixin.d.ts +2 -23
  62. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.d.ts +0 -16
  63. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.d.ts +2 -7
  64. package/lib/src/shared/content-settings/components/draggable-item-list/DraggableItemList.mixin.d.ts +0 -3
  65. package/lib/src/shared/content-settings/components/draggable-item-list/DraggableItemList.mixin.js +2 -19
  66. package/lib/src/shared/content-settings/components/form-fields-field/FormFieldsField.mixin.js +8 -18
  67. package/lib/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.d.ts +0 -64
  68. package/lib/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.js +0 -6
  69. package/lib/src/shared/logo-settings/components/EditLogoSettings.mixin.d.ts +0 -19
  70. package/lib/src/shared/logo-settings/components/EditLogoSettings.mixin.js +0 -11
  71. package/lib/src/shared/logo-settings/components/LogoSettings.mixin.d.ts +2 -10
  72. package/lib/src/shared/logo-settings/store/editable-logo-store.d.ts +1 -5
  73. package/lib/src/shared/logo-settings/store/editable-logo-store.js +0 -31
  74. package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +2 -24
  75. package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +2 -10
  76. package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +2 -23
  77. package/lib/src/shared/side-bar/components/SideBarTabButton.mixin.d.ts +0 -16
  78. package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +2 -23
  79. package/lib/src/shared/template-settings/components/TemplatesSettings.mixin.d.ts +0 -16
  80. package/package.json +1 -1
  81. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.ts +0 -9
  82. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.vue +3 -2
  83. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.ts +0 -1
  84. package/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.ts +0 -5
  85. package/src/brand-page-maker/components/cookie-collection/CookieSettings.vue +17 -18
  86. package/src/brand-page-maker/components/quick-link-bar/QuickLinkBar.mixin.ts +0 -13
  87. package/src/brand-page-maker/components/quick-link-bar/QuickLinkBar.vue +3 -26
  88. package/src/brand-page-maker/components/quick-link-bar/i18n/quick-link-bar.de-DE.json +4 -6
  89. package/src/brand-page-maker/components/quick-link-bar/i18n/quick-link-bar.es-ES.json +4 -6
  90. package/src/brand-page-maker/components/quick-link-bar/i18n/quick-link-bar.fr-CA.json +4 -6
  91. package/src/brand-page-maker/components/quick-link-bar/i18n/quick-link-bar.fr-FR.json +4 -6
  92. package/src/brand-page-maker/components/quick-link-bar/i18n/quick-link-bar.json +1 -3
  93. package/src/brand-page-maker/components/quick-link-bar/i18n/quick-link-bar.pt-BR.json +4 -6
  94. package/src/brand-page-maker/components/quick-link-bar/i18n/quick-link-bar.pt-PT.json +4 -6
  95. package/src/brand-page-maker/components/save-contact/SaveContact.vue +19 -12
  96. package/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.ts +0 -10
  97. package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.ts +1 -24
  98. package/src/brand-page-maker/composables/useEventTracker.ts +0 -29
  99. package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.test.ts +0 -334
  100. package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.ts +4 -371
  101. package/src/brand-page-maker/stores/logo-store/logo-store.ts +0 -5
  102. package/src/brand-page-maker/stores/user/user-store.ts +0 -1
  103. package/src/bundles/bundled-translations.de-DE.json +1 -3
  104. package/src/bundles/bundled-translations.es-ES.json +1 -3
  105. package/src/bundles/bundled-translations.fr-CA.json +1 -3
  106. package/src/bundles/bundled-translations.fr-FR.json +1 -3
  107. package/src/bundles/bundled-translations.json +1 -3
  108. package/src/bundles/bundled-translations.pt-BR.json +1 -3
  109. package/src/bundles/bundled-translations.pt-PT.json +1 -3
  110. package/src/constants/ui.ts +0 -1
  111. package/src/shared/content-settings/components/content-settings/ContentSettings.mixin.ts +0 -5
  112. package/src/shared/content-settings/components/content-settings/ContentSettings.stories.ts +0 -1
  113. package/src/shared/content-settings/components/draggable-item-list/DraggableItemList.mixin.ts +2 -19
  114. package/src/shared/content-settings/components/draggable-item-list/DraggableItemList.vue +1 -1
  115. package/src/shared/content-settings/components/form-fields-field/FormFieldsField.mixin.ts +10 -26
  116. package/src/shared/content-settings/components/logo-selection-field/LogoSelection.vue +48 -63
  117. package/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.vue +0 -4
  118. package/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.ts +0 -7
  119. package/src/shared/content-settings/components/text-field/TextField.vue +0 -1
  120. package/src/shared/content-settings/components/text-image-field/TextImageField.vue +4 -33
  121. package/src/shared/logo-settings/components/EditLogoSettings.mixin.ts +0 -11
  122. package/src/shared/logo-settings/store/editable-logo-store.ts +1 -42
  123. package/lib/src/brand-page-maker/composables/useUndoRedoFlag.d.ts +0 -17
  124. package/lib/src/brand-page-maker/composables/useUndoRedoFlag.js +0 -25
  125. package/lib/src/brand-page-maker/stores/history/history-store.d.ts +0 -83
  126. package/lib/src/brand-page-maker/stores/history/history-store.js +0 -495
  127. package/lib/src/bundled-translations-D1q3rSEz.js +0 -175
  128. package/lib/src/bundled-translations.de-DE-BxqLLwbh.js +0 -175
  129. package/lib/src/bundled-translations.es-ES-uh249NlJ.js +0 -175
  130. package/lib/src/bundled-translations.fr-CA-BEQmv2fX.js +0 -175
  131. package/lib/src/bundled-translations.fr-FR-BnNuCojH.js +0 -175
  132. package/lib/src/bundled-translations.pt-BR-CJUOxVlq.js +0 -175
  133. package/lib/src/bundled-translations.pt-PT-Ds9cMEqK.js +0 -175
  134. package/lib/src/metadata-builder/builders/reorder-pages-builder.d.ts +0 -13
  135. package/lib/src/metadata-builder/builders/reorder-pages-builder.js +0 -49
  136. package/src/brand-page-maker/components/quick-link-bar/RedoButton.vue +0 -66
  137. package/src/brand-page-maker/components/quick-link-bar/UndoButton.vue +0 -66
  138. package/src/brand-page-maker/components/quick-link-bar/undo-redo-buttons.test.ts +0 -116
  139. package/src/brand-page-maker/composables/useUndoRedoFlag.ts +0 -30
  140. package/src/brand-page-maker/stores/history/history-store.test.ts +0 -1120
  141. package/src/brand-page-maker/stores/history/history-store.ts +0 -660
  142. package/src/metadata-builder/builders/reorder-pages-builder.ts +0 -80
@@ -33,7 +33,6 @@ 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';
37
36
  import { useUiStore } from '../ui';
38
37
  import type { LogoSettingsState } from '@shared/logo-settings/store';
39
38
  import {
@@ -61,7 +60,6 @@ import {
61
60
  BRANDPAGE_DEFAULT_SAVE_MESSAGE_DESCRIPTION,
62
61
  MAKER_MOBILE_BREAKPOINT,
63
62
  MESSAGE_VISIBLE_DURATION,
64
- SIDE_BAR_TAB_NAMES,
65
63
  } from '@brand-page-maker/constants';
66
64
  import { useUiSideBarStore } from '@shared/side-bar/store';
67
65
  import { delayInMS } from '../../../utils/ui-util';
@@ -105,7 +103,6 @@ import { useConsent } from '@brand-page/composables/consent.composable';
105
103
  import { commonTr, errorTr } from '@src/composables/useTranslate';
106
104
  import { UPGRADE_CTA_LOCATIONS } from '../../composables/useEventTracker';
107
105
  import { useVideoStore } from '../video';
108
- import { useHistoryStore } from '../history/history-store';
109
106
  import { findValuesByKey } from '../../../helpers/ts.helper';
110
107
  import { useLogoStore } from '../logo-store';
111
108
 
@@ -670,16 +667,6 @@ export const useBrandPageMakerStore = defineStore('brandPageMaker', {
670
667
  description: payload.noDescription ? '' : description,
671
668
  },
672
669
  });
673
-
674
- // Any successful save re-baselines the undo stack so a user can't
675
- // undo back past the persisted state. This covers Save Progress /
676
- // Publish AND settings-only saves (updateBrandPage,
677
- // updateSensitiveContent, admin saveTemplate) — settings-tab
678
- // actions persist the metadata, so allowing undo to roll them
679
- // back would let the local stack drift from what's saved.
680
- // reset() no-ops in non-undo-redo sessions (no baseline = nothing
681
- // to clear).
682
- useHistoryStore().reset();
683
670
  },
684
671
  hideChangeTemplateConfirmModal() {
685
672
  this.setIsChangeTemplateConfirmModalVisible({
@@ -693,11 +680,10 @@ export const useBrandPageMakerStore = defineStore('brandPageMaker', {
693
680
  this.setSelectedTemplateId({ templateId: false });
694
681
  this.hideChangeTemplateConfirmModal();
695
682
  },
696
- async onChangeTemplateConfirmModalConfirm() {
697
- await this.applySelectedTemplate();
683
+ onChangeTemplateConfirmModalConfirm() {
684
+ this.applySelectedTemplate();
698
685
  this.hideChangeTemplateConfirmModal();
699
686
  this.isModifiedAfterTemplateApplied = false;
700
- this._captureTemplateSwitchIfEnabled();
701
687
  },
702
688
  onContentChanged() {
703
689
  this.setIsModifiedAfterTemplateApplied();
@@ -705,7 +691,7 @@ export const useBrandPageMakerStore = defineStore('brandPageMaker', {
705
691
  onStyleChanged(): void {
706
692
  this.setIsModifiedAfterTemplateApplied();
707
693
  },
708
- async onTemplateSelected(payload: OnTemplateSelectedPayload) {
694
+ onTemplateSelected(payload: OnTemplateSelectedPayload) {
709
695
  this.setSelectedTemplateId({
710
696
  templateId: payload.templateId,
711
697
  });
@@ -715,8 +701,7 @@ export const useBrandPageMakerStore = defineStore('brandPageMaker', {
715
701
  isVisible: true,
716
702
  });
717
703
  } else {
718
- await this.applySelectedTemplate();
719
- this._captureTemplateSwitchIfEnabled();
704
+ this.applySelectedTemplate();
720
705
  }
721
706
  },
722
707
  setSelectedTabName(payload) {
@@ -753,358 +738,6 @@ export const useBrandPageMakerStore = defineStore('brandPageMaker', {
753
738
  const uiContentSettingsStore = useUiContentSettingsStore();
754
739
 
755
740
  uiContentSettingsStore.updateContent<TContent>(payload);
756
-
757
- // NOTE (Bolt 1, 2026-04-23): this action is not the actual edit path used
758
- // by the UI — sidebar inputs call uiContentSettingsStore.updateItemValue
759
- // directly. History capture is driven by a deep `watch(brandPageData, ...)`
760
- // installed in history-store once the baseline is captured, so we do not
761
- // need to instrument this action. Kept here as a pass-through because
762
- // removing it may affect other callers.
763
- },
764
- /**
765
- * Restore every store that the `brandPageData` getter reads from, so undo
766
- * and redo bring back the EXACT document state captured at snapshot time.
767
- *
768
- * `initialiseStoresByBrandPageModelAsync` is too narrow for undo/redo — it
769
- * only rehydrates pages, sections, and nav structure, which is enough for
770
- * the AI-apply path but leaves navigation styles, backgrounds, button/text/
771
- * logo/gallery styles, shop config, and several own-store fields unchanged.
772
- * This action mirrors the full hydration surface of `applySelectedTemplate`
773
- * (minus the template-specific logo/personalisation logic) so a restore is
774
- * a complete round-trip of what `brandPageData` returns.
775
- *
776
- * Called ONLY by history-store during undo/redo. The history store sets
777
- * `isApplyingSnapshot=true` across this call to prevent the deep-watcher
778
- * on `brandPageData` from re-capturing the restored state.
779
- */
780
- /**
781
- * Force-commit a `template_switch` entry to the history store, if the
782
- * history store has a baseline (which only happens when the undo/redo
783
- * feature flag is on — see `BrandPageMaker.mixin.ts`).
784
- */
785
- _captureTemplateSwitchIfEnabled(): void {
786
- const historyStore = useHistoryStore();
787
-
788
- if (!historyStore.baselineCaptured) return;
789
-
790
- historyStore.captureTemplateSwitch();
791
- },
792
- async applyHistorySnapshot(
793
- snapshot: BrandPageModel,
794
- activePageId?: string,
795
- logoEditsStr?: string,
796
- ): Promise<void> {
797
- const styleSettingsStore = useUiStyleSettingsStore();
798
- const navigationStyleSettingsStore = useUiNavigationStyleSettingsStore();
799
- const backgroundSettingsStore = useUiBackgroundSettingsStore();
800
- const pageNavigationStore = usePageNavigationStore();
801
- const shopStore = useShopConfigStore();
802
-
803
- // 1. Pages + header/footer sections (also covers content items).
804
- this.initialisePagesForCurrentPage({
805
- pages: snapshot.pages,
806
- sections: {
807
- [PAGE_SECTIONS.header]: {
808
- [VIEWPORTS.desktop]: snapshot.pageHeaderDesktop,
809
- [VIEWPORTS.mobile]: snapshot.pageHeaderMobile,
810
- },
811
- [PAGE_SECTIONS.footer]: {
812
- [VIEWPORTS.desktop]: snapshot.pageFooterDesktop,
813
- [VIEWPORTS.mobile]: snapshot.pageFooterMobile,
814
- },
815
- },
816
- });
817
-
818
- // 2. Page-level nav structure (routes, orders).
819
- pageNavigationStore.setNav({ nav: snapshot.nav });
820
-
821
- // 3. Navigation STYLES (header/footer nav colors, alignment, etc.) —
822
- // this is the bit that was being dropped before.
823
- // Use function-form $patch so each nested style object is replaced as a
824
- // whole reference. The object-form $patch (used by setState) deep-merges
825
- // and would leave keys present in the live state but absent from the
826
- // snapshot in place — e.g. switching button styles then undoing would
827
- // leave the new style's borderRadius/borderStyle/borderWidth applied.
828
- navigationStyleSettingsStore.$patch((state) => {
829
- state.navigation[PAGE_SECTIONS.header][VIEWPORTS.desktop] =
830
- new NavigationDesktop(snapshot.pageHeaderDesktop?.navigation);
831
- state.navigation[PAGE_SECTIONS.header][VIEWPORTS.mobile] =
832
- new NavigationMobile(snapshot.pageHeaderMobile?.navigation);
833
- });
834
-
835
- // 4. Global styles (logo, button, text, gallery). Same whole-reference
836
- // replacement reasoning as step 3.
837
- styleSettingsStore.$patch((state) => {
838
- state.buttonStyles = snapshot.styles.buttonStyles;
839
- state.logoStyles = snapshot.styles.logoStyles;
840
- state.textStyles = snapshot.styles.textStyles;
841
- state.galleryStyles = snapshot.styles.galleryStyles;
842
- });
843
-
844
- // 5. Background styles. Same whole-reference replacement reasoning as
845
- // step 3 — `setBackgroundStyles` calls per-field setters that
846
- // `Object.assign` partials onto the live `style` and
847
- // `backgroundShapeStyle` objects, so keys from the previous mode
848
- // (e.g. background image url, shape style props) would survive an
849
- // undo back to a state that doesn't have them.
850
- backgroundSettingsStore.$patch((state) => {
851
- state.backgroundStyles = snapshot.styles.backgroundStyles;
852
- });
853
- backgroundSettingsStore.onBackgroundChanged();
854
-
855
- // 6. Shop products are derived from shop-content blocks inside `pages`,
856
- // so they're already implicitly restored at step 1. Re-run the shop
857
- // store's derivation to keep `products` in sync with the snapshot
858
- // pages. paymentConfig is intentionally NOT restored — selecting it is
859
- // backend-confirmed (Stripe Connect / payment-provider linkage) per
860
- // project-guardrails.md, so it must persist across undo. We pass the
861
- // live paymentConfig back in to preserve it.
862
- shopStore.initialiseShopStore({
863
- paymentConfig: shopStore.paymentConfig,
864
- pages: snapshot.pages ?? [],
865
- });
866
-
867
- // 7. Own-store scalar fields surfaced by the brandPageData getter.
868
- if (snapshot.isModifiedAfterTemplateApplied !== undefined) {
869
- this.isModifiedAfterTemplateApplied =
870
- snapshot.isModifiedAfterTemplateApplied;
871
- }
872
-
873
- if (snapshot.brandPageType) {
874
- this.setBrandPageType({ brandPageType: snapshot.brandPageType });
875
- }
876
-
877
- this.faviconUrl = snapshot.faviconUrl;
878
- this.ogImageUrl = snapshot.ogImageUrl;
879
- this.measurementID = snapshot.measurementID;
880
- this.adsenseID = snapshot.adsenseID;
881
- this.ogTitle = snapshot.ogTitle;
882
- this.ogDescription = snapshot.ogDescription;
883
- this.cookieOptions = snapshot.cookieOptions;
884
- this.saveContactSettings = snapshot.saveContactSettings;
885
-
886
- // 8. Re-sync the logo-settings sidebar's `selectedLogoImage` from the
887
- // restored header logo. The preview rehydrates via the page contents,
888
- // but `uiLogoSettings` holds its own copy that drives the sidebar
889
- // "current logo" state — same pattern as `initialiseStoresByBrandPageModelAsync`.
890
- // Also restores the variations grid + template asset for the
891
- // snapshot's draft token (both are sidecars to `brandPageData` —
892
- // BYO upload mutates them out of band). When the captured entry
893
- // carries a `logoEdits` sidecar (pre-purchase logo-tab edits —
894
- // text, support text, logo colors, fonts), `editableLogoStore.logoEdits`
895
- // is restored from that string so the sidebar form fields and the
896
- // save-time fabric-render POST both pick up the pre-edit state.
897
- await this._syncLogoSettingsFromSnapshot(snapshot, logoEditsStr);
898
-
899
- // 9. If the sidebar is editing a content item that no longer exists in
900
- // the restored page, fall back to the Content tab so the user doesn't
901
- // stare at a blank settings panel.
902
- this._fallbackSidebarIfSelectedContentMissing(snapshot);
903
-
904
- // 10. Switch to the page the user was viewing when this entry was
905
- // captured (or the closest still-existing page if the captured
906
- // page was the one being undone-away). The history store does the
907
- // walk-back resolution and passes us a pageId that's guaranteed to
908
- // exist in the restored nav — or undefined if no entry walking
909
- // back has a viable id, in which case we fall through to the
910
- // first/default route. Without this, the page-tabs carousel keeps
911
- // highlighting whatever page slug is in the URL (which can no
912
- // longer match any nav item after a page-add undo) and the
913
- // sidebar's `currentPage` getter silently falls back to page 0.
914
- this._navigateToActivePage(activePageId);
915
- },
916
-
917
- async _syncLogoSettingsFromSnapshot(
918
- snapshot: BrandPageModel,
919
- logoEditsStr?: string,
920
- ): Promise<void> {
921
- const logoSettingsStore = useUiLogoSettingsStore();
922
- const editableLogoStore = useUiEditableLogoStore();
923
- const logoStore = useLogoStore();
924
- const containerStore = useBrandPageContainerStore();
925
-
926
- // Pre-restore logo identity, used to short-circuit the
927
- // fabric-render call when only non-logo state changed.
928
- const prevLogoEditsStr = JSON.stringify(
929
- toRaw(editableLogoStore.logoEdits),
930
- );
931
- const prevDraftToken = editableLogoStore.logoDraftToken;
932
-
933
- // Wholesale-replace via $patch so prior textObjects/colors don't
934
- // leak across template switches.
935
- if (logoEditsStr) {
936
- try {
937
- const parsed = JSON.parse(logoEditsStr);
938
-
939
- editableLogoStore.$patch({ logoEdits: parsed });
940
- } catch (error) {
941
- console.error(
942
- 'brandpage-maker-store: failed to restore logoEdits',
943
- error,
944
- );
945
- }
946
- }
947
-
948
- const logoImage =
949
- snapshot.brandPageType === BRAND_PAGE_TYPES.default
950
- ? (
951
- snapshot.pages?.[0]?.contents?.find(
952
- (c) => c.type === 'logo',
953
- ) as any
954
- )?.logoImage
955
- : snapshot.pageHeaderDesktop?.logoImage;
956
-
957
- if (!logoImage) return;
958
-
959
- logoSettingsStore.setState({
960
- newState: { selectedLogoImage: logoImage },
961
- });
962
-
963
- const draftToken: string | undefined = logoImage.logoDraftToken;
964
-
965
- if (!draftToken) return;
966
-
967
- // Re-derive enableEditMode + templateAsset from the draft registry
968
- // (append-only for the session) instead of stashing on every entry.
969
- const draft = logoStore.getLogoDraftAssetByToken(draftToken);
970
-
971
- if (draft) {
972
- editableLogoStore.setEnableEditMode(!draft.isByo);
973
-
974
- if (draft.templateAsset) {
975
- logoStore.setLogoTemplateAsset(draft.templateAsset);
976
- }
977
- }
978
-
979
- editableLogoStore.setLogoDraftToken(draftToken);
980
-
981
- // No logo change → cache is still correct; just stamp base64 back
982
- // (snapshot doesn't carry logoImageBase64Url).
983
- const logoUnchanged =
984
- prevDraftToken === draftToken &&
985
- (logoEditsStr === undefined || logoEditsStr === prevLogoEditsStr);
986
-
987
- if (logoUnchanged) {
988
- editableLogoStore.stampLogoBase64IntoBrandPageData();
989
-
990
- return;
991
- }
992
-
993
- const isByo = !!draft?.isByo;
994
-
995
- if (isByo) {
996
- // BYO mints a fresh draftToken per upload so the per-token
997
- // cache always matches; no re-render needed.
998
- if (editableLogoStore.restoreVariationsForDraftToken(draftToken)) {
999
- editableLogoStore.stampLogoBase64IntoBrandPageData();
1000
- }
1001
-
1002
- return;
1003
- }
1004
-
1005
- // Designed: draft token is reused across edits, so the cache
1006
- // only holds the latest render. Re-issue fabric-render — same
1007
- // call as the live edit path. Awaited so concurrent undos
1008
- // serialize and the call sits inside the isApplyingSnapshot
1009
- // window (watcher guard suppresses the writeback).
1010
- if (
1011
- containerStore.isPrePurchase &&
1012
- logoEditsStr &&
1013
- logoStore.logoTemplateAsset
1014
- ) {
1015
- // Stamp the cached (pre-undo) base64 onto brandPageData first
1016
- // so the canvas keeps showing the previous logo while the
1017
- // re-render is in flight. Without this the logoImageBase64Url
1018
- // fields are undefined (snapshot is stripped pre-purchase) and
1019
- // the canvas flickers blank for ~500-1500ms.
1020
- editableLogoStore.stampLogoBase64IntoBrandPageData();
1021
-
1022
- try {
1023
- await editableLogoStore.updateEditableLogoImageUrlAsync();
1024
- } catch (error) {
1025
- console.error(
1026
- 'brandpage-maker-store: failed to re-render logo on history apply',
1027
- error,
1028
- );
1029
- }
1030
- }
1031
- },
1032
-
1033
- /**
1034
- * Restore the active page after a history apply. The id passed in is
1035
- * already validated against the restored nav by the history store; if
1036
- * it's undefined (no entry walking back had a viable page), fall back
1037
- * to the first/default route so the URL, `routeStore.currentRoute.params`,
1038
- * `pageNavigation.activePageId`, and the page-tab highlight all line up.
1039
- *
1040
- * `setCurrentActivePage` is called explicitly in addition to
1041
- * `navigateToPageByPageId` because `navigateToPageByPageId` is a no-op
1042
- * when the router instance is undefined (e.g. SSR / unit tests), but the
1043
- * Pinia state must still be updated so the sidebar's `currentPage`
1044
- * getter returns the right page.
1045
- */
1046
- _navigateToActivePage(activePageId?: string): void {
1047
- const pageNavigationStore = usePageNavigationStore();
1048
-
1049
- let targetPageId = activePageId;
1050
-
1051
- if (!targetPageId) {
1052
- const fallbackRoute = pageNavigationStore.routes.length
1053
- ? pageNavigationStore.getFirstOrDefaultRoute()
1054
- : undefined;
1055
-
1056
- targetPageId = fallbackRoute?.pageId;
1057
- }
1058
-
1059
- if (!targetPageId) return;
1060
-
1061
- // Skip both the Pinia write and the router push when the target page
1062
- // is already active. The router push fires `router.afterEach` even
1063
- // for same-page navigation, and BrandPageMaker.mixin's afterEach hook
1064
- // resets the content-settings modeStack — which would snap the
1065
- // sidebar back to the default Content tab on every undo/redo,
1066
- // regardless of whether the user was deep-editing a content item.
1067
- if (pageNavigationStore.activePageId === targetPageId) return;
1068
-
1069
- pageNavigationStore.setCurrentActivePage({ pageId: targetPageId });
1070
- navigateToPageByPageId(targetPageId);
1071
- },
1072
-
1073
- _fallbackSidebarIfSelectedContentMissing(snapshot: BrandPageModel): void {
1074
- const contentSettingsStore = useUiContentSettingsStore();
1075
- const sideBarStore = useUiSideBarStore();
1076
-
1077
- const selectedItemId = contentSettingsStore.selectedItemId;
1078
-
1079
- if (!selectedItemId) return;
1080
-
1081
- const existingContentIds = new Set<string>();
1082
-
1083
- snapshot.pages?.forEach((page) => {
1084
- page.contents?.forEach((content) => {
1085
- if (content?.id) existingContentIds.add(content.id);
1086
- });
1087
- });
1088
-
1089
- if (existingContentIds.has(selectedItemId)) return;
1090
-
1091
- // The previously-selected content was undone away. Restore the
1092
- // Content tab's natural landing state — the same shape produced
1093
- // when the user clicks the Content tab fresh — instead of leaving
1094
- // the sidebar stuck rendering `<FocusedContentItemSettings>` for
1095
- // a missing item, which paints a blank panel.
1096
- //
1097
- // `resetMode()` pops the modeStack back to the base `edit` entry
1098
- // (the default landing mode); clearing `selectedItemId` releases
1099
- // the pointer to the now-deleted item.
1100
- sideBarStore.setSelectedTabName({
1101
- tabName: SIDE_BAR_TAB_NAMES.CONTENT_SETTINGS,
1102
- });
1103
- contentSettingsStore.resetMode();
1104
- contentSettingsStore.selectedItemId = null;
1105
- contentSettingsStore.selectedItemFieldName = null;
1106
- contentSettingsStore.selectedItemIndex = null;
1107
- contentSettingsStore.selectedItemValue = null;
1108
741
  },
1109
742
  export(): BrandPageModel {
1110
743
  const data = this.brandPageData;
@@ -14,11 +14,6 @@ export interface LogoDraftAsset {
14
14
  tick: number;
15
15
  isByo: boolean;
16
16
  logoEditUrl?: string;
17
- // The `logoTemplateAsset` active when this draft was created. Stamped at
18
- // upload/setState time so undo/redo can restore the right template token
19
- // + isByo flag from a snapshot's `logoDraftToken` alone — without us
20
- // bloating each history entry with a copy of the asset.
21
- templateAsset?: LogoTemplateAsset;
22
17
  }
23
18
 
24
19
  export interface LogoStoreState {
@@ -33,7 +33,6 @@ export const useBrandPageMakerUserStore = defineStore('brandPageMakerUser', {
33
33
  canUseGettyVideos: false,
34
34
  canUseGoogleAdsense: false,
35
35
  googleAdsenseEnabled: false,
36
- canUseUndoRedo: false,
37
36
  },
38
37
  emailAddress: '',
39
38
  hasPremiumSubscription: false,
@@ -1126,9 +1126,7 @@
1126
1126
  "quickLinkBar": {
1127
1127
  "myWebPageLabel": "Meine Webseite:",
1128
1128
  "copyButton": "Kopieren",
1129
- "copiedButton": "Kopiert!",
1130
- "undoLabel": "Rückgängig machen",
1131
- "redoLabel": "Wiederholen"
1129
+ "copiedButton": "Kopiert!"
1132
1130
  },
1133
1131
  "saveContactSettings": {
1134
1132
  "saveContentInfo": "Lassen Sie Besucher Ihre Kontaktinformationen speichern, wenn sie Ihre digitale Visitenkarte ansehen.",
@@ -1126,9 +1126,7 @@
1126
1126
  "quickLinkBar": {
1127
1127
  "myWebPageLabel": "Mi página web:",
1128
1128
  "copyButton": "Copiar",
1129
- "copiedButton": "¡Copiado!",
1130
- "undoLabel": "Deshacer",
1131
- "redoLabel": "Rehacer"
1129
+ "copiedButton": "¡Copiado!"
1132
1130
  },
1133
1131
  "saveContactSettings": {
1134
1132
  "saveContentInfo": "Permite que los visitantes guarden tu información de contacto al ver tu tarjeta de visita digital.",
@@ -1126,9 +1126,7 @@
1126
1126
  "quickLinkBar": {
1127
1127
  "myWebPageLabel": "Ma page Web :",
1128
1128
  "copyButton": "Copier",
1129
- "copiedButton": "Copié !",
1130
- "undoLabel": "Annuler",
1131
- "redoLabel": "Rétablir"
1129
+ "copiedButton": "Copié !"
1132
1130
  },
1133
1131
  "saveContactSettings": {
1134
1132
  "saveContentInfo": "Permettez aux visiteurs d'enregistrer vos coordonnées lorsqu'ils consultent votre carte professionnelle numérique",
@@ -1126,9 +1126,7 @@
1126
1126
  "quickLinkBar": {
1127
1127
  "myWebPageLabel": "Ma page Web :",
1128
1128
  "copyButton": "Copier",
1129
- "copiedButton": "Copié !",
1130
- "undoLabel": "Annuler",
1131
- "redoLabel": "Rétablir"
1129
+ "copiedButton": "Copié !"
1132
1130
  },
1133
1131
  "saveContactSettings": {
1134
1132
  "saveContentInfo": "Permettez aux visiteurs d'enregistrer vos coordonnées lorsqu'ils consultent votre carte de visite numérique",
@@ -1126,9 +1126,7 @@
1126
1126
  "quickLinkBar": {
1127
1127
  "myWebPageLabel": "My web page:",
1128
1128
  "copyButton": "Copy",
1129
- "copiedButton": "Copied!",
1130
- "undoLabel": "Undo",
1131
- "redoLabel": "Redo"
1129
+ "copiedButton": "Copied!"
1132
1130
  },
1133
1131
  "saveContactSettings": {
1134
1132
  "saveContentInfo": "Let visitors save your contact information when they view your Digital Business Card",
@@ -1126,9 +1126,7 @@
1126
1126
  "quickLinkBar": {
1127
1127
  "myWebPageLabel": "Minha página web:",
1128
1128
  "copyButton": "Copiar",
1129
- "copiedButton": "Copiado!",
1130
- "undoLabel": "Desfazer",
1131
- "redoLabel": "Refazer"
1129
+ "copiedButton": "Copiado!"
1132
1130
  },
1133
1131
  "saveContactSettings": {
1134
1132
  "saveContentInfo": "Permita que os visitantes salvem suas informações de contato quando visualizarem seu cartão de visita digital",
@@ -1126,9 +1126,7 @@
1126
1126
  "quickLinkBar": {
1127
1127
  "myWebPageLabel": "A minha página Web:",
1128
1128
  "copyButton": "Copiar",
1129
- "copiedButton": "Copiado!",
1130
- "undoLabel": "Desfazer",
1131
- "redoLabel": "Refazer"
1129
+ "copiedButton": "Copiado!"
1132
1130
  },
1133
1131
  "saveContactSettings": {
1134
1132
  "saveContentInfo": "Permita que os visitantes guardem a sua informação de contacto quando visualizarem o seu cartão de visita digital",
@@ -14,7 +14,6 @@ export interface UIUserFeatures {
14
14
  canUseGettyVideos: boolean;
15
15
  canUseGoogleAdsense: boolean;
16
16
  googleAdsenseEnabled: boolean;
17
- canUseUndoRedo: boolean;
18
17
  }
19
18
 
20
19
  export const TEMPLATE_FIRST_PAGE_NO = 1;
@@ -29,7 +29,6 @@ import {
29
29
  } from '@brand-page-maker/utils';
30
30
  import { useUiStyleSettingsStore } from '../../../style-settings/store';
31
31
  import { usePageNavigationStore } from '../../../../shared/page-navigation/store/page-navigation-store';
32
- import { useHistoryStore } from '@brand-page-maker/stores/history/history-store';
33
32
 
34
33
  interface CategoryTab {
35
34
  category: string;
@@ -45,7 +44,6 @@ export default defineComponent({
45
44
  const styleSettingsStore = useUiStyleSettingsStore();
46
45
  const userStore = useBrandPageMakerUserStore();
47
46
  const eventTracker = useEventTracker();
48
- const historyStore = useHistoryStore();
49
47
  const { externalEditor } = useExternalRichTextEditor();
50
48
 
51
49
  return {
@@ -67,7 +65,6 @@ export default defineComponent({
67
65
  pageSettingsStore,
68
66
  styleSettingsStore,
69
67
  eventTracker,
70
- historyStore,
71
68
  externalEditor,
72
69
  };
73
70
  },
@@ -84,8 +81,6 @@ export default defineComponent({
84
81
  },
85
82
  mounted() {
86
83
  if (this.canUseRichTextEditor) {
87
- // RTE rewrap on tab mount — fold into current head.
88
- this.historyStore.mergeNextMutation();
89
84
  switchAllContentToRTE(
90
85
  this.pageSettingsStore,
91
86
  this.externalEditor,
@@ -32,7 +32,6 @@ export const Sample = (): any => {
32
32
  canUseGettyVideos: true,
33
33
  canUseGoogleAdsense: false,
34
34
  googleAdsenseEnabled: false,
35
- canUseUndoRedo: false,
36
35
  };
37
36
 
38
37
  const pinia = setupStoryPinia();
@@ -76,12 +76,6 @@ export default defineComponent({
76
76
  schema: 'https',
77
77
  textIcon: 'globe',
78
78
  textIcons: [] as string[],
79
- // Display-only override for the focused URL input. While a row is
80
- // focused we strip the schema visually but MUST NOT mutate modelValue —
81
- // doing so would land in the store and trigger a spurious undo/redo
82
- // history entry between focus and blur (BP-5506).
83
- focusedIndex: null as number | null,
84
- focusedDisplay: '',
85
79
  }),
86
80
  computed: {
87
81
  items: {
@@ -168,26 +162,15 @@ export default defineComponent({
168
162
  },
169
163
 
170
164
  onFocusOverride(index: number, itemValue: string): void {
165
+ const value = [...this.modelValue];
171
166
  const match = URL_RE.exec(itemValue);
172
167
 
173
168
  if (match) {
174
169
  this.schema = match[1];
175
- this.focusedIndex = index;
176
- this.focusedDisplay = match[2];
177
- } else {
178
- this.focusedIndex = index;
179
- this.focusedDisplay = itemValue;
170
+ value[index][this.valuePropName] = match[2];
180
171
  }
181
172
  },
182
- inputDisplayValue(index: number): string {
183
- return this.focusedIndex === index
184
- ? this.focusedDisplay
185
- : this.itemValue(index);
186
- },
187
173
  onBlurOverride(index: number, itemValue: string): void {
188
- this.focusedIndex = null;
189
- this.focusedDisplay = '';
190
-
191
174
  const value = [...this.modelValue];
192
175
 
193
176
  let isValid = true;
@@ -70,7 +70,7 @@
70
70
  hasError[index],
71
71
  }"
72
72
  :placeholder="placeholderPrefix"
73
- :value="inputDisplayValue(index)"
73
+ :value="itemValue(index)"
74
74
  :data-test-tag="'image-url-text-input'"
75
75
  @focus="onFocusOverride(index, $event.target.value)"
76
76
  @blur="onBlurOverride(index, $event.target.value)"