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.
@@ -0,0 +1,515 @@
1
+ "use strict";
2
+ 'use client';
3
+ var __assign = (this && this.__assign) || function () {
4
+ __assign = Object.assign || function(t) {
5
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
6
+ s = arguments[i];
7
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
8
+ t[p] = s[p];
9
+ }
10
+ return t;
11
+ };
12
+ return __assign.apply(this, arguments);
13
+ };
14
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ var desc = Object.getOwnPropertyDescriptor(m, k);
17
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
18
+ desc = { enumerable: true, get: function() { return m[k]; } };
19
+ }
20
+ Object.defineProperty(o, k2, desc);
21
+ }) : (function(o, m, k, k2) {
22
+ if (k2 === undefined) k2 = k;
23
+ o[k2] = m[k];
24
+ }));
25
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
26
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
27
+ }) : function(o, v) {
28
+ o["default"] = v;
29
+ });
30
+ var __importStar = (this && this.__importStar) || (function () {
31
+ var ownKeys = function(o) {
32
+ ownKeys = Object.getOwnPropertyNames || function (o) {
33
+ var ar = [];
34
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
35
+ return ar;
36
+ };
37
+ return ownKeys(o);
38
+ };
39
+ return function (mod) {
40
+ if (mod && mod.__esModule) return mod;
41
+ var result = {};
42
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
43
+ __setModuleDefault(result, mod);
44
+ return result;
45
+ };
46
+ })();
47
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
48
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
49
+ if (ar || !(i in from)) {
50
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
51
+ ar[i] = from[i];
52
+ }
53
+ }
54
+ return to.concat(ar || Array.prototype.slice.call(from));
55
+ };
56
+ var __importDefault = (this && this.__importDefault) || function (mod) {
57
+ return (mod && mod.__esModule) ? mod : { "default": mod };
58
+ };
59
+ Object.defineProperty(exports, "__esModule", { value: true });
60
+ var react_1 = __importStar(require("react"));
61
+ var pi_1 = require("react-icons/pi");
62
+ var Button_1 = __importDefault(require("../button/Button"));
63
+ var RowFlex_1 = __importDefault(require("../specials/RowFlex"));
64
+ var Text_1 = __importDefault(require("../text/Text"));
65
+ var Input_1 = __importDefault(require("../input/Input"));
66
+ var Div_1 = __importDefault(require("../div/Div"));
67
+ var sl_1 = require("react-icons/sl");
68
+ var Flex_1 = __importDefault(require("../flex/Flex"));
69
+ var Select_1 = __importDefault(require("../select/Select"));
70
+ var ProductCard_1 = __importDefault(require("./ProductCard"));
71
+ var CartModal_1 = __importDefault(require("./CartModal"));
72
+ var ProductDetail_1 = __importDefault(require("./ProductDetail"));
73
+ var theme_1 = require("../theme/theme");
74
+ var componentUtils_1 = require("../../utils/componentUtils");
75
+ var Empty_1 = __importDefault(require("../empty/Empty"));
76
+ var ri_1 = require("react-icons/ri");
77
+ var Store = function (localProps) {
78
+ // Use component configuration with variant
79
+ var mergeWithLocal = (0, componentUtils_1.useComponentConfiguration)('Store', localProps.variant).mergeWithLocal;
80
+ var final = mergeWithLocal(localProps).props;
81
+ // Destructure props from final merged configuration
82
+ var _a = final.products, products = _a === void 0 ? [] : _a, bucket = final.bucket, _b = final.bucketPage, bucketPage = _b === void 0 ? 1 : _b, _c = final.bucketSize, bucketSize = _c === void 0 ? 50 : _c, _d = final.title, title = _d === void 0 ? 'Products' : _d, _e = final.showHeader, showHeader = _e === void 0 ? true : _e, _f = final.showSearch, showSearch = _f === void 0 ? true : _f, _g = final.showFilters, showFilters = _g === void 0 ? true : _g, _h = final.showCart, showCart = _h === void 0 ? true : _h, _j = final.cartBadgeColor, cartBadgeColor = _j === void 0 ? 'error' : _j, cartBadgeText = final.cartBadgeText, _k = final.checkoutText, checkoutText = _k === void 0 ? 'Checkout' : _k, checkoutIcon = final.checkoutIcon, _l = final.currency, currency = _l === void 0 ? '$' : _l, _m = final.persistCart, persistCart = _m === void 0 ? true : _m, _o = final.storageKey, storageKey = _o === void 0 ? 'funui_cart' : _o, onAddToCart = final.onAddToCart, onRemoveFromCart = final.onRemoveFromCart, onUpdateQuantity = final.onUpdateQuantity, onCheckout = final.onCheckout, onProductClick = final.onProductClick, _p = final.className, className = _p === void 0 ? '' : _p, _q = final.gridClassName, gridClassName = _q === void 0 ? '' : _q, children = final.children, id = final.id, _r = final.funcss, funcss = _r === void 0 ? '' : _r, _s = final.fullWidth, fullWidth = _s === void 0 ? false : _s, _t = final.small, small = _t === void 0 ? false : _t, _u = final.big, big = _u === void 0 ? false : _u, _v = final.itemsPerPage, itemsPerPage = _v === void 0 ? 10 : _v;
83
+ // Loading state - track bucket loading and initial load
84
+ var _w = (0, react_1.useState)(true), isInitialLoading = _w[0], setIsInitialLoading = _w[1];
85
+ // Use bucket data if bucket prop is provided
86
+ var _x = (0, theme_1.usePaginatedRecords)(bucket || '', // Use bucket name if provided
87
+ bucketPage, bucketSize), bucketRecords = _x.records, bucketLoading = _x.loading;
88
+ // Function to calculate discount price
89
+ var calculateDiscountedPrice = (0, react_1.useCallback)(function (price, discount) {
90
+ if (discount && discount > 0 && discount <= 100) {
91
+ var discountAmount = (price * discount) / 100;
92
+ return {
93
+ finalPrice: price - discountAmount,
94
+ originalPrice: price
95
+ };
96
+ }
97
+ return {
98
+ finalPrice: price,
99
+ originalPrice: price
100
+ };
101
+ }, []);
102
+ // Apply discounts to products
103
+ var applyDiscounts = (0, react_1.useCallback)(function (products) {
104
+ return products.map(function (product) {
105
+ var _a, _b;
106
+ // Check if product has variants
107
+ if (product.variants && product.variants.length > 0) {
108
+ var discountedVariants = product.variants.map(function (variant) {
109
+ var _a = calculateDiscountedPrice(variant.price, variant.discount), finalPrice = _a.finalPrice, originalPrice = _a.originalPrice;
110
+ return __assign(__assign({}, variant), { price: finalPrice, comparePrice: originalPrice });
111
+ });
112
+ return __assign(__assign({}, product), { variants: discountedVariants,
113
+ // Use the first variant's price as the main product price
114
+ price: ((_a = discountedVariants[0]) === null || _a === void 0 ? void 0 : _a.price) || product.price, comparePrice: ((_b = discountedVariants[0]) === null || _b === void 0 ? void 0 : _b.comparePrice) || product.comparePrice });
115
+ }
116
+ else {
117
+ // Apply discount to main product
118
+ var _c = calculateDiscountedPrice(product.price, product.discount), finalPrice = _c.finalPrice, originalPrice = _c.originalPrice;
119
+ return __assign(__assign({}, product), { price: finalPrice, comparePrice: originalPrice !== finalPrice ? originalPrice : product.comparePrice });
120
+ }
121
+ });
122
+ }, [calculateDiscountedPrice]);
123
+ // Convert bucket records to products format with discount handling
124
+ var bucketProducts = (0, react_1.useMemo)(function () {
125
+ if (!bucket || !bucketRecords)
126
+ return null;
127
+ var mappedProducts = bucketRecords.map(function (record) {
128
+ var values = record.values || record;
129
+ // Extract discount from record - could be in various fields
130
+ var discount = values.discount || values.salePercentage || values.discountPercentage;
131
+ return {
132
+ id: values.id || record.id || "bucket_".concat(Math.random().toString(36).substr(2, 9)),
133
+ name: values.name || values.title || 'Unnamed Product',
134
+ price: parseFloat(values.price) || 0,
135
+ comparePrice: parseFloat(values.comparePrice) || parseFloat(values.originalPrice) || undefined,
136
+ currency: values.currency || currency,
137
+ description: values.description || '',
138
+ images: Array.isArray(values.images) ? values.images.map(function (image) { return image.url; }) :
139
+ values.image ? [values.image] : [],
140
+ category: values.category || values.type || '',
141
+ brand: values.brand || values.manufacturer || '',
142
+ tags: Array.isArray(values.tags) ? values.tags :
143
+ values.tag ? [values.tag] : [],
144
+ colors: values.colors || [],
145
+ sizes: values.sizes || [],
146
+ weight: parseFloat(values.weight) || undefined,
147
+ weightUnit: values.weightUnit,
148
+ sku: values.sku || values.productCode,
149
+ stock: parseInt(values.stock) || parseInt(values.quantity) || undefined,
150
+ rating: parseFloat(values.rating) || undefined,
151
+ isNew: values.isNew || values.newArrival || false,
152
+ isSale: values.isSale || values.onSale || false,
153
+ variants: values.variants ? values.variants.map(function (variant) { return (__assign(__assign({}, variant), { discount: variant.discount || discount // Pass discount to variants
154
+ })); }) : [],
155
+ manufacturer: values.manufacturer || '',
156
+ countryOfOrigin: values.countryOfOrigin || '',
157
+ warranty: values.warranty || '',
158
+ isFeatured: values.isFeatured || '',
159
+ discount: discount ? parseFloat(discount) : undefined
160
+ };
161
+ });
162
+ return applyDiscounts(mappedProducts);
163
+ }, [bucketRecords, bucket, currency, applyDiscounts]);
164
+ // Parse and process products - FIXED: No setState calls inside useMemo
165
+ var parsedProducts = react_1.default.useMemo(function () {
166
+ var productList;
167
+ // Use bucket products if bucket prop is provided and we have bucket data
168
+ if (bucket && bucketProducts) {
169
+ console.log("Using ".concat(bucketProducts.length, " products from bucket: ").concat(bucket));
170
+ productList = bucketProducts.map(function (product, index) { return (__assign(__assign({}, product), { id: product.id || "bucket_product_".concat(index, "_").concat(Date.now()) })); });
171
+ }
172
+ else {
173
+ // Fall back to local products prop
174
+ if (typeof products === 'string') {
175
+ try {
176
+ var parsed = JSON.parse(products);
177
+ productList = Array.isArray(parsed) ? parsed : [];
178
+ }
179
+ catch (error) {
180
+ console.error('Error parsing products JSON:', error);
181
+ productList = [];
182
+ }
183
+ }
184
+ else {
185
+ productList = products || [];
186
+ }
187
+ // Apply discounts to locally provided products
188
+ productList = applyDiscounts(productList);
189
+ }
190
+ // Ensure each product has a unique ID
191
+ return productList.map(function (product, index) { return (__assign(__assign({}, product), { id: product.id || "product_".concat(index, "_").concat(Date.now(), "_").concat(Math.random().toString(36).substr(2, 9)) })); });
192
+ }, [products, bucket, bucketProducts, applyDiscounts]);
193
+ // Handle loading state separately
194
+ (0, react_1.useEffect)(function () {
195
+ if (bucket) {
196
+ // For bucket data, loading is based on bucketLoading state
197
+ if (!bucketLoading && bucketProducts !== undefined) {
198
+ // Small delay for better UX
199
+ var timer_1 = setTimeout(function () {
200
+ setIsInitialLoading(false);
201
+ }, 300);
202
+ return function () { return clearTimeout(timer_1); };
203
+ }
204
+ }
205
+ else {
206
+ // For local data, loading is immediate after parsing
207
+ setIsInitialLoading(false);
208
+ }
209
+ }, [bucket, bucketLoading, bucketProducts]);
210
+ // Combined loading state
211
+ var showLoading = isInitialLoading || (bucket && bucketLoading);
212
+ // Initialize cart from localStorage with discount handling
213
+ var _y = (0, react_1.useState)(function () {
214
+ if (!persistCart)
215
+ return [];
216
+ try {
217
+ var stored = localStorage.getItem(storageKey);
218
+ if (stored) {
219
+ var parsed = JSON.parse(stored);
220
+ if (parsed.items && Array.isArray(parsed.items)) {
221
+ return parsed.items.map(function (item) { return (__assign(__assign({}, item), { product: __assign(__assign({}, item.product), { id: item.product.id || "restored_".concat(Date.now()) }),
222
+ // Ensure original price is preserved
223
+ originalPrice: item.originalPrice || item.product.comparePrice || item.product.price })); });
224
+ }
225
+ }
226
+ }
227
+ catch (error) {
228
+ console.error('Error loading cart from localStorage:', error);
229
+ }
230
+ return [];
231
+ }), cart = _y[0], setCart = _y[1];
232
+ // Save cart to localStorage
233
+ (0, react_1.useEffect)(function () {
234
+ if (persistCart) {
235
+ try {
236
+ var cartStorage = {
237
+ items: cart,
238
+ updatedAt: Date.now(),
239
+ };
240
+ localStorage.setItem(storageKey, JSON.stringify(cartStorage));
241
+ }
242
+ catch (error) {
243
+ console.error('Error saving cart to localStorage:', error);
244
+ }
245
+ }
246
+ }, [cart, persistCart, storageKey]);
247
+ var _z = (0, react_1.useState)(false), isCartOpen = _z[0], setIsCartOpen = _z[1];
248
+ var _0 = (0, react_1.useState)(false), isProductModalOpen = _0[0], setIsProductModalOpen = _0[1];
249
+ var _1 = (0, react_1.useState)(null), selectedProduct = _1[0], setSelectedProduct = _1[1];
250
+ var _2 = (0, react_1.useState)(''), searchQuery = _2[0], setSearchQuery = _2[1];
251
+ var _3 = (0, react_1.useState)('all'), selectedCategory = _3[0], setSelectedCategory = _3[1];
252
+ var _4 = (0, react_1.useState)('all'), selectedColor = _4[0], setSelectedColor = _4[1];
253
+ var _5 = (0, react_1.useState)('all'), selectedBrand = _5[0], setSelectedBrand = _5[1];
254
+ var _6 = (0, react_1.useState)(1), currentPage = _6[0], setCurrentPage = _6[1];
255
+ // Get unique categories
256
+ var categories = (0, react_1.useMemo)(function () {
257
+ if (showLoading)
258
+ return ['all'];
259
+ var allCategories = parsedProducts
260
+ .map(function (p) { return p.category; })
261
+ .filter(function (cat) { return typeof cat === 'string' && cat.trim() !== ''; });
262
+ var uniqueCategories = Array.from(new Set(allCategories));
263
+ return __spreadArray(['all'], uniqueCategories, true);
264
+ }, [parsedProducts, showLoading]);
265
+ // Get unique brands
266
+ var brands = (0, react_1.useMemo)(function () {
267
+ if (showLoading)
268
+ return ['all'];
269
+ var allBrands = parsedProducts
270
+ .map(function (p) { return p.brand; })
271
+ .filter(function (brand) { return typeof brand === 'string' && brand.trim() !== ''; });
272
+ return __spreadArray(['all'], Array.from(new Set(allBrands)), true);
273
+ }, [parsedProducts, showLoading]);
274
+ // Get unique colors
275
+ var colors = (0, react_1.useMemo)(function () {
276
+ if (showLoading)
277
+ return ['all'];
278
+ var allColors = [];
279
+ parsedProducts.forEach(function (product) {
280
+ var _a;
281
+ (_a = product.colors) === null || _a === void 0 ? void 0 : _a.forEach(function (color) {
282
+ if (!allColors.includes(color.name)) {
283
+ allColors.push(color.name);
284
+ }
285
+ });
286
+ });
287
+ return __spreadArray(['all'], allColors, true);
288
+ }, [parsedProducts, showLoading]);
289
+ // Filter products
290
+ var filteredProducts = (0, react_1.useMemo)(function () {
291
+ if (showLoading)
292
+ return [];
293
+ var filtered = __spreadArray([], parsedProducts, true);
294
+ if (searchQuery.trim()) {
295
+ var query_1 = searchQuery.toLowerCase();
296
+ filtered = filtered.filter(function (p) {
297
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
298
+ var nameMatch = (_b = (_a = p.name) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes(query_1)) !== null && _b !== void 0 ? _b : false;
299
+ var descMatch = (_d = (_c = p.description) === null || _c === void 0 ? void 0 : _c.toLowerCase().includes(query_1)) !== null && _d !== void 0 ? _d : false;
300
+ var brandMatch = (_f = (_e = p.brand) === null || _e === void 0 ? void 0 : _e.toLowerCase().includes(query_1)) !== null && _f !== void 0 ? _f : false;
301
+ var categoryMatch = (_h = (_g = p.category) === null || _g === void 0 ? void 0 : _g.toLowerCase().includes(query_1)) !== null && _h !== void 0 ? _h : false;
302
+ var tagsMatch = (_k = (_j = p.tags) === null || _j === void 0 ? void 0 : _j.some(function (tag) { return tag.toLowerCase().includes(query_1); })) !== null && _k !== void 0 ? _k : false;
303
+ return nameMatch || descMatch || brandMatch || categoryMatch || tagsMatch;
304
+ });
305
+ }
306
+ if (selectedCategory !== 'all') {
307
+ filtered = filtered.filter(function (p) { return p.category === selectedCategory; });
308
+ }
309
+ if (selectedBrand !== 'all') {
310
+ filtered = filtered.filter(function (p) { return p.brand === selectedBrand; });
311
+ }
312
+ if (selectedColor !== 'all') {
313
+ filtered = filtered.filter(function (p) { var _a; return (_a = p.colors) === null || _a === void 0 ? void 0 : _a.some(function (color) { return color.name === selectedColor; }); });
314
+ }
315
+ return filtered;
316
+ }, [parsedProducts, searchQuery, selectedCategory, selectedBrand, selectedColor, showLoading]);
317
+ // Pagination
318
+ var totalPages = Math.ceil(filteredProducts.length / itemsPerPage);
319
+ var startIndex = (currentPage - 1) * itemsPerPage;
320
+ var endIndex = startIndex + itemsPerPage;
321
+ var currentProducts = filteredProducts.slice(startIndex, endIndex);
322
+ (0, react_1.useEffect)(function () {
323
+ setCurrentPage(1);
324
+ }, [searchQuery, selectedCategory, selectedBrand, selectedColor]);
325
+ // Enhanced cart calculations with discount consideration
326
+ var totalItems = (0, react_1.useMemo)(function () { return cart.reduce(function (sum, item) { return sum + item.quantity; }, 0); }, [cart]);
327
+ var subtotal = (0, react_1.useMemo)(function () { return cart.reduce(function (sum, item) {
328
+ var _a;
329
+ var price = ((_a = item.variant) === null || _a === void 0 ? void 0 : _a.price) || item.product.price;
330
+ return sum + (price * item.quantity);
331
+ }, 0); }, [cart]);
332
+ // Calculate total savings from discounts
333
+ var totalSavings = (0, react_1.useMemo)(function () { return cart.reduce(function (sum, item) {
334
+ var _a;
335
+ var originalPrice = item.originalPrice || item.product.comparePrice || item.product.price;
336
+ var currentPrice = ((_a = item.variant) === null || _a === void 0 ? void 0 : _a.price) || item.product.price;
337
+ var savings = originalPrice !== currentPrice ? (originalPrice - currentPrice) * item.quantity : 0;
338
+ return sum + savings;
339
+ }, 0); }, [cart]);
340
+ // Generate cart item ID
341
+ var generateCartItemId = (0, react_1.useCallback)(function (product, options) {
342
+ var _a;
343
+ var parts = [
344
+ product.id,
345
+ ((_a = options === null || options === void 0 ? void 0 : options.variant) === null || _a === void 0 ? void 0 : _a.id) || '',
346
+ (options === null || options === void 0 ? void 0 : options.color) || '',
347
+ (options === null || options === void 0 ? void 0 : options.size) || ''
348
+ ].filter(Boolean);
349
+ return parts.join('_');
350
+ }, []);
351
+ // Enhanced cart functions with original price preservation
352
+ var addToCart = (0, react_1.useCallback)(function (product, selectedOptions) {
353
+ var _a;
354
+ var cartItemId = generateCartItemId(product, selectedOptions);
355
+ var existingItemIndex = cart.findIndex(function (item) {
356
+ var itemId = generateCartItemId(item.product, {
357
+ color: item.selectedColor,
358
+ size: item.selectedSize,
359
+ variant: item.variant
360
+ });
361
+ return itemId === cartItemId;
362
+ });
363
+ var updatedCart;
364
+ // Store original price before discount
365
+ var originalPrice = ((_a = selectedOptions === null || selectedOptions === void 0 ? void 0 : selectedOptions.variant) === null || _a === void 0 ? void 0 : _a.comparePrice) ||
366
+ product.comparePrice ||
367
+ product.price;
368
+ if (existingItemIndex !== -1) {
369
+ updatedCart = __spreadArray([], cart, true);
370
+ var existingItem = updatedCart[existingItemIndex];
371
+ updatedCart[existingItemIndex] = __assign(__assign({}, existingItem), { quantity: existingItem.quantity + 1 });
372
+ }
373
+ else {
374
+ var newItem = {
375
+ product: product,
376
+ variant: selectedOptions === null || selectedOptions === void 0 ? void 0 : selectedOptions.variant,
377
+ quantity: 1,
378
+ selectedColor: selectedOptions === null || selectedOptions === void 0 ? void 0 : selectedOptions.color,
379
+ selectedSize: selectedOptions === null || selectedOptions === void 0 ? void 0 : selectedOptions.size,
380
+ addedAt: Date.now(),
381
+ originalPrice: originalPrice
382
+ };
383
+ updatedCart = __spreadArray(__spreadArray([], cart, true), [newItem], false);
384
+ }
385
+ setCart(updatedCart);
386
+ if (existingItemIndex !== -1) {
387
+ var existingItem = cart[existingItemIndex];
388
+ onUpdateQuantity === null || onUpdateQuantity === void 0 ? void 0 : onUpdateQuantity(cartItemId, existingItem.quantity + 1);
389
+ }
390
+ else {
391
+ var newItem = updatedCart[updatedCart.length - 1];
392
+ onAddToCart === null || onAddToCart === void 0 ? void 0 : onAddToCart(newItem);
393
+ }
394
+ }, [cart, generateCartItemId, onUpdateQuantity, onAddToCart]);
395
+ var updateQuantity = (0, react_1.useCallback)(function (cartItemId, newQuantity) {
396
+ if (newQuantity < 1) {
397
+ removeFromCart(cartItemId);
398
+ return;
399
+ }
400
+ var updatedCart = cart.map(function (item) {
401
+ var itemId = generateCartItemId(item.product, {
402
+ color: item.selectedColor,
403
+ size: item.selectedSize,
404
+ variant: item.variant
405
+ });
406
+ if (itemId === cartItemId) {
407
+ return __assign(__assign({}, item), { quantity: newQuantity });
408
+ }
409
+ return item;
410
+ });
411
+ setCart(updatedCart);
412
+ onUpdateQuantity === null || onUpdateQuantity === void 0 ? void 0 : onUpdateQuantity(cartItemId, newQuantity);
413
+ }, [cart, generateCartItemId, onUpdateQuantity]);
414
+ var removeFromCart = (0, react_1.useCallback)(function (cartItemId) {
415
+ var updatedCart = cart.filter(function (item) {
416
+ var itemId = generateCartItemId(item.product, {
417
+ color: item.selectedColor,
418
+ size: item.selectedSize,
419
+ variant: item.variant
420
+ });
421
+ return itemId !== cartItemId;
422
+ });
423
+ setCart(updatedCart);
424
+ onRemoveFromCart === null || onRemoveFromCart === void 0 ? void 0 : onRemoveFromCart(cartItemId);
425
+ }, [cart, generateCartItemId, onRemoveFromCart]);
426
+ var clearCart = (0, react_1.useCallback)(function () {
427
+ setCart([]);
428
+ if (persistCart) {
429
+ localStorage.removeItem(storageKey);
430
+ }
431
+ }, [persistCart, storageKey]);
432
+ var handleCheckout = (0, react_1.useCallback)(function () {
433
+ if (onCheckout) {
434
+ onCheckout(cart, subtotal);
435
+ }
436
+ if (persistCart) {
437
+ clearCart();
438
+ }
439
+ setIsCartOpen(false);
440
+ }, [onCheckout, cart, subtotal, persistCart, clearCart]);
441
+ // Product modal
442
+ var openProductModal = (0, react_1.useCallback)(function (product) {
443
+ if (onProductClick) {
444
+ onProductClick(product);
445
+ return;
446
+ }
447
+ setSelectedProduct(product);
448
+ setIsProductModalOpen(true);
449
+ }, [onProductClick]);
450
+ var handleAddFromModal = (0, react_1.useCallback)(function (product, quantity, options) {
451
+ for (var i = 0; i < quantity; i++) {
452
+ addToCart(product, options);
453
+ }
454
+ setIsProductModalOpen(false);
455
+ }, [addToCart]);
456
+ // Pagination
457
+ var goToPage = (0, react_1.useCallback)(function (page) {
458
+ if (page >= 1 && page <= totalPages) {
459
+ setCurrentPage(page);
460
+ }
461
+ }, [totalPages]);
462
+ return (react_1.default.createElement(Div_1.default, { funcss: "funui_products_classname ".concat(className, " ").concat(funcss), id: id, customStyle: {
463
+ backgroundColor: final.bg,
464
+ color: final.color,
465
+ } },
466
+ showHeader && (react_1.default.createElement(RowFlex_1.default, { justify: "space-between", alignItems: "center", funcss: "mb-5" },
467
+ react_1.default.createElement(Text_1.default, { text: title, size: "h1" }),
468
+ showCart && (react_1.default.createElement("button", { onClick: function () { return setIsCartOpen(true); }, className: "cart-icon relative", type: "button", "aria-label": "Shopping cart (".concat(totalItems, " items)"), disabled: showLoading },
469
+ react_1.default.createElement(sl_1.SlHandbag, { size: 30 }),
470
+ totalItems > 0 && (react_1.default.createElement("div", { className: "cart-badge", style: { backgroundColor: cartBadgeColor } }, cartBadgeText || (totalItems > 99 ? '99+' : totalItems))))))),
471
+ (showSearch || showFilters) && (react_1.default.createElement(RowFlex_1.default, { gap: 1, alignItems: "center", justify: 'space-between' },
472
+ showSearch && (react_1.default.createElement(Input_1.default, { label: "Search products...", value: searchQuery, onChange: function (e) { return setSearchQuery(e.target.value); }, bordered: true, fullWidth: fullWidth, startIcon: react_1.default.createElement(pi_1.PiMagnifyingGlass, null) })),
473
+ showFilters && (react_1.default.createElement("div", { className: "col" },
474
+ react_1.default.createElement(Flex_1.default, { gap: 0.5, width: '100%', justify: 'flex-end' },
475
+ categories && categories.length > 0 && (react_1.default.createElement("div", { className: "w-150" },
476
+ react_1.default.createElement(Select_1.default, { options: categories.map(function (cat) { return ({ text: cat === 'all' ? 'All Categories' : cat, value: cat }); }), value: selectedCategory, onChange: function (e) { return setSelectedCategory(e); }, bordered: true, funcss: 'text-sm', disabled: showLoading }))),
477
+ brands && brands.length > 0 && (react_1.default.createElement("div", { className: "w-150" },
478
+ react_1.default.createElement(Select_1.default, { options: brands.map(function (brand) { return ({ text: brand === 'all' ? 'All Brands' : brand, value: brand }); }), value: selectedBrand, onChange: function (e) { return setSelectedBrand(e); }, bordered: true, funcss: 'text-sm', disabled: showLoading }))),
479
+ colors && colors.length > 0 && (react_1.default.createElement("div", { className: "w-150" },
480
+ react_1.default.createElement(Select_1.default, { options: colors.map(function (color) { return ({ text: color === 'all' ? 'All Colors' : color, value: color }); }), value: selectedColor, onChange: function (e) { return setSelectedColor(e); }, bordered: true, funcss: 'text-sm', disabled: showLoading })))))))),
481
+ showLoading ? (react_1.default.createElement(Div_1.default, { funcss: "funui_products_loading flex-center padding-40" },
482
+ react_1.default.createElement(Flex_1.default, { direction: "column", alignItems: "center", gap: 2 },
483
+ react_1.default.createElement(ri_1.RiLoader4Line, { size: 40, className: "spin" }),
484
+ react_1.default.createElement(Text_1.default, { text: "Loading products...", size: "large", color: "text-light" })))) : (react_1.default.createElement(react_1.default.Fragment, null,
485
+ currentProducts.length === 0 ? (react_1.default.createElement(Div_1.default, { funcss: "funui_products_empty flex-center padding-40" },
486
+ react_1.default.createElement(Empty_1.default, { title: 'No products found', ctaIcon: react_1.default.createElement(pi_1.PiSpinnerGap, null), ctaText: 'Reload Page!', ctaOnClick: function () { return window.location.reload(); } }))) : (react_1.default.createElement(react_1.default.Fragment, null,
487
+ react_1.default.createElement(Div_1.default, { funcss: "funui_products_grid grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 ".concat(gridClassName) }, currentProducts.map(function (product) { return (react_1.default.createElement(ProductCard_1.default, { key: product.id, product: product, currency: currency, onClick: function () { return openProductModal(product); }, onAddToCart: function () { return addToCart(product); }, showBadges: true })); })),
488
+ totalPages > 1 && (react_1.default.createElement(Flex_1.default, { width: '100%', justify: 'center', gap: 0.5 },
489
+ react_1.default.createElement(Button_1.default, { startIcon: react_1.default.createElement(pi_1.PiCaretLeft, null), onClick: function () { return goToPage(currentPage - 1); }, disabled: currentPage === 1, small: true, text: "Prev" }),
490
+ react_1.default.createElement(Div_1.default, { funcss: "pagination-numbers" },
491
+ Array.from({ length: Math.min(5, totalPages) }, function (_, i) {
492
+ var pageNum;
493
+ if (totalPages <= 5) {
494
+ pageNum = i + 1;
495
+ }
496
+ else if (currentPage <= 3) {
497
+ pageNum = i + 1;
498
+ }
499
+ else if (currentPage >= totalPages - 2) {
500
+ pageNum = totalPages - 4 + i;
501
+ }
502
+ else {
503
+ pageNum = currentPage - 2 + i;
504
+ }
505
+ return (react_1.default.createElement(Button_1.default, { key: pageNum, text: pageNum.toString(), onClick: function () { return goToPage(pageNum); }, bg: currentPage === pageNum ? 'primary' : undefined, color: currentPage === pageNum ? 'white' : 'text', small: true }));
506
+ }),
507
+ totalPages > 5 && currentPage < totalPages - 2 && (react_1.default.createElement(react_1.default.Fragment, null,
508
+ react_1.default.createElement(Text_1.default, { text: "...", color: "text-light" }),
509
+ react_1.default.createElement(Button_1.default, { text: totalPages.toString(), onClick: function () { return goToPage(totalPages); }, small: true })))),
510
+ react_1.default.createElement(Button_1.default, { endIcon: react_1.default.createElement(pi_1.PiCaretRight, null), onClick: function () { return goToPage(currentPage + 1); }, disabled: currentPage === totalPages, small: true, text: "Next" }))))),
511
+ children)),
512
+ showCart && (react_1.default.createElement(CartModal_1.default, { cart: cart, isOpen: isCartOpen, setIsOpen: setIsCartOpen, currency: currency, updateQuantity: updateQuantity, removeFromCart: removeFromCart, clearCart: clearCart, handleCheckout: handleCheckout, cartBadgeColor: cartBadgeColor, checkoutText: checkoutText, checkoutIcon: checkoutIcon, small: small, big: big, persistCart: persistCart })),
513
+ selectedProduct && (react_1.default.createElement(ProductDetail_1.default, { product: selectedProduct, open: isProductModalOpen, setOpen: setIsProductModalOpen, currency: currency, onAddToCart: handleAddFromModal }))));
514
+ };
515
+ exports.default = Store;
@@ -18,12 +18,14 @@ interface SideBarProps {
18
18
  sidebarCss?: string;
19
19
  activeCss?: string;
20
20
  iconCSS?: string;
21
+ accordionItemCss?: string;
21
22
  bodyCss?: string;
22
23
  popIcon?: boolean;
23
24
  dividers?: boolean;
24
25
  links?: SideBarLink[];
25
26
  children?: ReactNode;
26
27
  onClose?: () => void;
28
+ isAccordion?: boolean;
27
29
  }
28
- export default function SideBar({ funcss, position, open, header, content, footer, top, sidebarWidth, iconCSS, sidebarCss, activeCss, bodyCss, popIcon, dividers, links, children, onClose, }: SideBarProps): React.JSX.Element;
30
+ export default function SideBar({ funcss, position, open, header, content, footer, top, sidebarWidth, iconCSS, sidebarCss, activeCss, bodyCss, popIcon, dividers, accordionItemCss, links, children, onClose, isAccordion, }: SideBarProps): React.JSX.Element;
29
31
  export {};
@@ -44,16 +44,17 @@ var Text_1 = __importDefault(require("../text/Text"));
44
44
  var navigation_1 = require("next/navigation");
45
45
  var theme_1 = require("../theme/theme");
46
46
  var Button_1 = __importDefault(require("../button/Button"));
47
+ var Accordion_1 = __importDefault(require("../accordion/Accordion"));
47
48
  function SideBar(_a) {
48
49
  var _b;
49
- var _c = _a.funcss, funcss = _c === void 0 ? '' : _c, _d = _a.position, position = _d === void 0 ? 'left' : _d, _e = _a.open, open = _e === void 0 ? false : _e, header = _a.header, content = _a.content, footer = _a.footer, _f = _a.top, top = _f === void 0 ? 0 : _f, _g = _a.sidebarWidth, sidebarWidth = _g === void 0 ? 250 : _g, _h = _a.iconCSS, iconCSS = _h === void 0 ? '' : _h, _j = _a.sidebarCss, sidebarCss = _j === void 0 ? '' : _j, activeCss = _a.activeCss, _k = _a.bodyCss, bodyCss = _k === void 0 ? '' : _k, _l = _a.popIcon, popIcon = _l === void 0 ? false : _l, _m = _a.dividers, dividers = _m === void 0 ? false : _m, _o = _a.links, links = _o === void 0 ? [] : _o, children = _a.children, onClose = _a.onClose;
50
- var _p = (0, react_1.useState)(false), isMobile = _p[0], setIsMobile = _p[1];
51
- var _q = (0, react_1.useState)(open), internalOpen = _q[0], setInternalOpen = _q[1];
52
- var _r = (0, react_1.useState)('0px'), appBarHeight = _r[0], setAppBarHeight = _r[1];
50
+ var _c = _a.funcss, funcss = _c === void 0 ? '' : _c, _d = _a.position, position = _d === void 0 ? 'left' : _d, _e = _a.open, open = _e === void 0 ? false : _e, header = _a.header, content = _a.content, footer = _a.footer, _f = _a.top, top = _f === void 0 ? 0 : _f, _g = _a.sidebarWidth, sidebarWidth = _g === void 0 ? 250 : _g, _h = _a.iconCSS, iconCSS = _h === void 0 ? '' : _h, _j = _a.sidebarCss, sidebarCss = _j === void 0 ? '' : _j, activeCss = _a.activeCss, _k = _a.bodyCss, bodyCss = _k === void 0 ? '' : _k, _l = _a.popIcon, popIcon = _l === void 0 ? false : _l, _m = _a.dividers, dividers = _m === void 0 ? false : _m, accordionItemCss = _a.accordionItemCss, _o = _a.links, links = _o === void 0 ? [] : _o, children = _a.children, onClose = _a.onClose, _p = _a.isAccordion, isAccordion = _p === void 0 ? false : _p;
51
+ var _q = (0, react_1.useState)(false), isMobile = _q[0], setIsMobile = _q[1];
52
+ var _r = (0, react_1.useState)(open), internalOpen = _r[0], setInternalOpen = _r[1];
53
+ var _s = (0, react_1.useState)('0px'), appBarHeight = _s[0], setAppBarHeight = _s[1];
53
54
  var pathname = (0, navigation_1.usePathname)();
54
55
  var sidebarRef = (0, react_1.useRef)(null);
55
56
  var variant = (0, theme_1.useVariant)().variant;
56
- var _s = (0, react_1.useState)(""), selectedOption = _s[0], setselectedOption = _s[1];
57
+ var _t = (0, react_1.useState)(''), selectedOption = _t[0], setselectedOption = _t[1];
57
58
  var updateIsMobile = (0, react_1.useCallback)(function () {
58
59
  setIsMobile(window.innerWidth <= 992);
59
60
  }, []);
@@ -97,8 +98,42 @@ function SideBar(_a) {
97
98
  return acc;
98
99
  }, {});
99
100
  var isOverlay = isMobile;
101
+ // Prepare accordion items when isAccordion is true
102
+ var accordionItems = isAccordion
103
+ ? Object.entries(groupedLinks).map(function (_a) {
104
+ var _b;
105
+ var section = _a[0], sectionLinks = _a[1];
106
+ return ({
107
+ icon: (_b = sectionLinks[0]) === null || _b === void 0 ? void 0 : _b.icon,
108
+ title: section,
109
+ content: (react_1.default.createElement("div", { className: "sidebar-accordion-links" }, sectionLinks.map(function (link, index) {
110
+ var isActive = link.onClick
111
+ ? selectedOption === "".concat(section, "-").concat(index)
112
+ : pathname === link.uri;
113
+ return (react_1.default.createElement("div", { onClick: function () {
114
+ if (isMobile) {
115
+ handleClose();
116
+ }
117
+ if (link === null || link === void 0 ? void 0 : link.onClick) {
118
+ link.onClick();
119
+ setselectedOption("".concat(section, "-").concat(index));
120
+ }
121
+ else {
122
+ window.location.href = link.uri;
123
+ }
124
+ }, key: link.uri },
125
+ react_1.default.createElement(Button_1.default, { fullWidth: true, small: true, funcss: "sidebar-link ".concat(isActive ? "" : "p-0", " text-left ").concat(isActive ? "primary ".concat(activeCss || '') : 'hoverable'), startIcon: react_1.default.createElement("span", { className: "".concat(iconCSS || '', " ").concat(variant === 'standard' || popIcon
126
+ ? "p-1 ".concat(isActive ? 'primary' : 'lighter text-primary border', " central")
127
+ : variant === 'minimal' && !isActive
128
+ ? 'p-1 central lighter text-primary'
129
+ : ''), style: { lineHeight: 0, borderRadius: '0.4rem' } }, link.icon) },
130
+ react_1.default.createElement(Text_1.default, { text: link.text, size: "sm", weight: 400 }))));
131
+ }))),
132
+ });
133
+ })
134
+ : [];
100
135
  return (react_1.default.createElement("div", { className: "sidebar-container ".concat(isOverlay ? '' : 'with-content') },
101
- internalOpen && (react_1.default.createElement("aside", { role: "complementary", ref: sidebarRef, className: "sidebar ".concat(funcss, " ").concat(sidebarCss, " ").concat(isOverlay ? 'nav_overlay' : ''), style: (_b = {
136
+ internalOpen && (react_1.default.createElement("aside", { role: "complementary", ref: sidebarRef, className: "sidebar ".concat(funcss, " ").concat(sidebarCss, " ").concat(isOverlay ? 'nav_overlay' : ''), style: (_b = {
102
137
  width: isOverlay ? '100%' : "".concat(sidebarWidth, "px"),
103
138
  height: "calc(100vh - ".concat(appBarHeight || top || '0px', ")"),
104
139
  position: 'fixed',
@@ -109,10 +144,10 @@ function SideBar(_a) {
109
144
  _b) },
110
145
  react_1.default.createElement(RowFlex_1.default, { justify: "space-between", funcss: "pl-2 pr-2" }, header && react_1.default.createElement("div", null, header)),
111
146
  react_1.default.createElement("section", { className: "sidebar-body mt-3" },
112
- links.length > 0 && (react_1.default.createElement("nav", { className: "sidebar-links" }, Object.entries(groupedLinks).map(function (_a) {
147
+ links.length > 0 && (react_1.default.createElement("nav", { className: "sidebar-links" }, isAccordion ? (react_1.default.createElement(Accordion_1.default, { itemClass: accordionItemCss, items: accordionItems, allowMultiple: false, contentClass: "", titleClass: 'text-sm', activeClass: "" })) : (Object.entries(groupedLinks).map(function (_a) {
113
148
  var section = _a[0], sectionLinks = _a[1];
114
- return (react_1.default.createElement("div", { key: section, className: "sidebar-section ".concat(dividers ? "bt" : "", " pt-2 pb-2") },
115
- react_1.default.createElement(Text_1.default, { size: "sm", funcss: "opacity-6 p-1 pl-2 pr-2" }, section),
149
+ return (react_1.default.createElement("div", { key: section, className: "sidebar-section ".concat(dividers ? 'bt' : '', " pt-2 pb-2") },
150
+ react_1.default.createElement(Text_1.default, { size: "sm" }, section),
116
151
  sectionLinks.map(function (link, index) {
117
152
  var isActive = link.onClick
118
153
  ? selectedOption === "".concat(section, "-").concat(index)
@@ -129,10 +164,14 @@ function SideBar(_a) {
129
164
  window.location.href = link.uri;
130
165
  }
131
166
  }, key: link.uri },
132
- react_1.default.createElement(Button_1.default, { fullWidth: true, small: true, funcss: "p-1 pl-2 pr-2 sidebar-link text-left ".concat(isActive ? "primary ".concat(activeCss || '') : 'hoverable'), startIcon: react_1.default.createElement("span", { className: "".concat(iconCSS || '', " \n ").concat((variant === 'standard' || popIcon) ? "p-1 ".concat(isActive ? "primary" : "lighter text-primary border", " central") : (variant === "minimal" && !isActive) ? "p-1 central lighter text-primary" : ""), style: { lineHeight: 0, borderRadius: "0.4rem" } }, link.icon) },
167
+ react_1.default.createElement(Button_1.default, { fullWidth: true, small: true, funcss: "sidebar-link text-left ".concat(isActive ? "primary ".concat(activeCss || '') : 'hoverable'), startIcon: react_1.default.createElement("span", { className: "".concat(iconCSS || '', " ").concat(variant === 'standard' || popIcon
168
+ ? "p-1 ".concat(isActive ? 'primary' : 'lighter text-primary border', " central")
169
+ : variant === 'minimal' && !isActive
170
+ ? 'p-1 central lighter text-primary'
171
+ : ''), style: { lineHeight: 0, borderRadius: '0.4rem' } }, link.icon) },
133
172
  react_1.default.createElement(Text_1.default, { text: link.text, size: "sm", weight: 400 }))));
134
173
  })));
135
- }))),
174
+ })))),
136
175
  content),
137
176
  footer && react_1.default.createElement("footer", { className: "sidebar-footer mt-2" }, footer))),
138
177
  react_1.default.createElement("main", { className: "main-content ".concat(bodyCss), style: {
@@ -11,8 +11,9 @@ interface Circle_Props extends HTMLProps<HTMLDivElement> {
11
11
  raised?: boolean;
12
12
  bordered?: boolean;
13
13
  key?: React.Key;
14
+ body?: ReactNode;
14
15
  style?: React.CSSProperties;
15
16
  onClick?: () => void;
16
17
  }
17
- export default function Circle({ size, funcss, bg, color, children, hoverable, raised, key, onClick, className, bordered, style, ...rest }: Circle_Props): React.JSX.Element;
18
+ export default function Circle({ size, funcss, bg, color, children, hoverable, raised, key, onClick, className, bordered, body, style, ...rest }: Circle_Props): React.JSX.Element;
18
19
  export {};