@hh.ru/magritte-ui-scrollable-container 6.5.1 → 6.5.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.
- package/ObservableValue.js +17 -17
- package/ObservableValue.js.map +1 -1
- package/ScrollStateProvider.d.ts +2 -2
- package/ScrollStateProvider.js +11 -11
- package/ScrollStateProvider.js.map +1 -1
- package/ScrollableContainer.d.ts +8 -8
- package/ScrollableContainer.js +99 -60
- package/ScrollableContainer.js.map +1 -1
- package/ScrollableContainerButton.d.ts +1 -1
- package/ScrollableContainerButton.js +15 -12
- package/ScrollableContainerButton.js.map +1 -1
- package/ScrollableContainerDefaultLayout.d.ts +1 -1
- package/ScrollableContainerDefaultLayout.js +130 -68
- package/ScrollableContainerDefaultLayout.js.map +1 -1
- package/ScrollableContainerDotPages.d.ts +1 -1
- package/ScrollableContainerDotPages.js +59 -47
- package/ScrollableContainerDotPages.js.map +1 -1
- package/ScrollableContainerGallery.d.ts +1 -1
- package/ScrollableContainerGallery.js +85 -54
- package/ScrollableContainerGallery.js.map +1 -1
- package/ScrollableItem.d.ts +1 -1
- package/ScrollableItem.js +22 -12
- package/ScrollableItem.js.map +1 -1
- package/index.css +19 -19
- package/index.d.ts +6 -6
- package/index.js +1 -1
- package/index.mock.d.ts +4 -4
- package/index.mock.js +21 -21
- package/index.mock.js.map +1 -1
- package/package.json +6 -6
- package/scrollableContainer-CWsF-84M.js +5 -0
- package/scrollableContainer-CWsF-84M.js.map +1 -0
- package/types.js +1 -1
- package/types.js.map +1 -1
- package/useScrollContainer.js +181 -157
- package/useScrollContainer.js.map +1 -1
- package/useScrollableControls.d.ts +2 -2
- package/useScrollableControls.js +90 -72
- package/useScrollableControls.js.map +1 -1
- package/utils.d.ts +2 -2
- package/utils.js +157 -254
- package/utils.js.map +1 -1
- package/scrollableContainer-DFe-eO3O.js +0 -5
- package/scrollableContainer-DFe-eO3O.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useScrollableControls.js","sources":["src/useScrollableControls.tsx"],"sourcesContent":["import { useCallback, type RefObject } from 'react';\n\nimport { clamp } from '@hh.ru/magritte-internal-custom-scroll';\nimport { useScrollState, type ScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport type { ScrollableControls } from '@hh.ru/magritte-ui-scrollable-container/types';\nimport {\n findIndexNearestToSnapPoint,\n animateScrollToPosition,\n ensureItemReadyForScroll,\n computeScrollSnapBehavior,\n} from '@hh.ru/magritte-ui-scrollable-container/utils';\n\nexport const useScrollableControlsWithState: (scrollState: ScrollState) => ScrollableControls = (scrollState) => {\n const scrollSide = useCallback(\n (toRight: boolean = false) => {\n if (scrollState.scrollSnapAlign === 'none') {\n const delta = toRight ? -scrollState.viewportWidth.get() : scrollState.viewportWidth.get();\n const position = scrollState.scrollPosition.get() + delta;\n animateScrollToPosition(scrollState, position);\n return;\n }\n const index = findIndexNearestToSnapPoint(scrollState);\n const nextIndex = clamp(toRight ? index + 1 : index - 1, 0, scrollState.items.get().length - 1);\n if (!ensureItemReadyForScroll(scrollState, nextIndex)) {\n return;\n }\n const scrollSnapBehavior = computeScrollSnapBehavior(scrollState);\n const target = scrollSnapBehavior(scrollState, nextIndex);\n animateScrollToPosition(scrollState, target);\n },\n [scrollState]\n );\n\n const scrollToIndex = useCallback(\n (index: number) => {\n if (!ensureItemReadyForScroll(scrollState, index)) {\n return;\n }\n const scrollSnapBehavior = computeScrollSnapBehavior(scrollState);\n const target = scrollSnapBehavior(scrollState, index);\n animateScrollToPosition(scrollState, target);\n },\n [scrollState]\n );\n\n const scrollToFirstItem = useCallback(() => scrollToIndex(0), [scrollToIndex]);\n\n const scrollToLastItem = useCallback(\n () => scrollToIndex(scrollState.items.get().length - 1),\n [scrollState, scrollToIndex]\n );\n\n const scrollToItem = useCallback(\n (ref: RefObject<HTMLElement>) => {\n const index = scrollState.items.get().findIndex((item) => item.current && item.current === ref.current);\n index !== -1 && scrollToIndex(index);\n },\n [scrollState, scrollToIndex]\n );\n\n const jumpToIndex = useCallback(\n (index: number) => {\n if (!ensureItemReadyForScroll(scrollState, index, 'instant')) {\n return;\n }\n const scrollSnapBehavior = computeScrollSnapBehavior(scrollState);\n const target = scrollSnapBehavior(scrollState, index);\n const { scrollPosition, springScrollPosition, viewportWidth, contentWidth } = scrollState;\n if (target === null) {\n return;\n }\n const clampedTarget = clamp(target, viewportWidth.get() - contentWidth.get(), 0);\n const isScrollPositionReached = scrollPosition.get() === clampedTarget;\n const isSpringScrollPositionReached = !springScrollPosition || springScrollPosition.get() === clampedTarget;\n if (isScrollPositionReached && isSpringScrollPositionReached) {\n return;\n }\n scrollPosition.jump(clampedTarget);\n springScrollPosition?.jump(clampedTarget);\n },\n [scrollState]\n );\n\n const jumpBy = useCallback(\n (delta: number) => {\n const { scrollPosition, springScrollPosition, viewportWidth, contentWidth } = scrollState;\n const target = clamp(scrollPosition.get() + delta, viewportWidth.get() - contentWidth.get(), 0);\n const clampedDelta = target - scrollPosition.get();\n if (clampedDelta === 0) {\n return;\n }\n scrollPosition.jump(target);\n springScrollPosition?.jump(springScrollPosition.get() + clampedDelta);\n },\n [scrollState]\n );\n\n return {\n scrollLeft: () => scrollSide(),\n scrollRight: () => scrollSide(true),\n scrollToFirstItem,\n scrollToLastItem,\n scrollToIndex,\n scrollToItem,\n jumpToIndex,\n jumpBy,\n };\n};\n\nexport const useScrollableControls: () => ScrollableControls = () => {\n const scrollState = useScrollState();\n const controls = useScrollableControlsWithState(scrollState);\n return controls;\n};\n"],"names":[],"mappings":";;;;;;;;;AAYa,MAAA,
|
|
1
|
+
{"version":3,"file":"useScrollableControls.js","sources":["src/useScrollableControls.tsx"],"sourcesContent":["import { useCallback, type RefObject } from 'react';\n\nimport { clamp } from '@hh.ru/magritte-internal-custom-scroll';\nimport { useScrollState, type ScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport type { ScrollableControls } from '@hh.ru/magritte-ui-scrollable-container/types';\nimport {\n findIndexNearestToSnapPoint,\n animateScrollToPosition,\n ensureItemReadyForScroll,\n computeScrollSnapBehavior,\n} from '@hh.ru/magritte-ui-scrollable-container/utils';\n\nexport const useScrollableControlsWithState: (scrollState: ScrollState) => ScrollableControls = (scrollState) => {\n const scrollSide = useCallback(\n (toRight: boolean = false) => {\n if (scrollState.scrollSnapAlign === 'none') {\n const delta = toRight ? -scrollState.viewportWidth.get() : scrollState.viewportWidth.get();\n const position = scrollState.scrollPosition.get() + delta;\n animateScrollToPosition(scrollState, position);\n return;\n }\n const index = findIndexNearestToSnapPoint(scrollState);\n const nextIndex = clamp(toRight ? index + 1 : index - 1, 0, scrollState.items.get().length - 1);\n if (!ensureItemReadyForScroll(scrollState, nextIndex)) {\n return;\n }\n const scrollSnapBehavior = computeScrollSnapBehavior(scrollState);\n const target = scrollSnapBehavior(scrollState, nextIndex);\n animateScrollToPosition(scrollState, target);\n },\n [scrollState]\n );\n\n const scrollToIndex = useCallback(\n (index: number) => {\n if (!ensureItemReadyForScroll(scrollState, index)) {\n return;\n }\n const scrollSnapBehavior = computeScrollSnapBehavior(scrollState);\n const target = scrollSnapBehavior(scrollState, index);\n animateScrollToPosition(scrollState, target);\n },\n [scrollState]\n );\n\n const scrollToFirstItem = useCallback(() => scrollToIndex(0), [scrollToIndex]);\n\n const scrollToLastItem = useCallback(\n () => scrollToIndex(scrollState.items.get().length - 1),\n [scrollState, scrollToIndex]\n );\n\n const scrollToItem = useCallback(\n (ref: RefObject<HTMLElement>) => {\n const index = scrollState.items.get().findIndex((item) => item.current && item.current === ref.current);\n index !== -1 && scrollToIndex(index);\n },\n [scrollState, scrollToIndex]\n );\n\n const jumpToIndex = useCallback(\n (index: number) => {\n if (!ensureItemReadyForScroll(scrollState, index, 'instant')) {\n return;\n }\n const scrollSnapBehavior = computeScrollSnapBehavior(scrollState);\n const target = scrollSnapBehavior(scrollState, index);\n const { scrollPosition, springScrollPosition, viewportWidth, contentWidth } = scrollState;\n if (target === null) {\n return;\n }\n const clampedTarget = clamp(target, viewportWidth.get() - contentWidth.get(), 0);\n const isScrollPositionReached = scrollPosition.get() === clampedTarget;\n const isSpringScrollPositionReached = !springScrollPosition || springScrollPosition.get() === clampedTarget;\n if (isScrollPositionReached && isSpringScrollPositionReached) {\n return;\n }\n scrollPosition.jump(clampedTarget);\n springScrollPosition?.jump(clampedTarget);\n },\n [scrollState]\n );\n\n const jumpBy = useCallback(\n (delta: number) => {\n const { scrollPosition, springScrollPosition, viewportWidth, contentWidth } = scrollState;\n const target = clamp(scrollPosition.get() + delta, viewportWidth.get() - contentWidth.get(), 0);\n const clampedDelta = target - scrollPosition.get();\n if (clampedDelta === 0) {\n return;\n }\n scrollPosition.jump(target);\n springScrollPosition?.jump(springScrollPosition.get() + clampedDelta);\n },\n [scrollState]\n );\n\n return {\n scrollLeft: () => scrollSide(),\n scrollRight: () => scrollSide(true),\n scrollToFirstItem,\n scrollToLastItem,\n scrollToIndex,\n scrollToItem,\n jumpToIndex,\n jumpBy,\n };\n};\n\nexport const useScrollableControls: () => ScrollableControls = () => {\n const scrollState = useScrollState();\n const controls = useScrollableControlsWithState(scrollState);\n return controls;\n};\n"],"names":[],"mappings":"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"}
|
package/utils.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Breakpoint } from '@hh.ru/magritte-ui-breakpoint';
|
|
2
|
-
import { type ScrollState, type BehaviorScrollType } from '
|
|
3
|
-
import { type SpacingCorrectionProps, type ScrollDisableState, type ItemOffset } from '
|
|
2
|
+
import { type ScrollState, type BehaviorScrollType } from './ScrollStateProvider';
|
|
3
|
+
import { type SpacingCorrectionProps, type ScrollDisableState, type ItemOffset } from './types';
|
|
4
4
|
export declare const BREAKPOINTS_LIST: Breakpoint[];
|
|
5
5
|
export declare const NO_BUTTONS_START_FROM_BREAKPOINT = Breakpoint.S;
|
|
6
6
|
export declare function debounce<T extends unknown[]>(callback: (...args: T) => void, waitMs: number): typeof callback;
|
package/utils.js
CHANGED
|
@@ -6,291 +6,194 @@ import { Breakpoint } from '@hh.ru/magritte-ui-breakpoint';
|
|
|
6
6
|
import { OFFSET_ATTR } from './types.js';
|
|
7
7
|
|
|
8
8
|
const BREAKPOINTS_LIST = [
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
Breakpoint.XS,
|
|
10
|
+
Breakpoint.S,
|
|
11
|
+
Breakpoint.M,
|
|
12
|
+
Breakpoint.L,
|
|
13
|
+
Breakpoint.XL,
|
|
14
|
+
Breakpoint.XXL
|
|
15
15
|
];
|
|
16
16
|
const NO_BUTTONS_START_FROM_BREAKPOINT = Breakpoint.S;
|
|
17
17
|
function debounce(callback, waitMs) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
let timeout = 0;
|
|
19
|
+
return (...args) => {
|
|
20
|
+
clearTimeout(timeout);
|
|
21
|
+
timeout = setTimeout(() => {
|
|
22
|
+
callback(...args);
|
|
23
|
+
}, waitMs);
|
|
24
|
+
};
|
|
25
25
|
}
|
|
26
|
-
/**
|
|
27
|
-
* По переданным параметрам коррекции возвращает значения отступов для текущего брейкпоинта
|
|
28
|
-
* @param props Параметры коррекции
|
|
29
|
-
* @param breakpoint Текуший брейкпоинт
|
|
30
|
-
* @returns Объект содержащий значения отступов
|
|
31
|
-
*/
|
|
32
26
|
const getActualCorrection = (props, breakpoint) => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
(leftCorrection = props[leftCorrectionKey]);
|
|
47
|
-
props[rightCorrectionKey] !== undefined &&
|
|
48
|
-
rightCorrection === undefined &&
|
|
49
|
-
(rightCorrection = props[rightCorrectionKey]);
|
|
50
|
-
// Если для левой или правой стороны не найден параметр коррекции, то пробуем взять параметр correction для
|
|
51
|
-
// брейкпоинта который сейчас обрабатываем в цикле, например correctionM
|
|
52
|
-
if (props[commonCorrectionKey] !== undefined) {
|
|
53
|
-
leftCorrection === undefined && (leftCorrection = props[commonCorrectionKey]);
|
|
54
|
-
rightCorrection === undefined && (rightCorrection = props[commonCorrectionKey]);
|
|
55
|
-
}
|
|
56
|
-
// Если нашли значения для обеих сторон - возращаем
|
|
57
|
-
if (leftCorrection !== undefined && rightCorrection !== undefined) {
|
|
58
|
-
return { leftCorrection, rightCorrection };
|
|
59
|
-
}
|
|
27
|
+
const breakpointIndex = BREAKPOINTS_LIST.indexOf(breakpoint);
|
|
28
|
+
let leftCorrection;
|
|
29
|
+
let rightCorrection;
|
|
30
|
+
for (let i = breakpointIndex; i >= 0; i--) {
|
|
31
|
+
const breakpointName = BREAKPOINTS_LIST[i].toUpperCase();
|
|
32
|
+
const leftCorrectionKey = `correctionLeft${breakpointName}`;
|
|
33
|
+
const rightCorrectionKey = `correctionRight${breakpointName}`;
|
|
34
|
+
const commonCorrectionKey = `correction${breakpointName}`;
|
|
35
|
+
props[leftCorrectionKey] !== void 0 && leftCorrection === void 0 && (leftCorrection = props[leftCorrectionKey]);
|
|
36
|
+
props[rightCorrectionKey] !== void 0 && rightCorrection === void 0 && (rightCorrection = props[rightCorrectionKey]);
|
|
37
|
+
if (props[commonCorrectionKey] !== void 0) {
|
|
38
|
+
leftCorrection === void 0 && (leftCorrection = props[commonCorrectionKey]);
|
|
39
|
+
rightCorrection === void 0 && (rightCorrection = props[commonCorrectionKey]);
|
|
60
40
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
41
|
+
if (leftCorrection !== void 0 && rightCorrection !== void 0) {
|
|
42
|
+
return { leftCorrection, rightCorrection };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
leftCorrection: leftCorrection === void 0 ? props.correction || 0 : leftCorrection,
|
|
47
|
+
rightCorrection: rightCorrection === void 0 ? props.correction || 0 : rightCorrection
|
|
48
|
+
};
|
|
66
49
|
};
|
|
67
50
|
const useInitOnce = (func) => {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
51
|
+
const initializedRef = useRef(void 0);
|
|
52
|
+
if (initializedRef.current === void 0) {
|
|
53
|
+
initializedRef.current = func();
|
|
54
|
+
}
|
|
55
|
+
return initializedRef.current;
|
|
73
56
|
};
|
|
74
|
-
/**
|
|
75
|
-
* Отдает метрики элемента галереи
|
|
76
|
-
* @param scrollState стейт скролла
|
|
77
|
-
* @param index индекс элемента
|
|
78
|
-
* @returns метрики элемента, либо null (если элемента нет или его размеры еще не посчитаны)
|
|
79
|
-
*/
|
|
80
57
|
const getItemOffset = (scrollState, index) => scrollState.items.get()[index]?.current?.[OFFSET_ATTR] ?? null;
|
|
81
|
-
/**
|
|
82
|
-
* На основе стейта расчитывает флаги скрола
|
|
83
|
-
* @param scrollState стейт скролла
|
|
84
|
-
* @returns cостояние блокировки скролла
|
|
85
|
-
*/
|
|
86
58
|
const getDisableState = (scrollState) => {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
59
|
+
const { scrollPosition, viewportWidth, contentWidth } = scrollState;
|
|
60
|
+
return {
|
|
61
|
+
isScrollLeftDisabled: scrollPosition.get() >= 0,
|
|
62
|
+
isScrollRightDisabled: Math.abs(scrollPosition.get()) + viewportWidth.get() >= contentWidth.get()
|
|
63
|
+
};
|
|
92
64
|
};
|
|
93
|
-
/**
|
|
94
|
-
* Анимирует scrollPosition с учетом границ контенера
|
|
95
|
-
* @param scrollState стейт скролла
|
|
96
|
-
* @param position новая позиция
|
|
97
|
-
* @returns void
|
|
98
|
-
*/
|
|
99
65
|
const animateScrollToPosition = (scrollState, position) => {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
66
|
+
const { scrollPosition, viewportWidth, contentWidth } = scrollState;
|
|
67
|
+
if (position === null || scrollPosition.get() === position) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const clampedPosition = clamp(position, viewportWidth.get() - contentWidth.get(), 0);
|
|
71
|
+
animate(scrollPosition, clampedPosition, {
|
|
72
|
+
velocity: Math.max(scrollPosition.getVelocity(), 1)
|
|
73
|
+
});
|
|
108
74
|
};
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
scrollState.indexForDeferScroll = index;
|
|
119
|
-
scrollState.behaviorScrollTypeDeferScroll = behaviorScrollType;
|
|
120
|
-
return false;
|
|
121
|
-
}
|
|
122
|
-
return true;
|
|
75
|
+
const ensureItemReadyForScroll = (scrollState, index, behaviorScrollType = "animate") => {
|
|
76
|
+
const { items } = scrollState;
|
|
77
|
+
const item = items.get()[index]?.current;
|
|
78
|
+
if (!item || !item[OFFSET_ATTR]) {
|
|
79
|
+
scrollState.indexForDeferScroll = index;
|
|
80
|
+
scrollState.behaviorScrollTypeDeferScroll = behaviorScrollType;
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
return true;
|
|
123
84
|
};
|
|
124
|
-
/**
|
|
125
|
-
* Возвращает якорную точку отрезка в зависимости от scrollSnapAlign.
|
|
126
|
-
*
|
|
127
|
-
* start — левая граница элемента
|
|
128
|
-
* center — центр элемента
|
|
129
|
-
* end — правая граница элемента
|
|
130
|
-
*
|
|
131
|
-
* @param left левая граница элемента
|
|
132
|
-
* @param right правая граница элемента
|
|
133
|
-
* @param align режим выравнивания (scroll-snap-align)
|
|
134
|
-
* @returns координата якорной точки элемента
|
|
135
|
-
*/
|
|
136
85
|
const getAnchorPoint = (left, right, align) => {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
86
|
+
let point = 0;
|
|
87
|
+
switch (align) {
|
|
88
|
+
case "center":
|
|
89
|
+
point = (left + right) / 2;
|
|
90
|
+
break;
|
|
91
|
+
case "end":
|
|
92
|
+
point = right;
|
|
93
|
+
break;
|
|
94
|
+
case "start":
|
|
95
|
+
default:
|
|
96
|
+
point = left;
|
|
97
|
+
}
|
|
98
|
+
return point;
|
|
150
99
|
};
|
|
151
|
-
/**
|
|
152
|
-
* Вычисляет целевую точку прокрутки в зависимости от режима scroll-snap выравнивания.
|
|
153
|
-
*
|
|
154
|
-
* В качестве базовой позиции используется текущее значение scrollLeft,
|
|
155
|
-
* к которому добавляется смещение, зависящее от `scrollSnapAlign`:
|
|
156
|
-
* - start — начало области просмотра
|
|
157
|
-
* - center — центр области просмотра
|
|
158
|
-
* - end — конец области просмотра
|
|
159
|
-
*
|
|
160
|
-
* @param state Текущее состояние скролл
|
|
161
|
-
* @returns Координата целевой точки прокрутки
|
|
162
|
-
*/
|
|
163
100
|
const getTargetPoint = (state) => {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
101
|
+
const scrollLeft = Math.abs(state.scrollPosition.get());
|
|
102
|
+
let point = 0;
|
|
103
|
+
switch (state.scrollSnapAlign) {
|
|
104
|
+
case "center":
|
|
105
|
+
point = scrollLeft + state.viewportWidth.get() / 2;
|
|
106
|
+
break;
|
|
107
|
+
case "end":
|
|
108
|
+
point = scrollLeft + state.viewportWidth.get();
|
|
109
|
+
break;
|
|
110
|
+
case "start":
|
|
111
|
+
default:
|
|
112
|
+
point = scrollLeft;
|
|
113
|
+
}
|
|
114
|
+
return point;
|
|
178
115
|
};
|
|
179
|
-
/**
|
|
180
|
-
* На основе позиции, находит ближайший элемент к центру viewport
|
|
181
|
-
* @param scrollState стейт скролла
|
|
182
|
-
* @returns индекс найденого элемента
|
|
183
|
-
*/
|
|
184
116
|
const findIndexNearestToSnapPoint = (state) => {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
117
|
+
const items = state.items.get();
|
|
118
|
+
if (items.length === 0) {
|
|
119
|
+
return 0;
|
|
120
|
+
}
|
|
121
|
+
const targetPoint = getTargetPoint(state);
|
|
122
|
+
let idx = 0;
|
|
123
|
+
let minDist = Infinity;
|
|
124
|
+
for (let key = 0; key < items.length; key++) {
|
|
125
|
+
const element = items[key]?.current;
|
|
126
|
+
if (element && element[OFFSET_ATTR]) {
|
|
127
|
+
const { left, right } = element[OFFSET_ATTR];
|
|
128
|
+
const anchor = getAnchorPoint(left, right, state.scrollSnapAlign);
|
|
129
|
+
const dist = Math.abs(targetPoint - anchor);
|
|
130
|
+
if (dist < minDist) {
|
|
131
|
+
minDist = dist;
|
|
132
|
+
idx = key;
|
|
133
|
+
}
|
|
203
134
|
}
|
|
204
|
-
|
|
135
|
+
}
|
|
136
|
+
return idx;
|
|
205
137
|
};
|
|
206
|
-
/**
|
|
207
|
-
* Определят позицию, при которой элемент будет находится на левой границе viewport
|
|
208
|
-
* @param scrollState стейт скролла
|
|
209
|
-
* @param index индекс элемента
|
|
210
|
-
* @returns новая позиция
|
|
211
|
-
*/
|
|
212
138
|
const computeStartPositionForIndex = (scrollState, index) => {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
139
|
+
const { items, defaultButtonsCorrection } = scrollState;
|
|
140
|
+
const itemRef = items.get()[index];
|
|
141
|
+
if (!itemRef?.current) {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
const offset = itemRef.current[OFFSET_ATTR];
|
|
145
|
+
return -offset.left + defaultButtonsCorrection.get();
|
|
220
146
|
};
|
|
221
|
-
/**
|
|
222
|
-
* Определят позицию, при которой элемент будет находится на правой границе viewport
|
|
223
|
-
* @param scrollState стейт скролла
|
|
224
|
-
* @param index индекс элемента
|
|
225
|
-
* @returns новая позиция
|
|
226
|
-
*/
|
|
227
147
|
const computeEndPositionForIndex = (scrollState, index) => {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
148
|
+
const { items, defaultButtonsCorrection, viewportWidth } = scrollState;
|
|
149
|
+
const itemRef = items.get()[index];
|
|
150
|
+
if (!itemRef?.current) {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
const offset = itemRef.current[OFFSET_ATTR];
|
|
154
|
+
return -offset.right + viewportWidth.get() - defaultButtonsCorrection.get();
|
|
235
155
|
};
|
|
236
|
-
/**
|
|
237
|
-
* Определят позицию, при которой элемент будет в центре viewport
|
|
238
|
-
* @param scrollState стейт скролла
|
|
239
|
-
* @param index индекс элемента
|
|
240
|
-
* @returns новая позиция
|
|
241
|
-
*/
|
|
242
156
|
const computeCenterPositionForIndex = (scrollState, index) => {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
157
|
+
const { items, viewportWidth } = scrollState;
|
|
158
|
+
const itemRef = items.get()[index];
|
|
159
|
+
if (!itemRef?.current) {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
const offset = itemRef.current[OFFSET_ATTR];
|
|
163
|
+
const itemWidth = offset.right - offset.left;
|
|
164
|
+
const itemCenter = offset.left + itemWidth / 2;
|
|
165
|
+
const viewportCenter = viewportWidth.get() / 2;
|
|
166
|
+
return viewportCenter - itemCenter;
|
|
253
167
|
};
|
|
254
|
-
/**
|
|
255
|
-
* Определят позицию, при которой элемент будет находится во viewport (с учетом боковых кнопок в fade)
|
|
256
|
-
* @param scrollState стейт скролла
|
|
257
|
-
* @param index индекс элемента
|
|
258
|
-
* @returns новая позиция
|
|
259
|
-
*/
|
|
260
168
|
const computePositionForIndex = (scrollState, index) => {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
169
|
+
const { items, viewportWidth, scrollPosition, defaultButtonsCorrection } = scrollState;
|
|
170
|
+
const itemRef = items.get()[index];
|
|
171
|
+
if (!itemRef?.current) {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
const offset = itemRef.current[OFFSET_ATTR];
|
|
175
|
+
const viewportLeft = -scrollPosition.get() + defaultButtonsCorrection.get();
|
|
176
|
+
const viewportRight = viewportLeft + viewportWidth.get() - defaultButtonsCorrection.get();
|
|
177
|
+
if (offset.left >= viewportLeft && offset.right <= viewportRight) {
|
|
178
|
+
return scrollPosition.get();
|
|
179
|
+
}
|
|
180
|
+
if (offset.left < viewportLeft) {
|
|
181
|
+
return -(offset.left - defaultButtonsCorrection.get());
|
|
182
|
+
}
|
|
183
|
+
return viewportWidth.get() - offset.right - defaultButtonsCorrection.get();
|
|
276
184
|
};
|
|
277
|
-
/**
|
|
278
|
-
* Определят поведение "подскрола" ближайшего элемента
|
|
279
|
-
* @param scrollState стейт скролла
|
|
280
|
-
* @returns StrategyPosition
|
|
281
|
-
*/
|
|
282
185
|
const computeScrollSnapBehavior = (scrollState) => {
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
186
|
+
switch (scrollState.scrollSnapAlign) {
|
|
187
|
+
case "center":
|
|
188
|
+
return computeCenterPositionForIndex;
|
|
189
|
+
case "start":
|
|
190
|
+
return computeStartPositionForIndex;
|
|
191
|
+
case "end":
|
|
192
|
+
return computeEndPositionForIndex;
|
|
193
|
+
case "none":
|
|
194
|
+
default:
|
|
195
|
+
return computePositionForIndex;
|
|
196
|
+
}
|
|
294
197
|
};
|
|
295
198
|
|
|
296
199
|
export { BREAKPOINTS_LIST, NO_BUTTONS_START_FROM_BREAKPOINT, animateScrollToPosition, computeCenterPositionForIndex, computeEndPositionForIndex, computePositionForIndex, computeScrollSnapBehavior, computeStartPositionForIndex, debounce, ensureItemReadyForScroll, findIndexNearestToSnapPoint, getActualCorrection, getDisableState, getItemOffset, useInitOnce };
|
package/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["src/utils.ts"],"sourcesContent":["import { useRef } from 'react';\nimport { animate } from 'motion/react';\n\nimport { clamp } from '@hh.ru/magritte-internal-custom-scroll';\nimport { Breakpoint } from '@hh.ru/magritte-ui-breakpoint';\nimport { type ScrollState, type BehaviorScrollType } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport {\n type SpacingCorrectionProps,\n type ScrollDisableState,\n type ScrollSnapAlign,\n OFFSET_ATTR,\n type ItemOffset,\n} from '@hh.ru/magritte-ui-scrollable-container/types';\n\nexport const BREAKPOINTS_LIST = [\n Breakpoint.XS,\n Breakpoint.S,\n Breakpoint.M,\n Breakpoint.L,\n Breakpoint.XL,\n Breakpoint.XXL,\n];\nexport const NO_BUTTONS_START_FROM_BREAKPOINT = Breakpoint.S;\n\nexport function debounce<T extends unknown[]>(callback: (...args: T) => void, waitMs: number): typeof callback {\n let timeout = 0;\n return (...args: T) => {\n clearTimeout(timeout);\n timeout = setTimeout(() => {\n callback(...args);\n }, waitMs) as unknown as number;\n };\n}\n\ninterface ActualCorrection {\n leftCorrection: number;\n rightCorrection: number;\n}\n\n/**\n * По переданным параметрам коррекции возвращает значения отступов для текущего брейкпоинта\n * @param props Параметры коррекции\n * @param breakpoint Текуший брейкпоинт\n * @returns Объект содержащий значения отступов\n */\nexport const getActualCorrection = (props: SpacingCorrectionProps, breakpoint: Breakpoint): ActualCorrection => {\n const breakpointIndex = BREAKPOINTS_LIST.indexOf(breakpoint);\n let leftCorrection: number | undefined;\n let rightCorrection: number | undefined;\n // Проходимся по всем брейкпоинтам, начиная с текущего в сторону меньших разрешений\n for (let i = breakpointIndex; i >= 0; i--) {\n const breakpointName = BREAKPOINTS_LIST[i].toUpperCase();\n // Ключи, которые могут быть в параметрах коррекции (SpacingCorrectionProps)\n const leftCorrectionKey = `correctionLeft${breakpointName}` as keyof SpacingCorrectionProps;\n const rightCorrectionKey = `correctionRight${breakpointName}` as keyof SpacingCorrectionProps;\n const commonCorrectionKey = `correction${breakpointName}` as keyof SpacingCorrectionProps;\n // Если для текущего брейкпоинта есть параметры коррекции для левой/правой стороны, то берем их\n props[leftCorrectionKey] !== undefined &&\n leftCorrection === undefined &&\n (leftCorrection = props[leftCorrectionKey]);\n props[rightCorrectionKey] !== undefined &&\n rightCorrection === undefined &&\n (rightCorrection = props[rightCorrectionKey]);\n\n // Если для левой или правой стороны не найден параметр коррекции, то пробуем взять параметр correction для\n // брейкпоинта который сейчас обрабатываем в цикле, например correctionM\n if (props[commonCorrectionKey] !== undefined) {\n leftCorrection === undefined && (leftCorrection = props[commonCorrectionKey]);\n rightCorrection === undefined && (rightCorrection = props[commonCorrectionKey]);\n }\n\n // Если нашли значения для обеих сторон - возращаем\n if (leftCorrection !== undefined && rightCorrection !== undefined) {\n return { leftCorrection, rightCorrection };\n }\n }\n // Если не нашли значение для какой то из сторон, то берем значение из correction, без уточнения брейкпоинта\n return {\n leftCorrection: leftCorrection === undefined ? props.correction || 0 : leftCorrection,\n rightCorrection: rightCorrection === undefined ? props.correction || 0 : rightCorrection,\n };\n};\n\nexport const useInitOnce = <T>(func: () => T): T => {\n const initializedRef = useRef<T | undefined>(undefined);\n if (initializedRef.current === undefined) {\n initializedRef.current = func();\n }\n return initializedRef.current;\n};\n\n/**\n * Отдает метрики элемента галереи\n * @param scrollState стейт скролла\n * @param index индекс элемента\n * @returns метрики элемента, либо null (если элемента нет или его размеры еще не посчитаны)\n */\nexport const getItemOffset = (scrollState: ScrollState, index: number): ItemOffset | null =>\n scrollState.items.get()[index]?.current?.[OFFSET_ATTR] ?? null;\n\n/**\n * На основе стейта расчитывает флаги скрола\n * @param scrollState стейт скролла\n * @returns cостояние блокировки скролла\n */\nexport const getDisableState = (scrollState: ScrollState): ScrollDisableState => {\n const { scrollPosition, viewportWidth, contentWidth } = scrollState;\n return {\n isScrollLeftDisabled: scrollPosition.get() >= 0,\n isScrollRightDisabled: Math.abs(scrollPosition.get()) + viewportWidth.get() >= contentWidth.get(),\n };\n};\n\n/**\n * Анимирует scrollPosition с учетом границ контенера\n * @param scrollState стейт скролла\n * @param position новая позиция\n * @returns void\n */\nexport const animateScrollToPosition = (scrollState: ScrollState, position: number | null): void => {\n const { scrollPosition, viewportWidth, contentWidth } = scrollState;\n if (position === null || scrollPosition.get() === position) {\n return;\n }\n const clampedPosition = clamp(position, viewportWidth.get() - contentWidth.get(), 0);\n animate(scrollPosition, clampedPosition, {\n velocity: Math.max(scrollPosition.getVelocity(), 1),\n });\n};\n\n/**\n * scrollTo* может быть вызвана раньше чем появяться метрики элементов\n * например, scrollToIndex функция может вызвана в useEffect в tabs\n * запоминаем индекс и вызовем скролл, когда метрики будут посчитаны\n */\nexport const ensureItemReadyForScroll = (\n scrollState: ScrollState,\n index: number,\n behaviorScrollType: BehaviorScrollType = 'animate'\n): boolean => {\n const { items } = scrollState;\n const item = items.get()[index]?.current;\n if (!item || !item[OFFSET_ATTR]) {\n scrollState.indexForDeferScroll = index;\n scrollState.behaviorScrollTypeDeferScroll = behaviorScrollType;\n return false;\n }\n return true;\n};\n\n/**\n * Возвращает якорную точку отрезка в зависимости от scrollSnapAlign.\n *\n * start — левая граница элемента\n * center — центр элемента\n * end — правая граница элемента\n *\n * @param left левая граница элемента\n * @param right правая граница элемента\n * @param align режим выравнивания (scroll-snap-align)\n * @returns координата якорной точки элемента\n */\nconst getAnchorPoint = (left: number, right: number, align: ScrollSnapAlign): number => {\n let point = 0;\n switch (align) {\n case 'center':\n point = (left + right) / 2;\n break;\n case 'end':\n point = right;\n break;\n case 'start':\n default:\n point = left;\n }\n return point;\n};\n\n/**\n * Вычисляет целевую точку прокрутки в зависимости от режима scroll-snap выравнивания.\n *\n * В качестве базовой позиции используется текущее значение scrollLeft,\n * к которому добавляется смещение, зависящее от `scrollSnapAlign`:\n * - start — начало области просмотра\n * - center — центр области просмотра\n * - end — конец области просмотра\n *\n * @param state Текущее состояние скролл\n * @returns Координата целевой точки прокрутки\n */\nconst getTargetPoint = (state: ScrollState): number => {\n const scrollLeft = Math.abs(state.scrollPosition.get());\n let point = 0;\n switch (state.scrollSnapAlign) {\n case 'center':\n point = scrollLeft + state.viewportWidth.get() / 2;\n break;\n case 'end':\n point = scrollLeft + state.viewportWidth.get();\n break;\n case 'start':\n default:\n point = scrollLeft;\n }\n return point;\n};\n\n/**\n * На основе позиции, находит ближайший элемент к центру viewport\n * @param scrollState стейт скролла\n * @returns индекс найденого элемента\n */\nexport const findIndexNearestToSnapPoint = (state: ScrollState): number => {\n const items = state.items.get();\n if (items.length === 0) {\n return 0;\n }\n const targetPoint = getTargetPoint(state);\n let idx = 0;\n let minDist = Infinity;\n for (let key = 0; key < items.length; key++) {\n const element = items[key]?.current;\n if (element && element[OFFSET_ATTR]) {\n const { left, right } = element[OFFSET_ATTR];\n const anchor = getAnchorPoint(left, right, state.scrollSnapAlign);\n const dist = Math.abs(targetPoint - anchor);\n if (dist < minDist) {\n minDist = dist;\n idx = key;\n }\n }\n }\n return idx;\n};\n\ninterface ScrollBehavior {\n (scrollState: ScrollState, index: number): number | null;\n}\n\n/**\n * Определят позицию, при которой элемент будет находится на левой границе viewport\n * @param scrollState стейт скролла\n * @param index индекс элемента\n * @returns новая позиция\n */\nexport const computeStartPositionForIndex: ScrollBehavior = (scrollState, index) => {\n const { items, defaultButtonsCorrection } = scrollState;\n const itemRef = items.get()[index];\n if (!itemRef?.current) {\n return null;\n }\n const offset = itemRef.current[OFFSET_ATTR];\n return -offset.left + defaultButtonsCorrection.get();\n};\n\n/**\n * Определят позицию, при которой элемент будет находится на правой границе viewport\n * @param scrollState стейт скролла\n * @param index индекс элемента\n * @returns новая позиция\n */\nexport const computeEndPositionForIndex: ScrollBehavior = (scrollState, index) => {\n const { items, defaultButtonsCorrection, viewportWidth } = scrollState;\n const itemRef = items.get()[index];\n if (!itemRef?.current) {\n return null;\n }\n const offset = itemRef.current[OFFSET_ATTR];\n return -offset.right + viewportWidth.get() - defaultButtonsCorrection.get();\n};\n\n/**\n * Определят позицию, при которой элемент будет в центре viewport\n * @param scrollState стейт скролла\n * @param index индекс элемента\n * @returns новая позиция\n */\nexport const computeCenterPositionForIndex: ScrollBehavior = (scrollState, index) => {\n const { items, viewportWidth } = scrollState;\n const itemRef = items.get()[index];\n if (!itemRef?.current) {\n return null;\n }\n const offset = itemRef.current[OFFSET_ATTR];\n const itemWidth = offset.right - offset.left;\n const itemCenter = offset.left + itemWidth / 2;\n const viewportCenter = viewportWidth.get() / 2;\n return viewportCenter - itemCenter;\n};\n\n/**\n * Определят позицию, при которой элемент будет находится во viewport (с учетом боковых кнопок в fade)\n * @param scrollState стейт скролла\n * @param index индекс элемента\n * @returns новая позиция\n */\nexport const computePositionForIndex: ScrollBehavior = (scrollState, index) => {\n const { items, viewportWidth, scrollPosition, defaultButtonsCorrection } = scrollState;\n const itemRef = items.get()[index];\n if (!itemRef?.current) {\n return null;\n }\n const offset = itemRef.current[OFFSET_ATTR];\n const viewportLeft = -scrollPosition.get() + defaultButtonsCorrection.get();\n const viewportRight = viewportLeft + viewportWidth.get() - defaultButtonsCorrection.get();\n if (offset.left >= viewportLeft && offset.right <= viewportRight) {\n return scrollPosition.get();\n }\n if (offset.left < viewportLeft) {\n return -(offset.left - defaultButtonsCorrection.get());\n }\n return viewportWidth.get() - offset.right - defaultButtonsCorrection.get();\n};\n\n/**\n * Определят поведение \"подскрола\" ближайшего элемента\n * @param scrollState стейт скролла\n * @returns StrategyPosition\n */\nexport const computeScrollSnapBehavior = (scrollState: ScrollState): ScrollBehavior => {\n switch (scrollState.scrollSnapAlign) {\n case 'center':\n return computeCenterPositionForIndex;\n case 'start':\n return computeStartPositionForIndex;\n case 'end':\n return computeEndPositionForIndex;\n case 'none':\n default:\n return computePositionForIndex;\n }\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["src/utils.ts"],"sourcesContent":["import { useRef } from 'react';\nimport { animate } from 'motion/react';\n\nimport { clamp } from '@hh.ru/magritte-internal-custom-scroll';\nimport { Breakpoint } from '@hh.ru/magritte-ui-breakpoint';\nimport { type ScrollState, type BehaviorScrollType } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport {\n type SpacingCorrectionProps,\n type ScrollDisableState,\n type ScrollSnapAlign,\n OFFSET_ATTR,\n type ItemOffset,\n} from '@hh.ru/magritte-ui-scrollable-container/types';\n\nexport const BREAKPOINTS_LIST = [\n Breakpoint.XS,\n Breakpoint.S,\n Breakpoint.M,\n Breakpoint.L,\n Breakpoint.XL,\n Breakpoint.XXL,\n];\nexport const NO_BUTTONS_START_FROM_BREAKPOINT = Breakpoint.S;\n\nexport function debounce<T extends unknown[]>(callback: (...args: T) => void, waitMs: number): typeof callback {\n let timeout = 0;\n return (...args: T) => {\n clearTimeout(timeout);\n timeout = setTimeout(() => {\n callback(...args);\n }, waitMs) as unknown as number;\n };\n}\n\ninterface ActualCorrection {\n leftCorrection: number;\n rightCorrection: number;\n}\n\n/**\n * По переданным параметрам коррекции возвращает значения отступов для текущего брейкпоинта\n * @param props Параметры коррекции\n * @param breakpoint Текуший брейкпоинт\n * @returns Объект содержащий значения отступов\n */\nexport const getActualCorrection = (props: SpacingCorrectionProps, breakpoint: Breakpoint): ActualCorrection => {\n const breakpointIndex = BREAKPOINTS_LIST.indexOf(breakpoint);\n let leftCorrection: number | undefined;\n let rightCorrection: number | undefined;\n // Проходимся по всем брейкпоинтам, начиная с текущего в сторону меньших разрешений\n for (let i = breakpointIndex; i >= 0; i--) {\n const breakpointName = BREAKPOINTS_LIST[i].toUpperCase();\n // Ключи, которые могут быть в параметрах коррекции (SpacingCorrectionProps)\n const leftCorrectionKey = `correctionLeft${breakpointName}` as keyof SpacingCorrectionProps;\n const rightCorrectionKey = `correctionRight${breakpointName}` as keyof SpacingCorrectionProps;\n const commonCorrectionKey = `correction${breakpointName}` as keyof SpacingCorrectionProps;\n // Если для текущего брейкпоинта есть параметры коррекции для левой/правой стороны, то берем их\n props[leftCorrectionKey] !== undefined &&\n leftCorrection === undefined &&\n (leftCorrection = props[leftCorrectionKey]);\n props[rightCorrectionKey] !== undefined &&\n rightCorrection === undefined &&\n (rightCorrection = props[rightCorrectionKey]);\n\n // Если для левой или правой стороны не найден параметр коррекции, то пробуем взять параметр correction для\n // брейкпоинта который сейчас обрабатываем в цикле, например correctionM\n if (props[commonCorrectionKey] !== undefined) {\n leftCorrection === undefined && (leftCorrection = props[commonCorrectionKey]);\n rightCorrection === undefined && (rightCorrection = props[commonCorrectionKey]);\n }\n\n // Если нашли значения для обеих сторон - возращаем\n if (leftCorrection !== undefined && rightCorrection !== undefined) {\n return { leftCorrection, rightCorrection };\n }\n }\n // Если не нашли значение для какой то из сторон, то берем значение из correction, без уточнения брейкпоинта\n return {\n leftCorrection: leftCorrection === undefined ? props.correction || 0 : leftCorrection,\n rightCorrection: rightCorrection === undefined ? props.correction || 0 : rightCorrection,\n };\n};\n\nexport const useInitOnce = <T>(func: () => T): T => {\n const initializedRef = useRef<T | undefined>(undefined);\n if (initializedRef.current === undefined) {\n initializedRef.current = func();\n }\n return initializedRef.current;\n};\n\n/**\n * Отдает метрики элемента галереи\n * @param scrollState стейт скролла\n * @param index индекс элемента\n * @returns метрики элемента, либо null (если элемента нет или его размеры еще не посчитаны)\n */\nexport const getItemOffset = (scrollState: ScrollState, index: number): ItemOffset | null =>\n scrollState.items.get()[index]?.current?.[OFFSET_ATTR] ?? null;\n\n/**\n * На основе стейта расчитывает флаги скрола\n * @param scrollState стейт скролла\n * @returns cостояние блокировки скролла\n */\nexport const getDisableState = (scrollState: ScrollState): ScrollDisableState => {\n const { scrollPosition, viewportWidth, contentWidth } = scrollState;\n return {\n isScrollLeftDisabled: scrollPosition.get() >= 0,\n isScrollRightDisabled: Math.abs(scrollPosition.get()) + viewportWidth.get() >= contentWidth.get(),\n };\n};\n\n/**\n * Анимирует scrollPosition с учетом границ контенера\n * @param scrollState стейт скролла\n * @param position новая позиция\n * @returns void\n */\nexport const animateScrollToPosition = (scrollState: ScrollState, position: number | null): void => {\n const { scrollPosition, viewportWidth, contentWidth } = scrollState;\n if (position === null || scrollPosition.get() === position) {\n return;\n }\n const clampedPosition = clamp(position, viewportWidth.get() - contentWidth.get(), 0);\n animate(scrollPosition, clampedPosition, {\n velocity: Math.max(scrollPosition.getVelocity(), 1),\n });\n};\n\n/**\n * scrollTo* может быть вызвана раньше чем появяться метрики элементов\n * например, scrollToIndex функция может вызвана в useEffect в tabs\n * запоминаем индекс и вызовем скролл, когда метрики будут посчитаны\n */\nexport const ensureItemReadyForScroll = (\n scrollState: ScrollState,\n index: number,\n behaviorScrollType: BehaviorScrollType = 'animate'\n): boolean => {\n const { items } = scrollState;\n const item = items.get()[index]?.current;\n if (!item || !item[OFFSET_ATTR]) {\n scrollState.indexForDeferScroll = index;\n scrollState.behaviorScrollTypeDeferScroll = behaviorScrollType;\n return false;\n }\n return true;\n};\n\n/**\n * Возвращает якорную точку отрезка в зависимости от scrollSnapAlign.\n *\n * start — левая граница элемента\n * center — центр элемента\n * end — правая граница элемента\n *\n * @param left левая граница элемента\n * @param right правая граница элемента\n * @param align режим выравнивания (scroll-snap-align)\n * @returns координата якорной точки элемента\n */\nconst getAnchorPoint = (left: number, right: number, align: ScrollSnapAlign): number => {\n let point = 0;\n switch (align) {\n case 'center':\n point = (left + right) / 2;\n break;\n case 'end':\n point = right;\n break;\n case 'start':\n default:\n point = left;\n }\n return point;\n};\n\n/**\n * Вычисляет целевую точку прокрутки в зависимости от режима scroll-snap выравнивания.\n *\n * В качестве базовой позиции используется текущее значение scrollLeft,\n * к которому добавляется смещение, зависящее от `scrollSnapAlign`:\n * - start — начало области просмотра\n * - center — центр области просмотра\n * - end — конец области просмотра\n *\n * @param state Текущее состояние скролл\n * @returns Координата целевой точки прокрутки\n */\nconst getTargetPoint = (state: ScrollState): number => {\n const scrollLeft = Math.abs(state.scrollPosition.get());\n let point = 0;\n switch (state.scrollSnapAlign) {\n case 'center':\n point = scrollLeft + state.viewportWidth.get() / 2;\n break;\n case 'end':\n point = scrollLeft + state.viewportWidth.get();\n break;\n case 'start':\n default:\n point = scrollLeft;\n }\n return point;\n};\n\n/**\n * На основе позиции, находит ближайший элемент к центру viewport\n * @param scrollState стейт скролла\n * @returns индекс найденого элемента\n */\nexport const findIndexNearestToSnapPoint = (state: ScrollState): number => {\n const items = state.items.get();\n if (items.length === 0) {\n return 0;\n }\n const targetPoint = getTargetPoint(state);\n let idx = 0;\n let minDist = Infinity;\n for (let key = 0; key < items.length; key++) {\n const element = items[key]?.current;\n if (element && element[OFFSET_ATTR]) {\n const { left, right } = element[OFFSET_ATTR];\n const anchor = getAnchorPoint(left, right, state.scrollSnapAlign);\n const dist = Math.abs(targetPoint - anchor);\n if (dist < minDist) {\n minDist = dist;\n idx = key;\n }\n }\n }\n return idx;\n};\n\ninterface ScrollBehavior {\n (scrollState: ScrollState, index: number): number | null;\n}\n\n/**\n * Определят позицию, при которой элемент будет находится на левой границе viewport\n * @param scrollState стейт скролла\n * @param index индекс элемента\n * @returns новая позиция\n */\nexport const computeStartPositionForIndex: ScrollBehavior = (scrollState, index) => {\n const { items, defaultButtonsCorrection } = scrollState;\n const itemRef = items.get()[index];\n if (!itemRef?.current) {\n return null;\n }\n const offset = itemRef.current[OFFSET_ATTR];\n return -offset.left + defaultButtonsCorrection.get();\n};\n\n/**\n * Определят позицию, при которой элемент будет находится на правой границе viewport\n * @param scrollState стейт скролла\n * @param index индекс элемента\n * @returns новая позиция\n */\nexport const computeEndPositionForIndex: ScrollBehavior = (scrollState, index) => {\n const { items, defaultButtonsCorrection, viewportWidth } = scrollState;\n const itemRef = items.get()[index];\n if (!itemRef?.current) {\n return null;\n }\n const offset = itemRef.current[OFFSET_ATTR];\n return -offset.right + viewportWidth.get() - defaultButtonsCorrection.get();\n};\n\n/**\n * Определят позицию, при которой элемент будет в центре viewport\n * @param scrollState стейт скролла\n * @param index индекс элемента\n * @returns новая позиция\n */\nexport const computeCenterPositionForIndex: ScrollBehavior = (scrollState, index) => {\n const { items, viewportWidth } = scrollState;\n const itemRef = items.get()[index];\n if (!itemRef?.current) {\n return null;\n }\n const offset = itemRef.current[OFFSET_ATTR];\n const itemWidth = offset.right - offset.left;\n const itemCenter = offset.left + itemWidth / 2;\n const viewportCenter = viewportWidth.get() / 2;\n return viewportCenter - itemCenter;\n};\n\n/**\n * Определят позицию, при которой элемент будет находится во viewport (с учетом боковых кнопок в fade)\n * @param scrollState стейт скролла\n * @param index индекс элемента\n * @returns новая позиция\n */\nexport const computePositionForIndex: ScrollBehavior = (scrollState, index) => {\n const { items, viewportWidth, scrollPosition, defaultButtonsCorrection } = scrollState;\n const itemRef = items.get()[index];\n if (!itemRef?.current) {\n return null;\n }\n const offset = itemRef.current[OFFSET_ATTR];\n const viewportLeft = -scrollPosition.get() + defaultButtonsCorrection.get();\n const viewportRight = viewportLeft + viewportWidth.get() - defaultButtonsCorrection.get();\n if (offset.left >= viewportLeft && offset.right <= viewportRight) {\n return scrollPosition.get();\n }\n if (offset.left < viewportLeft) {\n return -(offset.left - defaultButtonsCorrection.get());\n }\n return viewportWidth.get() - offset.right - defaultButtonsCorrection.get();\n};\n\n/**\n * Определят поведение \"подскрола\" ближайшего элемента\n * @param scrollState стейт скролла\n * @returns StrategyPosition\n */\nexport const computeScrollSnapBehavior = (scrollState: ScrollState): ScrollBehavior => {\n switch (scrollState.scrollSnapAlign) {\n case 'center':\n return computeCenterPositionForIndex;\n case 'start':\n return computeStartPositionForIndex;\n case 'end':\n return computeEndPositionForIndex;\n case 'none':\n default:\n return computePositionForIndex;\n }\n};\n"],"names":[],"mappings":";;;;;;AAcO,MAAM,gBAAmB,GAAA;AAAA,EAC5B,UAAW,CAAA,EAAA;AAAA,EACX,UAAW,CAAA,CAAA;AAAA,EACX,UAAW,CAAA,CAAA;AAAA,EACX,UAAW,CAAA,CAAA;AAAA,EACX,UAAW,CAAA,EAAA;AAAA,EACX,UAAW,CAAA,GAAA;AACf,EAAA;AACO,MAAM,mCAAmC,UAAW,CAAA,EAAA;AAEpD,SAAS,QAAA,CAA8B,UAAgC,MAAiC,EAAA;AAC3G,EAAA,IAAI,OAAU,GAAA,CAAA,CAAA;AACd,EAAA,OAAO,IAAI,IAAY,KAAA;AACnB,IAAA,YAAA,CAAa,OAAO,CAAA,CAAA;AACpB,IAAA,OAAA,GAAU,WAAW,MAAM;AACvB,MAAA,QAAA,CAAS,GAAG,IAAI,CAAA,CAAA;AAAA,OACjB,MAAM,CAAA,CAAA;AAAA,GACb,CAAA;AACJ,CAAA;AAaa,MAAA,mBAAA,GAAsB,CAAC,KAAA,EAA+B,UAA6C,KAAA;AAC5G,EAAM,MAAA,eAAA,GAAkB,gBAAiB,CAAA,OAAA,CAAQ,UAAU,CAAA,CAAA;AAC3D,EAAI,IAAA,cAAA,CAAA;AACJ,EAAI,IAAA,eAAA,CAAA;AAEJ,EAAA,KAAA,IAAS,CAAI,GAAA,eAAA,EAAiB,CAAK,IAAA,CAAA,EAAG,CAAK,EAAA,EAAA;AACvC,IAAA,MAAM,cAAiB,GAAA,gBAAA,CAAiB,CAAC,CAAA,CAAE,WAAY,EAAA,CAAA;AAEvD,IAAM,MAAA,iBAAA,GAAoB,iBAAiB,cAAc,CAAA,CAAA,CAAA;AACzD,IAAM,MAAA,kBAAA,GAAqB,kBAAkB,cAAc,CAAA,CAAA,CAAA;AAC3D,IAAM,MAAA,mBAAA,GAAsB,aAAa,cAAc,CAAA,CAAA,CAAA;AAEvD,IAAA,KAAA,CAAM,iBAAiB,CAAM,KAAA,KAAA,CAAA,IACzB,mBAAmB,KAClB,CAAA,KAAA,cAAA,GAAiB,MAAM,iBAAiB,CAAA,CAAA,CAAA;AAC7C,IAAA,KAAA,CAAM,kBAAkB,CAAM,KAAA,KAAA,CAAA,IAC1B,oBAAoB,KACnB,CAAA,KAAA,eAAA,GAAkB,MAAM,kBAAkB,CAAA,CAAA,CAAA;AAI/C,IAAI,IAAA,KAAA,CAAM,mBAAmB,CAAA,KAAM,KAAW,CAAA,EAAA;AAC1C,MAAmB,cAAA,KAAA,KAAA,CAAA,KAAc,cAAiB,GAAA,KAAA,CAAM,mBAAmB,CAAA,CAAA,CAAA;AAC3E,MAAoB,eAAA,KAAA,KAAA,CAAA,KAAc,eAAkB,GAAA,KAAA,CAAM,mBAAmB,CAAA,CAAA,CAAA;AAAA,KACjF;AAGA,IAAI,IAAA,cAAA,KAAmB,KAAa,CAAA,IAAA,eAAA,KAAoB,KAAW,CAAA,EAAA;AAC/D,MAAO,OAAA,EAAE,gBAAgB,eAAgB,EAAA,CAAA;AAAA,KAC7C;AAAA,GACJ;AAEA,EAAO,OAAA;AAAA,IACH,cAAgB,EAAA,cAAA,KAAmB,KAAY,CAAA,GAAA,KAAA,CAAM,cAAc,CAAI,GAAA,cAAA;AAAA,IACvE,eAAiB,EAAA,eAAA,KAAoB,KAAY,CAAA,GAAA,KAAA,CAAM,cAAc,CAAI,GAAA,eAAA;AAAA,GAC7E,CAAA;AACJ,EAAA;AAEa,MAAA,WAAA,GAAc,CAAI,IAAqB,KAAA;AAChD,EAAM,MAAA,cAAA,GAAiB,OAAsB,KAAS,CAAA,CAAA,CAAA;AACtD,EAAI,IAAA,cAAA,CAAe,YAAY,KAAW,CAAA,EAAA;AACtC,IAAA,cAAA,CAAe,UAAU,IAAK,EAAA,CAAA;AAAA,GAClC;AACA,EAAA,OAAO,cAAe,CAAA,OAAA,CAAA;AAC1B,EAAA;AAQO,MAAM,aAAgB,GAAA,CAAC,WAA0B,EAAA,KAAA,KACpD,WAAY,CAAA,KAAA,CAAM,GAAI,EAAA,CAAE,KAAK,CAAA,EAAG,OAAU,GAAA,WAAW,CAAK,IAAA,KAAA;AAOjD,MAAA,eAAA,GAAkB,CAAC,WAAiD,KAAA;AAC7E,EAAA,MAAM,EAAE,cAAA,EAAgB,aAAe,EAAA,YAAA,EAAiB,GAAA,WAAA,CAAA;AACxD,EAAO,OAAA;AAAA,IACH,oBAAA,EAAsB,cAAe,CAAA,GAAA,EAAS,IAAA,CAAA;AAAA,IAC9C,qBAAA,EAAuB,IAAK,CAAA,GAAA,CAAI,cAAe,CAAA,GAAA,EAAK,CAAA,GAAI,aAAc,CAAA,GAAA,EAAS,IAAA,YAAA,CAAa,GAAI,EAAA;AAAA,GACpG,CAAA;AACJ,EAAA;AAQa,MAAA,uBAAA,GAA0B,CAAC,WAAA,EAA0B,QAAkC,KAAA;AAChG,EAAA,MAAM,EAAE,cAAA,EAAgB,aAAe,EAAA,YAAA,EAAiB,GAAA,WAAA,CAAA;AACxD,EAAA,IAAI,QAAa,KAAA,IAAA,IAAQ,cAAe,CAAA,GAAA,OAAU,QAAU,EAAA;AACxD,IAAA,OAAA;AAAA,GACJ;AACA,EAAM,MAAA,eAAA,GAAkB,MAAM,QAAU,EAAA,aAAA,CAAc,KAAQ,GAAA,YAAA,CAAa,GAAI,EAAA,EAAG,CAAC,CAAA,CAAA;AACnF,EAAA,OAAA,CAAQ,gBAAgB,eAAiB,EAAA;AAAA,IACrC,UAAU,IAAK,CAAA,GAAA,CAAI,cAAe,CAAA,WAAA,IAAe,CAAC,CAAA;AAAA,GACrD,CAAA,CAAA;AACL,EAAA;AAOO,MAAM,wBAA2B,GAAA,CACpC,WACA,EAAA,KAAA,EACA,qBAAyC,SAC/B,KAAA;AACV,EAAM,MAAA,EAAE,OAAU,GAAA,WAAA,CAAA;AAClB,EAAA,MAAM,IAAO,GAAA,KAAA,CAAM,GAAI,EAAA,CAAE,KAAK,CAAG,EAAA,OAAA,CAAA;AACjC,EAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,IAAA,CAAK,WAAW,CAAG,EAAA;AAC7B,IAAA,WAAA,CAAY,mBAAsB,GAAA,KAAA,CAAA;AAClC,IAAA,WAAA,CAAY,6BAAgC,GAAA,kBAAA,CAAA;AAC5C,IAAO,OAAA,KAAA,CAAA;AAAA,GACX;AACA,EAAO,OAAA,IAAA,CAAA;AACX,EAAA;AAcA,MAAM,cAAiB,GAAA,CAAC,IAAc,EAAA,KAAA,EAAe,KAAmC,KAAA;AACpF,EAAA,IAAI,KAAQ,GAAA,CAAA,CAAA;AACZ,EAAA,QAAQ,KAAO;AAAA,IACX,KAAK,QAAA;AACD,MAAA,KAAA,GAAA,CAAS,OAAO,KAAS,IAAA,CAAA,CAAA;AACzB,MAAA,MAAA;AAAA,IACJ,KAAK,KAAA;AACD,MAAQ,KAAA,GAAA,KAAA,CAAA;AACR,MAAA,MAAA;AAAA,IACJ,KAAK,OAAA,CAAA;AAAA,IACL;AACI,MAAQ,KAAA,GAAA,IAAA,CAAA;AAAA,GAChB;AACA,EAAO,OAAA,KAAA,CAAA;AACX,CAAA,CAAA;AAcA,MAAM,cAAA,GAAiB,CAAC,KAA+B,KAAA;AACnD,EAAA,MAAM,aAAa,IAAK,CAAA,GAAA,CAAI,KAAM,CAAA,cAAA,CAAe,KAAK,CAAA,CAAA;AACtD,EAAA,IAAI,KAAQ,GAAA,CAAA,CAAA;AACZ,EAAA,QAAQ,MAAM,eAAiB;AAAA,IAC3B,KAAK,QAAA;AACD,MAAA,KAAA,GAAQ,UAAa,GAAA,KAAA,CAAM,aAAc,CAAA,GAAA,EAAQ,GAAA,CAAA,CAAA;AACjD,MAAA,MAAA;AAAA,IACJ,KAAK,KAAA;AACD,MAAQ,KAAA,GAAA,UAAA,GAAa,KAAM,CAAA,aAAA,CAAc,GAAI,EAAA,CAAA;AAC7C,MAAA,MAAA;AAAA,IACJ,KAAK,OAAA,CAAA;AAAA,IACL;AACI,MAAQ,KAAA,GAAA,UAAA,CAAA;AAAA,GAChB;AACA,EAAO,OAAA,KAAA,CAAA;AACX,CAAA,CAAA;AAOa,MAAA,2BAAA,GAA8B,CAAC,KAA+B,KAAA;AACvE,EAAM,MAAA,KAAA,GAAQ,KAAM,CAAA,KAAA,CAAM,GAAI,EAAA,CAAA;AAC9B,EAAI,IAAA,KAAA,CAAM,WAAW,CAAG,EAAA;AACpB,IAAO,OAAA,CAAA,CAAA;AAAA,GACX;AACA,EAAM,MAAA,WAAA,GAAc,eAAe,KAAK,CAAA,CAAA;AACxC,EAAA,IAAI,GAAM,GAAA,CAAA,CAAA;AACV,EAAA,IAAI,OAAU,GAAA,QAAA,CAAA;AACd,EAAA,KAAA,IAAS,GAAM,GAAA,CAAA,EAAG,GAAM,GAAA,KAAA,CAAM,QAAQ,GAAO,EAAA,EAAA;AACzC,IAAM,MAAA,OAAA,GAAU,KAAM,CAAA,GAAG,CAAG,EAAA,OAAA,CAAA;AAC5B,IAAI,IAAA,OAAA,IAAW,OAAQ,CAAA,WAAW,CAAG,EAAA;AACjC,MAAA,MAAM,EAAE,IAAA,EAAM,KAAM,EAAA,GAAI,QAAQ,WAAW,CAAA,CAAA;AAC3C,MAAA,MAAM,MAAS,GAAA,cAAA,CAAe,IAAM,EAAA,KAAA,EAAO,MAAM,eAAe,CAAA,CAAA;AAChE,MAAA,MAAM,IAAO,GAAA,IAAA,CAAK,GAAI,CAAA,WAAA,GAAc,MAAM,CAAA,CAAA;AAC1C,MAAA,IAAI,OAAO,OAAS,EAAA;AAChB,QAAU,OAAA,GAAA,IAAA,CAAA;AACV,QAAM,GAAA,GAAA,GAAA,CAAA;AAAA,OACV;AAAA,KACJ;AAAA,GACJ;AACA,EAAO,OAAA,GAAA,CAAA;AACX,EAAA;AAYa,MAAA,4BAAA,GAA+C,CAAC,WAAA,EAAa,KAAU,KAAA;AAChF,EAAM,MAAA,EAAE,KAAO,EAAA,wBAAA,EAA6B,GAAA,WAAA,CAAA;AAC5C,EAAA,MAAM,OAAU,GAAA,KAAA,CAAM,GAAI,EAAA,CAAE,KAAK,CAAA,CAAA;AACjC,EAAI,IAAA,CAAC,SAAS,OAAS,EAAA;AACnB,IAAO,OAAA,IAAA,CAAA;AAAA,GACX;AACA,EAAM,MAAA,MAAA,GAAS,OAAQ,CAAA,OAAA,CAAQ,WAAW,CAAA,CAAA;AAC1C,EAAA,OAAO,CAAC,MAAA,CAAO,IAAO,GAAA,wBAAA,CAAyB,GAAI,EAAA,CAAA;AACvD,EAAA;AAQa,MAAA,0BAAA,GAA6C,CAAC,WAAA,EAAa,KAAU,KAAA;AAC9E,EAAA,MAAM,EAAE,KAAA,EAAO,wBAA0B,EAAA,aAAA,EAAkB,GAAA,WAAA,CAAA;AAC3D,EAAA,MAAM,OAAU,GAAA,KAAA,CAAM,GAAI,EAAA,CAAE,KAAK,CAAA,CAAA;AACjC,EAAI,IAAA,CAAC,SAAS,OAAS,EAAA;AACnB,IAAO,OAAA,IAAA,CAAA;AAAA,GACX;AACA,EAAM,MAAA,MAAA,GAAS,OAAQ,CAAA,OAAA,CAAQ,WAAW,CAAA,CAAA;AAC1C,EAAA,OAAO,CAAC,MAAO,CAAA,KAAA,GAAQ,cAAc,GAAI,EAAA,GAAI,yBAAyB,GAAI,EAAA,CAAA;AAC9E,EAAA;AAQa,MAAA,6BAAA,GAAgD,CAAC,WAAA,EAAa,KAAU,KAAA;AACjF,EAAM,MAAA,EAAE,KAAO,EAAA,aAAA,EAAkB,GAAA,WAAA,CAAA;AACjC,EAAA,MAAM,OAAU,GAAA,KAAA,CAAM,GAAI,EAAA,CAAE,KAAK,CAAA,CAAA;AACjC,EAAI,IAAA,CAAC,SAAS,OAAS,EAAA;AACnB,IAAO,OAAA,IAAA,CAAA;AAAA,GACX;AACA,EAAM,MAAA,MAAA,GAAS,OAAQ,CAAA,OAAA,CAAQ,WAAW,CAAA,CAAA;AAC1C,EAAM,MAAA,SAAA,GAAY,MAAO,CAAA,KAAA,GAAQ,MAAO,CAAA,IAAA,CAAA;AACxC,EAAM,MAAA,UAAA,GAAa,MAAO,CAAA,IAAA,GAAO,SAAY,GAAA,CAAA,CAAA;AAC7C,EAAM,MAAA,cAAA,GAAiB,aAAc,CAAA,GAAA,EAAQ,GAAA,CAAA,CAAA;AAC7C,EAAA,OAAO,cAAiB,GAAA,UAAA,CAAA;AAC5B,EAAA;AAQa,MAAA,uBAAA,GAA0C,CAAC,WAAA,EAAa,KAAU,KAAA;AAC3E,EAAA,MAAM,EAAE,KAAA,EAAO,aAAe,EAAA,cAAA,EAAgB,0BAA6B,GAAA,WAAA,CAAA;AAC3E,EAAA,MAAM,OAAU,GAAA,KAAA,CAAM,GAAI,EAAA,CAAE,KAAK,CAAA,CAAA;AACjC,EAAI,IAAA,CAAC,SAAS,OAAS,EAAA;AACnB,IAAO,OAAA,IAAA,CAAA;AAAA,GACX;AACA,EAAM,MAAA,MAAA,GAAS,OAAQ,CAAA,OAAA,CAAQ,WAAW,CAAA,CAAA;AAC1C,EAAA,MAAM,eAAe,CAAC,cAAA,CAAe,GAAI,EAAA,GAAI,yBAAyB,GAAI,EAAA,CAAA;AAC1E,EAAA,MAAM,gBAAgB,YAAe,GAAA,aAAA,CAAc,GAAI,EAAA,GAAI,yBAAyB,GAAI,EAAA,CAAA;AACxF,EAAA,IAAI,MAAO,CAAA,IAAA,IAAQ,YAAgB,IAAA,MAAA,CAAO,SAAS,aAAe,EAAA;AAC9D,IAAA,OAAO,eAAe,GAAI,EAAA,CAAA;AAAA,GAC9B;AACA,EAAI,IAAA,MAAA,CAAO,OAAO,YAAc,EAAA;AAC5B,IAAA,OAAO,EAAE,MAAA,CAAO,IAAO,GAAA,wBAAA,CAAyB,GAAI,EAAA,CAAA,CAAA;AAAA,GACxD;AACA,EAAA,OAAO,cAAc,GAAI,EAAA,GAAI,MAAO,CAAA,KAAA,GAAQ,yBAAyB,GAAI,EAAA,CAAA;AAC7E,EAAA;AAOa,MAAA,yBAAA,GAA4B,CAAC,WAA6C,KAAA;AACnF,EAAA,QAAQ,YAAY,eAAiB;AAAA,IACjC,KAAK,QAAA;AACD,MAAO,OAAA,6BAAA,CAAA;AAAA,IACX,KAAK,OAAA;AACD,MAAO,OAAA,4BAAA,CAAA;AAAA,IACX,KAAK,KAAA;AACD,MAAO,OAAA,0BAAA,CAAA;AAAA,IACX,KAAK,MAAA,CAAA;AAAA,IACL;AACI,MAAO,OAAA,uBAAA,CAAA;AAAA,GACf;AACJ;;;;"}
|