@designcrowd/library.brand-page 5.18.1 → 5.18.2-ast-padding-1

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 (108) hide show
  1. package/lib/src/{CreatedOnBrandCrowd-de-de-DFpjIAUv.js → CreatedOnBrandCrowd-de-de-GFYl8DtL.js} +1 -1
  2. package/lib/src/{CreatedOnBrandCrowd-en-us-BapIT2xO.js → CreatedOnBrandCrowd-en-us-D5CcXf2I.js} +1 -1
  3. package/lib/src/{CreatedOnBrandCrowd-es-es-DaSf3Dt6.js → CreatedOnBrandCrowd-es-es-Cr7J3ooe.js} +1 -1
  4. package/lib/src/{CreatedOnBrandCrowd-fr-fr-Cvgei7yn.js → CreatedOnBrandCrowd-fr-ca-BC1NFFIW.js} +1 -1
  5. package/lib/src/{CreatedOnBrandCrowd-fr-ca-Cvgei7yn.js → CreatedOnBrandCrowd-fr-fr-BC1NFFIW.js} +1 -1
  6. package/lib/src/{CreatedOnBrandCrowd-pt-pt-Duxd2NmR.js → CreatedOnBrandCrowd-pt-br-BdiCcpwi.js} +1 -1
  7. package/lib/src/{CreatedOnBrandCrowd-pt-br-Duxd2NmR.js → CreatedOnBrandCrowd-pt-pt-BdiCcpwi.js} +1 -1
  8. package/lib/src/{CreatedOnDcom-de-de-DXwNbruv.js → CreatedOnDcom-de-de-d4TmC_lo.js} +1 -1
  9. package/lib/src/{CreatedOnDcom-en-us-CkNGwN-p.js → CreatedOnDcom-en-us-DlvLEF-R.js} +1 -1
  10. package/lib/src/{CreatedOnDcom-es-es-Csyf5yhI.js → CreatedOnDcom-es-es-BulpVp3k.js} +1 -1
  11. package/lib/src/{CreatedOnDcom-fr-ca-GOIUmIdy.js → CreatedOnDcom-fr-ca-M4xqunZe.js} +1 -1
  12. package/lib/src/{CreatedOnDcom-fr-fr-DF63cL2a.js → CreatedOnDcom-fr-fr-BFqUXgzb.js} +1 -1
  13. package/lib/src/{CreatedOnDcom-pt-br-Ct6FWj7D.js → CreatedOnDcom-pt-br-CUVcVkV2.js} +1 -1
  14. package/lib/src/{CreatedOnDcom-pt-pt-D22yb8Ci.js → CreatedOnDcom-pt-pt-Dc4CZ4xW.js} +1 -1
  15. package/lib/src/brand-page/components/contact-form/ContactForm.mixin.d.ts +4 -0
  16. package/lib/src/brand-page/components/contact-form/ContactForm.mixin.js +8 -4
  17. package/lib/src/brand-page/components/image-gallery/ImageGallery.mixin.d.ts +4 -0
  18. package/lib/src/brand-page/components/image-gallery/ImageGallery.mixin.js +4 -0
  19. package/lib/src/brand-page/components/mailing-list/MailingList.mixin.d.ts +4 -0
  20. package/lib/src/brand-page/components/mailing-list/MailingList.mixin.js +4 -1
  21. package/lib/src/brand-page/components/page/Page.mixin.d.ts +1 -1
  22. package/lib/src/brand-page/components/page/PageComponent.mixin.d.ts +1 -1
  23. package/lib/src/brand-page/components/payment/request-payment/RequestPayment.mixin.d.ts +4 -0
  24. package/lib/src/brand-page/components/payment/request-payment/RequestPayment.mixin.js +4 -0
  25. package/lib/src/brand-page/components/payment/support-me/SupportMe.mixin.d.ts +4 -0
  26. package/lib/src/brand-page/components/payment/support-me/SupportMe.mixin.js +4 -1
  27. package/lib/src/brand-page/components/video/Video.mixin.d.ts +4 -0
  28. package/lib/src/brand-page/components/video/Video.mixin.js +4 -0
  29. package/lib/src/brand-page/constants/misc.constants.d.ts +17 -0
  30. package/lib/src/brand-page/constants/misc.constants.js +25 -0
  31. package/lib/src/brand-page/models/content.model.d.ts +2 -0
  32. package/lib/src/brand-page/utils/content-padding.util.d.ts +13 -0
  33. package/lib/src/brand-page/utils/content-padding.util.js +10 -0
  34. package/lib/src/brand-page/utils/index.d.ts +1 -0
  35. package/lib/src/brand-page/utils/index.js +1 -0
  36. package/lib/src/brand-page/utils/migration/migration-16.d.ts +2 -0
  37. package/lib/src/brand-page/utils/migration/migration-16.js +37 -0
  38. package/lib/src/brand-page/utils/migration.util.js +6 -0
  39. package/lib/src/brand-page-maker/components/admin-logo-settings/AdminLogoSettings.mixin.d.ts +2 -0
  40. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +12 -0
  41. package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +15 -1
  42. package/lib/src/brand-page-maker/constants/config-settings-constant.js +34 -0
  43. package/lib/src/brand-page-maker/convertors/banner-align-display-style.convertor.js +56 -2
  44. package/lib/src/brand-page-maker/convertors/contact-layout-style.convertor.js +6 -1
  45. package/lib/src/brand-page-maker/models/content-settings.js +30 -2
  46. package/lib/src/brand-page-maker/stores/ai-checkpoint/ai-checkpoint-store.d.ts +12 -0
  47. package/lib/src/{bundled-translations-CnareLWC.js → bundled-translations-DYd5oFZv.js} +1 -1
  48. package/lib/src/bundles/bundled-translations.json +2 -0
  49. package/lib/src/css/library.brand-page-brandCrowd.min.css +152 -140
  50. package/lib/src/css/library.brand-page-brandPage.min.css +153 -140
  51. package/lib/src/css/library.brand-page-designCom.min.css +152 -140
  52. package/lib/src/css/library.brand-page-preview.min.css +152 -140
  53. package/lib/src/index.mjs +1 -1
  54. package/lib/src/{lib-_iwoSD1Z.js → lib-CRihSxY0.js} +20195 -19572
  55. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +14 -0
  56. package/lib/src/shared/content-settings/components/content-settings/ReplaceImageSettingsForContent.mixin.d.ts +14 -0
  57. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.d.ts +12 -0
  58. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.d.ts +12 -0
  59. package/lib/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.d.ts +12 -0
  60. package/lib/src/shared/content-settings/components/slider-field/SliderField.mixin.js +9 -0
  61. package/lib/src/shared/content-settings/store/content-settings-store.d.ts +12 -0
  62. package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +16 -0
  63. package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +14 -0
  64. package/lib/src/utils/minify-brand-page-metadata.js +11 -1
  65. package/package.json +2 -2
  66. package/src/brand-page/components/banner-section/BannerSection.vue +360 -12
  67. package/src/brand-page/components/banner-section/BannerSection.vue.test.ts +201 -0
  68. package/src/brand-page/components/booking-section/BookingSection.vue +11 -3
  69. package/src/brand-page/components/contact-form/ContactForm.mixin.ts +12 -6
  70. package/src/brand-page/components/contact-form/ContactForm.vue +115 -118
  71. package/src/brand-page/components/image-gallery/ImageGallery.mixin.ts +5 -0
  72. package/src/brand-page/components/image-gallery/ImageGallery.vue +1 -1
  73. package/src/brand-page/components/mailing-list/MailingList.mixin.ts +8 -1
  74. package/src/brand-page/components/mailing-list/MailingList.vue +1 -1
  75. package/src/brand-page/components/map/Map.vue +5 -1
  76. package/src/brand-page/components/payment/request-payment/RequestPayment.mixin.ts +5 -0
  77. package/src/brand-page/components/payment/request-payment/RequestPayment.vue +1 -0
  78. package/src/brand-page/components/payment/support-me/SupportMe.mixin.ts +8 -1
  79. package/src/brand-page/components/payment/support-me/SupportMe.vue +1 -0
  80. package/src/brand-page/components/placeholder/Placeholder.vue +39 -100
  81. package/src/brand-page/components/social-links/SocialLinks.vue +7 -3
  82. package/src/brand-page/components/text/Text.vue +12 -5
  83. package/src/brand-page/components/text-media-section/TextMediaSection.vue +11 -3
  84. package/src/brand-page/components/video/Video.mixin.ts +5 -0
  85. package/src/brand-page/components/video/Video.vue +1 -1
  86. package/src/brand-page/constants/misc.constants.ts +26 -0
  87. package/src/brand-page/models/content.model.ts +2 -0
  88. package/src/brand-page/utils/__snapshots__/migration.util.test.ts.snap +7 -3
  89. package/src/brand-page/utils/content-padding.util.test.ts +29 -0
  90. package/src/brand-page/utils/content-padding.util.ts +13 -0
  91. package/src/brand-page/utils/index.ts +1 -0
  92. package/src/brand-page/utils/migration/migration-16.ts +51 -0
  93. package/src/brand-page/utils/migration.util.test.ts +64 -0
  94. package/src/brand-page/utils/migration.util.ts +7 -0
  95. package/src/brand-page-maker/constants/config-settings-constant.ts +40 -0
  96. package/src/brand-page-maker/convertors/banner-align-display-style.convertor.ts +61 -1
  97. package/src/brand-page-maker/convertors/contact-layout-style.convertor.test.ts +50 -0
  98. package/src/brand-page-maker/convertors/contact-layout-style.convertor.ts +8 -0
  99. package/src/brand-page-maker/models/content-settings.ts +32 -2
  100. package/src/bundles/bundled-translations.json +2 -0
  101. package/src/shared/content-settings/components/content-settings/i18n/content-settings.json +2 -0
  102. package/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.vue +1 -1
  103. package/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.vue +2 -2
  104. package/src/shared/content-settings/components/slider-field/SliderField.mixin.ts +9 -0
  105. package/src/utils/minify-brand-page-metadata.ts +11 -1
  106. package/lib/src/brand-page/components/banner-section/BannerSection.mixin.d.ts +0 -103
  107. package/lib/src/brand-page/components/banner-section/BannerSection.mixin.js +0 -178
  108. package/src/brand-page/components/banner-section/BannerSection.mixin.ts +0 -213
@@ -1,24 +1,12 @@
1
1
  <template>
2
2
  <section data-component="contact-form">
3
3
  <div
4
- :class="{
5
- 'tw-flex': isCenteredLayout && !hasBgImage,
6
- 'tw-block': !viewModel.layoutStyle,
7
- 'tw-relative': hasBgImage,
8
- }"
9
- :style="hasBgColor ? viewModel.backgroundStyle : {}"
4
+ :class="{ 'tw-block': !viewModel.layoutStyle }"
5
+ :style="[
6
+ hasBgColor ? viewModel.backgroundStyle : {},
7
+ contentPaddingStyle,
8
+ ]"
10
9
  >
11
- <Media
12
- v-if="hasBgImage && isCenteredLayout"
13
- :image-url="viewModel.imageUrl"
14
- :color-replacements="viewModel.colorReplacements"
15
- :context="context"
16
- :media-type="viewModel.mediaType"
17
- :role="viewModel.role"
18
- :size="viewModel.size"
19
- :content-index="contentIndex"
20
- img-classes="tw-w-full tw-h-full tw-object-cover tw-absolute tw-left-0 tw-top-0 tw-overflow-hidden"
21
- />
22
10
  <Collapsible
23
11
  v-if="
24
12
  !viewModel.layoutStyle ||
@@ -108,110 +96,125 @@
108
96
  </Collapsible>
109
97
  <div
110
98
  v-else-if="isCenteredLayout"
111
- class="contact-container tw-py-4"
112
- :class="{
113
- 'tw-px-6 tw-py-8': hasCard,
114
- 'tw-py-6': !hasCard,
115
- 'tw-w-full': !hasBgImage,
116
- }"
99
+ :class="{ 'tw-relative': hasBgImage, 'tw-flex': !hasBgImage }"
117
100
  >
101
+ <Media
102
+ v-if="hasBgImage"
103
+ :image-url="viewModel.imageUrl"
104
+ :color-replacements="viewModel.colorReplacements"
105
+ :context="context"
106
+ :media-type="viewModel.mediaType"
107
+ :role="viewModel.role"
108
+ :size="viewModel.size"
109
+ :content-index="contentIndex"
110
+ img-classes="tw-w-full tw-h-full tw-object-cover tw-absolute tw-left-0 tw-top-0 tw-overflow-hidden"
111
+ />
118
112
  <div
119
- :style="hasCard ? viewModel.cardStyle : {}"
120
- class="tw-relative tw-block tw-px-6 tw-py-8 tw-rounded-2xl"
113
+ class="contact-container"
114
+ :class="{
115
+ 'tw-px-6': hasCard,
116
+ 'tw-py-8': hasBgImage,
117
+ 'tw-w-full': !hasBgImage,
118
+ }"
121
119
  >
122
- <form v-if="!hasSubmitted" @submit.prevent="submitContactForm">
123
- <TextWrapper
124
- v-if="viewModel.title"
125
- :text-style="viewModel.titleStyle"
126
- :text="viewModel.title"
127
- element="h1"
128
- class="tw-mb-4 tw-text-base"
129
- />
130
- <TextWrapper
131
- v-if="renderText"
132
- :text-style="viewModel.descriptionStyle"
133
- :text="renderText"
134
- element="div"
135
- class="tw-mb-4 tw-text-base"
136
- />
137
- <div v-if="!isSubmitting" class="tw-grid tw-grid-cols-2 tw-gap-4">
138
- <div
139
- v-for="(value, index) in values"
140
- :key="index"
141
- class="tw-text-secondary-500 c-col-span-2"
142
- :class="{
143
- 'tw-col-span-2':
144
- value.field.type === 'text-area' || isMobileDevice,
145
- }"
146
- >
147
- <TextInput
148
- v-if="value.field.type !== 'text-area'"
149
- v-model="value.value"
150
- :placeholder="`${value.field.name}${
151
- value.field.required ? '*' : ''
152
- }`"
153
- :label="`${value.field.name}${value.field.required ? '*' : ''}`"
154
- :show-label-screen-reader-only="true"
155
- size="sm"
156
- :error="!!value.error"
157
- :type="getTextInputTypeByFieldType(value.field.type)"
158
- class="tw-w-full"
159
- @input="onValueChange(index)"
160
- />
161
- <Textarea
162
- v-if="value.field.type === 'text-area'"
163
- v-model="value.value"
164
- :placeholder="`${value.field.name}${
165
- value.field.required ? '*' : ''
166
- }`"
167
- :label="`${value.field.name}${value.field.required ? '*' : ''}`"
168
- :show-label-screen-reader-only="true"
169
- size="sm"
170
- :error="!!value.error"
171
- :resize="false"
172
- class="tw-w-full"
173
- @input="onValueChange(index)"
174
- />
175
- <p v-if="!!value.error" class="form-error">
176
- {{ value.error }}
177
- </p>
178
- </div>
179
- <div class="tw-flex tw-w-full tw-justify-center tw-col-span-2">
180
- <button
181
- v-if="isSubmitButtonVisible"
182
- class="tw-block tw-border-0 tw-py-2 tw-select-none tw-text-base tw-text-center tw-w-fit hover:tw-cursor-pointer tw-px-8 tw-py-3 c-button-full"
183
- :style="submitButtonStyle"
184
- :class="{ 'tw-w-full': isMobileDevice }"
120
+ <div
121
+ :style="hasCard ? viewModel.cardStyle : {}"
122
+ class="tw-relative tw-block tw-px-6 tw-py-8 tw-rounded-2xl"
123
+ >
124
+ <form v-if="!hasSubmitted" @submit.prevent="submitContactForm">
125
+ <TextWrapper
126
+ v-if="viewModel.title"
127
+ :text-style="viewModel.titleStyle"
128
+ :text="viewModel.title"
129
+ element="h1"
130
+ class="tw-mb-4 tw-text-base"
131
+ />
132
+ <TextWrapper
133
+ v-if="renderText"
134
+ :text-style="viewModel.descriptionStyle"
135
+ :text="renderText"
136
+ element="div"
137
+ class="tw-mb-4 tw-text-base"
138
+ />
139
+ <div v-if="!isSubmitting" class="tw-grid tw-grid-cols-2 tw-gap-4">
140
+ <div
141
+ v-for="(value, index) in values"
142
+ :key="index"
143
+ class="tw-text-secondary-500 c-col-span-2"
144
+ :class="{
145
+ 'tw-col-span-2':
146
+ value.field.type === 'text-area' || isMobileDevice,
147
+ }"
185
148
  >
186
- <TextWrapper
187
- :text-style="submitButtonTextStyle"
188
- :text="viewModel.buttonText"
189
- class="tw-text-center tw-text-base"
149
+ <TextInput
150
+ v-if="value.field.type !== 'text-area'"
151
+ v-model="value.value"
152
+ :placeholder="`${value.field.name}${
153
+ value.field.required ? '*' : ''
154
+ }`"
155
+ :label="`${value.field.name}${value.field.required ? '*' : ''}`"
156
+ :show-label-screen-reader-only="true"
157
+ size="sm"
158
+ :error="!!value.error"
159
+ :type="getTextInputTypeByFieldType(value.field.type)"
160
+ class="tw-w-full"
161
+ @input="onValueChange(index)"
190
162
  />
191
- </button>
163
+ <Textarea
164
+ v-if="value.field.type === 'text-area'"
165
+ v-model="value.value"
166
+ :placeholder="`${value.field.name}${
167
+ value.field.required ? '*' : ''
168
+ }`"
169
+ :label="`${value.field.name}${value.field.required ? '*' : ''}`"
170
+ :show-label-screen-reader-only="true"
171
+ size="sm"
172
+ :error="!!value.error"
173
+ :resize="false"
174
+ class="tw-w-full"
175
+ @input="onValueChange(index)"
176
+ />
177
+ <p v-if="!!value.error" class="form-error">
178
+ {{ value.error }}
179
+ </p>
180
+ </div>
181
+ <div class="tw-flex tw-w-full tw-justify-center tw-col-span-2">
182
+ <button
183
+ v-if="isSubmitButtonVisible"
184
+ class="tw-block tw-border-0 tw-py-2 tw-select-none tw-text-base tw-text-center tw-w-fit hover:tw-cursor-pointer tw-px-8 tw-py-3 c-button-full"
185
+ :style="submitButtonStyle"
186
+ :class="{ 'tw-w-full': isMobileDevice }"
187
+ >
188
+ <TextWrapper
189
+ :text-style="submitButtonTextStyle"
190
+ :text="viewModel.buttonText"
191
+ class="tw-text-center tw-text-base"
192
+ />
193
+ </button>
194
+ </div>
192
195
  </div>
196
+ <div v-else class="tw-w-full tw-flex tw-justify-center">
197
+ <Loader />
198
+ </div>
199
+ <p
200
+ v-if="hasSubmitError"
201
+ class="tw-text-center tw-mt-2 form-error"
202
+ >
203
+ {{ submitError }}
204
+ </p>
205
+ </form>
206
+ <div v-else :style="successMessageColorStyle">
207
+ <TextWrapper
208
+ v-if="viewModel.successMessage"
209
+ :text="renderSuccessText"
210
+ element="p"
211
+ :class="'tw-my-0.5'"
212
+ />
193
213
  </div>
194
- <div v-else class="tw-w-full tw-flex tw-justify-center">
195
- <Loader />
196
- </div>
197
- <p v-if="hasSubmitError" class="tw-text-center tw-mt-2 form-error">
198
- {{ submitError }}
199
- </p>
200
- </form>
201
- <div v-else :style="successMessageColorStyle">
202
- <TextWrapper
203
- v-if="viewModel.successMessage"
204
- :text="renderSuccessText"
205
- element="p"
206
- :class="'tw-my-0.5'"
207
- />
208
214
  </div>
209
215
  </div>
210
216
  </div>
211
- <div
212
- v-else-if="isTextOnly"
213
- class="tw-px-6 tw-py-8 tw-gap-2 contact-container"
214
- >
217
+ <div v-else-if="isTextOnly" class="tw-px-6 tw-gap-2 contact-container">
215
218
  <span v-if="!hasSubmitted" class="tw-grid tw-grid-cols-2">
216
219
  <div
217
220
  v-if="!isSubmitting"
@@ -350,10 +353,7 @@
350
353
  }"
351
354
  >
352
355
  <div
353
- class="tw-flex tw-flex-col tw-gap-2 tw-px-8 tw-w-full tw-justify-center c-py-6"
354
- :class="{
355
- 'tw-py-6': isMobileDevice,
356
- }"
356
+ class="tw-flex tw-flex-col tw-gap-2 tw-px-8 tw-py-6 tw-w-full tw-justify-center"
357
357
  >
358
358
  <span v-if="!hasSubmitted">
359
359
  <TextWrapper
@@ -516,9 +516,6 @@ export default {
516
516
  .c-text-padding {
517
517
  @apply tw-px-0 tw-col-span-2;
518
518
  }
519
- .c-py-6 {
520
- @apply tw-py-6;
521
- }
522
519
  .c-divided-container {
523
520
  @apply tw-flex-col;
524
521
  }
@@ -1,6 +1,7 @@
1
1
  import { defineComponent } from 'vue';
2
2
  import type { PropType } from 'vue';
3
3
  import type { ImageGalleryViewModel } from '@brand-page/view-models';
4
+ import { contentPaddingStyle as toContentPaddingStyle } from '@brand-page/utils';
4
5
  import ComponentCommonMixin from '../mixins/component-common.mixin';
5
6
  import ImageModalMixin from '../mixins/image-modal.mixin';
6
7
  import type { ImageGalleryImageClickPayload } from './models';
@@ -34,6 +35,10 @@ export default defineComponent({
34
35
  };
35
36
  },
36
37
  computed: {
38
+ contentPaddingStyle(): { paddingTop: string; paddingBottom: string } {
39
+ return toContentPaddingStyle(this.viewModel);
40
+ },
41
+
37
42
  getContainerStyle(): BrandPageCssStyle {
38
43
  if (this.galleryType === 'carousel') {
39
44
  const maxWidth = this.containerClientWidth
@@ -10,7 +10,7 @@
10
10
  'c-carousel-full-width':
11
11
  viewModel.isFullWidth && isPreview && galleryType === 'carousel',
12
12
  }"
13
- :style="getContainerStyle"
13
+ :style="[getContainerStyle, contentPaddingStyle]"
14
14
  >
15
15
  <component
16
16
  :is="galleryType"
@@ -2,7 +2,10 @@ import { defineComponent } from 'vue';
2
2
  import type { PropType } from 'vue';
3
3
  import type { MailingListViewModel } from '@brand-page/view-models';
4
4
  import brandPageClient from '../../clients/brand-page.client';
5
- import { getEmailValidationError } from '@brand-page/utils';
5
+ import {
6
+ getEmailValidationError,
7
+ contentPaddingStyle as toContentPaddingStyle,
8
+ } from '@brand-page/utils';
6
9
  import type { BrandPageContext } from '@brand-page/models';
7
10
  import {
8
11
  contentSettingsTr,
@@ -61,6 +64,10 @@ export default defineComponent({
61
64
  }
62
65
  },
63
66
  computed: {
67
+ contentPaddingStyle(): { paddingTop: string; paddingBottom: string } {
68
+ return toContentPaddingStyle(this.viewModel);
69
+ },
70
+
64
71
  hasNameError(): boolean {
65
72
  return !!this.nameError;
66
73
  },
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <section>
2
+ <section :style="contentPaddingStyle">
3
3
  <div
4
4
  v-if="show"
5
5
  class="tw-p-4"
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div data-component="map">
2
+ <div data-component="map" :style="contentPaddingStyle">
3
3
  <div
4
4
  class="c-map"
5
5
  :class="{
@@ -22,6 +22,7 @@ import Placeholder from '../placeholder/Placeholder.vue';
22
22
  import type { MapViewModel } from '@brand-page/view-models';
23
23
  import type { BrandPageContext } from '@brand-page/models';
24
24
  import { mapTr } from '@src/composables/useTranslate';
25
+ import { contentPaddingStyle as toContentPaddingStyle } from '@brand-page/utils';
25
26
  import { computed } from 'vue';
26
27
 
27
28
  interface Props {
@@ -37,6 +38,9 @@ const props = withDefaults(defineProps<Props>(), {
37
38
  });
38
39
 
39
40
  const placeId = computed(() => props.viewModel?.address?.placeId);
41
+ const contentPaddingStyle = computed(() =>
42
+ toContentPaddingStyle(props.viewModel),
43
+ );
40
44
  </script>
41
45
  <style scoped>
42
46
  .c-map {
@@ -14,6 +14,7 @@ import type { RequestPaymentViewModel } from '../../../view-models';
14
14
  import type { PaymentRequestDetails } from '../Payment.mixin';
15
15
  import { DEFAULT_CURRENCY_SYMBOL } from '../../../constants';
16
16
  import { addOpacityToHex } from '../../../utils/color.util';
17
+ import { contentPaddingStyle as toContentPaddingStyle } from '../../../utils';
17
18
  import { RGBAtoHex } from '@utils/helpers';
18
19
 
19
20
  const MAX_CUSTOM_REQUEST_CHARS = 500;
@@ -42,6 +43,10 @@ export default defineComponent({
42
43
  };
43
44
  },
44
45
  computed: {
46
+ contentPaddingStyle(): { paddingTop: string; paddingBottom: string } {
47
+ return toContentPaddingStyle(this.viewModel);
48
+ },
49
+
45
50
  isCustomerRequestDetailsValid(): boolean {
46
51
  return (
47
52
  !this.viewModel.requestPaymentConfig.isCustomerRequestDetailsEnabled ||
@@ -1,6 +1,7 @@
1
1
  <template>
2
2
  <div
3
3
  data-component="request-payment"
4
+ :style="contentPaddingStyle"
4
5
  :class="{
5
6
  'tw-my-8': context.isBrandSite,
6
7
  'tw-mb-4': context.isBrandPageOrIsBrandContact,
@@ -4,7 +4,10 @@ import { SUPPORT_ME_CUSTOM_PRODUCT_NAME } from '../../../constants';
4
4
  import type { BrandPageContext, PaymentOption } from '../../../models';
5
5
  import type { SupportMeViewModel } from '../../../view-models';
6
6
  import type { PaymentRequestDetails } from '../Payment.mixin';
7
- import { isPaymentAmountValid } from '../../../utils';
7
+ import {
8
+ isPaymentAmountValid,
9
+ contentPaddingStyle as toContentPaddingStyle,
10
+ } from '../../../utils';
8
11
  import {
9
12
  DEFAULT_CURRENCY_SYMBOL,
10
13
  DEFAULT_CURRENCY_CODE,
@@ -33,6 +36,10 @@ export default defineComponent({
33
36
  };
34
37
  },
35
38
  computed: {
39
+ contentPaddingStyle(): { paddingTop: string; paddingBottom: string } {
40
+ return toContentPaddingStyle(this.viewModel);
41
+ },
42
+
36
43
  isCustomAmountFieldVisible(): boolean {
37
44
  return this.viewModel.supportMeConfig.paymentOptions.some(
38
45
  (o) => o.name === SUPPORT_ME_CUSTOM_PRODUCT_NAME,
@@ -1,6 +1,7 @@
1
1
  <template>
2
2
  <div
3
3
  data-component="support-me"
4
+ :style="contentPaddingStyle"
4
5
  :class="{
5
6
  'tw-my-8': context.isBrandSite,
6
7
  'tw-mb-4': context.isBrandPageOrIsBrandContact,
@@ -5,15 +5,20 @@
5
5
  class="c-placeholder"
6
6
  :style="style"
7
7
  >
8
- <div class="c-placeholder__content" :style="cssProps" />
8
+ <svg
9
+ class="c-placeholder__icon"
10
+ viewBox="0 0 100 100"
11
+ preserveAspectRatio="none"
12
+ aria-hidden="true"
13
+ >
14
+ <rect class="c-placeholder__fill" width="100" height="100" />
15
+ <line x1="0" y1="0" x2="100" y2="100" />
16
+ <line x1="100" y1="0" x2="0" y2="100" />
17
+ </svg>
9
18
  </div>
10
19
  </template>
11
20
  <script>
12
- import debounce from 'lodash.debounce';
13
- const RESIZE_DEBOUNCE_WAIT_MS = 5;
14
-
15
21
  export default {
16
- components: {},
17
22
  props: {
18
23
  minHeight: {
19
24
  type: [Number, Boolean],
@@ -26,48 +31,14 @@ export default {
26
31
  required: false,
27
32
  },
28
33
  },
29
- data() {
30
- return {
31
- height: 0,
32
- width: 0,
33
- debouncedOnResize: undefined,
34
- };
35
- },
36
34
  computed: {
37
35
  style() {
38
36
  return {
39
37
  minHeight: this.minHeight ? `${this.minHeight}px` : undefined,
40
38
  minWidth: this.minWidth ? `${this.minWidth}px` : undefined,
41
- '--height': `${this.height}px`,
42
- '--width': `${this.width}px`,
43
- };
44
- },
45
- cssProps() {
46
- return {
47
- '--height': `${this.height}px`,
48
- '--width': `${this.width}px`,
49
39
  };
50
40
  },
51
41
  },
52
- mounted() {
53
- this.debouncedOnResize = debounce(this.onResize, RESIZE_DEBOUNCE_WAIT_MS);
54
-
55
- if (this.$refs.placeholder) {
56
- new ResizeObserver(this.debouncedOnResize).observe(
57
- this.$refs.placeholder,
58
- );
59
- }
60
-
61
- this.onResize();
62
- },
63
- methods: {
64
- onResize() {
65
- if (this.$refs.placeholder) {
66
- this.height = this.$refs.placeholder.clientHeight;
67
- this.width = this.$refs.placeholder.clientWidth;
68
- }
69
- },
70
- },
71
42
  };
72
43
  </script>
73
44
  <style scoped>
@@ -76,73 +47,41 @@ export default {
76
47
  display: block;
77
48
  }
78
49
 
79
- .c-placeholder__content {
50
+ /*
51
+ * Provide a positioning context for the absolute SVG icon — but only when the
52
+ * caller hasn't already positioned the placeholder itself. Some callers pass
53
+ * `tw-absolute` (e.g. the big-image banner uses it to fill the banner as a
54
+ * background); a blanket `position: relative` here would out-specify that
55
+ * utility and break the layout. An already-positioned placeholder is its own
56
+ * containing block, so the SVG fills it either way.
57
+ */
58
+ .c-placeholder:not(.tw-absolute):not(.tw-fixed) {
80
59
  position: relative;
81
- display: block;
82
- }
83
- .c-placeholder__content::after {
84
- --size: 1px;
85
- --n-size: -1px;
86
- --border: calc(var(--n-size) * 2 + var(--height) / 2);
87
- --border-left: calc(var(--n-size) * 2 + var(--width) / 2);
88
- --tw-border-opacity: 0.5;
89
- position: absolute;
90
- top: calc(var(--size) * 2);
91
- left: var(--size);
92
- content: ' ';
93
- border-top: var(--border) solid transparent;
94
- border-bottom: var(--border) solid transparent;
95
- border-left: var(--border-left) solid
96
- rgb(208 208 208 / var(--tw-border-opacity));
97
- }
98
- .c-placeholder__content::before {
99
- --size: 1px;
100
- --n-size: -1px;
101
- --border: calc(var(--n-size) * 2 + var(--height) / 2);
102
- --border-right: calc(var(--n-size) * 2 + var(--width) / 2);
103
- --tw-border-opacity: 0.5;
104
- position: absolute;
105
- top: calc(var(--size) * 2);
106
- right: var(--size);
107
- content: ' ';
108
- border-top: var(--border) solid transparent;
109
- border-bottom: var(--border) solid transparent;
110
- border-right: var(--border-right) solid
111
- rgb(208 208 208 / var(--tw-border-opacity));
112
60
  }
113
61
 
114
- .c-placeholder::after {
115
- --size: 1px;
116
- --n-size: -1px;
117
- --border: calc(var(--n-size) * 2 + var(--width) / 2);
118
- --border-right: calc(var(--n-size) * 2 + var(--height) / 2);
119
- --tw-border-opacity: 0.5;
62
+ /*
63
+ * The X icon is drawn as an SVG with preserveAspectRatio="none" so the
64
+ * diagonals always run corner-to-corner regardless of the box aspect ratio
65
+ * (square thumbnails through full-width 2/1 banners). vector-effect keeps the
66
+ * stroke an even width while the viewBox is stretched non-uniformly. The SVG
67
+ * is absolutely positioned so it fills the box sized by min-height / the
68
+ * caller's aspect-ratio class rather than driving the height itself.
69
+ */
70
+ .c-placeholder__icon {
120
71
  position: absolute;
121
- left: calc(var(--size) * 2);
122
- top: var(--size);
123
- content: ' ';
124
- border-left: var(--border) solid transparent;
125
- border-right: var(--border) solid transparent;
126
- border-top: var(--border-right) solid
127
- rgb(208 208 208 / var(--tw-border-opacity));
72
+ inset: 0;
73
+ display: block;
74
+ width: 100%;
75
+ height: 100%;
128
76
  }
129
- .c-placeholder::before {
130
- --size: 1px;
131
- --n-size: -1px;
132
- --border: calc(var(--n-size) * 2 + var(--width) / 2);
133
- --border-bottom: calc(var(--n-size) * 2 + var(--height) / 2);
134
- --tw-border-opacity: 0.5;
135
- position: absolute;
136
- left: calc(var(--size) * 2);
137
- bottom: var(--size);
138
- content: ' ';
139
- border-left: var(--border) solid transparent;
140
- border-right: var(--border) solid transparent;
141
- border-bottom: var(--border-bottom) solid
142
- rgb(208 208 208 / var(--tw-border-opacity));
77
+
78
+ .c-placeholder__fill {
79
+ fill: rgb(208 208 208 / 0.5);
143
80
  }
144
81
 
145
- .c-placeholder__content > * {
146
- padding-bottom: 0.5rem;
82
+ .c-placeholder__icon line {
83
+ stroke: #fff;
84
+ stroke-width: 2;
85
+ vector-effect: non-scaling-stroke;
147
86
  }
148
87
  </style>
@@ -1,11 +1,10 @@
1
1
  <template>
2
2
  <div data-component="social-links">
3
3
  <div
4
- class="tw-pb-8"
5
4
  :class="{
6
5
  'tw-mb-4': context.isBrandPageOrIsBrandContact,
7
6
  }"
8
- :style="containerStyles"
7
+ :style="[containerStyles, contentPaddingStyle]"
9
8
  style="container-type: inline-size"
10
9
  >
11
10
  <TextWrapper
@@ -14,7 +13,7 @@
14
13
  :text="title"
15
14
  element="h1"
16
15
  :class="textAlignClass"
17
- class="tw-py-8"
16
+ class="tw-pb-8"
18
17
  />
19
18
  <SocialLinksItems
20
19
  :id="id"
@@ -34,6 +33,7 @@ import TextWrapper from '../text-wrapper/TextWrapper.vue';
34
33
  import type { SocialLinksViewModel } from 'src/brand-page/view-models';
35
34
  import { SOCIAL_LINKS_ICON_DISPLAY_STYLES } from '@brand-page/models';
36
35
  import type { BrandPageContext, LinksItem } from '@brand-page/models';
36
+ import { contentPaddingStyle as toContentPaddingStyle } from '@brand-page/utils';
37
37
  import { computed } from 'vue';
38
38
 
39
39
  const props = withDefaults(
@@ -51,6 +51,10 @@ const containerStyles = computed((): BrandPageCssStyle => {
51
51
  return props.viewModel.backgroundStyles || {};
52
52
  });
53
53
 
54
+ const contentPaddingStyle = computed(() =>
55
+ toContentPaddingStyle(props.viewModel),
56
+ );
57
+
54
58
  const iconStyle = computed((): BrandPageCssStyle => {
55
59
  return props.viewModel.iconFillStyles || {};
56
60
  });