@deneb-ui/ui 2.0.72 → 2.0.74

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.
@@ -4,6 +4,7 @@ exports.CustomerReviews = void 0;
4
4
  exports.EditableCustomerReviews = EditableCustomerReviews;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
6
  const react_1 = require("react");
7
+ const SiteDataProvider_1 = require("./SiteDataProvider");
7
8
  const DEFAULT_REVIEWS = [
8
9
  {
9
10
  id: 1,
@@ -43,14 +44,47 @@ const DEFAULT_REVIEWS = [
43
44
  *
44
45
  * Created by Chamika Gayashan & Induranga Kawishwara
45
46
  */
46
- function EditableCustomerReviews({ sectionPath = 'home', title = 'Loved by Athletes & Runners Worldwide', subtitle = 'Verified Customer Reviews', averageRating = '4.9', totalReviews = '1,420+', reviews = DEFAULT_REVIEWS, className = '', style, ...props }) {
47
+ function EditableCustomerReviews({ sectionPath = 'home', title, subtitle, averageRating, totalReviews, reviews, className = '', style, ...props }) {
47
48
  const [selectedStarFilter, setSelectedStarFilter] = (0, react_1.useState)(null);
49
+ const liveReviews = (0, SiteDataProvider_1.useReviews)();
50
+ const siteData = (0, SiteDataProvider_1.useSiteData)();
51
+ const siteReviews = siteData?.content?.[sectionPath]?.reviews || siteData?.content?.reviews || siteData?.content?.home?.reviews;
52
+ const rawReviews = (reviews && reviews.length > 0)
53
+ ? reviews
54
+ : (liveReviews && liveReviews.length > 0)
55
+ ? liveReviews
56
+ : (Array.isArray(siteReviews) && siteReviews.length > 0)
57
+ ? siteReviews
58
+ : DEFAULT_REVIEWS;
59
+ const normalizedReviews = (0, react_1.useMemo)(() => {
60
+ return rawReviews.map((r, idx) => ({
61
+ id: r.id ?? idx + 1,
62
+ author: r.author || r.name || r.customerName || 'Customer',
63
+ rating: typeof r.rating === 'number' ? r.rating : (parseInt(r.rating, 10) || 5),
64
+ date: r.date || r.timeAgo || 'Recently',
65
+ comment: r.comment || r.body || r.feedback || r.quote || '',
66
+ verified: r.verified !== false,
67
+ productName: r.productName || r.item || undefined,
68
+ helpfulCount: r.helpfulCount || undefined,
69
+ }));
70
+ }, [rawReviews]);
71
+ const calculatedAvg = (0, react_1.useMemo)(() => {
72
+ if (!normalizedReviews.length)
73
+ return '5.0';
74
+ const sum = normalizedReviews.reduce((acc, r) => acc + (Number(r.rating) || 5), 0);
75
+ return (sum / normalizedReviews.length).toFixed(1);
76
+ }, [normalizedReviews]);
77
+ const hasLive = (liveReviews && liveReviews.length > 0) || (reviews && reviews.length > 0);
78
+ const resolvedAverageRating = averageRating ?? (hasLive ? calculatedAvg : '4.9');
79
+ const resolvedTotalReviews = totalReviews ?? (hasLive ? `${normalizedReviews.length}+` : '1,420+');
80
+ const resolvedTitle = title ?? siteData?.content?.[sectionPath]?.reviewsTitle ?? siteData?.content?.home?.reviewsTitle ?? 'Loved by Customers Worldwide';
81
+ const resolvedSubtitle = subtitle ?? siteData?.content?.[sectionPath]?.reviewsSubtitle ?? siteData?.content?.home?.reviewsSubtitle ?? 'Verified Customer Reviews';
48
82
  const filteredReviews = (0, react_1.useMemo)(() => {
49
83
  if (selectedStarFilter === null)
50
- return reviews;
51
- return reviews.filter((r) => r.rating === selectedStarFilter);
52
- }, [reviews, selectedStarFilter]);
53
- return ((0, jsx_runtime_1.jsxs)("section", { "data-preview-page-key": sectionPath, className: `editable-customer-reviews max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16 ${className}`.trim(), style: style, ...props, children: [(0, jsx_runtime_1.jsxs)("div", { className: "text-center max-w-2xl mx-auto mb-12", children: [subtitle && ((0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.reviewsSubtitle`, className: "text-xs font-black tracking-widest uppercase text-emerald-600 dark:text-lime-400 block mb-2", children: subtitle })), (0, jsx_runtime_1.jsx)("h2", { "data-preview-field-path": `${sectionPath}.reviewsTitle`, className: "text-3xl sm:text-4xl font-extrabold tracking-tight text-slate-900 dark:text-white leading-tight", children: title }), (0, jsx_runtime_1.jsxs)("div", { className: "mt-4 flex items-center justify-center gap-3", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex text-amber-500 dark:text-amber-400 text-lg", children: '★★★★★' }), (0, jsx_runtime_1.jsxs)("span", { className: "text-slate-900 dark:text-white font-extrabold text-lg", children: [(0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.reviewsAverage`, children: averageRating }), " / 5.0"] }), (0, jsx_runtime_1.jsxs)("span", { className: "text-slate-500 dark:text-slate-400 text-sm", children: ["(", (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.reviewsCount`, children: totalReviews }), " reviews)"] })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-center gap-2 mb-8", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setSelectedStarFilter(null), className: `px-3.5 py-1.5 rounded-xl text-xs font-bold transition-all ${selectedStarFilter === null
84
+ return normalizedReviews;
85
+ return normalizedReviews.filter((r) => r.rating === selectedStarFilter);
86
+ }, [normalizedReviews, selectedStarFilter]);
87
+ return ((0, jsx_runtime_1.jsxs)("section", { "data-preview-page-key": sectionPath, className: `editable-customer-reviews max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16 ${className}`.trim(), style: style, ...props, children: [(0, jsx_runtime_1.jsxs)("div", { className: "text-center max-w-2xl mx-auto mb-12", children: [subtitle && ((0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.reviewsSubtitle`, className: "text-xs font-black tracking-widest uppercase text-emerald-600 dark:text-lime-400 block mb-2", children: resolvedSubtitle })), (0, jsx_runtime_1.jsx)("h2", { "data-preview-field-path": `${sectionPath}.reviewsTitle`, className: "text-3xl sm:text-4xl font-extrabold tracking-tight text-slate-900 dark:text-white leading-tight", children: title }), (0, jsx_runtime_1.jsxs)("div", { className: "mt-4 flex items-center justify-center gap-3", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex text-amber-500 dark:text-amber-400 text-lg", children: '★★★★★' }), (0, jsx_runtime_1.jsxs)("span", { className: "text-slate-900 dark:text-white font-extrabold text-lg", children: [(0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.reviewsAverage`, children: resolvedAverageRating }), " / 5.0"] }), (0, jsx_runtime_1.jsxs)("span", { className: "text-slate-500 dark:text-slate-400 text-sm", children: ["(", (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.reviewsCount`, children: resolvedTotalReviews }), " reviews)"] })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-center gap-2 mb-8", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setSelectedStarFilter(null), className: `px-3.5 py-1.5 rounded-xl text-xs font-bold transition-all ${selectedStarFilter === null
54
88
  ? 'bg-slate-900 text-white dark:bg-lime-400 dark:text-slate-950 font-extrabold shadow-sm'
55
89
  : 'bg-slate-100 text-slate-600 hover:text-slate-900 border border-slate-200 dark:bg-slate-900/60 dark:text-slate-400 dark:hover:text-white dark:border-slate-800'}`, children: "All Reviews" }), [5, 4, 3].map((stars) => ((0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => setSelectedStarFilter(stars), className: `px-3.5 py-1.5 rounded-xl text-xs font-bold transition-all flex items-center gap-1 ${selectedStarFilter === stars
56
90
  ? 'bg-slate-900 text-white dark:bg-lime-400 dark:text-slate-950 font-extrabold shadow-sm'
@@ -23,3 +23,4 @@ export interface EditableGoogleFeedbackProps extends React.HTMLAttributes<HTMLEl
23
23
  cardClassName?: string;
24
24
  }
25
25
  export declare function EditableGoogleFeedback({ heading, subheading, badgeTitle, badgeRating, badgeReviewsCount, badgeIcon, feedbacks, maxStars, className, cardClassName, style, basePath, ...props }: EditableGoogleFeedbackProps): React.JSX.Element;
26
+ export declare const GoogleFeedback: typeof EditableGoogleFeedback;
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GoogleFeedback = void 0;
3
4
  exports.EditableGoogleFeedback = EditableGoogleFeedback;
4
5
  const jsx_runtime_1 = require("react/jsx-runtime");
5
6
  /* eslint-disable @next/next/no-img-element */
6
7
  const react_1 = require("react");
8
+ const SiteDataProvider_1 = require("./SiteDataProvider");
7
9
  const DEFAULT_GOOGLE_ICON = 'https://upload.wikimedia.org/wikipedia/commons/c/c1/Google_%22G%22_logo.svg';
8
10
  const DEFAULT_FEEDBACKS = [
9
11
  {
@@ -117,9 +119,42 @@ function FeedbackCard({ item, index, maxStars, badgeIcon, badgeTitle, cardClassN
117
119
  }, title: "Click to upload/change review platform icon (Google, Twitter, Trustpilot, etc.)" }));
118
120
  })()] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between gap-2 pt-1", children: [(0, jsx_runtime_1.jsxs)("div", { className: "inline-flex items-center gap-2 p-1 -ml-1 rounded-lg cursor-pointer transition-all hover:bg-amber-500/10 group", onClick: handleFocusRating, title: `Rating: ${currentRating} of ${maxStars} (Click to edit)`, children: [(0, jsx_runtime_1.jsx)("div", { className: "flex items-center gap-[2px]", "data-fivora-stars-row": "true", children: Array.from({ length: maxStars }).map((_, sIdx) => ((0, jsx_runtime_1.jsx)(GoogleStarSvg, { filled: sIdx < currentRating, size: 18 }, sIdx))) }), (0, jsx_runtime_1.jsx)("span", { ref: ratingRef, "data-preview-field-path": `feedback.feedbacks[${index}].rating`, "data-fivora-rating-text": "true", className: "text-xs font-black text-amber-600 bg-amber-500/10 px-1.5 py-0.5 rounded-md border border-amber-500/20 dark:text-amber-400 group-hover:bg-amber-500/20 transition-colors tabular-nums", title: "Star count (1-5)", children: currentRating })] }), (0, jsx_runtime_1.jsxs)("div", { className: "inline-flex items-center gap-1 text-[11px] font-bold text-blue-600 bg-blue-50 dark:text-blue-400 dark:bg-blue-500/10 px-2.5 py-1 rounded-full border border-blue-500/20", children: [(0, jsx_runtime_1.jsx)("svg", { className: "w-3 h-3 fill-current", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" }) }), (0, jsx_runtime_1.jsx)("span", { children: "Verified" })] })] }), (0, jsx_runtime_1.jsxs)("p", { "data-preview-field-path": `feedback.feedbacks[${index}].comment`, className: "text-sm sm:text-base text-slate-700 dark:text-slate-300 leading-relaxed italic font-normal pt-1", children: ["\u201C", reviewerComment, "\u201D"] })] }) }));
119
121
  }
120
- function EditableGoogleFeedback({ heading = 'Loved by Customers Worldwide', subheading = 'Real stories and verified 5-star reviews from our official Google Business profile.', badgeTitle = 'Google Reviews', badgeRating = '4.9', badgeReviewsCount = '128 verified reviews', badgeIcon, feedbacks = DEFAULT_FEEDBACKS, maxStars = 5, className = '', cardClassName = '', style, basePath = 'feedback', ...props }) {
121
- const items = Array.isArray(feedbacks) && feedbacks.length > 0 ? feedbacks : DEFAULT_FEEDBACKS;
122
+ function EditableGoogleFeedback({ heading, subheading, badgeTitle = 'Google Reviews', badgeRating, badgeReviewsCount, badgeIcon, feedbacks, maxStars = 5, className = '', cardClassName = '', style, basePath = 'feedback', ...props }) {
123
+ const liveReviews = (0, SiteDataProvider_1.useReviews)();
124
+ const siteData = (0, SiteDataProvider_1.useSiteData)();
125
+ const siteFeedback = siteData?.content?.[basePath]?.feedbacks || siteData?.content?.[basePath]?.reviews || siteData?.content?.reviews;
126
+ const rawFeedbacks = (feedbacks && feedbacks.length > 0)
127
+ ? feedbacks
128
+ : (liveReviews && liveReviews.length > 0)
129
+ ? liveReviews
130
+ : (Array.isArray(siteFeedback) && siteFeedback.length > 0)
131
+ ? siteFeedback
132
+ : DEFAULT_FEEDBACKS;
133
+ const items = (0, react_1.useMemo)(() => {
134
+ return rawFeedbacks.map((f, index) => ({
135
+ id: f.id ?? index + 1,
136
+ name: f.name || f.author || f.customerName || 'Customer',
137
+ avatar: f.avatar || `https://api.dicebear.com/7.x/avataaars/svg?seed=${encodeURIComponent(f.name || f.author || String(index))}`,
138
+ rating: typeof f.rating === 'number' ? f.rating : (parseInt(f.rating, 10) || 5),
139
+ date: f.date || f.timeAgo || 'Recently',
140
+ comment: f.comment || f.body || f.feedback || f.quote || '',
141
+ verified: f.verified !== false,
142
+ }));
143
+ }, [rawFeedbacks]);
144
+ const calculatedAvg = (0, react_1.useMemo)(() => {
145
+ if (!items.length)
146
+ return '5.0';
147
+ const sum = items.reduce((acc, r) => acc + (Number(r.rating) || 5), 0);
148
+ return (sum / items.length).toFixed(1);
149
+ }, [items]);
150
+ const hasLive = (liveReviews && liveReviews.length > 0) || (feedbacks && feedbacks.length > 0);
151
+ const effectiveBadgeRating = badgeRating ?? (hasLive ? calculatedAvg : '4.9');
152
+ const effectiveBadgeCount = badgeReviewsCount ?? (hasLive ? `${items.length} verified reviews` : '128 verified reviews');
153
+ const effectiveHeading = heading ?? siteData?.content?.[basePath]?.heading ?? 'Loved by Customers Worldwide';
154
+ const effectiveSubheading = subheading ?? siteData?.content?.[basePath]?.subheading ?? 'Real stories and verified 5-star reviews from our official Google Business profile.';
122
155
  const hasCustomPy = /(^|\s)(p|py|pt)-/.test(className);
123
156
  const defaultPadding = hasCustomPy ? '' : 'py-6 sm:py-8';
124
- return ((0, jsx_runtime_1.jsx)("section", { "data-preview-page-key": basePath, className: `editable-google-feedback w-full ${defaultPadding} ${className}`.trim(), style: style, ...props, children: (0, jsx_runtime_1.jsxs)("div", { className: "max-w-[1600px] mx-auto px-4 sm:px-6 lg:px-10", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col md:flex-row md:items-end justify-between gap-6 mb-6 sm:mb-8", children: [(0, jsx_runtime_1.jsxs)("div", { className: "max-w-2xl space-y-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "inline-flex items-center gap-2.5 px-3.5 py-1.5 rounded-full bg-slate-100 border border-slate-200 dark:bg-slate-900/80 dark:border-slate-800 shadow-sm", children: [(0, jsx_runtime_1.jsx)("img", { src: badgeIcon || DEFAULT_GOOGLE_ICON, alt: "Google", "data-preview-field-path": `feedback.badgeIcon`, className: "w-4 h-4 object-contain" }), (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `feedback.badgeTitle`, className: "text-xs uppercase tracking-widest font-black text-slate-800 dark:text-slate-200", children: badgeTitle }), (0, jsx_runtime_1.jsx)("span", { className: "w-1 h-1 rounded-full bg-slate-400 dark:bg-slate-600" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1.5", children: [(0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `feedback.badgeRating`, className: "text-xs font-black text-amber-600 dark:text-amber-400", children: badgeRating }), (0, jsx_runtime_1.jsx)("div", { className: "flex items-center gap-[2px]", children: Array.from({ length: 5 }).map((_, sIdx) => ((0, jsx_runtime_1.jsx)(GoogleStarSvg, { filled: true, size: 14 }, sIdx))) })] }), (0, jsx_runtime_1.jsxs)("span", { className: "text-[11px] text-slate-500 dark:text-slate-400 font-medium hidden sm:inline", children: ["(", (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `feedback.badgeReviewsCount`, children: badgeReviewsCount }), ")"] })] }), (0, jsx_runtime_1.jsx)("h2", { "data-preview-field-path": `feedback.heading`, className: "font-heading text-2xl xs:text-3xl sm:text-4xl lg:text-5xl font-black text-slate-900 dark:text-white tracking-tight", children: heading }), (0, jsx_runtime_1.jsx)("p", { "data-preview-field-path": `feedback.subheading`, className: "text-xs sm:text-base text-slate-600 dark:text-slate-400 leading-relaxed", children: subheading })] }), (0, jsx_runtime_1.jsx)("div", { className: "hidden md:flex flex-col items-end text-right", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `feedback.badgeRating`, className: "font-heading text-4xl font-black text-amber-500 dark:text-amber-400", children: badgeRating }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-start gap-0.5", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex items-center gap-[2px]", children: Array.from({ length: 5 }).map((_, sIdx) => ((0, jsx_runtime_1.jsx)(GoogleStarSvg, { filled: true, size: 16 }, sIdx))) }), (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `feedback.badgeReviewsCount`, className: "text-xs text-slate-500 dark:text-slate-400 font-bold", children: badgeReviewsCount })] })] }) })] }), (0, jsx_runtime_1.jsx)("div", { "data-preview-list-path": `feedback.feedbacks`, className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6", children: items.map((item, index) => ((0, jsx_runtime_1.jsx)(FeedbackCard, { item: item, index: index, maxStars: maxStars, badgeIcon: badgeIcon, badgeTitle: badgeTitle, cardClassName: cardClassName }, item.id || String(index)))) })] }) }));
157
+ return ((0, jsx_runtime_1.jsx)("section", { "data-preview-page-key": basePath, className: `editable-google-feedback w-full ${defaultPadding} ${className}`.trim(), style: style, ...props, children: (0, jsx_runtime_1.jsxs)("div", { className: "max-w-[1600px] mx-auto px-4 sm:px-6 lg:px-10", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col md:flex-row md:items-end justify-between gap-6 mb-6 sm:mb-8", children: [(0, jsx_runtime_1.jsxs)("div", { className: "max-w-2xl space-y-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "inline-flex items-center gap-2.5 px-3.5 py-1.5 rounded-full bg-slate-100 border border-slate-200 dark:bg-slate-900/80 dark:border-slate-800 shadow-sm", children: [(0, jsx_runtime_1.jsx)("img", { src: badgeIcon || DEFAULT_GOOGLE_ICON, alt: "Google", "data-preview-field-path": `feedback.badgeIcon`, className: "w-4 h-4 object-contain" }), (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `feedback.badgeTitle`, className: "text-xs uppercase tracking-widest font-black text-slate-800 dark:text-slate-200", children: badgeTitle }), (0, jsx_runtime_1.jsx)("span", { className: "w-1 h-1 rounded-full bg-slate-400 dark:bg-slate-600" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1.5", children: [(0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `feedback.badgeRating`, className: "text-xs font-black text-amber-600 dark:text-amber-400", children: effectiveBadgeRating }), (0, jsx_runtime_1.jsx)("div", { className: "flex items-center gap-[2px]", children: Array.from({ length: 5 }).map((_, sIdx) => ((0, jsx_runtime_1.jsx)(GoogleStarSvg, { filled: true, size: 14 }, sIdx))) })] }), (0, jsx_runtime_1.jsxs)("span", { className: "text-[11px] text-slate-500 dark:text-slate-400 font-medium hidden sm:inline", children: ["(", (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `feedback.badgeReviewsCount`, children: effectiveBadgeCount }), ")"] })] }), (0, jsx_runtime_1.jsx)("h2", { "data-preview-field-path": `feedback.heading`, className: "font-heading text-2xl xs:text-3xl sm:text-4xl lg:text-5xl font-black text-slate-900 dark:text-white tracking-tight", children: effectiveHeading }), (0, jsx_runtime_1.jsx)("p", { "data-preview-field-path": `feedback.subheading`, className: "text-xs sm:text-base text-slate-600 dark:text-slate-400 leading-relaxed", children: effectiveSubheading })] }), (0, jsx_runtime_1.jsx)("div", { className: "hidden md:flex flex-col items-end text-right", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `feedback.badgeRating`, className: "font-heading text-4xl font-black text-amber-500 dark:text-amber-400", children: badgeRating }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-start gap-0.5", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex items-center gap-[2px]", children: Array.from({ length: 5 }).map((_, sIdx) => ((0, jsx_runtime_1.jsx)(GoogleStarSvg, { filled: true, size: 16 }, sIdx))) }), (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `feedback.badgeReviewsCount`, className: "text-xs text-slate-500 dark:text-slate-400 font-bold", children: badgeReviewsCount })] })] }) })] }), (0, jsx_runtime_1.jsx)("div", { "data-preview-list-path": `feedback.feedbacks`, className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6", children: items.map((item, index) => ((0, jsx_runtime_1.jsx)(FeedbackCard, { item: item, index: index, maxStars: maxStars, badgeIcon: badgeIcon, badgeTitle: badgeTitle, cardClassName: cardClassName }, item.id || String(index)))) })] }) }));
125
158
  }
159
+ // Canonical alias
160
+ exports.GoogleFeedback = EditableGoogleFeedback;
@@ -15,3 +15,4 @@ export interface EditableTestimonialSectionProps extends React.HTMLAttributes<HT
15
15
  cardClassName?: string;
16
16
  }
17
17
  export declare function EditableTestimonialSection({ basePath, badge, heading, subheading, testimonials, maxStars, className, cardClassName, style, ...props }: EditableTestimonialSectionProps): React.JSX.Element;
18
+ export declare const TestimonialSection: typeof EditableTestimonialSection;
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TestimonialSection = void 0;
3
4
  exports.EditableTestimonialSection = EditableTestimonialSection;
4
5
  const jsx_runtime_1 = require("react/jsx-runtime");
5
6
  /* eslint-disable @next/next/no-img-element */
6
7
  const react_1 = require("react");
8
+ const SiteDataProvider_1 = require("./SiteDataProvider");
7
9
  const DEFAULT_TESTIMONIALS = [
8
10
  {
9
11
  id: 1,
@@ -83,26 +85,33 @@ function TestimonialCard({ item, index, maxStars, cardClassName, }) {
83
85
  const tagText = String(currentItem.tag || '');
84
86
  return ((0, jsx_runtime_1.jsxs)("div", { "data-preview-item-path": `testimonials.testimonials[${index}]`, className: `relative p-5 sm:p-7 lg:p-8 rounded-2xl sm:rounded-3xl bg-white border border-slate-200 hover:border-slate-300 shadow-sm hover:shadow-md dark:bg-gradient-to-b dark:from-slate-900/70 dark:to-slate-950/90 dark:border-slate-800/80 dark:hover:border-slate-700 dark:shadow-xl transition-[transform,box-shadow] duration-200 flex flex-col justify-between space-y-5 min-w-0 ${cardClassName || ''}`.trim(), children: [(0, jsx_runtime_1.jsxs)("div", { className: "space-y-4 min-w-0", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [Boolean(currentItem.tag) && ((0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `testimonials.testimonials[${index}].tag`, className: "px-2.5 py-1 rounded-full bg-slate-100 text-slate-700 border border-slate-200 dark:bg-slate-800/80 dark:text-lime-400 dark:border-lime-400/20 text-[10px] sm:text-[11px] uppercase tracking-wider font-extrabold shrink-0", children: tagText })), (0, jsx_runtime_1.jsxs)("div", { className: "inline-flex items-center gap-1.5 p-1 -mr-1 rounded-lg cursor-pointer transition-all hover:bg-amber-500/10 group ml-auto shrink-0", onClick: handleFocusRating, title: `Rating: ${currentRating} of ${maxStars} (Click to edit)`, children: [(0, jsx_runtime_1.jsx)("div", { className: "flex items-center gap-[2px]", "data-fivora-stars-row": "true", children: Array.from({ length: maxStars }).map((_, sIdx) => ((0, jsx_runtime_1.jsx)(StarSvg, { filled: sIdx < currentRating, size: 14 }, sIdx))) }), (0, jsx_runtime_1.jsx)("span", { ref: ratingRef, "data-preview-field-path": `testimonials.testimonials[${index}].rating`, "data-fivora-rating-text": "true", className: "text-xs font-black text-amber-600 bg-amber-500/10 px-1.5 py-0.5 rounded-md border border-amber-500/20 dark:text-amber-400 group-hover:bg-amber-500/20 transition-colors tabular-nums", title: "Star count (1-5)", children: currentRating })] })] }), (0, jsx_runtime_1.jsxs)("blockquote", { "data-preview-field-path": `testimonials.testimonials[${index}].quote`, className: "font-serif-italic text-sm sm:text-base text-slate-700 dark:text-slate-300 leading-relaxed break-words", children: ["\u201C", quoteText, "\u201D"] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "pt-4 border-t border-slate-100 dark:border-slate-800 flex items-center gap-3 min-w-0", children: [(0, jsx_runtime_1.jsx)("img", { src: authorAvatar, alt: authorName, "data-preview-field-path": `testimonials.testimonials[${index}].avatar`, className: "w-10 h-10 sm:w-12 sm:h-12 rounded-full object-cover border border-slate-200 dark:border-slate-700 shadow-sm shrink-0" }), (0, jsx_runtime_1.jsxs)("div", { className: "min-w-0 flex-1", children: [(0, jsx_runtime_1.jsx)("h4", { "data-preview-field-path": `testimonials.testimonials[${index}].author`, className: "font-heading font-black text-sm sm:text-base text-slate-900 dark:text-white truncate", children: authorName }), (0, jsx_runtime_1.jsx)("p", { "data-preview-field-path": `testimonials.testimonials[${index}].role`, className: "text-xs text-slate-500 dark:text-slate-400 font-medium leading-snug line-clamp-2", children: authorRole })] })] })] }));
85
87
  }
86
- function EditableTestimonialSection({ basePath = 'testimonials', badge = 'WORDS OF ACCLAIM', heading = 'WHAT THE CRITICS ARE SAYING', subheading = 'Reflections from international cuppers, culinary masters, and dedicated regulars.', testimonials = DEFAULT_TESTIMONIALS, maxStars = 5, className = '', cardClassName = '', style, ...props }) {
88
+ function EditableTestimonialSection({ basePath = 'testimonials', badge = 'WORDS OF ACCLAIM', heading, subheading, testimonials, maxStars = 5, className = '', cardClassName = '', style, ...props }) {
89
+ const liveReviews = (0, SiteDataProvider_1.useReviews)();
90
+ const siteData = (0, SiteDataProvider_1.useSiteData)();
91
+ const siteTestimonials = siteData?.content?.[basePath]?.testimonials || siteData?.content?.[basePath]?.reviews || siteData?.content?.reviews;
92
+ const rawTestimonials = (testimonials && testimonials.length > 0)
93
+ ? testimonials
94
+ : (liveReviews && liveReviews.length > 0)
95
+ ? liveReviews
96
+ : (Array.isArray(siteTestimonials) && siteTestimonials.length > 0)
97
+ ? siteTestimonials
98
+ : DEFAULT_TESTIMONIALS;
87
99
  const items = (0, react_1.useMemo)(() => {
88
- const list = Array.isArray(testimonials) ? testimonials : [];
89
- if (list.length === 0) {
90
- return DEFAULT_TESTIMONIALS;
91
- }
92
- return list.map((item, index) => {
93
- const fallback = DEFAULT_TESTIMONIALS[index % DEFAULT_TESTIMONIALS.length] || DEFAULT_TESTIMONIALS[0];
94
- if (!item || typeof item !== 'object') {
95
- return { ...fallback, id: `fallback-${index}` };
96
- }
97
- return {
98
- ...fallback,
99
- ...item,
100
- id: item.id || `testimonial-${index}`,
101
- rating: item.rating !== undefined && item.rating !== null ? item.rating : 5,
102
- };
103
- });
104
- }, [testimonials]);
100
+ return rawTestimonials.map((t, index) => ({
101
+ id: t.id ?? index + 1,
102
+ author: t.author || t.name || t.customerName || 'Customer',
103
+ role: t.role || (t.verified !== false ? 'Verified Customer' : 'Customer'),
104
+ quote: t.quote || t.comment || t.feedback || t.body || '',
105
+ avatar: t.avatar || `https://api.dicebear.com/7.x/avataaars/svg?seed=${encodeURIComponent(t.author || t.name || String(index))}`,
106
+ rating: typeof t.rating === 'number' ? t.rating : (parseInt(t.rating, 10) || 5),
107
+ tag: t.tag || 'Verified Buyer',
108
+ }));
109
+ }, [rawTestimonials]);
110
+ const effectiveHeading = heading ?? siteData?.content?.[basePath]?.heading ?? 'WHAT OUR CUSTOMERS ARE SAYING';
111
+ const effectiveSubheading = subheading ?? siteData?.content?.[basePath]?.subheading ?? 'Reflections and feedback from verified customers and dedicated regulars.';
105
112
  const hasCustomPy = /(^|\s)(p|py|pt)-/.test(className);
106
113
  const defaultPadding = hasCustomPy ? '' : 'py-6 sm:py-8';
107
114
  return ((0, jsx_runtime_1.jsx)("section", { "data-preview-page-key": basePath, "data-design-section": basePath, className: `editable-testimonial-section w-full ${defaultPadding} px-3 sm:px-6 lg:px-8 ${className}`.trim(), style: style, ...props, children: (0, jsx_runtime_1.jsxs)("div", { className: "w-full mx-auto", children: [(0, jsx_runtime_1.jsxs)("div", { className: "text-center max-w-3xl mx-auto space-y-3 mb-6 sm:mb-8 px-2", children: [badge && ((0, jsx_runtime_1.jsx)("div", { className: "inline-flex items-center gap-2 px-4 py-1.5 rounded-full bg-slate-100 text-slate-800 border border-slate-200 dark:bg-slate-800/80 dark:text-lime-400 dark:border-lime-400/20 text-xs uppercase tracking-widest font-black shadow-sm", children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `testimonials.badge`, children: badge }) })), (0, jsx_runtime_1.jsx)("h2", { "data-preview-field-path": `testimonials.heading`, className: "font-heading text-2xl xs:text-3xl sm:text-4xl lg:text-5xl font-black text-slate-900 dark:text-white tracking-tight", children: heading }), (0, jsx_runtime_1.jsx)("p", { "data-preview-field-path": `testimonials.subheading`, className: "text-xs sm:text-base text-slate-600 dark:text-slate-400 leading-relaxed max-w-2xl mx-auto", children: subheading })] }), (0, jsx_runtime_1.jsx)("div", { "data-preview-list-path": `testimonials.testimonials`, className: "grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-5 sm:gap-7 [grid-template-columns:repeat(auto-fit,minmax(min(100%,290px),1fr))] w-full", children: items.map((item, index) => ((0, jsx_runtime_1.jsx)(TestimonialCard, { item: item, index: index, maxStars: maxStars, cardClassName: cardClassName }, item.id || String(index)))) })] }) }));
108
115
  }
116
+ // Canonical alias
117
+ exports.TestimonialSection = EditableTestimonialSection;
@@ -126,3 +126,12 @@ export declare function useSiteCatalog(): {
126
126
  siteInstance: SiteInstanceData | null;
127
127
  api: SiteDataApiConfig | null;
128
128
  };
129
+ /**
130
+ * Hook to retrieve shop profile cleanly from SiteData, supporting both
131
+ * top-level siteData.shop and siteData.merchant.
132
+ */
133
+ export declare function useShop(fallback?: GenericRecord): GenericRecord;
134
+ /**
135
+ * Hook to retrieve customer reviews / testimonials cleanly from SiteData.
136
+ */
137
+ export declare function useReviews(fallback?: GenericRecord[]): GenericRecord[];
@@ -22,6 +22,8 @@ exports.useProducts = useProducts;
22
22
  exports.useServices = useServices;
23
23
  exports.useSiteApi = useSiteApi;
24
24
  exports.useSiteCatalog = useSiteCatalog;
25
+ exports.useShop = useShop;
26
+ exports.useReviews = useReviews;
25
27
  const jsx_runtime_1 = require("react/jsx-runtime");
26
28
  const react_1 = require("react");
27
29
  const core_1 = require("@deneb-ui/core");
@@ -256,31 +258,114 @@ function SiteDataProvider({ children, initialSiteData, fallbackSiteData, liveCat
256
258
  setSiteData((current) => {
257
259
  const currentContent = isRecord(current.content) ? current.content : {};
258
260
  const currentHome = isRecord(currentContent.home) ? currentContent.home : null;
261
+ const currentCommon = isRecord(currentContent.common) ? currentContent.common : {};
262
+ const currentContact = isRecord(currentContent.contact) ? currentContent.contact : {};
259
263
  const nextProducts = Array.isArray(live.products)
260
264
  ? live.products
261
265
  : currentContent.products;
262
266
  const nextServices = Array.isArray(live.services)
263
267
  ? live.services
264
268
  : currentContent.services;
269
+ const nextReviews = Array.isArray(live.reviews)
270
+ ? live.reviews
271
+ : null;
272
+ // Shop / Merchant profile live synchronization
273
+ let nextShop = isRecord(current.shop) ? { ...current.shop } : {};
274
+ let nextMerchant = isRecord(current.merchant) ? { ...current.merchant } : {};
275
+ let nextCommon = { ...currentCommon };
276
+ let nextContact = { ...currentContact };
277
+ let nextHome = currentHome ? { ...currentHome } : {};
278
+ if (isRecord(live.shop)) {
279
+ nextShop = mergeSiteData(nextShop, live.shop);
280
+ nextMerchant = mergeSiteData(nextMerchant, live.shop);
281
+ const contact = isRecord(live.shop.contact) ? live.shop.contact : null;
282
+ const address = isRecord(live.shop.address) ? live.shop.address : null;
283
+ if (contact) {
284
+ if (typeof contact.phone === 'string' && contact.phone.trim()) {
285
+ nextContact.phone = contact.phone;
286
+ nextContact.contactNumber = contact.phone;
287
+ nextCommon.contactNumber = contact.phone;
288
+ }
289
+ if (typeof contact.whatsapp === 'string' && contact.whatsapp.trim()) {
290
+ nextContact.whatsapp = contact.whatsapp;
291
+ nextCommon.whatsapp = contact.whatsapp;
292
+ const cleanWa = contact.whatsapp.replace(/\D/g, '');
293
+ if (cleanWa) {
294
+ nextContact.whatsappNumber = cleanWa;
295
+ nextCommon.whatsappNumber = cleanWa;
296
+ // Dynamically update any hardcoded or static wa.me URLs across home
297
+ const waRegex = /(https?:\/\/(?:wa\.me|api\.whatsapp\.com\/send\?phone=))\d+/gi;
298
+ for (const key of ['whatsappCtaUrl', 'whatsappOrderUrl', 'whatsappUrl']) {
299
+ if (typeof nextHome[key] === 'string' && waRegex.test(nextHome[key])) {
300
+ nextHome[key] = nextHome[key].replace(waRegex, `$1${cleanWa}`);
301
+ }
302
+ }
303
+ }
304
+ }
305
+ if (typeof contact.email === 'string' && contact.email.trim()) {
306
+ nextContact.email = contact.email;
307
+ nextCommon.email = contact.email;
308
+ }
309
+ }
310
+ if (address) {
311
+ const street = address.street || address.line1;
312
+ if (typeof street === 'string' && street.trim()) {
313
+ nextContact.address = street;
314
+ nextCommon.address = street;
315
+ }
316
+ if (typeof address.mapLocation === 'string' && address.mapLocation.trim()) {
317
+ nextContact.googleMapLink = address.mapLocation;
318
+ nextContact.mapLocation = address.mapLocation;
319
+ nextContact.mapUrl = address.mapLocation;
320
+ }
321
+ }
322
+ if (live.shop.openingHours) {
323
+ nextContact.hours = live.shop.openingHours;
324
+ nextContact.openingHours = live.shop.openingHours;
325
+ nextCommon.openingHours = live.shop.openingHours;
326
+ nextHome.businessHours = live.shop.openingHours;
327
+ }
328
+ if (typeof live.shop.businessName === 'string' && live.shop.businessName.trim()) {
329
+ nextCommon.websiteTitle = live.shop.businessName;
330
+ }
331
+ if (typeof live.shop.logoUrl === 'string' && live.shop.logoUrl.trim()) {
332
+ nextCommon.logoUrl = live.shop.logoUrl;
333
+ }
334
+ }
335
+ // Reviews / Testimonials live synchronization
336
+ if (nextReviews) {
337
+ nextHome.reviews = nextReviews;
338
+ nextHome.testimonials = nextReviews;
339
+ nextHome.feedbacks = nextReviews;
340
+ }
265
341
  return {
266
342
  ...current,
343
+ shop: nextShop,
344
+ merchant: nextMerchant,
345
+ reviews: nextReviews ?? current.reviews,
267
346
  content: {
268
347
  ...currentContent,
348
+ common: nextCommon,
349
+ contact: nextContact,
269
350
  ...(nextProducts !== undefined ? { products: nextProducts } : {}),
270
351
  ...(nextServices !== undefined ? { services: nextServices } : {}),
271
- ...(currentHome
352
+ ...(nextReviews !== null ? { reviews: nextReviews, testimonials: nextReviews, feedbacks: nextReviews } : {}),
353
+ ...(currentHome || Object.keys(nextHome).length > 0
272
354
  ? {
273
355
  home: {
274
- ...currentHome,
275
- ...(nextProducts !== undefined && 'products' in currentHome
356
+ ...nextHome,
357
+ ...(nextProducts !== undefined && 'products' in (currentHome || {})
276
358
  ? { products: nextProducts }
277
359
  : {}),
278
- ...(nextServices !== undefined && 'services' in currentHome
360
+ ...(nextServices !== undefined && 'services' in (currentHome || {})
279
361
  ? { services: nextServices }
280
362
  : {}),
281
- ...(nextProducts !== undefined && 'featuredProducts' in currentHome
363
+ ...(nextProducts !== undefined && 'featuredProducts' in (currentHome || {})
282
364
  ? { featuredProducts: nextProducts }
283
365
  : {}),
366
+ ...(nextServices !== undefined && 'featuredServices' in (currentHome || {})
367
+ ? { featuredServices: nextServices }
368
+ : {}),
284
369
  },
285
370
  }
286
371
  : {}),
@@ -613,3 +698,49 @@ function useSiteCatalog() {
613
698
  api: siteData?.api ?? null,
614
699
  };
615
700
  }
701
+ /**
702
+ * Hook to retrieve shop profile cleanly from SiteData, supporting both
703
+ * top-level siteData.shop and siteData.merchant.
704
+ */
705
+ function useShop(fallback = {}) {
706
+ const siteData = useSiteData();
707
+ if (isRecord(siteData?.shop))
708
+ return siteData.shop;
709
+ if (isRecord(siteData?.merchant))
710
+ return siteData.merchant;
711
+ return fallback;
712
+ }
713
+ /**
714
+ * Hook to retrieve customer reviews / testimonials cleanly from SiteData.
715
+ */
716
+ function useReviews(fallback = []) {
717
+ const siteData = useSiteData();
718
+ const content = isRecord(siteData?.content) ? siteData.content : null;
719
+ if (content) {
720
+ if (Array.isArray(content.reviews) && content.reviews.length > 0) {
721
+ return content.reviews;
722
+ }
723
+ if (Array.isArray(content.testimonials) && content.testimonials.length > 0) {
724
+ return content.testimonials;
725
+ }
726
+ if (Array.isArray(content.customerReviews) && content.customerReviews.length > 0) {
727
+ return content.customerReviews;
728
+ }
729
+ const home = isRecord(content.home) ? content.home : null;
730
+ if (home) {
731
+ if (Array.isArray(home.reviews) && home.reviews.length > 0) {
732
+ return home.reviews;
733
+ }
734
+ if (Array.isArray(home.testimonials) && home.testimonials.length > 0) {
735
+ return home.testimonials;
736
+ }
737
+ if (Array.isArray(home.feedbacks) && home.feedbacks.length > 0) {
738
+ return home.feedbacks;
739
+ }
740
+ }
741
+ }
742
+ if (Array.isArray(siteData?.reviews) && siteData.reviews.length > 0) {
743
+ return siteData.reviews;
744
+ }
745
+ return fallback;
746
+ }
@@ -16,5 +16,6 @@ export interface BusinessHoursProps {
16
16
  }
17
17
  /**
18
18
  * BusinessHours component displaying weekly operating schedule with live Open/Closed status.
19
+ * Automatically self-hydrates from live shop registration and site data when props are omitted.
19
20
  */
20
- export declare function BusinessHours({ hours, title, fieldPath, showStatusBadge, compact, className, style, }: BusinessHoursProps): React.JSX.Element | null;
21
+ export declare function BusinessHours({ hours, title, fieldPath, showStatusBadge, compact, className, style, }: BusinessHoursProps): React.JSX.Element;
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.BusinessHours = BusinessHours;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
6
  const react_1 = require("react");
7
+ const SiteDataProvider_1 = require("../SiteDataProvider");
7
8
  const DAYS_OF_WEEK = [
8
9
  'monday',
9
10
  'tuesday',
@@ -13,11 +14,19 @@ const DAYS_OF_WEEK = [
13
14
  'saturday',
14
15
  'sunday',
15
16
  ];
17
+ const DEFAULT_HOURS = {
18
+ monday: { open: '09:00', close: '18:00', closed: false },
19
+ tuesday: { open: '09:00', close: '18:00', closed: false },
20
+ wednesday: { open: '09:00', close: '18:00', closed: false },
21
+ thursday: { open: '09:00', close: '18:00', closed: false },
22
+ friday: { open: '09:00', close: '18:00', closed: false },
23
+ saturday: { open: '10:00', close: '16:00', closed: false },
24
+ sunday: { closed: true },
25
+ };
16
26
  function formatTime(timeStr) {
17
27
  if (!timeStr)
18
28
  return '';
19
29
  const clean = timeStr.trim();
20
- // If already contains AM/PM
21
30
  if (/am|pm/i.test(clean))
22
31
  return clean;
23
32
  const [hourStr, minStr = '00'] = clean.split(':');
@@ -30,16 +39,28 @@ function formatTime(timeStr) {
30
39
  }
31
40
  /**
32
41
  * BusinessHours component displaying weekly operating schedule with live Open/Closed status.
42
+ * Automatically self-hydrates from live shop registration and site data when props are omitted.
33
43
  */
34
44
  function BusinessHours({ hours, title = 'Business Hours', fieldPath = 'common.business.hours', showStatusBadge = true, compact = false, className = '', style, }) {
35
- // Determine current day and status
45
+ const liveShop = (0, SiteDataProvider_1.useShop)();
46
+ const siteData = (0, SiteDataProvider_1.useSiteData)();
47
+ const contact = siteData?.content?.contact || siteData?.content?.common?.contact || {};
48
+ const common = siteData?.content?.common || {};
49
+ const merchant = siteData?.merchant || {};
50
+ const effectiveHours = hours ||
51
+ liveShop?.openingHours ||
52
+ contact.hours ||
53
+ contact.openingHours ||
54
+ common.openingHours ||
55
+ merchant.openingHours ||
56
+ DEFAULT_HOURS;
36
57
  const currentStatus = (0, react_1.useMemo)(() => {
37
- if (!hours)
58
+ if (!effectiveHours)
38
59
  return null;
39
60
  const now = new Date();
40
- const dayIndex = (now.getDay() + 6) % 7; // Convert 0(Sun)-6(Sat) to 0(Mon)-6(Sun)
61
+ const dayIndex = (now.getDay() + 6) % 7;
41
62
  const todayName = DAYS_OF_WEEK[dayIndex];
42
- const todaySched = hours[todayName];
63
+ const todaySched = effectiveHours[todayName];
43
64
  if (!todaySched)
44
65
  return { todayName, isOpen: false };
45
66
  if (typeof todaySched === 'string') {
@@ -57,9 +78,7 @@ function BusinessHours({ hours, title = 'Business Hours', fieldPath = 'common.bu
57
78
  const closeMinutes = parseInt(closeH, 10) * 60 + parseInt(closeM, 10);
58
79
  const isOpen = currentMinutes >= openMinutes && currentMinutes < closeMinutes;
59
80
  return { todayName, isOpen };
60
- }, [hours]);
61
- if (!hours)
62
- return null;
81
+ }, [effectiveHours]);
63
82
  const containerStyles = {
64
83
  padding: compact ? '1rem' : '1.5rem',
65
84
  borderRadius: '0.75rem',
@@ -83,7 +102,7 @@ function BusinessHours({ hours, title = 'Business Hours', fieldPath = 'common.bu
83
102
  borderRadius: '50%',
84
103
  backgroundColor: currentStatus.isOpen ? '#10b981' : '#94a3b8',
85
104
  } }), currentStatus.isOpen ? 'Open Now' : 'Closed'] }))] }), (0, jsx_runtime_1.jsx)("div", { style: { display: 'flex', flexDirection: 'column', gap: compact ? '0.35rem' : '0.5rem' }, children: DAYS_OF_WEEK.map((day) => {
86
- const sched = hours[day];
105
+ const sched = effectiveHours[day];
87
106
  const isToday = currentStatus?.todayName === day;
88
107
  const dayLabel = day.charAt(0).toUpperCase() + day.slice(1);
89
108
  let scheduleText = 'Closed';
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { ContactButtonProps } from './ContactButton';
3
3
  export interface EmailButtonProps extends Omit<ContactButtonProps, 'type'> {
4
- emailAddress?: string | null;
4
+ email?: string | null;
5
5
  }
6
- export declare function EmailButton({ emailAddress, value, label, fieldPath, variant, subject, ...rest }: EmailButtonProps): React.JSX.Element | null;
6
+ export declare function EmailButton({ email, value, label, fieldPath, variant, ...rest }: EmailButtonProps): React.JSX.Element | null;
@@ -4,9 +4,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.EmailButton = EmailButton;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
6
  const ContactButton_1 = require("./ContactButton");
7
- function EmailButton({ emailAddress, value, label = 'Email Us', fieldPath = 'common.business.email', variant = 'secondary', subject, ...rest }) {
8
- const email = emailAddress || value;
9
- if (!email && !fieldPath)
7
+ const SiteDataProvider_1 = require("../SiteDataProvider");
8
+ function EmailButton({ email, value, label = 'Email Us', fieldPath = 'common.business.email', variant = 'outline', ...rest }) {
9
+ const liveShop = (0, SiteDataProvider_1.useShop)();
10
+ const siteData = (0, SiteDataProvider_1.useSiteData)();
11
+ const contact = siteData?.content?.contact || siteData?.content?.common?.contact || {};
12
+ const common = siteData?.content?.common || {};
13
+ const merchant = siteData?.merchant || {};
14
+ const effectiveEmail = email ||
15
+ value ||
16
+ liveShop?.contact?.email ||
17
+ contact.email ||
18
+ common.email ||
19
+ merchant.email ||
20
+ '';
21
+ if (!effectiveEmail && !fieldPath)
10
22
  return null;
11
- return ((0, jsx_runtime_1.jsx)(ContactButton_1.ContactButton, { type: "email", value: email, label: label, fieldPath: fieldPath, variant: variant, subject: subject, ...rest }));
23
+ return ((0, jsx_runtime_1.jsx)(ContactButton_1.ContactButton, { type: "email", value: effectiveEmail, label: label, fieldPath: fieldPath, variant: variant, ...rest }));
12
24
  }
@@ -4,9 +4,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.PhoneButton = PhoneButton;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
6
  const ContactButton_1 = require("./ContactButton");
7
+ const SiteDataProvider_1 = require("../SiteDataProvider");
7
8
  function PhoneButton({ phoneNumber, value, label = 'Call Us', fieldPath = 'common.business.phone', variant = 'primary', ...rest }) {
8
- const number = phoneNumber ?? value;
9
- if (!number && !fieldPath)
9
+ const liveShop = (0, SiteDataProvider_1.useShop)();
10
+ const siteData = (0, SiteDataProvider_1.useSiteData)();
11
+ const contact = siteData?.content?.contact || siteData?.content?.common?.contact || {};
12
+ const common = siteData?.content?.common || {};
13
+ const merchant = siteData?.merchant || {};
14
+ const effectiveNumber = phoneNumber ||
15
+ value ||
16
+ liveShop?.contact?.phone ||
17
+ contact.phone ||
18
+ common.phone ||
19
+ merchant.phone ||
20
+ '';
21
+ if (!effectiveNumber && !fieldPath)
10
22
  return null;
11
- return ((0, jsx_runtime_1.jsx)(ContactButton_1.ContactButton, { type: "phone", value: number, label: label, fieldPath: fieldPath, variant: variant, ...rest }));
23
+ return ((0, jsx_runtime_1.jsx)(ContactButton_1.ContactButton, { type: "phone", value: effectiveNumber, label: label, fieldPath: fieldPath, variant: variant, ...rest }));
12
24
  }
@@ -3,4 +3,8 @@ import { ContactButtonProps } from './ContactButton';
3
3
  export interface WhatsAppButtonProps extends Omit<ContactButtonProps, 'type'> {
4
4
  phoneNumber?: string | null;
5
5
  }
6
+ /**
7
+ * WhatsAppButton automatically connects customers directly to the shop's WhatsApp chat.
8
+ * Self-hydrates from live shop registration, contact config, and merchant profile if phoneNumber is omitted.
9
+ */
6
10
  export declare function WhatsAppButton({ phoneNumber, value, label, fieldPath, variant, message, ...rest }: WhatsAppButtonProps): React.JSX.Element | null;
@@ -4,10 +4,31 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.WhatsAppButton = WhatsAppButton;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
6
  const ContactButton_1 = require("./ContactButton");
7
+ const SiteDataProvider_1 = require("../SiteDataProvider");
8
+ /**
9
+ * WhatsAppButton automatically connects customers directly to the shop's WhatsApp chat.
10
+ * Self-hydrates from live shop registration, contact config, and merchant profile if phoneNumber is omitted.
11
+ */
7
12
  function WhatsAppButton({ phoneNumber, value, label = 'Chat on WhatsApp', fieldPath = 'common.business.whatsapp', variant = 'whatsapp', message, ...rest }) {
8
- const number = phoneNumber || value;
9
- // Don't render if no number and no fieldPath configured
10
- if (!number && !fieldPath)
13
+ const liveShop = (0, SiteDataProvider_1.useShop)();
14
+ const siteData = (0, SiteDataProvider_1.useSiteData)();
15
+ const contact = siteData?.content?.contact || siteData?.content?.common?.contact || {};
16
+ const common = siteData?.content?.common || {};
17
+ const home = siteData?.content?.home || {};
18
+ const merchant = siteData?.merchant || {};
19
+ const effectiveNumber = phoneNumber ||
20
+ value ||
21
+ liveShop?.contact?.whatsapp ||
22
+ liveShop?.contact?.phone ||
23
+ contact.whatsapp ||
24
+ contact.phone ||
25
+ home.whatsappNumber ||
26
+ home.whatsappCtaUrl ||
27
+ common.whatsapp ||
28
+ merchant.whatsapp ||
29
+ merchant.phone ||
30
+ '';
31
+ if (!effectiveNumber && !fieldPath)
11
32
  return null;
12
- return ((0, jsx_runtime_1.jsx)(ContactButton_1.ContactButton, { type: "whatsapp", value: number, label: label, fieldPath: fieldPath, variant: variant, message: message, ...rest }));
33
+ return ((0, jsx_runtime_1.jsx)(ContactButton_1.ContactButton, { type: "whatsapp", value: effectiveNumber, label: label, fieldPath: fieldPath, variant: variant, message: message, ...rest }));
13
34
  }
@@ -21,5 +21,6 @@ export interface LocationCardProps {
21
21
  }
22
22
  /**
23
23
  * Premium storefront LocationCard displaying address, pin icon, and Google Maps directions button.
24
+ * Automatically self-hydrates from live shop registration and site data when props are omitted.
24
25
  */
25
26
  export declare function LocationCard({ name, title, titleFieldPath, address, city, state, country, postalCode, mapUrl, addressUrl, url, fieldPath, nameFieldPath, addressFieldPath, mapUrlFieldPath, directionsLabel, className, style, }: LocationCardProps): React.JSX.Element | null;
@@ -6,14 +6,26 @@ const jsx_runtime_1 = require("react/jsx-runtime");
6
6
  const Address_1 = require("./Address");
7
7
  const MapLink_1 = require("./MapLink");
8
8
  const EditableText_1 = require("../EditableText");
9
+ const SiteDataProvider_1 = require("../SiteDataProvider");
9
10
  /**
10
11
  * Premium storefront LocationCard displaying address, pin icon, and Google Maps directions button.
12
+ * Automatically self-hydrates from live shop registration and site data when props are omitted.
11
13
  */
12
14
  function LocationCard({ name, title = 'Our Location', titleFieldPath, address, city, state, country, postalCode, mapUrl, addressUrl, url, fieldPath, nameFieldPath, addressFieldPath = 'common.business.location.address', mapUrlFieldPath = 'common.business.location.addressUrl', directionsLabel = 'Get Directions →', className = '', style, }) {
13
- const explicitUrl = (addressUrl || mapUrl || url || '').trim();
14
- const cardTitle = name || title || 'Our Location';
15
+ const liveShop = (0, SiteDataProvider_1.useShop)();
16
+ const siteData = (0, SiteDataProvider_1.useSiteData)();
17
+ const contact = siteData?.content?.contact || siteData?.content?.common?.contact || {};
18
+ const common = siteData?.content?.common || {};
19
+ const merchant = siteData?.merchant || {};
20
+ const effectiveAddress = address ?? liveShop?.address ?? contact.address ?? contact.location ?? merchant.address ?? '';
21
+ const effectiveCity = city ?? liveShop?.city ?? contact.city ?? merchant.city ?? '';
22
+ const effectiveState = state ?? '';
23
+ const effectiveCountry = country ?? contact.country ?? merchant.country ?? '';
24
+ const effectivePostalCode = postalCode ?? contact.postalCode ?? '';
25
+ const explicitUrl = (addressUrl || mapUrl || url || liveShop?.mapLocation || contact.googleMapLink || contact.mapLocation || merchant.mapLocation || merchant.googleMapLink || '').trim();
26
+ const effectiveName = name ?? liveShop?.name ?? common.websiteTitle ?? merchant.businessName ?? title ?? 'Our Location';
15
27
  const resolvedTitleFieldPath = nameFieldPath || titleFieldPath || (fieldPath ? `${fieldPath}.name` : 'contact.locationTitle');
16
- if (!address && !city && !country && !explicitUrl && !name) {
28
+ if (!effectiveAddress && !effectiveCity && !effectiveCountry && !explicitUrl && !effectiveName) {
17
29
  return null;
18
30
  }
19
31
  const cardStyles = {
@@ -40,5 +52,5 @@ function LocationCard({ name, title = 'Our Location', titleFieldPath, address, c
40
52
  alignItems: 'center',
41
53
  justifyContent: 'center',
42
54
  };
43
- return ((0, jsx_runtime_1.jsxs)("div", { className: `deneb-location-card ${className}`.trim(), style: cardStyles, children: [(0, jsx_runtime_1.jsx)("div", { style: iconCircleStyles, children: (0, jsx_runtime_1.jsxs)("svg", { "data-preview-static": "location-card-icon", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [(0, jsx_runtime_1.jsx)("path", { d: "M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" }), (0, jsx_runtime_1.jsx)("circle", { cx: "12", cy: "10", r: "3" })] }) }), (0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "h3", id: titleFieldPath || (fieldPath ? `${fieldPath}.title` : 'contact.locationTitle'), defaultValue: cardTitle, style: { margin: 0, fontSize: '1.25rem', fontWeight: 600, color: 'var(--color-text, #0f172a)' } }), (0, jsx_runtime_1.jsx)(Address_1.Address, { address: address, city: city, country: country, postalCode: postalCode, fieldPath: fieldPath, addressFieldPath: addressFieldPath }), (0, jsx_runtime_1.jsx)("div", { style: { marginTop: '0.5rem', width: '100%' }, children: (0, jsx_runtime_1.jsx)(MapLink_1.MapLink, { name: name, mapUrl: explicitUrl, addressUrl: explicitUrl, url: explicitUrl, address: address, city: city, state: state, country: country, postalCode: postalCode, label: directionsLabel, urlFieldPath: mapUrlFieldPath, variant: "primary", size: "md", style: { width: '100%' } }) })] }));
55
+ return ((0, jsx_runtime_1.jsxs)("div", { className: `deneb-location-card ${className}`.trim(), style: cardStyles, children: [(0, jsx_runtime_1.jsx)("div", { style: iconCircleStyles, children: (0, jsx_runtime_1.jsxs)("svg", { "data-preview-static": "location-card-icon", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [(0, jsx_runtime_1.jsx)("path", { d: "M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" }), (0, jsx_runtime_1.jsx)("circle", { cx: "12", cy: "10", r: "3" })] }) }), (0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "h3", id: resolvedTitleFieldPath, defaultValue: effectiveName, style: { margin: 0, fontSize: '1.25rem', fontWeight: 600, color: 'var(--color-text, #0f172a)' } }), (0, jsx_runtime_1.jsx)(Address_1.Address, { address: effectiveAddress, city: effectiveCity, country: effectiveCountry, postalCode: effectivePostalCode, fieldPath: fieldPath, addressFieldPath: addressFieldPath }), (0, jsx_runtime_1.jsx)("div", { style: { marginTop: '0.5rem', width: '100%' }, children: (0, jsx_runtime_1.jsx)(MapLink_1.MapLink, { name: effectiveName, mapUrl: explicitUrl, addressUrl: explicitUrl, url: explicitUrl, address: effectiveAddress, city: effectiveCity, state: effectiveState, country: effectiveCountry, postalCode: effectivePostalCode, label: directionsLabel, urlFieldPath: mapUrlFieldPath, variant: "primary", size: "md", style: { width: '100%' } }) })] }));
44
56
  }
@@ -14,5 +14,6 @@ export interface LocationLinkProps {
14
14
  }
15
15
  /**
16
16
  * Combines physical address with an interactive "Get Directions" action.
17
+ * Automatically self-hydrates from live shop registration and site data when props are omitted.
17
18
  */
18
19
  export declare function LocationLink({ address, city, country, mapUrl, fieldPath, addressFieldPath, mapUrlFieldPath, directionsLabel, showAddress, className, style, }: LocationLinkProps): React.JSX.Element | null;
@@ -5,11 +5,21 @@ exports.LocationLink = LocationLink;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
6
  const Address_1 = require("./Address");
7
7
  const MapLink_1 = require("./MapLink");
8
+ const SiteDataProvider_1 = require("../SiteDataProvider");
8
9
  /**
9
10
  * Combines physical address with an interactive "Get Directions" action.
11
+ * Automatically self-hydrates from live shop registration and site data when props are omitted.
10
12
  */
11
13
  function LocationLink({ address, city, country, mapUrl, fieldPath, addressFieldPath = 'common.business.location.address', mapUrlFieldPath = 'common.business.location.addressUrl', directionsLabel = 'Get Directions', showAddress = true, className = '', style, }) {
12
- if (!address && !city && !country && !mapUrl) {
14
+ const liveShop = (0, SiteDataProvider_1.useShop)();
15
+ const siteData = (0, SiteDataProvider_1.useSiteData)();
16
+ const contact = siteData?.content?.contact || siteData?.content?.common?.contact || {};
17
+ const merchant = siteData?.merchant || {};
18
+ const effectiveAddress = address ?? liveShop?.address ?? contact.address ?? contact.location ?? merchant.address ?? '';
19
+ const effectiveCity = city ?? liveShop?.city ?? contact.city ?? merchant.city ?? '';
20
+ const effectiveCountry = country ?? contact.country ?? merchant.country ?? '';
21
+ const effectiveMapUrl = (mapUrl || liveShop?.mapLocation || contact.googleMapLink || contact.mapLocation || merchant.mapLocation || '').trim();
22
+ if (!effectiveAddress && !effectiveCity && !effectiveCountry && !effectiveMapUrl) {
13
23
  return null;
14
24
  }
15
25
  const containerStyles = {
@@ -19,5 +29,5 @@ function LocationLink({ address, city, country, mapUrl, fieldPath, addressFieldP
19
29
  alignItems: 'flex-start',
20
30
  ...style,
21
31
  };
22
- return ((0, jsx_runtime_1.jsxs)("div", { className: `deneb-location-link ${className}`.trim(), style: containerStyles, children: [showAddress && ((0, jsx_runtime_1.jsx)(Address_1.Address, { address: address, city: city, country: country, fieldPath: fieldPath, addressFieldPath: addressFieldPath })), (0, jsx_runtime_1.jsx)(MapLink_1.MapLink, { mapUrl: mapUrl, address: address, city: city, country: country, label: directionsLabel, fieldPath: mapUrlFieldPath, variant: "outline", size: "sm" })] }));
32
+ return ((0, jsx_runtime_1.jsxs)("div", { className: `deneb-location-link ${className}`.trim(), style: containerStyles, children: [showAddress && ((0, jsx_runtime_1.jsx)(Address_1.Address, { address: effectiveAddress, city: effectiveCity, country: effectiveCountry, fieldPath: fieldPath, addressFieldPath: addressFieldPath })), (0, jsx_runtime_1.jsx)(MapLink_1.MapLink, { mapUrl: effectiveMapUrl, address: effectiveAddress, city: effectiveCity, country: effectiveCountry, label: directionsLabel, fieldPath: mapUrlFieldPath, variant: "outline", size: "sm" })] }));
23
33
  }
@@ -14,5 +14,6 @@ export interface MapEmbedProps {
14
14
  /**
15
15
  * Safe, responsive Google Maps Embed component with automatic fallback to MapLink
16
16
  * when an embed URL is not yet configured by the merchant.
17
+ * Automatically self-hydrates from live shop registration and site data when props are omitted.
17
18
  */
18
19
  export declare function MapEmbed({ embedUrl, mapUrl, address, city, country, title, fieldPath, height, className, style, }: MapEmbedProps): React.JSX.Element;
@@ -4,11 +4,22 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.MapEmbed = MapEmbed;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
6
  const MapLink_1 = require("./MapLink");
7
+ const SiteDataProvider_1 = require("../SiteDataProvider");
7
8
  /**
8
9
  * Safe, responsive Google Maps Embed component with automatic fallback to MapLink
9
10
  * when an embed URL is not yet configured by the merchant.
11
+ * Automatically self-hydrates from live shop registration and site data when props are omitted.
10
12
  */
11
13
  function MapEmbed({ embedUrl, mapUrl, address, city, country, title = 'Business Location Map', fieldPath = 'common.business.location.mapEmbedUrl', height = 360, className = '', style, }) {
14
+ const liveShop = (0, SiteDataProvider_1.useShop)();
15
+ const siteData = (0, SiteDataProvider_1.useSiteData)();
16
+ const contact = siteData?.content?.contact || siteData?.content?.common?.contact || {};
17
+ const merchant = siteData?.merchant || {};
18
+ const effectiveEmbedUrl = embedUrl ?? contact.mapEmbedUrl ?? merchant.mapEmbedUrl ?? '';
19
+ const effectiveMapUrl = (mapUrl || liveShop?.mapLocation || contact.googleMapLink || contact.mapLocation || merchant.mapLocation || '').trim();
20
+ const effectiveAddress = address ?? liveShop?.address ?? contact.address ?? contact.location ?? merchant.address ?? '';
21
+ const effectiveCity = city ?? liveShop?.city ?? contact.city ?? merchant.city ?? '';
22
+ const effectiveCountry = country ?? contact.country ?? merchant.country ?? '';
12
23
  const containerStyles = {
13
24
  width: '100%',
14
25
  height: typeof height === 'number' ? `${height}px` : height,
@@ -22,9 +33,9 @@ function MapEmbed({ embedUrl, mapUrl, address, city, country, title = 'Business
22
33
  justifyContent: 'center',
23
34
  ...style,
24
35
  };
25
- if (embedUrl && (embedUrl.startsWith('http://') || embedUrl.startsWith('https://'))) {
26
- return ((0, jsx_runtime_1.jsx)("div", { className: `deneb-map-embed ${className}`.trim(), style: containerStyles, children: (0, jsx_runtime_1.jsx)("iframe", { "data-preview-field-path": fieldPath, src: embedUrl, title: title, width: "100%", height: "100%", style: { border: 0 }, loading: "lazy", allowFullScreen: true, referrerPolicy: "no-referrer-when-downgrade" }) }));
36
+ if (effectiveEmbedUrl && (effectiveEmbedUrl.startsWith('http://') || effectiveEmbedUrl.startsWith('https://'))) {
37
+ return ((0, jsx_runtime_1.jsx)("div", { className: `deneb-map-embed ${className}`.trim(), style: containerStyles, children: (0, jsx_runtime_1.jsx)("iframe", { "data-preview-field-path": fieldPath, src: effectiveEmbedUrl, title: title, width: "100%", height: "100%", style: { border: 0 }, loading: "lazy", allowFullScreen: true, referrerPolicy: "no-referrer-when-downgrade" }) }));
27
38
  }
28
39
  // Fallback when no direct iframe URL is provided
29
- return ((0, jsx_runtime_1.jsx)("div", { className: `deneb-map-embed deneb-map-fallback ${className}`.trim(), style: containerStyles, children: (0, jsx_runtime_1.jsxs)("div", { style: { textAlign: 'center', padding: '1.5rem' }, children: [(0, jsx_runtime_1.jsx)("div", { style: { marginBottom: '0.75rem', opacity: 0.6 }, children: (0, jsx_runtime_1.jsxs)("svg", { "data-preview-static": "map-pin-icon", width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [(0, jsx_runtime_1.jsx)("path", { d: "M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" }), (0, jsx_runtime_1.jsx)("circle", { cx: "12", cy: "10", r: "3" })] }) }), (0, jsx_runtime_1.jsx)("p", { "data-preview-static": "map-placeholder-title", style: { margin: '0 0 0.75rem 0', fontWeight: 500, color: 'var(--color-text, #0f172a)' }, children: address ? `${address}${city ? `, ${city}` : ''}` : 'Location Map' }), (0, jsx_runtime_1.jsx)(MapLink_1.MapLink, { mapUrl: mapUrl, address: address, city: city, country: country, label: "Open in Google Maps \u2197", variant: "primary", size: "sm" })] }) }));
40
+ return ((0, jsx_runtime_1.jsx)("div", { className: `deneb-map-embed deneb-map-fallback ${className}`.trim(), style: containerStyles, children: (0, jsx_runtime_1.jsxs)("div", { style: { textAlign: 'center', padding: '1.5rem' }, children: [(0, jsx_runtime_1.jsx)("div", { style: { marginBottom: '0.75rem', opacity: 0.6 }, children: (0, jsx_runtime_1.jsxs)("svg", { "data-preview-static": "map-pin-icon", width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [(0, jsx_runtime_1.jsx)("path", { d: "M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" }), (0, jsx_runtime_1.jsx)("circle", { cx: "12", cy: "10", r: "3" })] }) }), (0, jsx_runtime_1.jsx)("p", { "data-preview-static": "map-placeholder-title", style: { margin: '0 0 0.75rem 0', fontWeight: 500, color: 'var(--color-text, #0f172a)' }, children: effectiveAddress ? `${effectiveAddress}${effectiveCity ? `, ${effectiveCity}` : ''}` : 'Location Map' }), (0, jsx_runtime_1.jsx)(MapLink_1.MapLink, { mapUrl: effectiveMapUrl, address: effectiveAddress, city: effectiveCity, country: effectiveCountry, label: "Open in Google Maps \u2197", variant: "primary", size: "sm" })] }) }));
30
41
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deneb-ui/ui",
3
- "version": "2.0.72",
3
+ "version": "2.0.74",
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.72"
53
+ "@deneb-ui/core": "^2.0.74"
54
54
  },
55
55
  "peerDependencies": {
56
56
  "react": "^18.0.0 || ^19.0.0",