@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
@@ -25,12 +25,6 @@ import {
25
25
  validateTestimonialSection,
26
26
  TESTIMONIAL_ITEM_CAP,
27
27
  } from '../section-rules/testimonial-section.rules';
28
- import {
29
- ensureItemIds,
30
- generateItemId,
31
- removeItemsByIds,
32
- repositionItemByAnchor,
33
- } from '../item-id-utils';
34
28
 
35
29
  const resolveItemColorsAsync = async (
36
30
  item: TestimonialItem,
@@ -56,7 +50,6 @@ const applyTestimonialItemsAsync = async (
56
50
  ): Promise<void> => {
57
51
  content.items = await Promise.all(
58
52
  items.map(async (item) => ({
59
- id: item.item_id || generateItemId(),
60
53
  imageUrl: item.avatar_shape_url || item.avatar_image_url || '',
61
54
  name: item.name || '',
62
55
  position: item.position || '',
@@ -67,77 +60,101 @@ const applyTestimonialItemsAsync = async (
67
60
  );
68
61
  };
69
62
 
70
- /**
71
- * Apply a batch of item operations by id (BP-5603), mirroring the section-level
72
- * id-based contract one level deeper:
73
- * - item with `item_id` matching an existing item → update in place (and
74
- * reposition if `move_before_item_id` is set);
75
- * - item without `item_id` → add a new item,
76
- * positioned by `move_before_item_id`;
77
- * - `_remove_item_ids` → delete by id.
78
- *
79
- * Existing items are id-backfilled first so legacy sections become referenceable
80
- * the moment the metadata builder touches them. Order-independent: there are no
81
- * positional indices to shift between operations.
82
- */
83
63
  const mergeTestimonialItemsAsync = async (
84
64
  content: TestimonialSectionContent,
85
65
  items: TestimonialItem[],
86
- removeIds: string[] | undefined,
66
+ replaceAll: boolean,
87
67
  ): Promise<void> => {
88
- ensureItemIds(content.items);
89
- content.items = removeItemsByIds(content.items, removeIds);
90
-
91
- for (const item of items) {
92
- if (item.item_id) {
93
- const existing = content.items.find((i) => i.id === item.item_id);
94
-
95
- // Unknown id — skip rather than guess at a position.
96
- if (!existing) continue;
97
-
98
- const prevImageUrl = existing.imageUrl;
68
+ const hasIndexedItems = items.some((item) => item.item_index !== undefined);
69
+
70
+ if (hasIndexedItems) {
71
+ await Promise.all(
72
+ items.map(async (item) => {
73
+ const targetIndex = item.item_index;
74
+
75
+ if (
76
+ targetIndex === undefined ||
77
+ targetIndex < 0 ||
78
+ !content.items?.[targetIndex]
79
+ )
80
+ return;
81
+
82
+ const existing = content.items[targetIndex];
83
+ const prevImageUrl = existing.imageUrl;
84
+
85
+ if (item.avatar_shape_url !== undefined) {
86
+ existing.imageUrl = item.avatar_shape_url;
87
+ existing.mediaType = 'shape';
88
+ } else if (item.avatar_image_url !== undefined) {
89
+ existing.imageUrl = item.avatar_image_url;
90
+ existing.mediaType = 'image';
91
+ }
92
+
93
+ if (item.name !== undefined) existing.name = item.name;
94
+
95
+ if (item.position !== undefined) existing.position = item.position;
96
+
97
+ if (item.testimonial !== undefined)
98
+ existing.testimonials = item.testimonial;
99
+
100
+ if (
101
+ item.avatar_shape_url !== undefined ||
102
+ item.color_theme !== undefined
103
+ ) {
104
+ existing.colorReplacements = await resolveItemColorsAsync(
105
+ item,
106
+ existing.colorReplacements,
107
+ prevImageUrl,
108
+ );
109
+ }
110
+ }),
111
+ );
99
112
 
100
- if (item.avatar_shape_url !== undefined) {
101
- existing.imageUrl = item.avatar_shape_url;
102
- existing.mediaType = 'shape';
103
- } else if (item.avatar_image_url !== undefined) {
104
- existing.imageUrl = item.avatar_image_url;
105
- existing.mediaType = 'image';
106
- }
113
+ return;
114
+ }
107
115
 
108
- if (item.name !== undefined) existing.name = item.name;
116
+ const itemsToMerge = items.filter((item) => item.insert_at === undefined);
109
117
 
110
- if (item.position !== undefined) existing.position = item.position;
118
+ const updatedItems = await Promise.all(
119
+ itemsToMerge.map(async (item, index) => {
120
+ const existing = content.items?.[index];
111
121
 
112
- if (item.testimonial !== undefined)
113
- existing.testimonials = item.testimonial;
122
+ const imageUrl =
123
+ item.avatar_shape_url ??
124
+ item.avatar_image_url ??
125
+ existing?.imageUrl ??
126
+ '';
127
+ const mediaType = item.avatar_shape_url
128
+ ? 'shape'
129
+ : item.avatar_image_url
130
+ ? 'image'
131
+ : (existing?.mediaType ?? 'image');
114
132
 
115
- if (
116
- item.avatar_shape_url !== undefined ||
117
- item.color_theme !== undefined
118
- ) {
119
- existing.colorReplacements = await resolveItemColorsAsync(
133
+ return {
134
+ ...(existing || {}),
135
+ imageUrl,
136
+ name: item.name ?? existing?.name ?? '',
137
+ position: item.position ?? existing?.position ?? '',
138
+ testimonials: item.testimonial ?? existing?.testimonials ?? '',
139
+ colorReplacements: await resolveItemColorsAsync(
120
140
  item,
121
- existing.colorReplacements,
122
- prevImageUrl,
123
- );
124
- }
141
+ existing?.colorReplacements,
142
+ existing?.imageUrl,
143
+ ),
144
+ mediaType,
145
+ };
146
+ }),
147
+ );
125
148
 
126
- repositionItemByAnchor(content.items, existing, item.move_before_item_id);
127
- } else {
128
- const newItem = {
129
- id: generateItemId(),
130
- imageUrl: item.avatar_shape_url ?? item.avatar_image_url ?? '',
131
- name: item.name ?? '',
132
- position: item.position ?? '',
133
- testimonials: item.testimonial ?? '',
134
- colorReplacements: await resolveItemColorsAsync(item, [], undefined),
135
- mediaType: item.avatar_shape_url ? 'shape' : 'image',
136
- } as TestimonialSectionContent['items'][number];
137
-
138
- repositionItemByAnchor(content.items, newItem, item.move_before_item_id);
139
- }
149
+ if (
150
+ !replaceAll &&
151
+ content.items &&
152
+ content.items.length > itemsToMerge.length
153
+ ) {
154
+ updatedItems.push(...content.items.slice(itemsToMerge.length));
140
155
  }
156
+
157
+ content.items = updatedItems;
141
158
  };
142
159
 
143
160
  export class TestimonialSectionBuilder extends BaseSectionBuilder<TestimonialSectionContent> {
@@ -211,29 +228,75 @@ export class TestimonialSectionBuilder extends BaseSectionBuilder<TestimonialSec
211
228
  };
212
229
  }
213
230
 
214
- if (args._replace_items && args.items && Array.isArray(args.items)) {
215
- // Full replacement: discard existing items and rebuild from the payload.
216
- await applyTestimonialItemsAsync(content, args.items);
217
- } else if (this.mode === 'create') {
218
- if (args.items && Array.isArray(args.items)) {
231
+ if (args.items && Array.isArray(args.items)) {
232
+ if (this.mode === 'create') {
219
233
  await applyTestimonialItemsAsync(content, args.items);
234
+ } else {
235
+ await mergeTestimonialItemsAsync(
236
+ content,
237
+ args.items,
238
+ !!args._replace_items,
239
+ );
240
+ }
241
+ }
242
+
243
+ // Phase 2: Item operations (remove, insert, reorder)
244
+ if (args._remove_item_indices?.length && content.items) {
245
+ const sorted = [...args._remove_item_indices].sort((a, b) => b - a);
246
+
247
+ for (const idx of sorted) {
248
+ if (idx >= 0 && idx < content.items.length) {
249
+ content.items.splice(idx, 1);
250
+ }
220
251
  }
221
- } else if (
222
- (args.items && Array.isArray(args.items)) ||
223
- args._remove_item_ids?.length
224
- ) {
225
- // Update: id-based add / edit / move / remove in a single pass.
226
- await mergeTestimonialItemsAsync(
227
- content,
228
- args.items ?? [],
229
- args._remove_item_ids,
252
+ }
253
+
254
+ if (args.items && Array.isArray(args.items)) {
255
+ const insertItems = args.items.filter(
256
+ (item) => item.insert_at !== undefined && item.item_index === undefined,
257
+ );
258
+ const sortedInserts = [...insertItems].sort(
259
+ (a, b) => (b.insert_at ?? 0) - (a.insert_at ?? 0),
230
260
  );
261
+
262
+ for (const item of sortedInserts) {
263
+ const pos = Math.max(
264
+ 0,
265
+ Math.min(item.insert_at ?? 0, content.items?.length ?? 0),
266
+ );
267
+ const newItem = {
268
+ imageUrl: item.avatar_shape_url ?? item.avatar_image_url ?? '',
269
+ name: item.name ?? '',
270
+ position: item.position ?? '',
271
+ testimonials: item.testimonial ?? '',
272
+ colorReplacements: await resolveItemColorsAsync(item, [], undefined),
273
+ mediaType: item.avatar_shape_url ? 'shape' : 'image',
274
+ };
275
+
276
+ content.items = content.items ?? [];
277
+ content.items.splice(pos, 0, newItem as any);
278
+ }
279
+ }
280
+
281
+ if (args._reorder_items?.length && content.items) {
282
+ const newOrder = args._reorder_items;
283
+ const unique = new Set(newOrder);
284
+
285
+ if (unique.size === newOrder.length) {
286
+ const reordered = newOrder
287
+ .filter((idx) => idx >= 0 && idx < content.items!.length)
288
+ .map((idx) => content.items![idx]);
289
+
290
+ if (reordered.length === content.items.length) {
291
+ content.items = reordered;
292
+ }
293
+ }
231
294
  }
232
295
 
233
296
  // Post-merge cap check. itemCapCheck only fires for create / update with
234
- // _replace_items, so adding new items to an already-full section silently
235
- // bloats the array. Surface as an error so the AI retry loop gets a signal
236
- // and can reissue with _remove_item_ids or fewer additions.
297
+ // _replace_items, so insert_at on an already-full section silently bloats
298
+ // the array. Surface as an error so the AI retry loop gets a signal and
299
+ // can reissue with _remove_item_indices or fewer inserts.
237
300
  // brandSite key mirrors base-section-builder's hardcoded brandPageType.
238
301
  const cap = TESTIMONIAL_ITEM_CAP.brandSite;
239
302
 
@@ -19,12 +19,6 @@ import {
19
19
  } from '../section-field-utils';
20
20
  import { BaseSectionBuilder } from './base-section-builder';
21
21
  import { validateTextSection } from '../section-rules/text-section.rules';
22
- import {
23
- ensureItemIds,
24
- generateItemId,
25
- removeItemsByIds,
26
- repositionItemByAnchor,
27
- } from '../item-id-utils';
28
22
 
29
23
  /** Resolve a RichTextField (string or TiptapDocument) to a plain HTML string. */
30
24
  const resolveText = (value: unknown): { html: string; wasTiptap: boolean } => {
@@ -58,7 +52,6 @@ const createTextItem = (
58
52
  const { html, wasTiptap } = resolveText(item.text);
59
53
 
60
54
  return {
61
- id: item.item_id || generateItemId(),
62
55
  text: html,
63
56
  textStyle: clearTextStyleTypeIfTiptap(
64
57
  textStyle,
@@ -68,10 +61,6 @@ const createTextItem = (
68
61
  };
69
62
  };
70
63
 
71
- /**
72
- * Full replacement: discard existing items and rebuild from the payload,
73
- * assigning a stable id to each new item.
74
- */
75
64
  const applyTextItems = (
76
65
  content: TextContent,
77
66
  items: TextSectionItem[],
@@ -82,33 +71,26 @@ const applyTextItems = (
82
71
  );
83
72
  };
84
73
 
85
- /**
86
- * Id-based merge (BP-5603): mirrors the section-level id contract one level
87
- * deeper.
88
- * - item with `item_id` matching an existing item → update in place and
89
- * reposition if `move_before_item_id` is set; unknown id is skipped.
90
- * - item without `item_id` → add a new item,
91
- * positioned by `move_before_item_id`.
92
- * - `removeIds` → delete by id.
93
- *
94
- * Existing items are id-backfilled first so legacy sections without ids
95
- * become referenceable the moment this builder processes them.
96
- */
97
74
  const mergeTextItems = (
98
75
  content: TextContent,
99
76
  items: TextSectionItem[],
100
- removeIds: string[] | undefined,
77
+ replaceAll: boolean,
101
78
  textStyleOptions: TextStyleOptions | undefined,
102
79
  ): void => {
103
- ensureItemIds(content.textItems);
104
- content.textItems = removeItemsByIds(content.textItems, removeIds);
80
+ const hasIndexedItems = items.some((item) => item.item_index !== undefined);
81
+
82
+ if (hasIndexedItems) {
83
+ for (const item of items) {
84
+ const targetIndex = item.item_index;
105
85
 
106
- for (const item of items) {
107
- if (item.item_id) {
108
- const existing = content.textItems?.find((i) => i.id === item.item_id);
86
+ if (
87
+ targetIndex === undefined ||
88
+ targetIndex < 0 ||
89
+ !content.textItems?.[targetIndex]
90
+ )
91
+ continue;
109
92
 
110
- // Unknown id — skip rather than guess at a position.
111
- if (!existing) continue;
93
+ const existing = content.textItems[targetIndex];
112
94
 
113
95
  if (item.text !== undefined) {
114
96
  const { html, wasTiptap } = resolveText(item.text);
@@ -122,32 +104,51 @@ const mergeTextItems = (
122
104
  }
123
105
 
124
106
  if (item.text_style && typeof item.text_style === 'object') {
125
- existing.textStyle = {
126
- ...(existing.textStyle || {}),
127
- ...item.text_style,
128
- } as TextStyleDeclaration;
107
+ const mergedStyle = (
108
+ item.text_style
109
+ ? { ...(existing.textStyle || {}), ...item.text_style }
110
+ : existing.textStyle || {}
111
+ ) as TextStyleDeclaration;
112
+
113
+ existing.textStyle = mergedStyle;
129
114
  }
115
+ }
130
116
 
131
- repositionItemByAnchor(
132
- content.textItems!,
133
- existing,
134
- item.move_before_item_id,
135
- );
136
- } else {
137
- const newItem = createTextItem(
138
- item,
139
- content.textStyle || {},
117
+ return;
118
+ }
119
+
120
+ const itemsToMerge = items.filter((item) => item.insert_at === undefined);
121
+
122
+ const updatedItems = itemsToMerge.map((item, index) => {
123
+ const existing = content.textItems?.[index];
124
+ const baseStyle = existing?.textStyle || content.textStyle || {};
125
+
126
+ const mergedStyle = (
127
+ item.text_style ? { ...baseStyle, ...item.text_style } : baseStyle
128
+ ) as TextStyleDeclaration;
129
+
130
+ const resolved = item.text !== undefined ? resolveText(item.text) : null;
131
+ const text = resolved ? resolved.html : (existing?.text ?? '');
132
+
133
+ return {
134
+ text,
135
+ textStyle: clearTextStyleTypeIfTiptap(
136
+ mergedStyle,
137
+ resolved?.wasTiptap ?? false,
140
138
  textStyleOptions,
141
- );
139
+ ),
140
+ };
141
+ });
142
142
 
143
- content.textItems = content.textItems ?? [];
144
- repositionItemByAnchor(
145
- content.textItems,
146
- newItem,
147
- item.move_before_item_id,
148
- );
149
- }
143
+ if (
144
+ !replaceAll &&
145
+ content.textItems &&
146
+ content.textItems.length > itemsToMerge.length
147
+ ) {
148
+ updatedItems.push(...content.textItems.slice(itemsToMerge.length));
150
149
  }
150
+
151
+ content.textItems = updatedItems;
151
152
  };
152
153
 
153
154
  /**
@@ -235,31 +236,82 @@ export class TextSectionBuilder extends BaseSectionBuilder<TextContent> {
235
236
 
236
237
  const args = this.args as TextSectionArguments;
237
238
 
238
- if (args._replace_items && args.items && Array.isArray(args.items)) {
239
- // Full replacement: discard existing items and rebuild from the payload.
240
- applyTextItems(content, args.items, textStyleOptions);
241
- } else if (this.mode === 'create') {
242
- if (args.items && Array.isArray(args.items)) {
239
+ if (args.items && Array.isArray(args.items)) {
240
+ if (this.mode === 'create') {
243
241
  applyTextItems(content, args.items, textStyleOptions);
244
242
  } else {
245
- applySingleTextField(content, args, textStyleOptions);
243
+ mergeTextItems(
244
+ content,
245
+ args.items,
246
+ !!args._replace_items,
247
+ textStyleOptions,
248
+ );
246
249
  }
247
- } else if (
248
- (args.items && Array.isArray(args.items)) ||
249
- args._remove_item_ids?.length
250
- ) {
251
- // Update: id-based add / edit / move / remove in a single pass.
252
- mergeTextItems(
253
- content,
254
- args.items ?? [],
255
- args._remove_item_ids,
256
- textStyleOptions,
257
- );
258
250
  } else {
259
- // No items array: apply the single text/text_style shorthand fields.
260
251
  applySingleTextField(content, args, textStyleOptions);
261
252
  }
262
253
 
254
+ // Phase 2: Item operations (remove, insert, reorder)
255
+ if (args._remove_item_indices?.length && content.textItems) {
256
+ const sorted = [...args._remove_item_indices].sort((a, b) => b - a);
257
+
258
+ for (const idx of sorted) {
259
+ if (idx >= 0 && idx < content.textItems.length) {
260
+ content.textItems.splice(idx, 1);
261
+ }
262
+ }
263
+ }
264
+
265
+ if (args.items && Array.isArray(args.items)) {
266
+ const insertItems = args.items.filter(
267
+ (item) => item.insert_at !== undefined && item.item_index === undefined,
268
+ );
269
+ const sortedInserts = [...insertItems].sort(
270
+ (a, b) => (b.insert_at ?? 0) - (a.insert_at ?? 0),
271
+ );
272
+
273
+ for (const item of sortedInserts) {
274
+ const pos = Math.max(
275
+ 0,
276
+ Math.min(item.insert_at ?? 0, content.textItems?.length ?? 0),
277
+ );
278
+ const baseStyle = content.textStyle || {};
279
+ const textStyle = (
280
+ item.text_style
281
+ ? { ...baseStyle, ...item.text_style }
282
+ : { ...baseStyle }
283
+ ) as TextStyleDeclaration;
284
+
285
+ const { html, wasTiptap } = resolveText(item.text);
286
+ const newItem: TextItem = {
287
+ text: html,
288
+ textStyle: clearTextStyleTypeIfTiptap(
289
+ textStyle,
290
+ wasTiptap,
291
+ textStyleOptions,
292
+ ),
293
+ };
294
+
295
+ content.textItems = content.textItems ?? [];
296
+ content.textItems.splice(pos, 0, newItem);
297
+ }
298
+ }
299
+
300
+ if (args._reorder_items?.length && content.textItems) {
301
+ const newOrder = args._reorder_items;
302
+ const unique = new Set(newOrder);
303
+
304
+ if (unique.size === newOrder.length) {
305
+ const reordered = newOrder
306
+ .filter((idx) => idx >= 0 && idx < content.textItems!.length)
307
+ .map((idx) => content.textItems![idx]);
308
+
309
+ if (reordered.length === content.textItems.length) {
310
+ content.textItems = reordered;
311
+ }
312
+ }
313
+ }
314
+
263
315
  if (args.background_color !== undefined) {
264
316
  content.backgroundColor = {
265
317
  ...content.backgroundColor,
@@ -109,7 +109,7 @@ export const applyScalarFields = (
109
109
  * - null → '' (explicitly clear/reset the property)
110
110
  * - everything else passes through as-is
111
111
  */
112
- const normalizeStyleValue = (key: string, value: unknown): unknown => {
112
+ export const normalizeStyleValue = (key: string, value: unknown): unknown => {
113
113
  if (value === null) return '';
114
114
 
115
115
  if (value === undefined) return undefined;
@@ -68,8 +68,8 @@ export const applyColorThemeToReplacements = (
68
68
  replacementColor:
69
69
  replacements.length === 1
70
70
  ? colorTheme
71
- : getNewColorBasedOnTargetColorTheme(
71
+ : (getNewColorBasedOnTargetColorTheme(
72
72
  r.originalColor,
73
73
  colorTheme,
74
- )?.toString() ?? colorTheme,
74
+ )?.toString() ?? colorTheme),
75
75
  }));
@@ -4,7 +4,7 @@ import type {
4
4
  HeaderDisplayStyle,
5
5
  NavigationDisplayType,
6
6
  } from '../../brand-page/constants';
7
- import type { SectionType } from './section-tool-arguments';
7
+ import type { SectionType, TextStyleArguments } from './section-tool-arguments';
8
8
 
9
9
  // Tool names — must match the function names generated by the AI pipeline.
10
10
  // Text element tools use camelCase names.
@@ -202,17 +202,8 @@ export interface ReorderPagesArguments {
202
202
  export interface UndoArguments {}
203
203
 
204
204
  export interface FooterSocialLinkItem {
205
- /**
206
- * Stable id of the existing link to update or move. Omit to ADD a new link.
207
- * Mirrors the section-level item_id convention (BP-5603).
208
- */
209
- item_id?: string;
210
- /**
211
- * Id of an existing link to position this link before (insert for new links,
212
- * move for existing ones). Use "__end__" for the end of the list. Omit to
213
- * leave an existing link in place / append a new link.
214
- */
215
- move_before_item_id?: string;
205
+ item_index?: number;
206
+ insert_at?: number;
216
207
  social_link_icon?: string;
217
208
  url?: string;
218
209
  }
@@ -224,7 +215,6 @@ export interface FooterSocialLinkItem {
224
215
  export interface ViewportFooterOverrides {
225
216
  display_style?: FooterDisplayStyle;
226
217
  background_color?: string | null;
227
- copyright_text_color?: string;
228
218
  icon_color?: string;
229
219
  is_logo_visible?: boolean;
230
220
  logo_image_height?: string;
@@ -233,11 +223,12 @@ export interface ViewportFooterOverrides {
233
223
 
234
224
  export interface UpdateFooterArguments {
235
225
  copyright_text?: string;
236
- copyright_text_font_family?: string;
226
+ /** Copyright line text-style object (typography + colour) — same shape as a section's *_style. Global: applies to both viewports. */
227
+ copyright_text_style?: TextStyleArguments;
237
228
  social_links?: FooterSocialLinkItem[];
238
229
  _replace_social_links?: boolean;
239
- /** Stable ids of social links to remove. Order-independent (replaces index-based _remove_social_link_indices). */
240
- _remove_social_link_ids?: string[];
230
+ _remove_social_link_indices?: number[];
231
+ _reorder_social_links?: number[];
241
232
  /** Desktop-only styling (display_style, background_color, icon_color, is_logo_visible, logo sizes). */
242
233
  desktop?: ViewportFooterOverrides;
243
234
  /** Mobile-only styling (display_style, background_color, icon_color, is_logo_visible, logo sizes). */