@designcrowd/library.brand-page 5.16.3 → 5.16.4-abtest-1

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 (125) hide show
  1. package/lib/src/{CreatedOnBrandCrowd-de-de-BVouwZJN.js → CreatedOnBrandCrowd-de-de-DQc3IjpR.js} +1 -1
  2. package/lib/src/{CreatedOnBrandCrowd-en-us-Dtx-1uWO.js → CreatedOnBrandCrowd-en-us-CIgIJjzf.js} +1 -1
  3. package/lib/src/{CreatedOnBrandCrowd-es-es-CmlnW8oC.js → CreatedOnBrandCrowd-es-es-C4JLISvP.js} +1 -1
  4. package/lib/src/{CreatedOnBrandCrowd-fr-fr-C95ioWzr.js → CreatedOnBrandCrowd-fr-ca-DPpWX0aJ.js} +1 -1
  5. package/lib/src/{CreatedOnBrandCrowd-fr-ca-C95ioWzr.js → CreatedOnBrandCrowd-fr-fr-DPpWX0aJ.js} +1 -1
  6. package/lib/src/{CreatedOnBrandCrowd-pt-pt-C_5SiaiE.js → CreatedOnBrandCrowd-pt-br-DmKD5o2o.js} +1 -1
  7. package/lib/src/{CreatedOnBrandCrowd-pt-br-C_5SiaiE.js → CreatedOnBrandCrowd-pt-pt-DmKD5o2o.js} +1 -1
  8. package/lib/src/{CreatedOnDcom-de-de-BP4saQXn.js → CreatedOnDcom-de-de-DhALOqwz.js} +1 -1
  9. package/lib/src/{CreatedOnDcom-en-us-B8Taru6f.js → CreatedOnDcom-en-us-LmejZqTn.js} +1 -1
  10. package/lib/src/{CreatedOnDcom-es-es-Bo3JhWwd.js → CreatedOnDcom-es-es-D3ZH5JD5.js} +1 -1
  11. package/lib/src/{CreatedOnDcom-fr-ca-CDk3ZAHU.js → CreatedOnDcom-fr-ca-BUOMh8kU.js} +1 -1
  12. package/lib/src/{CreatedOnDcom-fr-fr-CD04W_hw.js → CreatedOnDcom-fr-fr-CNc-56QW.js} +1 -1
  13. package/lib/src/{CreatedOnDcom-pt-br-B2DGv1qj.js → CreatedOnDcom-pt-br-BGvy2ON7.js} +1 -1
  14. package/lib/src/{CreatedOnDcom-pt-pt-TYqvgQ08.js → CreatedOnDcom-pt-pt-FaVxQHpN.js} +1 -1
  15. package/lib/src/brand-page/models/brand-page-context.model.d.ts +1 -1
  16. package/lib/src/brand-page/models/brand-page-context.model.js +5 -1
  17. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +13 -0
  18. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.js +30 -1
  19. package/lib/src/brand-page-maker/stores/brandpage-container/brand-page-container-store.js +0 -12
  20. package/lib/src/brand-page-maker/stores/index.d.ts +1 -0
  21. package/lib/src/brand-page-maker/stores/index.js +1 -0
  22. package/lib/src/brand-page-maker/stores/snapshot/snapshot-store.d.ts +14 -0
  23. package/lib/src/brand-page-maker/stores/snapshot/snapshot-store.js +21 -0
  24. package/lib/src/brand-page-maker/utils/rich-text-editor.util.d.ts +2 -0
  25. package/lib/src/brand-page-maker/utils/rich-text-editor.util.js +117 -0
  26. package/lib/src/bundled-translations-Dw3XtNmX.js +163 -0
  27. package/lib/src/bundled-translations.de-DE-B82Ik9M7.js +163 -0
  28. package/lib/src/bundled-translations.es-ES-cf3pdNuN.js +163 -0
  29. package/lib/src/bundled-translations.fr-CA-DP44EcAZ.js +163 -0
  30. package/lib/src/bundled-translations.fr-FR-V0Zt25kg.js +163 -0
  31. package/lib/src/bundled-translations.pt-BR-Brv6rCss.js +163 -0
  32. package/lib/src/bundled-translations.pt-PT-BTgscCTG.js +163 -0
  33. package/lib/src/bundles/bundled-translations.de-DE.json +15 -1
  34. package/lib/src/bundles/bundled-translations.es-ES.json +15 -1
  35. package/lib/src/bundles/bundled-translations.fr-CA.json +15 -1
  36. package/lib/src/bundles/bundled-translations.fr-FR.json +15 -1
  37. package/lib/src/bundles/bundled-translations.json +15 -1
  38. package/lib/src/bundles/bundled-translations.pt-BR.json +15 -1
  39. package/lib/src/bundles/bundled-translations.pt-PT.json +15 -1
  40. package/lib/src/clients/brand-page-client.d.ts +0 -4
  41. package/lib/src/clients/design-template-client.d.ts +2 -0
  42. package/lib/src/clients/design-template-client.js +33 -0
  43. package/lib/src/composables/useSnapshot.d.ts +5 -0
  44. package/lib/src/composables/useSnapshot.js +74 -0
  45. package/lib/src/composables/useTranslate.d.ts +2 -1
  46. package/lib/src/composables/useTranslate.js +2 -1
  47. package/lib/src/css/library.brand-page-brandCrowd.min.css +149 -8
  48. package/lib/src/css/library.brand-page-brandPage.min.css +136 -8
  49. package/lib/src/css/library.brand-page-designCom.min.css +149 -8
  50. package/lib/src/css/library.brand-page-preview.min.css +133 -8
  51. package/lib/src/index.mjs +1 -1
  52. package/lib/src/{lib-3sE17Ltm.js → lib-CqA2Cr9V.js} +20353 -19606
  53. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +1 -0
  54. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.js +3 -0
  55. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.d.ts +2 -0
  56. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.js +6 -0
  57. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.d.ts +8 -0
  58. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.js +44 -1
  59. package/lib/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.d.ts +1 -0
  60. package/lib/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.js +3 -0
  61. package/lib/src/shared/content-settings/components/testimonial-items-field/TestimonialItemsField.mixin.d.ts +21 -3
  62. package/lib/src/shared/content-settings/components/testimonial-items-field/TestimonialItemsField.mixin.js +39 -2
  63. package/lib/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.d.ts +20 -2
  64. package/lib/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.js +41 -2
  65. package/lib/src/shared/content-settings/utils.d.ts +1 -0
  66. package/lib/src/shared/content-settings/utils.js +6 -0
  67. package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +0 -1
  68. package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.js +0 -4
  69. package/package.json +2 -2
  70. package/src/brand-page/models/brand-page-context.model.ts +13 -3
  71. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.ts +31 -0
  72. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.vue +2 -1
  73. package/src/brand-page-maker/stores/brandpage-container/brand-page-container-store.ts +0 -36
  74. package/src/brand-page-maker/stores/index.ts +1 -0
  75. package/src/brand-page-maker/stores/snapshot/snapshot-store.ts +31 -0
  76. package/src/brand-page-maker/utils/rich-text-editor.util.ts +154 -0
  77. package/src/bundles/bundled-translations.de-DE.json +15 -1
  78. package/src/bundles/bundled-translations.es-ES.json +15 -1
  79. package/src/bundles/bundled-translations.fr-CA.json +15 -1
  80. package/src/bundles/bundled-translations.fr-FR.json +15 -1
  81. package/src/bundles/bundled-translations.json +15 -1
  82. package/src/bundles/bundled-translations.pt-BR.json +15 -1
  83. package/src/bundles/bundled-translations.pt-PT.json +15 -1
  84. package/src/clients/brand-page-client.ts +0 -4
  85. package/src/clients/design-template-client.ts +57 -0
  86. package/src/composables/useSnapshot.ts +97 -0
  87. package/src/composables/useTranslate.ts +3 -0
  88. package/src/shared/common/i18n/common.de-DE.json +5 -1
  89. package/src/shared/common/i18n/common.es-ES.json +5 -1
  90. package/src/shared/common/i18n/common.fr-CA.json +5 -1
  91. package/src/shared/common/i18n/common.fr-FR.json +5 -1
  92. package/src/shared/common/i18n/common.json +5 -1
  93. package/src/shared/common/i18n/common.pt-BR.json +5 -1
  94. package/src/shared/common/i18n/common.pt-PT.json +5 -1
  95. package/src/shared/content-settings/components/content-settings/ContentSettings.mixin.ts +3 -0
  96. package/src/shared/content-settings/components/content-settings/ContentSettings.vue +2 -0
  97. package/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.ts +8 -0
  98. package/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.vue +1 -0
  99. package/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.ts +54 -0
  100. package/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.vue +20 -2
  101. package/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.ts +3 -1
  102. package/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.vue +1 -0
  103. package/src/shared/content-settings/components/generate-ai-button/GenerateAiButton.vue +95 -0
  104. package/src/shared/content-settings/components/generate-ai-modal/GenerateAiModal.vue +500 -0
  105. package/src/shared/content-settings/components/generate-ai-modal/i18n/generate-ai.de-DE.json +12 -0
  106. package/src/shared/content-settings/components/generate-ai-modal/i18n/generate-ai.es-ES.json +12 -0
  107. package/src/shared/content-settings/components/generate-ai-modal/i18n/generate-ai.fr-CA.json +12 -0
  108. package/src/shared/content-settings/components/generate-ai-modal/i18n/generate-ai.fr-FR.json +12 -0
  109. package/src/shared/content-settings/components/generate-ai-modal/i18n/generate-ai.json +12 -0
  110. package/src/shared/content-settings/components/generate-ai-modal/i18n/generate-ai.pt-BR.json +12 -0
  111. package/src/shared/content-settings/components/generate-ai-modal/i18n/generate-ai.pt-PT.json +12 -0
  112. package/src/shared/content-settings/components/testimonial-items-field/TestimonialItemsField.mixin.ts +44 -2
  113. package/src/shared/content-settings/components/testimonial-items-field/TestimonialItemsField.vue +15 -3
  114. package/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.ts +52 -2
  115. package/src/shared/content-settings/components/text-items-field/TextItemsField.vue +16 -3
  116. package/src/shared/content-settings/utils.ts +9 -0
  117. package/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.ts +0 -6
  118. package/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.vue +1 -1
  119. package/lib/src/bundled-translations-D9iHE5G9.js +0 -161
  120. package/lib/src/bundled-translations.de-DE-DW3iDx_G.js +0 -161
  121. package/lib/src/bundled-translations.es-ES-C9I8wDyq.js +0 -161
  122. package/lib/src/bundled-translations.fr-CA-C0NN8DsO.js +0 -161
  123. package/lib/src/bundled-translations.fr-FR-oKV5NyE1.js +0 -161
  124. package/lib/src/bundled-translations.pt-BR-CTvCfv1X.js +0 -161
  125. package/lib/src/bundled-translations.pt-PT-CbwxwRY1.js +0 -161
@@ -431,18 +431,6 @@ export const useBrandPageContainerStore = defineStore('brandPageContainer', {
431
431
  throw new Error('Failed to set brand page slug');
432
432
  }
433
433
 
434
- if (response.websiteUpsellAbTestKey) {
435
- this.abTests.bp_4092_rotating_upsells_at_publish = getValueType(
436
- response.websiteUpsellAbTestKey,
437
- response.websiteUpsellAbTestValue,
438
- );
439
-
440
- eventTracker.sendExperimentStartedEvent(
441
- response.websiteUpsellAbTestKey,
442
- response.websiteUpsellAbTestValue,
443
- );
444
- }
445
-
446
434
  if (response.status) {
447
435
  await this.setBrandPageStatus(response.status);
448
436
  }
@@ -583,18 +571,6 @@ export const useBrandPageContainerStore = defineStore('brandPageContainer', {
583
571
  throw new Error('Failed to set brand page slug');
584
572
  }
585
573
 
586
- if (response.websiteUpsellAbTestKey) {
587
- this.abTests.bp_4092_rotating_upsells_at_publish = getValueType(
588
- response.websiteUpsellAbTestKey,
589
- response.websiteUpsellAbTestValue,
590
- );
591
-
592
- eventTracker.sendExperimentStartedEvent(
593
- response.websiteUpsellAbTestKey,
594
- response.websiteUpsellAbTestValue,
595
- );
596
- }
597
-
598
574
  await brandPageClient.getBrandPageIsCustomDomainEnabledAsync(
599
575
  brandPageMakerStore.brandPageType,
600
576
  this.designDraftToken,
@@ -880,18 +856,6 @@ export const useBrandPageContainerStore = defineStore('brandPageContainer', {
880
856
  return false;
881
857
  }
882
858
 
883
- if (response.websiteUpsellAbTestKey) {
884
- this.abTests.bp_4092_rotating_upsells_at_publish = getValueType(
885
- response.websiteUpsellAbTestKey,
886
- response.websiteUpsellAbTestValue,
887
- );
888
-
889
- eventTracker.sendExperimentStartedEvent(
890
- response.websiteUpsellAbTestKey,
891
- response.websiteUpsellAbTestValue,
892
- );
893
- }
894
-
895
859
  if (this.brandPageStatus !== response.status) {
896
860
  await this.setBrandPageStatus(response.status);
897
861
  }
@@ -11,3 +11,4 @@ export * from './event-manager';
11
11
  export * from './route';
12
12
  export * from './logo-store';
13
13
  export * from './video';
14
+ export * from './snapshot/snapshot-store';
@@ -0,0 +1,31 @@
1
+ import { defineStore } from 'pinia';
2
+
3
+ export interface SnapshotState {
4
+ snapshotBase64: string | null;
5
+ isCapturing: boolean;
6
+ }
7
+
8
+ export const useSnapshotStore = defineStore('snapshot', {
9
+ state: (): SnapshotState => ({
10
+ snapshotBase64: null,
11
+ isCapturing: false,
12
+ }),
13
+
14
+ actions: {
15
+ setBase64Snapshot(base64: string | null) {
16
+ this.snapshotBase64 = base64;
17
+ },
18
+
19
+ setIsCapturing(isCapturing: boolean) {
20
+ this.isCapturing = isCapturing;
21
+ },
22
+
23
+ clearSnapshot() {
24
+ this.snapshotBase64 = null;
25
+ },
26
+ },
27
+
28
+ getters: {
29
+ hasSnapshot: (state) => !!state.snapshotBase64,
30
+ },
31
+ });
@@ -154,6 +154,160 @@ export const hasRTEContent = (content: string): boolean => {
154
154
  return tagWrapRegex.test(trimmed);
155
155
  };
156
156
 
157
+ export const getPlainTextFromRTE = (content: string): string => {
158
+ if (typeof content !== 'string') {
159
+ return '';
160
+ }
161
+
162
+ // Only strip HTML tags if the value contains HTML
163
+ if (hasRTEContent(content)) {
164
+ return content.replace(/<[^>]*>/g, '').trim();
165
+ }
166
+
167
+ return content.trim();
168
+ };
169
+
170
+ export const replaceTextInRTE = (
171
+ existingHtml: string,
172
+ newText: string,
173
+ ): string => {
174
+ if (!hasRTEContent(existingHtml)) {
175
+ return `<p>${newText}</p>`;
176
+ }
177
+
178
+ const tempDiv = document.createElement('div');
179
+
180
+ tempDiv.innerHTML = existingHtml;
181
+
182
+ const blockElement = tempDiv.querySelector(
183
+ 'p, div, h1, h2, h3, h4, h5, h6, blockquote',
184
+ );
185
+
186
+ if (!blockElement) {
187
+ return `<p>${newText}</p>`;
188
+ }
189
+
190
+ // Collect all spans and their styles
191
+ const spans = blockElement.querySelectorAll('span');
192
+ const mergedStyles: Record<string, string> = {};
193
+
194
+ const hasFormatting = {
195
+ bold: false,
196
+ italic: false,
197
+ underline: false,
198
+ strikethrough: false,
199
+ mark: false,
200
+ markColor: '',
201
+ markStyle: '',
202
+ };
203
+
204
+ // Iterate through all spans to collect and merge styles
205
+ spans.forEach((span) => {
206
+ // Collect inline styles
207
+ if (span.style.cssText) {
208
+ const styleDeclarations = span.style.cssText.split(';');
209
+
210
+ styleDeclarations.forEach((declaration) => {
211
+ const [property, value] = declaration.split(':').map((s) => s.trim());
212
+
213
+ if (property && value) {
214
+ mergedStyles[property] = value; // Latest value overwrites previous
215
+ }
216
+ });
217
+ }
218
+
219
+ // Collect data attributes (like data-color for marks)
220
+ if (span.hasAttribute('data-color')) {
221
+ mergedStyles['data-color'] = span.getAttribute('data-color') || '';
222
+ }
223
+
224
+ // Check for formatting tags within this span
225
+ if (span.querySelector('strong, b')) hasFormatting.bold = true;
226
+
227
+ if (span.querySelector('em, i')) hasFormatting.italic = true;
228
+
229
+ if (span.querySelector('u')) hasFormatting.underline = true;
230
+
231
+ if (span.querySelector('s, strike, del'))
232
+ hasFormatting.strikethrough = true;
233
+
234
+ // Check for mark/highlight tags
235
+ const markElement = span.querySelector('mark');
236
+
237
+ if (markElement) {
238
+ hasFormatting.mark = true;
239
+
240
+ if (markElement.hasAttribute('data-color')) {
241
+ hasFormatting.markColor = markElement.getAttribute('data-color') || '';
242
+ }
243
+
244
+ if (markElement.style.cssText) {
245
+ hasFormatting.markStyle = markElement.style.cssText;
246
+ }
247
+ }
248
+ });
249
+
250
+ // Create the new span with merged styles
251
+ const newSpan = document.createElement('span');
252
+
253
+ // Apply collected inline styles
254
+ Object.entries(mergedStyles).forEach(([property, value]) => {
255
+ if (property === 'data-color') {
256
+ newSpan.setAttribute('data-color', value);
257
+ } else {
258
+ newSpan.style.setProperty(property, value);
259
+ }
260
+ });
261
+
262
+ // Build the formatted text with nested tags
263
+ let formattedText = newText;
264
+
265
+ // Apply mark/highlight if present
266
+ if (hasFormatting.mark) {
267
+ const markElement = document.createElement('mark');
268
+
269
+ if (hasFormatting.markColor) {
270
+ markElement.setAttribute('data-color', hasFormatting.markColor);
271
+ }
272
+
273
+ if (hasFormatting.markStyle) {
274
+ markElement.style.cssText = hasFormatting.markStyle;
275
+ }
276
+
277
+ markElement.textContent = formattedText;
278
+ formattedText = markElement.outerHTML;
279
+ }
280
+
281
+ // Apply underline
282
+ if (hasFormatting.underline) {
283
+ formattedText = `<u>${formattedText}</u>`;
284
+ }
285
+
286
+ // Apply strikethrough
287
+ if (hasFormatting.strikethrough) {
288
+ formattedText = `<s>${formattedText}</s>`;
289
+ }
290
+
291
+ // Apply italic
292
+ if (hasFormatting.italic) {
293
+ formattedText = `<em>${formattedText}</em>`;
294
+ }
295
+
296
+ // Apply bold
297
+ if (hasFormatting.bold) {
298
+ formattedText = `<strong>${formattedText}</strong>`;
299
+ }
300
+
301
+ // Set the formatted content to the span
302
+ newSpan.innerHTML = formattedText;
303
+
304
+ // Clear the block element and add the new span
305
+ blockElement.innerHTML = '';
306
+ blockElement.appendChild(newSpan);
307
+
308
+ return tempDiv.innerHTML;
309
+ };
310
+
157
311
  export const transformToRTE = (
158
312
  uiPageSettingStore: PageSettingsState,
159
313
  externalEditor: Editor,
@@ -343,6 +343,9 @@
343
343
  "replace": "Ersetzen",
344
344
  "save": "Speichern",
345
345
  "remove": "Entfernen",
346
+ "copy": "Kopieren",
347
+ "sendButtonText": "Senden",
348
+ "regenerateText": "Regenerieren",
346
349
  "addShapeLabel": "Form hinzufügen",
347
350
  "addImageLabel": "Bild hinzufügen",
348
351
  "addFaviconLabel": "Favicon hinzufügen",
@@ -358,7 +361,8 @@
358
361
  "continue": "Weiter",
359
362
  "defaultSaveDescription": "Vergessen Sie nicht, Ihre Änderungen zu veröffentlichen, sobald Sie mit Ihrem Design zufrieden sind.",
360
363
  "saveSuccess": "Gespeichert!",
361
- "changeTemplateConfirmationMessage": "Wenn Sie die Vorlagen ändern, gehen Ihre Änderungen verloren. Alle Ihre Inhalte werden gelöscht. Wir empfehlen Ihnen, Ihre Website vorher zu duplizieren, wenn Sie Ihre Änderungen beibehalten möchten."
364
+ "changeTemplateConfirmationMessage": "Wenn Sie die Vorlagen ändern, gehen Ihre Änderungen verloren. Alle Ihre Inhalte werden gelöscht. Wir empfehlen Ihnen, Ihre Website vorher zu duplizieren, wenn Sie Ihre Änderungen beibehalten möchten.",
365
+ "generateText": "Text generieren"
362
366
  },
363
367
  "error": {
364
368
  "maxCharacters": "Sie haben das Zeichenlimit erreicht",
@@ -592,6 +596,16 @@
592
596
  "field": "Feld",
593
597
  "required": "Erforderlich"
594
598
  },
599
+ "aiModal": {
600
+ "generateTitle": "Text mit KI generieren",
601
+ "generateDescription": "Der Inhalt wurde von einer KI generiert und muss möglicherweise zur Verbesserung der Genauigkeit bearbeitet werden",
602
+ "generatePlaceholder": "Beschreiben Sie Ihren Text.",
603
+ "generationStopped": "Die Textgenerierung wurde gestoppt. Starten Sie eine neue Eingabeaufforderung, um fortzufahren.",
604
+ "generateInputPlaceholder": "Geben Sie Ihre Eingabeaufforderung ein, um den Text zu beschreiben ...",
605
+ "stopGeneration": "Generierung anhalten",
606
+ "useText": "Text verwenden",
607
+ "promptTooLong": "Der Prompt darf maximal {{maxLength}} Zeichen lang sein ({{currentLength}})"
608
+ },
595
609
  "googleAddressField": {
596
610
  "addressPlaceholder": "Geben Sie einen Ort ein"
597
611
  },
@@ -343,6 +343,9 @@
343
343
  "replace": "Sustituir",
344
344
  "save": "Guardar",
345
345
  "remove": "Eliminar",
346
+ "copy": "Copiar",
347
+ "sendButtonText": "Enviar",
348
+ "regenerateText": "Volver a generar",
346
349
  "addShapeLabel": "Añadir forma",
347
350
  "addImageLabel": "Añadir imagen",
348
351
  "addFaviconLabel": "Añadir favicon",
@@ -358,7 +361,8 @@
358
361
  "continue": "Continuar",
359
362
  "defaultSaveDescription": "No olvides publicar los cambios una vez que tengas un diseño que te guste.",
360
363
  "saveSuccess": "¡Se ha guardado correctamente!",
361
- "changeTemplateConfirmationMessage": "Cambiar las plantillas hará que pierdas los cambios. Se borrará todo el contenido. Te recomendamos que hagas un duplicado de tu sitio web de antemano si quieres conservar los cambios."
364
+ "changeTemplateConfirmationMessage": "Cambiar las plantillas hará que pierdas los cambios. Se borrará todo el contenido. Te recomendamos que hagas un duplicado de tu sitio web de antemano si quieres conservar los cambios.",
365
+ "generateText": "Generar texto"
362
366
  },
363
367
  "error": {
364
368
  "maxCharacters": "Has alcanzado tu límite máximo de caracteres permitidos",
@@ -592,6 +596,16 @@
592
596
  "field": "Campo",
593
597
  "required": "Requerido"
594
598
  },
599
+ "aiModal": {
600
+ "generateTitle": "Generar texto con IA",
601
+ "generateDescription": "El contenido se genera mediante IA y podría necesitar una revisión para garantizar su precisión",
602
+ "generatePlaceholder": "Describe tu texto.",
603
+ "generationStopped": "El proceso de generación se ha detenido. Envía un nuevo mensaje para continuar.",
604
+ "generateInputPlaceholder": "Introduce tu mensaje para describir el texto...",
605
+ "stopGeneration": "Detén la generación",
606
+ "useText": "Usa texto",
607
+ "promptTooLong": "El mensaje debe tener {{maxLength}} caracteres como máximo ({{currentLength}})"
608
+ },
595
609
  "googleAddressField": {
596
610
  "addressPlaceholder": "Introduce una ubicación"
597
611
  },
@@ -343,6 +343,9 @@
343
343
  "replace": "Remplacer",
344
344
  "save": "Enregistrer",
345
345
  "remove": "Supprimer",
346
+ "copy": "Copier",
347
+ "sendButtonText": "Envoyer",
348
+ "regenerateText": "Régénérer",
346
349
  "addShapeLabel": "Ajouter une forme",
347
350
  "addImageLabel": "Ajouter une image",
348
351
  "addFaviconLabel": "Ajouter un favicon",
@@ -358,7 +361,8 @@
358
361
  "continue": "Continuer",
359
362
  "defaultSaveDescription": "N’oubliez pas de publier vos modifications une fois que votre design vous convient.",
360
363
  "saveSuccess": "Enregistrement réussi!",
361
- "changeTemplateConfirmationMessage": "Si vous changez de modèle, vous perdrez vos modifications et tout votre contenu sera effacé. Nous vous recommandons de dupliquer votre site au préalable si vous souhaitez conserver vos modifications."
364
+ "changeTemplateConfirmationMessage": "Si vous changez de modèle, vous perdrez vos modifications et tout votre contenu sera effacé. Nous vous recommandons de dupliquer votre site au préalable si vous souhaitez conserver vos modifications.",
365
+ "generateText": "Générer du texte"
362
366
  },
363
367
  "error": {
364
368
  "maxCharacters": "Vous avez atteint la limite maximale de caractères autorisés",
@@ -592,6 +596,16 @@
592
596
  "field": "Champ",
593
597
  "required": "Nécessaire"
594
598
  },
599
+ "aiModal": {
600
+ "generateTitle": "Générer du texte avec l'IA",
601
+ "generateDescription": "Le contenu est généré par l'IA et peut nécessiter des modifications pour plus de précision.",
602
+ "generatePlaceholder": "Décrivez votre texte.",
603
+ "generationStopped": "La génération de texte s'est arrêtée. Lancez une nouvelle requête pour continuer.",
604
+ "generateInputPlaceholder": "Entrez votre requête pour décrire le contenu...",
605
+ "stopGeneration": "Arrêter la génération",
606
+ "useText": "Utiliser le texte",
607
+ "promptTooLong": "La requête doit comporter {{maxLength}} caractères ou moins ({{currentLength}})"
608
+ },
595
609
  "googleAddressField": {
596
610
  "addressPlaceholder": "Entrez une adresse"
597
611
  },
@@ -343,6 +343,9 @@
343
343
  "replace": "Remplacer",
344
344
  "save": "Enregistrer",
345
345
  "remove": "Supprimer",
346
+ "copy": "Copier",
347
+ "sendButtonText": "Envoyer",
348
+ "regenerateText": "Régénérer",
346
349
  "addShapeLabel": "Ajouter une forme",
347
350
  "addImageLabel": "Ajouter une image",
348
351
  "addFaviconLabel": "Ajouter un favicon",
@@ -358,7 +361,8 @@
358
361
  "continue": "Continuer",
359
362
  "defaultSaveDescription": "N’oubliez pas de publier vos modifications une fois que votre design vous convient.",
360
363
  "saveSuccess": "Enregistrement réussi !",
361
- "changeTemplateConfirmationMessage": "Si vous changez de modèle, vous perdrez vos modifications et tout votre contenu sera effacé. Nous vous recommandons de dupliquer votre site au préalable si vous souhaitez conserver vos modifications."
364
+ "changeTemplateConfirmationMessage": "Si vous changez de modèle, vous perdrez vos modifications et tout votre contenu sera effacé. Nous vous recommandons de dupliquer votre site au préalable si vous souhaitez conserver vos modifications.",
365
+ "generateText": "Générer du texte"
362
366
  },
363
367
  "error": {
364
368
  "maxCharacters": "Vous avez atteint la limite maximale de caractères autorisés",
@@ -592,6 +596,16 @@
592
596
  "field": "Champ",
593
597
  "required": "Nécessaire"
594
598
  },
599
+ "aiModal": {
600
+ "generateTitle": "Générer du texte avec l'IA",
601
+ "generateDescription": "Le contenu est généré par l'IA et peut nécessiter des modifications pour plus de précision.",
602
+ "generatePlaceholder": "Décrivez votre texte.",
603
+ "generationStopped": "La génération de texte s'est arrêtée. Démarrez une nouvelle invite pour continuer.",
604
+ "generateInputPlaceholder": "Entrez votre prompt pour décrire le contenu...",
605
+ "stopGeneration": "Arrêter la génération",
606
+ "useText": "Utiliser le texte",
607
+ "promptTooLong": "L'invite doit comporter {{maxLength}} caractères ou moins ({{currentLength}})"
608
+ },
595
609
  "googleAddressField": {
596
610
  "addressPlaceholder": "Entrez une adresse"
597
611
  },
@@ -343,6 +343,9 @@
343
343
  "replace": "Replace",
344
344
  "save": "Save",
345
345
  "remove": "Remove",
346
+ "copy": "Copy",
347
+ "sendButtonText": "Send",
348
+ "regenerateText": "Regenerate",
346
349
  "addShapeLabel": "Add Shape",
347
350
  "addImageLabel": "Add Image",
348
351
  "addFaviconLabel": "Add Favicon",
@@ -358,7 +361,8 @@
358
361
  "continue": "Continue",
359
362
  "defaultSaveDescription": "Don’t forget to publish your changes once you are happy with your design.",
360
363
  "saveSuccess": "Save successful!",
361
- "changeTemplateConfirmationMessage": "Changing templates will cause you to lose your changes. All your content will be erased. We recommend you duplicate your site beforehand if you want to retain your changes."
364
+ "changeTemplateConfirmationMessage": "Changing templates will cause you to lose your changes. All your content will be erased. We recommend you duplicate your site beforehand if you want to retain your changes.",
365
+ "generateText": "Generate text"
362
366
  },
363
367
  "error": {
364
368
  "maxCharacters": "You have reached your maximum limit of characters allowed",
@@ -592,6 +596,16 @@
592
596
  "field": "Field",
593
597
  "required": "Required"
594
598
  },
599
+ "aiModal": {
600
+ "generateTitle": "Generate Text with AI",
601
+ "generateDescription": "Content is AI-generated and may require editing for accuracy",
602
+ "generatePlaceholder": "Describe your text.",
603
+ "generationStopped": "Text generation stopped. Start a new prompt to continue.",
604
+ "generateInputPlaceholder": "Enter your prompt to describe the text...",
605
+ "stopGeneration": "Stop generation",
606
+ "useText": "Use text",
607
+ "promptTooLong": "Prompt must be {{maxLength}} characters or less ({{currentLength}})"
608
+ },
595
609
  "googleAddressField": {
596
610
  "addressPlaceholder": "Enter a location"
597
611
  },
@@ -343,6 +343,9 @@
343
343
  "replace": "Substituir",
344
344
  "save": "Salvar",
345
345
  "remove": "Remover",
346
+ "copy": "Copiar",
347
+ "sendButtonText": "Enviar",
348
+ "regenerateText": "Regenerar",
346
349
  "addShapeLabel": "Adicionar forma",
347
350
  "addImageLabel": "Adicionar imagem",
348
351
  "addFaviconLabel": "Adicionar favicon",
@@ -358,7 +361,8 @@
358
361
  "continue": "Continuar",
359
362
  "defaultSaveDescription": "Não se esqueça de publicar as suas alterações quando estiver satisfeito com o seu design.",
360
363
  "saveSuccess": "Salvo com sucesso!",
361
- "changeTemplateConfirmationMessage": "Se alterar os modelos, você perderá suas alterações. Todo o seu conteúdo será apagado. Recomendamos que duplique seu site previamente caso queira manter suas alterações."
364
+ "changeTemplateConfirmationMessage": "Se alterar os modelos, você perderá suas alterações. Todo o seu conteúdo será apagado. Recomendamos que duplique seu site previamente caso queira manter suas alterações.",
365
+ "generateText": "Gerar texto"
362
366
  },
363
367
  "error": {
364
368
  "maxCharacters": "Você atingiu o limite máximo de caracteres permitido",
@@ -592,6 +596,16 @@
592
596
  "field": "Campo",
593
597
  "required": "Obrigatório"
594
598
  },
599
+ "aiModal": {
600
+ "generateTitle": "Gerar texto com IA",
601
+ "generateDescription": "O conteúdo é gerado por IA, pode precisar de alterações para melhorar a precisão",
602
+ "generatePlaceholder": "Descreva seu texto.",
603
+ "generationStopped": "A geração de texto parou. Inicie um novo prompt para continuar.",
604
+ "generateInputPlaceholder": "Digite o prompt para descrever o texto...",
605
+ "stopGeneration": "Parar de gerar",
606
+ "useText": "Usar texto",
607
+ "promptTooLong": "O prompt deve ter {{maxLength}} caracteres ou menos ({{currentLength}})"
608
+ },
595
609
  "googleAddressField": {
596
610
  "addressPlaceholder": "Introduza uma localização"
597
611
  },
@@ -343,6 +343,9 @@
343
343
  "replace": "Substituir",
344
344
  "save": "Guardar",
345
345
  "remove": "Remover",
346
+ "copy": "Copiar",
347
+ "sendButtonText": "Enviar",
348
+ "regenerateText": "Regenerar",
346
349
  "addShapeLabel": "Adicionar forma",
347
350
  "addImageLabel": "Adicionar imagem",
348
351
  "addFaviconLabel": "Adicionar Favicon",
@@ -358,7 +361,8 @@
358
361
  "continue": "Continuar",
359
362
  "defaultSaveDescription": "Não se esqueça de publicar as suas alterações quando estiver satisfeito com o seu design.",
360
363
  "saveSuccess": "Gravação bem-sucedida!",
361
- "changeTemplateConfirmationMessage": "Se alterar os modelos vai perder as suas alterações. Todo o seu conteúdo será apagado. Recomendamos que duplique o seu site previamente caso queira manter as suas alterações."
364
+ "changeTemplateConfirmationMessage": "Se alterar os modelos vai perder as suas alterações. Todo o seu conteúdo será apagado. Recomendamos que duplique o seu site previamente caso queira manter as suas alterações.",
365
+ "generateText": "Gerar texto"
362
366
  },
363
367
  "error": {
364
368
  "maxCharacters": "Atingiu o limite máximo de caracteres permitido",
@@ -592,6 +596,16 @@
592
596
  "field": "Campo",
593
597
  "required": "Obrigatório"
594
598
  },
599
+ "aiModal": {
600
+ "generateTitle": "Gerar Texto com IA",
601
+ "generateDescription": "O conteúdo é gerado por IA e pode precisar de edição para ser preciso",
602
+ "generatePlaceholder": "Descreva o seu texto.",
603
+ "generationStopped": "A geração de texto parou. Inicie um novo prompt para continuar.",
604
+ "generateInputPlaceholder": "Introduza o seu comando para descrever o texto...",
605
+ "stopGeneration": "Parar a geração",
606
+ "useText": "Utilizar texto",
607
+ "promptTooLong": "A mensagem tem de ter {{maxLength}} carateres ou menos ({{currentLength}})"
608
+ },
595
609
  "googleAddressField": {
596
610
  "addressPlaceholder": "Introduza uma localização"
597
611
  },
@@ -10,8 +10,6 @@ export interface SaveBrandPageResponse {
10
10
  status: string;
11
11
  slug: string;
12
12
  canPublish: boolean;
13
- websiteUpsellAbTestKey: string;
14
- websiteUpsellAbTestValue: string;
15
13
  websiteUpsellModalViewModel: any;
16
14
  }
17
15
 
@@ -19,8 +17,6 @@ export interface PublishBrandPageResponse {
19
17
  designDraftToken: string;
20
18
  status: string;
21
19
  slug: string;
22
- websiteUpsellAbTestKey: string;
23
- websiteUpsellAbTestValue: string;
24
20
  websiteUpsellModalViewModel: any;
25
21
  }
26
22
 
@@ -36,6 +36,9 @@ export const getTemplatesEndpoint = (templateTypeName: string) =>
36
36
  export const getTemplateEndpoint = (templateToken) =>
37
37
  `${window.bcnetApiUrl || ''}/maker/api/template/${templateToken}`;
38
38
 
39
+ export const getGenerateTextEndpoint = () =>
40
+ `${window.bcnetApiUrl || ''}/api/ai/websites/generate-text`;
41
+
39
42
  /**
40
43
  * This class is a partial clone of template-client.js with typing
41
44
  */
@@ -105,6 +108,60 @@ export class DesignTemplateClient {
105
108
 
106
109
  return null;
107
110
  }
111
+
112
+ async generateText(
113
+ prompt: string,
114
+ existingText?: string,
115
+ snapshotBase64?: string,
116
+ ): Promise<string | null> {
117
+ try {
118
+ // Get CSRF token from meta tag
119
+ const csrfToken = document.head
120
+ ?.querySelector('meta[name=csrf-token]')
121
+ ?.getAttribute('content');
122
+
123
+ const response = await axios.post<{
124
+ generatedText: string;
125
+ usage: {
126
+ inputTokens: number;
127
+ outputTokens: number;
128
+ totalTokens: number;
129
+ };
130
+ }>(
131
+ getGenerateTextEndpoint(),
132
+ {
133
+ prompt,
134
+ existingText: existingText || 'N/A',
135
+ snapshotBase64: snapshotBase64 || '',
136
+ },
137
+ {
138
+ withCredentials: true,
139
+ headers: {
140
+ 'Content-Type': 'application/json',
141
+ 'csrf-token': csrfToken || '',
142
+ },
143
+ },
144
+ );
145
+
146
+ if (response.status !== 200) {
147
+ if (process.env.NODE_ENV !== 'production') {
148
+ console.error(
149
+ `generateText got response status '${response.status}'`,
150
+ );
151
+ }
152
+
153
+ return null;
154
+ }
155
+
156
+ return response.data.generatedText;
157
+ } catch (e: any) {
158
+ if (process.env.NODE_ENV !== 'production') {
159
+ console.error('Failed to generate text:', e);
160
+ }
161
+
162
+ throw e;
163
+ }
164
+ }
108
165
  }
109
166
 
110
167
  let _instance: DesignTemplateClient | undefined;