@hh.ru/magritte-ui-scrollable-container 6.3.5 → 6.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ScrollStateProvider.d.ts +5 -0
- package/ScrollStateProvider.js +2 -0
- package/ScrollStateProvider.js.map +1 -1
- package/ScrollableContainer.js +1 -1
- package/ScrollableContainerDefaultLayout.js +1 -1
- package/ScrollableContainerDotPages.js +1 -1
- package/ScrollableContainerGallery.js +2 -1
- package/ScrollableContainerGallery.js.map +1 -1
- package/ScrollableItem.js +1 -1
- package/index.css +10 -10
- package/index.d.ts +2 -1
- package/index.js +4 -4
- package/index.mock.js +1 -1
- package/package.json +4 -4
- package/scrollableContainer-DNx3E7GT.js +5 -0
- package/scrollableContainer-DNx3E7GT.js.map +1 -0
- package/types.d.ts +13 -5
- package/types.js.map +1 -1
- package/useScrollContainer.js +9 -3
- package/useScrollContainer.js.map +1 -1
- package/useScrollableControls.js +31 -0
- package/useScrollableControls.js.map +1 -1
- package/utils.d.ts +10 -3
- package/utils.js +10 -2
- package/utils.js.map +1 -1
- package/scrollableContainer-CJSC-Im0.js +0 -5
- package/scrollableContainer-CJSC-Im0.js.map +0 -1
package/ScrollStateProvider.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { type RefObject } from 'react';
|
|
|
2
2
|
import { MotionValue } from 'motion/react';
|
|
3
3
|
import { ObservableValue } from '@hh.ru/magritte-ui-scrollable-container/ObservableValue';
|
|
4
4
|
import { type ItemWithOffset, type ScrollSnapAlign } from '@hh.ru/magritte-ui-scrollable-container/types';
|
|
5
|
+
export type BehaviorScrollType = 'animate' | 'instant';
|
|
5
6
|
export interface ScrollState {
|
|
6
7
|
/** ширина контента, которая складывается из ширины элементов галереи */
|
|
7
8
|
contentWidth: ObservableValue<number>;
|
|
@@ -11,6 +12,8 @@ export interface ScrollState {
|
|
|
11
12
|
items: ObservableValue<RefObject<HTMLElement & ItemWithOffset>[]>;
|
|
12
13
|
/** текущая позиция */
|
|
13
14
|
scrollPosition: MotionValue<number>;
|
|
15
|
+
/** текущая позиция, обернется в spring */
|
|
16
|
+
springScrollPosition: MotionValue<number> | null;
|
|
14
17
|
/** Определяет, как ближайший элемент будет размещён во вьюпорте при автоматическом скролле */
|
|
15
18
|
scrollSnapAlign: ScrollSnapAlign;
|
|
16
19
|
/**
|
|
@@ -23,6 +26,8 @@ export interface ScrollState {
|
|
|
23
26
|
rightCorrection: ObservableValue<number>;
|
|
24
27
|
/** индекс элемента для отложенного скролла */
|
|
25
28
|
indexForDeferScroll: number;
|
|
29
|
+
/** тип поведения для отложенного скролла */
|
|
30
|
+
behaviorScrollTypeDeferScroll: BehaviorScrollType;
|
|
26
31
|
}
|
|
27
32
|
export declare const createScrollState: () => ScrollState;
|
|
28
33
|
export declare const ScrollStateContext: import("react").Context<ScrollState>;
|
package/ScrollStateProvider.js
CHANGED
|
@@ -8,10 +8,12 @@ const createScrollState = () => ({
|
|
|
8
8
|
viewportWidth: new ObservableValue(0),
|
|
9
9
|
items: new ObservableValue([]),
|
|
10
10
|
scrollPosition: new MotionValue(0),
|
|
11
|
+
springScrollPosition: null,
|
|
11
12
|
defaultButtonsCorrection: new ObservableValue(0),
|
|
12
13
|
leftCorrection: new ObservableValue(0),
|
|
13
14
|
rightCorrection: new ObservableValue(0),
|
|
14
15
|
indexForDeferScroll: -1,
|
|
16
|
+
behaviorScrollTypeDeferScroll: 'animate',
|
|
15
17
|
scrollSnapAlign: 'none',
|
|
16
18
|
});
|
|
17
19
|
const ScrollStateContext = createContext(createScrollState());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScrollStateProvider.js","sources":["src/ScrollStateProvider.tsx"],"sourcesContent":["import { type RefObject, createContext, useContext } from 'react';\nimport { MotionValue } from 'motion/react';\n\nimport { ObservableValue } from '@hh.ru/magritte-ui-scrollable-container/ObservableValue';\nimport { type ItemWithOffset, type ScrollSnapAlign } from '@hh.ru/magritte-ui-scrollable-container/types';\n\nexport interface ScrollState {\n /** ширина контента, которая складывается из ширины элементов галереи */\n contentWidth: ObservableValue<number>;\n /** ширина вьюпорта для просмотра галереи */\n viewportWidth: ObservableValue<number>;\n /** элементы галереи */\n items: ObservableValue<RefObject<HTMLElement & ItemWithOffset>[]>;\n /** текущая позиция */\n scrollPosition: MotionValue<number>;\n /** Определяет, как ближайший элемент будет размещён во вьюпорте при автоматическом скролле */\n scrollSnapAlign: ScrollSnapAlign;\n /**\n * флаг коррекции \"по умолчанию\"\n * возникает при использовании \"стандартных\" (по спеке) кнопок в fade\n */\n defaultButtonsCorrection: ObservableValue<number>;\n /** значения коррекции */\n leftCorrection: ObservableValue<number>;\n rightCorrection: ObservableValue<number>;\n /** индекс элемента для отложенного скролла */\n indexForDeferScroll: number;\n}\n\nexport const createScrollState = (): ScrollState => ({\n contentWidth: new ObservableValue(0),\n viewportWidth: new ObservableValue(0),\n items: new ObservableValue<RefObject<HTMLElement & ItemWithOffset>[]>([]),\n scrollPosition: new MotionValue(0),\n defaultButtonsCorrection: new ObservableValue(0),\n leftCorrection: new ObservableValue(0),\n rightCorrection: new ObservableValue(0),\n indexForDeferScroll: -1,\n scrollSnapAlign: 'none',\n});\n\nexport const ScrollStateContext = createContext<ScrollState>(createScrollState());\n\nexport const useScrollState = (): ScrollState => useContext(ScrollStateContext);\n"],"names":[],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"ScrollStateProvider.js","sources":["src/ScrollStateProvider.tsx"],"sourcesContent":["import { type RefObject, createContext, useContext } from 'react';\nimport { MotionValue } from 'motion/react';\n\nimport { ObservableValue } from '@hh.ru/magritte-ui-scrollable-container/ObservableValue';\nimport { type ItemWithOffset, type ScrollSnapAlign } from '@hh.ru/magritte-ui-scrollable-container/types';\n\nexport type BehaviorScrollType = 'animate' | 'instant';\n\nexport interface ScrollState {\n /** ширина контента, которая складывается из ширины элементов галереи */\n contentWidth: ObservableValue<number>;\n /** ширина вьюпорта для просмотра галереи */\n viewportWidth: ObservableValue<number>;\n /** элементы галереи */\n items: ObservableValue<RefObject<HTMLElement & ItemWithOffset>[]>;\n /** текущая позиция */\n scrollPosition: MotionValue<number>;\n /** текущая позиция, обернется в spring */\n springScrollPosition: MotionValue<number> | null;\n /** Определяет, как ближайший элемент будет размещён во вьюпорте при автоматическом скролле */\n scrollSnapAlign: ScrollSnapAlign;\n /**\n * флаг коррекции \"по умолчанию\"\n * возникает при использовании \"стандартных\" (по спеке) кнопок в fade\n */\n defaultButtonsCorrection: ObservableValue<number>;\n /** значения коррекции */\n leftCorrection: ObservableValue<number>;\n rightCorrection: ObservableValue<number>;\n /** индекс элемента для отложенного скролла */\n indexForDeferScroll: number;\n /** тип поведения для отложенного скролла */\n behaviorScrollTypeDeferScroll: BehaviorScrollType;\n}\n\nexport const createScrollState = (): ScrollState => ({\n contentWidth: new ObservableValue(0),\n viewportWidth: new ObservableValue(0),\n items: new ObservableValue<RefObject<HTMLElement & ItemWithOffset>[]>([]),\n scrollPosition: new MotionValue(0),\n springScrollPosition: null,\n defaultButtonsCorrection: new ObservableValue(0),\n leftCorrection: new ObservableValue(0),\n rightCorrection: new ObservableValue(0),\n indexForDeferScroll: -1,\n behaviorScrollTypeDeferScroll: 'animate',\n scrollSnapAlign: 'none',\n});\n\nexport const ScrollStateContext = createContext<ScrollState>(createScrollState());\n\nexport const useScrollState = (): ScrollState => useContext(ScrollStateContext);\n"],"names":[],"mappings":";;;;AAmCa,MAAA,iBAAiB,GAAG,OAAoB;AACjD,IAAA,YAAY,EAAE,IAAI,eAAe,CAAC,CAAC,CAAC;AACpC,IAAA,aAAa,EAAE,IAAI,eAAe,CAAC,CAAC,CAAC;AACrC,IAAA,KAAK,EAAE,IAAI,eAAe,CAA4C,EAAE,CAAC;AACzE,IAAA,cAAc,EAAE,IAAI,WAAW,CAAC,CAAC,CAAC;AAClC,IAAA,oBAAoB,EAAE,IAAI;AAC1B,IAAA,wBAAwB,EAAE,IAAI,eAAe,CAAC,CAAC,CAAC;AAChD,IAAA,cAAc,EAAE,IAAI,eAAe,CAAC,CAAC,CAAC;AACtC,IAAA,eAAe,EAAE,IAAI,eAAe,CAAC,CAAC,CAAC;IACvC,mBAAmB,EAAE,CAAC,CAAC;AACvB,IAAA,6BAA6B,EAAE,SAAS;AACxC,IAAA,eAAe,EAAE,MAAM;AAC1B,CAAA,EAAE;MAEU,kBAAkB,GAAG,aAAa,CAAc,iBAAiB,EAAE,EAAE;AAErE,MAAA,cAAc,GAAG,MAAmB,UAAU,CAAC,kBAAkB;;;;"}
|
package/ScrollableContainer.js
CHANGED
|
@@ -11,7 +11,7 @@ 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-DNx3E7GT.js';
|
|
15
15
|
import 'motion/react';
|
|
16
16
|
import './ObservableValue.js';
|
|
17
17
|
import '@hh.ru/magritte-common-use-translation';
|
|
@@ -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-DNx3E7GT.js';
|
|
13
13
|
import './ObservableValue.js';
|
|
14
14
|
import './useScrollableControls.js';
|
|
15
15
|
import '@hh.ru/magritte-internal-custom-scroll';
|
|
@@ -7,7 +7,7 @@ import { useScrollState } from './ScrollStateProvider.js';
|
|
|
7
7
|
import { OFFSET_ATTR } from './types.js';
|
|
8
8
|
import { useInitOnce, findIndexNearestToSnapPoint } from './utils.js';
|
|
9
9
|
import { VSpacing } from '@hh.ru/magritte-ui-spacing';
|
|
10
|
-
import { s as styles } from './scrollableContainer-
|
|
10
|
+
import { s as styles } from './scrollableContainer-DNx3E7GT.js';
|
|
11
11
|
import 'motion/react';
|
|
12
12
|
import './ObservableValue.js';
|
|
13
13
|
import '@hh.ru/magritte-internal-custom-scroll';
|
|
@@ -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, findIndexNearestToSnapPoint, computeScrollSnapBehavior } from './utils.js';
|
|
9
|
-
import { s as styles } from './scrollableContainer-
|
|
9
|
+
import { s as styles } from './scrollableContainer-DNx3E7GT.js';
|
|
10
10
|
import './ObservableValue.js';
|
|
11
11
|
import '@hh.ru/magritte-common-func-utils';
|
|
12
12
|
import '@hh.ru/magritte-internal-custom-scroll';
|
|
@@ -66,6 +66,7 @@ const ScrollableContainerGallery = ({ children, onScroll, onReady, onChangeSize,
|
|
|
66
66
|
damping: 75,
|
|
67
67
|
mass: 0.5,
|
|
68
68
|
});
|
|
69
|
+
scrollState.springScrollPosition = springScrollPosition;
|
|
69
70
|
return (jsx(GalleryContext.Provider, { value: {
|
|
70
71
|
registerItem,
|
|
71
72
|
removeItem,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScrollableContainerGallery.js","sources":["src/ScrollableContainerGallery.tsx"],"sourcesContent":["import { type FC, createContext, useContext, useEffect, useRef } from 'react';\nimport { animate, motion, useSpring } from 'motion/react';\n\nimport { clamp } from '@hh.ru/magritte-internal-custom-scroll/initScrollHandlers';\nimport { useScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport type {\n ScrollableContainerGalleryProps,\n RegisterAndRemoveItem,\n} from '@hh.ru/magritte-ui-scrollable-container/types';\nimport { useScrollContainer } from '@hh.ru/magritte-ui-scrollable-container/useScrollContainer';\nimport {\n getDisableState,\n findIndexNearestToSnapPoint,\n computeScrollSnapBehavior,\n} from '@hh.ru/magritte-ui-scrollable-container/utils';\n\nimport styles from './scrollableContainer.less';\n\nconst GalleryContext = createContext<RegisterAndRemoveItem>({\n registerItem: () => null,\n removeItem: () => null,\n});\n\nexport const useGalleryContext = (): RegisterAndRemoveItem => useContext(GalleryContext);\n\nexport const ScrollableContainerGallery: FC<ScrollableContainerGalleryProps> = ({\n children,\n onScroll,\n onReady,\n onChangeSize,\n ...props\n}) => {\n const scrollState = useScrollState();\n const onReadyRef = useRef(onReady);\n const onScrollRef = useRef(onScroll);\n const onChangeSizeRef = useRef(onChangeSize);\n onReadyRef.current = onReady;\n onScrollRef.current = onScroll;\n onChangeSizeRef.current = onChangeSize;\n\n const { registerItem, removeItem, initScrollHandlers, containerRef, positionContainerRef, isTouch } =\n useScrollContainer();\n\n useEffect(() => {\n const { scrollPosition, viewportWidth, contentWidth } = scrollState;\n const updateScrollPositionByResize = () => {\n const index = findIndexNearestToSnapPoint(scrollState);\n const scrollSnapBehavior = computeScrollSnapBehavior(scrollState);\n const target = scrollSnapBehavior(scrollState, index);\n if (target === null) {\n return;\n }\n const position = clamp(target, viewportWidth.get() - contentWidth.get(), 0);\n onChangeSizeRef.current?.(getDisableState(scrollState));\n if (scrollPosition.get() === position) {\n return;\n }\n animate(scrollPosition, position, {\n velocity: Math.max(scrollPosition.getVelocity(), 1),\n });\n };\n const unsubscribe = [\n scrollPosition.on('change', () => {\n onScrollRef.current?.(getDisableState(scrollState));\n }),\n viewportWidth.on('change', updateScrollPositionByResize),\n contentWidth.on('change', updateScrollPositionByResize),\n ];\n return () => {\n unsubscribe.forEach((fn) => fn());\n };\n }, [scrollState]);\n\n useEffect(() => {\n onReadyRef.current?.(getDisableState(scrollState));\n return initScrollHandlers();\n }, [initScrollHandlers, scrollState]);\n\n const springScrollPosition = useSpring(scrollState.scrollPosition, {\n stiffness: 1800,\n damping: 75,\n mass: 0.5,\n });\n\n return (\n <GalleryContext.Provider\n value={{\n registerItem,\n removeItem,\n }}\n >\n <div\n ref={containerRef}\n role=\"list\"\n className={styles.scrollableContainer}\n data-qa=\"scrollable-container__overflow-container\"\n {...props}\n >\n <motion.div\n ref={positionContainerRef}\n data-qa=\"scrollable-container__position-container\"\n className={styles.positionContainer}\n style={{ x: isTouch ? scrollState.scrollPosition : springScrollPosition }}\n >\n {children}\n </motion.div>\n </div>\n </GalleryContext.Provider>\n );\n};\n"],"names":["_jsx"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ScrollableContainerGallery.js","sources":["src/ScrollableContainerGallery.tsx"],"sourcesContent":["import { type FC, createContext, useContext, useEffect, useRef } from 'react';\nimport { animate, motion, useSpring } from 'motion/react';\n\nimport { clamp } from '@hh.ru/magritte-internal-custom-scroll/initScrollHandlers';\nimport { useScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport type {\n ScrollableContainerGalleryProps,\n RegisterAndRemoveItem,\n} from '@hh.ru/magritte-ui-scrollable-container/types';\nimport { useScrollContainer } from '@hh.ru/magritte-ui-scrollable-container/useScrollContainer';\nimport {\n getDisableState,\n findIndexNearestToSnapPoint,\n computeScrollSnapBehavior,\n} from '@hh.ru/magritte-ui-scrollable-container/utils';\n\nimport styles from './scrollableContainer.less';\n\nconst GalleryContext = createContext<RegisterAndRemoveItem>({\n registerItem: () => null,\n removeItem: () => null,\n});\n\nexport const useGalleryContext = (): RegisterAndRemoveItem => useContext(GalleryContext);\n\nexport const ScrollableContainerGallery: FC<ScrollableContainerGalleryProps> = ({\n children,\n onScroll,\n onReady,\n onChangeSize,\n ...props\n}) => {\n const scrollState = useScrollState();\n const onReadyRef = useRef(onReady);\n const onScrollRef = useRef(onScroll);\n const onChangeSizeRef = useRef(onChangeSize);\n onReadyRef.current = onReady;\n onScrollRef.current = onScroll;\n onChangeSizeRef.current = onChangeSize;\n\n const { registerItem, removeItem, initScrollHandlers, containerRef, positionContainerRef, isTouch } =\n useScrollContainer();\n\n useEffect(() => {\n const { scrollPosition, viewportWidth, contentWidth } = scrollState;\n const updateScrollPositionByResize = () => {\n const index = findIndexNearestToSnapPoint(scrollState);\n const scrollSnapBehavior = computeScrollSnapBehavior(scrollState);\n const target = scrollSnapBehavior(scrollState, index);\n if (target === null) {\n return;\n }\n const position = clamp(target, viewportWidth.get() - contentWidth.get(), 0);\n onChangeSizeRef.current?.(getDisableState(scrollState));\n if (scrollPosition.get() === position) {\n return;\n }\n animate(scrollPosition, position, {\n velocity: Math.max(scrollPosition.getVelocity(), 1),\n });\n };\n const unsubscribe = [\n scrollPosition.on('change', () => {\n onScrollRef.current?.(getDisableState(scrollState));\n }),\n viewportWidth.on('change', updateScrollPositionByResize),\n contentWidth.on('change', updateScrollPositionByResize),\n ];\n return () => {\n unsubscribe.forEach((fn) => fn());\n };\n }, [scrollState]);\n\n useEffect(() => {\n onReadyRef.current?.(getDisableState(scrollState));\n return initScrollHandlers();\n }, [initScrollHandlers, scrollState]);\n\n const springScrollPosition = useSpring(scrollState.scrollPosition, {\n stiffness: 1800,\n damping: 75,\n mass: 0.5,\n });\n scrollState.springScrollPosition = springScrollPosition;\n\n return (\n <GalleryContext.Provider\n value={{\n registerItem,\n removeItem,\n }}\n >\n <div\n ref={containerRef}\n role=\"list\"\n className={styles.scrollableContainer}\n data-qa=\"scrollable-container__overflow-container\"\n {...props}\n >\n <motion.div\n ref={positionContainerRef}\n data-qa=\"scrollable-container__position-container\"\n className={styles.positionContainer}\n style={{ x: isTouch ? scrollState.scrollPosition : springScrollPosition }}\n >\n {children}\n </motion.div>\n </div>\n </GalleryContext.Provider>\n );\n};\n"],"names":["_jsx"],"mappings":"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"}
|
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-DNx3E7GT.js';
|
|
17
17
|
|
|
18
18
|
const ScrollableItem = ({ children, scrollToItemOnFocus, ...props }) => {
|
|
19
19
|
const ref = useRef(null);
|
package/index.css
CHANGED
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
.magritte-night-theme{
|
|
6
6
|
--magritte-gradient-component-chat-input-background-fade-v25-0-0:#1b1b1b00 0%, #1b1b1b 100%;
|
|
7
7
|
}
|
|
8
|
-
.magritte-scroll-wrapper___vTdZl_6-
|
|
8
|
+
.magritte-scroll-wrapper___vTdZl_6-4-1{
|
|
9
9
|
position:relative;
|
|
10
10
|
touch-action:pan-y pinch-zoom;
|
|
11
11
|
contain:layout;
|
|
12
12
|
}
|
|
13
|
-
.magritte-scrollable-container___AKIUp_6-
|
|
13
|
+
.magritte-scrollable-container___AKIUp_6-4-1{
|
|
14
14
|
display:block;
|
|
15
15
|
overflow-x:hidden;
|
|
16
16
|
overflow-x:clip;
|
|
@@ -26,10 +26,10 @@
|
|
|
26
26
|
margin-left:var(--magritte-ui-scrollabe-container-ml, -4px);
|
|
27
27
|
margin-right:var(--magritte-ui-scrollabe-container-mr, -4px);
|
|
28
28
|
}
|
|
29
|
-
.magritte-scroll-buttons-container___ZeI5a_6-
|
|
29
|
+
.magritte-scroll-buttons-container___ZeI5a_6-4-1{
|
|
30
30
|
position:relative;
|
|
31
31
|
}
|
|
32
|
-
.magritte-scroll-buttons___0SjoR_6-
|
|
32
|
+
.magritte-scroll-buttons___0SjoR_6-4-1{
|
|
33
33
|
--fade-left:linear-gradient(90deg, var(--magritte-gradient-component-chat-input-background-fade-v25-0-0));
|
|
34
34
|
--fade-right:linear-gradient(270deg, var(--magritte-gradient-component-chat-input-background-fade-v25-0-0));
|
|
35
35
|
--left-fade-mask:var(--fade-left) 30px 0 / 128px 100% no-repeat, linear-gradient(#000, #000) right / calc(100% - 158px) 100% no-repeat;
|
|
@@ -38,29 +38,29 @@
|
|
|
38
38
|
-webkit-mask:none;
|
|
39
39
|
mask:none;
|
|
40
40
|
}
|
|
41
|
-
.magritte-scroll-buttons-small___xG3MS_6-
|
|
41
|
+
.magritte-scroll-buttons-small___xG3MS_6-4-1{
|
|
42
42
|
--left-fade-mask:var(--fade-left) 0px 0 / 44px 100% no-repeat, linear-gradient(#000, #000) right / calc(100% - 44px) 100% no-repeat;
|
|
43
43
|
--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;
|
|
44
44
|
--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;
|
|
45
45
|
}
|
|
46
|
-
.magritte-scroll-button___4GQu3_6-
|
|
46
|
+
.magritte-scroll-button___4GQu3_6-4-1{
|
|
47
47
|
display:none;
|
|
48
48
|
position:absolute;
|
|
49
49
|
top:50%;
|
|
50
50
|
transform:translateY(-50%);
|
|
51
51
|
}
|
|
52
|
-
.magritte-scroll-button-left___UueEY_6-
|
|
52
|
+
.magritte-scroll-button-left___UueEY_6-4-1{
|
|
53
53
|
z-index:1;
|
|
54
54
|
left:0;
|
|
55
55
|
}
|
|
56
|
-
.magritte-scroll-button-right___wZOn-_6-
|
|
56
|
+
.magritte-scroll-button-right___wZOn-_6-4-1{
|
|
57
57
|
right:0;
|
|
58
58
|
}
|
|
59
|
-
.magritte-position-container___1A4Bv_6-
|
|
59
|
+
.magritte-position-container___1A4Bv_6-4-1{
|
|
60
60
|
box-sizing:border-box;
|
|
61
61
|
width:100%;
|
|
62
62
|
}
|
|
63
|
-
.magritte-dot-container___ahtlG_6-
|
|
63
|
+
.magritte-dot-container___ahtlG_6-4-1{
|
|
64
64
|
display:flex;
|
|
65
65
|
justify-content:center;
|
|
66
66
|
}
|
package/index.d.ts
CHANGED
|
@@ -2,4 +2,5 @@ export { ScrollableContainer } from '@hh.ru/magritte-ui-scrollable-container/Scr
|
|
|
2
2
|
export { useScrollableControls } from '@hh.ru/magritte-ui-scrollable-container/useScrollableControls';
|
|
3
3
|
export { useGalleryContext } from '@hh.ru/magritte-ui-scrollable-container/ScrollableContainerGallery';
|
|
4
4
|
export { useScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';
|
|
5
|
-
export
|
|
5
|
+
export { getItemOffset } from '@hh.ru/magritte-ui-scrollable-container/utils';
|
|
6
|
+
export type { ItemOffset, RegisterAndRemoveItem, ScrollableContainerProps, SpacingCorrectionProps, ScrollableControls, ScrollableItemProps, ScrollableContainerGalleryProps, ScrollableContainerDotPagesProps, ScrollDisableState, ScrollableContainerButtonProps, ScrollableContainerDefaultLayoutProps, ScrollableContainerDefaultLayoutSize, ScrollSnapAlign, } from '@hh.ru/magritte-ui-scrollable-container/types';
|
package/index.js
CHANGED
|
@@ -3,6 +3,7 @@ export { ScrollableContainer } from './ScrollableContainer.js';
|
|
|
3
3
|
export { useScrollableControls } from './useScrollableControls.js';
|
|
4
4
|
export { useGalleryContext } from './ScrollableContainerGallery.js';
|
|
5
5
|
export { useScrollState } from './ScrollStateProvider.js';
|
|
6
|
+
export { getItemOffset } from './utils.js';
|
|
6
7
|
import 'react/jsx-runtime';
|
|
7
8
|
import 'react';
|
|
8
9
|
import 'classnames';
|
|
@@ -12,15 +13,14 @@ import './ScrollableContainerDefaultLayout.js';
|
|
|
12
13
|
import 'motion/react';
|
|
13
14
|
import '@hh.ru/magritte-common-use-translation';
|
|
14
15
|
import '@hh.ru/magritte-ui-icon/icon';
|
|
15
|
-
import './
|
|
16
|
-
import '@hh.ru/magritte-internal-custom-scroll';
|
|
17
|
-
import './types.js';
|
|
18
|
-
import './scrollableContainer-CJSC-Im0.js';
|
|
16
|
+
import './scrollableContainer-DNx3E7GT.js';
|
|
19
17
|
import './ScrollableContainerDotPages.js';
|
|
20
18
|
import '@hh.ru/magritte-internal-custom-scroll/initScrollHandlers';
|
|
21
19
|
import '@hh.ru/magritte-ui-dot-pages';
|
|
20
|
+
import './types.js';
|
|
22
21
|
import '@hh.ru/magritte-ui-spacing';
|
|
23
22
|
import './ScrollableItem.js';
|
|
23
|
+
import '@hh.ru/magritte-internal-custom-scroll';
|
|
24
24
|
import './useScrollContainer.js';
|
|
25
25
|
import '@hh.ru/magritte-common-func-utils';
|
|
26
26
|
import './ObservableValue.js';
|
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-DNx3E7GT.js';
|
|
17
17
|
import './ObservableValue.js';
|
|
18
18
|
|
|
19
19
|
const staticProps = {
|
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.4.1",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"types": "index.d.ts",
|
|
6
6
|
"sideEffects": [
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"@hh.ru/magritte-design-tokens": "25.0.0",
|
|
25
25
|
"@hh.ru/magritte-internal-custom-scroll": "2.1.1",
|
|
26
26
|
"@hh.ru/magritte-ui-breakpoint": "6.1.1",
|
|
27
|
-
"@hh.ru/magritte-ui-dot-pages": "4.0.
|
|
28
|
-
"@hh.ru/magritte-ui-icon": "15.0.
|
|
27
|
+
"@hh.ru/magritte-ui-dot-pages": "4.0.32",
|
|
28
|
+
"@hh.ru/magritte-ui-icon": "15.0.1",
|
|
29
29
|
"@hh.ru/magritte-ui-mock-component": "1.1.7",
|
|
30
30
|
"@hh.ru/magritte-ui-spacing": "2.1.26"
|
|
31
31
|
},
|
|
@@ -37,5 +37,5 @@
|
|
|
37
37
|
"publishConfig": {
|
|
38
38
|
"access": "public"
|
|
39
39
|
},
|
|
40
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "673159d3e2d52fa7608da8042b16148b9fed7fb4"
|
|
41
41
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import './index.css';
|
|
2
|
+
var styles = {"scroll-wrapper":"magritte-scroll-wrapper___vTdZl_6-4-1","scrollWrapper":"magritte-scroll-wrapper___vTdZl_6-4-1","scrollable-container":"magritte-scrollable-container___AKIUp_6-4-1","scrollableContainer":"magritte-scrollable-container___AKIUp_6-4-1","scroll-buttons-container":"magritte-scroll-buttons-container___ZeI5a_6-4-1","scrollButtonsContainer":"magritte-scroll-buttons-container___ZeI5a_6-4-1","scroll-buttons":"magritte-scroll-buttons___0SjoR_6-4-1","scrollButtons":"magritte-scroll-buttons___0SjoR_6-4-1","scroll-buttons-small":"magritte-scroll-buttons-small___xG3MS_6-4-1","scrollButtonsSmall":"magritte-scroll-buttons-small___xG3MS_6-4-1","scroll-button":"magritte-scroll-button___4GQu3_6-4-1","scrollButton":"magritte-scroll-button___4GQu3_6-4-1","scroll-button-left":"magritte-scroll-button-left___UueEY_6-4-1","scrollButtonLeft":"magritte-scroll-button-left___UueEY_6-4-1","scroll-button-right":"magritte-scroll-button-right___wZOn-_6-4-1","scrollButtonRight":"magritte-scroll-button-right___wZOn-_6-4-1","position-container":"magritte-position-container___1A4Bv_6-4-1","positionContainer":"magritte-position-container___1A4Bv_6-4-1","dot-container":"magritte-dot-container___ahtlG_6-4-1","dotContainer":"magritte-dot-container___ahtlG_6-4-1"};
|
|
3
|
+
|
|
4
|
+
export { styles as s };
|
|
5
|
+
//# sourceMappingURL=scrollableContainer-DNx3E7GT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scrollableContainer-DNx3E7GT.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
package/types.d.ts
CHANGED
|
@@ -2,11 +2,12 @@ import type { HTMLAttributes, RefObject, MouseEventHandler, ReactNode } from 're
|
|
|
2
2
|
import { TokenBaseStaticSpace } from '@hh.ru/magritte-design-tokens/types';
|
|
3
3
|
import type { DotPagesProps } from '@hh.ru/magritte-ui-dot-pages';
|
|
4
4
|
export declare const OFFSET_ATTR: unique symbol;
|
|
5
|
+
export interface ItemOffset {
|
|
6
|
+
left: number;
|
|
7
|
+
right: number;
|
|
8
|
+
}
|
|
5
9
|
export interface ItemWithOffset {
|
|
6
|
-
[OFFSET_ATTR]:
|
|
7
|
-
left: number;
|
|
8
|
-
right: number;
|
|
9
|
-
};
|
|
10
|
+
[OFFSET_ATTR]: ItemOffset;
|
|
10
11
|
}
|
|
11
12
|
export interface ControlWithClick {
|
|
12
13
|
onClick?: MouseEventHandler;
|
|
@@ -33,13 +34,20 @@ export interface ScrollableControls {
|
|
|
33
34
|
scrollToFirstItem: () => void;
|
|
34
35
|
/** двигаем ScrollableContainer к последнему элементу */
|
|
35
36
|
scrollToLastItem: () => void;
|
|
36
|
-
/** скролл к элементу по индексу, элементы сортируются по расположению справа
|
|
37
|
+
/** скролл к элементу по индексу, элементы сортируются по расположению справа налево */
|
|
37
38
|
scrollToIndex: (index: number) => void;
|
|
38
39
|
/**
|
|
39
40
|
* скролл к элементу по ref, должен передаваться ref на элемент который был
|
|
40
41
|
* зарегистрирован с помощью registerItem API
|
|
41
42
|
**/
|
|
42
43
|
scrollToItem: (ref: RefObject<HTMLElement>) => void;
|
|
44
|
+
/** моментальный скролл к элементу по индексу */
|
|
45
|
+
jumpToIndex: (index: number) => void;
|
|
46
|
+
/**
|
|
47
|
+
* моментальный сдвиг позиции на дельту
|
|
48
|
+
* не выравнивает элемент по scrollSnapAlign (безопасен посреди жеста)
|
|
49
|
+
**/
|
|
50
|
+
jumpBy: (delta: number) => void;
|
|
43
51
|
}
|
|
44
52
|
/**
|
|
45
53
|
* Пропы для настройки коррекции отступов в режиме без кнопок, когда надо чтобы край скролла соответствовал
|
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
|
|
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 /** 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":"MAKa,WAAW,GAAG,MAAM,CAAC,oBAAoB;;;;"}
|
package/useScrollContainer.js
CHANGED
|
@@ -15,7 +15,7 @@ const MIN_DELTA_FOR_TOUCH = 5;
|
|
|
15
15
|
const MAX_OFFSET = { [OFFSET_ATTR]: { left: Number.MAX_SAFE_INTEGER } };
|
|
16
16
|
const useScrollContainer = () => {
|
|
17
17
|
const scrollState = useScrollState();
|
|
18
|
-
const { scrollToIndex } = useScrollableControls();
|
|
18
|
+
const { scrollToIndex, jumpToIndex } = useScrollableControls();
|
|
19
19
|
const [isTouch, setIsTouch] = useState(false);
|
|
20
20
|
const leftCorrection = scrollState.leftCorrection.get();
|
|
21
21
|
const rightCorrection = scrollState.rightCorrection.get();
|
|
@@ -51,10 +51,16 @@ const useScrollContainer = () => {
|
|
|
51
51
|
scrollState.contentWidth.set(contentWidth);
|
|
52
52
|
scrollState.items.set(items);
|
|
53
53
|
if (scrollState.indexForDeferScroll !== -1) {
|
|
54
|
-
|
|
54
|
+
if (scrollState.behaviorScrollTypeDeferScroll === 'instant') {
|
|
55
|
+
jumpToIndex(scrollState.indexForDeferScroll);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
scrollToIndex(scrollState.indexForDeferScroll);
|
|
59
|
+
}
|
|
60
|
+
scrollState.behaviorScrollTypeDeferScroll = 'animate';
|
|
55
61
|
scrollState.indexForDeferScroll = -1;
|
|
56
62
|
}
|
|
57
|
-
}, [scrollState, scrollToIndex]);
|
|
63
|
+
}, [scrollState, scrollToIndex, jumpToIndex]);
|
|
58
64
|
// eslint-disable-next-line disable-autofix/react-hooks/exhaustive-deps
|
|
59
65
|
const recalculateItemPositionsDebounced = useCallback(debounce(recalculateItemPositions, 10), [
|
|
60
66
|
recalculateItemPositions,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useScrollContainer.js","sources":["src/useScrollContainer.ts"],"sourcesContent":["import { useRef, useEffect, type RefObject, useCallback, useState } from 'react';\n\nimport { requestAnimation, debounce } from '@hh.ru/magritte-common-func-utils';\nimport { clamp, type ScrollGestureEvent, initScrollHandlers } from '@hh.ru/magritte-internal-custom-scroll';\nimport { useScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport { type ItemWithOffset, OFFSET_ATTR } from '@hh.ru/magritte-ui-scrollable-container/types';\nimport { useScrollableControls } from '@hh.ru/magritte-ui-scrollable-container/useScrollableControls';\nimport {\n useInitOnce,\n findIndexNearestToSnapPoint,\n animateScrollToPosition,\n computeScrollSnapBehavior,\n} from '@hh.ru/magritte-ui-scrollable-container/utils';\n\nconst EPSILON = 0.5;\nconst MIN_DELTA_FOR_TOUCH = 5;\nconst MAX_OFFSET = { [OFFSET_ATTR]: { left: Number.MAX_SAFE_INTEGER } };\n\n/**\n * Переменные полностью описывающие состояние скролла, хранятся в одном объекте, чтобы не плодить\n * кучу ref'ов и передавать всё состояние в функции одним аргументом, а не длинным списком переменных\n */\nexport interface ScrollInternalState {\n /** контейнер, в котором лежит positionContainer (определяет видимую область) */\n containerRef: RefObject<HTMLDivElement>;\n /** контейнер, с помощью изменения положения которого обеспечивается скролл */\n positionContainerRef: RefObject<HTMLDivElement>;\n /** размер коррекции отступов */\n correction: { leftCorrection: number; rightCorrection: number };\n /* Было ли взаимодействие с компонентом - скролл или прокрутка к элементу */\n wasInteracted: boolean;\n}\n\ninterface UseScrollContainer {\n registerItem: (ref: RefObject<HTMLElement>) => void;\n removeItem: (ref: RefObject<HTMLElement>) => void;\n initScrollHandlers: () => VoidFunction;\n containerRef: RefObject<HTMLDivElement>;\n positionContainerRef: RefObject<HTMLDivElement>;\n isTouch: boolean;\n}\n\nexport const useScrollContainer = (): UseScrollContainer => {\n const scrollState = useScrollState();\n const { scrollToIndex } = useScrollableControls();\n const [isTouch, setIsTouch] = useState(false);\n const leftCorrection = scrollState.leftCorrection.get();\n const rightCorrection = scrollState.rightCorrection.get();\n const scrollStateRef = useRef<ScrollInternalState>({\n containerRef: useRef<HTMLDivElement>(null),\n positionContainerRef: useRef<HTMLDivElement>(null),\n correction: { leftCorrection, rightCorrection },\n wasInteracted: false,\n });\n scrollStateRef.current.correction = { leftCorrection, rightCorrection };\n const resizeOberverRef = useRef<ResizeObserver | null>(null);\n\n // recalc positions + report widths into store\n const recalculateItemPositions = useCallback(() => {\n const state = scrollStateRef.current;\n const { containerRef, correction, positionContainerRef } = state;\n const { leftCorrection, rightCorrection } = correction;\n const items = scrollState.items.get();\n if (!containerRef.current || !positionContainerRef.current) {\n return;\n }\n const offsetLeft = positionContainerRef.current?.getBoundingClientRect().left ?? 0;\n items.forEach((itemRef) => {\n if (!itemRef.current) {\n return;\n }\n const rect = itemRef.current.getBoundingClientRect();\n itemRef.current[OFFSET_ATTR] = { left: rect.left - offsetLeft, right: rect.right - offsetLeft };\n });\n items.sort((a, b) => (a.current || MAX_OFFSET)[OFFSET_ATTR].left - (b.current || MAX_OFFSET)[OFFSET_ATTR].left);\n const viewportWidth = containerRef.current.offsetWidth - leftCorrection - rightCorrection;\n const contentWidth = items.reduce(\n (pos, itemRef) => Math.max(pos, itemRef.current?.[OFFSET_ATTR]?.right || 0),\n 0\n );\n scrollState.viewportWidth.set(viewportWidth);\n scrollState.contentWidth.set(contentWidth);\n scrollState.items.set(items);\n if (scrollState.indexForDeferScroll !== -1) {\n scrollToIndex(scrollState.indexForDeferScroll);\n scrollState.indexForDeferScroll = -1;\n }\n }, [scrollState, scrollToIndex]);\n\n // eslint-disable-next-line disable-autofix/react-hooks/exhaustive-deps\n const recalculateItemPositionsDebounced = useCallback(debounce(recalculateItemPositions, 10), [\n recalculateItemPositions,\n ]);\n\n // eslint-disable-next-line disable-autofix/react-hooks/exhaustive-deps\n const scrollToItemDebounced = useInitOnce(() =>\n debounce(() => {\n if (scrollState.scrollSnapAlign === 'none') {\n return;\n }\n const targetItemIndex = findIndexNearestToSnapPoint(scrollState);\n const scrollSnapBehavior = computeScrollSnapBehavior(scrollState);\n const target = scrollSnapBehavior(scrollState, targetItemIndex);\n animateScrollToPosition(scrollState, target);\n }, 100)\n );\n\n useEffect(() => {\n const state = scrollStateRef.current;\n const observer = new ResizeObserver(\n requestAnimation(() => {\n recalculateItemPositions();\n })\n );\n\n scrollState.items.get().forEach((item) => item.current && observer.observe(item.current));\n state.containerRef.current && observer.observe(state.containerRef.current);\n resizeOberverRef.current = observer;\n return () => observer.disconnect();\n // eslint-disable-next-line disable-autofix/react-hooks/exhaustive-deps\n }, []);\n\n // Слушатель нужен, чтобы не вызывать скролл в родительском контейнере (например в bs)\n useEffect(() => {\n const wrapperRef = scrollStateRef.current.containerRef.current;\n if (!wrapperRef) {\n return void 0;\n }\n const handleTouchStartHandler = (event: TouchEvent) => {\n event.stopPropagation();\n };\n wrapperRef.addEventListener('touchstart', handleTouchStartHandler);\n return () => {\n wrapperRef.removeEventListener('touchstart', handleTouchStartHandler);\n };\n }, []);\n\n // события тача\n const didContainerMove = useRef(false);\n const onTouchStart = useCallback(() => {\n setIsTouch(true);\n didContainerMove.current = false;\n scrollState.scrollPosition.stop();\n }, [scrollState]);\n\n const onTouchMove = useCallback(\n (event: ScrollGestureEvent) => {\n if (!didContainerMove.current) {\n // надо отличить тач от свайпа\n didContainerMove.current = Math.abs(event.delta) > MIN_DELTA_FOR_TOUCH;\n }\n scrollState.scrollPosition.set(\n clamp(\n scrollState.scrollPosition.get() + event.delta,\n scrollState.viewportWidth.get() - scrollState.contentWidth.get(),\n 0\n )\n );\n },\n [scrollState]\n );\n\n const onTouchEnd = useCallback(() => {\n if (didContainerMove.current) {\n scrollToItemDebounced();\n }\n }, [scrollToItemDebounced]);\n\n // события мыши\n const didContainerHovered = useRef(false);\n const onMouseEnter = useCallback(() => {\n didContainerHovered.current = true;\n }, []);\n\n const onWheelMove = useCallback(\n (event: ScrollGestureEvent) => {\n setIsTouch(false);\n if (!didContainerHovered.current) {\n return;\n }\n const currentPosition = scrollState.scrollPosition.get();\n const nextPosition = clamp(\n currentPosition + event.delta,\n scrollState.viewportWidth.get() - scrollState.contentWidth.get(),\n 0\n );\n if (Math.abs(nextPosition - currentPosition) > EPSILON) {\n scrollState.scrollPosition.set(nextPosition);\n scrollToItemDebounced();\n event.preventDefault();\n }\n },\n [scrollToItemDebounced, scrollState]\n );\n\n const onMouseLeave = useCallback(() => {\n didContainerHovered.current = false;\n }, []);\n\n const _initScrollHandlers = useCallback(\n () =>\n initScrollHandlers({\n axis: 'horizontal',\n wrapperRef: scrollStateRef.current.containerRef,\n onTouchStart,\n onTouchMove,\n onTouchEnd,\n onMouseEnter,\n onWheelMove,\n onMouseLeave,\n }),\n [onTouchMove, onTouchEnd, onWheelMove, onTouchStart, onMouseEnter, onMouseLeave]\n );\n\n const registerItem = useCallback(\n (ref: RefObject<HTMLElement>) => {\n if (!ref.current) {\n return;\n }\n scrollState.items.get().push(ref as unknown as RefObject<HTMLElement & ItemWithOffset>);\n scrollState.items.set(scrollState.items.get());\n resizeOberverRef.current?.observe(ref.current);\n recalculateItemPositions();\n },\n [recalculateItemPositions, scrollState]\n );\n\n const removeItem = useCallback(\n (ref: RefObject<HTMLElement>) => {\n if (!ref.current) {\n return;\n }\n scrollState.items.set(scrollState.items.get().filter((stored) => stored.current !== ref.current));\n resizeOberverRef.current?.unobserve(ref.current);\n recalculateItemPositionsDebounced();\n },\n [recalculateItemPositionsDebounced, scrollState]\n );\n\n return {\n registerItem,\n removeItem,\n initScrollHandlers: _initScrollHandlers,\n containerRef: scrollStateRef.current.containerRef,\n positionContainerRef: scrollStateRef.current.positionContainerRef,\n isTouch,\n };\n};\n"],"names":[],"mappings":";;;;;;;;;;;AAcA,MAAM,OAAO,GAAG,GAAG,CAAC;AACpB,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAC9B,MAAM,UAAU,GAAG,EAAE,CAAC,WAAW,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,gBAAgB,EAAE,EAAE,CAAC;AA0BjE,MAAM,kBAAkB,GAAG,MAAyB;AACvD,IAAA,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;AACrC,IAAA,MAAM,EAAE,aAAa,EAAE,GAAG,qBAAqB,EAAE,CAAC;IAClD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,cAAc,GAAG,WAAW,CAAC,cAAc,CAAC,GAAG,EAAE,CAAC;IACxD,MAAM,eAAe,GAAG,WAAW,CAAC,eAAe,CAAC,GAAG,EAAE,CAAC;IAC1D,MAAM,cAAc,GAAG,MAAM,CAAsB;AAC/C,QAAA,YAAY,EAAE,MAAM,CAAiB,IAAI,CAAC;AAC1C,QAAA,oBAAoB,EAAE,MAAM,CAAiB,IAAI,CAAC;AAClD,QAAA,UAAU,EAAE,EAAE,cAAc,EAAE,eAAe,EAAE;AAC/C,QAAA,aAAa,EAAE,KAAK;AACvB,KAAA,CAAC,CAAC;IACH,cAAc,CAAC,OAAO,CAAC,UAAU,GAAG,EAAE,cAAc,EAAE,eAAe,EAAE,CAAC;AACxE,IAAA,MAAM,gBAAgB,GAAG,MAAM,CAAwB,IAAI,CAAC,CAAC;;AAG7D,IAAA,MAAM,wBAAwB,GAAG,WAAW,CAAC,MAAK;AAC9C,QAAA,MAAM,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC;QACrC,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,oBAAoB,EAAE,GAAG,KAAK,CAAC;AACjE,QAAA,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,GAAG,UAAU,CAAC;QACvD,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QACtC,IAAI,CAAC,YAAY,CAAC,OAAO,IAAI,CAAC,oBAAoB,CAAC,OAAO,EAAE;YACxD,OAAO;SACV;AACD,QAAA,MAAM,UAAU,GAAG,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC;AACnF,QAAA,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,KAAI;AACtB,YAAA,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE;gBAClB,OAAO;aACV;YACD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC;YACrD,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,GAAG,UAAU,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,UAAU,EAAE,CAAC;AACpG,SAAC,CAAC,CAAC;AACH,QAAA,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,IAAI,UAAU,EAAE,WAAW,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,UAAU,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC;QAChH,MAAM,aAAa,GAAG,YAAY,CAAC,OAAO,CAAC,WAAW,GAAG,cAAc,GAAG,eAAe,CAAC;AAC1F,QAAA,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAC7B,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,GAAG,WAAW,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC,EAC3E,CAAC,CACJ,CAAC;AACF,QAAA,WAAW,CAAC,aAAa,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;AAC7C,QAAA,WAAW,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AAC3C,QAAA,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAC7B,QAAA,IAAI,WAAW,CAAC,mBAAmB,KAAK,CAAC,CAAC,EAAE;AACxC,YAAA,aAAa,CAAC,WAAW,CAAC,mBAAmB,CAAC,CAAC;AAC/C,YAAA,WAAW,CAAC,mBAAmB,GAAG,CAAC,CAAC,CAAC;SACxC;AACL,KAAC,EAAE,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC,CAAC;;IAGjC,MAAM,iCAAiC,GAAG,WAAW,CAAC,QAAQ,CAAC,wBAAwB,EAAE,EAAE,CAAC,EAAE;QAC1F,wBAAwB;AAC3B,KAAA,CAAC,CAAC;;IAGH,MAAM,qBAAqB,GAAG,WAAW,CAAC,MACtC,QAAQ,CAAC,MAAK;AACV,QAAA,IAAI,WAAW,CAAC,eAAe,KAAK,MAAM,EAAE;YACxC,OAAO;SACV;AACD,QAAA,MAAM,eAAe,GAAG,2BAA2B,CAAC,WAAW,CAAC,CAAC;AACjE,QAAA,MAAM,kBAAkB,GAAG,yBAAyB,CAAC,WAAW,CAAC,CAAC;QAClE,MAAM,MAAM,GAAG,kBAAkB,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;AAChE,QAAA,uBAAuB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;AACjD,KAAC,EAAE,GAAG,CAAC,CACV,CAAC;IAEF,SAAS,CAAC,MAAK;AACX,QAAA,MAAM,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC;QACrC,MAAM,QAAQ,GAAG,IAAI,cAAc,CAC/B,gBAAgB,CAAC,MAAK;AAClB,YAAA,wBAAwB,EAAE,CAAC;SAC9B,CAAC,CACL,CAAC;QAEF,WAAW,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;AAC1F,QAAA,KAAK,CAAC,YAAY,CAAC,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;AAC3E,QAAA,gBAAgB,CAAC,OAAO,GAAG,QAAQ,CAAC;AACpC,QAAA,OAAO,MAAM,QAAQ,CAAC,UAAU,EAAE,CAAC;;KAEtC,EAAE,EAAE,CAAC,CAAC;;IAGP,SAAS,CAAC,MAAK;QACX,MAAM,UAAU,GAAG,cAAc,CAAC,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC;QAC/D,IAAI,CAAC,UAAU,EAAE;YACb,OAAO,KAAK,CAAC,CAAC;SACjB;AACD,QAAA,MAAM,uBAAuB,GAAG,CAAC,KAAiB,KAAI;YAClD,KAAK,CAAC,eAAe,EAAE,CAAC;AAC5B,SAAC,CAAC;AACF,QAAA,UAAU,CAAC,gBAAgB,CAAC,YAAY,EAAE,uBAAuB,CAAC,CAAC;AACnE,QAAA,OAAO,MAAK;AACR,YAAA,UAAU,CAAC,mBAAmB,CAAC,YAAY,EAAE,uBAAuB,CAAC,CAAC;AAC1E,SAAC,CAAC;KACL,EAAE,EAAE,CAAC,CAAC;;AAGP,IAAA,MAAM,gBAAgB,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;AACvC,IAAA,MAAM,YAAY,GAAG,WAAW,CAAC,MAAK;QAClC,UAAU,CAAC,IAAI,CAAC,CAAC;AACjB,QAAA,gBAAgB,CAAC,OAAO,GAAG,KAAK,CAAC;AACjC,QAAA,WAAW,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;AACtC,KAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;AAElB,IAAA,MAAM,WAAW,GAAG,WAAW,CAC3B,CAAC,KAAyB,KAAI;AAC1B,QAAA,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE;;AAE3B,YAAA,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,mBAAmB,CAAC;SAC1E;AACD,QAAA,WAAW,CAAC,cAAc,CAAC,GAAG,CAC1B,KAAK,CACD,WAAW,CAAC,cAAc,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,KAAK,EAC9C,WAAW,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC,YAAY,CAAC,GAAG,EAAE,EAChE,CAAC,CACJ,CACJ,CAAC;AACN,KAAC,EACD,CAAC,WAAW,CAAC,CAChB,CAAC;AAEF,IAAA,MAAM,UAAU,GAAG,WAAW,CAAC,MAAK;AAChC,QAAA,IAAI,gBAAgB,CAAC,OAAO,EAAE;AAC1B,YAAA,qBAAqB,EAAE,CAAC;SAC3B;AACL,KAAC,EAAE,CAAC,qBAAqB,CAAC,CAAC,CAAC;;AAG5B,IAAA,MAAM,mBAAmB,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1C,IAAA,MAAM,YAAY,GAAG,WAAW,CAAC,MAAK;AAClC,QAAA,mBAAmB,CAAC,OAAO,GAAG,IAAI,CAAC;KACtC,EAAE,EAAE,CAAC,CAAC;AAEP,IAAA,MAAM,WAAW,GAAG,WAAW,CAC3B,CAAC,KAAyB,KAAI;QAC1B,UAAU,CAAC,KAAK,CAAC,CAAC;AAClB,QAAA,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE;YAC9B,OAAO;SACV;QACD,MAAM,eAAe,GAAG,WAAW,CAAC,cAAc,CAAC,GAAG,EAAE,CAAC;QACzD,MAAM,YAAY,GAAG,KAAK,CACtB,eAAe,GAAG,KAAK,CAAC,KAAK,EAC7B,WAAW,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC,YAAY,CAAC,GAAG,EAAE,EAChE,CAAC,CACJ,CAAC;QACF,IAAI,IAAI,CAAC,GAAG,CAAC,YAAY,GAAG,eAAe,CAAC,GAAG,OAAO,EAAE;AACpD,YAAA,WAAW,CAAC,cAAc,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AAC7C,YAAA,qBAAqB,EAAE,CAAC;YACxB,KAAK,CAAC,cAAc,EAAE,CAAC;SAC1B;AACL,KAAC,EACD,CAAC,qBAAqB,EAAE,WAAW,CAAC,CACvC,CAAC;AAEF,IAAA,MAAM,YAAY,GAAG,WAAW,CAAC,MAAK;AAClC,QAAA,mBAAmB,CAAC,OAAO,GAAG,KAAK,CAAC;KACvC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,mBAAmB,GAAG,WAAW,CACnC,MACI,kBAAkB,CAAC;AACf,QAAA,IAAI,EAAE,YAAY;AAClB,QAAA,UAAU,EAAE,cAAc,CAAC,OAAO,CAAC,YAAY;QAC/C,YAAY;QACZ,WAAW;QACX,UAAU;QACV,YAAY;QACZ,WAAW;QACX,YAAY;AACf,KAAA,CAAC,EACN,CAAC,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,CAAC,CACnF,CAAC;AAEF,IAAA,MAAM,YAAY,GAAG,WAAW,CAC5B,CAAC,GAA2B,KAAI;AAC5B,QAAA,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE;YACd,OAAO;SACV;QACD,WAAW,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAyD,CAAC,CAAC;AACxF,QAAA,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QAC/C,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAC/C,QAAA,wBAAwB,EAAE,CAAC;AAC/B,KAAC,EACD,CAAC,wBAAwB,EAAE,WAAW,CAAC,CAC1C,CAAC;AAEF,IAAA,MAAM,UAAU,GAAG,WAAW,CAC1B,CAAC,GAA2B,KAAI;AAC5B,QAAA,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE;YACd,OAAO;SACV;AACD,QAAA,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,OAAO,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;QAClG,gBAAgB,CAAC,OAAO,EAAE,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACjD,QAAA,iCAAiC,EAAE,CAAC;AACxC,KAAC,EACD,CAAC,iCAAiC,EAAE,WAAW,CAAC,CACnD,CAAC;IAEF,OAAO;QACH,YAAY;QACZ,UAAU;AACV,QAAA,kBAAkB,EAAE,mBAAmB;AACvC,QAAA,YAAY,EAAE,cAAc,CAAC,OAAO,CAAC,YAAY;AACjD,QAAA,oBAAoB,EAAE,cAAc,CAAC,OAAO,CAAC,oBAAoB;QACjE,OAAO;KACV,CAAC;AACN;;;;"}
|
|
1
|
+
{"version":3,"file":"useScrollContainer.js","sources":["src/useScrollContainer.ts"],"sourcesContent":["import { useRef, useEffect, type RefObject, useCallback, useState } from 'react';\n\nimport { requestAnimation, debounce } from '@hh.ru/magritte-common-func-utils';\nimport { clamp, type ScrollGestureEvent, initScrollHandlers } from '@hh.ru/magritte-internal-custom-scroll';\nimport { useScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport { type ItemWithOffset, OFFSET_ATTR } from '@hh.ru/magritte-ui-scrollable-container/types';\nimport { useScrollableControls } from '@hh.ru/magritte-ui-scrollable-container/useScrollableControls';\nimport {\n useInitOnce,\n findIndexNearestToSnapPoint,\n animateScrollToPosition,\n computeScrollSnapBehavior,\n} from '@hh.ru/magritte-ui-scrollable-container/utils';\n\nconst EPSILON = 0.5;\nconst MIN_DELTA_FOR_TOUCH = 5;\nconst MAX_OFFSET = { [OFFSET_ATTR]: { left: Number.MAX_SAFE_INTEGER } };\n\n/**\n * Переменные полностью описывающие состояние скролла, хранятся в одном объекте, чтобы не плодить\n * кучу ref'ов и передавать всё состояние в функции одним аргументом, а не длинным списком переменных\n */\nexport interface ScrollInternalState {\n /** контейнер, в котором лежит positionContainer (определяет видимую область) */\n containerRef: RefObject<HTMLDivElement>;\n /** контейнер, с помощью изменения положения которого обеспечивается скролл */\n positionContainerRef: RefObject<HTMLDivElement>;\n /** размер коррекции отступов */\n correction: { leftCorrection: number; rightCorrection: number };\n /* Было ли взаимодействие с компонентом - скролл или прокрутка к элементу */\n wasInteracted: boolean;\n}\n\ninterface UseScrollContainer {\n registerItem: (ref: RefObject<HTMLElement>) => void;\n removeItem: (ref: RefObject<HTMLElement>) => void;\n initScrollHandlers: () => VoidFunction;\n containerRef: RefObject<HTMLDivElement>;\n positionContainerRef: RefObject<HTMLDivElement>;\n isTouch: boolean;\n}\n\nexport const useScrollContainer = (): UseScrollContainer => {\n const scrollState = useScrollState();\n const { scrollToIndex, jumpToIndex } = useScrollableControls();\n const [isTouch, setIsTouch] = useState(false);\n const leftCorrection = scrollState.leftCorrection.get();\n const rightCorrection = scrollState.rightCorrection.get();\n const scrollStateRef = useRef<ScrollInternalState>({\n containerRef: useRef<HTMLDivElement>(null),\n positionContainerRef: useRef<HTMLDivElement>(null),\n correction: { leftCorrection, rightCorrection },\n wasInteracted: false,\n });\n scrollStateRef.current.correction = { leftCorrection, rightCorrection };\n const resizeOberverRef = useRef<ResizeObserver | null>(null);\n\n // recalc positions + report widths into store\n const recalculateItemPositions = useCallback(() => {\n const state = scrollStateRef.current;\n const { containerRef, correction, positionContainerRef } = state;\n const { leftCorrection, rightCorrection } = correction;\n const items = scrollState.items.get();\n if (!containerRef.current || !positionContainerRef.current) {\n return;\n }\n const offsetLeft = positionContainerRef.current?.getBoundingClientRect().left ?? 0;\n items.forEach((itemRef) => {\n if (!itemRef.current) {\n return;\n }\n const rect = itemRef.current.getBoundingClientRect();\n itemRef.current[OFFSET_ATTR] = { left: rect.left - offsetLeft, right: rect.right - offsetLeft };\n });\n items.sort((a, b) => (a.current || MAX_OFFSET)[OFFSET_ATTR].left - (b.current || MAX_OFFSET)[OFFSET_ATTR].left);\n const viewportWidth = containerRef.current.offsetWidth - leftCorrection - rightCorrection;\n const contentWidth = items.reduce(\n (pos, itemRef) => Math.max(pos, itemRef.current?.[OFFSET_ATTR]?.right || 0),\n 0\n );\n scrollState.viewportWidth.set(viewportWidth);\n scrollState.contentWidth.set(contentWidth);\n scrollState.items.set(items);\n if (scrollState.indexForDeferScroll !== -1) {\n if (scrollState.behaviorScrollTypeDeferScroll === 'instant') {\n jumpToIndex(scrollState.indexForDeferScroll);\n } else {\n scrollToIndex(scrollState.indexForDeferScroll);\n }\n scrollState.behaviorScrollTypeDeferScroll = 'animate';\n scrollState.indexForDeferScroll = -1;\n }\n }, [scrollState, scrollToIndex, jumpToIndex]);\n\n // eslint-disable-next-line disable-autofix/react-hooks/exhaustive-deps\n const recalculateItemPositionsDebounced = useCallback(debounce(recalculateItemPositions, 10), [\n recalculateItemPositions,\n ]);\n\n // eslint-disable-next-line disable-autofix/react-hooks/exhaustive-deps\n const scrollToItemDebounced = useInitOnce(() =>\n debounce(() => {\n if (scrollState.scrollSnapAlign === 'none') {\n return;\n }\n const targetItemIndex = findIndexNearestToSnapPoint(scrollState);\n const scrollSnapBehavior = computeScrollSnapBehavior(scrollState);\n const target = scrollSnapBehavior(scrollState, targetItemIndex);\n animateScrollToPosition(scrollState, target);\n }, 100)\n );\n\n useEffect(() => {\n const state = scrollStateRef.current;\n const observer = new ResizeObserver(\n requestAnimation(() => {\n recalculateItemPositions();\n })\n );\n\n scrollState.items.get().forEach((item) => item.current && observer.observe(item.current));\n state.containerRef.current && observer.observe(state.containerRef.current);\n resizeOberverRef.current = observer;\n return () => observer.disconnect();\n // eslint-disable-next-line disable-autofix/react-hooks/exhaustive-deps\n }, []);\n\n // Слушатель нужен, чтобы не вызывать скролл в родительском контейнере (например в bs)\n useEffect(() => {\n const wrapperRef = scrollStateRef.current.containerRef.current;\n if (!wrapperRef) {\n return void 0;\n }\n const handleTouchStartHandler = (event: TouchEvent) => {\n event.stopPropagation();\n };\n wrapperRef.addEventListener('touchstart', handleTouchStartHandler);\n return () => {\n wrapperRef.removeEventListener('touchstart', handleTouchStartHandler);\n };\n }, []);\n\n // события тача\n const didContainerMove = useRef(false);\n const onTouchStart = useCallback(() => {\n setIsTouch(true);\n didContainerMove.current = false;\n scrollState.scrollPosition.stop();\n }, [scrollState]);\n\n const onTouchMove = useCallback(\n (event: ScrollGestureEvent) => {\n if (!didContainerMove.current) {\n // надо отличить тач от свайпа\n didContainerMove.current = Math.abs(event.delta) > MIN_DELTA_FOR_TOUCH;\n }\n scrollState.scrollPosition.set(\n clamp(\n scrollState.scrollPosition.get() + event.delta,\n scrollState.viewportWidth.get() - scrollState.contentWidth.get(),\n 0\n )\n );\n },\n [scrollState]\n );\n\n const onTouchEnd = useCallback(() => {\n if (didContainerMove.current) {\n scrollToItemDebounced();\n }\n }, [scrollToItemDebounced]);\n\n // события мыши\n const didContainerHovered = useRef(false);\n const onMouseEnter = useCallback(() => {\n didContainerHovered.current = true;\n }, []);\n\n const onWheelMove = useCallback(\n (event: ScrollGestureEvent) => {\n setIsTouch(false);\n if (!didContainerHovered.current) {\n return;\n }\n const currentPosition = scrollState.scrollPosition.get();\n const nextPosition = clamp(\n currentPosition + event.delta,\n scrollState.viewportWidth.get() - scrollState.contentWidth.get(),\n 0\n );\n if (Math.abs(nextPosition - currentPosition) > EPSILON) {\n scrollState.scrollPosition.set(nextPosition);\n scrollToItemDebounced();\n event.preventDefault();\n }\n },\n [scrollToItemDebounced, scrollState]\n );\n\n const onMouseLeave = useCallback(() => {\n didContainerHovered.current = false;\n }, []);\n\n const _initScrollHandlers = useCallback(\n () =>\n initScrollHandlers({\n axis: 'horizontal',\n wrapperRef: scrollStateRef.current.containerRef,\n onTouchStart,\n onTouchMove,\n onTouchEnd,\n onMouseEnter,\n onWheelMove,\n onMouseLeave,\n }),\n [onTouchMove, onTouchEnd, onWheelMove, onTouchStart, onMouseEnter, onMouseLeave]\n );\n\n const registerItem = useCallback(\n (ref: RefObject<HTMLElement>) => {\n if (!ref.current) {\n return;\n }\n scrollState.items.get().push(ref as unknown as RefObject<HTMLElement & ItemWithOffset>);\n scrollState.items.set(scrollState.items.get());\n resizeOberverRef.current?.observe(ref.current);\n recalculateItemPositions();\n },\n [recalculateItemPositions, scrollState]\n );\n\n const removeItem = useCallback(\n (ref: RefObject<HTMLElement>) => {\n if (!ref.current) {\n return;\n }\n scrollState.items.set(scrollState.items.get().filter((stored) => stored.current !== ref.current));\n resizeOberverRef.current?.unobserve(ref.current);\n recalculateItemPositionsDebounced();\n },\n [recalculateItemPositionsDebounced, scrollState]\n );\n\n return {\n registerItem,\n removeItem,\n initScrollHandlers: _initScrollHandlers,\n containerRef: scrollStateRef.current.containerRef,\n positionContainerRef: scrollStateRef.current.positionContainerRef,\n isTouch,\n };\n};\n"],"names":[],"mappings":"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"}
|
package/useScrollableControls.js
CHANGED
|
@@ -39,6 +39,35 @@ const useScrollableControlsWithState = (scrollState) => {
|
|
|
39
39
|
const index = scrollState.items.get().findIndex((item) => item.current && item.current === ref.current);
|
|
40
40
|
index !== -1 && scrollToIndex(index);
|
|
41
41
|
}, [scrollState, scrollToIndex]);
|
|
42
|
+
const jumpToIndex = useCallback((index) => {
|
|
43
|
+
if (!ensureItemReadyForScroll(scrollState, index, 'instant')) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const scrollSnapBehavior = computeScrollSnapBehavior(scrollState);
|
|
47
|
+
const target = scrollSnapBehavior(scrollState, index);
|
|
48
|
+
const { scrollPosition, springScrollPosition, viewportWidth, contentWidth } = scrollState;
|
|
49
|
+
if (target === null) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const clampedTarget = clamp(target, viewportWidth.get() - contentWidth.get(), 0);
|
|
53
|
+
const isScrollPositionReached = scrollPosition.get() === clampedTarget;
|
|
54
|
+
const isSpringScrollPositionReached = !springScrollPosition || springScrollPosition.get() === clampedTarget;
|
|
55
|
+
if (isScrollPositionReached && isSpringScrollPositionReached) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
scrollPosition.jump(clampedTarget);
|
|
59
|
+
springScrollPosition?.jump(clampedTarget);
|
|
60
|
+
}, [scrollState]);
|
|
61
|
+
const jumpBy = useCallback((delta) => {
|
|
62
|
+
const { scrollPosition, springScrollPosition, viewportWidth, contentWidth } = scrollState;
|
|
63
|
+
const target = clamp(scrollPosition.get() + delta, viewportWidth.get() - contentWidth.get(), 0);
|
|
64
|
+
const clampedDelta = target - scrollPosition.get();
|
|
65
|
+
if (clampedDelta === 0) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
scrollPosition.jump(target);
|
|
69
|
+
springScrollPosition?.jump(springScrollPosition.get() + clampedDelta);
|
|
70
|
+
}, [scrollState]);
|
|
42
71
|
return {
|
|
43
72
|
scrollLeft: () => scrollSide(),
|
|
44
73
|
scrollRight: () => scrollSide(true),
|
|
@@ -46,6 +75,8 @@ const useScrollableControlsWithState = (scrollState) => {
|
|
|
46
75
|
scrollToLastItem,
|
|
47
76
|
scrollToIndex,
|
|
48
77
|
scrollToItem,
|
|
78
|
+
jumpToIndex,
|
|
79
|
+
jumpBy,
|
|
49
80
|
};
|
|
50
81
|
};
|
|
51
82
|
const useScrollableControls = () => {
|
|
@@ -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 return {\n scrollLeft: () => scrollSide(),\n scrollRight: () => scrollSide(true),\n scrollToFirstItem,\n scrollToLastItem,\n scrollToIndex,\n scrollToItem,\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,8BAA8B,GAAqD,CAAC,WAAW,KAAI;IAC5G,MAAM,UAAU,GAAG,WAAW,CAC1B,CAAC,OAAmB,GAAA,KAAK,KAAI;AACzB,QAAA,IAAI,WAAW,CAAC,eAAe,KAAK,MAAM,EAAE;YACxC,MAAM,KAAK,GAAG,OAAO,GAAG,CAAC,WAAW,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC;YAC3F,MAAM,QAAQ,GAAG,WAAW,CAAC,cAAc,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;AAC1D,YAAA,uBAAuB,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;YAC/C,OAAO;SACV;AACD,QAAA,MAAM,KAAK,GAAG,2BAA2B,CAAC,WAAW,CAAC,CAAC;AACvD,QAAA,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,GAAG,KAAK,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAChG,IAAI,CAAC,wBAAwB,CAAC,WAAW,EAAE,SAAS,CAAC,EAAE;YACnD,OAAO;SACV;AACD,QAAA,MAAM,kBAAkB,GAAG,yBAAyB,CAAC,WAAW,CAAC,CAAC;QAClE,MAAM,MAAM,GAAG,kBAAkB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;AAC1D,QAAA,uBAAuB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;AACjD,KAAC,EACD,CAAC,WAAW,CAAC,CAChB,CAAC;AAEF,IAAA,MAAM,aAAa,GAAG,WAAW,CAC7B,CAAC,KAAa,KAAI;QACd,IAAI,CAAC,wBAAwB,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE;YAC/C,OAAO;SACV;AACD,QAAA,MAAM,kBAAkB,GAAG,yBAAyB,CAAC,WAAW,CAAC,CAAC;QAClE,MAAM,MAAM,GAAG,kBAAkB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;AACtD,QAAA,uBAAuB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;AACjD,KAAC,EACD,CAAC,WAAW,CAAC,CAChB,CAAC;AAEF,IAAA,MAAM,iBAAiB,GAAG,WAAW,CAAC,MAAM,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;IAE/E,MAAM,gBAAgB,GAAG,WAAW,CAChC,MAAM,aAAa,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,EACvD,CAAC,WAAW,EAAE,aAAa,CAAC,CAC/B,CAAC;AAEF,IAAA,MAAM,YAAY,GAAG,WAAW,CAC5B,CAAC,GAA2B,KAAI;AAC5B,QAAA,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC;QACxG,KAAK,KAAK,CAAC,CAAC,IAAI,aAAa,CAAC,KAAK,CAAC,CAAC;AACzC,KAAC,EACD,CAAC,WAAW,EAAE,aAAa,CAAC,CAC/B,CAAC;IAEF,OAAO;AACH,QAAA,UAAU,EAAE,MAAM,UAAU,EAAE;AAC9B,QAAA,WAAW,EAAE,MAAM,UAAU,CAAC,IAAI,CAAC;QACnC,iBAAiB;QACjB,gBAAgB;QAChB,aAAa;QACb,YAAY;
|
|
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 } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';
|
|
3
|
-
import { type SpacingCorrectionProps, type ScrollDisableState } from '@hh.ru/magritte-ui-scrollable-container/types';
|
|
2
|
+
import { type ScrollState, type BehaviorScrollType } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';
|
|
3
|
+
import { type SpacingCorrectionProps, type ScrollDisableState, type ItemOffset } from '@hh.ru/magritte-ui-scrollable-container/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;
|
|
@@ -16,6 +16,13 @@ interface ActualCorrection {
|
|
|
16
16
|
*/
|
|
17
17
|
export declare const getActualCorrection: (props: SpacingCorrectionProps, breakpoint: Breakpoint) => ActualCorrection;
|
|
18
18
|
export declare const useInitOnce: <T>(func: () => T) => T;
|
|
19
|
+
/**
|
|
20
|
+
* Отдает метрики элемента галереи
|
|
21
|
+
* @param scrollState стейт скролла
|
|
22
|
+
* @param index индекс элемента
|
|
23
|
+
* @returns метрики элемента, либо null (если элемента нет или его размеры еще не посчитаны)
|
|
24
|
+
*/
|
|
25
|
+
export declare const getItemOffset: (scrollState: ScrollState, index: number) => ItemOffset | null;
|
|
19
26
|
/**
|
|
20
27
|
* На основе стейта расчитывает флаги скрола
|
|
21
28
|
* @param scrollState стейт скролла
|
|
@@ -34,7 +41,7 @@ export declare const animateScrollToPosition: (scrollState: ScrollState, positio
|
|
|
34
41
|
* например, scrollToIndex функция может вызвана в useEffect в tabs
|
|
35
42
|
* запоминаем индекс и вызовем скролл, когда метрики будут посчитаны
|
|
36
43
|
*/
|
|
37
|
-
export declare const ensureItemReadyForScroll: (scrollState: ScrollState, index: number) => boolean;
|
|
44
|
+
export declare const ensureItemReadyForScroll: (scrollState: ScrollState, index: number, behaviorScrollType?: BehaviorScrollType) => boolean;
|
|
38
45
|
/**
|
|
39
46
|
* На основе позиции, находит ближайший элемент к центру viewport
|
|
40
47
|
* @param scrollState стейт скролла
|
package/utils.js
CHANGED
|
@@ -71,6 +71,13 @@ const useInitOnce = (func) => {
|
|
|
71
71
|
}
|
|
72
72
|
return initializedRef.current;
|
|
73
73
|
};
|
|
74
|
+
/**
|
|
75
|
+
* Отдает метрики элемента галереи
|
|
76
|
+
* @param scrollState стейт скролла
|
|
77
|
+
* @param index индекс элемента
|
|
78
|
+
* @returns метрики элемента, либо null (если элемента нет или его размеры еще не посчитаны)
|
|
79
|
+
*/
|
|
80
|
+
const getItemOffset = (scrollState, index) => scrollState.items.get()[index]?.current?.[OFFSET_ATTR] ?? null;
|
|
74
81
|
/**
|
|
75
82
|
* На основе стейта расчитывает флаги скрола
|
|
76
83
|
* @param scrollState стейт скролла
|
|
@@ -104,11 +111,12 @@ const animateScrollToPosition = (scrollState, position) => {
|
|
|
104
111
|
* например, scrollToIndex функция может вызвана в useEffect в tabs
|
|
105
112
|
* запоминаем индекс и вызовем скролл, когда метрики будут посчитаны
|
|
106
113
|
*/
|
|
107
|
-
const ensureItemReadyForScroll = (scrollState, index) => {
|
|
114
|
+
const ensureItemReadyForScroll = (scrollState, index, behaviorScrollType = 'animate') => {
|
|
108
115
|
const { items } = scrollState;
|
|
109
116
|
const item = items.get()[index]?.current;
|
|
110
117
|
if (!item || !item[OFFSET_ATTR]) {
|
|
111
118
|
scrollState.indexForDeferScroll = index;
|
|
119
|
+
scrollState.behaviorScrollTypeDeferScroll = behaviorScrollType;
|
|
112
120
|
return false;
|
|
113
121
|
}
|
|
114
122
|
return true;
|
|
@@ -285,5 +293,5 @@ const computeScrollSnapBehavior = (scrollState) => {
|
|
|
285
293
|
}
|
|
286
294
|
};
|
|
287
295
|
|
|
288
|
-
export { BREAKPOINTS_LIST, NO_BUTTONS_START_FROM_BREAKPOINT, animateScrollToPosition, computeCenterPositionForIndex, computeEndPositionForIndex, computePositionForIndex, computeScrollSnapBehavior, computeStartPositionForIndex, debounce, ensureItemReadyForScroll, findIndexNearestToSnapPoint, getActualCorrection, getDisableState, useInitOnce };
|
|
296
|
+
export { BREAKPOINTS_LIST, NO_BUTTONS_START_FROM_BREAKPOINT, animateScrollToPosition, computeCenterPositionForIndex, computeEndPositionForIndex, computePositionForIndex, computeScrollSnapBehavior, computeStartPositionForIndex, debounce, ensureItemReadyForScroll, findIndexNearestToSnapPoint, getActualCorrection, getDisableState, getItemOffset, useInitOnce };
|
|
289
297
|
//# 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 } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport {\n type SpacingCorrectionProps,\n type ScrollDisableState,\n type ScrollSnapAlign,\n OFFSET_ATTR,\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 * @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 = (scrollState: ScrollState, index: number): boolean => {\n const { items } = scrollState;\n const item = items.get()[index]?.current;\n if (!item || !item[OFFSET_ATTR]) {\n scrollState.indexForDeferScroll = index;\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":"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"}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import './index.css';
|
|
2
|
-
var styles = {"scroll-wrapper":"magritte-scroll-wrapper___vTdZl_6-3-5","scrollWrapper":"magritte-scroll-wrapper___vTdZl_6-3-5","scrollable-container":"magritte-scrollable-container___AKIUp_6-3-5","scrollableContainer":"magritte-scrollable-container___AKIUp_6-3-5","scroll-buttons-container":"magritte-scroll-buttons-container___ZeI5a_6-3-5","scrollButtonsContainer":"magritte-scroll-buttons-container___ZeI5a_6-3-5","scroll-buttons":"magritte-scroll-buttons___0SjoR_6-3-5","scrollButtons":"magritte-scroll-buttons___0SjoR_6-3-5","scroll-buttons-small":"magritte-scroll-buttons-small___xG3MS_6-3-5","scrollButtonsSmall":"magritte-scroll-buttons-small___xG3MS_6-3-5","scroll-button":"magritte-scroll-button___4GQu3_6-3-5","scrollButton":"magritte-scroll-button___4GQu3_6-3-5","scroll-button-left":"magritte-scroll-button-left___UueEY_6-3-5","scrollButtonLeft":"magritte-scroll-button-left___UueEY_6-3-5","scroll-button-right":"magritte-scroll-button-right___wZOn-_6-3-5","scrollButtonRight":"magritte-scroll-button-right___wZOn-_6-3-5","position-container":"magritte-position-container___1A4Bv_6-3-5","positionContainer":"magritte-position-container___1A4Bv_6-3-5","dot-container":"magritte-dot-container___ahtlG_6-3-5","dotContainer":"magritte-dot-container___ahtlG_6-3-5"};
|
|
3
|
-
|
|
4
|
-
export { styles as s };
|
|
5
|
-
//# sourceMappingURL=scrollableContainer-CJSC-Im0.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scrollableContainer-CJSC-Im0.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|