react-native-toast-message 1.5.0 → 2.0.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/CHANGELOG.md +86 -2
- package/README.md +19 -235
- package/lib/index.d.ts +6 -0
- package/lib/index.js +6 -0
- package/lib/src/Toast.d.ts +7 -0
- package/lib/src/Toast.js +27 -0
- package/lib/src/ToastUI.d.ts +11 -0
- package/lib/src/ToastUI.js +40 -0
- package/lib/src/components/AnimatedContainer.d.ts +16 -0
- package/lib/src/components/AnimatedContainer.js +72 -0
- package/lib/src/components/AnimatedContainer.styles.d.ts +14 -0
- package/lib/src/components/AnimatedContainer.styles.js +15 -0
- package/lib/src/components/BaseToast.d.ts +3 -0
- package/lib/src/components/BaseToast.js +19 -0
- package/lib/src/components/BaseToast.styles.d.ts +41 -0
- package/lib/src/components/BaseToast.styles.js +39 -0
- package/lib/src/components/ErrorToast.d.ts +3 -0
- package/lib/src/components/ErrorToast.js +5 -0
- package/lib/src/components/InfoToast.d.ts +3 -0
- package/lib/src/components/InfoToast.js +5 -0
- package/lib/src/components/SuccessToast.d.ts +3 -0
- package/lib/src/components/SuccessToast.js +5 -0
- package/lib/src/components/Touchable.d.ts +8 -0
- package/lib/src/components/Touchable.js +7 -0
- package/lib/src/contexts/LoggerContext.d.ts +12 -0
- package/lib/src/contexts/LoggerContext.js +22 -0
- package/lib/src/contexts/index.d.ts +1 -0
- package/lib/src/contexts/index.js +1 -0
- package/lib/src/hooks/index.d.ts +5 -0
- package/lib/src/hooks/index.js +5 -0
- package/lib/src/hooks/useKeyboard.d.ts +4 -0
- package/lib/src/hooks/useKeyboard.js +31 -0
- package/lib/src/hooks/usePanResponder.d.ts +15 -0
- package/lib/src/hooks/usePanResponder.js +41 -0
- package/lib/src/hooks/useSlideAnimation.d.ts +24 -0
- package/lib/src/hooks/useSlideAnimation.js +49 -0
- package/lib/src/hooks/useTimeout.d.ts +6 -0
- package/lib/src/hooks/useTimeout.js +29 -0
- package/lib/src/hooks/useViewDimensions.d.ts +13 -0
- package/lib/src/hooks/useViewDimensions.js +20 -0
- package/lib/src/types/index.d.ts +165 -0
- package/lib/src/types/index.js +1 -0
- package/lib/src/useToast.d.ts +13 -0
- package/lib/src/useToast.js +79 -0
- package/lib/src/utils/array.d.ts +2 -0
- package/lib/src/utils/array.js +4 -0
- package/lib/src/utils/func.d.ts +1 -0
- package/lib/src/utils/func.js +1 -0
- package/lib/src/utils/number.d.ts +3 -0
- package/lib/src/utils/number.js +9 -0
- package/lib/src/utils/obj.d.ts +3 -0
- package/lib/src/utils/obj.js +11 -0
- package/lib/src/utils/platform.d.ts +1 -0
- package/lib/src/utils/platform.js +4 -0
- package/lib/src/utils/test-id.d.ts +1 -0
- package/lib/src/utils/test-id.js +3 -0
- package/package.json +46 -35
- package/.github/dependabot.yml +0 -17
- package/.github/workflows/publish.yml +0 -22
- package/.github/workflows/tag.yml +0 -16
- package/.github/workflows/tests.yml +0 -44
- package/babel.config.js +0 -3
- package/index.d.ts +0 -69
- package/index.js +0 -4
- package/jest.config.js +0 -5
- package/jest.setup.js +0 -1
- package/src/assets/icons/close.png +0 -0
- package/src/assets/icons/close@2x.png +0 -0
- package/src/assets/icons/close@3x.png +0 -0
- package/src/assets/icons/error.png +0 -0
- package/src/assets/icons/error@2x.png +0 -0
- package/src/assets/icons/error@3x.png +0 -0
- package/src/assets/icons/info.png +0 -0
- package/src/assets/icons/info@2x.png +0 -0
- package/src/assets/icons/info@3x.png +0 -0
- package/src/assets/icons/success.png +0 -0
- package/src/assets/icons/success@2x.png +0 -0
- package/src/assets/icons/success@3x.png +0 -0
- package/src/assets/index.js +0 -15
- package/src/colors/index.js +0 -10
- package/src/components/base/index.js +0 -134
- package/src/components/base/styles.js +0 -54
- package/src/components/error.js +0 -19
- package/src/components/icon/index.js +0 -40
- package/src/components/icon/styles.js +0 -8
- package/src/components/info.js +0 -19
- package/src/components/success.js +0 -19
- package/src/index.js +0 -420
- package/src/styles.js +0 -17
- package/src/utils/arr.js +0 -3
- package/src/utils/obj.js +0 -9
- package/src/utils/platform.js +0 -5
- package/src/utils/prop-types.js +0 -5
package/CHANGELOG.md
CHANGED
|
@@ -7,14 +7,98 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
|
7
7
|
|
|
8
8
|
Headers are one of:
|
|
9
9
|
|
|
10
|
-
- `Added`, `Changed`, `Removed` or `
|
|
10
|
+
- `Added`, `Changed`, `Removed`, `Fixed` or `Breaking`.
|
|
11
|
+
|
|
12
|
+
## [2.0.0]
|
|
13
|
+
|
|
14
|
+
### Breaking
|
|
15
|
+
|
|
16
|
+
- Setting the `ref` is no longer required when rendering the `Toast` component in your app's entry point. Ref storage is now handled internally using [React.createRef](https://reactjs.org/docs/react-api.html#reactcreateref). This should improve ref access reliability at runtime.
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
// App.jsx
|
|
20
|
+
import Toast from 'react-native-toast-message';
|
|
21
|
+
|
|
22
|
+
export function App(props) {
|
|
23
|
+
return (
|
|
24
|
+
<>
|
|
25
|
+
{/* ... */}
|
|
26
|
+
<Toast />
|
|
27
|
+
</>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
- When you want to have the Toast visible inside a Modal, you no longer need to set a separate `ref`.
|
|
33
|
+
|
|
34
|
+
Simply render the `Toast` component inside the Modal, as well as in your app's entry point. When the Modal is visible, the `ref` from inside the Modal will be automatically used.
|
|
35
|
+
|
|
36
|
+
- `onHide` callback is now always called when the Toast hides (does not matter if `autoHide` was `true` / `false`).
|
|
37
|
+
|
|
38
|
+
- `inProgress` state has been removed and can no longer be relied upon in a custom Toast config.
|
|
39
|
+
|
|
40
|
+
- `style` and `height` props from the Toast component were removed; with the purpose of achieving a cleaner API design. The only way to change the style / layout of different Toast types is through the `config` prop (fixes [#204](https://github.com/calintamas/react-native-toast-message/issues/204)).
|
|
41
|
+
|
|
42
|
+
### Added
|
|
43
|
+
|
|
44
|
+
- on the `BaseToast` component, the following props were added: `touchableContainerProps`, `contentContainerProps`, `text1Props`, `text2Props` , `text1NumberOfLines`, `text2NumberOfLines` (fixes [#112](https://github.com/calintamas/react-native-toast-message/issues/112), [#133](https://github.com/calintamas/react-native-toast-message/issues/133)).
|
|
45
|
+
|
|
46
|
+
- on the `Toast` component, the following callbacks were added as props: `onShow` , `onHide` and `onPress` (fixes [#143](https://github.com/calintamas/react-native-toast-message/issues/143)).
|
|
47
|
+
|
|
48
|
+
- A new `ToastShowParams` type is exported (fixes [#192](https://github.com/calintamas/react-native-toast-message/issues/192)).
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
|
|
52
|
+
- `topOffset` and `bottomOffset` are now by default `40px`
|
|
53
|
+
- New test ids on `BaseToast` component: `toastTouchableContainer`, `toastContentContainer`, `toastText1` and `toastText2`.
|
|
54
|
+
|
|
55
|
+
### Removed
|
|
56
|
+
|
|
57
|
+
- Success, error and info leading icons were removed from the package (to make it as lightweight as possible).
|
|
58
|
+
|
|
59
|
+
It's now possible to pass them via render functions (for more flexibility, see issues regarding svg support, using components as icons, etc) on `BaseToast` component, example below:
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
const toastConfig = {
|
|
63
|
+
success: (props) => (
|
|
64
|
+
<BaseToast
|
|
65
|
+
{...props}
|
|
66
|
+
renderLeadingIcon={() => <Image />}
|
|
67
|
+
renderTrailingIcon={() => <Image />}
|
|
68
|
+
/>
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Fixes [#188](https://github.com/calintamas/react-native-toast-message/issues/188), [#203](https://github.com/calintamas/react-native-toast-message/issues/203), [#245](https://github.com/calintamas/react-native-toast-message/issues/245), [#250](https://github.com/calintamas/react-native-toast-message/issues/250).
|
|
74
|
+
|
|
75
|
+
- Trailing close icon has been removed from default components `BaseToast`, `SuccessToast`, `ErrorToast` and `InfoToast`. Fixes [#167](https://github.com/calintamas/react-native-toast-message/issues/167).
|
|
76
|
+
|
|
77
|
+
### Fixed
|
|
78
|
+
|
|
79
|
+
- Failed prop type: Invalid props.text2Style key fontSize supplied to BaseToast [#174](https://github.com/calintamas/react-native-toast-message/issues/174).
|
|
80
|
+
- Changing Font Family does not work [#176](https://github.com/calintamas/react-native-toast-message/issues/176)
|
|
81
|
+
- Text1 not showing on Android [#194](https://github.com/calintamas/react-native-toast-message/issues/194)
|
|
82
|
+
- Toast background is Transparent [#219](https://github.com/calintamas/react-native-toast-message/issues/219)
|
|
83
|
+
- TypeError: Cannot read property 'show' of null [#232](https://github.com/calintamas/react-native-toast-message/issues/232)
|
|
84
|
+
- textStyle1 styles not been applied [#233](https://github.com/calintamas/react-native-toast-message/issues/233)
|
|
85
|
+
- Typescript-class component toast message in modal usage [#172](https://github.com/calintamas/react-native-toast-message/issues/172)
|
|
86
|
+
- Getting last toast along with native prompt [#149](https://github.com/calintamas/react-native-toast-message/issues/149)
|
|
87
|
+
- When modal request permission appear then the modal toast on the previous screen also appears -> android [#226](https://github.com/calintamas/react-native-toast-message/issues/226)
|
|
88
|
+
- autoHide: false crashes on android [#256](https://github.com/calintamas/react-native-toast-message/issues/256)
|
|
89
|
+
|
|
90
|
+
## [1.6.0]
|
|
91
|
+
|
|
92
|
+
### Added
|
|
93
|
+
|
|
94
|
+
- Export all default Toast components (`BaseToast`, `SuccessToast`, `InfoToast`, `ErrorToast`) to be able to reuse them with custom props ([#225](https://github.com/calintamas/react-native-toast-message/pull/225))
|
|
11
95
|
|
|
12
96
|
## [1.5.0]
|
|
13
97
|
|
|
14
98
|
### Changed
|
|
15
99
|
|
|
16
100
|
- Move `show` method options to separate `ToastShowOptions` interface ([#242](https://github.com/calintamas/react-native-toast-message/pull/242))
|
|
17
|
-
- Use `StyleProp` in type definition file, to allow different types of style to be used (eg. `style={[styles.one, styles.two]}`) ([#243](https://github.com/calintamas/react-native-toast-message/pull/
|
|
101
|
+
- Use `StyleProp` in type definition file, to allow different types of style to be used (eg. `style={[styles.one, styles.two]}`) ([#243](https://github.com/calintamas/react-native-toast-message/pull/243))
|
|
18
102
|
|
|
19
103
|
## [1.4.9]
|
|
20
104
|
|
package/README.md
CHANGED
|
@@ -3,249 +3,33 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/react-native-toast-message)
|
|
4
4
|
[](https://www.npmjs.com/package/react-native-toast-message)
|
|
5
5
|
[](https://github.com/calintamas/react-native-toast-message/actions?query=workflow%3Atests)
|
|
6
|
+
[](https://coveralls.io/github/calintamas/react-native-toast-message)
|
|
6
7
|
[](https://github.com/prettier/prettier)
|
|
7
8
|
|
|
8
9
|
Animated toast message component for React Native.
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
- Keyboard aware
|
|
12
|
-
- Flexible config
|
|
11
|
+

|
|
13
12
|
|
|
14
|
-
##
|
|
13
|
+
## Features
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
- 🚀 Imperative API
|
|
16
|
+
- 📦 Very lightweight (~40 kB)
|
|
17
|
+
- ⌨️ Keyboard-aware
|
|
18
|
+
- 🎨 Customizable layouts
|
|
19
|
+
- 🔧 Flexible config
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
## Documentation
|
|
21
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](./CHANGELOG.md#200).
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
- [Quick start](./docs/quick-start.md)
|
|
26
|
+
- [API](./docs/api.md)
|
|
27
|
+
- [Create custom layouts](./docs/custom-layouts.md)
|
|
28
|
+
- FAQ
|
|
29
|
+
- [How to show the Toast inside a Modal?](./docs/modal-usage.md)
|
|
30
|
+
- [How to render the Toast when using a Navigation library?](./docs/navigation-usage.md)
|
|
31
|
+
- [How to mock the library for testing with jest?](./docs/jest-testing.md)
|
|
25
32
|
|
|
26
|
-
|
|
27
|
-
// App.jsx
|
|
28
|
-
import Toast from 'react-native-toast-message';
|
|
33
|
+
## License
|
|
29
34
|
|
|
30
|
-
|
|
31
|
-
return (
|
|
32
|
-
<>
|
|
33
|
-
{/* ... */}
|
|
34
|
-
<Toast ref={(ref) => Toast.setRef(ref)} />
|
|
35
|
-
</>
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export default App;
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
Then use it anywhere in your app (even outside React components), by calling any `Toast` method directly:
|
|
43
|
-
|
|
44
|
-
```js
|
|
45
|
-
import Toast from 'react-native-toast-message';
|
|
46
|
-
|
|
47
|
-
function SomeComponent() {
|
|
48
|
-
React.useEffect(() => {
|
|
49
|
-
Toast.show({
|
|
50
|
-
type: 'success',
|
|
51
|
-
text1: 'Hello',
|
|
52
|
-
text2: 'This is some something 👋'
|
|
53
|
-
});
|
|
54
|
-
}, []);
|
|
55
|
-
|
|
56
|
-
return <View />;
|
|
57
|
-
}
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## API
|
|
61
|
-
|
|
62
|
-
### `show(options = {})`
|
|
63
|
-
|
|
64
|
-
When calling the `show` method, you can use the following `options` to suit your needs. Everything is optional, unless specified otherwise.
|
|
65
|
-
|
|
66
|
-
The usage of `|` below, means that only one of the values show should be used.
|
|
67
|
-
If only one value is shown, that's the default.
|
|
68
|
-
|
|
69
|
-
```js
|
|
70
|
-
Toast.show({
|
|
71
|
-
type: 'success | error | info',
|
|
72
|
-
position: 'top | bottom',
|
|
73
|
-
text1: 'Hello',
|
|
74
|
-
text2: 'This is some something 👋',
|
|
75
|
-
visibilityTime: 4000,
|
|
76
|
-
autoHide: true,
|
|
77
|
-
topOffset: 30,
|
|
78
|
-
bottomOffset: 40,
|
|
79
|
-
onShow: () => {},
|
|
80
|
-
onHide: () => {}, // called when Toast hides (if `autoHide` was set to `true`)
|
|
81
|
-
onPress: () => {},
|
|
82
|
-
props: {} // any custom props passed to the Toast component
|
|
83
|
-
});
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### `hide()`
|
|
87
|
-
|
|
88
|
-
```js
|
|
89
|
-
Toast.hide();
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
## props
|
|
93
|
-
|
|
94
|
-
Props that can be set on the `Toast` instance. They act as defaults for all Toasts that are shown.
|
|
95
|
-
|
|
96
|
-
```js
|
|
97
|
-
const props = {
|
|
98
|
-
type: 'success | error | info',
|
|
99
|
-
position: 'top' | 'bottom',
|
|
100
|
-
visibilityTime: Number,
|
|
101
|
-
autoHide: Boolean,
|
|
102
|
-
topOffset: Number,
|
|
103
|
-
bottomOffset: Number,
|
|
104
|
-
keyboardOffset: Number,
|
|
105
|
-
config: Object,
|
|
106
|
-
style: ViewStyle,
|
|
107
|
-
height: Number
|
|
108
|
-
};
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
> Default `Animated.View` styles can be found in [styles.js](https://github.com/calintamas/react-native-toast-message/blob/master/src/styles.js#L4). They can be extended using the `style` prop.
|
|
112
|
-
|
|
113
|
-
## Customize layout
|
|
114
|
-
|
|
115
|
-
If you want to add custom types - or overwrite the existing ones - you can add a `config` prop when rendering the `Toast` in your app `root`.
|
|
116
|
-
|
|
117
|
-
You can either use the default `BaseToast` style and adjust its layout, or create Toast layouts from scratch.
|
|
118
|
-
|
|
119
|
-
```js
|
|
120
|
-
// App.jsx
|
|
121
|
-
import Toast, { BaseToast } from 'react-native-toast-message';
|
|
122
|
-
|
|
123
|
-
const toastConfig = {
|
|
124
|
-
/*
|
|
125
|
-
overwrite 'success' type,
|
|
126
|
-
modifying the existing `BaseToast` component
|
|
127
|
-
*/
|
|
128
|
-
success: ({ text1, props, ...rest }) => (
|
|
129
|
-
<BaseToast
|
|
130
|
-
{...rest}
|
|
131
|
-
style={{ borderLeftColor: 'pink' }}
|
|
132
|
-
contentContainerStyle={{ paddingHorizontal: 15 }}
|
|
133
|
-
text1Style={{
|
|
134
|
-
fontSize: 15,
|
|
135
|
-
fontWeight: '400'
|
|
136
|
-
}}
|
|
137
|
-
text1={text1}
|
|
138
|
-
text2={props.uuid}
|
|
139
|
-
/>
|
|
140
|
-
),
|
|
141
|
-
|
|
142
|
-
/*
|
|
143
|
-
or create a completely new type - `my_custom_type`,
|
|
144
|
-
building the layout from scratch
|
|
145
|
-
*/
|
|
146
|
-
my_custom_type: ({ text1, props, ...rest }) => (
|
|
147
|
-
<View style={{ height: 60, width: '100%', backgroundColor: 'tomato' }}>
|
|
148
|
-
<Text>{text1}</Text>
|
|
149
|
-
</View>
|
|
150
|
-
)
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
function App(props) {
|
|
154
|
-
// pass `toastConfig` to the Toast instance
|
|
155
|
-
return (
|
|
156
|
-
<>
|
|
157
|
-
<Toast config={toastConfig} ref={(ref) => Toast.setRef(ref)} />
|
|
158
|
-
</>
|
|
159
|
-
);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
export default App;
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
Then just use the library as before
|
|
166
|
-
|
|
167
|
-
```js
|
|
168
|
-
Toast.show({
|
|
169
|
-
type: 'my_custom_type',
|
|
170
|
-
props: { uuid: 'bba1a7d0-6ab2-4a0a-a76e-ebbe05ae6d70' }
|
|
171
|
-
});
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
Available `props` on `BaseToast`:
|
|
175
|
-
|
|
176
|
-
```js
|
|
177
|
-
const baseToastProps = {
|
|
178
|
-
leadingIcon: ImageSource,
|
|
179
|
-
trailingIcon: ImageSource,
|
|
180
|
-
text1: String,
|
|
181
|
-
text2: String,
|
|
182
|
-
onPress: Function,
|
|
183
|
-
onLeadingIconPress: Function,
|
|
184
|
-
onTrailingIconPress: Function,
|
|
185
|
-
style: ViewStyle,
|
|
186
|
-
leadingIconContainerStyle: ViewStyle,
|
|
187
|
-
trailingIconContainerStyle: ViewStyle,
|
|
188
|
-
leadingIconStyle: ViewStyle,
|
|
189
|
-
trailingIconStyle: ViewStyle,
|
|
190
|
-
contentContainerStyle: ViewStyle,
|
|
191
|
-
text1Style: ViewStyle,
|
|
192
|
-
text2Style: ViewStyle,
|
|
193
|
-
activeOpacity: Number
|
|
194
|
-
};
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
## FAQ
|
|
198
|
-
|
|
199
|
-
### How to render the Toast when using [react-navigation](https://reactnavigation.org)?
|
|
200
|
-
|
|
201
|
-
To have the toast visible on top of the navigation `View` hierarchy, render it as the **last child** inside `NavigationContainer`.
|
|
202
|
-
|
|
203
|
-
```js
|
|
204
|
-
import Toast from 'react-native-toast-message'
|
|
205
|
-
import { NavigationContainer } from '@react-navigation/native';
|
|
206
|
-
|
|
207
|
-
export default function App() {
|
|
208
|
-
return (
|
|
209
|
-
<NavigationContainer>
|
|
210
|
-
{...}
|
|
211
|
-
<Toast ref={(ref) => Toast.setRef(ref)} />
|
|
212
|
-
</NavigationContainer>
|
|
213
|
-
);
|
|
214
|
-
}
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
### How to mock the library for testing with [jest](https://jestjs.io)?
|
|
218
|
-
|
|
219
|
-
```js
|
|
220
|
-
jest.mock('react-native-toast-message', () => ({
|
|
221
|
-
show: jest.fn(),
|
|
222
|
-
hide: jest.fn()
|
|
223
|
-
}));
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
### How to show the Toast inside a Modal?
|
|
227
|
-
|
|
228
|
-
When a `Modal` is visible, the Toast gets rendered behind it. This is due to [the way `Modal` is implemented](https://stackoverflow.com/a/57402783). As a workaround, you can have 2 separate Toast instances: one inside the Modal (let's call it a "modal toast") and a normal one outside.
|
|
229
|
-
|
|
230
|
-
For the one outside, set the ref on the Toast object (like usual)
|
|
231
|
-
```js
|
|
232
|
-
<Toast ref={ref => Toast.setRef(ref) />
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
And for the "modal toast", use another ref
|
|
236
|
-
```js
|
|
237
|
-
function ScreenWithModal() {
|
|
238
|
-
const modalToastRef = React.useRef();
|
|
239
|
-
|
|
240
|
-
return (
|
|
241
|
-
<Modal>
|
|
242
|
-
<Toast ref={modalToastRef} />
|
|
243
|
-
</Modal>
|
|
244
|
-
);
|
|
245
|
-
}
|
|
246
|
-
```
|
|
247
|
-
Then, when you want to show the "modal toast", call it using `modalToastRef.current.show()`.
|
|
248
|
-
|
|
249
|
-
## Credits
|
|
250
|
-
|
|
251
|
-
The icons for the default `success`, `error` and `info` types are made by [Pixel perfect](https://www.flaticon.com/authors/pixel-perfect) from [flaticon.com](www.flaticon.com).
|
|
35
|
+
MIT
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { Toast as default } from './src/Toast';
|
|
2
|
+
export { BaseToast } from './src/components/BaseToast';
|
|
3
|
+
export { SuccessToast } from './src/components/SuccessToast';
|
|
4
|
+
export { ErrorToast } from './src/components/ErrorToast';
|
|
5
|
+
export { InfoToast } from './src/components/InfoToast';
|
|
6
|
+
export * from './src/types';
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { Toast as default } from './src/Toast';
|
|
2
|
+
export { BaseToast } from './src/components/BaseToast';
|
|
3
|
+
export { SuccessToast } from './src/components/SuccessToast';
|
|
4
|
+
export { ErrorToast } from './src/components/ErrorToast';
|
|
5
|
+
export { InfoToast } from './src/components/InfoToast';
|
|
6
|
+
export * from './src/types';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { ToastProps, ToastShowParams } from './types';
|
|
3
|
+
export declare function Toast(props: ToastProps): JSX.Element;
|
|
4
|
+
export declare namespace Toast {
|
|
5
|
+
var show: (params: ToastShowParams) => void;
|
|
6
|
+
var hide: (params?: void | undefined) => void;
|
|
7
|
+
}
|
package/lib/src/Toast.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { LoggerProvider } from './contexts';
|
|
3
|
+
import { ToastUI } from './ToastUI';
|
|
4
|
+
import { useToast } from './useToast';
|
|
5
|
+
const ToastRoot = React.forwardRef((props, ref) => {
|
|
6
|
+
const { config, ...defaultOptions } = props;
|
|
7
|
+
const { show, hide, isVisible, options, data } = useToast({
|
|
8
|
+
defaultOptions
|
|
9
|
+
});
|
|
10
|
+
React.useImperativeHandle(ref, () => ({
|
|
11
|
+
show,
|
|
12
|
+
hide
|
|
13
|
+
}));
|
|
14
|
+
return (<ToastUI isVisible={isVisible} options={options} data={data} hide={hide} show={show} config={config}/>);
|
|
15
|
+
});
|
|
16
|
+
const toastRef = React.createRef();
|
|
17
|
+
export function Toast(props) {
|
|
18
|
+
return (<LoggerProvider enableLogs={false}>
|
|
19
|
+
<ToastRoot ref={toastRef} {...props}/>
|
|
20
|
+
</LoggerProvider>);
|
|
21
|
+
}
|
|
22
|
+
Toast.show = (params) => {
|
|
23
|
+
toastRef.current?.show(params);
|
|
24
|
+
};
|
|
25
|
+
Toast.hide = (params) => {
|
|
26
|
+
toastRef.current?.hide(params);
|
|
27
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { ToastConfig, ToastData, ToastHideParams, ToastOptions, ToastShowParams } from './types';
|
|
3
|
+
export declare type ToastUIProps = {
|
|
4
|
+
isVisible: boolean;
|
|
5
|
+
options: Required<ToastOptions>;
|
|
6
|
+
data: ToastData;
|
|
7
|
+
show: (params: ToastShowParams) => void;
|
|
8
|
+
hide: (params: ToastHideParams) => void;
|
|
9
|
+
config?: ToastConfig;
|
|
10
|
+
};
|
|
11
|
+
export declare function ToastUI(props: ToastUIProps): JSX.Element;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { AnimatedContainer } from './components/AnimatedContainer';
|
|
3
|
+
import { ErrorToast } from './components/ErrorToast';
|
|
4
|
+
import { InfoToast } from './components/InfoToast';
|
|
5
|
+
import { SuccessToast } from './components/SuccessToast';
|
|
6
|
+
const defaultToastConfig = {
|
|
7
|
+
success: (props) => <SuccessToast {...props}/>,
|
|
8
|
+
error: (props) => <ErrorToast {...props}/>,
|
|
9
|
+
info: (props) => <InfoToast {...props}/>
|
|
10
|
+
};
|
|
11
|
+
function renderComponent({ data, options, config, isVisible, show, hide }) {
|
|
12
|
+
const { text1, text2 } = data;
|
|
13
|
+
const { type, onPress, position, props } = options;
|
|
14
|
+
const toastConfig = {
|
|
15
|
+
...defaultToastConfig,
|
|
16
|
+
...config
|
|
17
|
+
};
|
|
18
|
+
const ToastComponent = toastConfig[type];
|
|
19
|
+
if (!ToastComponent) {
|
|
20
|
+
throw new Error(`Toast type: '${type}' does not exist. You can add it via the 'config' prop on the Toast instance. Learn more: https://github.com/calintamas/react-native-toast-message/blob/master/README.md`);
|
|
21
|
+
}
|
|
22
|
+
return ToastComponent({
|
|
23
|
+
position,
|
|
24
|
+
type,
|
|
25
|
+
isVisible,
|
|
26
|
+
text1,
|
|
27
|
+
text2,
|
|
28
|
+
show,
|
|
29
|
+
hide,
|
|
30
|
+
onPress,
|
|
31
|
+
props
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
export function ToastUI(props) {
|
|
35
|
+
const { isVisible, options, hide } = props;
|
|
36
|
+
const { position, topOffset, bottomOffset, keyboardOffset } = options;
|
|
37
|
+
return (<AnimatedContainer isVisible={isVisible} position={position} topOffset={topOffset} bottomOffset={bottomOffset} keyboardOffset={keyboardOffset} onHide={hide}>
|
|
38
|
+
{renderComponent(props)}
|
|
39
|
+
</AnimatedContainer>);
|
|
40
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { PanResponderGestureState } from 'react-native';
|
|
3
|
+
import { ReactChildren, ToastPosition } from '../types';
|
|
4
|
+
export declare type AnimatedContainerProps = {
|
|
5
|
+
children: ReactChildren;
|
|
6
|
+
isVisible: boolean;
|
|
7
|
+
position: ToastPosition;
|
|
8
|
+
topOffset: number;
|
|
9
|
+
bottomOffset: number;
|
|
10
|
+
keyboardOffset: number;
|
|
11
|
+
onHide: () => void;
|
|
12
|
+
onRestorePosition?: () => void;
|
|
13
|
+
};
|
|
14
|
+
export declare function dampingFor(gesture: PanResponderGestureState, position: ToastPosition): number;
|
|
15
|
+
export declare function animatedValueFor(gesture: PanResponderGestureState, position: ToastPosition, damping: number): number;
|
|
16
|
+
export declare function AnimatedContainer({ children, isVisible, position, topOffset, bottomOffset, keyboardOffset, onHide, onRestorePosition }: AnimatedContainerProps): JSX.Element;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Animated, Dimensions } from 'react-native';
|
|
3
|
+
import { useLogger } from '../contexts';
|
|
4
|
+
import { usePanResponder, useSlideAnimation, useViewDimensions } from '../hooks';
|
|
5
|
+
import { noop } from '../utils/func';
|
|
6
|
+
import { bound } from '../utils/number';
|
|
7
|
+
import { getTestId } from '../utils/test-id';
|
|
8
|
+
import { styles } from './AnimatedContainer.styles';
|
|
9
|
+
export function dampingFor(gesture, position) {
|
|
10
|
+
const { moveY } = gesture;
|
|
11
|
+
switch (position) {
|
|
12
|
+
case 'bottom': {
|
|
13
|
+
const { height: screenHeight } = Dimensions.get('screen');
|
|
14
|
+
return screenHeight - moveY;
|
|
15
|
+
}
|
|
16
|
+
case 'top':
|
|
17
|
+
return moveY;
|
|
18
|
+
default:
|
|
19
|
+
throw new Error(`Toast position: ${position} not implemented`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function animatedValueFor(gesture, position, damping) {
|
|
23
|
+
const boundValue = (val) => bound(val, 0, 2);
|
|
24
|
+
const { dy } = gesture;
|
|
25
|
+
switch (position) {
|
|
26
|
+
case 'bottom':
|
|
27
|
+
return boundValue(1 - dy / damping);
|
|
28
|
+
case 'top':
|
|
29
|
+
return boundValue(1 + dy / damping);
|
|
30
|
+
default:
|
|
31
|
+
throw new Error(`Toast position: ${position} not implemented`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export function AnimatedContainer({ children, isVisible, position, topOffset, bottomOffset, keyboardOffset, onHide, onRestorePosition = noop }) {
|
|
35
|
+
const { log } = useLogger();
|
|
36
|
+
const { computeViewDimensions, height } = useViewDimensions();
|
|
37
|
+
const { animatedValue, animate, animationStyles } = useSlideAnimation({
|
|
38
|
+
position,
|
|
39
|
+
height,
|
|
40
|
+
topOffset,
|
|
41
|
+
bottomOffset,
|
|
42
|
+
keyboardOffset
|
|
43
|
+
});
|
|
44
|
+
const onDismiss = React.useCallback(() => {
|
|
45
|
+
log('Swipe, dismissing');
|
|
46
|
+
animate(0);
|
|
47
|
+
onHide();
|
|
48
|
+
}, [animate, log, onHide]);
|
|
49
|
+
const onRestore = React.useCallback(() => {
|
|
50
|
+
log('Swipe, restoring to original position');
|
|
51
|
+
animate(1);
|
|
52
|
+
onRestorePosition();
|
|
53
|
+
}, [animate, log, onRestorePosition]);
|
|
54
|
+
const computeNewAnimatedValueForGesture = React.useCallback((gesture) => {
|
|
55
|
+
const damping = dampingFor(gesture, position);
|
|
56
|
+
const newAnimatedValue = animatedValueFor(gesture, position, damping);
|
|
57
|
+
return newAnimatedValue;
|
|
58
|
+
}, [position]);
|
|
59
|
+
const { panResponder } = usePanResponder({
|
|
60
|
+
animatedValue,
|
|
61
|
+
computeNewAnimatedValueForGesture,
|
|
62
|
+
onDismiss,
|
|
63
|
+
onRestore
|
|
64
|
+
});
|
|
65
|
+
React.useLayoutEffect(() => {
|
|
66
|
+
const newAnimationValue = isVisible ? 1 : 0;
|
|
67
|
+
animate(newAnimationValue);
|
|
68
|
+
}, [animate, isVisible]);
|
|
69
|
+
return (<Animated.View testID={getTestId('AnimatedContainer')} onLayout={computeViewDimensions} style={[styles.base, styles[position], animationStyles]} {...panResponder.panHandlers}>
|
|
70
|
+
{children}
|
|
71
|
+
</Animated.View>);
|
|
72
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
export const styles = StyleSheet.create({
|
|
3
|
+
base: {
|
|
4
|
+
position: 'absolute',
|
|
5
|
+
alignItems: 'center',
|
|
6
|
+
justifyContent: 'center',
|
|
7
|
+
alignSelf: 'center'
|
|
8
|
+
},
|
|
9
|
+
top: {
|
|
10
|
+
top: 0
|
|
11
|
+
},
|
|
12
|
+
bottom: {
|
|
13
|
+
bottom: 0
|
|
14
|
+
}
|
|
15
|
+
});
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { BaseToastProps } from '../types';
|
|
3
|
+
export declare function BaseToast({ text1, text2, onPress, activeOpacity, style, touchableContainerProps, contentContainerStyle, contentContainerProps, text1Style, text1NumberOfLines, text1Props, text2Style, text2NumberOfLines, text2Props, renderLeadingIcon, renderTrailingIcon }: BaseToastProps): JSX.Element;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Text, View } from 'react-native';
|
|
3
|
+
import { getTestId } from '../utils/test-id';
|
|
4
|
+
import { styles } from './BaseToast.styles';
|
|
5
|
+
import { Touchable } from './Touchable';
|
|
6
|
+
export function BaseToast({ text1, text2, onPress, activeOpacity, style, touchableContainerProps, contentContainerStyle, contentContainerProps, text1Style, text1NumberOfLines = 1, text1Props, text2Style, text2NumberOfLines = 1, text2Props, renderLeadingIcon, renderTrailingIcon }) {
|
|
7
|
+
return (<Touchable testID={getTestId('TouchableContainer')} onPress={onPress} activeOpacity={activeOpacity} style={[styles.base, styles.leadingBorder, style]} {...touchableContainerProps}>
|
|
8
|
+
{renderLeadingIcon && renderLeadingIcon()}
|
|
9
|
+
<View testID={getTestId('ContentContainer')} style={[styles.contentContainer, contentContainerStyle]} {...contentContainerProps}>
|
|
10
|
+
{text1 && text1.length > 0 && (<Text testID={getTestId('Text1')} style={[styles.text1, text1Style]} numberOfLines={text1NumberOfLines} ellipsizeMode='tail' {...text1Props}>
|
|
11
|
+
{text1}
|
|
12
|
+
</Text>)}
|
|
13
|
+
{text2 && text2?.length > 0 && (<Text testID={getTestId('Text2')} style={[styles.text2, text2Style]} numberOfLines={text2NumberOfLines} ellipsizeMode='tail' {...text2Props}>
|
|
14
|
+
{text2}
|
|
15
|
+
</Text>)}
|
|
16
|
+
</View>
|
|
17
|
+
{renderTrailingIcon && renderTrailingIcon()}
|
|
18
|
+
</Touchable>);
|
|
19
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export declare const HEIGHT = 60;
|
|
2
|
+
export declare const WIDTH = 340;
|
|
3
|
+
export declare const BORDER_RADIUS = 6;
|
|
4
|
+
export declare const styles: {
|
|
5
|
+
base: {
|
|
6
|
+
flexDirection: "row";
|
|
7
|
+
height: number;
|
|
8
|
+
width: number;
|
|
9
|
+
borderRadius: number;
|
|
10
|
+
shadowOffset: {
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
};
|
|
14
|
+
shadowOpacity: number;
|
|
15
|
+
shadowRadius: number;
|
|
16
|
+
elevation: number;
|
|
17
|
+
backgroundColor: string;
|
|
18
|
+
};
|
|
19
|
+
leadingBorder: {
|
|
20
|
+
borderLeftWidth: number;
|
|
21
|
+
borderLeftColor: string;
|
|
22
|
+
};
|
|
23
|
+
contentContainer: {
|
|
24
|
+
paddingHorizontal: number;
|
|
25
|
+
flex: number;
|
|
26
|
+
justifyContent: "center";
|
|
27
|
+
alignItems: "flex-start";
|
|
28
|
+
};
|
|
29
|
+
text1: {
|
|
30
|
+
fontSize: number;
|
|
31
|
+
fontWeight: "bold";
|
|
32
|
+
marginBottom: number;
|
|
33
|
+
color: string;
|
|
34
|
+
width: string;
|
|
35
|
+
};
|
|
36
|
+
text2: {
|
|
37
|
+
fontSize: number;
|
|
38
|
+
color: string;
|
|
39
|
+
width: string;
|
|
40
|
+
};
|
|
41
|
+
};
|