@designcrowd/library.brand-page 6.2.11 → 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 (576) hide show
  1. package/lib/src/{CreatedOnBrandCrowd-de-de-DDcraD5S.js → CreatedOnBrandCrowd-de-de-BtVKllNQ.js} +1 -1
  2. package/lib/src/{CreatedOnBrandCrowd-en-us-DtOeaisf.js → CreatedOnBrandCrowd-en-us-CX5V0v8u.js} +1 -1
  3. package/lib/src/{CreatedOnBrandCrowd-es-es-BZpmJPew.js → CreatedOnBrandCrowd-es-es-CbA02PCL.js} +1 -1
  4. package/lib/src/{CreatedOnBrandCrowd-fr-fr-CqRwC4e7.js → CreatedOnBrandCrowd-fr-ca-BQAKruBF.js} +1 -1
  5. package/lib/src/{CreatedOnBrandCrowd-fr-ca-CqRwC4e7.js → CreatedOnBrandCrowd-fr-fr-BQAKruBF.js} +1 -1
  6. package/lib/src/{CreatedOnBrandCrowd-pt-pt-DId9Dfjh.js → CreatedOnBrandCrowd-pt-br-Yk_yzB3s.js} +1 -1
  7. package/lib/src/{CreatedOnBrandCrowd-pt-br-DId9Dfjh.js → CreatedOnBrandCrowd-pt-pt-Yk_yzB3s.js} +1 -1
  8. package/lib/src/{CreatedOnDcom-de-de-BTDfmOcm.js → CreatedOnDcom-de-de-DJZQbPSD.js} +1 -1
  9. package/lib/src/{CreatedOnDcom-en-us-CeAu9Ayx.js → CreatedOnDcom-en-us-BJvNAa4l.js} +1 -1
  10. package/lib/src/{CreatedOnDcom-es-es-WCv0K41H.js → CreatedOnDcom-es-es-CUwB1FRY.js} +1 -1
  11. package/lib/src/{CreatedOnDcom-fr-ca-BlfevQDY.js → CreatedOnDcom-fr-ca-CK54U4oh.js} +1 -1
  12. package/lib/src/{CreatedOnDcom-fr-fr-Cvt7MHPZ.js → CreatedOnDcom-fr-fr-DuUNBGrM.js} +1 -1
  13. package/lib/src/{CreatedOnDcom-pt-br-DipZuylv.js → CreatedOnDcom-pt-br-BfODpFNV.js} +1 -1
  14. package/lib/src/{CreatedOnDcom-pt-pt-BCw4lcKN.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/index.d.ts +23 -24
  39. package/lib/src/brand-page/models/index.js +20 -7
  40. package/lib/src/brand-page/models/navigation-styles.model.d.ts +1 -1
  41. package/lib/src/brand-page/models/navigation-styles.model.js +17 -8
  42. package/lib/src/brand-page/models/payment.model.d.ts +11 -6
  43. package/lib/src/brand-page/models/styles.model.d.ts +53 -7
  44. package/lib/src/brand-page/models/styles.model.js +115 -27
  45. package/lib/src/brand-page/utils/color-palette.util.d.ts +43 -23
  46. package/lib/src/brand-page/utils/color-palette.util.js +65 -27
  47. package/lib/src/brand-page/utils/color.util.d.ts +13 -9
  48. package/lib/src/brand-page/utils/color.util.js +56 -15
  49. package/lib/src/brand-page/utils/container-text-color.util.d.ts +46 -13
  50. package/lib/src/brand-page/utils/container-text-color.util.js +321 -41
  51. package/lib/src/brand-page/utils/index.d.ts +1 -0
  52. package/lib/src/brand-page/utils/index.js +1 -0
  53. package/lib/src/brand-page/utils/migration/migration-20.js +6 -2
  54. package/lib/src/brand-page/utils/migration/migration-21.js +34 -6
  55. package/lib/src/brand-page/utils/migration/migration-22.d.ts +99 -0
  56. package/lib/src/brand-page/utils/migration/migration-22.js +909 -0
  57. package/lib/src/brand-page/utils/migration.util.js +17 -0
  58. package/lib/src/brand-page/utils/model.util.d.ts +4 -0
  59. package/lib/src/brand-page/utils/model.util.js +4 -0
  60. package/lib/src/brand-page/utils/personalisation.util.js +9 -1
  61. package/lib/src/brand-page/utils/rte-role-lift.util.d.ts +72 -0
  62. package/lib/src/brand-page/utils/rte-role-lift.util.js +275 -0
  63. package/lib/src/brand-page/utils/style.util.d.ts +5 -1
  64. package/lib/src/brand-page/utils/style.util.js +34 -11
  65. package/lib/src/brand-page/utils/text-role-css.util.d.ts +19 -0
  66. package/lib/src/brand-page/utils/text-role-css.util.js +186 -0
  67. package/lib/src/brand-page/utils/text-role-reconnect.util.d.ts +90 -0
  68. package/lib/src/brand-page/utils/text-role-reconnect.util.js +434 -0
  69. package/lib/src/brand-page/utils/text-style.util.d.ts +53 -23
  70. package/lib/src/brand-page/utils/text-style.util.js +122 -22
  71. package/lib/src/brand-page/utils/view-model.util.d.ts +9 -1
  72. package/lib/src/brand-page/utils/view-model.util.js +124 -111
  73. package/lib/src/brand-page/view-models.d.ts +1 -0
  74. package/lib/src/brand-page-maker/components/action-bar/ActionBar.mixin.d.ts +4 -1
  75. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +13 -2
  76. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.js +4 -4
  77. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMakerTemplateSettings.mixin.d.ts +4 -1
  78. package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.js +0 -10
  79. package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/content-settings-items.fixture.js +0 -1
  80. package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +23 -138
  81. package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.js +0 -28
  82. package/lib/src/brand-page-maker/components/brandpage-settings/ReplaceImageSettingsForBrandPageSettings.mixin.d.ts +4 -1
  83. package/lib/src/brand-page-maker/components/navigation/Navigation.mixin.d.ts +1 -1
  84. package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.d.ts +5 -2
  85. package/lib/src/brand-page-maker/components/seo-settings/UrlSettings.mixin.d.ts +4 -1
  86. package/lib/src/brand-page-maker/components/social-share/SocialShare.mixin.d.ts +4 -1
  87. package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.d.ts +4 -1
  88. package/lib/src/brand-page-maker/composables/ai-chat/useAiMetadataBuilder.d.ts +1 -0
  89. package/lib/src/brand-page-maker/composables/ai-chat/useAiMetadataBuilder.js +1 -0
  90. package/lib/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.js +1 -0
  91. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/RoleTypographyFill.d.ts +16 -0
  92. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/RoleTypographyFill.js +61 -0
  93. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/RteClipboard.d.ts +11 -0
  94. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/RteClipboard.js +236 -0
  95. package/lib/src/brand-page-maker/composables/rich-text-editor/font.d.ts +2 -1
  96. package/lib/src/brand-page-maker/composables/rich-text-editor/font.js +25 -6
  97. package/lib/src/brand-page-maker/composables/rich-text-editor/formatting.d.ts +17 -4
  98. package/lib/src/brand-page-maker/composables/rich-text-editor/formatting.js +204 -17
  99. package/lib/src/brand-page-maker/composables/rich-text-editor/hyperlink.d.ts +1 -1
  100. package/lib/src/brand-page-maker/composables/rich-text-editor/hyperlink.js +29 -31
  101. package/lib/src/brand-page-maker/composables/rich-text-editor/keepMarksOnEmpty.d.ts +20 -0
  102. package/lib/src/brand-page-maker/composables/rich-text-editor/keepMarksOnEmpty.js +60 -0
  103. package/lib/src/brand-page-maker/composables/rich-text-editor/spacing.d.ts +2 -1
  104. package/lib/src/brand-page-maker/composables/rich-text-editor/spacing.js +22 -6
  105. package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.d.ts +10 -4
  106. package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.js +319 -275
  107. package/lib/src/brand-page-maker/constants/config-settings-constant.js +1 -5
  108. package/lib/src/brand-page-maker/convertors/text-css-style-options.convertor.js +6 -2
  109. package/lib/src/brand-page-maker/convertors/text-size-value.convertor.d.ts +1 -1
  110. package/lib/src/brand-page-maker/convertors/text-size-value.convertor.js +3 -1
  111. package/lib/src/brand-page-maker/default-getters/payment-text-and-border-color.default-getter.js +7 -14
  112. package/lib/src/brand-page-maker/default-getters/text-color.default-getter.js +6 -13
  113. package/lib/src/brand-page-maker/models/content-settings.d.ts +8 -0
  114. package/lib/src/brand-page-maker/models/content-settings.js +112 -81
  115. package/lib/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store-utils.d.ts +2 -2
  116. package/lib/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store-utils.js +5 -2
  117. package/lib/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store.js +4 -3
  118. package/lib/src/brand-page-maker/stores/ai-checkpoint/ai-checkpoint-store.d.ts +1257 -117
  119. package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.d.ts +6 -1
  120. package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.js +17 -9
  121. package/lib/src/brand-page-maker/stores/history/history-store.d.ts +59 -5
  122. package/lib/src/brand-page-maker/stores/history/history-store.js +22 -2
  123. package/lib/src/brand-page-maker/utils/apply-color-strategy.js +26 -8
  124. package/lib/src/brand-page-maker/utils/index.d.ts +2 -1
  125. package/lib/src/brand-page-maker/utils/index.js +2 -1
  126. package/lib/src/brand-page-maker/utils/rich-text-editor.util.d.ts +117 -15
  127. package/lib/src/brand-page-maker/utils/rich-text-editor.util.js +435 -281
  128. package/lib/src/brand-page-maker/utils/rte-authoring.util.d.ts +4 -0
  129. package/lib/src/brand-page-maker/utils/rte-authoring.util.js +101 -0
  130. package/lib/src/brand-page-maker/utils/rte-clipboard.util.d.ts +126 -0
  131. package/lib/src/brand-page-maker/utils/rte-clipboard.util.js +307 -0
  132. package/lib/src/brand-page-maker/utils/rte-sanitize.util.js +13 -3
  133. package/lib/src/{bundled-translations-zfiA5Tsw.js → bundled-translations-yGrvPE5i.js} +17 -17
  134. package/lib/src/{bundled-translations.de-DE-ChsdSyAP.js → bundled-translations.de-DE-L4Znf8Hs.js} +17 -17
  135. package/lib/src/{bundled-translations.es-ES-DflsWQK0.js → bundled-translations.es-ES-D6iticrK.js} +15 -15
  136. package/lib/src/{bundled-translations.fr-CA-fpDRuZ52.js → bundled-translations.fr-CA-BgAVE-9k.js} +25 -25
  137. package/lib/src/{bundled-translations.fr-FR-Bub73Zt-.js → bundled-translations.fr-FR-B8GbyqxQ.js} +17 -17
  138. package/lib/src/{bundled-translations.pt-BR-BlnWE9TB.js → bundled-translations.pt-BR-DjPU3Db7.js} +25 -25
  139. package/lib/src/{bundled-translations.pt-PT-DmzXlnaS.js → bundled-translations.pt-PT-BaepaDpr.js} +23 -23
  140. package/lib/src/bundles/bundled-translations.de-DE.json +21 -2
  141. package/lib/src/bundles/bundled-translations.es-ES.json +21 -2
  142. package/lib/src/bundles/bundled-translations.fr-CA.json +21 -2
  143. package/lib/src/bundles/bundled-translations.fr-FR.json +21 -2
  144. package/lib/src/bundles/bundled-translations.json +21 -2
  145. package/lib/src/bundles/bundled-translations.pt-BR.json +21 -2
  146. package/lib/src/bundles/bundled-translations.pt-PT.json +21 -2
  147. package/lib/src/clients/ai-assistant-client.d.ts +1 -0
  148. package/lib/src/composables/useTranslate.d.ts +1 -1
  149. package/lib/src/composables/useTranslate.js +1 -1
  150. package/lib/src/css/library.brand-page-brandCrowd.min.css +303 -207
  151. package/lib/src/css/library.brand-page-brandPage.min.css +303 -207
  152. package/lib/src/css/library.brand-page-designCom.min.css +303 -207
  153. package/lib/src/css/library.brand-page-preview.min.css +303 -207
  154. package/lib/src/index.d.ts +2 -1
  155. package/lib/src/index.mjs +195 -191
  156. package/lib/src/{lib-1AqtEmvQ.js → lib-kGRlD3_P.js} +36855 -33893
  157. package/lib/src/lib.js +2 -1
  158. package/lib/src/metadata-builder/builders/footer-builder.js +4 -5
  159. package/lib/src/metadata-builder/builders/global-role-propagation.d.ts +58 -0
  160. package/lib/src/metadata-builder/builders/global-role-propagation.js +246 -0
  161. package/lib/src/metadata-builder/builders/global-styles-builder.d.ts +1 -0
  162. package/lib/src/metadata-builder/builders/global-styles-builder.js +116 -45
  163. package/lib/src/metadata-builder/builders/header-builder.js +13 -4
  164. package/lib/src/metadata-builder/builders/section-builders/about-section-builder.js +3 -3
  165. package/lib/src/metadata-builder/builders/section-builders/banner-section-builder.js +3 -3
  166. package/lib/src/metadata-builder/builders/section-builders/booking-section-builder.js +3 -3
  167. package/lib/src/metadata-builder/builders/section-builders/contact-form-builder.js +4 -4
  168. package/lib/src/metadata-builder/builders/section-builders/images-section-builder.js +3 -3
  169. package/lib/src/metadata-builder/builders/section-builders/mailing-list-builder.js +2 -2
  170. package/lib/src/metadata-builder/builders/section-builders/mailing-list-section-builder.js +2 -2
  171. package/lib/src/metadata-builder/builders/section-builders/profile-section-builder.js +4 -4
  172. package/lib/src/metadata-builder/builders/section-builders/shapes-section-builder.js +3 -3
  173. package/lib/src/metadata-builder/builders/section-builders/social-links-builder.js +8 -2
  174. package/lib/src/metadata-builder/builders/section-builders/testimonial-section-builder.js +2 -2
  175. package/lib/src/metadata-builder/builders/section-builders/text-section-builder.js +60 -29
  176. package/lib/src/metadata-builder/builders/section-field-maps.js +1 -0
  177. package/lib/src/metadata-builder/builders/section-field-utils.d.ts +48 -19
  178. package/lib/src/metadata-builder/builders/section-field-utils.js +128 -52
  179. package/lib/src/metadata-builder/builders/section-rules/global-styles.rules.d.ts +4 -2
  180. package/lib/src/metadata-builder/builders/section-rules/global-styles.rules.js +28 -12
  181. package/lib/src/metadata-builder/builders/section-rules/social-links.rules.js +5 -1
  182. package/lib/src/metadata-builder/helpers/rte.helpers.d.ts +1 -1
  183. package/lib/src/metadata-builder/helpers/rte.helpers.js +97 -40
  184. package/lib/src/metadata-builder/metadata-executor.js +23 -1
  185. package/lib/src/metadata-builder/models.d.ts +2 -0
  186. package/lib/src/metadata-builder/parsers/ai-toolcall-parser.d.ts +18 -19
  187. package/lib/src/metadata-builder/parsers/section-tool-arguments.d.ts +18 -1
  188. package/lib/src/metadata-builder/sanitizers/rte-schema-check.js +1 -1
  189. package/lib/src/metadata-builder/sanitizers/sanitizer-rules.d.ts +0 -1
  190. package/lib/src/metadata-builder/sanitizers/sanitizer-rules.js +5 -8
  191. package/lib/src/metadata-builder/sanitizers/section-args-validator.d.ts +7 -16
  192. package/lib/src/metadata-builder/sanitizers/section-args-validator.js +95 -22
  193. package/lib/src/shared/color-palette/section-color-matches.js +9 -25
  194. package/lib/src/shared/color-strategies/color-strategies.d.ts +15 -0
  195. package/lib/src/shared/color-strategies/color-strategies.js +31 -0
  196. package/lib/src/shared/color-strategies/rte-color.d.ts +8 -0
  197. package/lib/src/shared/color-strategies/rte-color.js +16 -0
  198. package/lib/src/shared/color-strategies/rte-field-pairs.d.ts +23 -0
  199. package/lib/src/shared/color-strategies/rte-field-pairs.js +28 -0
  200. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +9 -135
  201. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.js +1 -27
  202. package/lib/src/shared/content-settings/components/content-settings/ReplaceImageSettingsForContent.mixin.d.ts +12 -2
  203. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.d.ts +7 -0
  204. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.d.ts +75 -6
  205. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.js +18 -7
  206. package/lib/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.d.ts +6 -1
  207. package/lib/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.js +0 -7
  208. package/lib/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.d.ts +1 -0
  209. package/lib/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.js +8 -4
  210. package/lib/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.d.ts +1255 -26
  211. package/lib/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.js +203 -59
  212. package/lib/src/shared/content-settings/store/content-settings-store.d.ts +6 -0
  213. package/lib/src/shared/content-settings/store/content-settings-store.js +105 -8
  214. package/lib/src/shared/logo-settings/components/LogoSettings.mixin.d.ts +5 -1
  215. package/lib/src/shared/navigation-style-settings/store/index.d.ts +7 -3
  216. package/lib/src/shared/navigation-style-settings/store/index.js +40 -15
  217. package/lib/src/shared/page-settings/components/delete-page-modal/DeletePageModal.mixin.d.ts +1 -1
  218. package/lib/src/shared/page-settings/components/new-page-modal/NewPageModal.mixin.d.ts +1 -0
  219. package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +17 -5
  220. package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +70 -13
  221. package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.js +10 -2
  222. package/lib/src/shared/page-settings/store/page-settings-store.d.ts +2 -1
  223. package/lib/src/shared/page-settings/store/page-settings-store.js +17 -0
  224. package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +4 -1
  225. package/lib/src/shared/rte-extensions/AutoLink.d.ts +17 -0
  226. package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/AutoLink.js +67 -51
  227. package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/MaxLength.js +4 -1
  228. package/lib/src/shared/rte-extensions/TextEffects.d.ts +28 -0
  229. package/lib/src/shared/rte-extensions/TextEffects.js +96 -0
  230. package/lib/src/shared/rte-extensions/ViewDomParser.d.ts +2 -0
  231. package/lib/src/shared/rte-extensions/ViewDomParser.js +21 -0
  232. package/lib/src/shared/rte-extensions.util.d.ts +25 -0
  233. package/lib/src/{brand-page-maker/composables/rich-text-editor/getRteExtensions.js → shared/rte-extensions.util.js} +62 -7
  234. package/lib/src/shared/rte-link.util.d.ts +1 -0
  235. package/lib/src/shared/rte-link.util.js +1 -0
  236. package/lib/src/shared/rte-render.util.d.ts +112 -0
  237. package/lib/src/shared/rte-render.util.js +255 -0
  238. package/lib/src/shared/rte-shape.util.d.ts +6 -0
  239. package/lib/src/shared/rte-shape.util.js +18 -0
  240. package/lib/src/shared/side-bar/components/SideBar.mixin.d.ts +2 -1
  241. package/lib/src/shared/side-bar/components/SideBarTabButton.mixin.d.ts +1 -0
  242. package/lib/src/shared/side-bar/store/side-bar-store.d.ts +2 -0
  243. package/lib/src/shared/side-bar/store/side-bar-store.js +9 -0
  244. package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +155 -15
  245. package/lib/src/shared/style-settings/components/StyleSettings.mixin.js +7 -1
  246. package/lib/src/shared/style-settings/store/style-settings-store.d.ts +1 -9
  247. package/lib/src/shared/style-settings/store/style-settings-store.js +3 -33
  248. package/lib/src/shared/style-settings/text-style-size-order.d.ts +2 -0
  249. package/lib/src/shared/style-settings/text-style-size-order.js +13 -0
  250. package/lib/src/shared/text-role-typography.util.d.ts +64 -0
  251. package/lib/src/shared/text-role-typography.util.js +183 -0
  252. package/lib/src/utils/minify-brand-page-metadata.d.ts +16 -1
  253. package/lib/src/utils/minify-brand-page-metadata.js +31 -9
  254. package/package.json +1 -1
  255. package/src/brand-page/__fixtures__/migration-22-v21/edited-brandsite-sections.v21.json +982 -0
  256. package/src/brand-page/__fixtures__/migration-22-v21/new-brandcontact-every-section.v21.json +1231 -0
  257. package/src/brand-page/__fixtures__/migration-22-v21/new-brandpage-every-section.v21.json +1231 -0
  258. package/src/brand-page/__fixtures__/migration-22-v21/new-brandsite-every-section.v21.json +1243 -0
  259. package/src/brand-page/__fixtures__/migration-22-v21/real-brandcontact.v21.json +755 -0
  260. package/src/brand-page/__fixtures__/migration-22-v21/real-brandpage-general-link.v21.json +527 -0
  261. package/src/brand-page/__fixtures__/migration-22-v21/real-brandpage-links.v21.json +755 -0
  262. package/src/brand-page/__fixtures__/migration-22-v21/real-brandpage-social-links.v21.json +514 -0
  263. package/src/brand-page/__fixtures__/migration-22-v21/real-brandsite-about.v21.json +459 -0
  264. package/src/brand-page/__fixtures__/migration-22-v21/real-brandsite-footer.v21.json +469 -0
  265. package/src/brand-page/__fixtures__/migration-22-v21/real-brandsite-header-banner.v21.json +481 -0
  266. package/src/brand-page/__fixtures__/migration-22-v21/real-brandsite-sections.v21.json +800 -0
  267. package/src/brand-page/__fixtures__/production-text-style-resolver.fixture.ts +52 -0
  268. package/src/brand-page/components/about-section/AboutSection.vue.test.ts +0 -10
  269. package/src/brand-page/components/contact-form/ContactForm.mixin.test.ts +127 -0
  270. package/src/brand-page/components/contact-form/ContactForm.mixin.ts +31 -14
  271. package/src/brand-page/components/contact-form/ContactForm.vue +26 -12
  272. package/src/brand-page/components/contact-form/ContactForm.vue.test.ts +60 -0
  273. package/src/brand-page/components/mailing-list/MailingList.mixin.test.ts +92 -0
  274. package/src/brand-page/components/mailing-list/MailingList.mixin.ts +28 -3
  275. package/src/brand-page/components/mailing-list/MailingList.vue +9 -4
  276. package/src/brand-page/components/mailing-list/MailingList.vue.test.ts +63 -0
  277. package/src/brand-page/components/navigation/button-carousel/ButtonCarouselNavigation.mixin.ts +51 -1
  278. package/src/brand-page/components/navigation/button-carousel/ButtonCarouselNavigation.test.ts +114 -0
  279. package/src/brand-page/components/navigation/button-carousel/ButtonCarouselNavigation.vue +8 -2
  280. package/src/brand-page/components/navigation/navigation-carousel/NavigationCarousel.test.ts +182 -0
  281. package/src/brand-page/components/navigation/navigation-carousel/NavigationCarousel.vue +59 -12
  282. package/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.mixin.ts +40 -3
  283. package/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.vue +15 -7
  284. package/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.vue.test.ts +133 -3
  285. package/src/brand-page/components/page/Page.mixin.ts +41 -34
  286. package/src/brand-page/components/page/Page.vue +17 -6
  287. package/src/brand-page/components/page/Page.vue.test.ts +91 -1
  288. package/src/brand-page/components/page-footer/PageFooter.mixin.ts +32 -2
  289. package/src/brand-page/components/page-footer/PageFooter.test.ts +79 -0
  290. package/src/brand-page/components/page-footer/PageFooter.vue +12 -4
  291. package/src/brand-page/components/payment/Payment.mixin.ts +34 -2
  292. package/src/brand-page/components/payment/Payment.test.ts +188 -0
  293. package/src/brand-page/components/payment/Payment.vue +12 -5
  294. package/src/brand-page/components/payment/RequestPaymentStripe.vue +1 -0
  295. package/src/brand-page/components/payment/support-me/SupportMe.mixin.ts +49 -2
  296. package/src/brand-page/components/payment/support-me/SupportMe.test.ts +100 -0
  297. package/src/brand-page/components/payment/support-me/SupportMe.vue +7 -1
  298. package/src/brand-page/components/payment/support-me/SupportMe.vue.test.ts +66 -0
  299. package/src/brand-page/components/save-contact/SaveContactWidget.test.ts +100 -0
  300. package/src/brand-page/components/save-contact/SaveContactWidget.vue +6 -3
  301. package/src/brand-page/components/shop/PaymentModal.vue +2 -6
  302. package/src/brand-page/components/shop/PaymentShippingAddress.vue +6 -0
  303. package/src/brand-page/components/shop/Shop.vue +15 -2
  304. package/src/brand-page/components/shop/Shop.vue.test.ts +74 -2
  305. package/src/brand-page/components/social-links/SocialLinks.stories.ts +0 -3
  306. package/src/brand-page/components/social-links/SocialLinks.vue.test.ts +0 -3
  307. package/src/brand-page/components/testimonial-section/__fixtures__/data.ts +0 -3
  308. package/src/brand-page/components/text/Text.stories.ts +0 -17
  309. package/src/brand-page/components/text-wrapper/TextWrapper.parity.test.ts +136 -0
  310. package/src/brand-page/components/text-wrapper/TextWrapper.test.ts +358 -0
  311. package/src/brand-page/components/text-wrapper/TextWrapper.vue +82 -22
  312. package/src/brand-page/constants/font.constants.ts +37 -0
  313. package/src/brand-page/models/footer-icon-color.test.ts +22 -0
  314. package/src/brand-page/models/index.ts +50 -28
  315. package/src/brand-page/models/navigation-styles.model.test.ts +77 -1
  316. package/src/brand-page/models/navigation-styles.model.ts +26 -9
  317. package/src/brand-page/models/payment.model.ts +15 -6
  318. package/src/brand-page/models/styles.model.test.ts +104 -0
  319. package/src/brand-page/models/styles.model.ts +181 -47
  320. package/src/brand-page/utils/__snapshots__/migration.util.test.ts.snap +619 -115
  321. package/src/brand-page/utils/__snapshots__/migration2.util.test.ts.snap +150 -9
  322. package/src/brand-page/utils/__snapshots__/model.util.test.ts.snap +300 -18
  323. package/src/brand-page/utils/color-palette.util.test.ts +126 -1
  324. package/src/brand-page/utils/color-palette.util.ts +92 -26
  325. package/src/brand-page/utils/color.util.test.ts +62 -29
  326. package/src/brand-page/utils/color.util.ts +77 -14
  327. package/src/brand-page/utils/container-text-color.util.test.ts +672 -26
  328. package/src/brand-page/utils/container-text-color.util.ts +472 -46
  329. package/src/brand-page/utils/index.ts +1 -0
  330. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/edited-brandsite-sections.v22.json +1191 -0
  331. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/new-brandcontact-every-section.v22.json +2026 -0
  332. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/new-brandpage-every-section.v22.json +2017 -0
  333. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/new-brandsite-every-section.v22.json +2031 -0
  334. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandcontact.v22.json +1145 -0
  335. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandpage-general-link.v22.json +645 -0
  336. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandpage-links.v22.json +1136 -0
  337. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandpage-social-links.v22.json +662 -0
  338. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandsite-about.v22.json +638 -0
  339. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandsite-footer.v22.json +610 -0
  340. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandsite-header-banner.v22.json +660 -0
  341. package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandsite-sections.v22.json +1132 -0
  342. package/src/brand-page/utils/migration/migration-01.ts +293 -237
  343. package/src/brand-page/utils/migration/migration-02.ts +8 -1
  344. package/src/brand-page/utils/migration/migration-20.ts +6 -3
  345. package/src/brand-page/utils/migration/migration-20_5.test.ts +5 -2
  346. package/src/brand-page/utils/migration/migration-21.test.ts +34 -0
  347. package/src/brand-page/utils/migration/migration-21.ts +46 -10
  348. package/src/brand-page/utils/migration/migration-22.fixed-input.test.ts +43 -0
  349. package/src/brand-page/utils/migration/migration-22.test.ts +4103 -0
  350. package/src/brand-page/utils/migration/migration-22.text-font-family.test.ts +72 -0
  351. package/src/brand-page/utils/migration/migration-22.ts +1336 -0
  352. package/src/brand-page/utils/migration.util.test.ts +146 -32
  353. package/src/brand-page/utils/migration.util.ts +18 -0
  354. package/src/brand-page/utils/model.util.ts +4 -0
  355. package/src/brand-page/utils/personalisation.util.test.ts +148 -3
  356. package/src/brand-page/utils/personalisation.util.ts +9 -1
  357. package/src/brand-page/utils/rte-role-lift.util.ts +409 -0
  358. package/src/brand-page/utils/style.util.test.ts +35 -2
  359. package/src/brand-page/utils/style.util.ts +45 -11
  360. package/src/brand-page/utils/text-role-css.util.test.ts +525 -0
  361. package/src/brand-page/utils/text-role-css.util.ts +321 -0
  362. package/src/brand-page/utils/text-role-reconnect.util.test.ts +604 -0
  363. package/src/brand-page/utils/text-role-reconnect.util.ts +727 -0
  364. package/src/brand-page/utils/text-style.util.test.ts +305 -0
  365. package/src/brand-page/utils/text-style.util.ts +198 -24
  366. package/src/brand-page/utils/view-model.page-data.test.ts +232 -0
  367. package/src/brand-page/utils/view-model.util.test.ts +954 -133
  368. package/src/brand-page/utils/view-model.util.ts +187 -139
  369. package/src/brand-page/view-models.ts +4 -0
  370. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.blank-site.test.ts +57 -0
  371. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.ts +9 -5
  372. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.ts +0 -10
  373. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/content-settings-items.fixture.ts +0 -1
  374. package/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.ts +0 -44
  375. package/src/brand-page-maker/components/rich-text-editor/RichTextEditor.vue +253 -200
  376. package/src/brand-page-maker/components/shop/AddOrEditProductContainer.vue +1 -0
  377. package/src/brand-page-maker/components/template-preview/TemplatePreview.vue +1 -0
  378. package/src/brand-page-maker/composables/ai-chat/useAiMetadataBuilder.ts +2 -0
  379. package/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.ts +1 -0
  380. package/src/brand-page-maker/composables/rich-text-editor/block-typography.test.ts +519 -0
  381. package/src/brand-page-maker/composables/rich-text-editor/extensions/FontFamily.test.ts +1 -1
  382. package/src/brand-page-maker/composables/rich-text-editor/extensions/MaxLength.test.ts +26 -1
  383. package/src/brand-page-maker/composables/rich-text-editor/extensions/RoleTypographyFill.test.ts +110 -0
  384. package/src/brand-page-maker/composables/rich-text-editor/extensions/RoleTypographyFill.ts +99 -0
  385. package/src/brand-page-maker/composables/rich-text-editor/extensions/RteClipboard.ts +397 -0
  386. package/src/brand-page-maker/composables/rich-text-editor/extensions/ViewDomParser.test.ts +139 -0
  387. package/src/brand-page-maker/composables/rich-text-editor/font.ts +36 -5
  388. package/src/brand-page-maker/composables/rich-text-editor/formatting.test.ts +375 -1
  389. package/src/brand-page-maker/composables/rich-text-editor/formatting.ts +301 -17
  390. package/src/brand-page-maker/composables/rich-text-editor/hyperlink.test.ts +82 -1
  391. package/src/brand-page-maker/composables/rich-text-editor/hyperlink.ts +28 -34
  392. package/src/brand-page-maker/composables/rich-text-editor/keepMarksOnEmpty.test.ts +80 -0
  393. package/src/brand-page-maker/composables/rich-text-editor/keepMarksOnEmpty.ts +75 -0
  394. package/src/brand-page-maker/composables/rich-text-editor/spacing.ts +31 -6
  395. package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.test.ts +2485 -0
  396. package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.ts +435 -337
  397. package/src/brand-page-maker/constants/config-settings-constant.ts +0 -6
  398. package/src/brand-page-maker/convertors/text-css-style-options.convertor.test.ts +43 -0
  399. package/src/brand-page-maker/convertors/text-css-style-options.convertor.ts +6 -2
  400. package/src/brand-page-maker/convertors/text-size-value.convertor.test.ts +24 -0
  401. package/src/brand-page-maker/convertors/text-size-value.convertor.ts +17 -13
  402. package/src/brand-page-maker/default-getters/payment-text-and-border-color.default-getter.ts +7 -22
  403. package/src/brand-page-maker/default-getters/text-color.default-getter.ts +5 -21
  404. package/src/brand-page-maker/models/content-settings.test.ts +708 -0
  405. package/src/brand-page-maker/models/content-settings.ts +133 -82
  406. package/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store-utils.test.ts +63 -1
  407. package/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store-utils.ts +16 -3
  408. package/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store.test.ts +34 -0
  409. package/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store.ts +4 -2
  410. package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.test.ts +185 -1
  411. package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.ts +22 -34
  412. package/src/brand-page-maker/stores/history/history-store.ts +35 -2
  413. package/src/brand-page-maker/utils/__snapshots__/apply-color-strategy.golden.test.ts.snap +528 -0
  414. package/src/brand-page-maker/utils/__snapshots__/rte-render-parity.test.ts.snap +12 -0
  415. package/src/brand-page-maker/utils/apply-color-strategy.golden.test.ts +2 -0
  416. package/src/brand-page-maker/utils/apply-color-strategy.test.ts +181 -3
  417. package/src/brand-page-maker/utils/apply-color-strategy.ts +36 -4
  418. package/src/brand-page-maker/utils/index.ts +2 -1
  419. package/src/brand-page-maker/utils/rich-text-editor.util.test.ts +447 -410
  420. package/src/brand-page-maker/utils/rich-text-editor.util.ts +610 -506
  421. package/src/brand-page-maker/utils/rte-authoring.util.test.ts +244 -0
  422. package/src/brand-page-maker/utils/rte-authoring.util.ts +175 -0
  423. package/src/brand-page-maker/utils/rte-clipboard.util.test.ts +558 -0
  424. package/src/brand-page-maker/utils/rte-clipboard.util.ts +473 -0
  425. package/src/brand-page-maker/utils/rte-features.test.ts +99 -3
  426. package/src/brand-page-maker/utils/rte-render-parity.test.ts +1 -1
  427. package/src/brand-page-maker/utils/rte-render.util.test.ts +230 -0
  428. package/src/brand-page-maker/utils/rte-sanitize-json.test.ts +1 -1
  429. package/src/brand-page-maker/utils/rte-sanitize.util.ts +14 -3
  430. package/src/brand-page-maker/utils/rte-schema-version.test.ts +102 -0
  431. package/src/bundles/bundled-translations.de-DE.json +21 -2
  432. package/src/bundles/bundled-translations.es-ES.json +21 -2
  433. package/src/bundles/bundled-translations.fr-CA.json +21 -2
  434. package/src/bundles/bundled-translations.fr-FR.json +21 -2
  435. package/src/bundles/bundled-translations.json +21 -2
  436. package/src/bundles/bundled-translations.pt-BR.json +21 -2
  437. package/src/bundles/bundled-translations.pt-PT.json +21 -2
  438. package/src/clients/ai-assistant-client.ts +1 -0
  439. package/src/composables/useTranslate.ts +2 -1
  440. package/src/lib.ts +2 -2
  441. package/src/metadata-builder/builders/footer-builder.test.ts +70 -45
  442. package/src/metadata-builder/builders/footer-builder.ts +4 -8
  443. package/src/metadata-builder/builders/global-role-propagation.test.ts +907 -0
  444. package/src/metadata-builder/builders/global-role-propagation.ts +430 -0
  445. package/src/metadata-builder/builders/global-styles-builder.test.ts +1020 -0
  446. package/src/metadata-builder/builders/global-styles-builder.ts +194 -48
  447. package/src/metadata-builder/builders/header-builder.test.ts +112 -40
  448. package/src/metadata-builder/builders/header-builder.ts +18 -8
  449. package/src/metadata-builder/builders/section-builders/about-section-builder.ts +5 -3
  450. package/src/metadata-builder/builders/section-builders/banner-section-builder.ts +5 -3
  451. package/src/metadata-builder/builders/section-builders/booking-section-builder.ts +5 -3
  452. package/src/metadata-builder/builders/section-builders/contact-form-builder.ts +7 -4
  453. package/src/metadata-builder/builders/section-builders/images-section-builder.ts +5 -3
  454. package/src/metadata-builder/builders/section-builders/mailing-list-builder.ts +3 -2
  455. package/src/metadata-builder/builders/section-builders/mailing-list-section-builder.ts +3 -2
  456. package/src/metadata-builder/builders/section-builders/profile-section-builder.ts +7 -7
  457. package/src/metadata-builder/builders/section-builders/shapes-section-builder.ts +5 -3
  458. package/src/metadata-builder/builders/section-builders/social-links-builder.test.ts +2 -2
  459. package/src/metadata-builder/builders/section-builders/social-links-builder.ts +21 -10
  460. package/src/metadata-builder/builders/section-builders/support-me-builder.test.ts +10 -0
  461. package/src/metadata-builder/builders/section-builders/testimonial-section-builder.ts +3 -2
  462. package/src/metadata-builder/builders/section-builders/text-section-builder.ts +111 -61
  463. package/src/metadata-builder/builders/section-field-maps.ts +1 -0
  464. package/src/metadata-builder/builders/section-field-utils.test.ts +545 -2
  465. package/src/metadata-builder/builders/section-field-utils.ts +202 -69
  466. package/src/metadata-builder/builders/section-rules/global-styles.rules.ts +38 -13
  467. package/src/metadata-builder/builders/section-rules/social-links.rules.ts +5 -0
  468. package/src/metadata-builder/helpers/rte.helpers.test.ts +101 -0
  469. package/src/metadata-builder/helpers/rte.helpers.ts +129 -43
  470. package/src/metadata-builder/metadata-executor.test.ts +167 -0
  471. package/src/metadata-builder/metadata-executor.ts +34 -1
  472. package/src/metadata-builder/models.ts +2 -0
  473. package/src/metadata-builder/parsers/ai-toolcall-parser.ts +23 -7
  474. package/src/metadata-builder/parsers/section-tool-arguments.ts +21 -1
  475. package/src/metadata-builder/sanitizers/__tests__/section-args-validator.test.ts +215 -0
  476. package/src/metadata-builder/sanitizers/rte-schema-check.ts +1 -1
  477. package/src/metadata-builder/sanitizers/sanitizer-rules.ts +4 -8
  478. package/src/metadata-builder/sanitizers/section-args-validator.ts +136 -53
  479. package/src/shared/color-palette/section-color-matches.test.ts +15 -11
  480. package/src/shared/color-palette/section-color-matches.ts +9 -28
  481. package/src/shared/color-strategies/color-strategies.ts +35 -0
  482. package/src/shared/color-strategies/rte-color.test.ts +1 -1
  483. package/src/shared/color-strategies/rte-color.ts +19 -0
  484. package/src/shared/color-strategies/rte-field-pairs.test.ts +26 -5
  485. package/src/shared/color-strategies/rte-field-pairs.ts +33 -0
  486. package/src/shared/content-settings/components/color-matches-panel/ColorMatchesPanel.test.ts +43 -66
  487. package/src/shared/content-settings/components/color-matches-panel/ColorMatchesPanel.vue +7 -1
  488. package/src/shared/content-settings/components/content-settings/ContentSettings.mixin.ts +1 -48
  489. package/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.ts +33 -7
  490. package/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.test.ts +128 -1
  491. package/src/shared/content-settings/components/draggable-item-list/DraggableItemList.vue +1 -0
  492. package/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.ts +0 -6
  493. package/src/shared/content-settings/components/logo-selection-field/LogoSelection.vue +3 -0
  494. package/src/shared/content-settings/components/logo-size-field/LogoSizeSlider.vue +3 -0
  495. package/src/shared/content-settings/components/logo-size-field/LogoSizeSliderField.vue +1 -0
  496. package/src/shared/content-settings/components/testimonial-items-field/TestimonialItemsField.vue +1 -0
  497. package/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.test.ts +56 -3
  498. package/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.ts +11 -4
  499. package/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.test.ts +335 -25
  500. package/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.ts +248 -70
  501. package/src/shared/content-settings/components/text-style-field/TextStyleField.vue +113 -25
  502. package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.de-DE.json +17 -10
  503. package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.es-ES.json +17 -10
  504. package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.fr-CA.json +17 -10
  505. package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.fr-FR.json +17 -10
  506. package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.json +8 -1
  507. package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.pt-BR.json +17 -10
  508. package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.pt-PT.json +17 -10
  509. package/src/shared/content-settings/components/text-style-role-dropdown/TextStyleRoleDropdown.test.ts +141 -0
  510. package/src/shared/content-settings/components/text-style-role-dropdown/TextStyleRoleDropdown.vue +136 -0
  511. package/src/shared/content-settings/store/content-settings-store.test.ts +491 -6
  512. package/src/shared/content-settings/store/content-settings-store.ts +159 -17
  513. package/src/shared/logo-settings/components/EditLogoSettings.vue +1 -0
  514. package/src/shared/logo-settings/components/LogoVariations.vue +1 -0
  515. package/src/shared/navigation-style-settings/components/navigation-style-settings/NavigationStyleSettings.vue +1 -0
  516. package/src/shared/navigation-style-settings/store/index.test.ts +295 -0
  517. package/src/shared/navigation-style-settings/store/index.ts +65 -15
  518. package/src/shared/page-settings/components/header-settings-panel/HeaderSettingsPanel.vue +2 -0
  519. package/src/shared/page-settings/components/page-settings/PageElement.vue +1 -0
  520. package/src/shared/page-settings/components/page-settings-section-styles/HeaderButtonSettings.test.ts +44 -4
  521. package/src/shared/page-settings/components/page-settings-section-styles/HeaderButtonSettings.vue +13 -4
  522. package/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.navigation.test.ts +89 -0
  523. package/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.text-style.test.ts +91 -0
  524. package/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.ts +14 -2
  525. package/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.vue +2 -0
  526. package/src/shared/page-settings/store/page-settings-store.text-style.test.ts +84 -0
  527. package/src/shared/page-settings/store/page-settings-store.ts +30 -1
  528. package/src/shared/rte-extensions/AutoLink.test.ts +98 -0
  529. package/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/AutoLink.ts +87 -58
  530. package/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/MaxLength.ts +4 -1
  531. package/src/shared/rte-extensions/TextEffects.ts +151 -0
  532. package/src/shared/rte-extensions/ViewDomParser.ts +27 -0
  533. package/src/{brand-page-maker/composables/rich-text-editor/getRteExtensions.ts → shared/rte-extensions.util.ts} +66 -9
  534. package/src/shared/rte-link.util.ts +2 -0
  535. package/src/shared/rte-render.util.ts +385 -0
  536. package/src/shared/rte-shape.util.ts +29 -0
  537. package/src/shared/side-bar/store/side-bar-store.test.ts +27 -1
  538. package/src/shared/side-bar/store/side-bar-store.ts +11 -0
  539. package/src/shared/style-settings/components/StyleSettings.mixin.ts +7 -3
  540. package/src/shared/style-settings/components/StyleSettings.test.ts +116 -0
  541. package/src/shared/style-settings/components/StyleSettings.vue +75 -25
  542. package/src/shared/style-settings/components/i18n/style-settings.de-DE.json +32 -20
  543. package/src/shared/style-settings/components/i18n/style-settings.es-ES.json +32 -20
  544. package/src/shared/style-settings/components/i18n/style-settings.fr-CA.json +32 -20
  545. package/src/shared/style-settings/components/i18n/style-settings.fr-FR.json +32 -20
  546. package/src/shared/style-settings/components/i18n/style-settings.json +13 -3
  547. package/src/shared/style-settings/components/i18n/style-settings.pt-BR.json +32 -20
  548. package/src/shared/style-settings/components/i18n/style-settings.pt-PT.json +32 -20
  549. package/src/shared/style-settings/components/text-style-options-settings-with-state/TextStyleOptionsSettingsWithState.vue +14 -34
  550. package/src/shared/style-settings/store/style-settings-store.ts +3 -49
  551. package/src/shared/style-settings/text-style-size-order.test.ts +76 -0
  552. package/src/shared/style-settings/text-style-size-order.ts +28 -0
  553. package/src/shared/template-settings/components/TemplatesSettings.vue +4 -0
  554. package/src/shared/text-role-typography.util.ts +277 -0
  555. package/src/utils/minify-brand-page-metadata.test.ts +102 -7
  556. package/src/utils/minify-brand-page-metadata.ts +62 -8
  557. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/AutoLink.d.ts +0 -2
  558. package/lib/src/brand-page-maker/composables/rich-text-editor/getRteExtensions.d.ts +0 -28
  559. package/lib/src/brand-page-maker/utils/rte-render.util.d.ts +0 -63
  560. package/lib/src/brand-page-maker/utils/rte-render.util.js +0 -106
  561. package/lib/src/brand-page-maker/utils/rte-shape.d.ts +0 -18
  562. package/lib/src/brand-page-maker/utils/rte-shape.js +0 -21
  563. package/lib/src/metadata-builder/builders/global-font-propagation.d.ts +0 -41
  564. package/lib/src/metadata-builder/builders/global-font-propagation.js +0 -146
  565. package/src/brand-page-maker/utils/rte-render.util.ts +0 -179
  566. package/src/brand-page-maker/utils/rte-shape.ts +0 -29
  567. package/src/metadata-builder/builders/global-font-propagation.test.ts +0 -401
  568. package/src/metadata-builder/builders/global-font-propagation.ts +0 -238
  569. package/src/shared/style-settings/components/StyleSettingsSection.vue +0 -8
  570. /package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/FontFamily.d.ts +0 -0
  571. /package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/FontFamily.js +0 -0
  572. /package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/LetterSpacing.d.ts +0 -0
  573. /package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/LetterSpacing.js +0 -0
  574. /package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/MaxLength.d.ts +0 -0
  575. /package/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/FontFamily.ts +0 -0
  576. /package/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/LetterSpacing.ts +0 -0
@@ -3,6 +3,8 @@ import chroma from 'chroma-js';
3
3
  import type { ColorItem } from '../models';
4
4
  import {
5
5
  bestContrastBrandRole,
6
+ bestContrastNeutralRole,
7
+ firstViableContrastRole,
6
8
  generateNeutralPalette,
7
9
  classifyColor,
8
10
  paletteRoleIdForToken,
@@ -388,6 +390,129 @@ describe('bestContrastBrandRole (BP-5886 Phase 4)', () => {
388
390
  });
389
391
  });
390
392
 
393
+ describe('bestContrastNeutralRole', () => {
394
+ const LIGHT = '#ffffff';
395
+ const DARK = '#000000';
396
+
397
+ const palette = (light?: string, dark?: string): ColorItem[] => {
398
+ const colors: ColorItem[] = [
399
+ { id: PALETTE_COLOR_IDS.primary, value: '#ff0000', type: 'palette' },
400
+ { id: PALETTE_COLOR_IDS.secondary, value: '#00ff00', type: 'palette' },
401
+ ];
402
+
403
+ if (light) {
404
+ colors.push({
405
+ id: PALETTE_COLOR_IDS.neutralLight,
406
+ value: light,
407
+ type: 'palette',
408
+ });
409
+ }
410
+
411
+ if (dark) {
412
+ colors.push({
413
+ id: PALETTE_COLOR_IDS.neutralDark,
414
+ value: dark,
415
+ type: 'palette',
416
+ });
417
+ }
418
+
419
+ return colors;
420
+ };
421
+
422
+ test('takes the dark neutral on a light surface and the light neutral on a dark one', () => {
423
+ expect(bestContrastNeutralRole(LIGHT, palette('#f5f5f5', '#111111'))).toBe(
424
+ PALETTE_COLOR_IDS.neutralDark,
425
+ );
426
+ expect(bestContrastNeutralRole(DARK, palette('#f5f5f5', '#111111'))).toBe(
427
+ PALETTE_COLOR_IDS.neutralLight,
428
+ );
429
+ });
430
+
431
+ test('never picks a brand role, even when a brand colour contrasts more', () => {
432
+ // The brand roles are pure black/white (maximal contrast) but must be ignored — only the
433
+ // neutrals compete for body text on the page.
434
+ const colors: ColorItem[] = [
435
+ { id: PALETTE_COLOR_IDS.primary, value: '#000000', type: 'palette' },
436
+ { id: PALETTE_COLOR_IDS.secondary, value: '#ffffff', type: 'palette' },
437
+ { id: PALETTE_COLOR_IDS.neutralLight, value: '#e0e0e0', type: 'palette' },
438
+ { id: PALETTE_COLOR_IDS.neutralDark, value: '#202020', type: 'palette' },
439
+ ];
440
+
441
+ const role = bestContrastNeutralRole(LIGHT, colors);
442
+
443
+ expect(role).toBe(PALETTE_COLOR_IDS.neutralDark);
444
+ expect(role).not.toBe(PALETTE_COLOR_IDS.primary);
445
+ expect(role).not.toBe(PALETTE_COLOR_IDS.secondary);
446
+ });
447
+
448
+ test('undefined when there is no neutral role or the base is unusable', () => {
449
+ expect(bestContrastNeutralRole(LIGHT, palette())).toBeUndefined();
450
+ expect(
451
+ bestContrastNeutralRole('transparent', palette('#f5f5f5', '#111111')),
452
+ ).toBeUndefined();
453
+ expect(
454
+ bestContrastNeutralRole('', palette('#f5f5f5', '#111111')),
455
+ ).toBeUndefined();
456
+ });
457
+ });
458
+
459
+ describe('firstViableContrastRole', () => {
460
+ const colors = (p0: string, p1: string): ColorItem[] => [
461
+ { id: PALETTE_COLOR_IDS.primary, value: p0, type: 'palette' },
462
+ { id: PALETTE_COLOR_IDS.secondary, value: p1, type: 'palette' },
463
+ ];
464
+
465
+ test('returns the first listed role that clears the floor, not the highest-contrast one', () => {
466
+ // On white, palette-1 (#000, 21:1) contrasts more than palette-0 (#767676, ~4:1), but
467
+ // palette-0 is listed first and clears 3 → it wins by hierarchy.
468
+ const order = [PALETTE_COLOR_IDS.primary, PALETTE_COLOR_IDS.secondary];
469
+
470
+ expect(
471
+ firstViableContrastRole(
472
+ '#ffffff',
473
+ colors('#767676', '#000000'),
474
+ order,
475
+ 3,
476
+ ),
477
+ ).toBe(PALETTE_COLOR_IDS.primary);
478
+ });
479
+
480
+ test('skips a first role that breaches the floor and takes the next viable one', () => {
481
+ const order = [PALETTE_COLOR_IDS.primary, PALETTE_COLOR_IDS.secondary];
482
+
483
+ // palette-0 (#eeeeee) is illegible on white (<3); palette-1 (#000) clears it.
484
+ expect(
485
+ firstViableContrastRole(
486
+ '#ffffff',
487
+ colors('#eeeeee', '#000000'),
488
+ order,
489
+ 3,
490
+ ),
491
+ ).toBe(PALETTE_COLOR_IDS.secondary);
492
+ });
493
+
494
+ test('undefined when no listed role clears the floor or the base is unusable', () => {
495
+ const order = [PALETTE_COLOR_IDS.primary, PALETTE_COLOR_IDS.secondary];
496
+
497
+ expect(
498
+ firstViableContrastRole(
499
+ '#ffffff',
500
+ colors('#f2f2f2', '#eeeeee'),
501
+ order,
502
+ 3,
503
+ ),
504
+ ).toBeUndefined();
505
+ expect(
506
+ firstViableContrastRole(
507
+ 'transparent',
508
+ colors('#000000', '#ffffff'),
509
+ order,
510
+ 3,
511
+ ),
512
+ ).toBeUndefined();
513
+ });
514
+ });
515
+
391
516
  describe('paletteRoleIdForToken', () => {
392
517
  test('maps the bare logo token to its common', () => {
393
518
  expect(paletteRoleIdForToken('logo-text-color')).toBe('palette-0');
@@ -1085,7 +1210,7 @@ describe('logo-context-less templates (BP-5886)', () => {
1085
1210
  // MAKER-ONLY as of 2026-08-07: the admin needs four visible, editable
1086
1211
  // swatches, and a template save clears them again anyway
1087
1212
  // (`clearPaletteRoleValues`). What was removed is this running during
1088
- // `migrateBrandPageModel` — as `migration23` it wrote these defaults into
1213
+ // `migrateBrandPageModel` — the removed migration-time fallback wrote these defaults into
1089
1214
  // models on the ~17 call sites that have no logo, and blank-only filling
1090
1215
  // then stopped the customer's real logo ever correcting them. Renderers now
1091
1216
  // take their fallback at CSS emit instead, where it cannot be persisted.
@@ -10,6 +10,9 @@ import { isColorLinearGradient } from '@src/utils/helpers';
10
10
  * colour value, mint a deterministic palette id for it, and translate between an id
11
11
  * and its `var(--id)` reference. Side-effect and framework free so migration, maker
12
12
  * and renderer can all share them.
13
+ *
14
+ * MIGRATION-22 SNAPSHOT DEPENDENCY: its colour bake uses `isBlankColorValue`. Pin the v22
15
+ * interpretation before changing that helper after the migration releases.
13
16
  */
14
17
 
15
18
  const CUSTOM_ID_PREFIX = 'palette-custom-';
@@ -678,40 +681,39 @@ export const generateNeutralPalette = (
678
681
  });
679
682
 
680
683
  /**
681
- * The contrast a colour-strategy copy colour must clear against the layer it sits on, or
682
- * the strategy falls back to a neutral.
684
+ * The minimum contrast a BRAND text colour must clear against the surface it sits on for the
685
+ * birth-time bake to use it; below this the bake falls back (to the other brand role, then a
686
+ * neutral for the page). One colour covers *all* copy on a surface, so no threshold guarantees
687
+ * every size — this is a floor for large brand copy.
683
688
  *
684
- * **WCAG AA for LARGE text (3:1), not 4.5:1, deliberately.** One colour covers *all* copy
685
- * on a layer, so no threshold is a guarantee at every size; 3:1 keeps brand colours that
686
- * are still legible (a mid-blue primary on the dark neutral is 3.77:1, which 4.5 would
687
- * throw away for a near-white neutral) while catching the broken end (~1.1:1, invisible
688
- * text). Raising it to 4.5 is a one-line change.
689
+ * **2:1 — deliberately BELOW WCAG AA large-text (3:1).** The brand's own logo-text colour is the
690
+ * site identity and should lead its headings even when it's a bright mid-tone that lands ~2.3:1
691
+ * on white (a large bold heading still reads there — the BP-5969 call, ADR-0020). 2:1 keeps that
692
+ * while still rejecting the genuinely invisible end (~1:1, e.g. a near-white role on white). A
693
+ * brand-identity-over-strict-contrast trade; raising it back toward 3 is a one-line change.
689
694
  *
690
- * > NOTE: **dormant** — its only caller was the retired `light`/`dark` `contrast`
691
- * > resolver (BP-5886, ADR 0017). `bestContrastBrandRole`'s remaining callers use the
692
- * > default `minRatio` of 0. Retire alongside the other theme-pair leftovers.
695
+ * Live consumer: `viableBrandRole` (`container-text-color.util.ts`), the contrast bake's floor.
693
696
  */
694
- export const STRATEGY_COPY_MIN_CONTRAST = 3;
697
+ export const STRATEGY_COPY_MIN_CONTRAST = 2;
695
698
 
696
699
  /**
697
- * The brand role (`palette-0` / `palette-1`) whose colour reads best against `against` —
698
- * WCAG 2.1 contrast ratio. `undefined` when neither role holds a usable solid colour,
699
- * when `against` itself is not one, or when no role clears `minRatio`.
700
+ * The palette role from `candidateIds` whose colour reads best against `against` — WCAG 2.1
701
+ * contrast ratio. `undefined` when `against` is not a solid, no candidate holds a usable solid
702
+ * colour, or none clears `minRatio`. Candidates are ranked in the order given, so an exact tie
703
+ * resolves to the earlier id.
700
704
  *
701
- * The ratio, rather than a lightness comparison, answers the degenerate palettes with no
702
- * second rule: two dark brand colours against the dark neutral yield the less dark one.
703
- * Alpha is ignored (`chroma.contrast` composites nothing).
705
+ * The ratio, rather than a lightness comparison, answers the degenerate palettes with no second
706
+ * rule: two dark candidates against the dark neutral yield the less dark one. Alpha is ignored
707
+ * (`chroma.contrast` composites nothing).
704
708
  *
705
- * **`minRatio` is the legibility floor, and without it this ranks without judging** — it
706
- * returns the *best available* role even when unreadable (a mono dark logo puts near-black
707
- * copy on the dark neutral at 1.12:1). `undefined` then routes the caller to its neutral
708
- * fallback, which is right because the neutrals are *brand-hue tinted*, so the hue
709
- * survives; a lightness-adjusted brand colour could not be a palette **role**, so it would
710
- * be a literal and stop following palette edits.
709
+ * **`minRatio` is the legibility floor, and without it this ranks without judging** — it returns
710
+ * the *best available* role even when unreadable. `undefined` then routes the caller to its own
711
+ * fallback.
711
712
  */
712
- export const bestContrastBrandRole = (
713
+ export const bestContrastRole = (
713
714
  against: string,
714
715
  colors: ColorItem[] = [],
716
+ candidateIds: string[],
715
717
  minRatio = 0,
716
718
  ): string | undefined => {
717
719
  // `canonicalSolidHex` rather than `chroma.valid`: a gradient, an unresolved `var()`
@@ -724,8 +726,7 @@ export const bestContrastBrandRole = (
724
726
 
725
727
  const byId = new Map(colors.map((c) => [c.id, c.value]));
726
728
 
727
- // Primary first, so an exact tie resolves to it deterministically (`>` below).
728
- const candidates = [PALETTE_COLOR_IDS.primary, PALETTE_COLOR_IDS.secondary]
729
+ const candidates = candidateIds
729
730
  .map((id): { id: string; hex?: string } => ({
730
731
  id,
731
732
  hex: canonicalSolidHex(byId.get(id) ?? ''),
@@ -744,6 +745,71 @@ export const bestContrastBrandRole = (
744
745
  return best && best.ratio >= minRatio ? best.id : undefined;
745
746
  };
746
747
 
748
+ /**
749
+ * The BRAND role (`palette-0` / `palette-1`) that reads best against `against`; primary wins
750
+ * ties. The neutrals are excluded on purpose — a section title on a coloured surface takes a
751
+ * brand accent. See `bestContrastRole` for the ranking and the `minRatio` floor (without it, an
752
+ * `undefined` return routes the caller to its neutral fallback, which is right because the
753
+ * neutrals are brand-hue tinted, so the hue survives).
754
+ */
755
+ export const bestContrastBrandRole = (
756
+ against: string,
757
+ colors: ColorItem[] = [],
758
+ minRatio = 0,
759
+ ): string | undefined =>
760
+ bestContrastRole(
761
+ against,
762
+ colors,
763
+ [PALETTE_COLOR_IDS.primary, PALETTE_COLOR_IDS.secondary],
764
+ minRatio,
765
+ );
766
+
767
+ /**
768
+ * The NEUTRAL role (`palette-2` light / `palette-3` dark) that reads best against `against` — the
769
+ * readable, brand-hue-tinted text colour for copy on a plain surface (the page background),
770
+ * replacing the retired base coat. Light role wins ties.
771
+ */
772
+ export const bestContrastNeutralRole = (
773
+ against: string,
774
+ colors: ColorItem[] = [],
775
+ ): string | undefined =>
776
+ bestContrastRole(against, colors, [
777
+ PALETTE_COLOR_IDS.neutralLight,
778
+ PALETTE_COLOR_IDS.neutralDark,
779
+ ]);
780
+
781
+ /**
782
+ * The FIRST role in `orderedIds` whose colour clears `minRatio` against `against` — a PRIORITY
783
+ * pick, not a best-contrast pick: an earlier id wins even when a later one contrasts more. Honours
784
+ * a brand hierarchy (e.g. logo-text before logo-background) while still guaranteeing legibility via
785
+ * the floor. `undefined` when `against` is not a solid or no listed role clears `minRatio`, so the
786
+ * caller can route on to its own fallback.
787
+ */
788
+ export const firstViableContrastRole = (
789
+ against: string,
790
+ colors: ColorItem[] = [],
791
+ orderedIds: string[],
792
+ minRatio: number,
793
+ ): string | undefined => {
794
+ const baseHex = canonicalSolidHex(against);
795
+
796
+ if (!baseHex) {
797
+ return undefined;
798
+ }
799
+
800
+ const byId = new Map(colors.map((c) => [c.id, c.value]));
801
+
802
+ for (const id of orderedIds) {
803
+ const hex = canonicalSolidHex(byId.get(id) ?? '');
804
+
805
+ if (hex && chroma.contrast(baseHex, hex) >= minRatio) {
806
+ return id;
807
+ }
808
+ }
809
+
810
+ return undefined;
811
+ };
812
+
747
813
  // The fallback palette. The neutrals are generated from the two blues (one code path) so
748
814
  // it stays self-consistent with real logos.
749
815
  export const DEFAULT_PRIMARY = '#2b6cff';
@@ -306,54 +306,87 @@ describe('color.util - withColorOpacity fades references too (BP-5886)', () => {
306
306
  });
307
307
  });
308
308
 
309
- describe('color.util - getNavThemeByTextStyle', () => {
310
- // palette-0 dark, palette-1 light, plus brand-tinted neutrals.
311
- const PALETTE: ColorItem[] = [
312
- { id: 'palette-0', value: '#111111', type: 'palette' },
313
- { id: 'palette-1', value: '#eeeeee', type: 'palette' },
314
- { id: 'palette-2', value: '#f5f5f5', type: 'palette' },
315
- { id: 'palette-3', value: '#1a1a1a', type: 'palette' },
309
+ describe('color.util - getNavThemeByTextStyle (ADR-0022: nav themes off the logo)', () => {
310
+ // palette-0 = logo text (green), palette-1 = logo background (navy), + neutrals.
311
+ const LOGO_PALETTE: ColorItem[] = [
312
+ { id: 'palette-0', value: '#7abd2d', type: 'palette' }, // green — logo text
313
+ { id: 'palette-1', value: '#130e34', type: 'palette' }, // navy — logo background
314
+ { id: 'palette-2', value: '#455538', type: 'palette' },
315
+ { id: 'palette-3', value: '#ecedff', type: 'palette' },
316
316
  ];
317
317
 
318
- test('derives the contrasting brand role for a dark primary (the option-1 → option-2 bug)', () => {
319
- const theme = getNavThemeByTextStyle(
320
- { color: 'var(--palette-0)' },
321
- PALETTE,
322
- );
318
+ test('R1: logo text colour is legible on the header → primary = logo text, selected label inverts', () => {
319
+ // green clears 2:1 on a white header, so the nav themes on the logo text colour and the
320
+ // selected label takes the contrasting brand role (navy) so it reads on the green fill.
321
+ const theme = getNavThemeByTextStyle('#ffffff', LOGO_PALETTE);
323
322
 
324
- // primary is kept verbatim; the selected label takes the OTHER brand role so it
325
- // reads on the primary fill — the thing that regressed under color-v2.
326
323
  expect(theme.primaryColor).toBe('var(--palette-0)');
327
324
  expect(theme.secondaryColor).toBe('var(--palette-1)');
328
325
  expect(theme.secondaryColor).not.toBe(theme.primaryColor);
329
326
  });
330
327
 
331
- test('is symmetric — a light primary contrasts against the dark brand role', () => {
332
- const theme = getNavThemeByTextStyle(
333
- { color: 'var(--palette-1)' },
334
- PALETTE,
335
- );
328
+ test('R2: logo text colour fails 2:1 on the header → falls back to logo background colour', () => {
329
+ // header IS the green logo-text colour → green-on-green fails, navy clears.
330
+ const theme = getNavThemeByTextStyle('#7abd2d', LOGO_PALETTE);
336
331
 
337
332
  expect(theme.primaryColor).toBe('var(--palette-1)');
333
+ // selected label inverts to the other brand role (logo text / green) so it reads on the fill.
338
334
  expect(theme.secondaryColor).toBe('var(--palette-0)');
335
+ expect(theme.secondaryColor).not.toBe(theme.primaryColor);
339
336
  });
340
337
 
341
- test('a non-brand-role base still picks whichever brand role reads best against it', () => {
342
- // a dark neutral base: palette-1 (light) out-contrasts palette-0 (dark).
338
+ test('R3: neither brand role is legible → a generated neutral literal, not a palette ref', () => {
339
+ // both brand roles sit at the header's own luminance → both fail; primary is a generated
340
+ // neutral (a literal), so it is NOT a var(--palette-N) reference.
341
+ const grayPalette: ColorItem[] = [
342
+ { id: 'palette-0', value: '#7f7f7f', type: 'palette' },
343
+ { id: 'palette-1', value: '#808080', type: 'palette' },
344
+ { id: 'palette-2', value: '#f5f5f5', type: 'palette' },
345
+ { id: 'palette-3', value: '#111111', type: 'palette' },
346
+ ];
347
+
348
+ const theme = getNavThemeByTextStyle('#808080', grayPalette);
349
+
350
+ expect(theme.primaryColor).not.toMatch(/^var\(/);
351
+ expect(wcagContrast(theme.primaryColor, '#808080')).toBeGreaterThanOrEqual(
352
+ 2,
353
+ );
354
+ // even with a neutral-literal fill, the selected label still inverts to a brand role.
355
+ expect(theme.secondaryColor).toMatch(/^var\(--palette-\d+\)$/);
356
+ expect(theme.secondaryColor).not.toBe(theme.primaryColor);
357
+ });
358
+
359
+ test('R4: an unset/transparent header anchors to the page background', () => {
360
+ // Green logo text fails on the matching green page behind a transparent header, so navy wins.
343
361
  const theme = getNavThemeByTextStyle(
344
- { color: 'var(--palette-3)' },
345
- PALETTE,
362
+ 'transparent',
363
+ LOGO_PALETTE,
364
+ 'var(--palette-0)',
346
365
  );
347
366
 
348
- expect(theme.secondaryColor).toBe('var(--palette-1)');
367
+ expect(theme.primaryColor).toBe('var(--palette-1)');
349
368
  });
350
369
 
351
- test('falls back to the primary when the palette can supply no brand role', () => {
352
- // No palette at all — the reference cannot be resolved to a colour, so rather than
353
- // mint an off-palette literal we leave the label equal to the primary (no throw).
354
- const theme = getNavThemeByTextStyle({ color: 'var(--palette-0)' }, []);
370
+ test('R5: an unset header uses white only when the page has no solid anchor', () => {
371
+ // The signature carries no button-colour input at all (the ADR-0022 decouple).
372
+ const theme = getNavThemeByTextStyle(undefined, LOGO_PALETTE);
355
373
 
356
374
  expect(theme.primaryColor).toBe('var(--palette-0)');
357
- expect(theme.secondaryColor).toBe('var(--palette-0)');
375
+ });
376
+
377
+ test('R6: brand picks stay palette references so the nav tracks palette edits', () => {
378
+ const theme = getNavThemeByTextStyle('#ffffff', LOGO_PALETTE);
379
+
380
+ expect(theme.primaryColor).toMatch(/^var\(--palette-\d+\)$/);
381
+ expect(theme.secondaryColor).toMatch(/^var\(--palette-\d+\)$/);
382
+ });
383
+
384
+ test('degenerate: an empty palette yields a neutral literal and no invert (no throw)', () => {
385
+ // No palette → the brand roles cannot resolve → primary is a generated neutral; with no
386
+ // role to invert against, the selected label falls back to the primary (pre-ADR behaviour).
387
+ const theme = getNavThemeByTextStyle(undefined, []);
388
+
389
+ expect(theme.primaryColor).not.toMatch(/^var\(/);
390
+ expect(theme.secondaryColor).toBe(theme.primaryColor);
358
391
  });
359
392
  });
@@ -1,3 +1,8 @@
1
+ /**
2
+ * MIGRATION-22 SNAPSHOT DEPENDENCY: its colour bake reaches `backgroundColorFromStyle`,
3
+ * `isTransparentColour` and `isHexTransparent` through `container-text-color.util.ts`. After
4
+ * migration-22 releases, pin their v22 behaviour in the migration before changing them.
5
+ */
1
6
  import isHexColor from 'validator/lib/isHexColor';
2
7
  import { hexToRGBA, RGBAtoHex } from '@src/utils/helpers';
3
8
  import type { ColorItem, Theme } from '../models';
@@ -7,6 +12,8 @@ import {
7
12
  bestContrastBrandRole,
8
13
  resolveColorReference,
9
14
  toColorVarReference,
15
+ PALETTE_COLOR_IDS,
16
+ STRATEGY_COPY_MIN_CONTRAST,
10
17
  } from './color-palette.util';
11
18
  import Color, { type ColorInstance } from 'color';
12
19
 
@@ -256,26 +263,82 @@ export const backgroundColorFromStyle = (
256
263
  style: BrandPageCssStyle | undefined,
257
264
  ): string | undefined => style?.backgroundColor || style?.background;
258
265
 
266
+ // A solid, fully-opaque hex from any parseable colour, else undefined (transparent,
267
+ // gradient, image, `var(--…)`, unparseable) — so a contrast check only runs against a real
268
+ // surface.
269
+ const solidHex = (value: string | undefined): string | undefined => {
270
+ if (!value) {
271
+ return undefined;
272
+ }
273
+
274
+ try {
275
+ const parsed = Color(value);
276
+
277
+ return parsed.alpha() === 1 ? parsed.hex() : undefined;
278
+ } catch {
279
+ return undefined;
280
+ }
281
+ };
282
+
259
283
  /**
260
- * The nav "theme" for a display-type switch: the base colour the caller passes (kept
261
- * verbatim, incl. its palette `var(--id)` reference) plus the contrasting palette-role
262
- * reference to pair with it — e.g. a TAB_2 selected button paints its background with
263
- * `primaryColor` and its label with `secondaryColor`.
284
+ * The nav "theme" for a header nav display-type switch. Nav themes off the LOGO, independently
285
+ * of the page's button styling (ADR-0022): `primaryColor` — the dominant nav colour used for
286
+ * default text, border and the selected button's fill — is the first brand role that stays
287
+ * legible (>= `STRATEGY_COPY_MIN_CONTRAST`) on the header background: logo text colour
288
+ * (`palette-0`), else logo background colour (`palette-1`), else a generated neutral.
289
+ * `secondaryColor` — the selected button's label — is the brand role that best contrasts
290
+ * `primaryColor` (`bestContrastBrandRole`), so the label reads on the filled pill
291
+ * ("encapsulated contrast").
264
292
  *
265
- * `secondaryColor` is a palette-role reference, not a resolved literal, so the label
266
- * keeps tracking palette edits. It is the brand role that reads best (WCAG) against the
267
- * base's resolved value; when the palette can't supply one (empty/blank palette) it
268
- * falls back to the base so we never mint an off-palette colour.
293
+ * Brand picks are returned as palette `var(--id)` references so the nav keeps tracking palette
294
+ * edits; only the neutral fallback is a literal. `headerBackgroundColor` is the preferred surface
295
+ * the nav sits on. When it does not paint, `pageBackgroundColor` is the surface visible behind the
296
+ * header; white is the final fallback when neither resolves to a solid colour.
269
297
  */
270
298
  export const getNavThemeByTextStyle = (
271
- textStyle: BrandPageCssStyle,
299
+ headerBackgroundColor: string | undefined,
272
300
  colors: ColorItem[] = [],
301
+ pageBackgroundColor?: string,
273
302
  ): Theme => {
274
- const primaryColor = textStyle.color!;
275
- const baseValue = resolveColorReference(primaryColor, colors, {
276
- withRoleDefaults: true,
277
- });
278
- const contrastRole = bestContrastBrandRole(baseValue, colors);
303
+ const logoTextColor = toColorVarReference(PALETTE_COLOR_IDS.primary);
304
+ const logoBackgroundColor = toColorVarReference(PALETTE_COLOR_IDS.secondary);
305
+
306
+ const resolvedSurface = (color: string | undefined): string | undefined =>
307
+ solidHex(
308
+ resolveColorReference(color ?? '', colors, { withRoleDefaults: true }),
309
+ );
310
+
311
+ // A transparent/unset header reveals the page surface. Image and gradient backgrounds have no
312
+ // single contrast anchor, so only then does the historic light fallback apply.
313
+ const surface =
314
+ resolvedSurface(headerBackgroundColor) ??
315
+ resolvedSurface(pageBackgroundColor) ??
316
+ '#ffffff';
317
+
318
+ const clearsOnSurface = (roleRef: string): boolean => {
319
+ const resolved = solidHex(
320
+ resolveColorReference(roleRef, colors, { withRoleDefaults: true }),
321
+ );
322
+
323
+ return (
324
+ !!resolved &&
325
+ contrastRatio(Color(resolved), Color(surface)) >=
326
+ STRATEGY_COPY_MIN_CONTRAST
327
+ );
328
+ };
329
+
330
+ const primaryColor = clearsOnSurface(logoTextColor)
331
+ ? logoTextColor
332
+ : clearsOnSurface(logoBackgroundColor)
333
+ ? logoBackgroundColor
334
+ : (mutedTextForBackground(surface, {
335
+ targetContrast: STRATEGY_COPY_MIN_CONTRAST,
336
+ }) ?? logoTextColor);
337
+
338
+ const contrastRole = bestContrastBrandRole(
339
+ resolveColorReference(primaryColor, colors, { withRoleDefaults: true }),
340
+ colors,
341
+ );
279
342
 
280
343
  return {
281
344
  primaryColor,