@widergy/mobile-ui 1.34.0 → 1.36.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/UTStatusMessage/styles.js +1 -1
- package/lib/components/UTTabs/README.md +41 -0
- package/lib/components/UTTabs/constants.js +10 -0
- package/lib/components/UTTabs/index.js +86 -0
- package/lib/components/UTTabs/styles.js +82 -0
- package/lib/index.js +1 -0
- package/lib/utils/analyticsUtils/README.md +21 -0
- package/lib/utils/analyticsUtils/index.js +6 -0
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [1.36.0](https://github.com/widergy/mobile-ui/compare/v1.35.0...v1.36.0) (2025-02-03)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* [EVENSA-67] uttabs ([#409](https://github.com/widergy/mobile-ui/issues/409)) ([e82a497](https://github.com/widergy/mobile-ui/commit/e82a49721c179c63fef5cbfe7d61eaed172476d0))
|
|
7
|
+
|
|
8
|
+
# [1.35.0](https://github.com/widergy/mobile-ui/compare/v1.34.0...v1.35.0) (2025-01-31)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* added util for generating Flow Id's ([5db21ef](https://github.com/widergy/mobile-ui/commit/5db21ef0002558c272641928ea80e94c6ee85ce0))
|
|
14
|
+
|
|
1
15
|
# [1.34.0](https://github.com/widergy/mobile-ui/compare/v1.33.4...v1.34.0) (2025-01-27)
|
|
2
16
|
|
|
3
17
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# UTTabs
|
|
2
|
+
|
|
3
|
+
Tabs component.
|
|
4
|
+
|
|
5
|
+
## Props
|
|
6
|
+
Here's a new table for the additional props:
|
|
7
|
+
|
|
8
|
+
| Name | Type | Default | Description |
|
|
9
|
+
|------------|---------|------------|-----------------------------------------------------------|
|
|
10
|
+
| colorTheme | string | `accent` | Defines the color theme for the component. |
|
|
11
|
+
| hierarchy | string | `primary` | Determines the hierarchy or importance of the tabs. |
|
|
12
|
+
| onChange | func | | Callback function triggered when the selected tab changes.|
|
|
13
|
+
| style | object | | Custom styles for component. |
|
|
14
|
+
| tabs | array | | Array of tab items to be displayed within the component. |
|
|
15
|
+
| withTabSliding | bool | `true` | Defines if tabs can be changed with gesture. |
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### colorTheme
|
|
19
|
+
|
|
20
|
+
The value of `colorTheme` must be one of the following:
|
|
21
|
+
|
|
22
|
+
- `accent`
|
|
23
|
+
- `negative`
|
|
24
|
+
- `neutral`
|
|
25
|
+
|
|
26
|
+
### hierarchy
|
|
27
|
+
|
|
28
|
+
The value of `hierarchy` must be one of the following:
|
|
29
|
+
|
|
30
|
+
- `primary`
|
|
31
|
+
- `secondary`
|
|
32
|
+
|
|
33
|
+
### tabs
|
|
34
|
+
|
|
35
|
+
`tabs` is an array of object with the following optional props:
|
|
36
|
+
|
|
37
|
+
- `label`: text to render
|
|
38
|
+
- `icon`: name of `UTIcon` to render
|
|
39
|
+
- `badge`: not affected by `colorTheme`
|
|
40
|
+
|
|
41
|
+
Besides those, any other prop can be added to a tab to be accessed with the `onChange` callback
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Animated, View, Pressable, PanResponder } from 'react-native';
|
|
2
|
+
import { array, bool, func, object, string } from 'prop-types';
|
|
3
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
4
|
+
|
|
5
|
+
import { withTheme } from '../../theming';
|
|
6
|
+
import UTBadge from '../UTBadge';
|
|
7
|
+
import UTIcon from '../UTIcon';
|
|
8
|
+
import UTLabel from '../UTLabel';
|
|
9
|
+
|
|
10
|
+
import styleSheet from './styles';
|
|
11
|
+
import { COLOR_THEMES, HIERARCHIES } from './constants';
|
|
12
|
+
|
|
13
|
+
const UTTabs = ({
|
|
14
|
+
colorTheme = COLOR_THEMES.ACCENT,
|
|
15
|
+
hierarchy = HIERARCHIES.SECONDARY,
|
|
16
|
+
onChange,
|
|
17
|
+
style,
|
|
18
|
+
tabs,
|
|
19
|
+
theme,
|
|
20
|
+
withTabSliding = true
|
|
21
|
+
}) => {
|
|
22
|
+
const styles = styleSheet(theme);
|
|
23
|
+
const [selectedTab, setSelectedTab] = useState(0);
|
|
24
|
+
const position = useRef(new Animated.Value(0)).current;
|
|
25
|
+
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
onChange?.(tabs[selectedTab]);
|
|
28
|
+
}, []);
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
Animated.timing(position, {
|
|
32
|
+
toValue: selectedTab,
|
|
33
|
+
duration: 300
|
|
34
|
+
}).start();
|
|
35
|
+
onChange?.(tabs[selectedTab]);
|
|
36
|
+
}, [selectedTab]);
|
|
37
|
+
|
|
38
|
+
const panResponder = useRef(
|
|
39
|
+
PanResponder.create({
|
|
40
|
+
onMoveShouldSetPanResponder: (_, gestureState) => Math.abs(gestureState.dx),
|
|
41
|
+
onPanResponderRelease: (_, gestureState) => {
|
|
42
|
+
if (gestureState.dx > 1) setSelectedTab(prev => Math.max(0, prev - 1));
|
|
43
|
+
else if (gestureState.dx < -1) {
|
|
44
|
+
setSelectedTab(prev => Math.min(tabs.length - 1, prev + 1));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
).current;
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<View style={[styles.container, style]} {...(withTabSliding ? panResponder.panHandlers : {})}>
|
|
52
|
+
{tabs.map(({ badge, label, icon }, index) => {
|
|
53
|
+
const selected = selectedTab === index;
|
|
54
|
+
const colorThemeToUse = selected ? colorTheme : 'gray';
|
|
55
|
+
return (
|
|
56
|
+
<Pressable
|
|
57
|
+
disabled={selected}
|
|
58
|
+
key={`tab-${label || icon}`}
|
|
59
|
+
onPress={() => setSelectedTab(index)}
|
|
60
|
+
style={styles.tab(tabs.length)}
|
|
61
|
+
>
|
|
62
|
+
<UTIcon colorTheme={colorThemeToUse} name={icon} />
|
|
63
|
+
<UTLabel colorTheme={colorThemeToUse} shade="04" weight="medium">
|
|
64
|
+
{label}
|
|
65
|
+
</UTLabel>
|
|
66
|
+
{badge && <UTBadge colorTheme="accent" />}
|
|
67
|
+
</Pressable>
|
|
68
|
+
);
|
|
69
|
+
})}
|
|
70
|
+
<Animated.View style={styles.indicator(position, tabs.length, hierarchy, colorTheme)} />
|
|
71
|
+
<View style={styles.border} />
|
|
72
|
+
</View>
|
|
73
|
+
);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
UTTabs.propTypes = {
|
|
77
|
+
colorTheme: string,
|
|
78
|
+
hierarchy: string,
|
|
79
|
+
onChange: func,
|
|
80
|
+
style: object,
|
|
81
|
+
tabs: array,
|
|
82
|
+
theme: object,
|
|
83
|
+
withTabSliding: bool
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export default withTheme(UTTabs);
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
|
|
3
|
+
import { COLOR_THEMES, HIERARCHIES } from './constants';
|
|
4
|
+
|
|
5
|
+
export default StyleSheet.create(({ Palette: { accent, neutral, negative, light } }) => ({
|
|
6
|
+
border: {
|
|
7
|
+
position: 'absolute',
|
|
8
|
+
bottom: 0,
|
|
9
|
+
width: '100%',
|
|
10
|
+
height: 1,
|
|
11
|
+
backgroundColor: light['04'],
|
|
12
|
+
zIndex: 1
|
|
13
|
+
},
|
|
14
|
+
container: { display: 'flex', flexDirection: 'row', width: '100%' },
|
|
15
|
+
indicator: (position, length, hierarchy, colorTheme) =>
|
|
16
|
+
({
|
|
17
|
+
[HIERARCHIES.PRIMARY]: {
|
|
18
|
+
position: 'absolute',
|
|
19
|
+
bottom: 0,
|
|
20
|
+
width: `${100 / length}%`,
|
|
21
|
+
height: '100%',
|
|
22
|
+
borderRightWidth: position.interpolate({
|
|
23
|
+
inputRange: [0, length - 1],
|
|
24
|
+
outputRange: [1, 0]
|
|
25
|
+
}),
|
|
26
|
+
borderTopRightRadius: position.interpolate({
|
|
27
|
+
inputRange: [0, length - 1],
|
|
28
|
+
outputRange: [4, 0]
|
|
29
|
+
}),
|
|
30
|
+
borderLeftWidth: position.interpolate({
|
|
31
|
+
inputRange: [0, 1],
|
|
32
|
+
outputRange: [0, 1],
|
|
33
|
+
extrapolate: 'clamp'
|
|
34
|
+
}),
|
|
35
|
+
borderTopLeftRadius: position.interpolate({
|
|
36
|
+
inputRange: [0, 1],
|
|
37
|
+
outputRange: [0, 4],
|
|
38
|
+
extrapolate: 'clamp'
|
|
39
|
+
}),
|
|
40
|
+
backgroundColor: light['01'],
|
|
41
|
+
borderTopWidth: 1,
|
|
42
|
+
borderTopColor: light['04'],
|
|
43
|
+
borderLeftColor: light['04'],
|
|
44
|
+
borderRightColor: light['04'],
|
|
45
|
+
borderBottomWidth: 1,
|
|
46
|
+
borderBottomColor: light['01'],
|
|
47
|
+
left: position.interpolate({
|
|
48
|
+
inputRange: [0, length],
|
|
49
|
+
outputRange: ['0%', '100%']
|
|
50
|
+
}),
|
|
51
|
+
zIndex: 2
|
|
52
|
+
},
|
|
53
|
+
[HIERARCHIES.SECONDARY]: {
|
|
54
|
+
position: 'absolute',
|
|
55
|
+
bottom: 0,
|
|
56
|
+
width: `${100 / length}%`,
|
|
57
|
+
height: 4,
|
|
58
|
+
backgroundColor: {
|
|
59
|
+
[COLOR_THEMES.ACCENT]: accent['04'],
|
|
60
|
+
[COLOR_THEMES.NEUTRAL]: neutral['04'],
|
|
61
|
+
[COLOR_THEMES.NEGATIVE]: negative['04']
|
|
62
|
+
}[colorTheme],
|
|
63
|
+
left: position.interpolate({
|
|
64
|
+
inputRange: [0, length],
|
|
65
|
+
outputRange: ['0%', '100%']
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
})[hierarchy],
|
|
69
|
+
tab:
|
|
70
|
+
tabs =>
|
|
71
|
+
({ pressed }) => ({
|
|
72
|
+
alignItems: 'center',
|
|
73
|
+
display: 'flex',
|
|
74
|
+
flexBasis: `${100 / tabs}%`,
|
|
75
|
+
flexDirection: 'row',
|
|
76
|
+
gap: 8,
|
|
77
|
+
height: 48,
|
|
78
|
+
justifyContent: 'center',
|
|
79
|
+
zIndex: 3,
|
|
80
|
+
backgroundColor: pressed ? accent['01'] : null
|
|
81
|
+
})
|
|
82
|
+
}));
|
package/lib/index.js
CHANGED
|
@@ -65,6 +65,7 @@ export { default as UTSelectableCard } from './components/UTSelectableCard';
|
|
|
65
65
|
export { default as UTStatusMessage } from './components/UTStatusMessage';
|
|
66
66
|
export { default as UTStepFeedback } from './components/UTStepFeedback';
|
|
67
67
|
export { default as UTSwitch } from './components/UTSwitch';
|
|
68
|
+
export { default as UTTabs } from './components/UTTabs';
|
|
68
69
|
export { default as UTTextArea } from './components/UTTextArea';
|
|
69
70
|
export { default as UTTextInput } from './components/UTTextInput';
|
|
70
71
|
export { default as UTTooltip } from './components/UTTooltip';
|
|
@@ -59,6 +59,27 @@ export const store = createStore(
|
|
|
59
59
|
);
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
+
## `analyticsUtils.generateFlowId`
|
|
63
|
+
|
|
64
|
+
Generates a `flowId` that can be used to track a user's flow through the app (To either identify the session or the user's device).
|
|
65
|
+
|
|
66
|
+
### Type: `:string()`
|
|
67
|
+
|
|
68
|
+
### Params
|
|
69
|
+
|
|
70
|
+
No params required.
|
|
71
|
+
|
|
72
|
+
#### Example
|
|
73
|
+
|
|
74
|
+
```js
|
|
75
|
+
import { generateFlowId } from '@widergy/mobile-ui';
|
|
76
|
+
|
|
77
|
+
const handleSessionTimeout = () => {
|
|
78
|
+
const flowId = generateFlowId();
|
|
79
|
+
dispatch({ type: 'SET_SESSION_FLOW_ID', payload: { flowId } });
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
62
83
|
## `analyticsUtils.tracker`
|
|
63
84
|
|
|
64
85
|
Implemented inside the `middleware` returned by `analyticsUtils.createAnalyticsMiddleware`. Can be used individually to track events outside of redux.
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* */
|
|
6
6
|
|
|
7
7
|
import { isEmpty, merge } from 'lodash';
|
|
8
|
+
import uuid from 'react-native-uuid';
|
|
8
9
|
|
|
9
10
|
const LOG_EVENT = 'LOG_EVENT';
|
|
10
11
|
const SET_CURRENT_SCREEN = 'SET_CURRENT_SCREEN';
|
|
@@ -146,8 +147,13 @@ export const intercomUpdateUser = intercomInstance => userProperties => {
|
|
|
146
147
|
if (intercomInstance) intercomInstance.updateUser(userProperties);
|
|
147
148
|
};
|
|
148
149
|
|
|
150
|
+
export const generateFlowId = () => {
|
|
151
|
+
return uuid.v4();
|
|
152
|
+
};
|
|
153
|
+
|
|
149
154
|
export default {
|
|
150
155
|
createAnalyticsMiddleware,
|
|
156
|
+
generateFlowId,
|
|
151
157
|
intercomSingleEvent,
|
|
152
158
|
intercomUpdateUser,
|
|
153
159
|
mixpanelEventsFlush,
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@widergy/mobile-ui",
|
|
3
3
|
"description": "Widergy Mobile Components",
|
|
4
4
|
"author": "widergy",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.36.0",
|
|
6
6
|
"repository": "https://github.com/widergy/mobile-ui.git",
|
|
7
7
|
"main": "lib/index.js",
|
|
8
8
|
"files": [
|
|
@@ -48,9 +48,10 @@
|
|
|
48
48
|
"react-native-linear-gradient": "^2.8.3",
|
|
49
49
|
"react-native-markdown-display": "^7.0.0-alpha.2",
|
|
50
50
|
"react-native-modal": "^13.0.1",
|
|
51
|
-
"react-native-pager-view": "^6.2.
|
|
51
|
+
"react-native-pager-view": "^6.2.0",
|
|
52
52
|
"react-native-safe-area-context": "^4.5.0",
|
|
53
|
-
"react-native-svg": "^13.
|
|
53
|
+
"react-native-svg": "^13.0.0",
|
|
54
|
+
"react-native-uuid": "^2.0.3"
|
|
54
55
|
},
|
|
55
56
|
"devDependencies": {
|
|
56
57
|
"@babel/cli": "^7.22.10",
|