@fountain-ui/lab 2.0.0-beta.15 → 2.0.0-beta.16

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.
@@ -10,8 +10,8 @@ var _reactNative = require("react-native");
10
10
  function createDefaultScrollAnimation(animatedValue, toValue) {
11
11
  return _reactNative.Animated.timing(animatedValue, {
12
12
  toValue: toValue,
13
- duration: 220,
14
- easing: _reactNative.Easing.bezier(0.35, 0.5, 0.5, 0.75),
13
+ duration: 180,
14
+ easing: _reactNative.Easing.bezier(0.2, 0.2, 0.2, 1),
15
15
  useNativeDriver: true
16
16
  });
17
17
  }
@@ -1 +1 @@
1
- {"version":3,"names":["createDefaultScrollAnimation","animatedValue","toValue","Animated","timing","duration","easing","Easing","bezier","useNativeDriver"],"sources":["createDefaultScrollAnimation.ts"],"sourcesContent":["import { Animated, Easing } from 'react-native';\n\nexport default function createDefaultScrollAnimation(\n animatedValue: Animated.Value,\n toValue: number,\n): Animated.CompositeAnimation {\n return Animated.timing(animatedValue, {\n toValue: toValue,\n duration: 220,\n easing: Easing.bezier(0.35, 0.5, 0.5, 0.75),\n useNativeDriver: true,\n });\n};\n"],"mappings":";;;;;;;AAAA;;AAEe,SAASA,4BAAT,CACXC,aADW,EAEXC,OAFW,EAGgB;EAC3B,OAAOC,qBAAA,CAASC,MAAT,CAAgBH,aAAhB,EAA+B;IAClCC,OAAO,EAAEA,OADyB;IAElCG,QAAQ,EAAE,GAFwB;IAGlCC,MAAM,EAAEC,mBAAA,CAAOC,MAAP,CAAc,IAAd,EAAoB,GAApB,EAAyB,GAAzB,EAA8B,IAA9B,CAH0B;IAIlCC,eAAe,EAAE;EAJiB,CAA/B,CAAP;AAMH;;AAAA"}
1
+ {"version":3,"names":["createDefaultScrollAnimation","animatedValue","toValue","Animated","timing","duration","easing","Easing","bezier","useNativeDriver"],"sources":["createDefaultScrollAnimation.ts"],"sourcesContent":["import { Animated, Easing } from 'react-native';\n\nexport default function createDefaultScrollAnimation(\n animatedValue: Animated.Value,\n toValue: number,\n): Animated.CompositeAnimation {\n return Animated.timing(animatedValue, {\n toValue: toValue,\n duration: 180,\n easing: Easing.bezier(0.2, 0.2, 0.2, 1),\n useNativeDriver: true,\n });\n};\n"],"mappings":";;;;;;;AAAA;;AAEe,SAASA,4BAAT,CACXC,aADW,EAEXC,OAFW,EAGgB;EAC3B,OAAOC,qBAAA,CAASC,MAAT,CAAgBH,aAAhB,EAA+B;IAClCC,OAAO,EAAEA,OADyB;IAElCG,QAAQ,EAAE,GAFwB;IAGlCC,MAAM,EAAEC,mBAAA,CAAOC,MAAP,CAAc,GAAd,EAAmB,GAAnB,EAAwB,GAAxB,EAA6B,CAA7B,CAH0B;IAIlCC,eAAe,EAAE;EAJiB,CAA/B,CAAP;AAMH;;AAAA"}
@@ -17,7 +17,15 @@ function useIndexController(params) {
17
17
  onIndexChange
18
18
  } = params;
19
19
  const currentIndexRef = (0, _react.useRef)(initialIndex);
20
+ const indexChangedRef = (0, _react.useRef)(false);
20
21
  const getCurrentIndex = (0, _react.useCallback)(() => currentIndexRef.current, []);
22
+ const notifyAnimationState = (0, _react.useCallback)(state => {
23
+ if (state === 'finished' || state === 'interrupted') {
24
+ if (indexChangedRef.current) {
25
+ onIndexChange === null || onIndexChange === void 0 ? void 0 : onIndexChange(getCurrentIndex());
26
+ }
27
+ }
28
+ }, [getCurrentIndex, onIndexChange]);
21
29
  const notifyOffsetHasChanged = (0, _react.useCallback)(offset => {
22
30
  const roundedOffset = Math.round(offset / itemWidth) * itemWidth; // To prevent floating point problem, make sure index is integer type.
23
31
 
@@ -25,12 +33,13 @@ function useIndexController(params) {
25
33
 
26
34
  if (nextIndex !== currentIndexRef.current) {
27
35
  currentIndexRef.current = nextIndex;
28
- onIndexChange === null || onIndexChange === void 0 ? void 0 : onIndexChange(nextIndex);
36
+ indexChangedRef.current = true;
29
37
  }
30
- }, [itemWidth, numberOfOriginalData, onIndexChange]);
38
+ }, [itemWidth, numberOfOriginalData]);
31
39
  return {
32
40
  getCurrentIndex,
33
41
  lastIndex: numberOfOriginalData - 1,
42
+ notifyAnimationState,
34
43
  notifyOffsetHasChanged
35
44
  };
36
45
  }
@@ -1 +1 @@
1
- {"version":3,"names":["useIndexController","params","initialIndex","itemWidth","numberOfOriginalData","onIndexChange","currentIndexRef","useRef","getCurrentIndex","useCallback","current","notifyOffsetHasChanged","offset","roundedOffset","Math","round","nextIndex","floor","mod","lastIndex"],"sources":["useIndexController.tsx"],"sourcesContent":["import React, { useCallback, useRef } from 'react';\nimport { mod } from '@fountain-ui/utils';\nimport type { IndexController } from '../types';\n\nexport interface UseIndexControllerParameters {\n initialIndex: number;\n itemWidth: number;\n numberOfOriginalData: number;\n onIndexChange?: (newIndex: number) => void;\n}\n\nexport default function useIndexController(params: UseIndexControllerParameters): IndexController {\n const {\n initialIndex,\n itemWidth,\n numberOfOriginalData,\n onIndexChange,\n } = params;\n\n const currentIndexRef = useRef<number>(initialIndex);\n\n const getCurrentIndex = useCallback(() => currentIndexRef.current, []);\n\n const notifyOffsetHasChanged = useCallback((offset: number) => {\n const roundedOffset = Math.round(offset / itemWidth) * itemWidth;\n\n // To prevent floating point problem, make sure index is integer type.\n const nextIndex = Math.floor(mod((-roundedOffset / itemWidth), numberOfOriginalData));\n\n if (nextIndex !== currentIndexRef.current) {\n currentIndexRef.current = nextIndex;\n\n onIndexChange?.(nextIndex);\n }\n }, [\n itemWidth,\n numberOfOriginalData,\n onIndexChange,\n ]);\n\n return {\n getCurrentIndex,\n lastIndex: numberOfOriginalData - 1,\n notifyOffsetHasChanged,\n };\n};\n"],"mappings":";;;;;;;AAAA;;AACA;;AAUe,SAASA,kBAAT,CAA4BC,MAA5B,EAAmF;EAC9F,MAAM;IACFC,YADE;IAEFC,SAFE;IAGFC,oBAHE;IAIFC;EAJE,IAKFJ,MALJ;EAOA,MAAMK,eAAe,GAAG,IAAAC,aAAA,EAAeL,YAAf,CAAxB;EAEA,MAAMM,eAAe,GAAG,IAAAC,kBAAA,EAAY,MAAMH,eAAe,CAACI,OAAlC,EAA2C,EAA3C,CAAxB;EAEA,MAAMC,sBAAsB,GAAG,IAAAF,kBAAA,EAAaG,MAAD,IAAoB;IAC3D,MAAMC,aAAa,GAAGC,IAAI,CAACC,KAAL,CAAWH,MAAM,GAAGT,SAApB,IAAiCA,SAAvD,CAD2D,CAG3D;;IACA,MAAMa,SAAS,GAAGF,IAAI,CAACG,KAAL,CAAW,IAAAC,UAAA,EAAK,CAACL,aAAD,GAAiBV,SAAtB,EAAkCC,oBAAlC,CAAX,CAAlB;;IAEA,IAAIY,SAAS,KAAKV,eAAe,CAACI,OAAlC,EAA2C;MACvCJ,eAAe,CAACI,OAAhB,GAA0BM,SAA1B;MAEAX,aAAa,SAAb,IAAAA,aAAa,WAAb,YAAAA,aAAa,CAAGW,SAAH,CAAb;IACH;EACJ,CAX8B,EAW5B,CACCb,SADD,EAECC,oBAFD,EAGCC,aAHD,CAX4B,CAA/B;EAiBA,OAAO;IACHG,eADG;IAEHW,SAAS,EAAEf,oBAAoB,GAAG,CAF/B;IAGHO;EAHG,CAAP;AAKH;;AAAA"}
1
+ {"version":3,"names":["useIndexController","params","initialIndex","itemWidth","numberOfOriginalData","onIndexChange","currentIndexRef","useRef","indexChangedRef","getCurrentIndex","useCallback","current","notifyAnimationState","state","notifyOffsetHasChanged","offset","roundedOffset","Math","round","nextIndex","floor","mod","lastIndex"],"sources":["useIndexController.tsx"],"sourcesContent":["import React, { useCallback, useRef } from 'react';\nimport { mod } from '@fountain-ui/utils';\nimport type { AnimationState, IndexController } from '../types';\n\nexport interface UseIndexControllerParameters {\n initialIndex: number;\n itemWidth: number;\n numberOfOriginalData: number;\n onIndexChange?: (newIndex: number) => void;\n}\n\nexport default function useIndexController(params: UseIndexControllerParameters): IndexController {\n const {\n initialIndex,\n itemWidth,\n numberOfOriginalData,\n onIndexChange,\n } = params;\n\n const currentIndexRef = useRef<number>(initialIndex);\n const indexChangedRef = useRef<boolean>(false);\n\n const getCurrentIndex = useCallback(() => currentIndexRef.current, []);\n\n const notifyAnimationState = useCallback((state: AnimationState) => {\n if (state === 'finished' || state === 'interrupted') {\n if (indexChangedRef.current) {\n onIndexChange?.(getCurrentIndex());\n }\n }\n }, [\n getCurrentIndex,\n onIndexChange,\n ]);\n\n const notifyOffsetHasChanged = useCallback((offset: number) => {\n const roundedOffset = Math.round(offset / itemWidth) * itemWidth;\n\n // To prevent floating point problem, make sure index is integer type.\n const nextIndex = Math.floor(mod((-roundedOffset / itemWidth), numberOfOriginalData));\n\n if (nextIndex !== currentIndexRef.current) {\n currentIndexRef.current = nextIndex;\n indexChangedRef.current = true;\n }\n }, [itemWidth, numberOfOriginalData]);\n\n return {\n getCurrentIndex,\n lastIndex: numberOfOriginalData - 1,\n notifyAnimationState,\n notifyOffsetHasChanged,\n };\n};\n"],"mappings":";;;;;;;AAAA;;AACA;;AAUe,SAASA,kBAAT,CAA4BC,MAA5B,EAAmF;EAC9F,MAAM;IACFC,YADE;IAEFC,SAFE;IAGFC,oBAHE;IAIFC;EAJE,IAKFJ,MALJ;EAOA,MAAMK,eAAe,GAAG,IAAAC,aAAA,EAAeL,YAAf,CAAxB;EACA,MAAMM,eAAe,GAAG,IAAAD,aAAA,EAAgB,KAAhB,CAAxB;EAEA,MAAME,eAAe,GAAG,IAAAC,kBAAA,EAAY,MAAMJ,eAAe,CAACK,OAAlC,EAA2C,EAA3C,CAAxB;EAEA,MAAMC,oBAAoB,GAAG,IAAAF,kBAAA,EAAaG,KAAD,IAA2B;IAChE,IAAIA,KAAK,KAAK,UAAV,IAAwBA,KAAK,KAAK,aAAtC,EAAqD;MACjD,IAAIL,eAAe,CAACG,OAApB,EAA6B;QACzBN,aAAa,SAAb,IAAAA,aAAa,WAAb,YAAAA,aAAa,CAAGI,eAAe,EAAlB,CAAb;MACH;IACJ;EACJ,CAN4B,EAM1B,CACCA,eADD,EAECJ,aAFD,CAN0B,CAA7B;EAWA,MAAMS,sBAAsB,GAAG,IAAAJ,kBAAA,EAAaK,MAAD,IAAoB;IAC3D,MAAMC,aAAa,GAAGC,IAAI,CAACC,KAAL,CAAWH,MAAM,GAAGZ,SAApB,IAAiCA,SAAvD,CAD2D,CAG3D;;IACA,MAAMgB,SAAS,GAAGF,IAAI,CAACG,KAAL,CAAW,IAAAC,UAAA,EAAK,CAACL,aAAD,GAAiBb,SAAtB,EAAkCC,oBAAlC,CAAX,CAAlB;;IAEA,IAAIe,SAAS,KAAKb,eAAe,CAACK,OAAlC,EAA2C;MACvCL,eAAe,CAACK,OAAhB,GAA0BQ,SAA1B;MACAX,eAAe,CAACG,OAAhB,GAA0B,IAA1B;IACH;EACJ,CAV8B,EAU5B,CAACR,SAAD,EAAYC,oBAAZ,CAV4B,CAA/B;EAYA,OAAO;IACHK,eADG;IAEHa,SAAS,EAAElB,oBAAoB,GAAG,CAF/B;IAGHQ,oBAHG;IAIHE;EAJG,CAAP;AAMH;;AAAA"}
@@ -45,6 +45,7 @@ function usePagingAnimation(params) {
45
45
  const {
46
46
  getCurrentIndex,
47
47
  lastIndex,
48
+ notifyAnimationState,
48
49
  notifyOffsetHasChanged
49
50
  } = indexController;
50
51
  const toValueRef = (0, _react.useRef)(0);
@@ -71,8 +72,7 @@ function usePagingAnimation(params) {
71
72
  translateX.setValue(0);
72
73
  }, [ensureOffsetBoundary, offsetX, translateX]);
73
74
  const interruptAnimation = (0, _react.useCallback)(() => {
74
- if (toValueRef.current === 0) {
75
- // Performance optimization
75
+ if (!isAnimatingRef.current) {
76
76
  return;
77
77
  }
78
78
 
@@ -81,16 +81,18 @@ function usePagingAnimation(params) {
81
81
  const prevOffset = currentOffsetRef.current;
82
82
  const totalOffset = prevOffset + lastValue;
83
83
  notifyOffsetHasChanged(totalOffset);
84
+ notifyAnimationState('interrupted');
84
85
  requireNewOffset(totalOffset);
85
86
  });
86
87
  }, [requireNewOffset, translateX]);
87
88
  const finalizeAnimation = (0, _react.useCallback)(() => {
89
+ notifyAnimationState('finished');
88
90
  isAnimatingRef.current = false;
89
91
  const prevOffset = currentOffsetRef.current;
90
92
  const toValue = toValueRef.current;
91
93
  const totalOffset = prevOffset + toValue;
92
94
  requireNewOffset(totalOffset);
93
- }, [requireNewOffset]);
95
+ }, [notifyAnimationState, requireNewOffset]);
94
96
  const startPagingAnimation = (0, _react.useCallback)((type, config) => {
95
97
  if (isAnimatingRef.current) {
96
98
  return;
@@ -148,6 +150,7 @@ function usePagingAnimation(params) {
148
150
  const toValue = compensateToValue(wantedToValue, currentOffsetRef.current);
149
151
  toValueRef.current = toValue;
150
152
  isAnimatingRef.current = true;
153
+ notifyOffsetHasChanged(currentOffsetRef.current + toValue);
151
154
 
152
155
  if (configWithDefaults.animated) {
153
156
  const animation = createScrollAnimation(translateX, toValue);
@@ -160,12 +163,11 @@ function usePagingAnimation(params) {
160
163
  finalizeAnimation();
161
164
  }
162
165
  });
166
+ notifyAnimationState('started');
163
167
  } else {
164
168
  finalizeAnimation();
165
169
  }
166
-
167
- notifyOffsetHasChanged(currentOffsetRef.current + toValue);
168
- }, [createScrollAnimation, getCurrentIndex, finalizeAnimation, itemWidth, lastIndex, loop, notifyOffsetHasChanged]);
170
+ }, [createScrollAnimation, getCurrentIndex, finalizeAnimation, itemWidth, lastIndex, loop, notifyAnimationState, notifyOffsetHasChanged]);
169
171
  return {
170
172
  interruptAnimation,
171
173
  startPagingAnimation
@@ -1 +1 @@
1
- {"version":3,"names":["directionToValue","itemWidth","direction","toValueCompensator","toValue","currentOffset","remainder","Math","abs","halfOfItemWidth","compensateVector","usePagingAnimation","params","createScrollAnimation","indexController","loop","numberOfData","offsetX","translateX","getCurrentIndex","lastIndex","notifyOffsetHasChanged","toValueRef","useRef","currentOffsetRef","isAnimatingRef","maxWidth","ensureOffsetBoundary","useCallback","offset","isCloseToEnd","signOfOffset","requireNewOffset","newOffset","nextOffset","current","setValue","interruptAnimation","stopAnimation","lastValue","prevOffset","totalOffset","finalizeAnimation","startPagingAnimation","type","config","configWithDefaults","animated","currentIndex","getValueByDirectionOnAllAdjacentItemsVisible","compensateToValue","getValueByDirectionalPagingOnLoopDisabled","_config","isOriginatedFromGesture","getValueByDirectionalPaging","_configWithDefaults","getValueByIndexPaging","index","distance","wantedToValue","animation","start","finished"],"sources":["usePagingAnimation.ts"],"sourcesContent":["import { useCallback, useRef } from 'react';\nimport { Animated } from 'react-native';\nimport type {\n CreateScrollAnimation,\n DirectionalPagingAnimationConfig,\n IndexController,\n IndexPagingAnimationConfig,\n PagingAnimationConfig,\n PagingAnimationType,\n PagingDirection,\n StartPagingAnimation,\n} from '../types';\n\nexport interface PagingAnimationParameters {\n createScrollAnimation: CreateScrollAnimation;\n itemWidth: number;\n indexController: IndexController;\n loop: boolean;\n numberOfData: number;\n offsetX: Animated.Value;\n translateX: Animated.Value;\n}\n\nexport interface UsePagingAnimation {\n interruptAnimation: () => void;\n startPagingAnimation: StartPagingAnimation;\n}\n\nfunction directionToValue(itemWidth: number) {\n return function (direction: PagingDirection): number {\n switch (direction) {\n case 'next':\n return -itemWidth;\n case 'prev':\n return itemWidth;\n case 'stay':\n return 0;\n }\n };\n}\n\nfunction toValueCompensator(itemWidth: number) {\n return function (toValue: number, currentOffset: number): number {\n const remainder = Math.abs(currentOffset % itemWidth);\n\n const halfOfItemWidth = Math.abs(itemWidth / 2);\n const compensateVector = remainder > halfOfItemWidth\n ? remainder - itemWidth\n : remainder;\n\n const direction = currentOffset > 0 ? -1 : 1;\n\n return toValue + (direction * compensateVector);\n };\n}\n\nexport default function usePagingAnimation(params: PagingAnimationParameters): UsePagingAnimation {\n const {\n createScrollAnimation,\n itemWidth,\n indexController,\n loop,\n numberOfData,\n offsetX,\n translateX,\n } = params;\n\n const {\n getCurrentIndex,\n lastIndex,\n notifyOffsetHasChanged,\n } = indexController;\n\n const toValueRef = useRef<number>(0);\n const currentOffsetRef = useRef<number>(0);\n\n const isAnimatingRef = useRef<boolean>(false);\n\n const maxWidth = Math.abs(numberOfData * itemWidth);\n\n const ensureOffsetBoundary: (offset: number) => number = useCallback((offset: number) => {\n if (loop) {\n const isCloseToEnd = Math.abs(offset) >= (maxWidth - itemWidth);\n if (isCloseToEnd) {\n const signOfOffset = offset > 0 ? 1 : -1;\n return offset + (-signOfOffset * maxWidth);\n }\n }\n\n return offset % maxWidth;\n }, [itemWidth, loop, maxWidth]);\n\n const requireNewOffset = useCallback((newOffset: number) => {\n const nextOffset = ensureOffsetBoundary(newOffset);\n\n currentOffsetRef.current = nextOffset;\n offsetX.setValue(nextOffset);\n\n toValueRef.current = 0;\n translateX.setValue(0);\n }, [\n ensureOffsetBoundary,\n offsetX,\n translateX,\n ]);\n\n const interruptAnimation = useCallback(() => {\n if (toValueRef.current === 0) {\n // Performance optimization\n return;\n }\n\n translateX.stopAnimation(lastValue => {\n isAnimatingRef.current = false;\n\n const prevOffset = currentOffsetRef.current;\n const totalOffset = prevOffset + lastValue;\n\n notifyOffsetHasChanged(totalOffset);\n\n requireNewOffset(totalOffset);\n });\n }, [requireNewOffset, translateX]);\n\n const finalizeAnimation = useCallback(() => {\n isAnimatingRef.current = false;\n\n const prevOffset = currentOffsetRef.current;\n const toValue = toValueRef.current;\n const totalOffset = prevOffset + toValue;\n\n requireNewOffset(totalOffset);\n }, [requireNewOffset]);\n\n const startPagingAnimation = useCallback((type: PagingAnimationType, config: PagingAnimationConfig) => {\n if (isAnimatingRef.current) {\n return;\n }\n\n const configWithDefaults: PagingAnimationConfig = {\n animated: true,\n ...config,\n };\n\n const currentIndex = getCurrentIndex();\n\n const getValueByDirectionOnAllAdjacentItemsVisible = directionToValue(itemWidth);\n const compensateToValue = toValueCompensator(itemWidth);\n\n const getValueByDirectionalPagingOnLoopDisabled = (_config: DirectionalPagingAnimationConfig): number => {\n const { direction, isOriginatedFromGesture } = _config;\n\n if (currentIndex === 0 && direction === 'prev') {\n return isOriginatedFromGesture\n ? getValueByDirectionOnAllAdjacentItemsVisible('stay')\n : -lastIndex * itemWidth; // last position\n } else if (currentIndex === lastIndex && direction === 'next') {\n return isOriginatedFromGesture\n ? getValueByDirectionOnAllAdjacentItemsVisible('stay')\n : lastIndex * itemWidth; // first position\n }\n return getValueByDirectionOnAllAdjacentItemsVisible(direction);\n };\n\n const getValueByDirectionalPaging = (_config: DirectionalPagingAnimationConfig): number => {\n const _configWithDefaults: DirectionalPagingAnimationConfig = {\n isOriginatedFromGesture: false,\n ..._config,\n };\n\n return loop\n ? getValueByDirectionOnAllAdjacentItemsVisible(_configWithDefaults.direction)\n : getValueByDirectionalPagingOnLoopDisabled(_configWithDefaults);\n };\n\n const getValueByIndexPaging = ({ index }: IndexPagingAnimationConfig): number => {\n if (index < 0 || index > lastIndex || index === currentIndex) {\n // no animation if index is invalid or equals to current index\n return 0;\n }\n\n const distance = Math.abs(currentIndex - index) * itemWidth;\n const direction = index > currentIndex ? -1 : 1;\n\n return distance * direction;\n };\n\n const wantedToValue = type === 'directional'\n // @ts-ignore\n ? getValueByDirectionalPaging(configWithDefaults)\n // @ts-ignore\n : getValueByIndexPaging(configWithDefaults);\n\n const toValue = compensateToValue(wantedToValue, currentOffsetRef.current);\n\n toValueRef.current = toValue;\n isAnimatingRef.current = true;\n\n if (configWithDefaults.animated) {\n const animation = createScrollAnimation(translateX, toValue);\n\n animation.start(({ finished }) => {\n if (finished) {\n finalizeAnimation();\n }\n });\n } else {\n finalizeAnimation();\n }\n\n notifyOffsetHasChanged(currentOffsetRef.current + toValue);\n }, [\n createScrollAnimation,\n getCurrentIndex,\n finalizeAnimation,\n itemWidth,\n lastIndex,\n loop,\n notifyOffsetHasChanged,\n ]);\n\n return {\n interruptAnimation,\n startPagingAnimation,\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"names":["directionToValue","itemWidth","direction","toValueCompensator","toValue","currentOffset","remainder","Math","abs","halfOfItemWidth","compensateVector","usePagingAnimation","params","createScrollAnimation","indexController","loop","numberOfData","offsetX","translateX","getCurrentIndex","lastIndex","notifyAnimationState","notifyOffsetHasChanged","toValueRef","useRef","currentOffsetRef","isAnimatingRef","maxWidth","ensureOffsetBoundary","useCallback","offset","isCloseToEnd","signOfOffset","requireNewOffset","newOffset","nextOffset","current","setValue","interruptAnimation","stopAnimation","lastValue","prevOffset","totalOffset","finalizeAnimation","startPagingAnimation","type","config","configWithDefaults","animated","currentIndex","getValueByDirectionOnAllAdjacentItemsVisible","compensateToValue","getValueByDirectionalPagingOnLoopDisabled","_config","isOriginatedFromGesture","getValueByDirectionalPaging","_configWithDefaults","getValueByIndexPaging","index","distance","wantedToValue","animation","start","finished"],"sources":["usePagingAnimation.ts"],"sourcesContent":["import { useCallback, useRef } from 'react';\nimport { Animated } from 'react-native';\nimport type {\n CreateScrollAnimation,\n DirectionalPagingAnimationConfig,\n IndexController,\n IndexPagingAnimationConfig,\n PagingAnimationConfig,\n PagingAnimationType,\n PagingDirection,\n StartPagingAnimation,\n} from '../types';\n\nexport interface PagingAnimationParameters {\n createScrollAnimation: CreateScrollAnimation;\n itemWidth: number;\n indexController: IndexController;\n loop: boolean;\n numberOfData: number;\n offsetX: Animated.Value;\n translateX: Animated.Value;\n}\n\nexport interface UsePagingAnimation {\n interruptAnimation: () => void;\n startPagingAnimation: StartPagingAnimation;\n}\n\nfunction directionToValue(itemWidth: number) {\n return function (direction: PagingDirection): number {\n switch (direction) {\n case 'next':\n return -itemWidth;\n case 'prev':\n return itemWidth;\n case 'stay':\n return 0;\n }\n };\n}\n\nfunction toValueCompensator(itemWidth: number) {\n return function (toValue: number, currentOffset: number): number {\n const remainder = Math.abs(currentOffset % itemWidth);\n\n const halfOfItemWidth = Math.abs(itemWidth / 2);\n const compensateVector = remainder > halfOfItemWidth\n ? remainder - itemWidth\n : remainder;\n\n const direction = currentOffset > 0 ? -1 : 1;\n\n return toValue + (direction * compensateVector);\n };\n}\n\nexport default function usePagingAnimation(params: PagingAnimationParameters): UsePagingAnimation {\n const {\n createScrollAnimation,\n itemWidth,\n indexController,\n loop,\n numberOfData,\n offsetX,\n translateX,\n } = params;\n\n const {\n getCurrentIndex,\n lastIndex,\n notifyAnimationState,\n notifyOffsetHasChanged,\n } = indexController;\n\n const toValueRef = useRef<number>(0);\n const currentOffsetRef = useRef<number>(0);\n\n const isAnimatingRef = useRef<boolean>(false);\n\n const maxWidth = Math.abs(numberOfData * itemWidth);\n\n const ensureOffsetBoundary: (offset: number) => number = useCallback((offset: number) => {\n if (loop) {\n const isCloseToEnd = Math.abs(offset) >= (maxWidth - itemWidth);\n if (isCloseToEnd) {\n const signOfOffset = offset > 0 ? 1 : -1;\n return offset + (-signOfOffset * maxWidth);\n }\n }\n\n return offset % maxWidth;\n }, [itemWidth, loop, maxWidth]);\n\n const requireNewOffset = useCallback((newOffset: number) => {\n const nextOffset = ensureOffsetBoundary(newOffset);\n\n currentOffsetRef.current = nextOffset;\n offsetX.setValue(nextOffset);\n\n toValueRef.current = 0;\n translateX.setValue(0);\n }, [\n ensureOffsetBoundary,\n offsetX,\n translateX,\n ]);\n\n const interruptAnimation = useCallback(() => {\n if (!isAnimatingRef.current) {\n return;\n }\n\n translateX.stopAnimation(lastValue => {\n isAnimatingRef.current = false;\n\n const prevOffset = currentOffsetRef.current;\n const totalOffset = prevOffset + lastValue;\n\n notifyOffsetHasChanged(totalOffset);\n notifyAnimationState('interrupted');\n\n requireNewOffset(totalOffset);\n });\n }, [requireNewOffset, translateX]);\n\n const finalizeAnimation = useCallback(() => {\n notifyAnimationState('finished');\n\n isAnimatingRef.current = false;\n\n const prevOffset = currentOffsetRef.current;\n const toValue = toValueRef.current;\n const totalOffset = prevOffset + toValue;\n\n requireNewOffset(totalOffset);\n }, [\n notifyAnimationState,\n requireNewOffset,\n ]);\n\n const startPagingAnimation = useCallback((type: PagingAnimationType, config: PagingAnimationConfig) => {\n if (isAnimatingRef.current) {\n return;\n }\n\n const configWithDefaults: PagingAnimationConfig = {\n animated: true,\n ...config,\n };\n\n const currentIndex = getCurrentIndex();\n\n const getValueByDirectionOnAllAdjacentItemsVisible = directionToValue(itemWidth);\n const compensateToValue = toValueCompensator(itemWidth);\n\n const getValueByDirectionalPagingOnLoopDisabled = (_config: DirectionalPagingAnimationConfig): number => {\n const { direction, isOriginatedFromGesture } = _config;\n\n if (currentIndex === 0 && direction === 'prev') {\n return isOriginatedFromGesture\n ? getValueByDirectionOnAllAdjacentItemsVisible('stay')\n : -lastIndex * itemWidth; // last position\n } else if (currentIndex === lastIndex && direction === 'next') {\n return isOriginatedFromGesture\n ? getValueByDirectionOnAllAdjacentItemsVisible('stay')\n : lastIndex * itemWidth; // first position\n }\n return getValueByDirectionOnAllAdjacentItemsVisible(direction);\n };\n\n const getValueByDirectionalPaging = (_config: DirectionalPagingAnimationConfig): number => {\n const _configWithDefaults: DirectionalPagingAnimationConfig = {\n isOriginatedFromGesture: false,\n ..._config,\n };\n\n return loop\n ? getValueByDirectionOnAllAdjacentItemsVisible(_configWithDefaults.direction)\n : getValueByDirectionalPagingOnLoopDisabled(_configWithDefaults);\n };\n\n const getValueByIndexPaging = ({ index }: IndexPagingAnimationConfig): number => {\n if (index < 0 || index > lastIndex || index === currentIndex) {\n // no animation if index is invalid or equals to current index\n return 0;\n }\n\n const distance = Math.abs(currentIndex - index) * itemWidth;\n const direction = index > currentIndex ? -1 : 1;\n\n return distance * direction;\n };\n\n const wantedToValue = type === 'directional'\n // @ts-ignore\n ? getValueByDirectionalPaging(configWithDefaults)\n // @ts-ignore\n : getValueByIndexPaging(configWithDefaults);\n\n const toValue = compensateToValue(wantedToValue, currentOffsetRef.current);\n\n toValueRef.current = toValue;\n isAnimatingRef.current = true;\n\n notifyOffsetHasChanged(currentOffsetRef.current + toValue);\n\n if (configWithDefaults.animated) {\n const animation = createScrollAnimation(translateX, toValue);\n\n animation.start(({ finished }) => {\n if (finished) {\n finalizeAnimation();\n }\n });\n\n notifyAnimationState('started');\n } else {\n finalizeAnimation();\n }\n }, [\n createScrollAnimation,\n getCurrentIndex,\n finalizeAnimation,\n itemWidth,\n lastIndex,\n loop,\n notifyAnimationState,\n notifyOffsetHasChanged,\n ]);\n\n return {\n interruptAnimation,\n startPagingAnimation,\n };\n};\n"],"mappings":"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"}
@@ -4,4 +4,5 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  const directions = ['next', 'prev', 'stay'];
7
+ const animationStates = ['started', 'finished', 'interrupted'];
7
8
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["directions"],"sources":["types.ts"],"sourcesContent":["import type { ReactElement } from 'react';\nimport type { Animated, ViewProps } from 'react-native';\n\nconst directions = ['next', 'prev', 'stay'] as const;\n\nexport type PagingDirection = (typeof directions)[number];\n\nexport type ItemHeight = number | 'auto';\n\nexport interface RenderItem<T> {\n (info: { item: T, index: number, interpolation: Animated.AnimatedInterpolation }): ReactElement | null;\n}\n\nexport interface CreateScrollAnimation {\n (aValue: Animated.AnimatedValue, toValue: number): Animated.CompositeAnimation;\n}\n\nexport interface CreateItemStyle {\n (itemInterpolation: Animated.AnimatedInterpolation, itemWidth: number): Animated.AnimatedProps<ViewProps['style']>;\n}\n\nexport interface GetCurrentIndex {\n (): number;\n}\n\nexport interface IndexController {\n getCurrentIndex: GetCurrentIndex;\n lastIndex: number;\n notifyOffsetHasChanged: (offset: number) => void;\n}\n\nexport type PagingAnimationType = 'directional' | 'index';\n\nexport interface BasePagingAnimationConfig {\n animated?: boolean;\n}\n\nexport interface DirectionalPagingAnimationConfig extends BasePagingAnimationConfig {\n direction: PagingDirection;\n isOriginatedFromGesture?: boolean;\n}\n\nexport interface IndexPagingAnimationConfig extends BasePagingAnimationConfig {\n index: number;\n}\n\nexport type PagingAnimationConfig = DirectionalPagingAnimationConfig | IndexPagingAnimationConfig;\n\nexport interface StartPagingAnimation {\n (type: PagingAnimationType, config: PagingAnimationConfig): void;\n}\n\nexport type VisibleIndexRanges = Array<[number, number]>;\n\nexport interface StoreSubscription {\n (): void;\n}\n\nexport interface ItemVisibilityStore {\n dispatch: (ranges: VisibleIndexRanges) => void;\n subscribe: (listener: (ranges: VisibleIndexRanges) => void) => StoreSubscription;\n removeAllListeners: () => void;\n}\n\nexport interface AutoplayController {\n pause: () => void;\n resume: () => void;\n}\n\nexport interface ScrollToOption {\n index: number;\n animated?: boolean;\n}\n\nexport interface CarouselInstance {\n /**\n * Get current visible item index.\n */\n getCurrentIndex: GetCurrentIndex;\n\n /**\n * Scroll to next visible item.\n */\n next: () => void;\n\n /**\n * Scroll to previous visible item.\n */\n prev: () => void;\n\n /**\n * Scroll to desired indexed item.\n * Invalid index is ignored.\n */\n scrollTo: (option: ScrollToOption) => void;\n}\n"],"mappings":";;;;;AAGA,MAAMA,UAAU,GAAG,CAAC,MAAD,EAAS,MAAT,EAAiB,MAAjB,CAAnB"}
1
+ {"version":3,"names":["directions","animationStates"],"sources":["types.ts"],"sourcesContent":["import type { ReactElement } from 'react';\nimport type { Animated, ViewProps } from 'react-native';\n\nconst directions = ['next', 'prev', 'stay'] as const;\n\nexport type PagingDirection = (typeof directions)[number];\n\nconst animationStates = ['started', 'finished', 'interrupted'] as const;\n\nexport type AnimationState = (typeof animationStates)[number];\n\nexport type ItemHeight = number | 'auto';\n\nexport interface RenderItem<T> {\n (info: { item: T, index: number, interpolation: Animated.AnimatedInterpolation }): ReactElement | null;\n}\n\nexport interface CreateScrollAnimation {\n (aValue: Animated.AnimatedValue, toValue: number): Animated.CompositeAnimation;\n}\n\nexport interface CreateItemStyle {\n (itemInterpolation: Animated.AnimatedInterpolation, itemWidth: number): Animated.AnimatedProps<ViewProps['style']>;\n}\n\nexport interface GetCurrentIndex {\n (): number;\n}\n\nexport interface IndexController {\n getCurrentIndex: GetCurrentIndex;\n lastIndex: number;\n notifyAnimationState: (state: AnimationState) => void;\n notifyOffsetHasChanged: (offset: number) => void;\n}\n\nexport type PagingAnimationType = 'directional' | 'index';\n\nexport interface BasePagingAnimationConfig {\n animated?: boolean;\n}\n\nexport interface DirectionalPagingAnimationConfig extends BasePagingAnimationConfig {\n direction: PagingDirection;\n isOriginatedFromGesture?: boolean;\n}\n\nexport interface IndexPagingAnimationConfig extends BasePagingAnimationConfig {\n index: number;\n}\n\nexport type PagingAnimationConfig = DirectionalPagingAnimationConfig | IndexPagingAnimationConfig;\n\nexport interface StartPagingAnimation {\n (type: PagingAnimationType, config: PagingAnimationConfig): void;\n}\n\nexport type VisibleIndexRanges = Array<[number, number]>;\n\nexport interface StoreSubscription {\n (): void;\n}\n\nexport interface ItemVisibilityStore {\n dispatch: (ranges: VisibleIndexRanges) => void;\n subscribe: (listener: (ranges: VisibleIndexRanges) => void) => StoreSubscription;\n removeAllListeners: () => void;\n}\n\nexport interface AutoplayController {\n pause: () => void;\n resume: () => void;\n}\n\nexport interface ScrollToOption {\n index: number;\n animated?: boolean;\n}\n\nexport interface CarouselInstance {\n /**\n * Get current visible item index.\n */\n getCurrentIndex: GetCurrentIndex;\n\n /**\n * Scroll to next visible item.\n */\n next: () => void;\n\n /**\n * Scroll to previous visible item.\n */\n prev: () => void;\n\n /**\n * Scroll to desired indexed item.\n * Invalid index is ignored.\n */\n scrollTo: (option: ScrollToOption) => void;\n}\n"],"mappings":";;;;;AAGA,MAAMA,UAAU,GAAG,CAAC,MAAD,EAAS,MAAT,EAAiB,MAAjB,CAAnB;AAIA,MAAMC,eAAe,GAAG,CAAC,SAAD,EAAY,UAAZ,EAAwB,aAAxB,CAAxB"}
@@ -2,8 +2,8 @@ import { Animated, Easing } from 'react-native';
2
2
  export default function createDefaultScrollAnimation(animatedValue, toValue) {
3
3
  return Animated.timing(animatedValue, {
4
4
  toValue: toValue,
5
- duration: 220,
6
- easing: Easing.bezier(0.35, 0.5, 0.5, 0.75),
5
+ duration: 180,
6
+ easing: Easing.bezier(0.2, 0.2, 0.2, 1),
7
7
  useNativeDriver: true
8
8
  });
9
9
  }
@@ -1 +1 @@
1
- {"version":3,"names":["Animated","Easing","createDefaultScrollAnimation","animatedValue","toValue","timing","duration","easing","bezier","useNativeDriver"],"sources":["createDefaultScrollAnimation.ts"],"sourcesContent":["import { Animated, Easing } from 'react-native';\n\nexport default function createDefaultScrollAnimation(\n animatedValue: Animated.Value,\n toValue: number,\n): Animated.CompositeAnimation {\n return Animated.timing(animatedValue, {\n toValue: toValue,\n duration: 220,\n easing: Easing.bezier(0.35, 0.5, 0.5, 0.75),\n useNativeDriver: true,\n });\n};\n"],"mappings":"AAAA,SAASA,QAAT,EAAmBC,MAAnB,QAAiC,cAAjC;AAEA,eAAe,SAASC,4BAAT,CACXC,aADW,EAEXC,OAFW,EAGgB;EAC3B,OAAOJ,QAAQ,CAACK,MAAT,CAAgBF,aAAhB,EAA+B;IAClCC,OAAO,EAAEA,OADyB;IAElCE,QAAQ,EAAE,GAFwB;IAGlCC,MAAM,EAAEN,MAAM,CAACO,MAAP,CAAc,IAAd,EAAoB,GAApB,EAAyB,GAAzB,EAA8B,IAA9B,CAH0B;IAIlCC,eAAe,EAAE;EAJiB,CAA/B,CAAP;AAMH;AAAA"}
1
+ {"version":3,"names":["Animated","Easing","createDefaultScrollAnimation","animatedValue","toValue","timing","duration","easing","bezier","useNativeDriver"],"sources":["createDefaultScrollAnimation.ts"],"sourcesContent":["import { Animated, Easing } from 'react-native';\n\nexport default function createDefaultScrollAnimation(\n animatedValue: Animated.Value,\n toValue: number,\n): Animated.CompositeAnimation {\n return Animated.timing(animatedValue, {\n toValue: toValue,\n duration: 180,\n easing: Easing.bezier(0.2, 0.2, 0.2, 1),\n useNativeDriver: true,\n });\n};\n"],"mappings":"AAAA,SAASA,QAAT,EAAmBC,MAAnB,QAAiC,cAAjC;AAEA,eAAe,SAASC,4BAAT,CACXC,aADW,EAEXC,OAFW,EAGgB;EAC3B,OAAOJ,QAAQ,CAACK,MAAT,CAAgBF,aAAhB,EAA+B;IAClCC,OAAO,EAAEA,OADyB;IAElCE,QAAQ,EAAE,GAFwB;IAGlCC,MAAM,EAAEN,MAAM,CAACO,MAAP,CAAc,GAAd,EAAmB,GAAnB,EAAwB,GAAxB,EAA6B,CAA7B,CAH0B;IAIlCC,eAAe,EAAE;EAJiB,CAA/B,CAAP;AAMH;AAAA"}
@@ -8,7 +8,15 @@ export default function useIndexController(params) {
8
8
  onIndexChange
9
9
  } = params;
10
10
  const currentIndexRef = useRef(initialIndex);
11
+ const indexChangedRef = useRef(false);
11
12
  const getCurrentIndex = useCallback(() => currentIndexRef.current, []);
13
+ const notifyAnimationState = useCallback(state => {
14
+ if (state === 'finished' || state === 'interrupted') {
15
+ if (indexChangedRef.current) {
16
+ onIndexChange === null || onIndexChange === void 0 ? void 0 : onIndexChange(getCurrentIndex());
17
+ }
18
+ }
19
+ }, [getCurrentIndex, onIndexChange]);
12
20
  const notifyOffsetHasChanged = useCallback(offset => {
13
21
  const roundedOffset = Math.round(offset / itemWidth) * itemWidth; // To prevent floating point problem, make sure index is integer type.
14
22
 
@@ -16,12 +24,13 @@ export default function useIndexController(params) {
16
24
 
17
25
  if (nextIndex !== currentIndexRef.current) {
18
26
  currentIndexRef.current = nextIndex;
19
- onIndexChange === null || onIndexChange === void 0 ? void 0 : onIndexChange(nextIndex);
27
+ indexChangedRef.current = true;
20
28
  }
21
- }, [itemWidth, numberOfOriginalData, onIndexChange]);
29
+ }, [itemWidth, numberOfOriginalData]);
22
30
  return {
23
31
  getCurrentIndex,
24
32
  lastIndex: numberOfOriginalData - 1,
33
+ notifyAnimationState,
25
34
  notifyOffsetHasChanged
26
35
  };
27
36
  }
@@ -1 +1 @@
1
- {"version":3,"names":["useCallback","useRef","mod","useIndexController","params","initialIndex","itemWidth","numberOfOriginalData","onIndexChange","currentIndexRef","getCurrentIndex","current","notifyOffsetHasChanged","offset","roundedOffset","Math","round","nextIndex","floor","lastIndex"],"sources":["useIndexController.tsx"],"sourcesContent":["import React, { useCallback, useRef } from 'react';\nimport { mod } from '@fountain-ui/utils';\nimport type { IndexController } from '../types';\n\nexport interface UseIndexControllerParameters {\n initialIndex: number;\n itemWidth: number;\n numberOfOriginalData: number;\n onIndexChange?: (newIndex: number) => void;\n}\n\nexport default function useIndexController(params: UseIndexControllerParameters): IndexController {\n const {\n initialIndex,\n itemWidth,\n numberOfOriginalData,\n onIndexChange,\n } = params;\n\n const currentIndexRef = useRef<number>(initialIndex);\n\n const getCurrentIndex = useCallback(() => currentIndexRef.current, []);\n\n const notifyOffsetHasChanged = useCallback((offset: number) => {\n const roundedOffset = Math.round(offset / itemWidth) * itemWidth;\n\n // To prevent floating point problem, make sure index is integer type.\n const nextIndex = Math.floor(mod((-roundedOffset / itemWidth), numberOfOriginalData));\n\n if (nextIndex !== currentIndexRef.current) {\n currentIndexRef.current = nextIndex;\n\n onIndexChange?.(nextIndex);\n }\n }, [\n itemWidth,\n numberOfOriginalData,\n onIndexChange,\n ]);\n\n return {\n getCurrentIndex,\n lastIndex: numberOfOriginalData - 1,\n notifyOffsetHasChanged,\n };\n};\n"],"mappings":"AAAA,SAAgBA,WAAhB,EAA6BC,MAA7B,QAA2C,OAA3C;AACA,SAASC,GAAT,QAAoB,oBAApB;AAUA,eAAe,SAASC,kBAAT,CAA4BC,MAA5B,EAAmF;EAC9F,MAAM;IACFC,YADE;IAEFC,SAFE;IAGFC,oBAHE;IAIFC;EAJE,IAKFJ,MALJ;EAOA,MAAMK,eAAe,GAAGR,MAAM,CAASI,YAAT,CAA9B;EAEA,MAAMK,eAAe,GAAGV,WAAW,CAAC,MAAMS,eAAe,CAACE,OAAvB,EAAgC,EAAhC,CAAnC;EAEA,MAAMC,sBAAsB,GAAGZ,WAAW,CAAEa,MAAD,IAAoB;IAC3D,MAAMC,aAAa,GAAGC,IAAI,CAACC,KAAL,CAAWH,MAAM,GAAGP,SAApB,IAAiCA,SAAvD,CAD2D,CAG3D;;IACA,MAAMW,SAAS,GAAGF,IAAI,CAACG,KAAL,CAAWhB,GAAG,CAAE,CAACY,aAAD,GAAiBR,SAAnB,EAA+BC,oBAA/B,CAAd,CAAlB;;IAEA,IAAIU,SAAS,KAAKR,eAAe,CAACE,OAAlC,EAA2C;MACvCF,eAAe,CAACE,OAAhB,GAA0BM,SAA1B;MAEAT,aAAa,SAAb,IAAAA,aAAa,WAAb,YAAAA,aAAa,CAAGS,SAAH,CAAb;IACH;EACJ,CAXyC,EAWvC,CACCX,SADD,EAECC,oBAFD,EAGCC,aAHD,CAXuC,CAA1C;EAiBA,OAAO;IACHE,eADG;IAEHS,SAAS,EAAEZ,oBAAoB,GAAG,CAF/B;IAGHK;EAHG,CAAP;AAKH;AAAA"}
1
+ {"version":3,"names":["useCallback","useRef","mod","useIndexController","params","initialIndex","itemWidth","numberOfOriginalData","onIndexChange","currentIndexRef","indexChangedRef","getCurrentIndex","current","notifyAnimationState","state","notifyOffsetHasChanged","offset","roundedOffset","Math","round","nextIndex","floor","lastIndex"],"sources":["useIndexController.tsx"],"sourcesContent":["import React, { useCallback, useRef } from 'react';\nimport { mod } from '@fountain-ui/utils';\nimport type { AnimationState, IndexController } from '../types';\n\nexport interface UseIndexControllerParameters {\n initialIndex: number;\n itemWidth: number;\n numberOfOriginalData: number;\n onIndexChange?: (newIndex: number) => void;\n}\n\nexport default function useIndexController(params: UseIndexControllerParameters): IndexController {\n const {\n initialIndex,\n itemWidth,\n numberOfOriginalData,\n onIndexChange,\n } = params;\n\n const currentIndexRef = useRef<number>(initialIndex);\n const indexChangedRef = useRef<boolean>(false);\n\n const getCurrentIndex = useCallback(() => currentIndexRef.current, []);\n\n const notifyAnimationState = useCallback((state: AnimationState) => {\n if (state === 'finished' || state === 'interrupted') {\n if (indexChangedRef.current) {\n onIndexChange?.(getCurrentIndex());\n }\n }\n }, [\n getCurrentIndex,\n onIndexChange,\n ]);\n\n const notifyOffsetHasChanged = useCallback((offset: number) => {\n const roundedOffset = Math.round(offset / itemWidth) * itemWidth;\n\n // To prevent floating point problem, make sure index is integer type.\n const nextIndex = Math.floor(mod((-roundedOffset / itemWidth), numberOfOriginalData));\n\n if (nextIndex !== currentIndexRef.current) {\n currentIndexRef.current = nextIndex;\n indexChangedRef.current = true;\n }\n }, [itemWidth, numberOfOriginalData]);\n\n return {\n getCurrentIndex,\n lastIndex: numberOfOriginalData - 1,\n notifyAnimationState,\n notifyOffsetHasChanged,\n };\n};\n"],"mappings":"AAAA,SAAgBA,WAAhB,EAA6BC,MAA7B,QAA2C,OAA3C;AACA,SAASC,GAAT,QAAoB,oBAApB;AAUA,eAAe,SAASC,kBAAT,CAA4BC,MAA5B,EAAmF;EAC9F,MAAM;IACFC,YADE;IAEFC,SAFE;IAGFC,oBAHE;IAIFC;EAJE,IAKFJ,MALJ;EAOA,MAAMK,eAAe,GAAGR,MAAM,CAASI,YAAT,CAA9B;EACA,MAAMK,eAAe,GAAGT,MAAM,CAAU,KAAV,CAA9B;EAEA,MAAMU,eAAe,GAAGX,WAAW,CAAC,MAAMS,eAAe,CAACG,OAAvB,EAAgC,EAAhC,CAAnC;EAEA,MAAMC,oBAAoB,GAAGb,WAAW,CAAEc,KAAD,IAA2B;IAChE,IAAIA,KAAK,KAAK,UAAV,IAAwBA,KAAK,KAAK,aAAtC,EAAqD;MACjD,IAAIJ,eAAe,CAACE,OAApB,EAA6B;QACzBJ,aAAa,SAAb,IAAAA,aAAa,WAAb,YAAAA,aAAa,CAAGG,eAAe,EAAlB,CAAb;MACH;IACJ;EACJ,CANuC,EAMrC,CACCA,eADD,EAECH,aAFD,CANqC,CAAxC;EAWA,MAAMO,sBAAsB,GAAGf,WAAW,CAAEgB,MAAD,IAAoB;IAC3D,MAAMC,aAAa,GAAGC,IAAI,CAACC,KAAL,CAAWH,MAAM,GAAGV,SAApB,IAAiCA,SAAvD,CAD2D,CAG3D;;IACA,MAAMc,SAAS,GAAGF,IAAI,CAACG,KAAL,CAAWnB,GAAG,CAAE,CAACe,aAAD,GAAiBX,SAAnB,EAA+BC,oBAA/B,CAAd,CAAlB;;IAEA,IAAIa,SAAS,KAAKX,eAAe,CAACG,OAAlC,EAA2C;MACvCH,eAAe,CAACG,OAAhB,GAA0BQ,SAA1B;MACAV,eAAe,CAACE,OAAhB,GAA0B,IAA1B;IACH;EACJ,CAVyC,EAUvC,CAACN,SAAD,EAAYC,oBAAZ,CAVuC,CAA1C;EAYA,OAAO;IACHI,eADG;IAEHW,SAAS,EAAEf,oBAAoB,GAAG,CAF/B;IAGHM,oBAHG;IAIHE;EAJG,CAAP;AAMH;AAAA"}
@@ -38,6 +38,7 @@ export default function usePagingAnimation(params) {
38
38
  const {
39
39
  getCurrentIndex,
40
40
  lastIndex,
41
+ notifyAnimationState,
41
42
  notifyOffsetHasChanged
42
43
  } = indexController;
43
44
  const toValueRef = useRef(0);
@@ -64,8 +65,7 @@ export default function usePagingAnimation(params) {
64
65
  translateX.setValue(0);
65
66
  }, [ensureOffsetBoundary, offsetX, translateX]);
66
67
  const interruptAnimation = useCallback(() => {
67
- if (toValueRef.current === 0) {
68
- // Performance optimization
68
+ if (!isAnimatingRef.current) {
69
69
  return;
70
70
  }
71
71
 
@@ -74,16 +74,18 @@ export default function usePagingAnimation(params) {
74
74
  const prevOffset = currentOffsetRef.current;
75
75
  const totalOffset = prevOffset + lastValue;
76
76
  notifyOffsetHasChanged(totalOffset);
77
+ notifyAnimationState('interrupted');
77
78
  requireNewOffset(totalOffset);
78
79
  });
79
80
  }, [requireNewOffset, translateX]);
80
81
  const finalizeAnimation = useCallback(() => {
82
+ notifyAnimationState('finished');
81
83
  isAnimatingRef.current = false;
82
84
  const prevOffset = currentOffsetRef.current;
83
85
  const toValue = toValueRef.current;
84
86
  const totalOffset = prevOffset + toValue;
85
87
  requireNewOffset(totalOffset);
86
- }, [requireNewOffset]);
88
+ }, [notifyAnimationState, requireNewOffset]);
87
89
  const startPagingAnimation = useCallback((type, config) => {
88
90
  if (isAnimatingRef.current) {
89
91
  return;
@@ -141,6 +143,7 @@ export default function usePagingAnimation(params) {
141
143
  const toValue = compensateToValue(wantedToValue, currentOffsetRef.current);
142
144
  toValueRef.current = toValue;
143
145
  isAnimatingRef.current = true;
146
+ notifyOffsetHasChanged(currentOffsetRef.current + toValue);
144
147
 
145
148
  if (configWithDefaults.animated) {
146
149
  const animation = createScrollAnimation(translateX, toValue);
@@ -153,12 +156,11 @@ export default function usePagingAnimation(params) {
153
156
  finalizeAnimation();
154
157
  }
155
158
  });
159
+ notifyAnimationState('started');
156
160
  } else {
157
161
  finalizeAnimation();
158
162
  }
159
-
160
- notifyOffsetHasChanged(currentOffsetRef.current + toValue);
161
- }, [createScrollAnimation, getCurrentIndex, finalizeAnimation, itemWidth, lastIndex, loop, notifyOffsetHasChanged]);
163
+ }, [createScrollAnimation, getCurrentIndex, finalizeAnimation, itemWidth, lastIndex, loop, notifyAnimationState, notifyOffsetHasChanged]);
162
164
  return {
163
165
  interruptAnimation,
164
166
  startPagingAnimation
@@ -1 +1 @@
1
- {"version":3,"names":["useCallback","useRef","directionToValue","itemWidth","direction","toValueCompensator","toValue","currentOffset","remainder","Math","abs","halfOfItemWidth","compensateVector","usePagingAnimation","params","createScrollAnimation","indexController","loop","numberOfData","offsetX","translateX","getCurrentIndex","lastIndex","notifyOffsetHasChanged","toValueRef","currentOffsetRef","isAnimatingRef","maxWidth","ensureOffsetBoundary","offset","isCloseToEnd","signOfOffset","requireNewOffset","newOffset","nextOffset","current","setValue","interruptAnimation","stopAnimation","lastValue","prevOffset","totalOffset","finalizeAnimation","startPagingAnimation","type","config","configWithDefaults","animated","currentIndex","getValueByDirectionOnAllAdjacentItemsVisible","compensateToValue","getValueByDirectionalPagingOnLoopDisabled","_config","isOriginatedFromGesture","getValueByDirectionalPaging","_configWithDefaults","getValueByIndexPaging","index","distance","wantedToValue","animation","start","finished"],"sources":["usePagingAnimation.ts"],"sourcesContent":["import { useCallback, useRef } from 'react';\nimport { Animated } from 'react-native';\nimport type {\n CreateScrollAnimation,\n DirectionalPagingAnimationConfig,\n IndexController,\n IndexPagingAnimationConfig,\n PagingAnimationConfig,\n PagingAnimationType,\n PagingDirection,\n StartPagingAnimation,\n} from '../types';\n\nexport interface PagingAnimationParameters {\n createScrollAnimation: CreateScrollAnimation;\n itemWidth: number;\n indexController: IndexController;\n loop: boolean;\n numberOfData: number;\n offsetX: Animated.Value;\n translateX: Animated.Value;\n}\n\nexport interface UsePagingAnimation {\n interruptAnimation: () => void;\n startPagingAnimation: StartPagingAnimation;\n}\n\nfunction directionToValue(itemWidth: number) {\n return function (direction: PagingDirection): number {\n switch (direction) {\n case 'next':\n return -itemWidth;\n case 'prev':\n return itemWidth;\n case 'stay':\n return 0;\n }\n };\n}\n\nfunction toValueCompensator(itemWidth: number) {\n return function (toValue: number, currentOffset: number): number {\n const remainder = Math.abs(currentOffset % itemWidth);\n\n const halfOfItemWidth = Math.abs(itemWidth / 2);\n const compensateVector = remainder > halfOfItemWidth\n ? remainder - itemWidth\n : remainder;\n\n const direction = currentOffset > 0 ? -1 : 1;\n\n return toValue + (direction * compensateVector);\n };\n}\n\nexport default function usePagingAnimation(params: PagingAnimationParameters): UsePagingAnimation {\n const {\n createScrollAnimation,\n itemWidth,\n indexController,\n loop,\n numberOfData,\n offsetX,\n translateX,\n } = params;\n\n const {\n getCurrentIndex,\n lastIndex,\n notifyOffsetHasChanged,\n } = indexController;\n\n const toValueRef = useRef<number>(0);\n const currentOffsetRef = useRef<number>(0);\n\n const isAnimatingRef = useRef<boolean>(false);\n\n const maxWidth = Math.abs(numberOfData * itemWidth);\n\n const ensureOffsetBoundary: (offset: number) => number = useCallback((offset: number) => {\n if (loop) {\n const isCloseToEnd = Math.abs(offset) >= (maxWidth - itemWidth);\n if (isCloseToEnd) {\n const signOfOffset = offset > 0 ? 1 : -1;\n return offset + (-signOfOffset * maxWidth);\n }\n }\n\n return offset % maxWidth;\n }, [itemWidth, loop, maxWidth]);\n\n const requireNewOffset = useCallback((newOffset: number) => {\n const nextOffset = ensureOffsetBoundary(newOffset);\n\n currentOffsetRef.current = nextOffset;\n offsetX.setValue(nextOffset);\n\n toValueRef.current = 0;\n translateX.setValue(0);\n }, [\n ensureOffsetBoundary,\n offsetX,\n translateX,\n ]);\n\n const interruptAnimation = useCallback(() => {\n if (toValueRef.current === 0) {\n // Performance optimization\n return;\n }\n\n translateX.stopAnimation(lastValue => {\n isAnimatingRef.current = false;\n\n const prevOffset = currentOffsetRef.current;\n const totalOffset = prevOffset + lastValue;\n\n notifyOffsetHasChanged(totalOffset);\n\n requireNewOffset(totalOffset);\n });\n }, [requireNewOffset, translateX]);\n\n const finalizeAnimation = useCallback(() => {\n isAnimatingRef.current = false;\n\n const prevOffset = currentOffsetRef.current;\n const toValue = toValueRef.current;\n const totalOffset = prevOffset + toValue;\n\n requireNewOffset(totalOffset);\n }, [requireNewOffset]);\n\n const startPagingAnimation = useCallback((type: PagingAnimationType, config: PagingAnimationConfig) => {\n if (isAnimatingRef.current) {\n return;\n }\n\n const configWithDefaults: PagingAnimationConfig = {\n animated: true,\n ...config,\n };\n\n const currentIndex = getCurrentIndex();\n\n const getValueByDirectionOnAllAdjacentItemsVisible = directionToValue(itemWidth);\n const compensateToValue = toValueCompensator(itemWidth);\n\n const getValueByDirectionalPagingOnLoopDisabled = (_config: DirectionalPagingAnimationConfig): number => {\n const { direction, isOriginatedFromGesture } = _config;\n\n if (currentIndex === 0 && direction === 'prev') {\n return isOriginatedFromGesture\n ? getValueByDirectionOnAllAdjacentItemsVisible('stay')\n : -lastIndex * itemWidth; // last position\n } else if (currentIndex === lastIndex && direction === 'next') {\n return isOriginatedFromGesture\n ? getValueByDirectionOnAllAdjacentItemsVisible('stay')\n : lastIndex * itemWidth; // first position\n }\n return getValueByDirectionOnAllAdjacentItemsVisible(direction);\n };\n\n const getValueByDirectionalPaging = (_config: DirectionalPagingAnimationConfig): number => {\n const _configWithDefaults: DirectionalPagingAnimationConfig = {\n isOriginatedFromGesture: false,\n ..._config,\n };\n\n return loop\n ? getValueByDirectionOnAllAdjacentItemsVisible(_configWithDefaults.direction)\n : getValueByDirectionalPagingOnLoopDisabled(_configWithDefaults);\n };\n\n const getValueByIndexPaging = ({ index }: IndexPagingAnimationConfig): number => {\n if (index < 0 || index > lastIndex || index === currentIndex) {\n // no animation if index is invalid or equals to current index\n return 0;\n }\n\n const distance = Math.abs(currentIndex - index) * itemWidth;\n const direction = index > currentIndex ? -1 : 1;\n\n return distance * direction;\n };\n\n const wantedToValue = type === 'directional'\n // @ts-ignore\n ? getValueByDirectionalPaging(configWithDefaults)\n // @ts-ignore\n : getValueByIndexPaging(configWithDefaults);\n\n const toValue = compensateToValue(wantedToValue, currentOffsetRef.current);\n\n toValueRef.current = toValue;\n isAnimatingRef.current = true;\n\n if (configWithDefaults.animated) {\n const animation = createScrollAnimation(translateX, toValue);\n\n animation.start(({ finished }) => {\n if (finished) {\n finalizeAnimation();\n }\n });\n } else {\n finalizeAnimation();\n }\n\n notifyOffsetHasChanged(currentOffsetRef.current + toValue);\n }, [\n createScrollAnimation,\n getCurrentIndex,\n finalizeAnimation,\n itemWidth,\n lastIndex,\n loop,\n notifyOffsetHasChanged,\n ]);\n\n return {\n interruptAnimation,\n startPagingAnimation,\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"names":["useCallback","useRef","directionToValue","itemWidth","direction","toValueCompensator","toValue","currentOffset","remainder","Math","abs","halfOfItemWidth","compensateVector","usePagingAnimation","params","createScrollAnimation","indexController","loop","numberOfData","offsetX","translateX","getCurrentIndex","lastIndex","notifyAnimationState","notifyOffsetHasChanged","toValueRef","currentOffsetRef","isAnimatingRef","maxWidth","ensureOffsetBoundary","offset","isCloseToEnd","signOfOffset","requireNewOffset","newOffset","nextOffset","current","setValue","interruptAnimation","stopAnimation","lastValue","prevOffset","totalOffset","finalizeAnimation","startPagingAnimation","type","config","configWithDefaults","animated","currentIndex","getValueByDirectionOnAllAdjacentItemsVisible","compensateToValue","getValueByDirectionalPagingOnLoopDisabled","_config","isOriginatedFromGesture","getValueByDirectionalPaging","_configWithDefaults","getValueByIndexPaging","index","distance","wantedToValue","animation","start","finished"],"sources":["usePagingAnimation.ts"],"sourcesContent":["import { useCallback, useRef } from 'react';\nimport { Animated } from 'react-native';\nimport type {\n CreateScrollAnimation,\n DirectionalPagingAnimationConfig,\n IndexController,\n IndexPagingAnimationConfig,\n PagingAnimationConfig,\n PagingAnimationType,\n PagingDirection,\n StartPagingAnimation,\n} from '../types';\n\nexport interface PagingAnimationParameters {\n createScrollAnimation: CreateScrollAnimation;\n itemWidth: number;\n indexController: IndexController;\n loop: boolean;\n numberOfData: number;\n offsetX: Animated.Value;\n translateX: Animated.Value;\n}\n\nexport interface UsePagingAnimation {\n interruptAnimation: () => void;\n startPagingAnimation: StartPagingAnimation;\n}\n\nfunction directionToValue(itemWidth: number) {\n return function (direction: PagingDirection): number {\n switch (direction) {\n case 'next':\n return -itemWidth;\n case 'prev':\n return itemWidth;\n case 'stay':\n return 0;\n }\n };\n}\n\nfunction toValueCompensator(itemWidth: number) {\n return function (toValue: number, currentOffset: number): number {\n const remainder = Math.abs(currentOffset % itemWidth);\n\n const halfOfItemWidth = Math.abs(itemWidth / 2);\n const compensateVector = remainder > halfOfItemWidth\n ? remainder - itemWidth\n : remainder;\n\n const direction = currentOffset > 0 ? -1 : 1;\n\n return toValue + (direction * compensateVector);\n };\n}\n\nexport default function usePagingAnimation(params: PagingAnimationParameters): UsePagingAnimation {\n const {\n createScrollAnimation,\n itemWidth,\n indexController,\n loop,\n numberOfData,\n offsetX,\n translateX,\n } = params;\n\n const {\n getCurrentIndex,\n lastIndex,\n notifyAnimationState,\n notifyOffsetHasChanged,\n } = indexController;\n\n const toValueRef = useRef<number>(0);\n const currentOffsetRef = useRef<number>(0);\n\n const isAnimatingRef = useRef<boolean>(false);\n\n const maxWidth = Math.abs(numberOfData * itemWidth);\n\n const ensureOffsetBoundary: (offset: number) => number = useCallback((offset: number) => {\n if (loop) {\n const isCloseToEnd = Math.abs(offset) >= (maxWidth - itemWidth);\n if (isCloseToEnd) {\n const signOfOffset = offset > 0 ? 1 : -1;\n return offset + (-signOfOffset * maxWidth);\n }\n }\n\n return offset % maxWidth;\n }, [itemWidth, loop, maxWidth]);\n\n const requireNewOffset = useCallback((newOffset: number) => {\n const nextOffset = ensureOffsetBoundary(newOffset);\n\n currentOffsetRef.current = nextOffset;\n offsetX.setValue(nextOffset);\n\n toValueRef.current = 0;\n translateX.setValue(0);\n }, [\n ensureOffsetBoundary,\n offsetX,\n translateX,\n ]);\n\n const interruptAnimation = useCallback(() => {\n if (!isAnimatingRef.current) {\n return;\n }\n\n translateX.stopAnimation(lastValue => {\n isAnimatingRef.current = false;\n\n const prevOffset = currentOffsetRef.current;\n const totalOffset = prevOffset + lastValue;\n\n notifyOffsetHasChanged(totalOffset);\n notifyAnimationState('interrupted');\n\n requireNewOffset(totalOffset);\n });\n }, [requireNewOffset, translateX]);\n\n const finalizeAnimation = useCallback(() => {\n notifyAnimationState('finished');\n\n isAnimatingRef.current = false;\n\n const prevOffset = currentOffsetRef.current;\n const toValue = toValueRef.current;\n const totalOffset = prevOffset + toValue;\n\n requireNewOffset(totalOffset);\n }, [\n notifyAnimationState,\n requireNewOffset,\n ]);\n\n const startPagingAnimation = useCallback((type: PagingAnimationType, config: PagingAnimationConfig) => {\n if (isAnimatingRef.current) {\n return;\n }\n\n const configWithDefaults: PagingAnimationConfig = {\n animated: true,\n ...config,\n };\n\n const currentIndex = getCurrentIndex();\n\n const getValueByDirectionOnAllAdjacentItemsVisible = directionToValue(itemWidth);\n const compensateToValue = toValueCompensator(itemWidth);\n\n const getValueByDirectionalPagingOnLoopDisabled = (_config: DirectionalPagingAnimationConfig): number => {\n const { direction, isOriginatedFromGesture } = _config;\n\n if (currentIndex === 0 && direction === 'prev') {\n return isOriginatedFromGesture\n ? getValueByDirectionOnAllAdjacentItemsVisible('stay')\n : -lastIndex * itemWidth; // last position\n } else if (currentIndex === lastIndex && direction === 'next') {\n return isOriginatedFromGesture\n ? getValueByDirectionOnAllAdjacentItemsVisible('stay')\n : lastIndex * itemWidth; // first position\n }\n return getValueByDirectionOnAllAdjacentItemsVisible(direction);\n };\n\n const getValueByDirectionalPaging = (_config: DirectionalPagingAnimationConfig): number => {\n const _configWithDefaults: DirectionalPagingAnimationConfig = {\n isOriginatedFromGesture: false,\n ..._config,\n };\n\n return loop\n ? getValueByDirectionOnAllAdjacentItemsVisible(_configWithDefaults.direction)\n : getValueByDirectionalPagingOnLoopDisabled(_configWithDefaults);\n };\n\n const getValueByIndexPaging = ({ index }: IndexPagingAnimationConfig): number => {\n if (index < 0 || index > lastIndex || index === currentIndex) {\n // no animation if index is invalid or equals to current index\n return 0;\n }\n\n const distance = Math.abs(currentIndex - index) * itemWidth;\n const direction = index > currentIndex ? -1 : 1;\n\n return distance * direction;\n };\n\n const wantedToValue = type === 'directional'\n // @ts-ignore\n ? getValueByDirectionalPaging(configWithDefaults)\n // @ts-ignore\n : getValueByIndexPaging(configWithDefaults);\n\n const toValue = compensateToValue(wantedToValue, currentOffsetRef.current);\n\n toValueRef.current = toValue;\n isAnimatingRef.current = true;\n\n notifyOffsetHasChanged(currentOffsetRef.current + toValue);\n\n if (configWithDefaults.animated) {\n const animation = createScrollAnimation(translateX, toValue);\n\n animation.start(({ finished }) => {\n if (finished) {\n finalizeAnimation();\n }\n });\n\n notifyAnimationState('started');\n } else {\n finalizeAnimation();\n }\n }, [\n createScrollAnimation,\n getCurrentIndex,\n finalizeAnimation,\n itemWidth,\n lastIndex,\n loop,\n notifyAnimationState,\n notifyOffsetHasChanged,\n ]);\n\n return {\n interruptAnimation,\n startPagingAnimation,\n };\n};\n"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
1
  const directions = ['next', 'prev', 'stay'];
2
+ const animationStates = ['started', 'finished', 'interrupted'];
2
3
  export {};
3
4
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["directions"],"sources":["types.ts"],"sourcesContent":["import type { ReactElement } from 'react';\nimport type { Animated, ViewProps } from 'react-native';\n\nconst directions = ['next', 'prev', 'stay'] as const;\n\nexport type PagingDirection = (typeof directions)[number];\n\nexport type ItemHeight = number | 'auto';\n\nexport interface RenderItem<T> {\n (info: { item: T, index: number, interpolation: Animated.AnimatedInterpolation }): ReactElement | null;\n}\n\nexport interface CreateScrollAnimation {\n (aValue: Animated.AnimatedValue, toValue: number): Animated.CompositeAnimation;\n}\n\nexport interface CreateItemStyle {\n (itemInterpolation: Animated.AnimatedInterpolation, itemWidth: number): Animated.AnimatedProps<ViewProps['style']>;\n}\n\nexport interface GetCurrentIndex {\n (): number;\n}\n\nexport interface IndexController {\n getCurrentIndex: GetCurrentIndex;\n lastIndex: number;\n notifyOffsetHasChanged: (offset: number) => void;\n}\n\nexport type PagingAnimationType = 'directional' | 'index';\n\nexport interface BasePagingAnimationConfig {\n animated?: boolean;\n}\n\nexport interface DirectionalPagingAnimationConfig extends BasePagingAnimationConfig {\n direction: PagingDirection;\n isOriginatedFromGesture?: boolean;\n}\n\nexport interface IndexPagingAnimationConfig extends BasePagingAnimationConfig {\n index: number;\n}\n\nexport type PagingAnimationConfig = DirectionalPagingAnimationConfig | IndexPagingAnimationConfig;\n\nexport interface StartPagingAnimation {\n (type: PagingAnimationType, config: PagingAnimationConfig): void;\n}\n\nexport type VisibleIndexRanges = Array<[number, number]>;\n\nexport interface StoreSubscription {\n (): void;\n}\n\nexport interface ItemVisibilityStore {\n dispatch: (ranges: VisibleIndexRanges) => void;\n subscribe: (listener: (ranges: VisibleIndexRanges) => void) => StoreSubscription;\n removeAllListeners: () => void;\n}\n\nexport interface AutoplayController {\n pause: () => void;\n resume: () => void;\n}\n\nexport interface ScrollToOption {\n index: number;\n animated?: boolean;\n}\n\nexport interface CarouselInstance {\n /**\n * Get current visible item index.\n */\n getCurrentIndex: GetCurrentIndex;\n\n /**\n * Scroll to next visible item.\n */\n next: () => void;\n\n /**\n * Scroll to previous visible item.\n */\n prev: () => void;\n\n /**\n * Scroll to desired indexed item.\n * Invalid index is ignored.\n */\n scrollTo: (option: ScrollToOption) => void;\n}\n"],"mappings":"AAGA,MAAMA,UAAU,GAAG,CAAC,MAAD,EAAS,MAAT,EAAiB,MAAjB,CAAnB"}
1
+ {"version":3,"names":["directions","animationStates"],"sources":["types.ts"],"sourcesContent":["import type { ReactElement } from 'react';\nimport type { Animated, ViewProps } from 'react-native';\n\nconst directions = ['next', 'prev', 'stay'] as const;\n\nexport type PagingDirection = (typeof directions)[number];\n\nconst animationStates = ['started', 'finished', 'interrupted'] as const;\n\nexport type AnimationState = (typeof animationStates)[number];\n\nexport type ItemHeight = number | 'auto';\n\nexport interface RenderItem<T> {\n (info: { item: T, index: number, interpolation: Animated.AnimatedInterpolation }): ReactElement | null;\n}\n\nexport interface CreateScrollAnimation {\n (aValue: Animated.AnimatedValue, toValue: number): Animated.CompositeAnimation;\n}\n\nexport interface CreateItemStyle {\n (itemInterpolation: Animated.AnimatedInterpolation, itemWidth: number): Animated.AnimatedProps<ViewProps['style']>;\n}\n\nexport interface GetCurrentIndex {\n (): number;\n}\n\nexport interface IndexController {\n getCurrentIndex: GetCurrentIndex;\n lastIndex: number;\n notifyAnimationState: (state: AnimationState) => void;\n notifyOffsetHasChanged: (offset: number) => void;\n}\n\nexport type PagingAnimationType = 'directional' | 'index';\n\nexport interface BasePagingAnimationConfig {\n animated?: boolean;\n}\n\nexport interface DirectionalPagingAnimationConfig extends BasePagingAnimationConfig {\n direction: PagingDirection;\n isOriginatedFromGesture?: boolean;\n}\n\nexport interface IndexPagingAnimationConfig extends BasePagingAnimationConfig {\n index: number;\n}\n\nexport type PagingAnimationConfig = DirectionalPagingAnimationConfig | IndexPagingAnimationConfig;\n\nexport interface StartPagingAnimation {\n (type: PagingAnimationType, config: PagingAnimationConfig): void;\n}\n\nexport type VisibleIndexRanges = Array<[number, number]>;\n\nexport interface StoreSubscription {\n (): void;\n}\n\nexport interface ItemVisibilityStore {\n dispatch: (ranges: VisibleIndexRanges) => void;\n subscribe: (listener: (ranges: VisibleIndexRanges) => void) => StoreSubscription;\n removeAllListeners: () => void;\n}\n\nexport interface AutoplayController {\n pause: () => void;\n resume: () => void;\n}\n\nexport interface ScrollToOption {\n index: number;\n animated?: boolean;\n}\n\nexport interface CarouselInstance {\n /**\n * Get current visible item index.\n */\n getCurrentIndex: GetCurrentIndex;\n\n /**\n * Scroll to next visible item.\n */\n next: () => void;\n\n /**\n * Scroll to previous visible item.\n */\n prev: () => void;\n\n /**\n * Scroll to desired indexed item.\n * Invalid index is ignored.\n */\n scrollTo: (option: ScrollToOption) => void;\n}\n"],"mappings":"AAGA,MAAMA,UAAU,GAAG,CAAC,MAAD,EAAS,MAAT,EAAiB,MAAjB,CAAnB;AAIA,MAAMC,eAAe,GAAG,CAAC,SAAD,EAAY,UAAZ,EAAwB,aAAxB,CAAxB"}
@@ -2,6 +2,8 @@ import type { ReactElement } from 'react';
2
2
  import type { Animated, ViewProps } from 'react-native';
3
3
  declare const directions: readonly ["next", "prev", "stay"];
4
4
  export declare type PagingDirection = (typeof directions)[number];
5
+ declare const animationStates: readonly ["started", "finished", "interrupted"];
6
+ export declare type AnimationState = (typeof animationStates)[number];
5
7
  export declare type ItemHeight = number | 'auto';
6
8
  export interface RenderItem<T> {
7
9
  (info: {
@@ -22,6 +24,7 @@ export interface GetCurrentIndex {
22
24
  export interface IndexController {
23
25
  getCurrentIndex: GetCurrentIndex;
24
26
  lastIndex: number;
27
+ notifyAnimationState: (state: AnimationState) => void;
25
28
  notifyOffsetHasChanged: (offset: number) => void;
26
29
  }
27
30
  export declare type PagingAnimationType = 'directional' | 'index';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fountain-ui/lab",
3
- "version": "2.0.0-beta.15",
3
+ "version": "2.0.0-beta.16",
4
4
  "private": false,
5
5
  "author": "Fountain-UI Team",
6
6
  "description": "Incubator for Fountain-UI React components.",
@@ -70,5 +70,5 @@
70
70
  "publishConfig": {
71
71
  "access": "public"
72
72
  },
73
- "gitHead": "9c4af6d69493666d86b7736892f778af775a3c80"
73
+ "gitHead": "44c50a4474a3bca589e8cedd3ff476927e12061c"
74
74
  }
@@ -6,8 +6,8 @@ export default function createDefaultScrollAnimation(
6
6
  ): Animated.CompositeAnimation {
7
7
  return Animated.timing(animatedValue, {
8
8
  toValue: toValue,
9
- duration: 220,
10
- easing: Easing.bezier(0.35, 0.5, 0.5, 0.75),
9
+ duration: 180,
10
+ easing: Easing.bezier(0.2, 0.2, 0.2, 1),
11
11
  useNativeDriver: true,
12
12
  });
13
13
  };
@@ -1,6 +1,6 @@
1
1
  import React, { useCallback, useRef } from 'react';
2
2
  import { mod } from '@fountain-ui/utils';
3
- import type { IndexController } from '../types';
3
+ import type { AnimationState, IndexController } from '../types';
4
4
 
5
5
  export interface UseIndexControllerParameters {
6
6
  initialIndex: number;
@@ -18,9 +18,21 @@ export default function useIndexController(params: UseIndexControllerParameters)
18
18
  } = params;
19
19
 
20
20
  const currentIndexRef = useRef<number>(initialIndex);
21
+ const indexChangedRef = useRef<boolean>(false);
21
22
 
22
23
  const getCurrentIndex = useCallback(() => currentIndexRef.current, []);
23
24
 
25
+ const notifyAnimationState = useCallback((state: AnimationState) => {
26
+ if (state === 'finished' || state === 'interrupted') {
27
+ if (indexChangedRef.current) {
28
+ onIndexChange?.(getCurrentIndex());
29
+ }
30
+ }
31
+ }, [
32
+ getCurrentIndex,
33
+ onIndexChange,
34
+ ]);
35
+
24
36
  const notifyOffsetHasChanged = useCallback((offset: number) => {
25
37
  const roundedOffset = Math.round(offset / itemWidth) * itemWidth;
26
38
 
@@ -29,18 +41,14 @@ export default function useIndexController(params: UseIndexControllerParameters)
29
41
 
30
42
  if (nextIndex !== currentIndexRef.current) {
31
43
  currentIndexRef.current = nextIndex;
32
-
33
- onIndexChange?.(nextIndex);
44
+ indexChangedRef.current = true;
34
45
  }
35
- }, [
36
- itemWidth,
37
- numberOfOriginalData,
38
- onIndexChange,
39
- ]);
46
+ }, [itemWidth, numberOfOriginalData]);
40
47
 
41
48
  return {
42
49
  getCurrentIndex,
43
50
  lastIndex: numberOfOriginalData - 1,
51
+ notifyAnimationState,
44
52
  notifyOffsetHasChanged,
45
53
  };
46
54
  };
@@ -68,6 +68,7 @@ export default function usePagingAnimation(params: PagingAnimationParameters): U
68
68
  const {
69
69
  getCurrentIndex,
70
70
  lastIndex,
71
+ notifyAnimationState,
71
72
  notifyOffsetHasChanged,
72
73
  } = indexController;
73
74
 
@@ -105,8 +106,7 @@ export default function usePagingAnimation(params: PagingAnimationParameters): U
105
106
  ]);
106
107
 
107
108
  const interruptAnimation = useCallback(() => {
108
- if (toValueRef.current === 0) {
109
- // Performance optimization
109
+ if (!isAnimatingRef.current) {
110
110
  return;
111
111
  }
112
112
 
@@ -117,12 +117,15 @@ export default function usePagingAnimation(params: PagingAnimationParameters): U
117
117
  const totalOffset = prevOffset + lastValue;
118
118
 
119
119
  notifyOffsetHasChanged(totalOffset);
120
+ notifyAnimationState('interrupted');
120
121
 
121
122
  requireNewOffset(totalOffset);
122
123
  });
123
124
  }, [requireNewOffset, translateX]);
124
125
 
125
126
  const finalizeAnimation = useCallback(() => {
127
+ notifyAnimationState('finished');
128
+
126
129
  isAnimatingRef.current = false;
127
130
 
128
131
  const prevOffset = currentOffsetRef.current;
@@ -130,7 +133,10 @@ export default function usePagingAnimation(params: PagingAnimationParameters): U
130
133
  const totalOffset = prevOffset + toValue;
131
134
 
132
135
  requireNewOffset(totalOffset);
133
- }, [requireNewOffset]);
136
+ }, [
137
+ notifyAnimationState,
138
+ requireNewOffset,
139
+ ]);
134
140
 
135
141
  const startPagingAnimation = useCallback((type: PagingAnimationType, config: PagingAnimationConfig) => {
136
142
  if (isAnimatingRef.current) {
@@ -196,6 +202,8 @@ export default function usePagingAnimation(params: PagingAnimationParameters): U
196
202
  toValueRef.current = toValue;
197
203
  isAnimatingRef.current = true;
198
204
 
205
+ notifyOffsetHasChanged(currentOffsetRef.current + toValue);
206
+
199
207
  if (configWithDefaults.animated) {
200
208
  const animation = createScrollAnimation(translateX, toValue);
201
209
 
@@ -204,11 +212,11 @@ export default function usePagingAnimation(params: PagingAnimationParameters): U
204
212
  finalizeAnimation();
205
213
  }
206
214
  });
215
+
216
+ notifyAnimationState('started');
207
217
  } else {
208
218
  finalizeAnimation();
209
219
  }
210
-
211
- notifyOffsetHasChanged(currentOffsetRef.current + toValue);
212
220
  }, [
213
221
  createScrollAnimation,
214
222
  getCurrentIndex,
@@ -216,6 +224,7 @@ export default function usePagingAnimation(params: PagingAnimationParameters): U
216
224
  itemWidth,
217
225
  lastIndex,
218
226
  loop,
227
+ notifyAnimationState,
219
228
  notifyOffsetHasChanged,
220
229
  ]);
221
230
 
@@ -5,6 +5,10 @@ const directions = ['next', 'prev', 'stay'] as const;
5
5
 
6
6
  export type PagingDirection = (typeof directions)[number];
7
7
 
8
+ const animationStates = ['started', 'finished', 'interrupted'] as const;
9
+
10
+ export type AnimationState = (typeof animationStates)[number];
11
+
8
12
  export type ItemHeight = number | 'auto';
9
13
 
10
14
  export interface RenderItem<T> {
@@ -26,6 +30,7 @@ export interface GetCurrentIndex {
26
30
  export interface IndexController {
27
31
  getCurrentIndex: GetCurrentIndex;
28
32
  lastIndex: number;
33
+ notifyAnimationState: (state: AnimationState) => void;
29
34
  notifyOffsetHasChanged: (offset: number) => void;
30
35
  }
31
36