@deneb-ui/ui 2.0.51 → 2.0.53

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.
@@ -6,6 +6,7 @@ export interface ProductItem {
6
6
  title?: string;
7
7
  brand?: string;
8
8
  price?: string | number;
9
+ compareAtPrice?: string | number;
9
10
  originalPrice?: string | number;
10
11
  currency?: string;
11
12
  description?: string;
@@ -18,6 +19,7 @@ export interface ProductItem {
18
19
  reviewsCount?: number | string;
19
20
  isNew?: boolean;
20
21
  isBestSeller?: boolean;
22
+ isAvailable?: boolean;
21
23
  whatsappNumber?: string;
22
24
  whatsappButtonText?: string;
23
25
  addToCartButtonText?: string;
@@ -26,11 +26,13 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
26
26
  const rawPrice = product?.price;
27
27
  const priceNum = typeof rawPrice === 'number' ? rawPrice : parseFloat(String(rawPrice || '').replace(/[^0-9.]/g, '')) || 0;
28
28
  const formattedPrice = hasPrice ? (typeof rawPrice === 'string' && rawPrice.includes('LKR') ? rawPrice : (0, useCart_1.formatCurrency)(priceNum, currency)) : '';
29
- const originalPrice = product?.originalPrice !== undefined ? String(product.originalPrice) : '';
29
+ const comparePrice = product?.originalPrice ?? product?.compareAtPrice;
30
+ const originalPrice = comparePrice !== undefined && comparePrice !== null ? String(comparePrice) : '';
30
31
  const description = String(product?.description || '');
31
32
  const category = String(product?.category || '');
32
33
  const badge = String(product?.badge || '');
33
34
  const imageUrl = String(product?.imageUrl || product?.image || '');
35
+ const isAvailable = product?.isAvailable !== false;
34
36
  // Resolved phone number for WhatsApp
35
37
  const resolvedPhone = String(product?.whatsappNumber || whatsappNumber || '94770000000');
36
38
  const resolvedWhatsAppText = String(product?.whatsappButtonText || whatsappActionLabel);
@@ -38,6 +40,8 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
38
40
  const isHorizontal = cardVariant === 'horizontal';
39
41
  const handleWhatsAppClick = (e) => {
40
42
  e.stopPropagation();
43
+ if (!isAvailable)
44
+ return;
41
45
  const url = (0, useCart_1.getProductWhatsAppUrl)({ ...product, name, brand, price: formattedPrice }, resolvedPhone, { storeName, currency });
42
46
  if (onWhatsAppClick) {
43
47
  onWhatsAppClick(product, url);
@@ -48,6 +52,8 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
48
52
  };
49
53
  const handleAddToCartClick = (e) => {
50
54
  e.stopPropagation();
55
+ if (!isAvailable)
56
+ return;
51
57
  const itemToAdd = {
52
58
  id: String(product?.id || name.toLowerCase().replace(/\s+/g, '-')),
53
59
  name,
@@ -112,7 +118,18 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
112
118
  overflow: 'hidden',
113
119
  width: isHorizontal ? '40%' : '100%',
114
120
  flexShrink: 0,
115
- }, children: [(0, jsx_runtime_1.jsx)(EditableImage_1.EditableImage, { id: `${itemPath}.imageUrl`, "data-preview-field-path": `${itemPath}.imageUrl`, src: imageUrl, fallbackSrc: imageFallback, alt: name, aspectRatio: isHorizontal ? 'square' : '4/3', fit: "cover", hoverZoom: true, style: { width: '100%', height: '100%', display: 'block' } }), badge && ((0, jsx_runtime_1.jsx)("div", { style: { position: 'absolute', top: '10px', left: '10px', zIndex: 10 }, children: (0, jsx_runtime_1.jsx)(EditableText_2.EditableBadge, { id: `${itemPath}.badge`, "data-preview-field-path": `${itemPath}.badge`, defaultValue: badge, badgeVariant: "primary" }) }))] }), (0, jsx_runtime_1.jsxs)("div", { style: {
121
+ }, children: [(0, jsx_runtime_1.jsx)(EditableImage_1.EditableImage, { id: `${itemPath}.imageUrl`, "data-preview-field-path": `${itemPath}.imageUrl`, src: imageUrl, fallbackSrc: imageFallback, alt: name, aspectRatio: isHorizontal ? 'square' : '4/3', fit: "cover", hoverZoom: true, style: { width: '100%', height: '100%', display: 'block' } }), badge && ((0, jsx_runtime_1.jsx)("div", { style: { position: 'absolute', top: '10px', left: '10px', zIndex: 10 }, children: (0, jsx_runtime_1.jsx)(EditableText_2.EditableBadge, { id: `${itemPath}.badge`, "data-preview-field-path": `${itemPath}.badge`, defaultValue: badge, badgeVariant: "primary" }) })), !isAvailable && ((0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${itemPath}.isAvailable`, style: {
122
+ position: 'absolute',
123
+ right: '10px',
124
+ top: '10px',
125
+ zIndex: 10,
126
+ borderRadius: '999px',
127
+ backgroundColor: '#be123c',
128
+ color: '#ffffff',
129
+ fontSize: '0.75rem',
130
+ fontWeight: 700,
131
+ padding: '4px 10px',
132
+ }, children: "Out of Stock" }))] }), (0, jsx_runtime_1.jsxs)("div", { style: {
116
133
  padding: '1.25rem',
117
134
  display: 'flex',
118
135
  flexDirection: 'column',
@@ -169,7 +186,16 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
169
186
  fontSize: '0.8rem',
170
187
  fontWeight: 500,
171
188
  color: 'var(--muted-text, #64748b)',
172
- } })) : null] })) : null, actionSlot ? ((0, jsx_runtime_1.jsx)("div", { children: actionSlot })) : ((0, jsx_runtime_1.jsxs)("div", { style: {
189
+ } })) : null] })) : null, !isAvailable ? ((0, jsx_runtime_1.jsx)("div", { "data-preview-field-path": `${itemPath}.isAvailable`, role: "status", style: {
190
+ width: '100%',
191
+ borderRadius: '10px',
192
+ backgroundColor: '#e2e8f0',
193
+ color: '#475569',
194
+ padding: '0.65rem 0.75rem',
195
+ textAlign: 'center',
196
+ fontSize: '0.8125rem',
197
+ fontWeight: 700,
198
+ }, children: "Out of Stock" })) : actionSlot ? ((0, jsx_runtime_1.jsx)("div", { children: actionSlot })) : ((0, jsx_runtime_1.jsxs)("div", { style: {
173
199
  display: 'grid',
174
200
  gridTemplateColumns: showWhatsAppButton && showAddToCartButton ? '1fr 1fr' : '1fr',
175
201
  gap: '0.5rem',
@@ -7,6 +7,7 @@ export interface ProductDetailItem {
7
7
  brand?: string;
8
8
  category?: string;
9
9
  price?: string | number;
10
+ compareAtPrice?: string | number;
10
11
  originalPrice?: string | number;
11
12
  description?: string;
12
13
  badge?: string;
@@ -26,6 +27,7 @@ export interface ProductDetailItem {
26
27
  relatedTitle?: string;
27
28
  whatsappNumber?: string;
28
29
  whatsappMessage?: string;
30
+ isAvailable?: boolean;
29
31
  unit?: MeasurementUnit;
30
32
  measurement?: string;
31
33
  optionsLabel?: string;
@@ -40,6 +40,8 @@ function EditableProductDetail({ sectionPath = 'product', product, sizes = ['40'
40
40
  const [activeTab, setActiveTab] = (0, react_1.useState)('specs');
41
41
  const name = String(product.name || product.title || 'Product Title');
42
42
  const price = product.price !== undefined ? String(product.price) : 'LKR 0';
43
+ const originalPrice = product.originalPrice ?? product.compareAtPrice;
44
+ const isAvailable = product.isAvailable !== false;
43
45
  const description = String(product.description || '');
44
46
  const badge = String(product.badge || '');
45
47
  const addToSelectionLabel = String(product.addToSelectionLabel || 'Add to Selection');
@@ -53,9 +55,11 @@ function EditableProductDetail({ sectionPath = 'product', product, sizes = ['40'
53
55
  : '');
54
56
  return ((0, jsx_runtime_1.jsx)("section", { "data-preview-page-key": sectionPath, className: `editable-product-detail max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12 ${className}`.trim(), style: style, ...props, children: (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-1 lg:grid-cols-12 gap-12 lg:gap-16 items-start", children: [(0, jsx_runtime_1.jsxs)("div", { className: "lg:col-span-7 flex flex-col-reverse md:flex-row gap-4", children: [images.length > 1 && ((0, jsx_runtime_1.jsx)("div", { className: "deneb-product-detail-gallery flex md:flex-col gap-3 overflow-x-auto md:overflow-y-auto max-h-[580px] pb-2 md:pb-0 scrollbar-none", children: images.map((img, idx) => ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setActiveImage(img), className: `w-20 h-20 sm:w-24 sm:h-24 rounded-2xl overflow-hidden border-2 transition-all duration-200 flex-shrink-0 bg-slate-900/40 p-2 ${activeImage === img
55
57
  ? 'border-brand-primary scale-98 shadow-md'
56
- : 'border-slate-800/80 opacity-60 hover:opacity-100 hover:border-slate-700'}`, children: (0, jsx_runtime_1.jsx)("img", { src: (0, utils_1.withBasePath)(img), alt: "", className: "w-full h-full object-contain" }) }, idx))) })), (0, jsx_runtime_1.jsxs)("div", { className: "relative flex-1 aspect-square rounded-3xl bg-gradient-to-b from-slate-900/50 to-slate-950/80 border border-slate-800/80 p-8 flex items-center justify-center overflow-hidden group", children: [badge && ((0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.badge`, className: "absolute top-6 left-6 z-10 px-3.5 py-1 text-xs font-black tracking-wider uppercase rounded-full bg-lime-400 text-slate-950 shadow-lg", children: badge })), (0, jsx_runtime_1.jsx)("img", { "data-preview-field-path": `${sectionPath}.featuredImage`, src: (0, utils_1.withBasePath)(activeImage), alt: name, className: "w-full h-full object-contain transition-transform duration-500 group-hover:scale-105" })] })] }), (0, jsx_runtime_1.jsx)("div", { className: "lg:col-span-5 flex flex-col justify-between", children: (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h1", { "data-preview-field-path": `${sectionPath}.name`, className: "text-3xl sm:text-4xl font-extrabold tracking-tight text-white leading-tight", children: name }), (0, jsx_runtime_1.jsxs)("div", { className: "mt-4 flex items-baseline gap-3", children: [(0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.price`, className: "text-3xl font-black text-lime-400 tracking-tight", children: price }), product.originalPrice ? ((0, jsx_runtime_1.jsx)("span", { className: "text-lg font-medium text-slate-500 line-through", children: String(product.originalPrice) })) : null] }), description && ((0, jsx_runtime_1.jsx)("p", { "data-preview-field-path": `${sectionPath}.description`, className: "mt-6 text-base text-slate-300 leading-relaxed", children: description })), colors.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "mt-8", children: [(0, jsx_runtime_1.jsxs)("span", { className: "block text-xs font-bold uppercase tracking-wider text-slate-400 mb-3", children: ["Color \u2014 ", (0, jsx_runtime_1.jsx)("span", { className: "text-white", children: selectedColor })] }), (0, jsx_runtime_1.jsx)("div", { className: "flex gap-3", children: colors.map((c) => ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setSelectedColor(c.name), className: `w-9 h-9 rounded-full border-2 transition-all p-0.5 ${selectedColor === c.name
58
+ : 'border-slate-800/80 opacity-60 hover:opacity-100 hover:border-slate-700'}`, children: (0, jsx_runtime_1.jsx)("img", { src: (0, utils_1.withBasePath)(img), alt: "", className: "w-full h-full object-contain" }) }, idx))) })), (0, jsx_runtime_1.jsxs)("div", { className: "relative flex-1 aspect-square rounded-3xl bg-gradient-to-b from-slate-900/50 to-slate-950/80 border border-slate-800/80 p-8 flex items-center justify-center overflow-hidden group", children: [badge && ((0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.badge`, className: "absolute top-6 left-6 z-10 px-3.5 py-1 text-xs font-black tracking-wider uppercase rounded-full bg-lime-400 text-slate-950 shadow-lg", children: badge })), (0, jsx_runtime_1.jsx)("img", { "data-preview-field-path": `${sectionPath}.featuredImage`, src: (0, utils_1.withBasePath)(activeImage), alt: name, className: "w-full h-full object-contain transition-transform duration-500 group-hover:scale-105" })] })] }), (0, jsx_runtime_1.jsx)("div", { className: "lg:col-span-5 flex flex-col justify-between", children: (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h1", { "data-preview-field-path": `${sectionPath}.name`, className: "text-3xl sm:text-4xl font-extrabold tracking-tight text-white leading-tight", children: name }), (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.isAvailable`, className: `mt-3 inline-flex rounded-full px-3 py-1 text-xs font-bold ${isAvailable
59
+ ? 'bg-emerald-500/15 text-emerald-300'
60
+ : 'bg-rose-500/15 text-rose-300'}`, children: isAvailable ? 'In Stock' : 'Out of Stock' }), (0, jsx_runtime_1.jsxs)("div", { className: "mt-4 flex items-baseline gap-3", children: [(0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.price`, className: "text-3xl font-black text-lime-400 tracking-tight", children: price }), originalPrice ? ((0, jsx_runtime_1.jsx)("span", { className: "text-lg font-medium text-slate-500 line-through", children: String(originalPrice) })) : null] }), description && ((0, jsx_runtime_1.jsx)("p", { "data-preview-field-path": `${sectionPath}.description`, className: "mt-6 text-base text-slate-300 leading-relaxed", children: description })), colors.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "mt-8", children: [(0, jsx_runtime_1.jsxs)("span", { className: "block text-xs font-bold uppercase tracking-wider text-slate-400 mb-3", children: ["Color \u2014 ", (0, jsx_runtime_1.jsx)("span", { className: "text-white", children: selectedColor })] }), (0, jsx_runtime_1.jsx)("div", { className: "flex gap-3", children: colors.map((c) => ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setSelectedColor(c.name), className: `w-9 h-9 rounded-full border-2 transition-all p-0.5 ${selectedColor === c.name
57
61
  ? 'border-lime-400 ring-2 ring-lime-400/30 scale-105'
58
62
  : 'border-slate-700 hover:border-slate-500'}`, style: { backgroundColor: c.hex }, title: c.name, "aria-label": c.name }, c.name))) })] })), effectiveOptions.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "mt-8", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between mb-3", children: [(0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.${product.optionsLabel ? 'optionsLabel' : 'sizesLabel'}`, className: "block text-xs font-bold uppercase tracking-wider text-slate-400", children: effectiveOptionsLabel }), (0, jsx_runtime_1.jsx)("span", { className: "text-xs font-semibold text-slate-300", children: resolved.formatSelectedDisplay(selectedSize) })] }), (0, jsx_runtime_1.jsx)("div", { className: "deneb-product-detail-sizes grid grid-cols-3 sm:grid-cols-6 md:grid-cols-7 gap-2", children: effectiveOptions.map((s) => ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setSelectedSize(s), className: `py-2.5 px-2 rounded-xl font-bold text-sm transition-all duration-150 ${selectedSize === s
59
63
  ? 'bg-white text-slate-950 shadow-md font-extrabold scale-102'
60
- : 'bg-slate-900/60 text-slate-300 border border-slate-800 hover:bg-slate-800 hover:text-white'}`, children: resolved.formatOption(s) }, s))) })] })), (0, jsx_runtime_1.jsxs)("div", { className: "mt-8 flex flex-col gap-3", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => onAddToSelection?.(product, selectedSize, selectedColor), className: "w-full py-4 px-6 rounded-2xl font-black text-sm uppercase tracking-wider bg-lime-400 text-slate-950 hover:bg-lime-300 active:scale-98 transition-all duration-150 shadow-lg shadow-lime-400/20 flex items-center justify-center gap-2", children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.addToSelectionLabel`, children: addToSelectionLabel }) }), resolvedWhatsappUrl && ((0, jsx_runtime_1.jsxs)("a", { href: resolvedWhatsappUrl, target: "_blank", rel: "noopener noreferrer", className: "w-full py-3.5 px-6 rounded-2xl font-bold text-sm bg-emerald-600/20 text-emerald-400 hover:bg-emerald-600/30 border border-emerald-500/30 transition-all duration-150 flex items-center justify-center gap-2", children: [(0, jsx_runtime_1.jsx)("svg", { className: "w-5 h-5 fill-current", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { d: "M17.472 14.382c-.301-.15-1.78-.879-2.056-.98-.276-.1-.477-.15-.678.15-.201.3-.78 0.98-.956 1.18-.175.2-.351.226-.652.075-.301-.15-1.272-.469-2.423-1.496-.896-.799-1.501-1.787-1.677-2.088-.175-.301-.019-.464.132-.614.136-.135.301-.351.452-.527.15-.176.201-.301.301-.502.1-.2.05-.376-.025-.527-.075-.15-.678-1.635-.93-2.242-.244-.592-.493-.512-.678-.521-.175-.009-.376-.009-.577-.009-.201 0-.527.075-.803.376-.276.301-1.054 1.03-1.054 2.512 0 1.482 1.079 2.912 1.23 3.113.15.201 2.124 3.243 5.145 4.548.718.311 1.279.497 1.716.636.722.23 1.378.197 1.898.12.579-.087 1.78-.728 2.03-1.431.251-.703.251-1.305.176-1.431-.075-.126-.276-.201-.577-.351zM12.004 2C6.48 2 2 6.48 2 12c0 1.82.49 3.52 1.34 4.99L2 22l5.14-1.35c1.42.78 3.04 1.22 4.86 1.22 5.52 0 10-4.48 10-10S17.524 2 12.004 2z" }) }), (0, jsx_runtime_1.jsx)("span", { children: "Order Directly via WhatsApp" })] }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "mt-10 border-t border-slate-800/80 pt-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex gap-6 border-b border-slate-800 pb-3 mb-4", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setActiveTab('specs'), className: `text-sm font-bold tracking-wide transition-colors ${activeTab === 'specs' ? 'text-lime-400' : 'text-slate-400 hover:text-slate-200'}`, children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.specsTitle`, children: specsTitle }) }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setActiveTab('shipping'), className: `text-sm font-bold tracking-wide transition-colors ${activeTab === 'shipping' ? 'text-lime-400' : 'text-slate-400 hover:text-slate-200'}`, children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.shippingTitle`, children: shippingTitle }) })] }), activeTab === 'specs' ? ((0, jsx_runtime_1.jsx)("div", { className: "space-y-3", children: product.specs && product.specs.length > 0 ? (product.specs.map((spec, i) => ((0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between text-xs py-1 border-b border-slate-900", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-slate-400 font-medium", children: spec.label }), (0, jsx_runtime_1.jsx)("span", { className: "text-slate-200 font-semibold", children: spec.value })] }, i)))) : ((0, jsx_runtime_1.jsxs)("div", { className: "text-xs text-slate-400 space-y-2", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between py-1 border-b border-slate-800/50", children: [(0, jsx_runtime_1.jsx)("span", { children: "Upper Material" }), (0, jsx_runtime_1.jsx)("span", { className: "text-slate-200 font-semibold", children: "Engineered breathable mesh" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between py-1 border-b border-slate-800/50", children: [(0, jsx_runtime_1.jsx)("span", { children: "Midsole Technology" }), (0, jsx_runtime_1.jsx)("span", { className: "text-slate-200 font-semibold", children: "Dual-density responsive foam" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between py-1 border-b border-slate-800/50", children: [(0, jsx_runtime_1.jsx)("span", { children: "Outsole Grip" }), (0, jsx_runtime_1.jsx)("span", { className: "text-slate-200 font-semibold", children: "High-abrasion tactical rubber" })] })] })) })) : ((0, jsx_runtime_1.jsxs)("div", { className: "text-xs text-slate-300 space-y-3 leading-relaxed", children: [(0, jsx_runtime_1.jsx)("p", { "data-preview-field-path": `${sectionPath}.shippingSummary`, children: shippingSummary }), (0, jsx_runtime_1.jsx)("p", { "data-preview-field-path": `${sectionPath}.shippingReturns`, className: "text-slate-400", children: shippingReturns })] }))] })] }) })] }) }));
64
+ : 'bg-slate-900/60 text-slate-300 border border-slate-800 hover:bg-slate-800 hover:text-white'}`, children: resolved.formatOption(s) }, s))) })] })), (0, jsx_runtime_1.jsxs)("div", { className: "mt-8 flex flex-col gap-3", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", disabled: !isAvailable, onClick: () => onAddToSelection?.(product, selectedSize, selectedColor), className: "w-full py-4 px-6 rounded-2xl font-black text-sm uppercase tracking-wider bg-lime-400 text-slate-950 hover:bg-lime-300 active:scale-98 transition-all duration-150 shadow-lg shadow-lime-400/20 flex items-center justify-center gap-2 disabled:cursor-not-allowed disabled:bg-slate-700 disabled:text-slate-300 disabled:shadow-none", children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.addToSelectionLabel`, children: isAvailable ? addToSelectionLabel : 'Out of Stock' }) }), isAvailable && resolvedWhatsappUrl && ((0, jsx_runtime_1.jsxs)("a", { href: resolvedWhatsappUrl, target: "_blank", rel: "noopener noreferrer", className: "w-full py-3.5 px-6 rounded-2xl font-bold text-sm bg-emerald-600/20 text-emerald-400 hover:bg-emerald-600/30 border border-emerald-500/30 transition-all duration-150 flex items-center justify-center gap-2", children: [(0, jsx_runtime_1.jsx)("svg", { className: "w-5 h-5 fill-current", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { d: "M17.472 14.382c-.301-.15-1.78-.879-2.056-.98-.276-.1-.477-.15-.678.15-.201.3-.78 0.98-.956 1.18-.175.2-.351.226-.652.075-.301-.15-1.272-.469-2.423-1.496-.896-.799-1.501-1.787-1.677-2.088-.175-.301-.019-.464.132-.614.136-.135.301-.351.452-.527.15-.176.201-.301.301-.502.1-.2.05-.376-.025-.527-.075-.15-.678-1.635-.93-2.242-.244-.592-.493-.512-.678-.521-.175-.009-.376-.009-.577-.009-.201 0-.527.075-.803.376-.276.301-1.054 1.03-1.054 2.512 0 1.482 1.079 2.912 1.23 3.113.15.201 2.124 3.243 5.145 4.548.718.311 1.279.497 1.716.636.722.23 1.378.197 1.898.12.579-.087 1.78-.728 2.03-1.431.251-.703.251-1.305.176-1.431-.075-.126-.276-.201-.577-.351zM12.004 2C6.48 2 2 6.48 2 12c0 1.82.49 3.52 1.34 4.99L2 22l5.14-1.35c1.42.78 3.04 1.22 4.86 1.22 5.52 0 10-4.48 10-10S17.524 2 12.004 2z" }) }), (0, jsx_runtime_1.jsx)("span", { children: "Order Directly via WhatsApp" })] }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "mt-10 border-t border-slate-800/80 pt-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex gap-6 border-b border-slate-800 pb-3 mb-4", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setActiveTab('specs'), className: `text-sm font-bold tracking-wide transition-colors ${activeTab === 'specs' ? 'text-lime-400' : 'text-slate-400 hover:text-slate-200'}`, children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.specsTitle`, children: specsTitle }) }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setActiveTab('shipping'), className: `text-sm font-bold tracking-wide transition-colors ${activeTab === 'shipping' ? 'text-lime-400' : 'text-slate-400 hover:text-slate-200'}`, children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.shippingTitle`, children: shippingTitle }) })] }), activeTab === 'specs' ? ((0, jsx_runtime_1.jsx)("div", { className: "space-y-3", children: product.specs && product.specs.length > 0 ? (product.specs.map((spec, i) => ((0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between text-xs py-1 border-b border-slate-900", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-slate-400 font-medium", children: spec.label }), (0, jsx_runtime_1.jsx)("span", { className: "text-slate-200 font-semibold", children: spec.value })] }, i)))) : ((0, jsx_runtime_1.jsxs)("div", { className: "text-xs text-slate-400 space-y-2", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between py-1 border-b border-slate-800/50", children: [(0, jsx_runtime_1.jsx)("span", { children: "Upper Material" }), (0, jsx_runtime_1.jsx)("span", { className: "text-slate-200 font-semibold", children: "Engineered breathable mesh" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between py-1 border-b border-slate-800/50", children: [(0, jsx_runtime_1.jsx)("span", { children: "Midsole Technology" }), (0, jsx_runtime_1.jsx)("span", { className: "text-slate-200 font-semibold", children: "Dual-density responsive foam" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between py-1 border-b border-slate-800/50", children: [(0, jsx_runtime_1.jsx)("span", { children: "Outsole Grip" }), (0, jsx_runtime_1.jsx)("span", { className: "text-slate-200 font-semibold", children: "High-abrasion tactical rubber" })] })] })) })) : ((0, jsx_runtime_1.jsxs)("div", { className: "text-xs text-slate-300 space-y-3 leading-relaxed", children: [(0, jsx_runtime_1.jsx)("p", { "data-preview-field-path": `${sectionPath}.shippingSummary`, children: shippingSummary }), (0, jsx_runtime_1.jsx)("p", { "data-preview-field-path": `${sectionPath}.shippingReturns`, className: "text-slate-400", children: shippingReturns })] }))] })] }) })] }) }));
61
65
  }
@@ -10,6 +10,7 @@ export interface ProductQuickViewItem {
10
10
  imageUrl?: string;
11
11
  gallery?: string[];
12
12
  inStock?: boolean;
13
+ isAvailable?: boolean;
13
14
  rating?: number;
14
15
  reviewCount?: number;
15
16
  [key: string]: unknown;
@@ -43,7 +43,10 @@ function ProductQuickView({ product, isOpen, onClose, onAddToCart, className = '
43
43
  }
44
44
  const images = product.gallery && product.gallery.length > 0 ? product.gallery : [product.imageUrl || ''];
45
45
  const currency = product.currency || '$';
46
+ const isAvailable = product.isAvailable !== false && product.inStock !== false;
46
47
  const handleAddToCart = () => {
48
+ if (!isAvailable)
49
+ return;
47
50
  if (onAddToCart) {
48
51
  onAddToCart(product, quantity);
49
52
  }
@@ -52,8 +55,8 @@ function ProductQuickView({ product, isOpen, onClose, onAddToCart, className = '
52
55
  return ((0, jsx_runtime_1.jsx)("div", { role: "dialog", "aria-modal": "true", className: `fixed inset-0 z-50 flex items-center justify-center p-4 sm:p-6 bg-black/60 backdrop-blur-sm transition-opacity duration-200 ${className}`, onClick: (e) => {
53
56
  if (e.target === e.currentTarget)
54
57
  onClose();
55
- }, children: (0, jsx_runtime_1.jsxs)("div", { className: "relative w-full max-w-2xl overflow-hidden rounded-3xl bg-white shadow-2xl border border-slate-100 flex flex-col md:flex-row max-h-[90vh]", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: onClose, className: "absolute top-4 right-4 z-10 p-2 text-slate-400 hover:text-slate-700 bg-white/80 hover:bg-white rounded-full shadow-sm backdrop-blur transition-colors", "aria-label": "Close modal", children: (0, jsx_runtime_1.jsx)("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) }), (0, jsx_runtime_1.jsxs)("div", { className: "md:w-1/2 p-6 flex flex-col items-center justify-center bg-slate-50 border-b md:border-b-0 md:border-r border-slate-100", children: [(0, jsx_runtime_1.jsxs)("div", { className: "relative w-full aspect-square rounded-2xl overflow-hidden bg-white shadow-sm flex items-center justify-center", children: [product.badge && ((0, jsx_runtime_1.jsx)("span", { ...(itemPath ? { 'data-preview-field-path': `${itemPath}.badge` } : {}), className: "absolute top-3 left-3 px-2.5 py-1 text-xs font-bold text-white bg-red-500 rounded-lg shadow-sm", children: product.badge })), selectedImage ? ((0, jsx_runtime_1.jsx)("img", { ...(itemPath ? { 'data-preview-field-path': `${itemPath}.image` } : {}), src: (0, utils_1.withBasePath)(selectedImage), alt: product.title, className: "w-full h-full object-cover" })) : ((0, jsx_runtime_1.jsx)("div", { className: "text-slate-300 text-sm", children: "No image available" }))] }), images.length > 1 && ((0, jsx_runtime_1.jsx)("div", { className: "flex gap-2 mt-4 overflow-x-auto max-w-full pb-1", children: images.map((img, idx) => ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setSelectedImage(img), className: `w-12 h-12 rounded-lg overflow-hidden border-2 transition-all flex-shrink-0 ${selectedImage === img ? 'border-primary shadow-sm' : 'border-slate-200 opacity-60 hover:opacity-100'}`, children: (0, jsx_runtime_1.jsx)("img", { src: (0, utils_1.withBasePath)(img), alt: "", className: "w-full h-full object-cover" }) }, idx))) }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "md:w-1/2 p-6 flex flex-col justify-between overflow-y-auto", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 mb-2", children: [(0, jsx_runtime_1.jsx)("span", { className: `inline-flex items-center px-2 py-0.5 rounded text-xs font-semibold ${product.inStock !== false ? 'bg-emerald-50 text-emerald-700' : 'bg-rose-50 text-rose-700'}`, children: product.inStock !== false ? 'In Stock' : 'Out of Stock' }), product.rating && ((0, jsx_runtime_1.jsxs)("span", { className: "text-xs text-amber-500 flex items-center gap-1 font-medium", children: ["\u2605 ", product.rating, " ", product.reviewCount ? `(${product.reviewCount})` : ''] }))] }), (0, jsx_runtime_1.jsx)("h3", { ...(itemPath ? { 'data-preview-field-path': `${itemPath}.name` } : {}), className: "text-xl font-bold text-slate-900 leading-tight", children: product.title }), (0, jsx_runtime_1.jsxs)("div", { className: "mt-3 flex items-baseline gap-2", children: [(0, jsx_runtime_1.jsxs)("span", { ...(itemPath ? { 'data-preview-field-path': `${itemPath}.price` } : {}), className: "text-2xl font-black text-slate-900", children: [currency, product.price] }), product.originalPrice && ((0, jsx_runtime_1.jsxs)("span", { className: "text-sm font-semibold text-slate-400 line-through", children: [currency, product.originalPrice] }))] }), product.description && ((0, jsx_runtime_1.jsx)("p", { ...(itemPath ? { 'data-preview-field-path': `${itemPath}.description` } : {}), className: "mt-4 text-sm text-slate-600 leading-relaxed", children: product.description }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "mt-6 pt-6 border-t border-slate-100", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-sm font-medium text-slate-700", children: "Quantity" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center rounded-xl border border-slate-200 bg-slate-50 p-1", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setQuantity((q) => Math.max(1, q - 1)), className: "w-8 h-8 flex items-center justify-center rounded-lg hover:bg-white text-slate-600 font-bold transition-colors", children: "-" }), (0, jsx_runtime_1.jsx)("span", { className: "w-10 text-center font-bold text-sm text-slate-800", children: quantity }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setQuantity((q) => q + 1), className: "w-8 h-8 flex items-center justify-center rounded-lg hover:bg-white text-slate-600 font-bold transition-colors", children: "+" })] })] }), (0, jsx_runtime_1.jsxs)("button", { type: "button", disabled: product.inStock === false, onClick: handleAddToCart, className: "w-full py-3.5 px-4 rounded-xl font-bold text-sm text-white shadow-lg transition-all duration-200 active:scale-98 disabled:opacity-50 disabled:cursor-not-allowed hover:brightness-110 flex items-center justify-center gap-2", style: {
58
+ }, children: (0, jsx_runtime_1.jsxs)("div", { className: "relative w-full max-w-2xl overflow-hidden rounded-3xl bg-white shadow-2xl border border-slate-100 flex flex-col md:flex-row max-h-[90vh]", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: onClose, className: "absolute top-4 right-4 z-10 p-2 text-slate-400 hover:text-slate-700 bg-white/80 hover:bg-white rounded-full shadow-sm backdrop-blur transition-colors", "aria-label": "Close modal", children: (0, jsx_runtime_1.jsx)("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) }), (0, jsx_runtime_1.jsxs)("div", { className: "md:w-1/2 p-6 flex flex-col items-center justify-center bg-slate-50 border-b md:border-b-0 md:border-r border-slate-100", children: [(0, jsx_runtime_1.jsxs)("div", { className: "relative w-full aspect-square rounded-2xl overflow-hidden bg-white shadow-sm flex items-center justify-center", children: [product.badge && ((0, jsx_runtime_1.jsx)("span", { ...(itemPath ? { 'data-preview-field-path': `${itemPath}.badge` } : {}), className: "absolute top-3 left-3 px-2.5 py-1 text-xs font-bold text-white bg-red-500 rounded-lg shadow-sm", children: product.badge })), selectedImage ? ((0, jsx_runtime_1.jsx)("img", { ...(itemPath ? { 'data-preview-field-path': `${itemPath}.image` } : {}), src: (0, utils_1.withBasePath)(selectedImage), alt: product.title, className: "w-full h-full object-cover" })) : ((0, jsx_runtime_1.jsx)("div", { className: "text-slate-300 text-sm", children: "No image available" }))] }), images.length > 1 && ((0, jsx_runtime_1.jsx)("div", { className: "flex gap-2 mt-4 overflow-x-auto max-w-full pb-1", children: images.map((img, idx) => ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setSelectedImage(img), className: `w-12 h-12 rounded-lg overflow-hidden border-2 transition-all flex-shrink-0 ${selectedImage === img ? 'border-primary shadow-sm' : 'border-slate-200 opacity-60 hover:opacity-100'}`, children: (0, jsx_runtime_1.jsx)("img", { src: (0, utils_1.withBasePath)(img), alt: "", className: "w-full h-full object-cover" }) }, idx))) }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "md:w-1/2 p-6 flex flex-col justify-between overflow-y-auto", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 mb-2", children: [(0, jsx_runtime_1.jsx)("span", { className: `inline-flex items-center px-2 py-0.5 rounded text-xs font-semibold ${isAvailable ? 'bg-emerald-50 text-emerald-700' : 'bg-rose-50 text-rose-700'}`, children: isAvailable ? 'In Stock' : 'Out of Stock' }), product.rating && ((0, jsx_runtime_1.jsxs)("span", { className: "text-xs text-amber-500 flex items-center gap-1 font-medium", children: ["\u2605 ", product.rating, " ", product.reviewCount ? `(${product.reviewCount})` : ''] }))] }), (0, jsx_runtime_1.jsx)("h3", { ...(itemPath ? { 'data-preview-field-path': `${itemPath}.name` } : {}), className: "text-xl font-bold text-slate-900 leading-tight", children: product.title }), (0, jsx_runtime_1.jsxs)("div", { className: "mt-3 flex items-baseline gap-2", children: [(0, jsx_runtime_1.jsxs)("span", { ...(itemPath ? { 'data-preview-field-path': `${itemPath}.price` } : {}), className: "text-2xl font-black text-slate-900", children: [currency, product.price] }), product.originalPrice && ((0, jsx_runtime_1.jsxs)("span", { className: "text-sm font-semibold text-slate-400 line-through", children: [currency, product.originalPrice] }))] }), product.description && ((0, jsx_runtime_1.jsx)("p", { ...(itemPath ? { 'data-preview-field-path': `${itemPath}.description` } : {}), className: "mt-4 text-sm text-slate-600 leading-relaxed", children: product.description }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "mt-6 pt-6 border-t border-slate-100", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-sm font-medium text-slate-700", children: "Quantity" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center rounded-xl border border-slate-200 bg-slate-50 p-1", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setQuantity((q) => Math.max(1, q - 1)), className: "w-8 h-8 flex items-center justify-center rounded-lg hover:bg-white text-slate-600 font-bold transition-colors", children: "-" }), (0, jsx_runtime_1.jsx)("span", { className: "w-10 text-center font-bold text-sm text-slate-800", children: quantity }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setQuantity((q) => q + 1), className: "w-8 h-8 flex items-center justify-center rounded-lg hover:bg-white text-slate-600 font-bold transition-colors", children: "+" })] })] }), (0, jsx_runtime_1.jsxs)("button", { type: "button", disabled: !isAvailable, onClick: handleAddToCart, className: "w-full py-3.5 px-4 rounded-xl font-bold text-sm text-white shadow-lg transition-all duration-200 active:scale-98 disabled:opacity-50 disabled:cursor-not-allowed hover:brightness-110 flex items-center justify-center gap-2", style: {
56
59
  backgroundColor: 'var(--color-primary, #0f172a)',
57
60
  boxShadow: '0 4px 14px rgba(15, 23, 42, 0.25)',
58
- }, children: [(0, jsx_runtime_1.jsx)("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" }) }), (0, jsx_runtime_1.jsx)("span", { ...(itemPath ? { 'data-preview-field-path': `${itemPath}.addToSelectionLabel` } : {}), children: addToCartLabel })] })] })] })] }) }));
61
+ }, children: [(0, jsx_runtime_1.jsx)("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" }) }), (0, jsx_runtime_1.jsx)("span", { ...(itemPath ? { 'data-preview-field-path': `${itemPath}.addToSelectionLabel` } : {}), children: isAvailable ? addToCartLabel : 'Out of Stock' })] })] })] })] }) }));
59
62
  }
@@ -17,8 +17,7 @@ export interface ContactActionsProps {
17
17
  style?: React.CSSProperties;
18
18
  }
19
19
  /**
20
- * Smart container that automatically renders available contact channels.
21
- * When a merchant adds phone, WhatsApp, or email in site-data.json,
22
- * the corresponding action button appears automatically with zero template code changes.
20
+ * Always-mounted contact channels so Fivora empty-state validation keeps
21
+ * the field markers clickable when values are blank.
23
22
  */
24
- export declare function ContactActions({ phone, whatsapp, email, phoneFieldPath, whatsappFieldPath, emailFieldPath, labels, size, layout, className, style, }: ContactActionsProps): React.JSX.Element | null;
23
+ export declare function ContactActions({ phone, whatsapp, email, phoneFieldPath, whatsappFieldPath, emailFieldPath, labels, size, layout, className, style, }: ContactActionsProps): React.JSX.Element;
@@ -7,17 +7,10 @@ const WhatsAppButton_1 = require("./WhatsAppButton");
7
7
  const PhoneButton_1 = require("./PhoneButton");
8
8
  const EmailButton_1 = require("./EmailButton");
9
9
  /**
10
- * Smart container that automatically renders available contact channels.
11
- * When a merchant adds phone, WhatsApp, or email in site-data.json,
12
- * the corresponding action button appears automatically with zero template code changes.
10
+ * Always-mounted contact channels so Fivora empty-state validation keeps
11
+ * the field markers clickable when values are blank.
13
12
  */
14
13
  function ContactActions({ phone, whatsapp, email, phoneFieldPath = 'common.business.phone', whatsappFieldPath = 'common.business.whatsapp', emailFieldPath = 'common.business.email', labels = {}, size = 'md', layout = 'row', className = '', style, }) {
15
- const hasPhone = Boolean(phone && phone.trim());
16
- const hasWhatsApp = Boolean(whatsapp && whatsapp.trim());
17
- const hasEmail = Boolean(email && email.trim());
18
- if (!hasPhone && !hasWhatsApp && !hasEmail) {
19
- return null;
20
- }
21
14
  const layoutStyles = {
22
15
  display: 'flex',
23
16
  flexDirection: layout === 'column' ? 'column' : 'row',
@@ -26,5 +19,5 @@ function ContactActions({ phone, whatsapp, email, phoneFieldPath = 'common.busin
26
19
  gap: '0.75rem',
27
20
  ...style,
28
21
  };
29
- return ((0, jsx_runtime_1.jsxs)("div", { className: `deneb-contact-actions deneb-layout-${layout} ${className}`.trim(), style: layoutStyles, children: [hasPhone && ((0, jsx_runtime_1.jsx)(PhoneButton_1.PhoneButton, { value: phone, fieldPath: phoneFieldPath, label: labels.phone || 'Call Us', size: size })), hasWhatsApp && ((0, jsx_runtime_1.jsx)(WhatsAppButton_1.WhatsAppButton, { value: whatsapp, fieldPath: whatsappFieldPath, label: labels.whatsapp || 'Chat on WhatsApp', size: size })), hasEmail && ((0, jsx_runtime_1.jsx)(EmailButton_1.EmailButton, { value: email, fieldPath: emailFieldPath, label: labels.email || 'Email Us', size: size }))] }));
22
+ return ((0, jsx_runtime_1.jsxs)("div", { className: `deneb-contact-actions deneb-layout-${layout} ${className}`.trim(), style: layoutStyles, children: [(0, jsx_runtime_1.jsx)(PhoneButton_1.PhoneButton, { value: phone ?? '', fieldPath: phoneFieldPath, label: labels.phone || 'Call Us', size: size }), (0, jsx_runtime_1.jsx)(WhatsAppButton_1.WhatsAppButton, { value: whatsapp ?? '', fieldPath: whatsappFieldPath, label: labels.whatsapp || 'Chat on WhatsApp', size: size }), (0, jsx_runtime_1.jsx)(EmailButton_1.EmailButton, { value: email ?? '', fieldPath: emailFieldPath, label: labels.email || 'Email Us', size: size })] }));
30
23
  }
@@ -5,7 +5,7 @@ exports.PhoneButton = PhoneButton;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
6
  const ContactButton_1 = require("./ContactButton");
7
7
  function PhoneButton({ phoneNumber, value, label = 'Call Us', fieldPath = 'common.business.phone', variant = 'primary', ...rest }) {
8
- const number = phoneNumber || value;
8
+ const number = phoneNumber ?? value;
9
9
  if (!number && !fieldPath)
10
10
  return null;
11
11
  return ((0, jsx_runtime_1.jsx)(ContactButton_1.ContactButton, { type: "phone", value: number, label: label, fieldPath: fieldPath, variant: variant, ...rest }));
@@ -8,4 +8,4 @@ export interface SocialButtonProps extends React.AnchorHTMLAttributes<HTMLAnchor
8
8
  variant?: 'icon' | 'pill' | 'button';
9
9
  size?: 'sm' | 'md' | 'lg';
10
10
  }
11
- export declare function SocialButton({ platform, url, href, label, fieldPath, variant, size, className, style, ...rest }: SocialButtonProps): React.JSX.Element | null;
11
+ export declare function SocialButton({ platform, url, href, label, fieldPath, variant, size, className, style, ...rest }: SocialButtonProps): React.JSX.Element;
@@ -61,11 +61,7 @@ const PLATFORM_CONFIG = {
61
61
  };
62
62
  function SocialButton({ platform, url, href, label, fieldPath, variant = 'icon', size = 'md', className = '', style, ...rest }) {
63
63
  const derivedFieldPath = fieldPath || `common.business.social.${platform}`;
64
- const hasFieldPath = Boolean(fieldPath);
65
- const targetUrl = url || href || (hasFieldPath ? '#' : '');
66
- // Don't render broken button if no valid URL and no fieldPath
67
- if (!targetUrl)
68
- return null;
64
+ const targetUrl = url ?? href ?? '#';
69
65
  const config = PLATFORM_CONFIG[platform] || PLATFORM_CONFIG.x;
70
66
  const iconSize = size === 'sm' ? 16 : size === 'lg' ? 22 : 18;
71
67
  const baseStyles = {
@@ -8,7 +8,6 @@ export interface SocialLinksProps {
8
8
  style?: React.CSSProperties;
9
9
  }
10
10
  /**
11
- * Smart container rendering active social buttons.
12
- * Automatically filters out any unconfigured or empty platforms.
11
+ * Always-mounted social buttons so empty-state preview keeps field markers.
13
12
  */
14
- export declare function SocialLinks({ social, fieldPathPrefix, variant, size, className, style, }: SocialLinksProps): React.JSX.Element | null;
13
+ export declare function SocialLinks({ social, fieldPathPrefix, variant, size, className, style, }: SocialLinksProps): React.JSX.Element;
@@ -16,17 +16,11 @@ const SUPPORTED_PLATFORMS = [
16
16
  'github',
17
17
  ];
18
18
  /**
19
- * Smart container rendering active social buttons.
20
- * Automatically filters out any unconfigured or empty platforms.
19
+ * Always-mounted social buttons so empty-state preview keeps field markers.
21
20
  */
22
21
  function SocialLinks({ social = {}, fieldPathPrefix = 'common.business.social', variant = 'icon', size = 'md', className = '', style, }) {
23
- // Find platforms with valid URLs
24
- const activePlatforms = Object.entries(social).filter(([platform, url]) => {
25
- return Boolean(url && typeof url === 'string' && url.trim().length > 0);
26
- });
27
- if (activePlatforms.length === 0) {
28
- return null;
29
- }
22
+ const platforms = SUPPORTED_PLATFORMS.filter((platform) => Object.prototype.hasOwnProperty.call(social, platform) || Object.keys(social).length === 0);
23
+ const rendered = platforms.length ? platforms : SUPPORTED_PLATFORMS;
30
24
  const containerStyles = {
31
25
  display: 'inline-flex',
32
26
  alignItems: 'center',
@@ -34,9 +28,5 @@ function SocialLinks({ social = {}, fieldPathPrefix = 'common.business.social',
34
28
  gap: '0.625rem',
35
29
  ...style,
36
30
  };
37
- return ((0, jsx_runtime_1.jsx)("div", { className: `deneb-social-links ${className}`.trim(), style: containerStyles, children: activePlatforms.map(([key, url]) => {
38
- const lowerKey = key.toLowerCase();
39
- const platform = SUPPORTED_PLATFORMS.includes(lowerKey) ? lowerKey : 'x';
40
- return ((0, jsx_runtime_1.jsx)(SocialButton_1.SocialButton, { platform: platform, url: url, fieldPath: `${fieldPathPrefix}.${key}`, variant: variant, size: size }, key));
41
- }) }));
31
+ return ((0, jsx_runtime_1.jsx)("div", { className: `deneb-social-links ${className}`.trim(), style: containerStyles, children: rendered.map((platform) => ((0, jsx_runtime_1.jsx)(SocialButton_1.SocialButton, { platform: platform, url: social[platform] ?? '', fieldPath: `${fieldPathPrefix}.${platform}`, variant: variant, size: size }, platform))) }));
42
32
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deneb-ui/ui",
3
- "version": "2.0.51",
3
+ "version": "2.0.53",
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",
@@ -49,7 +49,7 @@
49
49
  ],
50
50
  "license": "MIT",
51
51
  "dependencies": {
52
- "@deneb-ui/core": "^2.0.51"
52
+ "@deneb-ui/core": "^2.0.53"
53
53
  },
54
54
  "peerDependencies": {
55
55
  "react": "^18.0.0 || ^19.0.0",