@vkontakte/vkui 6.7.3 → 6.7.4
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/cjs/components/BaseGallery/BaseGallery.d.ts.map +1 -1
- package/dist/cjs/components/BaseGallery/BaseGallery.js +5 -2
- package/dist/cjs/components/BaseGallery/BaseGallery.js.map +1 -1
- package/dist/cjs/components/Calendar/Calendar.d.ts +6 -6
- package/dist/cjs/components/Calendar/Calendar.d.ts.map +1 -1
- package/dist/cjs/components/Calendar/Calendar.js +25 -5
- package/dist/cjs/components/Calendar/Calendar.js.map +1 -1
- package/dist/cjs/components/CalendarDay/CalendarDay.d.ts +4 -1
- package/dist/cjs/components/CalendarDay/CalendarDay.d.ts.map +1 -1
- package/dist/cjs/components/CalendarDay/CalendarDay.js +5 -3
- package/dist/cjs/components/CalendarDay/CalendarDay.js.map +1 -1
- package/dist/cjs/components/CalendarDays/CalendarDays.d.ts +6 -3
- package/dist/cjs/components/CalendarDays/CalendarDays.d.ts.map +1 -1
- package/dist/cjs/components/CalendarDays/CalendarDays.js +5 -3
- package/dist/cjs/components/CalendarDays/CalendarDays.js.map +1 -1
- package/dist/cjs/components/CalendarHeader/CalendarHeader.d.ts +8 -2
- package/dist/cjs/components/CalendarHeader/CalendarHeader.d.ts.map +1 -1
- package/dist/cjs/components/CalendarHeader/CalendarHeader.js +14 -6
- package/dist/cjs/components/CalendarHeader/CalendarHeader.js.map +1 -1
- package/dist/cjs/components/CalendarRange/CalendarRange.d.ts +8 -4
- package/dist/cjs/components/CalendarRange/CalendarRange.d.ts.map +1 -1
- package/dist/cjs/components/CalendarRange/CalendarRange.js +13 -8
- package/dist/cjs/components/CalendarRange/CalendarRange.js.map +1 -1
- package/dist/cjs/components/CalendarTime/CalendarTime.d.ts +9 -2
- package/dist/cjs/components/CalendarTime/CalendarTime.d.ts.map +1 -1
- package/dist/cjs/components/CalendarTime/CalendarTime.js +10 -5
- package/dist/cjs/components/CalendarTime/CalendarTime.js.map +1 -1
- package/dist/cjs/components/Clickable/useState.d.ts +1 -1
- package/dist/cjs/components/Clickable/useState.d.ts.map +1 -1
- package/dist/cjs/components/Clickable/useState.js +12 -19
- package/dist/cjs/components/Clickable/useState.js.map +1 -1
- package/dist/cjs/components/DateInput/DateInput.d.ts +12 -3
- package/dist/cjs/components/DateInput/DateInput.d.ts.map +1 -1
- package/dist/cjs/components/DateInput/DateInput.js +26 -11
- package/dist/cjs/components/DateInput/DateInput.js.map +1 -1
- package/dist/cjs/components/DateRangeInput/DateRangeInput.d.ts +15 -3
- package/dist/cjs/components/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/cjs/components/DateRangeInput/DateRangeInput.js +22 -11
- package/dist/cjs/components/DateRangeInput/DateRangeInput.js.map +1 -1
- package/dist/cjs/components/FocusTrap/FocusTrap.d.ts +1 -1
- package/dist/cjs/components/FocusTrap/FocusTrap.d.ts.map +1 -1
- package/dist/cjs/components/FocusTrap/FocusTrap.js +50 -41
- package/dist/cjs/components/FocusTrap/FocusTrap.js.map +1 -1
- package/dist/cjs/components/Gallery/Gallery.d.ts +1 -1
- package/dist/cjs/components/Gallery/Gallery.d.ts.map +1 -1
- package/dist/cjs/components/Gallery/Gallery.js +12 -3
- package/dist/cjs/components/Gallery/Gallery.js.map +1 -1
- package/dist/cjs/components/Gallery/hooks.d.ts +9 -1
- package/dist/cjs/components/Gallery/hooks.d.ts.map +1 -1
- package/dist/cjs/components/Gallery/hooks.js +43 -25
- package/dist/cjs/components/Gallery/hooks.js.map +1 -1
- package/dist/cjs/components/HorizontalScroll/HorizontalScroll.d.ts.map +1 -1
- package/dist/cjs/components/HorizontalScroll/HorizontalScroll.js +19 -26
- package/dist/cjs/components/HorizontalScroll/HorizontalScroll.js.map +1 -1
- package/dist/cjs/components/Popover/Popover.js +1 -1
- package/dist/cjs/components/Popover/Popover.js.map +1 -1
- package/dist/cjs/hooks/useDateInput.d.ts +2 -1
- package/dist/cjs/hooks/useDateInput.d.ts.map +1 -1
- package/dist/cjs/hooks/useDateInput.js +29 -9
- package/dist/cjs/hooks/useDateInput.js.map +1 -1
- package/dist/cjs/lib/floating/customResizeObserver.d.ts.map +1 -1
- package/dist/cjs/lib/floating/customResizeObserver.js +0 -1
- package/dist/cjs/lib/floating/customResizeObserver.js.map +1 -1
- package/dist/cjs/lib/floating/types/component.d.ts +2 -2
- package/dist/cjs/lib/floating/types/component.d.ts.map +1 -1
- package/dist/cjs/lib/floating/useFloatingWithInteractions/index.d.ts +1 -0
- package/dist/cjs/lib/floating/useFloatingWithInteractions/index.d.ts.map +1 -1
- package/dist/cjs/lib/floating/useFloatingWithInteractions/index.js.map +1 -1
- package/dist/cjs/lib/floating/useFloatingWithInteractions/types.d.ts +2 -1
- package/dist/cjs/lib/floating/useFloatingWithInteractions/types.d.ts.map +1 -1
- package/dist/cjs/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.d.ts.map +1 -1
- package/dist/cjs/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js +14 -1
- package/dist/cjs/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js.map +1 -1
- package/dist/components/BaseGallery/BaseGallery.d.ts.map +1 -1
- package/dist/components/BaseGallery/BaseGallery.js +5 -2
- package/dist/components/BaseGallery/BaseGallery.js.map +1 -1
- package/dist/components/Calendar/Calendar.d.ts +6 -6
- package/dist/components/Calendar/Calendar.d.ts.map +1 -1
- package/dist/components/Calendar/Calendar.js +25 -5
- package/dist/components/Calendar/Calendar.js.map +1 -1
- package/dist/components/CalendarDay/CalendarDay.d.ts +4 -1
- package/dist/components/CalendarDay/CalendarDay.d.ts.map +1 -1
- package/dist/components/CalendarDay/CalendarDay.js +5 -3
- package/dist/components/CalendarDay/CalendarDay.js.map +1 -1
- package/dist/components/CalendarDays/CalendarDays.d.ts +6 -3
- package/dist/components/CalendarDays/CalendarDays.d.ts.map +1 -1
- package/dist/components/CalendarDays/CalendarDays.js +5 -3
- package/dist/components/CalendarDays/CalendarDays.js.map +1 -1
- package/dist/components/CalendarHeader/CalendarHeader.d.ts +8 -2
- package/dist/components/CalendarHeader/CalendarHeader.d.ts.map +1 -1
- package/dist/components/CalendarHeader/CalendarHeader.js +14 -6
- package/dist/components/CalendarHeader/CalendarHeader.js.map +1 -1
- package/dist/components/CalendarRange/CalendarRange.d.ts +8 -4
- package/dist/components/CalendarRange/CalendarRange.d.ts.map +1 -1
- package/dist/components/CalendarRange/CalendarRange.js +13 -8
- package/dist/components/CalendarRange/CalendarRange.js.map +1 -1
- package/dist/components/CalendarTime/CalendarTime.d.ts +9 -2
- package/dist/components/CalendarTime/CalendarTime.d.ts.map +1 -1
- package/dist/components/CalendarTime/CalendarTime.js +10 -5
- package/dist/components/CalendarTime/CalendarTime.js.map +1 -1
- package/dist/components/Clickable/useState.d.ts +1 -1
- package/dist/components/Clickable/useState.d.ts.map +1 -1
- package/dist/components/Clickable/useState.js +12 -19
- package/dist/components/Clickable/useState.js.map +1 -1
- package/dist/components/DateInput/DateInput.d.ts +12 -3
- package/dist/components/DateInput/DateInput.d.ts.map +1 -1
- package/dist/components/DateInput/DateInput.js +26 -11
- package/dist/components/DateInput/DateInput.js.map +1 -1
- package/dist/components/DateRangeInput/DateRangeInput.d.ts +15 -3
- package/dist/components/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/components/DateRangeInput/DateRangeInput.js +22 -11
- package/dist/components/DateRangeInput/DateRangeInput.js.map +1 -1
- package/dist/components/FocusTrap/FocusTrap.d.ts +1 -1
- package/dist/components/FocusTrap/FocusTrap.d.ts.map +1 -1
- package/dist/components/FocusTrap/FocusTrap.js +51 -42
- package/dist/components/FocusTrap/FocusTrap.js.map +1 -1
- package/dist/components/Gallery/Gallery.d.ts +1 -1
- package/dist/components/Gallery/Gallery.d.ts.map +1 -1
- package/dist/components/Gallery/Gallery.js +12 -3
- package/dist/components/Gallery/Gallery.js.map +1 -1
- package/dist/components/Gallery/hooks.d.ts +9 -1
- package/dist/components/Gallery/hooks.d.ts.map +1 -1
- package/dist/components/Gallery/hooks.js +43 -25
- package/dist/components/Gallery/hooks.js.map +1 -1
- package/dist/components/HorizontalScroll/HorizontalScroll.d.ts.map +1 -1
- package/dist/components/HorizontalScroll/HorizontalScroll.js +20 -27
- package/dist/components/HorizontalScroll/HorizontalScroll.js.map +1 -1
- package/dist/components/Popover/Popover.js +1 -1
- package/dist/components/Popover/Popover.js.map +1 -1
- package/dist/components.css +1 -1
- package/dist/components.css.map +1 -1
- package/dist/components.js.tmp +374 -212
- package/dist/cssm/components/BaseGallery/BaseGallery.d.ts.map +1 -1
- package/dist/cssm/components/BaseGallery/BaseGallery.js +3 -1
- package/dist/cssm/components/BaseGallery/BaseGallery.js.map +1 -1
- package/dist/cssm/components/Calendar/Calendar.d.ts +6 -6
- package/dist/cssm/components/Calendar/Calendar.d.ts.map +1 -1
- package/dist/cssm/components/Calendar/Calendar.js +14 -4
- package/dist/cssm/components/Calendar/Calendar.js.map +1 -1
- package/dist/cssm/components/CalendarDay/CalendarDay.d.ts +4 -1
- package/dist/cssm/components/CalendarDay/CalendarDay.d.ts.map +1 -1
- package/dist/cssm/components/CalendarDay/CalendarDay.js +2 -1
- package/dist/cssm/components/CalendarDay/CalendarDay.js.map +1 -1
- package/dist/cssm/components/CalendarDays/CalendarDays.d.ts +6 -3
- package/dist/cssm/components/CalendarDays/CalendarDays.d.ts.map +1 -1
- package/dist/cssm/components/CalendarDays/CalendarDays.js +2 -1
- package/dist/cssm/components/CalendarDays/CalendarDays.js.map +1 -1
- package/dist/cssm/components/CalendarHeader/CalendarHeader.d.ts +8 -2
- package/dist/cssm/components/CalendarHeader/CalendarHeader.d.ts.map +1 -1
- package/dist/cssm/components/CalendarHeader/CalendarHeader.js +7 -3
- package/dist/cssm/components/CalendarHeader/CalendarHeader.js.map +1 -1
- package/dist/cssm/components/CalendarRange/CalendarRange.d.ts +8 -4
- package/dist/cssm/components/CalendarRange/CalendarRange.d.ts.map +1 -1
- package/dist/cssm/components/CalendarRange/CalendarRange.js +9 -5
- package/dist/cssm/components/CalendarRange/CalendarRange.js.map +1 -1
- package/dist/cssm/components/CalendarTime/CalendarTime.d.ts +9 -2
- package/dist/cssm/components/CalendarTime/CalendarTime.d.ts.map +1 -1
- package/dist/cssm/components/CalendarTime/CalendarTime.js +10 -5
- package/dist/cssm/components/CalendarTime/CalendarTime.js.map +1 -1
- package/dist/cssm/components/CalendarTime/CalendarTime.module.css +4 -0
- package/dist/cssm/components/Clickable/useState.d.ts +1 -1
- package/dist/cssm/components/Clickable/useState.d.ts.map +1 -1
- package/dist/cssm/components/Clickable/useState.js +10 -11
- package/dist/cssm/components/Clickable/useState.js.map +1 -1
- package/dist/cssm/components/DateInput/DateInput.d.ts +12 -3
- package/dist/cssm/components/DateInput/DateInput.d.ts.map +1 -1
- package/dist/cssm/components/DateInput/DateInput.js +18 -9
- package/dist/cssm/components/DateInput/DateInput.js.map +1 -1
- package/dist/cssm/components/DateRangeInput/DateRangeInput.d.ts +15 -3
- package/dist/cssm/components/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/cssm/components/DateRangeInput/DateRangeInput.js +17 -9
- package/dist/cssm/components/DateRangeInput/DateRangeInput.js.map +1 -1
- package/dist/cssm/components/FocusTrap/FocusTrap.d.ts +1 -1
- package/dist/cssm/components/FocusTrap/FocusTrap.d.ts.map +1 -1
- package/dist/cssm/components/FocusTrap/FocusTrap.js +51 -42
- package/dist/cssm/components/FocusTrap/FocusTrap.js.map +1 -1
- package/dist/cssm/components/Gallery/Gallery.d.ts +1 -1
- package/dist/cssm/components/Gallery/Gallery.d.ts.map +1 -1
- package/dist/cssm/components/Gallery/Gallery.js +9 -2
- package/dist/cssm/components/Gallery/Gallery.js.map +1 -1
- package/dist/cssm/components/Gallery/hooks.d.ts +9 -1
- package/dist/cssm/components/Gallery/hooks.d.ts.map +1 -1
- package/dist/cssm/components/Gallery/hooks.js +43 -25
- package/dist/cssm/components/Gallery/hooks.js.map +1 -1
- package/dist/cssm/components/HorizontalScroll/HorizontalScroll.d.ts.map +1 -1
- package/dist/cssm/components/HorizontalScroll/HorizontalScroll.js +20 -27
- package/dist/cssm/components/HorizontalScroll/HorizontalScroll.js.map +1 -1
- package/dist/cssm/components/Popover/Popover.js +1 -1
- package/dist/cssm/components/Popover/Popover.js.map +1 -1
- package/dist/cssm/hooks/useDateInput.d.ts +2 -1
- package/dist/cssm/hooks/useDateInput.d.ts.map +1 -1
- package/dist/cssm/hooks/useDateInput.js +30 -9
- package/dist/cssm/hooks/useDateInput.js.map +1 -1
- package/dist/cssm/lib/floating/customResizeObserver.d.ts.map +1 -1
- package/dist/cssm/lib/floating/customResizeObserver.js +0 -1
- package/dist/cssm/lib/floating/customResizeObserver.js.map +1 -1
- package/dist/cssm/lib/floating/types/component.d.ts +2 -2
- package/dist/cssm/lib/floating/types/component.d.ts.map +1 -1
- package/dist/cssm/lib/floating/types/component.js.map +1 -1
- package/dist/cssm/lib/floating/useFloatingWithInteractions/index.d.ts +1 -0
- package/dist/cssm/lib/floating/useFloatingWithInteractions/index.d.ts.map +1 -1
- package/dist/cssm/lib/floating/useFloatingWithInteractions/index.js.map +1 -1
- package/dist/cssm/lib/floating/useFloatingWithInteractions/types.d.ts +2 -1
- package/dist/cssm/lib/floating/useFloatingWithInteractions/types.d.ts.map +1 -1
- package/dist/cssm/lib/floating/useFloatingWithInteractions/types.js.map +1 -1
- package/dist/cssm/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.d.ts.map +1 -1
- package/dist/cssm/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js +14 -1
- package/dist/cssm/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js.map +1 -1
- package/dist/hooks/useDateInput.d.ts +2 -1
- package/dist/hooks/useDateInput.d.ts.map +1 -1
- package/dist/hooks/useDateInput.js +30 -9
- package/dist/hooks/useDateInput.js.map +1 -1
- package/dist/lib/floating/customResizeObserver.d.ts.map +1 -1
- package/dist/lib/floating/customResizeObserver.js +0 -1
- package/dist/lib/floating/customResizeObserver.js.map +1 -1
- package/dist/lib/floating/types/component.d.ts +2 -2
- package/dist/lib/floating/types/component.d.ts.map +1 -1
- package/dist/lib/floating/types/component.js.map +1 -1
- package/dist/lib/floating/useFloatingWithInteractions/index.d.ts +1 -0
- package/dist/lib/floating/useFloatingWithInteractions/index.d.ts.map +1 -1
- package/dist/lib/floating/useFloatingWithInteractions/index.js.map +1 -1
- package/dist/lib/floating/useFloatingWithInteractions/types.d.ts +2 -1
- package/dist/lib/floating/useFloatingWithInteractions/types.d.ts.map +1 -1
- package/dist/lib/floating/useFloatingWithInteractions/types.js.map +1 -1
- package/dist/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.d.ts.map +1 -1
- package/dist/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js +14 -1
- package/dist/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js.map +1 -1
- package/dist/vkui.css +1 -1
- package/dist/vkui.css.map +1 -1
- package/dist/vkui.js.tmp +374 -212
- package/package.json +1 -1
- package/src/components/BaseGallery/BaseGallery.tsx +8 -1
- package/src/components/Calendar/Calendar.tsx +49 -6
- package/src/components/CalendarDay/CalendarDay.tsx +7 -1
- package/src/components/CalendarDays/CalendarDays.tsx +9 -1
- package/src/components/CalendarHeader/CalendarHeader.tsx +21 -1
- package/src/components/CalendarRange/CalendarRange.tsx +24 -3
- package/src/components/CalendarTime/CalendarTime.module.css +4 -0
- package/src/components/CalendarTime/CalendarTime.tsx +39 -10
- package/src/components/Clickable/useState.tsx +30 -27
- package/src/components/DateInput/DateInput.tsx +32 -3
- package/src/components/DateRangeInput/DateRangeInput.tsx +28 -1
- package/src/components/FocusTrap/FocusTrap.tsx +75 -45
- package/src/components/Gallery/Gallery.tsx +10 -1
- package/src/components/Gallery/hooks.ts +49 -33
- package/src/components/HorizontalScroll/HorizontalScroll.tsx +23 -28
- package/src/components/Popover/Popover.tsx +1 -1
- package/src/hooks/useDateInput.ts +23 -6
- package/src/lib/floating/customResizeObserver.ts +0 -1
- package/src/lib/floating/types/component.ts +2 -1
- package/src/lib/floating/useFloatingWithInteractions/index.ts +2 -0
- package/src/lib/floating/useFloatingWithInteractions/types.ts +3 -1
- package/src/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.ts +15 -3
|
@@ -2,7 +2,7 @@ import { type AllHTMLAttributes } from 'react';
|
|
|
2
2
|
import type { HasComponent, HasRootRef } from '../../types';
|
|
3
3
|
export interface FocusTrapProps<T extends HTMLElement = HTMLElement> extends Omit<AllHTMLAttributes<T>, 'autoFocus'>, HasRootRef<T>, HasComponent {
|
|
4
4
|
autoFocus?: boolean | 'root';
|
|
5
|
-
restoreFocus?: boolean | (() => boolean);
|
|
5
|
+
restoreFocus?: boolean | (() => boolean | HTMLElement);
|
|
6
6
|
mount?: boolean;
|
|
7
7
|
timeout?: number;
|
|
8
8
|
onClose?: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FocusTrap.d.ts","sourceRoot":"","sources":["../../../src/components/FocusTrap/FocusTrap.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,
|
|
1
|
+
{"version":3,"file":"FocusTrap.d.ts","sourceRoot":"","sources":["../../../src/components/FocusTrap/FocusTrap.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAoC,MAAM,OAAO,CAAC;AAcjF,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAqE5D,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,CACjE,SAAQ,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,EAC7C,UAAU,CAAC,CAAC,CAAC,EACb,YAAY;IACd,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC7B,YAAY,CAAC,EAAE,OAAO,GAAG,CAAC,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC;IACvD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,eAAO,MAAM,SAAS,GAAI,CAAC,SAAS,WAAW,+HAW5C,cAAc,CAAC,CAAC,CAAC,KAAG,KAAK,CAAC,SA4J5B,CAAC"}
|
|
@@ -2,14 +2,58 @@ import { _ as _object_spread } from "@swc/helpers/_/_object_spread";
|
|
|
2
2
|
import { _ as _object_spread_props } from "@swc/helpers/_/_object_spread_props";
|
|
3
3
|
import { _ as _object_without_properties } from "@swc/helpers/_/_object_without_properties";
|
|
4
4
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
5
|
-
import {
|
|
5
|
+
import { useRef, useState } from 'react';
|
|
6
6
|
import { arraysEquals } from '../../helpers/array';
|
|
7
7
|
import { useExternRef } from '../../hooks/useExternRef';
|
|
8
8
|
import { useMutationObserver } from '../../hooks/useMutationObserver';
|
|
9
|
+
import { useStableCallback } from '../../hooks/useStableCallback';
|
|
9
10
|
import { FOCUSABLE_ELEMENTS_LIST, Keys, pressedKey } from '../../lib/accessibility';
|
|
10
11
|
import { contains, getActiveElementByAnotherElement, getWindow, isHTMLElement, useDOM } from '../../lib/dom';
|
|
11
12
|
import { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';
|
|
12
13
|
const FOCUSABLE_ELEMENTS = FOCUSABLE_ELEMENTS_LIST.join();
|
|
14
|
+
const useRestoreFocus = ({ restoreFocus, timeout, mount, ref })=>{
|
|
15
|
+
const restoreFocusRef = useRef(restoreFocus);
|
|
16
|
+
restoreFocusRef.current = restoreFocus;
|
|
17
|
+
const [restoreFocusTo, setRestoreFocusTo] = useState(null);
|
|
18
|
+
const restoreFocusImpl = useStableCallback(()=>{
|
|
19
|
+
const shouldRestoreFocus = typeof restoreFocusRef.current === 'function' ? restoreFocusRef.current() : restoreFocusRef.current;
|
|
20
|
+
if (!shouldRestoreFocus) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
setTimeout(()=>{
|
|
24
|
+
const restoreFocusElement = isHTMLElement(shouldRestoreFocus) && shouldRestoreFocus || isHTMLElement(restoreFocusTo) && restoreFocusTo || null;
|
|
25
|
+
if (restoreFocusElement) {
|
|
26
|
+
restoreFocusElement.focus();
|
|
27
|
+
setRestoreFocusTo(null);
|
|
28
|
+
}
|
|
29
|
+
}, timeout);
|
|
30
|
+
});
|
|
31
|
+
useIsomorphicLayoutEffect(function calculateRestoreFocusTo() {
|
|
32
|
+
if (!ref.current || !restoreFocusRef.current || !mount) {
|
|
33
|
+
setRestoreFocusTo(null);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
setRestoreFocusTo(getActiveElementByAnotherElement(ref.current));
|
|
37
|
+
}, [
|
|
38
|
+
ref,
|
|
39
|
+
mount
|
|
40
|
+
]);
|
|
41
|
+
useIsomorphicLayoutEffect(function tryToRestoreFocusOnUnmount() {
|
|
42
|
+
return ()=>{
|
|
43
|
+
restoreFocusImpl();
|
|
44
|
+
};
|
|
45
|
+
}, [
|
|
46
|
+
restoreFocusImpl
|
|
47
|
+
]);
|
|
48
|
+
useIsomorphicLayoutEffect(function tryToRestoreFocusWhenFakeUnmount() {
|
|
49
|
+
if (!mount) {
|
|
50
|
+
restoreFocusImpl();
|
|
51
|
+
}
|
|
52
|
+
}, [
|
|
53
|
+
mount,
|
|
54
|
+
restoreFocusImpl
|
|
55
|
+
]);
|
|
56
|
+
};
|
|
13
57
|
/**
|
|
14
58
|
* @see https://vkcom.github.io/VKUI/#/FocusTrap
|
|
15
59
|
*/ export const FocusTrap = (_param)=>{
|
|
@@ -27,7 +71,12 @@ const FOCUSABLE_ELEMENTS = FOCUSABLE_ELEMENTS_LIST.join();
|
|
|
27
71
|
const ref = useExternRef(getRootRef);
|
|
28
72
|
const { document } = useDOM();
|
|
29
73
|
const focusableNodesRef = useRef([]);
|
|
30
|
-
|
|
74
|
+
useRestoreFocus({
|
|
75
|
+
restoreFocus,
|
|
76
|
+
timeout,
|
|
77
|
+
mount,
|
|
78
|
+
ref
|
|
79
|
+
});
|
|
31
80
|
const focusNodeByIndex = (nodeIndex)=>{
|
|
32
81
|
const element = focusableNodesRef.current[nodeIndex];
|
|
33
82
|
if (element) {
|
|
@@ -99,46 +148,6 @@ const FOCUSABLE_ELEMENTS = FOCUSABLE_ELEMENTS_LIST.join();
|
|
|
99
148
|
timeout,
|
|
100
149
|
disabled
|
|
101
150
|
]);
|
|
102
|
-
const restoreFocusImpl = useCallback(()=>{
|
|
103
|
-
const shouldRestoreFocus = typeof restoreFocus === 'function' ? restoreFocus() : restoreFocus;
|
|
104
|
-
if (!restoreFocusTo || !isHTMLElement(restoreFocusTo) || !shouldRestoreFocus) {
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
setTimeout(()=>{
|
|
108
|
-
if (restoreFocusTo) {
|
|
109
|
-
restoreFocusTo.focus();
|
|
110
|
-
setRestoreFocusTo(null);
|
|
111
|
-
}
|
|
112
|
-
}, timeout);
|
|
113
|
-
}, [
|
|
114
|
-
restoreFocus,
|
|
115
|
-
restoreFocusTo,
|
|
116
|
-
timeout
|
|
117
|
-
]);
|
|
118
|
-
useIsomorphicLayoutEffect(function calculateRestoreFocusTo() {
|
|
119
|
-
if (!ref.current || !restoreFocus || !mount) {
|
|
120
|
-
setRestoreFocusTo(null);
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
setRestoreFocusTo(getActiveElementByAnotherElement(ref.current));
|
|
124
|
-
}, [
|
|
125
|
-
ref,
|
|
126
|
-
mount,
|
|
127
|
-
restoreFocus
|
|
128
|
-
]);
|
|
129
|
-
useIsomorphicLayoutEffect(function tryToRestoreFocusOnUnmount() {
|
|
130
|
-
return ()=>restoreFocusImpl();
|
|
131
|
-
}, [
|
|
132
|
-
restoreFocusImpl
|
|
133
|
-
]);
|
|
134
|
-
useIsomorphicLayoutEffect(function tryToRestoreFocusWhenFakeUnmount() {
|
|
135
|
-
if (!mount) {
|
|
136
|
-
restoreFocusImpl();
|
|
137
|
-
}
|
|
138
|
-
}, [
|
|
139
|
-
mount,
|
|
140
|
-
restoreFocusImpl
|
|
141
|
-
]);
|
|
142
151
|
useIsomorphicLayoutEffect(()=>{
|
|
143
152
|
if (!ref.current) {
|
|
144
153
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/FocusTrap/FocusTrap.tsx"],"sourcesContent":["import { type AllHTMLAttributes, useCallback, useRef, useState } from 'react';\nimport { arraysEquals } from '../../helpers/array';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { useMutationObserver } from '../../hooks/useMutationObserver';\nimport { FOCUSABLE_ELEMENTS_LIST, Keys, pressedKey } from '../../lib/accessibility';\nimport {\n contains,\n getActiveElementByAnotherElement,\n getWindow,\n isHTMLElement,\n useDOM,\n} from '../../lib/dom';\nimport { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';\nimport type { HasComponent, HasRootRef } from '../../types';\n\nconst FOCUSABLE_ELEMENTS: string = FOCUSABLE_ELEMENTS_LIST.join();\nexport interface FocusTrapProps<T extends HTMLElement = HTMLElement>\n extends Omit<AllHTMLAttributes<T>, 'autoFocus'>,\n HasRootRef<T>,\n HasComponent {\n autoFocus?: boolean | 'root';\n restoreFocus?: boolean | (() => boolean);\n mount?: boolean;\n timeout?: number;\n onClose?: () => void;\n /**\n * Форсированное отключение захвата фокуса\n */\n disabled?: boolean;\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/FocusTrap\n */\nexport const FocusTrap = <T extends HTMLElement = HTMLElement>({\n Component = 'div',\n onClose,\n autoFocus = true,\n restoreFocus = true,\n disabled = false,\n mount = true,\n timeout = 0,\n getRootRef,\n children,\n ...restProps\n}: FocusTrapProps<T>): React.ReactNode => {\n const ref = useExternRef<T>(getRootRef);\n const { document } = useDOM();\n\n const focusableNodesRef = useRef<HTMLElement[]>([]);\n\n const [restoreFocusTo, setRestoreFocusTo] = useState<Element | null>(null);\n\n const focusNodeByIndex = (nodeIndex: number) => {\n const element = focusableNodesRef.current[nodeIndex];\n\n if (element) {\n element.focus({\n preventScroll: true,\n });\n }\n };\n\n const recalculateFocusableNodesRef = (parentNode: HTMLElement) => {\n // eslint-disable-next-line no-restricted-properties\n const newFocusableElements = parentNode.querySelectorAll<HTMLElement>(FOCUSABLE_ELEMENTS);\n\n const nodes: HTMLElement[] = [];\n newFocusableElements.forEach((focusableEl) => {\n const { display, visibility } = getComputedStyle(focusableEl);\n if (display !== 'none' && visibility !== 'hidden') {\n nodes.push(focusableEl);\n }\n });\n if (nodes.length === 0) {\n // Чтобы фокус был хотя бы на родителе\n nodes.push(parentNode);\n }\n focusableNodesRef.current = nodes;\n };\n\n const onMutateParentHandler = (parentNode: HTMLElement) => {\n const oldFocusableNodes = [...focusableNodesRef.current];\n\n recalculateFocusableNodesRef(parentNode);\n\n if (!autoFocus || arraysEquals(oldFocusableNodes, focusableNodesRef.current)) {\n return;\n }\n\n if (document) {\n const activeElement = document.activeElement as HTMLElement;\n const currentElementIndex = Math.max(\n document.activeElement ? focusableNodesRef.current.indexOf(activeElement) : -1,\n 0,\n );\n focusNodeByIndex(currentElementIndex);\n }\n };\n\n useMutationObserver(ref, () => ref.current && onMutateParentHandler(ref.current));\n\n useIsomorphicLayoutEffect(() => {\n ref.current && recalculateFocusableNodesRef(ref.current);\n }, [ref]);\n\n useIsomorphicLayoutEffect(\n function tryToAutoFocusToFirstNode() {\n if (!ref.current || !autoFocus || disabled) {\n return;\n }\n\n const autoFocusToNode = () => {\n if (!ref.current || !focusableNodesRef.current.length) {\n return;\n }\n const activeElement = getActiveElementByAnotherElement(ref.current);\n if (!contains(ref.current, activeElement)) {\n if (autoFocus === 'root') {\n ref.current?.focus();\n } else {\n focusableNodesRef.current[0].focus();\n }\n }\n };\n const timeoutId = setTimeout(autoFocusToNode, timeout);\n return () => {\n clearTimeout(timeoutId);\n };\n },\n [autoFocus, timeout, disabled],\n );\n\n const restoreFocusImpl = useCallback(() => {\n const shouldRestoreFocus = typeof restoreFocus === 'function' ? restoreFocus() : restoreFocus;\n\n if (!restoreFocusTo || !isHTMLElement(restoreFocusTo) || !shouldRestoreFocus) {\n return;\n }\n\n setTimeout(() => {\n if (restoreFocusTo) {\n restoreFocusTo.focus();\n setRestoreFocusTo(null);\n }\n }, timeout);\n }, [restoreFocus, restoreFocusTo, timeout]);\n\n useIsomorphicLayoutEffect(\n function calculateRestoreFocusTo() {\n if (!ref.current || !restoreFocus || !mount) {\n setRestoreFocusTo(null);\n return;\n }\n setRestoreFocusTo(getActiveElementByAnotherElement(ref.current));\n },\n [ref, mount, restoreFocus],\n );\n\n useIsomorphicLayoutEffect(\n function tryToRestoreFocusOnUnmount() {\n return () => restoreFocusImpl();\n },\n [restoreFocusImpl],\n );\n\n useIsomorphicLayoutEffect(\n function tryToRestoreFocusWhenFakeUnmount() {\n if (!mount) {\n restoreFocusImpl();\n }\n },\n [mount, restoreFocusImpl],\n );\n\n useIsomorphicLayoutEffect(() => {\n if (!ref.current) {\n return;\n }\n\n const onDocumentKeydown = (event: KeyboardEvent) => {\n if (disabled) {\n return;\n }\n\n const pressedKeyResult = pressedKey(event);\n\n switch (pressedKeyResult) {\n case Keys.TAB: {\n if (!focusableNodesRef.current.length) {\n return false;\n }\n\n const lastIdx = focusableNodesRef.current.length - 1;\n const targetIdx = focusableNodesRef.current.findIndex((node) => node === event.target);\n\n const shouldFocusFirstNode =\n targetIdx === -1 || (targetIdx === lastIdx && !event.shiftKey);\n\n if (shouldFocusFirstNode || (targetIdx === 0 && event.shiftKey)) {\n event.preventDefault();\n\n const node = focusableNodesRef.current[shouldFocusFirstNode ? 0 : lastIdx];\n\n if (node !== getActiveElementByAnotherElement(node)) {\n node.focus();\n }\n\n return false;\n }\n\n break;\n }\n case Keys.ESCAPE: {\n if (onClose) {\n event.preventDefault();\n onClose();\n }\n }\n }\n\n return true;\n };\n\n const doc = getWindow(ref.current).document;\n doc.addEventListener('keydown', onDocumentKeydown, {\n capture: true,\n });\n return () => {\n doc.removeEventListener('keydown', onDocumentKeydown, true);\n };\n }, [onClose, ref, disabled]);\n\n return (\n <Component tabIndex={-1} ref={ref} {...restProps}>\n {children}\n </Component>\n );\n};\n"],"names":["useCallback","useRef","useState","arraysEquals","useExternRef","useMutationObserver","FOCUSABLE_ELEMENTS_LIST","Keys","pressedKey","contains","getActiveElementByAnotherElement","getWindow","isHTMLElement","useDOM","useIsomorphicLayoutEffect","FOCUSABLE_ELEMENTS","join","FocusTrap","Component","onClose","autoFocus","restoreFocus","disabled","mount","timeout","getRootRef","children","restProps","ref","document","focusableNodesRef","restoreFocusTo","setRestoreFocusTo","focusNodeByIndex","nodeIndex","element","current","focus","preventScroll","recalculateFocusableNodesRef","parentNode","newFocusableElements","querySelectorAll","nodes","forEach","focusableEl","display","visibility","getComputedStyle","push","length","onMutateParentHandler","oldFocusableNodes","activeElement","currentElementIndex","Math","max","indexOf","tryToAutoFocusToFirstNode","autoFocusToNode","timeoutId","setTimeout","clearTimeout","restoreFocusImpl","shouldRestoreFocus","calculateRestoreFocusTo","tryToRestoreFocusOnUnmount","tryToRestoreFocusWhenFakeUnmount","onDocumentKeydown","event","pressedKeyResult","TAB","lastIdx","targetIdx","findIndex","node","target","shouldFocusFirstNode","shiftKey","preventDefault","ESCAPE","doc","addEventListener","capture","removeEventListener","tabIndex"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/FocusTrap/FocusTrap.tsx"],"sourcesContent":["import { type AllHTMLAttributes, type RefObject, useRef, useState } from 'react';\nimport { arraysEquals } from '../../helpers/array';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { useMutationObserver } from '../../hooks/useMutationObserver';\nimport { useStableCallback } from '../../hooks/useStableCallback';\nimport { FOCUSABLE_ELEMENTS_LIST, Keys, pressedKey } from '../../lib/accessibility';\nimport {\n contains,\n getActiveElementByAnotherElement,\n getWindow,\n isHTMLElement,\n useDOM,\n} from '../../lib/dom';\nimport { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';\nimport type { HasComponent, HasRootRef } from '../../types';\n\nconst FOCUSABLE_ELEMENTS: string = FOCUSABLE_ELEMENTS_LIST.join();\n\nconst useRestoreFocus = ({\n restoreFocus,\n timeout,\n mount,\n ref,\n}: Pick<FocusTrapProps, 'restoreFocus' | 'timeout' | 'mount'> & {\n ref: RefObject<HTMLElement | null>;\n}) => {\n const restoreFocusRef = useRef(restoreFocus);\n restoreFocusRef.current = restoreFocus;\n const [restoreFocusTo, setRestoreFocusTo] = useState<Element | null>(null);\n\n const restoreFocusImpl = useStableCallback(() => {\n const shouldRestoreFocus =\n typeof restoreFocusRef.current === 'function'\n ? restoreFocusRef.current()\n : restoreFocusRef.current;\n\n if (!shouldRestoreFocus) {\n return;\n }\n\n setTimeout(() => {\n const restoreFocusElement =\n (isHTMLElement(shouldRestoreFocus) && shouldRestoreFocus) ||\n (isHTMLElement(restoreFocusTo) && restoreFocusTo) ||\n null;\n\n if (restoreFocusElement) {\n restoreFocusElement.focus();\n setRestoreFocusTo(null);\n }\n }, timeout);\n });\n\n useIsomorphicLayoutEffect(\n function calculateRestoreFocusTo() {\n if (!ref.current || !restoreFocusRef.current || !mount) {\n setRestoreFocusTo(null);\n return;\n }\n setRestoreFocusTo(getActiveElementByAnotherElement(ref.current));\n },\n [ref, mount],\n );\n\n useIsomorphicLayoutEffect(\n function tryToRestoreFocusOnUnmount() {\n return () => {\n restoreFocusImpl();\n };\n },\n [restoreFocusImpl],\n );\n\n useIsomorphicLayoutEffect(\n function tryToRestoreFocusWhenFakeUnmount() {\n if (!mount) {\n restoreFocusImpl();\n }\n },\n [mount, restoreFocusImpl],\n );\n};\n\nexport interface FocusTrapProps<T extends HTMLElement = HTMLElement>\n extends Omit<AllHTMLAttributes<T>, 'autoFocus'>,\n HasRootRef<T>,\n HasComponent {\n autoFocus?: boolean | 'root';\n restoreFocus?: boolean | (() => boolean | HTMLElement);\n mount?: boolean;\n timeout?: number;\n onClose?: () => void;\n /**\n * Форсированное отключение захвата фокуса\n */\n disabled?: boolean;\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/FocusTrap\n */\nexport const FocusTrap = <T extends HTMLElement = HTMLElement>({\n Component = 'div',\n onClose,\n autoFocus = true,\n restoreFocus = true,\n disabled = false,\n mount = true,\n timeout = 0,\n getRootRef,\n children,\n ...restProps\n}: FocusTrapProps<T>): React.ReactNode => {\n const ref = useExternRef<T>(getRootRef);\n const { document } = useDOM();\n\n const focusableNodesRef = useRef<HTMLElement[]>([]);\n\n useRestoreFocus({\n restoreFocus,\n timeout,\n mount,\n ref,\n });\n\n const focusNodeByIndex = (nodeIndex: number) => {\n const element = focusableNodesRef.current[nodeIndex];\n\n if (element) {\n element.focus({\n preventScroll: true,\n });\n }\n };\n\n const recalculateFocusableNodesRef = (parentNode: HTMLElement) => {\n // eslint-disable-next-line no-restricted-properties\n const newFocusableElements = parentNode.querySelectorAll<HTMLElement>(FOCUSABLE_ELEMENTS);\n\n const nodes: HTMLElement[] = [];\n newFocusableElements.forEach((focusableEl) => {\n const { display, visibility } = getComputedStyle(focusableEl);\n if (display !== 'none' && visibility !== 'hidden') {\n nodes.push(focusableEl);\n }\n });\n if (nodes.length === 0) {\n // Чтобы фокус был хотя бы на родителе\n nodes.push(parentNode);\n }\n focusableNodesRef.current = nodes;\n };\n\n const onMutateParentHandler = (parentNode: HTMLElement) => {\n const oldFocusableNodes = [...focusableNodesRef.current];\n\n recalculateFocusableNodesRef(parentNode);\n\n if (!autoFocus || arraysEquals(oldFocusableNodes, focusableNodesRef.current)) {\n return;\n }\n\n if (document) {\n const activeElement = document.activeElement as HTMLElement;\n const currentElementIndex = Math.max(\n document.activeElement ? focusableNodesRef.current.indexOf(activeElement) : -1,\n 0,\n );\n focusNodeByIndex(currentElementIndex);\n }\n };\n\n useMutationObserver(ref, () => ref.current && onMutateParentHandler(ref.current));\n\n useIsomorphicLayoutEffect(() => {\n ref.current && recalculateFocusableNodesRef(ref.current);\n }, [ref]);\n\n useIsomorphicLayoutEffect(\n function tryToAutoFocusToFirstNode() {\n if (!ref.current || !autoFocus || disabled) {\n return;\n }\n\n const autoFocusToNode = () => {\n if (!ref.current || !focusableNodesRef.current.length) {\n return;\n }\n const activeElement = getActiveElementByAnotherElement(ref.current);\n if (!contains(ref.current, activeElement)) {\n if (autoFocus === 'root') {\n ref.current?.focus();\n } else {\n focusableNodesRef.current[0].focus();\n }\n }\n };\n const timeoutId = setTimeout(autoFocusToNode, timeout);\n return () => {\n clearTimeout(timeoutId);\n };\n },\n [autoFocus, timeout, disabled],\n );\n\n useIsomorphicLayoutEffect(() => {\n if (!ref.current) {\n return;\n }\n\n const onDocumentKeydown = (event: KeyboardEvent) => {\n if (disabled) {\n return;\n }\n\n const pressedKeyResult = pressedKey(event);\n\n switch (pressedKeyResult) {\n case Keys.TAB: {\n if (!focusableNodesRef.current.length) {\n return false;\n }\n\n const lastIdx = focusableNodesRef.current.length - 1;\n const targetIdx = focusableNodesRef.current.findIndex((node) => node === event.target);\n\n const shouldFocusFirstNode =\n targetIdx === -1 || (targetIdx === lastIdx && !event.shiftKey);\n\n if (shouldFocusFirstNode || (targetIdx === 0 && event.shiftKey)) {\n event.preventDefault();\n\n const node = focusableNodesRef.current[shouldFocusFirstNode ? 0 : lastIdx];\n\n if (node !== getActiveElementByAnotherElement(node)) {\n node.focus();\n }\n\n return false;\n }\n\n break;\n }\n case Keys.ESCAPE: {\n if (onClose) {\n event.preventDefault();\n onClose();\n }\n }\n }\n\n return true;\n };\n\n const doc = getWindow(ref.current).document;\n doc.addEventListener('keydown', onDocumentKeydown, {\n capture: true,\n });\n return () => {\n doc.removeEventListener('keydown', onDocumentKeydown, true);\n };\n }, [onClose, ref, disabled]);\n\n return (\n <Component tabIndex={-1} ref={ref} {...restProps}>\n {children}\n </Component>\n );\n};\n"],"names":["useRef","useState","arraysEquals","useExternRef","useMutationObserver","useStableCallback","FOCUSABLE_ELEMENTS_LIST","Keys","pressedKey","contains","getActiveElementByAnotherElement","getWindow","isHTMLElement","useDOM","useIsomorphicLayoutEffect","FOCUSABLE_ELEMENTS","join","useRestoreFocus","restoreFocus","timeout","mount","ref","restoreFocusRef","current","restoreFocusTo","setRestoreFocusTo","restoreFocusImpl","shouldRestoreFocus","setTimeout","restoreFocusElement","focus","calculateRestoreFocusTo","tryToRestoreFocusOnUnmount","tryToRestoreFocusWhenFakeUnmount","FocusTrap","Component","onClose","autoFocus","disabled","getRootRef","children","restProps","document","focusableNodesRef","focusNodeByIndex","nodeIndex","element","preventScroll","recalculateFocusableNodesRef","parentNode","newFocusableElements","querySelectorAll","nodes","forEach","focusableEl","display","visibility","getComputedStyle","push","length","onMutateParentHandler","oldFocusableNodes","activeElement","currentElementIndex","Math","max","indexOf","tryToAutoFocusToFirstNode","autoFocusToNode","timeoutId","clearTimeout","onDocumentKeydown","event","pressedKeyResult","TAB","lastIdx","targetIdx","findIndex","node","target","shouldFocusFirstNode","shiftKey","preventDefault","ESCAPE","doc","addEventListener","capture","removeEventListener","tabIndex"],"mappings":"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"}
|
|
@@ -8,5 +8,5 @@ export interface GalleryProps extends BaseGalleryProps {
|
|
|
8
8
|
/**
|
|
9
9
|
* @see https://vkcom.github.io/VKUI/#/Gallery
|
|
10
10
|
*/
|
|
11
|
-
export declare const Gallery: ({ initialSlideIndex, children, timeout, onChange, bullets, looped, ...props }: GalleryProps) => React.ReactNode;
|
|
11
|
+
export declare const Gallery: ({ initialSlideIndex, children, timeout, onChange, bullets, looped, onDragStart, onDragEnd, ...props }: GalleryProps) => React.ReactNode;
|
|
12
12
|
//# sourceMappingURL=Gallery.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Gallery.d.ts","sourceRoot":"","sources":["../../../src/components/Gallery/Gallery.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Gallery.d.ts","sourceRoot":"","sources":["../../../src/components/Gallery/Gallery.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAG7D,MAAM,WAAW,YAAa,SAAQ,gBAAgB;IACpD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,eAAO,MAAM,OAAO,0GAUjB,YAAY,KAAG,KAAK,CAAC,SA0DvB,CAAC"}
|
|
@@ -5,19 +5,22 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
5
5
|
import * as React from 'react';
|
|
6
6
|
import { clamp } from '../../helpers/math';
|
|
7
7
|
import { useIsClient } from '../../hooks/useIsClient';
|
|
8
|
+
import { callMultiple } from '../../lib/callMultiple';
|
|
8
9
|
import { BaseGallery } from '../BaseGallery/BaseGallery';
|
|
9
10
|
import { CarouselBase } from '../BaseGallery/CarouselBase/CarouselBase';
|
|
10
11
|
import { useAutoPlay } from './hooks';
|
|
11
12
|
/**
|
|
12
13
|
* @see https://vkcom.github.io/VKUI/#/Gallery
|
|
13
14
|
*/ export const Gallery = (_param)=>{
|
|
14
|
-
var { initialSlideIndex = 0, children, timeout = 0, onChange, bullets, looped } = _param, props = _object_without_properties(_param, [
|
|
15
|
+
var { initialSlideIndex = 0, children, timeout = 0, onChange, bullets, looped, onDragStart, onDragEnd } = _param, props = _object_without_properties(_param, [
|
|
15
16
|
"initialSlideIndex",
|
|
16
17
|
"children",
|
|
17
18
|
"timeout",
|
|
18
19
|
"onChange",
|
|
19
20
|
"bullets",
|
|
20
|
-
"looped"
|
|
21
|
+
"looped",
|
|
22
|
+
"onDragStart",
|
|
23
|
+
"onDragEnd"
|
|
21
24
|
]);
|
|
22
25
|
const [localSlideIndex, setSlideIndex] = React.useState(initialSlideIndex);
|
|
23
26
|
const isControlled = typeof props.slideIndex === 'number';
|
|
@@ -39,7 +42,11 @@ import { useAutoPlay } from './hooks';
|
|
|
39
42
|
onChange,
|
|
40
43
|
slideIndex
|
|
41
44
|
]);
|
|
42
|
-
|
|
45
|
+
const autoPlayControls = useAutoPlay({
|
|
46
|
+
timeout,
|
|
47
|
+
slideIndex,
|
|
48
|
+
onNext: ()=>handleChange((slideIndex + 1) % childCount)
|
|
49
|
+
});
|
|
43
50
|
// prevent invalid slideIndex
|
|
44
51
|
// any slide index is invalid with no slides, just keep it as is
|
|
45
52
|
const safeSlideIndex = childCount > 0 ? clamp(slideIndex, 0, childCount - 1) : slideIndex;
|
|
@@ -61,6 +68,8 @@ import { useAutoPlay } from './hooks';
|
|
|
61
68
|
return /*#__PURE__*/ _jsx(Component, _object_spread_props(_object_spread({
|
|
62
69
|
dragDisabled: isControlled && !onChange
|
|
63
70
|
}, props), {
|
|
71
|
+
onDragStart: callMultiple(onDragStart, autoPlayControls.pause),
|
|
72
|
+
onDragEnd: callMultiple(onDragEnd, autoPlayControls.resume),
|
|
64
73
|
bullets: childCount > 0 && bullets,
|
|
65
74
|
slideIndex: safeSlideIndex,
|
|
66
75
|
onChange: handleChange,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/Gallery/Gallery.tsx"],"sourcesContent":["import * as React from 'react';\nimport { clamp } from '../../helpers/math';\nimport { useIsClient } from '../../hooks/useIsClient';\nimport { BaseGallery } from '../BaseGallery/BaseGallery';\nimport { CarouselBase } from '../BaseGallery/CarouselBase/CarouselBase';\nimport type { BaseGalleryProps } from '../BaseGallery/types';\nimport { useAutoPlay } from './hooks';\n\nexport interface GalleryProps extends BaseGalleryProps {\n initialSlideIndex?: number;\n timeout?: number;\n // Отвечает за зацикливание слайдов\n looped?: boolean;\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/Gallery\n */\nexport const Gallery = ({\n initialSlideIndex = 0,\n children,\n timeout = 0,\n onChange,\n bullets,\n looped,\n ...props\n}: GalleryProps): React.ReactNode => {\n const [localSlideIndex, setSlideIndex] = React.useState(initialSlideIndex);\n const isControlled = typeof props.slideIndex === 'number';\n const slideIndex = isControlled ? props.slideIndex ?? 0 : localSlideIndex;\n const slides = React.useMemo(\n () => React.Children.toArray(children).filter((item) => Boolean(item)),\n [children],\n );\n const childCount = slides.length;\n const isClient = useIsClient();\n\n const handleChange: GalleryProps['onChange'] = React.useCallback(\n (current: number) => {\n if (current === slideIndex) {\n return;\n }\n !isControlled && setSlideIndex(current);\n onChange && onChange(current);\n },\n [isControlled, onChange, slideIndex],\n );\n\n useAutoPlay(timeout
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Gallery/Gallery.tsx"],"sourcesContent":["import * as React from 'react';\nimport { clamp } from '../../helpers/math';\nimport { useIsClient } from '../../hooks/useIsClient';\nimport { callMultiple } from '../../lib/callMultiple';\nimport { BaseGallery } from '../BaseGallery/BaseGallery';\nimport { CarouselBase } from '../BaseGallery/CarouselBase/CarouselBase';\nimport type { BaseGalleryProps } from '../BaseGallery/types';\nimport { useAutoPlay } from './hooks';\n\nexport interface GalleryProps extends BaseGalleryProps {\n initialSlideIndex?: number;\n timeout?: number;\n // Отвечает за зацикливание слайдов\n looped?: boolean;\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/Gallery\n */\nexport const Gallery = ({\n initialSlideIndex = 0,\n children,\n timeout = 0,\n onChange,\n bullets,\n looped,\n onDragStart,\n onDragEnd,\n ...props\n}: GalleryProps): React.ReactNode => {\n const [localSlideIndex, setSlideIndex] = React.useState(initialSlideIndex);\n const isControlled = typeof props.slideIndex === 'number';\n const slideIndex = isControlled ? props.slideIndex ?? 0 : localSlideIndex;\n const slides = React.useMemo(\n () => React.Children.toArray(children).filter((item) => Boolean(item)),\n [children],\n );\n const childCount = slides.length;\n const isClient = useIsClient();\n\n const handleChange: GalleryProps['onChange'] = React.useCallback(\n (current: number) => {\n if (current === slideIndex) {\n return;\n }\n !isControlled && setSlideIndex(current);\n onChange && onChange(current);\n },\n [isControlled, onChange, slideIndex],\n );\n\n const autoPlayControls = useAutoPlay({\n timeout,\n slideIndex,\n onNext: () => handleChange((slideIndex + 1) % childCount),\n });\n\n // prevent invalid slideIndex\n // any slide index is invalid with no slides, just keep it as is\n const safeSlideIndex = childCount > 0 ? clamp(slideIndex, 0, childCount - 1) : slideIndex;\n // notify parent in controlled mode\n React.useEffect(() => {\n if (onChange && safeSlideIndex !== slideIndex) {\n onChange(safeSlideIndex);\n }\n setSlideIndex(safeSlideIndex);\n }, [onChange, safeSlideIndex, slideIndex]);\n\n if (!isClient) {\n return null;\n }\n\n const Component = looped ? CarouselBase : BaseGallery;\n\n return (\n <Component\n dragDisabled={isControlled && !onChange}\n {...props}\n onDragStart={callMultiple(onDragStart, autoPlayControls.pause)}\n onDragEnd={callMultiple(onDragEnd, autoPlayControls.resume)}\n bullets={childCount > 0 && bullets}\n slideIndex={safeSlideIndex}\n onChange={handleChange}\n >\n {slides}\n </Component>\n );\n};\n"],"names":["React","clamp","useIsClient","callMultiple","BaseGallery","CarouselBase","useAutoPlay","Gallery","initialSlideIndex","children","timeout","onChange","bullets","looped","onDragStart","onDragEnd","props","localSlideIndex","setSlideIndex","useState","isControlled","slideIndex","slides","useMemo","Children","toArray","filter","item","Boolean","childCount","length","isClient","handleChange","useCallback","current","autoPlayControls","onNext","safeSlideIndex","useEffect","Component","dragDisabled","pause","resume"],"mappings":";;;;AAAA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,KAAK,QAAQ,qBAAqB;AAC3C,SAASC,WAAW,QAAQ,0BAA0B;AACtD,SAASC,YAAY,QAAQ,yBAAyB;AACtD,SAASC,WAAW,QAAQ,6BAA6B;AACzD,SAASC,YAAY,QAAQ,2CAA2C;AAExE,SAASC,WAAW,QAAQ,UAAU;AAStC;;CAEC,GACD,OAAO,MAAMC,UAAU;QAAC,EACtBC,oBAAoB,CAAC,EACrBC,QAAQ,EACRC,UAAU,CAAC,EACXC,QAAQ,EACRC,OAAO,EACPC,MAAM,EACNC,WAAW,EACXC,SAAS,EAEI,WADVC;QARHR;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;;IAGA,MAAM,CAACE,iBAAiBC,cAAc,GAAGlB,MAAMmB,QAAQ,CAACX;IACxD,MAAMY,eAAe,OAAOJ,MAAMK,UAAU,KAAK;QACfL;IAAlC,MAAMK,aAAaD,eAAeJ,CAAAA,oBAAAA,MAAMK,UAAU,cAAhBL,+BAAAA,oBAAoB,IAAIC;IAC1D,MAAMK,SAAStB,MAAMuB,OAAO,CAC1B,IAAMvB,MAAMwB,QAAQ,CAACC,OAAO,CAAChB,UAAUiB,MAAM,CAAC,CAACC,OAASC,QAAQD,QAChE;QAAClB;KAAS;IAEZ,MAAMoB,aAAaP,OAAOQ,MAAM;IAChC,MAAMC,WAAW7B;IAEjB,MAAM8B,eAAyChC,MAAMiC,WAAW,CAC9D,CAACC;QACC,IAAIA,YAAYb,YAAY;YAC1B;QACF;QACA,CAACD,gBAAgBF,cAAcgB;QAC/BvB,YAAYA,SAASuB;IACvB,GACA;QAACd;QAAcT;QAAUU;KAAW;IAGtC,MAAMc,mBAAmB7B,YAAY;QACnCI;QACAW;QACAe,QAAQ,IAAMJ,aAAa,AAACX,CAAAA,aAAa,CAAA,IAAKQ;IAChD;IAEA,6BAA6B;IAC7B,gEAAgE;IAChE,MAAMQ,iBAAiBR,aAAa,IAAI5B,MAAMoB,YAAY,GAAGQ,aAAa,KAAKR;IAC/E,mCAAmC;IACnCrB,MAAMsC,SAAS,CAAC;QACd,IAAI3B,YAAY0B,mBAAmBhB,YAAY;YAC7CV,SAAS0B;QACX;QACAnB,cAAcmB;IAChB,GAAG;QAAC1B;QAAU0B;QAAgBhB;KAAW;IAEzC,IAAI,CAACU,UAAU;QACb,OAAO;IACT;IAEA,MAAMQ,YAAY1B,SAASR,eAAeD;IAE1C,qBACE,KAACmC;QACCC,cAAcpB,gBAAgB,CAACT;OAC3BK;QACJF,aAAaX,aAAaW,aAAaqB,iBAAiBM,KAAK;QAC7D1B,WAAWZ,aAAaY,WAAWoB,iBAAiBO,MAAM;QAC1D9B,SAASiB,aAAa,KAAKjB;QAC3BS,YAAYgB;QACZ1B,UAAUqB;kBAETV;;AAGP,EAAE"}
|
|
@@ -1,2 +1,10 @@
|
|
|
1
|
-
export
|
|
1
|
+
export interface AutoPlayConfig {
|
|
2
|
+
timeout: number;
|
|
3
|
+
slideIndex: number;
|
|
4
|
+
onNext: VoidFunction;
|
|
5
|
+
}
|
|
6
|
+
export declare function useAutoPlay({ timeout, slideIndex, onNext }: AutoPlayConfig): {
|
|
7
|
+
pause: VoidFunction;
|
|
8
|
+
resume: VoidFunction;
|
|
9
|
+
};
|
|
2
10
|
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/components/Gallery/hooks.ts"],"names":[],"mappings":"AAKA,
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/components/Gallery/hooks.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,cAAc,GAAG;IAC5E,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;CACtB,CAoDA"}
|
|
@@ -1,42 +1,60 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useStableCallback } from '../../hooks/useStableCallback';
|
|
3
3
|
import { useDOM } from '../../lib/dom';
|
|
4
|
-
export function useAutoPlay(timeout, slideIndex,
|
|
4
|
+
export function useAutoPlay({ timeout, slideIndex, onNext }) {
|
|
5
5
|
const { document } = useDOM();
|
|
6
|
-
const
|
|
6
|
+
const [paused, setPaused] = React.useState(false);
|
|
7
|
+
const timeoutRef = React.useRef(null);
|
|
8
|
+
const callbackFn = useStableCallback(onNext);
|
|
9
|
+
const pause = React.useCallback(()=>setPaused(true), []);
|
|
10
|
+
const resume = React.useCallback(()=>setPaused(false), []);
|
|
11
|
+
// Выносим функции очистки и старта таймера в отдельные функции
|
|
12
|
+
const clearAutoPlayTimeout = React.useCallback(()=>{
|
|
13
|
+
if (timeoutRef.current) {
|
|
14
|
+
clearTimeout(timeoutRef.current);
|
|
15
|
+
timeoutRef.current = null;
|
|
16
|
+
}
|
|
17
|
+
}, []);
|
|
18
|
+
const startAutoPlayTimeout = React.useCallback(()=>{
|
|
19
|
+
if (!document || !timeout || paused) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (document.visibilityState === 'visible') {
|
|
23
|
+
clearAutoPlayTimeout();
|
|
24
|
+
timeoutRef.current = setTimeout(callbackFn, timeout);
|
|
25
|
+
} else {
|
|
26
|
+
clearAutoPlayTimeout();
|
|
27
|
+
}
|
|
28
|
+
}, [
|
|
29
|
+
document,
|
|
30
|
+
timeout,
|
|
31
|
+
paused,
|
|
32
|
+
clearAutoPlayTimeout,
|
|
33
|
+
callbackFn
|
|
34
|
+
]);
|
|
35
|
+
// Основной эффект для управления автопроигрыванием
|
|
7
36
|
React.useEffect(function initializeAutoPlay() {
|
|
8
|
-
if (!document || !timeout) {
|
|
37
|
+
if (!document || !timeout || paused) {
|
|
9
38
|
return;
|
|
10
39
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
if (timeoutId) {
|
|
14
|
-
clearTimeout(timeoutId);
|
|
15
|
-
timeoutId = null;
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
const start = ()=>{
|
|
19
|
-
switch(document.visibilityState){
|
|
20
|
-
case 'visible':
|
|
21
|
-
stop();
|
|
22
|
-
timeoutId = setTimeout(callbackFn, timeout);
|
|
23
|
-
break;
|
|
24
|
-
case 'hidden':
|
|
25
|
-
stop();
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
start();
|
|
29
|
-
document.addEventListener('visibilitychange', start);
|
|
40
|
+
startAutoPlayTimeout();
|
|
41
|
+
document.addEventListener('visibilitychange', startAutoPlayTimeout);
|
|
30
42
|
return ()=>{
|
|
31
|
-
|
|
32
|
-
document.removeEventListener('visibilitychange',
|
|
43
|
+
clearAutoPlayTimeout();
|
|
44
|
+
document.removeEventListener('visibilitychange', startAutoPlayTimeout);
|
|
33
45
|
};
|
|
34
46
|
}, [
|
|
35
47
|
document,
|
|
36
48
|
timeout,
|
|
37
49
|
slideIndex,
|
|
38
|
-
|
|
50
|
+
startAutoPlayTimeout,
|
|
51
|
+
clearAutoPlayTimeout,
|
|
52
|
+
paused
|
|
39
53
|
]);
|
|
54
|
+
return {
|
|
55
|
+
resume,
|
|
56
|
+
pause
|
|
57
|
+
};
|
|
40
58
|
}
|
|
41
59
|
|
|
42
60
|
//# sourceMappingURL=hooks.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/Gallery/hooks.ts"],"sourcesContent":["import * as React from 'react';\nimport { useStableCallback } from '../../hooks/useStableCallback';\nimport { useDOM } from '../../lib/dom';\nimport type { TimeoutId } from '../../types';\n\nexport
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Gallery/hooks.ts"],"sourcesContent":["import * as React from 'react';\nimport { useStableCallback } from '../../hooks/useStableCallback';\nimport { useDOM } from '../../lib/dom';\nimport type { TimeoutId } from '../../types';\n\nexport interface AutoPlayConfig {\n timeout: number;\n slideIndex: number;\n onNext: VoidFunction;\n}\n\nexport function useAutoPlay({ timeout, slideIndex, onNext }: AutoPlayConfig): {\n pause: VoidFunction;\n resume: VoidFunction;\n} {\n const { document } = useDOM();\n const [paused, setPaused] = React.useState(false);\n const timeoutRef = React.useRef<TimeoutId>(null);\n const callbackFn = useStableCallback(onNext);\n\n const pause = React.useCallback(() => setPaused(true), []);\n const resume = React.useCallback(() => setPaused(false), []);\n\n // Выносим функции очистки и старта таймера в отдельные функции\n const clearAutoPlayTimeout = React.useCallback(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n }, []);\n\n const startAutoPlayTimeout = React.useCallback(() => {\n if (!document || !timeout || paused) {\n return;\n }\n\n if (document.visibilityState === 'visible') {\n clearAutoPlayTimeout();\n timeoutRef.current = setTimeout(callbackFn, timeout);\n } else {\n clearAutoPlayTimeout();\n }\n }, [document, timeout, paused, clearAutoPlayTimeout, callbackFn]);\n\n // Основной эффект для управления автопроигрыванием\n React.useEffect(\n function initializeAutoPlay() {\n if (!document || !timeout || paused) {\n return;\n }\n\n startAutoPlayTimeout();\n document.addEventListener('visibilitychange', startAutoPlayTimeout);\n\n return () => {\n clearAutoPlayTimeout();\n document.removeEventListener('visibilitychange', startAutoPlayTimeout);\n };\n },\n [document, timeout, slideIndex, startAutoPlayTimeout, clearAutoPlayTimeout, paused],\n );\n\n return {\n resume,\n pause,\n };\n}\n"],"names":["React","useStableCallback","useDOM","useAutoPlay","timeout","slideIndex","onNext","document","paused","setPaused","useState","timeoutRef","useRef","callbackFn","pause","useCallback","resume","clearAutoPlayTimeout","current","clearTimeout","startAutoPlayTimeout","visibilityState","setTimeout","useEffect","initializeAutoPlay","addEventListener","removeEventListener"],"mappings":"AAAA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,iBAAiB,QAAQ,gCAAgC;AAClE,SAASC,MAAM,QAAQ,gBAAgB;AASvC,OAAO,SAASC,YAAY,EAAEC,OAAO,EAAEC,UAAU,EAAEC,MAAM,EAAkB;IAIzE,MAAM,EAAEC,QAAQ,EAAE,GAAGL;IACrB,MAAM,CAACM,QAAQC,UAAU,GAAGT,MAAMU,QAAQ,CAAC;IAC3C,MAAMC,aAAaX,MAAMY,MAAM,CAAY;IAC3C,MAAMC,aAAaZ,kBAAkBK;IAErC,MAAMQ,QAAQd,MAAMe,WAAW,CAAC,IAAMN,UAAU,OAAO,EAAE;IACzD,MAAMO,SAAShB,MAAMe,WAAW,CAAC,IAAMN,UAAU,QAAQ,EAAE;IAE3D,+DAA+D;IAC/D,MAAMQ,uBAAuBjB,MAAMe,WAAW,CAAC;QAC7C,IAAIJ,WAAWO,OAAO,EAAE;YACtBC,aAAaR,WAAWO,OAAO;YAC/BP,WAAWO,OAAO,GAAG;QACvB;IACF,GAAG,EAAE;IAEL,MAAME,uBAAuBpB,MAAMe,WAAW,CAAC;QAC7C,IAAI,CAACR,YAAY,CAACH,WAAWI,QAAQ;YACnC;QACF;QAEA,IAAID,SAASc,eAAe,KAAK,WAAW;YAC1CJ;YACAN,WAAWO,OAAO,GAAGI,WAAWT,YAAYT;QAC9C,OAAO;YACLa;QACF;IACF,GAAG;QAACV;QAAUH;QAASI;QAAQS;QAAsBJ;KAAW;IAEhE,mDAAmD;IACnDb,MAAMuB,SAAS,CACb,SAASC;QACP,IAAI,CAACjB,YAAY,CAACH,WAAWI,QAAQ;YACnC;QACF;QAEAY;QACAb,SAASkB,gBAAgB,CAAC,oBAAoBL;QAE9C,OAAO;YACLH;YACAV,SAASmB,mBAAmB,CAAC,oBAAoBN;QACnD;IACF,GACA;QAACb;QAAUH;QAASC;QAAYe;QAAsBH;QAAsBT;KAAO;IAGrF,OAAO;QACLQ;QACAF;IACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HorizontalScroll.d.ts","sourceRoot":"","sources":["../../../src/components/HorizontalScroll/HorizontalScroll.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"HorizontalScroll.d.ts","sourceRoot":"","sources":["../../../src/components/HorizontalScroll/HorizontalScroll.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,OAAO,KAAK,EAAE,MAAM,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAqBrE,MAAM,MAAM,qBAAqB,GAAG,CAAC,eAAe,EAAE,MAAM,KAAK,MAAM,CAAC;AAExE,MAAM,WAAW,qBACf,SAAQ,yBAAyB,CAAC,cAAc,CAAC,EAC/C,MAAM,CAAC,cAAc,CAAC;IACxB;;OAEG;IACH,eAAe,CAAC,EAAE,qBAAqB,CAAC;IACxC;;OAEG;IACH,gBAAgB,CAAC,EAAE,qBAAqB,CAAC;IACzC,SAAS,CAAC,EAAE,GAAG,GAAG,GAAG,CAAC;IACtB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,UAAU,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAChC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAsGD;;GAEG;AACH,eAAO,MAAM,gBAAgB,kKAY1B,qBAAqB,KAAG,KAAK,CAAC,SAkJhC,CAAC"}
|
|
@@ -3,10 +3,9 @@ import { _ as _object_spread_props } from "@swc/helpers/_/_object_spread_props";
|
|
|
3
3
|
import { _ as _object_without_properties } from "@swc/helpers/_/_object_without_properties";
|
|
4
4
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
5
5
|
import * as React from 'react';
|
|
6
|
-
import { classNames
|
|
6
|
+
import { classNames } from '@vkontakte/vkjs';
|
|
7
7
|
import { useAdaptivityHasPointer } from '../../hooks/useAdaptivityHasPointer';
|
|
8
8
|
import { useDirection } from '../../hooks/useDirection';
|
|
9
|
-
import { useEventListener } from '../../hooks/useEventListener';
|
|
10
9
|
import { useExternRef } from '../../hooks/useExternRef';
|
|
11
10
|
import { easeInOutSine } from '../../lib/fx';
|
|
12
11
|
import { RootComponent } from '../RootComponent/RootComponent';
|
|
@@ -156,42 +155,32 @@ function doScroll({ scrollElement, getScrollPosition, animationQueue, onScrollTo
|
|
|
156
155
|
setCanScrollStart,
|
|
157
156
|
setCanScrollEnd
|
|
158
157
|
]);
|
|
159
|
-
const scrollEvent = useEventListener('scroll', calculateArrowsVisibility);
|
|
160
|
-
React.useEffect(function addScrollerRefToScrollEvent() {
|
|
161
|
-
if (!scrollerRef.current) {
|
|
162
|
-
return noop;
|
|
163
|
-
}
|
|
164
|
-
scrollEvent.add(scrollerRef.current);
|
|
165
|
-
return scrollEvent.remove;
|
|
166
|
-
}, [
|
|
167
|
-
scrollEvent,
|
|
168
|
-
scrollerRef
|
|
169
|
-
]);
|
|
170
158
|
React.useEffect(calculateArrowsVisibility, [
|
|
171
159
|
calculateArrowsVisibility,
|
|
172
160
|
children
|
|
173
161
|
]);
|
|
174
|
-
|
|
175
|
-
* Прокрутка с помощью любого колеса мыши
|
|
176
|
-
*/ const onwheel = React.useCallback((e)=>{
|
|
162
|
+
const _onWheel = React.useCallback((e)=>{
|
|
177
163
|
scrollerRef.current.scrollBy({
|
|
178
164
|
left: e.deltaX + e.deltaY,
|
|
179
165
|
behavior: 'auto'
|
|
180
166
|
});
|
|
181
|
-
e.preventDefault();
|
|
182
167
|
}, [
|
|
183
168
|
scrollerRef
|
|
184
169
|
]);
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
170
|
+
/**
|
|
171
|
+
* Прокрутка с помощью любого колеса мыши
|
|
172
|
+
*/ const onScrollWheel = React.useCallback((e)=>{
|
|
173
|
+
_onWheel(e);
|
|
174
|
+
e.preventDefault();
|
|
175
|
+
}, [
|
|
176
|
+
_onWheel
|
|
177
|
+
]);
|
|
178
|
+
const onArrowWheel = React.useCallback((e)=>{
|
|
179
|
+
if (e.deltaX || e.deltaY && scrollOnAnyWheel) {
|
|
180
|
+
_onWheel(e);
|
|
189
181
|
}
|
|
190
|
-
wheelEvent.add(scrollerRef.current);
|
|
191
|
-
return wheelEvent.remove;
|
|
192
182
|
}, [
|
|
193
|
-
|
|
194
|
-
scrollerRef,
|
|
183
|
+
_onWheel,
|
|
195
184
|
scrollOnAnyWheel
|
|
196
185
|
]);
|
|
197
186
|
return /*#__PURE__*/ _jsxs(RootComponent, _object_spread_props(_object_spread({}, restProps), {
|
|
@@ -206,7 +195,8 @@ function doScroll({ scrollElement, getScrollPosition, animationQueue, onScrollTo
|
|
|
206
195
|
"aria-hidden": true,
|
|
207
196
|
tabIndex: -1,
|
|
208
197
|
className: classNames("vkuiHorizontalScroll__arrow", "vkuiHorizontalScroll__arrowLeft"),
|
|
209
|
-
onClick: scrollToLeft
|
|
198
|
+
onClick: scrollToLeft,
|
|
199
|
+
onWheel: onArrowWheel
|
|
210
200
|
}),
|
|
211
201
|
showArrows && (hasPointer || hasPointer === undefined) && canScrollRight && /*#__PURE__*/ _jsx(ScrollArrow, {
|
|
212
202
|
"data-testid": process.env.NODE_ENV === 'test' ? 'ScrollArrowRight' : undefined,
|
|
@@ -216,11 +206,14 @@ function doScroll({ scrollElement, getScrollPosition, animationQueue, onScrollTo
|
|
|
216
206
|
"aria-hidden": true,
|
|
217
207
|
tabIndex: -1,
|
|
218
208
|
className: classNames("vkuiHorizontalScroll__arrow", "vkuiHorizontalScroll__arrowRight"),
|
|
219
|
-
onClick: scrollToRight
|
|
209
|
+
onClick: scrollToRight,
|
|
210
|
+
onWheel: onArrowWheel
|
|
220
211
|
}),
|
|
221
212
|
/*#__PURE__*/ _jsx("div", {
|
|
222
213
|
className: "vkuiHorizontalScroll__in",
|
|
223
214
|
ref: scrollerRef,
|
|
215
|
+
onScroll: calculateArrowsVisibility,
|
|
216
|
+
onWheel: scrollOnAnyWheel ? onScrollWheel : undefined,
|
|
224
217
|
children: /*#__PURE__*/ _jsx("div", {
|
|
225
218
|
className: "vkuiHorizontalScroll__in-wrapper",
|
|
226
219
|
children: children
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/HorizontalScroll/HorizontalScroll.tsx"],"sourcesContent":["import * as React from 'react';\nimport { classNames, noop } from '@vkontakte/vkjs';\nimport { useAdaptivityHasPointer } from '../../hooks/useAdaptivityHasPointer';\nimport { useDirection } from '../../hooks/useDirection';\nimport { useEventListener } from '../../hooks/useEventListener';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { easeInOutSine } from '../../lib/fx';\nimport type { HasRef, HTMLAttributesWithRootRef } from '../../types';\nimport { RootComponent } from '../RootComponent/RootComponent';\nimport { ScrollArrow } from '../ScrollArrow/ScrollArrow';\nimport styles from './HorizontalScroll.module.css';\n\ninterface ScrollContext {\n scrollElement: HTMLElement | null;\n scrollAnimationDuration: number;\n animationQueue: VoidFunction[];\n getScrollPosition: (currentPosition: number) => number;\n onScrollToEndBorder: VoidFunction;\n onScrollEnd: VoidFunction;\n onScrollStart: VoidFunction;\n /**\n * Начальная ширина прокрутки.\n * В некоторых случаях может отличаться от текущей ширины прокрутки из-за transforms: translate\n */\n initialScrollWidth: number;\n textDirection: 'ltr' | 'rtl';\n}\n\nexport type ScrollPositionHandler = (currentPosition: number) => number;\n\nexport interface HorizontalScrollProps\n extends HTMLAttributesWithRootRef<HTMLDivElement>,\n HasRef<HTMLDivElement> {\n /**\n * Функция для расчета величины прокрутки при клике на левую стрелку.\n */\n getScrollToLeft?: ScrollPositionHandler;\n /**\n * Функция для расчета величины прокрутки при клике на правую стрелку.\n */\n getScrollToRight?: ScrollPositionHandler;\n arrowSize?: 'm' | 'l';\n /**\n * Смещает иконки кнопок навигации по вертикали.\n */\n arrowOffsetY?: number | string;\n showArrows?: boolean | 'always';\n scrollAnimationDuration?: number;\n /**\n * Добавляет возможность прокручивать контент на любое колесо мыши.\n * По умолчанию прокручивается как любой горизонтальный контент через shift.\n */\n scrollOnAnyWheel?: boolean;\n /**\n * Задает потомкам инлайновое положение (горизонально)\n */\n inline?: boolean;\n}\n\n/**\n * timing method\n */\nfunction now() {\n return performance && performance.now ? performance.now() : Date.now();\n}\n\n/**\n * Округление к большему по модулю\n *\n * ## Пример\n *\n * ```ts\n * import { strict as assert } from 'node:assert';\n *\n * assert.equal(roundingAwayFromZero(5.1), 6)\n * assert.equal(roundingAwayFromZero(-5.1), -6)\n * ```\n */\nfunction roundingAwayFromZero(value: number): number {\n return value > 0 ? Math.ceil(value) : Math.floor(value);\n}\n\n/**\n * Округляем el.scrollLeft\n * https://github.com/VKCOM/VKUI/pull/2445\n */\nconst roundUpElementScrollLeft = (el: HTMLElement) => roundingAwayFromZero(el.scrollLeft);\n\n/**\n * Код анимации скрола, на основе полифила: https://github.com/iamdustan/smoothscroll\n * Константа взята из полифила (468), на дизайн-ревью уточнили до 250\n * @var {number} SCROLL_ONE_FRAME_TIME время анимации скролла\n */\nconst SCROLL_ONE_FRAME_TIME = 250;\n\nfunction doScroll({\n scrollElement,\n getScrollPosition,\n animationQueue,\n onScrollToEndBorder,\n onScrollEnd,\n onScrollStart,\n initialScrollWidth,\n scrollAnimationDuration,\n textDirection,\n}: ScrollContext) {\n if (!scrollElement || !getScrollPosition) {\n return;\n }\n\n /**\n * крайнее значение сдвига\n */\n const extremeScrollLeft =\n (textDirection === 'ltr' ? 1 : -1) * (initialScrollWidth - scrollElement.offsetWidth);\n\n let startScrollLeft = roundUpElementScrollLeft(scrollElement);\n let endScrollLeft = getScrollPosition(startScrollLeft);\n\n onScrollStart();\n\n /**\n * Если окончание прокрутки вышло за ноль\n */\n if (startScrollLeft * endScrollLeft < 0) {\n endScrollLeft = 0;\n }\n\n if (Math.abs(endScrollLeft) >= Math.abs(extremeScrollLeft)) {\n onScrollToEndBorder();\n endScrollLeft = extremeScrollLeft;\n }\n\n const startTime = now();\n\n (function scroll() {\n const time = now();\n const elapsed = Math.min((time - startTime) / scrollAnimationDuration, 1);\n\n const value = easeInOutSine(elapsed);\n\n const currentScrollLeft = startScrollLeft + (endScrollLeft - startScrollLeft) * value;\n scrollElement.scrollLeft = roundingAwayFromZero(currentScrollLeft);\n\n const scrollEnd =\n textDirection === 'ltr' ? Math.max(0, endScrollLeft) : Math.min(0, endScrollLeft);\n if (roundUpElementScrollLeft(scrollElement) !== scrollEnd && elapsed !== 1) {\n requestAnimationFrame(scroll);\n return;\n }\n\n onScrollEnd();\n animationQueue.shift();\n if (animationQueue.length > 0) {\n animationQueue[0]();\n }\n })();\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/HorizontalScroll\n */\nexport const HorizontalScroll = ({\n children,\n getScrollToLeft,\n getScrollToRight,\n showArrows = true,\n arrowSize = 'l',\n arrowOffsetY,\n scrollAnimationDuration = SCROLL_ONE_FRAME_TIME,\n getRef,\n scrollOnAnyWheel = false,\n inline = false,\n ...restProps\n}: HorizontalScrollProps): React.ReactNode => {\n const [canScrollLeft, setCanScrollLeft] = React.useState(false);\n const [canScrollRight, setCanScrollRight] = React.useState(false);\n const [directionRef, textDirection] = useDirection<HTMLDivElement>();\n const direction = textDirection || 'ltr';\n const setCanScrollStart = direction === 'ltr' ? setCanScrollLeft : setCanScrollRight;\n const setCanScrollEnd = direction === 'ltr' ? setCanScrollRight : setCanScrollLeft;\n\n const isCustomScrollingRef = React.useRef(false);\n\n const scrollerRef = useExternRef(getRef, directionRef);\n\n const animationQueue = React.useRef<VoidFunction[]>([]);\n\n const hasPointer = useAdaptivityHasPointer();\n\n const scrollTo = React.useCallback(\n (getScrollPosition: ScrollPositionHandler) => {\n const scrollElement = scrollerRef.current;\n\n animationQueue.current.push(() =>\n doScroll({\n scrollElement,\n getScrollPosition,\n animationQueue: animationQueue.current,\n onScrollToEndBorder: () => setCanScrollEnd(false),\n onScrollEnd: () => (isCustomScrollingRef.current = false),\n onScrollStart: () => (isCustomScrollingRef.current = true),\n initialScrollWidth: scrollElement?.firstElementChild?.scrollWidth || 0,\n scrollAnimationDuration,\n textDirection: direction,\n }),\n );\n if (animationQueue.current.length === 1) {\n animationQueue.current[0]();\n }\n },\n [scrollerRef, scrollAnimationDuration, direction, setCanScrollEnd],\n );\n\n const scrollToLeft = React.useCallback(() => {\n const getScrollPosition =\n getScrollToLeft ?? ((i: number) => i - scrollerRef.current!.offsetWidth);\n scrollTo(getScrollPosition);\n }, [getScrollToLeft, scrollTo, scrollerRef]);\n\n const scrollToRight = React.useCallback(() => {\n const getScrollPosition =\n getScrollToRight ?? ((i: number) => i + scrollerRef.current!.offsetWidth);\n scrollTo(getScrollPosition);\n }, [getScrollToRight, scrollTo, scrollerRef]);\n\n const calculateArrowsVisibility = React.useCallback(() => {\n if (showArrows && hasPointer && scrollerRef.current && !isCustomScrollingRef.current) {\n const scrollElement = scrollerRef.current;\n\n setCanScrollStart(scrollElement.scrollLeft !== 0);\n setCanScrollEnd(\n Math.abs(roundUpElementScrollLeft(scrollElement)) + scrollElement.offsetWidth <\n scrollElement.scrollWidth,\n );\n }\n }, [showArrows, hasPointer, scrollerRef, setCanScrollStart, setCanScrollEnd]);\n\n const scrollEvent = useEventListener('scroll', calculateArrowsVisibility);\n React.useEffect(\n function addScrollerRefToScrollEvent() {\n if (!scrollerRef.current) {\n return noop;\n }\n\n scrollEvent.add(scrollerRef.current);\n return scrollEvent.remove;\n },\n [scrollEvent, scrollerRef],\n );\n\n React.useEffect(calculateArrowsVisibility, [calculateArrowsVisibility, children]);\n\n /**\n * Прокрутка с помощью любого колеса мыши\n */\n const onwheel = React.useCallback(\n (e: WheelEvent) => {\n scrollerRef.current!.scrollBy({ left: e.deltaX + e.deltaY, behavior: 'auto' });\n e.preventDefault();\n },\n [scrollerRef],\n );\n\n const wheelEvent = useEventListener('wheel', onwheel);\n React.useEffect(\n function addScrollerRefToWheelEvent() {\n if (!scrollerRef.current || !scrollOnAnyWheel) {\n return noop;\n }\n\n wheelEvent.add(scrollerRef.current);\n\n return wheelEvent.remove;\n },\n [wheelEvent, scrollerRef, scrollOnAnyWheel],\n );\n\n return (\n <RootComponent\n {...restProps}\n baseClassName={classNames(\n styles['HorizontalScroll'],\n 'vkuiInternalHorizontalScroll',\n showArrows === 'always' && styles['HorizontalScroll--withConstArrows'],\n inline && styles['HorizontalScroll--inline'],\n )}\n onMouseEnter={calculateArrowsVisibility}\n >\n {showArrows && (hasPointer || hasPointer === undefined) && canScrollLeft && (\n <ScrollArrow\n data-testid={process.env.NODE_ENV === 'test' ? 'ScrollArrowLeft' : undefined}\n size={arrowSize}\n offsetY={arrowOffsetY}\n direction=\"left\"\n aria-hidden\n tabIndex={-1}\n className={classNames(\n styles['HorizontalScroll__arrow'],\n styles['HorizontalScroll__arrowLeft'],\n )}\n onClick={scrollToLeft}\n />\n )}\n {showArrows && (hasPointer || hasPointer === undefined) && canScrollRight && (\n <ScrollArrow\n data-testid={process.env.NODE_ENV === 'test' ? 'ScrollArrowRight' : undefined}\n size={arrowSize}\n offsetY={arrowOffsetY}\n direction=\"right\"\n aria-hidden\n tabIndex={-1}\n className={classNames(\n styles['HorizontalScroll__arrow'],\n styles['HorizontalScroll__arrowRight'],\n )}\n onClick={scrollToRight}\n />\n )}\n <div className={styles['HorizontalScroll__in']} ref={scrollerRef}>\n <div className={styles['HorizontalScroll__in-wrapper']}>{children}</div>\n </div>\n </RootComponent>\n );\n};\n"],"names":["React","classNames","noop","useAdaptivityHasPointer","useDirection","useEventListener","useExternRef","easeInOutSine","RootComponent","ScrollArrow","now","performance","Date","roundingAwayFromZero","value","Math","ceil","floor","roundUpElementScrollLeft","el","scrollLeft","SCROLL_ONE_FRAME_TIME","doScroll","scrollElement","getScrollPosition","animationQueue","onScrollToEndBorder","onScrollEnd","onScrollStart","initialScrollWidth","scrollAnimationDuration","textDirection","extremeScrollLeft","offsetWidth","startScrollLeft","endScrollLeft","abs","startTime","scroll","time","elapsed","min","currentScrollLeft","scrollEnd","max","requestAnimationFrame","shift","length","HorizontalScroll","children","getScrollToLeft","getScrollToRight","showArrows","arrowSize","arrowOffsetY","getRef","scrollOnAnyWheel","inline","restProps","canScrollLeft","setCanScrollLeft","useState","canScrollRight","setCanScrollRight","directionRef","direction","setCanScrollStart","setCanScrollEnd","isCustomScrollingRef","useRef","scrollerRef","hasPointer","scrollTo","useCallback","current","push","firstElementChild","scrollWidth","scrollToLeft","i","scrollToRight","calculateArrowsVisibility","scrollEvent","useEffect","addScrollerRefToScrollEvent","add","remove","onwheel","e","scrollBy","left","deltaX","deltaY","behavior","preventDefault","wheelEvent","addScrollerRefToWheelEvent","baseClassName","onMouseEnter","undefined","data-testid","process","env","NODE_ENV","size","offsetY","aria-hidden","tabIndex","className","onClick","div","ref"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/HorizontalScroll/HorizontalScroll.tsx"],"sourcesContent":["import * as React from 'react';\nimport { classNames } from '@vkontakte/vkjs';\nimport { useAdaptivityHasPointer } from '../../hooks/useAdaptivityHasPointer';\nimport { useDirection } from '../../hooks/useDirection';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { easeInOutSine } from '../../lib/fx';\nimport type { HasRef, HTMLAttributesWithRootRef } from '../../types';\nimport { RootComponent } from '../RootComponent/RootComponent';\nimport { ScrollArrow } from '../ScrollArrow/ScrollArrow';\nimport styles from './HorizontalScroll.module.css';\n\ninterface ScrollContext {\n scrollElement: HTMLElement | null;\n scrollAnimationDuration: number;\n animationQueue: VoidFunction[];\n getScrollPosition: (currentPosition: number) => number;\n onScrollToEndBorder: VoidFunction;\n onScrollEnd: VoidFunction;\n onScrollStart: VoidFunction;\n /**\n * Начальная ширина прокрутки.\n * В некоторых случаях может отличаться от текущей ширины прокрутки из-за transforms: translate\n */\n initialScrollWidth: number;\n textDirection: 'ltr' | 'rtl';\n}\n\nexport type ScrollPositionHandler = (currentPosition: number) => number;\n\nexport interface HorizontalScrollProps\n extends HTMLAttributesWithRootRef<HTMLDivElement>,\n HasRef<HTMLDivElement> {\n /**\n * Функция для расчета величины прокрутки при клике на левую стрелку.\n */\n getScrollToLeft?: ScrollPositionHandler;\n /**\n * Функция для расчета величины прокрутки при клике на правую стрелку.\n */\n getScrollToRight?: ScrollPositionHandler;\n arrowSize?: 'm' | 'l';\n /**\n * Смещает иконки кнопок навигации по вертикали.\n */\n arrowOffsetY?: number | string;\n showArrows?: boolean | 'always';\n scrollAnimationDuration?: number;\n /**\n * Добавляет возможность прокручивать контент на любое колесо мыши.\n * По умолчанию прокручивается как любой горизонтальный контент через shift.\n */\n scrollOnAnyWheel?: boolean;\n /**\n * Задает потомкам инлайновое положение (горизонально)\n */\n inline?: boolean;\n}\n\n/**\n * timing method\n */\nfunction now() {\n return performance && performance.now ? performance.now() : Date.now();\n}\n\n/**\n * Округление к большему по модулю\n *\n * ## Пример\n *\n * ```ts\n * import { strict as assert } from 'node:assert';\n *\n * assert.equal(roundingAwayFromZero(5.1), 6)\n * assert.equal(roundingAwayFromZero(-5.1), -6)\n * ```\n */\nfunction roundingAwayFromZero(value: number): number {\n return value > 0 ? Math.ceil(value) : Math.floor(value);\n}\n\n/**\n * Округляем el.scrollLeft\n * https://github.com/VKCOM/VKUI/pull/2445\n */\nconst roundUpElementScrollLeft = (el: HTMLElement) => roundingAwayFromZero(el.scrollLeft);\n\n/**\n * Код анимации скрола, на основе полифила: https://github.com/iamdustan/smoothscroll\n * Константа взята из полифила (468), на дизайн-ревью уточнили до 250\n * @var {number} SCROLL_ONE_FRAME_TIME время анимации скролла\n */\nconst SCROLL_ONE_FRAME_TIME = 250;\n\nfunction doScroll({\n scrollElement,\n getScrollPosition,\n animationQueue,\n onScrollToEndBorder,\n onScrollEnd,\n onScrollStart,\n initialScrollWidth,\n scrollAnimationDuration,\n textDirection,\n}: ScrollContext) {\n if (!scrollElement || !getScrollPosition) {\n return;\n }\n\n /**\n * крайнее значение сдвига\n */\n const extremeScrollLeft =\n (textDirection === 'ltr' ? 1 : -1) * (initialScrollWidth - scrollElement.offsetWidth);\n\n let startScrollLeft = roundUpElementScrollLeft(scrollElement);\n let endScrollLeft = getScrollPosition(startScrollLeft);\n\n onScrollStart();\n\n /**\n * Если окончание прокрутки вышло за ноль\n */\n if (startScrollLeft * endScrollLeft < 0) {\n endScrollLeft = 0;\n }\n\n if (Math.abs(endScrollLeft) >= Math.abs(extremeScrollLeft)) {\n onScrollToEndBorder();\n endScrollLeft = extremeScrollLeft;\n }\n\n const startTime = now();\n\n (function scroll() {\n const time = now();\n const elapsed = Math.min((time - startTime) / scrollAnimationDuration, 1);\n\n const value = easeInOutSine(elapsed);\n\n const currentScrollLeft = startScrollLeft + (endScrollLeft - startScrollLeft) * value;\n scrollElement.scrollLeft = roundingAwayFromZero(currentScrollLeft);\n\n const scrollEnd =\n textDirection === 'ltr' ? Math.max(0, endScrollLeft) : Math.min(0, endScrollLeft);\n if (roundUpElementScrollLeft(scrollElement) !== scrollEnd && elapsed !== 1) {\n requestAnimationFrame(scroll);\n return;\n }\n\n onScrollEnd();\n animationQueue.shift();\n if (animationQueue.length > 0) {\n animationQueue[0]();\n }\n })();\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/HorizontalScroll\n */\nexport const HorizontalScroll = ({\n children,\n getScrollToLeft,\n getScrollToRight,\n showArrows = true,\n arrowSize = 'l',\n arrowOffsetY,\n scrollAnimationDuration = SCROLL_ONE_FRAME_TIME,\n getRef,\n scrollOnAnyWheel = false,\n inline = false,\n ...restProps\n}: HorizontalScrollProps): React.ReactNode => {\n const [canScrollLeft, setCanScrollLeft] = React.useState(false);\n const [canScrollRight, setCanScrollRight] = React.useState(false);\n const [directionRef, textDirection] = useDirection<HTMLDivElement>();\n const direction = textDirection || 'ltr';\n const setCanScrollStart = direction === 'ltr' ? setCanScrollLeft : setCanScrollRight;\n const setCanScrollEnd = direction === 'ltr' ? setCanScrollRight : setCanScrollLeft;\n\n const isCustomScrollingRef = React.useRef(false);\n\n const scrollerRef = useExternRef(getRef, directionRef);\n\n const animationQueue = React.useRef<VoidFunction[]>([]);\n\n const hasPointer = useAdaptivityHasPointer();\n\n const scrollTo = React.useCallback(\n (getScrollPosition: ScrollPositionHandler) => {\n const scrollElement = scrollerRef.current;\n\n animationQueue.current.push(() =>\n doScroll({\n scrollElement,\n getScrollPosition,\n animationQueue: animationQueue.current,\n onScrollToEndBorder: () => setCanScrollEnd(false),\n onScrollEnd: () => (isCustomScrollingRef.current = false),\n onScrollStart: () => (isCustomScrollingRef.current = true),\n initialScrollWidth: scrollElement?.firstElementChild?.scrollWidth || 0,\n scrollAnimationDuration,\n textDirection: direction,\n }),\n );\n if (animationQueue.current.length === 1) {\n animationQueue.current[0]();\n }\n },\n [scrollerRef, scrollAnimationDuration, direction, setCanScrollEnd],\n );\n\n const scrollToLeft = React.useCallback(() => {\n const getScrollPosition =\n getScrollToLeft ?? ((i: number) => i - scrollerRef.current!.offsetWidth);\n scrollTo(getScrollPosition);\n }, [getScrollToLeft, scrollTo, scrollerRef]);\n\n const scrollToRight = React.useCallback(() => {\n const getScrollPosition =\n getScrollToRight ?? ((i: number) => i + scrollerRef.current!.offsetWidth);\n scrollTo(getScrollPosition);\n }, [getScrollToRight, scrollTo, scrollerRef]);\n\n const calculateArrowsVisibility = React.useCallback(() => {\n if (showArrows && hasPointer && scrollerRef.current && !isCustomScrollingRef.current) {\n const scrollElement = scrollerRef.current;\n\n setCanScrollStart(scrollElement.scrollLeft !== 0);\n setCanScrollEnd(\n Math.abs(roundUpElementScrollLeft(scrollElement)) + scrollElement.offsetWidth <\n scrollElement.scrollWidth,\n );\n }\n }, [showArrows, hasPointer, scrollerRef, setCanScrollStart, setCanScrollEnd]);\n\n React.useEffect(calculateArrowsVisibility, [calculateArrowsVisibility, children]);\n\n const _onWheel = React.useCallback(\n (e: React.WheelEvent) => {\n scrollerRef.current!.scrollBy({ left: e.deltaX + e.deltaY, behavior: 'auto' });\n },\n [scrollerRef],\n );\n\n /**\n * Прокрутка с помощью любого колеса мыши\n */\n const onScrollWheel = React.useCallback(\n (e: React.WheelEvent) => {\n _onWheel(e);\n e.preventDefault();\n },\n [_onWheel],\n );\n\n const onArrowWheel = React.useCallback(\n (e: React.WheelEvent) => {\n if (e.deltaX || (e.deltaY && scrollOnAnyWheel)) {\n _onWheel(e);\n }\n },\n [_onWheel, scrollOnAnyWheel],\n );\n\n return (\n <RootComponent\n {...restProps}\n baseClassName={classNames(\n styles['HorizontalScroll'],\n 'vkuiInternalHorizontalScroll',\n showArrows === 'always' && styles['HorizontalScroll--withConstArrows'],\n inline && styles['HorizontalScroll--inline'],\n )}\n onMouseEnter={calculateArrowsVisibility}\n >\n {showArrows && (hasPointer || hasPointer === undefined) && canScrollLeft && (\n <ScrollArrow\n data-testid={process.env.NODE_ENV === 'test' ? 'ScrollArrowLeft' : undefined}\n size={arrowSize}\n offsetY={arrowOffsetY}\n direction=\"left\"\n aria-hidden\n tabIndex={-1}\n className={classNames(\n styles['HorizontalScroll__arrow'],\n styles['HorizontalScroll__arrowLeft'],\n )}\n onClick={scrollToLeft}\n onWheel={onArrowWheel}\n />\n )}\n {showArrows && (hasPointer || hasPointer === undefined) && canScrollRight && (\n <ScrollArrow\n data-testid={process.env.NODE_ENV === 'test' ? 'ScrollArrowRight' : undefined}\n size={arrowSize}\n offsetY={arrowOffsetY}\n direction=\"right\"\n aria-hidden\n tabIndex={-1}\n className={classNames(\n styles['HorizontalScroll__arrow'],\n styles['HorizontalScroll__arrowRight'],\n )}\n onClick={scrollToRight}\n onWheel={onArrowWheel}\n />\n )}\n <div\n className={styles['HorizontalScroll__in']}\n ref={scrollerRef}\n onScroll={calculateArrowsVisibility}\n onWheel={scrollOnAnyWheel ? onScrollWheel : undefined}\n >\n <div className={styles['HorizontalScroll__in-wrapper']}>{children}</div>\n </div>\n </RootComponent>\n );\n};\n"],"names":["React","classNames","useAdaptivityHasPointer","useDirection","useExternRef","easeInOutSine","RootComponent","ScrollArrow","now","performance","Date","roundingAwayFromZero","value","Math","ceil","floor","roundUpElementScrollLeft","el","scrollLeft","SCROLL_ONE_FRAME_TIME","doScroll","scrollElement","getScrollPosition","animationQueue","onScrollToEndBorder","onScrollEnd","onScrollStart","initialScrollWidth","scrollAnimationDuration","textDirection","extremeScrollLeft","offsetWidth","startScrollLeft","endScrollLeft","abs","startTime","scroll","time","elapsed","min","currentScrollLeft","scrollEnd","max","requestAnimationFrame","shift","length","HorizontalScroll","children","getScrollToLeft","getScrollToRight","showArrows","arrowSize","arrowOffsetY","getRef","scrollOnAnyWheel","inline","restProps","canScrollLeft","setCanScrollLeft","useState","canScrollRight","setCanScrollRight","directionRef","direction","setCanScrollStart","setCanScrollEnd","isCustomScrollingRef","useRef","scrollerRef","hasPointer","scrollTo","useCallback","current","push","firstElementChild","scrollWidth","scrollToLeft","i","scrollToRight","calculateArrowsVisibility","useEffect","_onWheel","e","scrollBy","left","deltaX","deltaY","behavior","onScrollWheel","preventDefault","onArrowWheel","baseClassName","onMouseEnter","undefined","data-testid","process","env","NODE_ENV","size","offsetY","aria-hidden","tabIndex","className","onClick","onWheel","div","ref","onScroll"],"mappings":"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"}
|
|
@@ -119,7 +119,7 @@ import { FocusTrap } from '../FocusTrap/FocusTrap';
|
|
|
119
119
|
mount: !hidden,
|
|
120
120
|
disabled: hidden,
|
|
121
121
|
autoFocus: disableInteractive ? false : autoFocus,
|
|
122
|
-
restoreFocus: restoreFocus ? onRestoreFocus : false,
|
|
122
|
+
restoreFocus: restoreFocus ? ()=>onRestoreFocus(restoreFocus) : false,
|
|
123
123
|
onClose: onEscapeKeyDown,
|
|
124
124
|
children: [
|
|
125
125
|
arrow,
|