@designcrowd/library.brand-page 5.16.18-pre-temp-5 → 5.16.18-save-8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/src/{CreatedOnBrandCrowd-de-de-CdAKMu3Z.js → CreatedOnBrandCrowd-de-de-D2lOtJs4.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-en-us-BBMDDAa_.js → CreatedOnBrandCrowd-en-us-DLqpBwRn.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-es-es-DTwS7YK8.js → CreatedOnBrandCrowd-es-es-B6btBOp9.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-fr-5VHOtmPC.js → CreatedOnBrandCrowd-fr-ca-QWKL4w6l.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-ca-5VHOtmPC.js → CreatedOnBrandCrowd-fr-fr-QWKL4w6l.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-pt-B7GPKvjK.js → CreatedOnBrandCrowd-pt-br-ThygWa-0.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-br-B7GPKvjK.js → CreatedOnBrandCrowd-pt-pt-ThygWa-0.js} +1 -1
- package/lib/src/{CreatedOnDcom-de-de-KIlwGfjA.js → CreatedOnDcom-de-de-CRNf4dHK.js} +1 -1
- package/lib/src/{CreatedOnDcom-en-us-CSdRVDnn.js → CreatedOnDcom-en-us-BPWElpqm.js} +1 -1
- package/lib/src/{CreatedOnDcom-es-es-CPFtzvn4.js → CreatedOnDcom-es-es-Dww_jODU.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-ca-CJqQeuni.js → CreatedOnDcom-fr-ca-hajmy4rx.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-fr-bYbEQhxp.js → CreatedOnDcom-fr-fr-DFMksyNQ.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-br-Cwe4yt9x.js → CreatedOnDcom-pt-br-Bgs1SmHM.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-pt-CgV-hgaC.js → CreatedOnDcom-pt-pt-_iqczcCA.js} +1 -1
- package/lib/src/brand-page/components/button/Button.mixin.d.ts +1 -0
- package/lib/src/brand-page/components/button/Button.mixin.js +3 -0
- package/lib/src/brand-page/components/page/Page.mixin.d.ts +1 -0
- package/lib/src/brand-page/components/page/Page.mixin.js +16 -0
- package/lib/src/brand-page/components/page-footer/PageFooter.mixin.d.ts +12 -1
- package/lib/src/brand-page/components/page-footer/PageFooter.mixin.js +5 -0
- package/lib/src/brand-page/components/payment/__fixtures__/request-payment.d.ts +1 -0
- package/lib/src/brand-page/components/payment/__fixtures__/support-me.d.ts +1 -0
- package/lib/src/brand-page/models/brand-page-context.model.d.ts +1 -0
- package/lib/src/brand-page/utils/vcard.util.d.ts +13 -0
- package/lib/src/brand-page/utils/vcard.util.js +176 -0
- package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +1 -0
- package/lib/src/brand-page-maker/components/preview/Preview.mixin.js +1 -0
- package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.js +5 -4
- package/lib/src/brand-page-maker/composables/useEventTracker.d.ts +2 -0
- package/lib/src/brand-page-maker/composables/useEventTracker.js +2 -0
- package/lib/src/bundled-translations-Dp4KzW9M.js +165 -0
- package/lib/src/bundled-translations.de-DE-CMNy5LEQ.js +165 -0
- package/lib/src/bundled-translations.es-ES-B20ONBTs.js +165 -0
- package/lib/src/bundled-translations.fr-CA-DwBf1MZ8.js +165 -0
- package/lib/src/bundled-translations.fr-FR-3GhDgrC4.js +165 -0
- package/lib/src/bundled-translations.pt-BR-DuzEDMF5.js +165 -0
- package/lib/src/bundled-translations.pt-PT-CtT4FOlX.js +165 -0
- package/lib/src/bundles/bundled-translations.de-DE.json +6 -0
- package/lib/src/bundles/bundled-translations.es-ES.json +6 -0
- package/lib/src/bundles/bundled-translations.fr-CA.json +6 -0
- package/lib/src/bundles/bundled-translations.fr-FR.json +6 -0
- package/lib/src/bundles/bundled-translations.json +6 -0
- package/lib/src/bundles/bundled-translations.pt-BR.json +6 -0
- package/lib/src/bundles/bundled-translations.pt-PT.json +6 -0
- package/lib/src/clients/design-template-client.d.ts +0 -2
- package/lib/src/clients/fabric-render-client.d.ts +0 -3
- package/lib/src/composables/useTranslate.d.ts +2 -1
- package/lib/src/composables/useTranslate.js +2 -1
- package/lib/src/css/library.brand-page-brandCrowd.min.css +161 -40
- package/lib/src/css/library.brand-page-brandPage.min.css +163 -40
- package/lib/src/css/library.brand-page-designCom.min.css +161 -40
- package/lib/src/css/library.brand-page-preview.min.css +161 -40
- package/lib/src/index.d.ts +1 -1
- package/lib/src/index.mjs +65 -66
- package/lib/src/{lib-DDTH2L4M.js → lib-CBDu-Guo.js} +17043 -16749
- package/lib/src/lib.js +1 -1
- package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.js +1 -0
- package/lib/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.js +1 -0
- package/lib/src/shared/logo-settings/components/EditLogoSettings.mixin.d.ts +0 -2
- package/lib/src/shared/logo-settings/components/LogoSettings.mixin.d.ts +0 -2
- package/lib/src/shared/logo-settings/store/editable-logo-store.d.ts +0 -4
- package/lib/src/shared/logo-settings/store/editable-logo-store.js +0 -11
- package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +0 -2
- package/lib/src/shared/template-settings/store/template-settings-store.js +8 -31
- package/package.json +1 -1
- package/src/brand-page/components/brand-page-footer/i18n/brand-page-footer.de-DE.json +5 -5
- package/src/brand-page/components/brand-page-footer/i18n/brand-page-footer.es-ES.json +5 -5
- package/src/brand-page/components/brand-page-footer/i18n/brand-page-footer.fr-CA.json +5 -5
- package/src/brand-page/components/brand-page-footer/i18n/brand-page-footer.fr-FR.json +5 -5
- package/src/brand-page/components/brand-page-footer/i18n/brand-page-footer.pt-BR.json +5 -5
- package/src/brand-page/components/brand-page-footer/i18n/brand-page-footer.pt-PT.json +5 -5
- package/src/brand-page/components/button/Button.mixin.ts +3 -0
- package/src/brand-page/components/button/Button.vue +68 -58
- package/src/brand-page/components/page/Page.mixin.ts +20 -0
- package/src/brand-page/components/page/Page.vue +10 -1
- package/src/brand-page/components/page-footer/PageFooter.mixin.ts +9 -1
- package/src/brand-page/components/save-contact/SaveContactWidget.vue +214 -0
- package/src/brand-page/components/save-contact/i18n/save-contact.de-DE.json +8 -0
- package/src/brand-page/components/save-contact/i18n/save-contact.es-ES.json +8 -0
- package/src/brand-page/components/save-contact/i18n/save-contact.fr-CA.json +8 -0
- package/src/brand-page/components/save-contact/i18n/save-contact.fr-FR.json +8 -0
- package/src/brand-page/components/save-contact/i18n/save-contact.json +8 -0
- package/src/brand-page/components/save-contact/i18n/save-contact.pt-BR.json +8 -0
- package/src/brand-page/components/save-contact/i18n/save-contact.pt-PT.json +8 -0
- package/src/brand-page/components/save-contact/popup-card/PopupCard.vue +156 -0
- package/src/brand-page/components/shop/ProductDetailModal.vue +1 -1
- package/src/brand-page/models/brand-page-context.model.ts +1 -0
- package/src/brand-page/utils/vcard.util.ts +252 -0
- package/src/brand-page-maker/components/preview/Preview.mixin.ts +1 -0
- package/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.ts +5 -4
- package/src/brand-page-maker/composables/useEventTracker.ts +2 -0
- package/src/bundles/bundled-translations.de-DE.json +6 -0
- package/src/bundles/bundled-translations.es-ES.json +6 -0
- package/src/bundles/bundled-translations.fr-CA.json +6 -0
- package/src/bundles/bundled-translations.fr-FR.json +6 -0
- package/src/bundles/bundled-translations.json +6 -0
- package/src/bundles/bundled-translations.pt-BR.json +6 -0
- package/src/bundles/bundled-translations.pt-PT.json +6 -0
- package/src/clients/design-template-client.ts +0 -2
- package/src/clients/fabric-render-client.ts +0 -3
- package/src/composables/useTranslate.ts +3 -0
- package/src/lib.ts +0 -1
- package/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.ts +1 -0
- package/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.ts +1 -0
- package/src/shared/logo-settings/store/editable-logo-store.ts +0 -13
- package/src/shared/template-settings/store/template-settings-store.ts +9 -44
- package/lib/src/bundled-translations-_qB5IIQe.js +0 -163
- package/lib/src/bundled-translations.de-DE-BO_hJ5Bu.js +0 -163
- package/lib/src/bundled-translations.es-ES-B5U67zCi.js +0 -163
- package/lib/src/bundled-translations.fr-CA-C5ZFrUtX.js +0 -163
- package/lib/src/bundled-translations.fr-FR-hG15gX3m.js +0 -163
- package/lib/src/bundled-translations.pt-BR-DlCmapd7.js +0 -163
- package/lib/src/bundled-translations.pt-PT-lUdbHOo4.js +0 -163
|
@@ -19,6 +19,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
19
19
|
isModalVisible: boolean;
|
|
20
20
|
}, {
|
|
21
21
|
buttonStyle(): BrandPageCssStyle;
|
|
22
|
+
buttonTitle(): string;
|
|
22
23
|
iconImgStyle(): BrandPageCssStyle;
|
|
23
24
|
isIconImage(): boolean;
|
|
24
25
|
iconColor(): string | undefined;
|
|
@@ -73,6 +73,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
73
73
|
bpShowTopNavigationMobile(): boolean;
|
|
74
74
|
bpShowTopNavigationDesktop(): boolean;
|
|
75
75
|
slug(): string;
|
|
76
|
+
shouldShowSaveContactWidget(): boolean;
|
|
76
77
|
}, {
|
|
77
78
|
openSideMenu(): void;
|
|
78
79
|
onLogoClick(tabName: string): void;
|
|
@@ -2,6 +2,7 @@ import { defineComponent } from 'vue';
|
|
|
2
2
|
import { DEFAULT_FONT_FAMILY_KEY, FALLBACK_FONT_FAMILIES, FONT_FAMILY_CONFIGS, } from '../../constants';
|
|
3
3
|
import { getSlugFromContext } from '../../utils';
|
|
4
4
|
import { BRAND_PAGE_TYPES } from '../../models';
|
|
5
|
+
import { hasProfileContent as checkHasProfileContent } from '../../utils/vcard.util';
|
|
5
6
|
export default defineComponent({
|
|
6
7
|
props: {
|
|
7
8
|
context: {
|
|
@@ -263,6 +264,21 @@ export default defineComponent({
|
|
|
263
264
|
slug() {
|
|
264
265
|
return getSlugFromContext(this.context);
|
|
265
266
|
},
|
|
267
|
+
shouldShowSaveContactWidget() {
|
|
268
|
+
try {
|
|
269
|
+
if (this.context.isPreview ||
|
|
270
|
+
this.context.options?.showOnGeneratedPreviews === false ||
|
|
271
|
+
!this.context.isBrandContact) {
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
const brandPageData = { pages: this.context?.pages || [] };
|
|
275
|
+
return checkHasProfileContent(brandPageData);
|
|
276
|
+
}
|
|
277
|
+
catch (error) {
|
|
278
|
+
console.error('Error checking profile content:', error);
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
},
|
|
266
282
|
},
|
|
267
283
|
watch: {
|
|
268
284
|
rootElementStyles() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PageFooterViewModel } from '../../view-models';
|
|
1
|
+
import type { PageFooterViewModel, BrandPageViewModel } from '../../view-models';
|
|
2
2
|
import type { PropType } from 'vue';
|
|
3
3
|
import type { BrandPageContext } from '../../models';
|
|
4
4
|
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
@@ -19,6 +19,11 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
19
19
|
required: false;
|
|
20
20
|
default: boolean;
|
|
21
21
|
};
|
|
22
|
+
brandPageViewModel: {
|
|
23
|
+
type: PropType<BrandPageViewModel>;
|
|
24
|
+
required: false;
|
|
25
|
+
default: undefined;
|
|
26
|
+
};
|
|
22
27
|
}>, {}, {}, {
|
|
23
28
|
containerStyle(): BrandPageCssStyle;
|
|
24
29
|
socialLinksIconStyle(): BrandPageCssStyle;
|
|
@@ -46,10 +51,16 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
46
51
|
required: false;
|
|
47
52
|
default: boolean;
|
|
48
53
|
};
|
|
54
|
+
brandPageViewModel: {
|
|
55
|
+
type: PropType<BrandPageViewModel>;
|
|
56
|
+
required: false;
|
|
57
|
+
default: undefined;
|
|
58
|
+
};
|
|
49
59
|
}>> & Readonly<{
|
|
50
60
|
"onOn-logo-click"?: ((...args: any[]) => any) | undefined;
|
|
51
61
|
"onFooter-container-click"?: ((...args: any[]) => any) | undefined;
|
|
52
62
|
}>, {
|
|
63
|
+
brandPageViewModel: BrandPageViewModel;
|
|
53
64
|
isMobile: boolean;
|
|
54
65
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
55
66
|
export default _default;
|
|
@@ -24,6 +24,7 @@ export declare const context: {
|
|
|
24
24
|
mediaSizes?: "size1x" | "size2x" | "sizeThumb" | undefined;
|
|
25
25
|
renderVideoAsImage?: boolean | undefined;
|
|
26
26
|
shouldPlayVideos?: boolean | undefined;
|
|
27
|
+
showOnGeneratedPreviews?: boolean | undefined;
|
|
27
28
|
} | undefined;
|
|
28
29
|
abTests?: import("../../../models").AbTest | undefined;
|
|
29
30
|
isCapturingPreview: boolean;
|
|
@@ -24,6 +24,7 @@ export declare const context: {
|
|
|
24
24
|
mediaSizes?: "size1x" | "size2x" | "sizeThumb" | undefined;
|
|
25
25
|
renderVideoAsImage?: boolean | undefined;
|
|
26
26
|
shouldPlayVideos?: boolean | undefined;
|
|
27
|
+
showOnGeneratedPreviews?: boolean | undefined;
|
|
27
28
|
} | undefined;
|
|
28
29
|
abTests?: import("../../../models").AbTest | undefined;
|
|
29
30
|
isCapturingPreview: boolean;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ProfileContent, BrandPageModel } from '../models';
|
|
2
|
+
export declare const findProfileContent: (brandPageData?: BrandPageModel | {
|
|
3
|
+
pages?: any[];
|
|
4
|
+
}) => ProfileContent | undefined;
|
|
5
|
+
export declare const hasProfileContent: (brandPageData?: BrandPageModel | {
|
|
6
|
+
pages?: any[];
|
|
7
|
+
}) => boolean;
|
|
8
|
+
export declare const generateVCard: (brandPageData: BrandPageModel | {
|
|
9
|
+
pages?: any[];
|
|
10
|
+
}) => string;
|
|
11
|
+
export declare const saveContact: (brandPageData: BrandPageModel | {
|
|
12
|
+
pages?: any[];
|
|
13
|
+
}) => void;
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { isValidUrl } from '../../helpers/url.helper';
|
|
2
|
+
// Constants
|
|
3
|
+
const HTML_ENTITIES = {
|
|
4
|
+
' ': ' ',
|
|
5
|
+
'&': '&',
|
|
6
|
+
'<': '<',
|
|
7
|
+
'>': '>',
|
|
8
|
+
'"': '"',
|
|
9
|
+
};
|
|
10
|
+
const SOCIAL_TYPE_MAP = {
|
|
11
|
+
facebook: 'FACEBOOK',
|
|
12
|
+
instagram: 'INSTAGRAM',
|
|
13
|
+
x: 'TWITTER',
|
|
14
|
+
linkedin: 'LINKEDIN',
|
|
15
|
+
youtube: 'YOUTUBE',
|
|
16
|
+
pinterest: 'PINTEREST',
|
|
17
|
+
tiktok: 'TIKTOK',
|
|
18
|
+
twitch: 'TWITCH',
|
|
19
|
+
website: 'WEBSITE',
|
|
20
|
+
};
|
|
21
|
+
// Utility Functions
|
|
22
|
+
const sanitizeForVCard = (value) => {
|
|
23
|
+
if (!value || typeof value !== 'string')
|
|
24
|
+
return '';
|
|
25
|
+
let text = value.replace(/<[^>]*>/g, ''); // Strip HTML tags
|
|
26
|
+
// Decode HTML entities
|
|
27
|
+
Object.entries(HTML_ENTITIES).forEach(([entity, char]) => {
|
|
28
|
+
text = text.replace(new RegExp(entity, 'g'), char);
|
|
29
|
+
});
|
|
30
|
+
// Escape backslash FIRST, then other vCard special characters
|
|
31
|
+
text = text.replace(/\\/g, '\\\\');
|
|
32
|
+
text = text.replace(/\n/g, '\\n');
|
|
33
|
+
text = text.replace(/,/g, '\\,');
|
|
34
|
+
text = text.replace(/;/g, '\\;');
|
|
35
|
+
return text.trim();
|
|
36
|
+
};
|
|
37
|
+
const normalizeUrl = (url) => {
|
|
38
|
+
const trimmed = url.trim();
|
|
39
|
+
if (!trimmed)
|
|
40
|
+
return '';
|
|
41
|
+
// Add protocol if missing
|
|
42
|
+
if (trimmed.startsWith('//')) {
|
|
43
|
+
return isValidUrl(`https:${trimmed}`) ? `https:${trimmed}` : '';
|
|
44
|
+
}
|
|
45
|
+
if (!trimmed.startsWith('http://') && !trimmed.startsWith('https://')) {
|
|
46
|
+
return isValidUrl(`https://${trimmed}`) ? `https://${trimmed}` : '';
|
|
47
|
+
}
|
|
48
|
+
return isValidUrl(trimmed) ? trimmed : '';
|
|
49
|
+
};
|
|
50
|
+
const findContentsByType = (brandPageData, type) => {
|
|
51
|
+
if (!brandPageData?.pages)
|
|
52
|
+
return [];
|
|
53
|
+
return brandPageData.pages.flatMap((page) => page.contents?.filter((content) => content.type === type) || []);
|
|
54
|
+
};
|
|
55
|
+
export const findProfileContent = (brandPageData) => {
|
|
56
|
+
if (!brandPageData?.pages)
|
|
57
|
+
return undefined;
|
|
58
|
+
for (const page of brandPageData.pages) {
|
|
59
|
+
const profile = page.contents?.find((content) => content.type === 'profile');
|
|
60
|
+
if (profile)
|
|
61
|
+
return profile;
|
|
62
|
+
}
|
|
63
|
+
return undefined;
|
|
64
|
+
};
|
|
65
|
+
export const hasProfileContent = (brandPageData) => findProfileContent(brandPageData) !== undefined;
|
|
66
|
+
// vCard Entry Handlers
|
|
67
|
+
const addPhoneEntry = (phoneNumber, vcardLines) => {
|
|
68
|
+
const cleaned = phoneNumber.replace(/[^\d+]/g, '');
|
|
69
|
+
vcardLines.push(`TEL;TYPE=CELL:${cleaned}`);
|
|
70
|
+
};
|
|
71
|
+
const addEmailEntry = (email, vcardLines) => {
|
|
72
|
+
vcardLines.push(`EMAIL:${email}`, `EMAIL;TYPE=WORK:${email}`);
|
|
73
|
+
};
|
|
74
|
+
const addUrlEntry = (url, type, vcardLines) => {
|
|
75
|
+
const formatted = normalizeUrl(url);
|
|
76
|
+
// Skip invalid URLs
|
|
77
|
+
if (!formatted)
|
|
78
|
+
return;
|
|
79
|
+
if (type) {
|
|
80
|
+
vcardLines.push(`URL;TYPE=${type}:${formatted}`);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
vcardLines.push(`URL:${formatted}`);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
const processContactUrl = (url, iconType, vcardLines) => {
|
|
87
|
+
if (url.startsWith('tel:')) {
|
|
88
|
+
addPhoneEntry(url.replace('tel:', ''), vcardLines);
|
|
89
|
+
}
|
|
90
|
+
else if (url.startsWith('mailto:')) {
|
|
91
|
+
addEmailEntry(url.replace('mailto:', ''), vcardLines);
|
|
92
|
+
}
|
|
93
|
+
else if (iconType === 'email') {
|
|
94
|
+
addEmailEntry(url, vcardLines);
|
|
95
|
+
}
|
|
96
|
+
else if (iconType === 'phone') {
|
|
97
|
+
addPhoneEntry(url, vcardLines);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
addUrlEntry(url, SOCIAL_TYPE_MAP[iconType], vcardLines);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const processButton = (button, vcardLines) => {
|
|
104
|
+
if (!button.url)
|
|
105
|
+
return;
|
|
106
|
+
const url = button.url.trim();
|
|
107
|
+
const iconType = button.iconUrl?.toLowerCase() || '';
|
|
108
|
+
processContactUrl(url, iconType, vcardLines);
|
|
109
|
+
};
|
|
110
|
+
const processSocialLinks = (socialLinksContent, vcardLines) => {
|
|
111
|
+
if (!socialLinksContent.links?.length)
|
|
112
|
+
return;
|
|
113
|
+
socialLinksContent.links.forEach((link) => {
|
|
114
|
+
if (!link.url)
|
|
115
|
+
return;
|
|
116
|
+
const url = link.url.trim();
|
|
117
|
+
const platform = link.imageUrl?.toLowerCase() || '';
|
|
118
|
+
processContactUrl(url, platform, vcardLines);
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
const addProfileInfo = (profile, vcardLines) => {
|
|
122
|
+
const name = sanitizeForVCard(profile.name || '');
|
|
123
|
+
const title = sanitizeForVCard(profile.title || '');
|
|
124
|
+
const description = sanitizeForVCard(profile.description || '');
|
|
125
|
+
if (name) {
|
|
126
|
+
const nameParts = name.trim().split(/\s+/);
|
|
127
|
+
const lastName = nameParts.length > 1 ? nameParts.pop() || '' : '';
|
|
128
|
+
const middleName = nameParts.length > 1 ? nameParts.pop() || '' : '';
|
|
129
|
+
const firstName = nameParts.join(' ');
|
|
130
|
+
vcardLines.push(`FN:${name}`, `N:${lastName};${firstName};${middleName};;`);
|
|
131
|
+
}
|
|
132
|
+
if (title)
|
|
133
|
+
vcardLines.push(`TITLE:${title}`);
|
|
134
|
+
if (description)
|
|
135
|
+
vcardLines.push(`NOTE:${description}`);
|
|
136
|
+
};
|
|
137
|
+
// Main Functions
|
|
138
|
+
export const generateVCard = (brandPageData) => {
|
|
139
|
+
const vcardLines = ['BEGIN:VCARD', 'VERSION:3.0'];
|
|
140
|
+
const profile = findProfileContent(brandPageData);
|
|
141
|
+
if (profile) {
|
|
142
|
+
addProfileInfo(profile, vcardLines);
|
|
143
|
+
}
|
|
144
|
+
const buttons = findContentsByType(brandPageData, 'button');
|
|
145
|
+
buttons.forEach((button) => processButton(button, vcardLines));
|
|
146
|
+
const socialLinks = findContentsByType(brandPageData, 'social-links');
|
|
147
|
+
socialLinks.forEach((links) => processSocialLinks(links, vcardLines));
|
|
148
|
+
vcardLines.push('END:VCARD');
|
|
149
|
+
return vcardLines.join('\r\n');
|
|
150
|
+
};
|
|
151
|
+
const generateVCardFilename = (name) => {
|
|
152
|
+
if (!name)
|
|
153
|
+
return 'contact.vcf';
|
|
154
|
+
const safeName = name
|
|
155
|
+
.replace(/[^a-z0-9]/gi, '_')
|
|
156
|
+
.toLowerCase()
|
|
157
|
+
.slice(0, 50);
|
|
158
|
+
return `${safeName}.vcf`;
|
|
159
|
+
};
|
|
160
|
+
const downloadVCard = (vcard, filename) => {
|
|
161
|
+
const blob = new Blob([vcard], { type: 'text/vcard;charset=utf-8' });
|
|
162
|
+
const url = URL.createObjectURL(blob);
|
|
163
|
+
const link = document.createElement('a');
|
|
164
|
+
link.href = url;
|
|
165
|
+
link.download = filename;
|
|
166
|
+
document.body.appendChild(link);
|
|
167
|
+
link.click();
|
|
168
|
+
document.body.removeChild(link);
|
|
169
|
+
URL.revokeObjectURL(url);
|
|
170
|
+
};
|
|
171
|
+
export const saveContact = (brandPageData) => {
|
|
172
|
+
const vcard = generateVCard(brandPageData);
|
|
173
|
+
const profile = findProfileContent(brandPageData);
|
|
174
|
+
const filename = generateVCardFilename(profile?.name);
|
|
175
|
+
downloadVCard(vcard, filename);
|
|
176
|
+
};
|
package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts
CHANGED
|
@@ -1169,6 +1169,7 @@ declare const _default: import("vue").DefineComponent<{}, {
|
|
|
1169
1169
|
bpShowTopNavigationMobile(): boolean;
|
|
1170
1170
|
bpShowTopNavigationDesktop(): boolean;
|
|
1171
1171
|
slug(): string;
|
|
1172
|
+
shouldShowSaveContactWidget(): boolean;
|
|
1172
1173
|
}, {
|
|
1173
1174
|
openSideMenu(): void;
|
|
1174
1175
|
onLogoClick(tabName: string): void;
|
|
@@ -81,6 +81,7 @@ export default defineComponent({
|
|
|
81
81
|
mediaSizes: MEDIA_SIZES.size1x,
|
|
82
82
|
renderVideoAsImage: false,
|
|
83
83
|
shouldPlayVideos: this.shouldPlayVideos,
|
|
84
|
+
showOnGeneratedPreviews: false,
|
|
84
85
|
},
|
|
85
86
|
stripePublishableKey: undefined,
|
|
86
87
|
runtimeEnvironment: this.runtimeEnvironment,
|
|
@@ -118,6 +118,7 @@ export default defineComponent({
|
|
|
118
118
|
disableNavigationSideMenu: true,
|
|
119
119
|
mediaSizes: MEDIA_SIZES.sizeThumb,
|
|
120
120
|
renderVideoAsImage: true,
|
|
121
|
+
showOnGeneratedPreviews: false,
|
|
121
122
|
},
|
|
122
123
|
isCapturingPreview: false,
|
|
123
124
|
};
|
|
@@ -188,7 +189,7 @@ export default defineComponent({
|
|
|
188
189
|
},
|
|
189
190
|
watch: {
|
|
190
191
|
template() {
|
|
191
|
-
if (this.isAdmin) {
|
|
192
|
+
if (this.isAdmin || this.isPrePurchase) {
|
|
192
193
|
this.updateViewModel();
|
|
193
194
|
}
|
|
194
195
|
else {
|
|
@@ -199,7 +200,7 @@ export default defineComponent({
|
|
|
199
200
|
},
|
|
200
201
|
logoTheme: {
|
|
201
202
|
handler() {
|
|
202
|
-
if (this.isAdmin) {
|
|
203
|
+
if (this.isAdmin || this.isPrePurchase) {
|
|
203
204
|
this.updateViewModel();
|
|
204
205
|
}
|
|
205
206
|
},
|
|
@@ -207,7 +208,7 @@ export default defineComponent({
|
|
|
207
208
|
},
|
|
208
209
|
previewImageUrl() {
|
|
209
210
|
// Reset loading state whenever the preview URL changes
|
|
210
|
-
if (!this.isAdmin) {
|
|
211
|
+
if (!this.isAdmin && !this.isPrePurchase) {
|
|
211
212
|
this.imageLoading = true;
|
|
212
213
|
this.imageLoadError = false;
|
|
213
214
|
}
|
|
@@ -266,7 +267,7 @@ export default defineComponent({
|
|
|
266
267
|
},
|
|
267
268
|
async updateViewModel(forceUpdate = true) {
|
|
268
269
|
// Only update view model for admin or pre-purchase mode
|
|
269
|
-
if (!this.isAdmin) {
|
|
270
|
+
if (!this.isAdmin && !this.isPrePurchase) {
|
|
270
271
|
return;
|
|
271
272
|
}
|
|
272
273
|
const videoStore = useVideoStore();
|
|
@@ -47,6 +47,8 @@ export declare const EVENTS: {
|
|
|
47
47
|
WEBSITE_MAKER_AI_SEND_PROMPT: string;
|
|
48
48
|
WEBSITE_MAKER_AI_COPY_RESPONSE: string;
|
|
49
49
|
WEBSITE_MAKER_AI_STOP_GENERATION: string;
|
|
50
|
+
WEBSITE_SAVE_CONTACT: string;
|
|
51
|
+
WEBSITE_START_FOR_FREE: string;
|
|
50
52
|
};
|
|
51
53
|
export declare const SELECT_LOCATIONS: {
|
|
52
54
|
MAKER_PREVIEW: string;
|
|
@@ -30,6 +30,8 @@ export const EVENTS = {
|
|
|
30
30
|
WEBSITE_MAKER_AI_SEND_PROMPT: 'website_maker_ai_send_prompt',
|
|
31
31
|
WEBSITE_MAKER_AI_COPY_RESPONSE: 'website_maker_ai_copy_response',
|
|
32
32
|
WEBSITE_MAKER_AI_STOP_GENERATION: 'website_maker_ai_stop_generation',
|
|
33
|
+
WEBSITE_SAVE_CONTACT: 'website_save_contact',
|
|
34
|
+
WEBSITE_START_FOR_FREE: 'website_start_for_free',
|
|
33
35
|
};
|
|
34
36
|
export const SELECT_LOCATIONS = {
|
|
35
37
|
MAKER_PREVIEW: 'maker_preview',
|