@deneb-ui/ui 2.0.106 → 2.0.108

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.
@@ -51,7 +51,9 @@ 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.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: () => {
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}`] })), item.showPrice === false ? ((0, jsx_runtime_1.jsx)("p", { className: "mt-1 text-xs font-semibold text-neutral-400", children: "Price on Request" })) : ((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: items.length > 0 && items.every((i) => i.showPrice === false)
55
+ ? "Price on Request"
56
+ : (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
57
  if (onCheckout)
56
58
  onCheckout(items, subtotal);
57
59
  if (checkoutUrl)
@@ -4,6 +4,7 @@ export interface ProductItem {
4
4
  id?: string | number;
5
5
  name?: string;
6
6
  title?: string;
7
+ showPrice?: boolean;
7
8
  isPriceRange?: boolean;
8
9
  productName?: string;
9
10
  itemTitle?: string;
@@ -58,6 +59,7 @@ export interface ProductItem {
58
59
  priceMin?: string | number;
59
60
  priceMax?: string | number;
60
61
  priceRange?: [number | string, number | string] | string;
62
+ customData?: Record<string, unknown>;
61
63
  [key: string]: unknown;
62
64
  }
63
65
  export type ProductCardVariant = 'modern-glass' | 'classic' | 'minimal' | 'horizontal';
@@ -99,8 +99,14 @@ function EditableProductCard({ itemPath, product: productProp, item: itemProp, c
99
99
  ? rawPriceCandidate
100
100
  : (0, useCart_1.formatCurrency)(basePriceNum, currency)
101
101
  : '');
102
+ const itemShowPrice = product?.showPrice !== undefined
103
+ ? Boolean(product.showPrice)
104
+ : (product?.customData?.showPrice !== undefined
105
+ ? Boolean(product.customData.showPrice)
106
+ : true);
107
+ const effectiveShowPrice = showPrice && itemShowPrice;
102
108
  const displayPrice = resolvedPrice.formattedPrice || baseFormattedPrice;
103
- const hasPrice = showPrice && Boolean(displayPrice && displayPrice.trim() !== '');
109
+ const hasPrice = effectiveShowPrice && Boolean(displayPrice && displayPrice.trim() !== '');
104
110
  const priceKey = 'cost' in (product || {}) && !('price' in (product || {}) && product.price !== undefined)
105
111
  ? 'cost'
106
112
  : ('amount' in (product || {}) && !('price' in (product || {}) && product.price !== undefined)
@@ -187,7 +193,8 @@ function EditableProductCard({ itemPath, product: productProp, item: itemProp, c
187
193
  ...product,
188
194
  name,
189
195
  brand,
190
- price: displayPrice,
196
+ price: effectiveShowPrice ? displayPrice : undefined,
197
+ showPrice: effectiveShowPrice,
191
198
  size: selectedOption || undefined,
192
199
  color: selectedColor || undefined,
193
200
  option: selectedOption || undefined,
@@ -214,6 +221,7 @@ function EditableProductCard({ itemPath, product: productProp, item: itemProp, c
214
221
  size: selectedOption || undefined,
215
222
  color: selectedColor || undefined,
216
223
  option: selectedOption || undefined,
224
+ showPrice: effectiveShowPrice,
217
225
  };
218
226
  if (cart) {
219
227
  cart.addItem(itemToAdd);
@@ -361,7 +369,7 @@ function EditableProductCard({ itemPath, product: productProp, item: itemProp, c
361
369
  fontWeight: 800,
362
370
  color: 'var(--brand-color, #ffffff)',
363
371
  letterSpacing: '-0.02em',
364
- } }), displayOriginalPrice ? ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.${originalPriceKey}`, "data-preview-field-path": `${itemPath}.${originalPriceKey}`, defaultValue: displayOriginalPrice, style: {
372
+ } }), displayOriginalPrice && !isRange ? ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.${originalPriceKey}`, "data-preview-field-path": `${itemPath}.${originalPriceKey}`, defaultValue: displayOriginalPrice, style: {
365
373
  fontSize: '0.875rem',
366
374
  textDecoration: 'line-through',
367
375
  color: 'var(--muted-text, #94a3b8)',
@@ -369,7 +377,18 @@ function EditableProductCard({ itemPath, product: productProp, item: itemProp, c
369
377
  fontSize: '0.8rem',
370
378
  fontWeight: 500,
371
379
  color: 'var(--muted-text, #64748b)',
372
- } })) : null] })) : null, actionSlot ? ((0, jsx_runtime_1.jsx)("div", { children: actionSlot })) : ((0, jsx_runtime_1.jsxs)("div", { style: {
380
+ } })) : null] })) : !effectiveShowPrice ? ((0, jsx_runtime_1.jsx)("div", { style: { display: 'flex', alignItems: 'center', gap: '0.5rem' }, children: (0, jsx_runtime_1.jsx)("span", { style: {
381
+ display: 'inline-flex',
382
+ alignItems: 'center',
383
+ padding: '4px 10px',
384
+ borderRadius: '8px',
385
+ fontSize: '0.8125rem',
386
+ fontWeight: 600,
387
+ backgroundColor: 'rgba(255, 255, 255, 0.08)',
388
+ color: 'var(--muted-text, #94a3b8)',
389
+ border: '1px solid rgba(255, 255, 255, 0.12)',
390
+ letterSpacing: '0.01em',
391
+ }, children: "Price on Request" }) })) : null, actionSlot ? ((0, jsx_runtime_1.jsx)("div", { children: actionSlot })) : ((0, jsx_runtime_1.jsxs)("div", { style: {
373
392
  display: 'grid',
374
393
  gridTemplateColumns: showWhatsAppButton && showAddToCartButton ? '1fr 1fr' : '1fr',
375
394
  gap: '0.5rem',
@@ -30,6 +30,9 @@ export interface ProductDetailItem {
30
30
  whatsappNumber?: string;
31
31
  whatsappMessage?: string;
32
32
  isAvailable?: boolean;
33
+ showPrice?: boolean;
34
+ isPriceRange?: boolean;
35
+ customData?: Record<string, unknown>;
33
36
  unit?: MeasurementUnit;
34
37
  measurement?: string;
35
38
  optionsLabel?: string;
@@ -124,8 +124,32 @@ function EditableProductDetail({ sectionPath = 'product', product, sizes, colors
124
124
  };
125
125
  const name = String(product.name || product.title || product.productName || product.itemTitle || 'Product Title');
126
126
  const rawPriceCandidate = product.price ?? product.cost ?? product.amount ?? product.productPrice;
127
- const basePrice = rawPriceCandidate !== undefined && rawPriceCandidate !== null ? String(rawPriceCandidate) : 'LKR 0';
127
+ const isRange = Boolean(product.isPriceRange ||
128
+ (product.minPrice !== undefined && product.maxPrice !== undefined) ||
129
+ product.priceRange);
130
+ let rangePriceString = '';
131
+ if (isRange) {
132
+ if (product.priceRange) {
133
+ rangePriceString = String(product.priceRange);
134
+ }
135
+ else {
136
+ const minNum = typeof product.minPrice === 'number' ? product.minPrice : parseFloat(String(product.minPrice || '').replace(/[^0-9.]/g, '')) || 0;
137
+ const maxNum = typeof product.maxPrice === 'number' ? product.maxPrice : parseFloat(String(product.maxPrice || '').replace(/[^0-9.]/g, '')) || 0;
138
+ rangePriceString = `LKR ${minNum.toLocaleString()} – LKR ${maxNum.toLocaleString()}`;
139
+ }
140
+ }
141
+ const basePrice = rangePriceString ||
142
+ (rawPriceCandidate !== undefined && rawPriceCandidate !== null
143
+ ? typeof rawPriceCandidate === 'number'
144
+ ? `LKR ${rawPriceCandidate.toLocaleString()}`
145
+ : String(rawPriceCandidate)
146
+ : 'LKR 0');
128
147
  const originalPrice = product.originalPrice ?? product.compareAtPrice;
148
+ const itemShowPrice = product.showPrice !== undefined
149
+ ? Boolean(product.showPrice)
150
+ : (product.customData?.showPrice !== undefined
151
+ ? Boolean(product.customData.showPrice)
152
+ : true);
129
153
  const displayPrice = resolvedPrice.formattedPrice || basePrice;
130
154
  const displayOriginalPrice = resolvedPrice.formattedOriginalPrice || (originalPrice ? String(originalPrice) : undefined);
131
155
  const isAvailable = product.isAvailable !== false;
@@ -138,7 +162,9 @@ function EditableProductDetail({ sectionPath = 'product', product, sizes, colors
138
162
  const shippingReturns = String(product.shippingReturns || '14-day hassle-free exchanges for unworn items in original packaging.');
139
163
  const orderSnippet = resolved.formatOrderSnippet(effectiveOptions.length > 0 ? selectedSize : undefined, effectiveColors.length > 0 ? selectedColor : undefined);
140
164
  const resolvedWhatsappUrl = whatsappUrl || (product.whatsappNumber
141
- ? (0, urls_1.createWhatsAppUrl)(product.whatsappNumber, product.whatsappMessage || `Hi, I would like to order ${name}${orderSnippet ? ` ${orderSnippet}` : ''} - ${displayPrice}`)
165
+ ? (0, urls_1.createWhatsAppUrl)(product.whatsappNumber, product.whatsappMessage || (itemShowPrice
166
+ ? `Hi, I would like to order ${name}${orderSnippet ? ` ${orderSnippet}` : ''} - ${displayPrice}`
167
+ : `Hi, I am interested in ${name}${orderSnippet ? ` ${orderSnippet}` : ''}. Could you please share the pricing, availability, and details?`))
142
168
  : '');
143
169
  // Dynamic Specs: Use explicit specs if provided, else fallback to available product metadata
144
170
  const effectiveSpecs = (0, react_1.useMemo)(() => {
@@ -162,9 +188,9 @@ function EditableProductDetail({ sectionPath = 'product', product, sizes, colors
162
188
  ? 'border-lime-400 scale-98 shadow-md ring-2 ring-lime-400/20'
163
189
  : 'border-slate-800/80 opacity-60 hover:opacity-100 hover:border-slate-700'}`, children: (0, jsx_runtime_1.jsx)("img", { src: (0, utils_1.withBasePath)(img), alt: "", className: "w-full h-full object-contain" }) }, idx))) })), (0, jsx_runtime_1.jsxs)("div", { className: "relative flex-1 aspect-square rounded-3xl bg-gradient-to-b from-slate-900/50 to-slate-950/80 border border-slate-800/80 p-8 flex items-center justify-center overflow-hidden group", children: [badge && ((0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.badge`, className: "absolute top-6 left-6 z-10 px-3.5 py-1 text-xs font-black tracking-wider uppercase rounded-full bg-lime-400 text-slate-950 shadow-lg", children: badge })), (0, jsx_runtime_1.jsx)("img", { "data-preview-field-path": `${sectionPath}.featuredImage`, src: (0, utils_1.withBasePath)(activeImage), alt: name, className: "w-full h-full object-contain transition-transform duration-500 group-hover:scale-105" })] })] }), (0, jsx_runtime_1.jsx)("div", { className: "lg:col-span-5 flex flex-col justify-between", children: (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h1", { "data-preview-field-path": `${sectionPath}.name`, className: "text-3xl sm:text-4xl font-extrabold tracking-tight text-white leading-tight", children: name }), (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.isAvailable`, className: `mt-3 inline-flex rounded-full px-3 py-1 text-xs font-bold ${isAvailable
164
190
  ? 'bg-emerald-500/15 text-emerald-300'
165
- : 'bg-rose-500/15 text-rose-300'}`, children: isAvailable ? 'In Stock' : 'Out of Stock' }), (0, jsx_runtime_1.jsxs)("div", { className: "mt-4 flex items-baseline gap-3", children: [(0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.price`, className: "text-3xl font-black text-lime-400 tracking-tight", children: displayPrice }), displayOriginalPrice ? ((0, jsx_runtime_1.jsx)("span", { className: "text-lg font-medium text-slate-500 line-through", children: String(displayOriginalPrice) })) : null] }), description && ((0, jsx_runtime_1.jsx)("p", { "data-preview-field-path": `${sectionPath}.description`, className: "mt-6 text-base text-slate-300 leading-relaxed", children: description })), effectiveColors.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "mt-8", children: [(0, jsx_runtime_1.jsxs)("span", { className: "block text-xs font-bold uppercase tracking-wider text-slate-400 mb-3", children: ["Color \u2014 ", (0, jsx_runtime_1.jsx)("span", { className: "text-white", children: selectedColor })] }), (0, jsx_runtime_1.jsx)("div", { className: "flex flex-wrap gap-3", children: effectiveColors.map((c) => ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => handleSelectColor(c), className: `w-9 h-9 rounded-full border-2 transition-all p-0.5 relative flex items-center justify-center ${selectedColor === c.name
191
+ : 'bg-rose-500/15 text-rose-300'}`, children: isAvailable ? 'In Stock' : 'Out of Stock' }), itemShowPrice ? ((0, jsx_runtime_1.jsxs)("div", { className: "mt-4 flex items-baseline gap-3", children: [(0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.price`, className: "text-3xl font-black text-lime-400 tracking-tight", children: displayPrice }), displayOriginalPrice && !isRange ? ((0, jsx_runtime_1.jsx)("span", { className: "text-lg font-medium text-slate-500 line-through", children: String(displayOriginalPrice) })) : null] })) : ((0, jsx_runtime_1.jsx)("div", { className: "mt-4 flex items-center gap-3", children: (0, jsx_runtime_1.jsx)("span", { className: "inline-flex items-center px-3.5 py-1.5 rounded-xl text-sm font-bold bg-slate-800/80 text-slate-300 border border-slate-700/60", children: "Price on Request" }) })), description && ((0, jsx_runtime_1.jsx)("p", { "data-preview-field-path": `${sectionPath}.description`, className: "mt-6 text-base text-slate-300 leading-relaxed", children: description })), effectiveColors.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "mt-8", children: [(0, jsx_runtime_1.jsxs)("span", { className: "block text-xs font-bold uppercase tracking-wider text-slate-400 mb-3", children: ["Color \u2014 ", (0, jsx_runtime_1.jsx)("span", { className: "text-white", children: selectedColor })] }), (0, jsx_runtime_1.jsx)("div", { className: "flex flex-wrap gap-3", children: effectiveColors.map((c) => ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => handleSelectColor(c), className: `w-9 h-9 rounded-full border-2 transition-all p-0.5 relative flex items-center justify-center ${selectedColor === c.name
166
192
  ? 'border-lime-400 ring-2 ring-lime-400/30 scale-105'
167
193
  : 'border-slate-700 hover:border-slate-500'}`, style: { backgroundColor: c.hex || '#334155' }, title: c.name, "aria-label": c.name, children: !c.hex && ((0, jsx_runtime_1.jsx)("span", { className: "text-[9px] font-bold text-white uppercase px-1 truncate", children: c.name.slice(0, 3) })) }, c.name))) })] })), effectiveOptions.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "mt-8", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between mb-3", children: [(0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.${product.optionsLabel ? 'optionsLabel' : 'sizesLabel'}`, className: "block text-xs font-bold uppercase tracking-wider text-slate-400", children: effectiveOptionsLabel }), (0, jsx_runtime_1.jsx)("span", { className: "text-xs font-semibold text-slate-300", children: resolved.formatSelectedDisplay(selectedSize) })] }), (0, jsx_runtime_1.jsx)("div", { className: "deneb-product-detail-sizes flex flex-wrap gap-2.5", children: effectiveOptions.map((s) => ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setSelectedSize(s), className: `py-2.5 px-3.5 min-w-[48px] rounded-xl font-bold text-sm transition-all duration-150 text-center ${selectedSize === s
168
194
  ? 'bg-white text-slate-950 shadow-md font-extrabold scale-102 ring-2 ring-white/20'
169
- : 'bg-slate-900/60 text-slate-300 border border-slate-800 hover:bg-slate-800 hover:text-white'}`, children: resolved.formatOption(s) }, s))) })] })), (0, jsx_runtime_1.jsxs)("div", { className: "mt-8 flex flex-col gap-3", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", disabled: !isAvailable, onClick: () => onAddToSelection?.({ ...product, price: resolvedPrice.numericPrice || product.price }, selectedSize || undefined, selectedColor || undefined), className: "w-full py-4 px-6 rounded-2xl font-black text-sm uppercase tracking-wider bg-lime-400 text-slate-950 hover:bg-lime-300 active:scale-98 transition-all duration-150 shadow-lg shadow-lime-400/20 flex items-center justify-center gap-2 disabled:cursor-not-allowed disabled:bg-slate-700 disabled:text-slate-300 disabled:shadow-none", children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.addToSelectionLabel`, children: isAvailable ? addToSelectionLabel : 'Out of Stock' }) }), isAvailable && resolvedWhatsappUrl && ((0, jsx_runtime_1.jsxs)("a", { href: resolvedWhatsappUrl, target: "_blank", rel: "noopener noreferrer", className: "w-full py-3.5 px-6 rounded-2xl font-bold text-sm bg-emerald-600/20 text-emerald-400 hover:bg-emerald-600/30 border border-emerald-500/30 transition-all duration-150 flex items-center justify-center gap-2", children: [(0, jsx_runtime_1.jsx)("svg", { className: "w-5 h-5 fill-current", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { d: "M17.472 14.382c-.301-.15-1.78-.879-2.056-.98-.276-.1-.477-.15-.678.15-.201.3-.78 0.98-.956 1.18-.175.2-.351.226-.652.075-.301-.15-1.272-.469-2.423-1.496-.896-.799-1.501-1.787-1.677-2.088-.175-.301-.019-.464.132-.614.136-.135.301-.351.452-.527.15-.176.201-.301.301-.502.1-.2.05-.376-.025-.527-.075-.15-.678-1.635-.93-2.242-.244-.592-.493-.512-.678-.521-.175-.009-.376-.009-.577-.009-.201 0-.527.075-.803.376-.276.301-1.054 1.03-1.054 2.512 0 1.482 1.079 2.912 1.23 3.113.15.201 2.124 3.243 5.145 4.548.718.311 1.279.497 1.716.636.722.23 1.378.197 1.898.12.579-.087 1.78-.728 2.03-1.431.251-.703.251-1.305.176-1.431-.075-.126-.276-.201-.577-.351zM12.004 2C6.48 2 2 6.48 2 12c0 1.82.49 3.52 1.34 4.99L2 22l5.14-1.35c1.42.78 3.04 1.22 4.86 1.22 5.52 0 10-4.48 10-10S17.524 2 12.004 2z" }) }), (0, jsx_runtime_1.jsx)("span", { children: "Order Directly via WhatsApp" })] }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "mt-10 border-t border-slate-800/80 pt-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex gap-6 border-b border-slate-800 pb-3 mb-4", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setActiveTab('specs'), className: `text-sm font-bold tracking-wide transition-colors ${activeTab === 'specs' ? 'text-lime-400' : 'text-slate-400 hover:text-slate-200'}`, children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.specsTitle`, children: specsTitle }) }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setActiveTab('shipping'), className: `text-sm font-bold tracking-wide transition-colors ${activeTab === 'shipping' ? 'text-lime-400' : 'text-slate-400 hover:text-slate-200'}`, children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.shippingTitle`, children: shippingTitle }) })] }), activeTab === 'specs' ? ((0, jsx_runtime_1.jsx)("div", { className: "space-y-3", children: effectiveSpecs.length > 0 ? (effectiveSpecs.map((spec, i) => ((0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between text-xs py-1 border-b border-slate-900", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-slate-400 font-medium", children: spec.label }), (0, jsx_runtime_1.jsx)("span", { className: "text-slate-200 font-semibold", children: spec.value })] }, i)))) : ((0, jsx_runtime_1.jsxs)("div", { className: "text-xs text-slate-400 space-y-2", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between py-1 border-b border-slate-800/50", children: [(0, jsx_runtime_1.jsx)("span", { children: "Status" }), (0, jsx_runtime_1.jsx)("span", { className: "text-slate-200 font-semibold", children: isAvailable ? 'Verified Authentic & In Stock' : 'Out of Stock' })] }), product.category && ((0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between py-1 border-b border-slate-800/50", children: [(0, jsx_runtime_1.jsx)("span", { children: "Category" }), (0, jsx_runtime_1.jsx)("span", { className: "text-slate-200 font-semibold", children: String(product.category) })] }))] })) })) : ((0, jsx_runtime_1.jsxs)("div", { className: "text-xs text-slate-300 space-y-3 leading-relaxed", children: [(0, jsx_runtime_1.jsx)("p", { "data-preview-field-path": `${sectionPath}.shippingSummary`, children: shippingSummary }), (0, jsx_runtime_1.jsx)("p", { "data-preview-field-path": `${sectionPath}.shippingReturns`, className: "text-slate-400", children: shippingReturns })] }))] })] }) })] }) }));
195
+ : 'bg-slate-900/60 text-slate-300 border border-slate-800 hover:bg-slate-800 hover:text-white'}`, children: resolved.formatOption(s) }, s))) })] })), (0, jsx_runtime_1.jsxs)("div", { className: "mt-8 flex flex-col gap-3", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", disabled: !isAvailable, onClick: () => onAddToSelection?.({ ...product, price: resolvedPrice.numericPrice || product.price, showPrice: itemShowPrice }, selectedSize || undefined, selectedColor || undefined), className: "w-full py-4 px-6 rounded-2xl font-black text-sm uppercase tracking-wider bg-lime-400 text-slate-950 hover:bg-lime-300 active:scale-98 transition-all duration-150 shadow-lg shadow-lime-400/20 flex items-center justify-center gap-2 disabled:cursor-not-allowed disabled:bg-slate-700 disabled:text-slate-300 disabled:shadow-none", children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.addToSelectionLabel`, children: isAvailable ? addToSelectionLabel : 'Out of Stock' }) }), isAvailable && resolvedWhatsappUrl && ((0, jsx_runtime_1.jsxs)("a", { href: resolvedWhatsappUrl, target: "_blank", rel: "noopener noreferrer", className: "w-full py-3.5 px-6 rounded-2xl font-bold text-sm bg-emerald-600/20 text-emerald-400 hover:bg-emerald-600/30 border border-emerald-500/30 transition-all duration-150 flex items-center justify-center gap-2", children: [(0, jsx_runtime_1.jsx)("svg", { className: "w-5 h-5 fill-current", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { d: "M17.472 14.382c-.301-.15-1.78-.879-2.056-.98-.276-.1-.477-.15-.678.15-.201.3-.78 0.98-.956 1.18-.175.2-.351.226-.652.075-.301-.15-1.272-.469-2.423-1.496-.896-.799-1.501-1.787-1.677-2.088-.175-.301-.019-.464.132-.614.136-.135.301-.351.452-.527.15-.176.201-.301.301-.502.1-.2.05-.376-.025-.527-.075-.15-.678-1.635-.93-2.242-.244-.592-.493-.512-.678-.521-.175-.009-.376-.009-.577-.009-.201 0-.527.075-.803.376-.276.301-1.054 1.03-1.054 2.512 0 1.482 1.079 2.912 1.23 3.113.15.201 2.124 3.243 5.145 4.548.718.311 1.279.497 1.716.636.722.23 1.378.197 1.898.12.579-.087 1.78-.728 2.03-1.431.251-.703.251-1.305.176-1.431-.075-.126-.276-.201-.577-.351zM12.004 2C6.48 2 2 6.48 2 12c0 1.82.49 3.52 1.34 4.99L2 22l5.14-1.35c1.42.78 3.04 1.22 4.86 1.22 5.52 0 10-4.48 10-10S17.524 2 12.004 2z" }) }), (0, jsx_runtime_1.jsx)("span", { children: "Order Directly via WhatsApp" })] }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "mt-10 border-t border-slate-800/80 pt-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex gap-6 border-b border-slate-800 pb-3 mb-4", children: [(0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setActiveTab('specs'), className: `text-sm font-bold tracking-wide transition-colors ${activeTab === 'specs' ? 'text-lime-400' : 'text-slate-400 hover:text-slate-200'}`, children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.specsTitle`, children: specsTitle }) }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => setActiveTab('shipping'), className: `text-sm font-bold tracking-wide transition-colors ${activeTab === 'shipping' ? 'text-lime-400' : 'text-slate-400 hover:text-slate-200'}`, children: (0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": `${sectionPath}.shippingTitle`, children: shippingTitle }) })] }), activeTab === 'specs' ? ((0, jsx_runtime_1.jsx)("div", { className: "space-y-3", children: effectiveSpecs.length > 0 ? (effectiveSpecs.map((spec, i) => ((0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between text-xs py-1 border-b border-slate-900", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-slate-400 font-medium", children: spec.label }), (0, jsx_runtime_1.jsx)("span", { className: "text-slate-200 font-semibold", children: spec.value })] }, i)))) : ((0, jsx_runtime_1.jsxs)("div", { className: "text-xs text-slate-400 space-y-2", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between py-1 border-b border-slate-800/50", children: [(0, jsx_runtime_1.jsx)("span", { children: "Status" }), (0, jsx_runtime_1.jsx)("span", { className: "text-slate-200 font-semibold", children: isAvailable ? 'Verified Authentic & In Stock' : 'Out of Stock' })] }), product.category && ((0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between py-1 border-b border-slate-800/50", children: [(0, jsx_runtime_1.jsx)("span", { children: "Category" }), (0, jsx_runtime_1.jsx)("span", { className: "text-slate-200 font-semibold", children: String(product.category) })] }))] })) })) : ((0, jsx_runtime_1.jsxs)("div", { className: "text-xs text-slate-300 space-y-3 leading-relaxed", children: [(0, jsx_runtime_1.jsx)("p", { "data-preview-field-path": `${sectionPath}.shippingSummary`, children: shippingSummary }), (0, jsx_runtime_1.jsx)("p", { "data-preview-field-path": `${sectionPath}.shippingReturns`, className: "text-slate-400", children: shippingReturns })] }))] })] }) })] }) }));
170
196
  }
@@ -4,6 +4,9 @@ export interface ServiceItem {
4
4
  name?: string;
5
5
  title?: string;
6
6
  price?: string | number;
7
+ priceLabel?: string;
8
+ showPrice?: boolean;
9
+ customData?: Record<string, unknown>;
7
10
  description?: string;
8
11
  imageUrl?: string;
9
12
  image?: string;
@@ -11,18 +11,48 @@ const EditableImage_1 = require("./EditableImage");
11
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
+ const itemShowPrice = service.showPrice !== undefined
15
+ ? Boolean(service.showPrice)
16
+ : (service.customData?.showPrice !== undefined
17
+ ? Boolean(service.customData.showPrice)
18
+ : true);
19
+ const effectiveShowPrice = showPrice && itemShowPrice;
20
+ const rawPriceCandidate = service?.price;
21
+ const hasRawPrice = rawPriceCandidate !== undefined && rawPriceCandidate !== null && String(rawPriceCandidate).trim() !== '';
22
+ const priceLabel = service?.priceLabel ? String(service.priceLabel) : '';
23
+ const hasPrice = effectiveShowPrice && (hasRawPrice || Boolean(priceLabel));
24
+ const formattedPrice = hasRawPrice
25
+ ? typeof rawPriceCandidate === 'number'
26
+ ? 'LKR ' + rawPriceCandidate.toLocaleString()
27
+ : String(rawPriceCandidate).includes('LKR')
28
+ ? String(rawPriceCandidate)
29
+ : 'LKR ' + String(rawPriceCandidate)
30
+ : '';
15
31
  const imageUrl = String(service?.imageUrl || service?.image || '');
16
32
  const features = Array.isArray(service?.features) ? service.features : [];
17
33
  const mergedStyle = {
18
34
  textAlign: align,
19
35
  ...style,
20
36
  };
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) => {
37
+ 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.jsxs)("div", { className: "service-card-price-wrap", style: { margin: '0.5rem 0', display: 'flex', alignItems: 'baseline', gap: '0.375rem', flexWrap: 'wrap' }, children: [hasRawPrice && ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.price`, "data-preview-field-path": `${itemPath}.price`, defaultValue: formattedPrice, className: "service-card-price", style: {
38
+ fontSize: '1.125rem',
39
+ fontWeight: 700,
40
+ color: 'var(--brand-color, #2563eb)',
41
+ } })), priceLabel && ((0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { as: "span", id: `${itemPath}.priceLabel`, "data-preview-field-path": `${itemPath}.priceLabel`, defaultValue: priceLabel, className: "service-card-price-label", style: {
42
+ fontSize: '0.8125rem',
43
+ fontWeight: 500,
44
+ color: 'var(--muted-text, #94a3b8)',
45
+ } }))] })) : !effectiveShowPrice ? ((0, jsx_runtime_1.jsx)("div", { className: "service-card-price-wrap", style: { margin: '0.5rem 0' }, children: (0, jsx_runtime_1.jsx)("span", { style: {
46
+ display: 'inline-flex',
47
+ alignItems: 'center',
48
+ padding: '3px 8px',
49
+ borderRadius: '6px',
50
+ fontSize: '0.75rem',
51
+ fontWeight: 600,
52
+ backgroundColor: 'rgba(255, 255, 255, 0.08)',
53
+ color: 'var(--muted-text, #94a3b8)',
54
+ border: '1px solid rgba(255, 255, 255, 0.12)',
55
+ }, children: "Quote on Request" }) })) : null, (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) => {
26
56
  const featureText = typeof feature === 'string'
27
57
  ? feature
28
58
  : typeof feature?.title === 'string'
@@ -11,6 +11,7 @@ export interface CartItem {
11
11
  quantity: number;
12
12
  sku?: string;
13
13
  metadata?: Record<string, unknown>;
14
+ showPrice?: boolean;
14
15
  }
15
16
  export declare function parseNumericPrice(value: unknown): number;
16
17
  export declare function formatCurrency(amount: number, currency?: string): string;
@@ -19,6 +20,7 @@ export declare function getProductWhatsAppUrl(product: {
19
20
  title?: string;
20
21
  brand?: string;
21
22
  price?: string | number;
23
+ showPrice?: boolean;
22
24
  size?: string | number;
23
25
  color?: string;
24
26
  option?: string | number;
@@ -42,18 +42,22 @@ function getProductWhatsAppUrl(product, whatsappNumber, options) {
42
42
  if (product.option && product.option !== product.size)
43
43
  variantParts.push(`Option: ${product.option}`);
44
44
  const variantStr = variantParts.length > 0 ? ` [${variantParts.join(", ")}]` : "";
45
+ const isPriceVisible = product.showPrice !== false && product.price !== undefined && product.price !== null && String(product.price).trim() !== '';
45
46
  const rawPriceStr = typeof product.price === "string" && product.price.trim() ? product.price.trim() : "";
46
47
  const priceNum = typeof product.price === "number" ? product.price : parseNumericPrice(product.price);
47
- const priceStr = rawPriceStr
48
- ? `\nPrice: ${rawPriceStr}`
49
- : (priceNum > 0 ? `\nPrice: ${formatCurrency(priceNum, options?.currency || "LKR")}` : "");
48
+ const priceStr = isPriceVisible
49
+ ? (rawPriceStr ? `\nPrice: ${rawPriceStr}` : (priceNum > 0 ? `\nPrice: ${formatCurrency(priceNum, options?.currency || "LKR")}` : ""))
50
+ : "";
50
51
  const store = options?.storeName ? ` at ${options.storeName}` : "";
52
+ const closingPrompt = isPriceVisible
53
+ ? `Could you please share more details, availability, and ordering instructions? Thank you!`
54
+ : `Could you please share the pricing, availability, and ordering instructions? Thank you!`;
51
55
  const message = [
52
56
  `Hello${store}! 👋`,
53
57
  `I am interested in this product:`,
54
58
  `*${title}*${brand}${variantStr}${priceStr}`,
55
59
  "",
56
- `Could you please share more details, availability, and ordering instructions? Thank you!`,
60
+ closingPrompt,
57
61
  ].join("\n");
58
62
  return `https://wa.me/${cleanNumber}?text=${encodeURIComponent(message)}`;
59
63
  }
@@ -128,7 +132,7 @@ function CartProvider({ children, storageKey = STORAGE_KEY, }) {
128
132
  }, []);
129
133
  const clearCart = (0, react_1.useCallback)(() => setItems([]), []);
130
134
  const totalCount = (0, react_1.useMemo)(() => items.reduce((acc, item) => acc + item.quantity, 0), [items]);
131
- const subtotal = (0, react_1.useMemo)(() => items.reduce((acc, item) => acc + item.price * item.quantity, 0), [items]);
135
+ const subtotal = (0, react_1.useMemo)(() => items.reduce((acc, item) => (item.showPrice !== false ? acc + item.price * item.quantity : acc), 0), [items]);
132
136
  const getWhatsAppOrderUrl = (0, react_1.useCallback)((whatsappNumber, options) => {
133
137
  const cleanNumber = (whatsappNumber || '').replace(/\D/g, '');
134
138
  const currency = options?.currency || 'LKR';
@@ -148,11 +152,26 @@ function CartProvider({ children, storageKey = STORAGE_KEY, }) {
148
152
  variantParts.push(`Color: ${item.color}`);
149
153
  const variantStr = variantParts.length > 0 ? ` [${variantParts.join(', ')}]` : '';
150
154
  lines.push(`${index + 1}. *${item.name}*${brandStr}${variantStr}`);
151
- lines.push(` Qty: ${item.quantity} x ${formatCurrency(item.price, currency)} = *${formatCurrency(item.price * item.quantity, currency)}*`);
155
+ if (item.showPrice === false) {
156
+ lines.push(` Qty: ${item.quantity} x *Price on Request*`);
157
+ }
158
+ else {
159
+ lines.push(` Qty: ${item.quantity} x ${formatCurrency(item.price, currency)} = *${formatCurrency(item.price * item.quantity, currency)}*`);
160
+ }
152
161
  });
162
+ const hasHiddenItems = items.some((item) => item.showPrice === false);
163
+ const allHidden = items.length > 0 && items.every((item) => item.showPrice === false);
153
164
  lines.push('');
154
165
  lines.push('──────────────────────────────');
155
- lines.push(`💰 *Grand Total: ${formatCurrency(subtotal, currency)}*`);
166
+ if (allHidden) {
167
+ lines.push(`💰 *Grand Total: Price on Request*`);
168
+ }
169
+ else if (hasHiddenItems) {
170
+ lines.push(`💰 *Grand Total: ${formatCurrency(subtotal, currency)}* _(Excluding Price on Request items)_`);
171
+ }
172
+ else {
173
+ lines.push(`💰 *Grand Total: ${formatCurrency(subtotal, currency)}*`);
174
+ }
156
175
  lines.push(`📊 Total Items: ${totalCount}`);
157
176
  lines.push('');
158
177
  lines.push('Please confirm availability and delivery details. Thank you! 🙏');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deneb-ui/ui",
3
- "version": "2.0.106",
3
+ "version": "2.0.108",
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.106"
53
+ "@deneb-ui/core": "^2.0.108"
54
54
  },
55
55
  "peerDependencies": {
56
56
  "react": "^18.0.0 || ^19.0.0",