@designcrowd/library.brand-page 6.0.5 → 6.0.6-ast-bugs

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 (395) hide show
  1. package/lib/src/{CreatedOnBrandCrowd-de-de-DhzvKlTS.js → CreatedOnBrandCrowd-de-de-SHCspMwS.js} +3 -3
  2. package/lib/src/{CreatedOnBrandCrowd-en-us-DKH4lmNV.js → CreatedOnBrandCrowd-en-us-C6lITAAT.js} +3 -3
  3. package/lib/src/{CreatedOnBrandCrowd-es-es-RloPCLuV.js → CreatedOnBrandCrowd-es-es-Uh69c4vZ.js} +3 -3
  4. package/lib/src/{CreatedOnBrandCrowd-fr-fr-Cu9e2H0K.js → CreatedOnBrandCrowd-fr-ca-Bb0rp7BV.js} +3 -3
  5. package/lib/src/{CreatedOnBrandCrowd-fr-ca-Cu9e2H0K.js → CreatedOnBrandCrowd-fr-fr-Bb0rp7BV.js} +3 -3
  6. package/lib/src/{CreatedOnBrandCrowd-pt-pt-CiCnjxBZ.js → CreatedOnBrandCrowd-pt-br-DsrQHcjs.js} +3 -3
  7. package/lib/src/{CreatedOnBrandCrowd-pt-br-CiCnjxBZ.js → CreatedOnBrandCrowd-pt-pt-DsrQHcjs.js} +3 -3
  8. package/lib/src/{CreatedOnDcom-de-de-CwlnedFV.js → CreatedOnDcom-de-de-BshZYzSp.js} +3 -3
  9. package/lib/src/{CreatedOnDcom-en-us-DFHex61v.js → CreatedOnDcom-en-us-CLu8mKUW.js} +3 -3
  10. package/lib/src/{CreatedOnDcom-es-es-BTxH6I4V.js → CreatedOnDcom-es-es-BZYhkONd.js} +3 -3
  11. package/lib/src/{CreatedOnDcom-fr-ca-BVw0KYxu.js → CreatedOnDcom-fr-ca-CIaBEp_9.js} +3 -3
  12. package/lib/src/{CreatedOnDcom-fr-fr-DaqNz1Er.js → CreatedOnDcom-fr-fr-dyF7hioJ.js} +3 -3
  13. package/lib/src/{CreatedOnDcom-pt-br-B4KsMI8W.js → CreatedOnDcom-pt-br-CUHjk2du.js} +3 -3
  14. package/lib/src/{CreatedOnDcom-pt-pt-CWoHEtOZ.js → CreatedOnDcom-pt-pt-CWDvQidv.js} +3 -3
  15. package/lib/src/brand-page/clients/brand-page.client.d.ts +9 -9
  16. package/lib/src/brand-page/components/banner-section/BannerSection.mixin.d.ts +103 -0
  17. package/lib/src/brand-page/components/banner-section/BannerSection.mixin.js +178 -0
  18. package/lib/src/brand-page/components/image-gallery/masonry/MasonryGallery.mixin.d.ts +1 -2
  19. package/lib/src/brand-page/components/navigation/hamburger/HamburgerNavigation.mixin.d.ts +4 -2
  20. package/lib/src/brand-page/components/navigation/hamburger/HamburgerNavigation.mixin.js +1 -0
  21. package/lib/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.mixin.d.ts +4 -2
  22. package/lib/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.mixin.js +11 -5
  23. package/lib/src/brand-page/components/page/Page.mixin.d.ts +1 -1
  24. package/lib/src/brand-page/components/page/PageComponent.mixin.d.ts +1 -1
  25. package/lib/src/brand-page/components/payment/Payment.mixin.d.ts +3 -3
  26. package/lib/src/brand-page/components/payment/__fixtures__/request-payment.d.ts +13 -13
  27. package/lib/src/brand-page/components/payment/__fixtures__/support-me.d.ts +13 -13
  28. package/lib/src/brand-page/constants/sections/footer-display.constants.js +1 -1
  29. package/lib/src/brand-page/models/index.d.ts +2 -13
  30. package/lib/src/brand-page/models/index.js +3 -0
  31. package/lib/src/brand-page/models/payment.model.d.ts +1 -1
  32. package/lib/src/brand-page/utils/personalisation.util.js +72 -14
  33. package/lib/src/brand-page-maker/components/action-bar/ActionBar.mixin.d.ts +21 -19
  34. package/lib/src/brand-page-maker/components/action-bar/ActionBar.mixin.js +1 -0
  35. package/lib/src/brand-page-maker/components/admin-background-settings/AdminBackgroundSettings.mixin.d.ts +16 -10
  36. package/lib/src/brand-page-maker/components/admin-background-settings/ShapePositionSlider.mixin.d.ts +1 -1
  37. package/lib/src/brand-page-maker/components/admin-logo-settings/AdminLogoSettings.mixin.d.ts +3 -3
  38. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +181 -170
  39. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.js +3 -0
  40. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.stories.js +1 -0
  41. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMakerTemplateSettings.mixin.d.ts +12 -12
  42. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMakerTemplateSettings.stories.js +2 -2
  43. package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-payment.js +0 -7
  44. package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +148 -149
  45. package/lib/src/brand-page-maker/components/brandpage-settings/ReplaceImageSettingsForBrandPageSettings.mixin.d.ts +21 -21
  46. package/lib/src/brand-page-maker/components/brandpage-settings/ReplaceImageSettingsForBrandPageSettings.mixin.js +1 -1
  47. package/lib/src/brand-page-maker/components/color-picker/components/ColorModeSelect.mixin.d.ts +4 -2
  48. package/lib/src/brand-page-maker/components/color-picker/components/ColorModeSelect.mixin.js +1 -0
  49. package/lib/src/brand-page-maker/components/color-picker/components/GradientColorSlider.mixin.d.ts +4 -2
  50. package/lib/src/brand-page-maker/components/color-picker/components/GradientColorSlider.mixin.js +1 -0
  51. package/lib/src/brand-page-maker/components/color-picker/components/GradientColorSliderHandler.mixin.d.ts +5 -2
  52. package/lib/src/brand-page-maker/components/color-picker/components/GradientColorSliderHandler.mixin.js +1 -0
  53. package/lib/src/brand-page-maker/components/color-picker/components/GradientTypeSelector.mixin.d.ts +4 -2
  54. package/lib/src/brand-page-maker/components/color-picker/components/GradientTypeSelector.mixin.js +1 -0
  55. package/lib/src/brand-page-maker/components/device/Device.mixin.d.ts +4 -2
  56. package/lib/src/brand-page-maker/components/device/Device.mixin.js +1 -0
  57. package/lib/src/brand-page-maker/components/navigation/Navigation.mixin.d.ts +4 -2
  58. package/lib/src/brand-page-maker/components/navigation/Navigation.mixin.js +1 -0
  59. package/lib/src/brand-page-maker/components/preview/Preview.mixin.d.ts +3 -3
  60. package/lib/src/brand-page-maker/components/quick-link-bar/QuickLinkBar.mixin.d.ts +11 -11
  61. package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.d.ts +27 -25
  62. package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.js +1 -0
  63. package/lib/src/brand-page-maker/components/seo-settings/UrlSettings.mixin.d.ts +27 -27
  64. package/lib/src/brand-page-maker/components/seo-settings/UrlSettings.mixin.js +1 -1
  65. package/lib/src/brand-page-maker/components/seo-settings/UseExistingDomainModal.mixin.d.ts +17 -12
  66. package/lib/src/brand-page-maker/components/social-share/SocialShare.mixin.d.ts +12 -12
  67. package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.d.ts +30 -32
  68. package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.js +16 -5
  69. package/lib/src/brand-page-maker/components/upgrade-to-premium-button/UpgradeToPremiumButton.mixin.d.ts +11 -11
  70. package/lib/src/brand-page-maker/composables/ai-chat/types.d.ts +3 -0
  71. package/lib/src/brand-page-maker/composables/ai-chat/ui-actions.d.ts +29 -0
  72. package/lib/src/brand-page-maker/composables/ai-chat/ui-actions.js +32 -0
  73. package/lib/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.js +204 -177
  74. package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.d.ts +1 -1
  75. package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.js +6 -6
  76. package/lib/src/brand-page-maker/composables/useEventTracker.d.ts +3 -2
  77. package/lib/src/brand-page-maker/composables/useEventTracker.js +1 -0
  78. package/lib/src/brand-page-maker/constants/config-settings-constant.d.ts +6 -6
  79. package/lib/src/brand-page-maker/constants/config-settings-constant.js +3 -3
  80. package/lib/src/brand-page-maker/convertors/text-image-display-style.convertor.d.ts +1 -1
  81. package/lib/src/brand-page-maker/convertors/text-image-display-style.convertor.js +1 -1
  82. package/lib/src/brand-page-maker/models/content-settings.d.ts +1 -1
  83. package/lib/src/brand-page-maker/models/navigation-style-configs.js +1 -1
  84. package/lib/src/brand-page-maker/routing/brand-page-maker-router.d.ts +1 -2
  85. package/lib/src/brand-page-maker/stores/ai-checkpoint/ai-checkpoint-store.d.ts +366 -378
  86. package/lib/src/brand-page-maker/stores/brandpage-container/brand-page-container-store.d.ts +5 -4
  87. package/lib/src/brand-page-maker/stores/brandpage-container/brand-page-container-store.js +8 -5
  88. package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.d.ts +3 -1
  89. package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.js +7 -3
  90. package/lib/src/brand-page-maker/stores/history/history-store.d.ts +15 -15
  91. package/lib/src/brand-page-maker/stores/ui/ui-store.d.ts +6 -0
  92. package/lib/src/brand-page-maker/stores/ui/ui-store.js +8 -0
  93. package/lib/src/brand-page-maker/utils/content-settings.util.js +1 -1
  94. package/lib/src/brand-page-maker/utils/rich-text-editor.util.d.ts +1 -1
  95. package/lib/src/brand-page-maker/utils/rich-text-editor.util.js +4 -4
  96. package/lib/src/clients/ai-assistant-client.d.ts +7 -0
  97. package/lib/src/clients/brand-page-client.d.ts +16 -15
  98. package/lib/src/clients/design-template-client.d.ts +3 -0
  99. package/lib/src/clients/media-client.d.ts +2 -2
  100. package/lib/src/clients/models.d.ts +2 -0
  101. package/lib/src/composables/useSnapshot.js +18 -18
  102. package/lib/src/css/library.brand-page-brandCrowd.min.css +371 -344
  103. package/lib/src/css/library.brand-page-brandPage.min.css +649 -344
  104. package/lib/src/css/library.brand-page-designCom.min.css +371 -344
  105. package/lib/src/css/library.brand-page-preview.min.css +627 -344
  106. package/lib/src/index.d.ts +4 -0
  107. package/lib/src/index.mjs +107 -104
  108. package/lib/src/{lib-BPI8E2Ui.js → lib-COw-Rz05.js} +37005 -33761
  109. package/lib/src/lib.js +10 -0
  110. package/lib/src/metadata-builder/builders/footer-builder.js +105 -62
  111. package/lib/src/metadata-builder/builders/section-builders/image-gallery-builder.js +68 -57
  112. package/lib/src/metadata-builder/builders/section-builders/images-section-builder.js +93 -58
  113. package/lib/src/metadata-builder/builders/section-builders/shapes-section-builder.js +99 -66
  114. package/lib/src/metadata-builder/builders/section-builders/social-links-builder.js +17 -57
  115. package/lib/src/metadata-builder/builders/section-builders/testimonial-section-builder.js +85 -51
  116. package/lib/src/metadata-builder/builders/section-builders/text-section-builder.js +74 -49
  117. package/lib/src/metadata-builder/builders/section-field-utils.d.ts +7 -0
  118. package/lib/src/metadata-builder/builders/section-field-utils.js +1 -1
  119. package/lib/src/metadata-builder/builders/shape-color-utils.js +1 -1
  120. package/lib/src/metadata-builder/parsers/ai-toolcall-parser.d.ts +7 -16
  121. package/lib/src/metadata-builder/parsers/section-tool-arguments.d.ts +48 -66
  122. package/lib/src/plugins/google-maps-plugin/google-maps-plugin.d.ts +1 -1
  123. package/lib/src/plugins/google-maps-plugin/google-maps-plugin.js +8 -8
  124. package/lib/src/shared/background-settings/components/background-shapes/BackgroundShapeSettings.mixin.d.ts +13 -13
  125. package/lib/src/shared/background-settings/store/background-settings-store.d.ts +3 -3
  126. package/lib/src/shared/color-picker/components/ColorPicker.mixin.d.ts +4 -2
  127. package/lib/src/shared/color-picker/components/ColorPicker.mixin.js +2 -2
  128. package/lib/src/shared/color-picker/components/ColorPickerSwatch.mixin.d.ts +4 -2
  129. package/lib/src/shared/color-picker/components/ColorPickerSwatch.mixin.js +1 -0
  130. package/lib/src/shared/confirm-modal/ConfirmModal.mixin.d.ts +5 -2
  131. package/lib/src/shared/confirm-modal/ConfirmModal.mixin.js +1 -0
  132. package/lib/src/shared/content-settings/components/GenericTextInput.mixin.d.ts +0 -1
  133. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +131 -129
  134. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.js +2 -1
  135. package/lib/src/shared/content-settings/components/content-settings/ReplaceImageSettingsForContent.mixin.d.ts +111 -110
  136. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.d.ts +84 -81
  137. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.js +5 -0
  138. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.d.ts +117 -109
  139. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.js +1 -14
  140. package/lib/src/shared/content-settings/components/email-field/EmailField.mixin.d.ts +0 -1
  141. package/lib/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.d.ts +72 -70
  142. package/lib/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.js +4 -3
  143. package/lib/src/shared/content-settings/components/form-fields-field/FormFieldsField.mixin.d.ts +4 -4
  144. package/lib/src/shared/content-settings/components/icon-library/IconLibrary.mixin.d.ts +3 -1
  145. package/lib/src/shared/content-settings/components/icon-library/IconLibrary.mixin.js +1 -0
  146. package/lib/src/shared/content-settings/components/images-field/ImagesField.mixin.d.ts +2 -2
  147. package/lib/src/shared/content-settings/components/items-field/ItemsField.mixin.d.ts +4 -3
  148. package/lib/src/shared/content-settings/components/items-field/ItemsField.mixin.js +1 -1
  149. package/lib/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.d.ts +40 -40
  150. package/lib/src/shared/content-settings/components/payment-config-field/PaymentConfigOptionField.mixin.d.ts +5 -6
  151. package/lib/src/shared/content-settings/components/shape-field/ShapeField.mixin.d.ts +0 -1
  152. package/lib/src/shared/content-settings/components/slider-field/SliderField.mixin.d.ts +2 -2
  153. package/lib/src/shared/content-settings/components/tel-field/TelField.mixin.d.ts +0 -1
  154. package/lib/src/shared/content-settings/components/testimonial-items-field/TestimonialItemsField.mixin.d.ts +1 -2
  155. package/lib/src/shared/content-settings/components/text-field/TextField.mixin.d.ts +0 -1
  156. package/lib/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.d.ts +1 -2
  157. package/lib/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.js +1 -1
  158. package/lib/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.d.ts +28 -28
  159. package/lib/src/shared/content-settings/components/textarea-field/TextareaField.mixin.d.ts +0 -1
  160. package/lib/src/shared/content-settings/components/toggle-field/ToggleField.mixin.d.ts +2 -2
  161. package/lib/src/shared/content-settings/components/url-field/UrlField.mixin.d.ts +0 -1
  162. package/lib/src/shared/content-settings/components/youtube-video-field/YoutubeVideoField.mixin.d.ts +0 -1
  163. package/lib/src/shared/content-settings/store/content-settings-store.d.ts +39 -39
  164. package/lib/src/shared/content-settings/utils.js +0 -1
  165. package/lib/src/shared/font-family-selector/FontFamilySelector.mixin.d.ts +6 -4
  166. package/lib/src/shared/font-family-selector/FontFamilySelector.mixin.js +1 -0
  167. package/lib/src/shared/image-gallery-style-settings/ImageGalleryStyleSettings.mixin.d.ts +4 -2
  168. package/lib/src/shared/image-gallery-style-settings/ImageGalleryStyleSettings.mixin.js +1 -0
  169. package/lib/src/shared/logo-settings/components/EditLogoSettings.mixin.d.ts +29 -21
  170. package/lib/src/shared/logo-settings/components/EditLogoSettings.mixin.js +1 -1
  171. package/lib/src/shared/logo-settings/components/LogoSettings.mixin.d.ts +50 -51
  172. package/lib/src/shared/logo-settings/components/LogoSettingsHeader.mixin.d.ts +6 -4
  173. package/lib/src/shared/logo-settings/components/LogoSettingsHeader.mixin.js +1 -0
  174. package/lib/src/shared/logo-settings/store/editable-logo-store.js +1 -1
  175. package/lib/src/shared/logo-settings/store/logo-settings-store.d.ts +1 -1
  176. package/lib/src/shared/logo-versions/LogoVersions.mixin.d.ts +13 -5
  177. package/lib/src/shared/logo-versions/LogoVersions.mixin.js +1 -0
  178. package/lib/src/shared/models.d.ts +2 -0
  179. package/lib/src/shared/my-designs/MyDesigns.mixin.d.ts +14 -6
  180. package/lib/src/shared/my-designs/MyDesigns.mixin.js +1 -0
  181. package/lib/src/shared/my-uploads/MyMedia.mixin.d.ts +14 -5
  182. package/lib/src/shared/my-uploads/MyMedia.mixin.js +1 -0
  183. package/lib/src/shared/my-uploads/MyUploads.mixin.d.ts +14 -5
  184. package/lib/src/shared/my-uploads/MyUploads.mixin.js +1 -0
  185. package/lib/src/shared/navigation-style-settings/components/navigation-style-settings/NavigationStyleSettings.mixin.d.ts +5 -3
  186. package/lib/src/shared/navigation-style-settings/components/navigation-style-settings/NavigationStyleSettings.mixin.js +1 -0
  187. package/lib/src/shared/navigation-style-settings/store/index.d.ts +2 -2
  188. package/lib/src/shared/page-navigation/store/page-navigation-store.d.ts +2 -2
  189. package/lib/src/shared/page-settings/components/new-page-modal/NewPageModal.mixin.d.ts +27 -28
  190. package/lib/src/shared/page-settings/components/new-page-modal/NewPageModal.mixin.js +0 -2
  191. package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +188 -179
  192. package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +181 -177
  193. package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.js +1 -1
  194. package/lib/src/shared/page-settings/store/page-settings-store.d.ts +9 -9
  195. package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +39 -39
  196. package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.js +0 -1
  197. package/lib/src/shared/side-bar/components/SideBar.mixin.d.ts +18 -18
  198. package/lib/src/shared/side-bar/components/SideBarTabButton.mixin.d.ts +6 -6
  199. package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +66 -60
  200. package/lib/src/shared/style-settings/store/style-settings-store.d.ts +1 -1
  201. package/lib/src/shared/style-settings/store/style-settings-store.js +1 -1
  202. package/lib/src/shared/template-settings/components/TemplatesSettings.mixin.d.ts +20 -450
  203. package/lib/src/shared/template-settings/components/TemplatesSettings.mixin.js +2 -2
  204. package/lib/src/shared/template-settings/models.d.ts +1 -0
  205. package/lib/src/shared/template-settings/store/template-settings-store.d.ts +4 -0
  206. package/lib/src/shared/template-settings/store/template-settings-store.js +79 -11
  207. package/lib/src/shared/unsplash-library/UnsplashLibrary.mixin.d.ts +9 -4
  208. package/lib/src/utils/build-asset-manifest.d.ts +4 -0
  209. package/lib/src/utils/build-asset-manifest.js +8 -0
  210. package/lib/src/utils/minify-brand-page-metadata.d.ts +0 -2
  211. package/lib/src/utils/minify-brand-page-metadata.js +2 -17
  212. package/package.json +60 -56
  213. package/src/brand-page/components/about-section/AboutSection.vue.test.ts +7 -5
  214. package/src/brand-page/components/banner-section/BannerSection.mixin.ts +210 -0
  215. package/src/brand-page/components/banner-section/BannerSection.vue +5 -1
  216. package/src/brand-page/components/brand-page-footer/BrandPageFooter.vue +1 -1
  217. package/src/brand-page/components/image/Image.mixin.ts +1 -1
  218. package/src/brand-page/components/image/Image.test.ts +1 -1
  219. package/src/brand-page/components/image-gallery/masonry/MasonryGallery.mixin.ts +1 -2
  220. package/src/brand-page/components/images-section/ImagesSection.vue +0 -1
  221. package/src/brand-page/components/logo/LogoRender.vue +188 -188
  222. package/src/brand-page/components/navigation/hamburger/HamburgerNavigation.mixin.ts +1 -0
  223. package/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.mixin.ts +25 -8
  224. package/src/brand-page/components/page-footer/PageFooter.vue +1 -0
  225. package/src/brand-page/components/page-header/HeaderLayout.vue +12 -6
  226. package/src/brand-page/components/page-header/PageHeader.vue +1 -0
  227. package/src/brand-page/components/shapes-section/ShapesSection.vue +1 -1
  228. package/src/brand-page/components/shop/CartModal.vue +1 -3
  229. package/src/brand-page/components/shop/FeaturedDisplay.vue +2 -2
  230. package/src/brand-page/components/shop/PaymentModal.vue +1 -5
  231. package/src/brand-page/components/shop/ProductDetailModal.vue +1 -1
  232. package/src/brand-page/components/shop/Shop.vue +1 -5
  233. package/src/brand-page/components/shop/TextDisplay.vue +1 -1
  234. package/src/brand-page/components/shop/ThumbnailDisplay.vue +2 -2
  235. package/src/brand-page/components/testimonial-section/TestimonialSection.vue +3 -3
  236. package/src/brand-page/components/text-wrapper/TextWrapper.vue +3 -1
  237. package/src/brand-page/constants/sections/footer-display.constants.ts +1 -1
  238. package/src/brand-page/models/index.ts +4 -12
  239. package/src/brand-page/models/payment.model.ts +2 -1
  240. package/src/brand-page/models/shop.model.ts +0 -2
  241. package/src/brand-page/models/user-personalisation.model.ts +1 -2
  242. package/src/brand-page/utils/__snapshots__/migration.util.test.ts.snap +3 -0
  243. package/src/brand-page/utils/__snapshots__/migration2.util.test.ts.snap +1 -0
  244. package/src/brand-page/utils/__snapshots__/model.util.test.ts.snap +2 -0
  245. package/src/brand-page/utils/migration/migration-01_1.ts +1 -1
  246. package/src/brand-page/utils/migration/migration-02.ts +0 -1
  247. package/src/brand-page/utils/migration/migration-03.ts +0 -1
  248. package/src/brand-page/utils/migration/migration-04.ts +0 -1
  249. package/src/brand-page/utils/migration/migration-05.ts +1 -5
  250. package/src/brand-page/utils/migration/migration-05_2.ts +1 -1
  251. package/src/brand-page/utils/migration/migration-08.test.ts +1 -1
  252. package/src/brand-page/utils/personalisation.util.test.ts +35 -0
  253. package/src/brand-page/utils/personalisation.util.ts +119 -23
  254. package/src/brand-page/view-models.ts +38 -56
  255. package/src/brand-page-maker/assessors/banner-section-description-visibility.assessor.ts +6 -6
  256. package/src/brand-page-maker/assessors/color-replacement-icon-visibility.assessor.ts +2 -2
  257. package/src/brand-page-maker/assessors/color-replacement-profile-visibility.assessor.ts +2 -2
  258. package/src/brand-page-maker/assessors/color-replacement-visibility.assessor.ts +2 -2
  259. package/src/brand-page-maker/assessors/contact-form-visibility.assessor.ts +14 -14
  260. package/src/brand-page-maker/components/action-bar/ActionBar.mixin.ts +1 -0
  261. package/src/brand-page-maker/components/ai-text-edit/AiActionButtons.vue +27 -12
  262. package/src/brand-page-maker/components/ai-text-edit/AiChatbox.vue +3 -2
  263. package/src/brand-page-maker/components/ai-text-edit/TextBubble.vue +8 -7
  264. package/src/brand-page-maker/components/ai-website-builder/AiWebsiteBuilder.vue +21 -1
  265. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.ts +5 -1
  266. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.stories.ts +1 -0
  267. package/src/brand-page-maker/components/brand-page-maker/BrandPageMakerTemplateSettings.stories.ts +2 -5
  268. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.ts +0 -5
  269. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-payment.ts +0 -8
  270. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-site-template.examples.ts +0 -2
  271. package/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.vue +1 -0
  272. package/src/brand-page-maker/components/brandpage-settings/ReplaceImageSettingsForBrandPageSettings.mixin.ts +1 -1
  273. package/src/brand-page-maker/components/color-palette/BpColorPalette.vue +1 -2
  274. package/src/brand-page-maker/components/color-picker/components/ColorModeSelect.mixin.ts +1 -0
  275. package/src/brand-page-maker/components/color-picker/components/GradientColorSlider.mixin.ts +1 -0
  276. package/src/brand-page-maker/components/color-picker/components/GradientColorSliderHandler.mixin.ts +1 -0
  277. package/src/brand-page-maker/components/color-picker/components/GradientTypeSelector.mixin.ts +1 -0
  278. package/src/brand-page-maker/components/device/Device.mixin.ts +1 -0
  279. package/src/brand-page-maker/components/navigation/Navigation.mixin.ts +1 -0
  280. package/src/brand-page-maker/components/rich-text-editor/RichTextEditor.vue +3 -1
  281. package/src/brand-page-maker/components/sensitive-content/SensitiveContent.vue +1 -4
  282. package/src/brand-page-maker/components/seo-settings/DeleteDomainModal.vue +1 -1
  283. package/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.ts +1 -0
  284. package/src/brand-page-maker/components/seo-settings/SeoPageSettings.vue +1 -1
  285. package/src/brand-page-maker/components/seo-settings/UrlSettings.mixin.ts +0 -1
  286. package/src/brand-page-maker/components/seo-settings/UrlSettings.vue +0 -1
  287. package/src/brand-page-maker/components/seo-settings/UseExistingDomainModal.vue +1 -5
  288. package/src/brand-page-maker/components/shop/AddOrEditProductContainer.vue +1 -1
  289. package/src/brand-page-maker/components/shop/ReplaceImageSettingsForShop.vue +1 -1
  290. package/src/brand-page-maker/components/social-share/SocialShare.vue +1 -1
  291. package/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.ts +22 -8
  292. package/src/brand-page-maker/components/template-preview/TemplatePreview.vue +5 -10
  293. package/src/brand-page-maker/components/template-preview/TemplatePreviewAiBadge.vue +12 -0
  294. package/src/brand-page-maker/components/video-play/VideoPlayButton.vue +1 -1
  295. package/src/brand-page-maker/composables/ai-chat/types.ts +6 -0
  296. package/src/brand-page-maker/composables/ai-chat/ui-actions.test.ts +80 -0
  297. package/src/brand-page-maker/composables/ai-chat/ui-actions.ts +58 -0
  298. package/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.ts +308 -262
  299. package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.ts +6 -6
  300. package/src/brand-page-maker/composables/useEventTracker.ts +1 -0
  301. package/src/brand-page-maker/constants/config-settings-constant.ts +5 -5
  302. package/src/brand-page-maker/convertors/text-image-display-style.convertor.ts +1 -1
  303. package/src/brand-page-maker/models/button-styles-config.ts +4 -2
  304. package/src/brand-page-maker/models/content-settings-configs.ts +4 -2
  305. package/src/brand-page-maker/models/navigation-style-configs.ts +5 -6
  306. package/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store.ts +0 -1
  307. package/src/brand-page-maker/stores/brandpage-container/brand-page-container-store.ts +8 -5
  308. package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.test.ts +1 -3
  309. package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.ts +12 -4
  310. package/src/brand-page-maker/stores/ui/ui-store.ts +16 -0
  311. package/src/brand-page-maker/utils/content-settings.util.ts +1 -1
  312. package/src/brand-page-maker/utils/rich-text-editor.util.ts +4 -4
  313. package/src/clients/ai-assistant-client.ts +7 -0
  314. package/src/clients/design-template-client.ts +3 -0
  315. package/src/clients/models.ts +2 -0
  316. package/src/composables/useSnapshot.ts +19 -22
  317. package/src/lib.ts +12 -0
  318. package/src/metadata-builder/builders/footer-builder.test.ts +130 -229
  319. package/src/metadata-builder/builders/footer-builder.ts +155 -90
  320. package/src/metadata-builder/builders/section-builders/image-gallery-builder.ts +88 -62
  321. package/src/metadata-builder/builders/section-builders/images-section-builder.ts +129 -66
  322. package/src/metadata-builder/builders/section-builders/shapes-section-builder.ts +160 -105
  323. package/src/metadata-builder/builders/section-builders/social-links-builder.ts +20 -65
  324. package/src/metadata-builder/builders/section-builders/testimonial-section-builder.ts +146 -83
  325. package/src/metadata-builder/builders/section-builders/text-section-builder.ts +122 -70
  326. package/src/metadata-builder/builders/section-field-utils.ts +1 -1
  327. package/src/metadata-builder/builders/shape-color-utils.ts +2 -2
  328. package/src/metadata-builder/parsers/ai-toolcall-parser.ts +7 -16
  329. package/src/metadata-builder/parsers/section-tool-arguments.ts +48 -66
  330. package/src/plugins/google-maps-plugin/google-maps-plugin.ts +8 -8
  331. package/src/shared/background-settings/components/BackgroundSettings.vue +1 -1
  332. package/src/shared/background-settings/components/background-color/BackgroundColorSettings.vue +1 -1
  333. package/src/shared/color-picker/components/ColorPicker.mixin.ts +2 -7
  334. package/src/shared/color-picker/components/ColorPickerSwatch.mixin.ts +1 -0
  335. package/src/shared/common/NumberInput.vue +1 -0
  336. package/src/shared/common/SideBarSettingsHeader.vue +2 -2
  337. package/src/shared/confirm-modal/ConfirmModal.mixin.ts +1 -0
  338. package/src/shared/content-settings/components/booking-url-field/BookingUrlField.vue +1 -0
  339. package/src/shared/content-settings/components/button-configuration-field/ButtonConfigurationField.vue +1 -0
  340. package/src/shared/content-settings/components/color-field/ColorField.vue +3 -10
  341. package/src/shared/content-settings/components/content-settings/ContentSettings.mixin.ts +1 -1
  342. package/src/shared/content-settings/components/content-settings/ContentSettingsLockedButton.vue +1 -0
  343. package/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.ts +5 -0
  344. package/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.ts +1 -14
  345. package/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.ts +4 -6
  346. package/src/shared/content-settings/components/icon-library/IconLibrary.mixin.ts +1 -0
  347. package/src/shared/content-settings/components/items-field/ItemsField.mixin.ts +1 -1
  348. package/src/shared/content-settings/components/logo-selection-field/LogoSelectionField.vue +1 -1
  349. package/src/shared/content-settings/components/logo-size-field/LogoSizeSliderField.vue +1 -1
  350. package/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.vue +1 -1
  351. package/src/shared/content-settings/components/personalisation-role-field/PersonalisationRoleField.vue +4 -4
  352. package/src/shared/content-settings/components/text-image-field/TextImageField.vue +2 -8
  353. package/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.ts +1 -1
  354. package/src/shared/content-settings/models.ts +3 -2
  355. package/src/shared/content-settings/utils.ts +0 -1
  356. package/src/shared/dropzone-image-uploader/components/DropzoneImageUploader.vue +1 -0
  357. package/src/shared/ecommerce-settings/store/cart-store.test.ts +1 -1
  358. package/src/shared/font-family-selector/FontFamilySelector.mixin.ts +1 -0
  359. package/src/shared/image-gallery-style-settings/ImageGalleryStyleSettings.mixin.ts +1 -0
  360. package/src/shared/logo-settings/components/EditLogoSettings.mixin.ts +1 -1
  361. package/src/shared/logo-settings/components/LogoSettings.mixin.ts +0 -1
  362. package/src/shared/logo-settings/components/LogoSettingsHeader.mixin.ts +1 -0
  363. package/src/shared/logo-settings/components/LogoStyleSettingsWithState.vue +2 -2
  364. package/src/shared/logo-settings/components/LogoTemplateSearch.vue +1 -1
  365. package/src/shared/logo-settings/store/editable-logo-store.ts +1 -1
  366. package/src/shared/logo-settings/store/logo-settings-store.test.ts +4 -4
  367. package/src/shared/logo-versions/LogoVersions.mixin.ts +1 -0
  368. package/src/shared/models.ts +6 -0
  369. package/src/shared/my-designs/MyDesigns.mixin.ts +1 -0
  370. package/src/shared/my-uploads/MyMedia.mixin.ts +1 -0
  371. package/src/shared/my-uploads/MyMediaSelectionItem.vue +2 -1
  372. package/src/shared/my-uploads/MyUploads.mixin.ts +1 -0
  373. package/src/shared/my-uploads/models.ts +1 -2
  374. package/src/shared/navigation-style-settings/components/navigation-style-settings/NavigationStyleSettings.mixin.ts +1 -0
  375. package/src/shared/navigation-style-settings/components/navigation-style-settings/NavigationStyleSettings.vue +1 -1
  376. package/src/shared/page-settings/components/new-page-modal/NewPageModal.mixin.ts +0 -3
  377. package/src/shared/page-settings/components/page-settings/NestedDraggable.vue +1 -1
  378. package/src/shared/page-settings/components/page-settings/PageSettings.vue +1 -2
  379. package/src/shared/page-settings/components/page-settings-section-styles/HeaderDisplayStyle.vue +1 -1
  380. package/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.ts +1 -1
  381. package/src/shared/page-settings/store/page-settings-store.test.ts +4 -8
  382. package/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.ts +0 -1
  383. package/src/shared/shape-library/ShapeLibrary.vue +2 -2
  384. package/src/shared/style-settings/store/style-settings-store.ts +1 -1
  385. package/src/shared/template-settings/components/TemplatesSettings.mixin.ts +2 -2
  386. package/src/shared/template-settings/models.ts +1 -0
  387. package/src/shared/template-settings/store/template-settings-store.ts +105 -18
  388. package/src/shared/unsplash-library/UnsplashLibrary.vue +2 -6
  389. package/src/shared/video-library/VideoLibrary.vue +1 -1
  390. package/src/utils/build-asset-manifest.ts +12 -0
  391. package/src/utils/minify-brand-page-metadata.ts +7 -27
  392. package/lib/src/metadata-builder/builders/item-id-utils.d.ts +0 -54
  393. package/lib/src/metadata-builder/builders/item-id-utils.js +0 -96
  394. package/src/metadata-builder/builders/item-id-utils.test.ts +0 -184
  395. package/src/metadata-builder/builders/item-id-utils.ts +0 -117
@@ -14,10 +14,6 @@ import { FooterBuilder } from './footer-builder';
14
14
  * The fix routes copyright style writes through `applyDetachedStyleOverride`,
15
15
  * which resolves the preset in and clears `textStyleType` so the per-element
16
16
  * override sticks.
17
- *
18
- * BP-5603: social link mutations converted from index-based to id-based
19
- * (item_id / move_before_item_id / _remove_social_link_ids), mirroring the
20
- * section-level move_before_content_id contract one level deeper.
21
17
  */
22
18
 
23
19
  const textStyleOptions = {
@@ -46,37 +42,6 @@ const makeModel = (copyrightStyle: Record<string, unknown>): BrandPageModel =>
46
42
  pageFooterMobile: { copyrightStyle: { ...copyrightStyle } },
47
43
  }) as unknown as BrandPageModel;
48
44
 
49
- const makeModelWithLinks = (
50
- links: { id?: string; imageUrl: string; url: string }[],
51
- ): BrandPageModel =>
52
- ({
53
- styles: { textStyles: { textStyleOptions } },
54
- pageFooterDesktop: {
55
- copyrightStyle: {},
56
- socialLinks: links.map((l) => ({
57
- id: l.id,
58
- imageUrl: l.imageUrl,
59
- url: l.url,
60
- imageTitle: '',
61
- width: 0,
62
- height: 0,
63
- imageLink: '',
64
- })),
65
- },
66
- pageFooterMobile: {
67
- copyrightStyle: {},
68
- socialLinks: links.map((l) => ({
69
- id: l.id,
70
- imageUrl: l.imageUrl,
71
- url: l.url,
72
- imageTitle: '',
73
- width: 0,
74
- height: 0,
75
- imageLink: '',
76
- })),
77
- },
78
- }) as unknown as BrandPageModel;
79
-
80
45
  const run = (args: UpdateFooterArguments, model: BrandPageModel) =>
81
46
  new FooterBuilder({
82
47
  id: 'f1',
@@ -84,10 +49,6 @@ const run = (args: UpdateFooterArguments, model: BrandPageModel) =>
84
49
  payload: args,
85
50
  }).buildAsync(model);
86
51
 
87
- // ---------------------------------------------------------------------------
88
- // Copyright font (BP-5420)
89
- // ---------------------------------------------------------------------------
90
-
91
52
  describe('FooterBuilder — copyright font vs global style', () => {
92
53
  it('detaches from the global preset: applies the font, clears textStyleType, retains preset values', async () => {
93
54
  const model = makeModel({
@@ -96,7 +57,7 @@ describe('FooterBuilder — copyright font vs global style', () => {
96
57
  });
97
58
 
98
59
  const { model: out } = await run(
99
- { copyright_text_font_family: 'Anton' },
60
+ { copyright_text_style: { fontFamily: 'Anton' } },
100
61
  model,
101
62
  );
102
63
 
@@ -112,263 +73,203 @@ describe('FooterBuilder — copyright font vs global style', () => {
112
73
  expect(style.color).toBe('#2d0b3f');
113
74
  expect(style.textAlign).toBe('center');
114
75
  });
115
- });
116
-
117
- // ---------------------------------------------------------------------------
118
- // Social links — id-based mutations (BP-5603)
119
- // ---------------------------------------------------------------------------
120
-
121
- describe('FooterBuilder — social links id-based mutations', () => {
122
- it('backfills ids on legacy links that have none', async () => {
123
- // Links without ids (legacy persisted data)
124
- const model = makeModelWithLinks([
125
- { imageUrl: 'facebook', url: 'https://fb.com' },
126
- { imageUrl: 'instagram', url: 'https://ig.com' },
127
- ]);
128
-
129
- const { model: out } = await run({}, model);
130
-
131
- const links = out.pageFooterDesktop!.socialLinks;
132
-
133
- expect(links[0].id).toBeTruthy();
134
- expect(links[1].id).toBeTruthy();
135
- expect(links[0].id).not.toBe(links[1].id);
136
- });
137
76
 
138
- it('updates an existing link in place by item_id', async () => {
139
- const model = makeModelWithLinks([
140
- { id: 'link-1', imageUrl: 'facebook', url: 'https://fb.com' },
141
- { id: 'link-2', imageUrl: 'instagram', url: 'https://ig.com' },
142
- ]);
77
+ it('applies copyright font size + weight via the style object, detaches, preserves the text', async () => {
78
+ const model = makeModel({
79
+ textStyleType: 'paragraphs',
80
+ textAlign: 'center',
81
+ fontWeight: 'bold',
82
+ });
143
83
 
144
84
  const { model: out } = await run(
145
- {
146
- social_links: [
147
- { item_id: 'link-1', url: 'https://facebook.com/mybrand' },
148
- ],
149
- },
85
+ { copyright_text_style: { fontSize: '0.875em', fontWeight: 'normal' } },
150
86
  model,
151
87
  );
152
88
 
153
- const links = out.pageFooterDesktop!.socialLinks;
154
-
155
- expect(links).toHaveLength(2);
156
- expect(links[0].url).toBe('https://facebook.com/mybrand');
157
- expect(links[0].id).toBe('link-1');
158
- // untouched link unchanged
159
- expect(links[1].id).toBe('link-2');
160
- expect(links[1].url).toBe('https://ig.com');
161
- });
162
-
163
- it('updates social_link_icon on an existing link', async () => {
164
- const model = makeModelWithLinks([
165
- { id: 'link-1', imageUrl: 'facebook', url: 'https://fb.com' },
166
- ]);
89
+ const desktop = out.pageFooterDesktop!;
90
+ const style = desktop.copyrightStyle as Record<string, unknown>;
167
91
 
168
- const { model: out } = await run(
169
- {
170
- social_links: [{ item_id: 'link-1', social_link_icon: 'facebook-v2' }],
171
- },
172
- model,
173
- );
174
-
175
- expect(out.pageFooterDesktop!.socialLinks[0].imageUrl).toBe('facebook-v2');
92
+ expect(style.fontSize).toBe('0.875em');
93
+ expect(style.fontWeight).toBe('normal');
94
+ expect(style.textStyleType).toBeUndefined();
95
+ // preset values resolved in, not lost
96
+ expect(style.fontFamily).toBe('Inter');
97
+ expect(style.textAlign).toBe('center');
98
+ // style-only change must NOT touch the copyright text itself
99
+ expect(desktop.copyrightText).toBeUndefined();
176
100
  });
177
101
 
178
- it('skips unknown item_id silently', async () => {
179
- const model = makeModelWithLinks([
180
- { id: 'link-1', imageUrl: 'facebook', url: 'https://fb.com' },
181
- ]);
102
+ it('applies copyright style to both viewports', async () => {
103
+ const model = makeModel({ textStyleType: 'paragraphs' });
182
104
 
183
105
  const { model: out } = await run(
184
- {
185
- social_links: [{ item_id: 'no-such-id', url: 'https://nowhere.com' }],
186
- },
106
+ { copyright_text_style: { fontSize: '0.75em', fontWeight: 'normal' } },
187
107
  model,
188
108
  );
189
109
 
190
- const links = out.pageFooterDesktop!.socialLinks;
110
+ for (const vp of [out.pageFooterDesktop!, out.pageFooterMobile!]) {
111
+ const style = vp.copyrightStyle as Record<string, unknown>;
191
112
 
192
- expect(links).toHaveLength(1);
193
- expect(links[0].url).toBe('https://fb.com');
113
+ expect(style.fontSize).toBe('0.75em');
114
+ expect(style.fontWeight).toBe('normal');
115
+ expect(style.textStyleType).toBeUndefined();
116
+ }
194
117
  });
195
118
 
196
- it('inserts a new link (no item_id) appended by default', async () => {
197
- const model = makeModelWithLinks([
198
- { id: 'link-1', imageUrl: 'facebook', url: 'https://fb.com' },
199
- ]);
119
+ it('applies copyright colour and normalises letterSpacing (int→em) via the style object', async () => {
120
+ const model = makeModel({ textStyleType: 'paragraphs' });
200
121
 
201
122
  const { model: out } = await run(
202
- {
203
- social_links: [
204
- { social_link_icon: 'instagram', url: 'https://ig.com' },
205
- ],
206
- },
123
+ { copyright_text_style: { color: '#f5f5f5', letterSpacing: 50 } },
207
124
  model,
208
125
  );
209
126
 
210
- const links = out.pageFooterDesktop!.socialLinks;
127
+ const style = out.pageFooterDesktop!.copyrightStyle as Record<
128
+ string,
129
+ unknown
130
+ >;
211
131
 
212
- expect(links).toHaveLength(2);
213
- expect(links[1].imageUrl).toBe('instagram');
214
- expect(links[1].id).toBeTruthy();
132
+ expect(style.color).toBe('#f5f5f5');
133
+ // letterSpacing int 0–100 is normalised to an em string (50 → '0.5em'),
134
+ // exactly as section *_style values are.
135
+ expect(style.letterSpacing).toBe('0.5em');
136
+ expect(style.textStyleType).toBeUndefined();
215
137
  });
138
+ });
216
139
 
217
- it('inserts a new link before an anchor via move_before_item_id', async () => {
218
- const model = makeModelWithLinks([
219
- { id: 'link-1', imageUrl: 'facebook', url: 'https://fb.com' },
220
- { id: 'link-2', imageUrl: 'instagram', url: 'https://ig.com' },
221
- ]);
140
+ type Link = { imageUrl: string; url: string };
222
141
 
223
- const { model: out } = await run(
224
- {
225
- social_links: [
226
- {
227
- social_link_icon: 'x',
228
- url: 'https://x.com',
229
- move_before_item_id: 'link-2',
230
- },
231
- ],
232
- },
233
- model,
234
- );
142
+ const link = (imageUrl: string): Link => ({
143
+ imageUrl,
144
+ url: `https://${imageUrl}.com`,
145
+ });
235
146
 
236
- const links = out.pageFooterDesktop!.socialLinks;
147
+ /**
148
+ * Footers migrated from the legacy single `footerStyles` model
149
+ * (migration-01) split into desktop + mobile via a shallow spread, leaving
150
+ * both viewports' `socialLinks` pointing at ONE shared array. `cloneDeep`
151
+ * preserves that shared reference. This factory reproduces that shape.
152
+ */
153
+ const makeSharedSocialModel = (links: Link[]): BrandPageModel => {
154
+ const shared = links.map((l) => ({ ...l }));
237
155
 
238
- expect(links).toHaveLength(3);
239
- expect(links[0].id).toBe('link-1');
240
- expect(links[1].imageUrl).toBe('x');
241
- expect(links[2].id).toBe('link-2');
242
- });
156
+ return {
157
+ styles: { textStyles: { textStyleOptions } },
158
+ pageFooterDesktop: { socialLinks: shared },
159
+ pageFooterMobile: { socialLinks: shared },
160
+ } as unknown as BrandPageModel;
161
+ };
162
+
163
+ const makeIndependentSocialModel = (links: Link[]): BrandPageModel =>
164
+ ({
165
+ styles: { textStyles: { textStyleOptions } },
166
+ pageFooterDesktop: { socialLinks: links.map((l) => ({ ...l })) },
167
+ pageFooterMobile: { socialLinks: links.map((l) => ({ ...l })) },
168
+ }) as unknown as BrandPageModel;
243
169
 
244
- it('inserts a new link at end via move_before_item_id "__end__"', async () => {
245
- const model = makeModelWithLinks([
246
- { id: 'link-1', imageUrl: 'facebook', url: 'https://fb.com' },
247
- { id: 'link-2', imageUrl: 'instagram', url: 'https://ig.com' },
170
+ const socialIcons = (footer: { socialLinks?: Link[] } | undefined) =>
171
+ (footer?.socialLinks ?? []).map((l) => l.imageUrl);
172
+
173
+ describe('FooterBuilder — social link removal (shared-array regression)', () => {
174
+ // Reproduces the bug: a single requested removal index dropped TWO links
175
+ // because both viewports shared one array and the builder spliced it twice.
176
+ it('removes exactly one link per requested index even when viewports share the array', async () => {
177
+ const model = makeSharedSocialModel([
178
+ link('facebook'),
179
+ link('instagram'),
180
+ link('x'),
181
+ link('youtube'),
248
182
  ]);
249
183
 
250
184
  const { model: out } = await run(
251
- {
252
- social_links: [
253
- {
254
- social_link_icon: 'x',
255
- url: 'https://x.com',
256
- move_before_item_id: '__end__',
257
- },
258
- ],
259
- },
185
+ { _remove_social_link_indices: [2] },
260
186
  model,
261
187
  );
262
188
 
263
- const links = out.pageFooterDesktop!.socialLinks;
264
-
265
- expect(links).toHaveLength(3);
266
- expect(links[2].imageUrl).toBe('x');
189
+ expect(socialIcons(out.pageFooterDesktop)).toEqual([
190
+ 'facebook',
191
+ 'instagram',
192
+ 'youtube',
193
+ ]);
194
+ expect(socialIcons(out.pageFooterMobile)).toEqual([
195
+ 'facebook',
196
+ 'instagram',
197
+ 'youtube',
198
+ ]);
267
199
  });
268
200
 
269
- it('moves an existing link before an anchor via move_before_item_id', async () => {
270
- const model = makeModelWithLinks([
271
- { id: 'link-1', imageUrl: 'facebook', url: 'https://fb.com' },
272
- { id: 'link-2', imageUrl: 'instagram', url: 'https://ig.com' },
273
- { id: 'link-3', imageUrl: 'x', url: 'https://x.com' },
201
+ it('un-shares the viewport arrays so later in-place edits cannot cross-corrupt', async () => {
202
+ const model = makeSharedSocialModel([
203
+ link('facebook'),
204
+ link('instagram'),
205
+ link('x'),
274
206
  ]);
275
207
 
276
208
  const { model: out } = await run(
277
- {
278
- social_links: [{ item_id: 'link-3', move_before_item_id: 'link-1' }],
279
- },
209
+ { _remove_social_link_indices: [0] },
280
210
  model,
281
211
  );
282
212
 
283
- const links = out.pageFooterDesktop!.socialLinks;
284
-
285
- expect(links.map((l) => l.id)).toEqual(['link-3', 'link-1', 'link-2']);
213
+ expect(out.pageFooterDesktop!.socialLinks).not.toBe(
214
+ out.pageFooterMobile!.socialLinks,
215
+ );
286
216
  });
287
217
 
288
- it('removes links by id', async () => {
289
- const model = makeModelWithLinks([
290
- { id: 'link-1', imageUrl: 'facebook', url: 'https://fb.com' },
291
- { id: 'link-2', imageUrl: 'instagram', url: 'https://ig.com' },
292
- { id: 'link-3', imageUrl: 'x', url: 'https://x.com' },
218
+ it('handles multiple removal indices on a shared array (descending splice)', async () => {
219
+ const model = makeSharedSocialModel([
220
+ link('facebook'),
221
+ link('instagram'),
222
+ link('x'),
223
+ link('youtube'),
293
224
  ]);
294
225
 
295
226
  const { model: out } = await run(
296
- { _remove_social_link_ids: ['link-1', 'link-3'] },
227
+ { _remove_social_link_indices: [0, 2] },
297
228
  model,
298
229
  );
299
230
 
300
- const links = out.pageFooterDesktop!.socialLinks;
301
-
302
- expect(links).toHaveLength(1);
303
- expect(links[0].id).toBe('link-2');
231
+ expect(socialIcons(out.pageFooterDesktop)).toEqual([
232
+ 'instagram',
233
+ 'youtube',
234
+ ]);
235
+ expect(socialIcons(out.pageFooterMobile)).toEqual(['instagram', 'youtube']);
304
236
  });
305
237
 
306
- it('_replace_social_links rebuilds the entire list and assigns fresh ids', async () => {
307
- const model = makeModelWithLinks([
308
- { id: 'old-1', imageUrl: 'facebook', url: 'https://fb.com' },
238
+ it('removes one link per index for independent viewport arrays (no regression)', async () => {
239
+ const model = makeIndependentSocialModel([
240
+ link('facebook'),
241
+ link('instagram'),
242
+ link('x'),
309
243
  ]);
310
244
 
311
245
  const { model: out } = await run(
312
- {
313
- _replace_social_links: true,
314
- social_links: [
315
- { social_link_icon: 'instagram', url: 'https://ig.com' },
316
- { social_link_icon: 'x', url: 'https://x.com' },
317
- ],
318
- },
246
+ { _remove_social_link_indices: [1] },
319
247
  model,
320
248
  );
321
249
 
322
- const links = out.pageFooterDesktop!.socialLinks;
323
-
324
- expect(links).toHaveLength(2);
325
- expect(links[0].imageUrl).toBe('instagram');
326
- expect(links[1].imageUrl).toBe('x');
327
- // fresh ids assigned, not the old one
328
- expect(links[0].id).toBeTruthy();
329
- expect(links[0].id).not.toBe('old-1');
330
- });
331
-
332
- it('_replace_social_links with empty social_links clears all', async () => {
333
- const model = makeModelWithLinks([
334
- { id: 'link-1', imageUrl: 'facebook', url: 'https://fb.com' },
335
- ]);
336
-
337
- const { model: out } = await run({ _replace_social_links: true }, model);
338
-
339
- expect(out.pageFooterDesktop!.socialLinks).toHaveLength(0);
250
+ expect(socialIcons(out.pageFooterDesktop)).toEqual(['facebook', 'x']);
251
+ expect(socialIcons(out.pageFooterMobile)).toEqual(['facebook', 'x']);
340
252
  });
341
253
 
342
- it('normalises mailto: and tel: prefixes on new links', async () => {
343
- const model = makeModelWithLinks([]);
254
+ it('inserts exactly one link on a shared array (symmetric add guard)', async () => {
255
+ const model = makeSharedSocialModel([link('facebook'), link('instagram')]);
344
256
 
345
257
  const { model: out } = await run(
346
258
  {
347
- social_links: [
348
- { social_link_icon: 'email', url: 'mailto:me@example.com' },
349
- { social_link_icon: 'phone', url: 'tel:+1234567890' },
350
- ],
259
+ social_links: [{ insert_at: 1, social_link_icon: 'x', url: 'x.com' }],
351
260
  },
352
261
  model,
353
262
  );
354
263
 
355
- const links = out.pageFooterDesktop!.socialLinks;
356
-
357
- expect(links[0].url).toBe('me@example.com');
358
- expect(links[1].url).toBe('+1234567890');
359
- });
360
-
361
- it('applies mutations to both desktop and mobile footers', async () => {
362
- const model = makeModelWithLinks([
363
- { id: 'link-1', imageUrl: 'facebook', url: 'https://fb.com' },
264
+ expect(socialIcons(out.pageFooterDesktop)).toEqual([
265
+ 'facebook',
266
+ 'x',
267
+ 'instagram',
268
+ ]);
269
+ expect(socialIcons(out.pageFooterMobile)).toEqual([
270
+ 'facebook',
271
+ 'x',
272
+ 'instagram',
364
273
  ]);
365
-
366
- const { model: out } = await run(
367
- { _remove_social_link_ids: ['link-1'] },
368
- model,
369
- );
370
-
371
- expect(out.pageFooterDesktop!.socialLinks).toHaveLength(0);
372
- expect(out.pageFooterMobile!.socialLinks).toHaveLength(0);
373
274
  });
374
275
  });