@vkontakte/vkui 7.11.4 → 7.11.6
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/dist/components/Touch/Touch.d.ts.map +1 -1
- package/dist/components/Touch/Touch.js +37 -9
- package/dist/components/Touch/Touch.js.map +1 -1
- package/dist/components.css +1 -1
- package/dist/components.css.map +1 -1
- package/dist/cssm/components/CustomScrollView/CustomScrollView.module.css +29 -23
- package/dist/cssm/components/Touch/Touch.js +37 -9
- package/dist/cssm/components/Touch/Touch.js.map +1 -1
- package/dist/cssm/lib/sheet/controllers/BottomSheetController.js +11 -2
- package/dist/cssm/lib/sheet/controllers/BottomSheetController.js.map +1 -1
- package/dist/lib/sheet/controllers/BottomSheetController.d.ts.map +1 -1
- package/dist/lib/sheet/controllers/BottomSheetController.js +11 -2
- package/dist/lib/sheet/controllers/BottomSheetController.js.map +1 -1
- package/dist/vkui.css +1 -1
- package/dist/vkui.css.map +1 -1
- package/package.json +1 -1
- package/src/components/CustomScrollView/CustomScrollView.module.css +29 -23
- package/src/components/CustomScrollView/CustomScrollView.module.css.d.ts.map +1 -1
- package/src/components/Touch/Touch.tsx +56 -9
- package/src/lib/sheet/controllers/BottomSheetController.ts +12 -2
|
@@ -21,33 +21,39 @@
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
@supports not (scrollbar-color: auto) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Android WebView не поддерживает scrollbar-color, поэтому отрисовываем
|
|
26
|
+
* полосы прокрутки только если основное указательное устройство мышь
|
|
27
|
+
*/
|
|
28
|
+
@media (pointer: fine) {
|
|
29
|
+
.scrollbarHidden::-webkit-scrollbar {
|
|
30
|
+
display: none;
|
|
31
|
+
}
|
|
27
32
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
.host::-webkit-scrollbar {
|
|
34
|
+
inline-size: 12px;
|
|
35
|
+
block-size: 12px;
|
|
36
|
+
background: 0 0;
|
|
37
|
+
}
|
|
33
38
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
.host::-webkit-scrollbar-track,
|
|
40
|
+
.host::-webkit-scrollbar-corner {
|
|
41
|
+
background: transparent;
|
|
42
|
+
}
|
|
38
43
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
.host::-webkit-scrollbar-thumb,
|
|
45
|
+
.host::-webkit-scrollbar-thumb {
|
|
46
|
+
background-color: var(--vkui--color_icon_tertiary_alpha);
|
|
47
|
+
background-clip: padding-box, content-box;
|
|
48
|
+
border: 3px solid transparent;
|
|
49
|
+
border-radius: 6px;
|
|
50
|
+
}
|
|
46
51
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
52
|
+
.host::-webkit-scrollbar-thumb:hover,
|
|
53
|
+
.host::-webkit-scrollbar-thumb:active {
|
|
54
|
+
background-color: var(--vkui--color_icon_tertiary_alpha--hover);
|
|
55
|
+
border: 2px solid transparent;
|
|
56
|
+
}
|
|
51
57
|
}
|
|
52
58
|
}
|
|
53
59
|
|
|
@@ -6,6 +6,36 @@ import { useStableCallback } from "../../hooks/useStableCallback.js";
|
|
|
6
6
|
import { getWindow, isHTMLElement, isSVGElement } from "../../lib/dom.js";
|
|
7
7
|
import { coordX, coordY, touchEnabled } from "../../lib/touch/index.js";
|
|
8
8
|
import { useIsomorphicLayoutEffect } from "../../lib/useIsomorphicLayoutEffect.js";
|
|
9
|
+
function isTouchEvent(event) {
|
|
10
|
+
return event.type.startsWith('touch');
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Телефоны после touch событий могут отправлять события мыши,
|
|
14
|
+
* Это может происходить при обычном нажатии.
|
|
15
|
+
*
|
|
16
|
+
* Нельзя использовать хук во время рендеринга.
|
|
17
|
+
*/ function useMouseEventLock() {
|
|
18
|
+
const isMouseEventLockRef = React.useRef(false);
|
|
19
|
+
const timerRef = React.useRef(undefined);
|
|
20
|
+
const isEventLock = React.useCallback((event)=>{
|
|
21
|
+
return !isTouchEvent(event) && isMouseEventLockRef.current === true;
|
|
22
|
+
}, []);
|
|
23
|
+
const checkEvent = React.useCallback((event)=>{
|
|
24
|
+
if (!isTouchEvent(event)) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
isMouseEventLockRef.current = true;
|
|
28
|
+
clearTimeout(timerRef.current);
|
|
29
|
+
timerRef.current = setTimeout(()=>{
|
|
30
|
+
isMouseEventLockRef.current = false;
|
|
31
|
+
}, 1000);
|
|
32
|
+
}, []);
|
|
33
|
+
React.useEffect(()=>()=>clearTimeout(timerRef.current), []);
|
|
34
|
+
return [
|
|
35
|
+
isEventLock,
|
|
36
|
+
checkEvent
|
|
37
|
+
];
|
|
38
|
+
}
|
|
9
39
|
/**
|
|
10
40
|
* @see https://vkui.io/components/touch
|
|
11
41
|
*/ export const Touch = ({ onStart, onStartX, onStartY, onMove, onMoveX, onMoveY, onEnter, onLeave, onEnd, onEndX, onEndY, onClickCapture, usePointerHover, slideThreshold = 5, useCapture = false, Component = 'div', getRootRef, noSlideClick = false, stopPropagation = false, ...restProps })=>{
|
|
@@ -14,6 +44,7 @@ import { useIsomorphicLayoutEffect } from "../../lib/useIsomorphicLayoutEffect.j
|
|
|
14
44
|
const gestureRef = React.useRef(null);
|
|
15
45
|
const didSlide = React.useRef(false);
|
|
16
46
|
const disposeTargetNativeGestureEvents = React.useRef(null);
|
|
47
|
+
const [isEventLock, checkEventForLock] = useMouseEventLock();
|
|
17
48
|
const cleanupTargetNativeGestureEvents = ()=>{
|
|
18
49
|
gestureRef.current = null;
|
|
19
50
|
if (disposeTargetNativeGestureEvents.current) {
|
|
@@ -22,9 +53,6 @@ import { useIsomorphicLayoutEffect } from "../../lib/useIsomorphicLayoutEffect.j
|
|
|
22
53
|
}
|
|
23
54
|
};
|
|
24
55
|
React.useEffect(()=>cleanupTargetNativeGestureEvents, []);
|
|
25
|
-
const isTouchEvent = (event)=>{
|
|
26
|
-
return event.type.startsWith('touch');
|
|
27
|
-
};
|
|
28
56
|
/**
|
|
29
57
|
* Note: используем `useStableCallback()`, чтобы не терялась область видимости `onEnd`/`onEndX`/`onEndY`.
|
|
30
58
|
*/ const handleNativePointerUp = useStableCallback((event)=>{
|
|
@@ -102,6 +130,11 @@ import { useIsomorphicLayoutEffect } from "../../lib/useIsomorphicLayoutEffect.j
|
|
|
102
130
|
});
|
|
103
131
|
const handlePointerDown = useStableCallback((event)=>{
|
|
104
132
|
// Если touchstart сэмулировало mousedown, то заканчиваем обработку
|
|
133
|
+
if (isEventLock(event)) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
// Помечаем что произошло touch событие
|
|
137
|
+
checkEventForLock(event);
|
|
105
138
|
if (gestureRef.current !== null) {
|
|
106
139
|
return;
|
|
107
140
|
}
|
|
@@ -205,12 +238,7 @@ import { useIsomorphicLayoutEffect } from "../../lib/useIsomorphicLayoutEffect.j
|
|
|
205
238
|
onMouseLeave: !usePointerHover ? handlePointerLeave : undefined,
|
|
206
239
|
// handlePointerDown(onTouchStart устанавливается отдельно через initializeNativeTouchEventStartWithPassiveFalse)
|
|
207
240
|
onMouseDownCapture: useCapture ? handlePointerDown : undefined,
|
|
208
|
-
onMouseDown: !useCapture ? handlePointerDown : undefined
|
|
209
|
-
onPointerDown: (event)=>{
|
|
210
|
-
if (event.pointerType === 'touch' || event.pointerType === 'pen') {
|
|
211
|
-
event.preventDefault();
|
|
212
|
-
}
|
|
213
|
-
}
|
|
241
|
+
onMouseDown: !useCapture ? handlePointerDown : undefined
|
|
214
242
|
});
|
|
215
243
|
};
|
|
216
244
|
function initGesture(startX, startY) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/Touch/Touch.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { useStableCallback } from '../../hooks/useStableCallback';\nimport { getWindow, isHTMLElement, isSVGElement } from '../../lib/dom';\nimport { coordX, coordY, touchEnabled, type VKUITouchEvent } from '../../lib/touch';\nimport { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';\nimport type { HasComponent, HasRootRef } from '../../types';\n\n/**\n * Костыль для правильной работы тайпскрипта.\n */\ntype HTMLorSVGElementWithEvents = {\n /**\n * AddEventListener.\n */\n addEventListener: (<K extends keyof HTMLElementEventMap>(\n type: K,\n listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any,\n options?: boolean | AddEventListenerOptions,\n ) => void) &\n (<K extends keyof SVGElementEventMap>(\n type: K,\n listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any,\n options?: boolean | AddEventListenerOptions,\n ) => void);\n /**\n * RemoveEventListener.\n */\n removeEventListener: (<K extends keyof HTMLElementEventMap>(\n type: K,\n listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any,\n options?: boolean | EventListenerOptions,\n ) => void) &\n (<K extends keyof SVGElementEventMap>(\n type: K,\n listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any,\n options?: boolean | EventListenerOptions,\n ) => void);\n};\n\nexport interface CustomTouchEvent extends Gesture {\n /**\n * Оригинальное событие.\n */\n originalEvent: VKUITouchEvent;\n}\n\nexport type HoverHandler = (outputEvent: MouseEvent) => void;\n\nexport type CustomTouchEventHandler = (event: CustomTouchEvent) => void;\n\nexport interface TouchProps\n extends React.AllHTMLAttributes<HTMLElement>,\n HasRootRef<HTMLElement>,\n HasComponent {\n /**\n * Использовать pointer-events для hover-состояний.\n * Работает на отключенных элементах (disabled inputs).\n */\n usePointerHover?: boolean;\n /**\n * Использовать фазу capture для событий.\n */\n useCapture?: boolean;\n /**\n * Порог расстояния в пикселях для активации свайпа.\n * @default 5\n */\n slideThreshold?: number;\n /**\n * Блокировать click-события после распознавания свайпа.\n */\n noSlideClick?: boolean;\n /**\n * Останавливать всплытие событий.\n */\n stopPropagation?: boolean;\n /**\n * Обработчик входа курсора в область.\n */\n onEnter?: HoverHandler;\n /**\n * Обработчик выхода курсора из области.\n */\n onLeave?: HoverHandler;\n /**\n * Общий обработчик начала взаимодействия.\n */\n onStart?: CustomTouchEventHandler;\n /**\n * Обработчик начала горизонтального перемещения.\n */\n onStartX?: CustomTouchEventHandler;\n /**\n * Обработчик начала вертикального перемещения.\n */\n onStartY?: CustomTouchEventHandler;\n /**\n * Общий обработчик перемещения.\n */\n onMove?: CustomTouchEventHandler;\n /**\n * Обработчик горизонтального перемещения.\n */\n onMoveX?: CustomTouchEventHandler;\n /**\n * Обработчик вертикального перемещения.\n */\n onMoveY?: CustomTouchEventHandler;\n /**\n * Общий обработчик завершения взаимодействия.\n */\n onEnd?: CustomTouchEventHandler;\n /**\n * Обработчик завершения горизонтального свайпа.\n */\n onEndX?: CustomTouchEventHandler;\n /**\n * Обработчик завершения вертикального свайпа.\n */\n onEndY?: CustomTouchEventHandler;\n}\n\nexport interface Gesture {\n /**\n * Начальная X-координата касания.\n */\n startX: number;\n\n /**\n * Начальная Y-координата касания.\n */\n startY: number;\n\n /**\n * Время начала взаимодействия.\n */\n startT: Date;\n\n /**\n * Длительность взаимодействия в миллисекундах.\n */\n duration: number;\n\n /**\n * Флаг активного нажатия.\n */\n isPressed: boolean;\n\n /**\n * Флаг вертикального перемещения.\n */\n isY: boolean;\n\n /**\n * Флаг горизонтального перемещения.\n */\n isX: boolean;\n\n /**\n * Флаг горизонтального свайпа.\n */\n isSlideX: boolean;\n\n /**\n * Флаг вертикального свайпа.\n */\n isSlideY: boolean;\n\n /**\n * Общий флаг свайпа (вертикального или горизонтального).\n */\n isSlide: boolean;\n\n /**\n * Текущая X-координата курсора/касания.\n */\n clientX: number;\n\n /**\n * Текущая Y-координата курсора/касания.\n */\n clientY: number;\n\n /**\n * Смещение по X относительно начальной точки.\n */\n shiftX: number;\n\n /**\n * Смещение по Y относительно начальной точки.\n */\n shiftY: number;\n\n /**\n * Абсолютное смещение по X.\n */\n shiftXAbs: number;\n\n /**\n * Абсолютное смещение по Y.\n */\n shiftYAbs: number;\n}\n\n/**\n * @see https://vkui.io/components/touch\n */\nexport const Touch = ({\n onStart,\n onStartX,\n onStartY,\n onMove,\n onMoveX,\n onMoveY,\n onEnter,\n onLeave,\n onEnd,\n onEndX,\n onEndY,\n onClickCapture,\n usePointerHover,\n slideThreshold = 5,\n useCapture = false,\n Component = 'div',\n getRootRef,\n noSlideClick = false,\n stopPropagation = false,\n ...restProps\n}: TouchProps) => {\n const hostRef = useExternRef(getRootRef);\n const [isTouchEnabled] = React.useState(touchEnabled);\n const gestureRef = React.useRef<Gesture | null>(null);\n const didSlide = React.useRef(false);\n const disposeTargetNativeGestureEvents = React.useRef<VoidFunction | null>(null);\n\n const cleanupTargetNativeGestureEvents = () => {\n gestureRef.current = null;\n if (disposeTargetNativeGestureEvents.current) {\n disposeTargetNativeGestureEvents.current();\n disposeTargetNativeGestureEvents.current = null;\n }\n };\n\n React.useEffect(() => cleanupTargetNativeGestureEvents, []);\n\n const isTouchEvent = (event: MouseEvent | TouchEvent) => {\n return event.type.startsWith('touch');\n };\n\n /**\n * Note: используем `useStableCallback()`, чтобы не терялась область видимости `onEnd`/`onEndX`/`onEndY`.\n */\n const handleNativePointerUp = useStableCallback((event: MouseEvent | TouchEvent) => {\n const gesture = gestureRef.current;\n\n /* istanbul ignore if: нужно для Typescript */\n if (!gesture) {\n return;\n }\n\n if (gesture.isPressed) {\n dispatchUserHandlers(event, gesture, [onEnd, onEndX, onEndY], stopPropagation);\n }\n\n if (isTouchEvent(event)) {\n // https://github.com/VKCOM/VKUI/issues/4414\n // если тач-устройство и был зафиксирован touchmove,\n // то событие клика не вызывается\n if (gesture.isSlide) {\n didSlide.current = false;\n }\n // Если это был тач-евент, симулируем отмену hover\n if (onLeave) {\n onLeave(event as MouseEvent);\n }\n } else {\n didSlide.current = Boolean(gesture.isSlide);\n }\n\n cleanupTargetNativeGestureEvents();\n });\n\n /**\n * Note: используем `useStableCallback()`, чтобы не терялась область видимости `onMove`/`onMoveX`/`onMoveY`.\n */\n const handleNativePointerMove = useStableCallback((event: MouseEvent | TouchEvent) => {\n const gesture = gestureRef.current;\n\n /* istanbul ignore if: нужно для Typescript */\n if (!gesture) {\n return;\n }\n\n const clientX = coordX(event);\n const clientY = coordY(event);\n\n // смещения\n const shiftX = clientX - gesture.startX;\n const shiftY = clientY - gesture.startY;\n\n // абсолютные значения смещений\n const shiftXAbs = Math.abs(shiftX);\n const shiftYAbs = Math.abs(shiftY);\n\n // Если определяем мультитач, то прерываем жест\n if ('touches' in event && event.touches.length > 1) {\n return handleNativePointerUp(event);\n }\n\n // если мы ещё не определились\n if (!gesture.isX && !gesture.isY) {\n const willBeX = shiftXAbs >= slideThreshold && shiftXAbs > shiftYAbs;\n const willBeY = shiftYAbs >= slideThreshold && shiftYAbs > shiftXAbs;\n const willBeSlidedX = willBeX && (!!onMoveX || !!onMove);\n const willBeSlidedY = willBeY && (!!onMoveY || !!onMove);\n\n gesture.isY = willBeY;\n gesture.isX = willBeX;\n gesture.isSlideX = willBeSlidedX;\n gesture.isSlideY = willBeSlidedY;\n gesture.isSlide = willBeSlidedX || willBeSlidedY;\n }\n\n if (gesture.isSlide) {\n gesture.clientX = clientX;\n gesture.clientY = clientY;\n gesture.shiftX = shiftX;\n gesture.shiftY = shiftY;\n gesture.shiftXAbs = shiftXAbs;\n gesture.shiftYAbs = shiftYAbs;\n\n dispatchUserHandlers(event, gesture, [onMove, onMoveX, onMoveY], stopPropagation);\n }\n });\n\n const handlePointerDown = useStableCallback(\n (event: React.MouseEvent<HTMLElement> | React.TouchEvent<HTMLElement> | TouchEvent) => {\n // Если touchstart сэмулировало mousedown, то заканчиваем обработку\n if (gestureRef.current !== null) {\n return;\n }\n\n const nativeEvent = 'nativeEvent' in event ? event.nativeEvent : event;\n\n gestureRef.current = initGesture(coordX(nativeEvent), coordY(nativeEvent));\n\n const shouldCallDirectionHandlerOnlyIsSlide = false;\n dispatchUserHandlers(\n event,\n gestureRef.current,\n [onStart, onStartX, onStartY],\n stopPropagation,\n shouldCallDirectionHandlerOnlyIsSlide,\n );\n\n const eventOptions = { capture: useCapture, passive: false };\n\n // FIXME: заменить touch/mouse-события ниже на pointer-события после того, как бразуеры из\n // .browserslistrc начнут поддерживать его (см. https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events#browser_compatibility).\n if (isTouchEvent(nativeEvent)) {\n if (isHTMLElement(event.target) || isSVGElement(event.target)) {\n // Тач-события не всплывают, поэтому навешиваем события на целевой элемент\n // см. #235, #1968, https://stackoverflow.com/a/45760014\n const target: HTMLorSVGElementWithEvents = event.target;\n\n target.addEventListener('touchmove', handleNativePointerMove, eventOptions);\n target.addEventListener('touchend', handleNativePointerUp, eventOptions);\n target.addEventListener('touchcancel', handleNativePointerUp, eventOptions);\n\n disposeTargetNativeGestureEvents.current = () => {\n target.removeEventListener('touchmove', handleNativePointerMove, eventOptions);\n target.removeEventListener('touchend', handleNativePointerUp, eventOptions);\n target.removeEventListener('touchcancel', handleNativePointerUp, eventOptions);\n };\n }\n } else {\n // Используем события на Document, т.к. mouse-события на целевом элементе могут теряться при\n // выходе за границы этого элемента.\n const doc = getWindow(event.currentTarget).document;\n\n doc.addEventListener('mousemove', handleNativePointerMove, eventOptions);\n doc.addEventListener('mouseup', handleNativePointerUp, eventOptions);\n doc.addEventListener('mouseleave', handleNativePointerUp, eventOptions);\n\n disposeTargetNativeGestureEvents.current = () => {\n doc.removeEventListener('mousemove', handleNativePointerMove, eventOptions);\n doc.removeEventListener('mouseup', handleNativePointerUp, eventOptions);\n doc.removeEventListener('mouseleave', handleNativePointerUp, eventOptions);\n };\n }\n },\n );\n\n const handlePointerEnter = onEnter\n ? (event: React.MouseEvent<HTMLElement>) => onEnter(event.nativeEvent)\n : undefined;\n\n const handlePointerLeave = onLeave\n ? (event: React.MouseEvent<HTMLElement>) => onLeave(event.nativeEvent)\n : undefined;\n\n /**\n * Отменяет нативное браузерное поведение для вложенных ссылок и изображений.\n */\n const handleDragStart = (event: React.DragEvent<HTMLElement>) => {\n const target = event.target as HTMLElement;\n if (target.tagName === 'A' || target.tagName === 'IMG') {\n event.preventDefault();\n }\n };\n\n /**\n * Отменяет переход по вложенной ссылке, если был зафиксирован свайп.\n */\n const handleClickCapture: typeof onClickCapture = (event) => {\n if (!didSlide.current) {\n return onClickCapture && onClickCapture(event);\n }\n\n if (noSlideClick) {\n event.stopPropagation();\n\n // https://github.com/VKCOM/VKUI/issues/1977\n // https://github.com/VKCOM/VKUI/issues/3892\n event.preventDefault();\n } else {\n onClickCapture && onClickCapture(event);\n }\n\n didSlide.current = false;\n };\n\n useIsomorphicLayoutEffect(\n function initializeNativeTouchStartEventWithPassiveFalse() {\n const hostEl = hostRef.current;\n if (!hostEl || !isTouchEnabled) {\n return;\n }\n\n const options = { capture: useCapture, passive: false };\n hostEl.addEventListener('touchstart', handlePointerDown, options);\n\n return () => {\n hostEl.removeEventListener('touchstart', handlePointerDown, options);\n };\n },\n [hostRef, isTouchEnabled, useCapture, handlePointerDown],\n );\n\n return (\n <Component\n {...restProps}\n ref={hostRef}\n onDragStart={handleDragStart}\n onClickCapture={handleClickCapture}\n // onEnter\n onPointerEnter={usePointerHover ? handlePointerEnter : undefined}\n onMouseEnter={!usePointerHover ? handlePointerEnter : undefined}\n // onLeave\n onPointerLeave={usePointerHover ? handlePointerLeave : undefined}\n onMouseLeave={!usePointerHover ? handlePointerLeave : undefined}\n // handlePointerDown(onTouchStart устанавливается отдельно через initializeNativeTouchEventStartWithPassiveFalse)\n onMouseDownCapture={useCapture ? handlePointerDown : undefined}\n onMouseDown={!useCapture ? handlePointerDown : undefined}\n onPointerDown={(event: PointerEvent) => {\n if (event.pointerType === 'touch' || event.pointerType === 'pen') {\n event.preventDefault();\n }\n }}\n />\n );\n};\n\nfunction initGesture(startX: number, startY: number): Gesture {\n return {\n startX,\n startY,\n startT: new Date(),\n duration: 0,\n isPressed: true,\n isY: false,\n isX: false,\n isSlideX: false,\n isSlideY: false,\n isSlide: false,\n clientX: 0,\n clientY: 0,\n shiftX: 0,\n shiftY: 0,\n shiftXAbs: 0,\n shiftYAbs: 0,\n };\n}\n\ntype Handlers = [\n CustomTouchEventHandler | undefined,\n CustomTouchEventHandler | undefined,\n CustomTouchEventHandler | undefined,\n];\n\nfunction dispatchUserHandlers(\n event: MouseEvent | TouchEvent | React.MouseEvent | React.TouchEvent,\n gesture: Gesture,\n [handler, handlerX, handlerY]: Handlers,\n stopPropagation?: boolean,\n shouldCallDirectionHandlerOnlyIsSlide = true,\n) {\n if (stopPropagation) {\n event.stopPropagation();\n }\n\n const data = {\n ...gesture,\n originalEvent: event as unknown as VKUITouchEvent,\n duration: Date.now() - gesture.startT.getTime(),\n };\n\n if (handler) {\n handler(data);\n }\n\n if (handlerX) {\n if (shouldCallDirectionHandlerOnlyIsSlide) {\n if (gesture.isSlideX) {\n handlerX(data);\n }\n } else {\n handlerX(data);\n }\n }\n\n if (handlerY) {\n if (shouldCallDirectionHandlerOnlyIsSlide) {\n if (gesture.isSlideY) {\n handlerY(data);\n }\n } else {\n handlerY(data);\n }\n }\n}\n"],"names":["React","useExternRef","useStableCallback","getWindow","isHTMLElement","isSVGElement","coordX","coordY","touchEnabled","useIsomorphicLayoutEffect","Touch","onStart","onStartX","onStartY","onMove","onMoveX","onMoveY","onEnter","onLeave","onEnd","onEndX","onEndY","onClickCapture","usePointerHover","slideThreshold","useCapture","Component","getRootRef","noSlideClick","stopPropagation","restProps","hostRef","isTouchEnabled","useState","gestureRef","useRef","didSlide","disposeTargetNativeGestureEvents","cleanupTargetNativeGestureEvents","current","useEffect","isTouchEvent","event","type","startsWith","handleNativePointerUp","gesture","isPressed","dispatchUserHandlers","isSlide","Boolean","handleNativePointerMove","clientX","clientY","shiftX","startX","shiftY","startY","shiftXAbs","Math","abs","shiftYAbs","touches","length","isX","isY","willBeX","willBeY","willBeSlidedX","willBeSlidedY","isSlideX","isSlideY","handlePointerDown","nativeEvent","initGesture","shouldCallDirectionHandlerOnlyIsSlide","eventOptions","capture","passive","target","addEventListener","removeEventListener","doc","currentTarget","document","handlePointerEnter","undefined","handlePointerLeave","handleDragStart","tagName","preventDefault","handleClickCapture","initializeNativeTouchStartEventWithPassiveFalse","hostEl","options","ref","onDragStart","onPointerEnter","onMouseEnter","onPointerLeave","onMouseLeave","onMouseDownCapture","onMouseDown","onPointerDown","pointerType","startT","Date","duration","handler","handlerX","handlerY","data","originalEvent","now","getTime"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/Touch/Touch.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { useStableCallback } from '../../hooks/useStableCallback';\nimport { getWindow, isHTMLElement, isSVGElement } from '../../lib/dom';\nimport { coordX, coordY, touchEnabled, type VKUITouchEvent } from '../../lib/touch';\nimport { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';\nimport type { HasComponent, HasRootRef } from '../../types';\n\ninterface EventWithType {\n /**\n * Тип события.\n */\n readonly type: string;\n}\n\nfunction isTouchEvent(event: EventWithType) {\n return event.type.startsWith('touch');\n}\n\ntype CheckEvent = (event: EventWithType) => void;\n\ntype IsEventLock = (event: EventWithType) => boolean;\n\n/**\n * Телефоны после touch событий могут отправлять события мыши,\n * Это может происходить при обычном нажатии.\n *\n * Нельзя использовать хук во время рендеринга.\n */\nfunction useMouseEventLock(): [IsEventLock, CheckEvent] {\n const isMouseEventLockRef = React.useRef<boolean>(false);\n const timerRef = React.useRef<ReturnType<typeof setTimeout>>(undefined);\n\n const isEventLock: IsEventLock = React.useCallback((event: EventWithType) => {\n return !isTouchEvent(event) && isMouseEventLockRef.current === true;\n }, []);\n\n const checkEvent: CheckEvent = React.useCallback((event: EventWithType) => {\n if (!isTouchEvent(event)) {\n return;\n }\n\n isMouseEventLockRef.current = true;\n\n clearTimeout(timerRef.current);\n timerRef.current = setTimeout(() => {\n isMouseEventLockRef.current = false;\n }, 1000);\n }, []);\n\n React.useEffect(() => () => clearTimeout(timerRef.current), []);\n\n return [isEventLock, checkEvent];\n}\n\n/**\n * Костыль для правильной работы тайпскрипта.\n */\ntype HTMLorSVGElementWithEvents = {\n /**\n * AddEventListener.\n */\n addEventListener: (<K extends keyof HTMLElementEventMap>(\n type: K,\n listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any,\n options?: boolean | AddEventListenerOptions,\n ) => void) &\n (<K extends keyof SVGElementEventMap>(\n type: K,\n listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any,\n options?: boolean | AddEventListenerOptions,\n ) => void);\n /**\n * RemoveEventListener.\n */\n removeEventListener: (<K extends keyof HTMLElementEventMap>(\n type: K,\n listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any,\n options?: boolean | EventListenerOptions,\n ) => void) &\n (<K extends keyof SVGElementEventMap>(\n type: K,\n listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any,\n options?: boolean | EventListenerOptions,\n ) => void);\n};\n\nexport interface CustomTouchEvent extends Gesture {\n /**\n * Оригинальное событие.\n */\n originalEvent: VKUITouchEvent;\n}\n\nexport type HoverHandler = (outputEvent: MouseEvent) => void;\n\nexport type CustomTouchEventHandler = (event: CustomTouchEvent) => void;\n\nexport interface TouchProps\n extends React.AllHTMLAttributes<HTMLElement>,\n HasRootRef<HTMLElement>,\n HasComponent {\n /**\n * Использовать pointer-events для hover-состояний.\n * Работает на отключенных элементах (disabled inputs).\n */\n usePointerHover?: boolean;\n /**\n * Использовать фазу capture для событий.\n */\n useCapture?: boolean;\n /**\n * Порог расстояния в пикселях для активации свайпа.\n * @default 5\n */\n slideThreshold?: number;\n /**\n * Блокировать click-события после распознавания свайпа.\n */\n noSlideClick?: boolean;\n /**\n * Останавливать всплытие событий.\n */\n stopPropagation?: boolean;\n /**\n * Обработчик входа курсора в область.\n */\n onEnter?: HoverHandler;\n /**\n * Обработчик выхода курсора из области.\n */\n onLeave?: HoverHandler;\n /**\n * Общий обработчик начала взаимодействия.\n */\n onStart?: CustomTouchEventHandler;\n /**\n * Обработчик начала горизонтального перемещения.\n */\n onStartX?: CustomTouchEventHandler;\n /**\n * Обработчик начала вертикального перемещения.\n */\n onStartY?: CustomTouchEventHandler;\n /**\n * Общий обработчик перемещения.\n */\n onMove?: CustomTouchEventHandler;\n /**\n * Обработчик горизонтального перемещения.\n */\n onMoveX?: CustomTouchEventHandler;\n /**\n * Обработчик вертикального перемещения.\n */\n onMoveY?: CustomTouchEventHandler;\n /**\n * Общий обработчик завершения взаимодействия.\n */\n onEnd?: CustomTouchEventHandler;\n /**\n * Обработчик завершения горизонтального свайпа.\n */\n onEndX?: CustomTouchEventHandler;\n /**\n * Обработчик завершения вертикального свайпа.\n */\n onEndY?: CustomTouchEventHandler;\n}\n\nexport interface Gesture {\n /**\n * Начальная X-координата касания.\n */\n startX: number;\n\n /**\n * Начальная Y-координата касания.\n */\n startY: number;\n\n /**\n * Время начала взаимодействия.\n */\n startT: Date;\n\n /**\n * Длительность взаимодействия в миллисекундах.\n */\n duration: number;\n\n /**\n * Флаг активного нажатия.\n */\n isPressed: boolean;\n\n /**\n * Флаг вертикального перемещения.\n */\n isY: boolean;\n\n /**\n * Флаг горизонтального перемещения.\n */\n isX: boolean;\n\n /**\n * Флаг горизонтального свайпа.\n */\n isSlideX: boolean;\n\n /**\n * Флаг вертикального свайпа.\n */\n isSlideY: boolean;\n\n /**\n * Общий флаг свайпа (вертикального или горизонтального).\n */\n isSlide: boolean;\n\n /**\n * Текущая X-координата курсора/касания.\n */\n clientX: number;\n\n /**\n * Текущая Y-координата курсора/касания.\n */\n clientY: number;\n\n /**\n * Смещение по X относительно начальной точки.\n */\n shiftX: number;\n\n /**\n * Смещение по Y относительно начальной точки.\n */\n shiftY: number;\n\n /**\n * Абсолютное смещение по X.\n */\n shiftXAbs: number;\n\n /**\n * Абсолютное смещение по Y.\n */\n shiftYAbs: number;\n}\n\n/**\n * @see https://vkui.io/components/touch\n */\nexport const Touch = ({\n onStart,\n onStartX,\n onStartY,\n onMove,\n onMoveX,\n onMoveY,\n onEnter,\n onLeave,\n onEnd,\n onEndX,\n onEndY,\n onClickCapture,\n usePointerHover,\n slideThreshold = 5,\n useCapture = false,\n Component = 'div',\n getRootRef,\n noSlideClick = false,\n stopPropagation = false,\n ...restProps\n}: TouchProps) => {\n const hostRef = useExternRef(getRootRef);\n const [isTouchEnabled] = React.useState(touchEnabled);\n const gestureRef = React.useRef<Gesture | null>(null);\n const didSlide = React.useRef(false);\n const disposeTargetNativeGestureEvents = React.useRef<VoidFunction | null>(null);\n\n const [isEventLock, checkEventForLock] = useMouseEventLock();\n\n const cleanupTargetNativeGestureEvents = () => {\n gestureRef.current = null;\n if (disposeTargetNativeGestureEvents.current) {\n disposeTargetNativeGestureEvents.current();\n disposeTargetNativeGestureEvents.current = null;\n }\n };\n\n React.useEffect(() => cleanupTargetNativeGestureEvents, []);\n\n /**\n * Note: используем `useStableCallback()`, чтобы не терялась область видимости `onEnd`/`onEndX`/`onEndY`.\n */\n const handleNativePointerUp = useStableCallback((event: MouseEvent | TouchEvent) => {\n const gesture = gestureRef.current;\n\n /* istanbul ignore if: нужно для Typescript */\n if (!gesture) {\n return;\n }\n\n if (gesture.isPressed) {\n dispatchUserHandlers(event, gesture, [onEnd, onEndX, onEndY], stopPropagation);\n }\n\n if (isTouchEvent(event)) {\n // https://github.com/VKCOM/VKUI/issues/4414\n // если тач-устройство и был зафиксирован touchmove,\n // то событие клика не вызывается\n if (gesture.isSlide) {\n didSlide.current = false;\n }\n // Если это был тач-евент, симулируем отмену hover\n if (onLeave) {\n onLeave(event as MouseEvent);\n }\n } else {\n didSlide.current = Boolean(gesture.isSlide);\n }\n\n cleanupTargetNativeGestureEvents();\n });\n\n /**\n * Note: используем `useStableCallback()`, чтобы не терялась область видимости `onMove`/`onMoveX`/`onMoveY`.\n */\n const handleNativePointerMove = useStableCallback((event: MouseEvent | TouchEvent) => {\n const gesture = gestureRef.current;\n\n /* istanbul ignore if: нужно для Typescript */\n if (!gesture) {\n return;\n }\n\n const clientX = coordX(event);\n const clientY = coordY(event);\n\n // смещения\n const shiftX = clientX - gesture.startX;\n const shiftY = clientY - gesture.startY;\n\n // абсолютные значения смещений\n const shiftXAbs = Math.abs(shiftX);\n const shiftYAbs = Math.abs(shiftY);\n\n // Если определяем мультитач, то прерываем жест\n if ('touches' in event && event.touches.length > 1) {\n return handleNativePointerUp(event);\n }\n\n // если мы ещё не определились\n if (!gesture.isX && !gesture.isY) {\n const willBeX = shiftXAbs >= slideThreshold && shiftXAbs > shiftYAbs;\n const willBeY = shiftYAbs >= slideThreshold && shiftYAbs > shiftXAbs;\n const willBeSlidedX = willBeX && (!!onMoveX || !!onMove);\n const willBeSlidedY = willBeY && (!!onMoveY || !!onMove);\n\n gesture.isY = willBeY;\n gesture.isX = willBeX;\n gesture.isSlideX = willBeSlidedX;\n gesture.isSlideY = willBeSlidedY;\n gesture.isSlide = willBeSlidedX || willBeSlidedY;\n }\n\n if (gesture.isSlide) {\n gesture.clientX = clientX;\n gesture.clientY = clientY;\n gesture.shiftX = shiftX;\n gesture.shiftY = shiftY;\n gesture.shiftXAbs = shiftXAbs;\n gesture.shiftYAbs = shiftYAbs;\n\n dispatchUserHandlers(event, gesture, [onMove, onMoveX, onMoveY], stopPropagation);\n }\n });\n\n const handlePointerDown = useStableCallback(\n (event: React.MouseEvent<HTMLElement> | React.TouchEvent<HTMLElement> | TouchEvent) => {\n // Если touchstart сэмулировало mousedown, то заканчиваем обработку\n if (isEventLock(event)) {\n return;\n }\n\n // Помечаем что произошло touch событие\n checkEventForLock(event);\n\n if (gestureRef.current !== null) {\n return;\n }\n\n const nativeEvent = 'nativeEvent' in event ? event.nativeEvent : event;\n\n gestureRef.current = initGesture(coordX(nativeEvent), coordY(nativeEvent));\n\n const shouldCallDirectionHandlerOnlyIsSlide = false;\n dispatchUserHandlers(\n event,\n gestureRef.current,\n [onStart, onStartX, onStartY],\n stopPropagation,\n shouldCallDirectionHandlerOnlyIsSlide,\n );\n\n const eventOptions = { capture: useCapture, passive: false };\n\n // FIXME: заменить touch/mouse-события ниже на pointer-события после того, как бразуеры из\n // .browserslistrc начнут поддерживать его (см. https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events#browser_compatibility).\n if (isTouchEvent(nativeEvent)) {\n if (isHTMLElement(event.target) || isSVGElement(event.target)) {\n // Тач-события не всплывают, поэтому навешиваем события на целевой элемент\n // см. #235, #1968, https://stackoverflow.com/a/45760014\n const target: HTMLorSVGElementWithEvents = event.target;\n\n target.addEventListener('touchmove', handleNativePointerMove, eventOptions);\n target.addEventListener('touchend', handleNativePointerUp, eventOptions);\n target.addEventListener('touchcancel', handleNativePointerUp, eventOptions);\n\n disposeTargetNativeGestureEvents.current = () => {\n target.removeEventListener('touchmove', handleNativePointerMove, eventOptions);\n target.removeEventListener('touchend', handleNativePointerUp, eventOptions);\n target.removeEventListener('touchcancel', handleNativePointerUp, eventOptions);\n };\n }\n } else {\n // Используем события на Document, т.к. mouse-события на целевом элементе могут теряться при\n // выходе за границы этого элемента.\n const doc = getWindow(event.currentTarget).document;\n\n doc.addEventListener('mousemove', handleNativePointerMove, eventOptions);\n doc.addEventListener('mouseup', handleNativePointerUp, eventOptions);\n doc.addEventListener('mouseleave', handleNativePointerUp, eventOptions);\n\n disposeTargetNativeGestureEvents.current = () => {\n doc.removeEventListener('mousemove', handleNativePointerMove, eventOptions);\n doc.removeEventListener('mouseup', handleNativePointerUp, eventOptions);\n doc.removeEventListener('mouseleave', handleNativePointerUp, eventOptions);\n };\n }\n },\n );\n\n const handlePointerEnter = onEnter\n ? (event: React.MouseEvent<HTMLElement>) => onEnter(event.nativeEvent)\n : undefined;\n\n const handlePointerLeave = onLeave\n ? (event: React.MouseEvent<HTMLElement>) => onLeave(event.nativeEvent)\n : undefined;\n\n /**\n * Отменяет нативное браузерное поведение для вложенных ссылок и изображений.\n */\n const handleDragStart = (event: React.DragEvent<HTMLElement>) => {\n const target = event.target as HTMLElement;\n if (target.tagName === 'A' || target.tagName === 'IMG') {\n event.preventDefault();\n }\n };\n\n /**\n * Отменяет переход по вложенной ссылке, если был зафиксирован свайп.\n */\n const handleClickCapture: typeof onClickCapture = (event) => {\n if (!didSlide.current) {\n return onClickCapture && onClickCapture(event);\n }\n\n if (noSlideClick) {\n event.stopPropagation();\n\n // https://github.com/VKCOM/VKUI/issues/1977\n // https://github.com/VKCOM/VKUI/issues/3892\n event.preventDefault();\n } else {\n onClickCapture && onClickCapture(event);\n }\n\n didSlide.current = false;\n };\n\n useIsomorphicLayoutEffect(\n function initializeNativeTouchStartEventWithPassiveFalse() {\n const hostEl = hostRef.current;\n if (!hostEl || !isTouchEnabled) {\n return;\n }\n\n const options = { capture: useCapture, passive: false };\n hostEl.addEventListener('touchstart', handlePointerDown, options);\n\n return () => {\n hostEl.removeEventListener('touchstart', handlePointerDown, options);\n };\n },\n [hostRef, isTouchEnabled, useCapture, handlePointerDown],\n );\n\n return (\n <Component\n {...restProps}\n ref={hostRef}\n onDragStart={handleDragStart}\n onClickCapture={handleClickCapture}\n // onEnter\n onPointerEnter={usePointerHover ? handlePointerEnter : undefined}\n onMouseEnter={!usePointerHover ? handlePointerEnter : undefined}\n // onLeave\n onPointerLeave={usePointerHover ? handlePointerLeave : undefined}\n onMouseLeave={!usePointerHover ? handlePointerLeave : undefined}\n // handlePointerDown(onTouchStart устанавливается отдельно через initializeNativeTouchEventStartWithPassiveFalse)\n onMouseDownCapture={useCapture ? handlePointerDown : undefined}\n onMouseDown={!useCapture ? handlePointerDown : undefined}\n />\n );\n};\n\nfunction initGesture(startX: number, startY: number): Gesture {\n return {\n startX,\n startY,\n startT: new Date(),\n duration: 0,\n isPressed: true,\n isY: false,\n isX: false,\n isSlideX: false,\n isSlideY: false,\n isSlide: false,\n clientX: 0,\n clientY: 0,\n shiftX: 0,\n shiftY: 0,\n shiftXAbs: 0,\n shiftYAbs: 0,\n };\n}\n\ntype Handlers = [\n CustomTouchEventHandler | undefined,\n CustomTouchEventHandler | undefined,\n CustomTouchEventHandler | undefined,\n];\n\nfunction dispatchUserHandlers(\n event: MouseEvent | TouchEvent | React.MouseEvent | React.TouchEvent,\n gesture: Gesture,\n [handler, handlerX, handlerY]: Handlers,\n stopPropagation?: boolean,\n shouldCallDirectionHandlerOnlyIsSlide = true,\n) {\n if (stopPropagation) {\n event.stopPropagation();\n }\n\n const data = {\n ...gesture,\n originalEvent: event as unknown as VKUITouchEvent,\n duration: Date.now() - gesture.startT.getTime(),\n };\n\n if (handler) {\n handler(data);\n }\n\n if (handlerX) {\n if (shouldCallDirectionHandlerOnlyIsSlide) {\n if (gesture.isSlideX) {\n handlerX(data);\n }\n } else {\n handlerX(data);\n }\n }\n\n if (handlerY) {\n if (shouldCallDirectionHandlerOnlyIsSlide) {\n if (gesture.isSlideY) {\n handlerY(data);\n }\n } else {\n handlerY(data);\n }\n }\n}\n"],"names":["React","useExternRef","useStableCallback","getWindow","isHTMLElement","isSVGElement","coordX","coordY","touchEnabled","useIsomorphicLayoutEffect","isTouchEvent","event","type","startsWith","useMouseEventLock","isMouseEventLockRef","useRef","timerRef","undefined","isEventLock","useCallback","current","checkEvent","clearTimeout","setTimeout","useEffect","Touch","onStart","onStartX","onStartY","onMove","onMoveX","onMoveY","onEnter","onLeave","onEnd","onEndX","onEndY","onClickCapture","usePointerHover","slideThreshold","useCapture","Component","getRootRef","noSlideClick","stopPropagation","restProps","hostRef","isTouchEnabled","useState","gestureRef","didSlide","disposeTargetNativeGestureEvents","checkEventForLock","cleanupTargetNativeGestureEvents","handleNativePointerUp","gesture","isPressed","dispatchUserHandlers","isSlide","Boolean","handleNativePointerMove","clientX","clientY","shiftX","startX","shiftY","startY","shiftXAbs","Math","abs","shiftYAbs","touches","length","isX","isY","willBeX","willBeY","willBeSlidedX","willBeSlidedY","isSlideX","isSlideY","handlePointerDown","nativeEvent","initGesture","shouldCallDirectionHandlerOnlyIsSlide","eventOptions","capture","passive","target","addEventListener","removeEventListener","doc","currentTarget","document","handlePointerEnter","handlePointerLeave","handleDragStart","tagName","preventDefault","handleClickCapture","initializeNativeTouchStartEventWithPassiveFalse","hostEl","options","ref","onDragStart","onPointerEnter","onMouseEnter","onPointerLeave","onMouseLeave","onMouseDownCapture","onMouseDown","startT","Date","duration","handler","handlerX","handlerY","data","originalEvent","now","getTime"],"mappings":"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"}
|
|
@@ -191,9 +191,18 @@ export class BottomSheetController {
|
|
|
191
191
|
}
|
|
192
192
|
static disableVerticalScrollBouncingIfNeeded(sheetScrollEl, targetEl) {
|
|
193
193
|
if (sheetScrollEl !== null && sheetScrollEl.scrollTop <= 0 && sheetScrollEl.contains(targetEl) && sheetScrollEl.scrollHeight > sheetScrollEl.clientHeight) {
|
|
194
|
-
sheetScrollEl.
|
|
194
|
+
const scrollbarWidth = sheetScrollEl.offsetWidth - sheetScrollEl.clientWidth;
|
|
195
|
+
Object.assign(sheetScrollEl.style, {
|
|
196
|
+
paddingInlineEnd: `${scrollbarWidth}px`,
|
|
197
|
+
overflowY: 'hidden',
|
|
198
|
+
boxSizing: 'border-box'
|
|
199
|
+
});
|
|
195
200
|
return function dispose() {
|
|
196
|
-
sheetScrollEl.style
|
|
201
|
+
Object.assign(sheetScrollEl.style, {
|
|
202
|
+
paddingInlineEnd: '',
|
|
203
|
+
overflowY: '',
|
|
204
|
+
boxSizing: ''
|
|
205
|
+
});
|
|
197
206
|
};
|
|
198
207
|
}
|
|
199
208
|
return noop;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/lib/sheet/controllers/BottomSheetController.ts"],"sourcesContent":["import { noop } from '@vkontakte/vkjs';\nimport { clamp } from '../../../helpers/math';\nimport { rubberbandIfOutOfBounds } from '../../animation';\nimport { getNearestOverflowAncestor, hasSelectionWithRangeType } from '../../dom';\nimport { UIPanGestureRecognizer } from '../../touch/UIPanGestureRecognizer';\nimport {\n BLOCK_SHEET_BEHAVIOR_DATA_ATTRIBUTE_KEY,\n DRAG_THRESHOLDS,\n DYNAMIC_SNAP_POINT_DATA,\n SNAP_POINT_DETENTS,\n} from '../constants';\nimport type { CSSTransitionController } from './CSSTransitionController';\n\nexport type SnapPointDetents = [number, number] | [number, number, number];\n\nexport type SnapPoint = 'auto' | { initial: number; detents: SnapPointDetents };\n\nexport type SnapPointChange = (snapPoint: number) => void;\n\nexport type BottomSheetControllerOptions = {\n sheetScrollEl: HTMLElement | null;\n sheetTransitionController: CSSTransitionController<string>;\n backdropTransitionController: CSSTransitionController | null;\n onSnapPointChange: SnapPointChange;\n onDismiss: VoidFunction;\n};\n\nexport class BottomSheetController {\n private readonly sheetEl: HTMLElement;\n\n constructor(\n sheetEl: HTMLElement,\n {\n sheetScrollEl,\n sheetTransitionController,\n backdropTransitionController,\n onSnapPointChange,\n onDismiss,\n }: BottomSheetControllerOptions,\n ) {\n this.sheetEl = sheetEl;\n this.onSnapPointChange = onSnapPointChange;\n this.onDismiss = onDismiss;\n this.panGestureRecognizer = new UIPanGestureRecognizer();\n this.sheetScrollEl = sheetScrollEl;\n this.sheetTransitionController = sheetTransitionController;\n this.backdropTransitionController = backdropTransitionController;\n }\n\n init(snapPoint: SnapPoint) {\n this.isInitialized = true;\n\n if (snapPoint === 'auto') {\n this.unit = 'px';\n this.currentSnapPoint = DYNAMIC_SNAP_POINT_DATA.IDLE_POINT_VALUE;\n this.snapPointDetents = [SNAP_POINT_DETENTS.MIN, DYNAMIC_SNAP_POINT_DATA.IDLE_POINT_VALUE];\n } else {\n this.unit = '%';\n this.currentSnapPoint = snapPoint.initial;\n this.snapPointDetents = snapPoint.detents;\n }\n }\n\n destroy() {\n this.isInitialized = false;\n this.pannedEl = null;\n this.sheetTransitionController.cleanup();\n this.backdropTransitionController?.cleanup();\n\n this.disableVerticalScrollBouncingDispose();\n this.disableVerticalScrollBouncingDispose = noop;\n }\n\n panStart(event: UIEvent) {\n if (\n !this.isInitialized ||\n this.panState !== 'idle' ||\n hasSelectionWithRangeType(event.target)\n ) {\n return;\n }\n\n this.panState = 'start';\n this.pannedEl = event.target as HTMLElement;\n this.panGestureRecognizer.setStartCoords(event);\n }\n\n panMove(event: UIEvent) {\n switch (this.panState) {\n case 'start':\n this.panGestureRecognizer.setInitialTimeOnce();\n this.panGestureRecognizer.setEndCoords(event);\n\n if (this.preventUntilPanGestureBecomesExpected()) {\n return;\n }\n\n if (this.preventImmediatelyIfPannedElIsNotValid()) {\n this.panState = 'idle';\n return;\n }\n\n if (this.preventUntilVerticalScrollingOnSheetScrollElBecomesExpected()) {\n return;\n }\n\n if (this.preventImmediatelyIfVerticalScrollingOnPannedElIsScrolled()) {\n this.panState = 'idle';\n return;\n }\n\n this.panState = 'moving';\n this.panGestureRecognizer.setStartCoords(event);\n\n this.sheetHeight = this.sheetEl.offsetHeight;\n\n this.disableVerticalScrollBouncingDispose =\n BottomSheetController.disableVerticalScrollBouncingIfNeeded(\n this.sheetScrollEl,\n this.pannedEl,\n );\n\n if (this.isDynamicSnapPoint) {\n this.currentSnapPoint = this.sheetHeight;\n this.snapPointDetents[DYNAMIC_SNAP_POINT_DATA.COMPUTED_INDEX] = this.sheetHeight;\n }\n break;\n case 'moving':\n this.panGestureRecognizer.setEndCoords(event);\n\n const { y1, y2 } = this.panGestureRecognizer;\n\n this.nextSnapPoint = rubberbandIfOutOfBounds(\n this.currentSnapPoint - ((y2 - y1) / this.sheetHeight) * this.currentSnapPoint,\n SNAP_POINT_DETENTS.MIN,\n this.isDynamicSnapPoint ? this.sheetHeight : SNAP_POINT_DETENTS.LARGE,\n );\n\n this.calculateSnapPoint(this.nextSnapPoint, true);\n break;\n }\n }\n\n panEnd() {\n switch (this.panState) {\n case 'moving':\n const prevCurrentSnapPoint = this.currentSnapPoint;\n this.currentSnapPoint = this.getSnapPointTo(this.nextSnapPoint);\n\n if (\n prevCurrentSnapPoint !== this.currentSnapPoint &&\n this.currentSnapPoint > SNAP_POINT_DETENTS.MIN\n ) {\n this.onSnapPointChange(this.currentSnapPoint);\n }\n\n this.calculateSnapPoint(this.currentSnapPoint);\n break;\n }\n\n this.panState = 'idle';\n this.panGestureRecognizer.reset();\n\n this.disableVerticalScrollBouncingDispose();\n this.disableVerticalScrollBouncingDispose = noop;\n }\n\n private isInitialized = false;\n private panState: 'idle' | 'start' | 'moving' = 'idle';\n private pannedEl: HTMLElement | null = null;\n private sheetHeight = 0;\n private rafId: number | null = null;\n private currentSnapPoint = 0;\n private nextSnapPoint = 0;\n private snapPointDetents: SnapPointDetents = [0, 0];\n private unit: 'px' | '%' = '%';\n private get isDynamicSnapPoint() {\n return this.unit === 'px';\n }\n private disableVerticalScrollBouncingDispose = noop;\n private readonly sheetScrollEl: HTMLElement | null;\n private readonly sheetTransitionController: CSSTransitionController<string>;\n private readonly backdropTransitionController: CSSTransitionController | null;\n private readonly panGestureRecognizer: UIPanGestureRecognizer;\n private readonly onSnapPointChange: SnapPointChange;\n private readonly onDismiss: VoidFunction;\n\n private calculateSnapPoint(nextSnapPoint: number, immediately = false) {\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n }\n\n if (nextSnapPoint <= SNAP_POINT_DETENTS.MIN) {\n this.sheetTransitionController.enableTransition();\n this.backdropTransitionController?.enableTransition();\n this.panState = 'idle';\n this.onDismiss();\n return;\n }\n\n const backdropOpacity = clamp(\n this.isDynamicSnapPoint\n ? nextSnapPoint / this.sheetHeight\n : (nextSnapPoint * 2) / SNAP_POINT_DETENTS.LARGE,\n 0,\n 1,\n );\n\n this.rafId = requestAnimationFrame(() => {\n if (immediately) {\n this.backdropTransitionController?.disableTransition().set(backdropOpacity);\n this.sheetTransitionController.disableTransition().set(`${nextSnapPoint}${this.unit}`);\n return;\n }\n\n if (this.isDynamicSnapPoint) {\n this.sheetTransitionController.cleanupOnTransitionEnd();\n }\n\n this.backdropTransitionController?.unset();\n this.sheetTransitionController.enableTransition().set(`${this.currentSnapPoint}${this.unit}`);\n });\n }\n\n private getSnapPointTo(nextSnapPoint: number) {\n const closestSnapPoint = BottomSheetController.getClosestSnapPoint(\n this.snapPointDetents,\n nextSnapPoint,\n );\n if (closestSnapPoint !== this.currentSnapPoint) {\n return closestSnapPoint;\n }\n\n const panDirection = this.panGestureRecognizer.direction();\n if (panDirection.axis !== 'y' || panDirection.direction === null) {\n return this.currentSnapPoint;\n }\n\n const velocity = this.panGestureRecognizer.velocity();\n if (Math.abs(velocity.y) < DRAG_THRESHOLDS.VELOCITY) {\n return this.currentSnapPoint;\n }\n\n const closestSnapPointByDirection = BottomSheetController.getClosestSnapPointByDirection(\n this.snapPointDetents,\n closestSnapPoint,\n panDirection.direction,\n );\n\n return closestSnapPointByDirection;\n }\n\n private preventUntilPanGestureBecomesExpected() {\n return (\n this.panGestureRecognizer.direction().axis === 'x' ||\n this.panGestureRecognizer.distance() < DRAG_THRESHOLDS.DISTANCE_FOR_MOVING_START\n );\n }\n\n private preventImmediatelyIfPannedElIsNotValid() {\n return (\n this.pannedEl === null ||\n // Элемент со специальным атрибутом\n this.pannedEl.closest(`[${BLOCK_SHEET_BEHAVIOR_DATA_ATTRIBUTE_KEY}=true]`) !== null || // eslint-disable-line no-restricted-properties\n // Элемент за пределами панели.\n !this.sheetEl.contains(this.pannedEl)\n );\n }\n\n private preventUntilVerticalScrollingOnSheetScrollElBecomesExpected() {\n if (\n this.sheetScrollEl === null ||\n !this.sheetScrollEl.contains(this.pannedEl) ||\n this.sheetScrollEl.scrollHeight <= this.sheetScrollEl.clientHeight\n ) {\n return false;\n }\n\n if (this.sheetScrollEl.scrollTop === 0) {\n return (\n this.panGestureRecognizer.direction().direction === -1 &&\n BottomSheetController.isLastSnapPointDetents(this.snapPointDetents, this.currentSnapPoint)\n );\n }\n\n return true;\n }\n\n private preventImmediatelyIfVerticalScrollingOnPannedElIsScrolled() {\n if (\n /* istanbul ignore next: покрываем TypeScript */\n this.pannedEl === null ||\n this.pannedEl === this.sheetEl ||\n this.pannedEl === this.sheetScrollEl\n ) {\n return false;\n }\n\n const overflowAncestor = getNearestOverflowAncestor(this.pannedEl, this.sheetEl);\n\n if (\n overflowAncestor === null ||\n this.sheetScrollEl === overflowAncestor ||\n overflowAncestor.scrollHeight <= overflowAncestor.clientHeight\n ) {\n return false;\n }\n\n return (\n overflowAncestor.scrollTop !== 0 || this.panGestureRecognizer.direction().direction === -1\n );\n }\n\n private static disableVerticalScrollBouncingIfNeeded(\n sheetScrollEl: HTMLElement | null,\n targetEl: HTMLElement | null,\n ) {\n if (\n sheetScrollEl !== null &&\n sheetScrollEl.scrollTop <= 0 &&\n sheetScrollEl.contains(targetEl) &&\n sheetScrollEl.scrollHeight > sheetScrollEl.clientHeight\n ) {\n sheetScrollEl.style.setProperty('overflow-y', 'hidden');\n return function dispose() {\n sheetScrollEl.style.removeProperty('overflow-y');\n };\n }\n return noop;\n }\n\n private static isLastSnapPointDetents(\n snapPointDetents: SnapPointDetents,\n currentY: number,\n ): boolean {\n return currentY === snapPointDetents[snapPointDetents.length - 1];\n }\n\n private static getClosestSnapPointByDirection(\n snapPointDetents: SnapPointDetents,\n currentY: number,\n direction: -1 | 1,\n ): number {\n const foundIndex = snapPointDetents.indexOf(currentY);\n switch (direction) {\n case -1:\n return snapPointDetents[foundIndex + 1] ?? snapPointDetents[snapPointDetents.length - 1];\n case 1:\n return snapPointDetents[foundIndex - 1] ?? snapPointDetents[0];\n }\n }\n\n private static getClosestSnapPoint(snapPointDetents: SnapPointDetents, currentY: number) {\n let closest = snapPointDetents[0];\n let minDifference = Math.abs(snapPointDetents[0] - currentY);\n\n for (let i = 1; i < snapPointDetents.length; i += 1) {\n const difference = Math.abs(snapPointDetents[i] - currentY);\n if (difference < minDifference) {\n closest = snapPointDetents[i];\n minDifference = difference;\n }\n }\n\n return closest;\n }\n}\n"],"names":["noop","clamp","rubberbandIfOutOfBounds","getNearestOverflowAncestor","hasSelectionWithRangeType","UIPanGestureRecognizer","BLOCK_SHEET_BEHAVIOR_DATA_ATTRIBUTE_KEY","DRAG_THRESHOLDS","DYNAMIC_SNAP_POINT_DATA","SNAP_POINT_DETENTS","BottomSheetController","sheetEl","sheetScrollEl","sheetTransitionController","backdropTransitionController","onSnapPointChange","onDismiss","panGestureRecognizer","init","snapPoint","isInitialized","unit","currentSnapPoint","IDLE_POINT_VALUE","snapPointDetents","MIN","initial","detents","destroy","pannedEl","cleanup","disableVerticalScrollBouncingDispose","panStart","event","panState","target","setStartCoords","panMove","setInitialTimeOnce","setEndCoords","preventUntilPanGestureBecomesExpected","preventImmediatelyIfPannedElIsNotValid","preventUntilVerticalScrollingOnSheetScrollElBecomesExpected","preventImmediatelyIfVerticalScrollingOnPannedElIsScrolled","sheetHeight","offsetHeight","disableVerticalScrollBouncingIfNeeded","isDynamicSnapPoint","COMPUTED_INDEX","y1","y2","nextSnapPoint","LARGE","calculateSnapPoint","panEnd","prevCurrentSnapPoint","getSnapPointTo","reset","rafId","immediately","cancelAnimationFrame","enableTransition","backdropOpacity","requestAnimationFrame","disableTransition","set","cleanupOnTransitionEnd","unset","closestSnapPoint","getClosestSnapPoint","panDirection","direction","axis","velocity","Math","abs","y","VELOCITY","closestSnapPointByDirection","getClosestSnapPointByDirection","distance","DISTANCE_FOR_MOVING_START","closest","contains","scrollHeight","clientHeight","scrollTop","isLastSnapPointDetents","overflowAncestor","targetEl","style","setProperty","dispose","removeProperty","currentY","length","foundIndex","indexOf","minDifference","i","difference"],"mappings":"AAAA,SAASA,IAAI,QAAQ,kBAAkB;AACvC,SAASC,KAAK,QAAQ,2BAAwB;AAC9C,SAASC,uBAAuB,QAAQ,2BAAkB;AAC1D,SAASC,0BAA0B,EAAEC,yBAAyB,QAAQ,eAAY;AAClF,SAASC,sBAAsB,QAAQ,wCAAqC;AAC5E,SACEC,uCAAuC,EACvCC,eAAe,EACfC,uBAAuB,EACvBC,kBAAkB,QACb,kBAAe;AAiBtB,OAAO,MAAMC;IACMC,QAAqB;IAEtC,YACEA,OAAoB,EACpB,EACEC,aAAa,EACbC,yBAAyB,EACzBC,4BAA4B,EAC5BC,iBAAiB,EACjBC,SAAS,EACoB,CAC/B;QACA,IAAI,CAACL,OAAO,GAAGA;QACf,IAAI,CAACI,iBAAiB,GAAGA;QACzB,IAAI,CAACC,SAAS,GAAGA;QACjB,IAAI,CAACC,oBAAoB,GAAG,IAAIZ;QAChC,IAAI,CAACO,aAAa,GAAGA;QACrB,IAAI,CAACC,yBAAyB,GAAGA;QACjC,IAAI,CAACC,4BAA4B,GAAGA;IACtC;IAEAI,KAAKC,SAAoB,EAAE;QACzB,IAAI,CAACC,aAAa,GAAG;QAErB,IAAID,cAAc,QAAQ;YACxB,IAAI,CAACE,IAAI,GAAG;YACZ,IAAI,CAACC,gBAAgB,GAAGd,wBAAwBe,gBAAgB;YAChE,IAAI,CAACC,gBAAgB,GAAG;gBAACf,mBAAmBgB,GAAG;gBAAEjB,wBAAwBe,gBAAgB;aAAC;QAC5F,OAAO;YACL,IAAI,CAACF,IAAI,GAAG;YACZ,IAAI,CAACC,gBAAgB,GAAGH,UAAUO,OAAO;YACzC,IAAI,CAACF,gBAAgB,GAAGL,UAAUQ,OAAO;QAC3C;IACF;IAEAC,UAAU;QACR,IAAI,CAACR,aAAa,GAAG;QACrB,IAAI,CAACS,QAAQ,GAAG;QAChB,IAAI,CAAChB,yBAAyB,CAACiB,OAAO;QACtC,IAAI,CAAChB,4BAA4B,EAAEgB;QAEnC,IAAI,CAACC,oCAAoC;QACzC,IAAI,CAACA,oCAAoC,GAAG/B;IAC9C;IAEAgC,SAASC,KAAc,EAAE;QACvB,IACE,CAAC,IAAI,CAACb,aAAa,IACnB,IAAI,CAACc,QAAQ,KAAK,UAClB9B,0BAA0B6B,MAAME,MAAM,GACtC;YACA;QACF;QAEA,IAAI,CAACD,QAAQ,GAAG;QAChB,IAAI,CAACL,QAAQ,GAAGI,MAAME,MAAM;QAC5B,IAAI,CAAClB,oBAAoB,CAACmB,cAAc,CAACH;IAC3C;IAEAI,QAAQJ,KAAc,EAAE;QACtB,OAAQ,IAAI,CAACC,QAAQ;YACnB,KAAK;gBACH,IAAI,CAACjB,oBAAoB,CAACqB,kBAAkB;gBAC5C,IAAI,CAACrB,oBAAoB,CAACsB,YAAY,CAACN;gBAEvC,IAAI,IAAI,CAACO,qCAAqC,IAAI;oBAChD;gBACF;gBAEA,IAAI,IAAI,CAACC,sCAAsC,IAAI;oBACjD,IAAI,CAACP,QAAQ,GAAG;oBAChB;gBACF;gBAEA,IAAI,IAAI,CAACQ,2DAA2D,IAAI;oBACtE;gBACF;gBAEA,IAAI,IAAI,CAACC,yDAAyD,IAAI;oBACpE,IAAI,CAACT,QAAQ,GAAG;oBAChB;gBACF;gBAEA,IAAI,CAACA,QAAQ,GAAG;gBAChB,IAAI,CAACjB,oBAAoB,CAACmB,cAAc,CAACH;gBAEzC,IAAI,CAACW,WAAW,GAAG,IAAI,CAACjC,OAAO,CAACkC,YAAY;gBAE5C,IAAI,CAACd,oCAAoC,GACvCrB,sBAAsBoC,qCAAqC,CACzD,IAAI,CAAClC,aAAa,EAClB,IAAI,CAACiB,QAAQ;gBAGjB,IAAI,IAAI,CAACkB,kBAAkB,EAAE;oBAC3B,IAAI,CAACzB,gBAAgB,GAAG,IAAI,CAACsB,WAAW;oBACxC,IAAI,CAACpB,gBAAgB,CAAChB,wBAAwBwC,cAAc,CAAC,GAAG,IAAI,CAACJ,WAAW;gBAClF;gBACA;YACF,KAAK;gBACH,IAAI,CAAC3B,oBAAoB,CAACsB,YAAY,CAACN;gBAEvC,MAAM,EAAEgB,EAAE,EAAEC,EAAE,EAAE,GAAG,IAAI,CAACjC,oBAAoB;gBAE5C,IAAI,CAACkC,aAAa,GAAGjD,wBACnB,IAAI,CAACoB,gBAAgB,GAAG,AAAE4B,CAAAA,KAAKD,EAAC,IAAK,IAAI,CAACL,WAAW,GAAI,IAAI,CAACtB,gBAAgB,EAC9Eb,mBAAmBgB,GAAG,EACtB,IAAI,CAACsB,kBAAkB,GAAG,IAAI,CAACH,WAAW,GAAGnC,mBAAmB2C,KAAK;gBAGvE,IAAI,CAACC,kBAAkB,CAAC,IAAI,CAACF,aAAa,EAAE;gBAC5C;QACJ;IACF;IAEAG,SAAS;QACP,OAAQ,IAAI,CAACpB,QAAQ;YACnB,KAAK;gBACH,MAAMqB,uBAAuB,IAAI,CAACjC,gBAAgB;gBAClD,IAAI,CAACA,gBAAgB,GAAG,IAAI,CAACkC,cAAc,CAAC,IAAI,CAACL,aAAa;gBAE9D,IACEI,yBAAyB,IAAI,CAACjC,gBAAgB,IAC9C,IAAI,CAACA,gBAAgB,GAAGb,mBAAmBgB,GAAG,EAC9C;oBACA,IAAI,CAACV,iBAAiB,CAAC,IAAI,CAACO,gBAAgB;gBAC9C;gBAEA,IAAI,CAAC+B,kBAAkB,CAAC,IAAI,CAAC/B,gBAAgB;gBAC7C;QACJ;QAEA,IAAI,CAACY,QAAQ,GAAG;QAChB,IAAI,CAACjB,oBAAoB,CAACwC,KAAK;QAE/B,IAAI,CAAC1B,oCAAoC;QACzC,IAAI,CAACA,oCAAoC,GAAG/B;IAC9C;IAEQoB,gBAAgB,MAAM;IACtBc,WAAwC,OAAO;IAC/CL,WAA+B,KAAK;IACpCe,cAAc,EAAE;IAChBc,QAAuB,KAAK;IAC5BpC,mBAAmB,EAAE;IACrB6B,gBAAgB,EAAE;IAClB3B,mBAAqC;QAAC;QAAG;KAAE,CAAC;IAC5CH,OAAmB,IAAI;IAC/B,IAAY0B,qBAAqB;QAC/B,OAAO,IAAI,CAAC1B,IAAI,KAAK;IACvB;IACQU,uCAAuC/B,KAAK;IACnCY,cAAkC;IAClCC,0BAA2D;IAC3DC,6BAA6D;IAC7DG,qBAA6C;IAC7CF,kBAAmC;IACnCC,UAAwB;IAEjCqC,mBAAmBF,aAAqB,EAAEQ,cAAc,KAAK,EAAE;QACrE,IAAI,IAAI,CAACD,KAAK,KAAK,MAAM;YACvBE,qBAAqB,IAAI,CAACF,KAAK;QACjC;QAEA,IAAIP,iBAAiB1C,mBAAmBgB,GAAG,EAAE;YAC3C,IAAI,CAACZ,yBAAyB,CAACgD,gBAAgB;YAC/C,IAAI,CAAC/C,4BAA4B,EAAE+C;YACnC,IAAI,CAAC3B,QAAQ,GAAG;YAChB,IAAI,CAAClB,SAAS;YACd;QACF;QAEA,MAAM8C,kBAAkB7D,MACtB,IAAI,CAAC8C,kBAAkB,GACnBI,gBAAgB,IAAI,CAACP,WAAW,GAChC,AAACO,gBAAgB,IAAK1C,mBAAmB2C,KAAK,EAClD,GACA;QAGF,IAAI,CAACM,KAAK,GAAGK,sBAAsB;YACjC,IAAIJ,aAAa;gBACf,IAAI,CAAC7C,4BAA4B,EAAEkD,oBAAoBC,IAAIH;gBAC3D,IAAI,CAACjD,yBAAyB,CAACmD,iBAAiB,GAAGC,GAAG,CAAC,GAAGd,gBAAgB,IAAI,CAAC9B,IAAI,EAAE;gBACrF;YACF;YAEA,IAAI,IAAI,CAAC0B,kBAAkB,EAAE;gBAC3B,IAAI,CAAClC,yBAAyB,CAACqD,sBAAsB;YACvD;YAEA,IAAI,CAACpD,4BAA4B,EAAEqD;YACnC,IAAI,CAACtD,yBAAyB,CAACgD,gBAAgB,GAAGI,GAAG,CAAC,GAAG,IAAI,CAAC3C,gBAAgB,GAAG,IAAI,CAACD,IAAI,EAAE;QAC9F;IACF;IAEQmC,eAAeL,aAAqB,EAAE;QAC5C,MAAMiB,mBAAmB1D,sBAAsB2D,mBAAmB,CAChE,IAAI,CAAC7C,gBAAgB,EACrB2B;QAEF,IAAIiB,qBAAqB,IAAI,CAAC9C,gBAAgB,EAAE;YAC9C,OAAO8C;QACT;QAEA,MAAME,eAAe,IAAI,CAACrD,oBAAoB,CAACsD,SAAS;QACxD,IAAID,aAAaE,IAAI,KAAK,OAAOF,aAAaC,SAAS,KAAK,MAAM;YAChE,OAAO,IAAI,CAACjD,gBAAgB;QAC9B;QAEA,MAAMmD,WAAW,IAAI,CAACxD,oBAAoB,CAACwD,QAAQ;QACnD,IAAIC,KAAKC,GAAG,CAACF,SAASG,CAAC,IAAIrE,gBAAgBsE,QAAQ,EAAE;YACnD,OAAO,IAAI,CAACvD,gBAAgB;QAC9B;QAEA,MAAMwD,8BAA8BpE,sBAAsBqE,8BAA8B,CACtF,IAAI,CAACvD,gBAAgB,EACrB4C,kBACAE,aAAaC,SAAS;QAGxB,OAAOO;IACT;IAEQtC,wCAAwC;QAC9C,OACE,IAAI,CAACvB,oBAAoB,CAACsD,SAAS,GAAGC,IAAI,KAAK,OAC/C,IAAI,CAACvD,oBAAoB,CAAC+D,QAAQ,KAAKzE,gBAAgB0E,yBAAyB;IAEpF;IAEQxC,yCAAyC;QAC/C,OACE,IAAI,CAACZ,QAAQ,KAAK,QAClB,mCAAmC;QACnC,IAAI,CAACA,QAAQ,CAACqD,OAAO,CAAC,CAAC,CAAC,EAAE5E,wCAAwC,MAAM,CAAC,MAAM,QAAQ,+CAA+C;QACtI,+BAA+B;QAC/B,CAAC,IAAI,CAACK,OAAO,CAACwE,QAAQ,CAAC,IAAI,CAACtD,QAAQ;IAExC;IAEQa,8DAA8D;QACpE,IACE,IAAI,CAAC9B,aAAa,KAAK,QACvB,CAAC,IAAI,CAACA,aAAa,CAACuE,QAAQ,CAAC,IAAI,CAACtD,QAAQ,KAC1C,IAAI,CAACjB,aAAa,CAACwE,YAAY,IAAI,IAAI,CAACxE,aAAa,CAACyE,YAAY,EAClE;YACA,OAAO;QACT;QAEA,IAAI,IAAI,CAACzE,aAAa,CAAC0E,SAAS,KAAK,GAAG;YACtC,OACE,IAAI,CAACrE,oBAAoB,CAACsD,SAAS,GAAGA,SAAS,KAAK,CAAC,KACrD7D,sBAAsB6E,sBAAsB,CAAC,IAAI,CAAC/D,gBAAgB,EAAE,IAAI,CAACF,gBAAgB;QAE7F;QAEA,OAAO;IACT;IAEQqB,4DAA4D;QAClE,IACE,8CAA8C,GAC9C,IAAI,CAACd,QAAQ,KAAK,QAClB,IAAI,CAACA,QAAQ,KAAK,IAAI,CAAClB,OAAO,IAC9B,IAAI,CAACkB,QAAQ,KAAK,IAAI,CAACjB,aAAa,EACpC;YACA,OAAO;QACT;QAEA,MAAM4E,mBAAmBrF,2BAA2B,IAAI,CAAC0B,QAAQ,EAAE,IAAI,CAAClB,OAAO;QAE/E,IACE6E,qBAAqB,QACrB,IAAI,CAAC5E,aAAa,KAAK4E,oBACvBA,iBAAiBJ,YAAY,IAAII,iBAAiBH,YAAY,EAC9D;YACA,OAAO;QACT;QAEA,OACEG,iBAAiBF,SAAS,KAAK,KAAK,IAAI,CAACrE,oBAAoB,CAACsD,SAAS,GAAGA,SAAS,KAAK,CAAC;IAE7F;IAEA,OAAezB,sCACblC,aAAiC,EACjC6E,QAA4B,EAC5B;QACA,IACE7E,kBAAkB,QAClBA,cAAc0E,SAAS,IAAI,KAC3B1E,cAAcuE,QAAQ,CAACM,aACvB7E,cAAcwE,YAAY,GAAGxE,cAAcyE,YAAY,EACvD;YACAzE,cAAc8E,KAAK,CAACC,WAAW,CAAC,cAAc;YAC9C,OAAO,SAASC;gBACdhF,cAAc8E,KAAK,CAACG,cAAc,CAAC;YACrC;QACF;QACA,OAAO7F;IACT;IAEA,OAAeuF,uBACb/D,gBAAkC,EAClCsE,QAAgB,EACP;QACT,OAAOA,aAAatE,gBAAgB,CAACA,iBAAiBuE,MAAM,GAAG,EAAE;IACnE;IAEA,OAAehB,+BACbvD,gBAAkC,EAClCsE,QAAgB,EAChBvB,SAAiB,EACT;QACR,MAAMyB,aAAaxE,iBAAiByE,OAAO,CAACH;QAC5C,OAAQvB;YACN,KAAK,CAAC;gBACJ,OAAO/C,gBAAgB,CAACwE,aAAa,EAAE,IAAIxE,gBAAgB,CAACA,iBAAiBuE,MAAM,GAAG,EAAE;YAC1F,KAAK;gBACH,OAAOvE,gBAAgB,CAACwE,aAAa,EAAE,IAAIxE,gBAAgB,CAAC,EAAE;QAClE;IACF;IAEA,OAAe6C,oBAAoB7C,gBAAkC,EAAEsE,QAAgB,EAAE;QACvF,IAAIZ,UAAU1D,gBAAgB,CAAC,EAAE;QACjC,IAAI0E,gBAAgBxB,KAAKC,GAAG,CAACnD,gBAAgB,CAAC,EAAE,GAAGsE;QAEnD,IAAK,IAAIK,IAAI,GAAGA,IAAI3E,iBAAiBuE,MAAM,EAAEI,KAAK,EAAG;YACnD,MAAMC,aAAa1B,KAAKC,GAAG,CAACnD,gBAAgB,CAAC2E,EAAE,GAAGL;YAClD,IAAIM,aAAaF,eAAe;gBAC9BhB,UAAU1D,gBAAgB,CAAC2E,EAAE;gBAC7BD,gBAAgBE;YAClB;QACF;QAEA,OAAOlB;IACT;AACF"}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/lib/sheet/controllers/BottomSheetController.ts"],"sourcesContent":["import { noop } from '@vkontakte/vkjs';\nimport { clamp } from '../../../helpers/math';\nimport { rubberbandIfOutOfBounds } from '../../animation';\nimport { getNearestOverflowAncestor, hasSelectionWithRangeType } from '../../dom';\nimport { UIPanGestureRecognizer } from '../../touch/UIPanGestureRecognizer';\nimport {\n BLOCK_SHEET_BEHAVIOR_DATA_ATTRIBUTE_KEY,\n DRAG_THRESHOLDS,\n DYNAMIC_SNAP_POINT_DATA,\n SNAP_POINT_DETENTS,\n} from '../constants';\nimport type { CSSTransitionController } from './CSSTransitionController';\n\nexport type SnapPointDetents = [number, number] | [number, number, number];\n\nexport type SnapPoint = 'auto' | { initial: number; detents: SnapPointDetents };\n\nexport type SnapPointChange = (snapPoint: number) => void;\n\nexport type BottomSheetControllerOptions = {\n sheetScrollEl: HTMLElement | null;\n sheetTransitionController: CSSTransitionController<string>;\n backdropTransitionController: CSSTransitionController | null;\n onSnapPointChange: SnapPointChange;\n onDismiss: VoidFunction;\n};\n\nexport class BottomSheetController {\n private readonly sheetEl: HTMLElement;\n\n constructor(\n sheetEl: HTMLElement,\n {\n sheetScrollEl,\n sheetTransitionController,\n backdropTransitionController,\n onSnapPointChange,\n onDismiss,\n }: BottomSheetControllerOptions,\n ) {\n this.sheetEl = sheetEl;\n this.onSnapPointChange = onSnapPointChange;\n this.onDismiss = onDismiss;\n this.panGestureRecognizer = new UIPanGestureRecognizer();\n this.sheetScrollEl = sheetScrollEl;\n this.sheetTransitionController = sheetTransitionController;\n this.backdropTransitionController = backdropTransitionController;\n }\n\n init(snapPoint: SnapPoint) {\n this.isInitialized = true;\n\n if (snapPoint === 'auto') {\n this.unit = 'px';\n this.currentSnapPoint = DYNAMIC_SNAP_POINT_DATA.IDLE_POINT_VALUE;\n this.snapPointDetents = [SNAP_POINT_DETENTS.MIN, DYNAMIC_SNAP_POINT_DATA.IDLE_POINT_VALUE];\n } else {\n this.unit = '%';\n this.currentSnapPoint = snapPoint.initial;\n this.snapPointDetents = snapPoint.detents;\n }\n }\n\n destroy() {\n this.isInitialized = false;\n this.pannedEl = null;\n this.sheetTransitionController.cleanup();\n this.backdropTransitionController?.cleanup();\n\n this.disableVerticalScrollBouncingDispose();\n this.disableVerticalScrollBouncingDispose = noop;\n }\n\n panStart(event: UIEvent) {\n if (\n !this.isInitialized ||\n this.panState !== 'idle' ||\n hasSelectionWithRangeType(event.target)\n ) {\n return;\n }\n\n this.panState = 'start';\n this.pannedEl = event.target as HTMLElement;\n this.panGestureRecognizer.setStartCoords(event);\n }\n\n panMove(event: UIEvent) {\n switch (this.panState) {\n case 'start':\n this.panGestureRecognizer.setInitialTimeOnce();\n this.panGestureRecognizer.setEndCoords(event);\n\n if (this.preventUntilPanGestureBecomesExpected()) {\n return;\n }\n\n if (this.preventImmediatelyIfPannedElIsNotValid()) {\n this.panState = 'idle';\n return;\n }\n\n if (this.preventUntilVerticalScrollingOnSheetScrollElBecomesExpected()) {\n return;\n }\n\n if (this.preventImmediatelyIfVerticalScrollingOnPannedElIsScrolled()) {\n this.panState = 'idle';\n return;\n }\n\n this.panState = 'moving';\n this.panGestureRecognizer.setStartCoords(event);\n\n this.sheetHeight = this.sheetEl.offsetHeight;\n\n this.disableVerticalScrollBouncingDispose =\n BottomSheetController.disableVerticalScrollBouncingIfNeeded(\n this.sheetScrollEl,\n this.pannedEl,\n );\n\n if (this.isDynamicSnapPoint) {\n this.currentSnapPoint = this.sheetHeight;\n this.snapPointDetents[DYNAMIC_SNAP_POINT_DATA.COMPUTED_INDEX] = this.sheetHeight;\n }\n break;\n case 'moving':\n this.panGestureRecognizer.setEndCoords(event);\n\n const { y1, y2 } = this.panGestureRecognizer;\n\n this.nextSnapPoint = rubberbandIfOutOfBounds(\n this.currentSnapPoint - ((y2 - y1) / this.sheetHeight) * this.currentSnapPoint,\n SNAP_POINT_DETENTS.MIN,\n this.isDynamicSnapPoint ? this.sheetHeight : SNAP_POINT_DETENTS.LARGE,\n );\n\n this.calculateSnapPoint(this.nextSnapPoint, true);\n break;\n }\n }\n\n panEnd() {\n switch (this.panState) {\n case 'moving':\n const prevCurrentSnapPoint = this.currentSnapPoint;\n this.currentSnapPoint = this.getSnapPointTo(this.nextSnapPoint);\n\n if (\n prevCurrentSnapPoint !== this.currentSnapPoint &&\n this.currentSnapPoint > SNAP_POINT_DETENTS.MIN\n ) {\n this.onSnapPointChange(this.currentSnapPoint);\n }\n\n this.calculateSnapPoint(this.currentSnapPoint);\n break;\n }\n\n this.panState = 'idle';\n this.panGestureRecognizer.reset();\n\n this.disableVerticalScrollBouncingDispose();\n this.disableVerticalScrollBouncingDispose = noop;\n }\n\n private isInitialized = false;\n private panState: 'idle' | 'start' | 'moving' = 'idle';\n private pannedEl: HTMLElement | null = null;\n private sheetHeight = 0;\n private rafId: number | null = null;\n private currentSnapPoint = 0;\n private nextSnapPoint = 0;\n private snapPointDetents: SnapPointDetents = [0, 0];\n private unit: 'px' | '%' = '%';\n private get isDynamicSnapPoint() {\n return this.unit === 'px';\n }\n private disableVerticalScrollBouncingDispose = noop;\n private readonly sheetScrollEl: HTMLElement | null;\n private readonly sheetTransitionController: CSSTransitionController<string>;\n private readonly backdropTransitionController: CSSTransitionController | null;\n private readonly panGestureRecognizer: UIPanGestureRecognizer;\n private readonly onSnapPointChange: SnapPointChange;\n private readonly onDismiss: VoidFunction;\n\n private calculateSnapPoint(nextSnapPoint: number, immediately = false) {\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n }\n\n if (nextSnapPoint <= SNAP_POINT_DETENTS.MIN) {\n this.sheetTransitionController.enableTransition();\n this.backdropTransitionController?.enableTransition();\n this.panState = 'idle';\n this.onDismiss();\n return;\n }\n\n const backdropOpacity = clamp(\n this.isDynamicSnapPoint\n ? nextSnapPoint / this.sheetHeight\n : (nextSnapPoint * 2) / SNAP_POINT_DETENTS.LARGE,\n 0,\n 1,\n );\n\n this.rafId = requestAnimationFrame(() => {\n if (immediately) {\n this.backdropTransitionController?.disableTransition().set(backdropOpacity);\n this.sheetTransitionController.disableTransition().set(`${nextSnapPoint}${this.unit}`);\n return;\n }\n\n if (this.isDynamicSnapPoint) {\n this.sheetTransitionController.cleanupOnTransitionEnd();\n }\n\n this.backdropTransitionController?.unset();\n this.sheetTransitionController.enableTransition().set(`${this.currentSnapPoint}${this.unit}`);\n });\n }\n\n private getSnapPointTo(nextSnapPoint: number) {\n const closestSnapPoint = BottomSheetController.getClosestSnapPoint(\n this.snapPointDetents,\n nextSnapPoint,\n );\n if (closestSnapPoint !== this.currentSnapPoint) {\n return closestSnapPoint;\n }\n\n const panDirection = this.panGestureRecognizer.direction();\n if (panDirection.axis !== 'y' || panDirection.direction === null) {\n return this.currentSnapPoint;\n }\n\n const velocity = this.panGestureRecognizer.velocity();\n if (Math.abs(velocity.y) < DRAG_THRESHOLDS.VELOCITY) {\n return this.currentSnapPoint;\n }\n\n const closestSnapPointByDirection = BottomSheetController.getClosestSnapPointByDirection(\n this.snapPointDetents,\n closestSnapPoint,\n panDirection.direction,\n );\n\n return closestSnapPointByDirection;\n }\n\n private preventUntilPanGestureBecomesExpected() {\n return (\n this.panGestureRecognizer.direction().axis === 'x' ||\n this.panGestureRecognizer.distance() < DRAG_THRESHOLDS.DISTANCE_FOR_MOVING_START\n );\n }\n\n private preventImmediatelyIfPannedElIsNotValid() {\n return (\n this.pannedEl === null ||\n // Элемент со специальным атрибутом\n this.pannedEl.closest(`[${BLOCK_SHEET_BEHAVIOR_DATA_ATTRIBUTE_KEY}=true]`) !== null || // eslint-disable-line no-restricted-properties\n // Элемент за пределами панели.\n !this.sheetEl.contains(this.pannedEl)\n );\n }\n\n private preventUntilVerticalScrollingOnSheetScrollElBecomesExpected() {\n if (\n this.sheetScrollEl === null ||\n !this.sheetScrollEl.contains(this.pannedEl) ||\n this.sheetScrollEl.scrollHeight <= this.sheetScrollEl.clientHeight\n ) {\n return false;\n }\n\n if (this.sheetScrollEl.scrollTop === 0) {\n return (\n this.panGestureRecognizer.direction().direction === -1 &&\n BottomSheetController.isLastSnapPointDetents(this.snapPointDetents, this.currentSnapPoint)\n );\n }\n\n return true;\n }\n\n private preventImmediatelyIfVerticalScrollingOnPannedElIsScrolled() {\n if (\n /* istanbul ignore next: покрываем TypeScript */\n this.pannedEl === null ||\n this.pannedEl === this.sheetEl ||\n this.pannedEl === this.sheetScrollEl\n ) {\n return false;\n }\n\n const overflowAncestor = getNearestOverflowAncestor(this.pannedEl, this.sheetEl);\n\n if (\n overflowAncestor === null ||\n this.sheetScrollEl === overflowAncestor ||\n overflowAncestor.scrollHeight <= overflowAncestor.clientHeight\n ) {\n return false;\n }\n\n return (\n overflowAncestor.scrollTop !== 0 || this.panGestureRecognizer.direction().direction === -1\n );\n }\n\n private static disableVerticalScrollBouncingIfNeeded(\n sheetScrollEl: HTMLElement | null,\n targetEl: HTMLElement | null,\n ) {\n if (\n sheetScrollEl !== null &&\n sheetScrollEl.scrollTop <= 0 &&\n sheetScrollEl.contains(targetEl) &&\n sheetScrollEl.scrollHeight > sheetScrollEl.clientHeight\n ) {\n const scrollbarWidth = sheetScrollEl.offsetWidth - sheetScrollEl.clientWidth;\n\n Object.assign(sheetScrollEl.style, {\n paddingInlineEnd: `${scrollbarWidth}px`,\n overflowY: 'hidden',\n boxSizing: 'border-box',\n });\n return function dispose() {\n Object.assign(sheetScrollEl.style, {\n paddingInlineEnd: '',\n overflowY: '',\n boxSizing: '',\n });\n };\n }\n return noop;\n }\n\n private static isLastSnapPointDetents(\n snapPointDetents: SnapPointDetents,\n currentY: number,\n ): boolean {\n return currentY === snapPointDetents[snapPointDetents.length - 1];\n }\n\n private static getClosestSnapPointByDirection(\n snapPointDetents: SnapPointDetents,\n currentY: number,\n direction: -1 | 1,\n ): number {\n const foundIndex = snapPointDetents.indexOf(currentY);\n switch (direction) {\n case -1:\n return snapPointDetents[foundIndex + 1] ?? snapPointDetents[snapPointDetents.length - 1];\n case 1:\n return snapPointDetents[foundIndex - 1] ?? snapPointDetents[0];\n }\n }\n\n private static getClosestSnapPoint(snapPointDetents: SnapPointDetents, currentY: number) {\n let closest = snapPointDetents[0];\n let minDifference = Math.abs(snapPointDetents[0] - currentY);\n\n for (let i = 1; i < snapPointDetents.length; i += 1) {\n const difference = Math.abs(snapPointDetents[i] - currentY);\n if (difference < minDifference) {\n closest = snapPointDetents[i];\n minDifference = difference;\n }\n }\n\n return closest;\n }\n}\n"],"names":["noop","clamp","rubberbandIfOutOfBounds","getNearestOverflowAncestor","hasSelectionWithRangeType","UIPanGestureRecognizer","BLOCK_SHEET_BEHAVIOR_DATA_ATTRIBUTE_KEY","DRAG_THRESHOLDS","DYNAMIC_SNAP_POINT_DATA","SNAP_POINT_DETENTS","BottomSheetController","sheetEl","sheetScrollEl","sheetTransitionController","backdropTransitionController","onSnapPointChange","onDismiss","panGestureRecognizer","init","snapPoint","isInitialized","unit","currentSnapPoint","IDLE_POINT_VALUE","snapPointDetents","MIN","initial","detents","destroy","pannedEl","cleanup","disableVerticalScrollBouncingDispose","panStart","event","panState","target","setStartCoords","panMove","setInitialTimeOnce","setEndCoords","preventUntilPanGestureBecomesExpected","preventImmediatelyIfPannedElIsNotValid","preventUntilVerticalScrollingOnSheetScrollElBecomesExpected","preventImmediatelyIfVerticalScrollingOnPannedElIsScrolled","sheetHeight","offsetHeight","disableVerticalScrollBouncingIfNeeded","isDynamicSnapPoint","COMPUTED_INDEX","y1","y2","nextSnapPoint","LARGE","calculateSnapPoint","panEnd","prevCurrentSnapPoint","getSnapPointTo","reset","rafId","immediately","cancelAnimationFrame","enableTransition","backdropOpacity","requestAnimationFrame","disableTransition","set","cleanupOnTransitionEnd","unset","closestSnapPoint","getClosestSnapPoint","panDirection","direction","axis","velocity","Math","abs","y","VELOCITY","closestSnapPointByDirection","getClosestSnapPointByDirection","distance","DISTANCE_FOR_MOVING_START","closest","contains","scrollHeight","clientHeight","scrollTop","isLastSnapPointDetents","overflowAncestor","targetEl","scrollbarWidth","offsetWidth","clientWidth","Object","assign","style","paddingInlineEnd","overflowY","boxSizing","dispose","currentY","length","foundIndex","indexOf","minDifference","i","difference"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BottomSheetController.d.ts","sourceRoot":"","sources":["../../../../src/lib/sheet/controllers/BottomSheetController.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAEzE,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAE3E,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAEhF,MAAM,MAAM,eAAe,GAAG,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;AAE1D,MAAM,MAAM,4BAA4B,GAAG;IACzC,aAAa,EAAE,WAAW,GAAG,IAAI,CAAC;IAClC,yBAAyB,EAAE,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAC3D,4BAA4B,EAAE,uBAAuB,GAAG,IAAI,CAAC;IAC7D,iBAAiB,EAAE,eAAe,CAAC;IACnC,SAAS,EAAE,YAAY,CAAC;CACzB,CAAC;AAEF,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;gBAGpC,OAAO,EAAE,WAAW,EACpB,EACE,aAAa,EACb,yBAAyB,EACzB,4BAA4B,EAC5B,iBAAiB,EACjB,SAAS,GACV,EAAE,4BAA4B;IAWjC,IAAI,CAAC,SAAS,EAAE,SAAS;IAczB,OAAO;IAUP,QAAQ,CAAC,KAAK,EAAE,OAAO;IAcvB,OAAO,CAAC,KAAK,EAAE,OAAO;IAwDtB,MAAM;IAwBN,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAuC;IACvD,OAAO,CAAC,QAAQ,CAA4B;IAC5C,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,gBAAgB,CAA4B;IACpD,OAAO,CAAC,IAAI,CAAmB;IAC/B,OAAO,KAAK,kBAAkB,GAE7B;IACD,OAAO,CAAC,oCAAoC,CAAQ;IACpD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IACnD,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAkC;IAC5E,OAAO,CAAC,QAAQ,CAAC,4BAA4B,CAAiC;IAC9E,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAyB;IAC9D,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAkB;IACpD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IAEzC,OAAO,CAAC,kBAAkB;IAqC1B,OAAO,CAAC,cAAc;IA4BtB,OAAO,CAAC,qCAAqC;IAO7C,OAAO,CAAC,sCAAsC;IAU9C,OAAO,CAAC,2DAA2D;IAmBnE,OAAO,CAAC,yDAAyD;IAyBjE,OAAO,CAAC,MAAM,CAAC,qCAAqC;
|
|
1
|
+
{"version":3,"file":"BottomSheetController.d.ts","sourceRoot":"","sources":["../../../../src/lib/sheet/controllers/BottomSheetController.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAEzE,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAE3E,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAEhF,MAAM,MAAM,eAAe,GAAG,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;AAE1D,MAAM,MAAM,4BAA4B,GAAG;IACzC,aAAa,EAAE,WAAW,GAAG,IAAI,CAAC;IAClC,yBAAyB,EAAE,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAC3D,4BAA4B,EAAE,uBAAuB,GAAG,IAAI,CAAC;IAC7D,iBAAiB,EAAE,eAAe,CAAC;IACnC,SAAS,EAAE,YAAY,CAAC;CACzB,CAAC;AAEF,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;gBAGpC,OAAO,EAAE,WAAW,EACpB,EACE,aAAa,EACb,yBAAyB,EACzB,4BAA4B,EAC5B,iBAAiB,EACjB,SAAS,GACV,EAAE,4BAA4B;IAWjC,IAAI,CAAC,SAAS,EAAE,SAAS;IAczB,OAAO;IAUP,QAAQ,CAAC,KAAK,EAAE,OAAO;IAcvB,OAAO,CAAC,KAAK,EAAE,OAAO;IAwDtB,MAAM;IAwBN,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAuC;IACvD,OAAO,CAAC,QAAQ,CAA4B;IAC5C,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,gBAAgB,CAA4B;IACpD,OAAO,CAAC,IAAI,CAAmB;IAC/B,OAAO,KAAK,kBAAkB,GAE7B;IACD,OAAO,CAAC,oCAAoC,CAAQ;IACpD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IACnD,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAkC;IAC5E,OAAO,CAAC,QAAQ,CAAC,4BAA4B,CAAiC;IAC9E,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAyB;IAC9D,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAkB;IACpD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IAEzC,OAAO,CAAC,kBAAkB;IAqC1B,OAAO,CAAC,cAAc;IA4BtB,OAAO,CAAC,qCAAqC;IAO7C,OAAO,CAAC,sCAAsC;IAU9C,OAAO,CAAC,2DAA2D;IAmBnE,OAAO,CAAC,yDAAyD;IAyBjE,OAAO,CAAC,MAAM,CAAC,qCAAqC;IA4BpD,OAAO,CAAC,MAAM,CAAC,sBAAsB;IAOrC,OAAO,CAAC,MAAM,CAAC,8BAA8B;IAc7C,OAAO,CAAC,MAAM,CAAC,mBAAmB;CAcnC"}
|
|
@@ -167,9 +167,18 @@ export class BottomSheetController {
|
|
|
167
167
|
}
|
|
168
168
|
static disableVerticalScrollBouncingIfNeeded(sheetScrollEl, targetEl) {
|
|
169
169
|
if (sheetScrollEl !== null && sheetScrollEl.scrollTop <= 0 && sheetScrollEl.contains(targetEl) && sheetScrollEl.scrollHeight > sheetScrollEl.clientHeight) {
|
|
170
|
-
sheetScrollEl.
|
|
170
|
+
const scrollbarWidth = sheetScrollEl.offsetWidth - sheetScrollEl.clientWidth;
|
|
171
|
+
Object.assign(sheetScrollEl.style, {
|
|
172
|
+
paddingInlineEnd: `${scrollbarWidth}px`,
|
|
173
|
+
overflowY: 'hidden',
|
|
174
|
+
boxSizing: 'border-box'
|
|
175
|
+
});
|
|
171
176
|
return function dispose() {
|
|
172
|
-
sheetScrollEl.style
|
|
177
|
+
Object.assign(sheetScrollEl.style, {
|
|
178
|
+
paddingInlineEnd: '',
|
|
179
|
+
overflowY: '',
|
|
180
|
+
boxSizing: ''
|
|
181
|
+
});
|
|
173
182
|
};
|
|
174
183
|
}
|
|
175
184
|
return noop;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/sheet/controllers/BottomSheetController.ts"],"sourcesContent":["import { noop } from '@vkontakte/vkjs';\nimport { clamp } from '../../../helpers/math';\nimport { rubberbandIfOutOfBounds } from '../../animation';\nimport { getNearestOverflowAncestor, hasSelectionWithRangeType } from '../../dom';\nimport { UIPanGestureRecognizer } from '../../touch/UIPanGestureRecognizer';\nimport {\n BLOCK_SHEET_BEHAVIOR_DATA_ATTRIBUTE_KEY,\n DRAG_THRESHOLDS,\n DYNAMIC_SNAP_POINT_DATA,\n SNAP_POINT_DETENTS,\n} from '../constants';\nimport type { CSSTransitionController } from './CSSTransitionController';\n\nexport type SnapPointDetents = [number, number] | [number, number, number];\n\nexport type SnapPoint = 'auto' | { initial: number; detents: SnapPointDetents };\n\nexport type SnapPointChange = (snapPoint: number) => void;\n\nexport type BottomSheetControllerOptions = {\n sheetScrollEl: HTMLElement | null;\n sheetTransitionController: CSSTransitionController<string>;\n backdropTransitionController: CSSTransitionController | null;\n onSnapPointChange: SnapPointChange;\n onDismiss: VoidFunction;\n};\n\nexport class BottomSheetController {\n private readonly sheetEl: HTMLElement;\n\n constructor(\n sheetEl: HTMLElement,\n {\n sheetScrollEl,\n sheetTransitionController,\n backdropTransitionController,\n onSnapPointChange,\n onDismiss,\n }: BottomSheetControllerOptions,\n ) {\n this.sheetEl = sheetEl;\n this.onSnapPointChange = onSnapPointChange;\n this.onDismiss = onDismiss;\n this.panGestureRecognizer = new UIPanGestureRecognizer();\n this.sheetScrollEl = sheetScrollEl;\n this.sheetTransitionController = sheetTransitionController;\n this.backdropTransitionController = backdropTransitionController;\n }\n\n init(snapPoint: SnapPoint) {\n this.isInitialized = true;\n\n if (snapPoint === 'auto') {\n this.unit = 'px';\n this.currentSnapPoint = DYNAMIC_SNAP_POINT_DATA.IDLE_POINT_VALUE;\n this.snapPointDetents = [SNAP_POINT_DETENTS.MIN, DYNAMIC_SNAP_POINT_DATA.IDLE_POINT_VALUE];\n } else {\n this.unit = '%';\n this.currentSnapPoint = snapPoint.initial;\n this.snapPointDetents = snapPoint.detents;\n }\n }\n\n destroy() {\n this.isInitialized = false;\n this.pannedEl = null;\n this.sheetTransitionController.cleanup();\n this.backdropTransitionController?.cleanup();\n\n this.disableVerticalScrollBouncingDispose();\n this.disableVerticalScrollBouncingDispose = noop;\n }\n\n panStart(event: UIEvent) {\n if (\n !this.isInitialized ||\n this.panState !== 'idle' ||\n hasSelectionWithRangeType(event.target)\n ) {\n return;\n }\n\n this.panState = 'start';\n this.pannedEl = event.target as HTMLElement;\n this.panGestureRecognizer.setStartCoords(event);\n }\n\n panMove(event: UIEvent) {\n switch (this.panState) {\n case 'start':\n this.panGestureRecognizer.setInitialTimeOnce();\n this.panGestureRecognizer.setEndCoords(event);\n\n if (this.preventUntilPanGestureBecomesExpected()) {\n return;\n }\n\n if (this.preventImmediatelyIfPannedElIsNotValid()) {\n this.panState = 'idle';\n return;\n }\n\n if (this.preventUntilVerticalScrollingOnSheetScrollElBecomesExpected()) {\n return;\n }\n\n if (this.preventImmediatelyIfVerticalScrollingOnPannedElIsScrolled()) {\n this.panState = 'idle';\n return;\n }\n\n this.panState = 'moving';\n this.panGestureRecognizer.setStartCoords(event);\n\n this.sheetHeight = this.sheetEl.offsetHeight;\n\n this.disableVerticalScrollBouncingDispose =\n BottomSheetController.disableVerticalScrollBouncingIfNeeded(\n this.sheetScrollEl,\n this.pannedEl,\n );\n\n if (this.isDynamicSnapPoint) {\n this.currentSnapPoint = this.sheetHeight;\n this.snapPointDetents[DYNAMIC_SNAP_POINT_DATA.COMPUTED_INDEX] = this.sheetHeight;\n }\n break;\n case 'moving':\n this.panGestureRecognizer.setEndCoords(event);\n\n const { y1, y2 } = this.panGestureRecognizer;\n\n this.nextSnapPoint = rubberbandIfOutOfBounds(\n this.currentSnapPoint - ((y2 - y1) / this.sheetHeight) * this.currentSnapPoint,\n SNAP_POINT_DETENTS.MIN,\n this.isDynamicSnapPoint ? this.sheetHeight : SNAP_POINT_DETENTS.LARGE,\n );\n\n this.calculateSnapPoint(this.nextSnapPoint, true);\n break;\n }\n }\n\n panEnd() {\n switch (this.panState) {\n case 'moving':\n const prevCurrentSnapPoint = this.currentSnapPoint;\n this.currentSnapPoint = this.getSnapPointTo(this.nextSnapPoint);\n\n if (\n prevCurrentSnapPoint !== this.currentSnapPoint &&\n this.currentSnapPoint > SNAP_POINT_DETENTS.MIN\n ) {\n this.onSnapPointChange(this.currentSnapPoint);\n }\n\n this.calculateSnapPoint(this.currentSnapPoint);\n break;\n }\n\n this.panState = 'idle';\n this.panGestureRecognizer.reset();\n\n this.disableVerticalScrollBouncingDispose();\n this.disableVerticalScrollBouncingDispose = noop;\n }\n\n private isInitialized = false;\n private panState: 'idle' | 'start' | 'moving' = 'idle';\n private pannedEl: HTMLElement | null = null;\n private sheetHeight = 0;\n private rafId: number | null = null;\n private currentSnapPoint = 0;\n private nextSnapPoint = 0;\n private snapPointDetents: SnapPointDetents = [0, 0];\n private unit: 'px' | '%' = '%';\n private get isDynamicSnapPoint() {\n return this.unit === 'px';\n }\n private disableVerticalScrollBouncingDispose = noop;\n private readonly sheetScrollEl: HTMLElement | null;\n private readonly sheetTransitionController: CSSTransitionController<string>;\n private readonly backdropTransitionController: CSSTransitionController | null;\n private readonly panGestureRecognizer: UIPanGestureRecognizer;\n private readonly onSnapPointChange: SnapPointChange;\n private readonly onDismiss: VoidFunction;\n\n private calculateSnapPoint(nextSnapPoint: number, immediately = false) {\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n }\n\n if (nextSnapPoint <= SNAP_POINT_DETENTS.MIN) {\n this.sheetTransitionController.enableTransition();\n this.backdropTransitionController?.enableTransition();\n this.panState = 'idle';\n this.onDismiss();\n return;\n }\n\n const backdropOpacity = clamp(\n this.isDynamicSnapPoint\n ? nextSnapPoint / this.sheetHeight\n : (nextSnapPoint * 2) / SNAP_POINT_DETENTS.LARGE,\n 0,\n 1,\n );\n\n this.rafId = requestAnimationFrame(() => {\n if (immediately) {\n this.backdropTransitionController?.disableTransition().set(backdropOpacity);\n this.sheetTransitionController.disableTransition().set(`${nextSnapPoint}${this.unit}`);\n return;\n }\n\n if (this.isDynamicSnapPoint) {\n this.sheetTransitionController.cleanupOnTransitionEnd();\n }\n\n this.backdropTransitionController?.unset();\n this.sheetTransitionController.enableTransition().set(`${this.currentSnapPoint}${this.unit}`);\n });\n }\n\n private getSnapPointTo(nextSnapPoint: number) {\n const closestSnapPoint = BottomSheetController.getClosestSnapPoint(\n this.snapPointDetents,\n nextSnapPoint,\n );\n if (closestSnapPoint !== this.currentSnapPoint) {\n return closestSnapPoint;\n }\n\n const panDirection = this.panGestureRecognizer.direction();\n if (panDirection.axis !== 'y' || panDirection.direction === null) {\n return this.currentSnapPoint;\n }\n\n const velocity = this.panGestureRecognizer.velocity();\n if (Math.abs(velocity.y) < DRAG_THRESHOLDS.VELOCITY) {\n return this.currentSnapPoint;\n }\n\n const closestSnapPointByDirection = BottomSheetController.getClosestSnapPointByDirection(\n this.snapPointDetents,\n closestSnapPoint,\n panDirection.direction,\n );\n\n return closestSnapPointByDirection;\n }\n\n private preventUntilPanGestureBecomesExpected() {\n return (\n this.panGestureRecognizer.direction().axis === 'x' ||\n this.panGestureRecognizer.distance() < DRAG_THRESHOLDS.DISTANCE_FOR_MOVING_START\n );\n }\n\n private preventImmediatelyIfPannedElIsNotValid() {\n return (\n this.pannedEl === null ||\n // Элемент со специальным атрибутом\n this.pannedEl.closest(`[${BLOCK_SHEET_BEHAVIOR_DATA_ATTRIBUTE_KEY}=true]`) !== null || // eslint-disable-line no-restricted-properties\n // Элемент за пределами панели.\n !this.sheetEl.contains(this.pannedEl)\n );\n }\n\n private preventUntilVerticalScrollingOnSheetScrollElBecomesExpected() {\n if (\n this.sheetScrollEl === null ||\n !this.sheetScrollEl.contains(this.pannedEl) ||\n this.sheetScrollEl.scrollHeight <= this.sheetScrollEl.clientHeight\n ) {\n return false;\n }\n\n if (this.sheetScrollEl.scrollTop === 0) {\n return (\n this.panGestureRecognizer.direction().direction === -1 &&\n BottomSheetController.isLastSnapPointDetents(this.snapPointDetents, this.currentSnapPoint)\n );\n }\n\n return true;\n }\n\n private preventImmediatelyIfVerticalScrollingOnPannedElIsScrolled() {\n if (\n /* istanbul ignore next: покрываем TypeScript */\n this.pannedEl === null ||\n this.pannedEl === this.sheetEl ||\n this.pannedEl === this.sheetScrollEl\n ) {\n return false;\n }\n\n const overflowAncestor = getNearestOverflowAncestor(this.pannedEl, this.sheetEl);\n\n if (\n overflowAncestor === null ||\n this.sheetScrollEl === overflowAncestor ||\n overflowAncestor.scrollHeight <= overflowAncestor.clientHeight\n ) {\n return false;\n }\n\n return (\n overflowAncestor.scrollTop !== 0 || this.panGestureRecognizer.direction().direction === -1\n );\n }\n\n private static disableVerticalScrollBouncingIfNeeded(\n sheetScrollEl: HTMLElement | null,\n targetEl: HTMLElement | null,\n ) {\n if (\n sheetScrollEl !== null &&\n sheetScrollEl.scrollTop <= 0 &&\n sheetScrollEl.contains(targetEl) &&\n sheetScrollEl.scrollHeight > sheetScrollEl.clientHeight\n ) {\n sheetScrollEl.style.setProperty('overflow-y', 'hidden');\n return function dispose() {\n sheetScrollEl.style.removeProperty('overflow-y');\n };\n }\n return noop;\n }\n\n private static isLastSnapPointDetents(\n snapPointDetents: SnapPointDetents,\n currentY: number,\n ): boolean {\n return currentY === snapPointDetents[snapPointDetents.length - 1];\n }\n\n private static getClosestSnapPointByDirection(\n snapPointDetents: SnapPointDetents,\n currentY: number,\n direction: -1 | 1,\n ): number {\n const foundIndex = snapPointDetents.indexOf(currentY);\n switch (direction) {\n case -1:\n return snapPointDetents[foundIndex + 1] ?? snapPointDetents[snapPointDetents.length - 1];\n case 1:\n return snapPointDetents[foundIndex - 1] ?? snapPointDetents[0];\n }\n }\n\n private static getClosestSnapPoint(snapPointDetents: SnapPointDetents, currentY: number) {\n let closest = snapPointDetents[0];\n let minDifference = Math.abs(snapPointDetents[0] - currentY);\n\n for (let i = 1; i < snapPointDetents.length; i += 1) {\n const difference = Math.abs(snapPointDetents[i] - currentY);\n if (difference < minDifference) {\n closest = snapPointDetents[i];\n minDifference = difference;\n }\n }\n\n return closest;\n }\n}\n"],"names":["noop","clamp","rubberbandIfOutOfBounds","getNearestOverflowAncestor","hasSelectionWithRangeType","UIPanGestureRecognizer","BLOCK_SHEET_BEHAVIOR_DATA_ATTRIBUTE_KEY","DRAG_THRESHOLDS","DYNAMIC_SNAP_POINT_DATA","SNAP_POINT_DETENTS","BottomSheetController","init","snapPoint","isInitialized","unit","currentSnapPoint","IDLE_POINT_VALUE","snapPointDetents","MIN","initial","detents","destroy","pannedEl","sheetTransitionController","cleanup","backdropTransitionController","disableVerticalScrollBouncingDispose","panStart","event","panState","target","panGestureRecognizer","setStartCoords","panMove","setInitialTimeOnce","setEndCoords","preventUntilPanGestureBecomesExpected","preventImmediatelyIfPannedElIsNotValid","preventUntilVerticalScrollingOnSheetScrollElBecomesExpected","preventImmediatelyIfVerticalScrollingOnPannedElIsScrolled","sheetHeight","sheetEl","offsetHeight","disableVerticalScrollBouncingIfNeeded","sheetScrollEl","isDynamicSnapPoint","COMPUTED_INDEX","y1","y2","nextSnapPoint","LARGE","calculateSnapPoint","panEnd","prevCurrentSnapPoint","getSnapPointTo","onSnapPointChange","reset","immediately","rafId","cancelAnimationFrame","enableTransition","onDismiss","backdropOpacity","requestAnimationFrame","disableTransition","set","cleanupOnTransitionEnd","unset","closestSnapPoint","getClosestSnapPoint","panDirection","direction","axis","velocity","Math","abs","y","VELOCITY","closestSnapPointByDirection","getClosestSnapPointByDirection","distance","DISTANCE_FOR_MOVING_START","closest","contains","scrollHeight","clientHeight","scrollTop","isLastSnapPointDetents","overflowAncestor","targetEl","style","setProperty","dispose","removeProperty","currentY","length","foundIndex","indexOf","minDifference","i","difference"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/sheet/controllers/BottomSheetController.ts"],"sourcesContent":["import { noop } from '@vkontakte/vkjs';\nimport { clamp } from '../../../helpers/math';\nimport { rubberbandIfOutOfBounds } from '../../animation';\nimport { getNearestOverflowAncestor, hasSelectionWithRangeType } from '../../dom';\nimport { UIPanGestureRecognizer } from '../../touch/UIPanGestureRecognizer';\nimport {\n BLOCK_SHEET_BEHAVIOR_DATA_ATTRIBUTE_KEY,\n DRAG_THRESHOLDS,\n DYNAMIC_SNAP_POINT_DATA,\n SNAP_POINT_DETENTS,\n} from '../constants';\nimport type { CSSTransitionController } from './CSSTransitionController';\n\nexport type SnapPointDetents = [number, number] | [number, number, number];\n\nexport type SnapPoint = 'auto' | { initial: number; detents: SnapPointDetents };\n\nexport type SnapPointChange = (snapPoint: number) => void;\n\nexport type BottomSheetControllerOptions = {\n sheetScrollEl: HTMLElement | null;\n sheetTransitionController: CSSTransitionController<string>;\n backdropTransitionController: CSSTransitionController | null;\n onSnapPointChange: SnapPointChange;\n onDismiss: VoidFunction;\n};\n\nexport class BottomSheetController {\n private readonly sheetEl: HTMLElement;\n\n constructor(\n sheetEl: HTMLElement,\n {\n sheetScrollEl,\n sheetTransitionController,\n backdropTransitionController,\n onSnapPointChange,\n onDismiss,\n }: BottomSheetControllerOptions,\n ) {\n this.sheetEl = sheetEl;\n this.onSnapPointChange = onSnapPointChange;\n this.onDismiss = onDismiss;\n this.panGestureRecognizer = new UIPanGestureRecognizer();\n this.sheetScrollEl = sheetScrollEl;\n this.sheetTransitionController = sheetTransitionController;\n this.backdropTransitionController = backdropTransitionController;\n }\n\n init(snapPoint: SnapPoint) {\n this.isInitialized = true;\n\n if (snapPoint === 'auto') {\n this.unit = 'px';\n this.currentSnapPoint = DYNAMIC_SNAP_POINT_DATA.IDLE_POINT_VALUE;\n this.snapPointDetents = [SNAP_POINT_DETENTS.MIN, DYNAMIC_SNAP_POINT_DATA.IDLE_POINT_VALUE];\n } else {\n this.unit = '%';\n this.currentSnapPoint = snapPoint.initial;\n this.snapPointDetents = snapPoint.detents;\n }\n }\n\n destroy() {\n this.isInitialized = false;\n this.pannedEl = null;\n this.sheetTransitionController.cleanup();\n this.backdropTransitionController?.cleanup();\n\n this.disableVerticalScrollBouncingDispose();\n this.disableVerticalScrollBouncingDispose = noop;\n }\n\n panStart(event: UIEvent) {\n if (\n !this.isInitialized ||\n this.panState !== 'idle' ||\n hasSelectionWithRangeType(event.target)\n ) {\n return;\n }\n\n this.panState = 'start';\n this.pannedEl = event.target as HTMLElement;\n this.panGestureRecognizer.setStartCoords(event);\n }\n\n panMove(event: UIEvent) {\n switch (this.panState) {\n case 'start':\n this.panGestureRecognizer.setInitialTimeOnce();\n this.panGestureRecognizer.setEndCoords(event);\n\n if (this.preventUntilPanGestureBecomesExpected()) {\n return;\n }\n\n if (this.preventImmediatelyIfPannedElIsNotValid()) {\n this.panState = 'idle';\n return;\n }\n\n if (this.preventUntilVerticalScrollingOnSheetScrollElBecomesExpected()) {\n return;\n }\n\n if (this.preventImmediatelyIfVerticalScrollingOnPannedElIsScrolled()) {\n this.panState = 'idle';\n return;\n }\n\n this.panState = 'moving';\n this.panGestureRecognizer.setStartCoords(event);\n\n this.sheetHeight = this.sheetEl.offsetHeight;\n\n this.disableVerticalScrollBouncingDispose =\n BottomSheetController.disableVerticalScrollBouncingIfNeeded(\n this.sheetScrollEl,\n this.pannedEl,\n );\n\n if (this.isDynamicSnapPoint) {\n this.currentSnapPoint = this.sheetHeight;\n this.snapPointDetents[DYNAMIC_SNAP_POINT_DATA.COMPUTED_INDEX] = this.sheetHeight;\n }\n break;\n case 'moving':\n this.panGestureRecognizer.setEndCoords(event);\n\n const { y1, y2 } = this.panGestureRecognizer;\n\n this.nextSnapPoint = rubberbandIfOutOfBounds(\n this.currentSnapPoint - ((y2 - y1) / this.sheetHeight) * this.currentSnapPoint,\n SNAP_POINT_DETENTS.MIN,\n this.isDynamicSnapPoint ? this.sheetHeight : SNAP_POINT_DETENTS.LARGE,\n );\n\n this.calculateSnapPoint(this.nextSnapPoint, true);\n break;\n }\n }\n\n panEnd() {\n switch (this.panState) {\n case 'moving':\n const prevCurrentSnapPoint = this.currentSnapPoint;\n this.currentSnapPoint = this.getSnapPointTo(this.nextSnapPoint);\n\n if (\n prevCurrentSnapPoint !== this.currentSnapPoint &&\n this.currentSnapPoint > SNAP_POINT_DETENTS.MIN\n ) {\n this.onSnapPointChange(this.currentSnapPoint);\n }\n\n this.calculateSnapPoint(this.currentSnapPoint);\n break;\n }\n\n this.panState = 'idle';\n this.panGestureRecognizer.reset();\n\n this.disableVerticalScrollBouncingDispose();\n this.disableVerticalScrollBouncingDispose = noop;\n }\n\n private isInitialized = false;\n private panState: 'idle' | 'start' | 'moving' = 'idle';\n private pannedEl: HTMLElement | null = null;\n private sheetHeight = 0;\n private rafId: number | null = null;\n private currentSnapPoint = 0;\n private nextSnapPoint = 0;\n private snapPointDetents: SnapPointDetents = [0, 0];\n private unit: 'px' | '%' = '%';\n private get isDynamicSnapPoint() {\n return this.unit === 'px';\n }\n private disableVerticalScrollBouncingDispose = noop;\n private readonly sheetScrollEl: HTMLElement | null;\n private readonly sheetTransitionController: CSSTransitionController<string>;\n private readonly backdropTransitionController: CSSTransitionController | null;\n private readonly panGestureRecognizer: UIPanGestureRecognizer;\n private readonly onSnapPointChange: SnapPointChange;\n private readonly onDismiss: VoidFunction;\n\n private calculateSnapPoint(nextSnapPoint: number, immediately = false) {\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n }\n\n if (nextSnapPoint <= SNAP_POINT_DETENTS.MIN) {\n this.sheetTransitionController.enableTransition();\n this.backdropTransitionController?.enableTransition();\n this.panState = 'idle';\n this.onDismiss();\n return;\n }\n\n const backdropOpacity = clamp(\n this.isDynamicSnapPoint\n ? nextSnapPoint / this.sheetHeight\n : (nextSnapPoint * 2) / SNAP_POINT_DETENTS.LARGE,\n 0,\n 1,\n );\n\n this.rafId = requestAnimationFrame(() => {\n if (immediately) {\n this.backdropTransitionController?.disableTransition().set(backdropOpacity);\n this.sheetTransitionController.disableTransition().set(`${nextSnapPoint}${this.unit}`);\n return;\n }\n\n if (this.isDynamicSnapPoint) {\n this.sheetTransitionController.cleanupOnTransitionEnd();\n }\n\n this.backdropTransitionController?.unset();\n this.sheetTransitionController.enableTransition().set(`${this.currentSnapPoint}${this.unit}`);\n });\n }\n\n private getSnapPointTo(nextSnapPoint: number) {\n const closestSnapPoint = BottomSheetController.getClosestSnapPoint(\n this.snapPointDetents,\n nextSnapPoint,\n );\n if (closestSnapPoint !== this.currentSnapPoint) {\n return closestSnapPoint;\n }\n\n const panDirection = this.panGestureRecognizer.direction();\n if (panDirection.axis !== 'y' || panDirection.direction === null) {\n return this.currentSnapPoint;\n }\n\n const velocity = this.panGestureRecognizer.velocity();\n if (Math.abs(velocity.y) < DRAG_THRESHOLDS.VELOCITY) {\n return this.currentSnapPoint;\n }\n\n const closestSnapPointByDirection = BottomSheetController.getClosestSnapPointByDirection(\n this.snapPointDetents,\n closestSnapPoint,\n panDirection.direction,\n );\n\n return closestSnapPointByDirection;\n }\n\n private preventUntilPanGestureBecomesExpected() {\n return (\n this.panGestureRecognizer.direction().axis === 'x' ||\n this.panGestureRecognizer.distance() < DRAG_THRESHOLDS.DISTANCE_FOR_MOVING_START\n );\n }\n\n private preventImmediatelyIfPannedElIsNotValid() {\n return (\n this.pannedEl === null ||\n // Элемент со специальным атрибутом\n this.pannedEl.closest(`[${BLOCK_SHEET_BEHAVIOR_DATA_ATTRIBUTE_KEY}=true]`) !== null || // eslint-disable-line no-restricted-properties\n // Элемент за пределами панели.\n !this.sheetEl.contains(this.pannedEl)\n );\n }\n\n private preventUntilVerticalScrollingOnSheetScrollElBecomesExpected() {\n if (\n this.sheetScrollEl === null ||\n !this.sheetScrollEl.contains(this.pannedEl) ||\n this.sheetScrollEl.scrollHeight <= this.sheetScrollEl.clientHeight\n ) {\n return false;\n }\n\n if (this.sheetScrollEl.scrollTop === 0) {\n return (\n this.panGestureRecognizer.direction().direction === -1 &&\n BottomSheetController.isLastSnapPointDetents(this.snapPointDetents, this.currentSnapPoint)\n );\n }\n\n return true;\n }\n\n private preventImmediatelyIfVerticalScrollingOnPannedElIsScrolled() {\n if (\n /* istanbul ignore next: покрываем TypeScript */\n this.pannedEl === null ||\n this.pannedEl === this.sheetEl ||\n this.pannedEl === this.sheetScrollEl\n ) {\n return false;\n }\n\n const overflowAncestor = getNearestOverflowAncestor(this.pannedEl, this.sheetEl);\n\n if (\n overflowAncestor === null ||\n this.sheetScrollEl === overflowAncestor ||\n overflowAncestor.scrollHeight <= overflowAncestor.clientHeight\n ) {\n return false;\n }\n\n return (\n overflowAncestor.scrollTop !== 0 || this.panGestureRecognizer.direction().direction === -1\n );\n }\n\n private static disableVerticalScrollBouncingIfNeeded(\n sheetScrollEl: HTMLElement | null,\n targetEl: HTMLElement | null,\n ) {\n if (\n sheetScrollEl !== null &&\n sheetScrollEl.scrollTop <= 0 &&\n sheetScrollEl.contains(targetEl) &&\n sheetScrollEl.scrollHeight > sheetScrollEl.clientHeight\n ) {\n const scrollbarWidth = sheetScrollEl.offsetWidth - sheetScrollEl.clientWidth;\n\n Object.assign(sheetScrollEl.style, {\n paddingInlineEnd: `${scrollbarWidth}px`,\n overflowY: 'hidden',\n boxSizing: 'border-box',\n });\n return function dispose() {\n Object.assign(sheetScrollEl.style, {\n paddingInlineEnd: '',\n overflowY: '',\n boxSizing: '',\n });\n };\n }\n return noop;\n }\n\n private static isLastSnapPointDetents(\n snapPointDetents: SnapPointDetents,\n currentY: number,\n ): boolean {\n return currentY === snapPointDetents[snapPointDetents.length - 1];\n }\n\n private static getClosestSnapPointByDirection(\n snapPointDetents: SnapPointDetents,\n currentY: number,\n direction: -1 | 1,\n ): number {\n const foundIndex = snapPointDetents.indexOf(currentY);\n switch (direction) {\n case -1:\n return snapPointDetents[foundIndex + 1] ?? snapPointDetents[snapPointDetents.length - 1];\n case 1:\n return snapPointDetents[foundIndex - 1] ?? snapPointDetents[0];\n }\n }\n\n private static getClosestSnapPoint(snapPointDetents: SnapPointDetents, currentY: number) {\n let closest = snapPointDetents[0];\n let minDifference = Math.abs(snapPointDetents[0] - currentY);\n\n for (let i = 1; i < snapPointDetents.length; i += 1) {\n const difference = Math.abs(snapPointDetents[i] - currentY);\n if (difference < minDifference) {\n closest = snapPointDetents[i];\n minDifference = difference;\n }\n }\n\n return closest;\n }\n}\n"],"names":["noop","clamp","rubberbandIfOutOfBounds","getNearestOverflowAncestor","hasSelectionWithRangeType","UIPanGestureRecognizer","BLOCK_SHEET_BEHAVIOR_DATA_ATTRIBUTE_KEY","DRAG_THRESHOLDS","DYNAMIC_SNAP_POINT_DATA","SNAP_POINT_DETENTS","BottomSheetController","init","snapPoint","isInitialized","unit","currentSnapPoint","IDLE_POINT_VALUE","snapPointDetents","MIN","initial","detents","destroy","pannedEl","sheetTransitionController","cleanup","backdropTransitionController","disableVerticalScrollBouncingDispose","panStart","event","panState","target","panGestureRecognizer","setStartCoords","panMove","setInitialTimeOnce","setEndCoords","preventUntilPanGestureBecomesExpected","preventImmediatelyIfPannedElIsNotValid","preventUntilVerticalScrollingOnSheetScrollElBecomesExpected","preventImmediatelyIfVerticalScrollingOnPannedElIsScrolled","sheetHeight","sheetEl","offsetHeight","disableVerticalScrollBouncingIfNeeded","sheetScrollEl","isDynamicSnapPoint","COMPUTED_INDEX","y1","y2","nextSnapPoint","LARGE","calculateSnapPoint","panEnd","prevCurrentSnapPoint","getSnapPointTo","onSnapPointChange","reset","immediately","rafId","cancelAnimationFrame","enableTransition","onDismiss","backdropOpacity","requestAnimationFrame","disableTransition","set","cleanupOnTransitionEnd","unset","closestSnapPoint","getClosestSnapPoint","panDirection","direction","axis","velocity","Math","abs","y","VELOCITY","closestSnapPointByDirection","getClosestSnapPointByDirection","distance","DISTANCE_FOR_MOVING_START","closest","contains","scrollHeight","clientHeight","scrollTop","isLastSnapPointDetents","overflowAncestor","targetEl","scrollbarWidth","offsetWidth","clientWidth","Object","assign","style","paddingInlineEnd","overflowY","boxSizing","dispose","currentY","length","foundIndex","indexOf","minDifference","i","difference"],"mappings":"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"}
|