@hh.ru/magritte-ui-scrollable-container 6.6.0 → 6.7.0
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/ScrollableContainer.js +2 -2
- package/ScrollableContainerDefaultLayout.js +1 -1
- package/ScrollableContainerDotPages.d.ts +1 -1
- package/ScrollableContainerDotPages.js +31 -24
- package/ScrollableContainerDotPages.js.map +1 -1
- package/ScrollableContainerGallery.js +1 -1
- package/ScrollableItem.js +1 -1
- package/index.css +13 -13
- package/index.d.ts +1 -1
- package/index.js +2 -2
- package/index.mock.d.ts +1 -1
- package/index.mock.js +1 -1
- package/index.mock.js.map +1 -1
- package/package.json +3 -3
- package/scrollableContainer-DMskt4X2.js +5 -0
- package/scrollableContainer-DMskt4X2.js.map +1 -0
- package/types.d.ts +12 -0
- package/types.js.map +1 -1
- package/utils.d.ts +17 -0
- package/utils.js +27 -1
- package/utils.js.map +1 -1
- package/scrollableContainer-C_ZfFVZw.js +0 -5
- package/scrollableContainer-C_ZfFVZw.js.map +0 -1
package/ScrollableContainer.js
CHANGED
|
@@ -11,14 +11,14 @@ import { ScrollableContainerGallery } from './ScrollableContainerGallery.js';
|
|
|
11
11
|
import { ScrollableItem } from './ScrollableItem.js';
|
|
12
12
|
import { useScrollableControlsWithState } from './useScrollableControls.js';
|
|
13
13
|
import { getActualCorrection, useInitOnce } from './utils.js';
|
|
14
|
-
import { s as styles } from './scrollableContainer-
|
|
14
|
+
import { s as styles } from './scrollableContainer-DMskt4X2.js';
|
|
15
15
|
import 'motion/react';
|
|
16
16
|
import './ObservableValue.js';
|
|
17
17
|
import '@hh.ru/magritte-common-use-translation';
|
|
18
18
|
import '@hh.ru/magritte-ui-icon/icon';
|
|
19
|
-
import '@hh.ru/magritte-internal-custom-scroll/initScrollHandlers';
|
|
20
19
|
import '@hh.ru/magritte-ui-dot-pages';
|
|
21
20
|
import '@hh.ru/magritte-ui-spacing';
|
|
21
|
+
import '@hh.ru/magritte-internal-custom-scroll/initScrollHandlers';
|
|
22
22
|
import './useScrollContainer.js';
|
|
23
23
|
import '@hh.ru/magritte-common-func-utils';
|
|
24
24
|
import '@hh.ru/magritte-internal-custom-scroll';
|
|
@@ -9,7 +9,7 @@ import { ChevronLeftOutlinedSize24, ChevronRightOutlinedSize24 } from '@hh.ru/ma
|
|
|
9
9
|
import { useScrollState } from './ScrollStateProvider.js';
|
|
10
10
|
import { ScrollableContainerLeft, ScrollableContainerRight } from './ScrollableContainerButton.js';
|
|
11
11
|
import { BREAKPOINTS_LIST, NO_BUTTONS_START_FROM_BREAKPOINT, useInitOnce } from './utils.js';
|
|
12
|
-
import { s as styles } from './scrollableContainer-
|
|
12
|
+
import { s as styles } from './scrollableContainer-DMskt4X2.js';
|
|
13
13
|
import './ObservableValue.js';
|
|
14
14
|
import './useScrollableControls.js';
|
|
15
15
|
import '@hh.ru/magritte-internal-custom-scroll';
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import './index.css';
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
3
|
import { useState, useRef, useEffect } from 'react';
|
|
4
|
-
import { clamp } from '@hh.ru/magritte-internal-custom-scroll/initScrollHandlers';
|
|
5
4
|
import { DotPages } from '@hh.ru/magritte-ui-dot-pages';
|
|
6
5
|
import { useScrollState } from './ScrollStateProvider.js';
|
|
7
|
-
import { useInitOnce, findNearestSnapIndex } from './utils.js';
|
|
6
|
+
import { useInitOnce, computePagesCount, findActivePageIndex, findNearestSnapIndex } from './utils.js';
|
|
8
7
|
import { VSpacing } from '@hh.ru/magritte-ui-spacing';
|
|
9
|
-
import { s as styles } from './scrollableContainer-
|
|
8
|
+
import { s as styles } from './scrollableContainer-DMskt4X2.js';
|
|
10
9
|
import 'motion/react';
|
|
11
10
|
import './ObservableValue.js';
|
|
12
11
|
import '@hh.ru/magritte-internal-custom-scroll';
|
|
@@ -14,48 +13,56 @@ import '@hh.ru/magritte-ui-breakpoint';
|
|
|
14
13
|
import './types.js';
|
|
15
14
|
|
|
16
15
|
const DEFAULT_DOT = 1;
|
|
16
|
+
const getDotsState = (scrollState, mode) => {
|
|
17
|
+
if (mode === "pages") {
|
|
18
|
+
const count2 = computePagesCount(scrollState);
|
|
19
|
+
return { count: count2, activeIndex: count2 > 0 ? findActivePageIndex(scrollState, count2) : 0 };
|
|
20
|
+
}
|
|
21
|
+
const count = scrollState.items.get().length;
|
|
22
|
+
return { count, activeIndex: count > 0 ? findNearestSnapIndex(scrollState) : 0 };
|
|
23
|
+
};
|
|
17
24
|
const ScrollableContainerDotPages = ({
|
|
25
|
+
mode = "items",
|
|
18
26
|
onChangeDot,
|
|
19
27
|
dotPagesProps,
|
|
20
28
|
offsetTop = 8
|
|
21
29
|
}) => {
|
|
22
30
|
const scrollState = useScrollState();
|
|
23
31
|
const [activeDot, setActiveDot] = useState(DEFAULT_DOT);
|
|
24
|
-
const [
|
|
32
|
+
const [dotsCount, setDotsCount] = useState(0);
|
|
25
33
|
const activeDotRef = useRef(DEFAULT_DOT);
|
|
34
|
+
const dotsCountRef = useRef(0);
|
|
26
35
|
const onChangeDotRef = useRef(onChangeDot);
|
|
27
36
|
onChangeDotRef.current = onChangeDot;
|
|
28
|
-
const
|
|
29
|
-
|
|
37
|
+
const modeRef = useRef(mode);
|
|
38
|
+
modeRef.current = mode;
|
|
39
|
+
const updateDots = useInitOnce(() => () => {
|
|
40
|
+
const { count, activeIndex } = getDotsState(scrollState, modeRef.current);
|
|
41
|
+
if (count !== dotsCountRef.current) {
|
|
42
|
+
dotsCountRef.current = count;
|
|
43
|
+
setDotsCount(count);
|
|
44
|
+
}
|
|
45
|
+
const dot = activeIndex + 1;
|
|
46
|
+
if (count === 0 || dot === activeDotRef.current) {
|
|
30
47
|
return;
|
|
31
48
|
}
|
|
32
49
|
setActiveDot(dot);
|
|
33
50
|
onChangeDotRef.current?.(dot);
|
|
34
51
|
activeDotRef.current = dot;
|
|
35
52
|
});
|
|
36
|
-
const updateActiveDot = useInitOnce(() => () => {
|
|
37
|
-
if (scrollState.items.get().length === 0) {
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
setDotAndEmitOnChange(findNearestSnapIndex(scrollState) + 1);
|
|
41
|
-
});
|
|
42
53
|
useEffect(() => {
|
|
54
|
+
updateDots();
|
|
43
55
|
const unsubscribe = [
|
|
44
|
-
scrollState.scrollPosition.on("change",
|
|
45
|
-
scrollState.items.on("change",
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
setDotAndEmitOnChange(clamp(activeDotRef.current, 0, items.length - 1));
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
updateActiveDot();
|
|
52
|
-
})
|
|
56
|
+
scrollState.scrollPosition.on("change", updateDots),
|
|
57
|
+
scrollState.items.on("change", updateDots),
|
|
58
|
+
scrollState.viewportWidth.on("change", updateDots),
|
|
59
|
+
scrollState.contentWidth.on("change", updateDots)
|
|
53
60
|
];
|
|
54
61
|
return () => {
|
|
55
62
|
unsubscribe.forEach((fn) => fn());
|
|
56
63
|
};
|
|
57
|
-
}, [scrollState,
|
|
58
|
-
if (
|
|
64
|
+
}, [scrollState, updateDots, mode]);
|
|
65
|
+
if (dotsCount === 0) {
|
|
59
66
|
return null;
|
|
60
67
|
}
|
|
61
68
|
return /* @__PURE__ */ jsxs("div", { children: [
|
|
@@ -64,7 +71,7 @@ const ScrollableContainerDotPages = ({
|
|
|
64
71
|
DotPages,
|
|
65
72
|
{
|
|
66
73
|
active: activeDot,
|
|
67
|
-
count:
|
|
74
|
+
count: dotsCount,
|
|
68
75
|
"data-qa": dotPagesProps?.["data-qa"] || "scrollable-container__dot-pages",
|
|
69
76
|
...dotPagesProps
|
|
70
77
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScrollableContainerDotPages.js","sources":["src/ScrollableContainerDotPages.tsx"],"sourcesContent":["import { type FC, useState, useEffect, useRef } from 'react';\n\nimport {
|
|
1
|
+
{"version":3,"file":"ScrollableContainerDotPages.js","sources":["src/ScrollableContainerDotPages.tsx"],"sourcesContent":["import { type FC, useState, useEffect, useRef } from 'react';\n\nimport { DotPages } from '@hh.ru/magritte-ui-dot-pages';\nimport { type ScrollState, useScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport {\n type ScrollableContainerDotPagesMode,\n type ScrollableContainerDotPagesProps,\n} from '@hh.ru/magritte-ui-scrollable-container/types';\nimport {\n useInitOnce,\n findNearestSnapIndex,\n computePagesCount,\n findActivePageIndex,\n} from '@hh.ru/magritte-ui-scrollable-container/utils';\nimport { VSpacing } from '@hh.ru/magritte-ui-spacing';\n\nimport styles from './scrollableContainer.less';\n\nconst DEFAULT_DOT = 1;\n\ninterface DotsState {\n count: number;\n activeIndex: number;\n}\n\nconst getDotsState = (scrollState: ScrollState, mode: ScrollableContainerDotPagesMode): DotsState => {\n if (mode === 'pages') {\n const count = computePagesCount(scrollState);\n return { count, activeIndex: count > 0 ? findActivePageIndex(scrollState, count) : 0 };\n }\n const count = scrollState.items.get().length;\n return { count, activeIndex: count > 0 ? findNearestSnapIndex(scrollState) : 0 };\n};\n\nexport const ScrollableContainerDotPages: FC<ScrollableContainerDotPagesProps> = ({\n mode = 'items',\n onChangeDot,\n dotPagesProps,\n offsetTop = 8,\n}) => {\n const scrollState = useScrollState();\n const [activeDot, setActiveDot] = useState(DEFAULT_DOT);\n const [dotsCount, setDotsCount] = useState(0);\n const activeDotRef = useRef(DEFAULT_DOT);\n const dotsCountRef = useRef(0);\n const onChangeDotRef = useRef(onChangeDot);\n onChangeDotRef.current = onChangeDot;\n const modeRef = useRef(mode);\n modeRef.current = mode;\n\n const updateDots = useInitOnce(() => () => {\n const { count, activeIndex } = getDotsState(scrollState, modeRef.current);\n // вызывается на каждый кадр прокрутки — стейт трогаем только при изменении\n if (count !== dotsCountRef.current) {\n dotsCountRef.current = count;\n setDotsCount(count);\n }\n const dot = activeIndex + 1;\n if (count === 0 || dot === activeDotRef.current) {\n return;\n }\n setActiveDot(dot);\n onChangeDotRef.current?.(dot);\n activeDotRef.current = dot;\n });\n\n useEffect(() => {\n updateDots();\n // количество и активный dot зависят и от раскладки: размеры меняются без изменения позиции скролла\n const unsubscribe = [\n scrollState.scrollPosition.on('change', updateDots),\n scrollState.items.on('change', updateDots),\n scrollState.viewportWidth.on('change', updateDots),\n scrollState.contentWidth.on('change', updateDots),\n ];\n return () => {\n unsubscribe.forEach((fn) => fn());\n };\n }, [scrollState, updateDots, mode]);\n\n if (dotsCount === 0) {\n return null;\n }\n\n return (\n <div>\n <VSpacing default={offsetTop} />\n <div className={styles.dotContainer}>\n <DotPages\n active={activeDot}\n count={dotsCount}\n data-qa={dotPagesProps?.['data-qa'] || 'scrollable-container__dot-pages'}\n {...dotPagesProps}\n />\n </div>\n </div>\n );\n};\n"],"names":["count"],"mappings":"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"}
|
|
@@ -6,7 +6,7 @@ import { clamp } from '@hh.ru/magritte-internal-custom-scroll/initScrollHandlers
|
|
|
6
6
|
import { useScrollState } from './ScrollStateProvider.js';
|
|
7
7
|
import { useScrollContainer } from './useScrollContainer.js';
|
|
8
8
|
import { getDisableState, findNearestSnapIndex, computeTargetPositionForIndex } from './utils.js';
|
|
9
|
-
import { s as styles } from './scrollableContainer-
|
|
9
|
+
import { s as styles } from './scrollableContainer-DMskt4X2.js';
|
|
10
10
|
import './ObservableValue.js';
|
|
11
11
|
import '@hh.ru/magritte-common-func-utils';
|
|
12
12
|
import '@hh.ru/magritte-internal-custom-scroll';
|
package/ScrollableItem.js
CHANGED
|
@@ -13,7 +13,7 @@ import '@hh.ru/magritte-internal-custom-scroll';
|
|
|
13
13
|
import './types.js';
|
|
14
14
|
import './utils.js';
|
|
15
15
|
import '@hh.ru/magritte-ui-breakpoint';
|
|
16
|
-
import './scrollableContainer-
|
|
16
|
+
import './scrollableContainer-DMskt4X2.js';
|
|
17
17
|
|
|
18
18
|
const ScrollableItem = ({ children, scrollToItemOnFocus, ...props }) => {
|
|
19
19
|
const ref = useRef(null);
|
package/index.css
CHANGED
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
.magritte-night-theme{
|
|
10
10
|
--magritte-gradient-component-chat-input-background-fade-v26-0-2:#1b1b1b00 0%, #1b1b1b 100%;
|
|
11
11
|
}
|
|
12
|
-
.magritte-scroll-wrapper___vTdZl_6-
|
|
12
|
+
.magritte-scroll-wrapper___vTdZl_6-7-0{
|
|
13
13
|
position:relative;
|
|
14
14
|
touch-action:pan-y pinch-zoom;
|
|
15
15
|
contain:layout;
|
|
16
16
|
}
|
|
17
|
-
.magritte-scrollable-container___AKIUp_6-
|
|
17
|
+
.magritte-scrollable-container___AKIUp_6-7-0{
|
|
18
18
|
display:block;
|
|
19
19
|
isolation:isolate;
|
|
20
20
|
overflow-x:hidden;
|
|
@@ -31,25 +31,25 @@
|
|
|
31
31
|
margin-left:var(--magritte-ui-scrollabe-container-ml, -4px);
|
|
32
32
|
margin-right:var(--magritte-ui-scrollabe-container-mr, -4px);
|
|
33
33
|
}
|
|
34
|
-
.magritte-scroll-buttons-container___ZeI5a_6-
|
|
34
|
+
.magritte-scroll-buttons-container___ZeI5a_6-7-0{
|
|
35
35
|
position:relative;
|
|
36
36
|
}
|
|
37
|
-
.magritte-scroll-buttons-container-on-hover___PFUvV_6-
|
|
37
|
+
.magritte-scroll-buttons-container-on-hover___PFUvV_6-7-0 .magritte-scroll-button___4GQu3_6-7-0{
|
|
38
38
|
opacity:0;
|
|
39
39
|
pointer-events:none;
|
|
40
40
|
transition:opacity var(--magritte-semantic-animation-time-s-duration-v26-0-2) ease-in-out;
|
|
41
41
|
}
|
|
42
|
-
.magritte-scroll-buttons-container-on-hover___PFUvV_6-
|
|
42
|
+
.magritte-scroll-buttons-container-on-hover___PFUvV_6-7-0 .magritte-scroll-button___4GQu3_6-7-0:focus-within{
|
|
43
43
|
opacity:1;
|
|
44
44
|
pointer-events:auto;
|
|
45
45
|
}
|
|
46
46
|
@media (hover: hover){
|
|
47
|
-
.magritte-scroll-buttons-container-on-hover___PFUvV_6-
|
|
47
|
+
.magritte-scroll-buttons-container-on-hover___PFUvV_6-7-0:hover .magritte-scroll-button___4GQu3_6-7-0{
|
|
48
48
|
opacity:1;
|
|
49
49
|
pointer-events:auto;
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
|
-
.magritte-scroll-buttons___0SjoR_6-
|
|
52
|
+
.magritte-scroll-buttons___0SjoR_6-7-0{
|
|
53
53
|
--fade-left:linear-gradient(90deg, var(--magritte-gradient-component-chat-input-background-fade-v26-0-2));
|
|
54
54
|
--fade-right:linear-gradient(270deg, var(--magritte-gradient-component-chat-input-background-fade-v26-0-2));
|
|
55
55
|
--left-fade-mask:var(--fade-left) 30px 0 / 128px 100% no-repeat, linear-gradient(#000, #000) right / calc(100% - 158px) 100% no-repeat;
|
|
@@ -58,29 +58,29 @@
|
|
|
58
58
|
-webkit-mask:none;
|
|
59
59
|
mask:none;
|
|
60
60
|
}
|
|
61
|
-
.magritte-scroll-buttons-small___xG3MS_6-
|
|
61
|
+
.magritte-scroll-buttons-small___xG3MS_6-7-0{
|
|
62
62
|
--left-fade-mask:var(--fade-left) 0px 0 / 44px 100% no-repeat, linear-gradient(#000, #000) right / calc(100% - 44px) 100% no-repeat;
|
|
63
63
|
--right-fade-mask:var(--fade-right) calc(100% - 0px) 0 / 44px 100% no-repeat, linear-gradient(#000, #000) left / calc(100% - 44px) 100% no-repeat;
|
|
64
64
|
--both-sides-mask:var(--fade-left) 0px 0 / 44px 100% no-repeat, var(--fade-right) calc(100% - 0px) 0 / 44px 100% no-repeat, linear-gradient(#000, #000) center / calc(100% - 44px - 44px) 100% no-repeat;
|
|
65
65
|
}
|
|
66
|
-
.magritte-scroll-button___4GQu3_6-
|
|
66
|
+
.magritte-scroll-button___4GQu3_6-7-0{
|
|
67
67
|
display:none;
|
|
68
68
|
position:absolute;
|
|
69
69
|
top:50%;
|
|
70
70
|
transform:translateY(-50%);
|
|
71
71
|
}
|
|
72
|
-
.magritte-scroll-button-left___UueEY_6-
|
|
72
|
+
.magritte-scroll-button-left___UueEY_6-7-0{
|
|
73
73
|
z-index:1;
|
|
74
74
|
left:var(--magritte-ui-scrollable-container-buttons-offset, 0);
|
|
75
75
|
}
|
|
76
|
-
.magritte-scroll-button-right___wZOn-_6-
|
|
76
|
+
.magritte-scroll-button-right___wZOn-_6-7-0{
|
|
77
77
|
right:var(--magritte-ui-scrollable-container-buttons-offset, 0);
|
|
78
78
|
}
|
|
79
|
-
.magritte-position-container___1A4Bv_6-
|
|
79
|
+
.magritte-position-container___1A4Bv_6-7-0{
|
|
80
80
|
box-sizing:border-box;
|
|
81
81
|
width:100%;
|
|
82
82
|
}
|
|
83
|
-
.magritte-dot-container___ahtlG_6-
|
|
83
|
+
.magritte-dot-container___ahtlG_6-7-0{
|
|
84
84
|
display:flex;
|
|
85
85
|
justify-content:center;
|
|
86
86
|
}
|
package/index.d.ts
CHANGED
|
@@ -3,4 +3,4 @@ export { useScrollableControls } from './useScrollableControls';
|
|
|
3
3
|
export { useGalleryContext } from './ScrollableContainerGallery';
|
|
4
4
|
export { useScrollState } from './ScrollStateProvider';
|
|
5
5
|
export { getItemOffset } from './utils';
|
|
6
|
-
export type { ItemOffset, RegisterAndRemoveItem, ScrollableContainerProps, SpacingCorrectionProps, ScrollableControls, ScrollableItemProps, ScrollableContainerGalleryProps, ScrollableContainerDotPagesProps, ScrollDisableState, ScrollableContainerButtonProps, ScrollableContainerDefaultLayoutProps, ScrollableContainerDefaultLayoutSize, ScrollSnapAlign, } from './types';
|
|
6
|
+
export type { ItemOffset, RegisterAndRemoveItem, ScrollableContainerProps, SpacingCorrectionProps, ScrollableControls, ScrollableItemProps, ScrollableContainerGalleryProps, ScrollableContainerDotPagesProps, ScrollableContainerDotPagesMode, ScrollDisableState, ScrollableContainerButtonProps, ScrollableContainerDefaultLayoutProps, ScrollableContainerDefaultLayoutSize, ScrollSnapAlign, } from './types';
|
package/index.js
CHANGED
|
@@ -13,13 +13,13 @@ import './ScrollableContainerDefaultLayout.js';
|
|
|
13
13
|
import 'motion/react';
|
|
14
14
|
import '@hh.ru/magritte-common-use-translation';
|
|
15
15
|
import '@hh.ru/magritte-ui-icon/icon';
|
|
16
|
-
import './scrollableContainer-
|
|
16
|
+
import './scrollableContainer-DMskt4X2.js';
|
|
17
17
|
import './ScrollableContainerDotPages.js';
|
|
18
|
-
import '@hh.ru/magritte-internal-custom-scroll/initScrollHandlers';
|
|
19
18
|
import '@hh.ru/magritte-ui-dot-pages';
|
|
20
19
|
import '@hh.ru/magritte-ui-spacing';
|
|
21
20
|
import './ScrollableItem.js';
|
|
22
21
|
import '@hh.ru/magritte-internal-custom-scroll';
|
|
22
|
+
import '@hh.ru/magritte-internal-custom-scroll/initScrollHandlers';
|
|
23
23
|
import './useScrollContainer.js';
|
|
24
24
|
import '@hh.ru/magritte-common-func-utils';
|
|
25
25
|
import './types.js';
|
package/index.mock.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { RegisterAndRemoveItem, ScrollableContainerProps, SpacingCorrectionProps, ScrollableControls, ScrollableItemProps, ScrollableContainerGalleryProps, ScrollableContainerDotPagesProps, ScrollDisableState, ScrollableContainerButtonProps, ScrollableContainerDefaultLayoutProps, ScrollableContainerDefaultLayoutSize, ScrollSnapAlign, } from './types';
|
|
1
|
+
export type { RegisterAndRemoveItem, ScrollableContainerProps, SpacingCorrectionProps, ScrollableControls, ScrollableItemProps, ScrollableContainerGalleryProps, ScrollableContainerDotPagesProps, ScrollableContainerDotPagesMode, ScrollDisableState, ScrollableContainerButtonProps, ScrollableContainerDefaultLayoutProps, ScrollableContainerDefaultLayoutSize, ScrollSnapAlign, } from './types';
|
|
2
2
|
export declare const ScrollableContainer: import("react").ForwardRefExoticComponent<Record<string, unknown>>;
|
|
3
3
|
export { useScrollableControls } from './useScrollableControls';
|
|
4
4
|
export { useGalleryContext } from './ScrollableContainerGallery';
|
package/index.mock.js
CHANGED
|
@@ -13,7 +13,7 @@ import 'react/jsx-runtime';
|
|
|
13
13
|
import '@hh.ru/magritte-internal-custom-scroll/initScrollHandlers';
|
|
14
14
|
import './useScrollContainer.js';
|
|
15
15
|
import '@hh.ru/magritte-common-func-utils';
|
|
16
|
-
import './scrollableContainer-
|
|
16
|
+
import './scrollableContainer-DMskt4X2.js';
|
|
17
17
|
import './ObservableValue.js';
|
|
18
18
|
|
|
19
19
|
const staticProps = {
|
package/index.mock.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mock.js","sources":["src/index.mock.ts"],"sourcesContent":["import { mockComponent } from '@hh.ru/magritte-ui-mock-component';\n\nexport type {\n RegisterAndRemoveItem,\n ScrollableContainerProps,\n SpacingCorrectionProps,\n ScrollableControls,\n ScrollableItemProps,\n ScrollableContainerGalleryProps,\n ScrollableContainerDotPagesProps,\n ScrollDisableState,\n ScrollableContainerButtonProps,\n ScrollableContainerDefaultLayoutProps,\n ScrollableContainerDefaultLayoutSize,\n ScrollSnapAlign,\n} from '@hh.ru/magritte-ui-scrollable-container/types';\n\nconst staticProps = {\n Left: mockComponent('Left', undefined, {\n withChildren: true,\n }),\n Right: mockComponent('Right', undefined, {\n withChildren: true,\n }),\n Item: mockComponent('Item', undefined, {\n withChildren: true,\n }),\n Gallery: mockComponent('Gallery', undefined, {\n withChildren: true,\n }),\n DefaultLayout: mockComponent('DefaultLayout', undefined, {\n withChildren: true,\n }),\n DotPages: mockComponent('DotPages', undefined, {\n withChildren: true,\n }),\n};\n\nexport const ScrollableContainer = mockComponent('ScrollableContainer', staticProps, {\n withChildren: true,\n});\n\nexport { useScrollableControls } from '@hh.ru/magritte-ui-scrollable-container/useScrollableControls';\nexport { useGalleryContext } from '@hh.ru/magritte-ui-scrollable-container/ScrollableContainerGallery';\nexport { useScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.mock.js","sources":["src/index.mock.ts"],"sourcesContent":["import { mockComponent } from '@hh.ru/magritte-ui-mock-component';\n\nexport type {\n RegisterAndRemoveItem,\n ScrollableContainerProps,\n SpacingCorrectionProps,\n ScrollableControls,\n ScrollableItemProps,\n ScrollableContainerGalleryProps,\n ScrollableContainerDotPagesProps,\n ScrollableContainerDotPagesMode,\n ScrollDisableState,\n ScrollableContainerButtonProps,\n ScrollableContainerDefaultLayoutProps,\n ScrollableContainerDefaultLayoutSize,\n ScrollSnapAlign,\n} from '@hh.ru/magritte-ui-scrollable-container/types';\n\nconst staticProps = {\n Left: mockComponent('Left', undefined, {\n withChildren: true,\n }),\n Right: mockComponent('Right', undefined, {\n withChildren: true,\n }),\n Item: mockComponent('Item', undefined, {\n withChildren: true,\n }),\n Gallery: mockComponent('Gallery', undefined, {\n withChildren: true,\n }),\n DefaultLayout: mockComponent('DefaultLayout', undefined, {\n withChildren: true,\n }),\n DotPages: mockComponent('DotPages', undefined, {\n withChildren: true,\n }),\n};\n\nexport const ScrollableContainer = mockComponent('ScrollableContainer', staticProps, {\n withChildren: true,\n});\n\nexport { useScrollableControls } from '@hh.ru/magritte-ui-scrollable-container/useScrollableControls';\nexport { useGalleryContext } from '@hh.ru/magritte-ui-scrollable-container/ScrollableContainerGallery';\nexport { useScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAkBA,MAAM,WAAc,GAAA;AAAA,EAChB,IAAA,EAAM,aAAc,CAAA,MAAA,EAAQ,KAAW,CAAA,EAAA;AAAA,IACnC,YAAc,EAAA,IAAA;AAAA,GACjB,CAAA;AAAA,EACD,KAAA,EAAO,aAAc,CAAA,OAAA,EAAS,KAAW,CAAA,EAAA;AAAA,IACrC,YAAc,EAAA,IAAA;AAAA,GACjB,CAAA;AAAA,EACD,IAAA,EAAM,aAAc,CAAA,MAAA,EAAQ,KAAW,CAAA,EAAA;AAAA,IACnC,YAAc,EAAA,IAAA;AAAA,GACjB,CAAA;AAAA,EACD,OAAA,EAAS,aAAc,CAAA,SAAA,EAAW,KAAW,CAAA,EAAA;AAAA,IACzC,YAAc,EAAA,IAAA;AAAA,GACjB,CAAA;AAAA,EACD,aAAA,EAAe,aAAc,CAAA,eAAA,EAAiB,KAAW,CAAA,EAAA;AAAA,IACrD,YAAc,EAAA,IAAA;AAAA,GACjB,CAAA;AAAA,EACD,QAAA,EAAU,aAAc,CAAA,UAAA,EAAY,KAAW,CAAA,EAAA;AAAA,IAC3C,YAAc,EAAA,IAAA;AAAA,GACjB,CAAA;AACL,CAAA,CAAA;AAEa,MAAA,mBAAA,GAAsB,aAAc,CAAA,qBAAA,EAAuB,WAAa,EAAA;AAAA,EACjF,YAAc,EAAA,IAAA;AAClB,CAAC;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hh.ru/magritte-ui-scrollable-container",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.7.0",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"types": "index.d.ts",
|
|
6
6
|
"sideEffects": [
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"@hh.ru/magritte-design-tokens": "26.0.2",
|
|
26
26
|
"@hh.ru/magritte-internal-custom-scroll": "2.1.3",
|
|
27
27
|
"@hh.ru/magritte-ui-breakpoint": "6.1.3",
|
|
28
|
-
"@hh.ru/magritte-ui-dot-pages": "4.0.
|
|
28
|
+
"@hh.ru/magritte-ui-dot-pages": "4.0.41",
|
|
29
29
|
"@hh.ru/magritte-ui-icon": "15.2.0",
|
|
30
30
|
"@hh.ru/magritte-ui-mock-component": "1.1.9",
|
|
31
31
|
"@hh.ru/magritte-ui-spacing": "2.1.32"
|
|
@@ -38,5 +38,5 @@
|
|
|
38
38
|
"publishConfig": {
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "c4a95a3ae0a370fb14e16f79e2294b053bfcf67e"
|
|
42
42
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import './index.css';
|
|
2
|
+
var styles = {"scroll-wrapper":"magritte-scroll-wrapper___vTdZl_6-7-0","scrollWrapper":"magritte-scroll-wrapper___vTdZl_6-7-0","scrollable-container":"magritte-scrollable-container___AKIUp_6-7-0","scrollableContainer":"magritte-scrollable-container___AKIUp_6-7-0","scroll-buttons-container":"magritte-scroll-buttons-container___ZeI5a_6-7-0","scrollButtonsContainer":"magritte-scroll-buttons-container___ZeI5a_6-7-0","scroll-buttons-container-on-hover":"magritte-scroll-buttons-container-on-hover___PFUvV_6-7-0","scrollButtonsContainerOnHover":"magritte-scroll-buttons-container-on-hover___PFUvV_6-7-0","scroll-button":"magritte-scroll-button___4GQu3_6-7-0","scrollButton":"magritte-scroll-button___4GQu3_6-7-0","scroll-buttons":"magritte-scroll-buttons___0SjoR_6-7-0","scrollButtons":"magritte-scroll-buttons___0SjoR_6-7-0","scroll-buttons-small":"magritte-scroll-buttons-small___xG3MS_6-7-0","scrollButtonsSmall":"magritte-scroll-buttons-small___xG3MS_6-7-0","scroll-button-left":"magritte-scroll-button-left___UueEY_6-7-0","scrollButtonLeft":"magritte-scroll-button-left___UueEY_6-7-0","scroll-button-right":"magritte-scroll-button-right___wZOn-_6-7-0","scrollButtonRight":"magritte-scroll-button-right___wZOn-_6-7-0","position-container":"magritte-position-container___1A4Bv_6-7-0","positionContainer":"magritte-position-container___1A4Bv_6-7-0","dot-container":"magritte-dot-container___ahtlG_6-7-0","dotContainer":"magritte-dot-container___ahtlG_6-7-0"};
|
|
3
|
+
|
|
4
|
+
export { styles as s };
|
|
5
|
+
//# sourceMappingURL=scrollableContainer-DMskt4X2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scrollableContainer-DMskt4X2.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
package/types.d.ts
CHANGED
|
@@ -127,7 +127,19 @@ export interface ScrollableContainerGalleryProps extends Omit<HTMLAttributes<HTM
|
|
|
127
127
|
/** Элементы галереи, которые отображаются внутри контейнера и прокручиваются по горизонтали */
|
|
128
128
|
children: ReactNode;
|
|
129
129
|
}
|
|
130
|
+
export type ScrollableContainerDotPagesMode = 'items' | 'pages';
|
|
130
131
|
export interface ScrollableContainerDotPagesProps {
|
|
132
|
+
/**
|
|
133
|
+
* Что обозначает dot
|
|
134
|
+
*
|
|
135
|
+
* - `items` - элемент галереи, активен элемент, ближайший к своей позиции выравнивания
|
|
136
|
+
* - `pages` - страница прокрутки: количество dots равно количеству вьюпортов, которые занимает контент
|
|
137
|
+
* (но не меньше трёх). Крайние dots активны только у краёв прокрутки, средние делят остальной диапазон поровну,
|
|
138
|
+
* поэтому некрайний dot означает скрытый контент с обеих сторон. Подходит, когда во вьюпорт помещается
|
|
139
|
+
* несколько элементов. Если диапазон прокрутки меньше 50px, индикатор не отображается
|
|
140
|
+
* @default items
|
|
141
|
+
*/
|
|
142
|
+
mode?: ScrollableContainerDotPagesMode;
|
|
131
143
|
/** Колбэк при изменении active dot в компоненте dot-pages*/
|
|
132
144
|
onChangeDot?: (dot: number) => void;
|
|
133
145
|
/** Свойства dot-pages*/
|
package/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sources":["src/types.ts"],"sourcesContent":["import type { HTMLAttributes, RefObject, MouseEventHandler, ReactNode } from 'react';\n\nimport { TokenBaseStaticSpace } from '@hh.ru/magritte-design-tokens/types';\nimport type { DotPagesProps } from '@hh.ru/magritte-ui-dot-pages';\n\nexport const OFFSET_ATTR = Symbol('scroll-item-offset');\nexport interface ItemOffset {\n left: number;\n right: number;\n}\nexport interface ItemWithOffset {\n [OFFSET_ATTR]: ItemOffset;\n}\n\nexport interface ControlWithClick {\n onClick?: MouseEventHandler;\n 'data-qa'?: string;\n}\n\nexport interface RegisterAndRemoveItem {\n /** колбэк для регистрации элемента галерии */\n registerItem: (ref: RefObject<HTMLElement>) => void;\n /** колбэк для удаления элемента галерии */\n removeItem: (ref: RefObject<HTMLElement>) => void;\n}\n\nexport interface ScrollDisableState {\n /** заблокирован ли скролл влево */\n isScrollRightDisabled: boolean;\n /** заблокирован ли скролл вправо */\n isScrollLeftDisabled: boolean;\n}\n\nexport interface ScrollableControls {\n /** двигаем ScrollableContainer налево */\n scrollLeft: () => void;\n /** двигаем ScrollableContainer направо */\n scrollRight: () => void;\n /** двигаем ScrollableContainer к первому элементу */\n scrollToFirstItem: () => void;\n /** двигаем ScrollableContainer к последнему элементу */\n scrollToLastItem: () => void;\n /** скролл к элементу по индексу, элементы сортируются по расположению справа налево */\n scrollToIndex: (index: number) => void;\n /**\n * скролл к элементу по ref, должен передаваться ref на элемент который был\n * зарегистрирован с помощью registerItem API\n **/\n scrollToItem: (ref: RefObject<HTMLElement>) => void;\n /** моментальный скролл к элементу по индексу */\n jumpToIndex: (index: number) => void;\n /**\n * моментальный сдвиг позиции на дельту\n * не выравнивает элемент по scrollSnapAlign (безопасен посреди жеста)\n **/\n jumpBy: (delta: number) => void;\n}\n\n/**\n * Пропы для настройки коррекции отступов в режиме без кнопок, когда надо чтобы край скролла соответствовал\n * краю родительского контейнера, у которого могут быть отступы. Задаются в виде положительного числа.\n * более специфичные пропсы переопределяют менее специфичные. При выборе значения коррекции для разрешения выбирается\n * ближайшее заданное значение для разрешений меньшего или равного размера. Т.е. если задано correction и correctionM,\n * то для разрешений S и XS будет использовано correction, а для остальных correctionM. Если задано\n * еще и correctionLeftM, то для разрешений начиная с M и больше для левого края будет использовано\n * correctionLeftM, а для правого correctionM.\n */\nexport interface SpacingCorrectionProps {\n /** Величина коррекции отступа, положительное число или 0 */\n correction?: number;\n /** Величина коррекции отступа для разрешения XS и больше, положительное число или 0 */\n correctionXS?: number;\n /** Величина коррекции отступа для разрешения S и больше, положительное число или 0 */\n correctionS?: number;\n /** Величина коррекции отступа для разрешения M и больше, положительное число или 0 */\n correctionM?: number;\n /** Величина коррекции отступа для разрешения L и больше, положительное число или 0 */\n correctionL?: number;\n /** Величина коррекции отступа для разрешения XL и больше, положительное число или 0 */\n correctionXL?: number;\n /** Величина коррекции отступа для разрешения XXL и больше, положительное число или 0 */\n correctionXXL?: number;\n /** Величина коррекции отступа слева для разрешения XS и больше, положительное число или 0 */\n correctionLeftXS?: number;\n /** Величина коррекции левого отступа для разрешения S и больше, положительное число или 0 */\n correctionLeftS?: number;\n /** Величина коррекции левого отступа для разрешения M и больше, положительное число или 0 */\n correctionLeftM?: number;\n /** Величина коррекции левого отступа для разрешения L и больше, положительное число или 0 */\n correctionLeftL?: number;\n /** Величина коррекции левого отступа для разрешения XL и больше, положительное число или 0 */\n correctionLeftXL?: number;\n /** Величина коррекции левого отступа для разрешения XXL и больше, положительное число или 0 */\n correctionLeftXXL?: number;\n /** Величина коррекции отступа справа для разрешения XS и больше, положительное число или 0 */\n correctionRightXS?: number;\n /** Величина коррекции отступа справа для разрешения S и больше, положительное число или 0 */\n correctionRightS?: number;\n /** Величина коррекции отступа справа для разрешения M и больше, положительное число или 0 */\n correctionRightM?: number;\n /** Величина коррекции отступа справа для разрешения L и больше, положительное число или 0 */\n correctionRightL?: number;\n /** Величина коррекции отступа справа для разрешения XL и больше, положительное число или 0 */\n correctionRightXL?: number;\n /** Величина коррекции отступа справа для разрешения XXL и больше, положительное число или 0 */\n correctionRightXXL?: number;\n}\n\nexport type ScrollSnapAlign = 'start' | 'end' | 'center' | 'none';\n\nexport type ScrollableContainerProps = SpacingCorrectionProps & {\n /** Контент ScrollableContainer */\n children: ReactNode;\n /**\n * Определяет, как ближайший элемент будет размещён во вьюпорте при автоматическом скролле\n *\n * - `center` - ближайший элемент центрируется во вьюпорте\n * - `start` - ближайший элемент выравнивается по левой границе вьюпорта\n * - `end` - ближайший элемент выравнивается по правой границе вьюпорта\n */\n scrollSnapAlign?: ScrollSnapAlign;\n} & HTMLAttributes<HTMLDivElement>;\n\nexport interface ScrollableItemProps extends HTMLAttributes<HTMLDivElement> {\n /** Элемент галереи */\n children: ReactNode;\n /** Нужно ли скролить к элементу при фокусе */\n scrollToItemOnFocus?: boolean;\n}\n\nexport interface ScrollableContainerGalleryProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onScroll'> {\n /** Колбэк при прокрутке контейнера */\n onScroll?: (scrollInfo: ScrollDisableState) => void;\n /** Колбэк при инициализации контейнера */\n onReady?: (scrollInfo: ScrollDisableState) => void;\n /** Колбэк при изменении размеров контейнера */\n onChangeSize?: (scrollInfo: ScrollDisableState) => void;\n /** Элементы галереи, которые отображаются внутри контейнера и прокручиваются по горизонтали */\n children: ReactNode;\n}\n\nexport interface ScrollableContainerDotPagesProps {\n /** Колбэк при изменении active dot в компоненте dot-pages*/\n onChangeDot?: (dot: number) => void;\n /** Свойства dot-pages*/\n dotPagesProps?: Omit<DotPagesProps, 'active' | 'count'>;\n /** Верхний отступ для DotPages */\n offsetTop?: TokenBaseStaticSpace;\n}\n\nexport interface ScrollableContainerButtonProps {\n /** Кнопка для скрола налево/направо */\n children: ReactNode;\n}\n\nexport type ScrollableContainerDefaultLayoutSize = 'medium' | 'small';\n\nexport interface ScrollableContainerDefaultLayoutProps {\n /** Контент ScrollableContainerGallery */\n children: ReactNode;\n /**\n * Размер кнопок листания\n *\n * - `medium` - иконка 24px с паддингом 8px (кнопка 40px)\n * - `small` - иконка 24px с паддингом 4px (кнопка 32px)\n * @default medium\n */\n size?: ScrollableContainerDefaultLayoutSize;\n /**\n * Показывать краевые фейды на мобильных брейкпоинтах (XS/S), где кнопки листания\n * скрыты. По умолчанию фейды видны только вместе с кнопками — с брейкпоинта M.\n * @default false\n */\n fadeOnMobile?: boolean;\n /**\n * Отключает краевые фейды на десктопных брейкпоинтах (с M), где показываются кнопки листания;\n * сами кнопки при этом остаются. Вместе с `fadeOnMobile` позволяет задать фейды для мобильных\n * и десктопных брейкпоинтов независимо.\n * @default false\n */\n noFadeOnDesktop?: boolean;\n /**\n * Отступ кнопок листания от краёв контейнера в пикселях. Учитывается при прокрутке к элементам,\n * чтобы они не оказывались под кнопками\n * @default 0\n */\n buttonsOffset?: number;\n /**\n * Показывать кнопки листания только при наведении курсора на контейнер (и при фокусе кнопки\n * с клавиатуры). На устройствах без ховера кнопки не показываются\n * @default false\n */\n buttonsOnHover?: boolean;\n /** aria-label кнопки налево */\n leftButtonAriaLabel?: string;\n /** aria-label кнопки направо */\n rightButtonAriaLabel?: string;\n /** aria-controls кнопки налево */\n leftAriaControls?: string;\n /** aria-controls кнопки направо */\n rightAriaControls?: string;\n}\n"],"names":[],"mappings":"AAKa,MAAA,WAAA,GAAc,OAAO,oBAAoB;;;;"}
|
|
1
|
+
{"version":3,"file":"types.js","sources":["src/types.ts"],"sourcesContent":["import type { HTMLAttributes, RefObject, MouseEventHandler, ReactNode } from 'react';\n\nimport { TokenBaseStaticSpace } from '@hh.ru/magritte-design-tokens/types';\nimport type { DotPagesProps } from '@hh.ru/magritte-ui-dot-pages';\n\nexport const OFFSET_ATTR = Symbol('scroll-item-offset');\nexport interface ItemOffset {\n left: number;\n right: number;\n}\nexport interface ItemWithOffset {\n [OFFSET_ATTR]: ItemOffset;\n}\n\nexport interface ControlWithClick {\n onClick?: MouseEventHandler;\n 'data-qa'?: string;\n}\n\nexport interface RegisterAndRemoveItem {\n /** колбэк для регистрации элемента галерии */\n registerItem: (ref: RefObject<HTMLElement>) => void;\n /** колбэк для удаления элемента галерии */\n removeItem: (ref: RefObject<HTMLElement>) => void;\n}\n\nexport interface ScrollDisableState {\n /** заблокирован ли скролл влево */\n isScrollRightDisabled: boolean;\n /** заблокирован ли скролл вправо */\n isScrollLeftDisabled: boolean;\n}\n\nexport interface ScrollableControls {\n /** двигаем ScrollableContainer налево */\n scrollLeft: () => void;\n /** двигаем ScrollableContainer направо */\n scrollRight: () => void;\n /** двигаем ScrollableContainer к первому элементу */\n scrollToFirstItem: () => void;\n /** двигаем ScrollableContainer к последнему элементу */\n scrollToLastItem: () => void;\n /** скролл к элементу по индексу, элементы сортируются по расположению справа налево */\n scrollToIndex: (index: number) => void;\n /**\n * скролл к элементу по ref, должен передаваться ref на элемент который был\n * зарегистрирован с помощью registerItem API\n **/\n scrollToItem: (ref: RefObject<HTMLElement>) => void;\n /** моментальный скролл к элементу по индексу */\n jumpToIndex: (index: number) => void;\n /**\n * моментальный сдвиг позиции на дельту\n * не выравнивает элемент по scrollSnapAlign (безопасен посреди жеста)\n **/\n jumpBy: (delta: number) => void;\n}\n\n/**\n * Пропы для настройки коррекции отступов в режиме без кнопок, когда надо чтобы край скролла соответствовал\n * краю родительского контейнера, у которого могут быть отступы. Задаются в виде положительного числа.\n * более специфичные пропсы переопределяют менее специфичные. При выборе значения коррекции для разрешения выбирается\n * ближайшее заданное значение для разрешений меньшего или равного размера. Т.е. если задано correction и correctionM,\n * то для разрешений S и XS будет использовано correction, а для остальных correctionM. Если задано\n * еще и correctionLeftM, то для разрешений начиная с M и больше для левого края будет использовано\n * correctionLeftM, а для правого correctionM.\n */\nexport interface SpacingCorrectionProps {\n /** Величина коррекции отступа, положительное число или 0 */\n correction?: number;\n /** Величина коррекции отступа для разрешения XS и больше, положительное число или 0 */\n correctionXS?: number;\n /** Величина коррекции отступа для разрешения S и больше, положительное число или 0 */\n correctionS?: number;\n /** Величина коррекции отступа для разрешения M и больше, положительное число или 0 */\n correctionM?: number;\n /** Величина коррекции отступа для разрешения L и больше, положительное число или 0 */\n correctionL?: number;\n /** Величина коррекции отступа для разрешения XL и больше, положительное число или 0 */\n correctionXL?: number;\n /** Величина коррекции отступа для разрешения XXL и больше, положительное число или 0 */\n correctionXXL?: number;\n /** Величина коррекции отступа слева для разрешения XS и больше, положительное число или 0 */\n correctionLeftXS?: number;\n /** Величина коррекции левого отступа для разрешения S и больше, положительное число или 0 */\n correctionLeftS?: number;\n /** Величина коррекции левого отступа для разрешения M и больше, положительное число или 0 */\n correctionLeftM?: number;\n /** Величина коррекции левого отступа для разрешения L и больше, положительное число или 0 */\n correctionLeftL?: number;\n /** Величина коррекции левого отступа для разрешения XL и больше, положительное число или 0 */\n correctionLeftXL?: number;\n /** Величина коррекции левого отступа для разрешения XXL и больше, положительное число или 0 */\n correctionLeftXXL?: number;\n /** Величина коррекции отступа справа для разрешения XS и больше, положительное число или 0 */\n correctionRightXS?: number;\n /** Величина коррекции отступа справа для разрешения S и больше, положительное число или 0 */\n correctionRightS?: number;\n /** Величина коррекции отступа справа для разрешения M и больше, положительное число или 0 */\n correctionRightM?: number;\n /** Величина коррекции отступа справа для разрешения L и больше, положительное число или 0 */\n correctionRightL?: number;\n /** Величина коррекции отступа справа для разрешения XL и больше, положительное число или 0 */\n correctionRightXL?: number;\n /** Величина коррекции отступа справа для разрешения XXL и больше, положительное число или 0 */\n correctionRightXXL?: number;\n}\n\nexport type ScrollSnapAlign = 'start' | 'end' | 'center' | 'none';\n\nexport type ScrollableContainerProps = SpacingCorrectionProps & {\n /** Контент ScrollableContainer */\n children: ReactNode;\n /**\n * Определяет, как ближайший элемент будет размещён во вьюпорте при автоматическом скролле\n *\n * - `center` - ближайший элемент центрируется во вьюпорте\n * - `start` - ближайший элемент выравнивается по левой границе вьюпорта\n * - `end` - ближайший элемент выравнивается по правой границе вьюпорта\n */\n scrollSnapAlign?: ScrollSnapAlign;\n} & HTMLAttributes<HTMLDivElement>;\n\nexport interface ScrollableItemProps extends HTMLAttributes<HTMLDivElement> {\n /** Элемент галереи */\n children: ReactNode;\n /** Нужно ли скролить к элементу при фокусе */\n scrollToItemOnFocus?: boolean;\n}\n\nexport interface ScrollableContainerGalleryProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onScroll'> {\n /** Колбэк при прокрутке контейнера */\n onScroll?: (scrollInfo: ScrollDisableState) => void;\n /** Колбэк при инициализации контейнера */\n onReady?: (scrollInfo: ScrollDisableState) => void;\n /** Колбэк при изменении размеров контейнера */\n onChangeSize?: (scrollInfo: ScrollDisableState) => void;\n /** Элементы галереи, которые отображаются внутри контейнера и прокручиваются по горизонтали */\n children: ReactNode;\n}\n\nexport type ScrollableContainerDotPagesMode = 'items' | 'pages';\n\nexport interface ScrollableContainerDotPagesProps {\n /**\n * Что обозначает dot\n *\n * - `items` - элемент галереи, активен элемент, ближайший к своей позиции выравнивания\n * - `pages` - страница прокрутки: количество dots равно количеству вьюпортов, которые занимает контент\n * (но не меньше трёх). Крайние dots активны только у краёв прокрутки, средние делят остальной диапазон поровну,\n * поэтому некрайний dot означает скрытый контент с обеих сторон. Подходит, когда во вьюпорт помещается\n * несколько элементов. Если диапазон прокрутки меньше 50px, индикатор не отображается\n * @default items\n */\n mode?: ScrollableContainerDotPagesMode;\n /** Колбэк при изменении active dot в компоненте dot-pages*/\n onChangeDot?: (dot: number) => void;\n /** Свойства dot-pages*/\n dotPagesProps?: Omit<DotPagesProps, 'active' | 'count'>;\n /** Верхний отступ для DotPages */\n offsetTop?: TokenBaseStaticSpace;\n}\n\nexport interface ScrollableContainerButtonProps {\n /** Кнопка для скрола налево/направо */\n children: ReactNode;\n}\n\nexport type ScrollableContainerDefaultLayoutSize = 'medium' | 'small';\n\nexport interface ScrollableContainerDefaultLayoutProps {\n /** Контент ScrollableContainerGallery */\n children: ReactNode;\n /**\n * Размер кнопок листания\n *\n * - `medium` - иконка 24px с паддингом 8px (кнопка 40px)\n * - `small` - иконка 24px с паддингом 4px (кнопка 32px)\n * @default medium\n */\n size?: ScrollableContainerDefaultLayoutSize;\n /**\n * Показывать краевые фейды на мобильных брейкпоинтах (XS/S), где кнопки листания\n * скрыты. По умолчанию фейды видны только вместе с кнопками — с брейкпоинта M.\n * @default false\n */\n fadeOnMobile?: boolean;\n /**\n * Отключает краевые фейды на десктопных брейкпоинтах (с M), где показываются кнопки листания;\n * сами кнопки при этом остаются. Вместе с `fadeOnMobile` позволяет задать фейды для мобильных\n * и десктопных брейкпоинтов независимо.\n * @default false\n */\n noFadeOnDesktop?: boolean;\n /**\n * Отступ кнопок листания от краёв контейнера в пикселях. Учитывается при прокрутке к элементам,\n * чтобы они не оказывались под кнопками\n * @default 0\n */\n buttonsOffset?: number;\n /**\n * Показывать кнопки листания только при наведении курсора на контейнер (и при фокусе кнопки\n * с клавиатуры). На устройствах без ховера кнопки не показываются\n * @default false\n */\n buttonsOnHover?: boolean;\n /** aria-label кнопки налево */\n leftButtonAriaLabel?: string;\n /** aria-label кнопки направо */\n rightButtonAriaLabel?: string;\n /** aria-controls кнопки налево */\n leftAriaControls?: string;\n /** aria-controls кнопки направо */\n rightAriaControls?: string;\n}\n"],"names":[],"mappings":"AAKa,MAAA,WAAA,GAAc,OAAO,oBAAoB;;;;"}
|
package/utils.d.ts
CHANGED
|
@@ -70,6 +70,23 @@ export declare const computeSnapPositions: (state: ScrollState) => number[];
|
|
|
70
70
|
* @returns индекс найденого элемента
|
|
71
71
|
*/
|
|
72
72
|
export declare const findNearestSnapIndex: (state: ScrollState) => number;
|
|
73
|
+
/**
|
|
74
|
+
* Количество страниц для индикатора в режиме `pages`: сколько вьюпортов занимает контент, но не меньше трёх,
|
|
75
|
+
* чтобы у начала, середины и конца прокрутки были свои dots
|
|
76
|
+
* @param state стейт скролла
|
|
77
|
+
* @returns количество страниц, 0 — если диапазон прокрутки меньше PAGES_MIN_SCROLL_RANGE, элементов нет
|
|
78
|
+
* или размеры еще не посчитаны
|
|
79
|
+
*/
|
|
80
|
+
export declare const computePagesCount: (state: ScrollState) => number;
|
|
81
|
+
/**
|
|
82
|
+
* Индекс активной страницы в режиме `pages`. Крайние dots активны только у краёв прокрутки,
|
|
83
|
+
* поэтому любой другой dot означает, что с обеих сторон есть скрытый контент. Средние dots делят
|
|
84
|
+
* остальной диапазон прокрутки поровну
|
|
85
|
+
* @param state стейт скролла
|
|
86
|
+
* @param pagesCount количество страниц, см. computePagesCount
|
|
87
|
+
* @returns индекс активной страницы
|
|
88
|
+
*/
|
|
89
|
+
export declare const findActivePageIndex: (state: ScrollState, pagesCount: number) => number;
|
|
73
90
|
interface ScrollBehavior {
|
|
74
91
|
(scrollState: ScrollState, index: number): number | null;
|
|
75
92
|
}
|
package/utils.js
CHANGED
|
@@ -152,6 +152,32 @@ const findNearestSnapIndex = (state) => {
|
|
|
152
152
|
}
|
|
153
153
|
return index;
|
|
154
154
|
};
|
|
155
|
+
const PAGES_EPSILON = 0.5;
|
|
156
|
+
const PAGES_MIN_SCROLL_RANGE = 50;
|
|
157
|
+
const PAGES_EDGE_ZONE = 20;
|
|
158
|
+
const MIN_PAGES_COUNT = 3;
|
|
159
|
+
const computePagesCount = (state) => {
|
|
160
|
+
const viewport = state.viewportWidth.get();
|
|
161
|
+
const content = state.contentWidth.get();
|
|
162
|
+
if (state.items.get().length === 0 || viewport <= 0 || content - viewport < PAGES_MIN_SCROLL_RANGE) {
|
|
163
|
+
return 0;
|
|
164
|
+
}
|
|
165
|
+
return Math.max(Math.ceil((content - PAGES_EPSILON) / viewport), MIN_PAGES_COUNT);
|
|
166
|
+
};
|
|
167
|
+
const findActivePageIndex = (state, pagesCount) => {
|
|
168
|
+
const range = Math.max(state.contentWidth.get() - state.viewportWidth.get(), 0);
|
|
169
|
+
const distance = clamp(-state.scrollPosition.get(), 0, range);
|
|
170
|
+
const edgeZone = Math.min(PAGES_EDGE_ZONE, range / MIN_PAGES_COUNT);
|
|
171
|
+
if (pagesCount < MIN_PAGES_COUNT || distance <= edgeZone) {
|
|
172
|
+
return 0;
|
|
173
|
+
}
|
|
174
|
+
if (distance >= range - edgeZone) {
|
|
175
|
+
return pagesCount - 1;
|
|
176
|
+
}
|
|
177
|
+
const middleCount = pagesCount - 2;
|
|
178
|
+
const middleIndex = Math.floor((distance - edgeZone) / (range - 2 * edgeZone) * middleCount);
|
|
179
|
+
return 1 + Math.min(middleIndex, middleCount - 1);
|
|
180
|
+
};
|
|
155
181
|
const computePositionForIndex = (scrollState, index) => {
|
|
156
182
|
const { items, viewportWidth, scrollPosition, defaultButtonsCorrection } = scrollState;
|
|
157
183
|
const itemRef = items.get()[index];
|
|
@@ -176,5 +202,5 @@ const computeTargetPositionForIndex = (scrollState, index) => {
|
|
|
176
202
|
return computeSnapPositions(scrollState)[index] ?? null;
|
|
177
203
|
};
|
|
178
204
|
|
|
179
|
-
export { BREAKPOINTS_LIST, NO_BUTTONS_START_FROM_BREAKPOINT, animateScrollToPosition, computePositionForIndex, computeSnapPositions, computeTargetPositionForIndex, debounce, ensureItemReadyForScroll, findNearestSnapIndex, getActualCorrection, getDisableState, getItemOffset, useInitOnce };
|
|
205
|
+
export { BREAKPOINTS_LIST, NO_BUTTONS_START_FROM_BREAKPOINT, animateScrollToPosition, computePagesCount, computePositionForIndex, computeSnapPositions, computeTargetPositionForIndex, debounce, ensureItemReadyForScroll, findActivePageIndex, findNearestSnapIndex, getActualCorrection, getDisableState, getItemOffset, useInitOnce };
|
|
180
206
|
//# sourceMappingURL=utils.js.map
|
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 * Позиция скролла, при которой элемент выровнен во вьюпорте согласно align\n * @param offset метрики элемента\n * @param align режим выравнивания\n * @param viewportWidth ширина вьюпорта\n * @param correction коррекция на кнопки по краям\n * @returns позиция скролла (0 — начало контента, отрицательные значения — прокрутка вправо)\n */\nconst getAlignedPosition = (\n offset: ItemOffset,\n align: ScrollSnapAlign,\n viewportWidth: number,\n correction: number\n): number => {\n switch (align) {\n case 'center':\n return viewportWidth / 2 - (offset.left + offset.right) / 2;\n case 'end':\n return viewportWidth - offset.right - correction;\n case 'start':\n default:\n return -offset.left + correction;\n }\n};\n\n/**\n * Список snap-позиций — по одной на элемент, в порядке элементов.\n *\n * Если элемент можно выровнять согласно scrollSnapAlign, берётся честная позиция.\n * У краёв контента честное выравнивание недостижимо (например, центр узкого последнего элемента\n * нельзя подвести к центру вьюпорта) — тогда элемент доводится до полной видимости у ближнего края.\n * Позиции не возрастают по индексу. Совпасть у соседних элементов они могут только когда в диапазоне\n * прокрутки физически нет места для отдельных состояний (контент выступает за вьюпорт меньше,\n * чем на ширину хвостовых элементов).\n *\n * В режиме `none` позиции считаются как для `start` без коррекции на кнопки\n * и используются только индикатором (DotPages).\n *\n * Результат кэшируется на стейте: DotPages вызывает расчёт на каждое изменение scrollPosition,\n * а позиции меняются только вместе с раскладкой. Возвращаемый массив нельзя мутировать.\n *\n * @param state стейт скролла\n * @returns массив позиций\n */\nexport const computeSnapPositions = (state: ScrollState): number[] => {\n const { items, viewportWidth, contentWidth, defaultButtonsCorrection, scrollSnapAlign } = state;\n const viewport = viewportWidth.get();\n const minPosition = Math.min(viewport - contentWidth.get(), 0);\n const isSnap = scrollSnapAlign !== 'none';\n const align = isSnap ? scrollSnapAlign : 'start';\n const correction = isSnap ? defaultButtonsCorrection.get() : 0;\n const itemsCount = items.get().length;\n // метрики элементов переписываются только в recalculateItemPositions (layoutVersion),\n // остальные входы — размеры, коррекция и режим — сравниваются явно\n const cache = state.snapPositionsCache;\n if (\n cache &&\n cache.layoutVersion === state.layoutVersion &&\n cache.itemsCount === itemsCount &&\n cache.viewportWidth === viewport &&\n cache.minPosition === minPosition &&\n cache.correction === correction &&\n cache.align === align\n ) {\n return cache.positions;\n }\n let previous = 0;\n const positions = items.get().map((itemRef) => {\n const offset = itemRef.current?.[OFFSET_ATTR];\n if (!offset) {\n return previous;\n }\n let position = getAlignedPosition(offset, align, viewport, correction);\n if (position > 0) {\n position = getAlignedPosition(offset, 'start', viewport, correction);\n } else if (position < minPosition) {\n position = getAlignedPosition(offset, 'end', viewport, correction);\n }\n previous = Math.min(clamp(position, minPosition, 0), previous);\n return previous;\n });\n state.snapPositionsCache = {\n layoutVersion: state.layoutVersion,\n itemsCount,\n viewportWidth: viewport,\n minPosition,\n correction,\n align,\n positions,\n };\n return positions;\n};\n\n/**\n * Индекс элемента, чья snap-позиция ближе всего к текущей позиции скролла.\n * Если несколько элементов делят позицию у правого края, выбирается последний («доехали до конца»),\n * в остальных случаях — первый из них.\n * @param state стейт скролла\n * @returns индекс найденого элемента\n */\nexport const findNearestSnapIndex = (state: ScrollState): number => {\n const positions = computeSnapPositions(state);\n if (positions.length === 0) {\n return 0;\n }\n const current = state.scrollPosition.get();\n let index = 0;\n let minDistance = Infinity;\n positions.forEach((position, i) => {\n const distance = Math.abs(position - current);\n if (distance < minDistance) {\n minDistance = distance;\n index = i;\n }\n });\n const lastPosition = positions[positions.length - 1];\n if (lastPosition < 0 && positions[index] === lastPosition) {\n return positions.length - 1;\n }\n return index;\n};\n\ninterface ScrollBehavior {\n (scrollState: ScrollState, index: number): number | null;\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 * в режиме `none` — минимальный сдвиг до полной видимости, иначе — snap-позиция элемента\n * @param scrollState стейт скролла\n * @param index индекс элемента\n * @returns новая позиция, либо null (если элемента нет)\n */\nexport const computeTargetPositionForIndex: ScrollBehavior = (scrollState, index) => {\n if (scrollState.scrollSnapAlign === 'none') {\n return computePositionForIndex(scrollState, index);\n }\n return computeSnapPositions(scrollState)[index] ?? null;\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 * Позиция скролла, при которой элемент выровнен во вьюпорте согласно align\n * @param offset метрики элемента\n * @param align режим выравнивания\n * @param viewportWidth ширина вьюпорта\n * @param correction коррекция на кнопки по краям\n * @returns позиция скролла (0 — начало контента, отрицательные значения — прокрутка вправо)\n */\nconst getAlignedPosition = (\n offset: ItemOffset,\n align: ScrollSnapAlign,\n viewportWidth: number,\n correction: number\n): number => {\n switch (align) {\n case 'center':\n return viewportWidth / 2 - (offset.left + offset.right) / 2;\n case 'end':\n return viewportWidth - offset.right - correction;\n case 'start':\n default:\n return -offset.left + correction;\n }\n};\n\n/**\n * Список snap-позиций — по одной на элемент, в порядке элементов.\n *\n * Если элемент можно выровнять согласно scrollSnapAlign, берётся честная позиция.\n * У краёв контента честное выравнивание недостижимо (например, центр узкого последнего элемента\n * нельзя подвести к центру вьюпорта) — тогда элемент доводится до полной видимости у ближнего края.\n * Позиции не возрастают по индексу. Совпасть у соседних элементов они могут только когда в диапазоне\n * прокрутки физически нет места для отдельных состояний (контент выступает за вьюпорт меньше,\n * чем на ширину хвостовых элементов).\n *\n * В режиме `none` позиции считаются как для `start` без коррекции на кнопки\n * и используются только индикатором (DotPages).\n *\n * Результат кэшируется на стейте: DotPages вызывает расчёт на каждое изменение scrollPosition,\n * а позиции меняются только вместе с раскладкой. Возвращаемый массив нельзя мутировать.\n *\n * @param state стейт скролла\n * @returns массив позиций\n */\nexport const computeSnapPositions = (state: ScrollState): number[] => {\n const { items, viewportWidth, contentWidth, defaultButtonsCorrection, scrollSnapAlign } = state;\n const viewport = viewportWidth.get();\n const minPosition = Math.min(viewport - contentWidth.get(), 0);\n const isSnap = scrollSnapAlign !== 'none';\n const align = isSnap ? scrollSnapAlign : 'start';\n const correction = isSnap ? defaultButtonsCorrection.get() : 0;\n const itemsCount = items.get().length;\n // метрики элементов переписываются только в recalculateItemPositions (layoutVersion),\n // остальные входы — размеры, коррекция и режим — сравниваются явно\n const cache = state.snapPositionsCache;\n if (\n cache &&\n cache.layoutVersion === state.layoutVersion &&\n cache.itemsCount === itemsCount &&\n cache.viewportWidth === viewport &&\n cache.minPosition === minPosition &&\n cache.correction === correction &&\n cache.align === align\n ) {\n return cache.positions;\n }\n let previous = 0;\n const positions = items.get().map((itemRef) => {\n const offset = itemRef.current?.[OFFSET_ATTR];\n if (!offset) {\n return previous;\n }\n let position = getAlignedPosition(offset, align, viewport, correction);\n if (position > 0) {\n position = getAlignedPosition(offset, 'start', viewport, correction);\n } else if (position < minPosition) {\n position = getAlignedPosition(offset, 'end', viewport, correction);\n }\n previous = Math.min(clamp(position, minPosition, 0), previous);\n return previous;\n });\n state.snapPositionsCache = {\n layoutVersion: state.layoutVersion,\n itemsCount,\n viewportWidth: viewport,\n minPosition,\n correction,\n align,\n positions,\n };\n return positions;\n};\n\n/**\n * Индекс элемента, чья snap-позиция ближе всего к текущей позиции скролла.\n * Если несколько элементов делят позицию у правого края, выбирается последний («доехали до конца»),\n * в остальных случаях — первый из них.\n * @param state стейт скролла\n * @returns индекс найденого элемента\n */\nexport const findNearestSnapIndex = (state: ScrollState): number => {\n const positions = computeSnapPositions(state);\n if (positions.length === 0) {\n return 0;\n }\n const current = state.scrollPosition.get();\n let index = 0;\n let minDistance = Infinity;\n positions.forEach((position, i) => {\n const distance = Math.abs(position - current);\n if (distance < minDistance) {\n minDistance = distance;\n index = i;\n }\n });\n const lastPosition = positions[positions.length - 1];\n if (lastPosition < 0 && positions[index] === lastPosition) {\n return positions.length - 1;\n }\n return index;\n};\n\n// допуск на дробные размеры: контент, который больше вьюпорта на доли пикселя, не даёт лишней страницы\nconst PAGES_EPSILON = 0.5;\n// при более короткой прокрутке индицировать нечего: скрыта узкая полоска контента\nconst PAGES_MIN_SCROLL_RANGE = 50;\n// участок у края прокрутки, на котором активен крайний dot\nconst PAGES_EDGE_ZONE = 20;\n// крайний, средний и крайний dot — меньше состояний у прокручиваемого контента не бывает\nconst MIN_PAGES_COUNT = 3;\n\n/**\n * Количество страниц для индикатора в режиме `pages`: сколько вьюпортов занимает контент, но не меньше трёх,\n * чтобы у начала, середины и конца прокрутки были свои dots\n * @param state стейт скролла\n * @returns количество страниц, 0 — если диапазон прокрутки меньше PAGES_MIN_SCROLL_RANGE, элементов нет\n * или размеры еще не посчитаны\n */\nexport const computePagesCount = (state: ScrollState): number => {\n const viewport = state.viewportWidth.get();\n const content = state.contentWidth.get();\n if (state.items.get().length === 0 || viewport <= 0 || content - viewport < PAGES_MIN_SCROLL_RANGE) {\n return 0;\n }\n return Math.max(Math.ceil((content - PAGES_EPSILON) / viewport), MIN_PAGES_COUNT);\n};\n\n/**\n * Индекс активной страницы в режиме `pages`. Крайние dots активны только у краёв прокрутки,\n * поэтому любой другой dot означает, что с обеих сторон есть скрытый контент. Средние dots делят\n * остальной диапазон прокрутки поровну\n * @param state стейт скролла\n * @param pagesCount количество страниц, см. computePagesCount\n * @returns индекс активной страницы\n */\nexport const findActivePageIndex = (state: ScrollState, pagesCount: number): number => {\n const range = Math.max(state.contentWidth.get() - state.viewportWidth.get(), 0);\n const distance = clamp(-state.scrollPosition.get(), 0, range);\n // у короткой прокрутки зоны краёв не должны съедать середину\n const edgeZone = Math.min(PAGES_EDGE_ZONE, range / MIN_PAGES_COUNT);\n if (pagesCount < MIN_PAGES_COUNT || distance <= edgeZone) {\n return 0;\n }\n if (distance >= range - edgeZone) {\n return pagesCount - 1;\n }\n const middleCount = pagesCount - 2;\n const middleIndex = Math.floor(((distance - edgeZone) / (range - 2 * edgeZone)) * middleCount);\n return 1 + Math.min(middleIndex, middleCount - 1);\n};\n\ninterface ScrollBehavior {\n (scrollState: ScrollState, index: number): number | null;\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 * в режиме `none` — минимальный сдвиг до полной видимости, иначе — snap-позиция элемента\n * @param scrollState стейт скролла\n * @param index индекс элемента\n * @returns новая позиция, либо null (если элемента нет)\n */\nexport const computeTargetPositionForIndex: ScrollBehavior = (scrollState, index) => {\n if (scrollState.scrollSnapAlign === 'none') {\n return computePositionForIndex(scrollState, index);\n }\n return computeSnapPositions(scrollState)[index] ?? null;\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import './index.css';
|
|
2
|
-
var styles = {"scroll-wrapper":"magritte-scroll-wrapper___vTdZl_6-6-0","scrollWrapper":"magritte-scroll-wrapper___vTdZl_6-6-0","scrollable-container":"magritte-scrollable-container___AKIUp_6-6-0","scrollableContainer":"magritte-scrollable-container___AKIUp_6-6-0","scroll-buttons-container":"magritte-scroll-buttons-container___ZeI5a_6-6-0","scrollButtonsContainer":"magritte-scroll-buttons-container___ZeI5a_6-6-0","scroll-buttons-container-on-hover":"magritte-scroll-buttons-container-on-hover___PFUvV_6-6-0","scrollButtonsContainerOnHover":"magritte-scroll-buttons-container-on-hover___PFUvV_6-6-0","scroll-button":"magritte-scroll-button___4GQu3_6-6-0","scrollButton":"magritte-scroll-button___4GQu3_6-6-0","scroll-buttons":"magritte-scroll-buttons___0SjoR_6-6-0","scrollButtons":"magritte-scroll-buttons___0SjoR_6-6-0","scroll-buttons-small":"magritte-scroll-buttons-small___xG3MS_6-6-0","scrollButtonsSmall":"magritte-scroll-buttons-small___xG3MS_6-6-0","scroll-button-left":"magritte-scroll-button-left___UueEY_6-6-0","scrollButtonLeft":"magritte-scroll-button-left___UueEY_6-6-0","scroll-button-right":"magritte-scroll-button-right___wZOn-_6-6-0","scrollButtonRight":"magritte-scroll-button-right___wZOn-_6-6-0","position-container":"magritte-position-container___1A4Bv_6-6-0","positionContainer":"magritte-position-container___1A4Bv_6-6-0","dot-container":"magritte-dot-container___ahtlG_6-6-0","dotContainer":"magritte-dot-container___ahtlG_6-6-0"};
|
|
3
|
-
|
|
4
|
-
export { styles as s };
|
|
5
|
-
//# sourceMappingURL=scrollableContainer-C_ZfFVZw.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scrollableContainer-C_ZfFVZw.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|