@designcrowd/library.brand-page 5.10.20 → 5.10.30
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.
- package/lib/src/brand-page/models/index.d.ts +5 -0
- package/lib/src/brand-page/models/index.js +4 -0
- package/lib/src/brand-page/utils/style.util.d.ts +8 -1
- package/lib/src/brand-page/utils/style.util.js +58 -5
- package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.js +1 -1
- package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/content-settings-items.fixture.js +1 -0
- package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/page-content-items.d.ts +1 -1
- package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/page-content-items.js +2 -1
- package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +33 -0
- package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.js +35 -1
- package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.d.ts +1 -0
- package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.js +17 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/bubbleMenu.d.ts +19 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/bubbleMenu.js +31 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/AutoLink.d.ts +2 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/AutoLink.js +161 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/MaxLength.js +3 -3
- package/lib/src/brand-page-maker/composables/rich-text-editor/font.d.ts +1 -1
- package/lib/src/brand-page-maker/composables/rich-text-editor/font.js +0 -1
- package/lib/src/brand-page-maker/composables/rich-text-editor/formatting.d.ts +1 -1
- package/lib/src/brand-page-maker/composables/rich-text-editor/formatting.js +0 -1
- package/lib/src/brand-page-maker/composables/rich-text-editor/hyperlink.d.ts +19 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/hyperlink.js +87 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/spacing.d.ts +1 -1
- package/lib/src/brand-page-maker/composables/rich-text-editor/spacing.js +0 -1
- package/lib/src/brand-page-maker/composables/rich-text-editor/textAlign.d.ts +1 -1
- package/lib/src/brand-page-maker/composables/rich-text-editor/textAlign.js +0 -1
- package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.d.ts +24 -3
- package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.js +214 -33
- package/lib/src/brand-page-maker/models/button-group.model.d.ts +2 -0
- package/lib/src/brand-page-maker/utils/rich-text-editor.util.d.ts +19 -2
- package/lib/src/brand-page-maker/utils/rich-text-editor.util.js +340 -8
- package/lib/src/{bundled-translations.de-DE-O4sKkzBX.js → bundled-translations.de-DE-DjQFwukR.js} +1 -1
- package/lib/src/{bundled-translations.es-ES-C4lGaf08.js → bundled-translations.es-ES--EbGRI7e.js} +1 -1
- package/lib/src/bundled-translations.fr-FR-BS3Kia5y.js +117 -0
- package/lib/src/{bundled-translations.fr-FR-CIy8KjAV.js → bundled-translations.fr-FR-VtC2JYUC.js} +1 -1
- package/lib/src/{bundled-translations.pt-PT-C8EcSdyX.js → bundled-translations.pt-PT-l9cEldEo.js} +1 -1
- package/lib/src/bundles/bundled-translations.fr-FR.json +2 -2
- package/lib/src/css/library.brand-page-brandCrowd.min.css +96 -70
- package/lib/src/css/library.brand-page-brandPage.min.css +96 -70
- package/lib/src/css/library.brand-page-designCom.min.css +96 -70
- package/lib/src/css/library.brand-page-preview.min.css +96 -70
- package/lib/src/index.d.ts +1 -0
- package/lib/src/index.mjs +29673 -27225
- package/lib/src/lib.js +1 -0
- package/lib/src/mockServiceWorker.js +91 -54
- package/lib/src/shared/content-settings/components/color-field/ColorField.mixin.d.ts +11 -0
- package/lib/src/shared/content-settings/components/color-field/ColorField.mixin.js +5 -0
- package/lib/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.mixin.d.ts +11 -1
- package/lib/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.mixin.js +4 -0
- package/lib/src/shared/content-settings/components/url-field/UrlField.mixin.d.ts +2 -0
- package/lib/src/shared/content-settings/components/url-field/UrlField.mixin.js +12 -7
- package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +2 -0
- package/package.json +6 -3
- package/src/brand-page/components/banner-section/BannerSection.vue +6 -0
- package/src/brand-page/components/text/Text.vue +2 -0
- package/src/brand-page/components/text-wrapper/TextWrapper.vue +31 -11
- package/src/brand-page/models/index.ts +6 -0
- package/src/brand-page/utils/style.util.ts +105 -5
- package/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.ts +1 -1
- package/src/brand-page-maker/components/brand-page-maker/__fixtures__/content-settings-items.fixture.ts +1 -0
- package/src/brand-page-maker/components/brand-page-maker/__fixtures__/page-content-items.ts +2 -0
- package/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.ts +44 -1
- package/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.vue +1 -0
- package/src/brand-page-maker/components/brandpage-settings/i18n/brand-page-settings.fr-FR.json +1 -1
- package/src/brand-page-maker/components/google-analytics/i18n/google-analytics.fr-FR.json +1 -1
- package/src/brand-page-maker/components/rich-text-editor/RichTextEditor.vue +539 -50
- package/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.ts +22 -0
- package/src/brand-page-maker/components/template-preview/TemplatePreview.vue +1 -1
- package/src/brand-page-maker/composables/rich-text-editor/bubbleMenu.ts +42 -0
- package/src/brand-page-maker/composables/rich-text-editor/extensions/AutoLink.ts +227 -0
- package/src/brand-page-maker/composables/rich-text-editor/extensions/MaxLength.test.ts +1 -1
- package/src/brand-page-maker/composables/rich-text-editor/extensions/MaxLength.ts +4 -15
- package/src/brand-page-maker/composables/rich-text-editor/font.ts +1 -1
- package/src/brand-page-maker/composables/rich-text-editor/formatting.ts +1 -1
- package/src/brand-page-maker/composables/rich-text-editor/hyperlink.ts +114 -0
- package/src/brand-page-maker/composables/rich-text-editor/spacing.ts +1 -1
- package/src/brand-page-maker/composables/rich-text-editor/textAlign.ts +1 -1
- package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.ts +299 -41
- package/src/brand-page-maker/models/button-group.model.ts +2 -0
- package/src/brand-page-maker/stores/brandpage-maker/__snapshots__/brandpage-maker-store.test.ts.snap +1 -0
- package/src/brand-page-maker/utils/rich-text-editor.util.test.ts +418 -0
- package/src/brand-page-maker/utils/rich-text-editor.util.ts +470 -25
- package/src/bundles/bundled-translations.fr-FR.json +2 -2
- package/src/lib.ts +1 -0
- package/src/shared/content-settings/components/color-field/ColorField.mixin.ts +5 -0
- package/src/shared/content-settings/components/color-field/ColorField.vue +1 -1
- package/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.mixin.ts +4 -0
- package/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.vue +2 -2
- package/src/shared/content-settings/components/text-field/TextField.vue +1 -1
- package/src/shared/content-settings/components/text-items-field/TextItemsField.vue +2 -2
- package/src/shared/content-settings/components/textarea-field/TextareaField.vue +3 -3
- package/src/shared/content-settings/components/url-field/UrlField.mixin.ts +15 -10
- package/src/shared/content-settings/components/url-field/UrlField.vue +1 -0
- package/lib/src/bundled-translations.fr-FR-CTnDppmf.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
|
-
|
|
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 {
|
|
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
|
-
|
|
216
|
-
event.preventDefault();
|
|
275
|
+
const selection = view.state.selection;
|
|
217
276
|
|
|
218
|
-
|
|
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
|
|
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
|
-
|
|
283
|
+
const slice = selection.content(),
|
|
284
|
+
{ dom, text } = view.serializeForClipboard(slice);
|
|
231
285
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
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
|
-
|
|
241
|
-
|
|
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
|
|
465
|
+
const sanitizedData = sanitiseClientSideRTE(editor.getHTML());
|
|
380
466
|
|
|
381
|
-
emit('update:modelValue',
|
|
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
|
-
|
|
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
|
-
|
|
431
|
-
|
|
432
|
-
|
|
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
|
|
494
|
-
|
|
495
|
-
globalStyles?.
|
|
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 =
|
|
516
|
-
|
|
517
|
-
|
|
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
|
-
|
|
547
|
-
|
|
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
|
};
|