@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.
- package/lib/src/brand-page/constants/font.constants.d.ts +4 -4
- 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/models/styles.model.d.ts +5 -5
- 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/BrandPageMaker.stories.js +2 -2
- 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/navigation/Navigation.mixin.d.ts +2 -2
- package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.d.ts +3 -3
- 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/components/upgrade-to-premium-button/UpgradeToPremiumButton.mixin.d.ts +2 -2
- 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/constants/brandpage-meta-constant.d.ts +5 -5
- package/lib/src/brand-page-maker/constants/index.d.ts +2 -2
- 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-BXxQYq2i.js +119 -0
- package/lib/src/bundled-translations.de-DE-BXcluMZ2.js +119 -0
- 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.es-ES-DSd-wV16.js +119 -0
- package/lib/src/{bundled-translations.fr-FR-CIy8KjAV.js → bundled-translations.fr-FR-VtC2JYUC.js} +1 -1
- package/lib/src/bundled-translations.fr-FR-jKR_dxWR.js +119 -0
- package/lib/src/bundled-translations.pt-PT-CwvYqXXo.js +119 -0
- package/lib/src/{bundled-translations.pt-PT-C8EcSdyX.js → bundled-translations.pt-PT-l9cEldEo.js} +1 -1
- package/lib/src/bundles/bundled-translations.de-DE.json +11 -0
- package/lib/src/bundles/bundled-translations.es-ES.json +11 -0
- package/lib/src/bundles/bundled-translations.fr-FR.json +13 -2
- package/lib/src/bundles/bundled-translations.json +11 -0
- package/lib/src/bundles/bundled-translations.pt-PT.json +11 -0
- package/lib/src/composables/useTranslate.d.ts +64 -62
- package/lib/src/composables/useTranslate.js +18 -7
- package/lib/src/css/library.brand-page-brandCrowd.min.css +101 -75
- package/lib/src/css/library.brand-page-brandPage.min.css +101 -75
- package/lib/src/css/library.brand-page-designCom.min.css +101 -75
- package/lib/src/css/library.brand-page-preview.min.css +101 -75
- package/lib/src/index.d.ts +3 -1
- package/lib/src/index.mjs +30209 -27738
- package/lib/src/lib.js +2 -1
- package/lib/src/mockServiceWorker.js +91 -54
- package/lib/src/shared/content-settings/components/GenericTextInput.mixin.d.ts +2 -2
- 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/email-field/EmailField.mixin.d.ts +2 -2
- 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/shape-field/ShapeField.mixin.d.ts +1 -1
- package/lib/src/shared/content-settings/components/tel-field/TelField.mixin.d.ts +2 -2
- package/lib/src/shared/content-settings/components/testimonial-items-field/TestimonialItemsField.mixin.d.ts +2 -2
- package/lib/src/shared/content-settings/components/text-field/TextField.mixin.d.ts +2 -2
- package/lib/src/shared/content-settings/components/text-image-field/TextImageField.mixin.d.ts +2 -2
- package/lib/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.d.ts +2 -2
- package/lib/src/shared/content-settings/components/textarea-field/TextareaField.mixin.d.ts +2 -2
- package/lib/src/shared/content-settings/components/url-field/UrlField.mixin.d.ts +4 -2
- package/lib/src/shared/content-settings/components/url-field/UrlField.mixin.js +12 -7
- package/lib/src/shared/content-settings/components/youtube-video-field/YoutubeVideoField.mixin.d.ts +2 -2
- package/lib/src/shared/logo-settings/components/EditLogoSettings.mixin.d.ts +3 -3
- package/lib/src/shared/my-uploads/MyUploads.mixin.d.ts +1 -1
- package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +1 -1
- package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +4 -2
- package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +4 -4
- package/lib/src/shared/shape-library/ShapeLibrary.mixin.d.ts +1 -1
- package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +2 -2
- package/lib/src/shared/template-settings/models.d.ts +3 -3
- package/package.json +6 -3
- package/src/brand-page/components/banner-section/BannerSection.vue +6 -0
- package/src/brand-page/components/sensitive-content/SensitiveContentModal.vue +28 -11
- package/src/brand-page/components/sensitive-content/i18n/sensitive-content-modal.de-DE.json +13 -0
- package/src/brand-page/components/sensitive-content/i18n/sensitive-content-modal.es-ES.json +13 -0
- package/src/brand-page/components/sensitive-content/i18n/sensitive-content-modal.fr-FR.json +13 -0
- package/src/brand-page/components/sensitive-content/i18n/sensitive-content-modal.json +13 -0
- package/src/brand-page/components/sensitive-content/i18n/sensitive-content-modal.pt-PT.json +13 -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/BrandPageMaker.stories.ts +2 -2
- 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.de-DE.json +11 -0
- package/src/bundles/bundled-translations.es-ES.json +11 -0
- package/src/bundles/bundled-translations.fr-FR.json +13 -2
- package/src/bundles/bundled-translations.json +11 -0
- package/src/bundles/bundled-translations.pt-PT.json +11 -0
- package/src/composables/useTranslate.ts +25 -8
- package/src/lib.ts +7 -1
- 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-DaK60m67.js +0 -117
- package/lib/src/bundled-translations.de-DE-848cpWPB.js +0 -117
- package/lib/src/bundled-translations.es-ES-CtPI5G7I.js +0 -117
- package/lib/src/bundled-translations.fr-FR-CTnDppmf.js +0 -117
- package/lib/src/bundled-translations.pt-PT-Balnne-7.js +0 -117
|
@@ -1,4 +1,60 @@
|
|
|
1
1
|
<template>
|
|
2
|
+
<div v-if="isAdmin" class="tw-p-3">
|
|
3
|
+
<p
|
|
4
|
+
class="tw-font-sans tw-font-bold tw-text-secondary-800 tw-text-sm tw-mb-2 tw-mt-4"
|
|
5
|
+
>
|
|
6
|
+
{{ textStyleFieldTr(`color`) }}
|
|
7
|
+
</p>
|
|
8
|
+
<ColorField
|
|
9
|
+
:id="`${rawId}-color${textItemIndex ?? ''}`"
|
|
10
|
+
:enable-color-match="true"
|
|
11
|
+
:name="name + 'TextStyle'"
|
|
12
|
+
:value="textColorValue"
|
|
13
|
+
:options="colorConvertor.convert(props.styles)"
|
|
14
|
+
:is-admin="isAdmin"
|
|
15
|
+
:logo-theme="logoTheme"
|
|
16
|
+
:show-color-pallet="false"
|
|
17
|
+
:is-toggled="true"
|
|
18
|
+
@update:model-value="
|
|
19
|
+
(color: ColorPickerEvent) => {
|
|
20
|
+
handleAdminColorChange(color, 'textColor');
|
|
21
|
+
|
|
22
|
+
if (!color.value || color.value === '') {
|
|
23
|
+
isTextColorPickerDisabled = false;
|
|
24
|
+
} else {
|
|
25
|
+
isTextColorPickerDisabled = true;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
"
|
|
29
|
+
/>
|
|
30
|
+
<p
|
|
31
|
+
class="tw-font-sans tw-font-bold tw-text-secondary-800 tw-text-sm tw-mb-2 tw-mt-4"
|
|
32
|
+
>
|
|
33
|
+
{{ textStyleFieldTr(`backgroundColor`) }}
|
|
34
|
+
</p>
|
|
35
|
+
<ColorField
|
|
36
|
+
:id="`${rawId}-backgroundStyle${textItemIndex ?? ''}`"
|
|
37
|
+
:enable-color-match="true"
|
|
38
|
+
:name="name"
|
|
39
|
+
:value="textBackgroundColorValue"
|
|
40
|
+
:options="backgroundColorConvertor.convert(props.styles)"
|
|
41
|
+
:is-admin="isAdmin"
|
|
42
|
+
:show-color-pallet="false"
|
|
43
|
+
:logo-theme="logoTheme"
|
|
44
|
+
:is-toggled="false"
|
|
45
|
+
@update:model-value="
|
|
46
|
+
(color: ColorPickerEvent) => {
|
|
47
|
+
handleAdminColorChange(color, 'backgroundColor');
|
|
48
|
+
|
|
49
|
+
if (!color.value || color.value === '') {
|
|
50
|
+
isBackgroundColorPickerDisabled = false;
|
|
51
|
+
} else {
|
|
52
|
+
isBackgroundColorPickerDisabled = true;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
"
|
|
56
|
+
/>
|
|
57
|
+
</div>
|
|
2
58
|
<div
|
|
3
59
|
class="rich-text-editor tw-border tw-border-solid tw-border-grayscale-500 tw-rounded"
|
|
4
60
|
>
|
|
@@ -6,6 +62,7 @@
|
|
|
6
62
|
<div class="style-editor">
|
|
7
63
|
<Dropdown
|
|
8
64
|
ref="textStyleTypeDropdownRef"
|
|
65
|
+
v-click-outside="(e: MouseEvent) => clickOutsideTextStyle(e)"
|
|
9
66
|
data-test-tag="text-style-dropdown"
|
|
10
67
|
class="style-editor-button style-editor-button-textstyle"
|
|
11
68
|
:title="
|
|
@@ -16,7 +73,6 @@
|
|
|
16
73
|
icon-size="xs"
|
|
17
74
|
element-classes="text-dropdown-title"
|
|
18
75
|
menu-element-classes="tw-min-w-[310px] tw-left-0"
|
|
19
|
-
v-click-outside="(e: MouseEvent) => clickOutsideTextStyle(e)"
|
|
20
76
|
>
|
|
21
77
|
<div
|
|
22
78
|
class="tw-z-1000 tw-bg-white tw-text-grayscale-600"
|
|
@@ -25,8 +81,8 @@
|
|
|
25
81
|
<div
|
|
26
82
|
v-for="option in textStyleTypeOptions"
|
|
27
83
|
:key="option.value"
|
|
28
|
-
@click="onSelectTextStyleType(option)"
|
|
29
84
|
class="tw-flex tw-items-center tw-px-2 tw-py-2 drop-down-item tw-cursor-pointer"
|
|
85
|
+
@click="onSelectTextStyleType(option)"
|
|
30
86
|
>
|
|
31
87
|
<span
|
|
32
88
|
class="tw-flex tw-flex-row tw-w-full tw-justify-between tw-items-center"
|
|
@@ -39,6 +95,7 @@
|
|
|
39
95
|
</Dropdown>
|
|
40
96
|
<Dropdown
|
|
41
97
|
ref="fontStyleDropdownRef"
|
|
98
|
+
v-click-outside="(e: MouseEvent) => clickOutsideFontStyle(e)"
|
|
42
99
|
data-test-tag="font-style-dropdown"
|
|
43
100
|
:title="fontSettings.selectedFont"
|
|
44
101
|
icon-size="xs"
|
|
@@ -47,7 +104,6 @@
|
|
|
47
104
|
menu-element-classes="tw-min-w-[340px] left-align"
|
|
48
105
|
menu-align="left"
|
|
49
106
|
tooltip="Font"
|
|
50
|
-
v-click-outside="(e: MouseEvent) => clickOutsideFontStyle(e)"
|
|
51
107
|
>
|
|
52
108
|
<DropdownItem
|
|
53
109
|
:key="fontFamilySelectorKey"
|
|
@@ -55,8 +111,8 @@
|
|
|
55
111
|
class="tw-min-w-[340px] tw-max-h-[400px] tw-overflow-auto tw-z-1000 tw-bg-white hover:tw-bg-white tw-text-grayscale-600"
|
|
56
112
|
>
|
|
57
113
|
<FontFamilySelector
|
|
58
|
-
class="tw-w-full"
|
|
59
114
|
:key="fontFamilySelectorKey"
|
|
115
|
+
class="tw-w-full"
|
|
60
116
|
:font-family-options="availableTextFontFamilyOptions"
|
|
61
117
|
:value="fontSettings.selectedFont"
|
|
62
118
|
@on-select="
|
|
@@ -93,8 +149,11 @@
|
|
|
93
149
|
</div>
|
|
94
150
|
<div class="style-editor-button" title="Text Color">
|
|
95
151
|
<ColorField
|
|
96
|
-
class="tw-max-h-9 tw-max-w-9 tw-justify-center"
|
|
97
152
|
id="text-color-picker"
|
|
153
|
+
class="tw-max-h-9 tw-max-w-9 tw-justify-center"
|
|
154
|
+
:class="{
|
|
155
|
+
'tw-opacity-50 tw-pointer-events-none': isTextColorPickerDisabled,
|
|
156
|
+
}"
|
|
98
157
|
data-test-tag="text-color-picker"
|
|
99
158
|
name="fill"
|
|
100
159
|
:is-rich-text-editor="true"
|
|
@@ -122,33 +181,31 @@
|
|
|
122
181
|
class="toolbar-editor-button"
|
|
123
182
|
data-test-tag="bold-toolbar"
|
|
124
183
|
icon="maker-bold"
|
|
125
|
-
|
|
184
|
+
icon-size="sm"
|
|
126
185
|
:class="{
|
|
127
186
|
active: editor.isActive('bold'),
|
|
128
187
|
}"
|
|
129
188
|
@click="
|
|
130
189
|
triggerEditorStyleChange({ type: 'fontWeight', value: 'bold' })
|
|
131
190
|
"
|
|
132
|
-
alt-text="Bold"
|
|
133
191
|
/>
|
|
134
192
|
<Button
|
|
135
193
|
class="toolbar-editor-button"
|
|
136
194
|
data-test-tag="italic-toolbar"
|
|
137
195
|
icon="maker-italic"
|
|
138
|
-
|
|
196
|
+
icon-size="sm"
|
|
139
197
|
:class="{
|
|
140
198
|
active: editor.isActive('italic'),
|
|
141
199
|
}"
|
|
142
200
|
@click="
|
|
143
201
|
triggerEditorStyleChange({ type: 'fontStyle', value: 'italic' })
|
|
144
202
|
"
|
|
145
|
-
alt-text="Italic"
|
|
146
203
|
/>
|
|
147
204
|
<Button
|
|
148
205
|
class="toolbar-editor-button"
|
|
149
206
|
icon="maker-underline"
|
|
150
207
|
data-test-tag="underline-toolbar"
|
|
151
|
-
|
|
208
|
+
icon-size="sm"
|
|
152
209
|
:class="{
|
|
153
210
|
active: editor.isActive('underline'),
|
|
154
211
|
}"
|
|
@@ -158,7 +215,6 @@
|
|
|
158
215
|
value: 'underline',
|
|
159
216
|
})
|
|
160
217
|
"
|
|
161
|
-
alt-text="Underline"
|
|
162
218
|
/>
|
|
163
219
|
|
|
164
220
|
<div class="border mobile" />
|
|
@@ -166,7 +222,7 @@
|
|
|
166
222
|
class="toolbar-editor-button"
|
|
167
223
|
data-test-tag="strikethrough-toolbar"
|
|
168
224
|
icon="maker-strikethrough"
|
|
169
|
-
|
|
225
|
+
icon-size="sm"
|
|
170
226
|
justify="center"
|
|
171
227
|
:class="{
|
|
172
228
|
active: editor.isActive('strike'),
|
|
@@ -177,12 +233,15 @@
|
|
|
177
233
|
value: 'line-through',
|
|
178
234
|
})
|
|
179
235
|
"
|
|
180
|
-
alt-text="Strikethrough"
|
|
181
236
|
/>
|
|
182
237
|
<div class="toolbar-editor-button" title="Highlight Color">
|
|
183
238
|
<ColorField
|
|
184
|
-
class="tw-max-h-9 tw-max-w-9 tw-justify-center"
|
|
185
239
|
id="text-background-color-picker"
|
|
240
|
+
class="tw-max-h-9 tw-max-w-9 tw-justify-center"
|
|
241
|
+
:class="{
|
|
242
|
+
'tw-opacity-50 tw-pointer-events-none':
|
|
243
|
+
isBackgroundColorPickerDisabled,
|
|
244
|
+
}"
|
|
186
245
|
data-test-tag="background-color-picker"
|
|
187
246
|
name="fill"
|
|
188
247
|
:is-rich-text-editor="true"
|
|
@@ -207,7 +266,7 @@
|
|
|
207
266
|
class="toolbar-editor-button"
|
|
208
267
|
:icon="currentAlignment.icon"
|
|
209
268
|
data-test-tag="alignment-toolbar"
|
|
210
|
-
|
|
269
|
+
icon-size="sm"
|
|
211
270
|
justify="center"
|
|
212
271
|
:class="{
|
|
213
272
|
active: currentAlignment.isActive(),
|
|
@@ -215,13 +274,12 @@
|
|
|
215
274
|
@click="
|
|
216
275
|
triggerEditorStyleChange({ type: 'textAlign', value: 'center' })
|
|
217
276
|
"
|
|
218
|
-
alt-text="Alignment"
|
|
219
277
|
/>
|
|
220
278
|
<Button
|
|
221
279
|
class="toolbar-editor-button"
|
|
222
280
|
data-test-tag="alignment-toolbar"
|
|
223
281
|
icon="maker-spacing"
|
|
224
|
-
|
|
282
|
+
icon-size="sm"
|
|
225
283
|
justify="center"
|
|
226
284
|
:class="{
|
|
227
285
|
active:
|
|
@@ -230,48 +288,151 @@
|
|
|
230
288
|
isSpacingDropdownOpen,
|
|
231
289
|
}"
|
|
232
290
|
@click="isSpacingDropdownOpen = !isSpacingDropdownOpen"
|
|
233
|
-
|
|
291
|
+
/>
|
|
292
|
+
<Button
|
|
293
|
+
class="toolbar-editor-button"
|
|
294
|
+
data-test-tag="link-toolbar"
|
|
295
|
+
icon="maker-link"
|
|
296
|
+
icon-size="sm"
|
|
297
|
+
justify="center"
|
|
298
|
+
:class="{
|
|
299
|
+
active: editor.isActive('link'),
|
|
300
|
+
}"
|
|
301
|
+
@click="onClickHyperlink()"
|
|
234
302
|
/>
|
|
235
303
|
</div>
|
|
236
304
|
<div
|
|
237
305
|
v-if="isSpacingDropdownOpen"
|
|
238
306
|
ref="spacingPopupRef"
|
|
239
|
-
class="spacing-popup-container tw-max-w-[310px]"
|
|
240
|
-
data-test-tag="spacing-toolbar"
|
|
241
307
|
v-click-outside="(e: MouseEvent) => clickOutsideTextSpacing(e)"
|
|
308
|
+
class="popup-container tw-max-w-[310px] spacing-popup"
|
|
309
|
+
data-test-tag="spacing-toolbar"
|
|
242
310
|
>
|
|
243
|
-
<div class="
|
|
311
|
+
<div class="popup-panel">
|
|
244
312
|
<label class="tw-block tw-text-sm tw-mb-1 tw-font-bold"
|
|
245
313
|
>Letter Spacing</label
|
|
246
314
|
>
|
|
247
315
|
<Slider
|
|
316
|
+
v-model="letterSpacingValue"
|
|
248
317
|
:min="MIN_LETTER_SPACING_PERCENT"
|
|
249
318
|
:max="MAX_LETTER_SPACING_PERCENT"
|
|
250
319
|
:prevent-negative="true"
|
|
251
|
-
v-model="letterSpacingValue"
|
|
252
320
|
/>
|
|
253
321
|
|
|
254
322
|
<label class="tw-block tw-text-sm tw-mt-3 tw-mb-1 tw-font-bold"
|
|
255
323
|
>Line Height</label
|
|
256
324
|
>
|
|
257
325
|
<Slider
|
|
326
|
+
v-model="lineHeightValue"
|
|
258
327
|
:min="MIN_LINE_HEIGHT"
|
|
259
328
|
:max="MAX_LINE_HEIGHT"
|
|
260
329
|
:step="0.1"
|
|
261
330
|
:max-decimal-point="1"
|
|
262
|
-
|
|
331
|
+
/>
|
|
332
|
+
</div>
|
|
333
|
+
</div>
|
|
334
|
+
<div
|
|
335
|
+
v-if="isHyperlinkPopupOpen"
|
|
336
|
+
ref="linkPopupRef"
|
|
337
|
+
v-click-outside="(e: MouseEvent) => clickOutsideHyperlink(e)"
|
|
338
|
+
class="popup-container tw-min-w-[300px] hyperlink-popup"
|
|
339
|
+
data-test-tag="hyperlink-toolbar"
|
|
340
|
+
>
|
|
341
|
+
<div class="popup-panel tw-flex tw-flex-col tw-gap-3">
|
|
342
|
+
<FieldSubHeader title="Text" />
|
|
343
|
+
<TextInput v-model="markedText" placeholder="Display Text" />
|
|
344
|
+
|
|
345
|
+
<FieldSubHeader title="Link to" />
|
|
346
|
+
<ButtonGroup
|
|
347
|
+
:options="btnLinkOptions"
|
|
348
|
+
:columns="2"
|
|
349
|
+
@on-select="onSelectLinkType"
|
|
350
|
+
/>
|
|
351
|
+
<UrlField
|
|
352
|
+
v-if="selectedLinkType === HYPERLINK_TYPE.url"
|
|
353
|
+
id="id"
|
|
354
|
+
name="url"
|
|
355
|
+
:role="selectedLinkTypeValue"
|
|
356
|
+
:value="hyperlinkUrlValue"
|
|
357
|
+
:settings="urlValidationSettings"
|
|
358
|
+
placeholder="https://example.com"
|
|
359
|
+
@update:model-value="(obj) => setHyperlinkUrlValue(obj.value)"
|
|
360
|
+
/>
|
|
361
|
+
<PageDropdownField
|
|
362
|
+
v-if="selectedLinkType === HYPERLINK_TYPE.page"
|
|
363
|
+
id="page-dropdown"
|
|
364
|
+
name="page"
|
|
365
|
+
:value="selectedPage"
|
|
366
|
+
placeholder="Select a page"
|
|
367
|
+
:show-upgrade-btn="false"
|
|
368
|
+
@update:model-value="onPageSelected"
|
|
369
|
+
/>
|
|
370
|
+
<Button
|
|
371
|
+
:disabled="isAddLinkButtonDisabled"
|
|
372
|
+
class="tw-w-full"
|
|
373
|
+
:full-width="true"
|
|
374
|
+
label="Add Link"
|
|
375
|
+
variant="secondary"
|
|
376
|
+
size="small"
|
|
377
|
+
@click="applyHyperlink"
|
|
263
378
|
/>
|
|
264
379
|
</div>
|
|
265
380
|
</div>
|
|
266
381
|
</div>
|
|
267
|
-
<
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
382
|
+
<div class="tw-relative">
|
|
383
|
+
<BubbleMenu
|
|
384
|
+
:editor="editor"
|
|
385
|
+
:tippy-options="tippyOptions"
|
|
386
|
+
:update-delay="0"
|
|
387
|
+
:should-show="shouldShow"
|
|
388
|
+
class="tw-w-fit"
|
|
389
|
+
>
|
|
390
|
+
<div class="bubble-menu">
|
|
391
|
+
<div
|
|
392
|
+
class="popup-panel tw-grid tw-grid-cols-4 tw-gap-2 tw-items-center tw-justify-between"
|
|
393
|
+
>
|
|
394
|
+
<div
|
|
395
|
+
class="tw-border-solid tw-border-r tw-border-grayscale-500 tw-pr-4 tw-mr-4 tw-col-span-3 tw-overflow-hidden tw-text-ellipsis"
|
|
396
|
+
>
|
|
397
|
+
<a
|
|
398
|
+
v-if="isExternalLink"
|
|
399
|
+
:href="editor.getAttributes('link').href"
|
|
400
|
+
target="_blank"
|
|
401
|
+
rel="noopener noreferrer"
|
|
402
|
+
class="maker-anchor tw-whitespace-pre"
|
|
403
|
+
>
|
|
404
|
+
{{ editor.getAttributes('link').href }}
|
|
405
|
+
</a>
|
|
406
|
+
<div v-else class="tw-whitespace-pre">
|
|
407
|
+
{{ `/${editor.getAttributes('link').href}` }}
|
|
408
|
+
</div>
|
|
409
|
+
</div>
|
|
410
|
+
<div class="tw-flex tw-gap-4 tw-col-span-1">
|
|
411
|
+
<Icon
|
|
412
|
+
name="edit"
|
|
413
|
+
size="sm"
|
|
414
|
+
class="tw-cursor-pointer"
|
|
415
|
+
@click="onClickHyperlink()"
|
|
416
|
+
/>
|
|
417
|
+
<Icon
|
|
418
|
+
name="delete"
|
|
419
|
+
size="sm"
|
|
420
|
+
class="tw-cursor-pointer"
|
|
421
|
+
@click="handleHyperlink('remove')"
|
|
422
|
+
/>
|
|
423
|
+
</div>
|
|
424
|
+
</div>
|
|
425
|
+
</div>
|
|
426
|
+
</BubbleMenu>
|
|
427
|
+
<EditorContent
|
|
428
|
+
:id="id"
|
|
429
|
+
tabindex="0"
|
|
430
|
+
:editor="editor"
|
|
431
|
+
:v-model="model"
|
|
432
|
+
@focus="onFocus"
|
|
433
|
+
@blur="onBlur"
|
|
434
|
+
/>
|
|
435
|
+
</div>
|
|
275
436
|
</div>
|
|
276
437
|
</template>
|
|
277
438
|
|
|
@@ -285,6 +446,7 @@ import {
|
|
|
285
446
|
ref,
|
|
286
447
|
onMounted,
|
|
287
448
|
watch,
|
|
449
|
+
nextTick,
|
|
288
450
|
} from 'vue';
|
|
289
451
|
import {
|
|
290
452
|
Button,
|
|
@@ -293,14 +455,19 @@ import {
|
|
|
293
455
|
NumberStepper,
|
|
294
456
|
Slider,
|
|
295
457
|
Icon,
|
|
458
|
+
ButtonGroup,
|
|
459
|
+
TextInput,
|
|
296
460
|
} from '@designcrowd/fe-shared-lib';
|
|
297
|
-
import { EditorContent } from '@tiptap/vue-3';
|
|
461
|
+
import { EditorContent, BubbleMenu } from '@tiptap/vue-3';
|
|
298
462
|
import { useRichTextEditor } from '../../composables/rich-text-editor/useRichTextEditor';
|
|
299
463
|
import FontFamilySelector from '../../../shared/font-family-selector/FontFamilySelector.vue';
|
|
300
464
|
import ColorField from '../../../shared/content-settings/components/color-field/ColorField.vue';
|
|
465
|
+
import UrlField from '../../../shared/content-settings/components/url-field/UrlField.vue';
|
|
301
466
|
|
|
302
467
|
import { useUiStyleSettingsStore } from '../../../shared/style-settings/store';
|
|
303
468
|
import { useUiContentSettingsStore } from '../../../shared/content-settings/store';
|
|
469
|
+
import { useUiPageSettingsStore } from '../../../shared/page-settings/store';
|
|
470
|
+
import { URL_REG_EX } from '../../../shared/content-settings/constants';
|
|
304
471
|
import { v4 as uuidV4 } from 'uuid';
|
|
305
472
|
import {
|
|
306
473
|
MIN_LETTER_SPACING_PERCENT,
|
|
@@ -310,12 +477,23 @@ import {
|
|
|
310
477
|
DEFAULT_FONT_SIZE,
|
|
311
478
|
MAX_TEXT_SIZE_PX,
|
|
312
479
|
TEXT_STYLE_TYPES,
|
|
480
|
+
HYPERLINK_TYPE,
|
|
313
481
|
type TextStyleDeclaration,
|
|
314
482
|
type TextStyles,
|
|
315
483
|
type TextItem,
|
|
484
|
+
type HyperlinkType,
|
|
485
|
+
STYLE_THEME_KEYS,
|
|
316
486
|
} from '../../../brand-page';
|
|
317
487
|
import { useBrandPageMakerUserStore, useUiStore } from '../../stores';
|
|
318
488
|
import type { ButtonGroupOption } from '../../models/button-group.model';
|
|
489
|
+
import FieldSubHeader from '../../../shared/content-settings/components/field-sub-header/FieldSubHeader.vue';
|
|
490
|
+
import PageDropdownField from '../../../shared/content-settings/components/page-dropdown-field/PageDropdownField.vue';
|
|
491
|
+
import { textStyleFieldTr } from '../../../composables/useTranslate';
|
|
492
|
+
import {
|
|
493
|
+
backgroundColorConvertor,
|
|
494
|
+
colorConvertor,
|
|
495
|
+
} from '../../../brand-page-maker/convertors';
|
|
496
|
+
import { hasLogoColorVar } from '../../../brand-page-maker/utils';
|
|
319
497
|
|
|
320
498
|
interface DropdownInstance {
|
|
321
499
|
hideMenu: () => void;
|
|
@@ -358,6 +536,7 @@ const props = withDefaults(
|
|
|
358
536
|
|
|
359
537
|
const styleSettingsStore = useUiStyleSettingsStore();
|
|
360
538
|
const contentSettingStore = useUiContentSettingsStore();
|
|
539
|
+
const pageSettingsStore = useUiPageSettingsStore();
|
|
361
540
|
|
|
362
541
|
const fontStyleDropdownRef = ref<DropdownInstance>();
|
|
363
542
|
const textStyleTypeDropdownRef = ref<DropdownInstance>();
|
|
@@ -367,7 +546,12 @@ const availableTextFontFamilyOptions = computed(
|
|
|
367
546
|
);
|
|
368
547
|
|
|
369
548
|
const model = defineModel();
|
|
370
|
-
const emit = defineEmits([
|
|
549
|
+
const emit = defineEmits([
|
|
550
|
+
'focus',
|
|
551
|
+
'blur',
|
|
552
|
+
'update:modelValue',
|
|
553
|
+
'update:adminColorMatch',
|
|
554
|
+
]);
|
|
371
555
|
|
|
372
556
|
const fontFamilySelectorKey = computed(() => `fontFamilySelector-${uuidV4()}`);
|
|
373
557
|
|
|
@@ -387,9 +571,24 @@ const fontSettings = reactive({
|
|
|
387
571
|
selectedTextColor: '#000000',
|
|
388
572
|
selectedBackgroundColor: 'transparent',
|
|
389
573
|
});
|
|
390
|
-
|
|
391
574
|
const updateRichTextEditor = ref(false);
|
|
392
575
|
|
|
576
|
+
// Control disabled state of color pickers based on color values
|
|
577
|
+
const isTextColorPickerDisabled = ref(false);
|
|
578
|
+
const isBackgroundColorPickerDisabled = ref(false);
|
|
579
|
+
|
|
580
|
+
// Initialize disabled states based on admin color values
|
|
581
|
+
const initializeDisabledStates = () => {
|
|
582
|
+
if (props.textItemIndex !== undefined && selectedGlobalTextStyles.value) {
|
|
583
|
+
toggleTextColor.value = selectedGlobalTextStyles.value?.style?.color ?? '';
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
isTextColorPickerDisabled.value = hasLogoColorVar(textColorValue.value);
|
|
587
|
+
isBackgroundColorPickerDisabled.value = hasLogoColorVar(
|
|
588
|
+
textBackgroundColorValue.value,
|
|
589
|
+
);
|
|
590
|
+
};
|
|
591
|
+
|
|
393
592
|
const textStyleTypeOptions = reactive([
|
|
394
593
|
{
|
|
395
594
|
value: undefined,
|
|
@@ -411,15 +610,177 @@ const selectedGlobalTextStyles = computed({
|
|
|
411
610
|
set: (type: string) => styleSettingsStore.textStyles.textStyleOptions[type],
|
|
412
611
|
});
|
|
413
612
|
|
|
613
|
+
const isHyperlinkPopupOpen = ref(false);
|
|
614
|
+
const selectedPage = ref('');
|
|
615
|
+
const selectedLinkTypeValue = ref<HyperlinkType>(HYPERLINK_TYPE.url);
|
|
616
|
+
|
|
617
|
+
const btnLinkOptions = computed(() => [
|
|
618
|
+
{
|
|
619
|
+
value: HYPERLINK_TYPE.url,
|
|
620
|
+
label: 'URL',
|
|
621
|
+
isSelected: selectedLinkTypeValue.value === HYPERLINK_TYPE.url,
|
|
622
|
+
},
|
|
623
|
+
{
|
|
624
|
+
value: HYPERLINK_TYPE.page,
|
|
625
|
+
label: 'Page',
|
|
626
|
+
isSelected: selectedLinkTypeValue.value === HYPERLINK_TYPE.page,
|
|
627
|
+
disabled: pageSettingsStore.pages.length <= 1,
|
|
628
|
+
},
|
|
629
|
+
]);
|
|
630
|
+
|
|
631
|
+
const selectedLinkType = computed({
|
|
632
|
+
get: (): HyperlinkType => selectedLinkTypeValue.value,
|
|
633
|
+
set: (type: HyperlinkType) => {
|
|
634
|
+
selectedLinkTypeValue.value = type;
|
|
635
|
+
},
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
const hyperlinkUrlValue = computed(() => hyperlinkValue.value?.value || '');
|
|
639
|
+
const urlValidationSettings = computed(() => {
|
|
640
|
+
const urlValue = hyperlinkUrlValue.value;
|
|
641
|
+
const isValidUrl = !urlValue || URL_REG_EX.test(urlValue);
|
|
642
|
+
|
|
643
|
+
return {
|
|
644
|
+
isValid: isValidUrl,
|
|
645
|
+
errorMessage: isValidUrl ? '' : 'Please enter a valid URL',
|
|
646
|
+
};
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
const isAddLinkButtonDisabled = computed(() => {
|
|
650
|
+
if (selectedLinkType.value === HYPERLINK_TYPE.url) {
|
|
651
|
+
const urlValue = hyperlinkUrlValue.value;
|
|
652
|
+
// Check if URL is invalid OR doesn't have https protocol
|
|
653
|
+
const hasValidProtocol =
|
|
654
|
+
urlValue.startsWith('https://') || urlValue.startsWith('http://');
|
|
655
|
+
return (
|
|
656
|
+
!urlValue || !urlValidationSettings.value.isValid || !hasValidProtocol
|
|
657
|
+
);
|
|
658
|
+
}
|
|
659
|
+
return selectedLinkType.value === HYPERLINK_TYPE.page && !selectedPage.value;
|
|
660
|
+
});
|
|
661
|
+
|
|
662
|
+
const toggleTextColor = ref(props.styles.color ?? '');
|
|
663
|
+
|
|
664
|
+
const textColorValue = computed(() => toggleTextColor.value);
|
|
665
|
+
|
|
666
|
+
watch(
|
|
667
|
+
() => props.styles.color,
|
|
668
|
+
(newColor) => {
|
|
669
|
+
if (isAdmin.value) {
|
|
670
|
+
toggleTextColor.value = newColor ?? '';
|
|
671
|
+
isTextColorPickerDisabled.value = hasLogoColorVar(newColor ?? '');
|
|
672
|
+
}
|
|
673
|
+
},
|
|
674
|
+
);
|
|
675
|
+
|
|
676
|
+
const toggleTextBackgroundColor = ref(props.styles.backgroundColor ?? '');
|
|
677
|
+
|
|
678
|
+
const textBackgroundColorValue = computed(
|
|
679
|
+
() => toggleTextBackgroundColor.value,
|
|
680
|
+
);
|
|
681
|
+
|
|
682
|
+
watch(
|
|
683
|
+
() => props.styles.backgroundColor,
|
|
684
|
+
(newColor) => {
|
|
685
|
+
if (isAdmin.value) {
|
|
686
|
+
toggleTextBackgroundColor.value = newColor ?? '';
|
|
687
|
+
isBackgroundColorPickerDisabled.value = hasLogoColorVar(newColor ?? '');
|
|
688
|
+
}
|
|
689
|
+
},
|
|
690
|
+
);
|
|
691
|
+
|
|
692
|
+
watch(
|
|
693
|
+
() =>
|
|
694
|
+
contentSettingStore.getItem(props.rawId)?.settings?.content?.textItemsStyle
|
|
695
|
+
?.color,
|
|
696
|
+
(newColor) => {
|
|
697
|
+
if (isAdmin.value) {
|
|
698
|
+
if (props.textItemIndex !== undefined && selectedGlobalTextStyles) {
|
|
699
|
+
toggleTextColor.value =
|
|
700
|
+
selectedGlobalTextStyles.value.style.color ?? '';
|
|
701
|
+
isTextColorPickerDisabled.value = hasLogoColorVar(
|
|
702
|
+
selectedGlobalTextStyles.value.style.color ?? '',
|
|
703
|
+
);
|
|
704
|
+
contentSettingStore.updateTextItemTextStyleTypeWithStyles({
|
|
705
|
+
id: props.rawId,
|
|
706
|
+
name: props.name,
|
|
707
|
+
value: {
|
|
708
|
+
color: selectedGlobalTextStyles.value.style.color,
|
|
709
|
+
},
|
|
710
|
+
index: props.textItemIndex,
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
},
|
|
715
|
+
);
|
|
716
|
+
|
|
717
|
+
if (isAdmin.value) initializeDisabledStates();
|
|
718
|
+
|
|
414
719
|
watch(
|
|
415
720
|
() => props.styles.textStyleType,
|
|
416
721
|
(newType) => {
|
|
417
722
|
if (newType) {
|
|
418
723
|
unsetAllMarks();
|
|
419
|
-
|
|
724
|
+
const globalStyle =
|
|
420
725
|
styleSettingsStore.textStyles.textStyleOptions[newType ?? 'titles']
|
|
421
|
-
.style
|
|
422
|
-
);
|
|
726
|
+
.style;
|
|
727
|
+
copyGlobalStyleSettings(globalStyle);
|
|
728
|
+
|
|
729
|
+
// syncing with admin global color match feature
|
|
730
|
+
if (isAdmin.value) {
|
|
731
|
+
if (
|
|
732
|
+
globalStyle.color &&
|
|
733
|
+
(globalStyle.color.includes(STYLE_THEME_KEYS.LogoTextColor) ||
|
|
734
|
+
globalStyle.color.includes(STYLE_THEME_KEYS.LogoTextMultiColor))
|
|
735
|
+
) {
|
|
736
|
+
if (props.name === 'textItems') {
|
|
737
|
+
contentSettingStore.updateTextItemTextStyleTypeWithStyles({
|
|
738
|
+
id: props.rawId,
|
|
739
|
+
name: props.name,
|
|
740
|
+
value: {
|
|
741
|
+
color: globalStyle.color,
|
|
742
|
+
backgroundColor: undefined,
|
|
743
|
+
},
|
|
744
|
+
index: props.textItemIndex,
|
|
745
|
+
});
|
|
746
|
+
} else {
|
|
747
|
+
contentSettingStore.updateTextStyles({
|
|
748
|
+
id: props.rawId,
|
|
749
|
+
name: props.name,
|
|
750
|
+
value: {
|
|
751
|
+
color: globalStyle.color,
|
|
752
|
+
backgroundColor: undefined,
|
|
753
|
+
},
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
toggleTextColor.value = globalStyle.color;
|
|
757
|
+
} else {
|
|
758
|
+
isTextColorPickerDisabled.value = false;
|
|
759
|
+
isBackgroundColorPickerDisabled.value = false;
|
|
760
|
+
toggleTextColor.value = globalStyle.color ?? '';
|
|
761
|
+
|
|
762
|
+
if (props.name === 'textItems') {
|
|
763
|
+
contentSettingStore.updateTextItemTextStyleTypeWithStyles({
|
|
764
|
+
id: props.rawId,
|
|
765
|
+
name: props.name,
|
|
766
|
+
value: {
|
|
767
|
+
color: globalStyle.color ?? '',
|
|
768
|
+
backgroundColor: undefined,
|
|
769
|
+
},
|
|
770
|
+
index: props.textItemIndex,
|
|
771
|
+
});
|
|
772
|
+
} else {
|
|
773
|
+
contentSettingStore.updateTextStyles({
|
|
774
|
+
id: props.rawId,
|
|
775
|
+
name: props.name,
|
|
776
|
+
value: {
|
|
777
|
+
color: globalStyle.color ?? '',
|
|
778
|
+
backgroundColor: undefined,
|
|
779
|
+
},
|
|
780
|
+
});
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
}
|
|
423
784
|
} else {
|
|
424
785
|
// make sure text style options are updated and selected Global style is set to none
|
|
425
786
|
if (selectedGlobalTextStyles.value) {
|
|
@@ -428,6 +789,18 @@ watch(
|
|
|
428
789
|
}
|
|
429
790
|
},
|
|
430
791
|
);
|
|
792
|
+
// Watch pages button should be disabled if no other pages and switch to URL if page type is selected but no pages available
|
|
793
|
+
watch(
|
|
794
|
+
() => pageSettingsStore.pages.length,
|
|
795
|
+
(pagesCount) => {
|
|
796
|
+
if (
|
|
797
|
+
pagesCount <= 1 &&
|
|
798
|
+
selectedLinkTypeValue.value === HYPERLINK_TYPE.page
|
|
799
|
+
) {
|
|
800
|
+
selectedLinkTypeValue.value = HYPERLINK_TYPE.url;
|
|
801
|
+
}
|
|
802
|
+
},
|
|
803
|
+
);
|
|
431
804
|
|
|
432
805
|
const onSelectTextStyleType = (option: ButtonGroupOption) => {
|
|
433
806
|
textStyleTypeOptions.forEach((item) => {
|
|
@@ -490,10 +863,7 @@ const onSelectTextStyleType = (option: ButtonGroupOption) => {
|
|
|
490
863
|
textStyleTypeDropdownRef.value?.hideMenu();
|
|
491
864
|
};
|
|
492
865
|
|
|
493
|
-
|
|
494
|
-
setInitialStyleSettings();
|
|
495
|
-
});
|
|
496
|
-
|
|
866
|
+
// Event handlers for dropdowns and popups
|
|
497
867
|
const clickOutsideTextStyle = (event: MouseEvent) => {
|
|
498
868
|
const target = event.target as HTMLElement;
|
|
499
869
|
if (!target.closest('.toolbar-editor-button')) {
|
|
@@ -501,24 +871,47 @@ const clickOutsideTextStyle = (event: MouseEvent) => {
|
|
|
501
871
|
}
|
|
502
872
|
};
|
|
503
873
|
|
|
874
|
+
const clickOutsideFontStyle = (event: MouseEvent) => {
|
|
875
|
+
const target = event.target as HTMLElement;
|
|
876
|
+
if (!target.closest('.toolbar-editor-button')) {
|
|
877
|
+
fontStyleDropdownRef.value?.hideMenu();
|
|
878
|
+
}
|
|
879
|
+
};
|
|
880
|
+
|
|
504
881
|
const clickOutsideTextSpacing = (event: MouseEvent) => {
|
|
505
882
|
const target = event.target as HTMLElement;
|
|
506
|
-
if (!target.closest('.spacing-popup
|
|
883
|
+
if (!target.closest('.spacing-popup')) {
|
|
507
884
|
isSpacingDropdownOpen.value = false;
|
|
508
885
|
}
|
|
509
886
|
};
|
|
510
887
|
|
|
511
|
-
const
|
|
888
|
+
const clickOutsideHyperlink = (event: MouseEvent) => {
|
|
512
889
|
const target = event.target as HTMLElement;
|
|
513
|
-
if (!target.closest('.
|
|
514
|
-
|
|
890
|
+
if (!target.closest('.hyperlink-popup')) {
|
|
891
|
+
isHyperlinkPopupOpen.value = false;
|
|
515
892
|
}
|
|
516
893
|
};
|
|
517
894
|
|
|
895
|
+
// Handle link type selection
|
|
896
|
+
const onSelectLinkType = (option: ButtonGroupOption) => {
|
|
897
|
+
const isPageOption = option.value === HYPERLINK_TYPE.page;
|
|
898
|
+
const isDisabled = isPageOption && pageSettingsStore.pages.length <= 1;
|
|
899
|
+
|
|
900
|
+
if (!isDisabled) {
|
|
901
|
+
selectedLinkType.value = option.value as HyperlinkType;
|
|
902
|
+
}
|
|
903
|
+
};
|
|
904
|
+
|
|
905
|
+
onMounted(() => {
|
|
906
|
+
setInitialStyleSettings();
|
|
907
|
+
});
|
|
908
|
+
|
|
518
909
|
const onForceUpdate = () => {
|
|
519
910
|
updateRichTextEditor.value = true;
|
|
520
911
|
};
|
|
521
912
|
|
|
913
|
+
const markedText = ref('');
|
|
914
|
+
|
|
522
915
|
defineExpose({
|
|
523
916
|
onForceUpdate,
|
|
524
917
|
});
|
|
@@ -534,6 +927,12 @@ const {
|
|
|
534
927
|
setInitialStyleSettings,
|
|
535
928
|
copyGlobalStyleSettings,
|
|
536
929
|
unsetAllMarks,
|
|
930
|
+
handleHyperlink,
|
|
931
|
+
hyperlinkValue,
|
|
932
|
+
setHyperlinkUrlValue,
|
|
933
|
+
shouldShow,
|
|
934
|
+
tippyOptions,
|
|
935
|
+
handleAdminColorChange,
|
|
537
936
|
} = useRichTextEditor(
|
|
538
937
|
model,
|
|
539
938
|
props,
|
|
@@ -544,7 +943,84 @@ const {
|
|
|
544
943
|
onSelectTextStyleType,
|
|
545
944
|
updateRichTextEditor,
|
|
546
945
|
textStyleTypeOptions,
|
|
946
|
+
markedText,
|
|
947
|
+
isHyperlinkPopupOpen,
|
|
547
948
|
);
|
|
949
|
+
|
|
950
|
+
const isExternalLink = computed(() => {
|
|
951
|
+
const href = editor.getAttributes('link').href;
|
|
952
|
+
return href && (href.startsWith('http://') || href.startsWith('https://'));
|
|
953
|
+
});
|
|
954
|
+
|
|
955
|
+
// Apply hyperlink based on selected type (page or URL)
|
|
956
|
+
const applyHyperlink = () => {
|
|
957
|
+
const url =
|
|
958
|
+
selectedLinkType.value === HYPERLINK_TYPE.page
|
|
959
|
+
? getPageUrl(selectedPage.value)
|
|
960
|
+
: hyperlinkValue.value?.value || '';
|
|
961
|
+
|
|
962
|
+
if (url) {
|
|
963
|
+
setHyperlinkUrlValue(url);
|
|
964
|
+
handleHyperlink('apply');
|
|
965
|
+
} else {
|
|
966
|
+
isHyperlinkPopupOpen.value = false;
|
|
967
|
+
}
|
|
968
|
+
};
|
|
969
|
+
|
|
970
|
+
// Generate page slug for internal page links
|
|
971
|
+
const getPageUrl = (pageSlug: string): string => {
|
|
972
|
+
const page = pageSettingsStore.pages.find((p) => p.slug === pageSlug);
|
|
973
|
+
if (!page) return '';
|
|
974
|
+
|
|
975
|
+
return page.slug;
|
|
976
|
+
};
|
|
977
|
+
|
|
978
|
+
// Handle page selection from dropdown
|
|
979
|
+
const onPageSelected = (obj: { id: string; name: string; value: string }) => {
|
|
980
|
+
selectedPage.value = obj.value;
|
|
981
|
+
};
|
|
982
|
+
|
|
983
|
+
// Find page by slug (matches page slug only)
|
|
984
|
+
const findPageByUrl = (href: string) => {
|
|
985
|
+
return pageSettingsStore.pages.find((p) => {
|
|
986
|
+
return href === p.slug;
|
|
987
|
+
});
|
|
988
|
+
};
|
|
989
|
+
|
|
990
|
+
// Reset all hyperlink form values
|
|
991
|
+
const resetHyperlinkValues = () => {
|
|
992
|
+
selectedPage.value = '';
|
|
993
|
+
setHyperlinkUrlValue('');
|
|
994
|
+
markedText.value = '';
|
|
995
|
+
selectedLinkTypeValue.value = HYPERLINK_TYPE.url;
|
|
996
|
+
};
|
|
997
|
+
|
|
998
|
+
const pageLinkEdit = (page: any) => {
|
|
999
|
+
selectedLinkType.value = HYPERLINK_TYPE.page;
|
|
1000
|
+
selectedPage.value = page.slug;
|
|
1001
|
+
handleHyperlink('toggle');
|
|
1002
|
+
};
|
|
1003
|
+
|
|
1004
|
+
const urlLinkEdit = (linkHref?: string, text?: string) => {
|
|
1005
|
+
selectedLinkType.value = HYPERLINK_TYPE.url;
|
|
1006
|
+
handleHyperlink(
|
|
1007
|
+
'toggle',
|
|
1008
|
+
linkHref && text ? { href: linkHref, text } : undefined,
|
|
1009
|
+
);
|
|
1010
|
+
};
|
|
1011
|
+
|
|
1012
|
+
// Handle hyperlink editing - detects if link is internal page or external URL
|
|
1013
|
+
const onClickHyperlink = (href?: string, text?: string) => {
|
|
1014
|
+
resetHyperlinkValues();
|
|
1015
|
+
const linkHref = href || editor.getAttributes('link').href;
|
|
1016
|
+
|
|
1017
|
+
if (linkHref) {
|
|
1018
|
+
const page = findPageByUrl(linkHref);
|
|
1019
|
+
page ? pageLinkEdit(page) : urlLinkEdit(linkHref, text);
|
|
1020
|
+
} else {
|
|
1021
|
+
urlLinkEdit();
|
|
1022
|
+
}
|
|
1023
|
+
};
|
|
548
1024
|
</script>
|
|
549
1025
|
|
|
550
1026
|
<style scoped>
|
|
@@ -596,26 +1072,36 @@ const {
|
|
|
596
1072
|
font-family: 'Lato' !important;
|
|
597
1073
|
}
|
|
598
1074
|
|
|
1075
|
+
::v-deep .ProseMirror a,
|
|
1076
|
+
::v-deep .ProseMirror a * {
|
|
1077
|
+
color: #0097d7 !important;
|
|
1078
|
+
text-decoration: underline !important;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
599
1081
|
.error-message {
|
|
600
1082
|
color: #d32f2f;
|
|
601
1083
|
font-size: 0.875rem;
|
|
602
1084
|
margin-top: 4px;
|
|
603
1085
|
}
|
|
604
1086
|
|
|
605
|
-
.
|
|
606
|
-
@apply tw-absolute;
|
|
607
|
-
z-index: 9999;
|
|
1087
|
+
.popup-container {
|
|
1088
|
+
@apply tw-absolute tw-z-10;
|
|
608
1089
|
right: 8%;
|
|
609
1090
|
}
|
|
610
1091
|
|
|
611
|
-
.
|
|
1092
|
+
.hyperlink-preview {
|
|
1093
|
+
@apply tw-absolute;
|
|
1094
|
+
z-index: 10;
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
.popup-panel {
|
|
612
1098
|
background: #fff;
|
|
613
1099
|
border: 1px solid #ccc;
|
|
614
1100
|
border-radius: 8px;
|
|
615
1101
|
padding: 18px;
|
|
616
1102
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
|
|
617
1103
|
}
|
|
618
|
-
.
|
|
1104
|
+
.popup-panel ::v-deep input {
|
|
619
1105
|
border: 1px solid #ccc;
|
|
620
1106
|
border-radius: 8px;
|
|
621
1107
|
}
|
|
@@ -659,6 +1145,9 @@ const {
|
|
|
659
1145
|
::v-deep .left-align {
|
|
660
1146
|
transform: translateX(-50%);
|
|
661
1147
|
}
|
|
1148
|
+
.hyperlink-popup {
|
|
1149
|
+
z-index: 9999;
|
|
1150
|
+
}
|
|
662
1151
|
}
|
|
663
1152
|
|
|
664
1153
|
@media (min-width: 400px) {
|