@widergy/mobile-ui 1.12.6 → 1.13.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 +14 -0
- package/lib/components/UTAutocomplete/index.js +6 -2
- package/lib/components/UTLoading/README.md +15 -11
- package/lib/components/UTLoading/components/AnimatedCircles/constants.js +9 -0
- package/lib/components/UTLoading/components/AnimatedCircles/index.js +112 -0
- package/lib/components/UTLoading/components/AnimatedCircles/styles.js +28 -0
- package/lib/components/UTLoading/components/Spinner/index.js +56 -0
- package/lib/components/UTLoading/index.js +8 -45
- package/lib/components/UTMenu/components/ListView/index.js +1 -1
- package/lib/components/UTMenu/index.js +8 -7
- package/lib/components/UTMenu/styles.js +0 -1
- package/package.json +1 -1
- /package/lib/components/UTLoading/{styles.js → components/Spinner/styles.js} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [1.13.0](https://github.com/widergy/mobile-ui/compare/v1.12.7...v1.13.0) (2024-07-11)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* new loader ([#312](https://github.com/widergy/mobile-ui/issues/312)) ([2293385](https://github.com/widergy/mobile-ui/commit/229338516523e69a1d0f8104087acab2d3e9b1cb))
|
|
7
|
+
|
|
8
|
+
## [1.12.7](https://github.com/widergy/mobile-ui/compare/v1.12.6...v1.12.7) (2024-07-08)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* utmenu passes selected item value to onclose func ([#307](https://github.com/widergy/mobile-ui/issues/307)) ([b82c033](https://github.com/widergy/mobile-ui/commit/b82c033a284dfa3d647930cd33b0c5b0dfd269ce))
|
|
14
|
+
|
|
1
15
|
## [1.12.6](https://github.com/widergy/mobile-ui/compare/v1.12.5...v1.12.6) (2024-07-03)
|
|
2
16
|
|
|
3
17
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { arrayOf, bool, element, func, oneOf, shape, string } from 'prop-types';
|
|
2
2
|
import React, { useEffect, useState } from 'react';
|
|
3
3
|
import { View } from 'react-native';
|
|
4
|
+
import { ViewPropTypes } from 'deprecated-react-native-prop-types';
|
|
4
5
|
|
|
5
6
|
import { WINDOW_HEIGHT } from '../../utils/scaleUtils';
|
|
6
7
|
import UTMenu from '../UTMenu';
|
|
@@ -21,7 +22,8 @@ const UTAutocomplete = ({
|
|
|
21
22
|
MenuOptionComponent,
|
|
22
23
|
options,
|
|
23
24
|
persistSelectedOption = false,
|
|
24
|
-
variant
|
|
25
|
+
variant,
|
|
26
|
+
styles: propStyles
|
|
25
27
|
}) => {
|
|
26
28
|
const [selectedOption, setSelectedOption] = useState();
|
|
27
29
|
|
|
@@ -54,6 +56,7 @@ const UTAutocomplete = ({
|
|
|
54
56
|
options={options}
|
|
55
57
|
selectedOption={selectedOption?.id}
|
|
56
58
|
withAutocomplete
|
|
59
|
+
styles={propStyles?.UTMenu}
|
|
57
60
|
>
|
|
58
61
|
<UTTextInput
|
|
59
62
|
disabled={disabled}
|
|
@@ -94,7 +97,8 @@ UTAutocomplete.propTypes = {
|
|
|
94
97
|
})
|
|
95
98
|
),
|
|
96
99
|
persistSelectedOption: bool,
|
|
97
|
-
variant: string
|
|
100
|
+
variant: string,
|
|
101
|
+
styles: ViewPropTypes.style
|
|
98
102
|
};
|
|
99
103
|
|
|
100
104
|
export default UTAutocomplete;
|
|
@@ -4,24 +4,27 @@ Wraps a component within a screen and displays a loading indicator until it's do
|
|
|
4
4
|
|
|
5
5
|
## Props
|
|
6
6
|
|
|
7
|
-
|NAME|TYPE|REQUIRED|DESCRIPTION|
|
|
8
|
-
|
|
9
|
-
|children|PropTypes.element|Yes|The component that you want to wrap until it's done loading|
|
|
10
|
-
|loading|PropTypes.bool|Yes|The boolean
|
|
11
|
-
|color|PropTypes.string|No|Color of spinner. Uses the theme's primary color by default|
|
|
12
|
-
|size|PropTypes.number|No|The size of the spinner, defaults to
|
|
13
|
-
|thickness|PropTypes.number|No|The thickness of the spinner, defaults to
|
|
14
|
-
|style|ViewPropTypes.style|No|custom style applied to the spinner's container|
|
|
15
|
-
|message|PropTypes.string|No|A message to display below the spinner|
|
|
16
|
-
|messageStyle|ViewPropTypes.style|No|Custom style applied to the message|
|
|
7
|
+
| NAME | TYPE | REQUIRED | USED BY | DESCRIPTION |
|
|
8
|
+
| ----------------- | ------------------- | -------- | :-----------------------: | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
9
|
+
| children | PropTypes.element | Yes | AnimatedCircles - Spinner | The component that you want to wrap until it's done loading |
|
|
10
|
+
| loading | PropTypes.bool | Yes | AnimatedCircles - Spinner | The boolean`loading` that you want the spinner to depend on |
|
|
11
|
+
| color | PropTypes.string | No | AnimatedCircles - Spinner | Color of spinner. Uses the theme's primary color by default |
|
|
12
|
+
| size | PropTypes.number | No | Spinner | The size of the spinner, defaults to`70` |
|
|
13
|
+
| thickness | PropTypes.number | No | Spinner | The thickness of the spinner, defaults to`3` |
|
|
14
|
+
| style | ViewPropTypes.style | No | Spinner | custom style applied to the spinner's container |
|
|
15
|
+
| message | PropTypes.string | No | Spinner | A message to display below the spinner |
|
|
16
|
+
| messageStyle | ViewPropTypes.style | No | Spinner | Custom style applied to the message |
|
|
17
|
+
| Logo | PropTypes.number | No | AnimatedCircles | Utility logo (png) shown above the animated circles. |
|
|
18
|
+
| useUtilityLoading | PropTypes.bool | No | AnimatedCircles - Spinner | Flag that determines whether to show the classic loader (spinner) or the new one (animated circles with utility logo).<br /> (_Default: classic loader_). |
|
|
17
19
|
|
|
18
20
|
## Example
|
|
21
|
+
|
|
19
22
|
```js
|
|
20
23
|
import { Loading } from "@widergy/mobile-ui";
|
|
21
24
|
|
|
22
25
|
return (
|
|
23
26
|
<Label>This component does not depend on the loader</Label>
|
|
24
|
-
<UTLoading
|
|
27
|
+
<UTLoading
|
|
25
28
|
loading={this.props.loading}
|
|
26
29
|
color="blue"
|
|
27
30
|
size={200}
|
|
@@ -33,3 +36,4 @@ import { Loading } from "@widergy/mobile-ui";
|
|
|
33
36
|
{your wrapped component goes here}
|
|
34
37
|
</UTLoading>
|
|
35
38
|
)
|
|
39
|
+
```
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const OPACITY_LOW = 0.33;
|
|
2
|
+
export const OPACITY_MEDIUM = 0.66;
|
|
3
|
+
export const OPACITY_HIGH = 1;
|
|
4
|
+
|
|
5
|
+
export const TRANSLATE_INITIAL_VALUE = -12;
|
|
6
|
+
export const TRANSLATE_FINAL_VALUE = 0;
|
|
7
|
+
|
|
8
|
+
export const TRANSLATE_DURATION = 280;
|
|
9
|
+
export const OPACITY_DURATION = 200;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/* eslint-disable react/no-array-index-key */
|
|
2
|
+
import React, { useEffect, useRef } from 'react';
|
|
3
|
+
import { Animated, Image, View } from 'react-native';
|
|
4
|
+
import { string, bool, node, number } from 'prop-types';
|
|
5
|
+
|
|
6
|
+
import { useTheme } from '../../../../theming';
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
OPACITY_DURATION,
|
|
10
|
+
OPACITY_HIGH,
|
|
11
|
+
OPACITY_LOW,
|
|
12
|
+
OPACITY_MEDIUM,
|
|
13
|
+
TRANSLATE_DURATION,
|
|
14
|
+
TRANSLATE_FINAL_VALUE,
|
|
15
|
+
TRANSLATE_INITIAL_VALUE
|
|
16
|
+
} from './constants';
|
|
17
|
+
import styles from './styles';
|
|
18
|
+
|
|
19
|
+
const AnimatedCircles = ({ children, color, loading, Logo }) => {
|
|
20
|
+
const theme = useTheme();
|
|
21
|
+
const neutralTheme = theme.Palette.neutral;
|
|
22
|
+
const lightTheme = theme.Palette.light;
|
|
23
|
+
const animations = useRef([new Animated.Value(0), new Animated.Value(0), new Animated.Value(0)]).current;
|
|
24
|
+
const opacities = useRef([
|
|
25
|
+
new Animated.Value(OPACITY_HIGH),
|
|
26
|
+
new Animated.Value(OPACITY_LOW),
|
|
27
|
+
new Animated.Value(OPACITY_MEDIUM)
|
|
28
|
+
]).current;
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
const onAnimate = index => {
|
|
32
|
+
const nextIndex = (index + 1) % animations.length;
|
|
33
|
+
Animated.sequence([
|
|
34
|
+
Animated.parallel([
|
|
35
|
+
Animated.timing(animations[index], {
|
|
36
|
+
duration: TRANSLATE_DURATION,
|
|
37
|
+
toValue: TRANSLATE_INITIAL_VALUE,
|
|
38
|
+
useNativeDriver: true
|
|
39
|
+
}),
|
|
40
|
+
Animated.timing(opacities[index], {
|
|
41
|
+
duration: OPACITY_DURATION,
|
|
42
|
+
toValue: OPACITY_HIGH,
|
|
43
|
+
useNativeDriver: true
|
|
44
|
+
})
|
|
45
|
+
]),
|
|
46
|
+
Animated.delay(500),
|
|
47
|
+
Animated.parallel([
|
|
48
|
+
Animated.timing(animations[index], {
|
|
49
|
+
duration: TRANSLATE_DURATION,
|
|
50
|
+
toValue: TRANSLATE_FINAL_VALUE,
|
|
51
|
+
useNativeDriver: true
|
|
52
|
+
}),
|
|
53
|
+
Animated.timing(opacities[index], {
|
|
54
|
+
duration: OPACITY_DURATION,
|
|
55
|
+
toValue: OPACITY_MEDIUM,
|
|
56
|
+
useNativeDriver: true
|
|
57
|
+
}),
|
|
58
|
+
Animated.timing(animations[nextIndex], {
|
|
59
|
+
duration: TRANSLATE_DURATION,
|
|
60
|
+
toValue: TRANSLATE_INITIAL_VALUE,
|
|
61
|
+
useNativeDriver: true
|
|
62
|
+
}),
|
|
63
|
+
Animated.timing(opacities[nextIndex], {
|
|
64
|
+
duration: OPACITY_DURATION,
|
|
65
|
+
toValue: OPACITY_HIGH,
|
|
66
|
+
useNativeDriver: true
|
|
67
|
+
}),
|
|
68
|
+
Animated.timing(opacities[(index + 2) % animations.length], {
|
|
69
|
+
duration: OPACITY_DURATION,
|
|
70
|
+
toValue: OPACITY_LOW,
|
|
71
|
+
useNativeDriver: true
|
|
72
|
+
})
|
|
73
|
+
])
|
|
74
|
+
]).start(() => {
|
|
75
|
+
onAnimate(nextIndex);
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
onAnimate(0);
|
|
80
|
+
}, [animations, opacities]);
|
|
81
|
+
|
|
82
|
+
return loading ? (
|
|
83
|
+
<View style={{ ...styles.container, backgroundColor: lightTheme['01'] }}>
|
|
84
|
+
{Logo && <Image resizeMode="contain" source={Logo} style={styles.imageStyle} />}
|
|
85
|
+
|
|
86
|
+
<View style={styles.circlesContainer}>
|
|
87
|
+
{animations.map((_, index) => (
|
|
88
|
+
<Animated.View
|
|
89
|
+
key={index}
|
|
90
|
+
style={[
|
|
91
|
+
{ ...styles.circle, backgroundColor: color || neutralTheme['04'] },
|
|
92
|
+
{ transform: [{ translateY: animations[index] }], opacity: opacities[index] }
|
|
93
|
+
]}
|
|
94
|
+
/>
|
|
95
|
+
))}
|
|
96
|
+
</View>
|
|
97
|
+
</View>
|
|
98
|
+
) : (
|
|
99
|
+
children
|
|
100
|
+
);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
AnimatedCircles.displayName = 'UTLoading';
|
|
104
|
+
|
|
105
|
+
AnimatedCircles.propTypes = {
|
|
106
|
+
children: node,
|
|
107
|
+
color: string,
|
|
108
|
+
loading: bool,
|
|
109
|
+
Logo: number
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export default AnimatedCircles;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
|
|
3
|
+
import { verticalScale } from '../../../../utils/scaleUtils';
|
|
4
|
+
|
|
5
|
+
export default StyleSheet.create({
|
|
6
|
+
container: {
|
|
7
|
+
alignItems: 'center',
|
|
8
|
+
backgroundColor: '#ffffff',
|
|
9
|
+
flex: 1,
|
|
10
|
+
flexDirection: 'column',
|
|
11
|
+
justifyContent: 'center',
|
|
12
|
+
width: '100%'
|
|
13
|
+
},
|
|
14
|
+
circlesContainer: {
|
|
15
|
+
marginTop: 50,
|
|
16
|
+
flexDirection: 'row'
|
|
17
|
+
},
|
|
18
|
+
circle: {
|
|
19
|
+
backgroundColor: '#000000',
|
|
20
|
+
borderRadius: 10,
|
|
21
|
+
height: 16,
|
|
22
|
+
margin: 4,
|
|
23
|
+
width: 16
|
|
24
|
+
},
|
|
25
|
+
imageStyle: {
|
|
26
|
+
height: verticalScale(40)
|
|
27
|
+
}
|
|
28
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React, { Fragment } from 'react';
|
|
2
|
+
import { number, string, bool } from 'prop-types';
|
|
3
|
+
import { View } from 'react-native';
|
|
4
|
+
import { ViewPropTypes } from 'deprecated-react-native-prop-types';
|
|
5
|
+
|
|
6
|
+
import Loading from '../../../Loading';
|
|
7
|
+
|
|
8
|
+
import styles from './styles';
|
|
9
|
+
|
|
10
|
+
const Spinner = ({
|
|
11
|
+
children,
|
|
12
|
+
color,
|
|
13
|
+
loading,
|
|
14
|
+
message,
|
|
15
|
+
messageStyle,
|
|
16
|
+
preventUnmount,
|
|
17
|
+
size,
|
|
18
|
+
style,
|
|
19
|
+
thickness
|
|
20
|
+
}) => {
|
|
21
|
+
return (
|
|
22
|
+
<Fragment>
|
|
23
|
+
{!!loading && (
|
|
24
|
+
<Loading
|
|
25
|
+
style={[styles.spinner, style]}
|
|
26
|
+
message={message}
|
|
27
|
+
color={color}
|
|
28
|
+
size={size}
|
|
29
|
+
thickness={thickness}
|
|
30
|
+
messageStyle={messageStyle}
|
|
31
|
+
/>
|
|
32
|
+
)}
|
|
33
|
+
{preventUnmount ? (
|
|
34
|
+
// eslint-disable-next-line react-native/no-inline-styles
|
|
35
|
+
<View style={{ display: loading ? 'none' : 'flex' }}>{children}</View>
|
|
36
|
+
) : (
|
|
37
|
+
!loading && children
|
|
38
|
+
)}
|
|
39
|
+
</Fragment>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
Spinner.displayName = 'UTLoading';
|
|
44
|
+
|
|
45
|
+
Spinner.propTypes = {
|
|
46
|
+
color: string,
|
|
47
|
+
loading: bool,
|
|
48
|
+
message: string,
|
|
49
|
+
messageStyle: ViewPropTypes.style,
|
|
50
|
+
preventUnmount: bool,
|
|
51
|
+
size: number,
|
|
52
|
+
style: ViewPropTypes.style,
|
|
53
|
+
thickness: number
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export default Spinner;
|
|
@@ -1,55 +1,18 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import {
|
|
3
|
-
import { View } from 'react-native';
|
|
4
|
-
import { ViewPropTypes } from 'deprecated-react-native-prop-types';
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { bool } from 'prop-types';
|
|
5
3
|
|
|
6
|
-
import
|
|
4
|
+
import AnimatedCircles from './components/AnimatedCircles';
|
|
5
|
+
import Spinner from './components/Spinner';
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
children,
|
|
12
|
-
color,
|
|
13
|
-
loading,
|
|
14
|
-
message,
|
|
15
|
-
messageStyle,
|
|
16
|
-
preventUnmount,
|
|
17
|
-
size,
|
|
18
|
-
style,
|
|
19
|
-
thickness
|
|
20
|
-
}) => {
|
|
21
|
-
return (
|
|
22
|
-
<Fragment>
|
|
23
|
-
{!!loading && (
|
|
24
|
-
<Loading
|
|
25
|
-
style={[styles.spinner, style]}
|
|
26
|
-
message={message}
|
|
27
|
-
color={color}
|
|
28
|
-
size={size}
|
|
29
|
-
thickness={thickness}
|
|
30
|
-
messageStyle={messageStyle}
|
|
31
|
-
/>
|
|
32
|
-
)}
|
|
33
|
-
{preventUnmount ? (
|
|
34
|
-
<View style={{ display: loading ? 'none' : 'flex' }}>{children}</View>
|
|
35
|
-
) : (
|
|
36
|
-
!loading && children
|
|
37
|
-
)}
|
|
38
|
-
</Fragment>
|
|
39
|
-
);
|
|
7
|
+
const UTLoading = props => {
|
|
8
|
+
const { useUtilityLoading } = props || {};
|
|
9
|
+
return useUtilityLoading ? <AnimatedCircles {...props} /> : <Spinner {...props} />;
|
|
40
10
|
};
|
|
41
11
|
|
|
42
12
|
UTLoading.displayName = 'UTLoading';
|
|
43
13
|
|
|
44
14
|
UTLoading.propTypes = {
|
|
45
|
-
|
|
46
|
-
loading: bool,
|
|
47
|
-
message: string,
|
|
48
|
-
messageStyle: ViewPropTypes.style,
|
|
49
|
-
preventUnmount: bool,
|
|
50
|
-
size: number,
|
|
51
|
-
style: ViewPropTypes.style,
|
|
52
|
-
thickness: number
|
|
15
|
+
useUtilityLoader: bool
|
|
53
16
|
};
|
|
54
17
|
|
|
55
18
|
export default UTLoading;
|
|
@@ -28,7 +28,7 @@ class ListView extends PureComponent {
|
|
|
28
28
|
|
|
29
29
|
handleOnPress = item => {
|
|
30
30
|
const { handleOptionPress, onPress } = this.props;
|
|
31
|
-
return handleOptionPress(item.action || (() => onPress(item)));
|
|
31
|
+
return handleOptionPress(item.action || (() => onPress(item)), item?.value);
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
renderItem = ({ item }) => {
|
|
@@ -3,6 +3,7 @@ import { Dimensions, Keyboard, KeyboardAvoidingView, Modal, TouchableOpacity, Vi
|
|
|
3
3
|
|
|
4
4
|
import useKeyboardHeight from '../../hooks/useKeyboardHeight';
|
|
5
5
|
import UTTextInput from '../UTTextInput';
|
|
6
|
+
import Surface from '../Surface';
|
|
6
7
|
|
|
7
8
|
import MenuOption from './components/MenuOption';
|
|
8
9
|
import ListView from './components/ListView';
|
|
@@ -101,15 +102,15 @@ const UTMenu = ({
|
|
|
101
102
|
setTimeout(() => setIsOpen(true), 20);
|
|
102
103
|
if (onOpen) onOpen();
|
|
103
104
|
};
|
|
104
|
-
const closeMenu =
|
|
105
|
+
const closeMenu = value => {
|
|
105
106
|
setIsOpen(false);
|
|
106
107
|
setQuery('');
|
|
107
|
-
if (onClose) onClose();
|
|
108
|
+
if (onClose) onClose(value);
|
|
108
109
|
};
|
|
109
110
|
|
|
110
|
-
const handleOptionPress = action => {
|
|
111
|
+
const handleOptionPress = (action, value) => {
|
|
111
112
|
action();
|
|
112
|
-
if (!isMultiple) closeMenu();
|
|
113
|
+
if (!isMultiple) closeMenu(value);
|
|
113
114
|
};
|
|
114
115
|
|
|
115
116
|
const focusSearchInput = () => withAutocomplete && searchTextInputRef.current?.focus();
|
|
@@ -140,14 +141,14 @@ const UTMenu = ({
|
|
|
140
141
|
<TouchableOpacity onPress={closeMenu} style={styles.overlayTouchable}>
|
|
141
142
|
<View style={styles.overlay} />
|
|
142
143
|
</TouchableOpacity>
|
|
143
|
-
<
|
|
144
|
+
<Surface
|
|
144
145
|
style={[styles.menu, position, fullWidth && { width: anchorMeasure?.width }, propStyles?.menu]}
|
|
145
146
|
ref={menuRef}
|
|
146
147
|
onLayout={handleMenuLayout}
|
|
147
148
|
>
|
|
148
149
|
<KeyboardAvoidingView behavior="height">
|
|
149
150
|
{withAutocomplete && (
|
|
150
|
-
<View style={styles.searchContainer}>
|
|
151
|
+
<View style={[styles.searchContainer, propStyles?.searchContainer]}>
|
|
151
152
|
<UTTextInput
|
|
152
153
|
InputRef={searchTextInputRef}
|
|
153
154
|
value={query}
|
|
@@ -177,7 +178,7 @@ const UTMenu = ({
|
|
|
177
178
|
isMultiple={isMultiple}
|
|
178
179
|
/>
|
|
179
180
|
</KeyboardAvoidingView>
|
|
180
|
-
</
|
|
181
|
+
</Surface>
|
|
181
182
|
</Modal>
|
|
182
183
|
</Fragment>
|
|
183
184
|
);
|
package/package.json
CHANGED
|
File without changes
|