@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.
- package/dist/EditableCustomerReviews.js +39 -5
- package/dist/EditableGoogleFeedback.d.ts +1 -0
- package/dist/EditableGoogleFeedback.js +38 -3
- package/dist/EditableTestimonialSection.d.ts +1 -0
- package/dist/EditableTestimonialSection.js +27 -18
- package/dist/SiteDataProvider.d.ts +9 -0
- package/dist/SiteDataProvider.js +136 -5
- package/dist/business/BusinessHours.d.ts +2 -1
- package/dist/business/BusinessHours.js +28 -9
- package/dist/contact/EmailButton.d.ts +2 -2
- package/dist/contact/EmailButton.js +16 -4
- package/dist/contact/PhoneButton.js +15 -3
- package/dist/contact/WhatsAppButton.d.ts +4 -0
- package/dist/contact/WhatsAppButton.js +25 -4
- package/dist/location/LocationCard.d.ts +1 -0
- package/dist/location/LocationCard.js +16 -4
- package/dist/location/LocationLink.d.ts +1 -0
- package/dist/location/LocationLink.js +12 -2
- package/dist/location/MapEmbed.d.ts +1 -0
- package/dist/location/MapEmbed.js +14 -3
- package/package.json +2 -2
|
@@ -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
|
|
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
|
|
51
|
-
return
|
|
52
|
-
}, [
|
|
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:
|
|
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
|
|
121
|
-
const
|
|
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:
|
|
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
|
|
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
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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[];
|
package/dist/SiteDataProvider.js
CHANGED
|
@@ -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
|
-
...(
|
|
352
|
+
...(nextReviews !== null ? { reviews: nextReviews, testimonials: nextReviews, feedbacks: nextReviews } : {}),
|
|
353
|
+
...(currentHome || Object.keys(nextHome).length > 0
|
|
272
354
|
? {
|
|
273
355
|
home: {
|
|
274
|
-
...
|
|
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
|
|
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
|
-
|
|
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 (!
|
|
58
|
+
if (!effectiveHours)
|
|
38
59
|
return null;
|
|
39
60
|
const now = new Date();
|
|
40
|
-
const dayIndex = (now.getDay() + 6) % 7;
|
|
61
|
+
const dayIndex = (now.getDay() + 6) % 7;
|
|
41
62
|
const todayName = DAYS_OF_WEEK[dayIndex];
|
|
42
|
-
const todaySched =
|
|
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
|
-
}, [
|
|
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 =
|
|
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
|
-
|
|
4
|
+
email?: string | null;
|
|
5
5
|
}
|
|
6
|
-
export declare function EmailButton({
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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:
|
|
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
|
|
9
|
-
|
|
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:
|
|
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
|
|
9
|
-
|
|
10
|
-
|
|
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:
|
|
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
|
|
14
|
-
const
|
|
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 (!
|
|
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:
|
|
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
|
-
|
|
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:
|
|
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 (
|
|
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:
|
|
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:
|
|
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.
|
|
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.
|
|
53
|
+
"@deneb-ui/core": "^2.0.74"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
56
|
"react": "^18.0.0 || ^19.0.0",
|