funuicss 3.8.8 → 3.8.10
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 +311 -1
- package/index.d.ts +2 -0
- package/index.js +6 -2
- package/package.json +1 -1
- package/ui/button/Button.d.ts +4 -4
- package/ui/button/Button.js +187 -82
- package/ui/carousel/Carousel.d.ts +3 -0
- package/ui/carousel/Carousel.js +140 -16
- package/ui/feature/Feature.d.ts +26 -39
- package/ui/feature/Feature.js +87 -148
- package/ui/flex/Flex.d.ts +11 -10
- package/ui/flex/Flex.js +102 -6
- package/ui/form/Form.d.ts +21 -12
- package/ui/form/Form.js +428 -319
- package/ui/input/Input.d.ts +16 -21
- package/ui/input/Input.js +156 -1345
- package/ui/notification/Notification.js +6 -2
- package/ui/products/ProductDetail.js +31 -23
- package/ui/products/Store.js +5 -5
- package/ui/sidebar/SideBar.js +1 -2
- package/ui/specials/CircleGroup.d.ts +2 -1
- package/ui/specials/CircleGroup.js +3 -3
package/ui/button/Button.js
CHANGED
|
@@ -99,75 +99,170 @@ function Button(_a) {
|
|
|
99
99
|
stringPrefix: stringPrefix !== null && stringPrefix !== void 0 ? stringPrefix : mergedProps.stringPrefix,
|
|
100
100
|
stringSuffix: stringSuffix !== null && stringSuffix !== void 0 ? stringSuffix : mergedProps.stringSuffix,
|
|
101
101
|
};
|
|
102
|
-
|
|
103
|
-
var
|
|
104
|
-
var
|
|
105
|
-
var
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
//
|
|
102
|
+
// State for dynamic icons
|
|
103
|
+
var _g = (0, react_1.useState)(null), dynamicStartIcon = _g[0], setDynamicStartIcon = _g[1];
|
|
104
|
+
var _h = (0, react_1.useState)(null), dynamicEndIcon = _h[0], setDynamicEndIcon = _h[1];
|
|
105
|
+
var _j = (0, react_1.useState)(null), dynamicPrefix = _j[0], setDynamicPrefix = _j[1];
|
|
106
|
+
var _k = (0, react_1.useState)(null), dynamicSuffix = _k[0], setDynamicSuffix = _k[1];
|
|
107
|
+
var _l = (0, react_1.useState)(null), dynamicStringPrefix = _l[0], setDynamicStringPrefix = _l[1];
|
|
108
|
+
var _m = (0, react_1.useState)(null), dynamicStringSuffix = _m[0], setDynamicStringSuffix = _m[1];
|
|
109
|
+
// Function to check if a value is a string (dynamic icon)
|
|
110
|
+
var isStringIcon = function (icon) {
|
|
111
|
+
return typeof icon === 'string' && icon.trim() !== '';
|
|
112
|
+
};
|
|
113
|
+
// Function to check if a value is a ReactNode (static icon)
|
|
114
|
+
var isReactNodeIcon = function (icon) {
|
|
115
|
+
return icon !== undefined && !isStringIcon(icon) && react_1.default.isValidElement(icon);
|
|
116
|
+
};
|
|
117
|
+
// Load dynamic icons from string props
|
|
110
118
|
(0, react_1.useEffect)(function () {
|
|
111
|
-
|
|
112
|
-
if (
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
119
|
+
// Handle startIcon if it's a string
|
|
120
|
+
if (isStringIcon(startIcon)) {
|
|
121
|
+
(0, getDynamicIcon_1.getDynamicIcon)(startIcon).then(function (node) {
|
|
122
|
+
if (node) {
|
|
123
|
+
setDynamicStartIcon(node);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
setDynamicStartIcon(null);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
setDynamicStartIcon(null);
|
|
132
|
+
}
|
|
133
|
+
// Handle endIcon if it's a string
|
|
134
|
+
if (isStringIcon(endIcon)) {
|
|
135
|
+
(0, getDynamicIcon_1.getDynamicIcon)(endIcon).then(function (node) {
|
|
136
|
+
if (node) {
|
|
137
|
+
setDynamicEndIcon(node);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
setDynamicEndIcon(null);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
setDynamicEndIcon(null);
|
|
146
|
+
}
|
|
147
|
+
// Handle prefix if it's a string
|
|
148
|
+
if (isStringIcon(prefix)) {
|
|
149
|
+
(0, getDynamicIcon_1.getDynamicIcon)(prefix).then(function (node) {
|
|
150
|
+
if (node) {
|
|
151
|
+
setDynamicPrefix(node);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
setDynamicPrefix(null);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
setDynamicPrefix(null);
|
|
160
|
+
}
|
|
161
|
+
// Handle suffix if it's a string
|
|
162
|
+
if (isStringIcon(suffix)) {
|
|
163
|
+
(0, getDynamicIcon_1.getDynamicIcon)(suffix).then(function (node) {
|
|
164
|
+
if (node) {
|
|
165
|
+
setDynamicSuffix(node);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
setDynamicSuffix(null);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
setDynamicSuffix(null);
|
|
174
|
+
}
|
|
175
|
+
}, [startIcon, endIcon, prefix, suffix]);
|
|
176
|
+
// Load dynamic icons from stringPrefix and stringSuffix (backward compatibility)
|
|
129
177
|
(0, react_1.useEffect)(function () {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
178
|
+
if (final.stringPrefix && final.stringPrefix.trim() !== '') {
|
|
179
|
+
(0, getDynamicIcon_1.getDynamicIcon)(final.stringPrefix).then(function (node) {
|
|
180
|
+
if (node) {
|
|
181
|
+
setDynamicStringPrefix(node);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
setDynamicStringPrefix(null);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
setDynamicStringPrefix(null);
|
|
190
|
+
}
|
|
191
|
+
if (final.stringSuffix && final.stringSuffix.trim() !== '') {
|
|
192
|
+
(0, getDynamicIcon_1.getDynamicIcon)(final.stringSuffix).then(function (node) {
|
|
193
|
+
if (node) {
|
|
194
|
+
setDynamicStringSuffix(node);
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
setDynamicStringSuffix(null);
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
setDynamicStringSuffix(null);
|
|
203
|
+
}
|
|
204
|
+
}, [final.stringPrefix, final.stringSuffix]);
|
|
205
|
+
// Determine which start icon to show with proper priority
|
|
206
|
+
var actualStartIcon = (0, react_1.useMemo)(function () {
|
|
207
|
+
if (final.status) {
|
|
208
|
+
// Status icons have highest priority for start position
|
|
209
|
+
switch (final.status) {
|
|
210
|
+
case 'success':
|
|
211
|
+
return react_1.default.createElement(pi_1.PiCheck, { size: iconSize });
|
|
212
|
+
case 'info':
|
|
213
|
+
return react_1.default.createElement(pi_1.PiInfo, { size: iconSize });
|
|
214
|
+
case 'warning':
|
|
215
|
+
return react_1.default.createElement(pi_1.PiWarning, { size: iconSize });
|
|
216
|
+
case 'error':
|
|
217
|
+
return react_1.default.createElement(pi_1.PiX, { size: iconSize });
|
|
218
|
+
default:
|
|
219
|
+
return null;
|
|
144
220
|
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if (
|
|
153
|
-
return
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
221
|
+
}
|
|
222
|
+
if (isStringIcon(startIcon)) {
|
|
223
|
+
return dynamicStartIcon;
|
|
224
|
+
}
|
|
225
|
+
if (isReactNodeIcon(startIcon)) {
|
|
226
|
+
return startIcon;
|
|
227
|
+
}
|
|
228
|
+
if (isStringIcon(prefix)) {
|
|
229
|
+
return dynamicPrefix;
|
|
230
|
+
}
|
|
231
|
+
if (isReactNodeIcon(prefix)) {
|
|
232
|
+
return prefix;
|
|
233
|
+
}
|
|
234
|
+
if (dynamicStringPrefix) {
|
|
235
|
+
return dynamicStringPrefix;
|
|
236
|
+
}
|
|
237
|
+
return null;
|
|
238
|
+
}, [
|
|
239
|
+
final.status,
|
|
240
|
+
startIcon,
|
|
241
|
+
prefix,
|
|
242
|
+
dynamicStartIcon,
|
|
243
|
+
dynamicPrefix,
|
|
244
|
+
dynamicStringPrefix,
|
|
245
|
+
iconSize,
|
|
246
|
+
]);
|
|
247
|
+
// Determine which end icon to show with proper priority
|
|
248
|
+
var actualEndIcon = (0, react_1.useMemo)(function () {
|
|
249
|
+
if (isStringIcon(endIcon)) {
|
|
250
|
+
return dynamicEndIcon;
|
|
251
|
+
}
|
|
252
|
+
if (isReactNodeIcon(endIcon)) {
|
|
253
|
+
return endIcon;
|
|
254
|
+
}
|
|
255
|
+
if (isStringIcon(suffix)) {
|
|
256
|
+
return dynamicSuffix;
|
|
257
|
+
}
|
|
258
|
+
if (isReactNodeIcon(suffix)) {
|
|
259
|
+
return suffix;
|
|
260
|
+
}
|
|
261
|
+
if (dynamicStringSuffix) {
|
|
262
|
+
return dynamicStringSuffix;
|
|
263
|
+
}
|
|
264
|
+
return null;
|
|
265
|
+
}, [endIcon, suffix, dynamicEndIcon, dynamicSuffix, dynamicStringSuffix]);
|
|
171
266
|
var textColorClass = final.bg
|
|
172
267
|
? final.color
|
|
173
268
|
? final.color
|
|
@@ -208,27 +303,37 @@ function Button(_a) {
|
|
|
208
303
|
};
|
|
209
304
|
// Helper function to render icon with proper size
|
|
210
305
|
var renderIcon = function (icon, className) {
|
|
306
|
+
var _a;
|
|
211
307
|
if (className === void 0) { className = ''; }
|
|
212
308
|
if (!icon)
|
|
213
309
|
return null;
|
|
214
|
-
|
|
310
|
+
// If it's a React element that we know accepts size prop
|
|
311
|
+
if (react_1.default.isValidElement(icon)) {
|
|
312
|
+
// Create a wrapper span and clone the icon with size prop if needed
|
|
313
|
+
var iconProps = {};
|
|
314
|
+
// Only add size prop if iconSize is provided and not already set
|
|
315
|
+
if (iconSize && !((_a = icon.props) === null || _a === void 0 ? void 0 : _a.size)) {
|
|
316
|
+
iconProps.size = iconSize;
|
|
317
|
+
}
|
|
318
|
+
// Only clone with props if we have props to add
|
|
319
|
+
if (Object.keys(iconProps).length > 0) {
|
|
320
|
+
return (react_1.default.createElement("span", { className: className, style: iconWrapperStyle }, react_1.default.cloneElement(icon, iconProps)));
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
// Otherwise just render the icon in a span
|
|
324
|
+
return (react_1.default.createElement("span", { className: className, style: iconWrapperStyle }, icon));
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
// If it's not a valid React element, just render it as is
|
|
328
|
+
return (react_1.default.createElement("span", { className: className, style: iconWrapperStyle }, icon));
|
|
215
329
|
};
|
|
330
|
+
// Determine if we should show icons on left or right
|
|
331
|
+
var hasStartIcon = Boolean(actualStartIcon);
|
|
332
|
+
var hasEndIcon = Boolean(actualEndIcon);
|
|
216
333
|
return (react_1.default.createElement("span", null,
|
|
217
|
-
react_1.default.createElement("button", __assign({ type: final.type || 'button', disabled: disabled || final.isLoading || false, className: "".concat(classNames, " ").concat((
|
|
218
|
-
final.isLoading ? (renderIcon(react_1.default.createElement(pi_1.PiSpinner, { className: "rotate" }), 'btn_left_icon')) : (react_1.default.createElement(react_1.default.Fragment, null,
|
|
219
|
-
final.status && (react_1.default.createElement("span", { className: "btn_left_icon", style: iconWrapperStyle },
|
|
220
|
-
final.status === 'success' && react_1.default.createElement(pi_1.PiCheck, { size: iconSize }),
|
|
221
|
-
final.status === 'info' && react_1.default.createElement(pi_1.PiInfo, { size: iconSize }),
|
|
222
|
-
final.status === 'warning' && react_1.default.createElement(pi_1.PiWarning, { size: iconSize }),
|
|
223
|
-
final.status === 'error' && react_1.default.createElement(pi_1.PiX, { size: iconSize }))),
|
|
224
|
-
!final.status && showPrefix && (react_1.default.createElement(react_1.default.Fragment, null,
|
|
225
|
-
startIcon && renderIcon(startIcon, 'btn_left_icon'),
|
|
226
|
-
!startIcon && prefix && renderIcon(prefix, 'btn_left_icon'),
|
|
227
|
-
!startIcon && !prefix && hasValidStringPrefix && renderIcon(prefixNode, 'btn_left_icon'))))),
|
|
334
|
+
react_1.default.createElement("button", __assign({ type: final.type || 'button', disabled: disabled || final.isLoading || false, className: "".concat(classNames, " ").concat((hasStartIcon || hasEndIcon || final.isLoading) ? 'iconic' : ''), style: __assign({ height: (_b = height !== null && height !== void 0 ? height : mergedProps.height) !== null && _b !== void 0 ? _b : '', width: final.fullWidth ? '100%' : (_c = width !== null && width !== void 0 ? width : mergedProps.width) !== null && _c !== void 0 ? _c : '', borderRadius: final.flat ? '0rem' : '' }, style), onClick: onClick || (url ? function () { return (window.location.href = url); } : undefined) }, mergedProps),
|
|
335
|
+
final.isLoading ? (renderIcon(react_1.default.createElement(pi_1.PiSpinner, { className: "rotate" }), 'btn_left_icon')) : (react_1.default.createElement(react_1.default.Fragment, null, hasStartIcon && renderIcon(actualStartIcon, 'btn_left_icon'))),
|
|
228
336
|
final.fillAnimation && react_1.default.createElement("span", { className: "button_fill_span ".concat(effectiveBg) }),
|
|
229
337
|
children ? children : final.text ? final.text : "",
|
|
230
|
-
|
|
231
|
-
endIcon && renderIcon(endIcon, 'btn_right_icon'),
|
|
232
|
-
!endIcon && suffix && renderIcon(suffix, 'btn_right_icon'),
|
|
233
|
-
!endIcon && !suffix && hasValidStringSuffix && renderIcon(suffixNode, 'btn_right_icon'))))));
|
|
338
|
+
hasEndIcon && !final.isLoading && renderIcon(actualEndIcon, 'btn_right_icon'))));
|
|
234
339
|
}
|
|
@@ -9,6 +9,9 @@ interface CarouselProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
9
9
|
itemPadding?: string;
|
|
10
10
|
controlerSize?: number;
|
|
11
11
|
controlerIconSize?: number;
|
|
12
|
+
infiniteScroll?: boolean;
|
|
13
|
+
infiniteScrollSpeed?: number;
|
|
14
|
+
infiniteScrollDirection?: 'left' | 'right' | 'alternate';
|
|
12
15
|
}
|
|
13
16
|
declare const Carousel: React.FC<CarouselProps>;
|
|
14
17
|
export default Carousel;
|
package/ui/carousel/Carousel.js
CHANGED
|
@@ -65,11 +65,17 @@ var Circle_1 = __importDefault(require("../specials/Circle"));
|
|
|
65
65
|
var RowFlex_1 = __importDefault(require("../specials/RowFlex"));
|
|
66
66
|
var Functions_1 = require("../../utils/Functions");
|
|
67
67
|
var Carousel = function (_a) {
|
|
68
|
-
var _b = _a.scrollNumber, scrollNumber = _b === void 0 ? 320 : _b, _c = _a.gap, gap = _c === void 0 ? 0.5 : _c, _d = _a.funcss, funcss = _d === void 0 ? '' : _d, _e = _a.showDashes, showDashes = _e === void 0 ? true : _e, _f = _a.allowVerticalOverflow, allowVerticalOverflow = _f === void 0 ? false : _f, _g = _a.itemPadding, itemPadding = _g === void 0 ? '0rem' : _g, children = _a.children, _h = _a.controlerSize, controlerSize = _h === void 0 ? 2.5 : _h, _j = _a.controlerIconSize, controlerIconSize = _j === void 0 ? 20 : _j, rest = __rest(_a, ["scrollNumber", "gap", "funcss", "showDashes", "allowVerticalOverflow", "itemPadding", "children", "controlerSize", "controlerIconSize"]);
|
|
68
|
+
var _b = _a.scrollNumber, scrollNumber = _b === void 0 ? 320 : _b, _c = _a.gap, gap = _c === void 0 ? 0.5 : _c, _d = _a.funcss, funcss = _d === void 0 ? '' : _d, _e = _a.showDashes, showDashes = _e === void 0 ? true : _e, _f = _a.allowVerticalOverflow, allowVerticalOverflow = _f === void 0 ? false : _f, _g = _a.itemPadding, itemPadding = _g === void 0 ? '0rem' : _g, children = _a.children, _h = _a.controlerSize, controlerSize = _h === void 0 ? 2.5 : _h, _j = _a.controlerIconSize, controlerIconSize = _j === void 0 ? 20 : _j, _k = _a.infiniteScroll, infiniteScroll = _k === void 0 ? false : _k, _l = _a.infiniteScrollSpeed, infiniteScrollSpeed = _l === void 0 ? 50 : _l, _m = _a.infiniteScrollDirection, infiniteScrollDirection = _m === void 0 ? 'left' : _m, rest = __rest(_a, ["scrollNumber", "gap", "funcss", "showDashes", "allowVerticalOverflow", "itemPadding", "children", "controlerSize", "controlerIconSize", "infiniteScroll", "infiniteScrollSpeed", "infiniteScrollDirection"]);
|
|
69
69
|
var scrollRef = (0, react_1.useRef)(null);
|
|
70
|
-
var
|
|
71
|
-
var
|
|
72
|
-
var
|
|
70
|
+
var containerRef = (0, react_1.useRef)(null);
|
|
71
|
+
var _o = (0, react_1.useState)('start'), scrollPosition = _o[0], setScrollPosition = _o[1];
|
|
72
|
+
var _p = (0, react_1.useState)(false), isPhone = _p[0], setIsPhone = _p[1];
|
|
73
|
+
var _q = (0, react_1.useState)(false), isScrollable = _q[0], setIsScrollable = _q[1];
|
|
74
|
+
var _r = (0, react_1.useState)(infiniteScrollDirection === 'right' ? 'right' : 'left'), autoScrollDirection = _r[0], setAutoScrollDirection = _r[1];
|
|
75
|
+
var _s = (0, react_1.useState)(false), isHovered = _s[0], setIsHovered = _s[1];
|
|
76
|
+
var animationRef = (0, react_1.useRef)(null);
|
|
77
|
+
var lastScrollTimeRef = (0, react_1.useRef)(0);
|
|
78
|
+
var isProgrammaticScrollRef = (0, react_1.useRef)(false);
|
|
73
79
|
var checkScrollable = function () {
|
|
74
80
|
var container = scrollRef.current;
|
|
75
81
|
if (container) {
|
|
@@ -78,7 +84,7 @@ var Carousel = function (_a) {
|
|
|
78
84
|
};
|
|
79
85
|
(0, react_1.useEffect)(function () {
|
|
80
86
|
checkScrollable();
|
|
81
|
-
window.addEventListener('resize', checkScrollable);
|
|
87
|
+
window.addEventListener('resize', checkScrollable);
|
|
82
88
|
return function () { return window.removeEventListener('resize', checkScrollable); };
|
|
83
89
|
}, [children]);
|
|
84
90
|
(0, react_1.useEffect)(function () {
|
|
@@ -89,8 +95,11 @@ var Carousel = function (_a) {
|
|
|
89
95
|
setIsPhone(false);
|
|
90
96
|
}
|
|
91
97
|
}, []);
|
|
92
|
-
// Track scroll position
|
|
93
98
|
var handleScroll = function () {
|
|
99
|
+
if (isProgrammaticScrollRef.current) {
|
|
100
|
+
isProgrammaticScrollRef.current = false;
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
94
103
|
var container = scrollRef.current;
|
|
95
104
|
if (!container)
|
|
96
105
|
return;
|
|
@@ -105,6 +114,7 @@ var Carousel = function (_a) {
|
|
|
105
114
|
else {
|
|
106
115
|
setScrollPosition('middle');
|
|
107
116
|
}
|
|
117
|
+
lastScrollTimeRef.current = Date.now();
|
|
108
118
|
};
|
|
109
119
|
var scroll = function (direction) {
|
|
110
120
|
var container = scrollRef.current;
|
|
@@ -115,6 +125,57 @@ var Carousel = function (_a) {
|
|
|
115
125
|
behavior: 'smooth',
|
|
116
126
|
});
|
|
117
127
|
};
|
|
128
|
+
var infiniteScrollAnimation = function () {
|
|
129
|
+
if (!infiniteScroll || !scrollRef.current || isHovered || !isScrollable) {
|
|
130
|
+
if (animationRef.current) {
|
|
131
|
+
cancelAnimationFrame(animationRef.current);
|
|
132
|
+
animationRef.current = null;
|
|
133
|
+
}
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
var container = scrollRef.current;
|
|
137
|
+
var scrollLeft = container.scrollLeft, scrollWidth = container.scrollWidth, clientWidth = container.clientWidth;
|
|
138
|
+
var maxScrollLeft = scrollWidth - clientWidth;
|
|
139
|
+
var newDirection = autoScrollDirection;
|
|
140
|
+
if (infiniteScrollDirection === 'alternate') {
|
|
141
|
+
if (scrollLeft <= 0) {
|
|
142
|
+
newDirection = 'right';
|
|
143
|
+
setAutoScrollDirection('right');
|
|
144
|
+
}
|
|
145
|
+
else if (scrollLeft >= maxScrollLeft - 1) {
|
|
146
|
+
newDirection = 'left';
|
|
147
|
+
setAutoScrollDirection('left');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
var scrollAmount = infiniteScrollSpeed / 60;
|
|
151
|
+
isProgrammaticScrollRef.current = true;
|
|
152
|
+
if (newDirection === 'left') {
|
|
153
|
+
container.scrollLeft -= scrollAmount;
|
|
154
|
+
if (scrollLeft <= 0 && infiniteScrollDirection !== 'alternate') {
|
|
155
|
+
container.scrollLeft = maxScrollLeft;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
container.scrollLeft += scrollAmount;
|
|
160
|
+
if (scrollLeft >= maxScrollLeft - 1 && infiniteScrollDirection !== 'alternate') {
|
|
161
|
+
container.scrollLeft = 0;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
animationRef.current = requestAnimationFrame(infiniteScrollAnimation);
|
|
165
|
+
};
|
|
166
|
+
(0, react_1.useEffect)(function () {
|
|
167
|
+
if (infiniteScroll) {
|
|
168
|
+
infiniteScrollAnimation();
|
|
169
|
+
}
|
|
170
|
+
return function () {
|
|
171
|
+
if (animationRef.current) {
|
|
172
|
+
cancelAnimationFrame(animationRef.current);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
}, [infiniteScroll, infiniteScrollSpeed, infiniteScrollDirection, isHovered, isScrollable, autoScrollDirection]);
|
|
176
|
+
(0, react_1.useEffect)(function () {
|
|
177
|
+
setAutoScrollDirection(infiniteScrollDirection === 'right' ? 'right' : 'left');
|
|
178
|
+
}, [infiniteScrollDirection]);
|
|
118
179
|
(0, react_1.useEffect)(function () {
|
|
119
180
|
var container = scrollRef.current;
|
|
120
181
|
if (container) {
|
|
@@ -122,9 +183,54 @@ var Carousel = function (_a) {
|
|
|
122
183
|
return function () { return container.removeEventListener('scroll', handleScroll); };
|
|
123
184
|
}
|
|
124
185
|
}, []);
|
|
125
|
-
|
|
186
|
+
var cloneChildren = function () {
|
|
187
|
+
var childrenArray = react_1.default.Children.toArray(children);
|
|
188
|
+
if (childrenArray.length === 0)
|
|
189
|
+
return children;
|
|
190
|
+
// Clone enough items to create a seamless infinite effect
|
|
191
|
+
// We need enough clones to fill at least 3 times the viewport width
|
|
192
|
+
var container = scrollRef.current;
|
|
193
|
+
var clonesNeeded = container ? Math.ceil(container.clientWidth * 3 / (scrollNumber || 320)) : 3;
|
|
194
|
+
var clonedItems = [];
|
|
195
|
+
for (var i = 0; i < clonesNeeded; i++) {
|
|
196
|
+
clonedItems.push.apply(clonedItems, childrenArray);
|
|
197
|
+
}
|
|
198
|
+
return (react_1.default.createElement(react_1.default.Fragment, null, clonedItems.map(function (child, index) { return (react_1.default.createElement("div", { key: index, className: "carousel-item", style: { flexShrink: 0 } },
|
|
199
|
+
react_1.default.createElement("div", { className: "carousel-card" }, child))); })));
|
|
200
|
+
};
|
|
201
|
+
var handleMouseEnter = function () {
|
|
202
|
+
setIsHovered(true);
|
|
203
|
+
if (animationRef.current) {
|
|
204
|
+
cancelAnimationFrame(animationRef.current);
|
|
205
|
+
animationRef.current = null;
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
var handleMouseLeave = function () {
|
|
209
|
+
setIsHovered(false);
|
|
210
|
+
if (infiniteScroll && !isHovered) {
|
|
211
|
+
infiniteScrollAnimation();
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
// Handle touch events for mobile
|
|
215
|
+
var handleTouchStart = function () {
|
|
216
|
+
setIsHovered(true);
|
|
217
|
+
if (animationRef.current) {
|
|
218
|
+
cancelAnimationFrame(animationRef.current);
|
|
219
|
+
animationRef.current = null;
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
var handleTouchEnd = function () {
|
|
223
|
+
// Wait a bit before resuming to allow user to interact
|
|
224
|
+
setTimeout(function () {
|
|
225
|
+
setIsHovered(false);
|
|
226
|
+
if (infiniteScroll && !isHovered) {
|
|
227
|
+
infiniteScrollAnimation();
|
|
228
|
+
}
|
|
229
|
+
}, 1000); // Resume after 1 second of inactivity
|
|
230
|
+
};
|
|
231
|
+
return (react_1.default.createElement("div", __assign({ ref: containerRef, className: "carousel-wrapper ".concat(funcss), onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onTouchStart: handleTouchStart, onTouchEnd: handleTouchEnd }, rest),
|
|
126
232
|
react_1.default.createElement(react_1.default.Fragment, null,
|
|
127
|
-
!isPhone && isScrollable && (react_1.default.createElement("div", { className: 'carouselLeft' },
|
|
233
|
+
!isPhone && isScrollable && !infiniteScroll && (react_1.default.createElement("div", { className: 'carouselLeft' },
|
|
128
234
|
react_1.default.createElement(Circle_1.default, { bordered: true, size: controlerSize, onClick: function () { return scroll('left'); } },
|
|
129
235
|
react_1.default.createElement(pi_1.PiCaretLeft, { className: 'text-primary', size: controlerIconSize })))),
|
|
130
236
|
react_1.default.createElement("div", { ref: scrollRef, className: "carousel-container scrollbar-hide w-full", style: {
|
|
@@ -134,16 +240,17 @@ var Carousel = function (_a) {
|
|
|
134
240
|
overflowY: 'visible',
|
|
135
241
|
display: 'flex',
|
|
136
242
|
justifyItems: (isScrollable || isPhone) ? 'flex-start' : 'center',
|
|
137
|
-
scrollSnapType: 'x mandatory',
|
|
243
|
+
scrollSnapType: infiniteScroll ? 'none' : 'x mandatory',
|
|
138
244
|
scrollBehavior: 'smooth',
|
|
139
|
-
padding: itemPadding || "0.5rem"
|
|
140
|
-
|
|
141
|
-
react_1.default.createElement("div", { className: "carousel-
|
|
142
|
-
|
|
245
|
+
padding: itemPadding || "0.5rem",
|
|
246
|
+
cursor: infiniteScroll ? 'grab' : 'default'
|
|
247
|
+
}, onMouseDown: function () { return infiniteScroll && handleMouseEnter(); }, onMouseUp: function () { return infiniteScroll && handleMouseLeave(); }, onScroll: handleScroll }, infiniteScroll ? cloneChildren() : (react_1.default.Children.map(children, function (child, index) { return (react_1.default.createElement("div", { className: "carousel-item", style: { flexShrink: 0 } },
|
|
248
|
+
react_1.default.createElement("div", { className: "carousel-card" }, child))); }))),
|
|
249
|
+
!isPhone && isScrollable && !infiniteScroll && (react_1.default.createElement("div", { className: 'carouselRight' },
|
|
143
250
|
react_1.default.createElement(Circle_1.default, { bordered: true, size: controlerSize, onClick: function () { return scroll('right'); } },
|
|
144
251
|
react_1.default.createElement(pi_1.PiCaretRight, { className: 'text-primary', size: controlerIconSize }))))),
|
|
145
|
-
(showDashes && isScrollable) && (react_1.default.createElement("div", { className: "center padding-top-10" },
|
|
146
|
-
react_1.default.createElement(RowFlex_1.default, { gap: 0.5, justify: "center" }, ['start', 'middle', 'end'].map(function (pos) { return (react_1.default.createElement("div", { className: 'pointer
|
|
252
|
+
(showDashes && isScrollable && !infiniteScroll) && (react_1.default.createElement("div", { className: "center padding-top-10" },
|
|
253
|
+
react_1.default.createElement(RowFlex_1.default, { gap: 0.5, justify: "center" }, ['start', 'middle', 'end'].map(function (pos) { return (react_1.default.createElement("div", { className: 'pointer', key: pos, onClick: function () {
|
|
147
254
|
var _a, _b;
|
|
148
255
|
if (pos === 'start') {
|
|
149
256
|
scroll('left');
|
|
@@ -164,6 +271,23 @@ var Carousel = function (_a) {
|
|
|
164
271
|
borderRadius: '50%',
|
|
165
272
|
transform: scrollPosition === pos ? 'scale(1.3)' : 'scale(0.9)',
|
|
166
273
|
transition: 'transform 0.3s ease, background 0.3s ease',
|
|
167
|
-
} })); }))))
|
|
274
|
+
} })); })))),
|
|
275
|
+
infiniteScroll && isHovered && (react_1.default.createElement("div", { style: {
|
|
276
|
+
position: 'absolute',
|
|
277
|
+
top: '50%',
|
|
278
|
+
left: '50%',
|
|
279
|
+
transform: 'translate(-50%, -50%)',
|
|
280
|
+
background: 'rgba(0,0,0,0.7)',
|
|
281
|
+
color: 'white',
|
|
282
|
+
padding: '5px 10px',
|
|
283
|
+
borderRadius: '5px',
|
|
284
|
+
fontSize: '12px',
|
|
285
|
+
zIndex: 10,
|
|
286
|
+
pointerEvents: 'none',
|
|
287
|
+
opacity: 0,
|
|
288
|
+
animation: 'fadeInOut 2s ease'
|
|
289
|
+
} },
|
|
290
|
+
"Scroll paused",
|
|
291
|
+
react_1.default.createElement("style", null, "\n @keyframes fadeInOut {\n 0% { opacity: 0; }\n 10% { opacity: 1; }\n 90% { opacity: 1; }\n 100% { opacity: 0; }\n }\n ")))));
|
|
168
292
|
};
|
|
169
293
|
exports.default = Carousel;
|