@deneb-ui/ui 2.0.76 → 2.0.78
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/EditableProductDetail.d.ts +14 -8
- package/dist/EditableProductDetail.js +114 -28
- package/package.json +2 -2
|
@@ -41,6 +41,7 @@ export interface ProductDetailItem {
|
|
|
41
41
|
colors?: Array<string | {
|
|
42
42
|
name: string;
|
|
43
43
|
hex?: string;
|
|
44
|
+
image?: string;
|
|
44
45
|
}> | string;
|
|
45
46
|
colorsText?: string;
|
|
46
47
|
colorsLabel?: string;
|
|
@@ -56,15 +57,18 @@ export interface EditableProductDetailProps extends React.HTMLAttributes<HTMLEle
|
|
|
56
57
|
*/
|
|
57
58
|
product: ProductDetailItem;
|
|
58
59
|
/**
|
|
59
|
-
*
|
|
60
|
+
* Optional custom available sizes or options (e.g. ['S', 'M', 'L'] or ['50ml', '100ml']).
|
|
61
|
+
* If omitted, resolved dynamically from the product object.
|
|
60
62
|
*/
|
|
61
63
|
sizes?: string[];
|
|
62
64
|
/**
|
|
63
|
-
*
|
|
65
|
+
* Optional custom color swatches.
|
|
66
|
+
* If omitted, resolved dynamically from the product object.
|
|
64
67
|
*/
|
|
65
68
|
colors?: Array<{
|
|
66
69
|
name: string;
|
|
67
70
|
hex: string;
|
|
71
|
+
image?: string;
|
|
68
72
|
}>;
|
|
69
73
|
/**
|
|
70
74
|
* Callback on adding product to selection or cart.
|
|
@@ -81,12 +85,14 @@ export interface EditableProductDetailProps extends React.HTMLAttributes<HTMLEle
|
|
|
81
85
|
* engineered for high-conversion commerce and 100% compliant with Fivora Visual Editing.
|
|
82
86
|
*
|
|
83
87
|
* Features:
|
|
84
|
-
* -
|
|
85
|
-
*
|
|
86
|
-
* -
|
|
87
|
-
* -
|
|
88
|
-
* -
|
|
89
|
-
* -
|
|
88
|
+
* - Truly Adaptive: Seamlessly renders shoes/apparel (sizes), liquids/cosmetics (ml, L),
|
|
89
|
+
* food/groceries (g, kg), single-dimension items, and simple products without variants.
|
|
90
|
+
* - Multi-image gallery with active thumbnail selector and basePath resolution.
|
|
91
|
+
* - Dynamic color swatches with optional color-to-image auto-switching.
|
|
92
|
+
* - Floating badges with conditional rendering (zero hidden marker contract violations).
|
|
93
|
+
* - Live synchronized field paths for Title, Price, Description, CTAs, and Policies.
|
|
94
|
+
* - Direct WhatsApp Click-to-Order integration with dynamic variant snippets.
|
|
95
|
+
* - Context-aware specifications and Shipping & Returns tabs.
|
|
90
96
|
*
|
|
91
97
|
* Created by Chamika Gayashan & Induranga Kawishwara
|
|
92
98
|
*/
|
|
@@ -11,33 +11,101 @@ const urls_1 = require("./utils/urls");
|
|
|
11
11
|
* engineered for high-conversion commerce and 100% compliant with Fivora Visual Editing.
|
|
12
12
|
*
|
|
13
13
|
* Features:
|
|
14
|
-
* -
|
|
15
|
-
*
|
|
16
|
-
* -
|
|
17
|
-
* -
|
|
18
|
-
* -
|
|
19
|
-
* -
|
|
14
|
+
* - Truly Adaptive: Seamlessly renders shoes/apparel (sizes), liquids/cosmetics (ml, L),
|
|
15
|
+
* food/groceries (g, kg), single-dimension items, and simple products without variants.
|
|
16
|
+
* - Multi-image gallery with active thumbnail selector and basePath resolution.
|
|
17
|
+
* - Dynamic color swatches with optional color-to-image auto-switching.
|
|
18
|
+
* - Floating badges with conditional rendering (zero hidden marker contract violations).
|
|
19
|
+
* - Live synchronized field paths for Title, Price, Description, CTAs, and Policies.
|
|
20
|
+
* - Direct WhatsApp Click-to-Order integration with dynamic variant snippets.
|
|
21
|
+
* - Context-aware specifications and Shipping & Returns tabs.
|
|
20
22
|
*
|
|
21
23
|
* Created by Chamika Gayashan & Induranga Kawishwara
|
|
22
24
|
*/
|
|
23
|
-
function EditableProductDetail({ sectionPath = 'product', product, sizes
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
function EditableProductDetail({ sectionPath = 'product', product, sizes, colors, onAddToSelection, whatsappUrl, className = '', style, ...props }) {
|
|
26
|
+
// 1. Resolve Images: Support gallery, images array, and single image fields
|
|
27
|
+
const validImages = (0, react_1.useMemo)(() => {
|
|
28
|
+
const rawList = (product.gallery && product.gallery.length > 0)
|
|
29
|
+
? product.gallery
|
|
30
|
+
: (product.images && product.images.length > 0)
|
|
31
|
+
? product.images
|
|
32
|
+
: [product.featuredImage || product.imageUrl || product.image || '/products/vanta-aero-x.jpg'];
|
|
33
|
+
return rawList.filter(Boolean);
|
|
34
|
+
}, [product.gallery, product.images, product.featuredImage, product.imageUrl, product.image]);
|
|
35
|
+
// 2. Resolve Options (Sizes, Volumes, Weights, Counts)
|
|
30
36
|
const resolved = (0, productOptions_1.resolveProductOptions)(product);
|
|
31
|
-
const effectiveOptions =
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
?
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
const effectiveOptions = (0, react_1.useMemo)(() => {
|
|
38
|
+
const hasProductOptions = Boolean((product.options && product.options.length > 0) ||
|
|
39
|
+
(typeof product.optionsText === 'string' && product.optionsText.trim()) ||
|
|
40
|
+
(product.sizes && (Array.isArray(product.sizes) ? product.sizes.length > 0 : Boolean(product.sizes))) ||
|
|
41
|
+
(typeof product.sizesText === 'string' && product.sizesText.trim()) ||
|
|
42
|
+
(typeof product.measurement === 'string' && product.measurement.trim()));
|
|
43
|
+
if (hasProductOptions) {
|
|
44
|
+
return resolved.options;
|
|
45
|
+
}
|
|
46
|
+
if (sizes && sizes.length > 0) {
|
|
47
|
+
return sizes;
|
|
48
|
+
}
|
|
49
|
+
return [];
|
|
50
|
+
}, [product.options, product.optionsText, product.sizes, product.sizesText, product.measurement, resolved.options, sizes]);
|
|
51
|
+
const effectiveOptionsLabel = resolved.optionsLabel || 'Available Options';
|
|
52
|
+
// 3. Resolve Colors
|
|
53
|
+
const effectiveColors = (0, react_1.useMemo)(() => {
|
|
54
|
+
if (Array.isArray(product.colors) && product.colors.length > 0) {
|
|
55
|
+
return product.colors.map((c) => {
|
|
56
|
+
if (typeof c === 'string') {
|
|
57
|
+
return { name: c.trim(), hex: undefined };
|
|
58
|
+
}
|
|
59
|
+
return c;
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
if (typeof product.colorsText === 'string' && product.colorsText.trim()) {
|
|
63
|
+
return product.colorsText
|
|
64
|
+
.split(',')
|
|
65
|
+
.map((s) => s.trim())
|
|
66
|
+
.filter(Boolean)
|
|
67
|
+
.map((name) => ({ name, hex: undefined }));
|
|
68
|
+
}
|
|
69
|
+
if (colors && colors.length > 0) {
|
|
70
|
+
return colors;
|
|
71
|
+
}
|
|
72
|
+
return [];
|
|
73
|
+
}, [product.colors, product.colorsText, colors]);
|
|
74
|
+
// Component States
|
|
75
|
+
const [activeImage, setActiveImage] = (0, react_1.useState)(validImages[0] || '');
|
|
38
76
|
const [selectedSize, setSelectedSize] = (0, react_1.useState)(effectiveOptions[0] || '');
|
|
39
|
-
const [selectedColor, setSelectedColor] = (0, react_1.useState)(
|
|
77
|
+
const [selectedColor, setSelectedColor] = (0, react_1.useState)(effectiveColors[0]?.name || '');
|
|
40
78
|
const [activeTab, setActiveTab] = (0, react_1.useState)('specs');
|
|
79
|
+
// Keep active image in sync when product or images change
|
|
80
|
+
(0, react_1.useEffect)(() => {
|
|
81
|
+
if (validImages.length > 0 && !validImages.includes(activeImage)) {
|
|
82
|
+
setActiveImage(validImages[0]);
|
|
83
|
+
}
|
|
84
|
+
}, [validImages, activeImage]);
|
|
85
|
+
// Keep selected size in sync when options change
|
|
86
|
+
(0, react_1.useEffect)(() => {
|
|
87
|
+
if (effectiveOptions.length > 0 && (!selectedSize || !effectiveOptions.includes(selectedSize))) {
|
|
88
|
+
setSelectedSize(effectiveOptions[0]);
|
|
89
|
+
}
|
|
90
|
+
else if (effectiveOptions.length === 0 && selectedSize) {
|
|
91
|
+
setSelectedSize('');
|
|
92
|
+
}
|
|
93
|
+
}, [effectiveOptions, selectedSize]);
|
|
94
|
+
// Keep selected color in sync when colors change
|
|
95
|
+
(0, react_1.useEffect)(() => {
|
|
96
|
+
if (effectiveColors.length > 0 && (!selectedColor || !effectiveColors.some((c) => c.name === selectedColor))) {
|
|
97
|
+
setSelectedColor(effectiveColors[0]?.name || '');
|
|
98
|
+
}
|
|
99
|
+
else if (effectiveColors.length === 0 && selectedColor) {
|
|
100
|
+
setSelectedColor('');
|
|
101
|
+
}
|
|
102
|
+
}, [effectiveColors, selectedColor]);
|
|
103
|
+
const handleSelectColor = (c) => {
|
|
104
|
+
setSelectedColor(c.name);
|
|
105
|
+
if (c.image) {
|
|
106
|
+
setActiveImage(c.image);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
41
109
|
const name = String(product.name || product.title || 'Product Title');
|
|
42
110
|
const price = product.price !== undefined ? String(product.price) : 'LKR 0';
|
|
43
111
|
const originalPrice = product.originalPrice ?? product.compareAtPrice;
|
|
@@ -49,17 +117,35 @@ function EditableProductDetail({ sectionPath = 'product', product, sizes = ['40'
|
|
|
49
117
|
const shippingTitle = String(product.shippingTitle || 'Shipping & Returns');
|
|
50
118
|
const shippingSummary = String(product.shippingSummary || 'Free Islandwide Delivery within 2-3 business days. Cash on delivery available.');
|
|
51
119
|
const shippingReturns = String(product.shippingReturns || '14-day hassle-free exchanges for unworn items in original packaging.');
|
|
52
|
-
const orderSnippet = resolved.formatOrderSnippet(selectedSize, selectedColor);
|
|
120
|
+
const orderSnippet = resolved.formatOrderSnippet(effectiveOptions.length > 0 ? selectedSize : undefined, effectiveColors.length > 0 ? selectedColor : undefined);
|
|
53
121
|
const resolvedWhatsappUrl = whatsappUrl || (product.whatsappNumber
|
|
54
122
|
? (0, urls_1.createWhatsAppUrl)(product.whatsappNumber, product.whatsappMessage || `Hi, I would like to order ${name}${orderSnippet ? ` ${orderSnippet}` : ''} - ${price}`)
|
|
55
123
|
: '');
|
|
56
|
-
|
|
57
|
-
|
|
124
|
+
// Dynamic Specs: Use explicit specs if provided, else fallback to available product metadata
|
|
125
|
+
const effectiveSpecs = (0, react_1.useMemo)(() => {
|
|
126
|
+
if (product.specs && product.specs.length > 0) {
|
|
127
|
+
return product.specs;
|
|
128
|
+
}
|
|
129
|
+
const dynamic = [];
|
|
130
|
+
if (product.brand)
|
|
131
|
+
dynamic.push({ label: 'Brand', value: String(product.brand) });
|
|
132
|
+
if (product.category)
|
|
133
|
+
dynamic.push({ label: 'Category', value: String(product.category) });
|
|
134
|
+
if (product.unit && product.unit !== 'size') {
|
|
135
|
+
dynamic.push({ label: 'Measurement Unit', value: String(product.unit).toUpperCase() });
|
|
136
|
+
}
|
|
137
|
+
if (product.measurement) {
|
|
138
|
+
dynamic.push({ label: 'Measurement', value: String(product.measurement) });
|
|
139
|
+
}
|
|
140
|
+
return dynamic;
|
|
141
|
+
}, [product.specs, product.brand, product.category, product.unit, product.measurement]);
|
|
142
|
+
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: [validImages.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: validImages.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
|
|
143
|
+
? 'border-lime-400 scale-98 shadow-md ring-2 ring-lime-400/20'
|
|
58
144
|
: '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
145
|
? '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 })),
|
|
146
|
+
: '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 })), effectiveColors.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 flex-wrap gap-3", children: effectiveColors.map((c) => ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => handleSelectColor(c), className: `w-9 h-9 rounded-full border-2 transition-all p-0.5 relative flex items-center justify-center ${selectedColor === c.name
|
|
61
147
|
? 'border-lime-400 ring-2 ring-lime-400/30 scale-105'
|
|
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
|
|
63
|
-
? 'bg-white text-slate-950 shadow-md font-extrabold scale-102'
|
|
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:
|
|
148
|
+
: 'border-slate-700 hover:border-slate-500'}`, style: { backgroundColor: c.hex || '#334155' }, title: c.name, "aria-label": c.name, children: !c.hex && ((0, jsx_runtime_1.jsx)("span", { className: "text-[9px] font-bold text-white uppercase px-1 truncate", children: c.name.slice(0, 3) })) }, 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 flex flex-wrap gap-2.5", children: effectiveOptions.map((s) => ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setSelectedSize(s), className: `py-2.5 px-3.5 min-w-[48px] rounded-xl font-bold text-sm transition-all duration-150 text-center ${selectedSize === s
|
|
149
|
+
? 'bg-white text-slate-950 shadow-md font-extrabold scale-102 ring-2 ring-white/20'
|
|
150
|
+
: '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 || undefined, selectedColor || undefined), 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: effectiveSpecs.length > 0 ? (effectiveSpecs.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: "Status" }), (0, jsx_runtime_1.jsx)("span", { className: "text-slate-200 font-semibold", children: isAvailable ? 'Verified Authentic & In Stock' : 'Out of Stock' })] }), product.category && ((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: "Category" }), (0, jsx_runtime_1.jsx)("span", { className: "text-slate-200 font-semibold", children: String(product.category) })] }))] })) })) : ((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 })] }))] })] }) })] }) }));
|
|
65
151
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deneb-ui/ui",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.78",
|
|
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.78"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
56
|
"react": "^18.0.0 || ^19.0.0",
|