@deneb-ui/ui 2.0.79 → 2.0.81
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/dist/EditableFooter.js
CHANGED
|
@@ -72,18 +72,20 @@ function EditableFooter({ defaultLinks = DEFAULT_FOOTER_PAGES, links, basePath =
|
|
|
72
72
|
const common = (content?.common || {});
|
|
73
73
|
const contact = (content?.contact || {});
|
|
74
74
|
const business = (common?.business || {});
|
|
75
|
+
const shop = (siteData?.shop || {});
|
|
76
|
+
const shopContact = (shop?.contact || {});
|
|
75
77
|
// Auto-synchronized with Header
|
|
76
|
-
const siteName = String(common?.websiteTitle || common?.siteName || 'Storefront');
|
|
77
|
-
const logoUrl = String(common?.logoUrl || '');
|
|
78
|
+
const siteName = String(common?.websiteTitle || common?.siteName || shop?.businessName || 'Storefront');
|
|
79
|
+
const logoUrl = String(common?.logoUrl || shop?.logoUrl || '');
|
|
78
80
|
const navLabels = (common?.navLabels || {});
|
|
79
81
|
// Footer-specific editable fields
|
|
80
82
|
const shortDescription = String(common?.shortDescription || 'A modern digital storefront engineered for high conversion and seamless visual editing.');
|
|
81
83
|
const footerHeading = String(common?.footerHeading || 'Stay Connected');
|
|
82
84
|
const copyright = String(common?.copyright || `© ${new Date().getFullYear()} ${siteName}. All rights reserved.`);
|
|
83
85
|
// Contact / business values
|
|
84
|
-
const phone = String(business?.phone || common?.phone || contact?.phone || '');
|
|
85
|
-
const emailContact = String(business?.email || common?.email || contact?.email || '');
|
|
86
|
-
const address = String(business?.location?.address || common?.address || contact?.address || '');
|
|
86
|
+
const phone = String(shopContact?.phone || shop?.businessPhone || business?.phone || common?.phone || contact?.phone || '');
|
|
87
|
+
const emailContact = String(shopContact?.email || shop?.businessEmail || business?.email || common?.email || contact?.email || '');
|
|
88
|
+
const address = String(shop?.address?.line1 || business?.location?.address || common?.address || contact?.address || '');
|
|
87
89
|
// Social media mapping with live editable URL bindings
|
|
88
90
|
const rawSocial = (common?.socialMedia || content?.socialMedia || props.socialMedia || {});
|
|
89
91
|
const socialPlatforms = Object.keys(rawSocial).length > 0
|
package/dist/EditableNavbar.js
CHANGED
|
@@ -30,8 +30,9 @@ function EditableNavbar({ defaultLinks = DEFAULT_PAGES, sticky = true, activeRou
|
|
|
30
30
|
const [mobileMenuOpen, setMobileMenuOpen] = (0, react_1.useState)(false);
|
|
31
31
|
const content = (siteData?.content || {});
|
|
32
32
|
const common = (content?.common || {});
|
|
33
|
-
const
|
|
34
|
-
const
|
|
33
|
+
const shop = (siteData?.shop || {});
|
|
34
|
+
const siteName = String(common?.websiteTitle || common?.siteName || shop?.businessName || 'Storefront');
|
|
35
|
+
const logoUrl = String(common?.logoUrl || shop?.logoUrl || '');
|
|
35
36
|
const headerCtaLabel = String(common?.headerCtaLabel || 'Get in Touch');
|
|
36
37
|
const navLabels = (common?.navLabels || {});
|
|
37
38
|
const requiredPages = Array.isArray(siteData?.requirements?.requiredPages)
|
|
@@ -123,3 +123,4 @@ export interface EditableProductGridProps extends React.HTMLAttributes<HTMLEleme
|
|
|
123
123
|
*/
|
|
124
124
|
export declare function EditableProductGrid({ sectionPath, listPath, title, subtitle, products: userProducts, categories, cardVariant, columns, onQuickView, cardPrefix, showSearch, searchPlaceholder, enableBackendSearch, onSearchChange, enablePagination, pageSize, pageSizeOptions, showPageSizeSelector, paginationVariant, hidePaginationOnSinglePage, currentPage: controlledPage, initialPage, onPageChange, scrollToTopOnPageChange, totalProducts, className, style, ...props }: EditableProductGridProps): React.JSX.Element;
|
|
125
125
|
export declare const ProductGrid: typeof EditableProductGrid;
|
|
126
|
+
export type ProductGridItem = ProductItem;
|
|
@@ -135,3 +135,14 @@ export declare function useShop(fallback?: GenericRecord): GenericRecord;
|
|
|
135
135
|
* Hook to retrieve customer reviews / testimonials cleanly from SiteData.
|
|
136
136
|
*/
|
|
137
137
|
export declare function useReviews(fallback?: GenericRecord[]): GenericRecord[];
|
|
138
|
+
/**
|
|
139
|
+
* Hook to retrieve common storefront metadata (website title, slogan, branding, etc.)
|
|
140
|
+
* with safe hierarchical fallbacks across content.common, shop profile, and user fallbacks.
|
|
141
|
+
* Never throws ReferenceError or crashes on missing data.
|
|
142
|
+
*/
|
|
143
|
+
export declare function useCommon(fallback?: GenericRecord): GenericRecord;
|
|
144
|
+
/**
|
|
145
|
+
* Hook to retrieve contact information (WhatsApp, phone, address, email, map link)
|
|
146
|
+
* with robust fallbacks across contact, common, and shop profile.
|
|
147
|
+
*/
|
|
148
|
+
export declare function useContact(fallback?: GenericRecord): GenericRecord;
|
package/dist/SiteDataProvider.js
CHANGED
|
@@ -24,6 +24,8 @@ exports.useSiteApi = useSiteApi;
|
|
|
24
24
|
exports.useSiteCatalog = useSiteCatalog;
|
|
25
25
|
exports.useShop = useShop;
|
|
26
26
|
exports.useReviews = useReviews;
|
|
27
|
+
exports.useCommon = useCommon;
|
|
28
|
+
exports.useContact = useContact;
|
|
27
29
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
28
30
|
const react_1 = require("react");
|
|
29
31
|
const core_1 = require("@deneb-ui/core");
|
|
@@ -566,6 +568,35 @@ function SiteDataProvider({ children, initialSiteData, fallbackSiteData, liveCat
|
|
|
566
568
|
window.parent.postMessage({ type: exports.LEGACY_PREVIEW_READY_MESSAGE, pathname: window.location.pathname }, parentOrigin ?? '*');
|
|
567
569
|
return () => window.removeEventListener('message', onMessage);
|
|
568
570
|
}, []);
|
|
571
|
+
// Synchronize document.title and favicon in client environments (both preview and live)
|
|
572
|
+
(0, react_1.useEffect)(() => {
|
|
573
|
+
if (typeof document === "undefined")
|
|
574
|
+
return;
|
|
575
|
+
const sd = siteData;
|
|
576
|
+
const common = isRecord(sd?.content?.common) ? sd.content.common : null;
|
|
577
|
+
const shop = isRecord(sd?.shop) ? sd.shop : null;
|
|
578
|
+
const site = isRecord(sd?.site) ? sd.site : null;
|
|
579
|
+
const candidateTitle = (typeof common?.websiteTitle === "string" && common.websiteTitle.trim()) ||
|
|
580
|
+
(typeof shop?.businessName === "string" && shop.businessName.trim()) ||
|
|
581
|
+
(typeof site?.name === "string" && site.name.trim());
|
|
582
|
+
if (candidateTitle) {
|
|
583
|
+
document.title = candidateTitle;
|
|
584
|
+
}
|
|
585
|
+
const candidateIcon = (typeof common?.logoUrl === "string" && common.logoUrl.trim()) ||
|
|
586
|
+
(typeof shop?.logoUrl === "string" && shop.logoUrl.trim()) ||
|
|
587
|
+
(typeof site?.logoUrl === "string" && site.logoUrl.trim());
|
|
588
|
+
if (candidateIcon) {
|
|
589
|
+
let link = document.querySelector("link[rel*='icon']");
|
|
590
|
+
if (!link) {
|
|
591
|
+
link = document.createElement("link");
|
|
592
|
+
link.rel = "icon";
|
|
593
|
+
document.head.appendChild(link);
|
|
594
|
+
}
|
|
595
|
+
if (link.href !== candidateIcon) {
|
|
596
|
+
link.href = candidateIcon;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}, [siteData]);
|
|
569
600
|
const value = (0, react_1.useMemo)(() => siteData, [siteData]);
|
|
570
601
|
return ((0, jsx_runtime_1.jsxs)(exports.SiteDataContext.Provider, { value: value, children: [(0, jsx_runtime_1.jsx)(ThemeStyles_1.ThemeStyles, { theme: value?.theme }), (0, jsx_runtime_1.jsx)(FontLoader_1.FontLoader, {}), (0, jsx_runtime_1.jsx)(ResponsiveBaseStyles_1.ResponsiveBaseStyles, {}), (0, jsx_runtime_1.jsx)(DenebComponentStyles_1.DenebComponentStyles, {}), children] }));
|
|
571
602
|
}
|
|
@@ -773,3 +804,93 @@ function useReviews(fallback = []) {
|
|
|
773
804
|
}
|
|
774
805
|
return fallback;
|
|
775
806
|
}
|
|
807
|
+
/**
|
|
808
|
+
* Hook to retrieve common storefront metadata (website title, slogan, branding, etc.)
|
|
809
|
+
* with safe hierarchical fallbacks across content.common, shop profile, and user fallbacks.
|
|
810
|
+
* Never throws ReferenceError or crashes on missing data.
|
|
811
|
+
*/
|
|
812
|
+
function useCommon(fallback = {}) {
|
|
813
|
+
const siteData = useSiteData();
|
|
814
|
+
const content = isRecord(siteData?.content) ? siteData.content : null;
|
|
815
|
+
const common = isRecord(content?.common) ? content.common : {};
|
|
816
|
+
const contact = isRecord(content?.contact) ? content.contact : {};
|
|
817
|
+
const shop = useShop();
|
|
818
|
+
const websiteTitle = (typeof common.websiteTitle === 'string' && common.websiteTitle.trim()) ||
|
|
819
|
+
(typeof shop.name === 'string' && shop.name.trim()) ||
|
|
820
|
+
(typeof shop.businessName === 'string' && shop.businessName.trim()) ||
|
|
821
|
+
(typeof fallback.websiteTitle === 'string' && fallback.websiteTitle.trim()) ||
|
|
822
|
+
'Store';
|
|
823
|
+
const whatsappNumber = (typeof common.whatsappNumber === 'string' && common.whatsappNumber.trim()) ||
|
|
824
|
+
(typeof contact.whatsappNumber === 'string' && contact.whatsappNumber.trim()) ||
|
|
825
|
+
(typeof shop.whatsappNumber === 'string' && shop.whatsappNumber.trim()) ||
|
|
826
|
+
(typeof shop.phone === 'string' && shop.phone.trim()) ||
|
|
827
|
+
(typeof fallback.whatsappNumber === 'string' && fallback.whatsappNumber.trim()) ||
|
|
828
|
+
'';
|
|
829
|
+
const cleanWa = whatsappNumber.replace(/\D+/g, '');
|
|
830
|
+
const whatsappUrl = (typeof common.whatsappUrl === 'string' && common.whatsappUrl.trim()) ||
|
|
831
|
+
(cleanWa ? `https://wa.me/${cleanWa}` : '') ||
|
|
832
|
+
(typeof fallback.whatsappUrl === 'string' && fallback.whatsappUrl.trim()) ||
|
|
833
|
+
'';
|
|
834
|
+
const address = (typeof common.address === 'string' && common.address.trim()) ||
|
|
835
|
+
(typeof common.footerAddress === 'string' && common.footerAddress.trim()) ||
|
|
836
|
+
(typeof contact.address === 'string' && contact.address.trim()) ||
|
|
837
|
+
(typeof shop.address === 'string' && shop.address.trim()) ||
|
|
838
|
+
(typeof fallback.address === 'string' && fallback.address.trim()) ||
|
|
839
|
+
'';
|
|
840
|
+
const logoUrl = (typeof common.logoUrl === 'string' && common.logoUrl.trim()) ||
|
|
841
|
+
(typeof shop.logoUrl === 'string' && shop.logoUrl.trim()) ||
|
|
842
|
+
(typeof fallback.logoUrl === 'string' && fallback.logoUrl.trim()) ||
|
|
843
|
+
'';
|
|
844
|
+
return {
|
|
845
|
+
...fallback,
|
|
846
|
+
...common,
|
|
847
|
+
websiteTitle,
|
|
848
|
+
whatsappNumber,
|
|
849
|
+
whatsappUrl,
|
|
850
|
+
address,
|
|
851
|
+
logoUrl,
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
/**
|
|
855
|
+
* Hook to retrieve contact information (WhatsApp, phone, address, email, map link)
|
|
856
|
+
* with robust fallbacks across contact, common, and shop profile.
|
|
857
|
+
*/
|
|
858
|
+
function useContact(fallback = {}) {
|
|
859
|
+
const siteData = useSiteData();
|
|
860
|
+
const content = isRecord(siteData?.content) ? siteData.content : null;
|
|
861
|
+
const contact = isRecord(content?.contact) ? content.contact : {};
|
|
862
|
+
const common = isRecord(content?.common) ? content.common : {};
|
|
863
|
+
const shop = useShop();
|
|
864
|
+
const whatsappNumber = (typeof contact.whatsappNumber === 'string' && contact.whatsappNumber.trim()) ||
|
|
865
|
+
(typeof common.whatsappNumber === 'string' && common.whatsappNumber.trim()) ||
|
|
866
|
+
(typeof shop.whatsappNumber === 'string' && shop.whatsappNumber.trim()) ||
|
|
867
|
+
(typeof shop.phone === 'string' && shop.phone.trim()) ||
|
|
868
|
+
(typeof fallback.whatsappNumber === 'string' && fallback.whatsappNumber.trim()) ||
|
|
869
|
+
'';
|
|
870
|
+
const cleanWa = whatsappNumber.replace(/\D+/g, '');
|
|
871
|
+
const whatsappUrl = (typeof contact.whatsappUrl === 'string' && contact.whatsappUrl.trim()) ||
|
|
872
|
+
(typeof common.whatsappUrl === 'string' && common.whatsappUrl.trim()) ||
|
|
873
|
+
(cleanWa ? `https://wa.me/${cleanWa}` : '') ||
|
|
874
|
+
'';
|
|
875
|
+
const address = (typeof contact.address === 'string' && contact.address.trim()) ||
|
|
876
|
+
(typeof common.address === 'string' && common.address.trim()) ||
|
|
877
|
+
(typeof shop.address === 'string' && shop.address.trim()) ||
|
|
878
|
+
(typeof fallback.address === 'string' && fallback.address.trim()) ||
|
|
879
|
+
'';
|
|
880
|
+
const email = (typeof contact.email === 'string' && contact.email.trim()) ||
|
|
881
|
+
(typeof shop.email === 'string' && shop.email.trim()) ||
|
|
882
|
+
(typeof fallback.email === 'string' && fallback.email.trim()) ||
|
|
883
|
+
'';
|
|
884
|
+
const googleMapLink = (typeof contact.googleMapLink === 'string' && contact.googleMapLink.trim()) ||
|
|
885
|
+
(typeof fallback.googleMapLink === 'string' && fallback.googleMapLink.trim()) ||
|
|
886
|
+
'';
|
|
887
|
+
return {
|
|
888
|
+
...fallback,
|
|
889
|
+
...contact,
|
|
890
|
+
whatsappNumber,
|
|
891
|
+
whatsappUrl,
|
|
892
|
+
address,
|
|
893
|
+
email,
|
|
894
|
+
googleMapLink,
|
|
895
|
+
};
|
|
896
|
+
}
|
|
@@ -18,11 +18,42 @@ function FloatingContactWidget({ fieldPath = 'contact', defaultPhone, defaultWha
|
|
|
18
18
|
const { siteData } = (0, SiteDataProvider_1.useSiteData)();
|
|
19
19
|
const [isOpen, setIsOpen] = (0, react_1.useState)(false);
|
|
20
20
|
const sdRecord = (siteData && typeof siteData === 'object' ? siteData : {});
|
|
21
|
+
const content = (sdRecord.content && typeof sdRecord.content === 'object' ? sdRecord.content : {});
|
|
22
|
+
const common = (content.common && typeof content.common === 'object' ? content.common : {});
|
|
23
|
+
const contentContact = (content.contact && typeof content.contact === 'object' ? content.contact : {});
|
|
24
|
+
const shop = (sdRecord.shop && typeof sdRecord.shop === 'object' ? sdRecord.shop : {});
|
|
25
|
+
const shopContact = (shop.contact && typeof shop.contact === 'object' ? shop.contact : {});
|
|
21
26
|
const contactData = (sdRecord.contact && typeof sdRecord.contact === 'object' ? sdRecord.contact : {});
|
|
22
|
-
const phone =
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
const phone = String(contentContact.phone ||
|
|
28
|
+
contentContact.contactNumber ||
|
|
29
|
+
common.contactNumber ||
|
|
30
|
+
shopContact.phone ||
|
|
31
|
+
shop.businessPhone ||
|
|
32
|
+
contactData.phone ||
|
|
33
|
+
defaultPhone ||
|
|
34
|
+
'').trim();
|
|
35
|
+
const whatsapp = String(common.whatsapp ||
|
|
36
|
+
common.whatsappNumber ||
|
|
37
|
+
contentContact.whatsapp ||
|
|
38
|
+
contentContact.whatsappNumber ||
|
|
39
|
+
shopContact.whatsapp ||
|
|
40
|
+
shop.businessWhatsapp ||
|
|
41
|
+
shop.whatsapp ||
|
|
42
|
+
contactData.whatsapp ||
|
|
43
|
+
defaultWhatsApp ||
|
|
44
|
+
phone ||
|
|
45
|
+
'').trim();
|
|
46
|
+
const email = String(contentContact.email ||
|
|
47
|
+
common.email ||
|
|
48
|
+
shopContact.email ||
|
|
49
|
+
shop.businessEmail ||
|
|
50
|
+
contactData.email ||
|
|
51
|
+
defaultEmail ||
|
|
52
|
+
'').trim();
|
|
53
|
+
const storeName = String(common.websiteTitle ||
|
|
54
|
+
shop.businessName ||
|
|
55
|
+
sdRecord.site?.name ||
|
|
56
|
+
'Support').trim();
|
|
26
57
|
const hasWhatsApp = Boolean(whatsapp && whatsapp.trim().length > 0);
|
|
27
58
|
const hasPhone = Boolean(phone && phone.trim().length > 0);
|
|
28
59
|
const hasEmail = Boolean(email && email.trim().length > 0);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deneb-ui/ui",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.81",
|
|
4
4
|
"description": "Visual-first React component library for editable commerce storefronts. Built for Next.js and Fivora.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
],
|
|
51
51
|
"license": "MIT",
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@deneb-ui/core": "^2.0.
|
|
53
|
+
"@deneb-ui/core": "^2.0.81"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
56
|
"react": "^18.0.0 || ^19.0.0",
|