@deneb-ui/ui 2.0.40 → 2.0.42
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.
|
@@ -12,6 +12,7 @@ const EditableText_2 = require("./EditableText");
|
|
|
12
12
|
*/
|
|
13
13
|
function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass', imageFallback, as: Component = 'article', showPrice = true, showDescription = true, showCategory = true, actionSlot, actionLabel, actionLabelPath, className = '', style, ...props }) {
|
|
14
14
|
const name = String(product?.name || product?.title || '');
|
|
15
|
+
const hasPrice = showPrice && product?.price !== undefined && product?.price !== null && String(product.price).trim() !== '';
|
|
15
16
|
const price = product?.price !== undefined ? String(product.price) : '';
|
|
16
17
|
const originalPrice = product?.originalPrice !== undefined ? String(product.originalPrice) : '';
|
|
17
18
|
const description = String(product?.description || '');
|
|
@@ -61,13 +62,13 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
|
|
|
61
62
|
overflow: 'hidden',
|
|
62
63
|
width: isHorizontal ? '100%' : '100%',
|
|
63
64
|
flexShrink: 0,
|
|
64
|
-
}, children: [(0, jsx_runtime_1.jsx)(EditableImage_1.EditableImage, { id: `${itemPath}.imageUrl`, src: imageUrl, fallbackSrc: imageFallback, alt: name, aspectRatio: isHorizontal ? 'square' : '4/3', fit: "cover", hoverZoom: true, style: { width: '100%', height: '100%', display: 'block' } }), badge && ((0, jsx_runtime_1.jsx)("div", { style: { position: 'absolute', top: '10px', left: '10px', zIndex: 10 }, children: (0, jsx_runtime_1.jsx)(EditableText_2.EditableBadge, { id: `${itemPath}.badge`, defaultValue: badge, badgeVariant: "primary" }) }))] }), (0, jsx_runtime_1.jsxs)("div", { style: {
|
|
65
|
+
}, children: [(0, jsx_runtime_1.jsx)(EditableImage_1.EditableImage, { id: `${itemPath}.imageUrl`, "data-preview-field-path": `${itemPath}.imageUrl`, src: imageUrl, fallbackSrc: imageFallback, alt: name, aspectRatio: isHorizontal ? 'square' : '4/3', fit: "cover", hoverZoom: true, style: { width: '100%', height: '100%', display: 'block' } }), badge && ((0, jsx_runtime_1.jsx)("div", { style: { position: 'absolute', top: '10px', left: '10px', zIndex: 10 }, children: (0, jsx_runtime_1.jsx)(EditableText_2.EditableBadge, { id: `${itemPath}.badge`, "data-preview-field-path": `${itemPath}.badge`, defaultValue: badge, badgeVariant: "primary" }) }))] }), (0, jsx_runtime_1.jsxs)("div", { style: {
|
|
65
66
|
padding: '1.25rem',
|
|
66
67
|
display: 'flex',
|
|
67
68
|
flexDirection: 'column',
|
|
68
69
|
flex: 1,
|
|
69
70
|
justifyContent: 'space-between',
|
|
70
|
-
}, children: [(0, jsx_runtime_1.jsxs)("div", { children: [showCategory && ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.category`, defaultValue: category, style: {
|
|
71
|
+
}, children: [(0, jsx_runtime_1.jsxs)("div", { children: [showCategory && ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.category`, "data-preview-field-path": `${itemPath}.category`, defaultValue: category, style: {
|
|
71
72
|
fontSize: '0.75rem',
|
|
72
73
|
textTransform: 'uppercase',
|
|
73
74
|
letterSpacing: '0.05em',
|
|
@@ -75,13 +76,13 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
|
|
|
75
76
|
fontWeight: 600,
|
|
76
77
|
display: 'inline-block',
|
|
77
78
|
marginBottom: '0.375rem',
|
|
78
|
-
} })), (0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "h3", id: `${itemPath}.name`, defaultValue: name, style: {
|
|
79
|
+
} })), (0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "h3", id: `${itemPath}.name`, "data-preview-field-path": `${itemPath}.name`, defaultValue: name, style: {
|
|
79
80
|
fontSize: '1.125rem',
|
|
80
81
|
fontWeight: 700,
|
|
81
82
|
lineHeight: 1.3,
|
|
82
83
|
color: 'var(--heading-color, #0f172a)',
|
|
83
84
|
marginBottom: '0.375rem',
|
|
84
|
-
} }), showDescription && ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "p", id: `${itemPath}.description`, defaultValue: description, style: {
|
|
85
|
+
} }), showDescription && ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "p", id: `${itemPath}.description`, "data-preview-field-path": `${itemPath}.description`, defaultValue: description, style: {
|
|
85
86
|
fontSize: '0.875rem',
|
|
86
87
|
color: 'var(--muted-text, #64748b)',
|
|
87
88
|
lineHeight: 1.5,
|
|
@@ -94,20 +95,20 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
|
|
|
94
95
|
alignItems: 'center',
|
|
95
96
|
justifyContent: 'space-between',
|
|
96
97
|
gap: '0.5rem',
|
|
97
|
-
}, children: [
|
|
98
|
+
}, children: [hasPrice ? ((0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', alignItems: 'baseline', gap: '0.375rem' }, children: [(0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.price`, "data-preview-field-path": `${itemPath}.price`, defaultValue: price, style: {
|
|
98
99
|
fontSize: '1.25rem',
|
|
99
100
|
fontWeight: 700,
|
|
100
101
|
color: 'var(--brand-color, #2563eb)',
|
|
101
|
-
} }), originalPrice ? ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.originalPrice`, defaultValue: originalPrice, style: {
|
|
102
|
+
} }), originalPrice ? ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.originalPrice`, "data-preview-field-path": `${itemPath}.originalPrice`, defaultValue: originalPrice, style: {
|
|
102
103
|
fontSize: '0.875rem',
|
|
103
104
|
textDecoration: 'line-through',
|
|
104
105
|
color: 'var(--muted-text, #94a3b8)',
|
|
105
|
-
} })) : null, product?.measurement ? ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.measurement`, defaultValue: `/ ${String(product.measurement)}`, style: {
|
|
106
|
+
} })) : 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: {
|
|
106
107
|
fontSize: '0.8rem',
|
|
107
108
|
fontWeight: 500,
|
|
108
109
|
color: 'var(--muted-text, #64748b)',
|
|
109
110
|
marginLeft: '0.25rem',
|
|
110
|
-
} })) : null] })), actionSlot ? ((0, jsx_runtime_1.jsx)("div", { children: actionSlot })) : ((0, jsx_runtime_1.jsx)("button", { type: "button", style: {
|
|
111
|
+
} })) : null] })) : null, actionSlot ? ((0, jsx_runtime_1.jsx)("div", { children: actionSlot })) : ((0, jsx_runtime_1.jsx)("button", { type: "button", style: {
|
|
111
112
|
backgroundColor: 'var(--brand-color, #2563eb)',
|
|
112
113
|
color: '#ffffff',
|
|
113
114
|
border: 'none',
|
|
@@ -117,5 +118,5 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
|
|
|
117
118
|
fontWeight: 600,
|
|
118
119
|
cursor: 'pointer',
|
|
119
120
|
transition: 'opacity 0.2s ease',
|
|
120
|
-
}, children: (0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: actionLabelPath || `${itemPath}.buttonText`, defaultValue: actionLabel || product?.buttonText || 'Buy Now', style: { color: '#ffffff', fontWeight: 600 } }) }))] })] })] }));
|
|
121
|
+
}, children: (0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: actionLabelPath || `${itemPath}.buttonText`, "data-preview-field-path": actionLabelPath || `${itemPath}.buttonText`, defaultValue: actionLabel || product?.buttonText || 'Buy Now', style: { color: '#ffffff', fontWeight: 600 } }) }))] })] })] }));
|
|
121
122
|
}
|
|
@@ -5,6 +5,11 @@ export interface EditableProductGridProps extends React.HTMLAttributes<HTMLEleme
|
|
|
5
5
|
* Field path prefix for live Fivora Visual Editing synchronization (e.g. "home").
|
|
6
6
|
*/
|
|
7
7
|
sectionPath?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Collection path for products (default: "products").
|
|
10
|
+
* When set, products are iterated with standard array indexing (e.g. "products[0]").
|
|
11
|
+
*/
|
|
12
|
+
listPath?: string;
|
|
8
13
|
/**
|
|
9
14
|
* Title of the product grid section.
|
|
10
15
|
*/
|
|
@@ -51,5 +56,5 @@ export interface EditableProductGridProps extends React.HTMLAttributes<HTMLEleme
|
|
|
51
56
|
*
|
|
52
57
|
* Created by Chamika Gayashan & Induranga Kawishwara
|
|
53
58
|
*/
|
|
54
|
-
export declare function EditableProductGrid({ sectionPath, title, subtitle, products, categories, cardVariant, columns, onQuickView, cardPrefix, className, style, ...props }: EditableProductGridProps): React.JSX.Element;
|
|
59
|
+
export declare function EditableProductGrid({ sectionPath, listPath, title, subtitle, products, categories, cardVariant, columns, onQuickView, cardPrefix, className, style, ...props }: EditableProductGridProps): React.JSX.Element;
|
|
55
60
|
export declare const ProductGrid: typeof EditableProductGrid;
|
|
@@ -12,7 +12,7 @@ const EditableProductCard_1 = require("./EditableProductCard");
|
|
|
12
12
|
*
|
|
13
13
|
* Created by Chamika Gayashan & Induranga Kawishwara
|
|
14
14
|
*/
|
|
15
|
-
function EditableProductGrid({ sectionPath = 'home', title = 'Featured Collection', subtitle = 'Just Dropped', products = [], categories = ['All'], cardVariant = 'modern-glass', columns = { mobile: 1, tablet: 2, desktop: 4 }, onQuickView, cardPrefix = 'product', className = '', style, ...props }) {
|
|
15
|
+
function EditableProductGrid({ sectionPath = 'home', listPath = 'products', title = 'Featured Collection', subtitle = 'Just Dropped', products = [], categories = ['All'], cardVariant = 'modern-glass', columns = { mobile: 1, tablet: 2, desktop: 4 }, onQuickView, cardPrefix = 'product', className = '', style, ...props }) {
|
|
16
16
|
const [activeCategory, setActiveCategory] = (0, react_1.useState)(categories[0] || 'All');
|
|
17
17
|
const filteredProducts = (0, react_1.useMemo)(() => {
|
|
18
18
|
if (!activeCategory || activeCategory.toLowerCase() === 'all') {
|
|
@@ -38,9 +38,11 @@ function EditableProductGrid({ sectionPath = 'home', title = 'Featured Collectio
|
|
|
38
38
|
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
|
|
39
39
|
? 'bg-white text-slate-950 shadow-md scale-102 font-extrabold'
|
|
40
40
|
: 'bg-slate-900/60 text-slate-400 hover:text-white border border-slate-800/80 hover:bg-slate-850'}`, children: cat }, cat));
|
|
41
|
-
}) }))] }), filteredProducts.length > 0 ? ((0, jsx_runtime_1.jsx)("div", { className: `deneb-product-grid grid ${gridColClasses} gap-6 sm:gap-8`, children: filteredProducts.map((product, idx) => {
|
|
42
|
-
const itemPath =
|
|
43
|
-
|
|
41
|
+
}) }))] }), filteredProducts.length > 0 ? ((0, jsx_runtime_1.jsx)("div", { ...(listPath ? { 'data-preview-list-path': listPath } : {}), className: `deneb-product-grid grid ${gridColClasses} gap-6 sm:gap-8`, children: filteredProducts.map((product, idx) => {
|
|
42
|
+
const itemPath = listPath
|
|
43
|
+
? `${listPath}[${idx}]`
|
|
44
|
+
: `${sectionPath}.${cardPrefix}${idx + 1}`;
|
|
45
|
+
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));
|
|
44
46
|
}) })) : (
|
|
45
47
|
/* Empty State */
|
|
46
48
|
(0, jsx_runtime_1.jsxs)("div", { className: "text-center py-20 px-4 rounded-3xl border border-dashed border-slate-800 bg-slate-900/30", children: [(0, jsx_runtime_1.jsxs)("p", { className: "text-sm font-medium text-slate-400", children: ["No products found matching category \"", activeCategory, "\"."] }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setActiveCategory('All'), className: "mt-4 px-4 py-2 rounded-xl text-xs font-bold bg-lime-400 text-slate-950 hover:bg-lime-300 transition-colors", children: "View All Products" })] }))] }));
|
|
@@ -3,6 +3,7 @@ export interface ServiceItem {
|
|
|
3
3
|
id?: string | number;
|
|
4
4
|
name?: string;
|
|
5
5
|
title?: string;
|
|
6
|
+
price?: string | number;
|
|
6
7
|
description?: string;
|
|
7
8
|
imageUrl?: string;
|
|
8
9
|
image?: string;
|
|
@@ -30,9 +31,10 @@ export interface EditableServiceCardProps extends React.HTMLAttributes<HTMLEleme
|
|
|
30
31
|
* Text/content alignment for the card ('left' | 'center' | 'right').
|
|
31
32
|
*/
|
|
32
33
|
align?: 'left' | 'center' | 'right';
|
|
34
|
+
showPrice?: boolean;
|
|
33
35
|
}
|
|
34
36
|
/**
|
|
35
37
|
* EditableServiceCard standardizes service presentation across Home and Services pages.
|
|
36
38
|
* Supports service name, description, image, and repeatable features checklist.
|
|
37
39
|
*/
|
|
38
|
-
export declare function EditableServiceCard({ itemPath, service, imageFallback, as: Component, align, className, style, children, ...props }: EditableServiceCardProps): React.JSX.Element;
|
|
40
|
+
export declare function EditableServiceCard({ itemPath, service, imageFallback, as: Component, align, showPrice, className, style, children, ...props }: EditableServiceCardProps): React.JSX.Element;
|
|
@@ -8,16 +8,21 @@ const EditableImage_1 = require("./EditableImage");
|
|
|
8
8
|
* EditableServiceCard standardizes service presentation across Home and Services pages.
|
|
9
9
|
* Supports service name, description, image, and repeatable features checklist.
|
|
10
10
|
*/
|
|
11
|
-
function EditableServiceCard({ itemPath, service, imageFallback = '/placeholder.svg', as: Component = 'article', align = 'left', className = '', style, children, ...props }) {
|
|
11
|
+
function EditableServiceCard({ itemPath, service, imageFallback = '/placeholder.svg', as: Component = 'article', align = 'left', showPrice = true, className = '', style, children, ...props }) {
|
|
12
12
|
const name = String(service?.name || service?.title || '');
|
|
13
13
|
const description = String(service?.description || '');
|
|
14
|
+
const hasPrice = showPrice && service?.price !== undefined && service?.price !== null && String(service.price).trim() !== '';
|
|
14
15
|
const imageUrl = String(service?.imageUrl || service?.image || '');
|
|
15
16
|
const features = Array.isArray(service?.features) ? service.features : [];
|
|
16
17
|
const mergedStyle = {
|
|
17
18
|
textAlign: align,
|
|
18
19
|
...style,
|
|
19
20
|
};
|
|
20
|
-
return ((0, jsx_runtime_1.jsxs)(Component, { "data-preview-item-path": itemPath, className: `editable-service-card ${className}`.trim(), style: mergedStyle, ...props, children: [(imageUrl || service?.imageUrl !== undefined || service?.image !== undefined) && ((0, jsx_runtime_1.jsx)("div", { className: "service-card-image-wrap", children: (0, jsx_runtime_1.jsx)(EditableImage_1.EditableImage, { id: `${itemPath}.imageUrl`, "data-preview-field-path": `${itemPath}.imageUrl`, src: imageUrl, fallbackSrc: imageFallback, alt: name, className: "service-card-image" }) })), (0, jsx_runtime_1.jsxs)("div", { className: "service-card-body", children: [(0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "h2", id: `${itemPath}.name`, "data-preview-field-path": `${itemPath}.name`, defaultValue: name, className: "service-card-title" }), (0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "p", id: `${itemPath}.description`, "data-preview-field-path": `${itemPath}.description`, defaultValue: description, className: "service-card-description" }),
|
|
21
|
+
return ((0, jsx_runtime_1.jsxs)(Component, { "data-preview-item-path": itemPath, className: `editable-service-card ${className}`.trim(), style: mergedStyle, ...props, children: [(imageUrl || service?.imageUrl !== undefined || service?.image !== undefined) && ((0, jsx_runtime_1.jsx)("div", { className: "service-card-image-wrap", children: (0, jsx_runtime_1.jsx)(EditableImage_1.EditableImage, { id: `${itemPath}.imageUrl`, "data-preview-field-path": `${itemPath}.imageUrl`, src: imageUrl, fallbackSrc: imageFallback, alt: name, className: "service-card-image" }) })), (0, jsx_runtime_1.jsxs)("div", { className: "service-card-body", children: [(0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "h2", id: `${itemPath}.name`, "data-preview-field-path": `${itemPath}.name`, defaultValue: name, className: "service-card-title" }), (0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "p", id: `${itemPath}.description`, "data-preview-field-path": `${itemPath}.description`, defaultValue: description, className: "service-card-description" }), hasPrice && ((0, jsx_runtime_1.jsx)("div", { className: "service-card-price-wrap", style: { margin: '0.5rem 0' }, children: (0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.price`, "data-preview-field-path": `${itemPath}.price`, defaultValue: String(service.price), className: "service-card-price", style: {
|
|
22
|
+
fontSize: '1.125rem',
|
|
23
|
+
fontWeight: 700,
|
|
24
|
+
color: 'var(--brand-color, #2563eb)',
|
|
25
|
+
} }) })), (features.length > 0 || Array.isArray(service?.features)) && ((0, jsx_runtime_1.jsx)("ul", { "data-preview-list-path": `${itemPath}.features`, className: "service-card-features", children: features.map((feature, featureIndex) => {
|
|
21
26
|
const featureText = typeof feature === 'string'
|
|
22
27
|
? feature
|
|
23
28
|
: typeof feature?.title === 'string'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deneb-ui/ui",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.42",
|
|
4
4
|
"description": "Visual-first React component library for editable commerce storefronts. Built for Next.js and Fivora.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
],
|
|
50
50
|
"license": "MIT",
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@deneb-ui/core": "^2.0.
|
|
52
|
+
"@deneb-ui/core": "^2.0.42"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"react": "^18.0.0 || ^19.0.0",
|