@deneb-ui/ui 2.0.43 → 2.0.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/EditableCartDrawer.js +3 -3
- package/dist/EditableProductCard.d.ts +52 -7
- package/dist/EditableProductCard.js +127 -41
- package/dist/cart/useCart.d.ts +13 -0
- package/dist/cart/useCart.js +45 -11
- package/package.json +2 -2
|
@@ -8,7 +8,7 @@ const react_1 = require("react");
|
|
|
8
8
|
const useCart_1 = require("./cart/useCart");
|
|
9
9
|
const SiteDataProvider_1 = require("./SiteDataProvider");
|
|
10
10
|
const urls_1 = require("./utils/urls");
|
|
11
|
-
function EditableCartDrawer({ basePath = 'cart', whatsappNumber = '94770000000', storeName, currency = '
|
|
11
|
+
function EditableCartDrawer({ basePath = 'cart', whatsappNumber = '94770000000', storeName, currency = 'LKR', checkoutUrl, freeShippingThreshold, onCheckout, className = '', }) {
|
|
12
12
|
const { items, isOpen, closeCart, removeItem, updateQuantity, clearCart, totalCount, subtotal, getWhatsAppOrderUrl, } = (0, useCart_1.useCart)();
|
|
13
13
|
const { siteData } = (0, SiteDataProvider_1.useSiteData)();
|
|
14
14
|
// Helper to read content from siteData
|
|
@@ -42,7 +42,7 @@ function EditableCartDrawer({ basePath = 'cart', whatsappNumber = '94770000000',
|
|
|
42
42
|
const subtotalLabel = getContent('subtotalLabel', 'Subtotal');
|
|
43
43
|
const shippingNote = getContent('shippingNote', 'Taxes and shipping calculated at checkout');
|
|
44
44
|
const checkoutButtonText = getContent('checkoutButtonText', 'Proceed to Checkout');
|
|
45
|
-
const whatsappButtonText = getContent('whatsappButtonText', '
|
|
45
|
+
const whatsappButtonText = getContent('whatsappButtonText', 'Purchase through WhatsApp');
|
|
46
46
|
const clearCartText = getContent('clearCartText', 'Clear all');
|
|
47
47
|
const whatsappHref = getWhatsAppOrderUrl(whatsappNumber, {
|
|
48
48
|
storeName,
|
|
@@ -51,7 +51,7 @@ function EditableCartDrawer({ basePath = 'cart', whatsappNumber = '94770000000',
|
|
|
51
51
|
const progressPercent = freeShippingThreshold
|
|
52
52
|
? Math.min(100, Math.round((subtotal / freeShippingThreshold) * 100))
|
|
53
53
|
: 100;
|
|
54
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: `deneb-cart-drawer-root fixed inset-0 z-50 flex justify-end ${className}`, children: [(0, jsx_runtime_1.jsx)("div", { className: "fixed inset-0 bg-black/60 backdrop-blur-sm transition-opacity", onClick: closeCart, "data-preview-static": "cart-backdrop", "aria-hidden": "true" }), (0, jsx_runtime_1.jsxs)("aside", { className: "relative z-10 flex h-full w-full max-w-md flex-col bg-neutral-900 text-white shadow-2xl transition-transform duration-300 ease-out border-l border-neutral-800", "aria-label": "Shopping Cart Drawer", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between border-b border-neutral-800 px-6 py-5", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h2", { className: "text-xl font-bold tracking-tight text-white", "data-preview-field-path": fieldPath('title'), children: title }), (0, jsx_runtime_1.jsx)("p", { className: "text-xs text-neutral-400 mt-0.5", "data-preview-field-path": fieldPath('subtitle'), children: subtitle })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [items.length > 0 && ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: clearCart, className: "text-xs text-neutral-400 hover:text-red-400 transition-colors px-2 py-1 rounded", "data-preview-static": "cart-clear-btn", children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": fieldPath('clearCartText'), children: clearCartText }) })), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: closeCart, className: "rounded-full p-2 text-neutral-400 hover:bg-neutral-800 hover:text-white transition-colors", "data-preview-static": "cart-close-btn", "aria-label": "Close cart", children: (0, jsx_runtime_1.jsx)("svg", { className: "h-5 w-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] })] }), freeShippingThreshold && ((0, jsx_runtime_1.jsxs)("div", { className: "border-b border-neutral-800 bg-neutral-950/50 px-6 py-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between text-xs text-neutral-400 mb-1.5", children: [(0, jsx_runtime_1.jsx)("span", { children: subtotal >= freeShippingThreshold ? ((0, jsx_runtime_1.jsx)("span", { className: "font-semibold text-emerald-400", children: "\uD83C\uDF89 You unlocked free shipping!" })) : ((0, jsx_runtime_1.jsxs)("span", { children: ["Add ", (0, jsx_runtime_1.jsxs)("strong", { className: "text-white", children: [currency, (freeShippingThreshold - subtotal).toFixed(2)] }), " more for free shipping"] })) }), (0, jsx_runtime_1.jsxs)("span", { children: [progressPercent, "%"] })] }), (0, jsx_runtime_1.jsx)("div", { className: "h-1.5 w-full overflow-hidden rounded-full bg-neutral-800", children: (0, jsx_runtime_1.jsx)("div", { className: "h-full bg-emerald-500 transition-all duration-300", style: { width: `${progressPercent}%` } }) })] })), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 overflow-y-auto px-6 py-4", children: items.length === 0 ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex h-full flex-col items-center justify-center text-center py-12", children: [(0, jsx_runtime_1.jsx)("div", { className: "mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-neutral-800 text-neutral-400", children: (0, jsx_runtime_1.jsx)("svg", { className: "h-8 w-8", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" }) }) }), (0, jsx_runtime_1.jsx)("h3", { className: "text-base font-semibold text-white", "data-preview-field-path": fieldPath('emptyTitle'), children: emptyTitle }), (0, jsx_runtime_1.jsx)("p", { className: "mt-1 text-sm text-neutral-400 max-w-xs", "data-preview-field-path": fieldPath('emptyMessage'), children: emptyMessage })] })) : ((0, jsx_runtime_1.jsx)("ul", { className: "divide-y divide-neutral-800", "data-preview-list-path": fieldPath('items'), children: items.map((item, idx) => ((0, jsx_runtime_1.jsxs)("li", { className: "flex gap-4 py-4", "data-preview-item-path": `${fieldPath('items')}[${idx}]`, children: [item.image ? ((0, jsx_runtime_1.jsx)("img", { src: (0, urls_1.withBasePath)(item.image), alt: item.name, className: "h-20 w-20 flex-shrink-0 rounded-lg object-cover bg-neutral-800 border border-neutral-700", "data-preview-static": "cart-item-image" })) : ((0, jsx_runtime_1.jsx)("div", { className: "flex h-20 w-20 flex-shrink-0 items-center justify-center rounded-lg bg-neutral-800 text-neutral-500 border border-neutral-700", "data-preview-static": "cart-item-placeholder", children: (0, jsx_runtime_1.jsx)("svg", { className: "h-8 w-8", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" }) }) })), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-1 flex-col justify-between", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between", children: [(0, jsx_runtime_1.jsx)("h4", { className: "text-sm font-medium text-white line-clamp-1", children: item.name }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => removeItem(item.id, item.size, item.color), className: "text-neutral-500 hover:text-red-400 transition-colors p-1", "data-preview-static": "cart-item-remove", "aria-label": `Remove ${item.name}`, children: (0, jsx_runtime_1.jsx)("svg", { className: "h-4 w-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) }) })] }), (item.size || item.color) && ((0, jsx_runtime_1.jsxs)("p", { className: "mt-0.5 text-xs text-neutral-400", children: [item.size && `Size: ${item.size}`, item.size && item.color && ' · ', item.color && `Color: ${item.color}`] })), (0, jsx_runtime_1.
|
|
54
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: `deneb-cart-drawer-root fixed inset-0 z-50 flex justify-end ${className}`, children: [(0, jsx_runtime_1.jsx)("div", { className: "fixed inset-0 bg-black/60 backdrop-blur-sm transition-opacity", onClick: closeCart, "data-preview-static": "cart-backdrop", "aria-hidden": "true" }), (0, jsx_runtime_1.jsxs)("aside", { className: "relative z-10 flex h-full w-full max-w-md flex-col bg-neutral-900 text-white shadow-2xl transition-transform duration-300 ease-out border-l border-neutral-800", "aria-label": "Shopping Cart Drawer", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between border-b border-neutral-800 px-6 py-5", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h2", { className: "text-xl font-bold tracking-tight text-white", "data-preview-field-path": fieldPath('title'), children: title }), (0, jsx_runtime_1.jsx)("p", { className: "text-xs text-neutral-400 mt-0.5", "data-preview-field-path": fieldPath('subtitle'), children: subtitle })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [items.length > 0 && ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: clearCart, className: "text-xs text-neutral-400 hover:text-red-400 transition-colors px-2 py-1 rounded", "data-preview-static": "cart-clear-btn", children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": fieldPath('clearCartText'), children: clearCartText }) })), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: closeCart, className: "rounded-full p-2 text-neutral-400 hover:bg-neutral-800 hover:text-white transition-colors", "data-preview-static": "cart-close-btn", "aria-label": "Close cart", children: (0, jsx_runtime_1.jsx)("svg", { className: "h-5 w-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] })] }), freeShippingThreshold && ((0, jsx_runtime_1.jsxs)("div", { className: "border-b border-neutral-800 bg-neutral-950/50 px-6 py-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between text-xs text-neutral-400 mb-1.5", children: [(0, jsx_runtime_1.jsx)("span", { children: subtotal >= freeShippingThreshold ? ((0, jsx_runtime_1.jsx)("span", { className: "font-semibold text-emerald-400", children: "\uD83C\uDF89 You unlocked free shipping!" })) : ((0, jsx_runtime_1.jsxs)("span", { children: ["Add ", (0, jsx_runtime_1.jsxs)("strong", { className: "text-white", children: [currency, (freeShippingThreshold - subtotal).toFixed(2)] }), " more for free shipping"] })) }), (0, jsx_runtime_1.jsxs)("span", { children: [progressPercent, "%"] })] }), (0, jsx_runtime_1.jsx)("div", { className: "h-1.5 w-full overflow-hidden rounded-full bg-neutral-800", children: (0, jsx_runtime_1.jsx)("div", { className: "h-full bg-emerald-500 transition-all duration-300", style: { width: `${progressPercent}%` } }) })] })), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 overflow-y-auto px-6 py-4", children: items.length === 0 ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex h-full flex-col items-center justify-center text-center py-12", children: [(0, jsx_runtime_1.jsx)("div", { className: "mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-neutral-800 text-neutral-400", children: (0, jsx_runtime_1.jsx)("svg", { className: "h-8 w-8", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" }) }) }), (0, jsx_runtime_1.jsx)("h3", { className: "text-base font-semibold text-white", "data-preview-field-path": fieldPath('emptyTitle'), children: emptyTitle }), (0, jsx_runtime_1.jsx)("p", { className: "mt-1 text-sm text-neutral-400 max-w-xs", "data-preview-field-path": fieldPath('emptyMessage'), children: emptyMessage })] })) : ((0, jsx_runtime_1.jsx)("ul", { className: "divide-y divide-neutral-800", "data-preview-list-path": fieldPath('items'), children: items.map((item, idx) => ((0, jsx_runtime_1.jsxs)("li", { className: "flex gap-4 py-4", "data-preview-item-path": `${fieldPath('items')}[${idx}]`, children: [item.image ? ((0, jsx_runtime_1.jsx)("img", { src: (0, urls_1.withBasePath)(item.image), alt: item.name, className: "h-20 w-20 flex-shrink-0 rounded-lg object-cover bg-neutral-800 border border-neutral-700", "data-preview-static": "cart-item-image" })) : ((0, jsx_runtime_1.jsx)("div", { className: "flex h-20 w-20 flex-shrink-0 items-center justify-center rounded-lg bg-neutral-800 text-neutral-500 border border-neutral-700", "data-preview-static": "cart-item-placeholder", children: (0, jsx_runtime_1.jsx)("svg", { className: "h-8 w-8", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" }) }) })), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-1 flex-col justify-between", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between", children: [(0, jsx_runtime_1.jsx)("h4", { className: "text-sm font-medium text-white line-clamp-1", children: item.name }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => removeItem(item.id, item.size, item.color), className: "text-neutral-500 hover:text-red-400 transition-colors p-1", "data-preview-static": "cart-item-remove", "aria-label": `Remove ${item.name}`, children: (0, jsx_runtime_1.jsx)("svg", { className: "h-4 w-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) }) })] }), (item.brand || item.size || item.color) && ((0, jsx_runtime_1.jsxs)("p", { className: "mt-0.5 text-xs text-neutral-400", children: [item.brand && (0, jsx_runtime_1.jsx)("span", { className: "text-emerald-400 font-semibold", children: item.brand }), item.brand && (item.size || item.color) && ' · ', item.size && `Size: ${item.size}`, item.size && item.color && ' · ', item.color && `Color: ${item.color}`] })), (0, jsx_runtime_1.jsx)("p", { className: "mt-1 text-sm font-semibold text-emerald-400", children: (0, useCart_1.formatCurrency)(item.price * item.quantity, currency) })] }), (0, jsx_runtime_1.jsx)("div", { className: "flex items-center gap-2 mt-2", children: (0, jsx_runtime_1.jsxs)("div", { className: "inline-flex items-center rounded-lg border border-neutral-700 bg-neutral-800", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => updateQuantity(item.id, item.quantity - 1, item.size, item.color), className: "h-7 w-7 flex items-center justify-center text-neutral-300 hover:text-white transition-colors", "data-preview-static": "cart-item-decrement", "aria-label": "Decrease quantity", children: "-" }), (0, jsx_runtime_1.jsx)("span", { className: "w-8 text-center text-xs font-semibold text-white", children: item.quantity }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => updateQuantity(item.id, item.quantity + 1, item.size, item.color), className: "h-7 w-7 flex items-center justify-center text-neutral-300 hover:text-white transition-colors", "data-preview-static": "cart-item-increment", "aria-label": "Increase quantity", children: "+" })] }) })] })] }, `${item.id}-${item.size || ''}-${item.color || ''}`))) })) }), items.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "border-t border-neutral-800 bg-neutral-950 px-6 py-5", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-baseline mb-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-sm text-neutral-400", "data-preview-field-path": fieldPath('subtotalLabel'), children: subtotalLabel }), (0, jsx_runtime_1.jsx)("span", { className: "text-xl font-bold text-white", children: (0, useCart_1.formatCurrency)(subtotal, currency) })] }), (0, jsx_runtime_1.jsx)("p", { className: "text-xs text-neutral-500 mb-4", "data-preview-field-path": fieldPath('shippingNote'), children: shippingNote }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-2.5", children: [(0, jsx_runtime_1.jsxs)("a", { href: whatsappHref, target: "_blank", rel: "noopener noreferrer", "data-preview-static": "cart-whatsapp-cta", className: "flex w-full items-center justify-center gap-2 rounded-xl bg-emerald-600 px-5 py-3.5 text-sm font-semibold text-white shadow-lg shadow-emerald-900/30 hover:bg-emerald-500 transition-all active:scale-[0.98]", children: [(0, jsx_runtime_1.jsx)("svg", { className: "h-4 w-4 fill-current", 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-.711 2.598 2.664-.699c.971.531 1.769.813 2.796.813h.001c3.182 0 5.768-2.586 5.768-5.766 0-3.18-2.586-5.766-5.769-5.766zm9.969 5.766c0 5.518-4.482 10-10 10-1.745 0-3.415-.453-4.887-1.258l-5.113 1.341 1.365-4.989c-.931-1.537-1.465-3.327-1.465-5.094 0-5.518 4.482-10 10-10 5.518 0 10 4.482 10 10z" }) }), (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": fieldPath('whatsappButtonText'), children: whatsappButtonText })] }), (checkoutUrl || onCheckout) && ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => {
|
|
55
55
|
if (onCheckout)
|
|
56
56
|
onCheckout(items, subtotal);
|
|
57
57
|
if (checkoutUrl)
|
|
@@ -7,6 +7,7 @@ export interface ProductItem {
|
|
|
7
7
|
brand?: string;
|
|
8
8
|
price?: string | number;
|
|
9
9
|
originalPrice?: string | number;
|
|
10
|
+
currency?: string;
|
|
10
11
|
description?: string;
|
|
11
12
|
category?: string;
|
|
12
13
|
imageUrl?: string;
|
|
@@ -17,6 +18,10 @@ export interface ProductItem {
|
|
|
17
18
|
reviewsCount?: number | string;
|
|
18
19
|
isNew?: boolean;
|
|
19
20
|
isBestSeller?: boolean;
|
|
21
|
+
whatsappNumber?: string;
|
|
22
|
+
whatsappButtonText?: string;
|
|
23
|
+
addToCartButtonText?: string;
|
|
24
|
+
buttonText?: string;
|
|
20
25
|
unit?: MeasurementUnit;
|
|
21
26
|
measurement?: string;
|
|
22
27
|
optionsLabel?: string;
|
|
@@ -55,6 +60,14 @@ export interface EditableProductCardProps extends React.HTMLAttributes<HTMLEleme
|
|
|
55
60
|
* HTML wrapper tag (default: 'article').
|
|
56
61
|
*/
|
|
57
62
|
as?: React.ElementType;
|
|
63
|
+
/**
|
|
64
|
+
* Currency code or symbol (default: 'LKR').
|
|
65
|
+
*/
|
|
66
|
+
currency?: string;
|
|
67
|
+
/**
|
|
68
|
+
* Whether to display the brand tag (default: true).
|
|
69
|
+
*/
|
|
70
|
+
showBrand?: boolean;
|
|
58
71
|
/**
|
|
59
72
|
* Whether to display the price field (default: true).
|
|
60
73
|
*/
|
|
@@ -68,21 +81,53 @@ export interface EditableProductCardProps extends React.HTMLAttributes<HTMLEleme
|
|
|
68
81
|
*/
|
|
69
82
|
showCategory?: boolean;
|
|
70
83
|
/**
|
|
71
|
-
*
|
|
84
|
+
* Default WhatsApp account number for inquiries (e.g. '94771234567').
|
|
85
|
+
*/
|
|
86
|
+
whatsappNumber?: string;
|
|
87
|
+
/**
|
|
88
|
+
* Store name for WhatsApp message templates.
|
|
89
|
+
*/
|
|
90
|
+
storeName?: string;
|
|
91
|
+
/**
|
|
92
|
+
* Whether to display the WhatsApp contact button (default: true).
|
|
93
|
+
*/
|
|
94
|
+
showWhatsAppButton?: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Whether to display the Add to Cart button (default: true).
|
|
97
|
+
*/
|
|
98
|
+
showAddToCartButton?: boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Default label for the WhatsApp button (default: 'Inquire on WhatsApp').
|
|
101
|
+
*/
|
|
102
|
+
whatsappActionLabel?: string;
|
|
103
|
+
/**
|
|
104
|
+
* Default label for the Add to Cart button (default: 'Add to Cart').
|
|
105
|
+
*/
|
|
106
|
+
addToCartLabel?: string;
|
|
107
|
+
/**
|
|
108
|
+
* Optional custom action slot (overrides dual action buttons).
|
|
72
109
|
*/
|
|
73
110
|
actionSlot?: React.ReactNode;
|
|
74
111
|
/**
|
|
75
|
-
*
|
|
112
|
+
* Legacy action label fallback.
|
|
76
113
|
*/
|
|
77
114
|
actionLabel?: string;
|
|
78
115
|
/**
|
|
79
|
-
*
|
|
116
|
+
* Legacy action label path fallback.
|
|
80
117
|
*/
|
|
81
118
|
actionLabelPath?: string;
|
|
119
|
+
/**
|
|
120
|
+
* Optional callback when Add to Cart is clicked.
|
|
121
|
+
*/
|
|
122
|
+
onAddToCart?: (product: ProductItem) => void;
|
|
123
|
+
/**
|
|
124
|
+
* Optional callback when WhatsApp button is clicked.
|
|
125
|
+
*/
|
|
126
|
+
onWhatsAppClick?: (product: ProductItem, url: string) => void;
|
|
82
127
|
}
|
|
83
128
|
/**
|
|
84
|
-
* EditableProductCard is an elite, auto-balancing commerce card
|
|
85
|
-
*
|
|
86
|
-
* strict Fivora visual editing synchronization.
|
|
129
|
+
* EditableProductCard is an elite, auto-balancing commerce card featuring
|
|
130
|
+
* Sri Lankan Rupee (LKR) pricing, dual WhatsApp + Add to Cart actions,
|
|
131
|
+
* brand attribution, and strict Fivora visual editing synchronization.
|
|
87
132
|
*/
|
|
88
|
-
export declare function EditableProductCard({ itemPath, product, cardVariant, imageFallback, as: Component, showPrice, showDescription, showCategory, actionSlot, actionLabel, actionLabelPath, className, style, ...props }: EditableProductCardProps): React.JSX.Element;
|
|
133
|
+
export declare function EditableProductCard({ itemPath, product, cardVariant, imageFallback, as: Component, currency, showBrand, showPrice, showDescription, showCategory, whatsappNumber, storeName, showWhatsAppButton, showAddToCartButton, whatsappActionLabel, addToCartLabel, actionSlot, actionLabel, actionLabelPath, onAddToCart, onWhatsAppClick, className, style, ...props }: EditableProductCardProps): React.JSX.Element;
|
|
@@ -5,21 +5,65 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
5
5
|
const EditableText_1 = require("./EditableText");
|
|
6
6
|
const EditableImage_1 = require("./EditableImage");
|
|
7
7
|
const EditableText_2 = require("./EditableText");
|
|
8
|
+
const useCart_1 = require("./cart/useCart");
|
|
9
|
+
// Clean inline SVG icons for zero external dependencies
|
|
10
|
+
function WhatsAppIcon({ className = '', style = {} }) {
|
|
11
|
+
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
|
+
}
|
|
13
|
+
function CartIcon({ className = '', style = {} }) {
|
|
14
|
+
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
|
+
}
|
|
8
16
|
/**
|
|
9
|
-
* EditableProductCard is an elite, auto-balancing commerce card
|
|
10
|
-
*
|
|
11
|
-
* strict Fivora visual editing synchronization.
|
|
17
|
+
* EditableProductCard is an elite, auto-balancing commerce card featuring
|
|
18
|
+
* Sri Lankan Rupee (LKR) pricing, dual WhatsApp + Add to Cart actions,
|
|
19
|
+
* brand attribution, and strict Fivora visual editing synchronization.
|
|
12
20
|
*/
|
|
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
|
-
const
|
|
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 }) {
|
|
22
|
+
const cart = (0, useCart_1.useOptionalCart)();
|
|
23
|
+
const name = String(product?.name || product?.title || 'Untitled Product');
|
|
24
|
+
const brand = String(product?.brand || '');
|
|
15
25
|
const hasPrice = showPrice && product?.price !== undefined && product?.price !== null && String(product.price).trim() !== '';
|
|
16
|
-
const
|
|
26
|
+
const rawPrice = product?.price;
|
|
27
|
+
const priceNum = typeof rawPrice === 'number' ? rawPrice : parseFloat(String(rawPrice || '').replace(/[^0-9.]/g, '')) || 0;
|
|
28
|
+
const formattedPrice = hasPrice ? (typeof rawPrice === 'string' && rawPrice.includes('LKR') ? rawPrice : (0, useCart_1.formatCurrency)(priceNum, currency)) : '';
|
|
17
29
|
const originalPrice = product?.originalPrice !== undefined ? String(product.originalPrice) : '';
|
|
18
30
|
const description = String(product?.description || '');
|
|
19
31
|
const category = String(product?.category || '');
|
|
20
32
|
const badge = String(product?.badge || '');
|
|
21
33
|
const imageUrl = String(product?.imageUrl || product?.image || '');
|
|
34
|
+
// Resolved phone number for WhatsApp
|
|
35
|
+
const resolvedPhone = String(product?.whatsappNumber || whatsappNumber || '94770000000');
|
|
36
|
+
const resolvedWhatsAppText = String(product?.whatsappButtonText || whatsappActionLabel);
|
|
37
|
+
const resolvedAddToCartText = String(product?.addToCartButtonText || addToCartLabel);
|
|
22
38
|
const isHorizontal = cardVariant === 'horizontal';
|
|
39
|
+
const handleWhatsAppClick = (e) => {
|
|
40
|
+
e.stopPropagation();
|
|
41
|
+
const url = (0, useCart_1.getProductWhatsAppUrl)({ ...product, name, brand, price: formattedPrice }, resolvedPhone, { storeName, currency });
|
|
42
|
+
if (onWhatsAppClick) {
|
|
43
|
+
onWhatsAppClick(product, url);
|
|
44
|
+
}
|
|
45
|
+
if (typeof window !== 'undefined') {
|
|
46
|
+
window.open(url, '_blank', 'noopener,noreferrer');
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const handleAddToCartClick = (e) => {
|
|
50
|
+
e.stopPropagation();
|
|
51
|
+
const itemToAdd = {
|
|
52
|
+
id: String(product?.id || name.toLowerCase().replace(/\s+/g, '-')),
|
|
53
|
+
name,
|
|
54
|
+
brand,
|
|
55
|
+
price: priceNum,
|
|
56
|
+
image: imageUrl,
|
|
57
|
+
quantity: 1,
|
|
58
|
+
};
|
|
59
|
+
if (cart) {
|
|
60
|
+
cart.addItem(itemToAdd);
|
|
61
|
+
cart.openCart();
|
|
62
|
+
}
|
|
63
|
+
if (onAddToCart) {
|
|
64
|
+
onAddToCart(product);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
23
67
|
const variantStyles = {
|
|
24
68
|
'modern-glass': {
|
|
25
69
|
backgroundColor: 'rgba(255, 255, 255, 0.85)',
|
|
@@ -30,27 +74,33 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
|
|
|
30
74
|
boxShadow: '0 10px 25px -5px rgba(0, 0, 0, 0.05), 0 8px 10px -6px rgba(0, 0, 0, 0.01)',
|
|
31
75
|
overflow: 'hidden',
|
|
32
76
|
transition: 'transform 0.25s ease, box-shadow 0.25s ease',
|
|
77
|
+
display: 'flex',
|
|
78
|
+
flexDirection: 'column',
|
|
33
79
|
},
|
|
34
80
|
classic: {
|
|
35
81
|
backgroundColor: '#ffffff',
|
|
36
82
|
border: '1px solid #e2e8f0',
|
|
37
|
-
borderRadius: '
|
|
83
|
+
borderRadius: '14px',
|
|
38
84
|
boxShadow: '0 1px 3px 0 rgba(0, 0, 0, 0.05)',
|
|
39
85
|
overflow: 'hidden',
|
|
40
86
|
transition: 'transform 0.2s ease',
|
|
87
|
+
display: 'flex',
|
|
88
|
+
flexDirection: 'column',
|
|
41
89
|
},
|
|
42
90
|
minimal: {
|
|
43
91
|
backgroundColor: 'transparent',
|
|
44
92
|
border: 'none',
|
|
45
93
|
overflow: 'hidden',
|
|
94
|
+
display: 'flex',
|
|
95
|
+
flexDirection: 'column',
|
|
46
96
|
},
|
|
47
97
|
horizontal: {
|
|
48
98
|
backgroundColor: '#ffffff',
|
|
49
99
|
border: '1px solid #e2e8f0',
|
|
50
|
-
borderRadius: '
|
|
100
|
+
borderRadius: '16px',
|
|
51
101
|
overflow: 'hidden',
|
|
52
102
|
display: 'flex',
|
|
53
|
-
flexDirection: '
|
|
103
|
+
flexDirection: 'row',
|
|
54
104
|
alignItems: 'stretch',
|
|
55
105
|
},
|
|
56
106
|
};
|
|
@@ -60,7 +110,7 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
|
|
|
60
110
|
}, className: `editable-product-card group ${isHorizontal ? 'is-horizontal' : ''} ${className}`.trim(), ...props, children: [(0, jsx_runtime_1.jsxs)("div", { className: "deneb-product-card-media", style: {
|
|
61
111
|
position: 'relative',
|
|
62
112
|
overflow: 'hidden',
|
|
63
|
-
width: isHorizontal ? '
|
|
113
|
+
width: isHorizontal ? '40%' : '100%',
|
|
64
114
|
flexShrink: 0,
|
|
65
115
|
}, children: [(0, jsx_runtime_1.jsx)(EditableImage_1.EditableImage, { id: `${itemPath}.imageUrl`, "data-preview-field-path": `${itemPath}.imageUrl`, src: imageUrl, fallbackSrc: imageFallback, alt: name, aspectRatio: isHorizontal ? 'square' : '4/3', fit: "cover", hoverZoom: true, style: { width: '100%', height: '100%', display: 'block' } }), badge && ((0, jsx_runtime_1.jsx)("div", { style: { position: 'absolute', top: '10px', left: '10px', zIndex: 10 }, children: (0, jsx_runtime_1.jsx)(EditableText_2.EditableBadge, { id: `${itemPath}.badge`, "data-preview-field-path": `${itemPath}.badge`, defaultValue: badge, badgeVariant: "primary" }) }))] }), (0, jsx_runtime_1.jsxs)("div", { style: {
|
|
66
116
|
padding: '1.25rem',
|
|
@@ -68,37 +118,49 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
|
|
|
68
118
|
flexDirection: 'column',
|
|
69
119
|
flex: 1,
|
|
70
120
|
justifyContent: 'space-between',
|
|
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: {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
121
|
+
}, children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '0.5rem', marginBottom: '0.375rem' }, children: [showCategory && category ? ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.category`, "data-preview-field-path": `${itemPath}.category`, defaultValue: category, style: {
|
|
122
|
+
fontSize: '0.75rem',
|
|
123
|
+
textTransform: 'uppercase',
|
|
124
|
+
letterSpacing: '0.05em',
|
|
125
|
+
color: 'var(--brand-accent, #14b8a6)',
|
|
126
|
+
fontWeight: 600,
|
|
127
|
+
display: 'inline-block',
|
|
128
|
+
} })) : null, showBrand && brand ? ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.brand`, "data-preview-field-path": `${itemPath}.brand`, defaultValue: brand, style: {
|
|
129
|
+
fontSize: '0.75rem',
|
|
130
|
+
fontWeight: 700,
|
|
131
|
+
letterSpacing: '0.08em',
|
|
132
|
+
textTransform: 'uppercase',
|
|
133
|
+
color: 'var(--muted-text, #64748b)',
|
|
134
|
+
backgroundColor: 'rgba(241, 245, 249, 0.9)',
|
|
135
|
+
padding: '2px 8px',
|
|
136
|
+
borderRadius: '6px',
|
|
137
|
+
} })) : null] }), (0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "h3", id: `${itemPath}.name`, "data-preview-field-path": `${itemPath}.name`, defaultValue: name, style: {
|
|
80
138
|
fontSize: '1.125rem',
|
|
81
139
|
fontWeight: 700,
|
|
82
|
-
lineHeight: 1.
|
|
140
|
+
lineHeight: 1.35,
|
|
83
141
|
color: 'var(--heading-color, #0f172a)',
|
|
84
142
|
marginBottom: '0.375rem',
|
|
85
|
-
} }), showDescription && ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "p", id: `${itemPath}.description`, "data-preview-field-path": `${itemPath}.description`, defaultValue: description, style: {
|
|
143
|
+
} }), showDescription && description ? ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "p", id: `${itemPath}.description`, "data-preview-field-path": `${itemPath}.description`, defaultValue: description, style: {
|
|
86
144
|
fontSize: '0.875rem',
|
|
87
145
|
color: 'var(--muted-text, #64748b)',
|
|
88
146
|
lineHeight: 1.5,
|
|
89
147
|
marginBottom: '0.75rem',
|
|
90
|
-
|
|
148
|
+
display: '-webkit-box',
|
|
149
|
+
WebkitLineClamp: 2,
|
|
150
|
+
WebkitBoxOrient: 'vertical',
|
|
151
|
+
overflow: 'hidden',
|
|
152
|
+
} })) : null] }), (0, jsx_runtime_1.jsxs)("div", { style: {
|
|
91
153
|
marginTop: '0.75rem',
|
|
92
154
|
paddingTop: '0.75rem',
|
|
93
|
-
borderTop: cardVariant === 'minimal' ? 'none' : '1px solid rgba(226, 232, 240, 0.
|
|
155
|
+
borderTop: cardVariant === 'minimal' ? 'none' : '1px solid rgba(226, 232, 240, 0.7)',
|
|
94
156
|
display: 'flex',
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
fontWeight: 700,
|
|
157
|
+
flexDirection: 'column',
|
|
158
|
+
gap: '0.75rem',
|
|
159
|
+
}, 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}.price`, "data-preview-field-path": `${itemPath}.price`, defaultValue: formattedPrice, style: {
|
|
160
|
+
fontSize: '1.3rem',
|
|
161
|
+
fontWeight: 800,
|
|
101
162
|
color: 'var(--brand-color, #2563eb)',
|
|
163
|
+
letterSpacing: '-0.02em',
|
|
102
164
|
} }), originalPrice ? ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.originalPrice`, "data-preview-field-path": `${itemPath}.originalPrice`, defaultValue: originalPrice, style: {
|
|
103
165
|
fontSize: '0.875rem',
|
|
104
166
|
textDecoration: 'line-through',
|
|
@@ -107,16 +169,40 @@ function EditableProductCard({ itemPath, product, cardVariant = 'modern-glass',
|
|
|
107
169
|
fontSize: '0.8rem',
|
|
108
170
|
fontWeight: 500,
|
|
109
171
|
color: 'var(--muted-text, #64748b)',
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
172
|
+
} })) : null] })) : null, actionSlot ? ((0, jsx_runtime_1.jsx)("div", { children: actionSlot })) : ((0, jsx_runtime_1.jsxs)("div", { style: {
|
|
173
|
+
display: 'grid',
|
|
174
|
+
gridTemplateColumns: showWhatsAppButton && showAddToCartButton ? '1fr 1fr' : '1fr',
|
|
175
|
+
gap: '0.5rem',
|
|
176
|
+
width: '100%',
|
|
177
|
+
}, children: [showWhatsAppButton && ((0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: handleWhatsAppClick, title: "Chat directly on WhatsApp about this product", style: {
|
|
178
|
+
backgroundColor: '#25D366',
|
|
179
|
+
color: '#ffffff',
|
|
180
|
+
border: 'none',
|
|
181
|
+
padding: '0.55rem 0.75rem',
|
|
182
|
+
borderRadius: '10px',
|
|
183
|
+
fontSize: '0.8125rem',
|
|
184
|
+
fontWeight: 600,
|
|
185
|
+
cursor: 'pointer',
|
|
186
|
+
display: 'flex',
|
|
187
|
+
alignItems: 'center',
|
|
188
|
+
justifyContent: 'center',
|
|
189
|
+
gap: '0.375rem',
|
|
190
|
+
transition: 'all 0.2s ease',
|
|
191
|
+
boxShadow: '0 2px 8px rgba(37, 211, 102, 0.25)',
|
|
192
|
+
}, className: "hover:brightness-105 active:scale-95", children: [(0, jsx_runtime_1.jsx)(WhatsAppIcon, {}), (0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.whatsappButtonText`, "data-preview-field-path": `${itemPath}.whatsappButtonText`, defaultValue: resolvedWhatsAppText, style: { color: '#ffffff', fontWeight: 600, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' } })] })), showAddToCartButton && ((0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: handleAddToCartClick, title: "Add this product to shopping cart", style: {
|
|
193
|
+
backgroundColor: 'var(--brand-color, #2563eb)',
|
|
194
|
+
color: '#ffffff',
|
|
195
|
+
border: 'none',
|
|
196
|
+
padding: '0.55rem 0.75rem',
|
|
197
|
+
borderRadius: '10px',
|
|
198
|
+
fontSize: '0.8125rem',
|
|
199
|
+
fontWeight: 600,
|
|
200
|
+
cursor: 'pointer',
|
|
201
|
+
display: 'flex',
|
|
202
|
+
alignItems: 'center',
|
|
203
|
+
justifyContent: 'center',
|
|
204
|
+
gap: '0.375rem',
|
|
205
|
+
transition: 'all 0.2s ease',
|
|
206
|
+
boxShadow: '0 2px 8px rgba(37, 99, 235, 0.25)',
|
|
207
|
+
}, className: "hover:brightness-105 active:scale-95", children: [(0, jsx_runtime_1.jsx)(CartIcon, {}), (0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.addToCartButtonText`, "data-preview-field-path": `${itemPath}.addToCartButtonText`, defaultValue: resolvedAddToCartText, style: { color: '#ffffff', fontWeight: 600, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' } })] }))] }))] })] })] }));
|
|
122
208
|
}
|
package/dist/cart/useCart.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import React from 'react';
|
|
|
2
2
|
export interface CartItem {
|
|
3
3
|
id: string;
|
|
4
4
|
name: string;
|
|
5
|
+
brand?: string;
|
|
5
6
|
price: number;
|
|
6
7
|
originalPrice?: number;
|
|
7
8
|
image?: string;
|
|
@@ -11,6 +12,17 @@ export interface CartItem {
|
|
|
11
12
|
sku?: string;
|
|
12
13
|
metadata?: Record<string, unknown>;
|
|
13
14
|
}
|
|
15
|
+
export declare function formatCurrency(amount: number, currency?: string): string;
|
|
16
|
+
export declare function getProductWhatsAppUrl(product: {
|
|
17
|
+
name?: string;
|
|
18
|
+
title?: string;
|
|
19
|
+
brand?: string;
|
|
20
|
+
price?: string | number;
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
}, whatsappNumber: string, options?: {
|
|
23
|
+
storeName?: string;
|
|
24
|
+
currency?: string;
|
|
25
|
+
}): string;
|
|
14
26
|
export interface CartContextValue {
|
|
15
27
|
items: CartItem[];
|
|
16
28
|
isOpen: boolean;
|
|
@@ -34,4 +46,5 @@ export declare function CartProvider({ children, storageKey, }: {
|
|
|
34
46
|
children: React.ReactNode;
|
|
35
47
|
storageKey?: string;
|
|
36
48
|
}): React.JSX.Element;
|
|
49
|
+
export declare function useOptionalCart(): CartContextValue | null;
|
|
37
50
|
export declare function useCart(): CartContextValue;
|
package/dist/cart/useCart.js
CHANGED
|
@@ -1,10 +1,39 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
'use client';
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.formatCurrency = formatCurrency;
|
|
5
|
+
exports.getProductWhatsAppUrl = getProductWhatsAppUrl;
|
|
4
6
|
exports.CartProvider = CartProvider;
|
|
7
|
+
exports.useOptionalCart = useOptionalCart;
|
|
5
8
|
exports.useCart = useCart;
|
|
6
9
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
10
|
const react_1 = require("react");
|
|
11
|
+
function formatCurrency(amount, currency = 'LKR') {
|
|
12
|
+
const formatted = (amount || 0).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
13
|
+
if (currency === 'LKR' || currency === 'Rs.' || currency === 'Rs') {
|
|
14
|
+
return `LKR ${formatted}`;
|
|
15
|
+
}
|
|
16
|
+
if (currency === '$' || currency === 'USD') {
|
|
17
|
+
return `$${formatted}`;
|
|
18
|
+
}
|
|
19
|
+
return `${currency} ${formatted}`;
|
|
20
|
+
}
|
|
21
|
+
function getProductWhatsAppUrl(product, whatsappNumber, options) {
|
|
22
|
+
const cleanNumber = (whatsappNumber || '').replace(/\D/g, '');
|
|
23
|
+
const title = product.name || product.title || 'Product';
|
|
24
|
+
const brand = product.brand ? ` (Brand: ${product.brand})` : '';
|
|
25
|
+
const priceNum = typeof product.price === 'number' ? product.price : parseFloat(String(product.price || '').replace(/[^0-9.]/g, '')) || 0;
|
|
26
|
+
const priceStr = priceNum > 0 ? `\nPrice: ${formatCurrency(priceNum, options?.currency || 'LKR')}` : '';
|
|
27
|
+
const store = options?.storeName ? ` at ${options.storeName}` : '';
|
|
28
|
+
const message = [
|
|
29
|
+
`Hello${store}! 👋`,
|
|
30
|
+
`I am interested in this product:`,
|
|
31
|
+
`*${title}*${brand}${priceStr}`,
|
|
32
|
+
'',
|
|
33
|
+
`Could you please share more details, availability, and ordering instructions? Thank you!`,
|
|
34
|
+
].join('\n');
|
|
35
|
+
return `https://wa.me/${cleanNumber}?text=${encodeURIComponent(message)}`;
|
|
36
|
+
}
|
|
8
37
|
const CartContext = (0, react_1.createContext)(null);
|
|
9
38
|
const STORAGE_KEY = 'deneb_cart_items_v1';
|
|
10
39
|
function CartProvider({ children, storageKey = STORAGE_KEY, }) {
|
|
@@ -78,30 +107,32 @@ function CartProvider({ children, storageKey = STORAGE_KEY, }) {
|
|
|
78
107
|
const totalCount = (0, react_1.useMemo)(() => items.reduce((acc, item) => acc + item.quantity, 0), [items]);
|
|
79
108
|
const subtotal = (0, react_1.useMemo)(() => items.reduce((acc, item) => acc + item.price * item.quantity, 0), [items]);
|
|
80
109
|
const getWhatsAppOrderUrl = (0, react_1.useCallback)((whatsappNumber, options) => {
|
|
81
|
-
const cleanNumber = whatsappNumber.replace(/\D/g, '');
|
|
82
|
-
const currency = options?.currency || '
|
|
110
|
+
const cleanNumber = (whatsappNumber || '').replace(/\D/g, '');
|
|
111
|
+
const currency = options?.currency || 'LKR';
|
|
83
112
|
const store = options?.storeName ? ` at *${options.storeName}*` : '';
|
|
84
113
|
const lines = [
|
|
85
|
-
|
|
86
|
-
|
|
114
|
+
`🛒 *New Order Request${store}*`,
|
|
115
|
+
`📅 Date: ${new Date().toLocaleDateString()}`,
|
|
87
116
|
'',
|
|
88
|
-
'*Order Items:*',
|
|
117
|
+
'📦 *Order Items:*',
|
|
89
118
|
];
|
|
90
119
|
items.forEach((item, index) => {
|
|
120
|
+
const brandStr = item.brand ? ` (Brand: *${item.brand}*)` : '';
|
|
91
121
|
const variantParts = [];
|
|
92
122
|
if (item.size)
|
|
93
123
|
variantParts.push(`Size: ${item.size}`);
|
|
94
124
|
if (item.color)
|
|
95
125
|
variantParts.push(`Color: ${item.color}`);
|
|
96
|
-
const variantStr = variantParts.length > 0 ? `
|
|
97
|
-
lines.push(`${index + 1}. *${item.name}*${variantStr}`);
|
|
98
|
-
lines.push(` Qty: ${item.quantity} x ${
|
|
126
|
+
const variantStr = variantParts.length > 0 ? ` [${variantParts.join(', ')}]` : '';
|
|
127
|
+
lines.push(`${index + 1}. *${item.name}*${brandStr}${variantStr}`);
|
|
128
|
+
lines.push(` Qty: ${item.quantity} x ${formatCurrency(item.price, currency)} = *${formatCurrency(item.price * item.quantity, currency)}*`);
|
|
99
129
|
});
|
|
100
130
|
lines.push('');
|
|
101
|
-
lines.push(
|
|
102
|
-
lines.push(
|
|
131
|
+
lines.push('──────────────────────────────');
|
|
132
|
+
lines.push(`💰 *Grand Total: ${formatCurrency(subtotal, currency)}*`);
|
|
133
|
+
lines.push(`📊 Total Items: ${totalCount}`);
|
|
103
134
|
lines.push('');
|
|
104
|
-
lines.push('Please confirm availability and delivery details. Thank you!');
|
|
135
|
+
lines.push('Please confirm availability and delivery details. Thank you! 🙏');
|
|
105
136
|
return `https://wa.me/${cleanNumber}?text=${encodeURIComponent(lines.join('\n'))}`;
|
|
106
137
|
}, [items, subtotal, totalCount]);
|
|
107
138
|
const value = (0, react_1.useMemo)(() => ({
|
|
@@ -133,6 +164,9 @@ function CartProvider({ children, storageKey = STORAGE_KEY, }) {
|
|
|
133
164
|
]);
|
|
134
165
|
return (0, jsx_runtime_1.jsx)(CartContext.Provider, { value: value, children: children });
|
|
135
166
|
}
|
|
167
|
+
function useOptionalCart() {
|
|
168
|
+
return (0, react_1.useContext)(CartContext);
|
|
169
|
+
}
|
|
136
170
|
function useCart() {
|
|
137
171
|
const context = (0, react_1.useContext)(CartContext);
|
|
138
172
|
if (!context) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deneb-ui/ui",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.45",
|
|
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.45"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"react": "^18.0.0 || ^19.0.0",
|