@designcrowd/library.brand-page 6.0.13 → 6.0.14-5804-2

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 (96) hide show
  1. package/lib/src/{CreatedOnBrandCrowd-de-de-CBjFFeBP.js → CreatedOnBrandCrowd-de-de-BW15_bVX.js} +1 -1
  2. package/lib/src/{CreatedOnBrandCrowd-en-us-NuNXF81K.js → CreatedOnBrandCrowd-en-us-MXDRWPa1.js} +1 -1
  3. package/lib/src/{CreatedOnBrandCrowd-es-es-BJG8nfug.js → CreatedOnBrandCrowd-es-es-BkeN_bU4.js} +1 -1
  4. package/lib/src/{CreatedOnBrandCrowd-fr-fr-uX-nL53e.js → CreatedOnBrandCrowd-fr-ca-DWPl8vN2.js} +1 -1
  5. package/lib/src/{CreatedOnBrandCrowd-fr-ca-uX-nL53e.js → CreatedOnBrandCrowd-fr-fr-DWPl8vN2.js} +1 -1
  6. package/lib/src/{CreatedOnBrandCrowd-pt-pt-DTrgFGQV.js → CreatedOnBrandCrowd-pt-br-B2_xFYID.js} +1 -1
  7. package/lib/src/{CreatedOnBrandCrowd-pt-br-DTrgFGQV.js → CreatedOnBrandCrowd-pt-pt-B2_xFYID.js} +1 -1
  8. package/lib/src/{CreatedOnDcom-de-de-DSfpxioT.js → CreatedOnDcom-de-de-D-Y_NKQ3.js} +1 -1
  9. package/lib/src/{CreatedOnDcom-en-us-C7G4gKem.js → CreatedOnDcom-en-us-TkzWmLPE.js} +1 -1
  10. package/lib/src/{CreatedOnDcom-es-es-DVckCaji.js → CreatedOnDcom-es-es-BRcN78-W.js} +1 -1
  11. package/lib/src/{CreatedOnDcom-fr-ca-C5GDrm_C.js → CreatedOnDcom-fr-ca-DcpgnOV-.js} +1 -1
  12. package/lib/src/{CreatedOnDcom-fr-fr-v5eMm-j2.js → CreatedOnDcom-fr-fr-CdppomFF.js} +1 -1
  13. package/lib/src/{CreatedOnDcom-pt-br-Dq3-fPUc.js → CreatedOnDcom-pt-br-Dm05huFx.js} +1 -1
  14. package/lib/src/{CreatedOnDcom-pt-pt-DFsncYax.js → CreatedOnDcom-pt-pt-C2O9rV7u.js} +1 -1
  15. package/lib/src/brand-page/components/contact-form/ContactForm.mixin.d.ts +1 -0
  16. package/lib/src/brand-page/components/contact-form/ContactForm.mixin.js +19 -1
  17. package/lib/src/brand-page/components/mailing-list/MailingList.mixin.d.ts +1 -0
  18. package/lib/src/brand-page/components/mailing-list/MailingList.mixin.js +8 -1
  19. package/lib/src/brand-page/utils/color.util.d.ts +16 -0
  20. package/lib/src/brand-page/utils/color.util.js +56 -0
  21. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +1 -0
  22. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.js +5 -0
  23. package/lib/src/brand-page-maker/components/quick-link-bar/QuickLinkBar.mixin.d.ts +1 -1
  24. package/lib/src/brand-page-maker/components/quick-link-bar/QuickLinkBar.mixin.js +4 -6
  25. package/lib/src/brand-page-maker/composables/useQuickLinkBarVisibility.d.ts +17 -0
  26. package/lib/src/brand-page-maker/composables/useQuickLinkBarVisibility.js +23 -0
  27. package/lib/src/bundled-translations-2HkRBbBD.js +177 -0
  28. package/lib/src/bundled-translations.de-DE-DmmZFmGP.js +177 -0
  29. package/lib/src/bundled-translations.es-ES-D7JmTUKc.js +177 -0
  30. package/lib/src/bundled-translations.fr-CA-LANZnNuX.js +177 -0
  31. package/lib/src/bundled-translations.fr-FR-BQybH6dF.js +177 -0
  32. package/lib/src/bundled-translations.pt-BR-DRAIsAdg.js +177 -0
  33. package/lib/src/bundled-translations.pt-PT-CEqBjj6N.js +177 -0
  34. package/lib/src/bundles/bundled-translations.de-DE.json +5 -2
  35. package/lib/src/bundles/bundled-translations.es-ES.json +5 -2
  36. package/lib/src/bundles/bundled-translations.fr-CA.json +5 -2
  37. package/lib/src/bundles/bundled-translations.fr-FR.json +5 -2
  38. package/lib/src/bundles/bundled-translations.json +5 -2
  39. package/lib/src/bundles/bundled-translations.pt-BR.json +5 -2
  40. package/lib/src/bundles/bundled-translations.pt-PT.json +5 -2
  41. package/lib/src/composables/useTranslate.d.ts +2 -1
  42. package/lib/src/composables/useTranslate.js +2 -1
  43. package/lib/src/css/library.brand-page-brandCrowd.min.css +82 -65
  44. package/lib/src/css/library.brand-page-brandPage.min.css +82 -65
  45. package/lib/src/css/library.brand-page-designCom.min.css +82 -65
  46. package/lib/src/css/library.brand-page-preview.min.css +82 -65
  47. package/lib/src/index.mjs +1 -1
  48. package/lib/src/{lib-BG-pyXi9.js → lib-DwLhDsXL.js} +14511 -14413
  49. package/package.json +1 -1
  50. package/src/brand-page/components/button/Button.vue +20 -0
  51. package/src/brand-page/components/button/Button.vue.test.ts +175 -0
  52. package/src/brand-page/components/contact-form/ContactForm.mixin.test.ts +59 -0
  53. package/src/brand-page/components/contact-form/ContactForm.mixin.ts +24 -0
  54. package/src/brand-page/components/contact-form/ContactForm.vue +9 -0
  55. package/src/brand-page/components/mailing-list/MailingList.mixin.ts +11 -0
  56. package/src/brand-page/components/mailing-list/MailingList.vue +3 -0
  57. package/src/brand-page/components/page/Page.vue +9 -0
  58. package/src/brand-page/components/recaptcha-disclosure/RecaptchaDisclosure.vue +60 -0
  59. package/src/brand-page/components/recaptcha-disclosure/RecaptchaDisclosure.vue.test.ts +36 -0
  60. package/src/brand-page/components/recaptcha-disclosure/i18n/recaptcha.de-DE.json +5 -0
  61. package/src/brand-page/components/recaptcha-disclosure/i18n/recaptcha.es-ES.json +5 -0
  62. package/src/brand-page/components/recaptcha-disclosure/i18n/recaptcha.fr-CA.json +5 -0
  63. package/src/brand-page/components/recaptcha-disclosure/i18n/recaptcha.fr-FR.json +5 -0
  64. package/src/brand-page/components/recaptcha-disclosure/i18n/recaptcha.json +5 -0
  65. package/src/brand-page/components/recaptcha-disclosure/i18n/recaptcha.pt-BR.json +5 -0
  66. package/src/brand-page/components/recaptcha-disclosure/i18n/recaptcha.pt-PT.json +5 -0
  67. package/src/brand-page/utils/color.util.test.ts +78 -1
  68. package/src/brand-page/utils/color.util.ts +82 -0
  69. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.ts +5 -0
  70. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.vue +2 -2
  71. package/src/brand-page-maker/components/device/Device.vue +0 -1
  72. package/src/brand-page-maker/components/quick-link-bar/QuickLinkBar.mixin.ts +4 -7
  73. package/src/brand-page-maker/composables/useQuickLinkBarVisibility.test.ts +81 -0
  74. package/src/brand-page-maker/composables/useQuickLinkBarVisibility.ts +25 -0
  75. package/src/bundles/bundled-translations.de-DE.json +5 -2
  76. package/src/bundles/bundled-translations.es-ES.json +5 -2
  77. package/src/bundles/bundled-translations.fr-CA.json +5 -2
  78. package/src/bundles/bundled-translations.fr-FR.json +5 -2
  79. package/src/bundles/bundled-translations.json +5 -2
  80. package/src/bundles/bundled-translations.pt-BR.json +5 -2
  81. package/src/bundles/bundled-translations.pt-PT.json +5 -2
  82. package/src/composables/useTranslate.ts +3 -0
  83. package/src/shared/content-settings/components/content-settings/i18n/content-settings.de-DE.json +2 -2
  84. package/src/shared/content-settings/components/content-settings/i18n/content-settings.es-ES.json +2 -2
  85. package/src/shared/content-settings/components/content-settings/i18n/content-settings.fr-CA.json +2 -2
  86. package/src/shared/content-settings/components/content-settings/i18n/content-settings.fr-FR.json +2 -2
  87. package/src/shared/content-settings/components/content-settings/i18n/content-settings.json +2 -2
  88. package/src/shared/content-settings/components/content-settings/i18n/content-settings.pt-BR.json +2 -2
  89. package/src/shared/content-settings/components/content-settings/i18n/content-settings.pt-PT.json +2 -2
  90. package/lib/src/bundled-translations-BzzINHD2.js +0 -175
  91. package/lib/src/bundled-translations.de-DE-opJOfLO-.js +0 -175
  92. package/lib/src/bundled-translations.es-ES-MaidBiW6.js +0 -175
  93. package/lib/src/bundled-translations.fr-CA-CuG0285l.js +0 -175
  94. package/lib/src/bundled-translations.fr-FR-DWh-DHys.js +0 -175
  95. package/lib/src/bundled-translations.pt-BR-DG6n1YPu.js +0 -175
  96. package/lib/src/bundled-translations.pt-PT-J5-Lhk0H.js +0 -175
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-BG-pyXi9.js";
2
+ import { _ as t } from "./lib-DwLhDsXL.js";
3
3
  const i = {}, h = {
4
4
  width: "275",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-BG-pyXi9.js";
2
+ import { _ as t } from "./lib-DwLhDsXL.js";
3
3
  const i = {}, h = {
4
4
  width: "251",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-BG-pyXi9.js";
2
+ import { _ as t } from "./lib-DwLhDsXL.js";
3
3
  const i = {}, h = {
4
4
  width: "250",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-BG-pyXi9.js";
2
+ import { _ as t } from "./lib-DwLhDsXL.js";
3
3
  const i = {}, h = {
4
4
  width: "237",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-BG-pyXi9.js";
2
+ import { _ as t } from "./lib-DwLhDsXL.js";
3
3
  const i = {}, h = {
4
4
  width: "237",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-BG-pyXi9.js";
2
+ import { _ as t } from "./lib-DwLhDsXL.js";
3
3
  const i = {}, h = {
4
4
  width: "263",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as e, createElementBlock as l, createStaticVNode as a } from "vue";
2
- import { _ as t } from "./lib-BG-pyXi9.js";
2
+ import { _ as t } from "./lib-DwLhDsXL.js";
3
3
  const i = {}, h = {
4
4
  width: "263",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as e } from "./lib-BG-pyXi9.js";
2
+ import { _ as e } from "./lib-DwLhDsXL.js";
3
3
  const M = {}, Z = {
4
4
  width: "242",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as e } from "./lib-BG-pyXi9.js";
2
+ import { _ as e } from "./lib-DwLhDsXL.js";
3
3
  const i = {}, M = {
4
4
  width: "231",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as e } from "./lib-BG-pyXi9.js";
2
+ import { _ as e } from "./lib-DwLhDsXL.js";
3
3
  const M = {}, Z = {
4
4
  width: "230",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as e } from "./lib-BG-pyXi9.js";
2
+ import { _ as e } from "./lib-DwLhDsXL.js";
3
3
  const i = {}, l = {
4
4
  width: "216",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as e } from "./lib-BG-pyXi9.js";
2
+ import { _ as e } from "./lib-DwLhDsXL.js";
3
3
  const i = {}, l = {
4
4
  width: "216",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as M } from "./lib-BG-pyXi9.js";
2
+ import { _ as M } from "./lib-DwLhDsXL.js";
3
3
  const Z = {}, e = {
4
4
  width: "232",
5
5
  height: "36",
@@ -1,5 +1,5 @@
1
1
  import { openBlock as H, createElementBlock as V, createStaticVNode as t } from "vue";
2
- import { _ as M } from "./lib-BG-pyXi9.js";
2
+ import { _ as M } from "./lib-DwLhDsXL.js";
3
3
  const Z = {}, e = {
4
4
  width: "232",
5
5
  height: "36",
@@ -65,6 +65,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
65
65
  renderText(): string;
66
66
  renderSuccessText(): string;
67
67
  successMessageColorStyle(): BrandPageCssStyle;
68
+ disclosureColor(): string | undefined;
68
69
  }, {
69
70
  submitContactForm(): Promise<void>;
70
71
  validateFormValues(): void;
@@ -4,7 +4,7 @@ import { getEmailValidationError, getMessageValidationError, getNameValidationEr
4
4
  import brandPageClient from '../../clients/brand-page.client';
5
5
  import { isEmail } from '../../../utils/validator.util';
6
6
  import { ALIGN_CARD_CENTER, ALIGN_CARD_CENTER_IMAGE, ALIGN_CENTERED, ALIGN_LEFT_FULL_IMAGE, ALIGN_RIGHT_FULL_IMAGE, DISPLAY_STYLE_COLLAPSED, RECAPTCHA_ACTION_CONTACT_FORM, TEXT_ONLY, } from '../../constants';
7
- import { getRenderText, contentPaddingStyle as toContentPaddingStyle, } from '@brand-page/utils';
7
+ import { getRenderText, contentPaddingStyle as toContentPaddingStyle, mutedTextForBackground, backgroundColorFromStyle, } from '@brand-page/utils';
8
8
  import { hasRTEContent } from '@brand-page-maker/utils';
9
9
  import { useReCaptcha } from '../../composables/recaptcha.composable';
10
10
  export default defineComponent({
@@ -146,6 +146,24 @@ export default defineComponent({
146
146
  }
147
147
  return {};
148
148
  },
149
+ disclosureColor() {
150
+ // Anchor the reCAPTCHA footnote to the surface it visually sits on, which
151
+ // differs by website type:
152
+ // - brandSite: the card style (card + divided layouts) or the section
153
+ // background (other layouts).
154
+ // - brand.page / brand.contact: there's no section background, so the
155
+ // coloured surface is the global button fill.
156
+ // Falls back to the title colour when there's no solid colour to anchor to.
157
+ const style = this.context.isBrandSite
158
+ ? this.hasCard || this.isDividedContent
159
+ ? this.viewModel.cardStyle
160
+ : this.hasBgColor
161
+ ? this.viewModel.backgroundStyle
162
+ : undefined
163
+ : this.viewModel.buttonStyles?.style;
164
+ return (mutedTextForBackground(backgroundColorFromStyle(style)) ??
165
+ this.viewModel.titleStyle?.color);
166
+ },
149
167
  },
150
168
  watch: {
151
169
  fields(fields) {
@@ -48,6 +48,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
48
48
  hasFormError(): boolean;
49
49
  isNameRequired(): boolean;
50
50
  hasSubmitError(): boolean;
51
+ disclosureColor(): string | undefined;
51
52
  buttonStyle(): BrandPageCssStyle;
52
53
  buttonText(): string;
53
54
  containerStyle(): BrandPageCssStyle;
@@ -1,6 +1,6 @@
1
1
  import { defineComponent } from 'vue';
2
2
  import brandPageClient from '../../clients/brand-page.client';
3
- import { getEmailValidationError, contentPaddingStyle as toContentPaddingStyle, } from '@brand-page/utils';
3
+ import { getEmailValidationError, contentPaddingStyle as toContentPaddingStyle, mutedTextForBackground, backgroundColorFromStyle, } from '@brand-page/utils';
4
4
  import { contentSettingsTr, mailingListTr, } from '@src/composables/useTranslate';
5
5
  import { useReCaptcha } from '../../composables/recaptcha.composable';
6
6
  import { RECAPTCHA_ACTION_MAILING_LIST } from '../../constants';
@@ -69,6 +69,13 @@ export default defineComponent({
69
69
  hasSubmitError() {
70
70
  return Boolean(this.submitError);
71
71
  },
72
+ disclosureColor() {
73
+ // The mailing-list box uses the button style as its background, so anchor
74
+ // the reCAPTCHA footnote to that. Falls back to the title colour when the
75
+ // background isn't a solid colour.
76
+ const bg = backgroundColorFromStyle(this.viewModel.styles?.style);
77
+ return mutedTextForBackground(bg) ?? this.viewModel.titleStyle?.color;
78
+ },
72
79
  buttonStyle() {
73
80
  const buttonStyle = { ...this.viewModel.styles?.style };
74
81
  if (buttonStyle.borderStyle !== 'solid') {
@@ -7,5 +7,21 @@ export declare const removeAlphaFromHex: (hex: string) => string;
7
7
  export declare const addTransparentAlphaChannelToHex: (hex: string) => string;
8
8
  export declare const addOpacityToHex: (hex: string, opacity: number) => string;
9
9
  export declare const setRgbAlpha: (rgb: string, alpha: number) => string;
10
+ /**
11
+ * A muted text colour whose lightness runs opposite to the background: darker
12
+ * text on light backgrounds (e.g. beige), lighter text on dark ones. Starts
13
+ * faded (close to the background) and is nudged toward black or white — whichever
14
+ * the background contrasts with more — only until it reaches a legible target
15
+ * contrast, so the result is as subtle as legibility allows.
16
+ *
17
+ * Returns undefined when the background isn't a solid, opaque colour (image,
18
+ * gradient, transparent, unparseable) so callers can fall back.
19
+ */
20
+ export declare const mutedTextForBackground: (bgColor: string | undefined, { targetContrast, start, step }?: {
21
+ targetContrast?: number | undefined;
22
+ start?: number | undefined;
23
+ step?: number | undefined;
24
+ }) => string | undefined;
25
+ export declare const backgroundColorFromStyle: (style: BrandPageCssStyle | undefined) => string | undefined;
10
26
  export declare const getThemeByTextStyleAndLogoTheme: (textStyle: BrandPageCssStyle, logoTheme: LogoTheme) => Theme;
11
27
  export declare const getNewColorBasedOnTargetColorTheme: (originalColor: string, targetColor: string) => ColorInstance | undefined;
@@ -47,6 +47,62 @@ export const setRgbAlpha = (rgb, alpha) => {
47
47
  }
48
48
  return `rgba(${match[1]},${match[2]},${match[3]},${alpha})`;
49
49
  };
50
+ // Weighted linear blend of two colours in sRGB (weight = amount of `b`, 0..1).
51
+ const mixRgb = (a, b, weight) => {
52
+ const [ar, ag, ab] = a.rgb().array();
53
+ const [br, bg, bb] = b.rgb().array();
54
+ return Color.rgb(ar + (br - ar) * weight, ag + (bg - ag) * weight, ab + (bb - ab) * weight);
55
+ };
56
+ // WCAG contrast ratio (1..21) between two colours.
57
+ const contrastRatio = (a, b) => {
58
+ const [ar, ag, ab] = a.rgb().array();
59
+ const [br, bg, bb] = b.rgb().array();
60
+ const la = luminance(ar, ag, ab);
61
+ const lb = luminance(br, bg, bb);
62
+ return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);
63
+ };
64
+ /**
65
+ * A muted text colour whose lightness runs opposite to the background: darker
66
+ * text on light backgrounds (e.g. beige), lighter text on dark ones. Starts
67
+ * faded (close to the background) and is nudged toward black or white — whichever
68
+ * the background contrasts with more — only until it reaches a legible target
69
+ * contrast, so the result is as subtle as legibility allows.
70
+ *
71
+ * Returns undefined when the background isn't a solid, opaque colour (image,
72
+ * gradient, transparent, unparseable) so callers can fall back.
73
+ */
74
+ export const mutedTextForBackground = (bgColor, { targetContrast = 3.5, start = 0.12, step = 0.04 } = {}) => {
75
+ if (!bgColor) {
76
+ return undefined;
77
+ }
78
+ let bg;
79
+ try {
80
+ bg = Color(bgColor);
81
+ }
82
+ catch {
83
+ return undefined;
84
+ }
85
+ // Can't anchor to a see-through background — caller should fall back.
86
+ if (bg.alpha() === 0) {
87
+ return undefined;
88
+ }
89
+ const black = Color.rgb(0, 0, 0);
90
+ const white = Color.rgb(255, 255, 255);
91
+ const target = contrastRatio(bg, black) >= contrastRatio(bg, white) ? black : white;
92
+ let weight = start;
93
+ let text = mixRgb(bg, target, weight);
94
+ while (weight < 1 && contrastRatio(text, bg) < targetContrast) {
95
+ weight += step;
96
+ text = mixRgb(bg, target, weight);
97
+ }
98
+ return text.hex();
99
+ };
100
+ // Pull a usable background colour out of a style object. Section backgrounds are
101
+ // written under the `background` shorthand (the background-settings store forbids
102
+ // `backgroundColor`), while card/button styles use `backgroundColor` — so check
103
+ // both. The value may be a gradient/shorthand; callers that need a solid colour
104
+ // pass it through mutedTextForBackground, which rejects anything unparseable.
105
+ export const backgroundColorFromStyle = (style) => style?.backgroundColor || style?.background;
50
106
  export const getThemeByTextStyleAndLogoTheme = (textStyle, logoTheme) => {
51
107
  const primaryColor = textStyle.color;
52
108
  let secondaryColor = primaryColor;
@@ -50,6 +50,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
50
50
  isSaving: import("vue").ComputedRef<boolean>;
51
51
  isPublishing: import("vue").ComputedRef<boolean>;
52
52
  isPublished: import("vue").ComputedRef<boolean>;
53
+ shouldShowQuickLinkBar: import("vue").ComputedRef<boolean>;
53
54
  isBrandPageOrIsBrandContact: import("vue").ComputedRef<boolean>;
54
55
  brandPageViewModel: import("vue").ComputedRef<import("@brand-page").BrandPageViewModel>;
55
56
  backUrl: import("vue").ComputedRef<string>;
@@ -13,6 +13,7 @@ import { UI_DEVICE_MODES, UI_SCREENSIZE_MODES, } from '@shared/models';
13
13
  import { useBrandPageMakerStore, useBrandPageMakerUserStore, useLocalisedRouteStore, useUiStore, useSnapshotStore, useVideoStore, } from '@brand-page-maker/stores';
14
14
  import { useHistoryStore } from '@brand-page-maker/stores/history/history-store';
15
15
  import { useUndoRedoFlag } from '@brand-page-maker/composables/useUndoRedoFlag';
16
+ import { useQuickLinkBarVisibility } from '@brand-page-maker/composables/useQuickLinkBarVisibility';
16
17
  import { useUiContentSettingsStore } from '@shared/content-settings/store';
17
18
  import { useUiTemplateSettingsStore } from '@shared/template-settings/store';
18
19
  import { useUiPageSettingsStore } from '@shared/page-settings/store';
@@ -73,6 +74,10 @@ export default defineComponent({
73
74
  isSaving: computed(() => brandPageMakerStore.isSaving),
74
75
  isPublishing: computed(() => brandPageMakerStore.isPublishing),
75
76
  isPublished: computed(() => brandPageMakerStore.isPublished),
77
+ // Whether the QuickLinkBar renders — used to offset the preview (Device)
78
+ // and SideBar clear of the fixed bar on mobile. Must match the bar's own
79
+ // render condition, so it shares the same predicate.
80
+ shouldShowQuickLinkBar: useQuickLinkBarVisibility(),
76
81
  isBrandPageOrIsBrandContact: computed(() => brandPageMakerStore.isBrandPageOrIsBrandContact),
77
82
  brandPageViewModel: computed(() => brandPageMakerStore.brandPageViewModel),
78
83
  backUrl: computed(() => localisedRouteStore.backToWebsiteManageUrlPath),
@@ -292,11 +292,11 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
292
292
  pushManageWebPageUnpublishClickEvent(): Promise<void>;
293
293
  }>;
294
294
  undoRedoEnabled: import("vue").ComputedRef<boolean>;
295
+ shouldShowBar: import("vue").ComputedRef<boolean>;
295
296
  }, {
296
297
  copied: boolean;
297
298
  }, {
298
299
  isPublished(): boolean;
299
- shouldShowBar(): boolean;
300
300
  brandPageUrl(): string;
301
301
  copyButtonLabel(): string;
302
302
  }, {
@@ -2,6 +2,7 @@ import { defineComponent } from 'vue';
2
2
  import { CUSTOM_DOMAIN_STATUSES } from '@brand-page-maker/constants';
3
3
  import { useBrandPageContainerStore, useEventManagerStore, } from '@brand-page-maker/stores';
4
4
  import { useUndoRedoFlag } from '@brand-page-maker/composables/useUndoRedoFlag';
5
+ import { useQuickLinkBarVisibility } from '@brand-page-maker/composables/useQuickLinkBarVisibility';
5
6
  import { quickLinkBarTr } from '@src/composables/useTranslate';
6
7
  export default defineComponent({
7
8
  props: {
@@ -19,6 +20,9 @@ export default defineComponent({
19
20
  brandPageContainerStore: useBrandPageContainerStore(),
20
21
  eventManagerStore: useEventManagerStore(),
21
22
  undoRedoEnabled: useUndoRedoFlag(),
23
+ // Single source of truth for whether the bar renders — shared with the
24
+ // layout components (Device, SideBar) that offset content clear of it.
25
+ shouldShowBar: useQuickLinkBarVisibility(),
22
26
  };
23
27
  },
24
28
  data() {
@@ -30,12 +34,6 @@ export default defineComponent({
30
34
  isPublished() {
31
35
  return this.brandPageContainerStore.isPublished;
32
36
  },
33
- // Only render the bar when at least one inner cluster has something to
34
- // show. Otherwise we'd render an empty white strip — e.g. on an
35
- // unpublished page with the undo flag off.
36
- shouldShowBar() {
37
- return Boolean(this.undoRedoEnabled) || this.isPublished;
38
- },
39
37
  brandPageUrl() {
40
38
  if (this.brandPageContainerStore.isCustomDomainEnabled &&
41
39
  this.brandPageContainerStore.customDomain &&
@@ -0,0 +1,17 @@
1
+ import { type ComputedRef } from 'vue';
2
+ /**
3
+ * Whether the QuickLinkBar is rendered in the maker.
4
+ *
5
+ * The bar shows when at least one of its inner clusters has something to
6
+ * display: the undo/redo controls (flag on, non-admin — see
7
+ * {@link useUndoRedoFlag}) OR the published-URL cluster (page published).
8
+ *
9
+ * This is the single source of truth shared by the bar itself
10
+ * (`QuickLinkBar`) and the layout components that offset their content to sit
11
+ * clear of the fixed bar on mobile (`Device`, `SideBar`). Keeping the offset
12
+ * bound to the same predicate the bar renders on prevents the two from
13
+ * drifting — a drift where the bar showed for the undo/redo reason but the
14
+ * offset only accounted for the published reason caused the bar to overlap
15
+ * the mobile preview.
16
+ */
17
+ export declare function useQuickLinkBarVisibility(): ComputedRef<boolean>;
@@ -0,0 +1,23 @@
1
+ import { computed } from 'vue';
2
+ import { useBrandPageContainerStore } from '@brand-page-maker/stores';
3
+ import { useUndoRedoFlag } from './useUndoRedoFlag';
4
+ /**
5
+ * Whether the QuickLinkBar is rendered in the maker.
6
+ *
7
+ * The bar shows when at least one of its inner clusters has something to
8
+ * display: the undo/redo controls (flag on, non-admin — see
9
+ * {@link useUndoRedoFlag}) OR the published-URL cluster (page published).
10
+ *
11
+ * This is the single source of truth shared by the bar itself
12
+ * (`QuickLinkBar`) and the layout components that offset their content to sit
13
+ * clear of the fixed bar on mobile (`Device`, `SideBar`). Keeping the offset
14
+ * bound to the same predicate the bar renders on prevents the two from
15
+ * drifting — a drift where the bar showed for the undo/redo reason but the
16
+ * offset only accounted for the published reason caused the bar to overlap
17
+ * the mobile preview.
18
+ */
19
+ export function useQuickLinkBarVisibility() {
20
+ const containerStore = useBrandPageContainerStore();
21
+ const undoRedoEnabled = useUndoRedoFlag();
22
+ return computed(() => undoRedoEnabled.value || containerStore.isPublished);
23
+ }