@designcrowd/library.brand-page 6.2.0 → 6.2.2-live-preview-1

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 (186) hide show
  1. package/lib/src/{CreatedOnBrandCrowd-de-de-VQCQvlMg.js → CreatedOnBrandCrowd-de-de-Cn0M-eZ1.js} +1 -1
  2. package/lib/src/{CreatedOnBrandCrowd-en-us-DSf3BjCG.js → CreatedOnBrandCrowd-en-us-DRLMSDZr.js} +1 -1
  3. package/lib/src/{CreatedOnBrandCrowd-es-es-DGcdM9Ec.js → CreatedOnBrandCrowd-es-es-BglTu73U.js} +1 -1
  4. package/lib/src/{CreatedOnBrandCrowd-fr-fr-C9g1fc39.js → CreatedOnBrandCrowd-fr-ca-Bj6YZ_el.js} +1 -1
  5. package/lib/src/{CreatedOnBrandCrowd-fr-ca-C9g1fc39.js → CreatedOnBrandCrowd-fr-fr-Bj6YZ_el.js} +1 -1
  6. package/lib/src/{CreatedOnBrandCrowd-pt-pt-DSXr7Bxl.js → CreatedOnBrandCrowd-pt-br-DEoOmQ1F.js} +1 -1
  7. package/lib/src/{CreatedOnBrandCrowd-pt-br-DSXr7Bxl.js → CreatedOnBrandCrowd-pt-pt-DEoOmQ1F.js} +1 -1
  8. package/lib/src/{CreatedOnDcom-de-de-BPdCL6wS.js → CreatedOnDcom-de-de-BZ7gTt4Z.js} +1 -1
  9. package/lib/src/{CreatedOnDcom-en-us-CLkSTQRu.js → CreatedOnDcom-en-us-CD6Km5sH.js} +1 -1
  10. package/lib/src/{CreatedOnDcom-es-es-CRknMAGv.js → CreatedOnDcom-es-es-CNpZHvEl.js} +1 -1
  11. package/lib/src/{CreatedOnDcom-fr-ca-ClAY_dHI.js → CreatedOnDcom-fr-ca-URS-ydJ1.js} +1 -1
  12. package/lib/src/{CreatedOnDcom-fr-fr-DQtv9rR-.js → CreatedOnDcom-fr-fr-D2AVeA3H.js} +1 -1
  13. package/lib/src/{CreatedOnDcom-pt-br-BbIxvmxv.js → CreatedOnDcom-pt-br-C32frnFs.js} +1 -1
  14. package/lib/src/{CreatedOnDcom-pt-pt-BOfOesBj.js → CreatedOnDcom-pt-pt-TDYGjRXS.js} +1 -1
  15. package/lib/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.mixin.d.ts +16 -2
  16. package/lib/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.mixin.js +17 -0
  17. package/lib/src/brand-page/components/page/Page.mixin.d.ts +2 -1
  18. package/lib/src/brand-page/components/page/Page.mixin.js +12 -7
  19. package/lib/src/brand-page/components/page-header/HeaderLayout.stories.d.ts +1 -0
  20. package/lib/src/brand-page/components/page-header/HeaderLayout.stories.js +9 -0
  21. package/lib/src/brand-page/components/page-header/PageHeader.mixin.d.ts +3 -1
  22. package/lib/src/brand-page/components/page-header/PageHeader.mixin.js +10 -4
  23. package/lib/src/brand-page/constants/sections/header-display.constants.d.ts +3 -0
  24. package/lib/src/brand-page/constants/sections/header-display.constants.js +15 -0
  25. package/lib/src/brand-page/models/brand-page-context.model.d.ts +0 -2
  26. package/lib/src/brand-page/models/brand-page-context.model.js +0 -12
  27. package/lib/src/brand-page/models/index.d.ts +12 -0
  28. package/lib/src/brand-page/models/index.js +4 -0
  29. package/lib/src/brand-page/utils/context.util.d.ts +1 -0
  30. package/lib/src/brand-page/utils/context.util.js +9 -0
  31. package/lib/src/brand-page/utils/route.util.d.ts +1 -0
  32. package/lib/src/brand-page/utils/route.util.js +9 -0
  33. package/lib/src/brand-page/utils/view-model.util.js +53 -1
  34. package/lib/src/brand-page/view-models.d.ts +3 -1
  35. package/lib/src/brand-page-maker/components/action-bar/ActionBar.mixin.d.ts +0 -1
  36. package/lib/src/brand-page-maker/components/action-bar/ActionBar.mixin.js +0 -9
  37. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +9 -44
  38. package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +8 -43
  39. package/lib/src/brand-page-maker/components/preview/Preview.mixin.d.ts +0 -14
  40. package/lib/src/brand-page-maker/components/quick-link-bar/QuickLinkBar.mixin.d.ts +0 -42
  41. package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.d.ts +0 -42
  42. package/lib/src/brand-page-maker/components/seo-settings/UrlSettings.mixin.d.ts +0 -42
  43. package/lib/src/brand-page-maker/components/seo-settings/UseExistingDomainModal.mixin.d.ts +0 -42
  44. package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.d.ts +0 -42
  45. package/lib/src/brand-page-maker/components/upgrade-to-premium-button/UpgradeToPremiumButton.mixin.d.ts +0 -42
  46. package/lib/src/brand-page-maker/composables/useEventTracker.d.ts +3 -0
  47. package/lib/src/brand-page-maker/composables/useEventTracker.js +10 -0
  48. package/lib/src/brand-page-maker/stores/ai-checkpoint/ai-checkpoint-store.d.ts +1626 -0
  49. package/lib/src/brand-page-maker/stores/brandpage-container/brand-page-container-store.d.ts +0 -42
  50. package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.js +2 -4
  51. package/lib/src/brand-page-maker/validators/section-button.validator.d.ts +5 -2
  52. package/lib/src/brand-page-maker/validators/section-button.validator.js +11 -15
  53. package/lib/src/{bundled-translations-B2q5GWTQ.js → bundled-translations-BYUfWBT3.js} +17 -17
  54. package/lib/src/{bundled-translations.de-DE-FhH2H_rd.js → bundled-translations.de-DE-MmzUu1tt.js} +21 -21
  55. package/lib/src/{bundled-translations.es-ES-_ZExxMi7.js → bundled-translations.es-ES-D-tG33XL.js} +5 -5
  56. package/lib/src/{bundled-translations.fr-CA-Tg-ODIiC.js → bundled-translations.fr-CA-CNc1H1h3.js} +1 -1
  57. package/lib/src/{bundled-translations.fr-FR-C0sU51Mz.js → bundled-translations.fr-FR-DX0-yepT.js} +9 -9
  58. package/lib/src/{bundled-translations.pt-BR-MYFIhA4u.js → bundled-translations.pt-BR-ih1-LRgy.js} +9 -9
  59. package/lib/src/{bundled-translations.pt-PT-DeUBSzCB.js → bundled-translations.pt-PT-Dq2CmD1p.js} +22 -22
  60. package/lib/src/bundles/bundled-translations.de-DE.json +9 -2
  61. package/lib/src/bundles/bundled-translations.es-ES.json +9 -2
  62. package/lib/src/bundles/bundled-translations.fr-CA.json +9 -2
  63. package/lib/src/bundles/bundled-translations.fr-FR.json +9 -2
  64. package/lib/src/bundles/bundled-translations.json +9 -2
  65. package/lib/src/bundles/bundled-translations.pt-BR.json +9 -2
  66. package/lib/src/bundles/bundled-translations.pt-PT.json +9 -2
  67. package/lib/src/composables/useTranslate.d.ts +1 -1
  68. package/lib/src/composables/useTranslate.js +1 -1
  69. package/lib/src/css/library.brand-page-brandCrowd.min.css +577 -139
  70. package/lib/src/css/library.brand-page-brandPage.min.css +577 -139
  71. package/lib/src/css/library.brand-page-designCom.min.css +577 -139
  72. package/lib/src/css/library.brand-page-preview.min.css +577 -139
  73. package/lib/src/index.mjs +2 -2
  74. package/lib/src/{lib-BMVF4uNy.js → lib-Dm9AuOJL.js} +22487 -21900
  75. package/lib/src/metadata-builder/builders/item-id-utils.d.ts +2 -0
  76. package/lib/src/metadata-builder/builders/item-id-utils.js +8 -2
  77. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +10 -2
  78. package/lib/src/shared/content-settings/components/content-settings/ReplaceImageSettingsForContent.mixin.d.ts +7 -1
  79. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.d.ts +1 -0
  80. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.d.ts +6 -1
  81. package/lib/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.d.ts +6 -43
  82. package/lib/src/shared/content-settings/components/text-field/TextField.mixin.d.ts +14 -2
  83. package/lib/src/shared/content-settings/components/text-field/TextField.mixin.js +14 -0
  84. package/lib/src/shared/ecommerce-settings/util/refreshDuplicatedMetadata.d.ts +9 -1
  85. package/lib/src/shared/ecommerce-settings/util/refreshDuplicatedMetadata.js +31 -9
  86. package/lib/src/shared/logo-settings/components/EditLogoSettings.mixin.d.ts +1 -0
  87. package/lib/src/shared/logo-settings/components/LogoSettings.mixin.d.ts +6 -43
  88. package/lib/src/shared/page-navigation/store/page-navigation-store.d.ts +3 -1
  89. package/lib/src/shared/page-navigation/store/page-navigation-store.js +34 -9
  90. package/lib/src/shared/page-settings/components/delete-page-modal/DeletePageModal.mixin.d.ts +1 -1
  91. package/lib/src/shared/page-settings/components/new-page-modal/NewPageModal.mixin.d.ts +9 -2
  92. package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +200 -44
  93. package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.js +12 -35
  94. package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +190 -44
  95. package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.js +34 -2
  96. package/lib/src/shared/page-settings/duplicate-page.util.d.ts +4 -0
  97. package/lib/src/shared/page-settings/duplicate-page.util.js +82 -0
  98. package/lib/src/shared/page-settings/models.d.ts +1 -0
  99. package/lib/src/shared/page-settings/store/page-settings-store.d.ts +7 -2
  100. package/lib/src/shared/page-settings/store/page-settings-store.js +90 -7
  101. package/lib/src/shared/page-settings/utils.d.ts +3 -0
  102. package/lib/src/shared/page-settings/utils.js +6 -0
  103. package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +1 -56
  104. package/lib/src/shared/side-bar/components/SideBar.mixin.d.ts +0 -42
  105. package/lib/src/shared/side-bar/components/SideBarTabButton.mixin.d.ts +1 -0
  106. package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +4 -42
  107. package/lib/src/shared/template-settings/components/TemplatesSettings.mixin.d.ts +1 -0
  108. package/lib/src/tracker.mjs +1 -1
  109. package/lib/src/{useEventTracker-C5Ql5p7u.js → useEventTracker-DwPTmzpa.js} +13 -3
  110. package/package.json +2 -2
  111. package/src/brand-page/components/navigation/hamburger/HamburgerNavigation.vue +1 -0
  112. package/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.mixin.ts +18 -1
  113. package/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.vue +73 -3
  114. package/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.vue.test.ts +181 -0
  115. package/src/brand-page/components/page/Page.mixin.ts +21 -11
  116. package/src/brand-page/components/page/Page.vue +2 -0
  117. package/src/brand-page/components/page-header/HeaderLayout.stories.ts +10 -0
  118. package/src/brand-page/components/page-header/HeaderLayout.vue +415 -71
  119. package/src/brand-page/components/page-header/PageHeader.mixin.ts +14 -10
  120. package/src/brand-page/components/page-header/PageHeader.vue +16 -1
  121. package/src/brand-page/components/page-header/PageHeader.vue.test.ts +339 -0
  122. package/src/brand-page/constants/sections/header-display.constants.test.ts +44 -0
  123. package/src/brand-page/constants/sections/header-display.constants.ts +35 -0
  124. package/src/brand-page/models/brand-page-context.model.ts +0 -23
  125. package/src/brand-page/models/header-button.model.test.ts +85 -0
  126. package/src/brand-page/models/index.ts +19 -0
  127. package/src/brand-page/utils/context.util.ts +15 -0
  128. package/src/brand-page/utils/route.util.ts +13 -0
  129. package/src/brand-page/utils/view-model.util.test.ts +151 -1
  130. package/src/brand-page/utils/view-model.util.ts +73 -1
  131. package/src/brand-page/view-models.ts +3 -0
  132. package/src/brand-page-maker/components/action-bar/ActionBar.mixin.ts +0 -10
  133. package/src/brand-page-maker/components/action-bar/ActionBarNavigation.test.ts +8 -49
  134. package/src/brand-page-maker/components/action-bar/ActionBarNavigation.vue +1 -1
  135. package/src/brand-page-maker/composables/useEventTracker.ts +13 -0
  136. package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.ts +2 -4
  137. package/src/brand-page-maker/validators/section-button.validator.ts +23 -19
  138. package/src/bundles/bundled-translations.de-DE.json +9 -2
  139. package/src/bundles/bundled-translations.es-ES.json +9 -2
  140. package/src/bundles/bundled-translations.fr-CA.json +9 -2
  141. package/src/bundles/bundled-translations.fr-FR.json +9 -2
  142. package/src/bundles/bundled-translations.json +9 -2
  143. package/src/bundles/bundled-translations.pt-BR.json +9 -2
  144. package/src/bundles/bundled-translations.pt-PT.json +9 -2
  145. package/src/composables/useTranslate.ts +2 -1
  146. package/src/metadata-builder/builders/item-id-utils.ts +9 -2
  147. package/src/shared/content-settings/components/text-field/TextField.mixin.ts +15 -0
  148. package/src/shared/content-settings/components/url-field/UrlField.vue +1 -0
  149. package/src/shared/ecommerce-settings/components/product-config-field/ProductConfigOption.vue +0 -2
  150. package/src/shared/ecommerce-settings/util/refreshDuplicatedMetadata.ts +32 -10
  151. package/src/shared/page-navigation/store/page-navigation-store.ts +57 -13
  152. package/src/shared/page-settings/components/header-settings-panel/HeaderSettingsPanel.button-section.test.ts +131 -0
  153. package/src/shared/page-settings/components/header-settings-panel/HeaderSettingsPanel.vue +65 -10
  154. package/src/shared/page-settings/components/page-settings/NestedDraggable.vue +3 -0
  155. package/src/shared/page-settings/components/page-settings/PageElement.vue +2 -0
  156. package/src/shared/page-settings/components/page-settings/PageSettingMenu.test.ts +105 -0
  157. package/src/shared/page-settings/components/page-settings/PageSettingMenu.vue +16 -0
  158. package/src/shared/page-settings/components/page-settings/PageSettings.duplicate.test.ts +108 -0
  159. package/src/shared/page-settings/components/page-settings/PageSettings.mixin.ts +22 -50
  160. package/src/shared/page-settings/components/page-settings/PageSettings.vue +1 -0
  161. package/src/shared/page-settings/components/page-settings/i18n/page-settings.de-DE.json +3 -1
  162. package/src/shared/page-settings/components/page-settings/i18n/page-settings.es-ES.json +3 -1
  163. package/src/shared/page-settings/components/page-settings/i18n/page-settings.fr-CA.json +3 -1
  164. package/src/shared/page-settings/components/page-settings/i18n/page-settings.fr-FR.json +3 -1
  165. package/src/shared/page-settings/components/page-settings/i18n/page-settings.json +3 -1
  166. package/src/shared/page-settings/components/page-settings/i18n/page-settings.pt-BR.json +3 -1
  167. package/src/shared/page-settings/components/page-settings/i18n/page-settings.pt-PT.json +3 -1
  168. package/src/shared/page-settings/components/page-settings-section-styles/HeaderButtonSettings.test.ts +305 -0
  169. package/src/shared/page-settings/components/page-settings-section-styles/HeaderButtonSettings.vue +265 -0
  170. package/src/shared/page-settings/components/page-settings-section-styles/HeaderDisplayStyle.test.ts +354 -0
  171. package/src/shared/page-settings/components/page-settings-section-styles/HeaderDisplayStyle.vue +48 -9
  172. package/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.header-button.test.ts +114 -0
  173. package/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.ts +38 -1
  174. package/src/shared/page-settings/components/page-settings-section-styles/i18n/page-settings-section.de-DE.json +6 -1
  175. package/src/shared/page-settings/components/page-settings-section-styles/i18n/page-settings-section.es-ES.json +6 -1
  176. package/src/shared/page-settings/components/page-settings-section-styles/i18n/page-settings-section.fr-CA.json +6 -1
  177. package/src/shared/page-settings/components/page-settings-section-styles/i18n/page-settings-section.fr-FR.json +6 -1
  178. package/src/shared/page-settings/components/page-settings-section-styles/i18n/page-settings-section.json +6 -1
  179. package/src/shared/page-settings/components/page-settings-section-styles/i18n/page-settings-section.pt-BR.json +6 -1
  180. package/src/shared/page-settings/components/page-settings-section-styles/i18n/page-settings-section.pt-PT.json +6 -1
  181. package/src/shared/page-settings/duplicate-page.util.test.ts +382 -0
  182. package/src/shared/page-settings/duplicate-page.util.ts +124 -0
  183. package/src/shared/page-settings/models.ts +1 -0
  184. package/src/shared/page-settings/store/page-settings-store.test.ts +441 -1
  185. package/src/shared/page-settings/store/page-settings-store.ts +147 -11
  186. package/src/shared/page-settings/utils.ts +10 -0
@@ -1856,7 +1856,9 @@
1856
1856
  "showPage": "Seite anzeigen",
1857
1857
  "hidePage": "Seite ausblenden",
1858
1858
  "delete": "Seite löschen",
1859
- "addSubPage": "Unterseite hinzufügen"
1859
+ "addSubPage": "Unterseite hinzufügen",
1860
+ "duplicatePage": "Seite duplizieren",
1861
+ "duplicatePageTitle": "{{title}} Kopieren"
1860
1862
  },
1861
1863
  "pageSettingsSection": {
1862
1864
  "showNavigationBelow": "Navigation unter dem Logo anzeigen",
@@ -1867,7 +1869,12 @@
1867
1869
  "iconStyle": "Symbol-Stil",
1868
1870
  "logoSize": "Logogröße",
1869
1871
  "socialLinks": "Social-Media-Links",
1870
- "copyright": "Copyright"
1872
+ "copyright": "Copyright",
1873
+ "buttonLabel": "Etikett",
1874
+ "buttonLabelPlaceholder": "Kontakt",
1875
+ "buttonLink": "Link",
1876
+ "buttonFillColor": "Füllfarbe",
1877
+ "buttonBorderColor": "Randfarbe"
1871
1878
  },
1872
1879
  "publishBrandPageModalWithState": {
1873
1880
  "domainSearchButtonLabel": "Suche",
@@ -1856,7 +1856,9 @@
1856
1856
  "showPage": "Mostrar página",
1857
1857
  "hidePage": "Ocultar página",
1858
1858
  "delete": "Eliminar página",
1859
- "addSubPage": "Añadir subpágina"
1859
+ "addSubPage": "Añadir subpágina",
1860
+ "duplicatePage": "Duplicar página",
1861
+ "duplicatePageTitle": "{{title}} copia"
1860
1862
  },
1861
1863
  "pageSettingsSection": {
1862
1864
  "showNavigationBelow": "Muestra la navegación debajo del logo",
@@ -1867,7 +1869,12 @@
1867
1869
  "iconStyle": "Estilo de icono",
1868
1870
  "logoSize": "Tamaño del logo",
1869
1871
  "socialLinks": "Enlaces a redes sociales",
1870
- "copyright": "Derechos de autor"
1872
+ "copyright": "Derechos de autor",
1873
+ "buttonLabel": "Etiqueta",
1874
+ "buttonLabelPlaceholder": "Contacto",
1875
+ "buttonLink": "Enlace",
1876
+ "buttonFillColor": "Color de relleno",
1877
+ "buttonBorderColor": "Color del borde"
1871
1878
  },
1872
1879
  "publishBrandPageModalWithState": {
1873
1880
  "domainSearchButtonLabel": "Buscar",
@@ -1856,7 +1856,9 @@
1856
1856
  "showPage": "Afficher la page",
1857
1857
  "hidePage": "Masquez la page",
1858
1858
  "delete": "Supprimer la page",
1859
- "addSubPage": "Ajouter une sous-page"
1859
+ "addSubPage": "Ajouter une sous-page",
1860
+ "duplicatePage": "Dupliquer la page",
1861
+ "duplicatePageTitle": "{{title}} Copie"
1860
1862
  },
1861
1863
  "pageSettingsSection": {
1862
1864
  "showNavigationBelow": "Afficher la navigation sous le logo",
@@ -1867,7 +1869,12 @@
1867
1869
  "iconStyle": "Style d'icône",
1868
1870
  "logoSize": "Taille du logo",
1869
1871
  "socialLinks": "Liens vers les réseaux sociaux",
1870
- "copyright": "Droits d’auteur"
1872
+ "copyright": "Droits d’auteur",
1873
+ "buttonLabel": "Étiquette",
1874
+ "buttonLabelPlaceholder": "Nous joindre",
1875
+ "buttonLink": "Lien",
1876
+ "buttonFillColor": "Couleur de remplissage",
1877
+ "buttonBorderColor": "Couleur de bordure"
1871
1878
  },
1872
1879
  "publishBrandPageModalWithState": {
1873
1880
  "domainSearchButtonLabel": "Rechercher",
@@ -1856,7 +1856,9 @@
1856
1856
  "showPage": "Afficher la page",
1857
1857
  "hidePage": "Masquez la page",
1858
1858
  "delete": "Supprimer la page",
1859
- "addSubPage": "Ajouter une sous-page"
1859
+ "addSubPage": "Ajouter une sous-page",
1860
+ "duplicatePage": "Dupliquer la page",
1861
+ "duplicatePageTitle": "Copie de {{title}}"
1860
1862
  },
1861
1863
  "pageSettingsSection": {
1862
1864
  "showNavigationBelow": "Afficher la navigation sous le logo",
@@ -1867,7 +1869,12 @@
1867
1869
  "iconStyle": "Style d'icône",
1868
1870
  "logoSize": "Taille du logo",
1869
1871
  "socialLinks": "Liens vers les réseaux sociaux",
1870
- "copyright": "Droits d’auteur"
1872
+ "copyright": "Droits d’auteur",
1873
+ "buttonLabel": "Étiquette",
1874
+ "buttonLabelPlaceholder": "Contactez-nous",
1875
+ "buttonLink": "Lien",
1876
+ "buttonFillColor": "Couleur de remplissage",
1877
+ "buttonBorderColor": "Couleur de bordure"
1871
1878
  },
1872
1879
  "publishBrandPageModalWithState": {
1873
1880
  "domainSearchButtonLabel": "Rechercher",
@@ -1856,7 +1856,9 @@
1856
1856
  "showPage": "Show page",
1857
1857
  "hidePage": "Hide page",
1858
1858
  "delete": "Delete page",
1859
- "addSubPage": "Add subpage"
1859
+ "addSubPage": "Add subpage",
1860
+ "duplicatePage": "Duplicate page",
1861
+ "duplicatePageTitle": "{{title}} Copy"
1860
1862
  },
1861
1863
  "pageSettingsSection": {
1862
1864
  "showNavigationBelow": "Show navigation below logo",
@@ -1867,7 +1869,12 @@
1867
1869
  "iconStyle": "Icon style",
1868
1870
  "logoSize": "Logo Size",
1869
1871
  "socialLinks": "Social Links",
1870
- "copyright": "Copyright"
1872
+ "copyright": "Copyright",
1873
+ "buttonLabel": "Label",
1874
+ "buttonLabelPlaceholder": "Contact Us",
1875
+ "buttonLink": "Link",
1876
+ "buttonFillColor": "Fill color",
1877
+ "buttonBorderColor": "Border color"
1871
1878
  },
1872
1879
  "publishBrandPageModalWithState": {
1873
1880
  "domainSearchButtonLabel": "Search",
@@ -1856,7 +1856,9 @@
1856
1856
  "showPage": "Mostrar página",
1857
1857
  "hidePage": "Ocultar página",
1858
1858
  "delete": "Eliminar página",
1859
- "addSubPage": "Adicionar subpágina"
1859
+ "addSubPage": "Adicionar subpágina",
1860
+ "duplicatePage": "Duplicar página",
1861
+ "duplicatePageTitle": "{{title}} Copiar"
1860
1862
  },
1861
1863
  "pageSettingsSection": {
1862
1864
  "showNavigationBelow": "Mostrar navegação abaixo do logotipo",
@@ -1867,7 +1869,12 @@
1867
1869
  "iconStyle": "Estilo de ícone",
1868
1870
  "logoSize": "Tamanho do logotipo",
1869
1871
  "socialLinks": "Links de redes sociais",
1870
- "copyright": "Direitos autorais"
1872
+ "copyright": "Direitos autorais",
1873
+ "buttonLabel": "Rótulo",
1874
+ "buttonLabelPlaceholder": "Entre em contato",
1875
+ "buttonLink": "Link",
1876
+ "buttonFillColor": "Cor de preenchimento",
1877
+ "buttonBorderColor": "Cor da borda"
1871
1878
  },
1872
1879
  "publishBrandPageModalWithState": {
1873
1880
  "domainSearchButtonLabel": "Pesquisar",
@@ -1856,7 +1856,9 @@
1856
1856
  "showPage": "Mostrar página",
1857
1857
  "hidePage": "Ocultar página",
1858
1858
  "delete": "Eliminar página",
1859
- "addSubPage": "Adicionar subpágina"
1859
+ "addSubPage": "Adicionar subpágina",
1860
+ "duplicatePage": "Duplicar página",
1861
+ "duplicatePageTitle": "{{title}} Cópia"
1860
1862
  },
1861
1863
  "pageSettingsSection": {
1862
1864
  "showNavigationBelow": "Mostrar a navegação por baixo do logótipo",
@@ -1867,7 +1869,12 @@
1867
1869
  "iconStyle": "Estilo de Ícone",
1868
1870
  "logoSize": "Tamanho do logótipo",
1869
1871
  "socialLinks": "Links de redes sociais",
1870
- "copyright": "Direitos de autor"
1872
+ "copyright": "Direitos de autor",
1873
+ "buttonLabel": "Etiqueta",
1874
+ "buttonLabelPlaceholder": "Contacte-nos",
1875
+ "buttonLink": "Link",
1876
+ "buttonFillColor": "Cor de preenchimento",
1877
+ "buttonBorderColor": "Cor da borda"
1871
1878
  },
1872
1879
  "publishBrandPageModalWithState": {
1873
1880
  "domainSearchButtonLabel": "Pesquisar",
@@ -142,7 +142,8 @@ const productConfigOptionTr = (key) => tr(`productConfigOption.${key}`);
142
142
  const editLogoSettingsTr = (key) => tr(`editLogoSettings.${key}`);
143
143
  const myUploadSettingsTr = (key, valuesToInterpolate = {}) =>
144
144
  tr(`myUploadSettings.${key}`, valuesToInterpolate);
145
- const pageSettingsTr = (key) => tr(`pageSettings.${key}`);
145
+ const pageSettingsTr = (key, valuesToInterpolate = {}) =>
146
+ tr(`pageSettings.${key}`, valuesToInterpolate);
146
147
  const pageSettingsSectionTr = (key) => tr(`pageSettingsSection.${key}`);
147
148
  const templateSettingsTr = (key) => tr(`templateSettings.${key}`);
148
149
  const unsplashLibraryTr = (key) => tr(`unsplashLibrary.${key}`);
@@ -10,6 +10,14 @@ export const END_ITEM_ANCHOR = '__end__';
10
10
  /** Generate a stable item id. Mirrors section-level `uuid.v4()` id generation. */
11
11
  export const generateItemId = (): string => uuidv4();
12
12
 
13
+ /** Every array field the minifier surfaces to the AI as a list of items. */
14
+ export const ITEM_ID_BEARING_FIELDS = [
15
+ 'images',
16
+ 'items',
17
+ 'textItems',
18
+ 'links',
19
+ ] as const;
20
+
13
21
  /**
14
22
  * Walk an entire BrandPageModel and backfill a stable uuid `id` onto every
15
23
  * nested array item that lacks one (gallery images, images/shapes/testimonial
@@ -23,8 +31,7 @@ export const generateItemId = (): string => uuidv4();
23
31
  */
24
32
  export const ensureBrandPageItemIds = (model: BrandPageModel): void => {
25
33
  const ensureContentItemIds = (content: Record<string, unknown>): void => {
26
- // Every array field that the minifier surfaces as a list of items.
27
- for (const field of ['images', 'items', 'textItems', 'links'] as const) {
34
+ for (const field of ITEM_ID_BEARING_FIELDS) {
28
35
  const arr = content[field];
29
36
 
30
37
  if (Array.isArray(arr)) ensureItemIds(arr as { id?: string }[]);
@@ -1,5 +1,20 @@
1
1
  import { defineComponent } from 'vue';
2
2
  import GenericTextInputMixin from '../GenericTextInput.mixin';
3
+
3
4
  export default defineComponent({
4
5
  mixins: [GenericTextInputMixin],
6
+ props: {
7
+ // Opt-in: clearing the field shows its error at once, not only after blur.
8
+ showErrorWhenEmpty: {
9
+ type: Boolean,
10
+ default: false,
11
+ },
12
+ },
13
+ watch: {
14
+ value(value: string | false | undefined): void {
15
+ if (this.showErrorWhenEmpty && !(value || '').trim()) {
16
+ this.isDirty = false;
17
+ }
18
+ },
19
+ },
5
20
  });
@@ -11,6 +11,7 @@
11
11
  :icon="icon"
12
12
  :error="isErrorVisible"
13
13
  @focus="onFocusOverride"
14
+ @blur="onBlur"
14
15
  @input="onInputOverride"
15
16
  @keyup="onChangeOverride"
16
17
  />
@@ -96,7 +96,6 @@ const onEditProduct = (index: number) => {
96
96
  product.enableNotes,
97
97
  );
98
98
  const tempProduct = cloneDeep(shopSettingStore.getProductById(product.id));
99
- console.log(tempProduct, 'tempProduct');
100
99
  productSettingStore.openModal(tempProduct);
101
100
  };
102
101
 
@@ -147,7 +146,6 @@ const onSaveProductModal = (event: {
147
146
  onItemsChange(newProductArray);
148
147
  // Update shop store
149
148
  if (event.isNewProduct) {
150
- console.log(event.product, 'new product');
151
149
  shopSettingStore.addProduct(event.product);
152
150
  } else {
153
151
  shopSettingStore.updateProduct(event.product.id, event.product);
@@ -24,10 +24,9 @@ export function refreshDuplicatedMetadata(
24
24
 
25
25
  model.pages.forEach((page) =>
26
26
  page.contents.forEach((content) => {
27
+ rotateMonetizationIds(content);
28
+
27
29
  if (isShopContent(content)) {
28
- // Shop products collide on the global product / sku_key tables. The shop's payment-config
29
- // link is written with throwaway ids (not the content id), so only the product ids rotate.
30
- content.products.forEach(rotateProductIds);
31
30
  disconnectPayment(content.shopPaymentConfig);
32
31
  } else if (isPayment(content)) {
33
32
  resetPaymentBlock(content, content.requestPaymentConfig);
@@ -40,6 +39,25 @@ export function refreshDuplicatedMetadata(
40
39
  return model;
41
40
  }
42
41
 
42
+ /**
43
+ * Rotate the client-minted ids the brand-page-api keys a **global** row on — shop product / sku_key
44
+ * and payment-option ids. A verbatim copy collides with its source on those tables.
45
+ *
46
+ * Shared with page duplication, which wants only this half: that copy keeps the same owner, so it
47
+ * keeps its payment connection.
48
+ */
49
+ export function rotateMonetizationIds(content: Content): void {
50
+ if (isShopContent(content)) {
51
+ // The shop's payment-config link is written with throwaway ids (not the content id), so only
52
+ // the product ids rotate here.
53
+ content.products.forEach(rotateProductIds);
54
+ } else if (isPayment(content)) {
55
+ rotatePaymentOptionIds(content.requestPaymentConfig);
56
+ } else if (isSupportMe(content)) {
57
+ rotatePaymentOptionIds(content.supportMeConfig);
58
+ }
59
+ }
60
+
43
61
  function rotateProductIds(product: ProductModel): void {
44
62
  product.id = uuid();
45
63
 
@@ -72,19 +90,23 @@ function rotateProductIds(product: ProductModel): void {
72
90
  });
73
91
  }
74
92
 
93
+ // `brand_page_product` is keyed on the payment-option id, so a verbatim copy would adopt the
94
+ // source's product rows on its next payment upsert.
95
+ function rotatePaymentOptionIds(config: PaymentConfig): void {
96
+ config.paymentOptions.forEach((option) => {
97
+ option.id = uuid();
98
+ });
99
+ }
100
+
75
101
  /**
76
102
  * request-payment / support-me content. The api keys `content_block_payment_config` on the content
77
- * id (PK) and `brand_page_product` on the payment-option id (PK), both global. A verbatim copy
78
- * would, on its next payment upsert, repoint the source's config link and adopt its product rows —
79
- * so rotate both to make the copy independent, then drop the connection.
103
+ * id (PK), so a verbatim copy would repoint the source's config link on its next payment upsert -
104
+ * re-mint it, then drop the connection. (The option ids are rotated upstream, for both kinds of
105
+ * duplication.)
80
106
  */
81
107
  function resetPaymentBlock(content: Content, config: PaymentConfig): void {
82
108
  content.id = uuid();
83
109
 
84
- config.paymentOptions.forEach((option) => {
85
- option.id = uuid();
86
- });
87
-
88
110
  disconnectPayment(config);
89
111
  }
90
112
 
@@ -38,13 +38,13 @@ const findParentRouteIdForRouteId = (
38
38
  return undefined;
39
39
  };
40
40
 
41
- // This function will find all the page slugs that exist at the depth that we're modifying, this way, we can avoid duplication of page slugs
42
- // This will help support the use of similar named routes, e.g /home/home-1 and /my-home/home-1
43
- const getPageSlugsForCurrentDepth = (
41
+ // Routes at one depth. Slugs and titles only need to be unique among siblings,
42
+ // so /home/home-1 and /my-home/home-1 can coexist.
43
+ const getRoutesForCurrentDepth = (
44
44
  navModel: NavModel,
45
45
  parentRouteId?: string,
46
46
  excludeRouteId?: string,
47
- ): string[] => {
47
+ ): NavRoute[] => {
48
48
  let ordersAtDepth: NavOrder[];
49
49
 
50
50
  if (!parentRouteId) {
@@ -60,14 +60,21 @@ const getPageSlugsForCurrentDepth = (
60
60
 
61
61
  const routeIdsAtDepth = ordersAtDepth.map((order) => order.routeId);
62
62
 
63
- return navModel.routes
64
- .filter(
65
- (route) =>
66
- routeIdsAtDepth.includes(route.id) && route.id !== excludeRouteId,
67
- )
68
- .map((route) => route.pageSlug);
63
+ return navModel.routes.filter(
64
+ (route) =>
65
+ routeIdsAtDepth.includes(route.id) && route.id !== excludeRouteId,
66
+ );
69
67
  };
70
68
 
69
+ const getPageSlugsForCurrentDepth = (
70
+ navModel: NavModel,
71
+ parentRouteId?: string,
72
+ excludeRouteId?: string,
73
+ ): string[] =>
74
+ getRoutesForCurrentDepth(navModel, parentRouteId, excludeRouteId).map(
75
+ (route) => route.pageSlug,
76
+ );
77
+
71
78
  export const usePageNavigationStore = defineStore('pageNavigation', {
72
79
  state: (): PageNavigationState => ({
73
80
  routes: [],
@@ -81,11 +88,32 @@ export const usePageNavigationStore = defineStore('pageNavigation', {
81
88
  orders: this.orders,
82
89
  });
83
90
  },
91
+ // Mirrors the renderer's hasVisibleNavigation (route.util.ts) on the maker's nav state:
92
+ // the header shows a nav for >1 visible top-level page, or 1 with a visible subpage.
93
+ hasVisibleNavigation(): boolean {
94
+ const isVisible = (order: NavOrder): boolean => {
95
+ const route = this.routes.find((r) => r.id === order.routeId);
96
+
97
+ return route !== undefined && !route.isHidden;
98
+ };
99
+ const visibleOrders = this.orders.filter(isVisible);
100
+
101
+ return (
102
+ visibleOrders.length > 1 ||
103
+ (visibleOrders.length === 1 &&
104
+ visibleOrders[0].subRoutes.some(isVisible))
105
+ );
106
+ },
84
107
  },
85
108
  actions: {
86
109
  getPageSlugsForDepth(parentRouteId?: string): string[] {
87
110
  return getPageSlugsForCurrentDepth(this.nav, parentRouteId);
88
111
  },
112
+ getDisplayNamesForDepth(parentRouteId?: string): string[] {
113
+ return getRoutesForCurrentDepth(this.nav, parentRouteId).map(
114
+ (route) => route.displayName,
115
+ );
116
+ },
89
117
  getParentRouteIdForPage(pageId: string): string | undefined {
90
118
  const route = this.routes.find((r) => r.pageId === pageId);
91
119
 
@@ -127,12 +155,28 @@ export const usePageNavigationStore = defineStore('pageNavigation', {
127
155
  this.routes = nav.routes;
128
156
  this.orders = nav.orders;
129
157
  },
130
- addNavRoute(newRoute: NavRoute, parentRouteId?: string): void {
158
+ addNavRoute(
159
+ newRoute: NavRoute,
160
+ parentRouteId?: string,
161
+ insertAfterRouteId?: string,
162
+ ): void {
131
163
  const newOrder: NavOrder = {
132
164
  routeId: newRoute.id,
133
165
  subRoutes: [],
134
166
  };
135
167
 
168
+ const addToSiblings = (siblings: NavOrder[]): void => {
169
+ const afterIndex = insertAfterRouteId
170
+ ? siblings.findIndex((order) => order.routeId === insertAfterRouteId)
171
+ : -1;
172
+
173
+ if (afterIndex === -1) {
174
+ siblings.push(newOrder);
175
+ } else {
176
+ siblings.splice(afterIndex + 1, 0, newOrder);
177
+ }
178
+ };
179
+
136
180
  if (parentRouteId) {
137
181
  // Find where to insert the new route into order
138
182
  const parentOrder = findParentOrderByRouteId(
@@ -141,7 +185,7 @@ export const usePageNavigationStore = defineStore('pageNavigation', {
141
185
  );
142
186
 
143
187
  if (parentOrder) {
144
- parentOrder.subRoutes.push(newOrder);
188
+ addToSiblings(parentOrder.subRoutes);
145
189
  } else {
146
190
  console.error(
147
191
  `Parent route with id ${parentRouteId} not found in nav orders.`,
@@ -149,7 +193,7 @@ export const usePageNavigationStore = defineStore('pageNavigation', {
149
193
  }
150
194
  } else {
151
195
  // Push to root of orders object as this is not a nested route
152
- this.orders.push(newOrder);
196
+ addToSiblings(this.orders);
153
197
  }
154
198
 
155
199
  this.routes.push(newRoute);
@@ -0,0 +1,131 @@
1
+ import { describe, test, expect, beforeEach } from 'vitest';
2
+ import { createPinia, setActivePinia } from 'pinia';
3
+ import { shallowMount } from '@vue/test-utils';
4
+ import { Toggle } from '@designcrowd/fe-shared-lib';
5
+ import type { LogoTheme } from '@brand-page';
6
+ import { VIEWPORTS } from '@brand-page';
7
+ import HeaderSettingsPanel from './HeaderSettingsPanel.vue';
8
+ import HeaderButtonSettings from '../page-settings-section-styles/HeaderButtonSettings.vue';
9
+ import { useUiPageSettingsStore } from '../../store';
10
+ import { FabricRenderClient } from '../../../../clients/fabric-render-client';
11
+
12
+ // Button section: brandsite-only, header toggle shows/hides the fields, writes sync both viewports.
13
+ describe('HeaderSettingsPanel — Button section', () => {
14
+ beforeEach(() => {
15
+ setActivePinia(createPinia());
16
+ // The Logo section renders alongside and needs the client singleton.
17
+ FabricRenderClient.setInstance({ baseUrl: 'http://localhost:3000' });
18
+ });
19
+
20
+ const CollapsiblePanelStub = {
21
+ template: '<div><slot name="header-actions" /><slot /></div>',
22
+ };
23
+
24
+ const mountPanel = (isBrandSite: boolean) =>
25
+ shallowMount(HeaderSettingsPanel, {
26
+ props: {
27
+ isAdminMaker: false,
28
+ isBrandSite,
29
+ logoTheme: {} as LogoTheme,
30
+ sectionName: 'header',
31
+ styleOptions: [],
32
+ },
33
+ global: {
34
+ // Render CollapsiblePanel slots so the toggle and body aren't swallowed.
35
+ stubs: { CollapsiblePanel: CollapsiblePanelStub },
36
+ },
37
+ });
38
+
39
+ const buttonToggle = (wrapper: ReturnType<typeof mountPanel>) =>
40
+ wrapper
41
+ .findAllComponents(Toggle)
42
+ .find(
43
+ (t) => t.attributes('data-test-header-button-toggle') !== undefined,
44
+ );
45
+
46
+ test('brandsite: the header toggle renders, off, and the fields stay hidden', () => {
47
+ const wrapper = mountPanel(true);
48
+
49
+ expect(buttonToggle(wrapper)).toBeDefined();
50
+ // the stubbed Toggle carries its props as attributes
51
+ expect(buttonToggle(wrapper)?.attributes('model-value')).toBe('false');
52
+ expect(wrapper.findComponent(HeaderButtonSettings).exists()).toBe(false);
53
+ });
54
+
55
+ test('brand page / brand contact: no Button section at all', () => {
56
+ const wrapper = mountPanel(false);
57
+
58
+ expect(buttonToggle(wrapper)).toBeUndefined();
59
+ expect(wrapper.findComponent(HeaderButtonSettings).exists()).toBe(false);
60
+ });
61
+
62
+ test('toggling on writes isVisible to BOTH viewports and reveals the fields', async () => {
63
+ const wrapper = mountPanel(true);
64
+
65
+ await buttonToggle(wrapper)?.vm.$emit('update:model-value', true);
66
+ await wrapper.vm.$nextTick();
67
+
68
+ const sections = useUiPageSettingsStore().sections.header;
69
+
70
+ expect(sections[VIEWPORTS.desktop].headerButton?.isVisible).toBe(true);
71
+ expect(sections[VIEWPORTS.mobile].headerButton?.isVisible).toBe(true);
72
+ expect(wrapper.findComponent(HeaderButtonSettings).exists()).toBe(true);
73
+ });
74
+
75
+ test('expanding via the chevron while off switches the button on; later collapses freely', async () => {
76
+ const wrapper = mountPanel(true);
77
+ const sectionHeader = wrapper.get(
78
+ '[data-test-header-button-section-header]',
79
+ );
80
+
81
+ // off + collapsed: expanding turns the button on and shows the fields
82
+ await sectionHeader.trigger('click');
83
+
84
+ const sections = useUiPageSettingsStore().sections.header;
85
+
86
+ expect(sections[VIEWPORTS.desktop].headerButton?.isVisible).toBe(true);
87
+ expect(sections[VIEWPORTS.mobile].headerButton?.isVisible).toBe(true);
88
+ expect(wrapper.findComponent(HeaderButtonSettings).exists()).toBe(true);
89
+
90
+ // on: the chevron only collapses/expands, never switches the button off
91
+ await sectionHeader.trigger('click');
92
+
93
+ expect(sections[VIEWPORTS.desktop].headerButton?.isVisible).toBe(true);
94
+ expect(wrapper.findComponent(HeaderButtonSettings).exists()).toBe(false);
95
+
96
+ await sectionHeader.trigger('click');
97
+
98
+ expect(wrapper.findComponent(HeaderButtonSettings).exists()).toBe(true);
99
+ });
100
+
101
+ test('toggling off hides the fields but keeps the configuration for a re-enable', async () => {
102
+ const wrapper = mountPanel(true);
103
+
104
+ await buttonToggle(wrapper)?.vm.$emit('update:model-value', true);
105
+ // simulate a label edit, which the mixin dual-writes to both viewports
106
+ [VIEWPORTS.desktop, VIEWPORTS.mobile].forEach((viewport) => {
107
+ useUiPageSettingsStore().setPageSettingsSectionValue({
108
+ sectionName: 'header',
109
+ propName: 'headerButton',
110
+ value: { isVisible: true, text: 'Book now', buttonLinkType: 'url' },
111
+ viewport,
112
+ });
113
+ });
114
+ await buttonToggle(wrapper)?.vm.$emit('update:model-value', false);
115
+ await wrapper.vm.$nextTick();
116
+
117
+ const desktop = useUiPageSettingsStore().sections.header[VIEWPORTS.desktop];
118
+
119
+ expect(wrapper.findComponent(HeaderButtonSettings).exists()).toBe(false);
120
+ expect(desktop.headerButton?.isVisible).toBe(false);
121
+ expect(desktop.headerButton?.text).toBe('Book now');
122
+
123
+ // Toggling off also collapses, so one chevron click re-enables — no dead first click.
124
+ await wrapper
125
+ .get('[data-test-header-button-section-header]')
126
+ .trigger('click');
127
+
128
+ expect(desktop.headerButton?.isVisible).toBe(true);
129
+ expect(wrapper.findComponent(HeaderButtonSettings).exists()).toBe(true);
130
+ });
131
+ });