@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
@@ -0,0 +1,49 @@
1
+ import {} from '../../brand-page/models';
2
+ import { getPageSlugFromPageTitle } from '../../brand-page-maker/utils/slug.util';
3
+ import { BaseMetadataBuilder, } from '../models';
4
+ import { RENAME_PAGE_CHECKS, } from './section-rules/rename-page.rules';
5
+ export class RenamePageBuilder extends BaseMetadataBuilder {
6
+ constructor(request, logger) {
7
+ super(request, logger);
8
+ }
9
+ async validateAsync() {
10
+ const errors = RENAME_PAGE_CHECKS.flatMap((check) => {
11
+ const err = check(this.request.payload);
12
+ return err ? [err] : [];
13
+ });
14
+ return { errors };
15
+ }
16
+ async buildAsync(model) {
17
+ this.log('Build called');
18
+ const validation = await this.validateAsync();
19
+ if (validation.errors.length) {
20
+ return { request: this.request, model, errors: validation.errors };
21
+ }
22
+ const { pageId, pageName } = this.request.payload;
23
+ const page = model.pages.find((p) => p.id === pageId);
24
+ if (!page) {
25
+ return {
26
+ request: this.request,
27
+ model,
28
+ errors: [`Page with ID "${pageId}" not found`],
29
+ };
30
+ }
31
+ const previousTitle = page.title;
32
+ page.title = pageName;
33
+ // Update the matching nav route's display name and recompute its slug.
34
+ // Slug uniqueness is computed against sibling routes (excluding the route
35
+ // being renamed) so we don't collide with our own previous slug.
36
+ const route = model.nav.routes.find((r) => r.pageId === pageId);
37
+ if (route) {
38
+ const siblingSlugs = model.nav.routes
39
+ .filter((r) => r.id !== route.id)
40
+ .map((r) => r.pageSlug);
41
+ route.displayName = pageName;
42
+ route.pageSlug = getPageSlugFromPageTitle(pageName, siblingSlugs);
43
+ }
44
+ this.log({
45
+ message: `Renamed page "${previousTitle}" → "${pageName}" (${pageId})`,
46
+ });
47
+ return { request: this.request, model };
48
+ }
49
+ }
@@ -1,6 +1,8 @@
1
1
  import type { AboutSectionContent, BrandPageModel } from '../../../brand-page/models';
2
2
  import type { BuilderResult } from '../../models';
3
3
  import { BaseSectionBuilder } from './base-section-builder';
4
+ import { validateAboutSection } from '../section-rules/about-section.rules';
4
5
  export declare class AboutSectionBuilder extends BaseSectionBuilder<AboutSectionContent> {
6
+ protected get sectionValidate(): typeof validateAboutSection;
5
7
  buildAsync(model: BrandPageModel): Promise<BuilderResult>;
6
8
  }
@@ -1,18 +1,58 @@
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';
6
+ import { validateAboutSection } from '../section-rules/about-section.rules';
3
7
  export class AboutSectionBuilder extends BaseSectionBuilder {
8
+ get sectionValidate() {
9
+ return validateAboutSection;
10
+ }
4
11
  async buildAsync(model) {
5
12
  this.log('Build called');
6
13
  const validation = await this.validateAsync();
7
14
  if (validation.errors.length) {
8
15
  return { request: this.request, model, errors: validation.errors };
9
16
  }
10
- const resolved = this.resolveContent(model);
17
+ const resolved = this.resolveAndRepositionContent(model);
11
18
  if ('error' in resolved)
12
19
  return resolved.error;
13
- applyScalarFields(resolved.content, this.args, this.sectionType);
14
- applyStyleFields(resolved.content, this.args, this.sectionType);
15
20
  const aboutArgs = this.args;
21
+ const prevImageUrl = resolved.content.imageUrl;
22
+ applyScalarFields(resolved.content, this.args, this.sectionType);
23
+ applyStyleFields(resolved.content, this.args, this.sectionType, this.getGlobalTextStyles(model));
24
+ const textStyleOptions = model.styles?.textStyles?.textStyleOptions;
25
+ if (aboutArgs.title !== undefined) {
26
+ if (isTiptapDocument(aboutArgs.title)) {
27
+ resolved.content.title = tiptapJsonToHtml(aboutArgs.title);
28
+ resolved.content.titleStyle = resolveGlobalPresetIntoStyle(resolved.content.titleStyle, textStyleOptions);
29
+ }
30
+ else {
31
+ resolved.content.title = aboutArgs.title;
32
+ }
33
+ }
34
+ if (aboutArgs.paragraph !== undefined) {
35
+ if (isTiptapDocument(aboutArgs.paragraph)) {
36
+ resolved.content.paragraph = tiptapJsonToHtml(aboutArgs.paragraph);
37
+ resolved.content.paragraphStyle = resolveGlobalPresetIntoStyle(resolved.content.paragraphStyle, textStyleOptions);
38
+ }
39
+ else {
40
+ resolved.content.paragraph = aboutArgs.paragraph;
41
+ }
42
+ }
43
+ if (aboutArgs.about_shape_url) {
44
+ resolved.content.mediaType = 'shape';
45
+ if (aboutArgs.about_shape_url !== prevImageUrl) {
46
+ resolved.content.colorReplacements =
47
+ await resolveShapeColorReplacementsAsync(aboutArgs.about_shape_url);
48
+ }
49
+ }
50
+ else if (aboutArgs.about_image_url) {
51
+ resolved.content.mediaType = 'image';
52
+ }
53
+ if (aboutArgs.color_theme) {
54
+ resolved.content.colorReplacements = applyColorThemeToReplacements(resolved.content.colorReplacements ?? [], aboutArgs.color_theme);
55
+ }
16
56
  if (aboutArgs.background_color !== undefined) {
17
57
  resolved.content.backgroundStyle = {
18
58
  ...resolved.content.backgroundStyle,
@@ -1,6 +1,8 @@
1
1
  import type { BannerSectionContent, BrandPageModel } from '../../../brand-page/models';
2
2
  import type { BuilderResult } from '../../models';
3
3
  import { BaseSectionBuilder } from './base-section-builder';
4
+ import { validateBannerSection } from '../section-rules/banner-section.rules';
4
5
  export declare class BannerSectionBuilder extends BaseSectionBuilder<BannerSectionContent> {
6
+ protected get sectionValidate(): typeof validateBannerSection;
5
7
  buildAsync(model: BrandPageModel): Promise<BuilderResult>;
6
8
  }
@@ -1,32 +1,96 @@
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 { applyButtonLink, applyScalarFields, applyStyleFields, resolveGlobalPresetIntoStyle, } from '../section-field-utils';
4
+ import { applyColorThemeToReplacements, resolveShapeColorReplacementsAsync, } from '../shape-color-utils';
2
5
  import { BaseSectionBuilder } from './base-section-builder';
6
+ import { validateBannerSection } from '../section-rules/banner-section.rules';
3
7
  const applyBackgroundImage = (content, args) => {
4
8
  if (args.background_image_url) {
5
9
  content.media = undefined;
6
10
  content.mediaType = 'image';
7
11
  }
8
12
  };
13
+ const applyBackgroundShapeAsync = async (content, args, prevImageUrl) => {
14
+ if (args.background_shape_url) {
15
+ content.media = undefined;
16
+ content.mediaType = 'shape';
17
+ content.size = '100%';
18
+ if (args.background_shape_url !== prevImageUrl) {
19
+ content.colorReplacements = await resolveShapeColorReplacementsAsync(args.background_shape_url);
20
+ }
21
+ }
22
+ if (args.color_theme) {
23
+ content.colorReplacements = applyColorThemeToReplacements(content.colorReplacements ?? [], args.color_theme);
24
+ }
25
+ };
9
26
  export class BannerSectionBuilder extends BaseSectionBuilder {
27
+ get sectionValidate() {
28
+ return validateBannerSection;
29
+ }
10
30
  async buildAsync(model) {
11
31
  this.log('Build called');
12
32
  const validation = await this.validateAsync();
13
33
  if (validation.errors.length) {
14
34
  return { request: this.request, model, errors: validation.errors };
15
35
  }
16
- const resolved = this.resolveContent(model);
36
+ const resolved = this.resolveAndRepositionContent(model);
17
37
  if ('error' in resolved)
18
38
  return resolved.error;
19
- applyScalarFields(resolved.content, this.args, this.sectionType);
20
- applyStyleFields(resolved.content, this.args, this.sectionType);
21
- applyRTEStyles(resolved.content, this.args, this.sectionType);
22
- applyBackgroundImage(resolved.content, this.args);
39
+ // FOR TESTING PURPOSE: If the generated content contains "@test", return an error message to replace it with "@dev-test"
40
+ // LETS KEEP THIS FOR NOW TO TEST THE EVEN LOOPING OF THE BUILD PROCESS, SINCE WE HAVE SEEN SOME ISSUES WITH IT DURING TESTING
41
+ const strrr = JSON.stringify((this.request.payload?.arguments).title?.content || {});
42
+ if (strrr.includes('@test')) {
43
+ return {
44
+ request: this.request,
45
+ model,
46
+ errors: [
47
+ 'When there is generated text contain "@test", should return as "@dev-test" instead',
48
+ ],
49
+ };
50
+ }
51
+ // TEST END
23
52
  const bannerArgs = this.args;
53
+ const prevImageUrl = resolved.content.imageUrl;
54
+ applyScalarFields(resolved.content, this.args, this.sectionType);
55
+ applyButtonLink(resolved.content, bannerArgs);
56
+ applyStyleFields(resolved.content, this.args, this.sectionType, this.getGlobalTextStyles(model));
57
+ const textStyleOptions = model.styles?.textStyles?.textStyleOptions;
58
+ if (bannerArgs.title !== undefined) {
59
+ if (isTiptapDocument(bannerArgs.title)) {
60
+ resolved.content.title = tiptapJsonToHtml(bannerArgs.title);
61
+ resolved.content.titleStyle = resolveGlobalPresetIntoStyle(resolved.content.titleStyle, textStyleOptions);
62
+ }
63
+ else {
64
+ resolved.content.title = bannerArgs.title;
65
+ }
66
+ }
67
+ if (bannerArgs.description !== undefined) {
68
+ if (isTiptapDocument(bannerArgs.description)) {
69
+ resolved.content.description = tiptapJsonToHtml(bannerArgs.description);
70
+ resolved.content.descriptionStyle = resolveGlobalPresetIntoStyle(resolved.content.descriptionStyle, textStyleOptions);
71
+ }
72
+ else {
73
+ resolved.content.description = bannerArgs.description;
74
+ }
75
+ }
76
+ applyBackgroundImage(resolved.content, bannerArgs);
77
+ await applyBackgroundShapeAsync(resolved.content, bannerArgs, prevImageUrl);
24
78
  if (bannerArgs.background_color !== undefined) {
25
79
  resolved.content.backgroundStyle = {
26
80
  ...resolved.content.backgroundStyle,
27
81
  backgroundColor: bannerArgs.background_color ?? '',
28
82
  };
29
83
  }
84
+ if (bannerArgs.card_style && typeof bannerArgs.card_style === 'object') {
85
+ const existing = resolved.content.cardStyle || {};
86
+ resolved.content.cardStyle = {
87
+ ...existing,
88
+ ...Object.fromEntries(Object.entries(bannerArgs.card_style).map(([k, v]) => [
89
+ k,
90
+ v === null ? '' : v,
91
+ ])),
92
+ };
93
+ }
30
94
  return { request: this.request, model };
31
95
  }
32
96
  }
@@ -1,7 +1,10 @@
1
1
  import { type BrandPageModel, type Content } from '../../../brand-page/models';
2
+ import type { TextStyleOptions } from '../../../brand-page/models/styles.model';
3
+ import { type EventTracker } from '../../../brand-page-maker/composables/useEventTracker';
2
4
  import type { Logger } from '../../logger';
3
5
  import { BaseMetadataBuilder, type BuilderResult, type MetadataBuilderRequest } from '../../models';
4
6
  import type { SectionToolArguments, SectionType } from '../../parsers/section-tool-arguments';
7
+ import type { ValidationContext } from '../../sanitizers/section-args-validator';
5
8
  export interface SectionBuilderPayload {
6
9
  sectionType: SectionType;
7
10
  arguments: SectionToolArguments;
@@ -9,19 +12,47 @@ export interface SectionBuilderPayload {
9
12
  contentId?: string;
10
13
  /** Target page ID — used for create operations to place the new section on the correct page. */
11
14
  pageId?: string;
15
+ /** Insert/move before this existing content ID (create: position on insert; update: reposition). */
16
+ moveBeforeContentId?: string;
12
17
  }
13
18
  /**
14
19
  * Abstract base for per-section builders.
15
20
  *
16
21
  * Concrete builders implement `buildAsync` directly, using
17
- * `resolveContent()` to obtain the content object to mutate.
22
+ * `resolveAndRepositionContent()` to obtain the content object to mutate.
18
23
  */
19
24
  export declare abstract class BaseSectionBuilder<C extends Content = Content> extends BaseMetadataBuilder<SectionBuilderPayload> {
20
- constructor(request: MetadataBuilderRequest<SectionBuilderPayload>, logger?: Logger);
25
+ /**
26
+ * Content ID resolved during `resolveAndRepositionContent` (CREATE: the
27
+ * id of the freshly-created content; UPDATE: the id of the located target).
28
+ * `MetadataExecutor` reads this via `getResolvedContentId()` to surface it
29
+ * on the returned BuilderResult, so callers can anchor follow-up operations
30
+ * (notably the AI retry vacant-slot tracker) to the section we just touched.
31
+ */
32
+ protected resolvedContentId?: string;
33
+ constructor(request: MetadataBuilderRequest<SectionBuilderPayload>, logger?: Logger, eventTracker?: EventTracker);
34
+ getResolvedContentId(): string | undefined;
21
35
  protected get sectionType(): SectionType;
22
36
  protected get mode(): 'create' | 'update';
23
37
  protected get args(): SectionToolArguments;
24
- /** Override in subclasses for per-section validation. */
38
+ /**
39
+ * Returns the explicit validate function for this section's AI arguments.
40
+ * Override in concrete builders to return the colocated validate function.
41
+ * Return undefined (default) to skip validation — used by structural
42
+ * builders (delete, move) that have no argument constraints.
43
+ */
44
+ protected get sectionValidate(): ((args: Record<string, unknown>, ctx: ValidationContext) => string[]) | undefined;
45
+ /**
46
+ * Returns the model's global text style options. Used by `applyStyleFields`
47
+ * to resolve an existing style's `textStyleType` preset into concrete
48
+ * values before clearing the preset reference when applying an AI override.
49
+ */
50
+ protected getGlobalTextStyles(model: BrandPageModel): TextStyleOptions | undefined;
51
+ /**
52
+ * Returns validation errors for the section's AI arguments.
53
+ * Override in subclasses to add section-specific checks — call super.validateSection()
54
+ * to inherit the base rule enforcement.
55
+ */
25
56
  protected validateSection(): string[];
26
57
  validateAsync(): Promise<{
27
58
  errors: string[];
@@ -30,11 +61,12 @@ export declare abstract class BaseSectionBuilder<C extends Content = Content> ex
30
61
  * Validates the request, then creates or finds the target content.
31
62
  * Returns `{ content }` on success, or `{ error }` with a BuilderResult on failure.
32
63
  */
33
- protected resolveContent(model: BrandPageModel): {
64
+ protected resolveAndRepositionContent(model: BrandPageModel): {
34
65
  content: C;
35
66
  } | {
36
67
  error: BuilderResult;
37
68
  };
38
69
  private createContent;
70
+ private moveContent;
39
71
  private findContent;
40
72
  }
@@ -1,15 +1,27 @@
1
- import {} from '../../../brand-page/models';
1
+ import { BRAND_PAGE_TYPES, } from '../../../brand-page/models';
2
+ import { TRIGGER_TYPE, } from '../../../brand-page-maker/composables/useEventTracker';
2
3
  import { BaseMetadataBuilder, } from '../../models';
3
4
  import { createDefaultSectionContent } from '../section-content-factory';
4
5
  /**
5
6
  * Abstract base for per-section builders.
6
7
  *
7
8
  * Concrete builders implement `buildAsync` directly, using
8
- * `resolveContent()` to obtain the content object to mutate.
9
+ * `resolveAndRepositionContent()` to obtain the content object to mutate.
9
10
  */
10
11
  export class BaseSectionBuilder extends BaseMetadataBuilder {
11
- constructor(request, logger) {
12
- super(request, logger);
12
+ /**
13
+ * Content ID resolved during `resolveAndRepositionContent` (CREATE: the
14
+ * id of the freshly-created content; UPDATE: the id of the located target).
15
+ * `MetadataExecutor` reads this via `getResolvedContentId()` to surface it
16
+ * on the returned BuilderResult, so callers can anchor follow-up operations
17
+ * (notably the AI retry vacant-slot tracker) to the section we just touched.
18
+ */
19
+ resolvedContentId;
20
+ constructor(request, logger, eventTracker) {
21
+ super(request, logger, eventTracker);
22
+ }
23
+ getResolvedContentId() {
24
+ return this.resolvedContentId;
13
25
  }
14
26
  get sectionType() {
15
27
  return this.request.payload.sectionType;
@@ -20,9 +32,37 @@ export class BaseSectionBuilder extends BaseMetadataBuilder {
20
32
  get args() {
21
33
  return this.request.payload.arguments;
22
34
  }
23
- /** Override in subclasses for per-section validation. */
35
+ /**
36
+ * Returns the explicit validate function for this section's AI arguments.
37
+ * Override in concrete builders to return the colocated validate function.
38
+ * Return undefined (default) to skip validation — used by structural
39
+ * builders (delete, move) that have no argument constraints.
40
+ */
41
+ get sectionValidate() {
42
+ return undefined;
43
+ }
44
+ /**
45
+ * Returns the model's global text style options. Used by `applyStyleFields`
46
+ * to resolve an existing style's `textStyleType` preset into concrete
47
+ * values before clearing the preset reference when applying an AI override.
48
+ */
49
+ getGlobalTextStyles(model) {
50
+ return model.styles?.textStyles?.textStyleOptions;
51
+ }
52
+ /**
53
+ * Returns validation errors for the section's AI arguments.
54
+ * Override in subclasses to add section-specific checks — call super.validateSection()
55
+ * to inherit the base rule enforcement.
56
+ */
24
57
  validateSection() {
25
- return [];
58
+ const validate = this.sectionValidate;
59
+ if (!validate)
60
+ return [];
61
+ // TODO(KP): Pass brandPageType from the request when available, to enforce item caps correctly.
62
+ return validate(this.args, {
63
+ brandPageType: BRAND_PAGE_TYPES.brandSite,
64
+ mode: this.mode,
65
+ });
26
66
  }
27
67
  async validateAsync() {
28
68
  const errors = [];
@@ -37,23 +77,44 @@ export class BaseSectionBuilder extends BaseMetadataBuilder {
37
77
  errors.push('contentId is required for update operations');
38
78
  }
39
79
  }
40
- errors.push(...this.validateSection());
80
+ try {
81
+ errors.push(...this.validateSection());
82
+ }
83
+ catch (error) {
84
+ // Validation is a background concern — never let a validator bug break the build.
85
+ this.log({
86
+ message: 'validateSection failed unexpectedly — skipping arg validation',
87
+ error,
88
+ });
89
+ }
41
90
  return { errors };
42
91
  }
43
92
  /**
44
93
  * Validates the request, then creates or finds the target content.
45
94
  * Returns `{ content }` on success, or `{ error }` with a BuilderResult on failure.
46
95
  */
47
- resolveContent(model) {
96
+ resolveAndRepositionContent(model) {
48
97
  if (this.mode === 'create') {
49
- return this.createContent(model);
98
+ const created = this.createContent(model);
99
+ if ('content' in created) {
100
+ this.resolvedContentId = created.content.id;
101
+ }
102
+ return created;
103
+ }
104
+ const result = this.findContent(model);
105
+ if ('error' in result)
106
+ return result;
107
+ this.resolvedContentId = result.content.id;
108
+ const { moveBeforeContentId } = this.request.payload;
109
+ if (moveBeforeContentId) {
110
+ this.moveContent(model, result.content, moveBeforeContentId);
50
111
  }
51
- return this.findContent(model);
112
+ return result;
52
113
  }
53
114
  createContent(model) {
54
115
  const payload = this.request.payload;
55
116
  const { pageId } = payload;
56
- const content = createDefaultSectionContent(this.sectionType);
117
+ const content = createDefaultSectionContent(this.sectionType, model.brandPageType);
57
118
  if (!content) {
58
119
  return {
59
120
  error: {
@@ -81,13 +142,42 @@ export class BaseSectionBuilder extends BaseMetadataBuilder {
81
142
  },
82
143
  };
83
144
  }
84
- targetPage.contents.push(content);
145
+ const { moveBeforeContentId } = payload;
146
+ if (moveBeforeContentId) {
147
+ const anchorIndex = targetPage.contents.findIndex((c) => c.id === moveBeforeContentId);
148
+ if (anchorIndex !== -1) {
149
+ targetPage.contents.splice(anchorIndex, 0, content);
150
+ }
151
+ else {
152
+ targetPage.contents.push(content);
153
+ }
154
+ }
155
+ else {
156
+ targetPage.contents.push(content);
157
+ }
158
+ this.eventTracker?.sendAddContentEvent(this.sectionType, undefined, undefined, TRIGGER_TYPE.AI_BUILDER);
85
159
  this.log({
86
160
  message: `Created ${this.sectionType} section on page ${targetPage.id}`,
87
161
  contentId: content.id,
88
162
  });
89
163
  return { content: content };
90
164
  }
165
+ moveContent(model, content, beforeContentId) {
166
+ for (const page of model.pages) {
167
+ const currentIndex = page.contents.findIndex((c) => c.id === content.id);
168
+ if (currentIndex === -1)
169
+ continue;
170
+ page.contents.splice(currentIndex, 1);
171
+ const anchorIndex = page.contents.findIndex((c) => c.id === beforeContentId);
172
+ if (anchorIndex !== -1) {
173
+ page.contents.splice(anchorIndex, 0, content);
174
+ }
175
+ else {
176
+ page.contents.push(content);
177
+ }
178
+ return;
179
+ }
180
+ }
91
181
  findContent(model) {
92
182
  const { contentId } = this.request.payload;
93
183
  for (const page of model.pages) {
@@ -0,0 +1,8 @@
1
+ import type { BookingSectionContent, BrandPageModel } from '../../../brand-page/models';
2
+ import type { BuilderResult } from '../../models';
3
+ import { BaseSectionBuilder } from './base-section-builder';
4
+ import { validateBookingSection } from '../section-rules/booking-section.rules';
5
+ export declare class BookingSectionBuilder extends BaseSectionBuilder<BookingSectionContent> {
6
+ protected get sectionValidate(): typeof validateBookingSection;
7
+ buildAsync(model: BrandPageModel): Promise<BuilderResult>;
8
+ }
@@ -0,0 +1,50 @@
1
+ import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
2
+ import { isTiptapDocument, } from '../../parsers/section-tool-arguments';
3
+ import { applyButtonLink, applyScalarFields, applyStyleFields, resolveGlobalPresetIntoStyle, } from '../section-field-utils';
4
+ import { BaseSectionBuilder } from './base-section-builder';
5
+ import { validateBookingSection } from '../section-rules/booking-section.rules';
6
+ export class BookingSectionBuilder extends BaseSectionBuilder {
7
+ get sectionValidate() {
8
+ return validateBookingSection;
9
+ }
10
+ async buildAsync(model) {
11
+ this.log('Build called');
12
+ const validation = await this.validateAsync();
13
+ if (validation.errors.length) {
14
+ return { request: this.request, model, errors: validation.errors };
15
+ }
16
+ const resolved = this.resolveAndRepositionContent(model);
17
+ if ('error' in resolved)
18
+ return resolved.error;
19
+ const bookingArgs = this.args;
20
+ applyScalarFields(resolved.content, this.args, this.sectionType);
21
+ applyButtonLink(resolved.content, bookingArgs);
22
+ applyStyleFields(resolved.content, this.args, this.sectionType, this.getGlobalTextStyles(model));
23
+ const textStyleOptions = model.styles?.textStyles?.textStyleOptions;
24
+ if (bookingArgs.title !== undefined) {
25
+ if (isTiptapDocument(bookingArgs.title)) {
26
+ resolved.content.title = tiptapJsonToHtml(bookingArgs.title);
27
+ resolved.content.titleStyle = resolveGlobalPresetIntoStyle(resolved.content.titleStyle, textStyleOptions);
28
+ }
29
+ else {
30
+ resolved.content.title = bookingArgs.title;
31
+ }
32
+ }
33
+ if (bookingArgs.description !== undefined) {
34
+ if (isTiptapDocument(bookingArgs.description)) {
35
+ resolved.content.description = tiptapJsonToHtml(bookingArgs.description);
36
+ resolved.content.descriptionStyle = resolveGlobalPresetIntoStyle(resolved.content.descriptionStyle, textStyleOptions);
37
+ }
38
+ else {
39
+ resolved.content.description = bookingArgs.description;
40
+ }
41
+ }
42
+ if (bookingArgs.background_color !== undefined) {
43
+ resolved.content.backgroundStyle = {
44
+ ...resolved.content.backgroundStyle,
45
+ backgroundColor: bookingArgs.background_color ?? '',
46
+ };
47
+ }
48
+ return { request: this.request, model };
49
+ }
50
+ }
@@ -1,6 +1,8 @@
1
1
  import type { ButtonContent, BrandPageModel } from '../../../brand-page/models';
2
2
  import type { BuilderResult } from '../../models';
3
3
  import { BaseSectionBuilder } from './base-section-builder';
4
+ import { validateButtonSection } from '../section-rules/button-section.rules';
4
5
  export declare class ButtonSectionBuilder extends BaseSectionBuilder<ButtonContent> {
6
+ protected get sectionValidate(): typeof validateButtonSection;
5
7
  buildAsync(model: BrandPageModel): Promise<BuilderResult>;
6
8
  }
@@ -1,13 +1,17 @@
1
1
  import { applyScalarFields } from '../section-field-utils';
2
2
  import { BaseSectionBuilder } from './base-section-builder';
3
+ import { validateButtonSection } from '../section-rules/button-section.rules';
3
4
  export class ButtonSectionBuilder extends BaseSectionBuilder {
5
+ get sectionValidate() {
6
+ return validateButtonSection;
7
+ }
4
8
  async buildAsync(model) {
5
9
  this.log('Build called');
6
10
  const validation = await this.validateAsync();
7
11
  if (validation.errors.length) {
8
12
  return { request: this.request, model, errors: validation.errors };
9
13
  }
10
- const resolved = this.resolveContent(model);
14
+ const resolved = this.resolveAndRepositionContent(model);
11
15
  if ('error' in resolved)
12
16
  return resolved.error;
13
17
  applyScalarFields(resolved.content, this.args, this.sectionType);
@@ -1,6 +1,8 @@
1
1
  import type { ContactFormContent, BrandPageModel } from '../../../brand-page/models';
2
2
  import type { BuilderResult } from '../../models';
3
3
  import { BaseSectionBuilder } from './base-section-builder';
4
+ import { validateContactForm } from '../section-rules/contact-form.rules';
4
5
  export declare class ContactFormBuilder extends BaseSectionBuilder<ContactFormContent> {
6
+ protected get sectionValidate(): typeof validateContactForm;
5
7
  buildAsync(model: BrandPageModel): Promise<BuilderResult>;
6
8
  }
@@ -1,19 +1,53 @@
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';
2
4
  import { BaseSectionBuilder } from './base-section-builder';
5
+ import { validateContactForm } from '../section-rules/contact-form.rules';
3
6
  export class ContactFormBuilder extends BaseSectionBuilder {
7
+ get sectionValidate() {
8
+ return validateContactForm;
9
+ }
4
10
  async buildAsync(model) {
5
11
  this.log('Build called');
6
12
  const validation = await this.validateAsync();
7
13
  if (validation.errors.length) {
8
14
  return { request: this.request, model, errors: validation.errors };
9
15
  }
10
- const resolved = this.resolveContent(model);
16
+ const resolved = this.resolveAndRepositionContent(model);
11
17
  if ('error' in resolved)
12
18
  return resolved.error;
13
19
  const content = resolved.content;
14
20
  applyScalarFields(content, this.args, this.sectionType);
15
- applyStyleFields(content, this.args, this.sectionType);
21
+ applyStyleFields(content, this.args, this.sectionType, this.getGlobalTextStyles(model));
16
22
  const args = this.args;
23
+ const textStyleOptions = model.styles?.textStyles?.textStyleOptions;
24
+ if (args.title !== undefined) {
25
+ if (isTiptapDocument(args.title)) {
26
+ content.title = tiptapJsonToHtml(args.title);
27
+ content.titleStyle = resolveGlobalPresetIntoStyle(content.titleStyle, textStyleOptions);
28
+ }
29
+ else {
30
+ content.title = args.title;
31
+ }
32
+ }
33
+ if (args.description !== undefined) {
34
+ if (isTiptapDocument(args.description)) {
35
+ content.description = tiptapJsonToHtml(args.description);
36
+ content.descriptionStyle = resolveGlobalPresetIntoStyle(content.descriptionStyle, textStyleOptions);
37
+ }
38
+ else {
39
+ content.description = args.description;
40
+ }
41
+ }
42
+ if (args.success_message !== undefined) {
43
+ if (isTiptapDocument(args.success_message)) {
44
+ content.successMessage = tiptapJsonToHtml(args.success_message);
45
+ content.successMessageStyle = resolveGlobalPresetIntoStyle(content.successMessageStyle, textStyleOptions);
46
+ }
47
+ else {
48
+ content.successMessage = args.success_message;
49
+ }
50
+ }
17
51
  if (args.fields && Array.isArray(args.fields) && content.fields) {
18
52
  for (const toggle of args.fields) {
19
53
  const field = content.fields.find((f) => f.id === toggle.field_id);
@@ -28,6 +62,16 @@ export class ContactFormBuilder extends BaseSectionBuilder {
28
62
  backgroundColor: args.background_color ?? '',
29
63
  };
30
64
  }
65
+ if (args.card_style && typeof args.card_style === 'object') {
66
+ const existing = content.cardStyle || {};
67
+ content.cardStyle = {
68
+ ...existing,
69
+ ...Object.fromEntries(Object.entries(args.card_style).map(([k, v]) => [
70
+ k,
71
+ v === null ? '' : v,
72
+ ])),
73
+ };
74
+ }
31
75
  return { request: this.request, model };
32
76
  }
33
77
  }