react-native-toast-message 2.3.3 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -20,8 +20,6 @@ Animated toast message component for React Native.
20
20
 
21
21
  ## Documentation
22
22
 
23
- > This is the documentation for `react-native-toast-message@v2`, which has a similar API to v1, but contains a few important changes. [Read the complete changelog](https://github.com/calintamas/react-native-toast-message/releases/tag/v2.0.0).
24
-
25
23
  - [Quick start](./docs/quick-start.md)
26
24
  - [API](./docs/api.md)
27
25
  - [Create custom layouts](./docs/custom-layouts.md)
@@ -35,8 +35,8 @@ function renderComponent({ data, options, config, isVisible, show, hide }) {
35
35
  }
36
36
  export function ToastUI(props) {
37
37
  const { isVisible, options, hide } = props;
38
- const { position, topOffset, bottomOffset, keyboardOffset, avoidKeyboard, swipeable } = options;
39
- return (<AnimatedContainer isVisible={isVisible} position={position} topOffset={topOffset} bottomOffset={bottomOffset} keyboardOffset={keyboardOffset} avoidKeyboard={avoidKeyboard} swipeable={swipeable} onHide={hide}>
38
+ const { position, topOffset, bottomOffset, keyboardOffset, avoidKeyboard, swipeable, animationConfig } = options;
39
+ return (<AnimatedContainer isVisible={isVisible} position={position} topOffset={topOffset} bottomOffset={bottomOffset} keyboardOffset={keyboardOffset} avoidKeyboard={avoidKeyboard} swipeable={swipeable} animationConfig={animationConfig} onHide={hide}>
40
40
  {renderComponent(props)}
41
41
  </AnimatedContainer>);
42
42
  }
@@ -1,6 +1,6 @@
1
1
  /// <reference types="react" />
2
2
  import { PanResponderGestureState } from 'react-native';
3
- import { ReactChildren, ToastPosition } from '../types';
3
+ import { ReactChildren, ToastAnimationConfig, ToastPosition } from '../types';
4
4
  export declare type AnimatedContainerProps = {
5
5
  children: ReactChildren;
6
6
  isVisible: boolean;
@@ -10,6 +10,7 @@ export declare type AnimatedContainerProps = {
10
10
  bottomOffset: number;
11
11
  keyboardOffset: number;
12
12
  avoidKeyboard: boolean;
13
+ animationConfig?: ToastAnimationConfig;
13
14
  onHide: () => void;
14
15
  onRestorePosition?: () => void;
15
16
  };
@@ -21,4 +22,4 @@ export declare type AnimatedContainerProps = {
21
22
  */
22
23
  export declare function dampingFor(gesture: PanResponderGestureState, position: ToastPosition): number;
23
24
  export declare function animatedValueFor(gesture: PanResponderGestureState, position: ToastPosition, damping: number): number;
24
- export declare function AnimatedContainer({ children, isVisible, position, topOffset, bottomOffset, keyboardOffset, avoidKeyboard, onHide, onRestorePosition, swipeable }: AnimatedContainerProps): JSX.Element;
25
+ export declare function AnimatedContainer({ children, isVisible, position, topOffset, bottomOffset, keyboardOffset, avoidKeyboard, animationConfig, onHide, onRestorePosition, swipeable }: AnimatedContainerProps): JSX.Element;
@@ -37,7 +37,7 @@ export function animatedValueFor(gesture, position, damping) {
37
37
  throw new Error(`Toast position: ${position} not implemented`);
38
38
  }
39
39
  }
40
- export function AnimatedContainer({ children, isVisible, position, topOffset, bottomOffset, keyboardOffset, avoidKeyboard, onHide, onRestorePosition = noop, swipeable }) {
40
+ export function AnimatedContainer({ children, isVisible, position, topOffset, bottomOffset, keyboardOffset, avoidKeyboard, animationConfig, onHide, onRestorePosition = noop, swipeable }) {
41
41
  const { log } = useLogger();
42
42
  const { panning } = useGesture();
43
43
  const { computeViewDimensions, height } = useViewDimensions();
@@ -47,7 +47,8 @@ export function AnimatedContainer({ children, isVisible, position, topOffset, bo
47
47
  topOffset,
48
48
  bottomOffset,
49
49
  keyboardOffset,
50
- avoidKeyboard
50
+ avoidKeyboard,
51
+ animationConfig
51
52
  });
52
53
  const disable = !swipeable || !isVisible;
53
54
  const onStart = React.useCallback(() => {
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { Animated } from 'react-native';
3
- import { ToastPosition } from '../types';
3
+ import { ToastAnimationConfig, ToastPosition } from '../types';
4
4
  declare type UseSlideAnimationParams = {
5
5
  position: ToastPosition;
6
6
  height: number;
@@ -8,11 +8,12 @@ declare type UseSlideAnimationParams = {
8
8
  bottomOffset: number;
9
9
  keyboardOffset: number;
10
10
  avoidKeyboard: boolean;
11
+ animationConfig?: ToastAnimationConfig;
11
12
  };
12
13
  export declare function translateYOutputRangeFor({ position, height, topOffset, bottomOffset, keyboardHeight, keyboardOffset, avoidKeyboard }: UseSlideAnimationParams & {
13
14
  keyboardHeight: number;
14
15
  }): number[];
15
- export declare function useSlideAnimation({ position, height, topOffset, bottomOffset, keyboardOffset, avoidKeyboard }: UseSlideAnimationParams): {
16
+ export declare function useSlideAnimation({ position, height, topOffset, bottomOffset, keyboardOffset, avoidKeyboard, animationConfig }: UseSlideAnimationParams): {
16
17
  animatedValue: React.MutableRefObject<Animated.Value>;
17
18
  animate: (toValue: number) => void;
18
19
  animationStyles: {
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { Animated, Platform } from 'react-native';
3
3
  import { additiveInverseArray } from '../utils/array';
4
+ import { resolveAnimationConfig } from '../utils/animationConfig';
4
5
  import { useKeyboard } from './useKeyboard';
5
6
  export function translateYOutputRangeFor({ position, height, topOffset, bottomOffset, keyboardHeight, keyboardOffset, avoidKeyboard }) {
6
7
  const offset = position === 'bottom' ? bottomOffset : topOffset;
@@ -13,16 +14,28 @@ const useNativeDriver = Platform.select({
13
14
  ios: true,
14
15
  default: false
15
16
  });
16
- export function useSlideAnimation({ position, height, topOffset, bottomOffset, keyboardOffset, avoidKeyboard }) {
17
+ export function useSlideAnimation({ position, height, topOffset, bottomOffset, keyboardOffset, avoidKeyboard, animationConfig }) {
17
18
  const animatedValue = React.useRef(new Animated.Value(0));
18
19
  const { keyboardHeight } = useKeyboard();
19
20
  const animate = React.useCallback((toValue) => {
20
- Animated.spring(animatedValue.current, {
21
- toValue,
22
- useNativeDriver,
23
- friction: 8
24
- }).start();
25
- }, []);
21
+ const resolved = resolveAnimationConfig(animationConfig, toValue === 1 ? 'enter' : 'exit');
22
+ if (resolved.type === 'timing') {
23
+ const { type: _type, ...timingConfig } = resolved;
24
+ Animated.timing(animatedValue.current, {
25
+ ...timingConfig,
26
+ toValue,
27
+ useNativeDriver
28
+ }).start();
29
+ }
30
+ else {
31
+ const { type: _type, ...springConfig } = resolved;
32
+ Animated.spring(animatedValue.current, {
33
+ ...springConfig,
34
+ toValue,
35
+ useNativeDriver
36
+ }).start();
37
+ }
38
+ }, [animationConfig]);
26
39
  const translateY = React.useMemo(() => animatedValue.current.interpolate({
27
40
  inputRange: [0, 1],
28
41
  outputRange: translateYOutputRangeFor({
@@ -1,8 +1,19 @@
1
1
  import React from 'react';
2
- import { StyleProp, TextProps, TextStyle, TouchableOpacityProps, ViewProps, ViewStyle } from 'react-native';
2
+ import { Animated, StyleProp, TextProps, TextStyle, TouchableOpacityProps, ViewProps, ViewStyle } from 'react-native';
3
3
  export declare type ReactChildren = React.ReactNode;
4
4
  export declare type ToastType = 'success' | 'error' | 'info' | (string & {});
5
5
  export declare type ToastPosition = 'top' | 'bottom';
6
+ export declare type ToastSpringAnimationConfig = {
7
+ type: 'spring';
8
+ } & Omit<Parameters<typeof Animated.spring>[1], 'useNativeDriver' | 'toValue'>;
9
+ export declare type ToastTimingAnimationConfig = {
10
+ type: 'timing';
11
+ } & Omit<Parameters<typeof Animated.timing>[1], 'useNativeDriver' | 'toValue'>;
12
+ export declare type ToastSingleAnimationConfig = ToastSpringAnimationConfig | ToastTimingAnimationConfig;
13
+ export declare type ToastAnimationConfig = ToastSingleAnimationConfig | {
14
+ enter?: ToastSingleAnimationConfig;
15
+ exit?: ToastSingleAnimationConfig;
16
+ };
6
17
  export declare type ToastOptions = {
7
18
  /**
8
19
  * Toast type.
@@ -64,9 +75,9 @@ export declare type ToastOptions = {
64
75
  */
65
76
  avoidKeyboard?: boolean;
66
77
  /**
67
- * Called when Toast is shown
78
+ * Called when Toast is shown, receives the show params
68
79
  */
69
- onShow?: () => void;
80
+ onShow?: (params: ToastShowParams) => void;
70
81
  /**
71
82
  * Called when Toast hides
72
83
  */
@@ -81,6 +92,15 @@ export declare type ToastOptions = {
81
92
  * on the Toast instance) that uses the `props` parameter
82
93
  */
83
94
  props?: any;
95
+ /**
96
+ * Configures the enter/exit animation.
97
+ *
98
+ * Pass a single `{ type: 'spring' | 'timing', ...config }` to use the same animation
99
+ * for both phases, or `{ enter, exit }` to configure them separately.
100
+ *
101
+ * Default: `{ type: 'spring', friction: 8 }`
102
+ */
103
+ animationConfig?: ToastAnimationConfig;
84
104
  };
85
105
  export declare type ToastData = {
86
106
  text1?: string;
@@ -187,9 +207,9 @@ export declare type ToastProps = {
187
207
  */
188
208
  avoidKeyboard?: boolean;
189
209
  /**
190
- * Called when any Toast is shown
210
+ * Called when any Toast is shown, receives the show params
191
211
  */
192
- onShow?: () => void;
212
+ onShow?: (params: ToastShowParams) => void;
193
213
  /**
194
214
  * Called when any Toast hides
195
215
  */
@@ -198,4 +218,11 @@ export declare type ToastProps = {
198
218
  * Called on any Toast press
199
219
  */
200
220
  onPress?: () => void;
221
+ /**
222
+ * Default enter/exit animation configuration applied to every Toast.
223
+ * Can be overridden per-call via `Toast.show({ animationConfig })`.
224
+ *
225
+ * Default: `{ type: 'spring', friction: 8 }`
226
+ */
227
+ animationConfig?: ToastAnimationConfig;
201
228
  };
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { useLogger, useGesture } from './contexts';
3
3
  import { useTimeout } from './hooks';
4
+ import { DEFAULT_ANIMATION_CONFIG } from './utils/animationConfig';
4
5
  import { noop } from './utils/func';
5
6
  import { mergeIfDefined } from './utils/obj';
6
7
  export const DEFAULT_DATA = {
@@ -22,7 +23,8 @@ export const DEFAULT_OPTIONS = {
22
23
  onShow: noop,
23
24
  onHide: noop,
24
25
  onPress: noop,
25
- props: {}
26
+ props: {},
27
+ animationConfig: DEFAULT_ANIMATION_CONFIG
26
28
  };
27
29
  export function useToast({ defaultOptions }) {
28
30
  const { log } = useLogger();
@@ -50,7 +52,7 @@ export function useToast({ defaultOptions }) {
50
52
  }, [clearTimer, log, options]);
51
53
  const show = React.useCallback((params) => {
52
54
  log(`Showing with params: ${JSON.stringify(params)}`);
53
- const { text1 = DEFAULT_DATA.text1, text2 = DEFAULT_DATA.text2, type = initialOptions.type, text1Style = initialOptions.text1Style, text2Style = initialOptions.text2Style, position = initialOptions.position, autoHide = initialOptions.autoHide, visibilityTime = initialOptions.visibilityTime, topOffset = initialOptions.topOffset, bottomOffset = initialOptions.bottomOffset, keyboardOffset = initialOptions.keyboardOffset, avoidKeyboard = initialOptions.avoidKeyboard, onShow = initialOptions.onShow, onHide = initialOptions.onHide, onPress = initialOptions.onPress, swipeable = initialOptions.swipeable, props = initialOptions.props } = params;
55
+ const { text1 = DEFAULT_DATA.text1, text2 = DEFAULT_DATA.text2, type = initialOptions.type, text1Style = initialOptions.text1Style, text2Style = initialOptions.text2Style, position = initialOptions.position, autoHide = initialOptions.autoHide, visibilityTime = initialOptions.visibilityTime, topOffset = initialOptions.topOffset, bottomOffset = initialOptions.bottomOffset, keyboardOffset = initialOptions.keyboardOffset, avoidKeyboard = initialOptions.avoidKeyboard, onShow = initialOptions.onShow, onHide = initialOptions.onHide, onPress = initialOptions.onPress, swipeable = initialOptions.swipeable, props = initialOptions.props, animationConfig = initialOptions.animationConfig } = params;
54
56
  setData({
55
57
  text1,
56
58
  text2
@@ -70,12 +72,13 @@ export function useToast({ defaultOptions }) {
70
72
  onHide,
71
73
  onPress,
72
74
  swipeable,
73
- props
75
+ props,
76
+ animationConfig
74
77
  }));
75
78
  // TODO: validate input
76
79
  // TODO: use a queue when Toast is already visible
77
80
  setIsVisible(true);
78
- onShow();
81
+ onShow(params);
79
82
  }, [initialOptions, log]);
80
83
  React.useEffect(() => {
81
84
  const { autoHide } = options;
@@ -0,0 +1,4 @@
1
+ import { ToastAnimationConfig, ToastSingleAnimationConfig, ToastSpringAnimationConfig } from '../types';
2
+ export declare const DEFAULT_ANIMATION_CONFIG: ToastSpringAnimationConfig;
3
+ export declare type AnimationPhase = 'enter' | 'exit';
4
+ export declare function resolveAnimationConfig(config: ToastAnimationConfig | undefined, phase: AnimationPhase): ToastSingleAnimationConfig;
@@ -0,0 +1,13 @@
1
+ export const DEFAULT_ANIMATION_CONFIG = {
2
+ type: 'spring',
3
+ friction: 8
4
+ };
5
+ export function resolveAnimationConfig(config, phase) {
6
+ if (!config) {
7
+ return DEFAULT_ANIMATION_CONFIG;
8
+ }
9
+ if ('type' in config) {
10
+ return config;
11
+ }
12
+ return config[phase] ?? DEFAULT_ANIMATION_CONFIG;
13
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-toast-message",
3
- "version": "2.3.3",
3
+ "version": "2.4.0",
4
4
  "description": "Toast message component for React Native",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./lib/index.d.ts",
@@ -17,13 +17,14 @@
17
17
  ],
18
18
  "scripts": {
19
19
  "prepare": "husky install",
20
+ "setup": "./scripts/setup.sh",
21
+ "bump": "./scripts/bump.sh",
20
22
  "build": "rm -rf ./lib && tsc",
21
23
  "prettier": "./node_modules/.bin/prettier --write",
22
- "lint": "./node_modules/.bin/eslint --fix",
23
- "lint-staged": "./node_modules/.bin/lint-staged",
24
+ "lint": "./node_modules/.bin/eslint --fix --cache",
24
25
  "test": "./node_modules/.bin/jest",
25
- "yalc:push": "yarn build && yalc publish --push",
26
- "quality": "yarn lint && tsc --noEmit"
26
+ "type-check": "tsc --build --incremental",
27
+ "quality": "yarn type-check && yarn lint && yarn test --coverage"
27
28
  },
28
29
  "author": "Calin Tamas <calintamas2@gmail.com>",
29
30
  "license": "MIT",
@@ -43,8 +44,7 @@
43
44
  "prettier": "^2.4.1",
44
45
  "prettier-plugin-import-sort": "^0.0.7",
45
46
  "react-test-renderer": "^17.0.2",
46
- "typescript": "^4.4.3",
47
- "yalc": "^1.0.0-pre.53"
47
+ "typescript": "^4.4.3"
48
48
  },
49
49
  "peerDependencies": {
50
50
  "react": "*",