@designcrowd/library.brand-page 5.10.20 → 5.10.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/lib/src/brand-page/constants/font.constants.d.ts +4 -4
  2. package/lib/src/brand-page/models/index.d.ts +5 -0
  3. package/lib/src/brand-page/models/index.js +4 -0
  4. package/lib/src/brand-page/models/styles.model.d.ts +5 -5
  5. package/lib/src/brand-page/utils/style.util.d.ts +8 -1
  6. package/lib/src/brand-page/utils/style.util.js +58 -5
  7. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.stories.js +2 -2
  8. package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.js +1 -1
  9. package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/content-settings-items.fixture.js +1 -0
  10. package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/page-content-items.d.ts +1 -1
  11. package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/page-content-items.js +2 -1
  12. package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +33 -0
  13. package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.js +35 -1
  14. package/lib/src/brand-page-maker/components/navigation/Navigation.mixin.d.ts +2 -2
  15. package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.d.ts +3 -3
  16. package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.d.ts +1 -0
  17. package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.js +17 -0
  18. package/lib/src/brand-page-maker/components/upgrade-to-premium-button/UpgradeToPremiumButton.mixin.d.ts +2 -2
  19. package/lib/src/brand-page-maker/composables/rich-text-editor/bubbleMenu.d.ts +19 -0
  20. package/lib/src/brand-page-maker/composables/rich-text-editor/bubbleMenu.js +31 -0
  21. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/AutoLink.d.ts +2 -0
  22. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/AutoLink.js +161 -0
  23. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/MaxLength.js +3 -3
  24. package/lib/src/brand-page-maker/composables/rich-text-editor/font.d.ts +1 -1
  25. package/lib/src/brand-page-maker/composables/rich-text-editor/font.js +0 -1
  26. package/lib/src/brand-page-maker/composables/rich-text-editor/formatting.d.ts +1 -1
  27. package/lib/src/brand-page-maker/composables/rich-text-editor/formatting.js +0 -1
  28. package/lib/src/brand-page-maker/composables/rich-text-editor/hyperlink.d.ts +19 -0
  29. package/lib/src/brand-page-maker/composables/rich-text-editor/hyperlink.js +87 -0
  30. package/lib/src/brand-page-maker/composables/rich-text-editor/spacing.d.ts +1 -1
  31. package/lib/src/brand-page-maker/composables/rich-text-editor/spacing.js +0 -1
  32. package/lib/src/brand-page-maker/composables/rich-text-editor/textAlign.d.ts +1 -1
  33. package/lib/src/brand-page-maker/composables/rich-text-editor/textAlign.js +0 -1
  34. package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.d.ts +24 -3
  35. package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.js +214 -33
  36. package/lib/src/brand-page-maker/constants/brandpage-meta-constant.d.ts +5 -5
  37. package/lib/src/brand-page-maker/constants/index.d.ts +2 -2
  38. package/lib/src/brand-page-maker/models/button-group.model.d.ts +2 -0
  39. package/lib/src/brand-page-maker/utils/rich-text-editor.util.d.ts +19 -2
  40. package/lib/src/brand-page-maker/utils/rich-text-editor.util.js +340 -8
  41. package/lib/src/bundled-translations-BXxQYq2i.js +119 -0
  42. package/lib/src/bundled-translations.de-DE-BXcluMZ2.js +119 -0
  43. package/lib/src/{bundled-translations.de-DE-O4sKkzBX.js → bundled-translations.de-DE-DjQFwukR.js} +1 -1
  44. package/lib/src/{bundled-translations.es-ES-C4lGaf08.js → bundled-translations.es-ES--EbGRI7e.js} +1 -1
  45. package/lib/src/bundled-translations.es-ES-DSd-wV16.js +119 -0
  46. package/lib/src/{bundled-translations.fr-FR-CIy8KjAV.js → bundled-translations.fr-FR-VtC2JYUC.js} +1 -1
  47. package/lib/src/bundled-translations.fr-FR-jKR_dxWR.js +119 -0
  48. package/lib/src/bundled-translations.pt-PT-CwvYqXXo.js +119 -0
  49. package/lib/src/{bundled-translations.pt-PT-C8EcSdyX.js → bundled-translations.pt-PT-l9cEldEo.js} +1 -1
  50. package/lib/src/bundles/bundled-translations.de-DE.json +11 -0
  51. package/lib/src/bundles/bundled-translations.es-ES.json +11 -0
  52. package/lib/src/bundles/bundled-translations.fr-FR.json +13 -2
  53. package/lib/src/bundles/bundled-translations.json +11 -0
  54. package/lib/src/bundles/bundled-translations.pt-PT.json +11 -0
  55. package/lib/src/composables/useTranslate.d.ts +64 -62
  56. package/lib/src/composables/useTranslate.js +18 -7
  57. package/lib/src/css/library.brand-page-brandCrowd.min.css +101 -75
  58. package/lib/src/css/library.brand-page-brandPage.min.css +101 -75
  59. package/lib/src/css/library.brand-page-designCom.min.css +101 -75
  60. package/lib/src/css/library.brand-page-preview.min.css +101 -75
  61. package/lib/src/index.d.ts +3 -1
  62. package/lib/src/index.mjs +30209 -27738
  63. package/lib/src/lib.js +2 -1
  64. package/lib/src/mockServiceWorker.js +91 -54
  65. package/lib/src/shared/content-settings/components/GenericTextInput.mixin.d.ts +2 -2
  66. package/lib/src/shared/content-settings/components/color-field/ColorField.mixin.d.ts +11 -0
  67. package/lib/src/shared/content-settings/components/color-field/ColorField.mixin.js +5 -0
  68. package/lib/src/shared/content-settings/components/email-field/EmailField.mixin.d.ts +2 -2
  69. package/lib/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.mixin.d.ts +11 -1
  70. package/lib/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.mixin.js +4 -0
  71. package/lib/src/shared/content-settings/components/shape-field/ShapeField.mixin.d.ts +1 -1
  72. package/lib/src/shared/content-settings/components/tel-field/TelField.mixin.d.ts +2 -2
  73. package/lib/src/shared/content-settings/components/testimonial-items-field/TestimonialItemsField.mixin.d.ts +2 -2
  74. package/lib/src/shared/content-settings/components/text-field/TextField.mixin.d.ts +2 -2
  75. package/lib/src/shared/content-settings/components/text-image-field/TextImageField.mixin.d.ts +2 -2
  76. package/lib/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.d.ts +2 -2
  77. package/lib/src/shared/content-settings/components/textarea-field/TextareaField.mixin.d.ts +2 -2
  78. package/lib/src/shared/content-settings/components/url-field/UrlField.mixin.d.ts +4 -2
  79. package/lib/src/shared/content-settings/components/url-field/UrlField.mixin.js +12 -7
  80. package/lib/src/shared/content-settings/components/youtube-video-field/YoutubeVideoField.mixin.d.ts +2 -2
  81. package/lib/src/shared/logo-settings/components/EditLogoSettings.mixin.d.ts +3 -3
  82. package/lib/src/shared/my-uploads/MyUploads.mixin.d.ts +1 -1
  83. package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +1 -1
  84. package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +4 -2
  85. package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +4 -4
  86. package/lib/src/shared/shape-library/ShapeLibrary.mixin.d.ts +1 -1
  87. package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +2 -2
  88. package/lib/src/shared/template-settings/models.d.ts +3 -3
  89. package/package.json +6 -3
  90. package/src/brand-page/components/banner-section/BannerSection.vue +6 -0
  91. package/src/brand-page/components/sensitive-content/SensitiveContentModal.vue +28 -11
  92. package/src/brand-page/components/sensitive-content/i18n/sensitive-content-modal.de-DE.json +13 -0
  93. package/src/brand-page/components/sensitive-content/i18n/sensitive-content-modal.es-ES.json +13 -0
  94. package/src/brand-page/components/sensitive-content/i18n/sensitive-content-modal.fr-FR.json +13 -0
  95. package/src/brand-page/components/sensitive-content/i18n/sensitive-content-modal.json +13 -0
  96. package/src/brand-page/components/sensitive-content/i18n/sensitive-content-modal.pt-PT.json +13 -0
  97. package/src/brand-page/components/text/Text.vue +2 -0
  98. package/src/brand-page/components/text-wrapper/TextWrapper.vue +31 -11
  99. package/src/brand-page/models/index.ts +6 -0
  100. package/src/brand-page/utils/style.util.ts +105 -5
  101. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.stories.ts +2 -2
  102. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.ts +1 -1
  103. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/content-settings-items.fixture.ts +1 -0
  104. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/page-content-items.ts +2 -0
  105. package/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.ts +44 -1
  106. package/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.vue +1 -0
  107. package/src/brand-page-maker/components/brandpage-settings/i18n/brand-page-settings.fr-FR.json +1 -1
  108. package/src/brand-page-maker/components/google-analytics/i18n/google-analytics.fr-FR.json +1 -1
  109. package/src/brand-page-maker/components/rich-text-editor/RichTextEditor.vue +539 -50
  110. package/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.ts +22 -0
  111. package/src/brand-page-maker/components/template-preview/TemplatePreview.vue +1 -1
  112. package/src/brand-page-maker/composables/rich-text-editor/bubbleMenu.ts +42 -0
  113. package/src/brand-page-maker/composables/rich-text-editor/extensions/AutoLink.ts +227 -0
  114. package/src/brand-page-maker/composables/rich-text-editor/extensions/MaxLength.test.ts +1 -1
  115. package/src/brand-page-maker/composables/rich-text-editor/extensions/MaxLength.ts +4 -15
  116. package/src/brand-page-maker/composables/rich-text-editor/font.ts +1 -1
  117. package/src/brand-page-maker/composables/rich-text-editor/formatting.ts +1 -1
  118. package/src/brand-page-maker/composables/rich-text-editor/hyperlink.ts +114 -0
  119. package/src/brand-page-maker/composables/rich-text-editor/spacing.ts +1 -1
  120. package/src/brand-page-maker/composables/rich-text-editor/textAlign.ts +1 -1
  121. package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.ts +299 -41
  122. package/src/brand-page-maker/models/button-group.model.ts +2 -0
  123. package/src/brand-page-maker/stores/brandpage-maker/__snapshots__/brandpage-maker-store.test.ts.snap +1 -0
  124. package/src/brand-page-maker/utils/rich-text-editor.util.test.ts +418 -0
  125. package/src/brand-page-maker/utils/rich-text-editor.util.ts +470 -25
  126. package/src/bundles/bundled-translations.de-DE.json +11 -0
  127. package/src/bundles/bundled-translations.es-ES.json +11 -0
  128. package/src/bundles/bundled-translations.fr-FR.json +13 -2
  129. package/src/bundles/bundled-translations.json +11 -0
  130. package/src/bundles/bundled-translations.pt-PT.json +11 -0
  131. package/src/composables/useTranslate.ts +25 -8
  132. package/src/lib.ts +7 -1
  133. package/src/shared/content-settings/components/color-field/ColorField.mixin.ts +5 -0
  134. package/src/shared/content-settings/components/color-field/ColorField.vue +1 -1
  135. package/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.mixin.ts +4 -0
  136. package/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.vue +2 -2
  137. package/src/shared/content-settings/components/text-field/TextField.vue +1 -1
  138. package/src/shared/content-settings/components/text-items-field/TextItemsField.vue +2 -2
  139. package/src/shared/content-settings/components/textarea-field/TextareaField.vue +3 -3
  140. package/src/shared/content-settings/components/url-field/UrlField.mixin.ts +15 -10
  141. package/src/shared/content-settings/components/url-field/UrlField.vue +1 -0
  142. package/lib/src/bundled-translations-DaK60m67.js +0 -117
  143. package/lib/src/bundled-translations.de-DE-848cpWPB.js +0 -117
  144. package/lib/src/bundled-translations.es-ES-CtPI5G7I.js +0 -117
  145. package/lib/src/bundled-translations.fr-FR-CTnDppmf.js +0 -117
  146. package/lib/src/bundled-translations.pt-PT-Balnne-7.js +0 -117
@@ -1,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
- iconSize="sm"
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
- iconSize="sm"
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
- iconSize="sm"
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
- iconSize="sm"
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
- iconSize="sm"
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
- iconSize="sm"
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
- alt-text="Spacing"
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="spacing-popup-panel">
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
- v-model="lineHeightValue"
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
- <EditorContent
268
- tabindex="0"
269
- @focus="onFocus"
270
- @blur="onBlur"
271
- :id="id"
272
- :editor="editor"
273
- :v-model="model"
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(['focus', 'blur', 'update:modelValue']);
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
- copyGlobalStyleSettings(
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
- onMounted(() => {
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-container')) {
883
+ if (!target.closest('.spacing-popup')) {
507
884
  isSpacingDropdownOpen.value = false;
508
885
  }
509
886
  };
510
887
 
511
- const clickOutsideFontStyle = (event: MouseEvent) => {
888
+ const clickOutsideHyperlink = (event: MouseEvent) => {
512
889
  const target = event.target as HTMLElement;
513
- if (!target.closest('.toolbar-editor-button')) {
514
- fontStyleDropdownRef.value?.hideMenu();
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
- .spacing-popup-container {
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
- .spacing-popup-panel {
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
- .spacing-popup-panel ::v-deep input {
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) {