@designcrowd/library.brand-page 5.17.28 → 5.18.0

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 (380) hide show
  1. package/lib/src/{CreatedOnBrandCrowd-de-de-CJZpKPNH.js → CreatedOnBrandCrowd-de-de-xmkupPus.js} +1 -1
  2. package/lib/src/{CreatedOnBrandCrowd-en-us-DkIa7iEb.js → CreatedOnBrandCrowd-en-us-Ck7EdTtb.js} +1 -1
  3. package/lib/src/{CreatedOnBrandCrowd-es-es-CE2p6XHz.js → CreatedOnBrandCrowd-es-es-BC8sJuDH.js} +1 -1
  4. package/lib/src/{CreatedOnBrandCrowd-fr-fr-BBjOZS3M.js → CreatedOnBrandCrowd-fr-ca-CN-UBe1q.js} +1 -1
  5. package/lib/src/{CreatedOnBrandCrowd-fr-ca-BBjOZS3M.js → CreatedOnBrandCrowd-fr-fr-CN-UBe1q.js} +1 -1
  6. package/lib/src/{CreatedOnBrandCrowd-pt-pt-Dayzl4BZ.js → CreatedOnBrandCrowd-pt-br-CajQyNkx.js} +1 -1
  7. package/lib/src/{CreatedOnBrandCrowd-pt-br-Dayzl4BZ.js → CreatedOnBrandCrowd-pt-pt-CajQyNkx.js} +1 -1
  8. package/lib/src/{CreatedOnDcom-de-de-CFzDqfCb.js → CreatedOnDcom-de-de-BRCNMmDq.js} +1 -1
  9. package/lib/src/{CreatedOnDcom-en-us-C2jIPBDY.js → CreatedOnDcom-en-us-BzQDtZhc.js} +1 -1
  10. package/lib/src/{CreatedOnDcom-es-es-qejpzqho.js → CreatedOnDcom-es-es-D-qAM4Cd.js} +1 -1
  11. package/lib/src/{CreatedOnDcom-fr-ca-DMO9Ld7K.js → CreatedOnDcom-fr-ca-CZ1irFOc.js} +1 -1
  12. package/lib/src/{CreatedOnDcom-fr-fr-BFWN9qTP.js → CreatedOnDcom-fr-fr-Gb5BCF0N.js} +1 -1
  13. package/lib/src/{CreatedOnDcom-pt-br-CneD3ghF.js → CreatedOnDcom-pt-br-CAQV0q6o.js} +1 -1
  14. package/lib/src/{CreatedOnDcom-pt-pt-Cg1B7s0o.js → CreatedOnDcom-pt-pt-D6tQdQFh.js} +1 -1
  15. package/lib/src/brand-page/components/image-gallery/ImageGalleryModal.mixin.js +2 -2
  16. package/lib/src/brand-page/models/brand-page-context.model.d.ts +0 -2
  17. package/lib/src/brand-page/models/brand-page-context.model.js +1 -11
  18. package/lib/src/brand-page/models/index.d.ts +1 -0
  19. package/lib/src/brand-page/models/index.js +1 -0
  20. package/lib/src/brand-page/utils/color.util.js +23 -3
  21. package/lib/src/brand-page/utils/raygun.util.d.ts +5 -1
  22. package/lib/src/brand-page/utils/raygun.util.js +7 -2
  23. package/lib/src/brand-page/utils/svg-color.util.js +1 -2
  24. package/lib/src/brand-page/utils/view-model.util.js +1 -1
  25. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +1 -31
  26. package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.js +0 -2
  27. package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +2 -31
  28. package/lib/src/brand-page-maker/components/preview/Preview.mixin.d.ts +0 -14
  29. package/lib/src/brand-page-maker/components/quick-link-bar/QuickLinkBar.mixin.d.ts +0 -28
  30. package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.d.ts +0 -28
  31. package/lib/src/brand-page-maker/components/seo-settings/UrlSettings.mixin.d.ts +0 -28
  32. package/lib/src/brand-page-maker/components/seo-settings/UseExistingDomainModal.mixin.d.ts +0 -28
  33. package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.d.ts +0 -28
  34. package/lib/src/brand-page-maker/components/upgrade-to-premium-button/UpgradeToPremiumButton.mixin.d.ts +0 -28
  35. package/lib/src/brand-page-maker/composables/ai-chat/aiErrorCopy.d.ts +35 -0
  36. package/lib/src/brand-page-maker/composables/ai-chat/aiErrorCopy.js +108 -0
  37. package/lib/src/brand-page-maker/composables/ai-chat/{useAiChat.d.ts → types.d.ts} +5 -13
  38. package/lib/src/brand-page-maker/composables/ai-chat/types.js +1 -0
  39. package/lib/src/brand-page-maker/composables/ai-chat/useAiMetadataBuilder.d.ts +19 -0
  40. package/lib/src/brand-page-maker/composables/ai-chat/useAiMetadataBuilder.js +1 -0
  41. package/lib/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.d.ts +1 -1
  42. package/lib/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.js +488 -82
  43. package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.js +5 -5
  44. package/lib/src/brand-page-maker/composables/useEventTracker.d.ts +6 -16
  45. package/lib/src/brand-page-maker/composables/useEventTracker.js +19 -21
  46. package/lib/src/brand-page-maker/constants/sidebar-constant.d.ts +0 -1
  47. package/lib/src/brand-page-maker/constants/sidebar-constant.js +7 -15
  48. package/lib/src/brand-page-maker/convertors/image-aspect-ratio.convertor.js +2 -2
  49. package/lib/src/brand-page-maker/convertors/text-size-value.convertor.js +3 -1
  50. package/lib/src/brand-page-maker/stores/ai-checkpoint/ai-checkpoint-store.d.ts +30660 -0
  51. package/lib/src/brand-page-maker/stores/ai-checkpoint/ai-checkpoint-store.js +34 -0
  52. package/lib/src/brand-page-maker/stores/ai-thread/ai-website-builder-thread-store.d.ts +1 -1
  53. package/lib/src/brand-page-maker/stores/brandpage-container/brand-page-container-store.d.ts +0 -28
  54. package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.js +42 -2
  55. package/lib/src/brand-page-maker/stores/index.d.ts +1 -1
  56. package/lib/src/brand-page-maker/stores/index.js +1 -1
  57. package/lib/src/brand-page-maker/stores/user/user-store.js +0 -1
  58. package/lib/src/bundled-translations-CnareLWC.js +175 -0
  59. package/lib/src/bundled-translations.de-DE-2Ys7epLO.js +175 -0
  60. package/lib/src/bundled-translations.es-ES-Cjp-G8rT.js +175 -0
  61. package/lib/src/bundled-translations.fr-CA-CsaW4Oae.js +175 -0
  62. package/lib/src/bundled-translations.fr-FR-DIT2dd8J.js +175 -0
  63. package/lib/src/bundled-translations.pt-BR-BamoBpDW.js +175 -0
  64. package/lib/src/bundled-translations.pt-PT-C9A4hY_e.js +175 -0
  65. package/lib/src/bundles/bundled-translations.de-DE.json +1 -20
  66. package/lib/src/bundles/bundled-translations.es-ES.json +1 -20
  67. package/lib/src/bundles/bundled-translations.fr-CA.json +1 -20
  68. package/lib/src/bundles/bundled-translations.fr-FR.json +1 -20
  69. package/lib/src/bundles/bundled-translations.json +1 -20
  70. package/lib/src/bundles/bundled-translations.pt-BR.json +1 -20
  71. package/lib/src/bundles/bundled-translations.pt-PT.json +1 -20
  72. package/lib/src/clients/ai-assistant-client.d.ts +30 -29
  73. package/lib/src/clients/ai-assistant-client.js +16 -16
  74. package/lib/src/clients/design-template-client.d.ts +0 -2
  75. package/lib/src/clients/design-template-client.js +0 -38
  76. package/lib/src/clients/websocket-gateway-client.d.ts +9 -1
  77. package/lib/src/composables/useTranslate.d.ts +2 -1
  78. package/lib/src/composables/useTranslate.js +2 -1
  79. package/lib/src/constants/ui.d.ts +0 -1
  80. package/lib/src/css/library.brand-page-brandCrowd.min.css +225 -134
  81. package/lib/src/css/library.brand-page-brandPage.min.css +227 -121
  82. package/lib/src/css/library.brand-page-designCom.min.css +225 -134
  83. package/lib/src/css/library.brand-page-preview.min.css +225 -118
  84. package/lib/src/index.d.ts +1 -1
  85. package/lib/src/index.mjs +1 -1
  86. package/lib/src/{lib-33w_DBny.js → lib-CSRUPpSo.js} +30887 -29395
  87. package/lib/src/metadata-builder/ai-metadata-executor.d.ts +21 -0
  88. package/lib/src/metadata-builder/ai-metadata-executor.js +56 -3
  89. package/lib/src/metadata-builder/builders/add-page-builder.d.ts +2 -4
  90. package/lib/src/metadata-builder/builders/add-page-builder.js +5 -8
  91. package/lib/src/metadata-builder/builders/footer-builder.d.ts +11 -0
  92. package/lib/src/metadata-builder/builders/footer-builder.js +151 -0
  93. package/lib/src/metadata-builder/builders/global-styles-builder.d.ts +15 -0
  94. package/lib/src/metadata-builder/builders/global-styles-builder.js +129 -0
  95. package/lib/src/metadata-builder/builders/header-builder.d.ts +11 -0
  96. package/lib/src/metadata-builder/builders/header-builder.js +167 -0
  97. package/lib/src/metadata-builder/builders/rename-page-builder.d.ts +12 -0
  98. package/lib/src/metadata-builder/builders/rename-page-builder.js +49 -0
  99. package/lib/src/metadata-builder/builders/section-builders/about-section-builder.d.ts +2 -0
  100. package/lib/src/metadata-builder/builders/section-builders/about-section-builder.js +44 -4
  101. package/lib/src/metadata-builder/builders/section-builders/banner-section-builder.d.ts +2 -0
  102. package/lib/src/metadata-builder/builders/section-builders/banner-section-builder.js +70 -6
  103. package/lib/src/metadata-builder/builders/section-builders/base-section-builder.d.ts +36 -4
  104. package/lib/src/metadata-builder/builders/section-builders/base-section-builder.js +102 -12
  105. package/lib/src/metadata-builder/builders/section-builders/booking-section-builder.d.ts +8 -0
  106. package/lib/src/metadata-builder/builders/section-builders/booking-section-builder.js +50 -0
  107. package/lib/src/metadata-builder/builders/section-builders/button-section-builder.d.ts +2 -0
  108. package/lib/src/metadata-builder/builders/section-builders/button-section-builder.js +5 -1
  109. package/lib/src/metadata-builder/builders/section-builders/contact-form-builder.d.ts +2 -0
  110. package/lib/src/metadata-builder/builders/section-builders/contact-form-builder.js +47 -3
  111. package/lib/src/metadata-builder/builders/section-builders/delete-section-builder.d.ts +2 -1
  112. package/lib/src/metadata-builder/builders/section-builders/delete-section-builder.js +5 -2
  113. package/lib/src/metadata-builder/builders/section-builders/divider-section-builder.d.ts +2 -0
  114. package/lib/src/metadata-builder/builders/section-builders/divider-section-builder.js +11 -1
  115. package/lib/src/metadata-builder/builders/section-builders/image-gallery-builder.d.ts +2 -0
  116. package/lib/src/metadata-builder/builders/section-builders/image-gallery-builder.js +52 -13
  117. package/lib/src/metadata-builder/builders/section-builders/images-section-builder.d.ts +2 -0
  118. package/lib/src/metadata-builder/builders/section-builders/images-section-builder.js +47 -17
  119. package/lib/src/metadata-builder/builders/section-builders/index.d.ts +1 -0
  120. package/lib/src/metadata-builder/builders/section-builders/index.js +1 -0
  121. package/lib/src/metadata-builder/builders/section-builders/mailing-list-builder.d.ts +2 -0
  122. package/lib/src/metadata-builder/builders/section-builders/mailing-list-builder.js +20 -2
  123. package/lib/src/metadata-builder/builders/section-builders/mailing-list-section-builder.d.ts +2 -0
  124. package/lib/src/metadata-builder/builders/section-builders/mailing-list-section-builder.js +20 -2
  125. package/lib/src/metadata-builder/builders/section-builders/profile-section-builder.d.ts +2 -0
  126. package/lib/src/metadata-builder/builders/section-builders/profile-section-builder.js +36 -2
  127. package/lib/src/metadata-builder/builders/section-builders/shapes-section-builder.d.ts +2 -0
  128. package/lib/src/metadata-builder/builders/section-builders/shapes-section-builder.js +70 -27
  129. package/lib/src/metadata-builder/builders/section-builders/social-links-builder.d.ts +2 -0
  130. package/lib/src/metadata-builder/builders/section-builders/social-links-builder.js +7 -2
  131. package/lib/src/metadata-builder/builders/section-builders/testimonial-section-builder.d.ts +2 -0
  132. package/lib/src/metadata-builder/builders/section-builders/testimonial-section-builder.js +91 -26
  133. package/lib/src/metadata-builder/builders/section-builders/text-section-builder.d.ts +2 -0
  134. package/lib/src/metadata-builder/builders/section-builders/text-section-builder.js +69 -31
  135. package/lib/src/metadata-builder/builders/section-content-factory.d.ts +2 -2
  136. package/lib/src/metadata-builder/builders/section-content-factory.js +8 -2
  137. package/lib/src/metadata-builder/builders/section-field-maps.js +30 -2
  138. package/lib/src/metadata-builder/builders/section-field-utils.d.ts +46 -7
  139. package/lib/src/metadata-builder/builders/section-field-utils.js +86 -62
  140. package/lib/src/metadata-builder/builders/section-rules/about-section.rules.d.ts +2 -0
  141. package/lib/src/metadata-builder/builders/section-rules/about-section.rules.js +20 -0
  142. package/lib/src/metadata-builder/builders/section-rules/add-page.rules.d.ts +7 -0
  143. package/lib/src/metadata-builder/builders/section-rules/add-page.rules.js +8 -0
  144. package/lib/src/metadata-builder/builders/section-rules/banner-section.rules.d.ts +2 -0
  145. package/lib/src/metadata-builder/builders/section-rules/banner-section.rules.js +27 -0
  146. package/lib/src/metadata-builder/builders/section-rules/booking-section.rules.d.ts +2 -0
  147. package/lib/src/metadata-builder/builders/section-rules/booking-section.rules.js +16 -0
  148. package/lib/src/metadata-builder/builders/section-rules/button-section.rules.d.ts +2 -0
  149. package/lib/src/metadata-builder/builders/section-rules/button-section.rules.js +13 -0
  150. package/lib/src/metadata-builder/builders/section-rules/contact-form.rules.d.ts +2 -0
  151. package/lib/src/metadata-builder/builders/section-rules/contact-form.rules.js +16 -0
  152. package/lib/src/metadata-builder/builders/section-rules/divider-section.rules.d.ts +2 -0
  153. package/lib/src/metadata-builder/builders/section-rules/divider-section.rules.js +7 -0
  154. package/lib/src/metadata-builder/builders/section-rules/footer.rules.d.ts +4 -0
  155. package/lib/src/metadata-builder/builders/section-rules/footer.rules.js +5 -0
  156. package/lib/src/metadata-builder/builders/section-rules/global-styles.rules.d.ts +6 -0
  157. package/lib/src/metadata-builder/builders/section-rules/global-styles.rules.js +26 -0
  158. package/lib/src/metadata-builder/builders/section-rules/header.rules.d.ts +4 -0
  159. package/lib/src/metadata-builder/builders/section-rules/header.rules.js +41 -0
  160. package/lib/src/metadata-builder/builders/section-rules/image-gallery.rules.d.ts +2 -0
  161. package/lib/src/metadata-builder/builders/section-rules/image-gallery.rules.js +10 -0
  162. package/lib/src/metadata-builder/builders/section-rules/images-section.rules.d.ts +2 -0
  163. package/lib/src/metadata-builder/builders/section-rules/images-section.rules.js +31 -0
  164. package/lib/src/metadata-builder/builders/section-rules/mailing-list.rules.d.ts +2 -0
  165. package/lib/src/metadata-builder/builders/section-rules/mailing-list.rules.js +11 -0
  166. package/lib/src/metadata-builder/builders/section-rules/profile.rules.d.ts +2 -0
  167. package/lib/src/metadata-builder/builders/section-rules/profile.rules.js +14 -0
  168. package/lib/src/metadata-builder/builders/section-rules/rename-page.rules.d.ts +7 -0
  169. package/lib/src/metadata-builder/builders/section-rules/rename-page.rules.js +8 -0
  170. package/lib/src/metadata-builder/builders/section-rules/shapes-section.rules.d.ts +2 -0
  171. package/lib/src/metadata-builder/builders/section-rules/shapes-section.rules.js +27 -0
  172. package/lib/src/metadata-builder/builders/section-rules/social-links.rules.d.ts +2 -0
  173. package/lib/src/metadata-builder/builders/section-rules/social-links.rules.js +9 -0
  174. package/lib/src/metadata-builder/builders/section-rules/testimonial-section.rules.d.ts +7 -0
  175. package/lib/src/metadata-builder/builders/section-rules/testimonial-section.rules.js +26 -0
  176. package/lib/src/metadata-builder/builders/section-rules/text-section.rules.d.ts +2 -0
  177. package/lib/src/metadata-builder/builders/section-rules/text-section.rules.js +14 -0
  178. package/lib/src/metadata-builder/builders/shape-color-utils.d.ts +26 -0
  179. package/lib/src/metadata-builder/builders/shape-color-utils.js +52 -0
  180. package/lib/src/metadata-builder/builders/undo-builder.d.ts +48 -0
  181. package/lib/src/metadata-builder/builders/undo-builder.js +58 -0
  182. package/lib/src/metadata-builder/builders/update-content-text-style-builder.js +5 -1
  183. package/lib/src/metadata-builder/helpers/rte.helpers.d.ts +15 -4
  184. package/lib/src/metadata-builder/helpers/rte.helpers.js +24 -10
  185. package/lib/src/metadata-builder/metadata-executor.d.ts +2 -1
  186. package/lib/src/metadata-builder/metadata-executor.js +32 -5
  187. package/lib/src/metadata-builder/models.d.ts +26 -1
  188. package/lib/src/metadata-builder/models.js +14 -1
  189. package/lib/src/metadata-builder/parsers/ai-toolcall-parser.d.ts +144 -0
  190. package/lib/src/metadata-builder/parsers/ai-toolcall-parser.js +17 -0
  191. package/lib/src/metadata-builder/parsers/section-tool-arguments.d.ts +113 -24
  192. package/lib/src/metadata-builder/parsers/section-tool-arguments.js +5 -1
  193. package/lib/src/metadata-builder/sanitizers/rte-schema-check.d.ts +22 -0
  194. package/lib/src/metadata-builder/sanitizers/rte-schema-check.js +84 -0
  195. package/lib/src/metadata-builder/sanitizers/sanitizer-rules.d.ts +47 -0
  196. package/lib/src/metadata-builder/sanitizers/sanitizer-rules.js +60 -0
  197. package/lib/src/metadata-builder/sanitizers/section-args-validator.d.ts +41 -0
  198. package/lib/src/metadata-builder/sanitizers/section-args-validator.js +274 -0
  199. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +2 -1
  200. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.js +2 -16
  201. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.stories.js +0 -1
  202. package/lib/src/shared/content-settings/components/content-settings/ReplaceImageSettingsForContent.mixin.d.ts +2 -1
  203. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.d.ts +2 -3
  204. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.d.ts +0 -4
  205. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.js +6 -8
  206. package/lib/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.d.ts +0 -28
  207. package/lib/src/shared/logo-settings/components/EditLogoSettings.mixin.d.ts +2 -1
  208. package/lib/src/shared/logo-settings/components/LogoSettings.mixin.d.ts +0 -28
  209. package/lib/src/shared/navigation-style-settings/store/index.js +1 -0
  210. package/lib/src/shared/page-navigation/store/page-navigation-store.js +1 -20
  211. package/lib/src/shared/page-navigation/utils/nav-order-utils.d.ts +3 -0
  212. package/lib/src/shared/page-navigation/utils/nav-order-utils.js +20 -0
  213. package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +2 -30
  214. package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +0 -28
  215. package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +2 -43
  216. package/lib/src/shared/side-bar/components/SideBar.mixin.d.ts +0 -30
  217. package/lib/src/shared/side-bar/components/SideBarTabButton.mixin.d.ts +2 -3
  218. package/lib/src/shared/side-bar/store/side-bar-store.d.ts +0 -12
  219. package/lib/src/shared/side-bar/store/side-bar-store.js +0 -7
  220. package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +2 -29
  221. package/lib/src/shared/template-settings/components/TemplatesSettings.mixin.d.ts +2 -1
  222. package/lib/src/utils/build-asset-manifest.d.ts +26 -0
  223. package/lib/src/utils/build-asset-manifest.js +114 -0
  224. package/lib/src/utils/minify-brand-page-metadata.d.ts +49 -1
  225. package/lib/src/utils/minify-brand-page-metadata.js +216 -129
  226. package/package.json +1 -1
  227. package/src/brand-page/components/banner-section/BannerSection.vue +1 -1
  228. package/src/brand-page/components/contact-form/ContactForm.vue +29 -26
  229. package/src/brand-page/components/image-gallery/ImageGalleryModal.mixin.ts +6 -2
  230. package/src/brand-page/components/text-media-section/TextMediaSection.vue +1 -5
  231. package/src/brand-page/models/brand-page-context.model.ts +1 -25
  232. package/src/brand-page/models/index.ts +1 -0
  233. package/src/brand-page/utils/color.util.test.ts +48 -0
  234. package/src/brand-page/utils/color.util.ts +29 -4
  235. package/src/brand-page/utils/raygun.util.ts +11 -2
  236. package/src/brand-page/utils/svg-color.util.ts +1 -3
  237. package/src/brand-page/utils/view-model.util.ts +1 -4
  238. package/src/brand-page-maker/components/ai-text-edit/AiChatbox.vue +2 -2
  239. package/src/brand-page-maker/components/ai-text-edit/AiProgressFeed.vue +162 -0
  240. package/src/brand-page-maker/components/ai-text-edit/TextBubble.vue +57 -5
  241. package/src/brand-page-maker/components/ai-text-edit/i18n/generate-ai.de-DE.json +0 -20
  242. package/src/brand-page-maker/components/ai-text-edit/i18n/generate-ai.es-ES.json +0 -20
  243. package/src/brand-page-maker/components/ai-text-edit/i18n/generate-ai.fr-CA.json +0 -20
  244. package/src/brand-page-maker/components/ai-text-edit/i18n/generate-ai.fr-FR.json +0 -20
  245. package/src/brand-page-maker/components/ai-text-edit/i18n/generate-ai.json +0 -20
  246. package/src/brand-page-maker/components/ai-text-edit/i18n/generate-ai.pt-BR.json +0 -20
  247. package/src/brand-page-maker/components/ai-text-edit/i18n/generate-ai.pt-PT.json +0 -20
  248. package/src/brand-page-maker/components/ai-website-builder/AiWebsiteBuilder.vue +1 -2
  249. package/src/brand-page-maker/components/ai-website-builder/i18n/ai-website-builder.de-DE.json +3 -0
  250. package/src/brand-page-maker/components/ai-website-builder/i18n/ai-website-builder.es-ES.json +3 -0
  251. package/src/brand-page-maker/components/ai-website-builder/i18n/ai-website-builder.fr-CA.json +3 -0
  252. package/src/brand-page-maker/components/ai-website-builder/i18n/ai-website-builder.fr-FR.json +3 -0
  253. package/src/brand-page-maker/components/ai-website-builder/i18n/ai-website-builder.json +3 -0
  254. package/src/brand-page-maker/components/ai-website-builder/i18n/ai-website-builder.pt-BR.json +3 -0
  255. package/src/brand-page-maker/components/ai-website-builder/i18n/ai-website-builder.pt-PT.json +3 -0
  256. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.vue +3 -28
  257. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.ts +0 -2
  258. package/src/brand-page-maker/composables/ai-chat/aiErrorCopy.test.ts +229 -0
  259. package/src/brand-page-maker/composables/ai-chat/aiErrorCopy.ts +164 -0
  260. package/src/brand-page-maker/composables/ai-chat/types.ts +49 -0
  261. package/src/brand-page-maker/composables/ai-chat/useAiMetadataBuilder.ts +20 -0
  262. package/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.ts +651 -94
  263. package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.ts +9 -9
  264. package/src/brand-page-maker/composables/useEventTracker.ts +31 -25
  265. package/src/brand-page-maker/constants/sidebar-constant.ts +7 -15
  266. package/src/brand-page-maker/convertors/image-aspect-ratio.convertor.ts +2 -2
  267. package/src/brand-page-maker/convertors/text-size-value.convertor.ts +3 -3
  268. package/src/brand-page-maker/stores/ai-checkpoint/ai-checkpoint-store.ts +54 -0
  269. package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.ts +76 -0
  270. package/src/brand-page-maker/stores/index.ts +1 -1
  271. package/src/brand-page-maker/stores/user/user-store.ts +0 -1
  272. package/src/bundles/bundled-translations.de-DE.json +1 -20
  273. package/src/bundles/bundled-translations.es-ES.json +1 -20
  274. package/src/bundles/bundled-translations.fr-CA.json +1 -20
  275. package/src/bundles/bundled-translations.fr-FR.json +1 -20
  276. package/src/bundles/bundled-translations.json +1 -20
  277. package/src/bundles/bundled-translations.pt-BR.json +1 -20
  278. package/src/bundles/bundled-translations.pt-PT.json +1 -20
  279. package/src/clients/ai-assistant-client.ts +59 -46
  280. package/src/clients/design-template-client.ts +0 -66
  281. package/src/clients/websocket-gateway-client.ts +17 -1
  282. package/src/composables/useTranslate.ts +3 -0
  283. package/src/constants/ui.ts +0 -1
  284. package/src/lib.ts +1 -0
  285. package/src/metadata-builder/ai-metadata-executor.ts +94 -1
  286. package/src/metadata-builder/builders/add-page-builder.ts +9 -13
  287. package/src/metadata-builder/builders/footer-builder.test.ts +76 -0
  288. package/src/metadata-builder/builders/footer-builder.ts +226 -0
  289. package/src/metadata-builder/builders/global-styles-builder.ts +187 -0
  290. package/src/metadata-builder/builders/header-builder.test.ts +106 -0
  291. package/src/metadata-builder/builders/header-builder.ts +254 -0
  292. package/src/metadata-builder/builders/rename-page-builder.ts +79 -0
  293. package/src/metadata-builder/builders/section-builders/about-section-builder.ts +73 -5
  294. package/src/metadata-builder/builders/section-builders/banner-section-builder.ts +112 -7
  295. package/src/metadata-builder/builders/section-builders/base-section-builder.ts +149 -11
  296. package/src/metadata-builder/builders/section-builders/booking-section-builder.ts +87 -0
  297. package/src/metadata-builder/builders/section-builders/button-section-builder.ts +6 -1
  298. package/src/metadata-builder/builders/section-builders/contact-form-builder.ts +74 -4
  299. package/src/metadata-builder/builders/section-builders/delete-section-builder.ts +15 -1
  300. package/src/metadata-builder/builders/section-builders/divider-section-builder.ts +13 -1
  301. package/src/metadata-builder/builders/section-builders/image-gallery-builder.ts +91 -31
  302. package/src/metadata-builder/builders/section-builders/images-section-builder.ts +102 -48
  303. package/src/metadata-builder/builders/section-builders/index.ts +1 -0
  304. package/src/metadata-builder/builders/section-builders/mailing-list-builder.ts +38 -2
  305. package/src/metadata-builder/builders/section-builders/mailing-list-section-builder.ts +38 -2
  306. package/src/metadata-builder/builders/section-builders/profile-section-builder.ts +55 -3
  307. package/src/metadata-builder/builders/section-builders/shapes-section-builder.ts +170 -77
  308. package/src/metadata-builder/builders/section-builders/social-links-builder.test.ts +119 -0
  309. package/src/metadata-builder/builders/section-builders/social-links-builder.ts +13 -2
  310. package/src/metadata-builder/builders/section-builders/testimonial-section-builder.ts +178 -57
  311. package/src/metadata-builder/builders/section-builders/text-section-builder.ts +130 -30
  312. package/src/metadata-builder/builders/section-content-factory.ts +15 -2
  313. package/src/metadata-builder/builders/section-field-maps.ts +34 -1
  314. package/src/metadata-builder/builders/section-field-utils.ts +131 -72
  315. package/src/metadata-builder/builders/section-rules/about-section.rules.ts +38 -0
  316. package/src/metadata-builder/builders/section-rules/add-page.rules.ts +17 -0
  317. package/src/metadata-builder/builders/section-rules/banner-section.rules.ts +49 -0
  318. package/src/metadata-builder/builders/section-rules/booking-section.rules.ts +34 -0
  319. package/src/metadata-builder/builders/section-rules/button-section.rules.ts +22 -0
  320. package/src/metadata-builder/builders/section-rules/contact-form.rules.ts +30 -0
  321. package/src/metadata-builder/builders/section-rules/divider-section.rules.ts +17 -0
  322. package/src/metadata-builder/builders/section-rules/footer.rules.ts +21 -0
  323. package/src/metadata-builder/builders/section-rules/global-styles.rules.ts +44 -0
  324. package/src/metadata-builder/builders/section-rules/header.rules.ts +75 -0
  325. package/src/metadata-builder/builders/section-rules/image-gallery.rules.ts +22 -0
  326. package/src/metadata-builder/builders/section-rules/images-section.rules.ts +55 -0
  327. package/src/metadata-builder/builders/section-rules/mailing-list.rules.ts +21 -0
  328. package/src/metadata-builder/builders/section-rules/profile.rules.ts +27 -0
  329. package/src/metadata-builder/builders/section-rules/rename-page.rules.ts +17 -0
  330. package/src/metadata-builder/builders/section-rules/shapes-section.rules.ts +51 -0
  331. package/src/metadata-builder/builders/section-rules/social-links.rules.ts +27 -0
  332. package/src/metadata-builder/builders/section-rules/testimonial-section.rules.ts +48 -0
  333. package/src/metadata-builder/builders/section-rules/text-section.rules.ts +28 -0
  334. package/src/metadata-builder/builders/shape-color-utils.test.ts +115 -0
  335. package/src/metadata-builder/builders/shape-color-utils.ts +75 -0
  336. package/src/metadata-builder/builders/undo-builder.ts +105 -0
  337. package/src/metadata-builder/builders/update-content-text-style-builder.ts +4 -1
  338. package/src/metadata-builder/helpers/rte.helpers.ts +27 -13
  339. package/src/metadata-builder/metadata-executor.ts +42 -2
  340. package/src/metadata-builder/models.ts +39 -1
  341. package/src/metadata-builder/parsers/ai-toolcall-parser.ts +152 -0
  342. package/src/metadata-builder/parsers/section-tool-arguments.ts +138 -24
  343. package/src/metadata-builder/sanitizers/__tests__/section-args-validator.test.ts +659 -0
  344. package/src/metadata-builder/sanitizers/rte-schema-check.ts +99 -0
  345. package/src/metadata-builder/sanitizers/sanitizer-rules.ts +97 -0
  346. package/src/metadata-builder/sanitizers/section-args-validator.ts +445 -0
  347. package/src/shared/content-settings/components/content-settings/ContentSettings.mixin.ts +10 -16
  348. package/src/shared/content-settings/components/content-settings/ContentSettings.stories.ts +0 -1
  349. package/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.ts +6 -10
  350. package/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.vue +1 -23
  351. package/src/shared/content-settings/components/testimonial-items-field/TestimonialItemsField.vue +0 -15
  352. package/src/shared/content-settings/components/text-items-field/TextItemsField.vue +0 -15
  353. package/src/shared/navigation-style-settings/store/index.ts +5 -0
  354. package/src/shared/page-navigation/store/page-navigation-store.ts +4 -31
  355. package/src/shared/page-navigation/utils/nav-order-utils.ts +32 -0
  356. package/src/shared/side-bar/components/SideBar.vue +14 -1
  357. package/src/shared/side-bar/store/side-bar-store.ts +0 -20
  358. package/src/utils/build-asset-manifest.ts +153 -0
  359. package/src/utils/minify-brand-page-metadata.ts +362 -130
  360. package/lib/src/brand-page-maker/composables/ai-chat/useAiChat.js +0 -368
  361. package/lib/src/brand-page-maker/composables/ai-chat/useAiTextEditPrompts.d.ts +0 -18
  362. package/lib/src/brand-page-maker/composables/ai-chat/useAiTextEditPrompts.js +0 -144
  363. package/lib/src/brand-page-maker/stores/ai-thread/ai-thread-store.d.ts +0 -155
  364. package/lib/src/brand-page-maker/stores/ai-thread/ai-thread-store.js +0 -25
  365. package/lib/src/brand-page-maker/utils/mixpanel.util.d.ts +0 -1
  366. package/lib/src/brand-page-maker/utils/mixpanel.util.js +0 -29
  367. package/lib/src/bundled-translations-CNK7l6_v.js +0 -173
  368. package/lib/src/bundled-translations.de-DE-BLE4_y0H.js +0 -173
  369. package/lib/src/bundled-translations.es-ES-thO9osbg.js +0 -173
  370. package/lib/src/bundled-translations.fr-CA-BZkhiNgU.js +0 -173
  371. package/lib/src/bundled-translations.fr-FR-bhDLPKgZ.js +0 -173
  372. package/lib/src/bundled-translations.pt-BR-CI9a5Bq1.js +0 -173
  373. package/lib/src/bundled-translations.pt-PT-DBoErBaq.js +0 -173
  374. package/src/brand-page-maker/components/ai-text-edit/AiTextEdit.vue +0 -154
  375. package/src/brand-page-maker/composables/ai-chat/useAiChat.ts +0 -562
  376. package/src/brand-page-maker/composables/ai-chat/useAiTextEditPrompts.ts +0 -196
  377. package/src/brand-page-maker/stores/ai-thread/ai-thread-store.ts +0 -31
  378. package/src/brand-page-maker/utils/mixpanel.util.ts +0 -42
  379. package/src/shared/content-settings/components/generate-ai-button/GenerateAiButton.vue +0 -114
  380. package/src/shared/content-settings/components/generate-ai-modal/GenerateAiModal.vue +0 -761
@@ -1,7 +1,22 @@
1
- import { applyScalarFields, applyStyleFields, applyRTEStyles, } from '../section-field-utils';
1
+ import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
2
+ import { isTiptapDocument, } from '../../parsers/section-tool-arguments';
3
+ import { applyScalarFields, applyStyleFields, resolveGlobalPresetIntoStyle, } from '../section-field-utils';
4
+ import { applyColorThemeToReplacements, resolveShapeColorReplacementsAsync, } from '../shape-color-utils';
2
5
  import { BaseSectionBuilder } from './base-section-builder';
3
- const applyShapeItems = (content, items) => {
4
- content.items = items.map((item, index) => ({
6
+ import { validateShapesSection } from '../section-rules/shapes-section.rules';
7
+ const resolveItemColorsAsync = async (item, existing, prevImageUrl) => {
8
+ let colors = existing ?? [];
9
+ const newUrl = item.shape_url ?? item.icon_image_url;
10
+ if (newUrl && newUrl !== prevImageUrl) {
11
+ colors = await resolveShapeColorReplacementsAsync(newUrl);
12
+ }
13
+ if (item.color_theme) {
14
+ colors = applyColorThemeToReplacements(colors, item.color_theme);
15
+ }
16
+ return colors;
17
+ };
18
+ const applyShapeItemsAsync = async (content, items) => {
19
+ content.items = await Promise.all(items.map(async (item, index) => ({
5
20
  imageUrl: item.shape_url || item.icon_image_url || '',
6
21
  imageTitle: '',
7
22
  width: 0,
@@ -11,20 +26,20 @@ const applyShapeItems = (content, items) => {
11
26
  title: item.heading || '',
12
27
  paragraph: item.text || '',
13
28
  itemsId: index,
14
- colorReplacements: [],
15
- keepColor: item.keep_color ?? false,
16
- }));
29
+ colorReplacements: await resolveItemColorsAsync(item, [], undefined),
30
+ })));
17
31
  };
18
- const mergeShapeItems = (content, items, replaceAll) => {
32
+ const mergeShapeItemsAsync = async (content, items, replaceAll) => {
19
33
  const hasIndexedItems = items.some((item) => item.item_index !== undefined);
20
34
  if (hasIndexedItems) {
21
- for (const item of items) {
35
+ await Promise.all(items.map(async (item) => {
22
36
  const targetIndex = item.item_index;
23
37
  if (targetIndex === undefined ||
24
38
  targetIndex < 0 ||
25
39
  !content.items?.[targetIndex])
26
- continue;
40
+ return;
27
41
  const existing = content.items[targetIndex];
42
+ const prevImageUrl = existing.imageUrl;
28
43
  if (item.shape_url !== undefined || item.icon_image_url !== undefined) {
29
44
  existing.imageUrl =
30
45
  item.shape_url ?? item.icon_image_url ?? existing.imageUrl;
@@ -33,13 +48,14 @@ const mergeShapeItems = (content, items, replaceAll) => {
33
48
  existing.title = item.heading;
34
49
  if (item.text !== undefined)
35
50
  existing.paragraph = item.text;
36
- if (item.keep_color !== undefined) {
37
- existing.keepColor = item.keep_color;
51
+ if (item.shape_url !== undefined || item.color_theme !== undefined) {
52
+ existing.colorReplacements = await resolveItemColorsAsync(item, existing.colorReplacements, prevImageUrl);
38
53
  }
39
- }
54
+ }));
40
55
  return;
41
56
  }
42
- const updatedItems = items.map((item, index) => {
57
+ const itemsToMerge = items.filter((item) => item.insert_at === undefined);
58
+ const updatedItems = await Promise.all(itemsToMerge.map(async (item, index) => {
43
59
  const existing = content.items?.[index];
44
60
  const imageUrl = item.shape_url ?? item.icon_image_url ?? existing?.imageUrl ?? '';
45
61
  return {
@@ -53,32 +69,53 @@ const mergeShapeItems = (content, items, replaceAll) => {
53
69
  title: item.heading ?? existing?.title ?? '',
54
70
  paragraph: item.text ?? existing?.paragraph ?? '',
55
71
  itemsId: existing?.itemsId ?? index,
56
- colorReplacements: existing?.colorReplacements ?? [],
57
- keepColor: item.keep_color ??
58
- (existing && 'keepColor' in existing ? existing.keepColor : false),
72
+ colorReplacements: await resolveItemColorsAsync(item, existing?.colorReplacements, existing?.imageUrl),
59
73
  };
60
- });
61
- if (!replaceAll && content.items && content.items.length > items.length) {
62
- const remaining = content.items.slice(items.length);
74
+ }));
75
+ if (!replaceAll &&
76
+ content.items &&
77
+ content.items.length > itemsToMerge.length) {
78
+ const remaining = content.items.slice(itemsToMerge.length);
63
79
  updatedItems.push(...remaining);
64
80
  }
65
81
  content.items = updatedItems;
66
82
  };
67
83
  export class ShapesSectionBuilder extends BaseSectionBuilder {
84
+ get sectionValidate() {
85
+ return validateShapesSection;
86
+ }
68
87
  async buildAsync(model) {
69
88
  this.log('Build called');
70
89
  const validation = await this.validateAsync();
71
90
  if (validation.errors.length) {
72
91
  return { request: this.request, model, errors: validation.errors };
73
92
  }
74
- const resolved = this.resolveContent(model);
93
+ const resolved = this.resolveAndRepositionContent(model);
75
94
  if ('error' in resolved)
76
95
  return resolved.error;
77
96
  const content = resolved.content;
78
97
  applyScalarFields(content, this.args, this.sectionType);
79
- applyStyleFields(content, this.args, this.sectionType);
80
- applyRTEStyles(content, this.args, this.sectionType);
98
+ applyStyleFields(content, this.args, this.sectionType, this.getGlobalTextStyles(model));
81
99
  const args = this.args;
100
+ const textStyleOptions = model.styles?.textStyles?.textStyleOptions;
101
+ if (args.title !== undefined) {
102
+ if (isTiptapDocument(args.title)) {
103
+ content.title = tiptapJsonToHtml(args.title);
104
+ content.titleStyle = resolveGlobalPresetIntoStyle(content.titleStyle, textStyleOptions);
105
+ }
106
+ else {
107
+ content.title = args.title;
108
+ }
109
+ }
110
+ if (args.description !== undefined) {
111
+ if (isTiptapDocument(args.description)) {
112
+ content.description = tiptapJsonToHtml(args.description);
113
+ content.descriptionStyle = resolveGlobalPresetIntoStyle(content.descriptionStyle, textStyleOptions);
114
+ }
115
+ else {
116
+ content.description = args.description;
117
+ }
118
+ }
82
119
  if (args.background_style && typeof args.background_style === 'object') {
83
120
  const existing = content.backgroundStyle || {};
84
121
  content.backgroundStyle = {
@@ -101,10 +138,10 @@ export class ShapesSectionBuilder extends BaseSectionBuilder {
101
138
  }
102
139
  if (args.items && Array.isArray(args.items)) {
103
140
  if (this.mode === 'create') {
104
- applyShapeItems(content, args.items);
141
+ await applyShapeItemsAsync(content, args.items);
105
142
  }
106
143
  else {
107
- mergeShapeItems(content, args.items, !!args._replace_items);
144
+ await mergeShapeItemsAsync(content, args.items, !!args._replace_items);
108
145
  }
109
146
  }
110
147
  // Phase 2: Item operations (remove, insert, reorder)
@@ -121,9 +158,16 @@ export class ShapesSectionBuilder extends BaseSectionBuilder {
121
158
  // Process inserts in reverse order of insert_at to preserve indices
122
159
  const sortedInserts = [...insertItems].sort((a, b) => (b.insert_at ?? 0) - (a.insert_at ?? 0));
123
160
  for (const item of sortedInserts) {
161
+ const insertUrl = item.shape_url ?? item.icon_image_url ?? '';
162
+ // Skip if this shape/icon already exists — defensive against duplicate
163
+ // tool call application
164
+ if (insertUrl &&
165
+ content.items?.some((existing) => existing.imageUrl === insertUrl)) {
166
+ continue;
167
+ }
124
168
  const pos = Math.max(0, Math.min(item.insert_at ?? 0, content.items?.length ?? 0));
125
169
  const newItem = {
126
- imageUrl: item.shape_url ?? item.icon_image_url ?? '',
170
+ imageUrl: insertUrl,
127
171
  imageTitle: '',
128
172
  width: 0,
129
173
  height: 0,
@@ -132,8 +176,7 @@ export class ShapesSectionBuilder extends BaseSectionBuilder {
132
176
  title: item.heading ?? '',
133
177
  paragraph: item.text ?? '',
134
178
  itemsId: pos,
135
- colorReplacements: [],
136
- keepColor: item.keep_color ?? false,
179
+ colorReplacements: await resolveItemColorsAsync(item, [], undefined),
137
180
  };
138
181
  content.items = content.items ?? [];
139
182
  content.items.splice(pos, 0, newItem);
@@ -1,6 +1,8 @@
1
1
  import type { SocialLinksContent, BrandPageModel } from '../../../brand-page/models';
2
2
  import type { BuilderResult } from '../../models';
3
3
  import { BaseSectionBuilder } from './base-section-builder';
4
+ import { validateSocialLinks } from '../section-rules/social-links.rules';
4
5
  export declare class SocialLinksBuilder extends BaseSectionBuilder<SocialLinksContent> {
6
+ protected get sectionValidate(): typeof validateSocialLinks;
5
7
  buildAsync(model: BrandPageModel): Promise<BuilderResult>;
6
8
  }
@@ -1,5 +1,6 @@
1
- import { applyScalarFields } from '../section-field-utils';
1
+ import { applyScalarFields, applyStyleFields } from '../section-field-utils';
2
2
  import { BaseSectionBuilder } from './base-section-builder';
3
+ import { validateSocialLinks } from '../section-rules/social-links.rules';
3
4
  const applySocialLinks = (content, links) => {
4
5
  content.links = links.map((link) => ({
5
6
  imageUrl: link.platform || '',
@@ -25,17 +26,21 @@ const mergeSocialLinks = (content, links, replaceAll) => {
25
26
  content.links = updatedLinks;
26
27
  };
27
28
  export class SocialLinksBuilder extends BaseSectionBuilder {
29
+ get sectionValidate() {
30
+ return validateSocialLinks;
31
+ }
28
32
  async buildAsync(model) {
29
33
  this.log('Build called');
30
34
  const validation = await this.validateAsync();
31
35
  if (validation.errors.length) {
32
36
  return { request: this.request, model, errors: validation.errors };
33
37
  }
34
- const resolved = this.resolveContent(model);
38
+ const resolved = this.resolveAndRepositionContent(model);
35
39
  if ('error' in resolved)
36
40
  return resolved.error;
37
41
  const content = resolved.content;
38
42
  applyScalarFields(content, this.args, this.sectionType);
43
+ applyStyleFields(content, this.args, this.sectionType, this.getGlobalTextStyles(model));
39
44
  const args = this.args;
40
45
  if (args.links && Array.isArray(args.links)) {
41
46
  if (this.mode === 'create') {
@@ -1,6 +1,8 @@
1
1
  import type { TestimonialSectionContent, BrandPageModel } from '../../../brand-page/models';
2
2
  import type { BuilderResult } from '../../models';
3
3
  import { BaseSectionBuilder } from './base-section-builder';
4
+ import { validateTestimonialSection } from '../section-rules/testimonial-section.rules';
4
5
  export declare class TestimonialSectionBuilder extends BaseSectionBuilder<TestimonialSectionContent> {
6
+ protected get sectionValidate(): typeof validateTestimonialSection;
5
7
  buildAsync(model: BrandPageModel): Promise<BuilderResult>;
6
8
  }
@@ -1,67 +1,117 @@
1
- import { applyScalarFields, applyStyleFields } from '../section-field-utils';
1
+ import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
2
+ import { isTiptapDocument, } from '../../parsers/section-tool-arguments';
3
+ import { applyScalarFields, applyStyleFields, resolveGlobalPresetIntoStyle, } from '../section-field-utils';
4
+ import { applyColorThemeToReplacements, resolveShapeColorReplacementsAsync, } from '../shape-color-utils';
2
5
  import { BaseSectionBuilder } from './base-section-builder';
3
- const applyTestimonialItems = (content, items) => {
4
- content.items = items.map((item) => ({
5
- imageUrl: item.avatar_image_url || '',
6
+ import { validateTestimonialSection, TESTIMONIAL_ITEM_CAP, } from '../section-rules/testimonial-section.rules';
7
+ const resolveItemColorsAsync = async (item, existing, prevImageUrl) => {
8
+ let colors = existing ?? [];
9
+ if (item.avatar_shape_url && item.avatar_shape_url !== prevImageUrl) {
10
+ colors = await resolveShapeColorReplacementsAsync(item.avatar_shape_url);
11
+ }
12
+ if (item.color_theme) {
13
+ colors = applyColorThemeToReplacements(colors, item.color_theme);
14
+ }
15
+ return colors;
16
+ };
17
+ const applyTestimonialItemsAsync = async (content, items) => {
18
+ content.items = await Promise.all(items.map(async (item) => ({
19
+ imageUrl: item.avatar_shape_url || item.avatar_image_url || '',
6
20
  name: item.name || '',
7
21
  position: item.position || '',
8
22
  testimonials: item.testimonial || '',
9
- colorReplacements: [],
10
- mediaType: 'image',
11
- }));
23
+ colorReplacements: await resolveItemColorsAsync(item, [], undefined),
24
+ mediaType: item.avatar_shape_url ? 'shape' : 'image',
25
+ })));
12
26
  };
13
- const mergeTestimonialItems = (content, items, replaceAll) => {
27
+ const mergeTestimonialItemsAsync = async (content, items, replaceAll) => {
14
28
  const hasIndexedItems = items.some((item) => item.item_index !== undefined);
15
29
  if (hasIndexedItems) {
16
- for (const item of items) {
30
+ await Promise.all(items.map(async (item) => {
17
31
  const targetIndex = item.item_index;
18
32
  if (targetIndex === undefined ||
19
33
  targetIndex < 0 ||
20
34
  !content.items?.[targetIndex])
21
- continue;
35
+ return;
22
36
  const existing = content.items[targetIndex];
23
- if (item.avatar_image_url !== undefined)
37
+ const prevImageUrl = existing.imageUrl;
38
+ if (item.avatar_shape_url !== undefined) {
39
+ existing.imageUrl = item.avatar_shape_url;
40
+ existing.mediaType = 'shape';
41
+ }
42
+ else if (item.avatar_image_url !== undefined) {
24
43
  existing.imageUrl = item.avatar_image_url;
44
+ existing.mediaType = 'image';
45
+ }
25
46
  if (item.name !== undefined)
26
47
  existing.name = item.name;
27
48
  if (item.position !== undefined)
28
49
  existing.position = item.position;
29
50
  if (item.testimonial !== undefined)
30
51
  existing.testimonials = item.testimonial;
31
- }
52
+ if (item.avatar_shape_url !== undefined ||
53
+ item.color_theme !== undefined) {
54
+ existing.colorReplacements = await resolveItemColorsAsync(item, existing.colorReplacements, prevImageUrl);
55
+ }
56
+ }));
32
57
  return;
33
58
  }
34
- const updatedItems = items.map((item, index) => {
59
+ const itemsToMerge = items.filter((item) => item.insert_at === undefined);
60
+ const updatedItems = await Promise.all(itemsToMerge.map(async (item, index) => {
35
61
  const existing = content.items?.[index];
62
+ const imageUrl = item.avatar_shape_url ??
63
+ item.avatar_image_url ??
64
+ existing?.imageUrl ??
65
+ '';
66
+ const mediaType = item.avatar_shape_url
67
+ ? 'shape'
68
+ : item.avatar_image_url
69
+ ? 'image'
70
+ : existing?.mediaType ?? 'image';
36
71
  return {
37
72
  ...(existing || {}),
38
- imageUrl: item.avatar_image_url ?? existing?.imageUrl ?? '',
73
+ imageUrl,
39
74
  name: item.name ?? existing?.name ?? '',
40
75
  position: item.position ?? existing?.position ?? '',
41
76
  testimonials: item.testimonial ?? existing?.testimonials ?? '',
42
- colorReplacements: existing?.colorReplacements ?? [],
43
- mediaType: existing?.mediaType ?? 'image',
77
+ colorReplacements: await resolveItemColorsAsync(item, existing?.colorReplacements, existing?.imageUrl),
78
+ mediaType,
44
79
  };
45
- });
46
- if (!replaceAll && content.items && content.items.length > items.length) {
47
- updatedItems.push(...content.items.slice(items.length));
80
+ }));
81
+ if (!replaceAll &&
82
+ content.items &&
83
+ content.items.length > itemsToMerge.length) {
84
+ updatedItems.push(...content.items.slice(itemsToMerge.length));
48
85
  }
49
86
  content.items = updatedItems;
50
87
  };
51
88
  export class TestimonialSectionBuilder extends BaseSectionBuilder {
89
+ get sectionValidate() {
90
+ return validateTestimonialSection;
91
+ }
52
92
  async buildAsync(model) {
53
93
  this.log('Build called');
54
94
  const validation = await this.validateAsync();
55
95
  if (validation.errors.length) {
56
96
  return { request: this.request, model, errors: validation.errors };
57
97
  }
58
- const resolved = this.resolveContent(model);
98
+ const resolved = this.resolveAndRepositionContent(model);
59
99
  if ('error' in resolved)
60
100
  return resolved.error;
61
101
  const content = resolved.content;
62
102
  applyScalarFields(content, this.args, this.sectionType);
63
- applyStyleFields(content, this.args, this.sectionType);
103
+ applyStyleFields(content, this.args, this.sectionType, this.getGlobalTextStyles(model));
64
104
  const args = this.args;
105
+ const textStyleOptions = model.styles?.textStyles?.textStyleOptions;
106
+ if (args.title !== undefined) {
107
+ if (isTiptapDocument(args.title)) {
108
+ content.title = tiptapJsonToHtml(args.title);
109
+ content.titleStyle = resolveGlobalPresetIntoStyle(content.titleStyle, textStyleOptions);
110
+ }
111
+ else {
112
+ content.title = args.title;
113
+ }
114
+ }
65
115
  if (args.background_style && typeof args.background_style === 'object') {
66
116
  const existing = content.backgroundStyle || {};
67
117
  content.backgroundStyle = {
@@ -84,10 +134,10 @@ export class TestimonialSectionBuilder extends BaseSectionBuilder {
84
134
  }
85
135
  if (args.items && Array.isArray(args.items)) {
86
136
  if (this.mode === 'create') {
87
- applyTestimonialItems(content, args.items);
137
+ await applyTestimonialItemsAsync(content, args.items);
88
138
  }
89
139
  else {
90
- mergeTestimonialItems(content, args.items, !!args._replace_items);
140
+ await mergeTestimonialItemsAsync(content, args.items, !!args._replace_items);
91
141
  }
92
142
  }
93
143
  // Phase 2: Item operations (remove, insert, reorder)
@@ -105,12 +155,12 @@ export class TestimonialSectionBuilder extends BaseSectionBuilder {
105
155
  for (const item of sortedInserts) {
106
156
  const pos = Math.max(0, Math.min(item.insert_at ?? 0, content.items?.length ?? 0));
107
157
  const newItem = {
108
- imageUrl: item.avatar_image_url ?? '',
158
+ imageUrl: item.avatar_shape_url ?? item.avatar_image_url ?? '',
109
159
  name: item.name ?? '',
110
160
  position: item.position ?? '',
111
161
  testimonials: item.testimonial ?? '',
112
- colorReplacements: [],
113
- mediaType: 'image',
162
+ colorReplacements: await resolveItemColorsAsync(item, [], undefined),
163
+ mediaType: item.avatar_shape_url ? 'shape' : 'image',
114
164
  };
115
165
  content.items = content.items ?? [];
116
166
  content.items.splice(pos, 0, newItem);
@@ -128,6 +178,21 @@ export class TestimonialSectionBuilder extends BaseSectionBuilder {
128
178
  }
129
179
  }
130
180
  }
181
+ // Post-merge cap check. itemCapCheck only fires for create / update with
182
+ // _replace_items, so insert_at on an already-full section silently bloats
183
+ // the array. Surface as an error so the AI retry loop gets a signal and
184
+ // can reissue with _remove_item_indices or fewer inserts.
185
+ // brandSite key mirrors base-section-builder's hardcoded brandPageType.
186
+ const cap = TESTIMONIAL_ITEM_CAP.brandSite;
187
+ if (content.items && content.items.length > cap) {
188
+ return {
189
+ request: this.request,
190
+ model,
191
+ errors: [
192
+ `"${TESTIMONIAL_ITEM_CAP.arrayField}" has ${content.items.length} items but "testimonial-section" supports a maximum of ${cap}`,
193
+ ],
194
+ };
195
+ }
131
196
  return { request: this.request, model };
132
197
  }
133
198
  }
@@ -1,6 +1,8 @@
1
1
  import type { BuilderResult } from '../../models';
2
2
  import type { TextContent, BrandPageModel } from '../../../brand-page/models';
3
3
  import { BaseSectionBuilder } from './base-section-builder';
4
+ import { validateTextSection } from '../section-rules/text-section.rules';
4
5
  export declare class TextSectionBuilder extends BaseSectionBuilder<TextContent> {
6
+ protected get sectionValidate(): typeof validateTextSection;
5
7
  buildAsync(model: BrandPageModel): Promise<BuilderResult>;
6
8
  }
@@ -1,17 +1,29 @@
1
- import { updateRTEText } from '../../helpers/rte.helpers';
2
- import { applyScalarFields, applyStyleFields } from '../section-field-utils';
1
+ import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
2
+ import { isTiptapDocument, } from '../../parsers/section-tool-arguments';
3
+ import { applyScalarFields, applyStyleFields, resolveGlobalPresetIntoStyle, } from '../section-field-utils';
3
4
  import { BaseSectionBuilder } from './base-section-builder';
4
- const createTextItem = (item, baseStyle) => {
5
+ import { validateTextSection } from '../section-rules/text-section.rules';
6
+ /** Resolve a RichTextField (string or TiptapDocument) to a plain HTML string. */
7
+ const resolveText = (value) => {
8
+ if (isTiptapDocument(value))
9
+ return { html: tiptapJsonToHtml(value), wasTiptap: true };
10
+ return { html: typeof value === 'string' ? value : '', wasTiptap: false };
11
+ };
12
+ const clearTextStyleTypeIfTiptap = (style, wasTiptap, textStyleOptions) => wasTiptap
13
+ ? resolveGlobalPresetIntoStyle(style, textStyleOptions)
14
+ : style;
15
+ const createTextItem = (item, baseStyle, textStyleOptions) => {
5
16
  const textStyle = (item.text_style ? { ...baseStyle, ...item.text_style } : { ...baseStyle });
17
+ const { html, wasTiptap } = resolveText(item.text);
6
18
  return {
7
- text: item.text || '',
8
- textStyle,
19
+ text: html,
20
+ textStyle: clearTextStyleTypeIfTiptap(textStyle, wasTiptap, textStyleOptions),
9
21
  };
10
22
  };
11
- const applyTextItems = (content, items) => {
12
- content.textItems = items.map((item) => createTextItem(item, content.textStyle || {}));
23
+ const applyTextItems = (content, items, textStyleOptions) => {
24
+ content.textItems = items.map((item) => createTextItem(item, content.textStyle || {}, textStyleOptions));
13
25
  };
14
- const mergeTextItems = (content, items, replaceAll) => {
26
+ const mergeTextItems = (content, items, replaceAll, textStyleOptions) => {
15
27
  const hasIndexedItems = items.some((item) => item.item_index !== undefined);
16
28
  if (hasIndexedItems) {
17
29
  for (const item of items) {
@@ -21,32 +33,36 @@ const mergeTextItems = (content, items, replaceAll) => {
21
33
  !content.textItems?.[targetIndex])
22
34
  continue;
23
35
  const existing = content.textItems[targetIndex];
24
- if (item.text !== undefined)
25
- existing.text = item.text;
36
+ if (item.text !== undefined) {
37
+ const { html, wasTiptap } = resolveText(item.text);
38
+ existing.text = html;
39
+ existing.textStyle = clearTextStyleTypeIfTiptap(existing.textStyle || {}, wasTiptap, textStyleOptions);
40
+ }
26
41
  if (item.text_style && typeof item.text_style === 'object') {
27
42
  const mergedStyle = (item.text_style
28
43
  ? { ...(existing.textStyle || {}), ...item.text_style }
29
44
  : existing.textStyle || {});
30
45
  existing.textStyle = mergedStyle;
31
- existing.text = updateRTEText(existing.text, mergedStyle);
32
46
  }
33
47
  }
34
48
  return;
35
49
  }
36
- const updatedItems = items.map((item, index) => {
50
+ const itemsToMerge = items.filter((item) => item.insert_at === undefined);
51
+ const updatedItems = itemsToMerge.map((item, index) => {
37
52
  const existing = content.textItems?.[index];
38
53
  const baseStyle = existing?.textStyle || content.textStyle || {};
39
54
  const mergedStyle = (item.text_style ? { ...baseStyle, ...item.text_style } : baseStyle);
40
- const text = item.text ?? existing?.text ?? '';
55
+ const resolved = item.text !== undefined ? resolveText(item.text) : null;
56
+ const text = resolved ? resolved.html : existing?.text ?? '';
41
57
  return {
42
- text: item.text_style ? updateRTEText(text, mergedStyle) : text,
43
- textStyle: mergedStyle,
58
+ text,
59
+ textStyle: clearTextStyleTypeIfTiptap(mergedStyle, resolved?.wasTiptap ?? false, textStyleOptions),
44
60
  };
45
61
  });
46
62
  if (!replaceAll &&
47
63
  content.textItems &&
48
- content.textItems.length > items.length) {
49
- updatedItems.push(...content.textItems.slice(items.length));
64
+ content.textItems.length > itemsToMerge.length) {
65
+ updatedItems.push(...content.textItems.slice(itemsToMerge.length));
50
66
  }
51
67
  content.textItems = updatedItems;
52
68
  };
@@ -54,19 +70,21 @@ const mergeTextItems = (content, items, replaceAll) => {
54
70
  * Handles the single `text` + `text_style` fields (BrandPage/BrandContact
55
71
  * or shorthand for the first item).
56
72
  */
57
- const applySingleTextField = (content, args) => {
58
- if (typeof args.text === 'string') {
73
+ const applySingleTextField = (content, args, textStyleOptions) => {
74
+ if (args.text !== undefined) {
75
+ const { html, wasTiptap } = resolveText(args.text);
59
76
  if (Array.isArray(content.textItems) && content.textItems.length > 0) {
60
77
  content.textItems[0] = {
61
78
  ...content.textItems[0],
62
- text: args.text,
79
+ text: html,
80
+ textStyle: clearTextStyleTypeIfTiptap(content.textItems[0].textStyle || {}, wasTiptap, textStyleOptions),
63
81
  };
64
82
  }
65
83
  else {
66
84
  content.textItems = [
67
85
  {
68
- text: args.text,
69
- textStyle: { ...(content.textStyle || {}) },
86
+ text: html,
87
+ textStyle: clearTextStyleTypeIfTiptap({ ...(content.textStyle || {}) }, wasTiptap, textStyleOptions),
70
88
  },
71
89
  ];
72
90
  }
@@ -77,39 +95,42 @@ const applySingleTextField = (content, args) => {
77
95
  content.textItems.length > 0) {
78
96
  const mergedStyle = {
79
97
  ...(content.textItems[0].textStyle || {}),
80
- ...(content.textStyle || {}),
98
+ ...args.text_style,
81
99
  };
82
100
  content.textItems[0] = {
83
101
  ...content.textItems[0],
84
102
  textStyle: mergedStyle,
85
- text: updateRTEText(content.textItems[0].text, mergedStyle),
86
103
  };
87
104
  }
88
105
  };
89
106
  export class TextSectionBuilder extends BaseSectionBuilder {
107
+ get sectionValidate() {
108
+ return validateTextSection;
109
+ }
90
110
  async buildAsync(model) {
91
111
  this.log('Build called');
92
112
  const validation = await this.validateAsync();
93
113
  if (validation.errors.length) {
94
114
  return { request: this.request, model, errors: validation.errors };
95
115
  }
96
- const resolved = this.resolveContent(model);
116
+ const resolved = this.resolveAndRepositionContent(model);
97
117
  if ('error' in resolved)
98
118
  return resolved.error;
99
119
  const content = resolved.content;
120
+ const textStyleOptions = model.styles?.textStyles?.textStyleOptions;
100
121
  applyScalarFields(content, this.args, this.sectionType);
101
- applyStyleFields(content, this.args, this.sectionType);
122
+ applyStyleFields(content, this.args, this.sectionType, this.getGlobalTextStyles(model));
102
123
  const args = this.args;
103
124
  if (args.items && Array.isArray(args.items)) {
104
125
  if (this.mode === 'create') {
105
- applyTextItems(content, args.items);
126
+ applyTextItems(content, args.items, textStyleOptions);
106
127
  }
107
128
  else {
108
- mergeTextItems(content, args.items, !!args._replace_items);
129
+ mergeTextItems(content, args.items, !!args._replace_items, textStyleOptions);
109
130
  }
110
131
  }
111
132
  else {
112
- applySingleTextField(content, args);
133
+ applySingleTextField(content, args, textStyleOptions);
113
134
  }
114
135
  // Phase 2: Item operations (remove, insert, reorder)
115
136
  if (args._remove_item_indices?.length && content.textItems) {
@@ -129,9 +150,10 @@ export class TextSectionBuilder extends BaseSectionBuilder {
129
150
  const textStyle = (item.text_style
130
151
  ? { ...baseStyle, ...item.text_style }
131
152
  : { ...baseStyle });
153
+ const { html, wasTiptap } = resolveText(item.text);
132
154
  const newItem = {
133
- text: item.text ?? '',
134
- textStyle,
155
+ text: html,
156
+ textStyle: clearTextStyleTypeIfTiptap(textStyle, wasTiptap, textStyleOptions),
135
157
  };
136
158
  content.textItems = content.textItems ?? [];
137
159
  content.textItems.splice(pos, 0, newItem);
@@ -155,6 +177,22 @@ export class TextSectionBuilder extends BaseSectionBuilder {
155
177
  backgroundColor: args.background_color ?? '',
156
178
  };
157
179
  }
180
+ // CREATE-mode: the editor's `createInitialTextContent` factory seeds
181
+ // `content.text` with the i18n placeholder "This is a sample text" as a
182
+ // click-to-add affordance for the manual maker UI. That placeholder
183
+ // must not survive an AI-driven create. The AI flow writes resolved
184
+ // copy into `content.textItems` only — never to the legacy single-text
185
+ // `content.text` field — so when the renderer reads `content.text`
186
+ // (non-brandSite path in Text.vue, or any fallback for empty
187
+ // textItems), it falls back to the placeholder.
188
+ //
189
+ // Mirror the resolved first item's text into the legacy field so both
190
+ // renderer paths agree. Same pattern as yesterday's about-section /
191
+ // contact-form / testimonial RTE fix — clear the factory default and
192
+ // align both fields with the AI's actual output.
193
+ if (this.mode === 'create') {
194
+ content.text = content.textItems?.[0]?.text ?? '';
195
+ }
158
196
  return { request: this.request, model };
159
197
  }
160
198
  }
@@ -1,3 +1,3 @@
1
- import type { Content } from '../../brand-page/models';
1
+ import type { BrandPageType, Content } from '../../brand-page/models';
2
2
  import type { SectionType } from '../parsers/section-tool-arguments';
3
- export declare const createDefaultSectionContent: (sectionType: SectionType) => Content | null;
3
+ export declare const createDefaultSectionContent: (sectionType: SectionType, brandPageType?: BrandPageType) => Content | null;
@@ -3,11 +3,17 @@
3
3
  * Used by BaseSectionBuilder when adding a new section to a page.
4
4
  */
5
5
  import { CONTENT_SETTINGS_CONFIGS } from '../../brand-page-maker/constants/config-settings-constant';
6
- export const createDefaultSectionContent = (sectionType) => {
6
+ export const createDefaultSectionContent = (sectionType, brandPageType) => {
7
7
  const configs = CONTENT_SETTINGS_CONFIGS();
8
8
  const config = configs[sectionType];
9
9
  if (!config) {
10
10
  return null;
11
11
  }
12
- return config.createInitialContent();
12
+ const options = brandPageType
13
+ ? {
14
+ brandPageType,
15
+ userState: { emailAddress: '' },
16
+ }
17
+ : undefined;
18
+ return config.createInitialContent(options);
13
19
  };