@deneb-ui/ui 2.0.95 → 2.0.96
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/README.md +119 -0
- package/dist/DenebComponentStyles.js +7 -0
- package/dist/EditableCustomerReviews.d.ts +2 -1
- package/dist/EditableCustomerReviews.js +2 -2
- package/dist/EditableFAQAccordion.d.ts +3 -2
- package/dist/EditableFAQAccordion.js +2 -1
- package/dist/EditableGoogleFeedback.js +1 -1
- package/dist/EditableHero.js +2 -2
- package/dist/EditableProductCard.d.ts +15 -71
- package/dist/EditableProductCard.js +176 -27
- package/dist/EditableProductDetail.d.ts +11 -6
- package/dist/EditableProductDetail.js +24 -9
- package/dist/EditableProductGrid.d.ts +4 -1
- package/dist/EditableProductGrid.js +3 -3
- package/dist/EditableProductShowcase.js +1 -1
- package/dist/EditableSection.d.ts +32 -7
- package/dist/EditableSection.js +20 -7
- package/dist/EditableTestimonialSection.js +1 -1
- package/dist/EditableText.d.ts +5 -1
- package/dist/EditableText.js +2 -2
- package/dist/SiteDataProvider.js +16 -5
- package/dist/TrustBadges.js +1 -1
- package/dist/cart/useCart.d.ts +3 -0
- package/dist/cart/useCart.js +20 -9
- package/dist/examples/CompleteStorefrontExample.d.ts +11 -0
- package/dist/examples/CompleteStorefrontExample.js +97 -0
- package/dist/examples/ProductPricingExample.d.ts +9 -0
- package/dist/examples/ProductPricingExample.js +99 -0
- package/dist/examples/SectionLayoutExample.d.ts +7 -0
- package/dist/examples/SectionLayoutExample.js +17 -0
- package/dist/examples/index.d.ts +3 -0
- package/dist/examples/index.js +19 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/utils/productOptions.d.ts +57 -40
- package/dist/utils/productOptions.js +249 -62
- package/package.json +2 -2
|
@@ -2,24 +2,71 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.EditableProductCard = EditableProductCard;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
5
6
|
const EditableText_1 = require("./EditableText");
|
|
6
7
|
const EditableImage_1 = require("./EditableImage");
|
|
7
|
-
const EditableText_2 = require("./EditableText");
|
|
8
8
|
const useCart_1 = require("./cart/useCart");
|
|
9
|
-
|
|
9
|
+
const productOptions_1 = require("./utils/productOptions");
|
|
10
|
+
const COLOR_HEX_MAP = {
|
|
11
|
+
black: '#111827',
|
|
12
|
+
white: '#ffffff',
|
|
13
|
+
red: '#ef4444',
|
|
14
|
+
blue: '#3b82f6',
|
|
15
|
+
green: '#22c55e',
|
|
16
|
+
yellow: '#eab308',
|
|
17
|
+
orange: '#f97316',
|
|
18
|
+
purple: '#a855f7',
|
|
19
|
+
pink: '#ec4899',
|
|
20
|
+
navy: '#1e3a8a',
|
|
21
|
+
grey: '#6b7280',
|
|
22
|
+
gray: '#6b7280',
|
|
23
|
+
silver: '#d1d5db',
|
|
24
|
+
gold: '#f59e0b',
|
|
25
|
+
brown: '#78350f',
|
|
26
|
+
beige: '#f5f5dc',
|
|
27
|
+
maroon: '#800000',
|
|
28
|
+
olive: '#808000',
|
|
29
|
+
teal: '#14b8a6',
|
|
30
|
+
cyan: '#06b6d4',
|
|
31
|
+
rose: '#f43f5e',
|
|
32
|
+
emerald: '#10b981',
|
|
33
|
+
indigo: '#6366f1',
|
|
34
|
+
violet: '#8b5cf6',
|
|
35
|
+
sky: '#0ea5e9',
|
|
36
|
+
amber: '#f59e0b',
|
|
37
|
+
charcoal: '#374151',
|
|
38
|
+
cream: '#fffdd0',
|
|
39
|
+
burgundy: '#800020',
|
|
40
|
+
};
|
|
10
41
|
function WhatsAppIcon({ className = '', style = {} }) {
|
|
11
42
|
return ((0, jsx_runtime_1.jsx)("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "currentColor", className: className, style: { display: 'inline-block', verticalAlign: 'middle', flexShrink: 0, ...style }, "aria-hidden": "true", children: (0, jsx_runtime_1.jsx)("path", { d: "M12.031 0C5.398 0 .02 5.378.02 12.011c0 2.118.552 4.188 1.6 6.009L.055 24l6.16-1.615a11.97 11.97 0 005.816 1.488h.005c6.632 0 12.01-5.378 12.01-12.012 0-3.21-1.25-6.227-3.52-8.497A11.936 11.936 0 0012.031 0zm-.005 21.84a9.92 9.92 0 01-5.06-1.385l-.363-.216-3.762.986 1.004-3.668-.236-.376a9.924 9.924 0 01-1.52-5.37C2.089 6.52 6.549 2.06 12.026 2.06c2.652 0 5.147 1.033 7.02 2.906A9.878 9.878 0 0121.95 12c0 5.48-4.46 9.84-9.924 9.84zm5.438-7.389c-.298-.15-1.764-.87-2.037-.97-.273-.1-.472-.15-.67.15-.199.3-.77 9.7-.945 1.17-.174.199-.348.224-.646.075-.298-.15-1.258-.464-2.397-1.48a8.91 8.91 0 01-1.657-2.057c-.174-.299-.019-.46.13-.61.135-.133.298-.348.447-.522.15-.174.199-.298.298-.498.1-.199.05-.373-.025-.522-.075-.15-.67-1.618-.92-2.215-.243-.582-.49-.503-.67-.512l-.573-.01c-.198 0-.522.075-.795.373-.273.298-1.043 1.02-1.043 2.488s1.068 2.886 1.217 3.085c.15.199 2.102 3.21 5.093 4.502.711.308 1.267.492 1.7.63.715.228 1.365.196 1.88.119.573-.086 1.764-.72 2.012-1.416.248-.696.248-1.293.174-1.417-.075-.124-.273-.199-.572-.348z" }) }));
|
|
12
43
|
}
|
|
13
44
|
function CartIcon({ className = '', style = {} }) {
|
|
14
45
|
return ((0, jsx_runtime_1.jsxs)("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: className, style: { display: 'inline-block', verticalAlign: 'middle', flexShrink: 0, ...style }, "aria-hidden": "true", children: [(0, jsx_runtime_1.jsx)("circle", { cx: "9", cy: "21", r: "1" }), (0, jsx_runtime_1.jsx)("circle", { cx: "20", cy: "21", r: "1" }), (0, jsx_runtime_1.jsx)("path", { d: "M1 1h4l2.68 13.39a2 2 0 002 1.61h9.72a2 2 0 002-1.61L23 6H6" })] }));
|
|
15
46
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
* brand attribution, and strict Fivora visual editing synchronization.
|
|
20
|
-
*/
|
|
21
|
-
function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass', imageFallback, as: Component = 'article', currency = 'LKR', showBrand = true, showPrice = true, showDescription = true, showCategory = true, whatsappNumber = '94770000000', storeName, showWhatsAppButton = true, showAddToCartButton = true, whatsappActionLabel = 'Inquire on WhatsApp', addToCartLabel = 'Add to Cart', actionSlot, actionLabel, actionLabelPath, onAddToCart, onWhatsAppClick, className = '', style, ...props }) {
|
|
47
|
+
function EditableProductCard({ itemPath, product: productProp, item: itemProp, cardVariant = 'modern-glass', imageFallback, as: Component = 'article', currency = 'LKR', showBrand = true, showPrice = true, showDescription = true, showCategory = true, whatsappNumber: whatsappNumberProp, whatsappPhone: whatsappPhoneProp, showOptions, allowInteractiveSwatches, storeName, showWhatsAppButton = true, showAddToCartButton = true, whatsappActionLabel = 'Inquire on WhatsApp', addToCartLabel = 'Add to Cart', actionSlot, actionLabel, actionLabelPath, onAddToCart, onWhatsAppClick, className = '', style, ...props }) {
|
|
48
|
+
const product = (productProp || itemProp || {});
|
|
49
|
+
const whatsappNumber = whatsappPhoneProp || whatsappNumberProp || '94770000000';
|
|
22
50
|
const cart = (0, useCart_1.useOptionalCart)();
|
|
51
|
+
// Dynamic Options, Measurements & Colors resolution
|
|
52
|
+
const resolvedOptions = (0, react_1.useMemo)(() => (0, productOptions_1.resolveProductOptions)(product), [product]);
|
|
53
|
+
const [selectedColor, setSelectedColor] = (0, react_1.useState)('');
|
|
54
|
+
const [selectedOption, setSelectedOption] = (0, react_1.useState)('');
|
|
55
|
+
const [colorImage, setColorImage] = (0, react_1.useState)('');
|
|
56
|
+
// Sync if selection is no longer present in updated product (e.g. during live visual editing)
|
|
57
|
+
(0, react_1.useEffect)(() => {
|
|
58
|
+
if (selectedColor && !resolvedOptions.colors.some((c) => c.toLowerCase() === selectedColor.toLowerCase())) {
|
|
59
|
+
setSelectedColor('');
|
|
60
|
+
setColorImage('');
|
|
61
|
+
}
|
|
62
|
+
}, [product, resolvedOptions.colors]);
|
|
63
|
+
(0, react_1.useEffect)(() => {
|
|
64
|
+
if (selectedOption && !resolvedOptions.options.some((o) => o.toLowerCase() === selectedOption.toLowerCase())) {
|
|
65
|
+
setSelectedOption('');
|
|
66
|
+
}
|
|
67
|
+
}, [product, resolvedOptions.options]);
|
|
68
|
+
// Variant & Dynamic Price Resolution
|
|
69
|
+
const resolvedPrice = (0, react_1.useMemo)(() => (0, productOptions_1.resolveVariantPrice)(product, selectedOption, selectedColor, currency), [product, selectedOption, selectedColor, currency]);
|
|
23
70
|
const titleKey = 'title' in (product || {}) && !('name' in (product || {}) && product.name)
|
|
24
71
|
? 'title'
|
|
25
72
|
: ('productName' in (product || {}) && !('name' in (product || {}) && product.name)
|
|
@@ -28,17 +75,25 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
|
|
|
28
75
|
const name = String(product?.name || product?.title || product?.productName || product?.itemTitle || 'Untitled Product');
|
|
29
76
|
const brand = String(product?.brand || '');
|
|
30
77
|
const rawPriceCandidate = product?.price ?? product?.cost ?? product?.amount ?? product?.productPrice;
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const
|
|
78
|
+
const basePriceNum = typeof rawPriceCandidate === 'number'
|
|
79
|
+
? rawPriceCandidate
|
|
80
|
+
: parseFloat(String(rawPriceCandidate || '').replace(/[^0-9.]/g, '')) || 0;
|
|
81
|
+
const baseFormattedPrice = rawPriceCandidate !== undefined && rawPriceCandidate !== null && String(rawPriceCandidate).trim() !== ''
|
|
82
|
+
? typeof rawPriceCandidate === 'string' &&
|
|
83
|
+
(rawPriceCandidate.includes('LKR') || rawPriceCandidate.includes('-') || rawPriceCandidate.includes('–'))
|
|
84
|
+
? rawPriceCandidate
|
|
85
|
+
: (0, useCart_1.formatCurrency)(basePriceNum, currency)
|
|
86
|
+
: '';
|
|
87
|
+
const displayPrice = resolvedPrice.formattedPrice || baseFormattedPrice;
|
|
88
|
+
const hasPrice = showPrice && Boolean(displayPrice && displayPrice.trim() !== '');
|
|
35
89
|
const priceKey = 'cost' in (product || {}) && !('price' in (product || {}) && product.price !== undefined)
|
|
36
90
|
? 'cost'
|
|
37
91
|
: ('amount' in (product || {}) && !('price' in (product || {}) && product.price !== undefined)
|
|
38
92
|
? 'amount'
|
|
39
93
|
: 'price');
|
|
40
94
|
const rawOriginalPrice = product?.originalPrice ?? product?.compareAtPrice;
|
|
41
|
-
const
|
|
95
|
+
const baseOriginalPrice = rawOriginalPrice !== undefined && rawOriginalPrice !== null ? String(rawOriginalPrice) : '';
|
|
96
|
+
const displayOriginalPrice = resolvedPrice.formattedOriginalPrice || baseOriginalPrice;
|
|
42
97
|
const originalPriceKey = 'compareAtPrice' in (product || {}) && !('originalPrice' in (product || {}) && product.originalPrice !== undefined)
|
|
43
98
|
? 'compareAtPrice'
|
|
44
99
|
: 'originalPrice';
|
|
@@ -50,21 +105,68 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
|
|
|
50
105
|
const badgeKey = 'tag' in (product || {}) && !('badge' in (product || {}) && product.badge) ? 'tag' : 'badge';
|
|
51
106
|
const badge = String(product?.badge || product?.tag || '');
|
|
52
107
|
const fallbackImage = imageFallback || 'https://images.unsplash.com/photo-1542291026-7eec264c27ff?auto=format&fit=crop&w=800&q=80';
|
|
53
|
-
const rawImage = product?.imageUrl ||
|
|
54
|
-
|
|
108
|
+
const rawImage = product?.imageUrl ||
|
|
109
|
+
product?.image ||
|
|
110
|
+
product?.photo ||
|
|
111
|
+
product?.thumbnail ||
|
|
112
|
+
product?.productImage ||
|
|
113
|
+
(Array.isArray(product?.gallery) && product.gallery[0]) ||
|
|
114
|
+
(Array.isArray(product?.images) && product.images[0]);
|
|
115
|
+
const baseImageUrl = String(rawImage || fallbackImage);
|
|
116
|
+
// Active image: clicked color image -> resolved variant image -> product base image
|
|
117
|
+
const currentImage = colorImage || resolvedPrice.variantImage || baseImageUrl;
|
|
55
118
|
const imageKey = 'image' in (product || {}) && !('imageUrl' in (product || {}) && product.imageUrl)
|
|
56
119
|
? 'image'
|
|
57
120
|
: ('photo' in (product || {}) && !('imageUrl' in (product || {}) && product.imageUrl)
|
|
58
121
|
? 'photo'
|
|
59
122
|
: 'imageUrl');
|
|
60
|
-
// Resolved phone number for WhatsApp
|
|
61
123
|
const resolvedPhone = String(product?.whatsappNumber || whatsappNumber || '94770000000');
|
|
62
124
|
const resolvedWhatsAppText = String(product?.whatsappButtonText || whatsappActionLabel);
|
|
63
125
|
const resolvedAddToCartText = String(product?.addToCartButtonText || addToCartLabel);
|
|
64
126
|
const isHorizontal = cardVariant === 'horizontal';
|
|
127
|
+
const handleColorClick = (c, e) => {
|
|
128
|
+
e.stopPropagation();
|
|
129
|
+
if (selectedColor.toLowerCase() === c.name.toLowerCase()) {
|
|
130
|
+
setSelectedColor('');
|
|
131
|
+
setColorImage('');
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
setSelectedColor(c.name);
|
|
135
|
+
if (c.image) {
|
|
136
|
+
setColorImage(c.image);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
const v = product.variants?.find((item) => String(item.color || '').trim().toLowerCase() === c.name.toLowerCase() &&
|
|
140
|
+
(item.image || item.imageUrl || item.photo));
|
|
141
|
+
if (v) {
|
|
142
|
+
setColorImage(v.image || v.imageUrl || v.photo);
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
setColorImage('');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
const handleOptionClick = (opt, e) => {
|
|
151
|
+
e.stopPropagation();
|
|
152
|
+
if (selectedOption.toLowerCase() === opt.toLowerCase()) {
|
|
153
|
+
setSelectedOption('');
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
setSelectedOption(opt);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
65
159
|
const handleWhatsAppClick = (e) => {
|
|
66
160
|
e.stopPropagation();
|
|
67
|
-
const url = (0, useCart_1.getProductWhatsAppUrl)({
|
|
161
|
+
const url = (0, useCart_1.getProductWhatsAppUrl)({
|
|
162
|
+
...product,
|
|
163
|
+
name,
|
|
164
|
+
brand,
|
|
165
|
+
price: displayPrice,
|
|
166
|
+
size: selectedOption || undefined,
|
|
167
|
+
color: selectedColor || undefined,
|
|
168
|
+
option: selectedOption || undefined,
|
|
169
|
+
}, resolvedPhone, { storeName, currency });
|
|
68
170
|
if (onWhatsAppClick) {
|
|
69
171
|
onWhatsAppClick(product, url);
|
|
70
172
|
}
|
|
@@ -74,13 +176,19 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
|
|
|
74
176
|
};
|
|
75
177
|
const handleAddToCartClick = (e) => {
|
|
76
178
|
e.stopPropagation();
|
|
179
|
+
const effectivePrice = resolvedPrice.numericPrice || basePriceNum;
|
|
180
|
+
const variantSuffix = [selectedColor, selectedOption].filter(Boolean).join('-');
|
|
77
181
|
const itemToAdd = {
|
|
78
|
-
id: String(product?.id || name.toLowerCase().replace(/\s+/g, '-'))
|
|
182
|
+
id: String(product?.id || name.toLowerCase().replace(/\s+/g, '-')) +
|
|
183
|
+
(variantSuffix ? `-${variantSuffix}` : ''),
|
|
79
184
|
name,
|
|
80
185
|
brand,
|
|
81
|
-
price:
|
|
82
|
-
image:
|
|
186
|
+
price: effectivePrice,
|
|
187
|
+
image: currentImage,
|
|
83
188
|
quantity: 1,
|
|
189
|
+
size: selectedOption || undefined,
|
|
190
|
+
color: selectedColor || undefined,
|
|
191
|
+
option: selectedOption || undefined,
|
|
84
192
|
};
|
|
85
193
|
if (cart) {
|
|
86
194
|
cart.addItem(itemToAdd);
|
|
@@ -138,7 +246,7 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
|
|
|
138
246
|
overflow: 'hidden',
|
|
139
247
|
width: isHorizontal ? '40%' : '100%',
|
|
140
248
|
flexShrink: 0,
|
|
141
|
-
}, children: [(0, jsx_runtime_1.jsx)(EditableImage_1.EditableImage, { id: `${itemPath}.${imageKey}`, "data-preview-field-path": `${itemPath}.${imageKey}`, src:
|
|
249
|
+
}, children: [(0, jsx_runtime_1.jsx)(EditableImage_1.EditableImage, { id: `${itemPath}.${imageKey}`, "data-preview-field-path": `${itemPath}.${imageKey}`, src: currentImage, 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_1.EditableBadge, { id: `${itemPath}.${badgeKey}`, "data-preview-field-path": `${itemPath}.${badgeKey}`, defaultValue: badge, badgeVariant: "primary" }) }))] }), (0, jsx_runtime_1.jsxs)("div", { style: {
|
|
142
250
|
padding: '1.25rem',
|
|
143
251
|
display: 'flex',
|
|
144
252
|
flexDirection: 'column',
|
|
@@ -170,28 +278,69 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
|
|
|
170
278
|
fontSize: '0.875rem',
|
|
171
279
|
color: 'var(--muted-text, #94a3b8)',
|
|
172
280
|
lineHeight: 1.5,
|
|
173
|
-
marginBottom: '0.
|
|
281
|
+
marginBottom: '0.625rem',
|
|
174
282
|
display: '-webkit-box',
|
|
175
283
|
WebkitLineClamp: 2,
|
|
176
284
|
WebkitBoxOrient: 'vertical',
|
|
177
285
|
overflow: 'hidden',
|
|
178
|
-
} })) : null] }), (0, jsx_runtime_1.
|
|
286
|
+
} })) : null, resolvedOptions.detailedColors.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { style: { marginTop: '0.5rem', marginBottom: '0.375rem' }, children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '0.25rem' }, children: [(0, jsx_runtime_1.jsx)("span", { style: { fontSize: '0.7rem', fontWeight: 600, color: 'var(--muted-text, #94a3b8)', textTransform: 'uppercase', letterSpacing: '0.04em' }, children: product.colorsLabel ? String(product.colorsLabel) : 'Color' }), selectedColor ? ((0, jsx_runtime_1.jsx)("span", { style: { fontSize: '0.72rem', fontWeight: 700, color: 'var(--brand-accent, #a3e635)' }, children: selectedColor })) : null] }), (0, jsx_runtime_1.jsx)("div", { style: { display: 'flex', flexWrap: 'wrap', gap: '0.375rem', alignItems: 'center' }, children: resolvedOptions.detailedColors.map((c) => {
|
|
287
|
+
const isSelected = selectedColor.toLowerCase() === c.name.toLowerCase();
|
|
288
|
+
const colorHex = c.hex || COLOR_HEX_MAP[c.name.toLowerCase()] || '#64748b';
|
|
289
|
+
const isLight = colorHex.toLowerCase() === '#ffffff' || colorHex.toLowerCase() === '#fff' || colorHex.toLowerCase() === '#fffdd0' || colorHex.toLowerCase() === '#f5f5dc';
|
|
290
|
+
return ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: (e) => handleColorClick(c, e), title: c.name, "aria-label": `Select color ${c.name}`, style: {
|
|
291
|
+
width: '20px',
|
|
292
|
+
height: '20px',
|
|
293
|
+
borderRadius: '9999px',
|
|
294
|
+
backgroundColor: colorHex,
|
|
295
|
+
border: isLight ? '1px solid #cbd5e1' : '1px solid rgba(255, 255, 255, 0.2)',
|
|
296
|
+
outline: isSelected ? '2px solid var(--brand-accent, #a3e635)' : 'none',
|
|
297
|
+
outlineOffset: '2px',
|
|
298
|
+
cursor: 'pointer',
|
|
299
|
+
padding: 0,
|
|
300
|
+
display: 'flex',
|
|
301
|
+
alignItems: 'center',
|
|
302
|
+
justifyContent: 'center',
|
|
303
|
+
transition: 'transform 0.15s ease, outline 0.15s ease',
|
|
304
|
+
transform: isSelected ? 'scale(1.15)' : 'scale(1)',
|
|
305
|
+
boxShadow: isSelected ? '0 0 8px rgba(163, 230, 53, 0.4)' : '0 1px 2px rgba(0,0,0,0.1)',
|
|
306
|
+
} }, c.name));
|
|
307
|
+
}) })] })), resolvedOptions.options.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { style: { marginTop: '0.375rem', marginBottom: '0.5rem' }, children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '0.25rem' }, children: [(0, jsx_runtime_1.jsx)("span", { style: { fontSize: '0.7rem', fontWeight: 600, color: 'var(--muted-text, #94a3b8)', textTransform: 'uppercase', letterSpacing: '0.04em' }, children: product.sizesLabel || product.optionsLabel ? String(product.sizesLabel || product.optionsLabel) : resolvedOptions.optionsLabel }), selectedOption ? ((0, jsx_runtime_1.jsx)("span", { style: { fontSize: '0.72rem', fontWeight: 700, color: 'var(--brand-accent, #a3e635)' }, children: resolvedOptions.formatSelectedDisplay(selectedOption) })) : null] }), (0, jsx_runtime_1.jsx)("div", { style: { display: 'flex', flexWrap: 'wrap', gap: '0.35rem' }, children: resolvedOptions.options.map((opt) => {
|
|
308
|
+
const isSelected = selectedOption.toLowerCase() === opt.toLowerCase();
|
|
309
|
+
return ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: (e) => handleOptionClick(opt, e), style: {
|
|
310
|
+
padding: '2px 8px',
|
|
311
|
+
borderRadius: '6px',
|
|
312
|
+
fontSize: '0.72rem',
|
|
313
|
+
fontWeight: isSelected ? 700 : 500,
|
|
314
|
+
cursor: 'pointer',
|
|
315
|
+
border: isSelected
|
|
316
|
+
? '1px solid var(--brand-accent, #a3e635)'
|
|
317
|
+
: '1px solid var(--card-border, rgba(226, 232, 240, 0.4))',
|
|
318
|
+
backgroundColor: isSelected
|
|
319
|
+
? 'var(--brand-accent, #a3e635)'
|
|
320
|
+
: 'var(--tag-bg, rgba(255, 255, 255, 0.08))',
|
|
321
|
+
color: isSelected
|
|
322
|
+
? '#020617'
|
|
323
|
+
: 'var(--muted-text, #e2e8f0)',
|
|
324
|
+
transition: 'all 0.15s ease',
|
|
325
|
+
transform: isSelected ? 'scale(1.03)' : 'scale(1)',
|
|
326
|
+
}, children: resolvedOptions.formatOption(opt) }, opt));
|
|
327
|
+
}) })] }))] }), (0, jsx_runtime_1.jsxs)("div", { style: {
|
|
179
328
|
marginTop: '0.75rem',
|
|
180
329
|
paddingTop: '0.75rem',
|
|
181
330
|
borderTop: cardVariant === 'minimal' ? 'none' : '1px solid var(--card-border, var(--color-border, rgba(226, 232, 240, 0.7)))',
|
|
182
331
|
display: 'flex',
|
|
183
332
|
flexDirection: 'column',
|
|
184
333
|
gap: '0.75rem',
|
|
185
|
-
}, children: [hasPrice ? ((0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', alignItems: 'baseline', gap: '0.5rem', flexWrap: 'wrap' }, children: [(0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.${priceKey}`, "data-preview-field-path": `${itemPath}.${priceKey}`, defaultValue:
|
|
186
|
-
fontSize: '1.
|
|
334
|
+
}, children: [hasPrice ? ((0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', alignItems: 'baseline', gap: '0.5rem', flexWrap: 'wrap' }, children: [(0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.${priceKey}`, "data-preview-field-path": `${itemPath}.${priceKey}`, defaultValue: displayPrice, style: {
|
|
335
|
+
fontSize: '1.25rem',
|
|
187
336
|
fontWeight: 800,
|
|
188
337
|
color: 'var(--brand-color, #ffffff)',
|
|
189
338
|
letterSpacing: '-0.02em',
|
|
190
|
-
} }),
|
|
339
|
+
} }), displayOriginalPrice ? ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.${originalPriceKey}`, "data-preview-field-path": `${itemPath}.${originalPriceKey}`, defaultValue: displayOriginalPrice, style: {
|
|
191
340
|
fontSize: '0.875rem',
|
|
192
341
|
textDecoration: 'line-through',
|
|
193
342
|
color: 'var(--muted-text, #94a3b8)',
|
|
194
|
-
} })) : null, product?.measurement ? ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.measurement`, "data-preview-field-path": `${itemPath}.measurement`, defaultValue: `/ ${String(product.measurement)}`, style: {
|
|
343
|
+
} })) : null, product?.measurement && !selectedOption ? ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.measurement`, "data-preview-field-path": `${itemPath}.measurement`, defaultValue: `/ ${String(product.measurement)}`, style: {
|
|
195
344
|
fontSize: '0.8rem',
|
|
196
345
|
fontWeight: 500,
|
|
197
346
|
color: 'var(--muted-text, #64748b)',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { MeasurementUnit } from './utils/productOptions';
|
|
2
|
+
import { MeasurementUnit, ProductVariant } from './utils/productOptions';
|
|
3
3
|
export interface ProductDetailItem {
|
|
4
4
|
id?: string | number;
|
|
5
5
|
name?: string;
|
|
@@ -45,6 +45,13 @@ export interface ProductDetailItem {
|
|
|
45
45
|
}> | string;
|
|
46
46
|
colorsText?: string;
|
|
47
47
|
colorsLabel?: string;
|
|
48
|
+
variants?: ProductVariant[];
|
|
49
|
+
variantPrices?: Record<string, number | string>;
|
|
50
|
+
minPrice?: string | number;
|
|
51
|
+
maxPrice?: string | number;
|
|
52
|
+
priceMin?: string | number;
|
|
53
|
+
priceMax?: string | number;
|
|
54
|
+
priceRange?: [number | string, number | string] | string;
|
|
48
55
|
[key: string]: unknown;
|
|
49
56
|
}
|
|
50
57
|
export interface EditableProductDetailProps extends React.HTMLAttributes<HTMLElement> {
|
|
@@ -88,12 +95,10 @@ export interface EditableProductDetailProps extends React.HTMLAttributes<HTMLEle
|
|
|
88
95
|
* - Truly Adaptive: Seamlessly renders shoes/apparel (sizes), liquids/cosmetics (ml, L),
|
|
89
96
|
* food/groceries (g, kg), single-dimension items, and simple products without variants.
|
|
90
97
|
* - Multi-image gallery with active thumbnail selector and basePath resolution.
|
|
91
|
-
* - Dynamic color swatches with optional color-to-image auto-switching.
|
|
98
|
+
* - Dynamic color swatches with optional color-to-image auto-switching and variant pricing.
|
|
99
|
+
* - Fixed prices vs price ranges (e.g., LKR 2,500 – LKR 4,500).
|
|
92
100
|
* - Floating badges with conditional rendering (zero hidden marker contract violations).
|
|
93
101
|
* - Live synchronized field paths for Title, Price, Description, CTAs, and Policies.
|
|
94
|
-
* - Direct WhatsApp
|
|
95
|
-
* - Context-aware specifications and Shipping & Returns tabs.
|
|
96
|
-
*
|
|
97
|
-
* Created by Chamika Gayashan & Induranga Kawishwara
|
|
102
|
+
* - Direct WhatsApp order link with dynamic variant & option injection.
|
|
98
103
|
*/
|
|
99
104
|
export declare function EditableProductDetail({ sectionPath, product, sizes, colors, onAddToSelection, whatsappUrl, className, style, ...props }: EditableProductDetailProps): React.JSX.Element;
|
|
@@ -14,13 +14,11 @@ const urls_1 = require("./utils/urls");
|
|
|
14
14
|
* - Truly Adaptive: Seamlessly renders shoes/apparel (sizes), liquids/cosmetics (ml, L),
|
|
15
15
|
* food/groceries (g, kg), single-dimension items, and simple products without variants.
|
|
16
16
|
* - Multi-image gallery with active thumbnail selector and basePath resolution.
|
|
17
|
-
* - Dynamic color swatches with optional color-to-image auto-switching.
|
|
17
|
+
* - Dynamic color swatches with optional color-to-image auto-switching and variant pricing.
|
|
18
|
+
* - Fixed prices vs price ranges (e.g., LKR 2,500 – LKR 4,500).
|
|
18
19
|
* - Floating badges with conditional rendering (zero hidden marker contract violations).
|
|
19
20
|
* - Live synchronized field paths for Title, Price, Description, CTAs, and Policies.
|
|
20
|
-
* - Direct WhatsApp
|
|
21
|
-
* - Context-aware specifications and Shipping & Returns tabs.
|
|
22
|
-
*
|
|
23
|
-
* Created by Chamika Gayashan & Induranga Kawishwara
|
|
21
|
+
* - Direct WhatsApp order link with dynamic variant & option injection.
|
|
24
22
|
*/
|
|
25
23
|
function EditableProductDetail({ sectionPath = 'product', product, sizes, colors, onAddToSelection, whatsappUrl, className = '', style, ...props }) {
|
|
26
24
|
// 1. Resolve Images: Support gallery, images array, and single image fields
|
|
@@ -100,16 +98,33 @@ function EditableProductDetail({ sectionPath = 'product', product, sizes, colors
|
|
|
100
98
|
setSelectedColor('');
|
|
101
99
|
}
|
|
102
100
|
}, [effectiveColors, selectedColor]);
|
|
101
|
+
// Dynamic Price & Variant Resolution
|
|
102
|
+
const resolvedPrice = (0, react_1.useMemo)(() => (0, productOptions_1.resolveVariantPrice)(product, selectedSize, selectedColor), [product, selectedSize, selectedColor]);
|
|
103
|
+
// Sync variant image if variant has a dedicated image
|
|
104
|
+
(0, react_1.useEffect)(() => {
|
|
105
|
+
if (resolvedPrice.variantImage && resolvedPrice.variantImage !== activeImage) {
|
|
106
|
+
setActiveImage(resolvedPrice.variantImage);
|
|
107
|
+
}
|
|
108
|
+
}, [resolvedPrice.variantImage]);
|
|
103
109
|
const handleSelectColor = (c) => {
|
|
104
110
|
setSelectedColor(c.name);
|
|
105
111
|
if (c.image) {
|
|
106
112
|
setActiveImage(c.image);
|
|
107
113
|
}
|
|
114
|
+
else {
|
|
115
|
+
const v = product.variants?.find((item) => String(item.color || '').trim().toLowerCase() === c.name.toLowerCase() &&
|
|
116
|
+
(item.image || item.imageUrl || item.photo));
|
|
117
|
+
if (v) {
|
|
118
|
+
setActiveImage(v.image || v.imageUrl || v.photo);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
108
121
|
};
|
|
109
122
|
const name = String(product.name || product.title || product.productName || product.itemTitle || 'Product Title');
|
|
110
123
|
const rawPriceCandidate = product.price ?? product.cost ?? product.amount ?? product.productPrice;
|
|
111
|
-
const
|
|
124
|
+
const basePrice = rawPriceCandidate !== undefined && rawPriceCandidate !== null ? String(rawPriceCandidate) : 'LKR 0';
|
|
112
125
|
const originalPrice = product.originalPrice ?? product.compareAtPrice;
|
|
126
|
+
const displayPrice = resolvedPrice.formattedPrice || basePrice;
|
|
127
|
+
const displayOriginalPrice = resolvedPrice.formattedOriginalPrice || (originalPrice ? String(originalPrice) : undefined);
|
|
113
128
|
const isAvailable = product.isAvailable !== false;
|
|
114
129
|
const description = String(product.description || '');
|
|
115
130
|
const badge = String(product.badge || '');
|
|
@@ -120,7 +135,7 @@ function EditableProductDetail({ sectionPath = 'product', product, sizes, colors
|
|
|
120
135
|
const shippingReturns = String(product.shippingReturns || '14-day hassle-free exchanges for unworn items in original packaging.');
|
|
121
136
|
const orderSnippet = resolved.formatOrderSnippet(effectiveOptions.length > 0 ? selectedSize : undefined, effectiveColors.length > 0 ? selectedColor : undefined);
|
|
122
137
|
const resolvedWhatsappUrl = whatsappUrl || (product.whatsappNumber
|
|
123
|
-
? (0, urls_1.createWhatsAppUrl)(product.whatsappNumber, product.whatsappMessage || `Hi, I would like to order ${name}${orderSnippet ? ` ${orderSnippet}` : ''} - ${
|
|
138
|
+
? (0, urls_1.createWhatsAppUrl)(product.whatsappNumber, product.whatsappMessage || `Hi, I would like to order ${name}${orderSnippet ? ` ${orderSnippet}` : ''} - ${displayPrice}`)
|
|
124
139
|
: '');
|
|
125
140
|
// Dynamic Specs: Use explicit specs if provided, else fallback to available product metadata
|
|
126
141
|
const effectiveSpecs = (0, react_1.useMemo)(() => {
|
|
@@ -144,9 +159,9 @@ function EditableProductDetail({ sectionPath = 'product', product, sizes, colors
|
|
|
144
159
|
? 'border-lime-400 scale-98 shadow-md ring-2 ring-lime-400/20'
|
|
145
160
|
: '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
|
|
146
161
|
? 'bg-emerald-500/15 text-emerald-300'
|
|
147
|
-
: '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:
|
|
162
|
+
: '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: displayPrice }), displayOriginalPrice ? ((0, jsx_runtime_1.jsx)("span", { className: "text-lg font-medium text-slate-500 line-through", children: String(displayOriginalPrice) })) : 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
|
|
148
163
|
? 'border-lime-400 ring-2 ring-lime-400/30 scale-105'
|
|
149
164
|
: '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
|
|
150
165
|
? 'bg-white text-slate-950 shadow-md font-extrabold scale-102 ring-2 ring-white/20'
|
|
151
|
-
: '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 })] }))] })] }) })] }) }));
|
|
166
|
+
: '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, price: resolvedPrice.numericPrice || product.price }, 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 })] }))] })] }) })] }) }));
|
|
152
167
|
}
|
|
@@ -111,6 +111,9 @@ export interface EditableProductGridProps extends React.HTMLAttributes<HTMLEleme
|
|
|
111
111
|
* Total products count override when backend performs server-side pagination slicing.
|
|
112
112
|
*/
|
|
113
113
|
totalProducts?: number;
|
|
114
|
+
currency?: string;
|
|
115
|
+
whatsappNumber?: string;
|
|
116
|
+
whatsappPhone?: string;
|
|
114
117
|
className?: string;
|
|
115
118
|
}
|
|
116
119
|
/**
|
|
@@ -121,6 +124,6 @@ export interface EditableProductGridProps extends React.HTMLAttributes<HTMLEleme
|
|
|
121
124
|
*
|
|
122
125
|
* Created by Chamika Gayashan & Induranga Kawishwara
|
|
123
126
|
*/
|
|
124
|
-
export declare function EditableProductGrid({ sectionPath, listPath, title, subtitle, products: userProducts, categories, cardVariant, columns, onQuickView, cardPrefix, showSearch, searchPlaceholder, enableBackendSearch, onSearchChange, enablePagination, pageSize, pageSizeOptions, showPageSizeSelector, paginationVariant, hidePaginationOnSinglePage, currentPage: controlledPage, initialPage, onPageChange, scrollToTopOnPageChange, totalProducts, className, style, ...props }: EditableProductGridProps): React.JSX.Element;
|
|
127
|
+
export declare function EditableProductGrid({ currency, whatsappNumber, whatsappPhone, sectionPath, listPath, title, subtitle, products: userProducts, categories, cardVariant, columns, onQuickView, cardPrefix, showSearch, searchPlaceholder, enableBackendSearch, onSearchChange, enablePagination, pageSize, pageSizeOptions, showPageSizeSelector, paginationVariant, hidePaginationOnSinglePage, currentPage: controlledPage, initialPage, onPageChange, scrollToTopOnPageChange, totalProducts, className, style, ...props }: EditableProductGridProps): React.JSX.Element;
|
|
125
128
|
export declare const ProductGrid: typeof EditableProductGrid;
|
|
126
129
|
export type ProductGridItem = ProductItem;
|
|
@@ -14,7 +14,7 @@ const SiteDataProvider_1 = require("./SiteDataProvider");
|
|
|
14
14
|
*
|
|
15
15
|
* Created by Chamika Gayashan & Induranga Kawishwara
|
|
16
16
|
*/
|
|
17
|
-
function EditableProductGrid({ sectionPath = 'home', listPath = 'products', title = 'Featured Collection', subtitle = 'Just Dropped', products: userProducts, categories = ['All'], cardVariant = 'modern-glass', columns = { mobile: 1, tablet: 2, desktop: 4 }, onQuickView, cardPrefix = 'product', showSearch = true, searchPlaceholder = 'Search products by name, brand, or tag...', enableBackendSearch = true, onSearchChange, enablePagination = true, pageSize = 8, pageSizeOptions = [8, 16, 24, 48], showPageSizeSelector = false, paginationVariant = 'numbers', hidePaginationOnSinglePage = true, currentPage: controlledPage, initialPage = 1, onPageChange, scrollToTopOnPageChange = true, totalProducts, className = '', style, ...props }) {
|
|
17
|
+
function EditableProductGrid({ currency = 'LKR', whatsappNumber, whatsappPhone, sectionPath = 'home', listPath = 'products', title = 'Featured Collection', subtitle = 'Just Dropped', products: userProducts, categories = ['All'], cardVariant = 'modern-glass', columns = { mobile: 1, tablet: 2, desktop: 4 }, onQuickView, cardPrefix = 'product', showSearch = true, searchPlaceholder = 'Search products by name, brand, or tag...', enableBackendSearch = true, onSearchChange, enablePagination = true, pageSize = 8, pageSizeOptions = [8, 16, 24, 48], showPageSizeSelector = false, paginationVariant = 'numbers', hidePaginationOnSinglePage = true, currentPage: controlledPage, initialPage = 1, onPageChange, scrollToTopOnPageChange = true, totalProducts, className = '', style, ...props }) {
|
|
18
18
|
const sectionRef = (0, react_1.useRef)(null);
|
|
19
19
|
const siteData = (0, SiteDataProvider_1.useSiteData)();
|
|
20
20
|
const siteApi = (0, SiteDataProvider_1.useSiteApi)();
|
|
@@ -203,7 +203,7 @@ function EditableProductGrid({ sectionPath = 'home', listPath = 'products', titl
|
|
|
203
203
|
return `${mClass} ${tClass} ${dClass}`;
|
|
204
204
|
}, [columns]);
|
|
205
205
|
const shouldShowPagination = enablePagination && !(hidePaginationOnSinglePage && totalPages <= 1);
|
|
206
|
-
return ((0, jsx_runtime_1.jsxs)("section", { ref: sectionRef, "data-preview-page-key": sectionPath, className: `editable-product-grid 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: "flex flex-col md:flex-row md:items-end justify-between mb-8 gap-6", children: [(0, jsx_runtime_1.jsxs)("div", { children: [subtitle && ((0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.gridSubtitle`, className: "text-xs font-black tracking-widest uppercase text-emerald-600 dark:text-lime-400 block mb-2", children: subtitle })), (0, jsx_runtime_1.jsx)("h2", { "data-preview-field-path": `${sectionPath}.gridTitle`, className: "text-3xl sm:text-4xl font-extrabold tracking-tight text-slate-900 dark:text-white leading-tight", children: title })] }), resolvedCategories.length > 1 && ((0, jsx_runtime_1.jsx)("div", { className: "flex flex-wrap items-center gap-2", children: resolvedCategories.map((cat) => {
|
|
206
|
+
return ((0, jsx_runtime_1.jsxs)("section", { id: props.id || "products", ref: sectionRef, "data-design-section": props["data-design-section"] || "products", "data-section-id": props["data-section-id"] || "products", "data-preview-page-key": sectionPath, className: `editable-product-grid 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: "flex flex-col md:flex-row md:items-end justify-between mb-8 gap-6", children: [(0, jsx_runtime_1.jsxs)("div", { children: [subtitle && ((0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.gridSubtitle`, className: "text-xs font-black tracking-widest uppercase text-emerald-600 dark:text-lime-400 block mb-2", children: subtitle })), (0, jsx_runtime_1.jsx)("h2", { "data-preview-field-path": `${sectionPath}.gridTitle`, className: "text-3xl sm:text-4xl font-extrabold tracking-tight text-slate-900 dark:text-white leading-tight", children: title })] }), resolvedCategories.length > 1 && ((0, jsx_runtime_1.jsx)("div", { className: "flex flex-wrap items-center gap-2", children: resolvedCategories.map((cat) => {
|
|
207
207
|
const isActive = activeCategory.toLowerCase() === cat.toLowerCase();
|
|
208
208
|
return ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setActiveCategory(cat), className: `px-4 py-2 rounded-xl text-xs font-bold transition-all duration-200 ${isActive
|
|
209
209
|
? 'bg-slate-900 text-white dark:bg-white dark:text-slate-950 shadow-md scale-102 font-extrabold'
|
|
@@ -226,7 +226,7 @@ function EditableProductGrid({ sectionPath = 'home', listPath = 'products', titl
|
|
|
226
226
|
const itemPath = resolvedListPath
|
|
227
227
|
? `${resolvedListPath}[${effectiveIndex}]`
|
|
228
228
|
: `${sectionPath}.${cardPrefix}${effectiveIndex + 1}`;
|
|
229
|
-
return ((0, jsx_runtime_1.jsxs)("div", { "data-preview-item-path": itemPath, className: "relative group", children: [(0, jsx_runtime_1.jsx)(EditableProductCard_1.EditableProductCard, { itemPath: itemPath, product: product, cardVariant: cardVariant, className: "h-full" }), onQuickView && ((0, jsx_runtime_1.jsx)("div", { className: "absolute top-4 right-4 z-20 opacity-0 group-hover:opacity-100 transition-opacity duration-200", children: (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => onQuickView(product, itemPath), className: "p-2.5 rounded-xl bg-slate-950/80 backdrop-blur-md text-white hover:bg-lime-400 hover:text-slate-950 shadow-lg transition-all active:scale-95", title: "Quick View", "aria-label": `Quick View ${product.name || product.title}`, children: (0, jsx_runtime_1.jsxs)("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: [(0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 12a3 3 0 11-6 0 3 3 0 016 0z" }), (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" })] }) }) }))] }, product.id || idx));
|
|
229
|
+
return ((0, jsx_runtime_1.jsxs)("div", { "data-preview-item-path": itemPath, className: "relative group", children: [(0, jsx_runtime_1.jsx)(EditableProductCard_1.EditableProductCard, { itemPath: itemPath, product: product, cardVariant: cardVariant, currency: currency, whatsappPhone: whatsappPhone || whatsappNumber, className: "h-full" }), onQuickView && ((0, jsx_runtime_1.jsx)("div", { className: "absolute top-4 right-4 z-20 opacity-0 group-hover:opacity-100 transition-opacity duration-200", children: (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => onQuickView(product, itemPath), className: "p-2.5 rounded-xl bg-slate-950/80 backdrop-blur-md text-white hover:bg-lime-400 hover:text-slate-950 shadow-lg transition-all active:scale-95", title: "Quick View", "aria-label": `Quick View ${product.name || product.title}`, children: (0, jsx_runtime_1.jsxs)("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: [(0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 12a3 3 0 11-6 0 3 3 0 016 0z" }), (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" })] }) }) }))] }, product.id || idx));
|
|
230
230
|
})) : (
|
|
231
231
|
/* Empty State — strictly inside the listPath container */
|
|
232
232
|
(0, jsx_runtime_1.jsxs)("div", { className: "text-center py-16 px-4 rounded-3xl border border-dashed border-slate-300 dark:border-slate-800 bg-slate-50/50 dark:bg-slate-900/30 w-full", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-12 h-12 mx-auto mb-4 rounded-2xl bg-slate-100 dark:bg-slate-800 flex items-center justify-center text-slate-400", children: (0, jsx_runtime_1.jsx)("svg", { className: "w-6 h-6", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4" }) }) }), (0, jsx_runtime_1.jsx)("p", { className: "text-sm font-semibold text-slate-900 dark:text-white", children: "No products found" }), (0, jsx_runtime_1.jsx)("p", { className: "text-xs text-slate-500 dark:text-slate-400 mt-1 max-w-sm mx-auto", children: searchQuery
|
|
@@ -180,7 +180,7 @@ function EditableProductShowcase({ sectionPath = 'home', listPath = 'featuredPho
|
|
|
180
180
|
window.open(url, '_blank', 'noopener,noreferrer');
|
|
181
181
|
}
|
|
182
182
|
};
|
|
183
|
-
return ((0, jsx_runtime_1.jsxs)("section", { id: "
|
|
183
|
+
return ((0, jsx_runtime_1.jsxs)("section", { id: props.id || "featured-products", "data-design-section": "featured-products", "data-section-id": "featured-products", className: `relative py-20 sm:py-28 overflow-clip bg-white ${className}`, ...props, children: [(0, jsx_runtime_1.jsx)("div", { className: "pointer-events-none absolute top-10 right-10 h-96 w-96 rounded-full bg-cyan-500/10 blur-[120px]" }), (0, jsx_runtime_1.jsx)("div", { className: "pointer-events-none absolute bottom-10 left-10 h-96 w-96 rounded-full bg-blue-600/10 blur-[120px]" }), (0, jsx_runtime_1.jsxs)("div", { className: "container relative z-10 mx-auto px-4 sm:px-6 lg:px-8", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col md:flex-row md:items-end justify-between mb-12 sm:mb-16 gap-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "max-w-2xl", children: [(0, jsx_runtime_1.jsx)("div", { className: "inline-flex items-center gap-2 rounded-full border border-cyan-400/30 bg-cyan-500/10 px-3.5 py-1 text-xs font-semibold uppercase tracking-wider text-cyan-700 mb-4", children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.featuredProductsBadge`, "data-preview-style-target": `${sectionPath}.featuredProductsBadge`, "data-preview-style-type": "text", children: resolvedBadge }) }), (0, jsx_runtime_1.jsx)("h2", { className: "text-3xl sm:text-5xl font-extrabold text-zinc-950 tracking-tight", "data-preview-field-path": `${sectionPath}.featuredProductsHeading`, "data-preview-style-target": `${sectionPath}.featuredProductsHeading`, "data-preview-style-type": "text", children: resolvedHeading }), (0, jsx_runtime_1.jsx)("p", { className: "mt-3 text-sm sm:text-base text-zinc-600 leading-relaxed", "data-preview-field-path": `${sectionPath}.featuredProductsDescription`, "data-preview-style-target": `${sectionPath}.featuredProductsDescription`, "data-preview-style-type": "text", children: resolvedDescription })] }), resolvedCategories.length > 1 && ((0, jsx_runtime_1.jsx)("div", { className: "flex flex-wrap items-center gap-1.5 p-1 rounded-2xl border border-black/[0.08] bg-black/[0.02] backdrop-blur-md self-start md:self-auto", children: resolvedCategories.map((filter) => ((0, jsx_runtime_1.jsx)("button", { type: "button", "data-preview-static": "category-filter-pill", onClick: () => setSelectedFilter(filter), className: `rounded-xl px-3.5 sm:px-4 py-1.5 sm:py-2 text-xs font-semibold transition-all duration-200 cursor-pointer ${selectedFilter === filter
|
|
184
184
|
? 'bg-zinc-950 text-white shadow-md'
|
|
185
185
|
: 'text-zinc-600 hover:text-black hover:bg-black/5'}`, children: filter }, filter))) }))] }), (0, jsx_runtime_1.jsx)("ul", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 sm:gap-8 list-none p-0 m-0", "data-preview-list-path": `${sectionPath}.${listPath}`, "data-preview-style-target": `${sectionPath}.${listPath}.grid`, "data-preview-style-type": "grid", children: filteredProducts.map((phone) => {
|
|
186
186
|
const idx = phone._index;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import { BoxSpacing } from
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { BoxSpacing } from "./EditableBox";
|
|
3
3
|
export interface EditableSectionProps extends React.HTMLAttributes<HTMLElement> {
|
|
4
4
|
as?: React.ElementType;
|
|
5
5
|
/**
|
|
6
|
-
* Required fivora design section identifier (e.g.
|
|
7
|
-
* Automatically sets `data-design-section`
|
|
6
|
+
* Required fivora design section identifier (e.g. "home-hero", "home-features", "products", "testimonials").
|
|
7
|
+
* Automatically sets `data-design-section`, `data-section-id`, and `id` for full editor targeting.
|
|
8
8
|
*/
|
|
9
9
|
name: string;
|
|
10
10
|
/**
|
|
11
|
-
* Vertical section padding (
|
|
11
|
+
* Vertical section padding ("none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" or custom CSS).
|
|
12
12
|
*/
|
|
13
13
|
padding?: BoxSpacing;
|
|
14
14
|
/**
|
|
@@ -27,9 +27,34 @@ export interface EditableSectionProps extends React.HTMLAttributes<HTMLElement>
|
|
|
27
27
|
* Section border style.
|
|
28
28
|
*/
|
|
29
29
|
border?: string | boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Content alignment: "left" | "center" | "right".
|
|
32
|
+
*/
|
|
33
|
+
align?: "left" | "center" | "right";
|
|
34
|
+
/**
|
|
35
|
+
* Quick toggle to center all content and text horizontally.
|
|
36
|
+
*/
|
|
37
|
+
center?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Whether this section is hidden or deleted.
|
|
40
|
+
*/
|
|
41
|
+
hidden?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Visual flexbox order for section reordering (e.g. 1, 2, 3).
|
|
44
|
+
*/
|
|
45
|
+
order?: number | string;
|
|
46
|
+
/**
|
|
47
|
+
* Whether to wrap children in a responsive inner container.
|
|
48
|
+
*/
|
|
49
|
+
container?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Class name for the inner container if container=true.
|
|
52
|
+
*/
|
|
53
|
+
containerClassName?: string;
|
|
30
54
|
}
|
|
31
55
|
/**
|
|
32
56
|
* EditableSection standardizes section spacing and automatically applies the required
|
|
33
|
-
* `data-design-section`
|
|
57
|
+
* `data-design-section` and `data-section-id` markers for 100% fivora contract compliance,
|
|
58
|
+
* with first-class support for section deletion/hiding and instant centering.
|
|
34
59
|
*/
|
|
35
|
-
export declare function EditableSection({ as: Component, name, padding, bg, color, maxWidth, border, className, style, children, ...props }: EditableSectionProps): React.JSX.Element;
|
|
60
|
+
export declare function EditableSection({ as: Component, name, padding, bg, color, maxWidth, border, align, center, hidden, order, container, containerClassName, className, style, id, children, ...props }: EditableSectionProps): React.JSX.Element;
|