@widergy/mobile-ui 1.26.5 → 1.27.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 +7 -0
- package/lib/components/UTActionCard/README.md +25 -0
- package/lib/components/UTActionCard/components/AdditionalMessage/index.js +28 -0
- package/lib/components/UTActionCard/components/AdditionalMessage/styles.js +19 -0
- package/lib/components/UTActionCard/components/BottomActions/index.js +62 -0
- package/lib/components/UTActionCard/components/BottomActions/styles.js +48 -0
- package/lib/components/UTActionCard/components/Header/components/Avatar/index.js +44 -0
- package/lib/components/UTActionCard/components/Header/components/Avatar/styles.js +9 -0
- package/lib/components/UTActionCard/components/Header/components/Status/index.js +33 -0
- package/lib/components/UTActionCard/components/Header/components/Status/styles.js +18 -0
- package/lib/components/UTActionCard/components/Header/constants.js +12 -0
- package/lib/components/UTActionCard/components/Header/index.js +101 -0
- package/lib/components/UTActionCard/components/Header/styles.js +30 -0
- package/lib/components/UTActionCard/components/Header/utils.js +80 -0
- package/lib/components/UTActionCard/components/HeaderActions/index.js +80 -0
- package/lib/components/UTActionCard/components/HeaderActions/styles.js +21 -0
- package/lib/components/UTActionCard/components/HeaderActions/utils.js +17 -0
- package/lib/components/UTActionCard/constants.js +20 -0
- package/lib/components/UTActionCard/index.js +157 -0
- package/lib/components/UTActionCard/styles.js +39 -0
- package/lib/components/UTIcon/index.js +4 -3
- package/lib/components/UTMenu/proptypes.js +1 -1
- package/lib/index.js +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [1.27.0](https://github.com/widergy/mobile-ui/compare/v1.26.5...v1.27.0) (2024-10-07)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* ut action card ([#363](https://github.com/widergy/mobile-ui/issues/363)) ([9d539f0](https://github.com/widergy/mobile-ui/commit/9d539f0584489daf1b0f170ffc696402cf333446))
|
|
7
|
+
|
|
1
8
|
## [1.26.5](https://github.com/widergy/mobile-ui/compare/v1.26.4...v1.26.5) (2024-10-04)
|
|
2
9
|
|
|
3
10
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# UTButton
|
|
2
|
+
|
|
3
|
+
## Props
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
| Name | Type | Default | Description |
|
|
7
|
+
| :----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | ------------------------------------------------------------------------ |
|
|
8
|
+
| `additionalMessage` | `shape({ Icon: elementType, iconProps: shape({ colorTheme: string, size: string }), labelProps: shape({ colorTheme: string, variant: string }), message: string })` | | Additional message information, including icons and labels. |
|
|
9
|
+
| `adornment` | `shape({ alignment: oneOf(['center', 'end', 'start']), position: string, props: object, type: string })` | | Adornment object to customize alignment, position, and type. |
|
|
10
|
+
| `BackgroundImage` | `elementType` | | A React component for the background image. |
|
|
11
|
+
| `bottomActions` | `arrayOf(shape({ colorTheme: string, disabled: bool, Icon: elementType, label: string, loading: bool, onPress: func }))` | | Defines the list of actions to be displayed at the bottom of the card. |
|
|
12
|
+
| `bottomActionsVariant` | `oneOf(['default', 'redirection'])` | | Sets the style variant for bottom actions. |
|
|
13
|
+
| `classNames` | `objectOf(string)` | | Css classes |
|
|
14
|
+
| `description` | `string` | | Description text to be displayed. |
|
|
15
|
+
| `descriptionProps` | `shape({ colorTheme: string, variant: string })` | | Props to customize the description's style. |
|
|
16
|
+
| `headerActions` | `arrayOf(shape({ Icon: oneOfType([elementType, string]), id: oneOfType([number, string]), label: string, loading: bool, onPress: func }))` | | List of actions available in the header section. |
|
|
17
|
+
| `headerActionsProps` | `shape({ alignment: oneOf(['center', 'end', 'start']), buttonGroupProps: shape({ colorTheme: string, shape: string }), variant: oneOf(['default', 'buttonGroup']) })` | | Props to configure header actions alignment, button group, etc. |
|
|
18
|
+
| `mainAction` | `func` | | Main action function for the card. |
|
|
19
|
+
| `size` | `oneOf(['medium', 'small'])` | `'medium'` | Size of the card, either small or medium. |
|
|
20
|
+
| `status` | `string` | | Status text to be displayed. |
|
|
21
|
+
| `statusLabel` | `string` | | Status label for additional status info. |
|
|
22
|
+
| `statusAlignment` | `oneOf(['center', 'end', 'start'])` | | Alignment of the status element. |
|
|
23
|
+
| `title` | `string` | | The title of the card. |
|
|
24
|
+
| `titleProps` | `shape({ variant: string, weight: string })` | | Props to configure the title style. |
|
|
25
|
+
| `withBodyPadding` | `bool` | `false` | Adds padding to the card body if`true`. |
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React, { memo } from 'react';
|
|
2
|
+
import { oneOf, shape, string } from 'prop-types';
|
|
3
|
+
import { View } from 'react-native';
|
|
4
|
+
|
|
5
|
+
import UTIcon from '../../../UTIcon';
|
|
6
|
+
import UTLabel from '../../../UTLabel';
|
|
7
|
+
import { SIZES } from '../../constants';
|
|
8
|
+
|
|
9
|
+
import styles from './styles';
|
|
10
|
+
|
|
11
|
+
const AdditionalMessage = ({ icon, iconProps = {}, labelProps = {}, message, size = SIZES.SMALL }) => (
|
|
12
|
+
<View style={[styles.additionalMessageContainer, styles[size]]}>
|
|
13
|
+
{icon && <UTIcon area colorTheme="gray" name={icon} size={16} {...iconProps} />}
|
|
14
|
+
<UTLabel colorTheme="gray" variant="small" withMarkdown {...labelProps}>
|
|
15
|
+
{message}
|
|
16
|
+
</UTLabel>
|
|
17
|
+
</View>
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
AdditionalMessage.propTypes = {
|
|
21
|
+
icon: string,
|
|
22
|
+
iconProps: shape({ colorTheme: string, size: string }),
|
|
23
|
+
labelProps: shape({ colorTheme: string, variant: string }),
|
|
24
|
+
message: string,
|
|
25
|
+
size: oneOf([SIZES.MEDIUM, SIZES.SMALL])
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default memo(AdditionalMessage);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export default StyleSheet.create({
|
|
4
|
+
additionalMessageContainer: {
|
|
5
|
+
alignItems: 'center',
|
|
6
|
+
flexDirection: 'row',
|
|
7
|
+
gap: 8
|
|
8
|
+
},
|
|
9
|
+
medium: {
|
|
10
|
+
paddingTop: 0,
|
|
11
|
+
paddingHorizontal: 24,
|
|
12
|
+
paddingBottom: 24
|
|
13
|
+
},
|
|
14
|
+
small: {
|
|
15
|
+
paddingTop: 0,
|
|
16
|
+
paddingHorizontal: 16,
|
|
17
|
+
paddingBottom: 16
|
|
18
|
+
}
|
|
19
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React, { Fragment, memo } from 'react';
|
|
2
|
+
import { arrayOf, bool, elementType, func, oneOfType, shape, string } from 'prop-types';
|
|
3
|
+
import { View } from 'react-native';
|
|
4
|
+
|
|
5
|
+
import UTButton from '../../../UTButton';
|
|
6
|
+
import { ACTION_TYPES } from '../../constants';
|
|
7
|
+
import { useTheme } from '../../../../theming';
|
|
8
|
+
import { mergeMultipleStyles } from '../../../../utils/styleUtils';
|
|
9
|
+
|
|
10
|
+
import styles, { getThemeStyles } from './styles';
|
|
11
|
+
|
|
12
|
+
const BottomActions = ({ actions = [], bottomActionsVariant }) => {
|
|
13
|
+
const theme = useTheme();
|
|
14
|
+
const type = actions.length > 2 ? ACTION_TYPES.REDIRECTION : bottomActionsVariant || ACTION_TYPES.DEFAULT;
|
|
15
|
+
const isRedirection = type === ACTION_TYPES.REDIRECTION;
|
|
16
|
+
const themedStyles = mergeMultipleStyles(styles, getThemeStyles(theme, isRedirection));
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<View style={[themedStyles.actionsContainer, themedStyles.redirectionActionsContainer]}>
|
|
20
|
+
{actions.map(({ colorTheme = 'primary', disabled, Icon, label, loading, onClick }, i) => (
|
|
21
|
+
<Fragment key={label}>
|
|
22
|
+
{!isRedirection && i > 0 && <View style={[themedStyles.horizontalSeparator]} />}
|
|
23
|
+
<UTButton
|
|
24
|
+
style={{
|
|
25
|
+
icon: themedStyles.icon,
|
|
26
|
+
root: themedStyles.actionButton
|
|
27
|
+
}}
|
|
28
|
+
colorTheme={colorTheme}
|
|
29
|
+
disabled={disabled}
|
|
30
|
+
Icon={isRedirection ? 'IconChevronRight' : Icon}
|
|
31
|
+
iconPlacement={isRedirection ? 'right' : 'left'}
|
|
32
|
+
loading={loading}
|
|
33
|
+
onClick={onClick}
|
|
34
|
+
size="large"
|
|
35
|
+
variant="text"
|
|
36
|
+
>
|
|
37
|
+
{label}
|
|
38
|
+
</UTButton>
|
|
39
|
+
{isRedirection && actions.length > 1 && i !== actions.length - 1 && (
|
|
40
|
+
<View style={[themedStyles.verticalSeparator]} />
|
|
41
|
+
)}
|
|
42
|
+
</Fragment>
|
|
43
|
+
))}
|
|
44
|
+
</View>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
BottomActions.propTypes = {
|
|
49
|
+
actions: arrayOf(
|
|
50
|
+
shape({
|
|
51
|
+
colorTheme: string,
|
|
52
|
+
disabled: bool,
|
|
53
|
+
Icon: oneOfType([elementType, string]),
|
|
54
|
+
label: string,
|
|
55
|
+
loading: bool,
|
|
56
|
+
onClick: func
|
|
57
|
+
})
|
|
58
|
+
),
|
|
59
|
+
bottomActionsVariant: string
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export default memo(BottomActions);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export const getThemeStyles = (theme = {}, isRedirection) => {
|
|
4
|
+
const lightPalette = theme.Palette.light;
|
|
5
|
+
|
|
6
|
+
const commonStyles = {
|
|
7
|
+
actionsContainer: {
|
|
8
|
+
borderTopColor: lightPalette['04']
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
if (isRedirection) {
|
|
13
|
+
return {
|
|
14
|
+
...commonStyles,
|
|
15
|
+
verticalSeparator: {
|
|
16
|
+
backgroundColor: lightPalette['04'],
|
|
17
|
+
height: 1
|
|
18
|
+
},
|
|
19
|
+
redirectionActionsContainer: {
|
|
20
|
+
flexDirection: 'column'
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
...commonStyles,
|
|
27
|
+
actionButton: {
|
|
28
|
+
alignItems: 'center',
|
|
29
|
+
flex: 1
|
|
30
|
+
},
|
|
31
|
+
horizontalSeparator: {
|
|
32
|
+
backgroundColor: lightPalette['04'],
|
|
33
|
+
width: 1
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const styles = StyleSheet.create({
|
|
39
|
+
actionsContainer: {
|
|
40
|
+
borderTopWidth: 1,
|
|
41
|
+
flexDirection: 'row'
|
|
42
|
+
},
|
|
43
|
+
icon: {
|
|
44
|
+
marginLeft: 'auto'
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
export default styles;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { string, number } from 'prop-types';
|
|
3
|
+
import { View } from 'react-native';
|
|
4
|
+
|
|
5
|
+
import { useTheme } from '../../../../../../theming';
|
|
6
|
+
import UTLabel from '../../../../../UTLabel';
|
|
7
|
+
|
|
8
|
+
import styles from './styles';
|
|
9
|
+
|
|
10
|
+
const Avatar = ({ avatarColor, avatarSize, text = '', textColor = 'dark', textVariant = 'title1' }) => {
|
|
11
|
+
const theme = useTheme();
|
|
12
|
+
const backgroundColor = avatarColor || theme.colors.primary;
|
|
13
|
+
const avatarText = text?.trim().substring(0, 1) || '';
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<View
|
|
17
|
+
style={[
|
|
18
|
+
{
|
|
19
|
+
width: avatarSize,
|
|
20
|
+
height: avatarSize,
|
|
21
|
+
borderRadius: avatarSize / 2,
|
|
22
|
+
backgroundColor
|
|
23
|
+
},
|
|
24
|
+
styles.container
|
|
25
|
+
]}
|
|
26
|
+
>
|
|
27
|
+
{avatarText && (
|
|
28
|
+
<UTLabel colorTheme={textColor || theme.colors.secondary} numberOfLines={1} variant={textVariant}>
|
|
29
|
+
{avatarText}
|
|
30
|
+
</UTLabel>
|
|
31
|
+
)}
|
|
32
|
+
</View>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
Avatar.propTypes = {
|
|
37
|
+
avatarColor: string,
|
|
38
|
+
avatarSize: number,
|
|
39
|
+
text: string,
|
|
40
|
+
textColor: string,
|
|
41
|
+
textVariant: string
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export default Avatar;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { string } from 'prop-types';
|
|
3
|
+
import { View } from 'react-native';
|
|
4
|
+
|
|
5
|
+
import UTLabel from '../../../../../UTLabel';
|
|
6
|
+
|
|
7
|
+
import styles from './styles';
|
|
8
|
+
|
|
9
|
+
const Status = ({
|
|
10
|
+
alignment = 'start',
|
|
11
|
+
backgroundColor,
|
|
12
|
+
colorTheme = 'dark',
|
|
13
|
+
value,
|
|
14
|
+
variant = 'small',
|
|
15
|
+
weight = 'medium'
|
|
16
|
+
}) => (
|
|
17
|
+
<View style={[styles.container, styles[`alignSelf_${alignment}`], { backgroundColor }]}>
|
|
18
|
+
<UTLabel colorTheme={colorTheme} variant={variant} weight={weight}>
|
|
19
|
+
{value}
|
|
20
|
+
</UTLabel>
|
|
21
|
+
</View>
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
Status.propTypes = {
|
|
25
|
+
alignment: string,
|
|
26
|
+
backgroundColor: string,
|
|
27
|
+
colorTheme: string,
|
|
28
|
+
value: string,
|
|
29
|
+
variant: string,
|
|
30
|
+
weight: string
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export default Status;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export default StyleSheet.create({
|
|
4
|
+
container: {
|
|
5
|
+
borderRadius: 4,
|
|
6
|
+
paddingHorizontal: 8,
|
|
7
|
+
paddingVertical: 4
|
|
8
|
+
},
|
|
9
|
+
alignSelf_center: {
|
|
10
|
+
alignSelf: 'center'
|
|
11
|
+
},
|
|
12
|
+
alignSelf_start: {
|
|
13
|
+
alignSelf: 'flex-start'
|
|
14
|
+
},
|
|
15
|
+
alignSelf_end: {
|
|
16
|
+
alignSelf: 'flex-end'
|
|
17
|
+
}
|
|
18
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Image } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import UTIcon from '../../../UTIcon';
|
|
5
|
+
|
|
6
|
+
import Avatar from './components/Avatar';
|
|
7
|
+
|
|
8
|
+
export const ADORNMENT_COMPONENT_MAPPER = {
|
|
9
|
+
icon: UTIcon,
|
|
10
|
+
avatar: props => <Avatar text={props.userName} avatarSize={64} {...props} />,
|
|
11
|
+
image: props => <Image resizeMode="contain" {...props} />
|
|
12
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import React, { memo } from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import {
|
|
4
|
+
arrayOf,
|
|
5
|
+
bool,
|
|
6
|
+
elementType,
|
|
7
|
+
func,
|
|
8
|
+
number,
|
|
9
|
+
object,
|
|
10
|
+
objectOf,
|
|
11
|
+
oneOf,
|
|
12
|
+
oneOfType,
|
|
13
|
+
shape,
|
|
14
|
+
string
|
|
15
|
+
} from 'prop-types';
|
|
16
|
+
import { isEmpty } from '@widergy/web-utils/lib/array';
|
|
17
|
+
|
|
18
|
+
import UTLabel from '../../../UTLabel';
|
|
19
|
+
import HeaderActions from '../HeaderActions';
|
|
20
|
+
import { HEADER_ACTIONS_VARIANTS, PLACE_SELF_TYPES, SIZES } from '../../constants';
|
|
21
|
+
import { useTheme } from '../../../../theming';
|
|
22
|
+
|
|
23
|
+
import { renderAdornment, statusPropsMapper } from './utils';
|
|
24
|
+
import Status from './components/Status';
|
|
25
|
+
import styles from './styles';
|
|
26
|
+
|
|
27
|
+
const Header = ({
|
|
28
|
+
adornment,
|
|
29
|
+
classNames,
|
|
30
|
+
description,
|
|
31
|
+
descriptionProps,
|
|
32
|
+
headerActions,
|
|
33
|
+
headerActionsProps,
|
|
34
|
+
setMainActionHoverVisible,
|
|
35
|
+
size,
|
|
36
|
+
status,
|
|
37
|
+
statusAlignment,
|
|
38
|
+
statusLabel,
|
|
39
|
+
title,
|
|
40
|
+
titleProps
|
|
41
|
+
}) => {
|
|
42
|
+
const theme = useTheme();
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<View style={[styles.header, styles[size], classNames.header]}>
|
|
46
|
+
{renderAdornment(adornment, 'left', size)}
|
|
47
|
+
<View style={styles.headerTitles}>
|
|
48
|
+
{renderAdornment(adornment, 'top', size)}
|
|
49
|
+
<UTLabel variant="title3" weight="medium" {...titleProps}>
|
|
50
|
+
{title}
|
|
51
|
+
</UTLabel>
|
|
52
|
+
{description && (
|
|
53
|
+
<UTLabel colorTheme="gray" {...descriptionProps}>
|
|
54
|
+
{description}
|
|
55
|
+
</UTLabel>
|
|
56
|
+
)}
|
|
57
|
+
</View>
|
|
58
|
+
{status ? (
|
|
59
|
+
<Status
|
|
60
|
+
{...statusPropsMapper(status, theme)}
|
|
61
|
+
alignment={statusAlignment}
|
|
62
|
+
value={statusLabel || status}
|
|
63
|
+
/>
|
|
64
|
+
) : null}
|
|
65
|
+
{!isEmpty(headerActions) && (
|
|
66
|
+
<HeaderActions {...{ headerActions, headerActionsProps, setMainActionHoverVisible }} />
|
|
67
|
+
)}
|
|
68
|
+
</View>
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
Header.propTypes = {
|
|
73
|
+
adornment: shape({ position: string, props: object, type: string }),
|
|
74
|
+
classNames: objectOf(string),
|
|
75
|
+
description: string,
|
|
76
|
+
descriptionProps: shape({ colorTheme: string, variant: string }),
|
|
77
|
+
headerActions: arrayOf(
|
|
78
|
+
shape({
|
|
79
|
+
Icon: oneOfType([elementType, string]),
|
|
80
|
+
id: oneOfType([number, string]),
|
|
81
|
+
isPrimary: bool,
|
|
82
|
+
label: string,
|
|
83
|
+
loading: bool,
|
|
84
|
+
onPress: func
|
|
85
|
+
})
|
|
86
|
+
),
|
|
87
|
+
headerActionsProps: shape({
|
|
88
|
+
alignment: oneOf([PLACE_SELF_TYPES.CENTER, PLACE_SELF_TYPES.END, PLACE_SELF_TYPES.START]),
|
|
89
|
+
buttonGroupProps: shape({ colorTheme: string, shape: string }),
|
|
90
|
+
variant: oneOf([HEADER_ACTIONS_VARIANTS.DEFAULT, HEADER_ACTIONS_VARIANTS.BUTTON_GROUP])
|
|
91
|
+
}),
|
|
92
|
+
setMainActionHoverVisible: string,
|
|
93
|
+
size: oneOf([SIZES.MEDIUM, SIZES.SMALL]),
|
|
94
|
+
status: string,
|
|
95
|
+
statusAlignment: oneOf([PLACE_SELF_TYPES.CENTER, PLACE_SELF_TYPES.END, PLACE_SELF_TYPES.START]),
|
|
96
|
+
statusLabel: string,
|
|
97
|
+
title: string,
|
|
98
|
+
titleProps: shape({ variant: string, weight: string })
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export default memo(Header);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export default StyleSheet.create({
|
|
4
|
+
header: {
|
|
5
|
+
flexDirection: 'row',
|
|
6
|
+
gap: 16,
|
|
7
|
+
justifyContent: 'space-between'
|
|
8
|
+
},
|
|
9
|
+
headerTitles: {
|
|
10
|
+
flex: 1,
|
|
11
|
+
flexDirection: 'column',
|
|
12
|
+
gap: 8,
|
|
13
|
+
marginRight: 'auto'
|
|
14
|
+
},
|
|
15
|
+
medium: {
|
|
16
|
+
padding: 24
|
|
17
|
+
},
|
|
18
|
+
small: {
|
|
19
|
+
padding: 16
|
|
20
|
+
},
|
|
21
|
+
alignSelf_center: {
|
|
22
|
+
alignSelf: 'center'
|
|
23
|
+
},
|
|
24
|
+
alignSelf_start: {
|
|
25
|
+
alignSelf: 'flex-start'
|
|
26
|
+
},
|
|
27
|
+
alignSelf_end: {
|
|
28
|
+
alignSelf: 'flex-end'
|
|
29
|
+
}
|
|
30
|
+
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { isEmpty } from 'lodash';
|
|
3
|
+
|
|
4
|
+
import { PLACE_SELF_TYPES } from '../../constants';
|
|
5
|
+
|
|
6
|
+
import { ADORNMENT_COMPONENT_MAPPER } from './constants';
|
|
7
|
+
import styles from './styles';
|
|
8
|
+
|
|
9
|
+
const ACTIVE = 'active';
|
|
10
|
+
const APPROVED = 'approved';
|
|
11
|
+
const CHARGED_BILL = 'factura cobrada';
|
|
12
|
+
const FINISHED = 'finished';
|
|
13
|
+
const INACTIVE = 'inactive';
|
|
14
|
+
const PENDING = 'pending';
|
|
15
|
+
const BILLED = 'cobrada';
|
|
16
|
+
const PAID = 'pagado';
|
|
17
|
+
const ABOUT_TO_EXPIRE = 'por vencer';
|
|
18
|
+
const UNPAID = 'impaga';
|
|
19
|
+
const SUBSCRIBED = 'subscribed_from_utility';
|
|
20
|
+
const UNSUBSCRIBED = 'unsubscribed';
|
|
21
|
+
const CLOSED_STATUS = 'completed';
|
|
22
|
+
const OBSERVED_STATUS = 'observed';
|
|
23
|
+
const ONGOING_STATUS = 'pending';
|
|
24
|
+
const FORM_STATUS = {
|
|
25
|
+
CANCELED: 'cancelled',
|
|
26
|
+
FINISHED: 'finished',
|
|
27
|
+
IN_PROGRESS: 'in_progress',
|
|
28
|
+
ON_HOLD: 'on_hold',
|
|
29
|
+
COMPLETED: 'completed'
|
|
30
|
+
};
|
|
31
|
+
const PAYMENTPLAN_STATUS = {
|
|
32
|
+
ACTIVE: 'active',
|
|
33
|
+
CANCELLED: 'canceled',
|
|
34
|
+
DRAFT: 'draft',
|
|
35
|
+
FINISHED: 'finished',
|
|
36
|
+
PENDING: 'pending',
|
|
37
|
+
PAYMENT_IN_PROGRESS: 'payment_in_progress',
|
|
38
|
+
PENDING_OFFLINE_PAYMENT: 'pending_offline_payment',
|
|
39
|
+
PENDING_PAYMENT: 'pending_payment'
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const statusPropsMapper = (status, theme) => {
|
|
43
|
+
const paletteVariantMap = {
|
|
44
|
+
success: [ACTIVE, APPROVED, BILLED, CHARGED_BILL, FINISHED, PAID, SUBSCRIBED],
|
|
45
|
+
error: [INACTIVE, PAYMENTPLAN_STATUS.CANCELLED, UNSUBSCRIBED, FORM_STATUS.CANCELED],
|
|
46
|
+
warning: [
|
|
47
|
+
OBSERVED_STATUS,
|
|
48
|
+
PAYMENTPLAN_STATUS.PAYMENT_IN_PROGRESS,
|
|
49
|
+
PAYMENTPLAN_STATUS.PENDING_OFFLINE_PAYMENT,
|
|
50
|
+
PAYMENTPLAN_STATUS.PENDING_PAYMENT,
|
|
51
|
+
UNPAID,
|
|
52
|
+
FORM_STATUS.ON_HOLD
|
|
53
|
+
],
|
|
54
|
+
information: [ONGOING_STATUS, PENDING, FORM_STATUS.IN_PROGRESS],
|
|
55
|
+
unassigned: [CLOSED_STATUS, PAYMENTPLAN_STATUS.DRAFT, ABOUT_TO_EXPIRE]
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const variant =
|
|
59
|
+
Object.entries(paletteVariantMap).find(([, statuses]) => statuses.includes(status?.toLowerCase()))?.[0] ||
|
|
60
|
+
'error';
|
|
61
|
+
|
|
62
|
+
return { backgroundColor: theme.Palette[variant]['01'] };
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export const renderAdornment = (adornment, position, size) => {
|
|
66
|
+
if (isEmpty(adornment) || adornment.position !== position) return null;
|
|
67
|
+
const AdornmentComponent = ADORNMENT_COMPONENT_MAPPER[adornment.type];
|
|
68
|
+
const defaultPlaceSelf = adornment.position === 'left' ? PLACE_SELF_TYPES.CENTER : PLACE_SELF_TYPES.START;
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<AdornmentComponent
|
|
72
|
+
style={[
|
|
73
|
+
styles[`alignSelf_${adornment.alignment || defaultPlaceSelf}`],
|
|
74
|
+
position === 'top' && styles[`gap_${size}`],
|
|
75
|
+
adornment.type === 'image' && { width: adornment.props?.width, height: adornment.props?.height }
|
|
76
|
+
]}
|
|
77
|
+
{...(adornment.props || {})}
|
|
78
|
+
/>
|
|
79
|
+
);
|
|
80
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import React, { memo, useState } from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import isEmpty from 'lodash/isEmpty';
|
|
4
|
+
import { arrayOf, bool, elementType, func, number, oneOf, oneOfType, shape, string } from 'prop-types';
|
|
5
|
+
|
|
6
|
+
import UTButton from '../../../UTButton';
|
|
7
|
+
import UTButtonGroup from '../../../UTButtonGroup';
|
|
8
|
+
import UTMenu from '../../../UTMenu';
|
|
9
|
+
import UTIcon from '../../../UTIcon';
|
|
10
|
+
import { HEADER_ACTIONS_VARIANTS, PLACE_SELF_TYPES } from '../../constants';
|
|
11
|
+
|
|
12
|
+
import { processActions } from './utils';
|
|
13
|
+
import styles from './styles';
|
|
14
|
+
|
|
15
|
+
const HeaderActions = ({ headerActions, headerActionsProps }) => {
|
|
16
|
+
const [selectedAction, setSelectedAction] = useState(null);
|
|
17
|
+
const showButtonGroup = headerActionsProps.variant === HEADER_ACTIONS_VARIANTS.BUTTON_GROUP;
|
|
18
|
+
const { colorTheme: buttonGroupColorTheme = 'secondary', shape: buttonGroupShape } =
|
|
19
|
+
headerActionsProps?.buttonGroupProps || {};
|
|
20
|
+
|
|
21
|
+
const { primaryActions, secondaryActions } = processActions(headerActions);
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<View style={[styles.headerActionsContainer, styles[`alignSelf_${headerActionsProps.alignment}`]]}>
|
|
25
|
+
{primaryActions.map((buttonProps, i) =>
|
|
26
|
+
!buttonProps.onPress ? (
|
|
27
|
+
<UTIcon
|
|
28
|
+
name={buttonProps.Icon}
|
|
29
|
+
style={styles.notClickableIconContainer}
|
|
30
|
+
{...buttonProps}
|
|
31
|
+
key={buttonProps?.id || i}
|
|
32
|
+
/>
|
|
33
|
+
) : (
|
|
34
|
+
<UTButton size="medium" variant="text" {...buttonProps} key={buttonProps?.id || i} />
|
|
35
|
+
)
|
|
36
|
+
)}
|
|
37
|
+
{!isEmpty(secondaryActions) &&
|
|
38
|
+
(!showButtonGroup ? (
|
|
39
|
+
<View>
|
|
40
|
+
<UTMenu options={secondaryActions} horizontalOffset={-80}>
|
|
41
|
+
<UTIcon name="IconDots" />
|
|
42
|
+
</UTMenu>
|
|
43
|
+
</View>
|
|
44
|
+
) : (
|
|
45
|
+
<UTButtonGroup
|
|
46
|
+
actions={secondaryActions.map(action => ({
|
|
47
|
+
...action,
|
|
48
|
+
onPress: () => {
|
|
49
|
+
setSelectedAction(action.id);
|
|
50
|
+
action.onPress();
|
|
51
|
+
}
|
|
52
|
+
}))}
|
|
53
|
+
colorTheme={buttonGroupColorTheme}
|
|
54
|
+
selected={selectedAction || secondaryActions[0]?.id}
|
|
55
|
+
shape={buttonGroupShape}
|
|
56
|
+
/>
|
|
57
|
+
))}
|
|
58
|
+
</View>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
HeaderActions.propTypes = {
|
|
63
|
+
headerActions: arrayOf(
|
|
64
|
+
shape({
|
|
65
|
+
Icon: oneOfType([elementType, string]),
|
|
66
|
+
id: oneOfType([number, string]),
|
|
67
|
+
isPrimary: bool,
|
|
68
|
+
label: string,
|
|
69
|
+
loading: bool,
|
|
70
|
+
onPress: func
|
|
71
|
+
})
|
|
72
|
+
),
|
|
73
|
+
headerActionsProps: shape({
|
|
74
|
+
alignment: oneOf([PLACE_SELF_TYPES.CENTER, PLACE_SELF_TYPES.END, PLACE_SELF_TYPES.START]),
|
|
75
|
+
buttonGroupProps: shape({ colorTheme: string, shape: string }),
|
|
76
|
+
variant: oneOf([HEADER_ACTIONS_VARIANTS.DEFAULT, HEADER_ACTIONS_VARIANTS.BUTTON_GROUP])
|
|
77
|
+
})
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export default memo(HeaderActions);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export default StyleSheet.create({
|
|
4
|
+
headerActionsContainer: {
|
|
5
|
+
alignItems: 'center',
|
|
6
|
+
flexDirection: 'row',
|
|
7
|
+
gap: 8
|
|
8
|
+
},
|
|
9
|
+
alignSelf_center: {
|
|
10
|
+
alignSelf: 'center'
|
|
11
|
+
},
|
|
12
|
+
alignSelf_start: {
|
|
13
|
+
alignSelf: 'flex-start'
|
|
14
|
+
},
|
|
15
|
+
alignSelf_end: {
|
|
16
|
+
alignSelf: 'flex-end'
|
|
17
|
+
},
|
|
18
|
+
notClickableIconContainer: {
|
|
19
|
+
padding: 8
|
|
20
|
+
}
|
|
21
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { isEmpty } from 'lodash';
|
|
2
|
+
|
|
3
|
+
const mapAction = action => ({
|
|
4
|
+
...action,
|
|
5
|
+
action: () => {
|
|
6
|
+
action?.onPress?.();
|
|
7
|
+
}
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export const processActions = headerActions =>
|
|
11
|
+
headerActions.reduce(
|
|
12
|
+
(final, current) => {
|
|
13
|
+
if (current.isPrimary && isEmpty(final.primaryActions)) return { ...final, primaryActions: [current] };
|
|
14
|
+
return { ...final, secondaryActions: [...final.secondaryActions, mapAction(current)] };
|
|
15
|
+
},
|
|
16
|
+
{ primaryActions: [], secondaryActions: [] }
|
|
17
|
+
);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const SIZES = {
|
|
2
|
+
MEDIUM: 'medium',
|
|
3
|
+
SMALL: 'small'
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export const ACTION_TYPES = {
|
|
7
|
+
DEFAULT: 'default',
|
|
8
|
+
REDIRECTION: 'redirection'
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const HEADER_ACTIONS_VARIANTS = {
|
|
12
|
+
BUTTON_GROUP: 'buttonGroup',
|
|
13
|
+
DEFAULT: 'default'
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const PLACE_SELF_TYPES = {
|
|
17
|
+
CENTER: 'center',
|
|
18
|
+
END: 'end',
|
|
19
|
+
START: 'start'
|
|
20
|
+
};
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import React, { memo } from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import {
|
|
4
|
+
arrayOf,
|
|
5
|
+
bool,
|
|
6
|
+
elementType,
|
|
7
|
+
func,
|
|
8
|
+
number,
|
|
9
|
+
object,
|
|
10
|
+
objectOf,
|
|
11
|
+
oneOf,
|
|
12
|
+
oneOfType,
|
|
13
|
+
shape,
|
|
14
|
+
string
|
|
15
|
+
} from 'prop-types';
|
|
16
|
+
import { isEmpty } from 'lodash';
|
|
17
|
+
|
|
18
|
+
import Surface from '../Surface';
|
|
19
|
+
import Touchable from '../Touchable';
|
|
20
|
+
|
|
21
|
+
import { ACTION_TYPES, HEADER_ACTIONS_VARIANTS, PLACE_SELF_TYPES, SIZES } from './constants';
|
|
22
|
+
import Header from './components/Header';
|
|
23
|
+
import AdditionalMessage from './components/AdditionalMessage';
|
|
24
|
+
import BottomActions from './components/BottomActions';
|
|
25
|
+
import styles from './styles';
|
|
26
|
+
|
|
27
|
+
const UTActionCard = ({
|
|
28
|
+
additionalMessage,
|
|
29
|
+
adornment,
|
|
30
|
+
backgroundHeight = '100%',
|
|
31
|
+
BackgroundImage,
|
|
32
|
+
backgroundWidth = '100%',
|
|
33
|
+
bottomActions,
|
|
34
|
+
bottomActionsVariant,
|
|
35
|
+
children,
|
|
36
|
+
classNames = {},
|
|
37
|
+
description,
|
|
38
|
+
descriptionProps = {},
|
|
39
|
+
headerActions,
|
|
40
|
+
headerActionsProps = { variant: HEADER_ACTIONS_VARIANTS.DEFAULT },
|
|
41
|
+
mainAction,
|
|
42
|
+
size = SIZES.SMALL,
|
|
43
|
+
status,
|
|
44
|
+
statusAlignment,
|
|
45
|
+
statusLabel,
|
|
46
|
+
title,
|
|
47
|
+
titleProps = {},
|
|
48
|
+
withBodyPadding = true
|
|
49
|
+
}) => {
|
|
50
|
+
return (
|
|
51
|
+
<Surface elevation={1} style={[styles.cardContainer, classNames.container]}>
|
|
52
|
+
<Touchable
|
|
53
|
+
onPress={mainAction && (() => mainAction?.())}
|
|
54
|
+
style={[styles.innerContainer, classNames.innerContainer, mainAction && styles.withMainAction]}
|
|
55
|
+
>
|
|
56
|
+
<View>
|
|
57
|
+
{BackgroundImage && (
|
|
58
|
+
<BackgroundImage
|
|
59
|
+
height={backgroundHeight}
|
|
60
|
+
style={[styles.backgroundImage, classNames.backgroundImage]}
|
|
61
|
+
width={backgroundWidth}
|
|
62
|
+
/>
|
|
63
|
+
)}
|
|
64
|
+
<View style={[styles.headerAndChildrenContainer, classNames.headerAndChildrenContainer]}>
|
|
65
|
+
<Header
|
|
66
|
+
{...{
|
|
67
|
+
adornment,
|
|
68
|
+
classNames,
|
|
69
|
+
description,
|
|
70
|
+
descriptionProps,
|
|
71
|
+
headerActions,
|
|
72
|
+
headerActionsProps,
|
|
73
|
+
mainAction,
|
|
74
|
+
size,
|
|
75
|
+
status,
|
|
76
|
+
statusAlignment,
|
|
77
|
+
statusLabel,
|
|
78
|
+
title,
|
|
79
|
+
titleProps
|
|
80
|
+
}}
|
|
81
|
+
/>
|
|
82
|
+
{children && (
|
|
83
|
+
<View
|
|
84
|
+
style={[
|
|
85
|
+
withBodyPadding ? styles[`bodyPadding_${size}`] : styles[`withoutBodyPadding_${size}`]
|
|
86
|
+
]}
|
|
87
|
+
>
|
|
88
|
+
{children}
|
|
89
|
+
</View>
|
|
90
|
+
)}
|
|
91
|
+
</View>
|
|
92
|
+
</View>
|
|
93
|
+
</Touchable>
|
|
94
|
+
{!isEmpty(additionalMessage) && <AdditionalMessage {...additionalMessage} size={size} />}
|
|
95
|
+
{!isEmpty(bottomActions) && (
|
|
96
|
+
<BottomActions actions={bottomActions} bottomActionsVariant={bottomActionsVariant} />
|
|
97
|
+
)}
|
|
98
|
+
</Surface>
|
|
99
|
+
);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
UTActionCard.propTypes = {
|
|
103
|
+
additionalMessage: shape({
|
|
104
|
+
Icon: elementType,
|
|
105
|
+
iconProps: shape({ colorTheme: string, size: string }),
|
|
106
|
+
labelProps: shape({ colorTheme: string, variant: string }),
|
|
107
|
+
message: string
|
|
108
|
+
}),
|
|
109
|
+
adornment: shape({
|
|
110
|
+
alignment: oneOf([PLACE_SELF_TYPES.CENTER, PLACE_SELF_TYPES.END, PLACE_SELF_TYPES.START]),
|
|
111
|
+
position: string,
|
|
112
|
+
props: object,
|
|
113
|
+
type: string
|
|
114
|
+
}),
|
|
115
|
+
backgroundHeight: oneOfType([string, number]),
|
|
116
|
+
BackgroundImage: elementType,
|
|
117
|
+
backgroundWidth: oneOfType([string, number]),
|
|
118
|
+
bottomActions: arrayOf(
|
|
119
|
+
shape({
|
|
120
|
+
colorTheme: string,
|
|
121
|
+
disabled: bool,
|
|
122
|
+
Icon: elementType,
|
|
123
|
+
label: string,
|
|
124
|
+
loading: bool,
|
|
125
|
+
onClick: func
|
|
126
|
+
})
|
|
127
|
+
),
|
|
128
|
+
bottomActionsVariant: oneOf([ACTION_TYPES.DEFAULT, ACTION_TYPES.REDIRECTION]),
|
|
129
|
+
classNames: objectOf(string),
|
|
130
|
+
description: string,
|
|
131
|
+
descriptionProps: shape({ colorTheme: string, variant: string }),
|
|
132
|
+
headerActions: arrayOf(
|
|
133
|
+
shape({
|
|
134
|
+
Icon: oneOfType([elementType, string]),
|
|
135
|
+
id: oneOfType([number, string]),
|
|
136
|
+
isPrimary: bool,
|
|
137
|
+
label: string,
|
|
138
|
+
loading: bool,
|
|
139
|
+
onPress: func
|
|
140
|
+
})
|
|
141
|
+
),
|
|
142
|
+
headerActionsProps: shape({
|
|
143
|
+
alignment: oneOf([PLACE_SELF_TYPES.CENTER, PLACE_SELF_TYPES.END, PLACE_SELF_TYPES.START]),
|
|
144
|
+
buttonGroupProps: shape({ colorTheme: string, shape: string }),
|
|
145
|
+
variant: oneOf([HEADER_ACTIONS_VARIANTS.DEFAULT, HEADER_ACTIONS_VARIANTS.BUTTON_GROUP])
|
|
146
|
+
}),
|
|
147
|
+
mainAction: func,
|
|
148
|
+
size: oneOf([SIZES.MEDIUM, SIZES.SMALL]),
|
|
149
|
+
status: string,
|
|
150
|
+
statusLabel: string,
|
|
151
|
+
statusAlignment: oneOf([PLACE_SELF_TYPES.CENTER, PLACE_SELF_TYPES.END, PLACE_SELF_TYPES.START]),
|
|
152
|
+
title: string,
|
|
153
|
+
titleProps: shape({ variant: string, weight: string }),
|
|
154
|
+
withBodyPadding: bool
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
export default memo(UTActionCard);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export default StyleSheet.create({
|
|
4
|
+
cardContainer: {
|
|
5
|
+
borderRadius: 8,
|
|
6
|
+
overflow: 'hidden'
|
|
7
|
+
},
|
|
8
|
+
innerContainer: {
|
|
9
|
+
position: 'relative',
|
|
10
|
+
width: '100%'
|
|
11
|
+
},
|
|
12
|
+
backgroundImage: {
|
|
13
|
+
position: 'absolute',
|
|
14
|
+
zIndex: 0
|
|
15
|
+
},
|
|
16
|
+
headerAndChildrenContainer: {
|
|
17
|
+
flexDirection: 'column',
|
|
18
|
+
width: '100%',
|
|
19
|
+
zIndex: 1
|
|
20
|
+
},
|
|
21
|
+
bodyPadding_medium: {
|
|
22
|
+
paddingTop: 0,
|
|
23
|
+
paddingLeft: 24,
|
|
24
|
+
paddingRight: 24,
|
|
25
|
+
paddingBottom: 24
|
|
26
|
+
},
|
|
27
|
+
bodyPadding_small: {
|
|
28
|
+
paddingTop: 0,
|
|
29
|
+
paddingLeft: 16,
|
|
30
|
+
paddingRight: 16,
|
|
31
|
+
paddingBottom: 16
|
|
32
|
+
},
|
|
33
|
+
withoutBodyPadding_small: {
|
|
34
|
+
paddingBottom: 16
|
|
35
|
+
},
|
|
36
|
+
withoutBodyPadding_medium: {
|
|
37
|
+
paddingBottom: 24
|
|
38
|
+
}
|
|
39
|
+
});
|
|
@@ -40,13 +40,14 @@ const UTIcon = ({
|
|
|
40
40
|
|
|
41
41
|
return (
|
|
42
42
|
<View
|
|
43
|
-
style={
|
|
43
|
+
style={[
|
|
44
44
|
area && [
|
|
45
45
|
ownStyles.withArea,
|
|
46
46
|
ownStyles[`size${size}`],
|
|
47
47
|
getVariantStyle({ color: colorTheme || color, shade, theme, variant })
|
|
48
|
-
]
|
|
49
|
-
|
|
48
|
+
],
|
|
49
|
+
iconProps.style
|
|
50
|
+
]}
|
|
50
51
|
>
|
|
51
52
|
<IconComponent {...iconProps} />
|
|
52
53
|
</View>
|
|
@@ -2,7 +2,7 @@ import { arrayOf, bool, func, number, oneOfType, shape, string } from 'prop-type
|
|
|
2
2
|
|
|
3
3
|
const optionType = shape({
|
|
4
4
|
label: string.isRequired,
|
|
5
|
-
id: string.isRequired,
|
|
5
|
+
id: oneOfType([number, string]).isRequired,
|
|
6
6
|
action: func,
|
|
7
7
|
value: oneOfType([number, string])
|
|
8
8
|
});
|
package/lib/index.js
CHANGED
|
@@ -35,6 +35,7 @@ export { default as Touchable } from './components/Touchable';
|
|
|
35
35
|
export { default as TransformView } from './components/TransformView';
|
|
36
36
|
export { default as TransitionText } from './components/TransitionText';
|
|
37
37
|
export { default as TransitionView } from './components/TransitionView';
|
|
38
|
+
export { default as UTActionCard } from './components/UTActionCard';
|
|
38
39
|
export { default as UTAutocomplete } from './components/UTAutocomplete';
|
|
39
40
|
export { default as UTBadge } from './components/UTBadge';
|
|
40
41
|
export { default as UTBottomSheet } from './components/UTBottomSheet';
|
package/package.json
CHANGED