@deneb-ui/ui 2.0.80 → 2.0.82

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.
@@ -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
@@ -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 siteName = String(common?.websiteTitle || common?.siteName || 'Storefront');
34
- const logoUrl = String(common?.logoUrl || '');
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;
@@ -568,6 +568,35 @@ function SiteDataProvider({ children, initialSiteData, fallbackSiteData, liveCat
568
568
  window.parent.postMessage({ type: exports.LEGACY_PREVIEW_READY_MESSAGE, pathname: window.location.pathname }, parentOrigin ?? '*');
569
569
  return () => window.removeEventListener('message', onMessage);
570
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]);
571
600
  const value = (0, react_1.useMemo)(() => siteData, [siteData]);
572
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] }));
573
602
  }
@@ -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 = contactData.phone || defaultPhone || '';
23
- const whatsapp = contactData.whatsapp || defaultWhatsApp || phone;
24
- const email = contactData.email || defaultEmail || '';
25
- const storeName = typeof sdRecord.site?.name === 'string' ? sdRecord.site.name : 'Support';
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.80",
3
+ "version": "2.0.82",
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.80"
53
+ "@deneb-ui/core": "^2.0.82"
54
54
  },
55
55
  "peerDependencies": {
56
56
  "react": "^18.0.0 || ^19.0.0",