@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.
Files changed (95) hide show
  1. package/lib/src/brand-page/models/index.d.ts +5 -0
  2. package/lib/src/brand-page/models/index.js +4 -0
  3. package/lib/src/brand-page/utils/style.util.d.ts +8 -1
  4. package/lib/src/brand-page/utils/style.util.js +58 -5
  5. package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.js +1 -1
  6. package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/content-settings-items.fixture.js +1 -0
  7. package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/page-content-items.d.ts +1 -1
  8. package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/page-content-items.js +2 -1
  9. package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +33 -0
  10. package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.js +35 -1
  11. package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.d.ts +1 -0
  12. package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.js +17 -0
  13. package/lib/src/brand-page-maker/composables/rich-text-editor/bubbleMenu.d.ts +19 -0
  14. package/lib/src/brand-page-maker/composables/rich-text-editor/bubbleMenu.js +31 -0
  15. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/AutoLink.d.ts +2 -0
  16. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/AutoLink.js +161 -0
  17. package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/MaxLength.js +3 -3
  18. package/lib/src/brand-page-maker/composables/rich-text-editor/font.d.ts +1 -1
  19. package/lib/src/brand-page-maker/composables/rich-text-editor/font.js +0 -1
  20. package/lib/src/brand-page-maker/composables/rich-text-editor/formatting.d.ts +1 -1
  21. package/lib/src/brand-page-maker/composables/rich-text-editor/formatting.js +0 -1
  22. package/lib/src/brand-page-maker/composables/rich-text-editor/hyperlink.d.ts +19 -0
  23. package/lib/src/brand-page-maker/composables/rich-text-editor/hyperlink.js +87 -0
  24. package/lib/src/brand-page-maker/composables/rich-text-editor/spacing.d.ts +1 -1
  25. package/lib/src/brand-page-maker/composables/rich-text-editor/spacing.js +0 -1
  26. package/lib/src/brand-page-maker/composables/rich-text-editor/textAlign.d.ts +1 -1
  27. package/lib/src/brand-page-maker/composables/rich-text-editor/textAlign.js +0 -1
  28. package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.d.ts +24 -3
  29. package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.js +214 -33
  30. package/lib/src/brand-page-maker/models/button-group.model.d.ts +2 -0
  31. package/lib/src/brand-page-maker/utils/rich-text-editor.util.d.ts +19 -2
  32. package/lib/src/brand-page-maker/utils/rich-text-editor.util.js +340 -8
  33. package/lib/src/{bundled-translations.de-DE-O4sKkzBX.js → bundled-translations.de-DE-DjQFwukR.js} +1 -1
  34. package/lib/src/{bundled-translations.es-ES-C4lGaf08.js → bundled-translations.es-ES--EbGRI7e.js} +1 -1
  35. package/lib/src/bundled-translations.fr-FR-BS3Kia5y.js +117 -0
  36. package/lib/src/{bundled-translations.fr-FR-CIy8KjAV.js → bundled-translations.fr-FR-VtC2JYUC.js} +1 -1
  37. package/lib/src/{bundled-translations.pt-PT-C8EcSdyX.js → bundled-translations.pt-PT-l9cEldEo.js} +1 -1
  38. package/lib/src/bundles/bundled-translations.fr-FR.json +2 -2
  39. package/lib/src/css/library.brand-page-brandCrowd.min.css +96 -70
  40. package/lib/src/css/library.brand-page-brandPage.min.css +96 -70
  41. package/lib/src/css/library.brand-page-designCom.min.css +96 -70
  42. package/lib/src/css/library.brand-page-preview.min.css +96 -70
  43. package/lib/src/index.d.ts +1 -0
  44. package/lib/src/index.mjs +29673 -27225
  45. package/lib/src/lib.js +1 -0
  46. package/lib/src/mockServiceWorker.js +91 -54
  47. package/lib/src/shared/content-settings/components/color-field/ColorField.mixin.d.ts +11 -0
  48. package/lib/src/shared/content-settings/components/color-field/ColorField.mixin.js +5 -0
  49. package/lib/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.mixin.d.ts +11 -1
  50. package/lib/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.mixin.js +4 -0
  51. package/lib/src/shared/content-settings/components/url-field/UrlField.mixin.d.ts +2 -0
  52. package/lib/src/shared/content-settings/components/url-field/UrlField.mixin.js +12 -7
  53. package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +2 -0
  54. package/package.json +6 -3
  55. package/src/brand-page/components/banner-section/BannerSection.vue +6 -0
  56. package/src/brand-page/components/text/Text.vue +2 -0
  57. package/src/brand-page/components/text-wrapper/TextWrapper.vue +31 -11
  58. package/src/brand-page/models/index.ts +6 -0
  59. package/src/brand-page/utils/style.util.ts +105 -5
  60. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.ts +1 -1
  61. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/content-settings-items.fixture.ts +1 -0
  62. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/page-content-items.ts +2 -0
  63. package/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.ts +44 -1
  64. package/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.vue +1 -0
  65. package/src/brand-page-maker/components/brandpage-settings/i18n/brand-page-settings.fr-FR.json +1 -1
  66. package/src/brand-page-maker/components/google-analytics/i18n/google-analytics.fr-FR.json +1 -1
  67. package/src/brand-page-maker/components/rich-text-editor/RichTextEditor.vue +539 -50
  68. package/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.ts +22 -0
  69. package/src/brand-page-maker/components/template-preview/TemplatePreview.vue +1 -1
  70. package/src/brand-page-maker/composables/rich-text-editor/bubbleMenu.ts +42 -0
  71. package/src/brand-page-maker/composables/rich-text-editor/extensions/AutoLink.ts +227 -0
  72. package/src/brand-page-maker/composables/rich-text-editor/extensions/MaxLength.test.ts +1 -1
  73. package/src/brand-page-maker/composables/rich-text-editor/extensions/MaxLength.ts +4 -15
  74. package/src/brand-page-maker/composables/rich-text-editor/font.ts +1 -1
  75. package/src/brand-page-maker/composables/rich-text-editor/formatting.ts +1 -1
  76. package/src/brand-page-maker/composables/rich-text-editor/hyperlink.ts +114 -0
  77. package/src/brand-page-maker/composables/rich-text-editor/spacing.ts +1 -1
  78. package/src/brand-page-maker/composables/rich-text-editor/textAlign.ts +1 -1
  79. package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.ts +299 -41
  80. package/src/brand-page-maker/models/button-group.model.ts +2 -0
  81. package/src/brand-page-maker/stores/brandpage-maker/__snapshots__/brandpage-maker-store.test.ts.snap +1 -0
  82. package/src/brand-page-maker/utils/rich-text-editor.util.test.ts +418 -0
  83. package/src/brand-page-maker/utils/rich-text-editor.util.ts +470 -25
  84. package/src/bundles/bundled-translations.fr-FR.json +2 -2
  85. package/src/lib.ts +1 -0
  86. package/src/shared/content-settings/components/color-field/ColorField.mixin.ts +5 -0
  87. package/src/shared/content-settings/components/color-field/ColorField.vue +1 -1
  88. package/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.mixin.ts +4 -0
  89. package/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.vue +2 -2
  90. package/src/shared/content-settings/components/text-field/TextField.vue +1 -1
  91. package/src/shared/content-settings/components/text-items-field/TextItemsField.vue +2 -2
  92. package/src/shared/content-settings/components/textarea-field/TextareaField.vue +3 -3
  93. package/src/shared/content-settings/components/url-field/UrlField.mixin.ts +15 -10
  94. package/src/shared/content-settings/components/url-field/UrlField.vue +1 -0
  95. package/lib/src/bundled-translations.fr-FR-CTnDppmf.js +0 -117
package/lib/src/lib.js CHANGED
@@ -27,6 +27,7 @@ export { default as SensitiveContentModal } from './brand-page/components/sensit
27
27
  export { getBrandPageViewModelFromBrandPageModel, migrateBrandPageModel, } from './brand-page/utils';
28
28
  export * as brandPageUtils from './brand-page/utils';
29
29
  export { getOptimalLogoSize } from './brand-page/utils/logo.util';
30
+ export { sanitizeRTEHtml } from './brand-page-maker/utils';
30
31
  // stores
31
32
  export { useBrandPageMakerStore, useBrandPageMakerUserStore, useUiStore, useBrandPageContainerStore, useEventManagerStore, } from './brand-page-maker/stores';
32
33
  export { useShopConfigStore } from './shared/ecommerce-settings/store/shop-settings-store';
@@ -5,24 +5,23 @@
5
5
  * Mock Service Worker.
6
6
  * @see https://github.com/mswjs/msw
7
7
  * - Please do NOT modify this file.
8
- * - Please do NOT serve this file on production.
9
8
  */
10
9
 
11
- const PACKAGE_VERSION = '2.8.7'
12
- const INTEGRITY_CHECKSUM = '00729d72e3b82faf54ca8b9621dbb96f'
10
+ const PACKAGE_VERSION = '2.10.2'
11
+ const INTEGRITY_CHECKSUM = 'f5825c521429caf22a4dd13b66e243af'
13
12
  const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
14
13
  const activeClientIds = new Set()
15
14
 
16
- self.addEventListener('install', function () {
15
+ addEventListener('install', function () {
17
16
  self.skipWaiting()
18
17
  })
19
18
 
20
- self.addEventListener('activate', function (event) {
19
+ addEventListener('activate', function (event) {
21
20
  event.waitUntil(self.clients.claim())
22
21
  })
23
22
 
24
- self.addEventListener('message', async function (event) {
25
- const clientId = event.source.id
23
+ addEventListener('message', async function (event) {
24
+ const clientId = Reflect.get(event.source || {}, 'id')
26
25
 
27
26
  if (!clientId || !self.clients) {
28
27
  return
@@ -94,17 +93,18 @@ self.addEventListener('message', async function (event) {
94
93
  }
95
94
  })
96
95
 
97
- self.addEventListener('fetch', function (event) {
98
- const { request } = event
99
-
96
+ addEventListener('fetch', function (event) {
100
97
  // Bypass navigation requests.
101
- if (request.mode === 'navigate') {
98
+ if (event.request.mode === 'navigate') {
102
99
  return
103
100
  }
104
101
 
105
102
  // Opening the DevTools triggers the "only-if-cached" request
106
103
  // that cannot be handled by the worker. Bypass such requests.
107
- if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') {
104
+ if (
105
+ event.request.cache === 'only-if-cached' &&
106
+ event.request.mode !== 'same-origin'
107
+ ) {
108
108
  return
109
109
  }
110
110
 
@@ -115,48 +115,62 @@ self.addEventListener('fetch', function (event) {
115
115
  return
116
116
  }
117
117
 
118
- // Generate unique request ID.
119
118
  const requestId = crypto.randomUUID()
120
119
  event.respondWith(handleRequest(event, requestId))
121
120
  })
122
121
 
122
+ /**
123
+ * @param {FetchEvent} event
124
+ * @param {string} requestId
125
+ */
123
126
  async function handleRequest(event, requestId) {
124
127
  const client = await resolveMainClient(event)
128
+ const requestCloneForEvents = event.request.clone()
125
129
  const response = await getResponse(event, client, requestId)
126
130
 
127
131
  // Send back the response clone for the "response:*" life-cycle events.
128
132
  // Ensure MSW is active and ready to handle the message, otherwise
129
133
  // this message will pend indefinitely.
130
134
  if (client && activeClientIds.has(client.id)) {
131
- ;(async function () {
132
- const responseClone = response.clone()
133
-
134
- sendToClient(
135
- client,
136
- {
137
- type: 'RESPONSE',
138
- payload: {
139
- requestId,
140
- isMockedResponse: IS_MOCKED_RESPONSE in response,
135
+ const serializedRequest = await serializeRequest(requestCloneForEvents)
136
+
137
+ // Clone the response so both the client and the library could consume it.
138
+ const responseClone = response.clone()
139
+
140
+ sendToClient(
141
+ client,
142
+ {
143
+ type: 'RESPONSE',
144
+ payload: {
145
+ isMockedResponse: IS_MOCKED_RESPONSE in response,
146
+ request: {
147
+ id: requestId,
148
+ ...serializedRequest,
149
+ },
150
+ response: {
141
151
  type: responseClone.type,
142
152
  status: responseClone.status,
143
153
  statusText: responseClone.statusText,
144
- body: responseClone.body,
145
154
  headers: Object.fromEntries(responseClone.headers.entries()),
155
+ body: responseClone.body,
146
156
  },
147
157
  },
148
- [responseClone.body],
149
- )
150
- })()
158
+ },
159
+ responseClone.body ? [serializedRequest.body, responseClone.body] : [],
160
+ )
151
161
  }
152
162
 
153
163
  return response
154
164
  }
155
165
 
156
- // Resolve the main client for the given event.
157
- // Client that issues a request doesn't necessarily equal the client
158
- // that registered the worker. It's with the latter the worker should
159
- // communicate with during the response resolving phase.
166
+ /**
167
+ * Resolve the main client for the given event.
168
+ * Client that issues a request doesn't necessarily equal the client
169
+ * that registered the worker. It's with the latter the worker should
170
+ * communicate with during the response resolving phase.
171
+ * @param {FetchEvent} event
172
+ * @returns {Promise<Client | undefined>}
173
+ */
160
174
  async function resolveMainClient(event) {
161
175
  const client = await self.clients.get(event.clientId)
162
176
 
@@ -184,12 +198,16 @@ async function resolveMainClient(event) {
184
198
  })
185
199
  }
186
200
 
201
+ /**
202
+ * @param {FetchEvent} event
203
+ * @param {Client | undefined} client
204
+ * @param {string} requestId
205
+ * @returns {Promise<Response>}
206
+ */
187
207
  async function getResponse(event, client, requestId) {
188
- const { request } = event
189
-
190
208
  // Clone the request because it might've been already used
191
209
  // (i.e. its body has been read and sent to the client).
192
- const requestClone = request.clone()
210
+ const requestClone = event.request.clone()
193
211
 
194
212
  function passthrough() {
195
213
  // Cast the request headers to a new Headers instance
@@ -230,29 +248,17 @@ async function getResponse(event, client, requestId) {
230
248
  }
231
249
 
232
250
  // Notify the client that a request has been intercepted.
233
- const requestBuffer = await request.arrayBuffer()
251
+ const serializedRequest = await serializeRequest(event.request)
234
252
  const clientMessage = await sendToClient(
235
253
  client,
236
254
  {
237
255
  type: 'REQUEST',
238
256
  payload: {
239
257
  id: requestId,
240
- url: request.url,
241
- mode: request.mode,
242
- method: request.method,
243
- headers: Object.fromEntries(request.headers.entries()),
244
- cache: request.cache,
245
- credentials: request.credentials,
246
- destination: request.destination,
247
- integrity: request.integrity,
248
- redirect: request.redirect,
249
- referrer: request.referrer,
250
- referrerPolicy: request.referrerPolicy,
251
- body: requestBuffer,
252
- keepalive: request.keepalive,
258
+ ...serializedRequest,
253
259
  },
254
260
  },
255
- [requestBuffer],
261
+ [serializedRequest.body],
256
262
  )
257
263
 
258
264
  switch (clientMessage.type) {
@@ -268,6 +274,12 @@ async function getResponse(event, client, requestId) {
268
274
  return passthrough()
269
275
  }
270
276
 
277
+ /**
278
+ * @param {Client} client
279
+ * @param {any} message
280
+ * @param {Array<Transferable>} transferrables
281
+ * @returns {Promise<any>}
282
+ */
271
283
  function sendToClient(client, message, transferrables = []) {
272
284
  return new Promise((resolve, reject) => {
273
285
  const channel = new MessageChannel()
@@ -280,14 +292,18 @@ function sendToClient(client, message, transferrables = []) {
280
292
  resolve(event.data)
281
293
  }
282
294
 
283
- client.postMessage(
284
- message,
285
- [channel.port2].concat(transferrables.filter(Boolean)),
286
- )
295
+ client.postMessage(message, [
296
+ channel.port2,
297
+ ...transferrables.filter(Boolean),
298
+ ])
287
299
  })
288
300
  }
289
301
 
290
- async function respondWithMock(response) {
302
+ /**
303
+ * @param {Response} response
304
+ * @returns {Response}
305
+ */
306
+ function respondWithMock(response) {
291
307
  // Setting response status code to 0 is a no-op.
292
308
  // However, when responding with a "Response.error()", the produced Response
293
309
  // instance will have status code set to 0. Since it's not possible to create
@@ -305,3 +321,24 @@ async function respondWithMock(response) {
305
321
 
306
322
  return mockedResponse
307
323
  }
324
+
325
+ /**
326
+ * @param {Request} request
327
+ */
328
+ async function serializeRequest(request) {
329
+ return {
330
+ url: request.url,
331
+ mode: request.mode,
332
+ method: request.method,
333
+ headers: Object.fromEntries(request.headers.entries()),
334
+ cache: request.cache,
335
+ credentials: request.credentials,
336
+ destination: request.destination,
337
+ integrity: request.integrity,
338
+ redirect: request.redirect,
339
+ referrer: request.referrer,
340
+ referrerPolicy: request.referrerPolicy,
341
+ body: await request.arrayBuffer(),
342
+ keepalive: request.keepalive,
343
+ }
344
+ }
@@ -75,6 +75,11 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
75
75
  required: false;
76
76
  default: undefined;
77
77
  };
78
+ showColorPallet: {
79
+ type: BooleanConstructor;
80
+ required: false;
81
+ default: boolean;
82
+ };
78
83
  }>, {
79
84
  backgroundStyles: import("vue").ComputedRef<{
80
85
  style: {
@@ -369,6 +374,11 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
369
374
  required: false;
370
375
  default: undefined;
371
376
  };
377
+ showColorPallet: {
378
+ type: BooleanConstructor;
379
+ required: false;
380
+ default: boolean;
381
+ };
372
382
  }>> & Readonly<{
373
383
  "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
374
384
  "onOn-toggle-state-change"?: ((...args: any[]) => any) | undefined;
@@ -384,5 +394,6 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
384
394
  isToggled: boolean;
385
395
  toggleUniqueId: string;
386
396
  enableColorMatch: boolean;
397
+ showColorPallet: boolean;
387
398
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
388
399
  export default _default;
@@ -80,6 +80,11 @@ export default defineComponent({
80
80
  required: false,
81
81
  default: undefined,
82
82
  },
83
+ showColorPallet: {
84
+ type: Boolean,
85
+ required: false,
86
+ default: true,
87
+ },
83
88
  },
84
89
  setup() {
85
90
  const backgroundSettingsStore = useUiBackgroundSettingsStore();
@@ -16,6 +16,10 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
16
16
  type: StringConstructor;
17
17
  required: true;
18
18
  };
19
+ showUpgradeBtn: {
20
+ type: BooleanConstructor;
21
+ default: boolean;
22
+ };
19
23
  }>, {
20
24
  pageSettingsStore: import("pinia").Store<"uiPageSettings", import("../../../page-settings/store").PageSettingsState, {
21
25
  pageIndex(): number;
@@ -127,7 +131,13 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
127
131
  type: StringConstructor;
128
132
  required: true;
129
133
  };
134
+ showUpgradeBtn: {
135
+ type: BooleanConstructor;
136
+ default: boolean;
137
+ };
130
138
  }>> & Readonly<{
131
139
  "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
132
- }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
140
+ }>, {
141
+ showUpgradeBtn: boolean;
142
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
133
143
  export default _default;
@@ -20,6 +20,10 @@ export default defineComponent({
20
20
  type: String,
21
21
  required: true,
22
22
  },
23
+ showUpgradeBtn: {
24
+ type: Boolean,
25
+ default: true,
26
+ },
23
27
  },
24
28
  setup() {
25
29
  const pageSettingsStore = useUiPageSettingsStore();
@@ -1,8 +1,10 @@
1
1
  /// <reference types="types/lodash-shims" />
2
2
  declare const _default: import("vue").DefineComponent<{}, {}, Record<string, any>, {
3
3
  icon(): string;
4
+ formattedValue(): string;
4
5
  }, {
5
6
  onFocusOverride(): void;
7
+ onInputOverride(): void;
6
8
  onChangeOverride(): void;
7
9
  }, import("vue").DefineComponent<import("vue").ExtractPropTypes<{
8
10
  attrs: {
@@ -22,6 +22,14 @@ export default defineComponent({
22
22
  return 'globe';
23
23
  }
24
24
  },
25
+ formattedValue() {
26
+ if (this.role === 'url' &&
27
+ this.innerValue &&
28
+ !URL_RE.test(this.innerValue)) {
29
+ return `${this.schema}://${this.innerValue}`;
30
+ }
31
+ return this.innerValue;
32
+ },
25
33
  },
26
34
  watch: {
27
35
  value(newVal) {
@@ -35,13 +43,10 @@ export default defineComponent({
35
43
  methods: {
36
44
  onFocusOverride() {
37
45
  this.isDirty = true;
38
- if (this.role !== 'url') {
39
- return;
40
- }
41
- const match = URL_RE.exec(this.innerValue);
42
- if (match) {
43
- this.schema = match[1];
44
- this.innerValue = match[2];
46
+ },
47
+ onInputOverride() {
48
+ if (this.role === 'url') {
49
+ this.text = this.innerValue;
45
50
  }
46
51
  },
47
52
  onChangeOverride() {
@@ -3059,6 +3059,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
3059
3059
  label: string;
3060
3060
  isSelected: boolean;
3061
3061
  dataAttribute?: string | undefined;
3062
+ disabled?: boolean | undefined;
3062
3063
  } | {
3063
3064
  label?: string | undefined;
3064
3065
  value: string;
@@ -3068,6 +3069,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
3068
3069
  iconViewBox?: string | undefined;
3069
3070
  iconSize?: string | undefined;
3070
3071
  dataAttribute?: string | undefined;
3072
+ disabled?: boolean | undefined;
3071
3073
  };
3072
3074
  options: ("defaultBorderColor" | "selectedBorderColor" | "defaultTextStyle" | "defaultBackgroundColor" | "selectedTextColor" | "selectedBackgroundColor" | "iconColor" | "iconBackgroundColor")[];
3073
3075
  iconStyle: {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@designcrowd/library.brand-page",
3
3
  "description": "A collection of Maker/Designer applications",
4
- "version": "5.10.20",
4
+ "version": "5.10.30",
5
5
  "author": "Design.com Eng",
6
6
  "license": "UNLICENSED",
7
7
  "type": "module",
@@ -55,9 +55,10 @@
55
55
  },
56
56
  "dependencies": {
57
57
  "@ckpack/vue-color": "1.4.1",
58
- "@designcrowd/fe-shared-lib": "1.2.7",
58
+ "@designcrowd/fe-shared-lib": "1.2.11",
59
59
  "@pinia/nuxt": "0.11.0",
60
60
  "@storybook/react": "9.0.4",
61
+ "@tiptap/extension-bubble-menu": "^2.14.0",
61
62
  "@tiptap/extension-character-count": "2.11.7",
62
63
  "@tiptap/extension-color": "2.11.5",
63
64
  "@tiptap/extension-font-family": "2.11.5",
@@ -79,6 +80,7 @@
79
80
  "css-color-names": "1.0.1",
80
81
  "date-utils": "1.2.21",
81
82
  "deepmerge": "4.3.1",
83
+ "dompurify": "3.2.6",
82
84
  "dropzone-vue3": "1.0.2",
83
85
  "express": "4.18.2",
84
86
  "fs-extra": "11.2.0",
@@ -102,11 +104,11 @@
102
104
  "validator": "13.11.0",
103
105
  "vue": "3.5.15",
104
106
  "vue-cropperjs": "5.0.0",
105
- "vuedraggable": "4.1.0",
106
107
  "vue-router": "4.5.0",
107
108
  "vue-select": "4.0.0-beta.6",
108
109
  "vue3-lazy-hydration": "1.2.1",
109
110
  "vue3-shortkey": "4.0.0",
111
+ "vuedraggable": "4.1.0",
110
112
  "vuex": "4.1.0"
111
113
  },
112
114
  "peerDependencies": {
@@ -134,6 +136,7 @@
134
136
  "@stylistic/eslint-plugin": "1.5.4",
135
137
  "@types/axios-mock-adapter": "1.10.0",
136
138
  "@types/braces": "3.0.4",
139
+ "@types/dompurify": "3.2.0",
137
140
  "@types/express": "4.17.21",
138
141
  "@types/faker": "6.6.8",
139
142
  "@types/google.maps": "3.55.1",
@@ -81,12 +81,14 @@
81
81
  v-if="viewModel.title"
82
82
  :text-style="viewModel.titleStyle"
83
83
  :text="viewModel.title"
84
+ :slug="context.brandPageSlug"
84
85
  element="h1"
85
86
  />
86
87
  <TextWrapper
87
88
  v-if="hasDescriptionText"
88
89
  :text-style="viewModel.descriptionStyle"
89
90
  :text="renderText"
91
+ :slug="context.brandPageSlug"
90
92
  element="div"
91
93
  />
92
94
  <div class="tw-w-full tw-flex" :class="displayButtonClass">
@@ -120,12 +122,14 @@
120
122
  v-if="viewModel.title"
121
123
  :text-style="viewModel.titleStyle"
122
124
  :text="viewModel.title"
125
+ :slug="context.brandPageSlug"
123
126
  element="h1"
124
127
  />
125
128
  <TextWrapper
126
129
  v-if="hasDescriptionText"
127
130
  :text-style="viewModel.descriptionStyle"
128
131
  :text="renderText"
132
+ :slug="context.brandPageSlug"
129
133
  element="div"
130
134
  />
131
135
  <div class="tw-w-full tw-flex" :class="displayButtonClass">
@@ -201,12 +205,14 @@
201
205
  v-if="viewModel.title"
202
206
  :text-style="viewModel.titleStyle"
203
207
  :text="viewModel.title"
208
+ :slug="context.brandPageSlug"
204
209
  element="h1"
205
210
  />
206
211
  <TextWrapper
207
212
  v-if="hasDescriptionText"
208
213
  :text-style="viewModel.descriptionStyle"
209
214
  :text="renderText"
215
+ :slug="context.brandPageSlug"
210
216
  element="div"
211
217
  />
212
218
  <div class="tw-w-full tw-flex" :class="displayButtonClass">
@@ -10,6 +10,7 @@
10
10
  <TextWrapper
11
11
  :text-style="viewModel.textStyle"
12
12
  :text="renderText"
13
+ :slug="context.brandPageSlug"
13
14
  element="div"
14
15
  data-test-tag="text-content-text"
15
16
  />
@@ -27,6 +28,7 @@
27
28
  :key="index"
28
29
  :text-style="item.textStyle"
29
30
  :text="renderTextItem(item.text)"
31
+ :slug="context.brandPageSlug"
30
32
  element="div"
31
33
  class="tw-overflow-hidden"
32
34
  data-test-tag="text-content-text-item"
@@ -1,15 +1,15 @@
1
1
  <template>
2
- <div v-if="text" class="tw-w-full" :style="data.wrapperStyle">
2
+ <div v-if="sanitizeText" class="tw-w-full" :style="data.wrapperStyle">
3
3
  <div
4
4
  class="tw-w-full empty-para"
5
5
  :style="isRTEContent ? textStyleRTE : style"
6
6
  >
7
7
  <component
8
8
  :is="element"
9
- :class="padding"
10
- class="tw-box-decoration-clone tw-inline"
9
+ :class="[padding, { 'tw-inline': !isRTEContent }]"
10
+ class="tw-box-decoration-clone"
11
11
  :style="isRTEContent ? {} : textStyles"
12
- v-html="text"
12
+ v-html="sanitizeText"
13
13
  />
14
14
  </div>
15
15
  </div>
@@ -30,6 +30,7 @@ interface Props {
30
30
  textStyle: TextStyleDeclaration | undefined;
31
31
  text: string;
32
32
  element?: string;
33
+ slug?: string;
33
34
  }
34
35
 
35
36
  const props = withDefaults(defineProps<Props>(), {
@@ -72,23 +73,42 @@ const isRTEContent = computed(() => {
72
73
  return hasRTEContent(props.text);
73
74
  });
74
75
 
76
+ const sanitizeText = computed(() => {
77
+ const brandPageSlug = props.slug;
78
+
79
+ if (!brandPageSlug || !props.text.includes('<a ')) {
80
+ return props.text;
81
+ }
82
+
83
+ // Transform internal page links by adding brandPageSlug
84
+ return props.text.replace(
85
+ /<a\s+([^>]*?)href="([^"]*?)"([^>]*?)>/gi,
86
+ (match, existingAttrsStart, href, existingAttrsEnd) => {
87
+ // Only process internal links (no protocol, doesn't start with /)
88
+ if (href && !href.match(/^(https?:\/\/|\/)/)) {
89
+ return `<a ${existingAttrsStart}href="/${brandPageSlug}/${href}"${existingAttrsEnd}>`;
90
+ }
91
+ return match;
92
+ },
93
+ );
94
+ });
95
+
75
96
  const fontSize = computed<any>(() => props.textStyle.fontSize);
76
97
 
77
98
  watch(fontSize, () => {
78
99
  applyScale();
79
100
  });
80
101
 
81
- watch(
82
- () => props.text,
83
- () => {
84
- applyScale();
85
- },
86
- );
102
+ watch(sanitizeText, () => {
103
+ applyScale();
104
+ });
87
105
 
88
106
  const currentInstance = getCurrentInstance();
89
107
 
90
108
  const padding = computed(() =>
91
- props.textStyle.backgroundColor ? 'tw-py-2 tw-px-4' : '',
109
+ props.textStyle.backgroundColor && !isRTEContent.value
110
+ ? 'tw-py-2 tw-px-4'
111
+ : '',
92
112
  );
93
113
 
94
114
  onMounted(() => {
@@ -344,6 +344,12 @@ export const BUTTON_LINK_TYPE = {
344
344
  } as const;
345
345
  export type ButtonLinkType = keyof typeof BUTTON_LINK_TYPE;
346
346
 
347
+ export const HYPERLINK_TYPE = {
348
+ url: 'url',
349
+ page: 'page',
350
+ } as const;
351
+ export type HyperlinkType = keyof typeof HYPERLINK_TYPE;
352
+
347
353
  export const URL_TYPE = {
348
354
  url: 'url',
349
355
  email: 'email',