@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
@@ -0,0 +1,727 @@
1
+ import type { BrandPageModel, Content, TextStyleDeclaration } from '../models';
2
+ import {
3
+ isLegacyTextStyleType,
4
+ isCanonicalTextStyleType,
5
+ CANONICAL_TEXT_STYLE_TYPES,
6
+ type TextStyleOptions,
7
+ type LegacyTextStyleType,
8
+ type CanonicalTextStyleType,
9
+ } from '../models/styles.model';
10
+ import {
11
+ CONTENT_TEXT_STYLE_PROPERTY_KEYS,
12
+ DEFAULT_FONT_FAMILY_KEY,
13
+ FONT_FAMILY_CONFIGS,
14
+ FONT_SIZE_BODY,
15
+ FONT_SIZE_HEADINGS,
16
+ LINE_HEIGHT_BODY,
17
+ LINE_HEIGHT_HEADINGS,
18
+ TEXT_ROLE_STYLE_DEFAULTS,
19
+ type FontFamilyKey,
20
+ } from '../constants';
21
+ import { normalizeTextStyleAgainstRole } from './text-style.util';
22
+ import { isButtonContent } from './model.util';
23
+ import { isBlankColorValue } from './color-palette.util';
24
+ import { liftRteFieldOntoRole } from './rte-role-lift.util';
25
+
26
+ // Re-exported for migrations that already import the guard from here (a released migration's
27
+ // imports must not move) — render components import it from `styles.model.ts` directly.
28
+ export { isCanonicalTextStyleType };
29
+
30
+ /**
31
+ * The one definition of "a text field whose role isn't one of the ten reconnects to its nearest
32
+ * role and keeps its look" (ADR 0021), shared by migration-22 (upgrade) and the AI write
33
+ * boundary (`applyAiStyle`).
34
+ *
35
+ * MIGRATION-22 SNAPSHOT DEPENDENCY: this is shared with maker and AI writes, but migration-22 reads
36
+ * it as part of its v21 -> v22 output. Before changing reconnect behaviour after that migration
37
+ * releases, copy the v22 semantics into the migration (or add a later migration).
38
+ */
39
+
40
+ /**
41
+ * The per-site legacy → canonical target map. `paragraphs` and `buttons` are fixed; `titles`/
42
+ * `headings` snap to the heading tier whose default size is nearest the OLD role's size, kept on
43
+ * DISTINCT tiers so migration-22's colour seed is unambiguous.
44
+ */
45
+ export type LegacyTargetMap = Record<
46
+ LegacyTextStyleType,
47
+ CanonicalTextStyleType
48
+ >;
49
+
50
+ const parseEm = (value: string | undefined): number | undefined => {
51
+ if (!value) return undefined;
52
+
53
+ const match = /([\d.]+)\s*em/.exec(value);
54
+
55
+ return match ? parseFloat(match[1]) : undefined;
56
+ };
57
+
58
+ // Exported so migration-22 job A2 votes onto the same tiers, rather than a second list of them.
59
+ export const HEADING_TIERS = CANONICAL_TEXT_STYLE_TYPES.filter((t) =>
60
+ t.startsWith('heading'),
61
+ );
62
+ export const PARAGRAPH_TIERS = CANONICAL_TEXT_STYLE_TYPES.filter((t) =>
63
+ t.startsWith('paragraph'),
64
+ );
65
+
66
+ /** The kind of text a field holds — the tiers a site-wide edit of that kind reaches. */
67
+ export type TextRoleFamily = 'headings' | 'paragraphs' | 'button';
68
+
69
+ export const FAMILY_TIERS: Record<
70
+ TextRoleFamily,
71
+ readonly CanonicalTextStyleType[]
72
+ > = {
73
+ headings: HEADING_TIERS,
74
+ paragraphs: PARAGRAPH_TIERS,
75
+ button: ['button'],
76
+ };
77
+
78
+ // Above this em size a detached block reads as a heading, below it as body text.
79
+ const HEADING_SIZE_THRESHOLD_EM = 1.125;
80
+
81
+ export const nearestBySize = (
82
+ size: number,
83
+ tiers: readonly CanonicalTextStyleType[],
84
+ ): CanonicalTextStyleType =>
85
+ tiers.reduce((best, tier) => {
86
+ const diff = Math.abs(
87
+ (parseEm(TEXT_ROLE_STYLE_DEFAULTS[tier].fontSize) ?? 1) - size,
88
+ );
89
+ const bestDiff = Math.abs(
90
+ (parseEm(TEXT_ROLE_STYLE_DEFAULTS[best].fontSize) ?? 1) - size,
91
+ );
92
+
93
+ return diff < bestDiff ? tier : best;
94
+ }, tiers[0]);
95
+
96
+ export const computeLegacyTargets = (
97
+ options: Partial<TextStyleOptions> | undefined,
98
+ ): LegacyTargetMap => {
99
+ const nearestHeading = (
100
+ role: LegacyTextStyleType,
101
+ exclude?: CanonicalTextStyleType,
102
+ ): CanonicalTextStyleType | undefined => {
103
+ const size = parseEm(options?.[role]?.style.fontSize);
104
+
105
+ if (size === undefined) return undefined;
106
+
107
+ const tiers = exclude
108
+ ? HEADING_TIERS.filter((t) => t !== exclude)
109
+ : HEADING_TIERS;
110
+
111
+ return nearestBySize(size, tiers);
112
+ };
113
+
114
+ const titles = nearestHeading('titles') ?? 'heading1';
115
+ // Fallback must still respect the exclusion — a bare `?? 'heading4'` could collide with `titles`
116
+ // (its default mapping), and the colour seed relies on the two tiers being distinct.
117
+ const headings =
118
+ nearestHeading('headings', titles) ??
119
+ HEADING_TIERS.find((t) => t !== titles) ??
120
+ 'heading4';
121
+
122
+ return { titles, headings, paragraphs: 'paragraph1', buttons: 'button' };
123
+ };
124
+
125
+ /**
126
+ * The role nearest a field's own font size: heading tiers for display-sized text, paragraph tiers
127
+ * for body, `paragraph1` when there is no size. A `paragraphs`-family field stays on a paragraph
128
+ * tier however big it is, so a site-wide heading edit never repaints it. `button` is never a best
129
+ * fit — a button field reaches it through its starting role or the retired `buttons` successor.
130
+ */
131
+ export const bestFitRole = (
132
+ style: TextStyleDeclaration,
133
+ family?: TextRoleFamily,
134
+ ): CanonicalTextStyleType => {
135
+ const size = parseEm(style.fontSize);
136
+
137
+ if (size === undefined) return 'paragraph1';
138
+
139
+ // Not bounded the other way: a small `headings`-family title still takes a paragraph tier, as
140
+ // migration-22's frozen output expects.
141
+ return size >= HEADING_SIZE_THRESHOLD_EM && family !== 'paragraphs'
142
+ ? nearestBySize(size, HEADING_TIERS)
143
+ : nearestBySize(size, PARAGRAPH_TIERS);
144
+ };
145
+
146
+ // A field on no role rendered its UNSET typography from inheritance — normal weight and style, no
147
+ // decoration, browser-default line-height/spacing — never from a role. The role class paints all
148
+ // of these, so each unset one is pinned to its effective value; the new role gives identity, not
149
+ // appearance. Family/size are left alone: they inherit from the page as before.
150
+ export const DETACHED_UNSET_EFFECTIVE: Record<string, string> = {
151
+ fontWeight: 'normal',
152
+ fontStyle: 'normal',
153
+ textDecoration: 'none',
154
+ lineHeight: 'normal',
155
+ letterSpacing: 'normal',
156
+ };
157
+
158
+ const LEGACY_TYPOGRAPHY_PROPS = [
159
+ 'fontFamily',
160
+ 'fontSize',
161
+ 'fontWeight',
162
+ 'fontStyle',
163
+ 'textDecoration',
164
+ 'lineHeight',
165
+ 'letterSpacing',
166
+ ] as const;
167
+
168
+ const isUnset = (value: unknown): boolean =>
169
+ value === undefined || value === null || value === '';
170
+
171
+ // The page root sets no font size, so an unsized field drew `1em` of its parent — which is what
172
+ // `1em` still means once the role class is in play.
173
+ const INHERITED_FONT_SIZE = '1em';
174
+
175
+ // Before the per-property cascade, a field on a role drew that role's typography and none of its
176
+ // own (`getTextStyleByContentTextStyleProperty` on origin/develop): each prop is replaced with the
177
+ // old role's value, else what the page gave it. Pure — returns a new object, the seven typography
178
+ // props only — so `drawnFontFamily` (R16) can read just the font this way, without mutating a
179
+ // field that migration-22 job A2 only counts, never rewrites.
180
+ const pinDrawnLook = (
181
+ style: TextStyleDeclaration,
182
+ oldRoleStyle: object,
183
+ inheritedFontFamily?: string,
184
+ ): TextStyleDeclaration => {
185
+ const pinned = { ...style } as unknown as Record<string, unknown>;
186
+ const old = oldRoleStyle as Record<string, unknown>;
187
+ const inherited: Record<string, string | undefined> = {
188
+ ...DETACHED_UNSET_EFFECTIVE,
189
+ fontSize: INHERITED_FONT_SIZE,
190
+ fontFamily: inheritedFontFamily,
191
+ };
192
+
193
+ for (const prop of LEGACY_TYPOGRAPHY_PROPS) {
194
+ const value = isUnset(old[prop]) ? inherited[prop] : old[prop];
195
+
196
+ if (value === undefined) delete pinned[prop];
197
+ else pinned[prop] = value;
198
+ }
199
+
200
+ return pinned as unknown as TextStyleDeclaration;
201
+ };
202
+
203
+ // Applied to RTE style objects too: migration-22 job C reads them as the block override it bakes
204
+ // onto bare runs (the renderer ignores RTE style-object typography — no double-em).
205
+ export const materialiseLegacyTypography = (
206
+ style: TextStyleDeclaration,
207
+ oldRoleStyle: object,
208
+ inheritedFontFamily?: string,
209
+ ): void => {
210
+ const pinned = pinDrawnLook(
211
+ style,
212
+ oldRoleStyle,
213
+ inheritedFontFamily,
214
+ ) as unknown as Record<string, unknown>;
215
+ const props = style as unknown as Record<string, unknown>;
216
+
217
+ for (const prop of LEGACY_TYPOGRAPHY_PROPS) {
218
+ if (prop in pinned) props[prop] = pinned[prop];
219
+ else delete props[prop];
220
+ }
221
+ };
222
+
223
+ const typographyOf = (
224
+ style: object | undefined,
225
+ ): Record<string, string | undefined> => {
226
+ const props = (style ?? {}) as Record<string, string | undefined>;
227
+
228
+ return Object.fromEntries(
229
+ LEGACY_TYPOGRAPHY_PROPS.map((prop) => [prop, props[prop]]),
230
+ );
231
+ };
232
+
233
+ const pinUnset = (
234
+ style: TextStyleDeclaration,
235
+ values: Partial<Record<string, string | undefined>> | undefined,
236
+ ): void => {
237
+ const props = style as unknown as Record<string, unknown>;
238
+
239
+ for (const [prop, value] of Object.entries(values ?? {})) {
240
+ if (isUnset(props[prop]) && value !== undefined) props[prop] = value;
241
+ }
242
+ };
243
+
244
+ /**
245
+ * What a reconnect needs beyond the role table, all optional:
246
+ * - `startingRole` — the field's own role, which wins over successor and nearest-by-size;
247
+ * - `family` — the kind of text the field holds (`bestFitRole` keeps a paragraph on a paragraph
248
+ * tier; migration-22 job A2 votes its font into that family);
249
+ * - `renderedDefaults` — values a renderer draws for an unset prop, which beat the role, so they
250
+ * are the look to keep (the button view model's line height, the profile's sizes);
251
+ * - `inheritedFontFamily` — the site text font an unset family drew from the page root;
252
+ * - `drawnBeforeCascade` — the field was last drawn by the resolver before BP-5969's per-property
253
+ * cascade (migration-22's input), where a role replaced its typography and those defaults.
254
+ */
255
+ export interface ReconnectSpec {
256
+ startingRole?: CanonicalTextStyleType;
257
+ family?: TextRoleFamily;
258
+ renderedDefaults?: Partial<Record<string, string>>;
259
+ inheritedFontFamily?: string;
260
+ drawnBeforeCascade?: boolean;
261
+ }
262
+
263
+ export type RenderedDefaultsForContent = (
264
+ content: Record<string, unknown>,
265
+ key: string,
266
+ ) => Partial<Record<string, string>> | undefined;
267
+
268
+ // Production's renderer drew an unset label line height as `LINE_HEIGHT_HEADINGS`, over the role
269
+ // (Brief 3 R3 deletes that default outright; this is the look to keep on upgrade).
270
+ const BUTTON_VIEW_MODEL_DEFAULTS = { lineHeight: LINE_HEIGHT_HEADINGS };
271
+ const BUTTON_VIEW_MODEL_SECTIONS = new Set([
272
+ 'banner-section',
273
+ 'booking-section',
274
+ 'images-section',
275
+ ]);
276
+ // Production's renderer drew these defaults for an unset profile size and line height (R3
277
+ // deletes them outright; this is the look to keep on upgrade).
278
+ const PROFILE_VIEW_MODEL_DEFAULTS: Record<string, Record<string, string>> = {
279
+ titleStyle: { fontSize: FONT_SIZE_BODY, lineHeight: LINE_HEIGHT_BODY },
280
+ descriptionStyle: { fontSize: FONT_SIZE_BODY, lineHeight: LINE_HEIGHT_BODY },
281
+ nameStyle: { fontSize: FONT_SIZE_HEADINGS, lineHeight: LINE_HEIGHT_HEADINGS },
282
+ };
283
+
284
+ export const BUTTON_ELEMENT_RECONNECT: ReconnectSpec = {
285
+ startingRole: 'button',
286
+ family: 'button',
287
+ renderedDefaults: BUTTON_VIEW_MODEL_DEFAULTS,
288
+ };
289
+
290
+ // The kind of text each field holds, mirroring the pipeline's field → font slot map
291
+ // (font_generation.py `_DEFAULT_FIELD_TO_SLOT`: h1–h4 are headings, body and caption paragraphs).
292
+ // A field outside the map has no family, so only its size picks its tier. That includes a text
293
+ // section's `textStyle` and `textItems`: real sites set heading-sized text blocks, and moving them
294
+ // off heading tiers would change migration-22's frozen output.
295
+ const KEY_FAMILIES: Partial<Record<string, TextRoleFamily>> = {
296
+ titleStyle: 'headings',
297
+ headingStyle: 'headings',
298
+ nameStyle: 'headings',
299
+ descriptionStyle: 'paragraphs',
300
+ paragraphStyle: 'paragraphs',
301
+ successMessageStyle: 'paragraphs',
302
+ testimonialStyle: 'paragraphs',
303
+ positionStyle: 'paragraphs',
304
+ };
305
+
306
+ /**
307
+ * The reconnect spec for one content style field. Every button element starts on Button text and
308
+ * keeps what makes it different as overrides (James Joung, 2026-09-28): a section's
309
+ * `buttonTextStyle` and a link button's `titleStyle`.
310
+ */
311
+ export const contentFieldReconnectSpec = (
312
+ contentType: string | undefined,
313
+ key: string,
314
+ ): ReconnectSpec => {
315
+ if (key === 'buttonTextStyle') {
316
+ return {
317
+ startingRole: 'button',
318
+ family: 'button',
319
+ renderedDefaults: BUTTON_VIEW_MODEL_SECTIONS.has(contentType ?? '')
320
+ ? BUTTON_VIEW_MODEL_DEFAULTS
321
+ : undefined,
322
+ };
323
+ }
324
+
325
+ if (key === 'titleStyle' && isButtonContent({ type: contentType } as Content))
326
+ return BUTTON_ELEMENT_RECONNECT;
327
+
328
+ const family = KEY_FAMILIES[key];
329
+
330
+ if (contentType === 'profile')
331
+ return { family, renderedDefaults: PROFILE_VIEW_MODEL_DEFAULTS[key] };
332
+
333
+ return { family };
334
+ };
335
+
336
+ /**
337
+ * The font a field's own value shows, read the same way as the reconnect's look pin
338
+ * (`pinDrawnLook`), before its role's cascade would replace it (R16, migration-22 job A2, which
339
+ * only counts this — never mutates the field). A legacy role's font wins over the field's own, as
340
+ * production drew it; with no old role (undefined, `'none'`, an unknown string, or a retired role
341
+ * missing from the site's options) the field's own font wins, else the site's. A canonical role —
342
+ * which A2's input never holds — draws its own font, else the role's, else the site's.
343
+ */
344
+ export const drawnFontFamily = (
345
+ style: Partial<TextStyleDeclaration> | undefined,
346
+ options: TextStyleOptions | undefined,
347
+ siteFont: string,
348
+ ): string => {
349
+ const props = (style ?? {}) as unknown as Record<string, unknown>;
350
+ const type = props.textStyleType;
351
+ const ownFont = props.fontFamily as string | undefined;
352
+
353
+ if (isCanonicalTextStyleType(type)) {
354
+ const roleFont = (
355
+ options?.[type]?.style as unknown as Record<string, unknown> | undefined
356
+ )?.fontFamily as string | undefined;
357
+
358
+ return ownFont || roleFont || siteFont;
359
+ }
360
+
361
+ const retired = isLegacyTextStyleType(type as string | undefined)
362
+ ? (type as LegacyTextStyleType)
363
+ : undefined;
364
+ const oldRoleStyle = retired ? options?.[retired]?.style : undefined;
365
+
366
+ if (!oldRoleStyle) return ownFont || siteFont;
367
+
368
+ const pinned = pinDrawnLook(
369
+ props as unknown as TextStyleDeclaration,
370
+ oldRoleStyle,
371
+ siteFont,
372
+ ) as unknown as Record<string, unknown>;
373
+
374
+ return (pinned.fontFamily as string | undefined) ?? siteFont;
375
+ };
376
+
377
+ /**
378
+ * Reconnect one style to a canonical role, keeping its look. A canonical role is returned as is.
379
+ * Otherwise the role is `startingRole ?? (retired ? its successor : nearest by size)`, the look is
380
+ * pinned, and values equal to the new role are dropped, so only a real difference remains as an
381
+ * override. The look is the retired role's typography where that role replaced the field's own
382
+ * (`drawnBeforeCascade`); else the field's own values, then a renderer's defaults, then the old
383
+ * role's or the inherited values.
384
+ */
385
+ export const reconnectTextStyle = <T extends object>(
386
+ style: T,
387
+ targets: LegacyTargetMap,
388
+ options: TextStyleOptions | undefined,
389
+ spec: ReconnectSpec = {},
390
+ ): T => {
391
+ const type = (style as Record<string, unknown>).textStyleType;
392
+
393
+ if (isCanonicalTextStyleType(type)) return style;
394
+
395
+ const reconnected = { ...style } as TextStyleDeclaration;
396
+ const retired = isLegacyTextStyleType(type as string | undefined)
397
+ ? (type as LegacyTextStyleType)
398
+ : undefined;
399
+ // From the stored size, before any pin: a field with no size of its own goes to Paragraph 1.
400
+ const role =
401
+ spec.startingRole ??
402
+ (retired ? targets[retired] : bestFitRole(reconnected, spec.family));
403
+
404
+ const oldRoleStyle = retired ? options?.[retired]?.style : undefined;
405
+
406
+ if (oldRoleStyle && spec.drawnBeforeCascade) {
407
+ materialiseLegacyTypography(
408
+ reconnected,
409
+ oldRoleStyle,
410
+ spec.inheritedFontFamily,
411
+ );
412
+ } else {
413
+ pinUnset(reconnected, spec.renderedDefaults);
414
+ pinUnset(reconnected, typographyOf(oldRoleStyle));
415
+ pinUnset(reconnected, DETACHED_UNSET_EFFECTIVE);
416
+
417
+ if (!oldRoleStyle) {
418
+ pinUnset(reconnected, {
419
+ fontSize: INHERITED_FONT_SIZE,
420
+ fontFamily: spec.inheritedFontFamily,
421
+ });
422
+ }
423
+ }
424
+
425
+ reconnected.textStyleType = role;
426
+
427
+ const normalized = normalizeTextStyleAgainstRole(reconnected, options);
428
+ const kept = normalized as unknown as Record<string, unknown>;
429
+
430
+ // Where a renderer default beats the role, a value equal to the role still differs from what an
431
+ // unset prop would draw, so it stays.
432
+ for (const [prop, drawnDefault] of Object.entries(
433
+ spec.renderedDefaults ?? {},
434
+ )) {
435
+ const value = (reconnected as unknown as Record<string, unknown>)[prop];
436
+
437
+ if (!isUnset(value) && value !== drawnDefault) kept[prop] = value;
438
+ }
439
+
440
+ // A neutral (normal / none) the new role leaves unset draws the same unpinned, and unpinned a
441
+ // later role edit still reaches the field; keep it only where the role defines that prop.
442
+ const roleStyle = options?.[role]?.style as unknown as
443
+ | Record<string, unknown>
444
+ | undefined;
445
+
446
+ for (const [prop, neutral] of Object.entries(DETACHED_UNSET_EFFECTIVE)) {
447
+ if (
448
+ kept[prop] === neutral &&
449
+ isUnset(roleStyle?.[prop]) &&
450
+ !(prop in (spec.renderedDefaults ?? {}))
451
+ ) {
452
+ delete kept[prop];
453
+ }
454
+ }
455
+
456
+ return normalized as T;
457
+ };
458
+
459
+ // A role's colour, read defensively: the typed property is retired.
460
+ const roleColourOf = (
461
+ options: TextStyleOptions,
462
+ role: unknown,
463
+ ): string | undefined =>
464
+ (
465
+ options[role as keyof TextStyleOptions]?.style as unknown as
466
+ | Record<string, string | undefined>
467
+ | undefined
468
+ )?.color;
469
+
470
+ // A linked nav link draws `element || #000000` (`getTextStyleByContentTextStyle`). One with no colour
471
+ // of its own drew its legacy role's colour, or on no role inherited its parent's: for a tab the
472
+ // header's colour, else the page base coat (the paragraphs colour); for the hamburger menu, which
473
+ // renders beside the header under the page root (`Page.vue`), the base coat. That colour is kept
474
+ // before the link. Role colours are only still present during migration-22; later, only the
475
+ // header's colour is left to inherit.
476
+ const keepNavLinkColour = (
477
+ style: unknown,
478
+ options: TextStyleOptions,
479
+ headerColour: string | undefined,
480
+ ): void => {
481
+ if (!style || typeof style !== 'object') return;
482
+
483
+ const props = style as Record<string, unknown>;
484
+ const type = props.textStyleType;
485
+
486
+ if (!isBlankColorValue(props.color as string | undefined)) return;
487
+
488
+ if (isCanonicalTextStyleType(type)) return;
489
+
490
+ const colour = isLegacyTextStyleType(type as string | undefined)
491
+ ? roleColourOf(options, type)
492
+ : headerColour || roleColourOf(options, 'paragraphs');
493
+
494
+ if (!isBlankColorValue(colour)) props.color = colour;
495
+ };
496
+
497
+ type StyleHolder = Record<string, unknown> | undefined;
498
+
499
+ // `isTiptapDocument`, which lives maker-side.
500
+ const isTiptapDoc = (value: unknown): boolean =>
501
+ typeof value === 'object' &&
502
+ value !== null &&
503
+ (value as { type?: unknown }).type === 'doc';
504
+
505
+ // The sections whose success message now draws from its own `successMessageStyle`: the payment
506
+ // block (`Payment.vue`) and the shop checkout (`PaymentModal.vue`).
507
+ const SUCCESS_MESSAGE_TYPES: ReadonlySet<string> = new Set([
508
+ 'support-me',
509
+ 'request-payment',
510
+ 'shop-section',
511
+ ]);
512
+
513
+ // Before BP-5969 neither renderer drew `successMessageStyle`, so one on no canonical role (the
514
+ // old maker editor's `{ textAlign }`) is treated as absent (James Joung, 2026-09-28).
515
+ const seedsSuccessMessageStyle = (fields: Record<string, unknown>): boolean =>
516
+ SUCCESS_MESSAGE_TYPES.has(fields.type as string) &&
517
+ !isCanonicalTextStyleType(
518
+ (fields.successMessageStyle as StyleHolder)?.textStyleType,
519
+ );
520
+
521
+ // What the shop checkout drew its message with: the drawn (pre-reconnect) description's colour,
522
+ // less the container rung the shop lacks. On no role it drew `inherit`, which fe-shared-lib's `Modal`
523
+ // passes to the page root's Paragraphs colour (`Page.mixin` `rootElementStyles`), seeded onto
524
+ // Paragraph 1. Role colours are only still present during migration-22.
525
+ const shopSuccessMessageColour = (
526
+ drawnDescription: StyleHolder,
527
+ options: TextStyleOptions,
528
+ ): string | undefined =>
529
+ (drawnDescription?.color as string | undefined) ||
530
+ roleColourOf(options, drawnDescription?.textStyleType) ||
531
+ roleColourOf(options, 'paragraphs');
532
+
533
+ /**
534
+ * Give a success message the look it drew, on a role of its own (James Joung, 2026-09-28). The
535
+ * payment block drew it with its description's style, so it gets a copy of the reconnected
536
+ * description. With no description, and in the shop checkout (which took only the description's
537
+ * colour), it drew the page defaults, so it starts on Paragraph 2 keeping them, and the shop keeps
538
+ * that colour. A rich-text message drew only its runs and the page (`TextWrapper` gives rich text no
539
+ * typography from its style object), so on migration-22's input it keeps the page defaults on the
540
+ * description's role, lifted onto its runs: the render fill reads a neutral block value as "follow
541
+ * the role".
542
+ */
543
+ const seedSuccessMessageStyle = (
544
+ fields: Record<string, unknown>,
545
+ drawnDescription: StyleHolder,
546
+ options: TextStyleOptions,
547
+ reconnectAt: (holder: StyleHolder, key: string, spec?: ReconnectSpec) => void,
548
+ walk: Pick<ReconnectSpec, 'drawnBeforeCascade'>,
549
+ ): void => {
550
+ const description = fields.descriptionStyle as StyleHolder;
551
+ const isShop = fields.type === 'shop-section';
552
+ const drewPageDefaults =
553
+ !!walk.drawnBeforeCascade && isTiptapDoc(fields.successMessage);
554
+
555
+ if (
556
+ !isShop &&
557
+ !drewPageDefaults &&
558
+ description &&
559
+ typeof description === 'object'
560
+ ) {
561
+ fields.successMessageStyle = { ...description };
562
+
563
+ return;
564
+ }
565
+
566
+ const colour = isShop
567
+ ? shopSuccessMessageColour(drawnDescription, options)
568
+ : (description?.color as string | undefined);
569
+ const descriptionRole = description?.textStyleType;
570
+
571
+ fields.successMessageStyle = isBlankColorValue(colour)
572
+ ? {}
573
+ : { color: colour };
574
+ reconnectAt(fields, 'successMessageStyle', {
575
+ startingRole:
576
+ !isShop && isCanonicalTextStyleType(descriptionRole)
577
+ ? descriptionRole
578
+ : 'paragraph2',
579
+ });
580
+
581
+ if (drewPageDefaults) {
582
+ liftRteFieldOntoRole(
583
+ fields.successMessage,
584
+ fields.successMessageStyle as TextStyleDeclaration,
585
+ options,
586
+ );
587
+ }
588
+ };
589
+
590
+ // The font the v21 page root drew: the retired site text font, else the default. Only migration-22
591
+ // reads it (jobs A2 and B), before its last job deletes the field (`0036-retire-text-font-family.md`).
592
+ export const siteTextFontName = (
593
+ brandPageModel: BrandPageModel,
594
+ ): string | undefined => {
595
+ const textStyles = brandPageModel.styles?.textStyles as unknown as
596
+ | Record<string, unknown>
597
+ | undefined;
598
+ const textFontFamily = (textStyles?.['textFontFamily'] ||
599
+ DEFAULT_FONT_FAMILY_KEY) as FontFamilyKey;
600
+
601
+ return FONT_FAMILY_CONFIGS[textFontFamily]?.name;
602
+ };
603
+
604
+ /**
605
+ * Reconnect every persisted text field outside the ten, in place: content style keys (each with
606
+ * `contentFieldReconnectSpec`) and `textItems[].textStyle`, then per viewport the footer copyright,
607
+ * the nav tabs (starting role `paragraph1`), the hamburger menu (`button`) and the header button
608
+ * (`button`), then the Save Contact button (`button`). An unset family keeps the site text font.
609
+ * A payment or shop success message with no role of its own gets the look it drew
610
+ * (`seedSuccessMessageStyle`). Otherwise a no-op on canonical data.
611
+ */
612
+ export const reconnectTextStyleRoles = (
613
+ brandPageModel: BrandPageModel,
614
+ targets: LegacyTargetMap,
615
+ options: TextStyleOptions,
616
+ walk: Pick<ReconnectSpec, 'drawnBeforeCascade'> & {
617
+ renderedDefaultsForContent?: RenderedDefaultsForContent;
618
+ } = {},
619
+ ): void => {
620
+ const inheritedFontFamily = siteTextFontName(brandPageModel);
621
+
622
+ const reconnectAt = (
623
+ holder: StyleHolder,
624
+ key: string,
625
+ spec: ReconnectSpec = {},
626
+ ): void => {
627
+ const style = holder?.[key];
628
+
629
+ if (!holder || !style || typeof style !== 'object') return;
630
+
631
+ const renderedDefaults = walk.renderedDefaultsForContent?.(holder, key);
632
+
633
+ holder[key] = reconnectTextStyle(style, targets, options, {
634
+ ...spec,
635
+ drawnBeforeCascade: walk.drawnBeforeCascade,
636
+ renderedDefaults: {
637
+ ...spec.renderedDefaults,
638
+ ...renderedDefaults,
639
+ },
640
+ inheritedFontFamily,
641
+ });
642
+ };
643
+
644
+ const styleKeys = Object.keys(CONTENT_TEXT_STYLE_PROPERTY_KEYS);
645
+
646
+ for (const page of brandPageModel.pages ?? []) {
647
+ for (const content of page.contents ?? []) {
648
+ const fields = content as unknown as Record<string, unknown>;
649
+ const seedsSuccessMessage = seedsSuccessMessageStyle(fields);
650
+ // The reconnect replaces the style object, so this stays the description as it was drawn.
651
+ const drawnDescription = fields.descriptionStyle as StyleHolder;
652
+
653
+ if (seedsSuccessMessage) delete fields.successMessageStyle;
654
+
655
+ for (const key of styleKeys) {
656
+ reconnectAt(
657
+ fields,
658
+ key,
659
+ contentFieldReconnectSpec(fields.type as string | undefined, key),
660
+ );
661
+ }
662
+
663
+ if (seedsSuccessMessage) {
664
+ seedSuccessMessageStyle(
665
+ fields,
666
+ drawnDescription,
667
+ options,
668
+ reconnectAt,
669
+ walk,
670
+ );
671
+ }
672
+
673
+ const textItems = fields.textItems;
674
+
675
+ if (Array.isArray(textItems)) {
676
+ for (const item of textItems) {
677
+ if (item && typeof item === 'object') {
678
+ reconnectAt(item as StyleHolder, 'textStyle');
679
+ }
680
+ }
681
+ }
682
+ }
683
+ }
684
+
685
+ for (const footer of [
686
+ brandPageModel.pageFooterDesktop,
687
+ brandPageModel.pageFooterMobile,
688
+ ]) {
689
+ reconnectAt(footer as unknown as StyleHolder, 'copyrightStyle');
690
+ }
691
+
692
+ for (const header of [
693
+ brandPageModel.pageHeaderDesktop,
694
+ brandPageModel.pageHeaderMobile,
695
+ ]) {
696
+ const navigation = header?.navigation as unknown as StyleHolder;
697
+ const headerColour = (header?.style as { color?: string } | undefined)
698
+ ?.color;
699
+
700
+ keepNavLinkColour(navigation?.defaultButtonStyle, options, headerColour);
701
+ keepNavLinkColour(
702
+ (navigation?.hamburgerMenuStyle as StyleHolder)?.defaultButtonStyle,
703
+ options,
704
+ undefined,
705
+ );
706
+
707
+ reconnectAt(navigation, 'defaultButtonStyle', {
708
+ startingRole: 'paragraph1',
709
+ });
710
+ reconnectAt(
711
+ navigation?.hamburgerMenuStyle as StyleHolder,
712
+ 'defaultButtonStyle',
713
+ { startingRole: 'button' },
714
+ );
715
+ reconnectAt(
716
+ header?.headerButton as unknown as StyleHolder,
717
+ 'buttonTextStyle',
718
+ BUTTON_ELEMENT_RECONNECT,
719
+ );
720
+ }
721
+
722
+ reconnectAt(
723
+ brandPageModel.saveContactSettings as unknown as StyleHolder,
724
+ 'buttonTextStyle',
725
+ { startingRole: 'button' },
726
+ );
727
+ };