@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,75 @@
1
+ import { HEADER_DISPLAY_STYLE_CONFIGS } from '../../../brand-page/constants/sections/header-display.constants';
2
+ import type { UpdateHeaderArguments } from '../../parsers/ai-toolcall-parser';
3
+ import { validateLogoSize } from '../../sanitizers/section-args-validator';
4
+ import { PAGE_RULES, STYLE_RULES } from '../../sanitizers/sanitizer-rules';
5
+
6
+ type HeaderCheck = (args: UpdateHeaderArguments) => string | null;
7
+
8
+ export const HEADER_CHECKS: HeaderCheck[] = [
9
+ // Display style + nav type compatibility per viewport
10
+ ...(['desktop', 'mobile'] as const).map(
11
+ (viewport): HeaderCheck =>
12
+ (args) => {
13
+ const overrides = args[viewport];
14
+
15
+ if (!overrides?.nav_display_type || !overrides?.display_style)
16
+ return null;
17
+
18
+ const compatible = HEADER_DISPLAY_STYLE_CONFIGS.some(
19
+ (c) =>
20
+ c.option.value === overrides.display_style &&
21
+ c.supportedNavTypes.includes(overrides.nav_display_type!),
22
+ );
23
+
24
+ return compatible
25
+ ? null
26
+ : `Incompatible ${viewport} combination: display_style "${overrides.display_style}" is not compatible with nav_display_type "${overrides.nav_display_type}".`;
27
+ },
28
+ ),
29
+
30
+ // Nav link font per viewport
31
+ ...(['desktop', 'mobile'] as const).map(
32
+ (viewport): HeaderCheck =>
33
+ (args) => {
34
+ const font = args[viewport]?.link_text_font;
35
+
36
+ if (font == null) return null;
37
+
38
+ return !STYLE_RULES.fontFamilyNames.has(font)
39
+ ? `"${viewport}.link_text_font" "${font}" is not a recognized font family`
40
+ : null;
41
+ },
42
+ ),
43
+
44
+ // Logo sizes per viewport
45
+ ...(['desktop', 'mobile'] as const).flatMap((viewport): HeaderCheck[] => [
46
+ (args) =>
47
+ validateLogoSize(
48
+ `${viewport}.logo_image_height`,
49
+ args[viewport]?.logo_image_height,
50
+ viewport,
51
+ ),
52
+ (args) =>
53
+ validateLogoSize(
54
+ `${viewport}.logo_image_width`,
55
+ args[viewport]?.logo_image_width,
56
+ viewport,
57
+ ),
58
+ ]),
59
+
60
+ // Nav route display name length (returns first violation — retry loop handles the rest)
61
+ (args) => {
62
+ for (let i = 0; i < (args.nav_routes ?? []).length; i++) {
63
+ const displayName = args.nav_routes![i].display_name;
64
+
65
+ if (
66
+ displayName != null &&
67
+ displayName.length > PAGE_RULES.navDisplayName
68
+ ) {
69
+ return `nav_routes[${i}].display_name exceeds the maximum length of ${PAGE_RULES.navDisplayName} characters (got ${displayName.length})`;
70
+ }
71
+ }
72
+
73
+ return null;
74
+ },
75
+ ];
@@ -0,0 +1,22 @@
1
+ import { MAX_TITLE_LENGTH } from '../../../brand-page/constants/font.constants';
2
+ import {
3
+ enumCheck,
4
+ itemRteStyleCheck,
5
+ itemTextCheck,
6
+ runChecks,
7
+ type SectionCheck,
8
+ type ValidationContext,
9
+ } from '../../sanitizers/section-args-validator';
10
+
11
+ const CHECKS: SectionCheck[] = [
12
+ itemTextCheck('images', 'caption', MAX_TITLE_LENGTH),
13
+ itemRteStyleCheck('images', 'caption'),
14
+ enumCheck('gallery_type', ['grid', 'carousel', 'masonry'], 'image-gallery'),
15
+ ];
16
+
17
+ export function validateImageGallery(
18
+ args: Record<string, unknown>,
19
+ ctx: ValidationContext,
20
+ ): string[] {
21
+ return runChecks(CHECKS, args, ctx);
22
+ }
@@ -0,0 +1,55 @@
1
+ import {
2
+ MAX_TITLE_LENGTH,
3
+ MAX_DESCRIPTION_LENGTH,
4
+ } from '../../../brand-page/constants/font.constants';
5
+ import { ASPECT_RATIOS } from '../../../brand-page/models';
6
+ import {
7
+ enumCheck,
8
+ itemCapCheck,
9
+ itemRteStyleCheck,
10
+ itemTextCheck,
11
+ runChecks,
12
+ styleCheck,
13
+ type SectionCheck,
14
+ type ValidationContext,
15
+ } from '../../sanitizers/section-args-validator';
16
+ import { textAndRteChecks } from '../../sanitizers/rte-schema-check';
17
+
18
+ const CHECKS: SectionCheck[] = [
19
+ ...textAndRteChecks('title', MAX_TITLE_LENGTH),
20
+ ...textAndRteChecks('description', MAX_DESCRIPTION_LENGTH),
21
+ styleCheck('title_style'),
22
+ styleCheck('description_style'),
23
+ styleCheck('heading_style'),
24
+ styleCheck('paragraph_style'),
25
+ itemTextCheck('items', 'heading', MAX_TITLE_LENGTH),
26
+ itemRteStyleCheck('items', 'heading'),
27
+ itemTextCheck('items', 'text', MAX_DESCRIPTION_LENGTH),
28
+ itemRteStyleCheck('items', 'text'),
29
+ itemTextCheck('items', 'button_text', MAX_TITLE_LENGTH),
30
+ itemRteStyleCheck('items', 'button_text'),
31
+ enumCheck(
32
+ 'display_style',
33
+ [
34
+ 'left-aligned',
35
+ 'right-aligned',
36
+ 'centered',
37
+ 'media-only',
38
+ 'center-card-aligned-image',
39
+ 'alternate-image',
40
+ ],
41
+ 'images-section',
42
+ ),
43
+ enumCheck('aspect_ratio', Object.keys(ASPECT_RATIOS), 'images-section'),
44
+ itemCapCheck(
45
+ { brandSite: 5, brandPage: 2, arrayField: 'items' },
46
+ 'images-section',
47
+ ),
48
+ ];
49
+
50
+ export function validateImagesSection(
51
+ args: Record<string, unknown>,
52
+ ctx: ValidationContext,
53
+ ): string[] {
54
+ return runChecks(CHECKS, args, ctx);
55
+ }
@@ -0,0 +1,21 @@
1
+ import { MAX_TITLE_LENGTH } from '../../../brand-page/constants/font.constants';
2
+ import {
3
+ enumCheck,
4
+ runChecks,
5
+ type SectionCheck,
6
+ type ValidationContext,
7
+ } from '../../sanitizers/section-args-validator';
8
+ import { textAndRteChecks } from '../../sanitizers/rte-schema-check';
9
+
10
+ const CHECKS: SectionCheck[] = [
11
+ ...textAndRteChecks('title', MAX_TITLE_LENGTH),
12
+ ...textAndRteChecks('button_text', 25), // config-settings-constant.ts:1780 — field-specific limit
13
+ enumCheck('accepted_fields', ['emailOnly', 'nameAndEmail'], 'mailing-list'),
14
+ ];
15
+
16
+ export function validateMailingList(
17
+ args: Record<string, unknown>,
18
+ ctx: ValidationContext,
19
+ ): string[] {
20
+ return runChecks(CHECKS, args, ctx);
21
+ }
@@ -0,0 +1,27 @@
1
+ import {
2
+ MAX_TITLE_LENGTH,
3
+ MAX_DESCRIPTION_LENGTH,
4
+ } from '../../../brand-page/constants/font.constants';
5
+ import {
6
+ runChecks,
7
+ styleCheck,
8
+ type SectionCheck,
9
+ type ValidationContext,
10
+ } from '../../sanitizers/section-args-validator';
11
+ import { textAndRteChecks } from '../../sanitizers/rte-schema-check';
12
+
13
+ const CHECKS: SectionCheck[] = [
14
+ ...textAndRteChecks('name', MAX_TITLE_LENGTH),
15
+ ...textAndRteChecks('title', MAX_TITLE_LENGTH),
16
+ ...textAndRteChecks('description', MAX_DESCRIPTION_LENGTH),
17
+ styleCheck('name_style'),
18
+ styleCheck('title_style'),
19
+ styleCheck('description_style'),
20
+ ];
21
+
22
+ export function validateProfile(
23
+ args: Record<string, unknown>,
24
+ ctx: ValidationContext,
25
+ ): string[] {
26
+ return runChecks(CHECKS, args, ctx);
27
+ }
@@ -0,0 +1,17 @@
1
+ import { PAGE_RULES } from '../../sanitizers/sanitizer-rules';
2
+
3
+ export interface RenamePagePayload {
4
+ pageId: string;
5
+ pageName: string;
6
+ }
7
+
8
+ type PageCheck = (payload: RenamePagePayload | undefined) => string | null;
9
+
10
+ export const RENAME_PAGE_CHECKS: PageCheck[] = [
11
+ (p) => (!p?.pageId ? 'page_id is required for rename_page' : null),
12
+ (p) => (!p?.pageName ? 'page_name is required for rename_page' : null),
13
+ (p) =>
14
+ p?.pageName && p.pageName.length > PAGE_RULES.pageName
15
+ ? `page_name exceeds the maximum length of ${PAGE_RULES.pageName} characters (got ${p.pageName.length})`
16
+ : null,
17
+ ];
@@ -0,0 +1,51 @@
1
+ import {
2
+ MAX_TITLE_LENGTH,
3
+ MAX_DESCRIPTION_LENGTH,
4
+ } from '../../../brand-page/constants/font.constants';
5
+ import {
6
+ enumCheck,
7
+ itemCapCheck,
8
+ itemRteStyleCheck,
9
+ itemTextCheck,
10
+ runChecks,
11
+ styleCheck,
12
+ type SectionCheck,
13
+ type ValidationContext,
14
+ } from '../../sanitizers/section-args-validator';
15
+ import { textAndRteChecks } from '../../sanitizers/rte-schema-check';
16
+
17
+ const CHECKS: SectionCheck[] = [
18
+ ...textAndRteChecks('title', MAX_TITLE_LENGTH),
19
+ ...textAndRteChecks('description', MAX_DESCRIPTION_LENGTH),
20
+ styleCheck('title_style'),
21
+ styleCheck('description_style'),
22
+ styleCheck('heading_style'),
23
+ styleCheck('paragraph_style'),
24
+ itemTextCheck('items', 'heading', MAX_TITLE_LENGTH),
25
+ itemRteStyleCheck('items', 'heading'),
26
+ itemTextCheck('items', 'text', MAX_DESCRIPTION_LENGTH),
27
+ itemRteStyleCheck('items', 'text'),
28
+ enumCheck(
29
+ 'display_style',
30
+ [
31
+ 'left-aligned',
32
+ 'right-aligned',
33
+ 'centered',
34
+ 'media-only',
35
+ 'center-card-aligned-image',
36
+ 'alternate-image',
37
+ ],
38
+ 'shapes-section',
39
+ ),
40
+ itemCapCheck(
41
+ { brandSite: 5, brandPage: 2, arrayField: 'items' },
42
+ 'shapes-section',
43
+ ),
44
+ ];
45
+
46
+ export function validateShapesSection(
47
+ args: Record<string, unknown>,
48
+ ctx: ValidationContext,
49
+ ): string[] {
50
+ return runChecks(CHECKS, args, ctx);
51
+ }
@@ -0,0 +1,27 @@
1
+ import { SOCIAL_LINKS_ICON_DISPLAY_STYLES } from '../../../brand-page/models';
2
+ import {
3
+ enumCheck,
4
+ itemCapCheck,
5
+ runChecks,
6
+ type SectionCheck,
7
+ type ValidationContext,
8
+ } from '../../sanitizers/section-args-validator';
9
+
10
+ const CHECKS: SectionCheck[] = [
11
+ enumCheck(
12
+ 'icon_style',
13
+ Object.keys(SOCIAL_LINKS_ICON_DISPLAY_STYLES),
14
+ 'social-links',
15
+ ),
16
+ itemCapCheck(
17
+ { brandSite: 4, brandPage: 4, arrayField: 'links' },
18
+ 'social-links',
19
+ ),
20
+ ];
21
+
22
+ export function validateSocialLinks(
23
+ args: Record<string, unknown>,
24
+ ctx: ValidationContext,
25
+ ): string[] {
26
+ return runChecks(CHECKS, args, ctx);
27
+ }
@@ -0,0 +1,48 @@
1
+ import {
2
+ MAX_TITLE_LENGTH,
3
+ MAX_DESCRIPTION_LENGTH,
4
+ } from '../../../brand-page/constants/font.constants';
5
+ import {
6
+ enumCheck,
7
+ itemCapCheck,
8
+ itemRteStyleCheck,
9
+ itemTextCheck,
10
+ runChecks,
11
+ styleCheck,
12
+ type SectionCheck,
13
+ type ValidationContext,
14
+ } from '../../sanitizers/section-args-validator';
15
+ import { textAndRteChecks } from '../../sanitizers/rte-schema-check';
16
+
17
+ export const TESTIMONIAL_ITEM_CAP = {
18
+ brandSite: 3,
19
+ brandPage: 3,
20
+ arrayField: 'items',
21
+ } as const;
22
+
23
+ const CHECKS: SectionCheck[] = [
24
+ ...textAndRteChecks('title', MAX_TITLE_LENGTH),
25
+ styleCheck('title_style'),
26
+ styleCheck('testimonial_style'),
27
+ styleCheck('name_style'),
28
+ styleCheck('position_style'),
29
+ itemTextCheck('items', 'testimonial', MAX_DESCRIPTION_LENGTH),
30
+ itemRteStyleCheck('items', 'testimonial'),
31
+ itemTextCheck('items', 'name', MAX_TITLE_LENGTH),
32
+ itemRteStyleCheck('items', 'name'),
33
+ itemTextCheck('items', 'position', MAX_TITLE_LENGTH),
34
+ itemRteStyleCheck('items', 'position'),
35
+ enumCheck(
36
+ 'display_style',
37
+ ['centered', 'big-image', 'columns'],
38
+ 'testimonial-section',
39
+ ),
40
+ itemCapCheck(TESTIMONIAL_ITEM_CAP, 'testimonial-section'),
41
+ ];
42
+
43
+ export function validateTestimonialSection(
44
+ args: Record<string, unknown>,
45
+ ctx: ValidationContext,
46
+ ): string[] {
47
+ return runChecks(CHECKS, args, ctx);
48
+ }
@@ -0,0 +1,28 @@
1
+ import { MAX_TEXT_LENGTH } from '../../../brand-page/constants/font.constants';
2
+ import {
3
+ enumCheck,
4
+ itemRteStyleCheck,
5
+ itemStyleCheck,
6
+ itemTextCheck,
7
+ runChecks,
8
+ styleCheck,
9
+ type SectionCheck,
10
+ type ValidationContext,
11
+ } from '../../sanitizers/section-args-validator';
12
+ import { textAndRteChecks } from '../../sanitizers/rte-schema-check';
13
+
14
+ const CHECKS: SectionCheck[] = [
15
+ ...textAndRteChecks('text', MAX_TEXT_LENGTH),
16
+ styleCheck('text_style'),
17
+ itemTextCheck('items', 'text', MAX_TEXT_LENGTH),
18
+ itemRteStyleCheck('items', 'text'),
19
+ itemStyleCheck('items', 'text_style'),
20
+ enumCheck('column_style', ['1', '2', '3', '4'], 'text'),
21
+ ];
22
+
23
+ export function validateTextSection(
24
+ args: Record<string, unknown>,
25
+ ctx: ValidationContext,
26
+ ): string[] {
27
+ return runChecks(CHECKS, args, ctx);
28
+ }
@@ -0,0 +1,115 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import type { ColorReplacement } from '../../brand-page/models';
3
+ import {
4
+ applyColorThemeToReplacements,
5
+ resolveShapeColorReplacementsAsync,
6
+ } from './shape-color-utils';
7
+
8
+ describe('shape-color-utils', () => {
9
+ describe('resolveShapeColorReplacementsAsync', () => {
10
+ beforeEach(() => {
11
+ vi.restoreAllMocks();
12
+ });
13
+
14
+ it('returns [] for empty URL', async () => {
15
+ const result = await resolveShapeColorReplacementsAsync('');
16
+
17
+ expect(result).toEqual([]);
18
+ });
19
+
20
+ it('returns [] for proxy URL without fetching', async () => {
21
+ const fetchSpy = vi.spyOn(global, 'fetch');
22
+
23
+ const result = await resolveShapeColorReplacementsAsync(
24
+ 'https://example.com/asset/shape?id=123',
25
+ );
26
+
27
+ expect(result).toEqual([]);
28
+ expect(fetchSpy).not.toHaveBeenCalled();
29
+ });
30
+
31
+ it('fetches SVG and returns concrete identity-mapped entries per unique fill', async () => {
32
+ vi.spyOn(global, 'fetch').mockResolvedValueOnce({
33
+ ok: true,
34
+ text: async () => `<svg xmlns="http://www.w3.org/2000/svg">
35
+ <path style="fill: #111111" d="M10 10"/>
36
+ <path style="fill: #EEEEEE" d="M20 20"/>
37
+ </svg>`,
38
+ } as Response);
39
+
40
+ const result = await resolveShapeColorReplacementsAsync(
41
+ 'https://shapes.com/icon.svg',
42
+ );
43
+
44
+ const origs = result.map((r) => r.originalColor.toUpperCase());
45
+
46
+ expect(origs).toContain('#111111');
47
+ expect(origs).toContain('#EEEEEE');
48
+ // Identity-mapped: replacementColor equals originalColor (case-insensitive)
49
+ result.forEach((r) => {
50
+ expect(r.replacementColor.toLowerCase()).toBe(
51
+ r.originalColor.toLowerCase(),
52
+ );
53
+ expect(r.attribute).toBe('fill');
54
+ });
55
+ });
56
+
57
+ it('throws on HTTP failure', async () => {
58
+ vi.spyOn(global, 'fetch').mockResolvedValueOnce({
59
+ ok: false,
60
+ status: 404,
61
+ } as Response);
62
+
63
+ await expect(
64
+ resolveShapeColorReplacementsAsync('https://shapes.com/missing.svg'),
65
+ ).rejects.toThrow(/404/);
66
+ });
67
+ });
68
+
69
+ describe('applyColorThemeToReplacements', () => {
70
+ it('returns [] for empty input', () => {
71
+ expect(applyColorThemeToReplacements([], '#1D4ED8')).toEqual([]);
72
+ });
73
+
74
+ it('re-shades each entry preserving originalColor', () => {
75
+ const input: ColorReplacement[] = [
76
+ {
77
+ attribute: 'fill',
78
+ originalColor: '#808080',
79
+ replacementColor: '#808080',
80
+ },
81
+ {
82
+ attribute: 'fill',
83
+ originalColor: '#333333',
84
+ replacementColor: '#333333',
85
+ },
86
+ ];
87
+
88
+ const result = applyColorThemeToReplacements(input, '#1D4ED8');
89
+
90
+ expect(result).toHaveLength(2);
91
+ expect(result[0].originalColor).toBe('#808080');
92
+ expect(result[1].originalColor).toBe('#333333');
93
+ // replacementColor has been shifted — not equal to either original or raw theme
94
+ result.forEach((r, i) => {
95
+ expect(r.replacementColor).not.toBe(input[i].replacementColor);
96
+ expect(r.attribute).toBe('fill');
97
+ });
98
+ });
99
+
100
+ it('does not mutate the input array or its entries', () => {
101
+ const input: ColorReplacement[] = [
102
+ {
103
+ attribute: 'fill',
104
+ originalColor: '#808080',
105
+ replacementColor: '#808080',
106
+ },
107
+ ];
108
+ const originalReplacement = input[0].replacementColor;
109
+
110
+ applyColorThemeToReplacements(input, '#1D4ED8');
111
+
112
+ expect(input[0].replacementColor).toBe(originalReplacement);
113
+ });
114
+ });
115
+ });
@@ -0,0 +1,75 @@
1
+ import type { ColorReplacement } from '../../brand-page/models';
2
+ import { PROXY_SHAPE_URL_REGEX } from '../../brand-page/constants';
3
+ import { getNewColorBasedOnTargetColorTheme } from '../../brand-page/utils/color.util';
4
+ import { getColorReplacementsFromSvgStringServer } from '../../brand-page/utils/svg-color.util';
5
+
6
+ /**
7
+ * Fetch a shape's SVG and return concrete identity-mapped `ColorReplacement`
8
+ * entries, one per unique fill. Caller applies `color_theme` via
9
+ * `applyColorThemeToReplacements` as a second step when re-shading is needed.
10
+ *
11
+ * Returns `[]` for proxy URLs — those are served through `/asset/shape?...`
12
+ * and cannot be fetched for colour enumeration (render path renders them via
13
+ * `<object>` instead of downloading the SVG).
14
+ *
15
+ * Uses the svg-parser-based server variant (not DOMParser) so this works
16
+ * unchanged in both browser and SSR/test environments. For AI-authored shapes
17
+ * with style/class/direct fills, this covers every case; CSS computed-style
18
+ * only matters for shapes authored outside the AI flow.
19
+ *
20
+ * Throws on network or HTTP failure — no silent fallback.
21
+ */
22
+ export const resolveShapeColorReplacementsAsync = async (
23
+ shapeUrl: string,
24
+ ): Promise<ColorReplacement[]> => {
25
+ if (!shapeUrl || shapeUrl.match(PROXY_SHAPE_URL_REGEX)) {
26
+ return [];
27
+ }
28
+
29
+ const response = await fetch(shapeUrl);
30
+
31
+ if (!response.ok) {
32
+ throw new Error(
33
+ `Failed to fetch shape for colour enumeration (${response.status}): ${shapeUrl}`,
34
+ );
35
+ }
36
+
37
+ const svgText = await response.text();
38
+
39
+ const replacements = getColorReplacementsFromSvgStringServer(svgText);
40
+
41
+ // The server-side colour enumeration produces phantom #000000 entries from
42
+ // DEFAULT_FALLBACK_COLOR for elements whose class-based fill can't be
43
+ // resolved. Filter them out when real fill colours exist.
44
+ if (replacements.length > 1) {
45
+ const withoutPhantom = replacements.filter(
46
+ (r) => r.originalColor !== '#000000',
47
+ );
48
+
49
+ if (withoutPhantom.length > 0) return withoutPhantom;
50
+ }
51
+
52
+ return replacements;
53
+ };
54
+
55
+ /**
56
+ * Re-shade each entry's `replacementColor` to a luminance-preserving variant
57
+ * of `colorTheme`. Pure transformation over the existing array — no network.
58
+ *
59
+ * An empty input returns an empty array by design; the caller is expected to
60
+ * populate concrete entries via `resolveShapeColorReplacementsAsync` first.
61
+ */
62
+ export const applyColorThemeToReplacements = (
63
+ replacements: ColorReplacement[],
64
+ colorTheme: string,
65
+ ): ColorReplacement[] =>
66
+ replacements.map((r) => ({
67
+ ...r,
68
+ replacementColor:
69
+ replacements.length === 1
70
+ ? colorTheme
71
+ : getNewColorBasedOnTargetColorTheme(
72
+ r.originalColor,
73
+ colorTheme,
74
+ )?.toString() ?? colorTheme,
75
+ }));
@@ -0,0 +1,105 @@
1
+ import cloneDeep from 'lodash.clonedeep';
2
+ import { type BrandPageModel } from '../../brand-page/models';
3
+ import {
4
+ BaseMetadataBuilder,
5
+ type BuilderResult,
6
+ type MetadataBuilderRequest,
7
+ } from '../models';
8
+ import type { Logger } from '../logger';
9
+
10
+ /**
11
+ * Resolver called at undo-execution time to fetch the snapshot to restore to.
12
+ *
13
+ * Returning `null` means there is no snapshot available (e.g. fresh session,
14
+ * or the website has never been modified). The UndoBuilder surfaces this as
15
+ * a validation error so the caller can show a meaningful message.
16
+ *
17
+ * Async supported: the handler may return a `Promise<BrandPageModel | null>`
18
+ * if resolution involves I/O (IndexedDB, remote store, etc.). Sync returns
19
+ * work too — `await` is a no-op on non-promises.
20
+ */
21
+ export type UndoHandler = () =>
22
+ | BrandPageModel
23
+ | null
24
+ | Promise<BrandPageModel | null>;
25
+
26
+ /**
27
+ * Payload for the UndoBuilder.
28
+ *
29
+ * The snapshot itself is not stored in the payload. Instead, the payload
30
+ * carries an {@link UndoHandler} callback that the builder invokes at
31
+ * execute time to lazily resolve the snapshot. This keeps the library
32
+ * agnostic about *how* snapshots are stored — the caller owns that concern.
33
+ */
34
+ export interface UndoPayload {
35
+ undoHandler: UndoHandler;
36
+ }
37
+
38
+ /**
39
+ * UndoBuilder — executes the `undo` tool call by invoking the caller-supplied
40
+ * {@link UndoHandler} callback to resolve the snapshot, then replaces the
41
+ * current model with that snapshot. Also sets
42
+ * {@link BuilderResult.undoRequested} on the returned result so the caller
43
+ * can observe that an undo was executed (useful for telemetry, UI messaging,
44
+ * and audit logs).
45
+ *
46
+ * Contract guarantee from the AI pipeline (Website Planner WL9): the `undo`
47
+ * tool call is exclusive — it never co-occurs with build/update/delete tool
48
+ * calls in the same response. If that contract is ever violated upstream,
49
+ * fix the planner — do not add defensive ordering here. The sequential
50
+ * MetadataExecutor will apply any subsequent builders on top of the restored
51
+ * snapshot, which is the semantically correct "undo-then-apply" ordering.
52
+ */
53
+ export class UndoBuilder extends BaseMetadataBuilder<UndoPayload> {
54
+ constructor(request: MetadataBuilderRequest<UndoPayload>, logger?: Logger) {
55
+ super(request, logger);
56
+ }
57
+
58
+ async validateAsync(): Promise<{ errors: string[] }> {
59
+ const errors: string[] = [];
60
+ const payload = this.request.payload;
61
+
62
+ if (typeof payload?.undoHandler !== 'function') {
63
+ errors.push(
64
+ 'undo requires an `undoHandler` callback in the payload — caller must supply a function that resolves the pre-prompt snapshot',
65
+ );
66
+ }
67
+
68
+ return { errors };
69
+ }
70
+
71
+ async buildAsync(model: BrandPageModel): Promise<BuilderResult> {
72
+ this.log('Build called');
73
+
74
+ const validation = await this.validateAsync();
75
+
76
+ if (validation.errors.length) {
77
+ return { request: this.request, model, errors: validation.errors };
78
+ }
79
+
80
+ const snapshot = await this.request.payload!.undoHandler();
81
+
82
+ if (!snapshot) {
83
+ return {
84
+ request: this.request,
85
+ model,
86
+ errors: ['There are no previous snapshots to restore.'],
87
+ };
88
+ }
89
+
90
+ // Deep-clone the resolved snapshot so downstream builders (if any —
91
+ // exclusivity is enforced at the planner level but we don't rely on it
92
+ // here) mutate a fresh copy rather than the caller's stored snapshot.
93
+ const restored = cloneDeep(snapshot);
94
+
95
+ this.log({
96
+ message: 'Undo executed — model replaced with pre-prompt snapshot',
97
+ });
98
+
99
+ return {
100
+ request: this.request,
101
+ model: restored,
102
+ undoRequested: true,
103
+ };
104
+ }
105
+ }