@designcrowd/library.brand-page 5.10.20 → 5.10.31

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 (146) hide show
  1. package/lib/src/brand-page/constants/font.constants.d.ts +4 -4
  2. package/lib/src/brand-page/models/index.d.ts +5 -0
  3. package/lib/src/brand-page/models/index.js +4 -0
  4. package/lib/src/brand-page/models/styles.model.d.ts +5 -5
  5. package/lib/src/brand-page/utils/style.util.d.ts +8 -1
  6. package/lib/src/brand-page/utils/style.util.js +58 -5
  7. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.stories.js +2 -2
  8. package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.js +1 -1
  9. package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/content-settings-items.fixture.js +1 -0
  10. package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/page-content-items.d.ts +1 -1
  11. package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/page-content-items.js +2 -1
  12. package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +33 -0
  13. package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.js +35 -1
  14. package/lib/src/brand-page-maker/components/navigation/Navigation.mixin.d.ts +2 -2
  15. package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.d.ts +3 -3
  16. package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.d.ts +1 -0
  17. package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.js +17 -0
  18. package/lib/src/brand-page-maker/components/upgrade-to-premium-button/UpgradeToPremiumButton.mixin.d.ts +2 -2
  19. package/lib/src/brand-page-maker/composables/rich-text-editor/bubbleMenu.d.ts +19 -0
  20. package/lib/src/brand-page-maker/composables/rich-text-editor/bubbleMenu.js +31 -0
  21. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/AutoLink.d.ts +2 -0
  22. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/AutoLink.js +161 -0
  23. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/MaxLength.js +3 -3
  24. package/lib/src/brand-page-maker/composables/rich-text-editor/font.d.ts +1 -1
  25. package/lib/src/brand-page-maker/composables/rich-text-editor/font.js +0 -1
  26. package/lib/src/brand-page-maker/composables/rich-text-editor/formatting.d.ts +1 -1
  27. package/lib/src/brand-page-maker/composables/rich-text-editor/formatting.js +0 -1
  28. package/lib/src/brand-page-maker/composables/rich-text-editor/hyperlink.d.ts +19 -0
  29. package/lib/src/brand-page-maker/composables/rich-text-editor/hyperlink.js +87 -0
  30. package/lib/src/brand-page-maker/composables/rich-text-editor/spacing.d.ts +1 -1
  31. package/lib/src/brand-page-maker/composables/rich-text-editor/spacing.js +0 -1
  32. package/lib/src/brand-page-maker/composables/rich-text-editor/textAlign.d.ts +1 -1
  33. package/lib/src/brand-page-maker/composables/rich-text-editor/textAlign.js +0 -1
  34. package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.d.ts +24 -3
  35. package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.js +214 -33
  36. package/lib/src/brand-page-maker/constants/brandpage-meta-constant.d.ts +5 -5
  37. package/lib/src/brand-page-maker/constants/index.d.ts +2 -2
  38. package/lib/src/brand-page-maker/models/button-group.model.d.ts +2 -0
  39. package/lib/src/brand-page-maker/utils/rich-text-editor.util.d.ts +19 -2
  40. package/lib/src/brand-page-maker/utils/rich-text-editor.util.js +340 -8
  41. package/lib/src/bundled-translations-BXxQYq2i.js +119 -0
  42. package/lib/src/bundled-translations.de-DE-BXcluMZ2.js +119 -0
  43. package/lib/src/{bundled-translations.de-DE-O4sKkzBX.js → bundled-translations.de-DE-DjQFwukR.js} +1 -1
  44. package/lib/src/{bundled-translations.es-ES-C4lGaf08.js → bundled-translations.es-ES--EbGRI7e.js} +1 -1
  45. package/lib/src/bundled-translations.es-ES-DSd-wV16.js +119 -0
  46. package/lib/src/{bundled-translations.fr-FR-CIy8KjAV.js → bundled-translations.fr-FR-VtC2JYUC.js} +1 -1
  47. package/lib/src/bundled-translations.fr-FR-jKR_dxWR.js +119 -0
  48. package/lib/src/bundled-translations.pt-PT-CwvYqXXo.js +119 -0
  49. package/lib/src/{bundled-translations.pt-PT-C8EcSdyX.js → bundled-translations.pt-PT-l9cEldEo.js} +1 -1
  50. package/lib/src/bundles/bundled-translations.de-DE.json +11 -0
  51. package/lib/src/bundles/bundled-translations.es-ES.json +11 -0
  52. package/lib/src/bundles/bundled-translations.fr-FR.json +13 -2
  53. package/lib/src/bundles/bundled-translations.json +11 -0
  54. package/lib/src/bundles/bundled-translations.pt-PT.json +11 -0
  55. package/lib/src/composables/useTranslate.d.ts +64 -62
  56. package/lib/src/composables/useTranslate.js +18 -7
  57. package/lib/src/css/library.brand-page-brandCrowd.min.css +101 -75
  58. package/lib/src/css/library.brand-page-brandPage.min.css +101 -75
  59. package/lib/src/css/library.brand-page-designCom.min.css +101 -75
  60. package/lib/src/css/library.brand-page-preview.min.css +101 -75
  61. package/lib/src/index.d.ts +3 -1
  62. package/lib/src/index.mjs +30209 -27738
  63. package/lib/src/lib.js +2 -1
  64. package/lib/src/mockServiceWorker.js +91 -54
  65. package/lib/src/shared/content-settings/components/GenericTextInput.mixin.d.ts +2 -2
  66. package/lib/src/shared/content-settings/components/color-field/ColorField.mixin.d.ts +11 -0
  67. package/lib/src/shared/content-settings/components/color-field/ColorField.mixin.js +5 -0
  68. package/lib/src/shared/content-settings/components/email-field/EmailField.mixin.d.ts +2 -2
  69. package/lib/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.mixin.d.ts +11 -1
  70. package/lib/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.mixin.js +4 -0
  71. package/lib/src/shared/content-settings/components/shape-field/ShapeField.mixin.d.ts +1 -1
  72. package/lib/src/shared/content-settings/components/tel-field/TelField.mixin.d.ts +2 -2
  73. package/lib/src/shared/content-settings/components/testimonial-items-field/TestimonialItemsField.mixin.d.ts +2 -2
  74. package/lib/src/shared/content-settings/components/text-field/TextField.mixin.d.ts +2 -2
  75. package/lib/src/shared/content-settings/components/text-image-field/TextImageField.mixin.d.ts +2 -2
  76. package/lib/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.d.ts +2 -2
  77. package/lib/src/shared/content-settings/components/textarea-field/TextareaField.mixin.d.ts +2 -2
  78. package/lib/src/shared/content-settings/components/url-field/UrlField.mixin.d.ts +4 -2
  79. package/lib/src/shared/content-settings/components/url-field/UrlField.mixin.js +12 -7
  80. package/lib/src/shared/content-settings/components/youtube-video-field/YoutubeVideoField.mixin.d.ts +2 -2
  81. package/lib/src/shared/logo-settings/components/EditLogoSettings.mixin.d.ts +3 -3
  82. package/lib/src/shared/my-uploads/MyUploads.mixin.d.ts +1 -1
  83. package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +1 -1
  84. package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +4 -2
  85. package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +4 -4
  86. package/lib/src/shared/shape-library/ShapeLibrary.mixin.d.ts +1 -1
  87. package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +2 -2
  88. package/lib/src/shared/template-settings/models.d.ts +3 -3
  89. package/package.json +6 -3
  90. package/src/brand-page/components/banner-section/BannerSection.vue +6 -0
  91. package/src/brand-page/components/sensitive-content/SensitiveContentModal.vue +28 -11
  92. package/src/brand-page/components/sensitive-content/i18n/sensitive-content-modal.de-DE.json +13 -0
  93. package/src/brand-page/components/sensitive-content/i18n/sensitive-content-modal.es-ES.json +13 -0
  94. package/src/brand-page/components/sensitive-content/i18n/sensitive-content-modal.fr-FR.json +13 -0
  95. package/src/brand-page/components/sensitive-content/i18n/sensitive-content-modal.json +13 -0
  96. package/src/brand-page/components/sensitive-content/i18n/sensitive-content-modal.pt-PT.json +13 -0
  97. package/src/brand-page/components/text/Text.vue +2 -0
  98. package/src/brand-page/components/text-wrapper/TextWrapper.vue +31 -11
  99. package/src/brand-page/models/index.ts +6 -0
  100. package/src/brand-page/utils/style.util.ts +105 -5
  101. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.stories.ts +2 -2
  102. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.ts +1 -1
  103. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/content-settings-items.fixture.ts +1 -0
  104. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/page-content-items.ts +2 -0
  105. package/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.ts +44 -1
  106. package/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.vue +1 -0
  107. package/src/brand-page-maker/components/brandpage-settings/i18n/brand-page-settings.fr-FR.json +1 -1
  108. package/src/brand-page-maker/components/google-analytics/i18n/google-analytics.fr-FR.json +1 -1
  109. package/src/brand-page-maker/components/rich-text-editor/RichTextEditor.vue +539 -50
  110. package/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.ts +22 -0
  111. package/src/brand-page-maker/components/template-preview/TemplatePreview.vue +1 -1
  112. package/src/brand-page-maker/composables/rich-text-editor/bubbleMenu.ts +42 -0
  113. package/src/brand-page-maker/composables/rich-text-editor/extensions/AutoLink.ts +227 -0
  114. package/src/brand-page-maker/composables/rich-text-editor/extensions/MaxLength.test.ts +1 -1
  115. package/src/brand-page-maker/composables/rich-text-editor/extensions/MaxLength.ts +4 -15
  116. package/src/brand-page-maker/composables/rich-text-editor/font.ts +1 -1
  117. package/src/brand-page-maker/composables/rich-text-editor/formatting.ts +1 -1
  118. package/src/brand-page-maker/composables/rich-text-editor/hyperlink.ts +114 -0
  119. package/src/brand-page-maker/composables/rich-text-editor/spacing.ts +1 -1
  120. package/src/brand-page-maker/composables/rich-text-editor/textAlign.ts +1 -1
  121. package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.ts +299 -41
  122. package/src/brand-page-maker/models/button-group.model.ts +2 -0
  123. package/src/brand-page-maker/stores/brandpage-maker/__snapshots__/brandpage-maker-store.test.ts.snap +1 -0
  124. package/src/brand-page-maker/utils/rich-text-editor.util.test.ts +418 -0
  125. package/src/brand-page-maker/utils/rich-text-editor.util.ts +470 -25
  126. package/src/bundles/bundled-translations.de-DE.json +11 -0
  127. package/src/bundles/bundled-translations.es-ES.json +11 -0
  128. package/src/bundles/bundled-translations.fr-FR.json +13 -2
  129. package/src/bundles/bundled-translations.json +11 -0
  130. package/src/bundles/bundled-translations.pt-PT.json +11 -0
  131. package/src/composables/useTranslate.ts +25 -8
  132. package/src/lib.ts +7 -1
  133. package/src/shared/content-settings/components/color-field/ColorField.mixin.ts +5 -0
  134. package/src/shared/content-settings/components/color-field/ColorField.vue +1 -1
  135. package/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.mixin.ts +4 -0
  136. package/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.vue +2 -2
  137. package/src/shared/content-settings/components/text-field/TextField.vue +1 -1
  138. package/src/shared/content-settings/components/text-items-field/TextItemsField.vue +2 -2
  139. package/src/shared/content-settings/components/textarea-field/TextareaField.vue +3 -3
  140. package/src/shared/content-settings/components/url-field/UrlField.mixin.ts +15 -10
  141. package/src/shared/content-settings/components/url-field/UrlField.vue +1 -0
  142. package/lib/src/bundled-translations-DaK60m67.js +0 -117
  143. package/lib/src/bundled-translations.de-DE-848cpWPB.js +0 -117
  144. package/lib/src/bundled-translations.es-ES-CtPI5G7I.js +0 -117
  145. package/lib/src/bundled-translations.fr-FR-CTnDppmf.js +0 -117
  146. package/lib/src/bundled-translations.pt-PT-Balnne-7.js +0 -117
@@ -872,10 +872,10 @@ declare const _default: import("vue").DefineComponent<{}, {
872
872
  isRenderedInStorybook(): boolean;
873
873
  isWidthToggled(): boolean;
874
874
  brandName(): "Design.com" | "BrandCrowd";
875
- hideText(): string;
875
+ hideText(): any;
876
876
  }, {
877
877
  onColorPickerSelected(value: boolean): void;
878
- getButtonStyleConfigOptionTitle(option: ButtonStyleConfigOption): string;
878
+ getButtonStyleConfigOptionTitle(option: ButtonStyleConfigOption): any;
879
879
  getButtonStylesForUi(buttonStyles: BrandPageCssStyle): BrandPageCssStyle;
880
880
  onColorMatchToggled(option: ButtonStyleConfigOption | OtherStyleConfigOption, value: boolean): void;
881
881
  onColorPickerInput(option: ButtonStyleConfigOption, payload: UpdateItemValuePayload<string | Event | undefined>): void;
@@ -13,9 +13,9 @@ export declare const TEMPLATE_TABS: {
13
13
  };
14
14
  export type TemplateTab = keyof typeof TEMPLATE_TABS;
15
15
  export declare const TEMPLATE_TAB_DISPLAY_NAMES: () => {
16
- all: string;
17
- categories: string;
18
- AI: string;
16
+ all: any;
17
+ categories: any;
18
+ AI: any;
19
19
  };
20
20
  export interface OnTemplateSelectedPayload {
21
21
  templateId: string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@designcrowd/library.brand-page",
3
3
  "description": "A collection of Maker/Designer applications",
4
- "version": "5.10.20",
4
+ "version": "5.10.31",
5
5
  "author": "Design.com Eng",
6
6
  "license": "UNLICENSED",
7
7
  "type": "module",
@@ -55,9 +55,10 @@
55
55
  },
56
56
  "dependencies": {
57
57
  "@ckpack/vue-color": "1.4.1",
58
- "@designcrowd/fe-shared-lib": "1.2.7",
58
+ "@designcrowd/fe-shared-lib": "1.2.11",
59
59
  "@pinia/nuxt": "0.11.0",
60
60
  "@storybook/react": "9.0.4",
61
+ "@tiptap/extension-bubble-menu": "^2.14.0",
61
62
  "@tiptap/extension-character-count": "2.11.7",
62
63
  "@tiptap/extension-color": "2.11.5",
63
64
  "@tiptap/extension-font-family": "2.11.5",
@@ -79,6 +80,7 @@
79
80
  "css-color-names": "1.0.1",
80
81
  "date-utils": "1.2.21",
81
82
  "deepmerge": "4.3.1",
83
+ "dompurify": "3.2.6",
82
84
  "dropzone-vue3": "1.0.2",
83
85
  "express": "4.18.2",
84
86
  "fs-extra": "11.2.0",
@@ -102,11 +104,11 @@
102
104
  "validator": "13.11.0",
103
105
  "vue": "3.5.15",
104
106
  "vue-cropperjs": "5.0.0",
105
- "vuedraggable": "4.1.0",
106
107
  "vue-router": "4.5.0",
107
108
  "vue-select": "4.0.0-beta.6",
108
109
  "vue3-lazy-hydration": "1.2.1",
109
110
  "vue3-shortkey": "4.0.0",
111
+ "vuedraggable": "4.1.0",
110
112
  "vuex": "4.1.0"
111
113
  },
112
114
  "peerDependencies": {
@@ -134,6 +136,7 @@
134
136
  "@stylistic/eslint-plugin": "1.5.4",
135
137
  "@types/axios-mock-adapter": "1.10.0",
136
138
  "@types/braces": "3.0.4",
139
+ "@types/dompurify": "3.2.0",
137
140
  "@types/express": "4.17.21",
138
141
  "@types/faker": "6.6.8",
139
142
  "@types/google.maps": "3.55.1",
@@ -81,12 +81,14 @@
81
81
  v-if="viewModel.title"
82
82
  :text-style="viewModel.titleStyle"
83
83
  :text="viewModel.title"
84
+ :slug="context.brandPageSlug"
84
85
  element="h1"
85
86
  />
86
87
  <TextWrapper
87
88
  v-if="hasDescriptionText"
88
89
  :text-style="viewModel.descriptionStyle"
89
90
  :text="renderText"
91
+ :slug="context.brandPageSlug"
90
92
  element="div"
91
93
  />
92
94
  <div class="tw-w-full tw-flex" :class="displayButtonClass">
@@ -120,12 +122,14 @@
120
122
  v-if="viewModel.title"
121
123
  :text-style="viewModel.titleStyle"
122
124
  :text="viewModel.title"
125
+ :slug="context.brandPageSlug"
123
126
  element="h1"
124
127
  />
125
128
  <TextWrapper
126
129
  v-if="hasDescriptionText"
127
130
  :text-style="viewModel.descriptionStyle"
128
131
  :text="renderText"
132
+ :slug="context.brandPageSlug"
129
133
  element="div"
130
134
  />
131
135
  <div class="tw-w-full tw-flex" :class="displayButtonClass">
@@ -201,12 +205,14 @@
201
205
  v-if="viewModel.title"
202
206
  :text-style="viewModel.titleStyle"
203
207
  :text="viewModel.title"
208
+ :slug="context.brandPageSlug"
204
209
  element="h1"
205
210
  />
206
211
  <TextWrapper
207
212
  v-if="hasDescriptionText"
208
213
  :text-style="viewModel.descriptionStyle"
209
214
  :text="renderText"
215
+ :slug="context.brandPageSlug"
210
216
  element="div"
211
217
  />
212
218
  <div class="tw-w-full tw-flex" :class="displayButtonClass">
@@ -13,6 +13,7 @@
13
13
  <template #default>
14
14
  <div class="modal-content-container">
15
15
  <div
16
+ v-if="modalConfig.title"
16
17
  class="tw-flex tw-flex-col tw-items-center tw-py-2 tw-px-4 tw-text-white tw-bg-black"
17
18
  >
18
19
  <Icon name="eye-crossed" size="md" />
@@ -22,16 +23,16 @@
22
23
  </p>
23
24
  <div v-if="type === 'age'" class="button-container">
24
25
  <button class="primary-button" @click="onConfirmClicked">
25
- I'm over {{ ageRequirement }}
26
+ {{ imOver }}
26
27
  </button>
27
28
  <button class="secondary-button" @click="rejectAge">
28
- I'm under {{ ageRequirement }}
29
+ {{ imUnder }}
29
30
  </button>
30
31
  </div>
31
32
 
32
33
  <div v-if="type === 'sensitive'" class="button-container">
33
34
  <button class="primary-button" @click="onConfirmClicked">
34
- I Confirm
35
+ {{ iConfirm }}
35
36
  </button>
36
37
  </div>
37
38
  </div>
@@ -41,9 +42,10 @@
41
42
  </template>
42
43
 
43
44
  <script setup lang="ts">
44
- import { ref, computed, onMounted, watch } from 'vue';
45
+ import { ref, computed, watch } from 'vue';
45
46
  import { Modal, Icon } from '@designcrowd/fe-shared-lib';
46
47
  import { SENSITIVE_CONTENT_TYPES } from '../../';
48
+ import { sensitiveContentModalTr } from '../../../../src/composables/useTranslate';
47
49
 
48
50
  const props = defineProps({
49
51
  sensitiveContentState: {
@@ -75,20 +77,35 @@ const ageRequirement = computed(() => {
75
77
 
76
78
  const type = ref(verificationType.value);
77
79
 
80
+ const imOver = computed(() =>
81
+ sensitiveContentModalTr('iAcceptAgeButtonLabel', {
82
+ REQUIRED_MINIMUM_AGE: ageRequirement.value,
83
+ }),
84
+ );
85
+
86
+ const imUnder = computed(() =>
87
+ sensitiveContentModalTr('iDenyAgeButtonLabel', {
88
+ REQUIRED_MINIMUM_AGE: ageRequirement.value,
89
+ }),
90
+ );
91
+
92
+ const iConfirm = computed(() => sensitiveContentModalTr('iConfirmButtonLabel'));
93
+
78
94
  const modalConfig = computed(() => {
79
95
  const configs = {
80
96
  age: {
81
- title: 'Sensitive Content',
82
- message: `Confirm that you are of legal age to view this content`,
97
+ title: sensitiveContentModalTr('ageRestrictionDisplayTitle'),
98
+ message: sensitiveContentModalTr('ageRestrictionMessage'),
83
99
  },
84
100
  sensitive: {
85
- title: 'Sensitive Content',
86
- message:
87
- 'Confirm that you are willing to see potentially sensitive content',
101
+ title: sensitiveContentModalTr('sensitiveContentDisplayTitle'),
102
+ message: sensitiveContentModalTr('sensitiveContentmessage'),
88
103
  },
89
104
  rejected: {
90
- title: 'You cannot visit this site',
91
- message: `Access is restricted to users ${ageRequirement.value} and older`,
105
+ title: sensitiveContentModalTr('rejectedDisplayTitle'),
106
+ message: sensitiveContentModalTr('rejectedDisplayTMessage', {
107
+ REQUIRED_MINIMUM_AGE: ageRequirement.value,
108
+ }),
92
109
  },
93
110
  };
94
111
  return configs[type.value] || configs.sensitive;
@@ -0,0 +1,13 @@
1
+ {
2
+ "sensitiveContentModal" : {
3
+ "sensitiveContentDisplayTitle" : "Sensible Inhalte",
4
+ "sensitiveContentmessage" : "Bestätigen Sie, dass Sie bereit sind, potenziell sensible Inhalte zu sehen",
5
+ "ageRestrictionDisplayTitle" : "Sensible Inhalte",
6
+ "ageRestrictionMessage" : "Bestätigen Sie, dass Sie volljährig sind, um diesen Inhalt anzusehen",
7
+ "rejectedDisplayTitle" : "Sie können diese Seite nicht besuchen",
8
+ "rejectedDisplayTMessage" : "Der Zugang ist auf Benutzer ab {{REQUIRED_MINIMUM_AGE}} Jahren beschränkt.",
9
+ "iAcceptAgeButtonLabel" : "Ich bin älter als {{REQUIRED_MINIMUM_AGE}}.",
10
+ "iDenyAgeButtonLabel" : "Ich bin jünger als {{REQUIRED_MINIMUM_AGE}}.",
11
+ "iConfirmButtonLabel" : "Ich bestätige"
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "sensitiveContentModal" : {
3
+ "sensitiveContentDisplayTitle" : "Contenido sensible",
4
+ "sensitiveContentmessage" : "Confirma que estás dispuesto a ver contenido potencialmente sensible",
5
+ "ageRestrictionDisplayTitle" : "Contenido sensible",
6
+ "ageRestrictionMessage" : "Confirma que tienes la edad legal para ver este contenido",
7
+ "rejectedDisplayTitle" : "No puedes visitar este sitio",
8
+ "rejectedDisplayTMessage" : "El acceso está restringido a usuarios de {{REQUIRED_MINIMUM_AGE}} años o más",
9
+ "iAcceptAgeButtonLabel" : "Estoy harto de {{REQUIRED_MINIMUM_AGE}}",
10
+ "iDenyAgeButtonLabel" : "Tengo menos de {{REQUIRED_MINIMUM_AGE}} años",
11
+ "iConfirmButtonLabel" : "Confirmo"
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "sensitiveContentModal" : {
3
+ "sensitiveContentDisplayTitle" : "Contenu sensible",
4
+ "sensitiveContentmessage" : "Confirmez que vous êtes prêt à voir du contenu potentiellement sensible",
5
+ "ageRestrictionDisplayTitle" : "Contenu sensible",
6
+ "ageRestrictionMessage" : "Confirmez que vous avez l'âge légal pour voir ce contenu",
7
+ "rejectedDisplayTitle" : "Vous ne pouvez pas visiter ce site",
8
+ "rejectedDisplayTMessage" : "L'accès est restreint aux utilisateurs de {{REQUIRED_MINIMUM_AGE}} ans et plus",
9
+ "iAcceptAgeButtonLabel" : "J'ai plus de {{REQUIRED_MINIMUM_AGE}} ans",
10
+ "iDenyAgeButtonLabel" : "J'ai moins de {{REQUIRED_MINIMUM_AGE}} ans",
11
+ "iConfirmButtonLabel" : "Je confirme"
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "sensitiveContentModal": {
3
+ "sensitiveContentDisplayTitle": "Sensitive Content",
4
+ "sensitiveContentmessage": "Confirm that you are willing to see potentially sensitive content",
5
+ "ageRestrictionDisplayTitle": "Sensitive Content",
6
+ "ageRestrictionMessage": "Confirm that you are of legal age to view this content",
7
+ "rejectedDisplayTitle": "You cannot visit this site",
8
+ "rejectedDisplayTMessage": "Access is restricted to users {{REQUIRED_MINIMUM_AGE}} and older",
9
+ "iAcceptAgeButtonLabel": "I'm over {{REQUIRED_MINIMUM_AGE}}",
10
+ "iDenyAgeButtonLabel": "I'm under {{REQUIRED_MINIMUM_AGE}}",
11
+ "iConfirmButtonLabel": "I Confirm"
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "sensitiveContentModal" : {
3
+ "sensitiveContentDisplayTitle" : "Conteúdo sensível",
4
+ "sensitiveContentmessage" : "Confirme que está disposto a ver conteúdo potencialmente sensível",
5
+ "ageRestrictionDisplayTitle" : "Conteúdo sensível",
6
+ "ageRestrictionMessage" : "Confirme que tem idade legal para visualizar este conteúdo",
7
+ "rejectedDisplayTitle" : "Não pode visitar este site",
8
+ "rejectedDisplayTMessage" : "O acesso é restrito a utilizadores com {{REQUIRED_MINIMUM_AGE}} anos ou mais",
9
+ "iAcceptAgeButtonLabel" : "Estou farto de {{REQUIRED_MINIMUM_AGE}}",
10
+ "iDenyAgeButtonLabel" : "Tenho menos de {{REQUIRED_MINIMUM_AGE}}",
11
+ "iConfirmButtonLabel" : "Confirmo"
12
+ }
13
+ }
@@ -10,6 +10,7 @@
10
10
  <TextWrapper
11
11
  :text-style="viewModel.textStyle"
12
12
  :text="renderText"
13
+ :slug="context.brandPageSlug"
13
14
  element="div"
14
15
  data-test-tag="text-content-text"
15
16
  />
@@ -27,6 +28,7 @@
27
28
  :key="index"
28
29
  :text-style="item.textStyle"
29
30
  :text="renderTextItem(item.text)"
31
+ :slug="context.brandPageSlug"
30
32
  element="div"
31
33
  class="tw-overflow-hidden"
32
34
  data-test-tag="text-content-text-item"
@@ -1,15 +1,15 @@
1
1
  <template>
2
- <div v-if="text" class="tw-w-full" :style="data.wrapperStyle">
2
+ <div v-if="sanitizeText" class="tw-w-full" :style="data.wrapperStyle">
3
3
  <div
4
4
  class="tw-w-full empty-para"
5
5
  :style="isRTEContent ? textStyleRTE : style"
6
6
  >
7
7
  <component
8
8
  :is="element"
9
- :class="padding"
10
- class="tw-box-decoration-clone tw-inline"
9
+ :class="[padding, { 'tw-inline': !isRTEContent }]"
10
+ class="tw-box-decoration-clone"
11
11
  :style="isRTEContent ? {} : textStyles"
12
- v-html="text"
12
+ v-html="sanitizeText"
13
13
  />
14
14
  </div>
15
15
  </div>
@@ -30,6 +30,7 @@ interface Props {
30
30
  textStyle: TextStyleDeclaration | undefined;
31
31
  text: string;
32
32
  element?: string;
33
+ slug?: string;
33
34
  }
34
35
 
35
36
  const props = withDefaults(defineProps<Props>(), {
@@ -72,23 +73,42 @@ const isRTEContent = computed(() => {
72
73
  return hasRTEContent(props.text);
73
74
  });
74
75
 
76
+ const sanitizeText = computed(() => {
77
+ const brandPageSlug = props.slug;
78
+
79
+ if (!brandPageSlug || !props.text.includes('<a ')) {
80
+ return props.text;
81
+ }
82
+
83
+ // Transform internal page links by adding brandPageSlug
84
+ return props.text.replace(
85
+ /<a\s+([^>]*?)href="([^"]*?)"([^>]*?)>/gi,
86
+ (match, existingAttrsStart, href, existingAttrsEnd) => {
87
+ // Only process internal links (no protocol, doesn't start with /)
88
+ if (href && !href.match(/^(https?:\/\/|\/)/)) {
89
+ return `<a ${existingAttrsStart}href="/${brandPageSlug}/${href}"${existingAttrsEnd}>`;
90
+ }
91
+ return match;
92
+ },
93
+ );
94
+ });
95
+
75
96
  const fontSize = computed<any>(() => props.textStyle.fontSize);
76
97
 
77
98
  watch(fontSize, () => {
78
99
  applyScale();
79
100
  });
80
101
 
81
- watch(
82
- () => props.text,
83
- () => {
84
- applyScale();
85
- },
86
- );
102
+ watch(sanitizeText, () => {
103
+ applyScale();
104
+ });
87
105
 
88
106
  const currentInstance = getCurrentInstance();
89
107
 
90
108
  const padding = computed(() =>
91
- props.textStyle.backgroundColor ? 'tw-py-2 tw-px-4' : '',
109
+ props.textStyle.backgroundColor && !isRTEContent.value
110
+ ? 'tw-py-2 tw-px-4'
111
+ : '',
92
112
  );
93
113
 
94
114
  onMounted(() => {
@@ -344,6 +344,12 @@ export const BUTTON_LINK_TYPE = {
344
344
  } as const;
345
345
  export type ButtonLinkType = keyof typeof BUTTON_LINK_TYPE;
346
346
 
347
+ export const HYPERLINK_TYPE = {
348
+ url: 'url',
349
+ page: 'page',
350
+ } as const;
351
+ export type HyperlinkType = keyof typeof HYPERLINK_TYPE;
352
+
347
353
  export const URL_TYPE = {
348
354
  url: 'url',
349
355
  email: 'email',
@@ -27,6 +27,7 @@ import {
27
27
  getNewColorBasedOnTargetColorTheme,
28
28
  } from './color.util';
29
29
  import chroma from 'chroma-js';
30
+ import { hasRTEContent } from '../../brand-page-maker/utils';
30
31
 
31
32
  const MIN_LUM_RATIO = 0.3;
32
33
 
@@ -56,7 +57,7 @@ const parseFabricColorToCssStyle = (fabricColor: any): ThemeColor => {
56
57
  * @param colorData { rgb: 'rgb(0,255,0)', gradient: 'linear-gradient(180deg, rgb(0,0,0), rgb(255,0,0), 100%)'}
57
58
  * @returns string - rgb() or linear-gradient()
58
59
  */
59
- const getColorValueForCorrectCssProperty = (
60
+ export const getColorValueForCorrectCssProperty = (
60
61
  k: string,
61
62
  colorData: ThemeColor,
62
63
  ): string => {
@@ -100,8 +101,9 @@ export const colorMatchCssKeyValue = (
100
101
  }
101
102
 
102
103
  if (
103
- cssValue.match(new RegExp(STYLE_THEME_KEYS.LogoTextColor, 'g')) ||
104
- cssValue.match(new RegExp(STYLE_THEME_KEYS.LogoTextMultiColor, 'g'))
104
+ (cssValue.match(new RegExp(STYLE_THEME_KEYS.LogoTextColor, 'g')) ||
105
+ cssValue.match(new RegExp(STYLE_THEME_KEYS.LogoTextMultiColor, 'g'))) &&
106
+ !hasRTEContent(cssValue)
105
107
  ) {
106
108
  cssValue = getColorValueForCorrectCssProperty(
107
109
  cssKey,
@@ -110,8 +112,11 @@ export const colorMatchCssKeyValue = (
110
112
 
111
113
  return { cssValue, isModified: true };
112
114
  } else if (
113
- cssValue.match(new RegExp(STYLE_THEME_KEYS.LogoBackgroundColor, 'g')) ||
114
- cssValue.match(new RegExp(STYLE_THEME_KEYS.LogoBackgroundMultiColor, 'g'))
115
+ (cssValue.match(new RegExp(STYLE_THEME_KEYS.LogoBackgroundColor, 'g')) ||
116
+ cssValue.match(
117
+ new RegExp(STYLE_THEME_KEYS.LogoBackgroundMultiColor, 'g'),
118
+ )) &&
119
+ !hasRTEContent(cssValue)
115
120
  ) {
116
121
  cssValue = getColorValueForCorrectCssProperty(
117
122
  cssKey,
@@ -367,6 +372,9 @@ const CONTENT_STYLE_PROP_NAME_SUFFIX = [
367
372
  'Replacements',
368
373
  ];
369
374
 
375
+ const RTE_ALLOWED_SECTION_TYPES = ['text', 'banner-section'];
376
+ const RTE_ALLOWED_FIELDS = ['title', 'description', 'text', 'textItems'];
377
+
370
378
  export const applyLogoThemeToContents = (
371
379
  logoTheme: LogoTheme,
372
380
  pages: PageModel[],
@@ -397,6 +405,22 @@ export const applyLogoThemeToContents = (
397
405
  isModified = isModified || isApplied;
398
406
  }
399
407
 
408
+ const rteContentKeys = RTE_ALLOWED_SECTION_TYPES.includes(content.type)
409
+ ? Object.keys(content).filter((k) => RTE_ALLOWED_FIELDS.includes(k))
410
+ : [];
411
+
412
+ for (const key of rteContentKeys) {
413
+ const { newRTEContent, isApplied } =
414
+ applyLogoThemeToBrandPageRTEContentColorsRecursive(
415
+ newContent[key],
416
+ logoTheme,
417
+ isModified,
418
+ );
419
+
420
+ newContent[key] = newRTEContent;
421
+ isModified = isModified || isApplied;
422
+ }
423
+
400
424
  return newContent;
401
425
  });
402
426
 
@@ -406,6 +430,82 @@ export const applyLogoThemeToContents = (
406
430
  return { pages: newPages, isModified };
407
431
  };
408
432
 
433
+ type RteContent = Record<string, string | any>;
434
+
435
+ const applyLogoThemeToBrandPageRTEContentColorsRecursive = (
436
+ content: string | RteContent | RteContent[],
437
+ logoTheme: LogoTheme,
438
+ isModified: boolean,
439
+ ): {
440
+ isApplied: boolean;
441
+ newRTEContent: RteContent | RteContent[] | string;
442
+ } => {
443
+ let isApplied = false;
444
+ let newRTEContent: RteContent | RteContent[] | string = {};
445
+
446
+ if (typeof content === 'string' && hasRTEContent(content)) {
447
+ newRTEContent = replaceRTEContentColors(content, logoTheme);
448
+ isApplied = true;
449
+ } else if (Array.isArray(content)) {
450
+ newRTEContent = content.map((item) => {
451
+ const { newRTEContent: recursiveContent, isApplied: recursiveIsApplied } =
452
+ applyLogoThemeToBrandPageRTEContentColorsRecursive(
453
+ item,
454
+ logoTheme,
455
+ isModified,
456
+ );
457
+
458
+ isApplied = recursiveIsApplied;
459
+
460
+ return recursiveContent;
461
+ });
462
+ } else if (typeof content === 'object') {
463
+ for (const [key, value] of Object.entries(content)) {
464
+ if (
465
+ RTE_ALLOWED_FIELDS.includes(key) &&
466
+ typeof value === 'string' &&
467
+ hasRTEContent(value)
468
+ ) {
469
+ newRTEContent[key] = replaceRTEContentColors(value, logoTheme);
470
+ isApplied = true;
471
+ } else {
472
+ newRTEContent[key] = value;
473
+ }
474
+ }
475
+ } else {
476
+ newRTEContent = content;
477
+ isApplied = false;
478
+ }
479
+
480
+ return { isApplied, newRTEContent };
481
+ };
482
+
483
+ const replaceRTEContentColors = (
484
+ content: string,
485
+ logoTheme: LogoTheme,
486
+ ): string => {
487
+ return content
488
+ .replace(
489
+ new RegExp(`var\\(--${STYLE_THEME_KEYS.LogoTextColor}\\)`, 'g'),
490
+ logoTheme.logoTextColor.rgb,
491
+ )
492
+ .replace(
493
+ new RegExp(`var\\(--${STYLE_THEME_KEYS.LogoBackgroundColor}\\)`, 'g'),
494
+ logoTheme.logoBackgroundColor.rgb,
495
+ )
496
+ .replace(
497
+ new RegExp(`var\\(--${STYLE_THEME_KEYS.LogoTextMultiColor}\\)`, 'g'),
498
+ logoTheme.logoTextColor.rgb,
499
+ )
500
+ .replace(
501
+ new RegExp(
502
+ `var\\(--${STYLE_THEME_KEYS.LogoBackgroundMultiColor}\\)`,
503
+ 'g',
504
+ ),
505
+ logoTheme.logoBackgroundColor.rgb,
506
+ );
507
+ };
508
+
409
509
  export const applyLogoThemeToBrandPageStyles = (
410
510
  logoTheme: LogoTheme,
411
511
  pageStyles: PageStyles,
@@ -291,7 +291,7 @@ export const Sample = (args, { globals }): any => {
291
291
  InitialiseMakerStores({});
292
292
 
293
293
  watchEffect(async () => {
294
- await setLocaleAsync(globals.locale || 'en-US');
294
+ await setLocaleAsync(globals.locale);
295
295
  renderKeyForForcedRerender.value++;
296
296
  });
297
297
 
@@ -324,7 +324,7 @@ export const Sample = (args, { globals }): any => {
324
324
  `,
325
325
  pinia: setupStoryPinia(),
326
326
  async beforeMount() {
327
- await setLocaleAsync(globals.locale || 'en-US');
327
+ await setLocaleAsync(globals.locale);
328
328
  this.show = true;
329
329
  },
330
330
  };
@@ -210,7 +210,7 @@ export const BRAND_SITE: BrandPageData = {
210
210
  color: 'logo-text-color',
211
211
  fontSize: '1.5rem',
212
212
  textAlign: 'center',
213
- fontFamily: 'Nunito',
213
+ fontFamily: 'Exo 2',
214
214
  lineHeight: '2rem',
215
215
  },
216
216
  colorReplacements: [
@@ -64,6 +64,7 @@ export const textContent: TextContent = {
64
64
  textSize: {},
65
65
  textStyle: {
66
66
  textAlign: DEFAULT_TEXT_ALIGN,
67
+ fontSize: '2em',
67
68
  },
68
69
  textAlignment: {},
69
70
  textColor: {},
@@ -13,11 +13,13 @@ import {
13
13
  pinterestLink,
14
14
  twitchLink,
15
15
  tiktokLink,
16
+ textContent,
16
17
  } from './content-settings-items.fixture';
17
18
 
18
19
  export const brandPageContentsSampleData = [
19
20
  logoContent,
20
21
  profileContent,
22
+ textContent,
21
23
  generalLink,
22
24
  websiteLink,
23
25
  emailLink,
@@ -32,6 +32,7 @@ import type { DebounceHandle } from 'lodash.debounce';
32
32
  import { transformToRTE } from '../../../brand-page-maker/utils';
33
33
  import { useExternalRichTextEditor } from '../../../brand-page-maker/composables/rich-text-editor/useRichTextEditor';
34
34
  import { useUiStyleSettingsStore } from '../../../shared/style-settings/store';
35
+ import { STYLE_THEME_KEYS } from '../../../brand-page/constants';
35
36
 
36
37
  export default defineComponent({
37
38
  mixins: [PageMixin],
@@ -70,6 +71,7 @@ export default defineComponent({
70
71
  () => brandPageMakerUserStore.features.canUseRichTextEditor,
71
72
  ),
72
73
  isAdmin: computed(() => brandPageMakerUserStore.isAdmin),
74
+ logoTheme: computed(() => uiStore.logoTheme),
73
75
  contentSettingsStore,
74
76
  brandPageMakerStore,
75
77
  brandPageContainerStore,
@@ -141,6 +143,35 @@ export default defineComponent({
141
143
  return this.isContentSelected ? item.id === this.selectedItemId : false;
142
144
  };
143
145
  },
146
+ styleHtml(): string {
147
+ if (!this.logoTheme) {
148
+ return '';
149
+ }
150
+
151
+ // Generate CSS variables for logo theme colors
152
+ const cssVariables = Object.entries(STYLE_THEME_KEYS)
153
+ .map(([key, value]) => {
154
+ const themeColor = key.includes('Background')
155
+ ? this.logoTheme.logoBackgroundColor
156
+ : this.logoTheme.logoTextColor;
157
+
158
+ if (themeColor?.rgb) {
159
+ return `--${value}: ${themeColor.rgb};`;
160
+ }
161
+
162
+ return '';
163
+ })
164
+ .filter(Boolean)
165
+ .join('\n ');
166
+
167
+ return cssVariables
168
+ ? `<style>
169
+ :root {
170
+ ${cssVariables}
171
+ }
172
+ </style>`
173
+ : '';
174
+ },
144
175
  },
145
176
  mounted() {
146
177
  this.dispatchViewPortChangeEvent();
@@ -255,11 +286,23 @@ export default defineComponent({
255
286
  (item.type === 'banner-section' || item.type === 'text') &&
256
287
  this.canUseRichTextEditor
257
288
  ) {
289
+ let selectedItem = item;
290
+
291
+ if (this.isAdmin) {
292
+ const currentItem = this.items.find(
293
+ (i: { id: string }) => i.id === item.id,
294
+ );
295
+
296
+ if (currentItem) {
297
+ selectedItem = currentItem.settings.content;
298
+ }
299
+ }
300
+
258
301
  transformToRTE(
259
302
  this.pageSettingsStore,
260
303
  this.externalEditor,
261
304
  this.styleSettingsStore,
262
- item as Content,
305
+ selectedItem as Content,
263
306
  );
264
307
  }
265
308