funuicss 3.7.16 → 3.8.0

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.
@@ -0,0 +1,249 @@
1
+ "use strict";
2
+ // components/products/ProductDetail.tsx
3
+ 'use client';
4
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
+ if (k2 === undefined) k2 = k;
6
+ var desc = Object.getOwnPropertyDescriptor(m, k);
7
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
8
+ desc = { enumerable: true, get: function() { return m[k]; } };
9
+ }
10
+ Object.defineProperty(o, k2, desc);
11
+ }) : (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ o[k2] = m[k];
14
+ }));
15
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
16
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
17
+ }) : function(o, v) {
18
+ o["default"] = v;
19
+ });
20
+ var __importStar = (this && this.__importStar) || (function () {
21
+ var ownKeys = function(o) {
22
+ ownKeys = Object.getOwnPropertyNames || function (o) {
23
+ var ar = [];
24
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
25
+ return ar;
26
+ };
27
+ return ownKeys(o);
28
+ };
29
+ return function (mod) {
30
+ if (mod && mod.__esModule) return mod;
31
+ var result = {};
32
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
33
+ __setModuleDefault(result, mod);
34
+ return result;
35
+ };
36
+ })();
37
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
38
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
39
+ if (ar || !(i in from)) {
40
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
41
+ ar[i] = from[i];
42
+ }
43
+ }
44
+ return to.concat(ar || Array.prototype.slice.call(from));
45
+ };
46
+ var __importDefault = (this && this.__importDefault) || function (mod) {
47
+ return (mod && mod.__esModule) ? mod : { "default": mod };
48
+ };
49
+ Object.defineProperty(exports, "__esModule", { value: true });
50
+ var react_1 = __importStar(require("react"));
51
+ var pi_1 = require("react-icons/pi");
52
+ var tfi_1 = require("react-icons/tfi");
53
+ var si_1 = require("react-icons/si");
54
+ var Modal_1 = __importDefault(require("../modal/Modal"));
55
+ var Div_1 = __importDefault(require("../div/Div"));
56
+ var Text_1 = __importDefault(require("../text/Text"));
57
+ var Flex_1 = __importDefault(require("../flex/Flex"));
58
+ var Button_1 = __importDefault(require("../button/Button"));
59
+ var RowFlex_1 = __importDefault(require("../specials/RowFlex"));
60
+ var Input_1 = __importDefault(require("../input/Input"));
61
+ var Circle_1 = __importDefault(require("../specials/Circle"));
62
+ var Carousel_1 = __importDefault(require("../carousel/Carousel"));
63
+ var Select_1 = __importDefault(require("../select/Select"));
64
+ var io5_1 = require("react-icons/io5");
65
+ var ImageScaler_1 = __importDefault(require("../components/ImageScaler"));
66
+ var ProductDetail = function (_a) {
67
+ var product = _a.product, open = _a.open, setOpen = _a.setOpen, _b = _a.currency, currency = _b === void 0 ? '$' : _b, onAddToCart = _a.onAddToCart;
68
+ var _c = (0, react_1.useState)(0), selectedImageIndex = _c[0], setSelectedImageIndex = _c[1];
69
+ var _d = (0, react_1.useState)(''), selectedColor = _d[0], setSelectedColor = _d[1];
70
+ var _e = (0, react_1.useState)(''), selectedSize = _e[0], setSelectedSize = _e[1];
71
+ var _f = (0, react_1.useState)(1), quantity = _f[0], setQuantity = _f[1];
72
+ var _g = (0, react_1.useState)(false), showFullDescription = _g[0], setShowFullDescription = _g[1];
73
+ var hasDiscount = product.comparePrice && product.comparePrice > product.price;
74
+ var discountPercent = hasDiscount
75
+ ? Math.round(((product.comparePrice - product.price) / product.comparePrice) * 100)
76
+ : 0;
77
+ var getDisplayPrice = function () {
78
+ var price = product.price || 0;
79
+ var productCurrency = product.currency || currency;
80
+ return "".concat(productCurrency).concat(price.toFixed(2));
81
+ };
82
+ var handleAddToCart = function () {
83
+ onAddToCart === null || onAddToCart === void 0 ? void 0 : onAddToCart(product, quantity, {
84
+ color: selectedColor,
85
+ size: selectedSize,
86
+ });
87
+ setOpen(false);
88
+ };
89
+ var totalPrice = ((product.price || 0) * quantity).toFixed(2);
90
+ // Function to safely process description
91
+ var processDescription = function (description) {
92
+ if (!description)
93
+ return '';
94
+ // Remove h1, h2, h3 tags but keep their content
95
+ var processed = description
96
+ .replace(/<h[1-3][^>]*>/gi, '<p>')
97
+ .replace(/<\/h[1-3]>/gi, '</p>');
98
+ return processed;
99
+ };
100
+ // Function to truncate HTML while preserving tags
101
+ var truncateHTML = function (html, maxLength) {
102
+ if (html.length <= maxLength)
103
+ return html;
104
+ var truncated = '';
105
+ var length = 0;
106
+ var inTag = false;
107
+ var tagBuffer = '';
108
+ for (var i = 0; i < html.length && length < maxLength; i++) {
109
+ var char = html[i];
110
+ if (char === '<') {
111
+ inTag = true;
112
+ tagBuffer = char;
113
+ }
114
+ else if (char === '>') {
115
+ inTag = false;
116
+ tagBuffer += char;
117
+ truncated += tagBuffer;
118
+ tagBuffer = '';
119
+ }
120
+ else if (inTag) {
121
+ tagBuffer += char;
122
+ }
123
+ else {
124
+ truncated += char;
125
+ length++;
126
+ }
127
+ }
128
+ // Close any open tags
129
+ var tempDiv = document.createElement('div');
130
+ tempDiv.innerHTML = truncated + '...';
131
+ // Get the innerHTML to ensure tags are properly closed
132
+ return tempDiv.innerHTML;
133
+ };
134
+ // Process the description
135
+ var processedDescription = processDescription(product.description || '');
136
+ var maxDescriptionLength = 200;
137
+ var shouldTruncate = processedDescription.length > maxDescriptionLength;
138
+ var displayDescription = showFullDescription
139
+ ? processedDescription
140
+ : (shouldTruncate ? truncateHTML(processedDescription, maxDescriptionLength) : processedDescription);
141
+ // Check if description has HTML tags
142
+ var hasHTML = /<[a-z][\s\S]*>/i.test(processedDescription);
143
+ return (react_1.default.createElement(Modal_1.default, { animation: "SlideDown", open: open, setOpen: setOpen, maxWidth: '1000px', title: react_1.default.createElement(react_1.default.Fragment, null), body: react_1.default.createElement(Flex_1.default, { width: '100%', gap: 2 },
144
+ react_1.default.createElement("div", { className: "w-400" }, product.images && product.images.length > 0 && (react_1.default.createElement(Div_1.default, { funcss: "margin-bottom-20" },
145
+ react_1.default.createElement(Div_1.default, { funcss: "funui_products_main_image_container mb-3" },
146
+ react_1.default.createElement(ImageScaler_1.default, { src: product.images[selectedImageIndex], size: "100%" })),
147
+ product.images.length > 1 && (react_1.default.createElement(Carousel_1.default, { gap: 1 }, product.images.map(function (image, index) { return (react_1.default.createElement(Div_1.default, { key: index, funcss: "funui_products_thumbnail rounde-edge ".concat(selectedImageIndex === index ? 'funui_products_thumbnail-active' : ''), onClick: function () { return setSelectedImageIndex(index); } },
148
+ react_1.default.createElement(ImageScaler_1.default, { src: image, size: "100px" }))); })))))),
149
+ react_1.default.createElement("div", { className: "col" },
150
+ react_1.default.createElement(Flex_1.default, { direction: 'column', gap: 2, alignItems: 'flex-start', justify: 'flex-start' },
151
+ react_1.default.createElement("div", null,
152
+ react_1.default.createElement(Text_1.default, { text: product.name, size: "2xl", block: true }),
153
+ react_1.default.createElement(Flex_1.default, { justify: "space-between", alignItems: "center", width: '100%' },
154
+ react_1.default.createElement(Text_1.default, { text: getDisplayPrice(), size: "xl" }),
155
+ (hasDiscount || product.comparePrice) && (react_1.default.createElement(Text_1.default, { text: "".concat(product.currency || currency).concat(product.comparePrice.toFixed(2)), textDecoration: 'line-through' })))),
156
+ ((product.colors && product.colors.length > 0) || (product.sizes && product.sizes.length > 0)) &&
157
+ react_1.default.createElement(Flex_1.default, { width: '100%', gap: 1 },
158
+ product.colors && product.colors.length > 0 && (react_1.default.createElement("div", { className: "col" },
159
+ react_1.default.createElement(Select_1.default, { fullWidth: true, options: __spreadArray([
160
+ { text: 'Select Color', value: '' }
161
+ ], product.colors.map(function (color) { return ({
162
+ text: color.name,
163
+ value: color.name,
164
+ prefix: react_1.default.createElement("div", { className: 'circle', style: { width: "20px", height: '20px', backgroundColor: color.code } })
165
+ }); }), true), value: selectedColor, onChange: function (e) { return setSelectedColor(e); }, bordered: true }))),
166
+ product.sizes && product.sizes.length > 0 && (react_1.default.createElement("div", { className: "col" },
167
+ react_1.default.createElement(Select_1.default, { fullWidth: true, options: __spreadArray([
168
+ { text: 'Select Size', value: '' }
169
+ ], product.sizes.map(function (size) { return ({ text: size, value: size }); }), true), value: selectedSize, onChange: function (e) { return setSelectedSize(e); }, bordered: true })))),
170
+ processedDescription && (react_1.default.createElement("div", null,
171
+ react_1.default.createElement(Text_1.default, { text: "Description", size: "lg", funcss: "margin-bottom-1" }),
172
+ react_1.default.createElement("div", { className: "article text-sm ".concat(hasHTML ? '' : 'whitespace-pre-wrap'), dangerouslySetInnerHTML: { __html: displayDescription } }),
173
+ shouldTruncate && (react_1.default.createElement(Button_1.default, { text: showFullDescription ? 'Show Less' : 'Read More', onClick: function () { return setShowFullDescription(!showFullDescription); }, small: true, bg: 'lighter', startIcon: showFullDescription ? react_1.default.createElement(pi_1.PiCaretUp, null) : react_1.default.createElement(pi_1.PiCaretDown, null) })))),
174
+ react_1.default.createElement("div", null,
175
+ react_1.default.createElement(Flex_1.default, { gap: 3, width: '100%' },
176
+ product.warranty && (react_1.default.createElement(Flex_1.default, { gap: 0.3 },
177
+ react_1.default.createElement("div", null,
178
+ react_1.default.createElement(pi_1.PiShieldCheck, { className: 'text-primary' })),
179
+ react_1.default.createElement("div", null,
180
+ react_1.default.createElement(Text_1.default, { text: "Warranty", size: "xs", opacity: 4, block: true }),
181
+ react_1.default.createElement(Text_1.default, { text: product.warranty, size: "sm", block: true, lineHeight: '1' })))),
182
+ product.manufacturer && (react_1.default.createElement(Flex_1.default, { gap: 0.3 },
183
+ react_1.default.createElement("div", null,
184
+ react_1.default.createElement(pi_1.PiUser, { className: 'text-primary' })),
185
+ react_1.default.createElement("div", null,
186
+ react_1.default.createElement(Text_1.default, { text: "Manufacturer", size: "xs", opacity: 4, block: true }),
187
+ react_1.default.createElement(Text_1.default, { text: product.manufacturer, size: "sm", block: true, lineHeight: '1' })))),
188
+ product.countryOfOrigin && (react_1.default.createElement(Flex_1.default, { gap: 0.3 },
189
+ react_1.default.createElement("div", null,
190
+ react_1.default.createElement(pi_1.PiGlobe, { className: 'text-primary' })),
191
+ react_1.default.createElement("div", null,
192
+ react_1.default.createElement(Text_1.default, { text: "Country of Origin", size: "xs", opacity: 4, block: true }),
193
+ react_1.default.createElement(Text_1.default, { text: product.countryOfOrigin, size: "sm", block: true, lineHeight: '1' })))),
194
+ product.isFeatured && (react_1.default.createElement(Flex_1.default, { gap: 0.3 },
195
+ react_1.default.createElement("div", null,
196
+ react_1.default.createElement(pi_1.PiUsers, { className: 'text-primary' })),
197
+ react_1.default.createElement("div", null,
198
+ react_1.default.createElement(Text_1.default, { text: "Featured", size: "xs", opacity: 4, block: true }),
199
+ react_1.default.createElement(Text_1.default, { text: "Yes", size: "sm", block: true, lineHeight: '1' })))),
200
+ product.rating && (react_1.default.createElement(Flex_1.default, { gap: 0.3 },
201
+ react_1.default.createElement("div", null,
202
+ react_1.default.createElement(tfi_1.TfiComments, { className: 'text-primary' })),
203
+ react_1.default.createElement("div", null,
204
+ react_1.default.createElement(Text_1.default, { text: "Rating", size: "xs", opacity: 4, block: true }),
205
+ react_1.default.createElement(Text_1.default, { text: product.rating, size: "sm", block: true, lineHeight: '1' })))),
206
+ product.brand && (react_1.default.createElement(Flex_1.default, { gap: 0.3 },
207
+ react_1.default.createElement("div", null,
208
+ react_1.default.createElement(si_1.SiBlackmagicdesign, { className: 'text-primary' })),
209
+ react_1.default.createElement("div", null,
210
+ react_1.default.createElement(Text_1.default, { text: "Brand", size: "xs", opacity: 4, block: true }),
211
+ react_1.default.createElement(Text_1.default, { text: product.brand, size: "sm", block: true, lineHeight: '1' })))),
212
+ product.category && (react_1.default.createElement(Flex_1.default, { gap: 0.3 },
213
+ react_1.default.createElement("div", null,
214
+ react_1.default.createElement(io5_1.IoLayersOutline, { className: 'text-primary' })),
215
+ react_1.default.createElement("div", null,
216
+ react_1.default.createElement(Text_1.default, { text: "Category", size: "xs", opacity: 4, block: true }),
217
+ react_1.default.createElement(Text_1.default, { text: product.category, size: "sm", block: true, lineHeight: '1' })))),
218
+ product.isNew && (react_1.default.createElement(Flex_1.default, { gap: 0.3 },
219
+ react_1.default.createElement("div", null,
220
+ react_1.default.createElement(pi_1.PiChecks, { className: 'text-primary' })),
221
+ react_1.default.createElement("div", null,
222
+ react_1.default.createElement(Text_1.default, { text: "New", size: "xs", opacity: 4, block: true }),
223
+ react_1.default.createElement(Text_1.default, { text: "Yes", size: "sm", block: true, lineHeight: '1' })))),
224
+ product.isSale && (react_1.default.createElement(Flex_1.default, { gap: 0.3 },
225
+ react_1.default.createElement("div", null,
226
+ react_1.default.createElement(pi_1.PiChecks, { className: 'text-primary' })),
227
+ react_1.default.createElement("div", null,
228
+ react_1.default.createElement(Text_1.default, { text: "On Sale", size: "xs", opacity: 4, block: true }),
229
+ react_1.default.createElement(Text_1.default, { text: "Yes", size: "sm", block: true, lineHeight: '1' })))),
230
+ product.weight && (react_1.default.createElement(Flex_1.default, { gap: 0.3 },
231
+ react_1.default.createElement("div", null,
232
+ react_1.default.createElement(pi_1.PiScales, { className: 'text-primary' })),
233
+ react_1.default.createElement("div", null,
234
+ react_1.default.createElement(Text_1.default, { text: "Weight", size: "xs", opacity: 4, block: true }),
235
+ react_1.default.createElement(Text_1.default, { text: product.weight + " " + product.weightUnit, size: "sm", block: true, lineHeight: '1' }))))))))), footer: react_1.default.createElement(RowFlex_1.default, { gap: 1, justify: 'flex-end', funcss: 'pt' },
236
+ react_1.default.createElement(RowFlex_1.default, { gap: 0.5, alignItems: "center" },
237
+ react_1.default.createElement(Circle_1.default, { body: react_1.default.createElement(pi_1.PiMinus, null), onClick: function () { return setQuantity(Math.max(1, quantity - 1)); }, funcss: quantity <= 1 ? "disabled" : "" }),
238
+ react_1.default.createElement("div", { className: "w-90" },
239
+ react_1.default.createElement(Input_1.default, { type: "number", value: quantity, onChange: function (e) {
240
+ var value = parseInt(e.target.value);
241
+ if (!isNaN(value)) {
242
+ setQuantity(Math.max(1, value));
243
+ }
244
+ }, funcss: "text-center", bordered: true })),
245
+ react_1.default.createElement(Circle_1.default, { onClick: function () { return setQuantity(quantity + 1); }, bg: 'lighter' },
246
+ react_1.default.createElement(pi_1.PiPlus, null))),
247
+ react_1.default.createElement(Button_1.default, { text: "Add to Cart - ".concat(currency).concat(totalPrice), bg: "primary", raised: true, onClick: handleAddToCart })) }));
248
+ };
249
+ exports.default = ProductDetail;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { Product } from './Products';
3
+ declare const ProductDetailModal: React.MemoExoticComponent<({ isOpen, setIsOpen, selectedProduct, selectedImageIndex, setSelectedImageIndex, selectedColor, setSelectedColor, quantity, setQuantity, handleAddFromModal, small, big }: {
4
+ isOpen: boolean;
5
+ setIsOpen: (open: boolean) => void;
6
+ selectedProduct: Product;
7
+ selectedImageIndex: number;
8
+ setSelectedImageIndex: (index: number) => void;
9
+ selectedColor: string;
10
+ setSelectedColor: (color: string) => void;
11
+ quantity: number;
12
+ setQuantity: (qty: number) => void;
13
+ handleAddFromModal: () => void;
14
+ small?: boolean;
15
+ big?: boolean;
16
+ }) => React.JSX.Element>;
17
+ export default ProductDetailModal;
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ var react_1 = __importStar(require("react"));
40
+ var pi_1 = require("react-icons/pi");
41
+ var Modal_1 = __importDefault(require("../modal/Modal"));
42
+ var Close_1 = __importDefault(require("../modal/Close"));
43
+ var Button_1 = __importDefault(require("../button/Button"));
44
+ var RowFlex_1 = __importDefault(require("../specials/RowFlex"));
45
+ var Text_1 = __importDefault(require("../text/Text"));
46
+ var Input_1 = __importDefault(require("../input/Input"));
47
+ var Div_1 = __importDefault(require("../div/Div"));
48
+ var DETAIL_EMPTY_SVG = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" fill="%23f3f4f6"><rect width="100" height="100"/><text x="50" y="55" text-anchor="middle" fill="%239ca3af" font-size="12">No Image</text></svg>';
49
+ var THUMBNAIL_EMPTY_SVG = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" fill="%23f3f4f6"><rect width="100" height="100"/></svg>';
50
+ var ProductDetailModal = (0, react_1.memo)(function (_a) {
51
+ var isOpen = _a.isOpen, setIsOpen = _a.setIsOpen, selectedProduct = _a.selectedProduct, selectedImageIndex = _a.selectedImageIndex, setSelectedImageIndex = _a.setSelectedImageIndex, selectedColor = _a.selectedColor, setSelectedColor = _a.setSelectedColor, quantity = _a.quantity, setQuantity = _a.setQuantity, handleAddFromModal = _a.handleAddFromModal, small = _a.small, big = _a.big;
52
+ return (react_1.default.createElement(Modal_1.default, { animation: "ScaleUp", duration: 0.3, open: isOpen, setOpen: setIsOpen, funcss: "funui_products_detail_modal max-width-600", title: react_1.default.createElement(RowFlex_1.default, { justify: "space-between", alignItems: "center" },
53
+ react_1.default.createElement(Text_1.default, { text: selectedProduct.name, size: "h3", funcss: "text-bold", block: true }),
54
+ react_1.default.createElement(Close_1.default, { onClick: function () { return setIsOpen(false); } })), body: react_1.default.createElement(Div_1.default, { funcss: "funui_products_detail_body" },
55
+ selectedProduct.images && selectedProduct.images.length > 0 && (react_1.default.createElement(Div_1.default, { funcss: "margin-bottom-20" },
56
+ react_1.default.createElement(Div_1.default, { funcss: "margin-bottom-10" },
57
+ react_1.default.createElement("img", { src: selectedProduct.images[selectedImageIndex], alt: selectedProduct.name, style: { width: '100%', borderRadius: '0.5rem' }, loading: "lazy", onError: function (e) {
58
+ e.target.src = DETAIL_EMPTY_SVG;
59
+ } })),
60
+ selectedProduct.images.length > 1 && (react_1.default.createElement(RowFlex_1.default, { gap: 1, wrap: "wrap" }, selectedProduct.images.map(function (image, index) { return (react_1.default.createElement(Div_1.default, { key: index, funcss: "cursor-pointer ".concat(selectedImageIndex === index ? 'border-2 border-primary' : 'border border-light'), onClick: function () { return setSelectedImageIndex(index); }, customStyle: {
61
+ width: '80px',
62
+ height: '80px',
63
+ borderRadius: '0.5rem',
64
+ overflow: 'hidden',
65
+ cursor: 'pointer'
66
+ } },
67
+ react_1.default.createElement("img", { src: image, alt: "".concat(selectedProduct.name, " ").concat(index + 1), loading: "lazy", style: {
68
+ width: '100%',
69
+ height: '100%',
70
+ objectFit: 'cover'
71
+ }, onError: function (e) {
72
+ e.target.src = THUMBNAIL_EMPTY_SVG;
73
+ } }))); }))))),
74
+ react_1.default.createElement(Div_1.default, { funcss: "funui_products_detail_info space-y-3" },
75
+ react_1.default.createElement(RowFlex_1.default, { justify: "space-between", alignItems: "center" },
76
+ react_1.default.createElement(Text_1.default, { text: "$".concat(selectedProduct.price.toFixed(2)), size: "h3", funcss: "text-bold" }),
77
+ selectedProduct.comparePrice && selectedProduct.comparePrice > selectedProduct.price && (react_1.default.createElement(Text_1.default, { text: "$".concat(selectedProduct.comparePrice.toFixed(2)), funcss: "text-light line-through" }))),
78
+ selectedProduct.description && (react_1.default.createElement(Text_1.default, { text: selectedProduct.description, funcss: "text-light line-height-1.6" })),
79
+ selectedProduct.colors && selectedProduct.colors.length > 0 && (react_1.default.createElement(Div_1.default, { funcss: "funui_products_color_selection space-y-2" },
80
+ react_1.default.createElement(Text_1.default, { text: "Color", funcss: "text-bold" }),
81
+ react_1.default.createElement(RowFlex_1.default, { gap: 1, wrap: "wrap" }, selectedProduct.colors.map(function (color) { return (react_1.default.createElement(Button_1.default, { key: color.name, onClick: function () { return setSelectedColor(color.name); }, funcss: "padding-10 rounded ".concat(selectedColor === color.name
82
+ ? 'border-2 border-primary'
83
+ : 'border border-light'), style: { backgroundColor: color.code }, "aria-label": color.name }, selectedColor === color.name && (react_1.default.createElement(pi_1.PiCheck, { style: { color: 'white' } })))); })))),
84
+ react_1.default.createElement(Div_1.default, { funcss: "funui_products_quantity_selection space-y-2" },
85
+ react_1.default.createElement(Text_1.default, { text: "Quantity", funcss: "text-bold" }),
86
+ react_1.default.createElement(RowFlex_1.default, { gap: 2, alignItems: "center" },
87
+ react_1.default.createElement(Button_1.default, { startIcon: "-", onClick: function () { return setQuantity(Math.max(1, quantity - 1)); }, disabled: quantity <= 1, color: "text", small: small }),
88
+ react_1.default.createElement(Input_1.default, { type: "number", value: quantity, onChange: function (e) {
89
+ var value = parseInt(e.target.value);
90
+ if (!isNaN(value)) {
91
+ setQuantity(Math.max(1, value));
92
+ }
93
+ }, funcss: "width-100 text-center", bordered: true }),
94
+ react_1.default.createElement(Button_1.default, { startIcon: react_1.default.createElement(pi_1.PiPlus, null), onClick: function () { return setQuantity(quantity + 1); }, color: "text", small: small }))))), footer: react_1.default.createElement(RowFlex_1.default, { gap: 1, justify: "flex-end", funcss: "funui_products_detail_footer" },
95
+ react_1.default.createElement(Button_1.default, { text: "Cancel", color: "text", onClick: function () { return setIsOpen(false); }, small: small }),
96
+ react_1.default.createElement(Button_1.default, { text: "Add to Cart - $".concat(((selectedProduct.price || 0) * quantity).toFixed(2)), bg: "primary", raised: true, startIcon: react_1.default.createElement(pi_1.PiShoppingCart, null), onClick: handleAddFromModal, small: small, big: big })) }));
97
+ });
98
+ ProductDetailModal.displayName = 'ProductDetailModal';
99
+ exports.default = ProductDetailModal;
@@ -0,0 +1,60 @@
1
+ import React from 'react';
2
+ export type Product = {
3
+ id: string;
4
+ name: string;
5
+ price: number;
6
+ comparePrice?: number;
7
+ description?: string;
8
+ images?: string[];
9
+ category?: string;
10
+ brand?: string;
11
+ tags?: string[];
12
+ colors?: {
13
+ name: string;
14
+ code: string;
15
+ }[];
16
+ sku?: string;
17
+ stock?: number;
18
+ rating?: number;
19
+ isNew?: boolean;
20
+ isSale?: boolean;
21
+ discountPercentage?: number;
22
+ };
23
+ export type CartItem = {
24
+ product: Product;
25
+ quantity: number;
26
+ selectedColor?: string;
27
+ };
28
+ type ProductsPageProps = {
29
+ products: Product[] | string;
30
+ title?: string;
31
+ showHeader?: boolean;
32
+ showSearch?: boolean;
33
+ showFilters?: boolean;
34
+ showCart?: boolean;
35
+ cartIcon?: string | React.ReactNode;
36
+ cartBadgeColor?: string;
37
+ cartBadgeText?: string;
38
+ checkoutText?: string;
39
+ checkoutIcon?: string | React.ReactNode;
40
+ onAddToCart?: (item: CartItem) => void;
41
+ onRemoveFromCart?: (itemId: string) => void;
42
+ onUpdateQuantity?: (itemId: string, quantity: number) => void;
43
+ onCheckout?: (cartItems: CartItem[], totalAmount: number) => void;
44
+ onProductClick?: (product: Product) => void;
45
+ className?: string;
46
+ gridClassName?: string;
47
+ children?: React.ReactNode;
48
+ style?: React.CSSProperties;
49
+ id?: string;
50
+ funcss?: string;
51
+ bg?: string;
52
+ color?: string;
53
+ rounded?: boolean;
54
+ raised?: boolean;
55
+ fullWidth?: boolean;
56
+ small?: boolean;
57
+ big?: boolean;
58
+ };
59
+ declare const Products: React.FC<ProductsPageProps>;
60
+ export default Products;