@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
@@ -19,6 +19,7 @@ import { LetterSpacing } from './extensions/LetterSpacing';
19
19
  import { LineHeight } from './extensions/LineHeight';
20
20
  import Highlight from '@tiptap/extension-highlight';
21
21
  import Placeholder from '@tiptap/extension-placeholder';
22
+ import Link from '@tiptap/extension-link';
22
23
  import type { StyleTextFontFamilyOption } from '../../../shared/style-settings/models';
23
24
  import { createFormattingActions } from './formatting';
24
25
  import { useTextAlign } from './textAlign';
@@ -30,19 +31,28 @@ import {
30
31
  emToPx,
31
32
  isStyleChanged,
32
33
  pxToEm,
34
+ sanitiseClientSideRTE,
33
35
  skipStyleDetection,
34
36
  } from '../../../brand-page-maker/utils';
35
- import {
36
- TextStyles,
37
- type TextItem,
38
- type TextStyleDeclaration,
39
- } from '../../../brand-page';
37
+ import type { TextStyles } from '../../../brand-page';
38
+ import { type TextItem, type TextStyleDeclaration } from '../../../brand-page';
40
39
  import type { ButtonGroupOption } from '../../../brand-page-maker/models/button-group.model';
41
- import { letterSpacingValueConvertor } from '../../../brand-page-maker/convertors';
40
+ import {
41
+ letterSpacingValueConvertor,
42
+ colorConvertor,
43
+ backgroundColorConvertor,
44
+ } from '../../../brand-page-maker/convertors';
42
45
  import { useUiContentSettingsStore } from '../../../shared/content-settings/store';
43
- import { DOMSerializer } from 'prosemirror-model';
44
46
  import { AllSelection } from 'prosemirror-state';
45
47
  import { MaxLength } from './extensions/MaxLength';
48
+ import { AutoLink } from './extensions/AutoLink';
49
+ import { useHyperlink } from './hyperlink';
50
+ import { useBubbleMenu } from './bubbleMenu';
51
+ import {
52
+ hasLogoColorVar,
53
+ isLogoColor,
54
+ getRTEColor,
55
+ } from '../../utils/rich-text-editor.util';
46
56
 
47
57
  interface UseRichTextEditorReturn {
48
58
  editor: Editor;
@@ -69,6 +79,22 @@ interface UseRichTextEditorReturn {
69
79
  setInitialStyleSettings: (selectedTextStyle?: BrandPageCssStyle) => void;
70
80
  copyGlobalStyleSettings: (selectedTextStyle?: BrandPageCssStyle) => void;
71
81
  unsetAllMarks: () => void;
82
+ handleHyperlink: (
83
+ action: 'toggle' | 'apply' | 'remove',
84
+ data?: { href?: string; text?: string },
85
+ ) => void;
86
+ hyperlinkValue: ComputedRef<{ id: string; name: string; value: string }>;
87
+ setHyperlinkUrlValue: (url: string) => void;
88
+ shouldShow: ({ editor, state }: { editor: any; state: any }) => boolean;
89
+ tippyOptions: Record<string, any>;
90
+ handleAdminColorChange: (
91
+ color: {
92
+ id: string;
93
+ name: string;
94
+ value: string;
95
+ },
96
+ type: 'textColor' | 'backgroundColor',
97
+ ) => void;
72
98
  }
73
99
 
74
100
  interface DropdownInstance {
@@ -77,6 +103,7 @@ interface DropdownInstance {
77
103
 
78
104
  interface EditorOptionType {
79
105
  type:
106
+ | 'hyperlink'
80
107
  | 'fontFamily'
81
108
  | 'fontSize'
82
109
  | 'fontWeight'
@@ -115,6 +142,22 @@ export const useExternalRichTextEditor = (): {
115
142
  Highlight.configure({
116
143
  multicolor: true,
117
144
  }),
145
+ Link.configure({
146
+ openOnClick: false,
147
+ defaultProtocol: 'https',
148
+ autolink: true,
149
+ HTMLAttributes: (attrs) => {
150
+ const href = attrs.href;
151
+ const isExternal =
152
+ href && (href.startsWith('http://') || href.startsWith('https://'));
153
+
154
+ return {
155
+ rel: 'noopener noreferrer',
156
+ target: isExternal ? '_blank' : null,
157
+ };
158
+ },
159
+ }),
160
+ AutoLink,
118
161
  ],
119
162
  });
120
163
 
@@ -153,6 +196,8 @@ export const useRichTextEditor = (
153
196
  onSelectTextStyleType: (option: ButtonGroupOption) => void,
154
197
  updateRichTextEditor: Ref<boolean>,
155
198
  textStyleTypeOptions: ButtonGroupOption[],
199
+ markedText: Ref<string>,
200
+ isHyperlinkPopupOpen: Ref<boolean>,
156
201
  ): UseRichTextEditorReturn => {
157
202
  const editor = new Editor({
158
203
  content: model.value ?? '',
@@ -180,6 +225,21 @@ export const useRichTextEditor = (
180
225
  placeholder: props.placeholder,
181
226
  }),
182
227
  MaxLength.configure({ maxLength: props.maxLength }),
228
+ Link.configure({
229
+ openOnClick: false,
230
+ defaultProtocol: 'https',
231
+ autolink: true,
232
+ HTMLAttributes: (attrs) => {
233
+ const href = attrs.href;
234
+ const isExternal =
235
+ href && (href.startsWith('http://') || href.startsWith('https://'));
236
+
237
+ return {
238
+ target: isExternal ? '_blank' : null,
239
+ };
240
+ },
241
+ }),
242
+ AutoLink,
183
243
  ],
184
244
  editorProps: {
185
245
  handleDOMEvents: {
@@ -212,33 +272,25 @@ export const useRichTextEditor = (
212
272
  return false;
213
273
  },
214
274
  copy(view, event: ClipboardEvent) {
215
- // Prevent the browser’s default so we can inject our own blobs
216
- event.preventDefault();
275
+ const selection = view.state.selection;
217
276
 
218
- // 1) Plain text (already have this)
219
- const selectedText = view.state.doc.textBetween(
220
- view.state.selection.from,
221
- view.state.selection.to,
222
- '\n',
223
- );
277
+ if (selection.empty) return;
224
278
 
225
- event.clipboardData?.setData('text/plain', selectedText);
279
+ const data = event.clipboardData;
226
280
 
227
- // 2) custom style blob to add
228
281
  const styleData = JSON.stringify(props.styles);
229
282
 
230
- event.clipboardData?.setData('application/x-rte-styles', styleData);
283
+ const slice = selection.content(),
284
+ { dom, text } = view.serializeForClipboard(slice);
231
285
 
232
- // 3) HTML serialization via ProseMirror’s DOMSerializer
233
- const { from, to } = view.state.selection;
234
- const slice = view.state.doc.slice(from, to);
235
- const serializer = DOMSerializer.fromSchema(view.state.schema);
236
- const fragment = serializer.serializeFragment(slice.content);
237
- // Wrap in a container DIV so we can grab `innerHTML`
238
- const wrapper = document.createElement('div');
286
+ if (data) {
287
+ event.preventDefault();
288
+ data.clearData();
289
+ data.setData('text/html', dom.innerHTML);
290
+ data.setData('text/plain', text);
239
291
 
240
- wrapper.appendChild(fragment);
241
- event.clipboardData?.setData('text/html', wrapper.innerHTML);
292
+ if (styleData) data.setData('application/x-rte-styles', styleData);
293
+ }
242
294
 
243
295
  return true;
244
296
  },
@@ -292,6 +344,27 @@ export const useRichTextEditor = (
292
344
 
293
345
  return true;
294
346
  },
347
+ click(view, event) {
348
+ if (isHyperlinkPopupOpen?.value) return false;
349
+
350
+ const target = event.target as HTMLElement;
351
+
352
+ const linkElement = target.closest('a');
353
+
354
+ if (linkElement) {
355
+ const pos = view.posAtDOM(linkElement, 0);
356
+
357
+ if (pos !== null) {
358
+ editor.commands.setTextSelection(pos);
359
+
360
+ editor.commands.extendMarkRange('link');
361
+
362
+ return true; // Prevent default
363
+ }
364
+ }
365
+
366
+ return false;
367
+ },
295
368
  },
296
369
  },
297
370
  });
@@ -337,6 +410,19 @@ export const useRichTextEditor = (
337
410
  setLineHeightAll,
338
411
  } = useSpacing(editor);
339
412
 
413
+ const {
414
+ hyperlinkValue,
415
+ setHyperlinkUrl,
416
+ setHyperlinkUrlValue,
417
+ removeHyperlink: removeHyperlinkFromComposable,
418
+ applyHyperlinkToEditor,
419
+ } = useHyperlink(editor);
420
+
421
+ const { shouldShow, tippyOptions } = useBubbleMenu(
422
+ editor,
423
+ isHyperlinkPopupOpen,
424
+ );
425
+
340
426
  watch(
341
427
  () => props.styles.textAlign,
342
428
  (newAlignment) => {
@@ -376,9 +462,9 @@ export const useRichTextEditor = (
376
462
 
377
463
  // Update model when editor content changes
378
464
  editor.on('update', () => {
379
- const html = editor.getHTML();
465
+ const sanitizedData = sanitiseClientSideRTE(editor.getHTML());
380
466
 
381
- emit('update:modelValue', html);
467
+ emit('update:modelValue', sanitizedData.sanitizedHtml);
382
468
  });
383
469
 
384
470
  editor.on('selectionUpdate', () => {
@@ -421,15 +507,17 @@ export const useRichTextEditor = (
421
507
  }
422
508
 
423
509
  if (textStyleAttributes && textStyleAttributes.color) {
424
- fontSettings.selectedTextColor = Color(textStyleAttributes.color).hex();
510
+ if (!hasLogoColorVar(textStyleAttributes.color))
511
+ fontSettings.selectedTextColor = Color(textStyleAttributes.color).hex();
425
512
  } else {
426
513
  fontSettings.selectedTextColor = '#000000';
427
514
  }
428
515
 
429
516
  if (highlightAttributes && highlightAttributes.color) {
430
- fontSettings.selectedBackgroundColor = Color(
431
- highlightAttributes.color,
432
- ).hex();
517
+ if (!hasLogoColorVar(highlightAttributes.color))
518
+ fontSettings.selectedBackgroundColor = Color(
519
+ highlightAttributes.color,
520
+ ).hex();
433
521
  } else {
434
522
  fontSettings.selectedBackgroundColor = 'transparent';
435
523
  }
@@ -490,9 +578,14 @@ export const useRichTextEditor = (
490
578
  fontSettings.selectedFontSizePx = parseInt(
491
579
  emToPx(globalStyles?.fontSize ?? '2.25em'),
492
580
  );
493
- fontSettings.selectedTextColor = globalStyles?.color ?? '#000000';
494
- fontSettings.selectedBackgroundColor =
495
- globalStyles?.backgroundColor ?? 'transparent';
581
+ fontSettings.selectedTextColor = hasLogoColorVar(globalStyles.color ?? '')
582
+ ? '#000000'
583
+ : globalStyles?.color ?? '#000000';
584
+ fontSettings.selectedBackgroundColor = hasLogoColorVar(
585
+ globalStyles?.backgroundColor ?? '',
586
+ )
587
+ ? 'transparent'
588
+ : globalStyles?.backgroundColor ?? 'transparent';
496
589
  lineHeight.value = globalStyles?.lineHeight?.includes('em')
497
590
  ? emToPx(globalStyles?.lineHeight ?? '1em')
498
591
  : globalStyles?.lineHeight ?? '1';
@@ -512,9 +605,16 @@ export const useRichTextEditor = (
512
605
  fontSettings.selectedFontSizePx = parseInt(
513
606
  emToPx(props.styles?.fontSize ?? '2.25em'),
514
607
  );
515
- fontSettings.selectedTextColor = props.styles?.color ?? '#000000';
516
- fontSettings.selectedBackgroundColor =
517
- props.styles?.backgroundColor ?? 'transparent';
608
+ fontSettings.selectedTextColor = hasLogoColorVar(
609
+ props.styles?.color ?? '#000000',
610
+ )
611
+ ? '#000000'
612
+ : props.styles?.color ?? '#000000';
613
+ fontSettings.selectedBackgroundColor = hasLogoColorVar(
614
+ props.styles?.backgroundColor ?? '',
615
+ )
616
+ ? 'transparent'
617
+ : props.styles?.backgroundColor ?? 'transparent';
518
618
  lineHeight.value = props.styles?.lineHeight?.includes('em')
519
619
  ? emToPx(props.styles?.lineHeight ?? '1em')
520
620
  : props.styles?.lineHeight ?? '1';
@@ -543,8 +643,14 @@ export const useRichTextEditor = (
543
643
  toggleStrikeAll();
544
644
 
545
645
  if (globalStyles.color) {
546
- toggleTextColorAll(globalStyles.color);
547
- fontSettings.selectedTextColor = globalStyles.color;
646
+ if (!hasLogoColorVar(globalStyles.color)) {
647
+ toggleTextColorAll(globalStyles.color);
648
+ fontSettings.selectedTextColor = globalStyles.color;
649
+ } else {
650
+ // Apply logo color using CSS variable
651
+ toggleTextColorAll(getRTEColor(globalStyles.color, 'text'));
652
+ fontSettings.selectedTextColor = '#000000';
653
+ }
548
654
  }
549
655
 
550
656
  globalStyles.fontFamily && toggleFontAll(globalStyles.fontFamily);
@@ -630,6 +736,9 @@ export const useRichTextEditor = (
630
736
  toggleTextAlign();
631
737
  fontStyleChanges.textAlign = currentAlignment.value.alignment;
632
738
  break;
739
+ case 'hyperlink':
740
+ setHyperlinkUrl(editorOption.value as string);
741
+ break;
633
742
  }
634
743
 
635
744
  syncContentSettings(fontStyleChanges);
@@ -665,6 +774,149 @@ export const useRichTextEditor = (
665
774
  emit('blur');
666
775
  };
667
776
 
777
+ const handleHyperlink = (
778
+ action: 'toggle' | 'apply' | 'remove',
779
+ data?: { href?: string; text?: string },
780
+ ) => {
781
+ switch (action) {
782
+ case 'toggle':
783
+ isHyperlinkPopupOpen.value = !isHyperlinkPopupOpen.value;
784
+
785
+ if (isHyperlinkPopupOpen.value) {
786
+ if (data?.href && data?.text) {
787
+ setHyperlinkUrlValue(data.href);
788
+ markedText.value = data.text;
789
+ } else {
790
+ const linkAttrs = editor.getAttributes('link');
791
+
792
+ const selection = editor.state.selection;
793
+
794
+ if (linkAttrs.href) {
795
+ editor.commands.extendMarkRange('link');
796
+
797
+ const linkText = editor.state.doc.textBetween(
798
+ selection.from,
799
+ selection.to,
800
+ );
801
+
802
+ setHyperlinkUrlValue(linkAttrs.href);
803
+
804
+ markedText.value = linkText;
805
+ } else {
806
+ const selectedText = selection.empty
807
+ ? ''
808
+ : editor.state.doc.textBetween(selection.from, selection.to);
809
+
810
+ setHyperlinkUrlValue('');
811
+
812
+ markedText.value = selectedText;
813
+ }
814
+ }
815
+
816
+ editor.commands.focus(); // Hide bubble menu
817
+ }
818
+
819
+ break;
820
+
821
+ case 'apply':
822
+ const url = hyperlinkValue.value.value;
823
+
824
+ const text = markedText.value;
825
+
826
+ if (!url.trim()) {
827
+ isHyperlinkPopupOpen.value = false;
828
+
829
+ return;
830
+ }
831
+
832
+ const selection = editor.state?.selection;
833
+ const selectionRange = selection
834
+ ? { from: selection.from, to: selection.to }
835
+ : undefined;
836
+
837
+ applyHyperlinkToEditor(url, text, selectionRange);
838
+ isHyperlinkPopupOpen.value = false;
839
+ break;
840
+
841
+ case 'remove':
842
+ removeHyperlinkFromComposable();
843
+ isHyperlinkPopupOpen.value = false;
844
+ break;
845
+ }
846
+ };
847
+
848
+ const handleAdminColorChange = (
849
+ color: any,
850
+ colorType: 'textColor' | 'backgroundColor',
851
+ ) => {
852
+ const convertor =
853
+ colorType === 'textColor' ? colorConvertor : backgroundColorConvertor;
854
+ const convertedColor = convertor.convertBack(color.value);
855
+ const colorValue =
856
+ colorType === 'textColor'
857
+ ? convertedColor.color
858
+ : convertedColor.backgroundColor;
859
+
860
+ editor.commands.selectAll();
861
+
862
+ if (colorValue?.startsWith('#')) {
863
+ if (colorType === 'textColor') {
864
+ fontSettings.selectedTextColor = colorValue;
865
+ } else {
866
+ fontSettings.selectedBackgroundColor = colorValue;
867
+ }
868
+
869
+ triggerEditorStyleChange({
870
+ type: colorType,
871
+ value: colorValue,
872
+ });
873
+ } else {
874
+ // Handle logo theme colors using getRTEColor
875
+ if (isLogoColor(colorValue || '')) {
876
+ const processedColor = getRTEColor(
877
+ colorValue,
878
+ colorType === 'textColor' ? 'text' : 'background',
879
+ );
880
+
881
+ if (colorType === 'textColor') {
882
+ editor.commands.setColor(processedColor);
883
+ } else {
884
+ editor.commands.setHighlight({
885
+ color: processedColor,
886
+ });
887
+ }
888
+ } else {
889
+ if (colorType === 'textColor') {
890
+ editor.commands.unsetColor();
891
+ } else {
892
+ editor.commands.unsetHighlight();
893
+ }
894
+ }
895
+ }
896
+
897
+ const updateValue = {
898
+ textStyleType: undefined,
899
+ ...(colorType === 'textColor'
900
+ ? { color: colorValue }
901
+ : { backgroundColor: colorValue }),
902
+ };
903
+
904
+ if (props.name === 'textItems') {
905
+ contentSettingStore.updateTextItemTextStyleTypeWithStyles({
906
+ id: props.rawId,
907
+ name: props.name,
908
+ value: updateValue,
909
+ index: props.textItemIndex,
910
+ });
911
+ } else {
912
+ contentSettingStore.updateTextStyles({
913
+ id: props.rawId,
914
+ name: props.name,
915
+ value: updateValue,
916
+ });
917
+ }
918
+ };
919
+
668
920
  onBeforeUnmount(() => {
669
921
  editor.destroy();
670
922
  });
@@ -690,5 +942,11 @@ export const useRichTextEditor = (
690
942
  setInitialStyleSettings,
691
943
  copyGlobalStyleSettings,
692
944
  unsetAllMarks,
945
+ handleHyperlink,
946
+ hyperlinkValue,
947
+ setHyperlinkUrlValue,
948
+ shouldShow,
949
+ tippyOptions,
950
+ handleAdminColorChange,
693
951
  };
694
952
  };
@@ -5,6 +5,7 @@ export interface ButtonGroupBasicOption {
5
5
  label: string;
6
6
  isSelected: boolean;
7
7
  dataAttribute?: string;
8
+ disabled?: boolean;
8
9
  }
9
10
 
10
11
  export type ButtonGroupOption =
@@ -18,4 +19,5 @@ export type ButtonGroupOption =
18
19
  iconViewBox?: string;
19
20
  iconSize?: string;
20
21
  dataAttribute?: string;
22
+ disabled?: boolean;
21
23
  };
@@ -4,6 +4,7 @@ exports[`brand page maker store module > brand page maker module should returns
4
4
  [
5
5
  "logo",
6
6
  "profile",
7
+ "text",
7
8
  "general-link",
8
9
  "website",
9
10
  "email",