@via-profit/ui-kit 0.2.1-alpha.3 → 0.2.3

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.
Files changed (42) hide show
  1. package/Autocomplete/AutocompleteContainer.d.ts +5 -4
  2. package/Autocomplete/AutocompleteContainer.js +146 -152
  3. package/Autocomplete/AutocompleteItem.js +1 -1
  4. package/Autocomplete/context.d.ts +3 -5
  5. package/Autocomplete/context.js +22 -14
  6. package/CountryFlags/SwiperOverview.d.ts +257 -0
  7. package/CountryFlags/SwiperOverview.js +524 -0
  8. package/Highlighted/index.js +10 -5
  9. package/Highlighted/splitTextIntoParts.d.ts +5 -0
  10. package/Highlighted/splitTextIntoParts.js +46 -0
  11. package/MaskedField/index.d.ts +1 -0
  12. package/MaskedField/index.js +44 -36
  13. package/MaskedField/useMasked.js +7 -5
  14. package/Menu/MenuContainer.d.ts +24 -2
  15. package/Menu/MenuContainer.js +194 -243
  16. package/Menu/MenuList.d.ts +1 -0
  17. package/Menu/MenuList.js +15 -16
  18. package/Popper/Popper.d.ts +3 -2
  19. package/Popper/Popper.js +9 -7
  20. package/Popper/PopperContainer.d.ts +0 -1
  21. package/Popper/PopperContainer.js +8 -3
  22. package/Popper/index.d.ts +1 -1
  23. package/Popper/index.js +1 -1
  24. package/Popper/usePopper.d.ts +111 -0
  25. package/Popper/usePopper.js +522 -0
  26. package/Selectbox/SelectboxButton.js +2 -27
  27. package/Selectbox/SelectboxMenu.d.ts +0 -2
  28. package/Selectbox/SelectboxMenu.js +13 -5
  29. package/Selectbox/index.d.ts +5 -3
  30. package/Selectbox/index.js +4 -4
  31. package/Swiper/Swiper.d.ts +28 -17
  32. package/Swiper/Swiper.js +294 -38
  33. package/Swiper/SwiperContainer.d.ts +3 -3
  34. package/Swiper/SwiperContainer.js +1 -0
  35. package/Swiper/SwiperSlide.d.ts +10 -5
  36. package/Swiper/SwiperSlide.js +6 -3
  37. package/Swiper/SwiperSlidesRenderer.d.ts +11 -0
  38. package/Swiper/SwiperSlidesRenderer.js +74 -0
  39. package/Swiper/SwiperTrack.d.ts +4 -0
  40. package/Swiper/SwiperTrack.js +4 -7
  41. package/Swiper/SwiperWrapper.d.ts +2 -0
  42. package/package.json +1 -1
@@ -70,9 +70,8 @@ const generateGuid = () => {
70
70
  ].join('-');
71
71
  };
72
72
  const Selectbox = React.forwardRef((props, ref) => {
73
- const { items, value, multiple, isOpen = false, isLoading = false, anchorPos = 'bottom-fill', fullWidth = false, children, onChange, selectedItemToString, getOptionSelected, onRequestOpen = () => undefined, onRequestClose = () => undefined, overrides, id, label, onFocus, requiredAsterisk, error, errorText, notSetLabel = 'Not set' } = props, nativeButtonProps = __rest(props, ["items", "value", "multiple", "isOpen", "isLoading", "anchorPos", "fullWidth", "children", "onChange", "selectedItemToString", "getOptionSelected", "onRequestOpen", "onRequestClose", "overrides", "id", "label", "onFocus", "requiredAsterisk", "error", "errorText", "notSetLabel"]);
73
+ const { items, value, multiple, isOpen = false, isLoading = false, anchorPos = 'bottom-fill', fullWidth = false, children, onChange, selectedItemToString, getOptionSelected, onRequestOpen = () => undefined, onRequestClose = () => undefined, overrides, id, label, onFocus, requiredAsterisk, error, errorText, notSetLabel = 'Not set', autoFlip = true, positionStrategy } = props, nativeButtonProps = __rest(props, ["items", "value", "multiple", "isOpen", "isLoading", "anchorPos", "fullWidth", "children", "onChange", "selectedItemToString", "getOptionSelected", "onRequestOpen", "onRequestClose", "overrides", "id", "label", "onFocus", "requiredAsterisk", "error", "errorText", "notSetLabel", "autoFlip", "positionStrategy"]);
74
74
  const menuRef = React.useRef(null);
75
- const [actualPlacement, setActualPlacement] = React.useState(anchorPos);
76
75
  const [anchorElement, setAnchorElement] = React.useState(null);
77
76
  const overridesMap = React.useMemo(() => (Object.assign(Object.assign({}, DEFAULT_OVERRIDES), overrides)), [overrides]);
78
77
  const inputID = React.useMemo(() => {
@@ -136,7 +135,8 @@ const Selectbox = React.forwardRef((props, ref) => {
136
135
  }, [handleMouseDown]);
137
136
  const buttonProps = React.useMemo(() => (Object.assign({ fullWidth,
138
137
  error,
139
- isOpen, anchorPos: actualPlacement, endIcon: isLoading ? React.createElement(Spinner_1.default, null) : React.createElement(overridesMap.Icon, { isOpen: isOpen }) }, nativeButtonProps)), [fullWidth, error, isOpen, actualPlacement, isLoading, overridesMap, nativeButtonProps]);
138
+ isOpen,
139
+ anchorPos, endIcon: isLoading ? React.createElement(Spinner_1.default, null) : React.createElement(overridesMap.Icon, { isOpen: isOpen }) }, nativeButtonProps)), [fullWidth, error, isOpen, anchorPos, isLoading, overridesMap, nativeButtonProps]);
140
140
  const labelProps = React.useMemo(() => ({
141
141
  htmlFor: inputID,
142
142
  error,
@@ -151,7 +151,7 @@ const Selectbox = React.forwardRef((props, ref) => {
151
151
  React.createElement(overridesMap.ButtonWrapper, { fullWidth: fullWidth, error: error, isOpen: isOpen },
152
152
  React.createElement(overridesMap.Button, Object.assign({}, buttonProps, { onClick: handleButtonClick, ref: setRefs }), renderValueAsString())),
153
153
  React.createElement(overridesMap.ErrorText, { error: error }, errorText),
154
- React.createElement(SelectboxMenu_1.default, { actualPlacement: actualPlacement, multiple: multiple, items: items, value: value, isOpen: isOpen, anchorElement: anchorElement, getOptionSelected: getOptionSelected, onChange: onChange, onRequestClose: onRequestClose, onAnchorPosChanged: setActualPlacement, ref: menuRef }, children)));
154
+ React.createElement(SelectboxMenu_1.default, { multiple: multiple, items: items, value: value, isOpen: isOpen, anchorPos: anchorPos, positionStrategy: positionStrategy, autoFlip: autoFlip, alternativePlacements: ['bottom-fill', 'top-fill'], anchorElement: anchorElement, getOptionSelected: getOptionSelected, onChange: onChange, onRequestClose: onRequestClose, ref: menuRef }, children)));
155
155
  });
156
156
  Selectbox.displayName = 'Selectbox';
157
157
  exports.default = Selectbox;
@@ -2,43 +2,54 @@ import * as React from 'react';
2
2
  import { SwiperContainerProps } from './SwiperContainer';
3
3
  import { SwiperWrapperProps } from './SwiperWrapper';
4
4
  import { SwiperTrackProps } from './SwiperTrack';
5
+ import SwiperSlide, { SwiperSlideBaseProps, SwiperSlideProps } from './SwiperSlide';
6
+ export * from './SwiperSlide';
7
+ export type SwiperSlideBaseElement = React.ReactElement<SwiperSlideBaseProps, typeof SwiperSlide>;
8
+ export type SwiperSlideElement = React.ReactElement<SwiperSlideProps, typeof SwiperSlide>;
5
9
  export type SwiperRef = {
6
10
  next: () => void;
7
11
  prev: () => void;
8
12
  goToIndex: (index: number) => void;
13
+ getRealIndex: () => number;
14
+ getTotalSlides: () => number;
15
+ pause: () => void;
16
+ resume: () => void;
9
17
  };
10
18
  export interface SwiperOverrides {
11
- /**
12
- * Swiper main container
13
- */
14
19
  readonly Container?: React.ComponentType<SwiperContainerProps & React.RefAttributes<HTMLDivElement>>;
15
- /**
16
- * Swiper wrapper
17
- */
18
20
  readonly Wrapper?: React.ComponentType<SwiperWrapperProps & React.RefAttributes<HTMLDivElement>>;
19
- /**
20
- * Swiper slides track
21
- */
22
21
  readonly Track?: React.ComponentType<SwiperTrackProps & React.RefAttributes<HTMLDivElement>>;
23
22
  }
24
- export type SwiperProps = React.HTMLAttributes<HTMLDivElement> & {
23
+ export type SwiperProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> & {
25
24
  readonly dragThreshold?: number;
26
25
  readonly snap?: boolean;
27
26
  readonly draggable?: boolean;
28
27
  readonly initialIndex?: number;
29
- /**
30
- * Overridable components map
31
- */
28
+ readonly infinite?: boolean;
29
+ readonly onSlideChange?: (realIndex: number) => void;
30
+ readonly autoplay?: boolean;
31
+ readonly autoplayInterval?: number;
32
+ readonly pauseOnHover?: boolean;
33
+ readonly threshold?: number;
34
+ readonly resistance?: boolean;
35
+ readonly slidesPerView?: number;
36
+ readonly children?: readonly SwiperSlideBaseElement[];
32
37
  readonly overrides?: SwiperOverrides;
33
38
  };
34
- export declare const Swiper: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
39
+ export declare const Swiper: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<HTMLDivElement>, "children"> & {
35
40
  readonly dragThreshold?: number | undefined;
36
41
  readonly snap?: boolean | undefined;
37
42
  readonly draggable?: boolean | undefined;
38
43
  readonly initialIndex?: number | undefined;
39
- /**
40
- * Overridable components map
41
- */
44
+ readonly infinite?: boolean | undefined;
45
+ readonly onSlideChange?: ((realIndex: number) => void) | undefined;
46
+ readonly autoplay?: boolean | undefined;
47
+ readonly autoplayInterval?: number | undefined;
48
+ readonly pauseOnHover?: boolean | undefined;
49
+ readonly threshold?: number | undefined;
50
+ readonly resistance?: boolean | undefined;
51
+ readonly slidesPerView?: number | undefined;
52
+ readonly children?: readonly SwiperSlideBaseElement[] | undefined;
42
53
  readonly overrides?: SwiperOverrides | undefined;
43
54
  } & React.RefAttributes<SwiperRef>>;
44
55
  export default Swiper;
package/Swiper/Swiper.js CHANGED
@@ -22,6 +22,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
26
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
27
+ };
25
28
  var __rest = (this && this.__rest) || function (s, e) {
26
29
  var t = {};
27
30
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
@@ -42,26 +45,185 @@ const React = __importStar(require("react"));
42
45
  const SwiperContainer_1 = __importDefault(require("./SwiperContainer"));
43
46
  const SwiperWrapper_1 = __importDefault(require("./SwiperWrapper"));
44
47
  const SwiperTrack_1 = __importDefault(require("./SwiperTrack"));
48
+ const SwiperSlidesRenderer_1 = __importDefault(require("./SwiperSlidesRenderer"));
49
+ __exportStar(require("./SwiperSlide"), exports);
45
50
  exports.Swiper = React.forwardRef((props, ref) => {
46
- const { children, dragThreshold = 120, snap = true, draggable = true, overrides, initialIndex = 0 } = props, restProps = __rest(props, ["children", "dragThreshold", "snap", "draggable", "overrides", "initialIndex"]);
47
- const slides = React.Children.toArray(children);
51
+ const { children, dragThreshold = 240, snap = true, draggable = true, overrides, initialIndex = 0, infinite = false, onSlideChange, autoplay = false, autoplayInterval = 3000, pauseOnHover = true, threshold = 20, resistance = true, slidesPerView = 1 } = props, restProps = __rest(props, ["children", "dragThreshold", "snap", "draggable", "overrides", "initialIndex", "infinite", "onSlideChange", "autoplay", "autoplayInterval", "pauseOnHover", "threshold", "resistance", "slidesPerView"]);
52
+ // #region Slides
53
+ const slides = React.useMemo(() => {
54
+ const childrenSlides = Array.isArray(children)
55
+ ? children
56
+ : [children];
57
+ if (infinite) {
58
+ if (childrenSlides.length < 2) {
59
+ console.error('To infinite loop counts of the slides must be greater than 2');
60
+ return childrenSlides;
61
+ }
62
+ if (childrenSlides.length < slidesPerView + 1) {
63
+ console.error(`For infinite loop with slidesPerView=${slidesPerView}, need at least ${slidesPerView + 1} slides`);
64
+ return childrenSlides;
65
+ }
66
+ // Используем стабильные ключи без Date.now()
67
+ const headClones = childrenSlides.slice(-slidesPerView).map((slide, i) => React.cloneElement(slide, {
68
+ key: `clone-head-${i}`,
69
+ 'data-clone': 'head',
70
+ }));
71
+ const tailClones = childrenSlides.slice(0, slidesPerView).map((slide, i) => React.cloneElement(slide, {
72
+ key: `clone-tail-${i}`,
73
+ 'data-clone': 'tail',
74
+ }));
75
+ const mainSlides = childrenSlides.map((slide, idx) => React.cloneElement(slide, {
76
+ key: `slide-${idx}`,
77
+ }));
78
+ return [...headClones, ...mainSlides, ...tailClones];
79
+ }
80
+ return childrenSlides.map((slide, idx) => React.cloneElement(slide, {
81
+ key: `slide-${idx}`,
82
+ }));
83
+ }, [children, infinite, slidesPerView]);
48
84
  const total = slides.length;
49
- const [index, setIndex] = React.useState(initialIndex);
85
+ const realSlidesCount = infinite ? total - 2 * slidesPerView : total;
86
+ const maxIndex = Math.max(0, total - slidesPerView);
87
+ // #region States
88
+ const [index, setIndex] = React.useState(() => {
89
+ if (!infinite) {
90
+ return Math.max(0, Math.min(initialIndex, maxIndex));
91
+ }
92
+ return initialIndex + slidesPerView;
93
+ });
50
94
  const [offset, setOffset] = React.useState(0);
51
95
  const [isDragging, setIsDragging] = React.useState(false);
96
+ const [disableAnimation, setDisableAnimation] = React.useState(false);
97
+ const [isPaused, setIsPaused] = React.useState(false);
98
+ // #region Refs
52
99
  const dragging = React.useRef(false);
53
100
  const startX = React.useRef(0);
54
101
  const lastX = React.useRef(0);
55
102
  const lastTime = React.useRef(0);
56
103
  const velocity = React.useRef(0);
57
- const width = React.useRef(0);
58
104
  const wrapperRef = React.useRef(null);
59
- const onPointerDown = React.useCallback((e) => {
60
- if (!wrapperRef.current || !draggable) {
105
+ const trackRef = React.useRef(null);
106
+ const isAnimating = React.useRef(false);
107
+ const autoplayTimer = React.useRef();
108
+ const mounted = React.useRef(true);
109
+ const normalizeTimeout = React.useRef();
110
+ // #region Real Index
111
+ const realIndex = React.useMemo(() => {
112
+ if (!infinite) {
113
+ return index;
114
+ }
115
+ const realIndex = index - slidesPerView;
116
+ if (realIndex < 0) {
117
+ return realSlidesCount + realIndex;
118
+ }
119
+ if (realIndex >= realSlidesCount) {
120
+ return realIndex - realSlidesCount;
121
+ }
122
+ return Math.min(realIndex, realSlidesCount - slidesPerView);
123
+ }, [index, infinite, slidesPerView, realSlidesCount]);
124
+ const prevRealIndex = React.useRef(realIndex);
125
+ // #region Effects
126
+ React.useEffect(() => {
127
+ if (realIndex !== prevRealIndex.current && mounted.current) {
128
+ onSlideChange === null || onSlideChange === void 0 ? void 0 : onSlideChange(realIndex);
129
+ prevRealIndex.current = realIndex;
130
+ }
131
+ }, [realIndex, onSlideChange]);
132
+ React.useEffect(() => {
133
+ if (!mounted.current)
61
134
  return;
135
+ const newTotal = slides.length;
136
+ if (index >= newTotal) {
137
+ setIndex(Math.max(0, newTotal - 1));
62
138
  }
63
- width.current = wrapperRef.current.offsetWidth;
139
+ }, [slides.length, index]);
140
+ // #region Normalization
141
+ const normalizeIndex = React.useCallback(() => {
142
+ if (!infinite || !mounted.current)
143
+ return;
144
+ const firstRealIndex = slidesPerView;
145
+ const lastRealIndex = total - slidesPerView - 1;
146
+ if (index < firstRealIndex || index > lastRealIndex) {
147
+ const target = index < firstRealIndex ? lastRealIndex : firstRealIndex;
148
+ setDisableAnimation(true);
149
+ requestAnimationFrame(() => {
150
+ var _a;
151
+ if (!mounted.current)
152
+ return;
153
+ (_a = trackRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
154
+ setIndex(target);
155
+ setOffset(0);
156
+ requestAnimationFrame(() => {
157
+ if (mounted.current) {
158
+ setDisableAnimation(false);
159
+ }
160
+ });
161
+ });
162
+ }
163
+ }, [index, infinite, slidesPerView, total]);
164
+ // #region Navigation API
165
+ const indexRef = React.useRef(index);
166
+ React.useEffect(() => {
167
+ indexRef.current = index;
168
+ }, [index]);
169
+ const goToIndex = React.useCallback((i) => {
170
+ if (isAnimating.current)
171
+ return;
172
+ let targetIndex = i;
173
+ if (infinite) {
174
+ targetIndex = i + slidesPerView;
175
+ const minIndex = slidesPerView;
176
+ const maxIndex = slidesPerView + realSlidesCount - 1;
177
+ targetIndex = Math.max(minIndex, Math.min(maxIndex, targetIndex));
178
+ }
179
+ else {
180
+ targetIndex = Math.max(0, Math.min(maxIndex, i));
181
+ }
182
+ if (targetIndex === indexRef.current) {
183
+ return; // никуда не едем — флаг не трогаем
184
+ }
185
+ setDisableAnimation(false);
186
+ setIndex(targetIndex);
187
+ isAnimating.current = true;
188
+ }, [infinite, slidesPerView, realSlidesCount, maxIndex]);
189
+ const next = React.useCallback(() => {
190
+ // if (isAnimating.current) return;
191
+ setDisableAnimation(false);
192
+ setIndex(prev => {
193
+ let nextIndex;
194
+ if (infinite) {
195
+ nextIndex = Math.min(prev + 1, total - 1);
196
+ }
197
+ else {
198
+ nextIndex = Math.min(prev + 1, maxIndex);
199
+ }
200
+ // если индекс не меняется — не ставим флаг анимации
201
+ if (nextIndex === prev) {
202
+ return prev;
203
+ }
204
+ isAnimating.current = true;
205
+ return nextIndex;
206
+ });
207
+ }, [infinite, maxIndex, total]);
208
+ const prev = React.useCallback(() => {
209
+ // if (isAnimating.current) return;
210
+ setDisableAnimation(false);
211
+ setIndex(prev => {
212
+ const nextIndex = Math.max(prev - 1, 0);
213
+ if (nextIndex === prev) {
214
+ return prev;
215
+ }
216
+ isAnimating.current = true;
217
+ return nextIndex;
218
+ });
219
+ }, []);
220
+ // #region Pointer Events
221
+ const onPointerDown = React.useCallback((e) => {
222
+ if (!wrapperRef.current || !draggable)
223
+ return;
64
224
  dragging.current = true;
225
+ isAnimating.current = false;
226
+ setDisableAnimation(true);
65
227
  setIsDragging(true);
66
228
  startX.current = e.clientX;
67
229
  lastX.current = e.clientX;
@@ -70,9 +232,8 @@ exports.Swiper = React.forwardRef((props, ref) => {
70
232
  e.target.setPointerCapture(e.pointerId);
71
233
  }, [draggable]);
72
234
  const onPointerMove = React.useCallback((e) => {
73
- if (!dragging.current) {
235
+ if (!dragging.current || isAnimating.current)
74
236
  return;
75
- }
76
237
  const now = performance.now();
77
238
  const dx = e.clientX - lastX.current;
78
239
  const dt = now - lastTime.current;
@@ -82,58 +243,153 @@ exports.Swiper = React.forwardRef((props, ref) => {
82
243
  lastX.current = e.clientX;
83
244
  lastTime.current = now;
84
245
  let delta = lastX.current - startX.current;
85
- if (index === 0 && delta > 0) {
86
- delta *= 0.3;
87
- }
88
- if (index === total - 1 && delta < 0) {
89
- delta *= 0.3;
246
+ if (resistance && !infinite) {
247
+ if (index === 0 && delta > 0) {
248
+ delta *= 0.3;
249
+ }
250
+ if (index === maxIndex && delta < 0) {
251
+ delta *= 0.3;
252
+ }
90
253
  }
91
254
  setOffset(delta);
92
- }, [index, total]);
255
+ }, [resistance, infinite, index, maxIndex]);
93
256
  const onPointerUp = React.useCallback((e) => {
94
- if (!dragging.current) {
257
+ if (!dragging.current)
95
258
  return;
96
- }
97
259
  const delta = lastX.current - startX.current;
98
260
  const v = Math.abs(velocity.current);
99
261
  const velocityFactor = Math.min(v * 250, 0.65);
100
- const threshold = Math.max(20, Math.min(dragThreshold * (1 - velocityFactor), dragThreshold));
101
- let next = index;
102
- if (Math.abs(delta) > threshold) {
103
- next = delta < 0 ? index + 1 : index - 1;
262
+ const dynamicThreshold = Math.max(threshold, Math.min(dragThreshold * (1 - velocityFactor), dragThreshold));
263
+ let nextIndex = index;
264
+ if (Math.abs(delta) > dynamicThreshold) {
265
+ nextIndex = delta < 0 ? index + 1 : index - 1;
266
+ }
267
+ if (!infinite) {
268
+ nextIndex = Math.max(0, Math.min(maxIndex, nextIndex));
269
+ }
270
+ else {
271
+ nextIndex = Math.max(0, Math.min(total - 1, nextIndex));
104
272
  }
105
- next = Math.max(0, Math.min(total - 1, next));
273
+ setDisableAnimation(false);
106
274
  if (snap) {
107
- setIndex(next);
275
+ setIndex(nextIndex);
108
276
  setOffset(0);
109
277
  }
110
278
  else {
111
- setIndex(next);
279
+ setIndex(nextIndex);
112
280
  }
281
+ isAnimating.current = true;
113
282
  dragging.current = false;
114
283
  setIsDragging(false);
115
284
  e.target.releasePointerCapture(e.pointerId);
116
- }, [dragThreshold, index, snap, total]);
117
- const next = React.useCallback(() => {
118
- setIndex(i => Math.min(total - 1, i + 1));
119
- }, [total]);
120
- const prev = React.useCallback(() => {
121
- setIndex(i => Math.max(0, i - 1));
285
+ }, [threshold, dragThreshold, index, maxIndex, snap, infinite, total]);
286
+ const onLostPointerCapture = React.useCallback((e) => {
287
+ if (dragging.current) {
288
+ onPointerUp(e);
289
+ }
290
+ }, [onPointerUp]);
291
+ // #region Autoplay
292
+ const startAutoplay = React.useCallback(() => {
293
+ if (!autoplay || isPaused)
294
+ return;
295
+ autoplayTimer.current = setInterval(() => {
296
+ if (!isDragging && !isAnimating.current && mounted.current) {
297
+ next();
298
+ }
299
+ }, autoplayInterval);
300
+ }, [autoplay, autoplayInterval, isDragging, isPaused, next]);
301
+ const pause = React.useCallback(() => {
302
+ setIsPaused(true);
303
+ if (autoplayTimer.current) {
304
+ clearInterval(autoplayTimer.current);
305
+ autoplayTimer.current = undefined;
306
+ }
122
307
  }, []);
123
- const goToIndex = React.useCallback((i) => {
124
- setIndex(Math.max(0, Math.min(total - 1, i)));
125
- }, [total]);
126
- React.useImperativeHandle(ref, () => ({ next, prev, goToIndex }), [next, prev, goToIndex]);
308
+ const resume = React.useCallback(() => {
309
+ setIsPaused(false);
310
+ }, []);
311
+ // #region Hover
312
+ React.useEffect(() => {
313
+ if (!autoplay || !pauseOnHover)
314
+ return;
315
+ const wrapper = wrapperRef.current;
316
+ if (!wrapper)
317
+ return;
318
+ const handleMouseEnter = () => pause();
319
+ const handleMouseLeave = () => resume();
320
+ wrapper.addEventListener('mouseenter', handleMouseEnter);
321
+ wrapper.addEventListener('mouseleave', handleMouseLeave);
322
+ return () => {
323
+ wrapper.removeEventListener('mouseenter', handleMouseEnter);
324
+ wrapper.removeEventListener('mouseleave', handleMouseLeave);
325
+ };
326
+ }, [autoplay, pauseOnHover, pause, resume]);
327
+ // #region Autoplay Effect
328
+ React.useEffect(() => {
329
+ if (autoplay) {
330
+ startAutoplay();
331
+ }
332
+ return () => {
333
+ if (autoplayTimer.current) {
334
+ clearInterval(autoplayTimer.current);
335
+ autoplayTimer.current = undefined;
336
+ }
337
+ };
338
+ }, [autoplay, startAutoplay, isPaused]);
339
+ // #region Transition End
340
+ React.useEffect(() => {
341
+ const track = trackRef.current;
342
+ if (!track)
343
+ return;
344
+ const handleTransitionEnd = (e) => {
345
+ if (e.propertyName !== 'transform')
346
+ return;
347
+ isAnimating.current = false;
348
+ normalizeIndex(); // <-- вот здесь
349
+ };
350
+ track.addEventListener('transitionend', handleTransitionEnd);
351
+ return () => track.removeEventListener('transitionend', handleTransitionEnd);
352
+ }, [normalizeIndex]);
353
+ // #region Mount
354
+ React.useEffect(() => {
355
+ mounted.current = true;
356
+ return () => {
357
+ mounted.current = false;
358
+ };
359
+ }, []);
360
+ // #region Imperative Handle
361
+ React.useImperativeHandle(ref, () => ({
362
+ next,
363
+ prev,
364
+ goToIndex,
365
+ getRealIndex: () => realIndex,
366
+ getTotalSlides: () => realSlidesCount,
367
+ pause,
368
+ resume,
369
+ }), [next, prev, goToIndex, realIndex, realSlidesCount, pause, resume]);
370
+ // #region Overrides
127
371
  const overridesMap = React.useMemo(() => ({
128
372
  Container: (overrides === null || overrides === void 0 ? void 0 : overrides.Container) || SwiperContainer_1.default,
129
373
  Track: (overrides === null || overrides === void 0 ? void 0 : overrides.Track) || SwiperTrack_1.default,
130
374
  Wrapper: (overrides === null || overrides === void 0 ? void 0 : overrides.Wrapper) || SwiperWrapper_1.default,
131
375
  }), [overrides]);
376
+ const getSlideRealIndex = React.useCallback((domIndex) => {
377
+ if (!infinite) {
378
+ return domIndex;
379
+ }
380
+ const totalSlides = realSlidesCount;
381
+ if (domIndex < slidesPerView) {
382
+ return totalSlides - slidesPerView + domIndex;
383
+ }
384
+ if (domIndex >= total - slidesPerView) {
385
+ return domIndex - (total - slidesPerView);
386
+ }
387
+ return domIndex - slidesPerView;
388
+ }, [infinite, realSlidesCount, slidesPerView, total]);
132
389
  return (React.createElement(overridesMap.Container, Object.assign({}, restProps),
133
- React.createElement(overridesMap.Wrapper, { ref: wrapperRef, draggable: draggable, onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp },
134
- React.createElement(overridesMap.Track, { dragging: isDragging, index: index, offset: offset }, slides.map((slide, i) => (
135
- // eslint-disable-next-line react/no-array-index-key
136
- React.createElement(React.Fragment, { key: i }, slide)))))));
390
+ React.createElement(overridesMap.Wrapper, { ref: wrapperRef, draggable: draggable, slidesPerView: slidesPerView, onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp, onLostPointerCapture: onLostPointerCapture },
391
+ React.createElement(overridesMap.Track, { ref: trackRef, dragging: isDragging, index: index, offset: offset, disableAnimation: disableAnimation, slidesPerView: slidesPerView },
392
+ React.createElement(SwiperSlidesRenderer_1.default, { slides: slides, slidesPerView: slidesPerView, realIndex: realIndex, realSlidesCount: realSlidesCount, getSlideRealIndex: getSlideRealIndex })))));
137
393
  });
138
394
  exports.Swiper.displayName = 'Swiper';
139
395
  exports.default = exports.Swiper;
@@ -1,7 +1,7 @@
1
- /// <reference types="react" />
1
+ import React from 'react';
2
2
  export type SwiperContainerProps = React.HTMLAttributes<HTMLDivElement>;
3
3
  export declare const SwiperContainer: import("@emotion/styled").StyledComponent<{
4
4
  theme?: import("@emotion/react").Theme | undefined;
5
- as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
6
- }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
5
+ as?: React.ElementType<any, keyof React.JSX.IntrinsicElements> | undefined;
6
+ }, React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
7
7
  export default SwiperContainer;
@@ -7,6 +7,7 @@ exports.SwiperContainer = void 0;
7
7
  const styled_1 = __importDefault(require("@emotion/styled"));
8
8
  exports.SwiperContainer = styled_1.default.div `
9
9
  width: 100%;
10
+ max-width: 1200px;
10
11
  margin: 0 auto;
11
12
  overflow: hidden;
12
13
  position: relative;
@@ -1,7 +1,12 @@
1
1
  import * as React from 'react';
2
- export type SwiperSlideProps = React.HTMLAttributes<HTMLDivElement> & {
3
- readonly children: React.ReactNode | readonly React.ReactNode[];
2
+ export type SwiperSlideBaseProps = React.HTMLAttributes<HTMLDivElement> & {
3
+ readonly children: React.ReactNode;
4
4
  };
5
- export declare const SwiperSlide: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
6
- readonly children: React.ReactNode | readonly React.ReactNode[];
7
- } & React.RefAttributes<HTMLDivElement>>;
5
+ export type SwiperSlideProps = SwiperSlideBaseProps & {
6
+ readonly isVisible: boolean;
7
+ readonly isNearby: boolean;
8
+ readonly slidesPerView: number;
9
+ readonly key: string;
10
+ };
11
+ export declare const SwiperSlide: React.ForwardRefExoticComponent<(SwiperSlideBaseProps | SwiperSlideProps) & React.RefAttributes<HTMLDivElement>>;
12
+ export default SwiperSlide;
@@ -41,7 +41,9 @@ exports.SwiperSlide = void 0;
41
41
  const styled_1 = __importDefault(require("@emotion/styled"));
42
42
  const React = __importStar(require("react"));
43
43
  const StyledSlide = styled_1.default.div `
44
- flex: 0 0 100%;
44
+ flex-grow: 0;
45
+ flex-shrink: 0;
46
+ flex-basis: calc(100% / ${({ $slidesPerView }) => $slidesPerView});
45
47
  height: 100%;
46
48
  display: flex;
47
49
  align-items: center;
@@ -49,7 +51,8 @@ const StyledSlide = styled_1.default.div `
49
51
  box-sizing: border-box;
50
52
  `;
51
53
  exports.SwiperSlide = React.forwardRef((props, ref) => {
52
- const { children } = props, restProps = __rest(props, ["children"]);
53
- return (React.createElement(StyledSlide, Object.assign({}, restProps, { ref: ref }), children));
54
+ const _a = props, { children, isVisible = true, slidesPerView = 1, isNearby = true } = _a, restProps = __rest(_a, ["children", "isVisible", "slidesPerView", "isNearby"]);
55
+ return (React.createElement(StyledSlide, Object.assign({ "data-is-visible": isVisible, "data-is-nearby": isNearby }, restProps, { "$slidesPerView": slidesPerView, ref: ref }), isVisible || isNearby ? children : null));
54
56
  });
55
57
  exports.SwiperSlide.displayName = 'SwiperSlide';
58
+ exports.default = exports.SwiperSlide;
@@ -0,0 +1,11 @@
1
+ import * as React from 'react';
2
+ import { SwiperSlideElement } from './Swiper';
3
+ export type SwiperSlidesRendererProps = {
4
+ readonly slides: readonly SwiperSlideElement[];
5
+ readonly slidesPerView: number;
6
+ readonly realIndex: number;
7
+ readonly realSlidesCount: number;
8
+ readonly getSlideRealIndex: (index: number) => number;
9
+ };
10
+ declare const _default: React.NamedExoticComponent<SwiperSlidesRendererProps>;
11
+ export default _default;
@@ -0,0 +1,74 @@
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 (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ const React = __importStar(require("react"));
27
+ const SwiperSlidesRenderer = props => {
28
+ const { slides, slidesPerView, realIndex, realSlidesCount, getSlideRealIndex } = props;
29
+ // Мемоизируем вычисления видимости
30
+ const visibilityMap = React.useMemo(() => {
31
+ const map = new Map();
32
+ if (realSlidesCount <= slidesPerView) {
33
+ slides.forEach((_, i) => {
34
+ map.set(i, { isVisible: true, isNearby: false });
35
+ });
36
+ }
37
+ else {
38
+ const visibleIndices = [];
39
+ for (let j = 0; j < slidesPerView; j++) {
40
+ visibleIndices.push((realIndex + j) % realSlidesCount);
41
+ }
42
+ const prevIndex = (realIndex - 1 + realSlidesCount) % realSlidesCount;
43
+ const nextIndex = (realIndex + slidesPerView) % realSlidesCount;
44
+ slides.forEach((_, i) => {
45
+ const slideRealIndex = getSlideRealIndex(i);
46
+ const isVisible = visibleIndices.includes(slideRealIndex);
47
+ const isNearby = !isVisible && (slideRealIndex === prevIndex || slideRealIndex === nextIndex);
48
+ map.set(i, { isVisible, isNearby });
49
+ });
50
+ }
51
+ return map;
52
+ }, [slides, slidesPerView, realIndex, realSlidesCount, getSlideRealIndex]);
53
+ return (React.createElement(React.Fragment, null, slides.map((slide, i) => {
54
+ const { isVisible, isNearby } = visibilityMap.get(i) || {
55
+ isVisible: false,
56
+ isNearby: false,
57
+ };
58
+ const slideRealIndex = getSlideRealIndex(i);
59
+ // Не клонируем заново, если пропсы не изменились
60
+ if (slide.props.slidesPerView === slidesPerView &&
61
+ slide.props.isVisible === isVisible &&
62
+ slide.props.isNearby === isNearby) {
63
+ return slide;
64
+ }
65
+ return React.cloneElement(slide, {
66
+ slidesPerView,
67
+ isVisible,
68
+ isNearby,
69
+ 'data-index': i,
70
+ 'data-real-index': slideRealIndex,
71
+ });
72
+ })));
73
+ };
74
+ exports.default = React.memo(SwiperSlidesRenderer);