@deneb-ui/ui 2.0.57 → 2.0.58
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 +1 -0
- package/dist/EditableProductShowcase.d.ts +91 -0
- package/dist/EditableProductShowcase.js +194 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +5 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -98,6 +98,7 @@ export default function Page() {
|
|
|
98
98
|
| :--- | :--- | :--- | :--- |
|
|
99
99
|
| `ProductCard` | `EditableProductCard` | `data-preview-field-path`, `data-preview-item-path` | Product card with LKR/currency formatting, badge, & WhatsApp CTA |
|
|
100
100
|
| `ProductGrid` | `EditableProductGrid` | `data-preview-list-path`, `data-preview-item-path` | Catalog grid with quick-view modal hook & filter integration |
|
|
101
|
+
| `ProductShowcase` | `EditableProductShowcase` | `data-preview-field-path`, `data-preview-list-path`, `color` swatch | Flagship product showcase with color swatches, filter tabs, quick-view & WhatsApp order |
|
|
101
102
|
| `ProductDetail` | `EditableProductDetail` | `data-preview-page-key`, `data-preview-field-path` | Full single-product view with gallery, specs, & inquiry actions |
|
|
102
103
|
| `ProductQuickView` | `ProductQuickView` | `data-preview-field-path` | Instant lightbox modal product inspection with quantity counter |
|
|
103
104
|
| `CartDrawer` | `EditableCartDrawer` | `data-preview-list-path`, `data-preview-item-path` | Slide-over cart drawer with 1-click unified WhatsApp order compilation |
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface ProductShowcaseColor {
|
|
3
|
+
name: string;
|
|
4
|
+
hex: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ProductShowcaseItem {
|
|
7
|
+
id?: string | number;
|
|
8
|
+
name?: string;
|
|
9
|
+
title?: string;
|
|
10
|
+
brand?: string;
|
|
11
|
+
subtitle?: string;
|
|
12
|
+
price?: string | number;
|
|
13
|
+
compareAtPrice?: string | number;
|
|
14
|
+
originalPrice?: string | number;
|
|
15
|
+
condition?: string;
|
|
16
|
+
category?: string;
|
|
17
|
+
image?: string;
|
|
18
|
+
imageUrl?: string;
|
|
19
|
+
badge?: string;
|
|
20
|
+
colors?: Array<ProductShowcaseColor | string>;
|
|
21
|
+
isAvailable?: boolean;
|
|
22
|
+
[key: string]: unknown;
|
|
23
|
+
}
|
|
24
|
+
export interface EditableProductShowcaseProps extends React.HTMLAttributes<HTMLElement> {
|
|
25
|
+
/**
|
|
26
|
+
* Field path prefix for live Fivora visual editing synchronization (e.g. "home").
|
|
27
|
+
*/
|
|
28
|
+
sectionPath?: string;
|
|
29
|
+
/**
|
|
30
|
+
* List path under sectionPath (default: "featuredPhones").
|
|
31
|
+
*/
|
|
32
|
+
listPath?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Badge / tagline label displayed above the section title.
|
|
35
|
+
*/
|
|
36
|
+
badge?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Section heading text.
|
|
39
|
+
*/
|
|
40
|
+
heading?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Section description text.
|
|
43
|
+
*/
|
|
44
|
+
description?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Products array. If omitted, pulls live products from siteData.
|
|
47
|
+
*/
|
|
48
|
+
products?: ProductShowcaseItem[];
|
|
49
|
+
/**
|
|
50
|
+
* Currency symbol or code (default: "Rs").
|
|
51
|
+
*/
|
|
52
|
+
currency?: string;
|
|
53
|
+
/**
|
|
54
|
+
* Free courier or shipping label (default: "Free Insured Courier").
|
|
55
|
+
*/
|
|
56
|
+
shippingLabel?: string;
|
|
57
|
+
/**
|
|
58
|
+
* WhatsApp button order label (default: "Order via WhatsApp").
|
|
59
|
+
*/
|
|
60
|
+
whatsappOrderLabel?: string;
|
|
61
|
+
/**
|
|
62
|
+
* Category filter list (e.g. ['All', 'Apple', 'Samsung', 'Google', 'Refurbished']).
|
|
63
|
+
* If omitted, derived automatically from product categories/brands.
|
|
64
|
+
*/
|
|
65
|
+
categories?: string[];
|
|
66
|
+
/**
|
|
67
|
+
* Callback when user clicks quick view eye icon.
|
|
68
|
+
*/
|
|
69
|
+
onQuickView?: (product: ProductShowcaseItem, index: number) => void;
|
|
70
|
+
/**
|
|
71
|
+
* Base route for product detail pages (default: "/products/detail").
|
|
72
|
+
* Compatible with Fivora generated-site-product-route.ts middleware.
|
|
73
|
+
*/
|
|
74
|
+
productDetailRoutePrefix?: string;
|
|
75
|
+
className?: string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* EditableProductShowcase
|
|
79
|
+
*
|
|
80
|
+
* Elite, fully editable product showcase section featuring:
|
|
81
|
+
* - Direct showroom badge, section title & description with Fivora live bindings
|
|
82
|
+
* - Category filter pills with active state
|
|
83
|
+
* - Glassmorphism product cards with hover glow and transform transitions
|
|
84
|
+
* - Interactive color swatch buttons and active color label bindings ([DNB-COL-009])
|
|
85
|
+
* - Strikethrough compare-at price ([DNB-COL-009])
|
|
86
|
+
* - Full-width WhatsApp order button with dynamic merchant URL resolution ([DNB-WHA-008])
|
|
87
|
+
* - Guarded image fallback against empty strings ([DNB-IMG-002])
|
|
88
|
+
* - Aligned with Fivora generated-site product routing (/products/detail/?id=...)
|
|
89
|
+
*/
|
|
90
|
+
export declare function EditableProductShowcase({ sectionPath, listPath, badge, heading, description, products: userProducts, currency, shippingLabel, whatsappOrderLabel, categories, onQuickView, productDetailRoutePrefix, className, ...props }: EditableProductShowcaseProps): React.JSX.Element;
|
|
91
|
+
export { EditableProductShowcase as ProductShowcase };
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.EditableProductShowcase = EditableProductShowcase;
|
|
5
|
+
exports.ProductShowcase = EditableProductShowcase;
|
|
6
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
|
+
const react_1 = require("react");
|
|
8
|
+
const SiteDataProvider_1 = require("./SiteDataProvider");
|
|
9
|
+
const DEFAULT_PRODUCTS = [
|
|
10
|
+
{
|
|
11
|
+
id: 'phone-iphone-16-pro',
|
|
12
|
+
name: 'iPhone 16 Pro Max',
|
|
13
|
+
brand: 'Apple',
|
|
14
|
+
subtitle: 'Grade 5 Titanium · A18 Pro 3nm',
|
|
15
|
+
price: 1199,
|
|
16
|
+
originalPrice: 1299,
|
|
17
|
+
condition: 'Brand New',
|
|
18
|
+
category: 'Apple',
|
|
19
|
+
colors: [
|
|
20
|
+
{ name: 'Desert Titanium', hex: '#bba795' },
|
|
21
|
+
{ name: 'Natural Titanium', hex: '#9d9890' },
|
|
22
|
+
{ name: 'White Titanium', hex: '#f0ede6' },
|
|
23
|
+
{ name: 'Black Titanium', hex: '#393836' },
|
|
24
|
+
],
|
|
25
|
+
image: '/images/showcase-phone.jpg',
|
|
26
|
+
badge: 'Popular Flagship',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: 'phone-galaxy-s25-ultra',
|
|
30
|
+
name: 'Galaxy S25 Ultra',
|
|
31
|
+
brand: 'Samsung',
|
|
32
|
+
subtitle: 'Armor Titanium · Snapdragon 8 Elite',
|
|
33
|
+
price: 1299,
|
|
34
|
+
originalPrice: 1399,
|
|
35
|
+
condition: 'Brand New',
|
|
36
|
+
category: 'Samsung',
|
|
37
|
+
colors: [
|
|
38
|
+
{ name: 'Titanium Gray', hex: '#5e6166' },
|
|
39
|
+
{ name: 'Titanium Black', hex: '#26282b' },
|
|
40
|
+
{ name: 'Titanium Violet', hex: '#4d4359' },
|
|
41
|
+
{ name: 'Titanium Yellow', hex: '#d4c794' },
|
|
42
|
+
],
|
|
43
|
+
image: '/images/s24-ultra.jpg',
|
|
44
|
+
badge: 'AI Flagship',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: 'phone-pixel-9-pro',
|
|
48
|
+
name: 'Pixel 9 Pro XL',
|
|
49
|
+
brand: 'Google',
|
|
50
|
+
subtitle: 'Google Tensor G4 · Gemini Nano',
|
|
51
|
+
price: 1099,
|
|
52
|
+
originalPrice: 1199,
|
|
53
|
+
condition: 'Brand New',
|
|
54
|
+
category: 'Google',
|
|
55
|
+
colors: [
|
|
56
|
+
{ name: 'Obsidian', hex: '#222326' },
|
|
57
|
+
{ name: 'Porcelain', hex: '#ebe7de' },
|
|
58
|
+
{ name: 'Hazel', hex: '#878c7f' },
|
|
59
|
+
{ name: 'Rose', hex: '#e3b8b6' },
|
|
60
|
+
],
|
|
61
|
+
image: '/images/pixel-9.jpg',
|
|
62
|
+
badge: 'Pro Optics',
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
/**
|
|
66
|
+
* EditableProductShowcase
|
|
67
|
+
*
|
|
68
|
+
* Elite, fully editable product showcase section featuring:
|
|
69
|
+
* - Direct showroom badge, section title & description with Fivora live bindings
|
|
70
|
+
* - Category filter pills with active state
|
|
71
|
+
* - Glassmorphism product cards with hover glow and transform transitions
|
|
72
|
+
* - Interactive color swatch buttons and active color label bindings ([DNB-COL-009])
|
|
73
|
+
* - Strikethrough compare-at price ([DNB-COL-009])
|
|
74
|
+
* - Full-width WhatsApp order button with dynamic merchant URL resolution ([DNB-WHA-008])
|
|
75
|
+
* - Guarded image fallback against empty strings ([DNB-IMG-002])
|
|
76
|
+
* - Aligned with Fivora generated-site product routing (/products/detail/?id=...)
|
|
77
|
+
*/
|
|
78
|
+
function EditableProductShowcase({ sectionPath = 'home', listPath = 'featuredPhones', badge = 'Direct Showroom & Verified Refurbished', heading = 'Upgrade Your Everyday.', description = 'Brand new flagships and laboratory-certified refurbished devices. 100% genuine components, clean IMEI, and up to 12 months comprehensive warranty.', products: userProducts, currency = 'Rs', shippingLabel = 'Free Insured Courier', whatsappOrderLabel = 'Order via WhatsApp', categories, onQuickView, productDetailRoutePrefix = '/products/detail', className = '', ...props }) {
|
|
79
|
+
const siteData = (0, SiteDataProvider_1.useSiteData)();
|
|
80
|
+
const [selectedFilter, setSelectedFilter] = (0, react_1.useState)('All');
|
|
81
|
+
const [selectedColors, setSelectedColors] = (0, react_1.useState)({});
|
|
82
|
+
// Resolve section content from siteData
|
|
83
|
+
const secContent = siteData?.content?.[sectionPath] || {};
|
|
84
|
+
const resolvedBadge = secContent.featuredProductsBadge || secContent.badge || badge;
|
|
85
|
+
const resolvedHeading = secContent.featuredProductsHeading || secContent.heading || heading;
|
|
86
|
+
const resolvedDescription = secContent.featuredProductsDescription || secContent.description || description;
|
|
87
|
+
// Resolve raw products list
|
|
88
|
+
const liveList = secContent[listPath] || siteData?.content?.products;
|
|
89
|
+
const rawProducts = Array.isArray(userProducts) && userProducts.length > 0
|
|
90
|
+
? userProducts
|
|
91
|
+
: (Array.isArray(liveList) && liveList.length > 0 ? liveList : DEFAULT_PRODUCTS);
|
|
92
|
+
// Normalize product items
|
|
93
|
+
const normalizedProducts = (0, react_1.useMemo)(() => {
|
|
94
|
+
return rawProducts.map((item, idx) => {
|
|
95
|
+
const def = DEFAULT_PRODUCTS[idx] || DEFAULT_PRODUCTS[0];
|
|
96
|
+
const rawColors = item.colors || def.colors || [{ name: 'Default', hex: '#9d9890' }];
|
|
97
|
+
const normalizedColors = (Array.isArray(rawColors) ? rawColors : Object.values(rawColors)).map((c, cIdx) => {
|
|
98
|
+
if (typeof c === 'string')
|
|
99
|
+
return { name: `Color ${cIdx + 1}`, hex: c };
|
|
100
|
+
return { name: c?.name || `Color ${cIdx + 1}`, hex: c?.hex || '#9d9890' };
|
|
101
|
+
});
|
|
102
|
+
const resolvedImage = item.image && typeof item.image === 'string' && item.image.trim() !== ''
|
|
103
|
+
? item.image
|
|
104
|
+
: (item.imageUrl && typeof item.imageUrl === 'string' && item.imageUrl.trim() !== ''
|
|
105
|
+
? item.imageUrl
|
|
106
|
+
: (def.image || '/images/showcase-phone.jpg'));
|
|
107
|
+
return {
|
|
108
|
+
...def,
|
|
109
|
+
...item,
|
|
110
|
+
_index: idx,
|
|
111
|
+
id: item.id || `product-${idx}`,
|
|
112
|
+
name: item.name || item.title || def.name,
|
|
113
|
+
brand: item.brand || item.category || def.brand || 'Store',
|
|
114
|
+
subtitle: item.subtitle || def.subtitle || '',
|
|
115
|
+
price: item.price != null ? Number(item.price) : def.price,
|
|
116
|
+
originalPrice: item.originalPrice != null
|
|
117
|
+
? Number(item.originalPrice)
|
|
118
|
+
: (item.compareAtPrice != null ? Number(item.compareAtPrice) : def.originalPrice),
|
|
119
|
+
condition: item.condition || def.condition || 'Brand New',
|
|
120
|
+
category: item.category || item.brand || def.category || 'All',
|
|
121
|
+
badge: item.badge || def.badge || '',
|
|
122
|
+
image: resolvedImage,
|
|
123
|
+
colors: normalizedColors.length > 0 ? normalizedColors : [{ name: 'Default', hex: '#9d9890' }],
|
|
124
|
+
};
|
|
125
|
+
});
|
|
126
|
+
}, [rawProducts]);
|
|
127
|
+
// Derived category list
|
|
128
|
+
const resolvedCategories = (0, react_1.useMemo)(() => {
|
|
129
|
+
if (Array.isArray(categories) && categories.length > 0)
|
|
130
|
+
return categories;
|
|
131
|
+
const set = new Set(['All']);
|
|
132
|
+
for (const p of normalizedProducts) {
|
|
133
|
+
if (p.brand)
|
|
134
|
+
set.add(p.brand);
|
|
135
|
+
if (p.category && p.category !== p.brand)
|
|
136
|
+
set.add(p.category);
|
|
137
|
+
}
|
|
138
|
+
return Array.from(set);
|
|
139
|
+
}, [categories, normalizedProducts]);
|
|
140
|
+
// Filter products by selected category
|
|
141
|
+
const filteredProducts = (0, react_1.useMemo)(() => {
|
|
142
|
+
if (selectedFilter === 'All')
|
|
143
|
+
return normalizedProducts;
|
|
144
|
+
return normalizedProducts.filter((p) => {
|
|
145
|
+
const matchBrand = p.brand?.toLowerCase() === selectedFilter.toLowerCase();
|
|
146
|
+
const matchCat = p.category?.toLowerCase() === selectedFilter.toLowerCase();
|
|
147
|
+
const matchCond = p.condition?.toLowerCase().includes(selectedFilter.toLowerCase());
|
|
148
|
+
return matchBrand || matchCat || matchCond;
|
|
149
|
+
});
|
|
150
|
+
}, [normalizedProducts, selectedFilter]);
|
|
151
|
+
// Resolve merchant WhatsApp target dynamically ([DNB-WHA-008])
|
|
152
|
+
const rawWhatsAppTarget = secContent.whatsappOrderUrl ||
|
|
153
|
+
secContent.whatsappNumber ||
|
|
154
|
+
siteData?.content?.common?.business?.whatsapp ||
|
|
155
|
+
siteData?.content?.merchant?.whatsapp ||
|
|
156
|
+
'https://wa.me/15550192834';
|
|
157
|
+
const handleWhatsAppOrder = (product, colorName, e) => {
|
|
158
|
+
e.stopPropagation();
|
|
159
|
+
const productName = product.name || product.title || 'Product';
|
|
160
|
+
const message = `Hi, I would like to order: *${productName}* (${product.brand || 'Flagship'}, Color: ${colorName}, Price: ${currency} ${product.price}). Is it available?`;
|
|
161
|
+
let targetUrl = (rawWhatsAppTarget || '').trim();
|
|
162
|
+
if (!targetUrl.startsWith('http://') && !targetUrl.startsWith('https://')) {
|
|
163
|
+
const cleanNum = targetUrl.replace(/[^0-9]/g, '');
|
|
164
|
+
targetUrl = `https://wa.me/${cleanNum || '15550192834'}`;
|
|
165
|
+
}
|
|
166
|
+
const sep = targetUrl.includes('?') ? '&' : '?';
|
|
167
|
+
const url = `${targetUrl}${sep}text=${encodeURIComponent(message)}`;
|
|
168
|
+
if (typeof window !== 'undefined') {
|
|
169
|
+
window.open(url, '_blank', 'noopener,noreferrer');
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
return ((0, jsx_runtime_1.jsxs)("section", { id: "shop", 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
|
|
173
|
+
? 'bg-zinc-950 text-white shadow-md'
|
|
174
|
+
: '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) => {
|
|
175
|
+
const idx = phone._index;
|
|
176
|
+
const phoneId = String(phone.id || idx);
|
|
177
|
+
const activeColorIdx = selectedColors[phoneId] ?? 0;
|
|
178
|
+
const colorsList = phone.colors || [];
|
|
179
|
+
const activeColor = colorsList[activeColorIdx] || colorsList[0] || { name: 'Default', hex: '#9d9890' };
|
|
180
|
+
const detailUrl = `${productDetailRoutePrefix}/?id=${encodeURIComponent(phoneId)}`;
|
|
181
|
+
return ((0, jsx_runtime_1.jsxs)("li", { "data-preview-item-path": `${sectionPath}.${listPath}[${idx}]`, "data-preview-style-target": `${sectionPath}.${listPath}[${idx}].card`, "data-preview-style-type": "card", className: "group relative flex flex-col justify-between p-6 sm:p-7 rounded-3xl border border-black/[0.08] bg-white/95 hover:border-cyan-400/60 transition-all duration-300 hover:-translate-y-1.5 shadow-[0_10px_30px_rgba(0,0,0,0.04)] hover:shadow-[0_20px_40px_rgba(0,240,255,0.12)]", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-start justify-between gap-2", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("span", { className: "text-[11px] font-bold uppercase tracking-widest text-cyan-600 font-mono", "data-preview-field-path": `${sectionPath}.${listPath}[${idx}].brand`, "data-preview-style-target": `${sectionPath}.${listPath}[${idx}].brand`, "data-preview-style-type": "text", children: phone.brand }), (0, jsx_runtime_1.jsx)("h3", { className: "mt-1 text-xl font-bold text-zinc-950 tracking-tight group-hover:text-cyan-600 transition-colors", "data-preview-field-path": `${sectionPath}.${listPath}[${idx}].name`, "data-preview-style-target": `${sectionPath}.${listPath}[${idx}].name`, "data-preview-style-type": "text", children: (0, jsx_runtime_1.jsx)("a", { href: detailUrl, className: "hover:underline", children: phone.name }) }), phone.subtitle && ((0, jsx_runtime_1.jsx)("p", { className: "text-xs text-zinc-500 mt-0.5", "data-preview-field-path": `${sectionPath}.${listPath}[${idx}].subtitle`, "data-preview-style-target": `${sectionPath}.${listPath}[${idx}].subtitle`, "data-preview-style-type": "text", children: phone.subtitle }))] }), phone.badge && ((0, jsx_runtime_1.jsx)("span", { className: "shrink-0 rounded-full border border-black/[0.08] bg-black/[0.03] px-2.5 py-0.5 text-[10px] font-semibold text-zinc-700 backdrop-blur-md", "data-preview-field-path": `${sectionPath}.${listPath}[${idx}].badge`, "data-preview-style-target": `${sectionPath}.${listPath}[${idx}].badge`, "data-preview-style-type": "text", children: phone.badge }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "relative my-6 h-60 w-full overflow-clip rounded-2xl border border-black/[0.06] bg-slate-100 flex items-center justify-center", children: [(0, jsx_runtime_1.jsx)("img", { src: phone.image, alt: phone.name || 'Product Image', "data-preview-field-path": `${sectionPath}.${listPath}[${idx}].image`, className: "h-full w-full object-cover transition-transform duration-500 group-hover:scale-108" }), (0, jsx_runtime_1.jsx)("div", { className: "pointer-events-none absolute inset-0 bg-gradient-to-t from-black/40 via-transparent to-transparent opacity-30" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between pt-2 border-t border-black/[0.06]", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1.5", "data-preview-list-path": `${sectionPath}.${listPath}[${idx}].colors`, children: [colorsList.map((c, colorIdx) => ((0, jsx_runtime_1.jsxs)("div", { "data-preview-item-path": `${sectionPath}.${listPath}[${idx}].colors[${colorIdx}]`, className: "inline-flex items-center", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: (e) => {
|
|
182
|
+
e.stopPropagation();
|
|
183
|
+
setSelectedColors((prev) => ({ ...prev, [phoneId]: colorIdx }));
|
|
184
|
+
}, "aria-label": c.name, title: c.name, className: `h-4 w-4 rounded-full transition-all cursor-pointer ${activeColorIdx === colorIdx
|
|
185
|
+
? 'ring-2 ring-cyan-500 ring-offset-1 ring-offset-white scale-110'
|
|
186
|
+
: 'opacity-70 hover:opacity-100'}`, style: { backgroundColor: c.hex || '#9d9890' }, "data-preview-field-path": `${sectionPath}.${listPath}[${idx}].colors[${colorIdx}].hex`, "data-preview-field-type": "color" }), (0, jsx_runtime_1.jsx)("span", { className: "sr-only", "data-preview-field-path": `${sectionPath}.${listPath}[${idx}].colors[${colorIdx}].name`, "data-preview-style-target": `${sectionPath}.${listPath}[${idx}].colors[${colorIdx}].name`, "data-preview-style-type": "text", children: c.name })] }, c.name || colorIdx))), (0, jsx_runtime_1.jsx)("span", { className: "text-[11px] text-zinc-500 ml-1.5 [display:none] sm:inline cursor-pointer", "data-preview-field-path": `${sectionPath}.${listPath}[${idx}].colors[${activeColorIdx}].name`, "data-preview-style-target": `${sectionPath}.${listPath}[${idx}].colors[${activeColorIdx}].name`, "data-preview-style-type": "text", children: activeColor.name })] }), (0, jsx_runtime_1.jsx)("div", { className: "flex items-center gap-1 text-[11px] font-medium text-emerald-600", children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.${listPath}[${idx}].condition`, "data-preview-style-target": `${sectionPath}.${listPath}[${idx}].condition`, "data-preview-style-type": "text", children: phone.condition || 'Brand New' }) })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "mt-6 pt-4 border-t border-black/[0.06] space-y-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-baseline gap-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-xs font-semibold text-zinc-500", children: currency }), (0, jsx_runtime_1.jsx)("span", { className: "text-2xl font-black text-zinc-950 tracking-tight", "data-preview-field-path": `${sectionPath}.${listPath}[${idx}].price`, "data-preview-style-target": `${sectionPath}.${listPath}[${idx}].price`, "data-preview-style-type": "text", children: phone.price }), phone.originalPrice != null && ((0, jsx_runtime_1.jsxs)("span", { className: "text-xs text-zinc-400 line-through", "data-preview-field-path": `${sectionPath}.${listPath}[${idx}].originalPrice`, "data-preview-style-target": `${sectionPath}.${listPath}[${idx}].originalPrice`, "data-preview-style-type": "text", children: [currency, " ", phone.originalPrice] }))] }), (0, jsx_runtime_1.jsx)("p", { className: "text-[10px] text-zinc-500 mt-0.5", "data-preview-field-path": `${sectionPath}.${listPath}[${idx}].shippingLabel`, "data-preview-style-target": `${sectionPath}.${listPath}[${idx}].shippingLabel`, "data-preview-style-type": "text", children: shippingLabel })] }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: (e) => {
|
|
187
|
+
e.stopPropagation();
|
|
188
|
+
if (onQuickView)
|
|
189
|
+
onQuickView(phone, idx);
|
|
190
|
+
else if (typeof window !== 'undefined')
|
|
191
|
+
window.location.href = detailUrl;
|
|
192
|
+
}, className: "flex h-9 w-9 items-center justify-center rounded-full border border-black/10 bg-black/[0.02] text-zinc-600 hover:text-cyan-600 hover:border-cyan-400/50 hover:bg-cyan-50/50 transition-all cursor-pointer", title: "Quick View", "aria-label": "Quick View Product", children: (0, jsx_runtime_1.jsxs)("svg", { className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", 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" })] }) })] }), (0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: (e) => handleWhatsAppOrder(phone, activeColor.name, e), className: "w-full flex items-center justify-center gap-2 rounded-2xl bg-gradient-to-r from-cyan-400 via-sky-400 to-blue-600 py-3 px-4 text-xs font-bold text-white shadow-[0_4px_15px_rgba(0,240,255,0.25)] hover:shadow-[0_6px_25px_rgba(0,240,255,0.45)] transition-all hover:scale-[1.01] active:scale-[0.99] cursor-pointer", children: [(0, jsx_runtime_1.jsx)("svg", { className: "h-4 w-4 fill-white", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { d: "M12.031 6.172c-3.181 0-5.767 2.586-5.768 5.766-.001 1.298.38 2.27 1.019 3.287l-.582 2.128 2.182-.573c.978.58 1.911.928 3.145.929 3.178 0 5.767-2.587 5.768-5.766.001-3.187-2.575-5.771-5.764-5.771zm3.392 8.244c-.144.405-.837.774-1.17.824-.312.045-.634.055-.992-.061-.635-.206-1.464-.567-2.527-1.63-1.341-1.341-1.849-2.531-2.006-2.986-.157-.455-.015-.81.212-1.037.202-.202.455-.253.606-.253.152 0 .303.004.436.012.141.008.329-.053.515.394.192.465.657 1.602.714 1.719.057.116.096.253.019.405-.076.152-.114.248-.228.38-.114.133-.24.296-.343.397-.114.114-.233.238-.1.467.133.228.591.976 1.269 1.58 1.077.959 1.83 1.157 2.058 1.271.228.114.362.096.495-.057.133-.152.571-.666.723-.894.152-.228.303-.19.515-.114.212.076 1.346.635 1.575.749.228.114.38.171.436.266.057.095.057.553-.087.958z" }) }), (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.whatsappOrderLabel`, "data-preview-style-target": `${sectionPath}.whatsappOrderLabel`, "data-preview-style-type": "text", children: whatsappOrderLabel })] })] })] }, phoneId));
|
|
193
|
+
}) })] })] }));
|
|
194
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export * from './EditableGrid';
|
|
|
12
12
|
export * from './EditableSection';
|
|
13
13
|
export * from './EditableProductCard';
|
|
14
14
|
export * from './EditableProductGrid';
|
|
15
|
+
export * from './EditableProductShowcase';
|
|
15
16
|
export * from './EditableProductDetail';
|
|
16
17
|
export * from './EditableCustomerReviews';
|
|
17
18
|
export * from './EditableGoogleFeedback';
|
|
@@ -67,6 +68,7 @@ export { EditableBox as Box } from './EditableBox';
|
|
|
67
68
|
export { EditableList as List } from './EditableList';
|
|
68
69
|
export { EditableProductCard as ProductCard } from './EditableProductCard';
|
|
69
70
|
export { EditableProductGrid as ProductGrid } from './EditableProductGrid';
|
|
71
|
+
export { EditableProductShowcase as ProductShowcase } from './EditableProductShowcase';
|
|
70
72
|
export { EditableProductDetail as ProductDetail } from './EditableProductDetail';
|
|
71
73
|
export { EditableCustomerReviews as CustomerReviews } from './EditableCustomerReviews';
|
|
72
74
|
export { EditableGoogleFeedback as GoogleFeedback } from './EditableGoogleFeedback';
|
package/dist/index.js
CHANGED
|
@@ -18,8 +18,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
18
18
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
19
19
|
};
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.
|
|
22
|
-
exports.DENEB_AUTHOR = exports.DENEB_FRAMEWORK_VERSION = exports.DENEB_FRAMEWORK_NAME = exports.AdditionalPagesNav = exports.PlatformAdditionalPages = exports.FilterSidebar = exports.CartDrawer = exports.CategoryPills = exports.AnnouncementBar = exports.HeroSplit = exports.Hero = exports.Footer = exports.Header = exports.Navbar = void 0;
|
|
21
|
+
exports.FAQ = exports.Accordion = exports.Testimonials = exports.TestimonialSection = exports.TestimonialCard = exports.PricingCard = exports.ServiceCard = exports.GoogleFeedback = exports.CustomerReviews = exports.ProductDetail = exports.ProductShowcase = exports.ProductGrid = exports.ProductCard = exports.List = exports.Box = exports.Section = exports.Grid = exports.Map = exports.Image = exports.Quote = exports.Badge = exports.Paragraph = exports.Heading = exports.Text = exports.Dialog = exports.Card = exports.Button = exports.collectStyleTargetsFromHtml = exports.validateStyleTree = exports.styleToCssVariables = exports.patchStyleByPath = exports.patchElementStyle = exports.STYLE_TYPE_ATTRIBUTE = exports.STYLE_TARGET_ATTRIBUTE = exports.DENEB_STYLE_PATCH_MESSAGE = exports.STYLE_PATCH_MESSAGE = exports.formatResponsiveFontSize = exports.resolveInstallableFont = exports.normalizeFontId = exports.lookupFontDefinition = exports.listFontsByCategory = exports.collectFontIdsFromSiteData = exports.buildGoogleFontsStylesheetUrl = exports.DENEB_GOOGLE_FONT_COUNT = exports.DENEB_FONT_REGISTRY = exports.useDenebFonts = exports.DENEB_FONTS_LINK_ID = exports.FontLoader = exports.DenebComponentStyles = exports.ResponsiveBaseStyles = void 0;
|
|
22
|
+
exports.DENEB_AUTHOR = exports.DENEB_FRAMEWORK_VERSION = exports.DENEB_FRAMEWORK_NAME = exports.AdditionalPagesNav = exports.PlatformAdditionalPages = exports.FilterSidebar = exports.CartDrawer = exports.CategoryPills = exports.AnnouncementBar = exports.HeroSplit = exports.Hero = exports.Footer = exports.Header = exports.Navbar = exports.ContactForm = void 0;
|
|
23
23
|
__exportStar(require("./PreviewField"), exports);
|
|
24
24
|
__exportStar(require("./EditableText"), exports);
|
|
25
25
|
__exportStar(require("./EditableImage"), exports);
|
|
@@ -30,6 +30,7 @@ __exportStar(require("./EditableGrid"), exports);
|
|
|
30
30
|
__exportStar(require("./EditableSection"), exports);
|
|
31
31
|
__exportStar(require("./EditableProductCard"), exports);
|
|
32
32
|
__exportStar(require("./EditableProductGrid"), exports);
|
|
33
|
+
__exportStar(require("./EditableProductShowcase"), exports);
|
|
33
34
|
__exportStar(require("./EditableProductDetail"), exports);
|
|
34
35
|
__exportStar(require("./EditableCustomerReviews"), exports);
|
|
35
36
|
__exportStar(require("./EditableGoogleFeedback"), exports);
|
|
@@ -126,6 +127,8 @@ var EditableProductCard_1 = require("./EditableProductCard");
|
|
|
126
127
|
Object.defineProperty(exports, "ProductCard", { enumerable: true, get: function () { return EditableProductCard_1.EditableProductCard; } });
|
|
127
128
|
var EditableProductGrid_1 = require("./EditableProductGrid");
|
|
128
129
|
Object.defineProperty(exports, "ProductGrid", { enumerable: true, get: function () { return EditableProductGrid_1.EditableProductGrid; } });
|
|
130
|
+
var EditableProductShowcase_1 = require("./EditableProductShowcase");
|
|
131
|
+
Object.defineProperty(exports, "ProductShowcase", { enumerable: true, get: function () { return EditableProductShowcase_1.EditableProductShowcase; } });
|
|
129
132
|
var EditableProductDetail_1 = require("./EditableProductDetail");
|
|
130
133
|
Object.defineProperty(exports, "ProductDetail", { enumerable: true, get: function () { return EditableProductDetail_1.EditableProductDetail; } });
|
|
131
134
|
var EditableCustomerReviews_1 = require("./EditableCustomerReviews");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deneb-ui/ui",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.58",
|
|
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.58"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
56
|
"react": "^18.0.0 || ^19.0.0",
|