@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.
- package/lib/src/{CreatedOnBrandCrowd-de-de-DDcraD5S.js → CreatedOnBrandCrowd-de-de-BtVKllNQ.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-en-us-DtOeaisf.js → CreatedOnBrandCrowd-en-us-CX5V0v8u.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-es-es-BZpmJPew.js → CreatedOnBrandCrowd-es-es-CbA02PCL.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-fr-CqRwC4e7.js → CreatedOnBrandCrowd-fr-ca-BQAKruBF.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-ca-CqRwC4e7.js → CreatedOnBrandCrowd-fr-fr-BQAKruBF.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-pt-DId9Dfjh.js → CreatedOnBrandCrowd-pt-br-Yk_yzB3s.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-br-DId9Dfjh.js → CreatedOnBrandCrowd-pt-pt-Yk_yzB3s.js} +1 -1
- package/lib/src/{CreatedOnDcom-de-de-BTDfmOcm.js → CreatedOnDcom-de-de-DJZQbPSD.js} +1 -1
- package/lib/src/{CreatedOnDcom-en-us-CeAu9Ayx.js → CreatedOnDcom-en-us-BJvNAa4l.js} +1 -1
- package/lib/src/{CreatedOnDcom-es-es-WCv0K41H.js → CreatedOnDcom-es-es-CUwB1FRY.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-ca-BlfevQDY.js → CreatedOnDcom-fr-ca-CK54U4oh.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-fr-Cvt7MHPZ.js → CreatedOnDcom-fr-fr-DuUNBGrM.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-br-DipZuylv.js → CreatedOnDcom-pt-br-BfODpFNV.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-pt-BCw4lcKN.js → CreatedOnDcom-pt-pt-Cf6u2GCg.js} +1 -1
- package/lib/src/brand-page/__fixtures__/production-text-style-resolver.fixture.d.ts +16 -0
- package/lib/src/brand-page/__fixtures__/production-text-style-resolver.fixture.js +35 -0
- package/lib/src/brand-page/components/contact-form/ContactForm.mixin.d.ts +3 -0
- package/lib/src/brand-page/components/contact-form/ContactForm.mixin.js +19 -13
- package/lib/src/brand-page/components/mailing-list/MailingList.mixin.d.ts +3 -1
- package/lib/src/brand-page/components/mailing-list/MailingList.mixin.js +17 -2
- package/lib/src/brand-page/components/navigation/button-carousel/ButtonCarouselNavigation.mixin.d.ts +11 -3
- package/lib/src/brand-page/components/navigation/button-carousel/ButtonCarouselNavigation.mixin.js +35 -1
- package/lib/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.mixin.d.ts +8 -2
- package/lib/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.mixin.js +27 -3
- package/lib/src/brand-page/components/page/Page.mixin.d.ts +5 -2
- package/lib/src/brand-page/components/page/Page.mixin.js +33 -27
- package/lib/src/brand-page/components/page-footer/PageFooter.mixin.d.ts +7 -2
- package/lib/src/brand-page/components/page-footer/PageFooter.mixin.js +21 -1
- package/lib/src/brand-page/components/payment/Payment.mixin.d.ts +5 -2
- package/lib/src/brand-page/components/payment/Payment.mixin.js +22 -2
- package/lib/src/brand-page/components/payment/support-me/SupportMe.mixin.d.ts +6 -2
- package/lib/src/brand-page/components/payment/support-me/SupportMe.mixin.js +32 -1
- package/lib/src/brand-page/components/social-links/SocialLinks.stories.js +0 -3
- package/lib/src/brand-page/components/testimonial-section/__fixtures__/data.js +0 -3
- package/lib/src/brand-page/components/text/Text.stories.js +0 -17
- package/lib/src/brand-page/constants/font.constants.d.ts +62 -0
- package/lib/src/brand-page/constants/font.constants.js +35 -0
- package/lib/src/brand-page/models/index.d.ts +23 -24
- package/lib/src/brand-page/models/index.js +20 -7
- package/lib/src/brand-page/models/navigation-styles.model.d.ts +1 -1
- package/lib/src/brand-page/models/navigation-styles.model.js +17 -8
- package/lib/src/brand-page/models/payment.model.d.ts +11 -6
- package/lib/src/brand-page/models/styles.model.d.ts +53 -7
- package/lib/src/brand-page/models/styles.model.js +115 -27
- package/lib/src/brand-page/utils/color-palette.util.d.ts +43 -23
- package/lib/src/brand-page/utils/color-palette.util.js +65 -27
- package/lib/src/brand-page/utils/color.util.d.ts +13 -9
- package/lib/src/brand-page/utils/color.util.js +56 -15
- package/lib/src/brand-page/utils/container-text-color.util.d.ts +46 -13
- package/lib/src/brand-page/utils/container-text-color.util.js +321 -41
- package/lib/src/brand-page/utils/index.d.ts +1 -0
- package/lib/src/brand-page/utils/index.js +1 -0
- package/lib/src/brand-page/utils/migration/migration-20.js +6 -2
- package/lib/src/brand-page/utils/migration/migration-21.js +34 -6
- package/lib/src/brand-page/utils/migration/migration-22.d.ts +99 -0
- package/lib/src/brand-page/utils/migration/migration-22.js +909 -0
- package/lib/src/brand-page/utils/migration.util.js +17 -0
- package/lib/src/brand-page/utils/model.util.d.ts +4 -0
- package/lib/src/brand-page/utils/model.util.js +4 -0
- package/lib/src/brand-page/utils/personalisation.util.js +9 -1
- package/lib/src/brand-page/utils/rte-role-lift.util.d.ts +72 -0
- package/lib/src/brand-page/utils/rte-role-lift.util.js +275 -0
- package/lib/src/brand-page/utils/style.util.d.ts +5 -1
- package/lib/src/brand-page/utils/style.util.js +34 -11
- package/lib/src/brand-page/utils/text-role-css.util.d.ts +19 -0
- package/lib/src/brand-page/utils/text-role-css.util.js +186 -0
- package/lib/src/brand-page/utils/text-role-reconnect.util.d.ts +90 -0
- package/lib/src/brand-page/utils/text-role-reconnect.util.js +434 -0
- package/lib/src/brand-page/utils/text-style.util.d.ts +53 -23
- package/lib/src/brand-page/utils/text-style.util.js +122 -22
- package/lib/src/brand-page/utils/view-model.util.d.ts +9 -1
- package/lib/src/brand-page/utils/view-model.util.js +124 -111
- package/lib/src/brand-page/view-models.d.ts +1 -0
- package/lib/src/brand-page-maker/components/action-bar/ActionBar.mixin.d.ts +4 -1
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +13 -2
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.js +4 -4
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMakerTemplateSettings.mixin.d.ts +4 -1
- package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.js +0 -10
- package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/content-settings-items.fixture.js +0 -1
- package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +23 -138
- package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.js +0 -28
- package/lib/src/brand-page-maker/components/brandpage-settings/ReplaceImageSettingsForBrandPageSettings.mixin.d.ts +4 -1
- package/lib/src/brand-page-maker/components/navigation/Navigation.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.d.ts +5 -2
- package/lib/src/brand-page-maker/components/seo-settings/UrlSettings.mixin.d.ts +4 -1
- package/lib/src/brand-page-maker/components/social-share/SocialShare.mixin.d.ts +4 -1
- package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.d.ts +4 -1
- package/lib/src/brand-page-maker/composables/ai-chat/useAiMetadataBuilder.d.ts +1 -0
- package/lib/src/brand-page-maker/composables/ai-chat/useAiMetadataBuilder.js +1 -0
- package/lib/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.js +1 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/RoleTypographyFill.d.ts +16 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/RoleTypographyFill.js +61 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/RteClipboard.d.ts +11 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/RteClipboard.js +236 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/font.d.ts +2 -1
- package/lib/src/brand-page-maker/composables/rich-text-editor/font.js +25 -6
- package/lib/src/brand-page-maker/composables/rich-text-editor/formatting.d.ts +17 -4
- package/lib/src/brand-page-maker/composables/rich-text-editor/formatting.js +204 -17
- package/lib/src/brand-page-maker/composables/rich-text-editor/hyperlink.d.ts +1 -1
- package/lib/src/brand-page-maker/composables/rich-text-editor/hyperlink.js +29 -31
- package/lib/src/brand-page-maker/composables/rich-text-editor/keepMarksOnEmpty.d.ts +20 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/keepMarksOnEmpty.js +60 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/spacing.d.ts +2 -1
- package/lib/src/brand-page-maker/composables/rich-text-editor/spacing.js +22 -6
- package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.d.ts +10 -4
- package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.js +319 -275
- package/lib/src/brand-page-maker/constants/config-settings-constant.js +1 -5
- package/lib/src/brand-page-maker/convertors/text-css-style-options.convertor.js +6 -2
- package/lib/src/brand-page-maker/convertors/text-size-value.convertor.d.ts +1 -1
- package/lib/src/brand-page-maker/convertors/text-size-value.convertor.js +3 -1
- package/lib/src/brand-page-maker/default-getters/payment-text-and-border-color.default-getter.js +7 -14
- package/lib/src/brand-page-maker/default-getters/text-color.default-getter.js +6 -13
- package/lib/src/brand-page-maker/models/content-settings.d.ts +8 -0
- package/lib/src/brand-page-maker/models/content-settings.js +112 -81
- package/lib/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store-utils.d.ts +2 -2
- package/lib/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store-utils.js +5 -2
- package/lib/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store.js +4 -3
- package/lib/src/brand-page-maker/stores/ai-checkpoint/ai-checkpoint-store.d.ts +1257 -117
- package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.d.ts +6 -1
- package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.js +17 -9
- package/lib/src/brand-page-maker/stores/history/history-store.d.ts +59 -5
- package/lib/src/brand-page-maker/stores/history/history-store.js +22 -2
- package/lib/src/brand-page-maker/utils/apply-color-strategy.js +26 -8
- package/lib/src/brand-page-maker/utils/index.d.ts +2 -1
- package/lib/src/brand-page-maker/utils/index.js +2 -1
- package/lib/src/brand-page-maker/utils/rich-text-editor.util.d.ts +117 -15
- package/lib/src/brand-page-maker/utils/rich-text-editor.util.js +435 -281
- package/lib/src/brand-page-maker/utils/rte-authoring.util.d.ts +4 -0
- package/lib/src/brand-page-maker/utils/rte-authoring.util.js +101 -0
- package/lib/src/brand-page-maker/utils/rte-clipboard.util.d.ts +126 -0
- package/lib/src/brand-page-maker/utils/rte-clipboard.util.js +307 -0
- package/lib/src/brand-page-maker/utils/rte-sanitize.util.js +13 -3
- package/lib/src/{bundled-translations-zfiA5Tsw.js → bundled-translations-yGrvPE5i.js} +17 -17
- package/lib/src/{bundled-translations.de-DE-ChsdSyAP.js → bundled-translations.de-DE-L4Znf8Hs.js} +17 -17
- package/lib/src/{bundled-translations.es-ES-DflsWQK0.js → bundled-translations.es-ES-D6iticrK.js} +15 -15
- package/lib/src/{bundled-translations.fr-CA-fpDRuZ52.js → bundled-translations.fr-CA-BgAVE-9k.js} +25 -25
- package/lib/src/{bundled-translations.fr-FR-Bub73Zt-.js → bundled-translations.fr-FR-B8GbyqxQ.js} +17 -17
- package/lib/src/{bundled-translations.pt-BR-BlnWE9TB.js → bundled-translations.pt-BR-DjPU3Db7.js} +25 -25
- package/lib/src/{bundled-translations.pt-PT-DmzXlnaS.js → bundled-translations.pt-PT-BaepaDpr.js} +23 -23
- package/lib/src/bundles/bundled-translations.de-DE.json +21 -2
- package/lib/src/bundles/bundled-translations.es-ES.json +21 -2
- package/lib/src/bundles/bundled-translations.fr-CA.json +21 -2
- package/lib/src/bundles/bundled-translations.fr-FR.json +21 -2
- package/lib/src/bundles/bundled-translations.json +21 -2
- package/lib/src/bundles/bundled-translations.pt-BR.json +21 -2
- package/lib/src/bundles/bundled-translations.pt-PT.json +21 -2
- package/lib/src/clients/ai-assistant-client.d.ts +1 -0
- package/lib/src/composables/useTranslate.d.ts +1 -1
- package/lib/src/composables/useTranslate.js +1 -1
- package/lib/src/css/library.brand-page-brandCrowd.min.css +303 -207
- package/lib/src/css/library.brand-page-brandPage.min.css +303 -207
- package/lib/src/css/library.brand-page-designCom.min.css +303 -207
- package/lib/src/css/library.brand-page-preview.min.css +303 -207
- package/lib/src/index.d.ts +2 -1
- package/lib/src/index.mjs +195 -191
- package/lib/src/{lib-1AqtEmvQ.js → lib-kGRlD3_P.js} +36855 -33893
- package/lib/src/lib.js +2 -1
- package/lib/src/metadata-builder/builders/footer-builder.js +4 -5
- package/lib/src/metadata-builder/builders/global-role-propagation.d.ts +58 -0
- package/lib/src/metadata-builder/builders/global-role-propagation.js +246 -0
- package/lib/src/metadata-builder/builders/global-styles-builder.d.ts +1 -0
- package/lib/src/metadata-builder/builders/global-styles-builder.js +116 -45
- package/lib/src/metadata-builder/builders/header-builder.js +13 -4
- package/lib/src/metadata-builder/builders/section-builders/about-section-builder.js +3 -3
- package/lib/src/metadata-builder/builders/section-builders/banner-section-builder.js +3 -3
- package/lib/src/metadata-builder/builders/section-builders/booking-section-builder.js +3 -3
- package/lib/src/metadata-builder/builders/section-builders/contact-form-builder.js +4 -4
- package/lib/src/metadata-builder/builders/section-builders/images-section-builder.js +3 -3
- package/lib/src/metadata-builder/builders/section-builders/mailing-list-builder.js +2 -2
- package/lib/src/metadata-builder/builders/section-builders/mailing-list-section-builder.js +2 -2
- package/lib/src/metadata-builder/builders/section-builders/profile-section-builder.js +4 -4
- package/lib/src/metadata-builder/builders/section-builders/shapes-section-builder.js +3 -3
- package/lib/src/metadata-builder/builders/section-builders/social-links-builder.js +8 -2
- package/lib/src/metadata-builder/builders/section-builders/testimonial-section-builder.js +2 -2
- package/lib/src/metadata-builder/builders/section-builders/text-section-builder.js +60 -29
- package/lib/src/metadata-builder/builders/section-field-maps.js +1 -0
- package/lib/src/metadata-builder/builders/section-field-utils.d.ts +48 -19
- package/lib/src/metadata-builder/builders/section-field-utils.js +128 -52
- package/lib/src/metadata-builder/builders/section-rules/global-styles.rules.d.ts +4 -2
- package/lib/src/metadata-builder/builders/section-rules/global-styles.rules.js +28 -12
- package/lib/src/metadata-builder/builders/section-rules/social-links.rules.js +5 -1
- package/lib/src/metadata-builder/helpers/rte.helpers.d.ts +1 -1
- package/lib/src/metadata-builder/helpers/rte.helpers.js +97 -40
- package/lib/src/metadata-builder/metadata-executor.js +23 -1
- package/lib/src/metadata-builder/models.d.ts +2 -0
- package/lib/src/metadata-builder/parsers/ai-toolcall-parser.d.ts +18 -19
- package/lib/src/metadata-builder/parsers/section-tool-arguments.d.ts +18 -1
- package/lib/src/metadata-builder/sanitizers/rte-schema-check.js +1 -1
- package/lib/src/metadata-builder/sanitizers/sanitizer-rules.d.ts +0 -1
- package/lib/src/metadata-builder/sanitizers/sanitizer-rules.js +5 -8
- package/lib/src/metadata-builder/sanitizers/section-args-validator.d.ts +7 -16
- package/lib/src/metadata-builder/sanitizers/section-args-validator.js +95 -22
- package/lib/src/shared/color-palette/section-color-matches.js +9 -25
- package/lib/src/shared/color-strategies/color-strategies.d.ts +15 -0
- package/lib/src/shared/color-strategies/color-strategies.js +31 -0
- package/lib/src/shared/color-strategies/rte-color.d.ts +8 -0
- package/lib/src/shared/color-strategies/rte-color.js +16 -0
- package/lib/src/shared/color-strategies/rte-field-pairs.d.ts +23 -0
- package/lib/src/shared/color-strategies/rte-field-pairs.js +28 -0
- package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +9 -135
- package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.js +1 -27
- package/lib/src/shared/content-settings/components/content-settings/ReplaceImageSettingsForContent.mixin.d.ts +12 -2
- package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.d.ts +7 -0
- package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.d.ts +75 -6
- package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.js +18 -7
- package/lib/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.d.ts +6 -1
- package/lib/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.js +0 -7
- package/lib/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.d.ts +1 -0
- package/lib/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.js +8 -4
- package/lib/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.d.ts +1255 -26
- package/lib/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.js +203 -59
- package/lib/src/shared/content-settings/store/content-settings-store.d.ts +6 -0
- package/lib/src/shared/content-settings/store/content-settings-store.js +105 -8
- package/lib/src/shared/logo-settings/components/LogoSettings.mixin.d.ts +5 -1
- package/lib/src/shared/navigation-style-settings/store/index.d.ts +7 -3
- package/lib/src/shared/navigation-style-settings/store/index.js +40 -15
- package/lib/src/shared/page-settings/components/delete-page-modal/DeletePageModal.mixin.d.ts +1 -1
- package/lib/src/shared/page-settings/components/new-page-modal/NewPageModal.mixin.d.ts +1 -0
- package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +17 -5
- package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +70 -13
- package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.js +10 -2
- package/lib/src/shared/page-settings/store/page-settings-store.d.ts +2 -1
- package/lib/src/shared/page-settings/store/page-settings-store.js +17 -0
- package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +4 -1
- package/lib/src/shared/rte-extensions/AutoLink.d.ts +17 -0
- package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/AutoLink.js +67 -51
- package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/MaxLength.js +4 -1
- package/lib/src/shared/rte-extensions/TextEffects.d.ts +28 -0
- package/lib/src/shared/rte-extensions/TextEffects.js +96 -0
- package/lib/src/shared/rte-extensions/ViewDomParser.d.ts +2 -0
- package/lib/src/shared/rte-extensions/ViewDomParser.js +21 -0
- package/lib/src/shared/rte-extensions.util.d.ts +25 -0
- package/lib/src/{brand-page-maker/composables/rich-text-editor/getRteExtensions.js → shared/rte-extensions.util.js} +62 -7
- package/lib/src/shared/rte-link.util.d.ts +1 -0
- package/lib/src/shared/rte-link.util.js +1 -0
- package/lib/src/shared/rte-render.util.d.ts +112 -0
- package/lib/src/shared/rte-render.util.js +255 -0
- package/lib/src/shared/rte-shape.util.d.ts +6 -0
- package/lib/src/shared/rte-shape.util.js +18 -0
- package/lib/src/shared/side-bar/components/SideBar.mixin.d.ts +2 -1
- package/lib/src/shared/side-bar/components/SideBarTabButton.mixin.d.ts +1 -0
- package/lib/src/shared/side-bar/store/side-bar-store.d.ts +2 -0
- package/lib/src/shared/side-bar/store/side-bar-store.js +9 -0
- package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +155 -15
- package/lib/src/shared/style-settings/components/StyleSettings.mixin.js +7 -1
- package/lib/src/shared/style-settings/store/style-settings-store.d.ts +1 -9
- package/lib/src/shared/style-settings/store/style-settings-store.js +3 -33
- package/lib/src/shared/style-settings/text-style-size-order.d.ts +2 -0
- package/lib/src/shared/style-settings/text-style-size-order.js +13 -0
- package/lib/src/shared/text-role-typography.util.d.ts +64 -0
- package/lib/src/shared/text-role-typography.util.js +183 -0
- package/lib/src/utils/minify-brand-page-metadata.d.ts +16 -1
- package/lib/src/utils/minify-brand-page-metadata.js +31 -9
- package/package.json +1 -1
- package/src/brand-page/__fixtures__/migration-22-v21/edited-brandsite-sections.v21.json +982 -0
- package/src/brand-page/__fixtures__/migration-22-v21/new-brandcontact-every-section.v21.json +1231 -0
- package/src/brand-page/__fixtures__/migration-22-v21/new-brandpage-every-section.v21.json +1231 -0
- package/src/brand-page/__fixtures__/migration-22-v21/new-brandsite-every-section.v21.json +1243 -0
- package/src/brand-page/__fixtures__/migration-22-v21/real-brandcontact.v21.json +755 -0
- package/src/brand-page/__fixtures__/migration-22-v21/real-brandpage-general-link.v21.json +527 -0
- package/src/brand-page/__fixtures__/migration-22-v21/real-brandpage-links.v21.json +755 -0
- package/src/brand-page/__fixtures__/migration-22-v21/real-brandpage-social-links.v21.json +514 -0
- package/src/brand-page/__fixtures__/migration-22-v21/real-brandsite-about.v21.json +459 -0
- package/src/brand-page/__fixtures__/migration-22-v21/real-brandsite-footer.v21.json +469 -0
- package/src/brand-page/__fixtures__/migration-22-v21/real-brandsite-header-banner.v21.json +481 -0
- package/src/brand-page/__fixtures__/migration-22-v21/real-brandsite-sections.v21.json +800 -0
- package/src/brand-page/__fixtures__/production-text-style-resolver.fixture.ts +52 -0
- package/src/brand-page/components/about-section/AboutSection.vue.test.ts +0 -10
- package/src/brand-page/components/contact-form/ContactForm.mixin.test.ts +127 -0
- package/src/brand-page/components/contact-form/ContactForm.mixin.ts +31 -14
- package/src/brand-page/components/contact-form/ContactForm.vue +26 -12
- package/src/brand-page/components/contact-form/ContactForm.vue.test.ts +60 -0
- package/src/brand-page/components/mailing-list/MailingList.mixin.test.ts +92 -0
- package/src/brand-page/components/mailing-list/MailingList.mixin.ts +28 -3
- package/src/brand-page/components/mailing-list/MailingList.vue +9 -4
- package/src/brand-page/components/mailing-list/MailingList.vue.test.ts +63 -0
- package/src/brand-page/components/navigation/button-carousel/ButtonCarouselNavigation.mixin.ts +51 -1
- package/src/brand-page/components/navigation/button-carousel/ButtonCarouselNavigation.test.ts +114 -0
- package/src/brand-page/components/navigation/button-carousel/ButtonCarouselNavigation.vue +8 -2
- package/src/brand-page/components/navigation/navigation-carousel/NavigationCarousel.test.ts +182 -0
- package/src/brand-page/components/navigation/navigation-carousel/NavigationCarousel.vue +59 -12
- package/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.mixin.ts +40 -3
- package/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.vue +15 -7
- package/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.vue.test.ts +133 -3
- package/src/brand-page/components/page/Page.mixin.ts +41 -34
- package/src/brand-page/components/page/Page.vue +17 -6
- package/src/brand-page/components/page/Page.vue.test.ts +91 -1
- package/src/brand-page/components/page-footer/PageFooter.mixin.ts +32 -2
- package/src/brand-page/components/page-footer/PageFooter.test.ts +79 -0
- package/src/brand-page/components/page-footer/PageFooter.vue +12 -4
- package/src/brand-page/components/payment/Payment.mixin.ts +34 -2
- package/src/brand-page/components/payment/Payment.test.ts +188 -0
- package/src/brand-page/components/payment/Payment.vue +12 -5
- package/src/brand-page/components/payment/RequestPaymentStripe.vue +1 -0
- package/src/brand-page/components/payment/support-me/SupportMe.mixin.ts +49 -2
- package/src/brand-page/components/payment/support-me/SupportMe.test.ts +100 -0
- package/src/brand-page/components/payment/support-me/SupportMe.vue +7 -1
- package/src/brand-page/components/payment/support-me/SupportMe.vue.test.ts +66 -0
- package/src/brand-page/components/save-contact/SaveContactWidget.test.ts +100 -0
- package/src/brand-page/components/save-contact/SaveContactWidget.vue +6 -3
- package/src/brand-page/components/shop/PaymentModal.vue +2 -6
- package/src/brand-page/components/shop/PaymentShippingAddress.vue +6 -0
- package/src/brand-page/components/shop/Shop.vue +15 -2
- package/src/brand-page/components/shop/Shop.vue.test.ts +74 -2
- package/src/brand-page/components/social-links/SocialLinks.stories.ts +0 -3
- package/src/brand-page/components/social-links/SocialLinks.vue.test.ts +0 -3
- package/src/brand-page/components/testimonial-section/__fixtures__/data.ts +0 -3
- package/src/brand-page/components/text/Text.stories.ts +0 -17
- package/src/brand-page/components/text-wrapper/TextWrapper.parity.test.ts +136 -0
- package/src/brand-page/components/text-wrapper/TextWrapper.test.ts +358 -0
- package/src/brand-page/components/text-wrapper/TextWrapper.vue +82 -22
- package/src/brand-page/constants/font.constants.ts +37 -0
- package/src/brand-page/models/footer-icon-color.test.ts +22 -0
- package/src/brand-page/models/index.ts +50 -28
- package/src/brand-page/models/navigation-styles.model.test.ts +77 -1
- package/src/brand-page/models/navigation-styles.model.ts +26 -9
- package/src/brand-page/models/payment.model.ts +15 -6
- package/src/brand-page/models/styles.model.test.ts +104 -0
- package/src/brand-page/models/styles.model.ts +181 -47
- package/src/brand-page/utils/__snapshots__/migration.util.test.ts.snap +619 -115
- package/src/brand-page/utils/__snapshots__/migration2.util.test.ts.snap +150 -9
- package/src/brand-page/utils/__snapshots__/model.util.test.ts.snap +300 -18
- package/src/brand-page/utils/color-palette.util.test.ts +126 -1
- package/src/brand-page/utils/color-palette.util.ts +92 -26
- package/src/brand-page/utils/color.util.test.ts +62 -29
- package/src/brand-page/utils/color.util.ts +77 -14
- package/src/brand-page/utils/container-text-color.util.test.ts +672 -26
- package/src/brand-page/utils/container-text-color.util.ts +472 -46
- package/src/brand-page/utils/index.ts +1 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/edited-brandsite-sections.v22.json +1191 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/new-brandcontact-every-section.v22.json +2026 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/new-brandpage-every-section.v22.json +2017 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/new-brandsite-every-section.v22.json +2031 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandcontact.v22.json +1145 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandpage-general-link.v22.json +645 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandpage-links.v22.json +1136 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandpage-social-links.v22.json +662 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandsite-about.v22.json +638 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandsite-footer.v22.json +610 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandsite-header-banner.v22.json +660 -0
- package/src/brand-page/utils/migration/__snapshots__/migration-22-output/real-brandsite-sections.v22.json +1132 -0
- package/src/brand-page/utils/migration/migration-01.ts +293 -237
- package/src/brand-page/utils/migration/migration-02.ts +8 -1
- package/src/brand-page/utils/migration/migration-20.ts +6 -3
- package/src/brand-page/utils/migration/migration-20_5.test.ts +5 -2
- package/src/brand-page/utils/migration/migration-21.test.ts +34 -0
- package/src/brand-page/utils/migration/migration-21.ts +46 -10
- package/src/brand-page/utils/migration/migration-22.fixed-input.test.ts +43 -0
- package/src/brand-page/utils/migration/migration-22.test.ts +4103 -0
- package/src/brand-page/utils/migration/migration-22.text-font-family.test.ts +72 -0
- package/src/brand-page/utils/migration/migration-22.ts +1336 -0
- package/src/brand-page/utils/migration.util.test.ts +146 -32
- package/src/brand-page/utils/migration.util.ts +18 -0
- package/src/brand-page/utils/model.util.ts +4 -0
- package/src/brand-page/utils/personalisation.util.test.ts +148 -3
- package/src/brand-page/utils/personalisation.util.ts +9 -1
- package/src/brand-page/utils/rte-role-lift.util.ts +409 -0
- package/src/brand-page/utils/style.util.test.ts +35 -2
- package/src/brand-page/utils/style.util.ts +45 -11
- package/src/brand-page/utils/text-role-css.util.test.ts +525 -0
- package/src/brand-page/utils/text-role-css.util.ts +321 -0
- package/src/brand-page/utils/text-role-reconnect.util.test.ts +604 -0
- package/src/brand-page/utils/text-role-reconnect.util.ts +727 -0
- package/src/brand-page/utils/text-style.util.test.ts +305 -0
- package/src/brand-page/utils/text-style.util.ts +198 -24
- package/src/brand-page/utils/view-model.page-data.test.ts +232 -0
- package/src/brand-page/utils/view-model.util.test.ts +954 -133
- package/src/brand-page/utils/view-model.util.ts +187 -139
- package/src/brand-page/view-models.ts +4 -0
- package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.blank-site.test.ts +57 -0
- package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.ts +9 -5
- package/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.ts +0 -10
- package/src/brand-page-maker/components/brand-page-maker/__fixtures__/content-settings-items.fixture.ts +0 -1
- package/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.ts +0 -44
- package/src/brand-page-maker/components/rich-text-editor/RichTextEditor.vue +253 -200
- package/src/brand-page-maker/components/shop/AddOrEditProductContainer.vue +1 -0
- package/src/brand-page-maker/components/template-preview/TemplatePreview.vue +1 -0
- package/src/brand-page-maker/composables/ai-chat/useAiMetadataBuilder.ts +2 -0
- package/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.ts +1 -0
- package/src/brand-page-maker/composables/rich-text-editor/block-typography.test.ts +519 -0
- package/src/brand-page-maker/composables/rich-text-editor/extensions/FontFamily.test.ts +1 -1
- package/src/brand-page-maker/composables/rich-text-editor/extensions/MaxLength.test.ts +26 -1
- package/src/brand-page-maker/composables/rich-text-editor/extensions/RoleTypographyFill.test.ts +110 -0
- package/src/brand-page-maker/composables/rich-text-editor/extensions/RoleTypographyFill.ts +99 -0
- package/src/brand-page-maker/composables/rich-text-editor/extensions/RteClipboard.ts +397 -0
- package/src/brand-page-maker/composables/rich-text-editor/extensions/ViewDomParser.test.ts +139 -0
- package/src/brand-page-maker/composables/rich-text-editor/font.ts +36 -5
- package/src/brand-page-maker/composables/rich-text-editor/formatting.test.ts +375 -1
- package/src/brand-page-maker/composables/rich-text-editor/formatting.ts +301 -17
- package/src/brand-page-maker/composables/rich-text-editor/hyperlink.test.ts +82 -1
- package/src/brand-page-maker/composables/rich-text-editor/hyperlink.ts +28 -34
- package/src/brand-page-maker/composables/rich-text-editor/keepMarksOnEmpty.test.ts +80 -0
- package/src/brand-page-maker/composables/rich-text-editor/keepMarksOnEmpty.ts +75 -0
- package/src/brand-page-maker/composables/rich-text-editor/spacing.ts +31 -6
- package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.test.ts +2485 -0
- package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.ts +435 -337
- package/src/brand-page-maker/constants/config-settings-constant.ts +0 -6
- package/src/brand-page-maker/convertors/text-css-style-options.convertor.test.ts +43 -0
- package/src/brand-page-maker/convertors/text-css-style-options.convertor.ts +6 -2
- package/src/brand-page-maker/convertors/text-size-value.convertor.test.ts +24 -0
- package/src/brand-page-maker/convertors/text-size-value.convertor.ts +17 -13
- package/src/brand-page-maker/default-getters/payment-text-and-border-color.default-getter.ts +7 -22
- package/src/brand-page-maker/default-getters/text-color.default-getter.ts +5 -21
- package/src/brand-page-maker/models/content-settings.test.ts +708 -0
- package/src/brand-page-maker/models/content-settings.ts +133 -82
- package/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store-utils.test.ts +63 -1
- package/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store-utils.ts +16 -3
- package/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store.test.ts +34 -0
- package/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store.ts +4 -2
- package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.test.ts +185 -1
- package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.ts +22 -34
- package/src/brand-page-maker/stores/history/history-store.ts +35 -2
- package/src/brand-page-maker/utils/__snapshots__/apply-color-strategy.golden.test.ts.snap +528 -0
- package/src/brand-page-maker/utils/__snapshots__/rte-render-parity.test.ts.snap +12 -0
- package/src/brand-page-maker/utils/apply-color-strategy.golden.test.ts +2 -0
- package/src/brand-page-maker/utils/apply-color-strategy.test.ts +181 -3
- package/src/brand-page-maker/utils/apply-color-strategy.ts +36 -4
- package/src/brand-page-maker/utils/index.ts +2 -1
- package/src/brand-page-maker/utils/rich-text-editor.util.test.ts +447 -410
- package/src/brand-page-maker/utils/rich-text-editor.util.ts +610 -506
- package/src/brand-page-maker/utils/rte-authoring.util.test.ts +244 -0
- package/src/brand-page-maker/utils/rte-authoring.util.ts +175 -0
- package/src/brand-page-maker/utils/rte-clipboard.util.test.ts +558 -0
- package/src/brand-page-maker/utils/rte-clipboard.util.ts +473 -0
- package/src/brand-page-maker/utils/rte-features.test.ts +99 -3
- package/src/brand-page-maker/utils/rte-render-parity.test.ts +1 -1
- package/src/brand-page-maker/utils/rte-render.util.test.ts +230 -0
- package/src/brand-page-maker/utils/rte-sanitize-json.test.ts +1 -1
- package/src/brand-page-maker/utils/rte-sanitize.util.ts +14 -3
- package/src/brand-page-maker/utils/rte-schema-version.test.ts +102 -0
- package/src/bundles/bundled-translations.de-DE.json +21 -2
- package/src/bundles/bundled-translations.es-ES.json +21 -2
- package/src/bundles/bundled-translations.fr-CA.json +21 -2
- package/src/bundles/bundled-translations.fr-FR.json +21 -2
- package/src/bundles/bundled-translations.json +21 -2
- package/src/bundles/bundled-translations.pt-BR.json +21 -2
- package/src/bundles/bundled-translations.pt-PT.json +21 -2
- package/src/clients/ai-assistant-client.ts +1 -0
- package/src/composables/useTranslate.ts +2 -1
- package/src/lib.ts +2 -2
- package/src/metadata-builder/builders/footer-builder.test.ts +70 -45
- package/src/metadata-builder/builders/footer-builder.ts +4 -8
- package/src/metadata-builder/builders/global-role-propagation.test.ts +907 -0
- package/src/metadata-builder/builders/global-role-propagation.ts +430 -0
- package/src/metadata-builder/builders/global-styles-builder.test.ts +1020 -0
- package/src/metadata-builder/builders/global-styles-builder.ts +194 -48
- package/src/metadata-builder/builders/header-builder.test.ts +112 -40
- package/src/metadata-builder/builders/header-builder.ts +18 -8
- package/src/metadata-builder/builders/section-builders/about-section-builder.ts +5 -3
- package/src/metadata-builder/builders/section-builders/banner-section-builder.ts +5 -3
- package/src/metadata-builder/builders/section-builders/booking-section-builder.ts +5 -3
- package/src/metadata-builder/builders/section-builders/contact-form-builder.ts +7 -4
- package/src/metadata-builder/builders/section-builders/images-section-builder.ts +5 -3
- package/src/metadata-builder/builders/section-builders/mailing-list-builder.ts +3 -2
- package/src/metadata-builder/builders/section-builders/mailing-list-section-builder.ts +3 -2
- package/src/metadata-builder/builders/section-builders/profile-section-builder.ts +7 -7
- package/src/metadata-builder/builders/section-builders/shapes-section-builder.ts +5 -3
- package/src/metadata-builder/builders/section-builders/social-links-builder.test.ts +2 -2
- package/src/metadata-builder/builders/section-builders/social-links-builder.ts +21 -10
- package/src/metadata-builder/builders/section-builders/support-me-builder.test.ts +10 -0
- package/src/metadata-builder/builders/section-builders/testimonial-section-builder.ts +3 -2
- package/src/metadata-builder/builders/section-builders/text-section-builder.ts +111 -61
- package/src/metadata-builder/builders/section-field-maps.ts +1 -0
- package/src/metadata-builder/builders/section-field-utils.test.ts +545 -2
- package/src/metadata-builder/builders/section-field-utils.ts +202 -69
- package/src/metadata-builder/builders/section-rules/global-styles.rules.ts +38 -13
- package/src/metadata-builder/builders/section-rules/social-links.rules.ts +5 -0
- package/src/metadata-builder/helpers/rte.helpers.test.ts +101 -0
- package/src/metadata-builder/helpers/rte.helpers.ts +129 -43
- package/src/metadata-builder/metadata-executor.test.ts +167 -0
- package/src/metadata-builder/metadata-executor.ts +34 -1
- package/src/metadata-builder/models.ts +2 -0
- package/src/metadata-builder/parsers/ai-toolcall-parser.ts +23 -7
- package/src/metadata-builder/parsers/section-tool-arguments.ts +21 -1
- package/src/metadata-builder/sanitizers/__tests__/section-args-validator.test.ts +215 -0
- package/src/metadata-builder/sanitizers/rte-schema-check.ts +1 -1
- package/src/metadata-builder/sanitizers/sanitizer-rules.ts +4 -8
- package/src/metadata-builder/sanitizers/section-args-validator.ts +136 -53
- package/src/shared/color-palette/section-color-matches.test.ts +15 -11
- package/src/shared/color-palette/section-color-matches.ts +9 -28
- package/src/shared/color-strategies/color-strategies.ts +35 -0
- package/src/shared/color-strategies/rte-color.test.ts +1 -1
- package/src/shared/color-strategies/rte-color.ts +19 -0
- package/src/shared/color-strategies/rte-field-pairs.test.ts +26 -5
- package/src/shared/color-strategies/rte-field-pairs.ts +33 -0
- package/src/shared/content-settings/components/color-matches-panel/ColorMatchesPanel.test.ts +43 -66
- package/src/shared/content-settings/components/color-matches-panel/ColorMatchesPanel.vue +7 -1
- package/src/shared/content-settings/components/content-settings/ContentSettings.mixin.ts +1 -48
- package/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.ts +33 -7
- package/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.test.ts +128 -1
- package/src/shared/content-settings/components/draggable-item-list/DraggableItemList.vue +1 -0
- package/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.ts +0 -6
- package/src/shared/content-settings/components/logo-selection-field/LogoSelection.vue +3 -0
- package/src/shared/content-settings/components/logo-size-field/LogoSizeSlider.vue +3 -0
- package/src/shared/content-settings/components/logo-size-field/LogoSizeSliderField.vue +1 -0
- package/src/shared/content-settings/components/testimonial-items-field/TestimonialItemsField.vue +1 -0
- package/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.test.ts +56 -3
- package/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.ts +11 -4
- package/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.test.ts +335 -25
- package/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.ts +248 -70
- package/src/shared/content-settings/components/text-style-field/TextStyleField.vue +113 -25
- package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.de-DE.json +17 -10
- package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.es-ES.json +17 -10
- package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.fr-CA.json +17 -10
- package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.fr-FR.json +17 -10
- package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.json +8 -1
- package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.pt-BR.json +17 -10
- package/src/shared/content-settings/components/text-style-field/i18n/text-style-field.pt-PT.json +17 -10
- package/src/shared/content-settings/components/text-style-role-dropdown/TextStyleRoleDropdown.test.ts +141 -0
- package/src/shared/content-settings/components/text-style-role-dropdown/TextStyleRoleDropdown.vue +136 -0
- package/src/shared/content-settings/store/content-settings-store.test.ts +491 -6
- package/src/shared/content-settings/store/content-settings-store.ts +159 -17
- package/src/shared/logo-settings/components/EditLogoSettings.vue +1 -0
- package/src/shared/logo-settings/components/LogoVariations.vue +1 -0
- package/src/shared/navigation-style-settings/components/navigation-style-settings/NavigationStyleSettings.vue +1 -0
- package/src/shared/navigation-style-settings/store/index.test.ts +295 -0
- package/src/shared/navigation-style-settings/store/index.ts +65 -15
- package/src/shared/page-settings/components/header-settings-panel/HeaderSettingsPanel.vue +2 -0
- package/src/shared/page-settings/components/page-settings/PageElement.vue +1 -0
- package/src/shared/page-settings/components/page-settings-section-styles/HeaderButtonSettings.test.ts +44 -4
- package/src/shared/page-settings/components/page-settings-section-styles/HeaderButtonSettings.vue +13 -4
- package/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.navigation.test.ts +89 -0
- package/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.text-style.test.ts +91 -0
- package/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.ts +14 -2
- package/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.vue +2 -0
- package/src/shared/page-settings/store/page-settings-store.text-style.test.ts +84 -0
- package/src/shared/page-settings/store/page-settings-store.ts +30 -1
- package/src/shared/rte-extensions/AutoLink.test.ts +98 -0
- package/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/AutoLink.ts +87 -58
- package/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/MaxLength.ts +4 -1
- package/src/shared/rte-extensions/TextEffects.ts +151 -0
- package/src/shared/rte-extensions/ViewDomParser.ts +27 -0
- package/src/{brand-page-maker/composables/rich-text-editor/getRteExtensions.ts → shared/rte-extensions.util.ts} +66 -9
- package/src/shared/rte-link.util.ts +2 -0
- package/src/shared/rte-render.util.ts +385 -0
- package/src/shared/rte-shape.util.ts +29 -0
- package/src/shared/side-bar/store/side-bar-store.test.ts +27 -1
- package/src/shared/side-bar/store/side-bar-store.ts +11 -0
- package/src/shared/style-settings/components/StyleSettings.mixin.ts +7 -3
- package/src/shared/style-settings/components/StyleSettings.test.ts +116 -0
- package/src/shared/style-settings/components/StyleSettings.vue +75 -25
- package/src/shared/style-settings/components/i18n/style-settings.de-DE.json +32 -20
- package/src/shared/style-settings/components/i18n/style-settings.es-ES.json +32 -20
- package/src/shared/style-settings/components/i18n/style-settings.fr-CA.json +32 -20
- package/src/shared/style-settings/components/i18n/style-settings.fr-FR.json +32 -20
- package/src/shared/style-settings/components/i18n/style-settings.json +13 -3
- package/src/shared/style-settings/components/i18n/style-settings.pt-BR.json +32 -20
- package/src/shared/style-settings/components/i18n/style-settings.pt-PT.json +32 -20
- package/src/shared/style-settings/components/text-style-options-settings-with-state/TextStyleOptionsSettingsWithState.vue +14 -34
- package/src/shared/style-settings/store/style-settings-store.ts +3 -49
- package/src/shared/style-settings/text-style-size-order.test.ts +76 -0
- package/src/shared/style-settings/text-style-size-order.ts +28 -0
- package/src/shared/template-settings/components/TemplatesSettings.vue +4 -0
- package/src/shared/text-role-typography.util.ts +277 -0
- package/src/utils/minify-brand-page-metadata.test.ts +102 -7
- package/src/utils/minify-brand-page-metadata.ts +62 -8
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/AutoLink.d.ts +0 -2
- package/lib/src/brand-page-maker/composables/rich-text-editor/getRteExtensions.d.ts +0 -28
- package/lib/src/brand-page-maker/utils/rte-render.util.d.ts +0 -63
- package/lib/src/brand-page-maker/utils/rte-render.util.js +0 -106
- package/lib/src/brand-page-maker/utils/rte-shape.d.ts +0 -18
- package/lib/src/brand-page-maker/utils/rte-shape.js +0 -21
- package/lib/src/metadata-builder/builders/global-font-propagation.d.ts +0 -41
- package/lib/src/metadata-builder/builders/global-font-propagation.js +0 -146
- package/src/brand-page-maker/utils/rte-render.util.ts +0 -179
- package/src/brand-page-maker/utils/rte-shape.ts +0 -29
- package/src/metadata-builder/builders/global-font-propagation.test.ts +0 -401
- package/src/metadata-builder/builders/global-font-propagation.ts +0 -238
- package/src/shared/style-settings/components/StyleSettingsSection.vue +0 -8
- /package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/FontFamily.d.ts +0 -0
- /package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/FontFamily.js +0 -0
- /package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/LetterSpacing.d.ts +0 -0
- /package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/LetterSpacing.js +0 -0
- /package/lib/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/MaxLength.d.ts +0 -0
- /package/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/FontFamily.ts +0 -0
- /package/src/{brand-page-maker/composables/rich-text-editor/extensions → shared/rte-extensions}/LetterSpacing.ts +0 -0
|
@@ -1,20 +1,28 @@
|
|
|
1
1
|
import { onBeforeUnmount, computed, watch, } from 'vue';
|
|
2
2
|
import { Editor } from '@tiptap/vue-3';
|
|
3
|
-
import { getRteExtensions } from '
|
|
3
|
+
import { getRteExtensions } from '@shared/rte-extensions.util';
|
|
4
|
+
import { KeepMarksOnEmpty, keepMarksOnEmptyPluginKey, } from './keepMarksOnEmpty';
|
|
5
|
+
import { RoleTypographyFill } from './extensions/RoleTypographyFill';
|
|
6
|
+
import { RteClipboard } from './extensions/RteClipboard';
|
|
4
7
|
import { createFormattingActions } from './formatting';
|
|
5
8
|
import { useTextAlign } from './textAlign';
|
|
6
9
|
import { useFont } from './font';
|
|
7
10
|
import { useSpacing } from './spacing';
|
|
8
|
-
import { buildInitialMarks, emToPx, isSameRteContent,
|
|
11
|
+
import { buildInitialMarks, emToPx, isSameRteContent, sanitizeRteJson, skipStyleDetection, } from '@brand-page-maker/utils';
|
|
9
12
|
import { HYPERLINK_TYPE, } from '@brand-page';
|
|
10
13
|
import { letterSpacingValueConvertor } from '@brand-page-maker/convertors';
|
|
11
14
|
import { useUiContentSettingsStore } from '@shared/content-settings/store';
|
|
15
|
+
import { useUiStyleSettingsStore } from '@shared/style-settings/store';
|
|
12
16
|
import { useHistoryStore } from '@brand-page-maker/stores/history/history-store';
|
|
13
17
|
import { AllSelection } from 'prosemirror-state';
|
|
18
|
+
import { useUiColorPaletteStore } from '@shared/color-palette/store';
|
|
14
19
|
import { useHyperlink } from './hyperlink';
|
|
15
20
|
import { useBubbleMenu } from './bubbleMenu';
|
|
16
|
-
import { hasLogoColorVar,
|
|
21
|
+
import { hasLogoColorVar, getToolbarColorFromMark, resolveInitialToolbarTextColor, hasRunTypographyOverride, isCanonicalLinked, isRoleVarRef, mergePickedMarks, normTypographyValue, readBlockTypography, relinkRoleEqualRunsChain, relinkTypographyChain, } from '@brand-page-maker/utils/rich-text-editor.util';
|
|
22
|
+
import { composeTextDecoration } from '@shared/text-role-typography.util';
|
|
17
23
|
import { useEventTracker, EVENTS } from '../useEventTracker';
|
|
24
|
+
// Outlasts the slowest debounced toolbar command (spacing, 300 ms). See undo-redo.md.
|
|
25
|
+
const USER_COMMAND_WINDOW_MS = 1000;
|
|
18
26
|
export const useExternalRichTextEditor = () => {
|
|
19
27
|
const externalEditor = new Editor({
|
|
20
28
|
editable: false,
|
|
@@ -25,19 +33,76 @@ export const useExternalRichTextEditor = () => {
|
|
|
25
33
|
};
|
|
26
34
|
};
|
|
27
35
|
export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDropdownRef,
|
|
28
|
-
//
|
|
36
|
+
// The selected role's entry of `textStyleOptions`.
|
|
29
37
|
selectedGlobalTextStyles, onSelectTextStyleType, updateRichTextEditor, textStyleTypeOptions, markedText, isHyperlinkPopupOpen, selectedLinkTypeValue) => {
|
|
30
38
|
const historyStore = useHistoryStore();
|
|
39
|
+
const colorPaletteStore = useUiColorPaletteStore();
|
|
40
|
+
// A toolbar click moves focus off the editor before its command runs (Tiptap's `.focus()` restores
|
|
41
|
+
// it a frame later), so `isFocused` alone would file the user's edit as a mount write-back.
|
|
42
|
+
let userCommandUntil = 0;
|
|
43
|
+
const markUserCommand = () => {
|
|
44
|
+
userCommandUntil = Date.now() + USER_COMMAND_WINDOW_MS;
|
|
45
|
+
};
|
|
46
|
+
// The linked role's style for the var-or-literal write rule (BP-5969): a canonical-linked
|
|
47
|
+
// block resolves typography from its role, so a toolbar pick equal to the role is stored as
|
|
48
|
+
// the role var, not a literal. Undefined for legacy/unlinked blocks (they bake literals).
|
|
49
|
+
// Declared above the editor so RteClipboard's getContext (below) can close over it too.
|
|
50
|
+
const getRoleStyle = () => isCanonicalLinked(props.styles)
|
|
51
|
+
? selectedGlobalTextStyles.value?.style
|
|
52
|
+
: undefined;
|
|
53
|
+
// The first-type seed a genuinely fresh field takes, or the previous run's marks when the
|
|
54
|
+
// field was just cleared (KeepMarksOnEmpty's capture) — shared by `beforeinput` below and
|
|
55
|
+
// RteClipboard's text-only paste into an empty field, so a paste matches typing.
|
|
56
|
+
const getFirstInputMarks = (state) => {
|
|
57
|
+
const clearedMarks = keepMarksOnEmptyPluginKey.getState(state);
|
|
58
|
+
const pickedMarks = state.storedMarks;
|
|
59
|
+
if (clearedMarks && clearedMarks.length > 0) {
|
|
60
|
+
return mergePickedMarks(clearedMarks, pickedMarks);
|
|
61
|
+
}
|
|
62
|
+
const globalStyle = selectedGlobalTextStyles.value?.style;
|
|
63
|
+
// Element-first colour: see the matching comment in `beforeinput` below.
|
|
64
|
+
const styleSource = globalStyle
|
|
65
|
+
? { ...globalStyle, color: props.styles?.color }
|
|
66
|
+
: props.styles;
|
|
67
|
+
const marks = buildInitialMarks(state, styleSource, !isCanonicalLinked(props.styles));
|
|
68
|
+
return mergePickedMarks(marks, pickedMarks);
|
|
69
|
+
};
|
|
31
70
|
const editor = new Editor({
|
|
32
71
|
content: model.value ?? '',
|
|
33
72
|
editable: !props.readOnly,
|
|
34
|
-
extensions:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
73
|
+
extensions: [
|
|
74
|
+
...getRteExtensions({
|
|
75
|
+
restrictStarterKit: true,
|
|
76
|
+
editing: {
|
|
77
|
+
placeholder: props.placeholder,
|
|
78
|
+
maxLength: props.maxLength,
|
|
79
|
+
},
|
|
80
|
+
}),
|
|
81
|
+
// Captures a cleared run's marks so the first-type seed below can restore the
|
|
82
|
+
// style on retype (rather than reseeding from the role).
|
|
83
|
+
KeepMarksOnEmpty,
|
|
84
|
+
RoleTypographyFill.configure({
|
|
85
|
+
getFillSource: () => {
|
|
86
|
+
const role = isCanonicalLinked(props.styles)
|
|
87
|
+
? selectedGlobalTextStyles.value?.style
|
|
88
|
+
: undefined;
|
|
89
|
+
return role
|
|
90
|
+
? {
|
|
91
|
+
role: role,
|
|
92
|
+
block: props.styles,
|
|
93
|
+
}
|
|
94
|
+
: undefined;
|
|
95
|
+
},
|
|
96
|
+
}),
|
|
97
|
+
RteClipboard.configure({
|
|
98
|
+
getContext: () => ({
|
|
99
|
+
role: getRoleStyle(),
|
|
100
|
+
block: props.styles,
|
|
101
|
+
colors: colorPaletteStore.colors,
|
|
102
|
+
}),
|
|
103
|
+
getFirstInputMarks,
|
|
104
|
+
}),
|
|
105
|
+
],
|
|
41
106
|
editorProps: {
|
|
42
107
|
handleDOMEvents: {
|
|
43
108
|
drop(view, event) {
|
|
@@ -46,86 +111,19 @@ selectedGlobalTextStyles, onSelectTextStyleType, updateRichTextEditor, textStyle
|
|
|
46
111
|
},
|
|
47
112
|
beforeinput(view, event) {
|
|
48
113
|
const { state } = view;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const globalStyle = selectedGlobalTextStyles.value?.style;
|
|
53
|
-
// Element-first colour: once the doc is emptied, freshly-typed text must
|
|
54
|
-
// inherit a linked element's colour override (a creation-time contrast bake,
|
|
55
|
-
// or a colour picked while linked), not the linked global colour. Typography
|
|
56
|
-
// still comes from the global style (the element is linked), mirroring
|
|
57
|
-
// resolveTextColor's colour-only cascade.
|
|
58
|
-
const styleSource = globalStyle
|
|
59
|
-
? {
|
|
60
|
-
...globalStyle,
|
|
61
|
-
color: props.styles?.color || globalStyle.color,
|
|
62
|
-
}
|
|
63
|
-
: props.styles;
|
|
64
|
-
const marks = buildInitialMarks(state, styleSource);
|
|
65
|
-
const chain = editor.chain();
|
|
66
|
-
if (props.styles.textAlign)
|
|
67
|
-
chain.setTextAlign(props.styles.textAlign);
|
|
68
|
-
skipStyleDetection(chain, marks).run();
|
|
114
|
+
if (event.inputType !== 'insertText' ||
|
|
115
|
+
state.doc.textContent !== '') {
|
|
116
|
+
return false;
|
|
69
117
|
}
|
|
118
|
+
const chain = editor.chain();
|
|
119
|
+
// textAlign is a block-node attr, not a mark, and a full clear resets it — so
|
|
120
|
+
// re-apply the element's alignment regardless of which seed `getFirstInputMarks`
|
|
121
|
+
// takes below (it's the one thing that survives a full clear).
|
|
122
|
+
if (props.styles.textAlign)
|
|
123
|
+
chain.setTextAlign(props.styles.textAlign);
|
|
124
|
+
skipStyleDetection(chain, getFirstInputMarks(state)).run();
|
|
70
125
|
return false;
|
|
71
126
|
},
|
|
72
|
-
copy(view, event) {
|
|
73
|
-
const selection = view.state.selection;
|
|
74
|
-
if (selection.empty)
|
|
75
|
-
return;
|
|
76
|
-
const data = event.clipboardData;
|
|
77
|
-
const styleData = JSON.stringify(props.styles);
|
|
78
|
-
const slice = selection.content(), { dom, text } = view.serializeForClipboard(slice);
|
|
79
|
-
if (data) {
|
|
80
|
-
event.preventDefault();
|
|
81
|
-
data.clearData();
|
|
82
|
-
data.setData('text/html', dom.innerHTML);
|
|
83
|
-
data.setData('text/plain', text);
|
|
84
|
-
if (styleData)
|
|
85
|
-
data.setData('application/x-rte-styles', styleData);
|
|
86
|
-
}
|
|
87
|
-
return true;
|
|
88
|
-
},
|
|
89
|
-
paste(view, event) {
|
|
90
|
-
// Unified paste handler: strip styles if no styleData, enforce maxLength, handle selection
|
|
91
|
-
const styleData = event.clipboardData?.getData('application/x-rte-styles');
|
|
92
|
-
const pastedText = event.clipboardData?.getData('text/plain') || '';
|
|
93
|
-
const { state, dispatch } = view;
|
|
94
|
-
const { from, to } = state.selection;
|
|
95
|
-
let tr = state.tr;
|
|
96
|
-
if (styleData) {
|
|
97
|
-
try {
|
|
98
|
-
const pastedStyles = JSON.parse(styleData);
|
|
99
|
-
const fontStyleChanges = {
|
|
100
|
-
color: pastedStyles.color,
|
|
101
|
-
fontFamily: pastedStyles.fontFamily,
|
|
102
|
-
fontSize: pastedStyles.fontSize,
|
|
103
|
-
fontWeight: pastedStyles.fontWeight,
|
|
104
|
-
fontStyle: pastedStyles.fontStyle,
|
|
105
|
-
textDecoration: pastedStyles.textDecoration,
|
|
106
|
-
lineHeight: pastedStyles.lineHeight,
|
|
107
|
-
letterSpacing: pastedStyles.letterSpacing,
|
|
108
|
-
textAlign: pastedStyles.textAlign,
|
|
109
|
-
backgroundColor: pastedStyles.backgroundColor,
|
|
110
|
-
textStyleType: undefined,
|
|
111
|
-
};
|
|
112
|
-
syncContentSettings(fontStyleChanges);
|
|
113
|
-
return false;
|
|
114
|
-
}
|
|
115
|
-
catch {
|
|
116
|
-
// ignore malformed styleData
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
120
|
-
event.preventDefault();
|
|
121
|
-
tr.delete(from, to);
|
|
122
|
-
const createdMarks = buildInitialMarks(state, props.styles);
|
|
123
|
-
tr = tr.setStoredMarks(createdMarks).insertText(pastedText, from);
|
|
124
|
-
onSelectTextStyleType({ label: 'None' });
|
|
125
|
-
}
|
|
126
|
-
dispatch(tr);
|
|
127
|
-
return true;
|
|
128
|
-
},
|
|
129
127
|
click(view, event) {
|
|
130
128
|
if (isHyperlinkPopupOpen?.value)
|
|
131
129
|
return false;
|
|
@@ -145,11 +143,26 @@ selectedGlobalTextStyles, onSelectTextStyleType, updateRichTextEditor, textStyle
|
|
|
145
143
|
},
|
|
146
144
|
});
|
|
147
145
|
const contentSettingStore = useUiContentSettingsStore();
|
|
146
|
+
const styleSettingsStore = useUiStyleSettingsStore();
|
|
148
147
|
const eventTracker = useEventTracker();
|
|
149
|
-
const { toggleBold, toggleItalic, toggleUnderline, toggleStrike, toggleTextColor, toggleBackgroundColor,
|
|
148
|
+
const { toggleBold, toggleItalic, toggleUnderline, toggleStrike, toggleTextColor, toggleBackgroundColor, boldActive, italicActive, underlineActive, strikeActive, } = createFormattingActions(editor, getRoleStyle, () => props.styles);
|
|
150
149
|
const { currentAlignment, toggleTextAlign, idx: currentAlignmentIndex, keys: alignmentKeys, } = useTextAlign(editor);
|
|
151
|
-
const { selectedFont, toggleFont, toggleFontSize
|
|
152
|
-
const { letterSpacingValue, lineHeightValue, letterSpacing, lineHeight, setLetterSpaceAll, setLineHeightAll, } = useSpacing(editor);
|
|
150
|
+
const { selectedFont, toggleFont, toggleFontSize } = useFont(editor, fontSettings, fontStyleDropdownRef, getRoleStyle);
|
|
151
|
+
const { letterSpacingValue: letterSpacingSlider, lineHeightValue: lineHeightSlider, letterSpacing, lineHeight, setLetterSpaceAll, setLineHeightAll, } = useSpacing(editor, getRoleStyle);
|
|
152
|
+
const letterSpacingValue = computed({
|
|
153
|
+
get: () => letterSpacingSlider.value,
|
|
154
|
+
set: (value) => {
|
|
155
|
+
markUserCommand();
|
|
156
|
+
letterSpacingSlider.value = value;
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
const lineHeightValue = computed({
|
|
160
|
+
get: () => lineHeightSlider.value,
|
|
161
|
+
set: (value) => {
|
|
162
|
+
markUserCommand();
|
|
163
|
+
lineHeightSlider.value = value;
|
|
164
|
+
},
|
|
165
|
+
});
|
|
153
166
|
const { hyperlinkValue, setHyperlinkUrl, setHyperlinkUrlValue, removeHyperlink: removeHyperlinkFromComposable, applyHyperlinkToEditor, } = useHyperlink(editor);
|
|
154
167
|
const { shouldShow, bubbleMenuOptions } = useBubbleMenu(editor, isHyperlinkPopupOpen);
|
|
155
168
|
watch(() => props.styles.textAlign, (newAlignment) => {
|
|
@@ -190,44 +203,95 @@ selectedGlobalTextStyles, onSelectTextStyleType, updateRichTextEditor, textStyle
|
|
|
190
203
|
});
|
|
191
204
|
}
|
|
192
205
|
});
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
206
|
+
// BP-5969 (ADR-0019): the auto-detach that cleared `textStyleType` whenever the doc's
|
|
207
|
+
// style changed is gone — a style edit is now a per-run mark and the block keeps its
|
|
208
|
+
// role. (Was: `editor.on('transaction')` → `onSelectTextStyleType('None')`.)
|
|
209
|
+
// Refresh the B/I/U/S button state from the effective formatting (textStyle attr, resolved
|
|
210
|
+
// against the role, OR a legacy semantic mark). It runs on every transaction: a format picked with
|
|
211
|
+
// nothing selected only sets a stored mark, which fires neither `update` nor `selectionUpdate`.
|
|
212
|
+
const syncFormattingActiveState = () => {
|
|
213
|
+
fontSettings.isBold = boldActive();
|
|
214
|
+
fontSettings.isItalic = italicActive();
|
|
215
|
+
fontSettings.isUnderline = underlineActive();
|
|
216
|
+
fontSettings.isStrike = strikeActive();
|
|
217
|
+
};
|
|
218
|
+
// Skipped while a history snapshot applies, as `selectionUpdate` is (BP-5506).
|
|
219
|
+
editor.on('transaction', () => {
|
|
220
|
+
if (historyStore.isApplyingSnapshot)
|
|
199
221
|
return;
|
|
200
|
-
|
|
201
|
-
if (isStyleChanged(transaction) && props.styles.textStyleType) {
|
|
202
|
-
onSelectTextStyleType({
|
|
203
|
-
label: 'None',
|
|
204
|
-
});
|
|
205
|
-
}
|
|
222
|
+
syncFormattingActiveState();
|
|
206
223
|
});
|
|
224
|
+
// A role edit (Style tab, AI) reaches the editor without a transaction. An empty one repaints
|
|
225
|
+
// the B/I/U/S state and the box's role fill (`RoleTypographyFill`) without touching the doc.
|
|
226
|
+
watch(() => selectedGlobalTextStyles.value?.style, () => {
|
|
227
|
+
if (editor.isDestroyed)
|
|
228
|
+
return;
|
|
229
|
+
editor.view.dispatch(editor.state.tr.setMeta('addToHistory', false));
|
|
230
|
+
}, { deep: true });
|
|
207
231
|
// Update model when editor content changes. RTE content is stored as Tiptap
|
|
208
232
|
// JSON (BP-5787). getJSON() is already in hand (the editor holds the doc) and
|
|
209
233
|
// is sanitised natively — no getHTML(), no DOMPurify, no extra editor — so
|
|
210
234
|
// the per-keystroke path allocates nothing heavy.
|
|
211
235
|
editor.on('update', () => {
|
|
212
|
-
// An update fired while the editor is unfocused is
|
|
213
|
-
// model
|
|
214
|
-
// programmatic setContent — not a user edit. Tag the emit so the write
|
|
215
|
-
//
|
|
216
|
-
//
|
|
217
|
-
//
|
|
218
|
-
//
|
|
219
|
-
// debounce fires. Genuine edits happen while focused and commit
|
|
220
|
-
// normally.
|
|
221
|
-
//
|
|
222
|
-
// Known limitation: a programmatic toolbar command run on an editor the
|
|
223
|
-
// user hasn't focused yet would also merge (losing that undo step). Today
|
|
224
|
-
// the RTE only mounts inside an already-open settings drawer and the user
|
|
225
|
-
// focuses it before formatting, so this doesn't occur — revisit if a
|
|
226
|
-
// consumer ever drives toolbar actions on an unfocused editor.
|
|
236
|
+
// An update fired while the editor is unfocused and no toolbar command is in flight is
|
|
237
|
+
// TipTap rewriting the model into its canonical form during mount rehydration or a
|
|
238
|
+
// programmatic setContent — not a user edit. Tag the emit so the write folds into the
|
|
239
|
+
// current undo head instead of pushing a phantom entry (BP-5810). The flag travels WITH
|
|
240
|
+
// the value through the debounced field → store chain and arms the history merge at the
|
|
241
|
+
// moment of the store write — arming here at emit time would lapse before the debounce
|
|
242
|
+
// fires. Typing (focused) and toolbar commands (`markUserCommand`) commit normally.
|
|
227
243
|
emit('update:modelValue', sanitizeRteJson(editor.getJSON()), {
|
|
228
|
-
isHydrationWrite: !editor.isFocused,
|
|
244
|
+
isHydrationWrite: !editor.isFocused && Date.now() > userCommandUntil,
|
|
229
245
|
});
|
|
230
246
|
});
|
|
247
|
+
// The toolbar's read of the editor at the cursor: a mark holding a role var (or no mark) shows the
|
|
248
|
+
// linked role's value, a literal shows itself. Colours fall back to the given values when the run
|
|
249
|
+
// has none, so the mount-time seed can pass the element colour it resolved.
|
|
250
|
+
const syncToolbarFromEditor = ({ textColorFallback = '#000000', backgroundColorFallback = 'transparent', } = {}) => {
|
|
251
|
+
const textStyleAttributes = editor.getAttributes('textStyle');
|
|
252
|
+
const highlightAttributes = editor.getAttributes('highlight');
|
|
253
|
+
const focusedAlignment = editor.getAttributes(editor.state.selection.$anchor.node().type.name);
|
|
254
|
+
const roleStyle = getRoleStyle();
|
|
255
|
+
const markFontFamily = textStyleAttributes?.fontFamily;
|
|
256
|
+
const displayFont = markFontFamily && !isRoleVarRef(markFontFamily)
|
|
257
|
+
? markFontFamily.replace(/^['"]|['"]$/g, '')
|
|
258
|
+
: (roleStyle?.fontFamily ?? 'Lato');
|
|
259
|
+
selectedFont.value = displayFont;
|
|
260
|
+
fontSettings.selectedFont = displayFont;
|
|
261
|
+
const markFontSize = textStyleAttributes?.fontSize;
|
|
262
|
+
const sizeSource = markFontSize && !isRoleVarRef(markFontSize)
|
|
263
|
+
? markFontSize
|
|
264
|
+
: (roleStyle?.fontSize ?? fontSettings.selectedFontSize);
|
|
265
|
+
fontSettings.selectedFontSizePx = Math.ceil(parseFloat(emToPx(sizeSource)));
|
|
266
|
+
// A palette reference is kept verbatim (so ColorField can highlight the swatch); a literal is
|
|
267
|
+
// hex-normalised — Color().hex() throws on a var(), so the split lives in getToolbarColorFromMark.
|
|
268
|
+
fontSettings.selectedTextColor = getToolbarColorFromMark(textStyleAttributes?.color, textColorFallback);
|
|
269
|
+
fontSettings.selectedBackgroundColor = getToolbarColorFromMark(highlightAttributes?.color, backgroundColorFallback);
|
|
270
|
+
syncFormattingActiveState();
|
|
271
|
+
const markLineHeight = textStyleAttributes.lineHeight;
|
|
272
|
+
lineHeight.value =
|
|
273
|
+
markLineHeight && !isRoleVarRef(markLineHeight)
|
|
274
|
+
? markLineHeight
|
|
275
|
+
: (roleStyle?.lineHeight ?? '1');
|
|
276
|
+
const markLetterSpacing = textStyleAttributes?.letterSpacing;
|
|
277
|
+
const letterSpacingSource = markLetterSpacing && !isRoleVarRef(markLetterSpacing)
|
|
278
|
+
? markLetterSpacing
|
|
279
|
+
: roleStyle?.letterSpacing;
|
|
280
|
+
letterSpacing.value = letterSpacingSource
|
|
281
|
+
? letterSpacingValueConvertor.convert({
|
|
282
|
+
letterSpacing: letterSpacingSource,
|
|
283
|
+
})
|
|
284
|
+
: '0';
|
|
285
|
+
if (focusedAlignment && focusedAlignment.textAlign) {
|
|
286
|
+
const idx = alignmentKeys.indexOf(focusedAlignment.textAlign);
|
|
287
|
+
if (idx !== -1) {
|
|
288
|
+
currentAlignmentIndex.value = idx;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
currentAlignmentIndex.value = 0;
|
|
293
|
+
}
|
|
294
|
+
};
|
|
231
295
|
editor.on('selectionUpdate', () => {
|
|
232
296
|
// Skip while a history snapshot is being applied — `setContent` fires
|
|
233
297
|
// selectionUpdate before the editor has fully rehydrated, which causes
|
|
@@ -236,9 +300,6 @@ selectedGlobalTextStyles, onSelectTextStyleType, updateRichTextEditor, textStyle
|
|
|
236
300
|
// after apply completes, which lands the correct values (BP-5506).
|
|
237
301
|
if (historyStore.isApplyingSnapshot)
|
|
238
302
|
return;
|
|
239
|
-
const textStyleAttributes = editor.getAttributes('textStyle');
|
|
240
|
-
const highlightAttributes = editor.getAttributes('highlight');
|
|
241
|
-
const focusedAlignment = editor.getAttributes(editor.state.selection.$anchor.node().type.name);
|
|
242
303
|
const selection = editor.state.selection;
|
|
243
304
|
if (selection instanceof AllSelection) {
|
|
244
305
|
// to prevent selecting editor state
|
|
@@ -250,54 +311,19 @@ selectedGlobalTextStyles, onSelectTextStyleType, updateRichTextEditor, textStyle
|
|
|
250
311
|
}
|
|
251
312
|
// TODO: resolve the issue of missing style on text between empty lines
|
|
252
313
|
// retainStyleOnEmptyLine(editor, selection);
|
|
253
|
-
|
|
254
|
-
const font = textStyleAttributes.fontFamily.replace(/^['"]|['"]$/g, '');
|
|
255
|
-
selectedFont.value = font;
|
|
256
|
-
fontSettings.selectedFont = font;
|
|
257
|
-
}
|
|
258
|
-
else {
|
|
259
|
-
selectedFont.value = 'Lato';
|
|
260
|
-
fontSettings.selectedFont = 'Lato';
|
|
261
|
-
}
|
|
262
|
-
if (textStyleAttributes && textStyleAttributes.fontSize) {
|
|
263
|
-
fontSettings.selectedFontSizePx = Math.ceil(parseFloat(emToPx(textStyleAttributes.fontSize)));
|
|
264
|
-
}
|
|
265
|
-
else {
|
|
266
|
-
fontSettings.selectedFontSizePx = Math.ceil(parseFloat(emToPx(fontSettings.selectedFontSize)));
|
|
267
|
-
}
|
|
268
|
-
// Reflect the active mark colour on the toolbar. A palette reference is kept
|
|
269
|
-
// verbatim (so ColorField can highlight the swatch); a literal is hex-normalised —
|
|
270
|
-
// Color().hex() throws on a var(), so the split lives in getToolbarColorFromMark.
|
|
271
|
-
fontSettings.selectedTextColor = getToolbarColorFromMark(textStyleAttributes?.color, '#000000');
|
|
272
|
-
fontSettings.selectedBackgroundColor = getToolbarColorFromMark(highlightAttributes?.color, 'transparent');
|
|
273
|
-
if (textStyleAttributes.lineHeight) {
|
|
274
|
-
lineHeight.value = textStyleAttributes.lineHeight;
|
|
275
|
-
}
|
|
276
|
-
else {
|
|
277
|
-
lineHeight.value = '1';
|
|
278
|
-
}
|
|
279
|
-
if (textStyleAttributes && textStyleAttributes.letterSpacing) {
|
|
280
|
-
letterSpacing.value = letterSpacingValueConvertor.convert({
|
|
281
|
-
letterSpacing: textStyleAttributes.letterSpacing,
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
else {
|
|
285
|
-
letterSpacing.value = '0';
|
|
286
|
-
}
|
|
287
|
-
if (focusedAlignment && focusedAlignment.textAlign) {
|
|
288
|
-
const idx = alignmentKeys.indexOf(focusedAlignment.textAlign);
|
|
289
|
-
if (idx !== -1) {
|
|
290
|
-
currentAlignmentIndex.value = idx;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
else {
|
|
294
|
-
currentAlignmentIndex.value = 0;
|
|
295
|
-
}
|
|
314
|
+
syncToolbarFromEditor();
|
|
296
315
|
});
|
|
297
316
|
const setInitialStyleSettings = (selectedTextStyle) => {
|
|
298
317
|
const globalStyles = selectedTextStyle ?? selectedGlobalTextStyles.value?.style;
|
|
299
318
|
const currentAlignment = editor.getAttributes(editor.state.selection.$anchor.node().type.name);
|
|
300
319
|
if (globalStyles) {
|
|
320
|
+
// A canonical-linked block inherits typography from the role CSS class and stores
|
|
321
|
+
// only its per-property OVERRIDES (BP-5969). Re-deriving the role's typography onto
|
|
322
|
+
// the element on every RTE mount clobbered those overrides — selecting a block
|
|
323
|
+
// reverted its title to the role font/size — so bake typography here only for
|
|
324
|
+
// legacy/unlinked blocks (which still carry the resolved style inline). Mirrors the
|
|
325
|
+
// isCanonicalLinked gate in buildInitialMarks / getUpdatedHTMLFromEditor.
|
|
326
|
+
const bakeTypography = !isCanonicalLinked(props.styles);
|
|
301
327
|
// sync content settings style — a mount-time re-derivation, not a user
|
|
302
328
|
// edit. Flag it so the store folds it into the current undo head: this
|
|
303
329
|
// write lands ~100ms BEFORE the editor's canonical text write-back, and
|
|
@@ -307,32 +333,39 @@ selectedGlobalTextStyles, onSelectTextStyleType, updateRichTextEditor, textStyle
|
|
|
307
333
|
id: props.rawId,
|
|
308
334
|
name: props.name,
|
|
309
335
|
value: {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
336
|
+
...(bakeTypography
|
|
337
|
+
? {
|
|
338
|
+
fontSize: globalStyles.fontSize,
|
|
339
|
+
fontFamily: globalStyles.fontFamily,
|
|
340
|
+
fontWeight: globalStyles.fontWeight,
|
|
341
|
+
fontStyle: globalStyles.fontStyle,
|
|
342
|
+
textDecoration: globalStyles.textDecoration,
|
|
343
|
+
lineHeight: globalStyles.lineHeight,
|
|
344
|
+
letterSpacing: globalStyles.letterSpacing,
|
|
345
|
+
}
|
|
346
|
+
: {}),
|
|
347
|
+
// The element's own colour override (a creation-time contrast bake, or a colour
|
|
348
|
+
// picked while linked). ADR-0020: the role carries no colour, so there is no
|
|
349
|
+
// global fallback — an uncoloured element renders the page base coat.
|
|
350
|
+
color: props.styles?.color,
|
|
323
351
|
},
|
|
324
352
|
isHydrationWrite: !editor.isFocused,
|
|
325
353
|
});
|
|
326
|
-
// sync toolbar editor styles
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
fontSettings.
|
|
354
|
+
// sync toolbar editor styles — show the block's EFFECTIVE typography (its override,
|
|
355
|
+
// else the linked role) so the toolbar matches the render, not the role blindly.
|
|
356
|
+
const effectiveFontSize = props.styles?.fontSize ?? globalStyles?.fontSize ?? '2.25em';
|
|
357
|
+
fontSettings.selectedFont =
|
|
358
|
+
props.styles?.fontFamily ?? globalStyles?.fontFamily ?? 'Lato';
|
|
359
|
+
fontSettings.selectedFontSize = effectiveFontSize;
|
|
360
|
+
fontSettings.selectedFontSizePx = Math.ceil(parseFloat(emToPx(effectiveFontSize)));
|
|
330
361
|
// For an RTE field the mark is the source of truth — the render and the focus-time
|
|
331
362
|
// `selectionUpdate` both paint from it — so seed the swatch from the mark's first
|
|
332
363
|
// coloured run, falling back to the element→global cascade. Otherwise the unfocused
|
|
333
364
|
// swatch shows the linked global while the text renders its baked frame/override
|
|
334
365
|
// colour, and only snaps to the right colour on focus (BP-5886).
|
|
335
|
-
|
|
366
|
+
// BP-5969 (ADR-0020): the role contributes no colour — seed the swatch from the RTE
|
|
367
|
+
// mark, else the element's own colour.
|
|
368
|
+
fontSettings.selectedTextColor = resolveInitialToolbarTextColor(model.value, props.styles?.color);
|
|
336
369
|
// A global text style has no backgroundColor, so this resolves to undefined there.
|
|
337
370
|
const backgroundColour = 'backgroundColor' in globalStyles
|
|
338
371
|
? globalStyles.backgroundColor
|
|
@@ -348,142 +381,78 @@ selectedGlobalTextStyles, onSelectTextStyleType, updateRichTextEditor, textStyle
|
|
|
348
381
|
currentAlignment?.textAlign !== props.styles.textAlign) {
|
|
349
382
|
toggleTextAlign(props.styles.textAlign);
|
|
350
383
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
fontSettings.selectedFontSizePx = Math.ceil(parseFloat(emToPx(props.styles?.fontSize ?? '2.25em')));
|
|
357
|
-
// No linked global (props.styles carries no textStyleType) — still resolve the RTE
|
|
358
|
-
// mark first, so a field whose colour lives only in its mark (e.g. the tipping/payment
|
|
359
|
-
// success message, which has no style object) shows it instead of collapsing to black.
|
|
360
|
-
fontSettings.selectedTextColor = resolveInitialToolbarTextColor(model.value, props.styles?.color);
|
|
361
|
-
fontSettings.selectedBackgroundColor = hasLogoColorVar(props.styles?.backgroundColor ?? '')
|
|
362
|
-
? 'transparent'
|
|
363
|
-
: (props.styles?.backgroundColor ?? 'transparent');
|
|
364
|
-
lineHeight.value = props.styles?.lineHeight?.includes('em')
|
|
365
|
-
? emToPx(props.styles?.lineHeight ?? '1em')
|
|
366
|
-
: (props.styles?.lineHeight ?? '1');
|
|
367
|
-
letterSpacing.value = letterSpacingValueConvertor.convert(props.styles ?? {});
|
|
368
|
-
if (props.styles?.textAlign &&
|
|
369
|
-
currentAlignment?.textAlign !== props.styles.textAlign) {
|
|
370
|
-
toggleTextAlign(props.styles.textAlign);
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
};
|
|
374
|
-
const copyGlobalStyleSettings = (selectedTextStyle) => {
|
|
375
|
-
const globalStyles = selectedTextStyle ?? selectedGlobalTextStyles.value?.style;
|
|
376
|
-
if (globalStyles) {
|
|
377
|
-
globalStyles.fontWeight === 'bold' && toggleBoldAll();
|
|
378
|
-
globalStyles.fontStyle && toggleItalicAll();
|
|
379
|
-
globalStyles.textDecoration?.includes('underline') &&
|
|
380
|
-
toggleUnderlineAll();
|
|
381
|
-
globalStyles.textDecoration?.includes('line-through') &&
|
|
382
|
-
toggleStrikeAll();
|
|
383
|
-
if (globalStyles.color) {
|
|
384
|
-
if (!hasLogoColorVar(globalStyles.color)) {
|
|
385
|
-
toggleTextColorAll(globalStyles.color);
|
|
386
|
-
fontSettings.selectedTextColor = globalStyles.color;
|
|
387
|
-
}
|
|
388
|
-
else {
|
|
389
|
-
// Apply logo color using CSS variable
|
|
390
|
-
toggleTextColorAll(getRTEColor(globalStyles.color, 'text'));
|
|
391
|
-
fontSettings.selectedTextColor = '#000000';
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
globalStyles.fontFamily && toggleFontAll(globalStyles.fontFamily);
|
|
395
|
-
globalStyles.fontSize && toggleFontSizeAll(globalStyles.fontSize);
|
|
396
|
-
globalStyles.lineHeight && setLineHeightAll(globalStyles.lineHeight);
|
|
397
|
-
globalStyles.letterSpacing &&
|
|
398
|
-
setLetterSpaceAll(globalStyles.letterSpacing);
|
|
399
|
-
props.styles.textAlign &&
|
|
400
|
-
toggleTextAlign(props.styles.textAlign ?? 'none');
|
|
384
|
+
// Show the runs' own values (the role, or a per-run override) before the first click.
|
|
385
|
+
syncToolbarFromEditor({
|
|
386
|
+
textColorFallback: fontSettings.selectedTextColor,
|
|
387
|
+
backgroundColorFallback: fontSettings.selectedBackgroundColor,
|
|
388
|
+
});
|
|
401
389
|
}
|
|
402
390
|
};
|
|
391
|
+
// BP-5969 (ADR-0019): a toolbar edit applies a TipTap mark ONLY. The old sync wrote
|
|
392
|
+
// the flattened style back onto the block object AND cleared its role link
|
|
393
|
+
// (`textStyleType: undefined`) — that dual source of truth is the "a per-run colour
|
|
394
|
+
// edit repaints the whole block / drops the role" bug class. Now per-run formatting
|
|
395
|
+
// lives on marks; the block stays linked; whole-box size/family are authored from the
|
|
396
|
+
// sidebar. Alignment is the one block-level toolbar action, so it still persists — but
|
|
397
|
+
// without detaching the role.
|
|
403
398
|
const triggerEditorStyleChange = (editorOption) => {
|
|
404
|
-
|
|
399
|
+
markUserCommand();
|
|
405
400
|
switch (editorOption.type) {
|
|
406
401
|
case 'fontFamily':
|
|
407
402
|
toggleFont(editorOption.value);
|
|
408
|
-
fontStyleChanges.fontFamily = editorOption.value;
|
|
409
403
|
break;
|
|
410
|
-
case 'fontSize':
|
|
404
|
+
case 'fontSize': {
|
|
411
405
|
const size = editorOption.value;
|
|
412
406
|
fontSettings.selectedFontSizePx = size.includes('em')
|
|
413
407
|
? Math.ceil(parseFloat(emToPx(size)))
|
|
414
408
|
: parseInt(size);
|
|
415
409
|
toggleFontSize(size);
|
|
416
|
-
fontStyleChanges.fontSize = size.includes('em') ? size : pxToEm(size);
|
|
417
410
|
break;
|
|
411
|
+
}
|
|
418
412
|
case 'fontWeight':
|
|
419
413
|
toggleBold();
|
|
420
|
-
editor.isActive('bold')
|
|
421
|
-
? (fontStyleChanges.fontWeight = 'bold')
|
|
422
|
-
: (fontStyleChanges.fontWeight = undefined);
|
|
423
414
|
break;
|
|
424
415
|
case 'fontStyle':
|
|
425
416
|
toggleItalic();
|
|
426
|
-
editor.isActive('italic')
|
|
427
|
-
? (fontStyleChanges.fontStyle = 'italic')
|
|
428
|
-
: (fontStyleChanges.fontStyle = undefined);
|
|
429
417
|
break;
|
|
430
418
|
case 'textDecorationLine':
|
|
431
419
|
toggleUnderline();
|
|
432
|
-
editor.isActive('underline')
|
|
433
|
-
? fontStyleChanges.textDecoration
|
|
434
|
-
? (fontStyleChanges.textDecoration =
|
|
435
|
-
fontStyleChanges.textDecoration + ' underline')
|
|
436
|
-
: (fontStyleChanges.textDecoration = 'underline')
|
|
437
|
-
: (fontStyleChanges.textDecoration =
|
|
438
|
-
fontStyleChanges.textDecoration?.replace('underline', ''));
|
|
439
420
|
break;
|
|
440
421
|
case 'textDecorationStrike':
|
|
441
422
|
toggleStrike();
|
|
442
|
-
editor.isActive('strike')
|
|
443
|
-
? fontStyleChanges.textDecoration
|
|
444
|
-
? (fontStyleChanges.textDecoration =
|
|
445
|
-
fontStyleChanges.textDecoration + ' line-through')
|
|
446
|
-
: (fontStyleChanges.textDecoration = 'line-through')
|
|
447
|
-
: (fontStyleChanges.textDecoration =
|
|
448
|
-
fontStyleChanges.textDecoration?.replace('line-through', ''));
|
|
449
423
|
break;
|
|
450
424
|
case 'textColor':
|
|
451
425
|
toggleTextColor(editorOption.value);
|
|
452
|
-
fontStyleChanges.color = editorOption.value;
|
|
453
426
|
break;
|
|
454
427
|
case 'backgroundColor':
|
|
455
428
|
toggleBackgroundColor(editorOption.value);
|
|
456
|
-
fontStyleChanges.backgroundColor = editorOption.value;
|
|
457
429
|
break;
|
|
458
430
|
case 'lineHeight':
|
|
459
431
|
setLineHeightAll(editorOption.value);
|
|
460
|
-
fontStyleChanges.lineHeight = editorOption.value;
|
|
461
432
|
break;
|
|
462
433
|
case 'letterSpacing':
|
|
463
434
|
setLetterSpaceAll(editorOption.value);
|
|
464
|
-
fontStyleChanges.letterSpacing = letterSpacingValueConvertor.convert({
|
|
465
|
-
letterSpacing: editorOption.value,
|
|
466
|
-
});
|
|
467
435
|
break;
|
|
468
436
|
case 'textAlign':
|
|
469
437
|
toggleTextAlign();
|
|
470
|
-
|
|
438
|
+
persistBlockTextAlign(currentAlignment.value.alignment);
|
|
471
439
|
break;
|
|
472
440
|
case 'hyperlink':
|
|
473
441
|
setHyperlinkUrl(editorOption.value);
|
|
474
442
|
break;
|
|
475
443
|
}
|
|
476
|
-
syncContentSettings(fontStyleChanges);
|
|
477
444
|
};
|
|
478
|
-
|
|
445
|
+
// Alignment is block-level (not a per-run mark, not a role property), so it persists to
|
|
446
|
+
// the block/item style — writing ONLY `textAlign`, so the role link is untouched.
|
|
447
|
+
const persistBlockTextAlign = (textAlign) => {
|
|
448
|
+
if (!textAlign)
|
|
449
|
+
return;
|
|
450
|
+
const value = { textAlign };
|
|
479
451
|
if (props.name === 'textItems') {
|
|
480
452
|
contentSettingStore.updateTextItemTextStyleTypeWithStyles({
|
|
481
453
|
id: props.rawId,
|
|
482
454
|
name: props.name,
|
|
483
|
-
value
|
|
484
|
-
...fontStyleChanges,
|
|
485
|
-
fontSize: fontSettings.selectedFontSize,
|
|
486
|
-
},
|
|
455
|
+
value,
|
|
487
456
|
index: props.textItemIndex,
|
|
488
457
|
});
|
|
489
458
|
}
|
|
@@ -491,12 +460,83 @@ selectedGlobalTextStyles, onSelectTextStyleType, updateRichTextEditor, textStyle
|
|
|
491
460
|
contentSettingStore.updateTextStyles({
|
|
492
461
|
id: props.rawId,
|
|
493
462
|
name: props.name,
|
|
494
|
-
value
|
|
495
|
-
...fontStyleChanges,
|
|
496
|
-
},
|
|
463
|
+
value,
|
|
497
464
|
});
|
|
498
465
|
}
|
|
499
466
|
};
|
|
467
|
+
// The subset of the block's typography that DIFFERS from its linked role — the promotable
|
|
468
|
+
// override set. Empty when the block matches its role (colour is element-first, excluded).
|
|
469
|
+
const getTypographyOverride = () => {
|
|
470
|
+
const role = selectedGlobalTextStyles.value?.style;
|
|
471
|
+
if (!role)
|
|
472
|
+
return {};
|
|
473
|
+
const override = {};
|
|
474
|
+
Object.entries(readBlockTypography(editor)).forEach(([key, value]) => {
|
|
475
|
+
// A role-var mark is linked, not an override — the value IS the role.
|
|
476
|
+
if (isRoleVarRef(value))
|
|
477
|
+
return;
|
|
478
|
+
const promoted = key === 'textDecoration'
|
|
479
|
+
? composeTextDecoration(role[key], value)
|
|
480
|
+
: value;
|
|
481
|
+
if (typeof promoted === 'string' &&
|
|
482
|
+
normTypographyValue(key, promoted) !==
|
|
483
|
+
normTypographyValue(key, role[key])) {
|
|
484
|
+
override[key] = promoted;
|
|
485
|
+
}
|
|
486
|
+
});
|
|
487
|
+
return override;
|
|
488
|
+
};
|
|
489
|
+
// Drives the role dropdown's `*` and the "modified style" toggle: true when any run of this
|
|
490
|
+
// linked block differs from its role's typography — one bold word counts.
|
|
491
|
+
const hasTypographyOverride = () => {
|
|
492
|
+
const role = getRoleStyle();
|
|
493
|
+
return !!role && hasRunTypographyOverride(editor, role);
|
|
494
|
+
};
|
|
495
|
+
// A word-level override has no single value to promote, so "Apply changes to all" needs a
|
|
496
|
+
// whole-block one.
|
|
497
|
+
const canApplyTypographyToRole = () => isCanonicalLinked(props.styles) &&
|
|
498
|
+
Object.keys(getTypographyOverride()).length > 0;
|
|
499
|
+
// Reset to default: re-link this block's typography to its role (see `relinkTypographyChain`).
|
|
500
|
+
// skipStyleDetection keeps the role link so this doesn't read as a detaching style edit.
|
|
501
|
+
const resetTypographyToRole = () => {
|
|
502
|
+
const role = getRoleStyle();
|
|
503
|
+
markUserCommand();
|
|
504
|
+
skipStyleDetection(relinkTypographyChain(editor, role)).run();
|
|
505
|
+
};
|
|
506
|
+
// A role switch resets only typography (ADR-0020): runs relink to the new role, colour stays.
|
|
507
|
+
// An undo/redo restores the doc that went with the role, so it only moves the dropdown tick —
|
|
508
|
+
// the apply bumps `snapshotAppliedToken` in the same tick as it writes the role.
|
|
509
|
+
watch([() => props.styles.textStyleType, () => historyStore.snapshotAppliedToken], ([newType, token], [oldType, oldToken]) => {
|
|
510
|
+
if (!newType || newType === oldType)
|
|
511
|
+
return;
|
|
512
|
+
textStyleTypeOptions.forEach((item) => {
|
|
513
|
+
item.isSelected = item.value === newType;
|
|
514
|
+
});
|
|
515
|
+
if (token === oldToken)
|
|
516
|
+
resetTypographyToRole();
|
|
517
|
+
});
|
|
518
|
+
// Apply to all: promote this block's whole-block typography into the role definition (every
|
|
519
|
+
// block linked to the role adopts it), relink this block's runs that now equal the role —
|
|
520
|
+
// word-level overrides stay, unlike Reset — and re-normalize siblings against the new role.
|
|
521
|
+
// Mirrors the sidebar TextStyleField.saveToGlobal, sourcing the overrides from the RTE marks.
|
|
522
|
+
const applyTypographyToRole = () => {
|
|
523
|
+
const type = props.styles.textStyleType;
|
|
524
|
+
const role = selectedGlobalTextStyles.value?.style;
|
|
525
|
+
const override = getTypographyOverride();
|
|
526
|
+
if (!type || !role || !Object.keys(override).length)
|
|
527
|
+
return;
|
|
528
|
+
const previousRole = { ...role };
|
|
529
|
+
const nextRole = { ...role, ...override };
|
|
530
|
+
markUserCommand();
|
|
531
|
+
styleSettingsStore.setTextStyleOption({ type, style: nextRole });
|
|
532
|
+
skipStyleDetection(relinkRoleEqualRunsChain(editor, nextRole, previousRole)).run();
|
|
533
|
+
contentSettingStore.renormalizeTextStylesForRole(type, previousRole, {
|
|
534
|
+
id: props.rawId,
|
|
535
|
+
name: props.name,
|
|
536
|
+
index: props.textItemIndex,
|
|
537
|
+
doc: sanitizeRteJson(editor.getJSON()),
|
|
538
|
+
});
|
|
539
|
+
};
|
|
500
540
|
const onFocus = () => {
|
|
501
541
|
emit('focus');
|
|
502
542
|
};
|
|
@@ -561,6 +601,7 @@ selectedGlobalTextStyles, onSelectTextStyleType, updateRichTextEditor, textStyle
|
|
|
561
601
|
const selectionRange = selection
|
|
562
602
|
? { from: selection.from, to: selection.to }
|
|
563
603
|
: undefined;
|
|
604
|
+
markUserCommand();
|
|
564
605
|
applyHyperlinkToEditor(url, text, selectionRange);
|
|
565
606
|
isHyperlinkPopupOpen.value = false;
|
|
566
607
|
break;
|
|
@@ -572,6 +613,7 @@ selectedGlobalTextStyles, onSelectTextStyleType, updateRichTextEditor, textStyle
|
|
|
572
613
|
content_type: props.contentType,
|
|
573
614
|
},
|
|
574
615
|
});
|
|
616
|
+
markUserCommand();
|
|
575
617
|
removeHyperlinkFromComposable();
|
|
576
618
|
isHyperlinkPopupOpen.value = false;
|
|
577
619
|
break;
|
|
@@ -599,8 +641,10 @@ selectedGlobalTextStyles, onSelectTextStyleType, updateRichTextEditor, textStyle
|
|
|
599
641
|
lineHeightValue,
|
|
600
642
|
selectedFont: computed(() => selectedFont.value),
|
|
601
643
|
setInitialStyleSettings,
|
|
602
|
-
|
|
603
|
-
|
|
644
|
+
hasTypographyOverride,
|
|
645
|
+
canApplyTypographyToRole,
|
|
646
|
+
resetTypographyToRole,
|
|
647
|
+
applyTypographyToRole,
|
|
604
648
|
handleHyperlink,
|
|
605
649
|
hyperlinkValue,
|
|
606
650
|
setHyperlinkUrlValue,
|