@widergy/mobile-ui 1.35.0 → 1.36.1
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/UTRating/index.js +1 -1
- 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/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [1.36.1](https://github.com/widergy/mobile-ui/compare/v1.36.0...v1.36.1) (2025-02-12)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* fixes field label markdown ([#410](https://github.com/widergy/mobile-ui/issues/410)) ([df400b2](https://github.com/widergy/mobile-ui/commit/df400b2449a696ba4358f87f89296772f357d5ab))
|
|
7
|
+
|
|
8
|
+
# [1.36.0](https://github.com/widergy/mobile-ui/compare/v1.35.0...v1.36.0) (2025-02-03)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* [EVENSA-67] uttabs ([#409](https://github.com/widergy/mobile-ui/issues/409)) ([e82a497](https://github.com/widergy/mobile-ui/commit/e82a49721c179c63fef5cbfe7d61eaed172476d0))
|
|
14
|
+
|
|
1
15
|
# [1.35.0](https://github.com/widergy/mobile-ui/compare/v1.34.0...v1.35.0) (2025-01-31)
|
|
2
16
|
|
|
3
17
|
|
|
@@ -47,7 +47,7 @@ const UTRating = ({
|
|
|
47
47
|
return (
|
|
48
48
|
<View style={[styles.container, classNames.container]} data-testid={dataTestId}>
|
|
49
49
|
{title && (
|
|
50
|
-
<UTFieldLabel colorTheme="dark" required={required}>
|
|
50
|
+
<UTFieldLabel colorTheme="dark" required={required} withMarkdown>
|
|
51
51
|
{title}
|
|
52
52
|
</UTFieldLabel>
|
|
53
53
|
)}
|
|
@@ -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';
|
package/package.json
CHANGED