@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
@@ -1,9 +1,10 @@
1
1
  import type { ChainedCommands, Editor } from '@tiptap/vue-3';
2
- import { EditorState, Transaction, Selection } from 'prosemirror-state';
3
- import type { Content, TextStyleDeclaration, TextStyleType } from '../../brand-page';
2
+ import type { EditorState, Transaction, Selection } from 'prosemirror-state';
3
+ import { type Content, type TextStyleDeclaration, type TextStyleType } from '../../brand-page';
4
4
  import type { PageSettingsState } from '../../shared/page-settings/store';
5
5
  import type { StyleSettingsState } from '../../shared/style-settings/store';
6
6
  import type { Mark } from 'prosemirror-model';
7
+ import { type DOMPurify } from 'dompurify';
7
8
  export declare const isStyleChanged: (tr: Transaction) => boolean;
8
9
  export declare const skipStyleDetection: (chain: ChainedCommands, marks?: Mark[]) => ChainedCommands;
9
10
  export declare const hasRTEContent: (content: string) => boolean;
@@ -12,3 +13,19 @@ export declare const switchAllContentToRTE: (uiPageSettingStore: PageSettingsSta
12
13
  export declare const getUpdatedHTMLFromEditor: (externalEditor: Editor, contentText: string, newContentStyle: TextStyleDeclaration) => string;
13
14
  export declare const buildInitialMarks: (state: EditorState, style: TextStyleDeclaration) => any[];
14
15
  export declare const retainStyleOnEmptyLine: (editor: Editor, selection: Selection) => void;
16
+ export interface SanitizationResult {
17
+ sanitizedHtml: string;
18
+ removedElements: string[];
19
+ }
20
+ export declare const sanitiseClientSideRTE: (html: string) => SanitizationResult;
21
+ /**
22
+ * Sanitize HTML string using DOMPurify.
23
+ * Only allow tags and attributes that correspond to the enabled Tiptap extensions.
24
+ * Forbid dangerous tags and attributes.
25
+ * @param html HTML string to sanitize
26
+ * @returns sanitization result with sanitized HTML and removed elements info
27
+ */
28
+ export declare const sanitizeRTEHtml: (html: string, domPurify: DOMPurify) => SanitizationResult;
29
+ export declare const isLogoColor: (color: string) => boolean;
30
+ export declare const getRTEColor: (color: string | null | undefined, colorType?: 'text' | 'background', defaultValue?: string) => string;
31
+ export declare const hasLogoColorVar: (color: string) => boolean;
@@ -1,6 +1,94 @@
1
- import { EditorState, Transaction, Selection } from 'prosemirror-state';
1
+ import { STYLE_THEME_KEYS, } from '../../brand-page';
2
2
  import { ESCAPED_NEWLINE_CHARACTER } from '../../constants/ui';
3
3
  import { getRenderText } from '../../brand-page/utils';
4
+ import createDomPurify, {} from 'dompurify';
5
+ // Only allow tags used by the enabled Tiptap extensions
6
+ const allowedTags = [
7
+ 'p',
8
+ 'span',
9
+ 'strong',
10
+ 'em',
11
+ 'u',
12
+ 's',
13
+ 'mark',
14
+ 'div',
15
+ 'br',
16
+ 'ul',
17
+ 'ol',
18
+ 'li',
19
+ 'h1',
20
+ 'h2',
21
+ 'h3',
22
+ 'h4',
23
+ 'h5',
24
+ 'h6',
25
+ 'blockquote',
26
+ 'code',
27
+ 'pre',
28
+ 'hr',
29
+ 'a',
30
+ ];
31
+ // Block javascript: and data: protocols and other dangerous schemes
32
+ const dangerousProtocols = [
33
+ 'javascript:',
34
+ 'data:',
35
+ 'vbscript:',
36
+ 'file:',
37
+ 'about:',
38
+ 'chrome:',
39
+ 'chrome-extension:',
40
+ 'moz-extension:',
41
+ ];
42
+ // Allow specific attributes used by TipTap extensions and href for links
43
+ const allowedAttributes = ['style', 'data-color', 'href', 'target', 'rel'];
44
+ const forbiddenTags = [
45
+ 'script',
46
+ 'img',
47
+ 'iframe',
48
+ 'object',
49
+ 'embed',
50
+ 'link',
51
+ 'style',
52
+ 'meta',
53
+ 'form',
54
+ 'input',
55
+ 'button',
56
+ 'svg',
57
+ 'math',
58
+ ];
59
+ const forbiddenAttributes = [
60
+ 'onerror',
61
+ 'onclick',
62
+ 'onload',
63
+ 'onmouseover',
64
+ 'onfocus',
65
+ 'onblur',
66
+ 'src',
67
+ 'srcdoc',
68
+ 'formaction',
69
+ 'form',
70
+ 'action',
71
+ 'download',
72
+ 'class',
73
+ 'id',
74
+ 'data-type',
75
+ 'data-placeholder',
76
+ 'data-align',
77
+ 'data-text-align',
78
+ ];
79
+ // Only allow CSS properties used by TipTap extensions
80
+ const allowedCSSProperties = [
81
+ 'font-size',
82
+ 'font-family',
83
+ 'color',
84
+ 'line-height',
85
+ 'letter-spacing',
86
+ 'text-align',
87
+ 'background-color',
88
+ 'font-weight',
89
+ 'font-style',
90
+ 'text-decoration',
91
+ ];
4
92
  export const isStyleChanged = (tr) => {
5
93
  if (tr.getMeta('skipStyleDetection'))
6
94
  return false;
@@ -107,6 +195,28 @@ export const transformToRTE = (uiPageSettingStore, externalEditor, uiStyleSettin
107
195
  }
108
196
  }
109
197
  }
198
+ if ((!textContent.textItems || textContent.textItems.length === 0) &&
199
+ textContent.textStyle) {
200
+ const textStyleType = textContent.textStyle.textStyleType;
201
+ if (textStyleType &&
202
+ (textStyleType === type || uiStyleSettingsStore)) {
203
+ let globalContentStyle = uiStyleSettingsStore
204
+ ? uiStyleSettingsStore.textStyles.textStyleOptions[textStyleType].style
205
+ : newStyle ?? {};
206
+ globalContentStyle = {
207
+ ...globalContentStyle,
208
+ textAlign: textContent.textStyle.textAlign,
209
+ };
210
+ textContent.text = getUpdatedHTMLFromEditor(externalEditor, textContent.text, globalContentStyle);
211
+ }
212
+ else if (!textStyleType &&
213
+ newContent &&
214
+ newContent.id === textContent.id &&
215
+ !hasRTEContent(textContent.text)) {
216
+ const newContentStyle = newContent.textStyle;
217
+ textContent.text = getUpdatedHTMLFromEditor(externalEditor, textContent.text, newContentStyle);
218
+ }
219
+ }
110
220
  break;
111
221
  }
112
222
  }
@@ -129,7 +239,8 @@ export const switchAllContentToRTE = (uiPageSettingStore, externalEditor, uiStyl
129
239
  ...globalContentStyle,
130
240
  textAlign: bannerContent.titleStyle.textAlign,
131
241
  };
132
- bannerContent.title = getUpdatedHTMLFromEditor(externalEditor, bannerContent.title, globalContentStyle);
242
+ if (!hasRTEContent(bannerContent.title))
243
+ bannerContent.title = getUpdatedHTMLFromEditor(externalEditor, bannerContent.title, globalContentStyle);
133
244
  }
134
245
  else if (!titleTextStyleType &&
135
246
  !hasRTEContent(bannerContent.title)) {
@@ -144,7 +255,8 @@ export const switchAllContentToRTE = (uiPageSettingStore, externalEditor, uiStyl
144
255
  ...globalContentStyle,
145
256
  textAlign: bannerContent.descriptionStyle.textAlign,
146
257
  };
147
- bannerContent.description = getUpdatedHTMLFromEditor(externalEditor, bannerContent.description, globalContentStyle);
258
+ if (!hasRTEContent(bannerContent.description))
259
+ bannerContent.description = getUpdatedHTMLFromEditor(externalEditor, bannerContent.description, globalContentStyle);
148
260
  }
149
261
  else if (!descriptionTextStyleType &&
150
262
  !hasRTEContent(bannerContent.description)) {
@@ -165,7 +277,8 @@ export const switchAllContentToRTE = (uiPageSettingStore, externalEditor, uiStyl
165
277
  ...globalContentStyle,
166
278
  textAlign: textItemContent.textStyle.textAlign,
167
279
  };
168
- textItemContent.text = getUpdatedHTMLFromEditor(externalEditor, textItemContent.text, globalContentStyle);
280
+ if (!hasRTEContent(textItemContent.text))
281
+ textItemContent.text = getUpdatedHTMLFromEditor(externalEditor, textItemContent.text, globalContentStyle);
169
282
  }
170
283
  else if (!textItemStyleType &&
171
284
  !hasRTEContent(textItemContent.text)) {
@@ -174,6 +287,24 @@ export const switchAllContentToRTE = (uiPageSettingStore, externalEditor, uiStyl
174
287
  }
175
288
  }
176
289
  }
290
+ if ((!textContent.textItems || textContent.textItems.length === 0) &&
291
+ textContent.textStyle) {
292
+ const textStyleType = textContent.textStyle.textStyleType;
293
+ if (textStyleType && uiStyleSettingsStore) {
294
+ let globalContentStyle = uiStyleSettingsStore.textStyles
295
+ .textStyleOptions[textStyleType].style;
296
+ globalContentStyle = {
297
+ ...globalContentStyle,
298
+ textAlign: textContent.textStyle.textAlign,
299
+ };
300
+ if (!hasRTEContent(textContent.text))
301
+ textContent.text = getUpdatedHTMLFromEditor(externalEditor, textContent.text, globalContentStyle);
302
+ }
303
+ else if (!textStyleType && !hasRTEContent(textContent.text)) {
304
+ const newContentStyle = textContent.textStyle;
305
+ textContent.text = getUpdatedHTMLFromEditor(externalEditor, textContent.text, newContentStyle);
306
+ }
307
+ }
177
308
  break;
178
309
  }
179
310
  }
@@ -199,7 +330,14 @@ export const getUpdatedHTMLFromEditor = (externalEditor, contentText, newContent
199
330
  chain = chain.setLineHeight(newContentStyle.lineHeight);
200
331
  }
201
332
  if (newContentStyle?.color) {
202
- chain = chain.setMark('textStyle', { color: newContentStyle.color });
333
+ chain = chain.setMark('textStyle', {
334
+ color: getRTEColor(newContentStyle.color, 'text'),
335
+ });
336
+ }
337
+ if (newContentStyle?.backgroundColor) {
338
+ chain = chain.setMark('highlight', {
339
+ color: getRTEColor(newContentStyle.backgroundColor, 'background'),
340
+ });
203
341
  }
204
342
  if (!currentAlignment.textAlign && newContentStyle?.textAlign) {
205
343
  chain = chain.setTextAlign(newContentStyle.textAlign);
@@ -227,15 +365,18 @@ export const buildInitialMarks = (state, style) => {
227
365
  textStyleAttrs.fontFamily = fontFamily;
228
366
  if (fontSize)
229
367
  textStyleAttrs.fontSize = fontSize;
230
- if (color)
231
- textStyleAttrs.color = color;
368
+ if (color) {
369
+ textStyleAttrs.color = getRTEColor(color, 'text');
370
+ }
232
371
  if (letterSpacing)
233
372
  textStyleAttrs.letterSpacing = letterSpacing;
234
373
  if (lineHeight)
235
374
  textStyleAttrs.lineHeight = lineHeight;
236
375
  marks.push(state.schema.marks.textStyle.create(textStyleAttrs));
237
376
  if (backgroundColor) {
238
- marks.push(state.schema.marks.highlight.create({ color: backgroundColor }));
377
+ marks.push(state.schema.marks.highlight.create({
378
+ color: getRTEColor(backgroundColor, 'background'),
379
+ }));
239
380
  }
240
381
  // Bold and italic
241
382
  if (fontWeight) {
@@ -278,3 +419,194 @@ export const retainStyleOnEmptyLine = (editor, selection) => {
278
419
  }
279
420
  }
280
421
  };
422
+ let rteDomPurifyInstance = null;
423
+ const getRTEDomPurifyInstance = () => {
424
+ if (!rteDomPurifyInstance) {
425
+ rteDomPurifyInstance = createDomPurify;
426
+ }
427
+ return rteDomPurifyInstance;
428
+ };
429
+ export const sanitiseClientSideRTE = (html) => {
430
+ return sanitizeRTEHtml(html, getRTEDomPurifyInstance());
431
+ };
432
+ /**
433
+ * Validates if an href value is safe and returns a sanitized version
434
+ */
435
+ const validateAndSanitizeHref = (href) => {
436
+ if (!href || typeof href !== 'string')
437
+ return null;
438
+ // Trim whitespace and decode entities
439
+ const trimmedHref = href.trim();
440
+ if (!trimmedHref)
441
+ return null;
442
+ const lowerHref = trimmedHref.toLowerCase();
443
+ for (const protocol of dangerousProtocols) {
444
+ if (lowerHref.startsWith(protocol))
445
+ return null;
446
+ }
447
+ // Allow relative paths, absolute paths, and safe protocols
448
+ if (trimmedHref.startsWith('/') ||
449
+ trimmedHref.startsWith('./') ||
450
+ trimmedHref.startsWith('../')) {
451
+ return trimmedHref;
452
+ }
453
+ // Allow http and https URLs
454
+ if (lowerHref.startsWith('http://') || lowerHref.startsWith('https://')) {
455
+ try {
456
+ const url = new URL(trimmedHref);
457
+ // Additional validation for malformed URLs
458
+ if (url.hostname.includes('..') || url.hostname === '') {
459
+ return null;
460
+ }
461
+ return trimmedHref;
462
+ }
463
+ catch {
464
+ return null;
465
+ }
466
+ }
467
+ // Allow mailto links
468
+ if (lowerHref.startsWith('mailto:')) {
469
+ // Basic email validation
470
+ const emailPart = trimmedHref.substring(7);
471
+ if (/^[^\s@]+@[^\s@]+\.[^\s@]+/.test(emailPart)) {
472
+ return trimmedHref;
473
+ }
474
+ return null;
475
+ }
476
+ // Allow tel links
477
+ if (lowerHref.startsWith('tel:')) {
478
+ const telPart = trimmedHref.substring(4);
479
+ if (/^[\d\s\-\+\(\)]+$/.test(telPart)) {
480
+ return trimmedHref;
481
+ }
482
+ return null;
483
+ }
484
+ // For any other format, treat as relative path if it doesn't contain dangerous characters
485
+ if (!/[<>'"\\]/.test(trimmedHref)) {
486
+ return trimmedHref;
487
+ }
488
+ return null;
489
+ };
490
+ /**
491
+ * Sanitize HTML string using DOMPurify.
492
+ * Only allow tags and attributes that correspond to the enabled Tiptap extensions.
493
+ * Forbid dangerous tags and attributes.
494
+ * @param html HTML string to sanitize
495
+ * @returns sanitization result with sanitized HTML and removed elements info
496
+ */
497
+ export const sanitizeRTEHtml = (html, domPurify) => {
498
+ const removedElements = [];
499
+ // Use DOMPurify hook to handle href validation and external link attributes
500
+ domPurify.addHook('afterSanitizeAttributes', (node) => {
501
+ if (node.tagName === 'A' && node.hasAttribute('href')) {
502
+ const href = node.getAttribute('href');
503
+ const sanitizedHref = validateAndSanitizeHref(href || '');
504
+ if (sanitizedHref === null) {
505
+ node.removeAttribute('href');
506
+ removedElements.push(`href="${href}"`);
507
+ }
508
+ else if (sanitizedHref !== href) {
509
+ node.setAttribute('href', sanitizedHref);
510
+ }
511
+ // Add security attributes for external links
512
+ const finalHref = node.getAttribute('href');
513
+ if (finalHref &&
514
+ (finalHref.startsWith('http://') || finalHref.startsWith('https://'))) {
515
+ node.setAttribute('target', '_blank');
516
+ node.setAttribute('rel', 'noopener noreferrer');
517
+ }
518
+ }
519
+ });
520
+ try {
521
+ // Main DOMPurify sanitization
522
+ const sanitized = domPurify.sanitize(html, {
523
+ ALLOWED_TAGS: allowedTags,
524
+ ALLOWED_ATTR: allowedAttributes,
525
+ FORBID_TAGS: forbiddenTags,
526
+ FORBID_ATTR: forbiddenAttributes,
527
+ KEEP_CONTENT: true,
528
+ });
529
+ // Track elements/attributes removed by DOMPurify
530
+ if (domPurify.removed && Array.isArray(domPurify.removed)) {
531
+ domPurify.removed.forEach((removed) => {
532
+ if (removed.element) {
533
+ const tagName = removed.element.tagName?.toLowerCase();
534
+ if (tagName &&
535
+ tagName !== 'body' &&
536
+ !removedElements.includes(tagName)) {
537
+ removedElements.push(tagName);
538
+ }
539
+ }
540
+ if (removed.attribute) {
541
+ const attrInfo = `${removed.attribute.name}="${removed.attribute.value}"`;
542
+ if (!removedElements.includes(attrInfo)) {
543
+ removedElements.push(attrInfo);
544
+ }
545
+ }
546
+ });
547
+ }
548
+ // Post-process: sanitize CSS properties in style attributes
549
+ const finalHtml = sanitizeStyleAttributes(sanitized, removedElements);
550
+ return {
551
+ sanitizedHtml: finalHtml,
552
+ removedElements,
553
+ };
554
+ }
555
+ finally {
556
+ // Always remove the hook to prevent memory leaks
557
+ domPurify.removeHook('afterSanitizeAttributes');
558
+ }
559
+ };
560
+ /**
561
+ * Sanitize CSS properties within style attributes to only allow TipTap extension properties
562
+ */
563
+ const sanitizeStyleAttributes = (html, removedElements) => {
564
+ return html
565
+ .replace(/\s*style="([^"]*)"/g, (match, styleValue) => {
566
+ // Parse and validate individual CSS properties
567
+ const declarations = styleValue
568
+ .split('; ')
569
+ .filter((decl) => decl.trim());
570
+ const validDeclarations = declarations.filter((declaration) => {
571
+ const [property] = declaration.split(':').map((s) => s.trim());
572
+ return allowedCSSProperties.includes(property);
573
+ });
574
+ // Track removed CSS properties
575
+ const removedDeclarations = declarations.filter((declaration) => {
576
+ const [property] = declaration.split(':').map((s) => s.trim());
577
+ return !allowedCSSProperties.includes(property);
578
+ });
579
+ // Add removed CSS properties to the removed elements array
580
+ removedDeclarations.forEach((removedDecl) => {
581
+ const trimmedDecl = removedDecl.trim();
582
+ if (trimmedDecl && !removedElements.includes(trimmedDecl)) {
583
+ removedElements.push(trimmedDecl);
584
+ }
585
+ });
586
+ if (validDeclarations.length === 0) {
587
+ return '';
588
+ }
589
+ return ` style="${validDeclarations.join(';')}"`;
590
+ })
591
+ .replace(/\s+>/g, '>'); // Clean up any extra spaces before closing tags
592
+ };
593
+ // Helper function to check if color is a logo theme color
594
+ export const isLogoColor = (color) => {
595
+ return Object.values(STYLE_THEME_KEYS).some((themeKey) => color.startsWith(themeKey));
596
+ };
597
+ export const getRTEColor = (color, colorType = 'text', defaultValue) => {
598
+ if (!color) {
599
+ if (defaultValue)
600
+ return defaultValue;
601
+ return colorType === 'text' ? '#000000' : 'transparent';
602
+ }
603
+ const themeKey = Object.values(STYLE_THEME_KEYS).find((key) => color.startsWith(key));
604
+ if (themeKey) {
605
+ return `var(--${themeKey})`;
606
+ }
607
+ return color;
608
+ };
609
+ // Helper function to check if color is a logo theme color
610
+ export const hasLogoColorVar = (color) => {
611
+ return Object.values(STYLE_THEME_KEYS).some((themeKey) => color.includes(themeKey));
612
+ };
@@ -0,0 +1,119 @@
1
+ const e = { consentText: "We use cookies on our website to optimize your website experience. By accepting, you agree to our use of such cookies.", accept: "Accept" }, o = { productName: "{{PAYMENT_OPTIONS_LENGTH}} products", defaultPaymentSuccessMessage: "Thank you for your request! We'll get in touch with you as soon as possible.", yourMessage: "Your message", provideDetails: "Provide request details", selectAnAmount: "Select an amount {{CURRENCY_CODE}}", customAmountLabelOr: "or custom amount {{CURRENCY_CODE}}", customAmountLabel: "Custom amount {{CURRENCY_CODE}}" }, t = { sensitiveContentDisplayTitle: "Sensitive Content", sensitiveContentmessage: "Confirm that you are willing to see potentially sensitive content", ageRestrictionDisplayTitle: "Sensitive Content", ageRestrictionMessage: "Confirm that you are of legal age to view this content", rejectedDisplayTitle: "You cannot visit this site", rejectedDisplayTMessage: "Access is restricted to users {{REQUIRED_MINIMUM_AGE}} and older", iAcceptAgeButtonLabel: "I'm over {{REQUIRED_MINIMUM_AGE}}", iDenyAgeButtonLabel: "I'm under {{REQUIRED_MINIMUM_AGE}}", iConfirmButtonLabel: "I Confirm" }, a = { noProducts: "No products are listed at the moment", viewCart: "View Cart" }, i = { image: "image", shape: "shape" }, l = { saveProgress: "Save Progress", saveTemplate: "Save Template", publish: "Publish" }, s = { userImageUpgradeText: "With BrandPage Premium you can upload your own images as background.", libraryImageUpgradeText: "With BrandPage Premium you can add background images powered by Unsplash." }, r = { favicon: "Favicon", icon: "Icon", seoSettings: "SEO Settings", cookieCollection: "Cookie Collection", faviconDescription: "A favicon is a small icon next to your site title in the browser tab.", socialShareTitle: "Social Share", paymentProvidersTitle: "Payment Providers", paymentProvidersDescription: "Enable or sign up to a supported provider. Start collecting tips and payments, or sell products, services and more!", paymentProvidersAddProviderLabel: "Add payment providers" }, n = { newColor: "New Color" }, d = { cookieInfo: "Some regional laws require website owners to inform visitors of cookie tracking.", enableCookie: "Enable cookie collection banner", showPreview: "Show preview" }, c = { analyticsIntegrations: "Analytics Integrations", googleAnalyticsLabel: "Google Analytics: GA4", googleAnalyticsInfo: "Add your Google Analytics: GA4 Measurement ID to track your visitors using GA4, use this format G-XXXXXXXXX or AW-XXXXXXXXX" }, m = { mobile: "Mobile", desktop: "Desktop" }, p = { defaultBackButtonLabel: "Back", prePurchaseBackButtonLabel: "Back", postPurchaseBackButtonLabel: "Back to My Websites" }, g = { myWebPageLabel: "My web page:", copyButton: "Copy", copiedButton: "Copied!" }, u = { sensitiveContentInfo: "Display a sensitive content warning before visitors can view your profile", offSetting: "Off", sensitiveContentSetting: "Sensitive Content" }, h = { title: "Use your existing domain", description: "Choose from your purchased domain names or enter your existing domain name", purchasedDomainRadio: "Use my purchased domain names", selectDomainPlaceholder: "Select domain name", submitButton: "Submit", registrationInProgress: "Registration in progress", noPurchasedDomains: "You have not purchased any domains yet.", existingDomainRadio: "Use my existing domain", existingDomainPlaceholder: "example.com", connectButton: "Connect", errorMessage: "Something went wrong, please contact support." }, y = { seo: "SEO", customDomain: "Custom Domain", addCustomDomain: "Add Custom Domain", useExistingDomain: "Or use existing domain", pageUrl: "Page URL", connected: "Connected", type: "Type", host: "Host", target: "Target", changeUrl: "Change URL", setupInProgress: "Setup in progress", pending: "Pending Verification", failed: "Failed", failedToRenew: "Failed to Renew", dnsExpired: "Request expired. Please remove and setup a new custom domain.", dnsMissing: "Expected DNS records are missing. Please add the missing DNS records.", dnsInvalid: "Invalid DNS records exist. Please remove the invalid DNS records.", dnsError: "Invalid DNS records exist. Please remove the 'AAAA' DNS record.", checkStatus: "Check Status", resetDomain: "Are you sure you want to reset this domain name?", webDescription: "Short description for your Web Page", websiteDescription: "Short description for your Brand Website", customDomainError: "Something went wrong, please contact support.", customDomainNote: "Note: Please allow up to 72 hours for your domain to fully initialize", customDomainInfo: "Use your existing domain URL. You will need to purchase a domain name from a domain name registrar to use this functionality.", customDomainSettingInfo: "Go to your Domain Settings (under your Domain provider website) and make the changes below in your Records:" }, S = { customizeSocial: "Customize how your website will look when shared on social media", thumbnail: "Thumbnail", recommendedSize: "recommended size", enterTitle: "Enter title", enterDescription: "Enter description", addOgImage: "Add OG Image", replaceOgImage: "Replace OG Image" }, b = { previewDisplayName: "Preview", templatesDisplayName: "Templates", contentDisplayName: "Content", backgroundDisplayName: "Bkground", logoDisplayName: "Logo", styleDisplayName: "Style", settingsDisplayName: "Settings", classicDisplayName: "classic", modernDisplayName: "modern", uniqueDisplayName: "unique" }, T = { centered: "Centered", leftAligned: "Left aligned", url: "Url", page: "Page", emailAddress: "Email address", phoneNumber: "Phone number", preview: "Preview", collapsed: "Collapsed", grid: "Grid", carousel: "Carousel", masonry: "Masonry", original: "Original", circle: "Circle", default: "Default", textOnly: "Text only", thumbnail: "Thumbnail", featured: "Featured", small: "Small", medium: "Medium", large: "Large", bigImage: "Big Image", columns: "Columns" }, D = { defaultBackgroundColor: "Default background color", defaultBorderColor: "Default border color", defaultTextStyle: "Default text style", selectedBackgroundColor: "Selected background color", selectedBorderColor: "Selected border color", selectedTextColor: "Selected text color", iconColor: "Icon color", iconBackgroundColor: "Icon background color", allDisplayName: "all", generalDisplayName: "General", socialLinksDisplayName: "Socials", monetizeDisplayName: "Monetize", sectionsDisplayName: "Sections" }, C = { emptyStringMessage: "Please enter a value", invalidAddressMessage: "Please enter an address", invalidEmailMessage: "Please enter a valid email address", invalidTelMessage: "Please enter a valid telephone number", invalidUrlMessage: "Please enter a valid url", invalidYoutubeUrlMessage: "Please enter a valid YouTube url", selectAPage: "Please select a page" }, P = { recommendedColors: "Recommended Colors", logoColors: "Logo Colors", background: "Background", other: "Other", shapes: "Shapes", color: "Color", imageLibrary: "Image Library", myUploads: "My Uploads" }, L = { newColor: "New Color", defaultColors: "Default Colors", gradientColors: "Gradient Colors", selectThisColor: "Select this color" }, f = { desktop: "desktop", mobile: "mobile", back: "Back", none: "None", logo: "Logo", upload: "Upload", yes: "Yes", no: "No", all: "All", categories: "Categories", search: "Search", pageTitle: "Page title", title: "Title", description: "Description", settings: "Settings", domains: "Domains", sensitiveContent: "Sensitive Content", displayStyle: "Display style", colorMatched: "Color Matched", iconColor: "Icon color", backgroundColor: "Background Color", centered: "Centered", justified: "Justified", fontSettings: "Font Settings", defaultTextStyle: "Default text style", emptySearchLabel: "Sorry, we couldn’t find what you’re looking for.", small: "Small", medium: "Medium", large: "Large", wide: "wide", default: "Default", replace: "Replace", save: "Save", remove: "Remove", addShapeLabel: "Add Shape", addImageLabel: "Add Image", addFaviconLabel: "Add Favicon", replaceFaviconLabel: "Replace Favicon", updateSettings: "Update Settings", upgradeToPremium: "Upgrade to premium", done: "Done", copyrightTextPlaceholder: "Copyright text here", continue: "Continue", defaultSaveDescription: "Don’t forget to publish your changes once you are happy with your design.", saveSuccess: "Save successful!" }, A = { maxCharacters: "You have reached your maximum limit of characters allowed", maxCharactersDescription: "You have reached your maximum limit of characters allowed for your description", maxCharactersTitle: "You have reached your maximum limit of characters allowed for your title", invalidUrlMessage: "Please enter a valid url", testimonialEmpty: "Please enter a testimonial", textEmpty: "Please enter a text", invalidGoogleId: "Invalid Google Measurement ID", paymentMethodDescription: "Please enter a description for your payment method", maxTitleLength: "Please keep the page title to {{MAX_PAGE_TITLE_LENGTH}} characters.", acceptedTypesMessage: "We accept {{ACCEPTED_IMAGE_TYPES}}'s up to {{FILE_SIZE_LIMIT}}", fileTooLargeMessage: "File is too large. Please upload file less than {{MAX_FILE_SIZE}} MB.", incorrectDimensionsMessage: "Incorrect dimensions for {{MEDIA_TYPE}}. Recommended dimension is: {{DESIRED_WIDTH}}x{{DESIRED_HEIGHT}}", titleLengthError: "Title exceeds {{BRANDPAGE_TITLE_CHARACTER_LIMIT}} characters.", descriptionLengthError: "Description exceeds {{BRANDPAGE_DESCRIPTION_CHARACTER_LIMIT}} characters.", metaKeywordsError: "Please enter a maximum of 100 keywords", invalidSlugError: "Your brand page url contains invalid characters. It may only include alphanumeric characters and the '-' character", slugCharacterLimitError: "Your brand page url exceeds the maximum of {{BRANDPAGE_SLUG_CHARACTER_LIMIT}} characters", brandPageDescriptionLimitError: "Description exceeds 158 characters.", brandPageTitleLimitError: "Title exceeds 60 characters.", brandPageDefaultDescriptionError: "An error has occurred. Please try again later.", contentHasErrors: "`There are {{CONTENT_ERROR_COUNT}} content errors. Please check the Content tab for more info.`", pageTitleError: "Page title cannot be empty.", genericBrandPagePublishError: "An unexpected error occurred when publishing brand page. Please try again." }, I = { recommendedColors: "Recommended Colors", logoColors: "Logo Colors", transparent: "Transparent" }, v = { colorMatchShape: "Color match shape" }, x = { sideBarHeaderTitle: "Edit Content", managePagesButtonText: "Manage Pages", addNewPageButtonText: "Add New Page", addContentButtonText: "Add Content", addContentHeaderTitle: "Add Content", getStartedButtonText: "Get Started", logoDisplayName: "Logo", generalLinkDisplayName: "General Link", profileDisplayName: "Profile", websiteDisplayName: "Website", emailDisplayName: "Email", phoneDisplayName: "Phone", textDisplayName: "Text", imageDisplayName: "Image", imageSectionDisplayName: "Images", imageGalleryDisplayName: "Image Gallery", videoDisplayName: "Video", mapDisplayName: "Map", mailingListDisplayName: "Mailing list", facebookDisplayName: "Facebook", twitterDisplayName: "Twitter", instagramDisplayName: "Instagram", youtubeDisplayName: "YouTube", linkedinDisplayName: "LinkedIn", pinterestDisplayName: "Pinterest", twitchDisplayName: "Twitch", tiktokDisplayName: "Tiktok", supportMeDisplayName: "Tipping", requestPaymentDisplayName: "Payments", contactFormDisplayName: "Contact Form", bannerSectionDisplayName: "Banner", testimonialSectionDisplayName: "Testimonials", aboutSectionDisplayName: "About", socialLinksDisplayName: "Social Links", dividerSectionDisplayName: "Divider", shapesSectionDisplayName: "Shapes", shopSectionDisplayName: "Store", settingsDisplayName: "Settings", styleDisplayName: "Style", titleStyleLabel: "Title style", descriptionStyleLabel: "Description style", nameStyleLabel: "Name style", buttonTextStyleLabel: "Button text style", addImageButtonTitle: "Add image", addImageHeaderTitle: "Add image", imageReplaceTitle: "Replace image", imageGalleryAddButtonTitle: "Add images", imageGalleryReplaceTitle: "Add image", iconReplaceTitle: "Replace thumbnail", addIconHeaderTitle: "Add thumbnail", buttonModalAddButtonTitle: "Add design", buttonModalTitleHeader: "Add design", buttonModalReplaceTitle: "Replace design", addShapeButtonTitle: "Add shape", addShapeHeaderTitle: "Add shape", addShapeReplaceTitle: "Replace shape", linkDisplayName: "Link", openDesignDisplayName: "Open Design", pageDisplayName: "Page", productsAndServicesDisplayName: "Products and Services", emailOnlyDisplayName: "Email only", nameAndEmailDisplayName: "Name and email", logoTitle: "Logo", logoSizeTitle: "Logo size", backgroundColorTitle: "Background color", thumbnailTitle: "Thumbnail", shapeColorsTitle: "Shape Colors", displayStyleTitle: "Display Style", urlTitle: "URL", fontSettingsTitle: "Font settings", emailTitle: "Email", imageTitle: "Image", titleTitle: "Title", aspectRatioTitle: "Aspect ratio", pluralImagesTitle: "Images", styleTitle: "Style", phoneNumberTitle: "Phone number", textTitle: "Text", pluralAddItemsTitle: "Add Items", sizeTitle: "Size", alignmentTitle: "Alignment", colorTitle: "Color", columnsTitle: "Columns", addressTitle: "Address", buttonTitle: "Button", linkStyleTitle: "Link style", descriptionTitle: "Description", successMessageTitle: "Success Message", sendResponsesToTitle: "Send responses to", cardColorTitle: "Card color", successMessageTextColorTitle: "Success message text color", overlayColorTitle: "Overlay Color", overlayTitle: "Overlay", buttonLinkTitle: "Button Link", paragraphTitle: "Paragraph", cardFillColorTitle: "Card fill color", iconFillColorTitle: "Icon fill color", iconBackgroundColorTitle: "Icon background color", paddingTitle: "Padding", dividerStyleTitle: "Divider Style", dividerColorTitle: "Divider color", addItemTitle: "Add Item", buyNowTitle: "Buy Now", shopTitle: "Shop", supportMeTitle: "Support me", contactUsTitle: "Contact Us", thisIsABannerTitle: "This is a banner", imagesTitle: "Images", testimonialsTitle: "Testimonials", aboutSectionTitle: "This is the About Section", homeTitle: "Home", followUsOnTitle: "Follow us on", shapesTitle: "Shapes", defaultTextValue: "This is a sample text", titlePlaceholder: "Title", successMessagePlaceholder: "Success message", successThanksPlaceholder: "Thank you for your request!", successSupportPlaceholder: "Thank you for your support!", descriptionPlaceholder: "Description", recipientEmailPlaceholder: "Recipient email", getStartedPlaceholder: "Get Started", paragraphPlaceholder: "Paragraph", selectAPagePlaceholder: "Select a page", yourNamePlaceholder: "Your Name", websitePlaceholder: "Website", exampleWebsitePlaceholder: "https://example.com", addImageTitlePlaceholder: "Add image title", joinMailingListPlaceholder: "Join mailing list", subscribePlaceholder: "Subscribe", optionalDescriptionPlaceholder: "Description (optional)", textAreaDescriptionPlaceholder: "Write a short description about yourself or your brand", textAreaSamplePlaceholder: "This is a sample text", emailPlaceholder: "me@website.com", youtubeUrlPlaceholder: "Paste YouTube video URL", sendPlaceholder: "Send", formSuccessMessage: "Thank you! We'll get in touch with you as soon as possible.", fullWidthLabel: "Full width", autoplayLabel: "Autoplay", muteLabel: "Mute", headingStyleLabel: "Heading style", testimonialStyleLabel: "Testimonial style", paragraphStyleLabel: "Paragraph style", positionStyleLabel: "Position style", itemStyleLabel: "Item style", defaultFillColorLabel: "Default fill color", defaultBorderColorLabel: "Default border color", selectedBorderColorLabel: "Selected border color", textColorLabel: "Text color", multiProductSelectionLabel: "Allow multiple products to be selected", optionalDetailsLabel: "Option to provide details of their request", mailingListPromptText: "Join mailing list", defaultDescription: "Description", makeADonationDescription: "Make a donation", thickLineDivider: "Thick Line", thinLineDivider: "Thin Line", noneDivider: "None", styleNoneOption: "None", styleSquareOption: "Square", styleCircleOption: "Circle", mediaTypeImage: "image", mediaTypeShape: "shape", firstNameLabel: "First name", lastNameLabel: "Last name", emailAddressLabel: "Email address", phoneNumberLabel: "Phone number", messageLabel: "Message" }, N = { field: "Field", required: "Required" }, w = { addressPlaceholder: "Enter a location" }, k = { sampleText: "This is a sample text" }, M = { shapePrefix: "Shape", imagePrefix: "Image", placeholderSuffix: " title", addShapeLabel: "Add Shape", addImageLabel: "Add Image" }, E = { linkPlaceholderPrefix: "https://example.com", buttonLabel: "Add Item" }, B = { logoVariations: "Logo Variations", logoVersions: "Logo Versions", editLogo: "Edit logo", uploadLogo: "Upload logo" }, R = { paymentSetup: "Payment Setup", inactiveMessage: "Please enable a payment provider by clicking the button below to start accepting payments on your web page.", pendingPreOnboardingLabel: "Onboarding Incomplete", pendingPostOnboardingLabel: "Validation Required", defaultLabel: "Unsupported state", pendingPreOnboardingDescription: "Please complete onboarding via Stripe before continuing.", pendingPostOnboardingDescription: "Stripe still needs to verify some details. Check progress via the Stripe dashboard.", requiredActionCtaLabel: "Go to ", paymentImageAspectRatio: "Aspect Ratio", supportMeAmount: "Amount", supportMeDescription: "Donate", supportMeCustomAmount: " Option to add custom amount ", supportMeCustomMessage: " Include message to you ", addItem: "Add Item", price: "Price" }, U = { icon: "Icon", myUploads: "My Uploads", myDesigns: "My Designs", imageLibrary: "Image Library", shapeLibrary: "Shape Library" }, F = { shapeColors: "Shape Colors", shapeColor: "Shape Color", addItemLabel: "Add Item" }, O = { testimonial: "Testimonial", avatar: "Avatar", shapeColors: "Shape Colors", shapeColor: "Shape Color", position: "Position", name: "Name", ceoPlaceholder: "CEO of Company Name", addItem: "Add Item" }, _ = { maxReached: "You have reached your maximum limit of characters allowed" }, G = { shapeColors: "Shape Colors", shapeColor: "Shape Color", imageCaptionPlaceholder: "Add image caption", imageLink: "Image link", imageCaption: "Image caption", addTitlePlaceholder: "Add title", title: "Title", addParagraphPlaceholder: "Add paragraph", paragraph: "Paragraph", addItemLabel: "Add Item", image: "Image", shape: "Shape" }, H = { fontSettings: "Font Settings", addItem: "Add Item" }, Y = { textStyle: "Text Style", font: "Font", size: "Size", letterSpacing: "Letter Spacing", lineHeight: "Line Height", style: "Style", alignment: "Alignment", color: "Color", backgroundColor: "Background Color" }, X = { maxLimitReached: "You have reached your maximum limit of characters allowed" }, z = { loadingMessage: "Loading...", dropToUpload: "Drop your files here or click to upload.", acceptText: "We accept .jpg, .jpeg, .png's up to 25MB", maxFiles: "(Max 5 files at once)", check: "Check", error: "Error" }, W = { addItem: "Add Item" }, q = { loginPrompt: "Please login or register to start using the image uploader.", loginOrRegister: "Login or Register" }, V = { logoText: "Logo", headerLogoDesign: "Logo Design", headerUploadLogo: "Upload Logo", subHeaderLogoPreview: "Logo Preview", subHeaderLogoColors: "Logo Colors", subHeaderLogoText: "Logo Text", subHeaderSupportingText: "Supporting Text", uploadNewLogo: "Upload New logo", noUploadedLogoText: "You have no uploaded logo, upload a logo to start editing" }, j = { searchPlaceholder: "Search your designs", createNewDesign: "Create New Design", allDesigns: "All Designs", allLogos: "All Logos" }, J = { fileUploadLabel: "Drop your files here or click to upload.", emptyMediaLabel: "There are no images in your media library. Upload a new image to get started.", areyouSureLabel: "Are you sure?", deleteInfoLabel: "Note: It might take 24 hours to delete images across all your website content.", maxOneFile: "(Max {{MAX_UPLOADED_FILES}} file at once)", maxMultipleFiles: "(Max {{MAX_UPLOADED_FILES}} files at once)" }, Q = { headerSettings: "Header Settings", footerSettings: "Footer Settings", managePages: "Manage Pages", pages: "Pages", addPage: "Add Page", addPages: "Add Pages", addPagesDescription: "Add pages to better organize your content. Your home page will always be on and your first page. Drag and drop your other pages to reorder them.", upgradeBtn: "Upgrade to add more pages", copyrightStyle: "Copyright Style" }, Z = { showNavigationBelow: "Show navigation below logo", previewDescription: "Preview is not available on this screen size.", navigationStyle: "Navigation style", logoSize: "Logo Size", socialLinks: "Social Links", copyright: "Copyright" }, K = { domainSearchButtonLabel: "Search", customDomainCardDescription: "Make it easy for customers to find you with a domain that matches your business", customDomainLabel: "Custom Domain", recommendedLabel: "Recommended" }, $ = { loadMoreShapes: "Load More Shapes" }, ee = { titles: "Titles", headings: "Headings", paragraphs: "Paragraphs", buttons: "Buttons", premium: "Premium", logoBackgroundColor: "Logo background color", buttonBorderColor: "Button border color", buttonFillColor: "Button fill color", buttonShadowColor: "Button shadow color", buttonSoftShadowColor: "Button shadow color", buttonIconColor: "Icon color", defaultTextColor: "Default text color", customizeInfo: "Customize the appearance of text across your site", hideDesignLogo: "Hide Design.com logo", hideBrandCrowdLogo: "Hide BrandCrowd logo", styleTitle: "Style", buttonStyleTitle: "Button style", textStyleTitle: "Text style" }, oe = { searchPlaceholder: "Search", templatePreview: "Template Preview", loadMoreTemplatesButtonText: "Load more templates", headerAll: "All", headerCategories: "Categories", headerAi: "AI" }, te = { loadMoreImages: "Load more images", poweredBy: "Powered by" }, ae = {
2
+ cookie: e,
3
+ payment: o,
4
+ sensitiveContentModal: t,
5
+ shop: a,
6
+ index: i,
7
+ actionBar: l,
8
+ brandpageBackgroundSettings: s,
9
+ brandPageSettings: r,
10
+ colorPalette: n,
11
+ cookieSettings: d,
12
+ googleAnalytics: c,
13
+ layoutSwitcher: m,
14
+ navigation: p,
15
+ quickLinkBar: g,
16
+ sensitiveContentSettings: u,
17
+ existingDomainModal: h,
18
+ seoSettings: y,
19
+ socialShare: S,
20
+ constants: b,
21
+ converter: T,
22
+ model: D,
23
+ validator: C,
24
+ backgroundSettings: P,
25
+ colorPicker: L,
26
+ common: f,
27
+ error: A,
28
+ colorField: I,
29
+ colorReplacementField: v,
30
+ contentSettings: x,
31
+ formFields: N,
32
+ googleAddressField: w,
33
+ genericTextInput: k,
34
+ imagesField: M,
35
+ linksField: E,
36
+ logoSelectionSettings: B,
37
+ paymentConfig: R,
38
+ replaceImageSetting: U,
39
+ shapeField: F,
40
+ testimonialItemsField: O,
41
+ textField: _,
42
+ textImageField: G,
43
+ textItemsField: H,
44
+ textStyleField: Y,
45
+ textAreaField: X,
46
+ dropzoneUploader: z,
47
+ productConfigOption: W,
48
+ loginMessage: q,
49
+ editLogoSettings: V,
50
+ myDesigns: j,
51
+ myUploadSettings: J,
52
+ pageSettings: Q,
53
+ pageSettingsSection: Z,
54
+ publishBrandPageModalWithState: K,
55
+ shapeLibrary: $,
56
+ styleSettingsSection: ee,
57
+ templateSettings: oe,
58
+ unsplashLibrary: te
59
+ };
60
+ export {
61
+ l as actionBar,
62
+ P as backgroundSettings,
63
+ r as brandPageSettings,
64
+ s as brandpageBackgroundSettings,
65
+ I as colorField,
66
+ n as colorPalette,
67
+ L as colorPicker,
68
+ v as colorReplacementField,
69
+ f as common,
70
+ b as constants,
71
+ x as contentSettings,
72
+ T as converter,
73
+ e as cookie,
74
+ d as cookieSettings,
75
+ ae as default,
76
+ z as dropzoneUploader,
77
+ V as editLogoSettings,
78
+ A as error,
79
+ h as existingDomainModal,
80
+ N as formFields,
81
+ k as genericTextInput,
82
+ w as googleAddressField,
83
+ c as googleAnalytics,
84
+ M as imagesField,
85
+ i as index,
86
+ m as layoutSwitcher,
87
+ E as linksField,
88
+ q as loginMessage,
89
+ B as logoSelectionSettings,
90
+ D as model,
91
+ j as myDesigns,
92
+ J as myUploadSettings,
93
+ p as navigation,
94
+ Q as pageSettings,
95
+ Z as pageSettingsSection,
96
+ o as payment,
97
+ R as paymentConfig,
98
+ W as productConfigOption,
99
+ K as publishBrandPageModalWithState,
100
+ g as quickLinkBar,
101
+ U as replaceImageSetting,
102
+ t as sensitiveContentModal,
103
+ u as sensitiveContentSettings,
104
+ y as seoSettings,
105
+ F as shapeField,
106
+ $ as shapeLibrary,
107
+ a as shop,
108
+ S as socialShare,
109
+ ee as styleSettingsSection,
110
+ oe as templateSettings,
111
+ O as testimonialItemsField,
112
+ X as textAreaField,
113
+ _ as textField,
114
+ G as textImageField,
115
+ H as textItemsField,
116
+ Y as textStyleField,
117
+ te as unsplashLibrary,
118
+ C as validator
119
+ };