@designcrowd/library.brand-page 6.2.11-builder-v2-1 → 6.2.12

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 (579) hide show
  1. package/lib/src/{CreatedOnBrandCrowd-de-de-Dg2pOwbr.js → CreatedOnBrandCrowd-de-de-BtVKllNQ.js} +1 -1
  2. package/lib/src/{CreatedOnBrandCrowd-en-us-BILs_hsB.js → CreatedOnBrandCrowd-en-us-CX5V0v8u.js} +1 -1
  3. package/lib/src/{CreatedOnBrandCrowd-es-es-VpxQ0N5F.js → CreatedOnBrandCrowd-es-es-CbA02PCL.js} +1 -1
  4. package/lib/src/{CreatedOnBrandCrowd-fr-fr-CFHWRHzi.js → CreatedOnBrandCrowd-fr-ca-BQAKruBF.js} +1 -1
  5. package/lib/src/{CreatedOnBrandCrowd-fr-ca-CFHWRHzi.js → CreatedOnBrandCrowd-fr-fr-BQAKruBF.js} +1 -1
  6. package/lib/src/{CreatedOnBrandCrowd-pt-pt-CZfs45s9.js → CreatedOnBrandCrowd-pt-br-Yk_yzB3s.js} +1 -1
  7. package/lib/src/{CreatedOnBrandCrowd-pt-br-CZfs45s9.js → CreatedOnBrandCrowd-pt-pt-Yk_yzB3s.js} +1 -1
  8. package/lib/src/{CreatedOnDcom-de-de-DYMQ6sIF.js → CreatedOnDcom-de-de-DJZQbPSD.js} +1 -1
  9. package/lib/src/{CreatedOnDcom-en-us-Dj5sdPid.js → CreatedOnDcom-en-us-BJvNAa4l.js} +1 -1
  10. package/lib/src/{CreatedOnDcom-es-es-Cx9yNTro.js → CreatedOnDcom-es-es-CUwB1FRY.js} +1 -1
  11. package/lib/src/{CreatedOnDcom-fr-ca-Bzr0SjGq.js → CreatedOnDcom-fr-ca-CK54U4oh.js} +1 -1
  12. package/lib/src/{CreatedOnDcom-fr-fr-BgqKY35F.js → CreatedOnDcom-fr-fr-DuUNBGrM.js} +1 -1
  13. package/lib/src/{CreatedOnDcom-pt-br-CXK6qfvL.js → CreatedOnDcom-pt-br-BfODpFNV.js} +1 -1
  14. package/lib/src/{CreatedOnDcom-pt-pt-B8SggNTQ.js → CreatedOnDcom-pt-pt-Cf6u2GCg.js} +1 -1
  15. package/lib/src/brand-page/__fixtures__/production-text-style-resolver.fixture.d.ts +16 -0
  16. package/lib/src/brand-page/__fixtures__/production-text-style-resolver.fixture.js +35 -0
  17. package/lib/src/brand-page/components/contact-form/ContactForm.mixin.d.ts +3 -0
  18. package/lib/src/brand-page/components/contact-form/ContactForm.mixin.js +19 -13
  19. package/lib/src/brand-page/components/mailing-list/MailingList.mixin.d.ts +3 -1
  20. package/lib/src/brand-page/components/mailing-list/MailingList.mixin.js +17 -2
  21. package/lib/src/brand-page/components/navigation/button-carousel/ButtonCarouselNavigation.mixin.d.ts +11 -3
  22. package/lib/src/brand-page/components/navigation/button-carousel/ButtonCarouselNavigation.mixin.js +35 -1
  23. package/lib/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.mixin.d.ts +8 -2
  24. package/lib/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.mixin.js +27 -3
  25. package/lib/src/brand-page/components/page/Page.mixin.d.ts +5 -2
  26. package/lib/src/brand-page/components/page/Page.mixin.js +33 -27
  27. package/lib/src/brand-page/components/page-footer/PageFooter.mixin.d.ts +7 -2
  28. package/lib/src/brand-page/components/page-footer/PageFooter.mixin.js +21 -1
  29. package/lib/src/brand-page/components/payment/Payment.mixin.d.ts +5 -2
  30. package/lib/src/brand-page/components/payment/Payment.mixin.js +22 -2
  31. package/lib/src/brand-page/components/payment/support-me/SupportMe.mixin.d.ts +6 -2
  32. package/lib/src/brand-page/components/payment/support-me/SupportMe.mixin.js +32 -1
  33. package/lib/src/brand-page/components/social-links/SocialLinks.stories.js +0 -3
  34. package/lib/src/brand-page/components/testimonial-section/__fixtures__/data.js +0 -3
  35. package/lib/src/brand-page/components/text/Text.stories.js +0 -17
  36. package/lib/src/brand-page/constants/font.constants.d.ts +62 -0
  37. package/lib/src/brand-page/constants/font.constants.js +35 -0
  38. package/lib/src/brand-page/models/brand-page-context.model.d.ts +2 -0
  39. package/lib/src/brand-page/models/brand-page-context.model.js +7 -0
  40. package/lib/src/brand-page/models/index.d.ts +23 -24
  41. package/lib/src/brand-page/models/index.js +20 -7
  42. package/lib/src/brand-page/models/navigation-styles.model.d.ts +1 -1
  43. package/lib/src/brand-page/models/navigation-styles.model.js +17 -8
  44. package/lib/src/brand-page/models/payment.model.d.ts +11 -6
  45. package/lib/src/brand-page/models/styles.model.d.ts +53 -7
  46. package/lib/src/brand-page/models/styles.model.js +115 -27
  47. package/lib/src/brand-page/utils/color-palette.util.d.ts +43 -23
  48. package/lib/src/brand-page/utils/color-palette.util.js +65 -27
  49. package/lib/src/brand-page/utils/color.util.d.ts +13 -9
  50. package/lib/src/brand-page/utils/color.util.js +56 -15
  51. package/lib/src/brand-page/utils/container-text-color.util.d.ts +46 -13
  52. package/lib/src/brand-page/utils/container-text-color.util.js +321 -41
  53. package/lib/src/brand-page/utils/index.d.ts +1 -0
  54. package/lib/src/brand-page/utils/index.js +1 -0
  55. package/lib/src/brand-page/utils/migration/migration-20.js +6 -2
  56. package/lib/src/brand-page/utils/migration/migration-21.js +34 -6
  57. package/lib/src/brand-page/utils/migration/migration-22.d.ts +99 -0
  58. package/lib/src/brand-page/utils/migration/migration-22.js +909 -0
  59. package/lib/src/brand-page/utils/migration.util.js +17 -0
  60. package/lib/src/brand-page/utils/model.util.d.ts +4 -0
  61. package/lib/src/brand-page/utils/model.util.js +4 -0
  62. package/lib/src/brand-page/utils/personalisation.util.js +9 -1
  63. package/lib/src/brand-page/utils/rte-role-lift.util.d.ts +72 -0
  64. package/lib/src/brand-page/utils/rte-role-lift.util.js +275 -0
  65. package/lib/src/brand-page/utils/style.util.d.ts +5 -1
  66. package/lib/src/brand-page/utils/style.util.js +34 -11
  67. package/lib/src/brand-page/utils/text-role-css.util.d.ts +19 -0
  68. package/lib/src/brand-page/utils/text-role-css.util.js +186 -0
  69. package/lib/src/brand-page/utils/text-role-reconnect.util.d.ts +90 -0
  70. package/lib/src/brand-page/utils/text-role-reconnect.util.js +434 -0
  71. package/lib/src/brand-page/utils/text-style.util.d.ts +53 -23
  72. package/lib/src/brand-page/utils/text-style.util.js +122 -22
  73. package/lib/src/brand-page/utils/view-model.util.d.ts +9 -1
  74. package/lib/src/brand-page/utils/view-model.util.js +124 -111
  75. package/lib/src/brand-page/view-models.d.ts +1 -0
  76. package/lib/src/brand-page-maker/components/action-bar/ActionBar.mixin.d.ts +4 -1
  77. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +34 -2
  78. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.js +4 -4
  79. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMakerTemplateSettings.mixin.d.ts +4 -1
  80. package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.js +0 -10
  81. package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/content-settings-items.fixture.js +0 -1
  82. package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +44 -138
  83. package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.js +0 -28
  84. package/lib/src/brand-page-maker/components/brandpage-settings/ReplaceImageSettingsForBrandPageSettings.mixin.d.ts +4 -1
  85. package/lib/src/brand-page-maker/components/navigation/Navigation.mixin.d.ts +1 -1
  86. package/lib/src/brand-page-maker/components/preview/Preview.mixin.d.ts +7 -0
  87. package/lib/src/brand-page-maker/components/quick-link-bar/QuickLinkBar.mixin.d.ts +21 -0
  88. package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.d.ts +25 -1
  89. package/lib/src/brand-page-maker/components/seo-settings/UrlSettings.mixin.d.ts +25 -1
  90. package/lib/src/brand-page-maker/components/seo-settings/UseExistingDomainModal.mixin.d.ts +21 -0
  91. package/lib/src/brand-page-maker/components/social-share/SocialShare.mixin.d.ts +4 -1
  92. package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.d.ts +25 -1
  93. package/lib/src/brand-page-maker/components/upgrade-to-premium-button/UpgradeToPremiumButton.mixin.d.ts +21 -0
  94. package/lib/src/brand-page-maker/composables/ai-chat/ai-builder-experiment.d.ts +10 -0
  95. package/lib/src/brand-page-maker/composables/ai-chat/ai-builder-experiment.js +11 -0
  96. package/lib/src/brand-page-maker/composables/ai-chat/useAiMetadataBuilder.d.ts +1 -0
  97. package/lib/src/brand-page-maker/composables/ai-chat/useAiMetadataBuilder.js +1 -0
  98. package/lib/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.js +14 -0
  99. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/RoleTypographyFill.d.ts +16 -0
  100. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/RoleTypographyFill.js +61 -0
  101. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/RteClipboard.d.ts +11 -0
  102. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/RteClipboard.js +236 -0
  103. package/lib/src/brand-page-maker/composables/rich-text-editor/font.d.ts +2 -1
  104. package/lib/src/brand-page-maker/composables/rich-text-editor/font.js +25 -6
  105. package/lib/src/brand-page-maker/composables/rich-text-editor/formatting.d.ts +17 -4
  106. package/lib/src/brand-page-maker/composables/rich-text-editor/formatting.js +204 -17
  107. package/lib/src/brand-page-maker/composables/rich-text-editor/hyperlink.d.ts +1 -1
  108. package/lib/src/brand-page-maker/composables/rich-text-editor/hyperlink.js +29 -31
  109. package/lib/src/brand-page-maker/composables/rich-text-editor/keepMarksOnEmpty.d.ts +20 -0
  110. package/lib/src/brand-page-maker/composables/rich-text-editor/keepMarksOnEmpty.js +60 -0
  111. package/lib/src/brand-page-maker/composables/rich-text-editor/spacing.d.ts +2 -1
  112. package/lib/src/brand-page-maker/composables/rich-text-editor/spacing.js +22 -6
  113. package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.d.ts +10 -4
  114. package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.js +319 -275
  115. package/lib/src/brand-page-maker/constants/config-settings-constant.js +1 -5
  116. package/lib/src/brand-page-maker/convertors/text-css-style-options.convertor.js +6 -2
  117. package/lib/src/brand-page-maker/convertors/text-size-value.convertor.d.ts +1 -1
  118. package/lib/src/brand-page-maker/convertors/text-size-value.convertor.js +3 -1
  119. package/lib/src/brand-page-maker/default-getters/payment-text-and-border-color.default-getter.js +7 -14
  120. package/lib/src/brand-page-maker/default-getters/text-color.default-getter.js +6 -13
  121. package/lib/src/brand-page-maker/models/content-settings.d.ts +8 -0
  122. package/lib/src/brand-page-maker/models/content-settings.js +112 -81
  123. package/lib/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store-utils.d.ts +2 -2
  124. package/lib/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store-utils.js +5 -2
  125. package/lib/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store.js +4 -3
  126. package/lib/src/brand-page-maker/stores/ai-checkpoint/ai-checkpoint-store.d.ts +1257 -117
  127. package/lib/src/brand-page-maker/stores/ai-thread/ai-website-builder-thread-store.d.ts +9 -2
  128. package/lib/src/brand-page-maker/stores/ai-thread/ai-website-builder-thread-store.js +20 -0
  129. package/lib/src/brand-page-maker/stores/brandpage-container/brand-page-container-store.d.ts +21 -0
  130. package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.d.ts +6 -1
  131. package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.js +17 -9
  132. package/lib/src/brand-page-maker/stores/history/history-store.d.ts +59 -5
  133. package/lib/src/brand-page-maker/stores/history/history-store.js +22 -2
  134. package/lib/src/brand-page-maker/utils/apply-color-strategy.js +26 -8
  135. package/lib/src/brand-page-maker/utils/index.d.ts +2 -1
  136. package/lib/src/brand-page-maker/utils/index.js +2 -1
  137. package/lib/src/brand-page-maker/utils/rich-text-editor.util.d.ts +117 -15
  138. package/lib/src/brand-page-maker/utils/rich-text-editor.util.js +435 -281
  139. package/lib/src/brand-page-maker/utils/rte-authoring.util.d.ts +4 -0
  140. package/lib/src/brand-page-maker/utils/rte-authoring.util.js +101 -0
  141. package/lib/src/brand-page-maker/utils/rte-clipboard.util.d.ts +126 -0
  142. package/lib/src/brand-page-maker/utils/rte-clipboard.util.js +307 -0
  143. package/lib/src/brand-page-maker/utils/rte-sanitize.util.js +13 -3
  144. package/lib/src/{bundled-translations-zfiA5Tsw.js → bundled-translations-yGrvPE5i.js} +17 -17
  145. package/lib/src/{bundled-translations.de-DE-ChsdSyAP.js → bundled-translations.de-DE-L4Znf8Hs.js} +17 -17
  146. package/lib/src/{bundled-translations.es-ES-DflsWQK0.js → bundled-translations.es-ES-D6iticrK.js} +15 -15
  147. package/lib/src/{bundled-translations.fr-CA-fpDRuZ52.js → bundled-translations.fr-CA-BgAVE-9k.js} +25 -25
  148. package/lib/src/{bundled-translations.fr-FR-Bub73Zt-.js → bundled-translations.fr-FR-B8GbyqxQ.js} +17 -17
  149. package/lib/src/{bundled-translations.pt-BR-BlnWE9TB.js → bundled-translations.pt-BR-DjPU3Db7.js} +25 -25
  150. package/lib/src/{bundled-translations.pt-PT-DmzXlnaS.js → bundled-translations.pt-PT-BaepaDpr.js} +23 -23
  151. package/lib/src/bundles/bundled-translations.de-DE.json +21 -2
  152. package/lib/src/bundles/bundled-translations.es-ES.json +21 -2
  153. package/lib/src/bundles/bundled-translations.fr-CA.json +21 -2
  154. package/lib/src/bundles/bundled-translations.fr-FR.json +21 -2
  155. package/lib/src/bundles/bundled-translations.json +21 -2
  156. package/lib/src/bundles/bundled-translations.pt-BR.json +21 -2
  157. package/lib/src/bundles/bundled-translations.pt-PT.json +21 -2
  158. package/lib/src/clients/ai-assistant-client.d.ts +7 -1
  159. package/lib/src/clients/ai-assistant-client.js +7 -15
  160. package/lib/src/composables/useTranslate.d.ts +1 -1
  161. package/lib/src/composables/useTranslate.js +1 -1
  162. package/lib/src/css/library.brand-page-brandCrowd.min.css +284 -188
  163. package/lib/src/css/library.brand-page-brandPage.min.css +284 -188
  164. package/lib/src/css/library.brand-page-designCom.min.css +284 -188
  165. package/lib/src/css/library.brand-page-preview.min.css +284 -188
  166. package/lib/src/index.d.ts +2 -1
  167. package/lib/src/index.mjs +195 -191
  168. package/lib/src/{lib-7gtW85nE.js → lib-kGRlD3_P.js} +39082 -36131
  169. package/lib/src/lib.js +2 -1
  170. package/lib/src/metadata-builder/builders/footer-builder.js +4 -5
  171. package/lib/src/metadata-builder/builders/global-role-propagation.d.ts +58 -0
  172. package/lib/src/metadata-builder/builders/global-role-propagation.js +246 -0
  173. package/lib/src/metadata-builder/builders/global-styles-builder.d.ts +1 -0
  174. package/lib/src/metadata-builder/builders/global-styles-builder.js +116 -45
  175. package/lib/src/metadata-builder/builders/header-builder.js +13 -4
  176. package/lib/src/metadata-builder/builders/section-builders/about-section-builder.js +3 -3
  177. package/lib/src/metadata-builder/builders/section-builders/banner-section-builder.js +3 -3
  178. package/lib/src/metadata-builder/builders/section-builders/booking-section-builder.js +3 -3
  179. package/lib/src/metadata-builder/builders/section-builders/contact-form-builder.js +4 -4
  180. package/lib/src/metadata-builder/builders/section-builders/images-section-builder.js +3 -3
  181. package/lib/src/metadata-builder/builders/section-builders/mailing-list-builder.js +2 -2
  182. package/lib/src/metadata-builder/builders/section-builders/mailing-list-section-builder.js +2 -2
  183. package/lib/src/metadata-builder/builders/section-builders/profile-section-builder.js +4 -4
  184. package/lib/src/metadata-builder/builders/section-builders/shapes-section-builder.js +3 -3
  185. package/lib/src/metadata-builder/builders/section-builders/social-links-builder.js +8 -2
  186. package/lib/src/metadata-builder/builders/section-builders/testimonial-section-builder.js +2 -2
  187. package/lib/src/metadata-builder/builders/section-builders/text-section-builder.js +60 -29
  188. package/lib/src/metadata-builder/builders/section-field-maps.js +1 -0
  189. package/lib/src/metadata-builder/builders/section-field-utils.d.ts +48 -19
  190. package/lib/src/metadata-builder/builders/section-field-utils.js +128 -52
  191. package/lib/src/metadata-builder/builders/section-rules/global-styles.rules.d.ts +4 -2
  192. package/lib/src/metadata-builder/builders/section-rules/global-styles.rules.js +28 -12
  193. package/lib/src/metadata-builder/builders/section-rules/social-links.rules.js +5 -1
  194. package/lib/src/metadata-builder/helpers/rte.helpers.d.ts +1 -1
  195. package/lib/src/metadata-builder/helpers/rte.helpers.js +97 -40
  196. package/lib/src/metadata-builder/metadata-executor.js +23 -1
  197. package/lib/src/metadata-builder/models.d.ts +2 -0
  198. package/lib/src/metadata-builder/parsers/ai-toolcall-parser.d.ts +18 -19
  199. package/lib/src/metadata-builder/parsers/section-tool-arguments.d.ts +18 -1
  200. package/lib/src/metadata-builder/sanitizers/rte-schema-check.js +1 -1
  201. package/lib/src/metadata-builder/sanitizers/sanitizer-rules.d.ts +0 -1
  202. package/lib/src/metadata-builder/sanitizers/sanitizer-rules.js +5 -8
  203. package/lib/src/metadata-builder/sanitizers/section-args-validator.d.ts +7 -16
  204. package/lib/src/metadata-builder/sanitizers/section-args-validator.js +95 -22
  205. package/lib/src/shared/color-palette/section-color-matches.js +9 -25
  206. package/lib/src/shared/color-strategies/color-strategies.d.ts +15 -0
  207. package/lib/src/shared/color-strategies/color-strategies.js +31 -0
  208. package/lib/src/shared/color-strategies/rte-color.d.ts +8 -0
  209. package/lib/src/shared/color-strategies/rte-color.js +16 -0
  210. package/lib/src/shared/color-strategies/rte-field-pairs.d.ts +23 -0
  211. package/lib/src/shared/color-strategies/rte-field-pairs.js +28 -0
  212. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +9 -135
  213. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.js +1 -27
  214. package/lib/src/shared/content-settings/components/content-settings/ReplaceImageSettingsForContent.mixin.d.ts +12 -2
  215. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.d.ts +7 -0
  216. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.d.ts +75 -6
  217. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.js +18 -7
  218. package/lib/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.d.ts +6 -1
  219. package/lib/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.js +0 -7
  220. package/lib/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.d.ts +22 -0
  221. package/lib/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.js +8 -4
  222. package/lib/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.d.ts +1255 -26
  223. package/lib/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.js +203 -59
  224. package/lib/src/shared/content-settings/store/content-settings-store.d.ts +6 -0
  225. package/lib/src/shared/content-settings/store/content-settings-store.js +105 -8
  226. package/lib/src/shared/logo-settings/components/LogoSettings.mixin.d.ts +26 -1
  227. package/lib/src/shared/navigation-style-settings/store/index.d.ts +7 -3
  228. package/lib/src/shared/navigation-style-settings/store/index.js +40 -15
  229. package/lib/src/shared/page-settings/components/new-page-modal/NewPageModal.mixin.d.ts +1 -0
  230. package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +38 -5
  231. package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +91 -13
  232. package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.js +10 -2
  233. package/lib/src/shared/page-settings/store/page-settings-store.d.ts +2 -1
  234. package/lib/src/shared/page-settings/store/page-settings-store.js +17 -0
  235. package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +32 -1
  236. package/lib/src/shared/rte-extensions/AutoLink.d.ts +17 -0
  237. package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/AutoLink.js +67 -51
  238. package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/MaxLength.js +4 -1
  239. package/lib/src/shared/rte-extensions/TextEffects.d.ts +28 -0
  240. package/lib/src/shared/rte-extensions/TextEffects.js +96 -0
  241. package/lib/src/shared/rte-extensions/ViewDomParser.d.ts +2 -0
  242. package/lib/src/shared/rte-extensions/ViewDomParser.js +21 -0
  243. package/lib/src/shared/rte-extensions.util.d.ts +25 -0
  244. package/lib/src/{brand-page-maker/composables/rich-text-editor/getRteExtensions.js → shared/rte-extensions.util.js} +62 -7
  245. package/lib/src/shared/rte-link.util.d.ts +1 -0
  246. package/lib/src/shared/rte-link.util.js +1 -0
  247. package/lib/src/shared/rte-render.util.d.ts +112 -0
  248. package/lib/src/shared/rte-render.util.js +255 -0
  249. package/lib/src/shared/rte-shape.util.d.ts +6 -0
  250. package/lib/src/shared/rte-shape.util.js +18 -0
  251. package/lib/src/shared/side-bar/components/SideBar.mixin.d.ts +23 -1
  252. package/lib/src/shared/side-bar/components/SideBarTabButton.mixin.d.ts +1 -0
  253. package/lib/src/shared/side-bar/store/side-bar-store.d.ts +2 -0
  254. package/lib/src/shared/side-bar/store/side-bar-store.js +9 -0
  255. package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +176 -15
  256. package/lib/src/shared/style-settings/components/StyleSettings.mixin.js +7 -1
  257. package/lib/src/shared/style-settings/store/style-settings-store.d.ts +1 -9
  258. package/lib/src/shared/style-settings/store/style-settings-store.js +3 -33
  259. package/lib/src/shared/style-settings/text-style-size-order.d.ts +2 -0
  260. package/lib/src/shared/style-settings/text-style-size-order.js +13 -0
  261. package/lib/src/shared/text-role-typography.util.d.ts +64 -0
  262. package/lib/src/shared/text-role-typography.util.js +183 -0
  263. package/lib/src/utils/minify-brand-page-metadata.d.ts +16 -1
  264. package/lib/src/utils/minify-brand-page-metadata.js +31 -9
  265. package/package.json +1 -1
  266. package/src/brand-page/__fixtures__/migration-22-v21/edited-brandsite-sections.v21.json +982 -0
  267. package/src/brand-page/__fixtures__/migration-22-v21/new-brandcontact-every-section.v21.json +1231 -0
  268. package/src/brand-page/__fixtures__/migration-22-v21/new-brandpage-every-section.v21.json +1231 -0
  269. package/src/brand-page/__fixtures__/migration-22-v21/new-brandsite-every-section.v21.json +1243 -0
  270. package/src/brand-page/__fixtures__/migration-22-v21/real-brandcontact.v21.json +755 -0
  271. package/src/brand-page/__fixtures__/migration-22-v21/real-brandpage-general-link.v21.json +527 -0
  272. package/src/brand-page/__fixtures__/migration-22-v21/real-brandpage-links.v21.json +755 -0
  273. package/src/brand-page/__fixtures__/migration-22-v21/real-brandpage-social-links.v21.json +514 -0
  274. package/src/brand-page/__fixtures__/migration-22-v21/real-brandsite-about.v21.json +459 -0
  275. package/src/brand-page/__fixtures__/migration-22-v21/real-brandsite-footer.v21.json +469 -0
  276. package/src/brand-page/__fixtures__/migration-22-v21/real-brandsite-header-banner.v21.json +481 -0
  277. package/src/brand-page/__fixtures__/migration-22-v21/real-brandsite-sections.v21.json +800 -0
  278. package/src/brand-page/__fixtures__/production-text-style-resolver.fixture.ts +52 -0
  279. package/src/brand-page/components/about-section/AboutSection.vue.test.ts +0 -10
  280. package/src/brand-page/components/contact-form/ContactForm.mixin.test.ts +127 -0
  281. package/src/brand-page/components/contact-form/ContactForm.mixin.ts +31 -14
  282. package/src/brand-page/components/contact-form/ContactForm.vue +26 -12
  283. package/src/brand-page/components/contact-form/ContactForm.vue.test.ts +60 -0
  284. package/src/brand-page/components/mailing-list/MailingList.mixin.test.ts +92 -0
  285. package/src/brand-page/components/mailing-list/MailingList.mixin.ts +28 -3
  286. package/src/brand-page/components/mailing-list/MailingList.vue +9 -4
  287. package/src/brand-page/components/mailing-list/MailingList.vue.test.ts +63 -0
  288. package/src/brand-page/components/navigation/button-carousel/ButtonCarouselNavigation.mixin.ts +51 -1
  289. package/src/brand-page/components/navigation/button-carousel/ButtonCarouselNavigation.test.ts +114 -0
  290. package/src/brand-page/components/navigation/button-carousel/ButtonCarouselNavigation.vue +8 -2
  291. package/src/brand-page/components/navigation/navigation-carousel/NavigationCarousel.test.ts +182 -0
  292. package/src/brand-page/components/navigation/navigation-carousel/NavigationCarousel.vue +58 -12
  293. package/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.mixin.ts +40 -3
  294. package/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.vue +15 -7
  295. package/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.vue.test.ts +133 -3
  296. package/src/brand-page/components/page/Page.mixin.ts +41 -34
  297. package/src/brand-page/components/page/Page.vue +17 -6
  298. package/src/brand-page/components/page/Page.vue.test.ts +91 -1
  299. package/src/brand-page/components/page-footer/PageFooter.mixin.ts +32 -2
  300. package/src/brand-page/components/page-footer/PageFooter.test.ts +79 -0
  301. package/src/brand-page/components/page-footer/PageFooter.vue +12 -4
  302. package/src/brand-page/components/payment/Payment.mixin.ts +34 -2
  303. package/src/brand-page/components/payment/Payment.test.ts +188 -0
  304. package/src/brand-page/components/payment/Payment.vue +12 -5
  305. package/src/brand-page/components/payment/RequestPaymentStripe.vue +1 -0
  306. package/src/brand-page/components/payment/support-me/SupportMe.mixin.ts +49 -2
  307. package/src/brand-page/components/payment/support-me/SupportMe.test.ts +100 -0
  308. package/src/brand-page/components/payment/support-me/SupportMe.vue +7 -1
  309. package/src/brand-page/components/payment/support-me/SupportMe.vue.test.ts +66 -0
  310. package/src/brand-page/components/save-contact/SaveContactWidget.test.ts +100 -0
  311. package/src/brand-page/components/save-contact/SaveContactWidget.vue +6 -3
  312. package/src/brand-page/components/shop/PaymentModal.vue +2 -6
  313. package/src/brand-page/components/shop/PaymentShippingAddress.vue +6 -0
  314. package/src/brand-page/components/shop/Shop.vue +15 -2
  315. package/src/brand-page/components/shop/Shop.vue.test.ts +74 -2
  316. package/src/brand-page/components/social-links/SocialLinks.stories.ts +0 -3
  317. package/src/brand-page/components/social-links/SocialLinks.vue.test.ts +0 -3
  318. package/src/brand-page/components/testimonial-section/__fixtures__/data.ts +0 -3
  319. package/src/brand-page/components/text/Text.stories.ts +0 -17
  320. package/src/brand-page/components/text-wrapper/TextWrapper.parity.test.ts +136 -0
  321. package/src/brand-page/components/text-wrapper/TextWrapper.test.ts +358 -0
  322. package/src/brand-page/components/text-wrapper/TextWrapper.vue +82 -22
  323. package/src/brand-page/constants/font.constants.ts +37 -0
  324. package/src/brand-page/models/brand-page-context.model.ts +13 -0
  325. package/src/brand-page/models/footer-icon-color.test.ts +22 -0
  326. package/src/brand-page/models/index.ts +50 -28
  327. package/src/brand-page/models/navigation-styles.model.test.ts +77 -1
  328. package/src/brand-page/models/navigation-styles.model.ts +26 -9
  329. package/src/brand-page/models/payment.model.ts +15 -6
  330. package/src/brand-page/models/styles.model.test.ts +104 -0
  331. package/src/brand-page/models/styles.model.ts +181 -47
  332. package/src/brand-page/utils/__snapshots__/migration.util.test.ts.snap +619 -115
  333. package/src/brand-page/utils/__snapshots__/migration2.util.test.ts.snap +150 -9
  334. package/src/brand-page/utils/__snapshots__/model.util.test.ts.snap +300 -18
  335. package/src/brand-page/utils/color-palette.util.test.ts +126 -1
  336. package/src/brand-page/utils/color-palette.util.ts +92 -26
  337. package/src/brand-page/utils/color.util.test.ts +62 -29
  338. package/src/brand-page/utils/color.util.ts +77 -14
  339. package/src/brand-page/utils/container-text-color.util.test.ts +672 -26
  340. package/src/brand-page/utils/container-text-color.util.ts +472 -46
  341. package/src/brand-page/utils/index.ts +1 -0
  342. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/edited-brandsite-sections.v22.json +1191 -0
  343. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/new-brandcontact-every-section.v22.json +2026 -0
  344. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/new-brandpage-every-section.v22.json +2017 -0
  345. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/new-brandsite-every-section.v22.json +2031 -0
  346. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandcontact.v22.json +1145 -0
  347. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandpage-general-link.v22.json +645 -0
  348. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandpage-links.v22.json +1136 -0
  349. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandpage-social-links.v22.json +662 -0
  350. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandsite-about.v22.json +638 -0
  351. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandsite-footer.v22.json +610 -0
  352. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandsite-header-banner.v22.json +660 -0
  353. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandsite-sections.v22.json +1132 -0
  354. package/src/brand-page/utils/migration/migration-01.ts +293 -237
  355. package/src/brand-page/utils/migration/migration-02.ts +8 -1
  356. package/src/brand-page/utils/migration/migration-20.ts +6 -3
  357. package/src/brand-page/utils/migration/migration-20_5.test.ts +5 -2
  358. package/src/brand-page/utils/migration/migration-21.test.ts +34 -0
  359. package/src/brand-page/utils/migration/migration-21.ts +46 -10
  360. package/src/brand-page/utils/migration/migration-22.fixed-input.test.ts +43 -0
  361. package/src/brand-page/utils/migration/migration-22.test.ts +4103 -0
  362. package/src/brand-page/utils/migration/migration-22.text-font-family.test.ts +72 -0
  363. package/src/brand-page/utils/migration/migration-22.ts +1336 -0
  364. package/src/brand-page/utils/migration.util.test.ts +146 -32
  365. package/src/brand-page/utils/migration.util.ts +18 -0
  366. package/src/brand-page/utils/model.util.ts +4 -0
  367. package/src/brand-page/utils/personalisation.util.test.ts +148 -3
  368. package/src/brand-page/utils/personalisation.util.ts +9 -1
  369. package/src/brand-page/utils/rte-role-lift.util.ts +409 -0
  370. package/src/brand-page/utils/style.util.test.ts +35 -2
  371. package/src/brand-page/utils/style.util.ts +45 -11
  372. package/src/brand-page/utils/text-role-css.util.test.ts +525 -0
  373. package/src/brand-page/utils/text-role-css.util.ts +321 -0
  374. package/src/brand-page/utils/text-role-reconnect.util.test.ts +604 -0
  375. package/src/brand-page/utils/text-role-reconnect.util.ts +727 -0
  376. package/src/brand-page/utils/text-style.util.test.ts +305 -0
  377. package/src/brand-page/utils/text-style.util.ts +198 -24
  378. package/src/brand-page/utils/view-model.page-data.test.ts +232 -0
  379. package/src/brand-page/utils/view-model.util.test.ts +954 -133
  380. package/src/brand-page/utils/view-model.util.ts +187 -139
  381. package/src/brand-page/view-models.ts +4 -0
  382. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.blank-site.test.ts +57 -0
  383. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.ts +9 -5
  384. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.ts +0 -10
  385. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/content-settings-items.fixture.ts +0 -1
  386. package/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.ts +0 -44
  387. package/src/brand-page-maker/components/rich-text-editor/RichTextEditor.vue +253 -200
  388. package/src/brand-page-maker/composables/ai-chat/ai-builder-experiment.test.ts +82 -0
  389. package/src/brand-page-maker/composables/ai-chat/ai-builder-experiment.ts +19 -0
  390. package/src/brand-page-maker/composables/ai-chat/useAiMetadataBuilder.ts +2 -0
  391. package/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.ts +19 -0
  392. package/src/brand-page-maker/composables/rich-text-editor/block-typography.test.ts +519 -0
  393. package/src/brand-page-maker/composables/rich-text-editor/extensions/FontFamily.test.ts +1 -1
  394. package/src/brand-page-maker/composables/rich-text-editor/extensions/MaxLength.test.ts +26 -1
  395. package/src/brand-page-maker/composables/rich-text-editor/extensions/RoleTypographyFill.test.ts +110 -0
  396. package/src/brand-page-maker/composables/rich-text-editor/extensions/RoleTypographyFill.ts +99 -0
  397. package/src/brand-page-maker/composables/rich-text-editor/extensions/RteClipboard.ts +397 -0
  398. package/src/brand-page-maker/composables/rich-text-editor/extensions/ViewDomParser.test.ts +139 -0
  399. package/src/brand-page-maker/composables/rich-text-editor/font.ts +36 -5
  400. package/src/brand-page-maker/composables/rich-text-editor/formatting.test.ts +375 -1
  401. package/src/brand-page-maker/composables/rich-text-editor/formatting.ts +301 -17
  402. package/src/brand-page-maker/composables/rich-text-editor/hyperlink.test.ts +82 -1
  403. package/src/brand-page-maker/composables/rich-text-editor/hyperlink.ts +28 -34
  404. package/src/brand-page-maker/composables/rich-text-editor/keepMarksOnEmpty.test.ts +80 -0
  405. package/src/brand-page-maker/composables/rich-text-editor/keepMarksOnEmpty.ts +75 -0
  406. package/src/brand-page-maker/composables/rich-text-editor/spacing.ts +31 -6
  407. package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.test.ts +2485 -0
  408. package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.ts +435 -337
  409. package/src/brand-page-maker/constants/config-settings-constant.ts +0 -6
  410. package/src/brand-page-maker/convertors/text-css-style-options.convertor.test.ts +43 -0
  411. package/src/brand-page-maker/convertors/text-css-style-options.convertor.ts +6 -2
  412. package/src/brand-page-maker/convertors/text-size-value.convertor.test.ts +24 -0
  413. package/src/brand-page-maker/convertors/text-size-value.convertor.ts +17 -13
  414. package/src/brand-page-maker/default-getters/payment-text-and-border-color.default-getter.ts +7 -22
  415. package/src/brand-page-maker/default-getters/text-color.default-getter.ts +5 -21
  416. package/src/brand-page-maker/models/content-settings.test.ts +708 -0
  417. package/src/brand-page-maker/models/content-settings.ts +133 -82
  418. package/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store-utils.test.ts +63 -1
  419. package/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store-utils.ts +16 -3
  420. package/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store.test.ts +34 -0
  421. package/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store.ts +4 -2
  422. package/src/brand-page-maker/stores/ai-thread/ai-website-builder-thread-store.ts +30 -0
  423. package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.test.ts +185 -1
  424. package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.ts +22 -34
  425. package/src/brand-page-maker/stores/history/history-store.ts +35 -2
  426. package/src/brand-page-maker/utils/__snapshots__/apply-color-strategy.golden.test.ts.snap +528 -0
  427. package/src/brand-page-maker/utils/__snapshots__/rte-render-parity.test.ts.snap +12 -0
  428. package/src/brand-page-maker/utils/apply-color-strategy.golden.test.ts +2 -0
  429. package/src/brand-page-maker/utils/apply-color-strategy.test.ts +181 -3
  430. package/src/brand-page-maker/utils/apply-color-strategy.ts +36 -4
  431. package/src/brand-page-maker/utils/index.ts +2 -1
  432. package/src/brand-page-maker/utils/rich-text-editor.util.test.ts +447 -410
  433. package/src/brand-page-maker/utils/rich-text-editor.util.ts +610 -506
  434. package/src/brand-page-maker/utils/rte-authoring.util.test.ts +244 -0
  435. package/src/brand-page-maker/utils/rte-authoring.util.ts +175 -0
  436. package/src/brand-page-maker/utils/rte-clipboard.util.test.ts +558 -0
  437. package/src/brand-page-maker/utils/rte-clipboard.util.ts +473 -0
  438. package/src/brand-page-maker/utils/rte-features.test.ts +99 -3
  439. package/src/brand-page-maker/utils/rte-render-parity.test.ts +1 -1
  440. package/src/brand-page-maker/utils/rte-render.util.test.ts +230 -0
  441. package/src/brand-page-maker/utils/rte-sanitize-json.test.ts +1 -1
  442. package/src/brand-page-maker/utils/rte-sanitize.util.ts +14 -3
  443. package/src/brand-page-maker/utils/rte-schema-version.test.ts +102 -0
  444. package/src/bundles/bundled-translations.de-DE.json +21 -2
  445. package/src/bundles/bundled-translations.es-ES.json +21 -2
  446. package/src/bundles/bundled-translations.fr-CA.json +21 -2
  447. package/src/bundles/bundled-translations.fr-FR.json +21 -2
  448. package/src/bundles/bundled-translations.json +21 -2
  449. package/src/bundles/bundled-translations.pt-BR.json +21 -2
  450. package/src/bundles/bundled-translations.pt-PT.json +21 -2
  451. package/src/clients/ai-assistant-client.ts +13 -18
  452. package/src/composables/useTranslate.ts +2 -1
  453. package/src/lib.ts +2 -2
  454. package/src/metadata-builder/builders/footer-builder.test.ts +70 -45
  455. package/src/metadata-builder/builders/footer-builder.ts +4 -8
  456. package/src/metadata-builder/builders/global-role-propagation.test.ts +907 -0
  457. package/src/metadata-builder/builders/global-role-propagation.ts +430 -0
  458. package/src/metadata-builder/builders/global-styles-builder.test.ts +1020 -0
  459. package/src/metadata-builder/builders/global-styles-builder.ts +194 -48
  460. package/src/metadata-builder/builders/header-builder.test.ts +112 -40
  461. package/src/metadata-builder/builders/header-builder.ts +18 -8
  462. package/src/metadata-builder/builders/section-builders/about-section-builder.ts +5 -3
  463. package/src/metadata-builder/builders/section-builders/banner-section-builder.ts +5 -3
  464. package/src/metadata-builder/builders/section-builders/booking-section-builder.ts +5 -3
  465. package/src/metadata-builder/builders/section-builders/contact-form-builder.ts +7 -4
  466. package/src/metadata-builder/builders/section-builders/images-section-builder.ts +5 -3
  467. package/src/metadata-builder/builders/section-builders/mailing-list-builder.ts +3 -2
  468. package/src/metadata-builder/builders/section-builders/mailing-list-section-builder.ts +3 -2
  469. package/src/metadata-builder/builders/section-builders/profile-section-builder.ts +7 -7
  470. package/src/metadata-builder/builders/section-builders/shapes-section-builder.ts +5 -3
  471. package/src/metadata-builder/builders/section-builders/social-links-builder.test.ts +2 -2
  472. package/src/metadata-builder/builders/section-builders/social-links-builder.ts +21 -10
  473. package/src/metadata-builder/builders/section-builders/support-me-builder.test.ts +10 -0
  474. package/src/metadata-builder/builders/section-builders/testimonial-section-builder.ts +3 -2
  475. package/src/metadata-builder/builders/section-builders/text-section-builder.ts +111 -61
  476. package/src/metadata-builder/builders/section-field-maps.ts +1 -0
  477. package/src/metadata-builder/builders/section-field-utils.test.ts +545 -2
  478. package/src/metadata-builder/builders/section-field-utils.ts +202 -69
  479. package/src/metadata-builder/builders/section-rules/global-styles.rules.ts +38 -13
  480. package/src/metadata-builder/builders/section-rules/social-links.rules.ts +5 -0
  481. package/src/metadata-builder/helpers/rte.helpers.test.ts +101 -0
  482. package/src/metadata-builder/helpers/rte.helpers.ts +129 -43
  483. package/src/metadata-builder/metadata-executor.test.ts +167 -0
  484. package/src/metadata-builder/metadata-executor.ts +34 -1
  485. package/src/metadata-builder/models.ts +2 -0
  486. package/src/metadata-builder/parsers/ai-toolcall-parser.ts +23 -7
  487. package/src/metadata-builder/parsers/section-tool-arguments.ts +21 -1
  488. package/src/metadata-builder/sanitizers/__tests__/section-args-validator.test.ts +215 -0
  489. package/src/metadata-builder/sanitizers/rte-schema-check.ts +1 -1
  490. package/src/metadata-builder/sanitizers/sanitizer-rules.ts +4 -8
  491. package/src/metadata-builder/sanitizers/section-args-validator.ts +136 -53
  492. package/src/shared/color-palette/section-color-matches.test.ts +15 -11
  493. package/src/shared/color-palette/section-color-matches.ts +9 -28
  494. package/src/shared/color-strategies/color-strategies.ts +35 -0
  495. package/src/shared/color-strategies/rte-color.test.ts +1 -1
  496. package/src/shared/color-strategies/rte-color.ts +19 -0
  497. package/src/shared/color-strategies/rte-field-pairs.test.ts +26 -5
  498. package/src/shared/color-strategies/rte-field-pairs.ts +33 -0
  499. package/src/shared/content-settings/components/color-matches-panel/ColorMatchesPanel.test.ts +43 -66
  500. package/src/shared/content-settings/components/color-matches-panel/ColorMatchesPanel.vue +7 -1
  501. package/src/shared/content-settings/components/content-settings/ContentSettings.mixin.ts +1 -48
  502. package/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.ts +33 -7
  503. package/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.test.ts +128 -1
  504. package/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.ts +0 -6
  505. package/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.test.ts +56 -3
  506. package/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.ts +11 -4
  507. package/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.test.ts +335 -25
  508. package/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.ts +248 -70
  509. package/src/shared/content-settings/components/text-style-field/TextStyleField.vue +113 -25
  510. package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.de-DE.json +17 -10
  511. package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.es-ES.json +17 -10
  512. package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.fr-CA.json +17 -10
  513. package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.fr-FR.json +17 -10
  514. package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.json +8 -1
  515. package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.pt-BR.json +17 -10
  516. package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.pt-PT.json +17 -10
  517. package/src/shared/content-settings/components/text-style-role-dropdown/TextStyleRoleDropdown.test.ts +141 -0
  518. package/src/shared/content-settings/components/text-style-role-dropdown/TextStyleRoleDropdown.vue +136 -0
  519. package/src/shared/content-settings/store/content-settings-store.test.ts +491 -6
  520. package/src/shared/content-settings/store/content-settings-store.ts +159 -17
  521. package/src/shared/navigation-style-settings/store/index.test.ts +295 -0
  522. package/src/shared/navigation-style-settings/store/index.ts +65 -15
  523. package/src/shared/page-settings/components/page-settings-section-styles/HeaderButtonSettings.test.ts +44 -4
  524. package/src/shared/page-settings/components/page-settings-section-styles/HeaderButtonSettings.vue +13 -4
  525. package/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.navigation.test.ts +89 -0
  526. package/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.text-style.test.ts +91 -0
  527. package/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.ts +14 -2
  528. package/src/shared/page-settings/store/page-settings-store.text-style.test.ts +84 -0
  529. package/src/shared/page-settings/store/page-settings-store.ts +30 -1
  530. package/src/shared/rte-extensions/AutoLink.test.ts +98 -0
  531. package/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/AutoLink.ts +87 -58
  532. package/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/MaxLength.ts +4 -1
  533. package/src/shared/rte-extensions/TextEffects.ts +151 -0
  534. package/src/shared/rte-extensions/ViewDomParser.ts +27 -0
  535. package/src/{brand-page-maker/composables/rich-text-editor/getRteExtensions.ts → shared/rte-extensions.util.ts} +66 -9
  536. package/src/shared/rte-link.util.ts +2 -0
  537. package/src/shared/rte-render.util.ts +385 -0
  538. package/src/shared/rte-shape.util.ts +29 -0
  539. package/src/shared/side-bar/store/side-bar-store.test.ts +27 -1
  540. package/src/shared/side-bar/store/side-bar-store.ts +11 -0
  541. package/src/shared/style-settings/components/StyleSettings.mixin.ts +7 -3
  542. package/src/shared/style-settings/components/StyleSettings.test.ts +116 -0
  543. package/src/shared/style-settings/components/StyleSettings.vue +74 -25
  544. package/src/shared/style-settings/components/i18n/style-settings.de-DE.json +32 -20
  545. package/src/shared/style-settings/components/i18n/style-settings.es-ES.json +32 -20
  546. package/src/shared/style-settings/components/i18n/style-settings.fr-CA.json +32 -20
  547. package/src/shared/style-settings/components/i18n/style-settings.fr-FR.json +32 -20
  548. package/src/shared/style-settings/components/i18n/style-settings.json +13 -3
  549. package/src/shared/style-settings/components/i18n/style-settings.pt-BR.json +32 -20
  550. package/src/shared/style-settings/components/i18n/style-settings.pt-PT.json +32 -20
  551. package/src/shared/style-settings/components/text-style-options-settings-with-state/TextStyleOptionsSettingsWithState.vue +14 -34
  552. package/src/shared/style-settings/store/style-settings-store.ts +3 -49
  553. package/src/shared/style-settings/text-style-size-order.test.ts +76 -0
  554. package/src/shared/style-settings/text-style-size-order.ts +28 -0
  555. package/src/shared/text-role-typography.util.ts +277 -0
  556. package/src/utils/minify-brand-page-metadata.test.ts +102 -7
  557. package/src/utils/minify-brand-page-metadata.ts +62 -8
  558. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/AutoLink.d.ts +0 -2
  559. package/lib/src/brand-page-maker/composables/rich-text-editor/getRteExtensions.d.ts +0 -28
  560. package/lib/src/brand-page-maker/utils/rte-render.util.d.ts +0 -63
  561. package/lib/src/brand-page-maker/utils/rte-render.util.js +0 -106
  562. package/lib/src/brand-page-maker/utils/rte-shape.d.ts +0 -18
  563. package/lib/src/brand-page-maker/utils/rte-shape.js +0 -21
  564. package/lib/src/metadata-builder/builders/global-font-propagation.d.ts +0 -41
  565. package/lib/src/metadata-builder/builders/global-font-propagation.js +0 -146
  566. package/src/brand-page/models/brand-page-context.model.test.ts +0 -38
  567. package/src/brand-page-maker/utils/rte-render.util.ts +0 -179
  568. package/src/brand-page-maker/utils/rte-shape.ts +0 -29
  569. package/src/clients/ai-assistant-client.test.ts +0 -135
  570. package/src/metadata-builder/builders/global-font-propagation.test.ts +0 -401
  571. package/src/metadata-builder/builders/global-font-propagation.ts +0 -238
  572. package/src/shared/style-settings/components/StyleSettingsSection.vue +0 -8
  573. /package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/FontFamily.d.ts +0 -0
  574. /package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/FontFamily.js +0 -0
  575. /package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/LetterSpacing.d.ts +0 -0
  576. /package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/LetterSpacing.js +0 -0
  577. /package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/MaxLength.d.ts +0 -0
  578. /package/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/FontFamily.ts +0 -0
  579. /package/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/LetterSpacing.ts +0 -0
@@ -2,10 +2,12 @@ import type { Content, ColorItem } from '../models';
2
2
  import { BRAND_PAGE_TYPES, PageStyles } from '../models';
3
3
  import {
4
4
  containerTextColorDefaults,
5
- applyCardTextContrast,
5
+ applyTextContrast,
6
6
  rteFrameFallbackColour,
7
+ buttonLabelColorDefault,
7
8
  } from './container-text-color.util';
8
9
  import { DEFAULT_CARD_SURFACE_REFERENCE } from './color-palette.util';
10
+ import { ALIGN_CENTERED, ALIGN_CARD_CENTER_IMAGE } from '../constants';
9
11
 
10
12
  const BUTTON_FILL = 'var(--palette-1)';
11
13
  const BUTTON_TEXT = 'var(--palette-2)';
@@ -162,6 +164,7 @@ describe('containerTextColorDefaults', () => {
162
164
  ).toEqual({
163
165
  titleStyle: BUTTON_TEXT,
164
166
  descriptionStyle: BUTTON_TEXT,
167
+ successMessageStyle: BUTTON_TEXT,
165
168
  itemTextStyle: BUTTON_TEXT,
166
169
  });
167
170
  });
@@ -186,7 +189,7 @@ describe('containerTextColorDefaults', () => {
186
189
 
187
190
  test('request-payment with a custom option fill: item text defers to the bake, not the render default', () => {
188
191
  // A custom option fill that is not the button fill is handled by the creation-time bake
189
- // (applyCardTextContrast), so the render rung supplies nothing.
192
+ // (applyTextContrast), so the render rung supplies nothing.
190
193
  const content = {
191
194
  id: 'rp',
192
195
  type: 'request-payment',
@@ -406,7 +409,7 @@ describe('rteFrameFallbackColour', () => {
406
409
  });
407
410
  });
408
411
 
409
- describe('applyCardTextContrast — card-text colour bake', () => {
412
+ describe('applyTextContrast — birth-time colour bake (container blocks)', () => {
410
413
  const NEUTRAL_LIGHT: ColorItem[] = [
411
414
  { id: 'palette-0', value: '#101010', type: 'palette' }, // dark brand role
412
415
  { id: 'palette-1', value: '#ededed', type: 'palette' }, // light brand role
@@ -431,33 +434,30 @@ describe('applyCardTextContrast — card-text colour bake', () => {
431
434
  NEUTRAL_LIGHT,
432
435
  );
433
436
 
434
- const result = applyCardTextContrast(content, styles);
437
+ const result = applyTextContrast(content, styles);
435
438
 
436
439
  // palette-0 (dark) reads on the light card; palette-1 (light) does not.
437
440
  expect(titleColour(result)).toBe('var(--palette-0)');
438
441
  expect(result).toBe(content); // mutated in place
439
442
  });
440
443
 
441
- test('takes the better brand role even when the current colour already reads', () => {
442
- // The reported case: the linked colour is readable but not the best — the OTHER brand
443
- // colour contrasts more, so we use that (no "only if failing" gate).
444
+ test('keeps the logo-text role on a card when it clears the floor, even though palette-1 contrasts more', () => {
445
+ // BP-5969 supersedes the earlier "always take the higher-contrast brand" rule: the site
446
+ // identity (logo-text, palette-0) leads on a card too, as long as it stays legible.
444
447
  const content = newMailingList();
445
448
  const styles = stylesWith(
446
449
  { backgroundColor: '#767676', color: '#ffffff' },
447
450
  [
448
- { id: 'palette-0', value: '#767676', type: 'palette' }, // ~4:1 on the light card — reads
449
- { id: 'palette-1', value: '#1a1a1a', type: 'palette' }, // ~16:1 — much better
451
+ { id: 'palette-0', value: '#767676', type: 'palette' }, // ~4:1 on the light card — clears the floor
452
+ { id: 'palette-1', value: '#1a1a1a', type: 'palette' }, // ~16:1 — contrasts more, must NOT win
450
453
  { id: 'palette-2', value: '#f5f5f5', type: 'palette' }, // the card
451
454
  ],
452
455
  );
453
456
 
454
- // The title already links a readable brand colour…
455
- styles.textStyles.textStyleOptions.titles.style.color = 'var(--palette-0)';
456
-
457
- applyCardTextContrast(content, styles);
457
+ applyTextContrast(content, styles);
458
458
 
459
- // …but the other brand role contrasts more, so it wins.
460
- expect(titleColour(content)).toBe('var(--palette-1)');
459
+ // logo-text clears the floor on the card → it leads, even though palette-1 contrasts more.
460
+ expect(titleColour(content)).toBe('var(--palette-0)');
461
461
  });
462
462
 
463
463
  test('bakes card fields against the card, but leaves the button-bound item text', () => {
@@ -477,7 +477,7 @@ describe('applyCardTextContrast — card-text colour bake', () => {
477
477
  NEUTRAL_LIGHT,
478
478
  );
479
479
 
480
- applyCardTextContrast(content, styles);
480
+ applyTextContrast(content, styles);
481
481
 
482
482
  const fields = content as unknown as Record<string, { color?: string }>;
483
483
 
@@ -502,7 +502,7 @@ describe('applyCardTextContrast — card-text colour bake', () => {
502
502
  NEUTRAL_LIGHT,
503
503
  );
504
504
 
505
- applyCardTextContrast(content, styles);
505
+ applyTextContrast(content, styles);
506
506
 
507
507
  const fields = content as unknown as Record<string, { color?: string }>;
508
508
 
@@ -520,7 +520,7 @@ describe('applyCardTextContrast — card-text colour bake', () => {
520
520
  NEUTRAL_LIGHT,
521
521
  );
522
522
 
523
- applyCardTextContrast(content, styles);
523
+ applyTextContrast(content, styles);
524
524
 
525
525
  expect(titleColour(content)).toBe('var(--palette-1)');
526
526
  });
@@ -537,12 +537,15 @@ describe('applyCardTextContrast — card-text colour bake', () => {
537
537
  NEUTRAL_LIGHT,
538
538
  );
539
539
 
540
- applyCardTextContrast(content, styles);
540
+ applyTextContrast(content, styles);
541
541
 
542
542
  expect(titleColour(content)).toBeUndefined();
543
543
  });
544
544
 
545
- test('is a no-op for a content type that is not container-bound', () => {
545
+ test('a non-container type gets no container button-text default (takes the page neutral)', () => {
546
+ // The container button-text pairing (var(--palette-2) here) must not apply to a non-container
547
+ // type. With no solid section surface, its plain field falls to the page background instead —
548
+ // unresolvable in this fixture, so the neutral-dark stand-in — never the button-text colour.
546
549
  const content = {
547
550
  id: 't',
548
551
  type: 'text',
@@ -553,9 +556,10 @@ describe('applyCardTextContrast — card-text colour bake', () => {
553
556
  NEUTRAL_LIGHT,
554
557
  );
555
558
 
556
- applyCardTextContrast(content, styles);
559
+ applyTextContrast(content, styles);
557
560
 
558
- expect(titleColour(content)).toBeUndefined();
561
+ expect(titleColour(content)).not.toBe('var(--palette-2)');
562
+ expect(titleColour(content)).toBe('var(--palette-3)');
559
563
  });
560
564
 
561
565
  test('picks the higher-contrast brand role even in a low-contrast palette', () => {
@@ -573,7 +577,7 @@ describe('applyCardTextContrast — card-text colour bake', () => {
573
577
  ],
574
578
  );
575
579
 
576
- applyCardTextContrast(content, styles);
580
+ applyTextContrast(content, styles);
577
581
 
578
582
  expect(titleColour(content)).toBe('var(--palette-0)');
579
583
  });
@@ -595,7 +599,7 @@ describe('applyCardTextContrast — card-text colour bake', () => {
595
599
  ],
596
600
  );
597
601
 
598
- applyCardTextContrast(content, styles);
602
+ applyTextContrast(content, styles);
599
603
 
600
604
  const baked = titleColour(content);
601
605
 
@@ -619,7 +623,7 @@ describe('applyCardTextContrast — card-text colour bake', () => {
619
623
  [{ id: 'palette-2', value: '#f5f5f5', type: 'palette' }],
620
624
  );
621
625
 
622
- applyCardTextContrast(content, styles);
626
+ applyTextContrast(content, styles);
623
627
 
624
628
  expect(titleColour(content)).toBeUndefined();
625
629
  });
@@ -639,8 +643,650 @@ describe('applyCardTextContrast — card-text colour bake', () => {
639
643
  ],
640
644
  );
641
645
 
642
- applyCardTextContrast(content, styles);
646
+ applyTextContrast(content, styles);
643
647
 
644
648
  expect(titleColour(content)).toBe('var(--palette-1)');
645
649
  });
646
650
  });
651
+
652
+ describe('applyTextContrast — non-container sections (per-field)', () => {
653
+ // A brand palette split hard so the best-contrast pick is unambiguous.
654
+ const PALETTE: ColorItem[] = [
655
+ { id: 'palette-0', value: '#000000', type: 'palette' }, // dark brand
656
+ { id: 'palette-1', value: '#ffffff', type: 'palette' }, // light brand
657
+ ];
658
+
659
+ const stylesWithColors = (colors: ColorItem[] = PALETTE): PageStyles => {
660
+ const styles = new PageStyles();
661
+
662
+ styles.colors = colors;
663
+
664
+ return styles;
665
+ };
666
+
667
+ const colourOf = (content: Content, key: string): string | undefined =>
668
+ (content as unknown as Record<string, { color?: string }>)[key]?.color;
669
+
670
+ test('bakes a contrast colour into a section text field on a solid band', () => {
671
+ const content = {
672
+ id: 't',
673
+ type: 'text',
674
+ backgroundColor: { backgroundColor: 'var(--palette-0)' }, // dark band
675
+ textStyle: { textStyleType: 'paragraph1' },
676
+ } as unknown as Content;
677
+
678
+ applyTextContrast(content, stylesWithColors());
679
+
680
+ expect(colourOf(content, 'textStyle')).toBe('var(--palette-1)'); // light on dark
681
+ });
682
+
683
+ test('each field contrasts its own surface: the title sits on the card, not the band', () => {
684
+ const content = {
685
+ id: 's',
686
+ type: 'shapes-section',
687
+ cardStyle: { backgroundColor: 'var(--palette-1)' }, // light card (topmost)
688
+ backgroundColor: { backgroundColor: 'var(--palette-0)' }, // dark band
689
+ titleStyle: { textStyleType: 'heading1' },
690
+ } as unknown as Content;
691
+
692
+ applyTextContrast(content, stylesWithColors());
693
+
694
+ // Sits on the card (light) → the dark brand role.
695
+ expect(colourOf(content, 'titleStyle')).toBe('var(--palette-0)');
696
+ });
697
+
698
+ // Distinct brand vs neutral so "brand preferred, neutral only on breach" is provable.
699
+ const BRAND_AND_NEUTRALS: ColorItem[] = [
700
+ { id: 'palette-0', value: '#2f9e44', type: 'palette' }, // green brand (logo text)
701
+ { id: 'palette-1', value: '#0a2540', type: 'palette' }, // navy brand (logo bg)
702
+ { id: 'palette-2', value: '#f5f5f5', type: 'palette' }, // neutral-light
703
+ { id: 'palette-3', value: '#1a1a1a', type: 'palette' }, // neutral-dark
704
+ ];
705
+
706
+ const pageText = () =>
707
+ ({
708
+ id: 't',
709
+ type: 'text',
710
+ backgroundColor: { backgroundColor: 'transparent' }, // sits on the page
711
+ textStyle: { textStyleType: 'paragraph1' },
712
+ }) as unknown as Content;
713
+
714
+ test('uses the logo-text role (palette-0) on a dark page when it clears the floor', () => {
715
+ const styles = stylesWithColors(BRAND_AND_NEUTRALS);
716
+
717
+ styles.backgroundStyles.style = { background: 'var(--palette-1)' }; // dark navy page
718
+
719
+ const content = pageText();
720
+
721
+ applyTextContrast(content, styles);
722
+
723
+ // the logo-text (green) brand role clears the floor on navy → the site identity colour wins
724
+ expect(colourOf(content, 'textStyle')).toBe('var(--palette-0)');
725
+ });
726
+
727
+ test('keeps the logo-text role on a light page even when palette-1 contrasts more', () => {
728
+ const styles = stylesWithColors(BRAND_AND_NEUTRALS);
729
+
730
+ styles.backgroundStyles.style = { background: '#ffffff' }; // light page
731
+
732
+ const content = pageText();
733
+
734
+ applyTextContrast(content, styles);
735
+
736
+ // green (palette-0) clears the floor on white; navy (palette-1) contrasts more but must NOT
737
+ // win — logo-text leads by hierarchy, not by best contrast.
738
+ expect(colourOf(content, 'textStyle')).toBe('var(--palette-0)');
739
+ });
740
+
741
+ test('keeps a bright logo-text green on white (2.3:1 — below WCAG AA, above the 2:1 floor)', () => {
742
+ // The reported case: the brand's own logo-text green (#7abd2d) reads 2.3:1 on white — legible
743
+ // for a large heading and the chosen identity colour, so it must lead. It clears the 2:1 floor
744
+ // but not the old 3:1 one; the floor was lowered (BP-5969) precisely so brand identity wins here
745
+ // rather than deferring to the higher-contrast navy.
746
+ const styles = stylesWithColors([
747
+ { id: 'palette-0', value: '#7abd2d', type: 'palette' }, // logo-text green — 2.3:1 on white
748
+ { id: 'palette-1', value: '#130e34', type: 'palette' }, // logo-bg navy — 18:1, must NOT win
749
+ { id: 'palette-2', value: '#455538', type: 'palette' },
750
+ { id: 'palette-3', value: '#ecedff', type: 'palette' },
751
+ ]);
752
+
753
+ styles.backgroundStyles.style = { background: '#ffffff' };
754
+
755
+ const content = pageText();
756
+
757
+ applyTextContrast(content, styles);
758
+
759
+ expect(colourOf(content, 'textStyle')).toBe('var(--palette-0)');
760
+ });
761
+
762
+ test('drops to palette-1 only when the logo-text role breaches the floor', () => {
763
+ const styles = stylesWithColors(BRAND_AND_NEUTRALS);
764
+
765
+ // A green-ish page: the green logo-text role is illegible on it, but navy still clears.
766
+ styles.backgroundStyles.style = { background: '#5aa02e' };
767
+
768
+ const content = pageText();
769
+
770
+ applyTextContrast(content, styles);
771
+
772
+ expect(colourOf(content, 'textStyle')).toBe('var(--palette-1)');
773
+ });
774
+
775
+ test('falls back to a neutral when neither brand role clears the contrast floor', () => {
776
+ // Mid-grey page with two mid-grey brand roles: neither reaches the minimum viable contrast,
777
+ // so legibility wins over identity and a neutral is used.
778
+ const styles = stylesWithColors([
779
+ { id: 'palette-0', value: '#8a8a8a', type: 'palette' }, // brand, low contrast on grey
780
+ { id: 'palette-1', value: '#6e6e6e', type: 'palette' }, // brand, low contrast on grey
781
+ { id: 'palette-2', value: '#ffffff', type: 'palette' }, // neutral-light
782
+ { id: 'palette-3', value: '#000000', type: 'palette' }, // neutral-dark
783
+ ]);
784
+
785
+ styles.backgroundStyles.style = { background: '#808080' }; // mid-grey page
786
+
787
+ const content = pageText();
788
+
789
+ applyTextContrast(content, styles);
790
+
791
+ expect(colourOf(content, 'textStyle')).toBe('var(--palette-3)'); // the neutral that contrasts
792
+ });
793
+
794
+ test('falls back to the dark neutral when the page background is not a resolvable solid', () => {
795
+ const styles = stylesWithColors(BRAND_AND_NEUTRALS);
796
+
797
+ styles.backgroundStyles.style = {
798
+ background: 'linear-gradient(#fff, #000)',
799
+ }; // image/gradient
800
+
801
+ const content = pageText();
802
+
803
+ applyTextContrast(content, styles);
804
+
805
+ expect(colourOf(content, 'textStyle')).toBe('var(--palette-3)');
806
+ });
807
+
808
+ test('a centered banner contrasts the site background, not its unpainted white card', () => {
809
+ // Regression: the banner factory seeds cardStyle white, but the centered layout never paints
810
+ // it — the title sits on the (transparent) band → the site background. Contrast must target
811
+ // the site bg, or a dark title lands on a dark page (invisible).
812
+ const styles = stylesWithColors(BRAND_AND_NEUTRALS);
813
+
814
+ styles.backgroundStyles.style = { background: 'var(--palette-1)' }; // dark navy site bg
815
+
816
+ const content = {
817
+ id: 'b',
818
+ type: 'banner-section',
819
+ displayStyle: ALIGN_CENTERED,
820
+ cardStyle: { backgroundColor: 'rgb(255,255,255)' }, // white default, NOT painted here
821
+ backgroundStyle: {},
822
+ titleStyle: { textStyleType: 'heading2' },
823
+ } as unknown as Content;
824
+
825
+ applyTextContrast(content, styles);
826
+
827
+ // dark site bg → the green brand role (visible), not a dark colour for the phantom white card
828
+ expect(colourOf(content, 'titleStyle')).toBe('var(--palette-0)');
829
+ });
830
+
831
+ test('a card-layout banner still contrasts its painted card', () => {
832
+ const styles = stylesWithColors(BRAND_AND_NEUTRALS);
833
+
834
+ styles.backgroundStyles.style = { background: 'var(--palette-1)' }; // dark navy site bg
835
+
836
+ const content = {
837
+ id: 'b',
838
+ type: 'banner-section',
839
+ displayStyle: ALIGN_CARD_CENTER_IMAGE,
840
+ cardStyle: { backgroundColor: 'rgb(255,255,255)' }, // white card, painted in this layout
841
+ backgroundStyle: {},
842
+ titleStyle: { textStyleType: 'heading2' },
843
+ } as unknown as Content;
844
+
845
+ applyTextContrast(content, styles);
846
+
847
+ // white card → the logo-text brand role (green) leads via the card path: green clears the floor
848
+ // on white (~3.4:1), so it wins even though navy contrasts more.
849
+ expect(colourOf(content, 'titleStyle')).toBe('var(--palette-0)');
850
+ });
851
+
852
+ test('brandSite contact-form still bakes: cascades from the carved-out container surface to its card', () => {
853
+ // Regression: containerSurfaceForContent returns undefined for a brandSite contact-form
854
+ // (the render-default carve-out), so the field used to fall through and stay uncoloured.
855
+ // The cascade now routes it to the section's own painted card.
856
+ const styles = stylesWithColors([
857
+ { id: 'palette-0', value: '#7abd2d', type: 'palette' }, // bright logo-text green — 2.3:1 on white
858
+ { id: 'palette-1', value: '#0a2540', type: 'palette' }, // navy — higher contrast on white
859
+ { id: 'palette-2', value: '#ffffff', type: 'palette' },
860
+ { id: 'palette-3', value: '#000000', type: 'palette' },
861
+ ]);
862
+
863
+ const content = {
864
+ id: 'cf',
865
+ type: 'contact-form',
866
+ cardStyle: { backgroundColor: '#ffffff' }, // the painted white card
867
+ titleStyle: { textStyleType: 'heading2' },
868
+ } as unknown as Content;
869
+
870
+ applyTextContrast(content, styles, BRAND_PAGE_TYPES.brandSite);
871
+
872
+ // The cascade routes the field to the card, and the logo-text green clears the 2:1 floor on the
873
+ // white card → it leads (palette-0), even though navy contrasts more. The point is the field is
874
+ // baked from the carved-out container's card surface at all, not left uncoloured.
875
+ expect(colourOf(content, 'titleStyle')).toBe('var(--palette-0)');
876
+ });
877
+
878
+ test('bakes every textItems[] entry (the brand-site text section) against the page', () => {
879
+ // Regression: textItems is not a top-level style key, so it was skipped — the brand-site text
880
+ // section rendered its items uncoloured (browser-default black on a dark page).
881
+ const styles = stylesWithColors(BRAND_AND_NEUTRALS);
882
+
883
+ styles.backgroundStyles.style = { background: 'var(--palette-1)' }; // dark navy page
884
+
885
+ const content = {
886
+ id: 't',
887
+ type: 'text',
888
+ backgroundColor: { backgroundColor: 'transparent' },
889
+ textItems: [
890
+ { id: 'a', textStyle: { textStyleType: 'paragraph1' } },
891
+ { id: 'b', textStyle: { textStyleType: 'paragraph1' } },
892
+ ],
893
+ } as unknown as Content;
894
+
895
+ applyTextContrast(content, styles);
896
+
897
+ const items = (
898
+ content as unknown as { textItems: { textStyle: { color?: string } }[] }
899
+ ).textItems;
900
+
901
+ expect(items[0].textStyle.color).toBe('var(--palette-0)'); // logo-text green on the dark page
902
+ expect(items[1].textStyle.color).toBe('var(--palette-0)');
903
+ });
904
+
905
+ test('a new textItems entry inherits the item above it instead of re-contrasting', () => {
906
+ // The item above is recoloured (palette-3); a new uncoloured item must MATCH it, not fall to
907
+ // the page-contrast default (palette-0), so the section stays one colour.
908
+ const styles = stylesWithColors(BRAND_AND_NEUTRALS);
909
+
910
+ styles.backgroundStyles.style = { background: 'var(--palette-1)' }; // dark page → contrast = green
911
+
912
+ const content = {
913
+ id: 't',
914
+ type: 'text',
915
+ backgroundColor: { backgroundColor: 'transparent' },
916
+ textItems: [
917
+ {
918
+ id: 'a',
919
+ textStyle: { textStyleType: 'paragraph1', color: 'var(--palette-3)' },
920
+ },
921
+ { id: 'b', textStyle: { textStyleType: 'paragraph1' } }, // new, uncoloured
922
+ ],
923
+ } as unknown as Content;
924
+
925
+ applyTextContrast(content, styles);
926
+
927
+ const items = (
928
+ content as unknown as { textItems: { textStyle: { color?: string } }[] }
929
+ ).textItems;
930
+
931
+ expect(items[0].textStyle.color).toBe('var(--palette-3)'); // untouched
932
+ expect(items[1].textStyle.color).toBe('var(--palette-3)'); // inherited, NOT the green contrast
933
+ });
934
+
935
+ test('a new item follows the item directly above (the last), not the first', () => {
936
+ // Stacked items: first recoloured, second recoloured differently. A third (new) item takes the
937
+ // SECOND item's colour — the one above it in the stack — not the first, and not a re-contrast.
938
+ const styles = stylesWithColors(BRAND_AND_NEUTRALS);
939
+
940
+ styles.backgroundStyles.style = { background: 'var(--palette-1)' };
941
+
942
+ const content = {
943
+ id: 't',
944
+ type: 'text',
945
+ backgroundColor: { backgroundColor: 'transparent' },
946
+ textItems: [
947
+ {
948
+ id: 'a',
949
+ textStyle: { textStyleType: 'paragraph1', color: 'var(--palette-0)' }, // 1st: green
950
+ },
951
+ {
952
+ id: 'b',
953
+ textStyle: { textStyleType: 'paragraph1', color: 'var(--palette-3)' }, // 2nd: dark neutral
954
+ },
955
+ { id: 'c', textStyle: { textStyleType: 'paragraph1' } }, // 3rd: new, uncoloured
956
+ ],
957
+ } as unknown as Content;
958
+
959
+ applyTextContrast(content, styles);
960
+
961
+ const items = (
962
+ content as unknown as { textItems: { textStyle: { color?: string } }[] }
963
+ ).textItems;
964
+
965
+ expect(items[2].textStyle.color).toBe('var(--palette-3)'); // the item above (2nd), not the 1st
966
+ });
967
+
968
+ test('inherits the RENDERED mark colour, not a stale style colour left by an earlier bake', () => {
969
+ // The real repro: item 2 was inherited green (textStyle.color), then recoloured white — the RTE
970
+ // writes the MARK but leaves textStyle.color=green. A new item 3 must inherit the rendered white
971
+ // (the mark), not the stale green.
972
+ const markDoc = (color: string) => ({
973
+ type: 'doc',
974
+ content: [
975
+ {
976
+ type: 'paragraph',
977
+ content: [
978
+ {
979
+ type: 'text',
980
+ text: 'x',
981
+ marks: [{ type: 'textStyle', attrs: { color } }],
982
+ },
983
+ ],
984
+ },
985
+ ],
986
+ });
987
+
988
+ const styles = stylesWithColors(BRAND_AND_NEUTRALS);
989
+
990
+ styles.backgroundStyles.style = { background: 'var(--palette-1)' };
991
+
992
+ const content = {
993
+ id: 't',
994
+ type: 'text',
995
+ backgroundColor: { backgroundColor: 'transparent' },
996
+ textItems: [
997
+ {
998
+ id: 'a',
999
+ text: markDoc('var(--palette-3)'), // rendered white
1000
+ textStyle: { textStyleType: 'paragraph1', color: 'var(--palette-0)' }, // STALE green
1001
+ },
1002
+ { id: 'b', textStyle: { textStyleType: 'paragraph1' } }, // new, uncoloured
1003
+ ],
1004
+ } as unknown as Content;
1005
+
1006
+ applyTextContrast(content, styles);
1007
+
1008
+ const items = (
1009
+ content as unknown as { textItems: { textStyle: { color?: string } }[] }
1010
+ ).textItems;
1011
+
1012
+ expect(items[1].textStyle.color).toBe('var(--palette-3)'); // the mark, not the stale style
1013
+ });
1014
+
1015
+ test('inherits the above item colour from its RTE run mark when the style colour was cleared', () => {
1016
+ // After birth authoring, an item carries its colour in the run mark (style colour cleared).
1017
+ // A new item below must still inherit it.
1018
+ const styles = stylesWithColors(BRAND_AND_NEUTRALS);
1019
+
1020
+ styles.backgroundStyles.style = { background: 'var(--palette-1)' };
1021
+
1022
+ const content = {
1023
+ id: 't',
1024
+ type: 'text',
1025
+ backgroundColor: { backgroundColor: 'transparent' },
1026
+ textItems: [
1027
+ {
1028
+ id: 'a',
1029
+ text: {
1030
+ type: 'doc',
1031
+ content: [
1032
+ {
1033
+ type: 'paragraph',
1034
+ content: [
1035
+ {
1036
+ type: 'text',
1037
+ text: 'x',
1038
+ marks: [
1039
+ {
1040
+ type: 'textStyle',
1041
+ attrs: { color: 'var(--palette-3)' },
1042
+ },
1043
+ ],
1044
+ },
1045
+ ],
1046
+ },
1047
+ ],
1048
+ },
1049
+ textStyle: { textStyleType: 'paragraph1' }, // style colour cleared; lives in the mark
1050
+ },
1051
+ { id: 'b', textStyle: { textStyleType: 'paragraph1' } },
1052
+ ],
1053
+ } as unknown as Content;
1054
+
1055
+ applyTextContrast(content, styles);
1056
+
1057
+ const items = (
1058
+ content as unknown as { textItems: { textStyle: { color?: string } }[] }
1059
+ ).textItems;
1060
+
1061
+ expect(items[1].textStyle.color).toBe('var(--palette-3)'); // inherited from item[0]'s mark
1062
+ });
1063
+
1064
+ test('never overwrites an explicit element colour', () => {
1065
+ const content = {
1066
+ id: 't',
1067
+ type: 'text',
1068
+ backgroundColor: { backgroundColor: 'var(--palette-0)' },
1069
+ textStyle: { textStyleType: 'paragraph1', color: '#abcabc' },
1070
+ } as unknown as Content;
1071
+
1072
+ applyTextContrast(content, stylesWithColors());
1073
+
1074
+ expect(colourOf(content, 'textStyle')).toBe('#abcabc');
1075
+ });
1076
+
1077
+ test('never bakes the button label — it owns its own fill/text pairing', () => {
1078
+ const content = {
1079
+ id: 's',
1080
+ type: 'shapes-section',
1081
+ backgroundColor: { backgroundColor: 'var(--palette-0)' }, // dark band
1082
+ buttonTextStyle: { textStyleType: 'button' },
1083
+ } as unknown as Content;
1084
+
1085
+ applyTextContrast(content, stylesWithColors());
1086
+
1087
+ expect(colourOf(content, 'buttonTextStyle')).toBeUndefined();
1088
+ });
1089
+
1090
+ // BP-6144 S2: shop's title/description sit on the band, not the product tile — a
1091
+ // sibling surface below them, not behind them. `topmostSolidSurface`'s generic
1092
+ // top-of-stack scan would pick the tile (`fillColor` outranks `backgroundStyle`) and
1093
+ // MIScolour the title against a surface it doesn't render on.
1094
+ test('shop title contrasts the band, not a painted product tile', () => {
1095
+ const content = {
1096
+ id: 'sh',
1097
+ type: 'shop-section',
1098
+ fillColor: { backgroundColor: '#ffffff' }, // light tile
1099
+ backgroundStyle: { backgroundColor: 'var(--palette-0)' }, // dark band
1100
+ titleStyle: { textStyleType: 'heading1' },
1101
+ } as unknown as Content;
1102
+
1103
+ applyTextContrast(content, stylesWithColors());
1104
+
1105
+ // Light on the dark band — a tile-routed fallback would give the dark-on-dark brand role.
1106
+ expect(colourOf(content, 'titleStyle')).toBe('var(--palette-1)');
1107
+ });
1108
+
1109
+ test('shop description contrasts the band on the same rule as the title', () => {
1110
+ const content = {
1111
+ id: 'sh',
1112
+ type: 'shop-section',
1113
+ fillColor: { backgroundColor: '#ffffff' }, // light tile
1114
+ backgroundStyle: { backgroundColor: 'var(--palette-0)' }, // dark band
1115
+ descriptionStyle: { textStyleType: 'paragraph1' },
1116
+ } as unknown as Content;
1117
+
1118
+ applyTextContrast(content, stylesWithColors());
1119
+
1120
+ expect(colourOf(content, 'descriptionStyle')).toBe('var(--palette-1)');
1121
+ });
1122
+
1123
+ test('shop title defers to the page when the band paints nothing solid, not the tile', () => {
1124
+ const styles = stylesWithColors(); // palette-0 #000000 (dark), palette-1 #ffffff (light)
1125
+
1126
+ styles.backgroundStyles.style = { background: 'var(--palette-0)' }; // dark page
1127
+
1128
+ const content = {
1129
+ id: 'sh',
1130
+ type: 'shop-section',
1131
+ fillColor: { backgroundColor: 'var(--palette-1)' }, // light tile, would win a tile fallback
1132
+ backgroundStyle: {}, // transparent band
1133
+ titleStyle: { textStyleType: 'heading1' },
1134
+ } as unknown as Content;
1135
+
1136
+ applyTextContrast(content, styles);
1137
+
1138
+ // Falls through to the dark page → light text; a tile fallback would give dark-on-light.
1139
+ expect(colourOf(content, 'titleStyle')).toBe('var(--palette-1)');
1140
+ });
1141
+ });
1142
+
1143
+ describe('applyTextContrast — standalone button labels (BP-5969)', () => {
1144
+ // Every standalone button keeps its label in `titleStyle`. The label sits on the button fill,
1145
+ // so the button owns its own fill/text pairing and the label must NOT be baked against the page.
1146
+ // Source of truth for this set is `isButtonContent` (model.util.ts) — keep the two in sync.
1147
+ const BUTTON_CONTENT_TYPES = [
1148
+ 'general-link',
1149
+ 'website',
1150
+ 'email',
1151
+ 'phone',
1152
+ 'facebook',
1153
+ 'x',
1154
+ 'instagram',
1155
+ 'youtube',
1156
+ 'linkedin',
1157
+ 'pinterest',
1158
+ 'twitch',
1159
+ 'tiktok',
1160
+ ] as const;
1161
+
1162
+ const colourOf = (content: Content, key: string): string | undefined =>
1163
+ (content as unknown as Record<string, { color?: string }>)[key]?.color;
1164
+
1165
+ // Reproduces the default theme's collision: the button fill and the page-contrast pick are the
1166
+ // SAME brand role (palette-0 is both the fill and the dark role that contrasts a white page).
1167
+ // If the label were baked it would take that role and vanish into the fill.
1168
+ const collidingStyles = (): PageStyles => {
1169
+ const styles = new PageStyles();
1170
+
1171
+ styles.colors = [
1172
+ { id: 'palette-0', value: '#000000', type: 'palette' }, // dark brand — the button fill
1173
+ { id: 'palette-1', value: '#ffffff', type: 'palette' }, // light brand
1174
+ ];
1175
+ styles.backgroundStyles.style = { background: 'var(--palette-1)' }; // white page
1176
+ styles.buttonStyles.style = {
1177
+ backgroundColor: 'var(--palette-0)', // dark fill
1178
+ color: 'var(--palette-1)', // light on-fill label — what the unbaked label inherits at render
1179
+ };
1180
+
1181
+ return styles;
1182
+ };
1183
+
1184
+ test.each(BUTTON_CONTENT_TYPES)(
1185
+ 'leaves the %s label uncoloured so it inherits the button on-fill colour',
1186
+ (type) => {
1187
+ const content = {
1188
+ id: 'b',
1189
+ type,
1190
+ title: 'Link',
1191
+ titleStyle: { textStyleType: 'button', textAlign: 'center' },
1192
+ } as unknown as Content;
1193
+
1194
+ applyTextContrast(content, collidingStyles());
1195
+
1196
+ // Baked here it would become var(--palette-0) — the fill — and disappear.
1197
+ expect(colourOf(content, 'titleStyle')).toBeUndefined();
1198
+ },
1199
+ );
1200
+
1201
+ test('buttonLabelColorDefault gives the label the button on-fill colour for the swatch', () => {
1202
+ const styles = collidingStyles(); // button on-fill colour is var(--palette-1)
1203
+
1204
+ const button = { id: 'b', type: 'general-link' } as unknown as Content;
1205
+
1206
+ // The label field takes the on-fill colour so the maker swatch matches the canvas.
1207
+ expect(buttonLabelColorDefault(button, styles, 'titleStyle')).toBe(
1208
+ 'var(--palette-1)',
1209
+ );
1210
+
1211
+ // Not a label field, and not a button → nothing to default.
1212
+ expect(
1213
+ buttonLabelColorDefault(button, styles, 'descriptionStyle'),
1214
+ ).toBeUndefined();
1215
+ expect(
1216
+ buttonLabelColorDefault(
1217
+ { id: 's', type: 'shapes-section' } as unknown as Content,
1218
+ styles,
1219
+ 'titleStyle',
1220
+ ),
1221
+ ).toBeUndefined();
1222
+ });
1223
+
1224
+ test('the exemption is scoped to button content, not the titleStyle key globally', () => {
1225
+ // A section heading uses the same `titleStyle` key and MUST still bake against its band.
1226
+ const styles = new PageStyles();
1227
+
1228
+ styles.colors = [
1229
+ { id: 'palette-0', value: '#000000', type: 'palette' },
1230
+ { id: 'palette-1', value: '#ffffff', type: 'palette' },
1231
+ ];
1232
+ styles.buttonStyles.style = { backgroundColor: 'var(--palette-1)' }; // white fill ≠ the band
1233
+
1234
+ const content = {
1235
+ id: 's',
1236
+ type: 'shapes-section',
1237
+ backgroundColor: { backgroundColor: 'var(--palette-0)' }, // dark band
1238
+ titleStyle: { textStyleType: 'heading1' },
1239
+ } as unknown as Content;
1240
+
1241
+ applyTextContrast(content, styles);
1242
+
1243
+ expect(colourOf(content, 'titleStyle')).toBe('var(--palette-1)'); // light on the dark band
1244
+ });
1245
+ });
1246
+
1247
+ describe('applyTextContrast — social-links icon fill', () => {
1248
+ const styles = (): PageStyles => {
1249
+ const pageStyles = new PageStyles();
1250
+
1251
+ pageStyles.colors = [
1252
+ { id: 'palette-0', value: '#000000', type: 'palette' },
1253
+ { id: 'palette-1', value: '#ffffff', type: 'palette' },
1254
+ ];
1255
+
1256
+ return pageStyles;
1257
+ };
1258
+
1259
+ const socialLinks = (iconFillStyles: BrandPageCssStyle): Content =>
1260
+ ({
1261
+ id: 's',
1262
+ type: 'social-links',
1263
+ titleStyle: { textStyleType: 'heading4' },
1264
+ iconFillStyles,
1265
+ backgroundStyles: {},
1266
+ }) as unknown as Content;
1267
+
1268
+ const iconFill = (content: Content): string | undefined =>
1269
+ (content as unknown as { iconFillStyles: BrandPageCssStyle }).iconFillStyles
1270
+ .fill;
1271
+
1272
+ test('a new section stores the colour its title gets on the icons', () => {
1273
+ const content = socialLinks({});
1274
+
1275
+ applyTextContrast(content, styles());
1276
+
1277
+ const titleColour = (
1278
+ content as unknown as { titleStyle: { color?: string } }
1279
+ ).titleStyle.color;
1280
+
1281
+ expect(titleColour).toBeTruthy();
1282
+ expect(iconFill(content)).toBe(titleColour);
1283
+ });
1284
+
1285
+ test('an explicit icon fill is left alone', () => {
1286
+ const content = socialLinks({ fill: '#abcdef' });
1287
+
1288
+ applyTextContrast(content, styles());
1289
+
1290
+ expect(iconFill(content)).toBe('#abcdef');
1291
+ });
1292
+ });