funuicss 3.7.16 → 3.8.1
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/css/fun.css +324 -202
- package/demo/theme.tsx +1311 -0
- package/index.d.ts +2 -0
- package/index.js +5 -1
- package/package.json +1 -1
- package/ui/button/Button.d.ts +2 -1
- package/ui/button/Button.js +3 -3
- package/ui/components/ImageScaler.d.ts +6 -0
- package/ui/components/ImageScaler.js +17 -0
- package/ui/div/Div.d.ts +3 -1
- package/ui/div/Div.js +2 -2
- package/ui/empty/Empty.d.ts +17 -0
- package/ui/empty/Empty.js +66 -0
- package/ui/flex/Flex.d.ts +2 -1
- package/ui/flex/Flex.js +3 -3
- package/ui/modal/Modal.d.ts +1 -1
- package/ui/products/CartModal.d.ts +20 -0
- package/ui/products/CartModal.js +85 -0
- package/ui/products/ProductCard.d.ts +13 -0
- package/ui/products/ProductCard.js +56 -0
- package/ui/products/ProductDetail.d.ts +14 -0
- package/ui/products/ProductDetail.js +249 -0
- package/ui/products/ProductDetailModal.d.ts +17 -0
- package/ui/products/ProductDetailModal.js +99 -0
- package/ui/products/Products.d.ts +60 -0
- package/ui/products/Products.js +312 -0
- package/ui/products/Store.d.ts +99 -0
- package/ui/products/Store.js +515 -0
- package/ui/sidebar/SideBar.d.ts +3 -1
- package/ui/sidebar/SideBar.js +50 -11
- package/ui/specials/Circle.d.ts +2 -1
- package/ui/specials/Circle.js +2 -2
- package/ui/table/Table.d.ts +15 -1
- package/ui/table/Table.js +158 -31
- package/ui/theme/theme.d.ts +90 -0
- package/ui/theme/theme.js +440 -545
- package/utils/Buckets.d.ts +0 -0
- package/utils/Buckets.js +1 -0
|
@@ -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;
|