@widergy/mobile-ui 1.3.3 → 1.4.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/IconButton/index.js +8 -6
- package/lib/components/UTHeader/index.js +16 -9
- package/lib/components/UTProductItem/README.md +28 -0
- package/lib/components/UTProductItem/components/AdditionalInfo/index.js +19 -0
- package/lib/components/UTProductItem/components/Amount/index.js +17 -0
- package/lib/components/UTProductItem/components/Discount/index.js +28 -0
- package/lib/components/UTProductItem/components/QuantitySelector/index.js +59 -0
- package/lib/components/UTProductItem/components/Title/index.js +19 -0
- package/lib/components/UTProductItem/index.js +74 -0
- package/lib/components/UTProductItem/propTypes.js +9 -0
- package/lib/components/UTProductItem/styles.js +80 -0
- package/lib/components/UTProductItem/utils.js +29 -0
- package/lib/components/UTWorkflowContainer/versions/V1/components/BottomActions/components/ActionButton/index.js +2 -2
- package/lib/components/UTWorkflowContainer/versions/V1/components/BottomActions/index.js +32 -15
- package/lib/components/UTWorkflowContainer/versions/V1/index.js +8 -4
- package/lib/index.js +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [1.4.0](https://github.com/widergy/mobile-ui/compare/v1.3.4...v1.4.0) (2024-03-26)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* added UTProductItem ([#268](https://github.com/widergy/mobile-ui/issues/268)) ([c28b3e8](https://github.com/widergy/mobile-ui/commit/c28b3e83e9f3aea060857778dc15d5537aca7702))
|
|
7
|
+
|
|
8
|
+
## [1.3.4](https://github.com/widergy/mobile-ui/compare/v1.3.3...v1.3.4) (2024-03-19)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* themed styles and tagline fix ([#270](https://github.com/widergy/mobile-ui/issues/270)) ([6b5b325](https://github.com/widergy/mobile-ui/commit/6b5b32599b39dc1ee07f5af3dc2020fbab9219cf))
|
|
14
|
+
|
|
1
15
|
## [1.3.3](https://github.com/widergy/mobile-ui/compare/v1.3.2...v1.3.3) (2024-03-15)
|
|
2
16
|
|
|
3
17
|
|
|
@@ -10,14 +10,16 @@ import propTypes from './propTypes';
|
|
|
10
10
|
const IconButton = ({
|
|
11
11
|
color,
|
|
12
12
|
disabled,
|
|
13
|
+
effectColor,
|
|
14
|
+
height,
|
|
15
|
+
iconMargin,
|
|
16
|
+
iconStyle,
|
|
13
17
|
name,
|
|
14
18
|
onPress,
|
|
15
|
-
effectColor,
|
|
16
19
|
size,
|
|
17
20
|
style,
|
|
18
|
-
iconStyle,
|
|
19
21
|
type,
|
|
20
|
-
|
|
22
|
+
width
|
|
21
23
|
}) => (
|
|
22
24
|
<Touchable
|
|
23
25
|
borderless
|
|
@@ -26,15 +28,15 @@ const IconButton = ({
|
|
|
26
28
|
effectColor={effectColor}
|
|
27
29
|
style={[styles.container, getContainerSize(size, iconMargin), style]}
|
|
28
30
|
>
|
|
29
|
-
<Icon style={iconStyle}
|
|
31
|
+
<Icon style={iconStyle} {...{ color, height, name, size, type, width }} />
|
|
30
32
|
</Touchable>
|
|
31
33
|
);
|
|
32
34
|
|
|
33
35
|
IconButton.propTypes = propTypes;
|
|
34
36
|
|
|
35
37
|
IconButton.defaultProps = {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
iconMargin: ICON_MARGIN,
|
|
39
|
+
size: DEFAULT_ICON_SIZE
|
|
38
40
|
};
|
|
39
41
|
|
|
40
42
|
export default IconButton;
|
|
@@ -1,53 +1,58 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
3
|
import { string, bool, shape } from 'prop-types';
|
|
4
|
+
import merge from 'lodash/merge';
|
|
4
5
|
|
|
5
6
|
import Label from '../Label';
|
|
6
7
|
import UTBanner from '../UTBanner';
|
|
8
|
+
import { useTheme } from '../../theming';
|
|
7
9
|
|
|
8
10
|
import ownStyles from './styles';
|
|
9
11
|
|
|
10
|
-
const UTHeader = ({ tagline, title, subtitle, requiredFieldInfo, helpText, useMarkdown, banner }) => {
|
|
12
|
+
const UTHeader = ({ tagline, title, subtitle, requiredFieldInfo, helpText, useMarkdown, banner, style }) => {
|
|
13
|
+
const theme = useTheme();
|
|
14
|
+
const themedStyles = merge({}, ownStyles, theme?.UTHeader, style);
|
|
15
|
+
|
|
11
16
|
const renderComponent = (prop, standardComponent) =>
|
|
12
17
|
React.isValidElement(prop) ? prop : standardComponent;
|
|
13
18
|
|
|
14
19
|
const Tagline = renderComponent(
|
|
15
20
|
tagline,
|
|
16
|
-
<Label disabled bold useMarkdown={useMarkdown} style={
|
|
17
|
-
{tagline
|
|
21
|
+
<Label disabled bold useMarkdown={useMarkdown} style={themedStyles.child}>
|
|
22
|
+
{tagline?.toUpperCase?.()}
|
|
18
23
|
</Label>
|
|
19
24
|
);
|
|
20
25
|
|
|
21
26
|
const Title = renderComponent(
|
|
22
27
|
title,
|
|
23
|
-
<Label big bold style={
|
|
28
|
+
<Label big bold style={themedStyles.title} useMarkdown={useMarkdown}>
|
|
24
29
|
{title}
|
|
25
30
|
</Label>
|
|
26
31
|
);
|
|
27
32
|
|
|
28
33
|
const Subtitle = renderComponent(
|
|
29
34
|
subtitle,
|
|
30
|
-
<Label disabled useMarkdown={useMarkdown} style={
|
|
35
|
+
<Label disabled useMarkdown={useMarkdown} style={themedStyles.child}>
|
|
31
36
|
{subtitle}
|
|
32
37
|
</Label>
|
|
33
38
|
);
|
|
34
39
|
|
|
35
40
|
const RequiredFieldInfo = renderComponent(
|
|
36
41
|
requiredFieldInfo,
|
|
37
|
-
<Label disabled useMarkdown={useMarkdown} style={
|
|
42
|
+
<Label disabled useMarkdown={useMarkdown} style={themedStyles.child}>
|
|
38
43
|
{requiredFieldInfo}
|
|
39
44
|
</Label>
|
|
40
45
|
);
|
|
41
46
|
|
|
42
47
|
const HelpText = renderComponent(
|
|
43
48
|
helpText,
|
|
44
|
-
<Label disabled useMarkdown={useMarkdown} style={
|
|
49
|
+
<Label disabled useMarkdown={useMarkdown} style={themedStyles.child}>
|
|
45
50
|
{helpText}
|
|
46
51
|
</Label>
|
|
47
52
|
);
|
|
48
53
|
|
|
49
54
|
return (
|
|
50
|
-
<View style={
|
|
55
|
+
<View style={themedStyles.header}>
|
|
51
56
|
{!!tagline && Tagline}
|
|
52
57
|
<View>
|
|
53
58
|
{Title}
|
|
@@ -55,7 +60,9 @@ const UTHeader = ({ tagline, title, subtitle, requiredFieldInfo, helpText, useMa
|
|
|
55
60
|
</View>
|
|
56
61
|
{!!requiredFieldInfo && RequiredFieldInfo}
|
|
57
62
|
{!!helpText && HelpText}
|
|
58
|
-
{banner?.text &&
|
|
63
|
+
{banner?.text && (
|
|
64
|
+
<UTBanner text={banner.text} icon={banner.icon} style={{ banner: themedStyles.child }} />
|
|
65
|
+
)}
|
|
59
66
|
</View>
|
|
60
67
|
);
|
|
61
68
|
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# UTProductItem
|
|
2
|
+
|
|
3
|
+
### Description
|
|
4
|
+
|
|
5
|
+
This component displays a product with its corresponding image, price and/or discounts. It also provides handlers for adding/removing the amount of products selected.
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
|
|
9
|
+
| Name | Type | Default | Description |
|
|
10
|
+
| ---------------- | -------------- | ------- | ------------------------------------------------------------------------------- |
|
|
11
|
+
| action | actionType | | Renders a button on the rightSection of the component |
|
|
12
|
+
| additionalInfo | string | | Renders a smaller text under the title |
|
|
13
|
+
| amount | number | | Specifies the number to be displayed as a price |
|
|
14
|
+
| counter | counterType | | Renders a chip on the top right corner with a current number and a limit number |
|
|
15
|
+
| discount | number | | Renders a chip above the amount with the given discount as a percentage |
|
|
16
|
+
| imageProps | imagePropsType | | Renders an image at the leftmost part of the component |
|
|
17
|
+
| previousAmount | number | | Renders a text with strikethrough alongside the discount chip |
|
|
18
|
+
| secondaryAction | actionType | | Renders a button alongside the main action |
|
|
19
|
+
| selectedQuantity | number | | Renders a number between the action and the secondary action |
|
|
20
|
+
| title | string | | Renders the main text on the left section of the component |
|
|
21
|
+
|
|
22
|
+
### Custom Types
|
|
23
|
+
|
|
24
|
+
| Type | Shape |
|
|
25
|
+
| -------------- | ---------------------------------------------------------------------------- |
|
|
26
|
+
| actionType | `{ color: string, name: string, onPress: func, size: number, type: string }` |
|
|
27
|
+
| counterType | `{ current: number, limit: number }` |
|
|
28
|
+
| imagePropsType | `{ image: element \| string, withUri: bool }` |
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ViewPropTypes } from 'deprecated-react-native-prop-types';
|
|
2
|
+
import { bool, string } from 'prop-types';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
import Label from '../../../Label';
|
|
6
|
+
|
|
7
|
+
const AdditionalInfo = ({ additionalInfo, shouldUseGap, themedStyles }) => (
|
|
8
|
+
<Label small style={[themedStyles.additionalInfo, shouldUseGap ? themedStyles.gap : '']}>
|
|
9
|
+
{additionalInfo}
|
|
10
|
+
</Label>
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
AdditionalInfo.propTypes = {
|
|
14
|
+
additionalInfo: string,
|
|
15
|
+
shouldUseGap: bool,
|
|
16
|
+
themedStyles: ViewPropTypes.style
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default AdditionalInfo;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ViewPropTypes } from 'deprecated-react-native-prop-types';
|
|
2
|
+
import { bool, number } from 'prop-types';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
import Label from '../../../Label';
|
|
6
|
+
|
|
7
|
+
const Amount = ({ amount, shouldUseGap, themedStyles }) => (
|
|
8
|
+
<Label style={[themedStyles.amount, shouldUseGap ? themedStyles.gap : '']}>{`$ ${amount}`}</Label>
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
Amount.propTypes = {
|
|
12
|
+
amount: number,
|
|
13
|
+
shouldUseGap: bool,
|
|
14
|
+
themedStyles: ViewPropTypes.style
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default Amount;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ViewPropTypes } from 'deprecated-react-native-prop-types';
|
|
2
|
+
import { bool, number } from 'prop-types';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { View } from 'react-native';
|
|
5
|
+
|
|
6
|
+
import Label from '../../../Label';
|
|
7
|
+
|
|
8
|
+
const Discount = ({ previousAmount, shouldUseGap, discount, themedStyles }) => (
|
|
9
|
+
<View style={[themedStyles.amountContainer, shouldUseGap ? themedStyles.gap : '']}>
|
|
10
|
+
<View style={themedStyles.discountChip}>
|
|
11
|
+
<Label small style={themedStyles.discount}>
|
|
12
|
+
{discount}
|
|
13
|
+
</Label>
|
|
14
|
+
</View>
|
|
15
|
+
{previousAmount && (
|
|
16
|
+
<Label small color="gray" style={themedStyles.previousAmount}>{`$ ${previousAmount}`}</Label>
|
|
17
|
+
)}
|
|
18
|
+
</View>
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
Discount.propTypes = {
|
|
22
|
+
discount: number,
|
|
23
|
+
previousAmount: number,
|
|
24
|
+
shouldUseGap: bool,
|
|
25
|
+
themedStyles: ViewPropTypes.style
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default Discount;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { number } from 'prop-types';
|
|
3
|
+
import { View } from 'react-native';
|
|
4
|
+
import { ViewPropTypes } from 'deprecated-react-native-prop-types';
|
|
5
|
+
import isEmpty from 'lodash/isEmpty';
|
|
6
|
+
import isNil from 'lodash/isNil';
|
|
7
|
+
|
|
8
|
+
import IconButton from '../../../IconButton';
|
|
9
|
+
import Label from '../../../Label';
|
|
10
|
+
import { ActionPropTypes } from '../../propTypes';
|
|
11
|
+
import ImageButton from '../../../ImageButton';
|
|
12
|
+
import { useTheme } from '../../../../theming';
|
|
13
|
+
|
|
14
|
+
const QuantitySelector = ({ action, secondaryAction, selectedQuantity, themedStyles }) => {
|
|
15
|
+
const { UTProductItem } = useTheme();
|
|
16
|
+
const ICON_SIZE = 24;
|
|
17
|
+
|
|
18
|
+
const renderAction = ({ color, image, name, size, type, styles, onPress }) =>
|
|
19
|
+
image ? (
|
|
20
|
+
<ImageButton image={image} size={size || ICON_SIZE} containerStyle={styles.image} onPress={onPress} />
|
|
21
|
+
) : (
|
|
22
|
+
<IconButton
|
|
23
|
+
color={color || UTProductItem?.actionIconColor || '#091E42'}
|
|
24
|
+
height={size || ICON_SIZE}
|
|
25
|
+
iconMargin={8}
|
|
26
|
+
name={name}
|
|
27
|
+
onPress={onPress}
|
|
28
|
+
size={size || ICON_SIZE}
|
|
29
|
+
style={styles.icon}
|
|
30
|
+
type={type}
|
|
31
|
+
width={size || ICON_SIZE}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<View style={themedStyles.actionsContainer}>
|
|
37
|
+
{!isEmpty(secondaryAction) &&
|
|
38
|
+
renderAction({
|
|
39
|
+
...secondaryAction,
|
|
40
|
+
styles: { icon: themedStyles.secondaryActionIcon, image: themedStyles.secondaryActionImage }
|
|
41
|
+
})}
|
|
42
|
+
{!isNil(selectedQuantity) && <Label style={themedStyles.selectedQuantity}>{selectedQuantity}</Label>}
|
|
43
|
+
{!isEmpty(action) &&
|
|
44
|
+
renderAction({
|
|
45
|
+
...action,
|
|
46
|
+
styles: { icon: themedStyles.actionIcon, image: themedStyles.actionImage }
|
|
47
|
+
})}
|
|
48
|
+
</View>
|
|
49
|
+
);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
QuantitySelector.propTypes = {
|
|
53
|
+
action: ActionPropTypes,
|
|
54
|
+
secondaryAction: ActionPropTypes,
|
|
55
|
+
selectedQuantity: number,
|
|
56
|
+
themedStyles: ViewPropTypes.style
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export default QuantitySelector;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ViewPropTypes } from 'deprecated-react-native-prop-types';
|
|
2
|
+
import { bool, string } from 'prop-types';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
import Label from '../../../Label';
|
|
6
|
+
|
|
7
|
+
const Title = ({ shouldUseGap, themedStyles, title }) => (
|
|
8
|
+
<Label medium style={[themedStyles.title, shouldUseGap ? themedStyles.gap : '']}>
|
|
9
|
+
{title}
|
|
10
|
+
</Label>
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
Title.propTypes = {
|
|
14
|
+
shouldUseGap: bool,
|
|
15
|
+
themedStyles: ViewPropTypes.style,
|
|
16
|
+
title: string
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default Title;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import merge from 'lodash/merge';
|
|
4
|
+
import { bool, element, number, oneOf, shape, string } from 'prop-types';
|
|
5
|
+
import isEmpty from 'lodash/isEmpty';
|
|
6
|
+
|
|
7
|
+
import ImageIcon from '../ImageIcon';
|
|
8
|
+
import { useTheme } from '../../theming';
|
|
9
|
+
import Label from '../Label';
|
|
10
|
+
|
|
11
|
+
import { leftSectionComponents } from './utils';
|
|
12
|
+
import QuantitySelector from './components/QuantitySelector';
|
|
13
|
+
import { ActionPropTypes } from './propTypes';
|
|
14
|
+
import { getUTProductItemStyles } from './styles';
|
|
15
|
+
|
|
16
|
+
const UTProductItem = ({
|
|
17
|
+
action,
|
|
18
|
+
additionalInfo,
|
|
19
|
+
amount,
|
|
20
|
+
counter,
|
|
21
|
+
discount,
|
|
22
|
+
imageProps,
|
|
23
|
+
previousAmount,
|
|
24
|
+
secondaryAction,
|
|
25
|
+
selectedQuantity,
|
|
26
|
+
style,
|
|
27
|
+
title
|
|
28
|
+
}) => {
|
|
29
|
+
const theme = useTheme();
|
|
30
|
+
const themedStyles = merge({}, getUTProductItemStyles(theme?.UTProductItem), theme?.UTProductItem, style);
|
|
31
|
+
|
|
32
|
+
const IMAGE_SIZE = 70;
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<View style={themedStyles.container}>
|
|
36
|
+
<View style={themedStyles.leftSection}>
|
|
37
|
+
{!isEmpty(imageProps) && <ImageIcon style={themedStyles.image} size={IMAGE_SIZE} {...imageProps} />}
|
|
38
|
+
<View style={themedStyles.mainInfo}>
|
|
39
|
+
{leftSectionComponents({
|
|
40
|
+
additionalInfo,
|
|
41
|
+
amount,
|
|
42
|
+
discount,
|
|
43
|
+
previousAmount,
|
|
44
|
+
themedStyles,
|
|
45
|
+
title
|
|
46
|
+
}).map(({ Component, props }, index, array) => (
|
|
47
|
+
<Component key={Math.random} {...props} shouldUseGap={index !== array.length - 1} />
|
|
48
|
+
))}
|
|
49
|
+
</View>
|
|
50
|
+
</View>
|
|
51
|
+
<View style={[themedStyles.rightSection, !isEmpty(counter) && themedStyles.spaceBetween]}>
|
|
52
|
+
{!isEmpty(counter) && (
|
|
53
|
+
<Label small style={themedStyles.counter}>{`${counter.current}/${counter.limit}`}</Label>
|
|
54
|
+
)}
|
|
55
|
+
<QuantitySelector {...{ action, secondaryAction, selectedQuantity, themedStyles }} />
|
|
56
|
+
</View>
|
|
57
|
+
</View>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
UTProductItem.propTypes = {
|
|
62
|
+
action: ActionPropTypes,
|
|
63
|
+
additionalInfo: string,
|
|
64
|
+
amount: number,
|
|
65
|
+
counter: shape({ current: number, limit: number }),
|
|
66
|
+
discount: number,
|
|
67
|
+
imageProps: shape({ image: oneOf([string, element]), withUri: bool }),
|
|
68
|
+
previousAmount: number,
|
|
69
|
+
secondaryAction: ActionPropTypes,
|
|
70
|
+
selectedQuantity: number,
|
|
71
|
+
title: string
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export default UTProductItem;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export const getUTProductItemStyles = (theme = {}) =>
|
|
4
|
+
StyleSheet.create({
|
|
5
|
+
actionsContainer: {
|
|
6
|
+
alignItems: 'center',
|
|
7
|
+
backgroundColor: theme.actionsBackground || '#E4E6EA',
|
|
8
|
+
borderRadius: 8,
|
|
9
|
+
display: 'flex',
|
|
10
|
+
flexDirection: 'row'
|
|
11
|
+
},
|
|
12
|
+
additionalInfo: {
|
|
13
|
+
color: theme.additionalInfoColor || 'gray'
|
|
14
|
+
},
|
|
15
|
+
amountContainer: {
|
|
16
|
+
alignItems: 'center',
|
|
17
|
+
display: 'flex',
|
|
18
|
+
flexDirection: 'row'
|
|
19
|
+
},
|
|
20
|
+
container: {
|
|
21
|
+
borderBottomColor: theme.separatorColor || 'gray',
|
|
22
|
+
borderBottomWidth: 1,
|
|
23
|
+
display: 'flex',
|
|
24
|
+
flexDirection: 'row',
|
|
25
|
+
justifyContent: 'space-between',
|
|
26
|
+
paddingVertical: 24
|
|
27
|
+
},
|
|
28
|
+
counter: {
|
|
29
|
+
backgroundColor: theme.counterBackground || '#EBF8FD',
|
|
30
|
+
borderRadius: 4,
|
|
31
|
+
color: theme.counterColor || '#035B83',
|
|
32
|
+
paddingHorizontal: 8,
|
|
33
|
+
paddingVertical: 4
|
|
34
|
+
},
|
|
35
|
+
discount: {
|
|
36
|
+
color: theme.discountColor || 'white'
|
|
37
|
+
},
|
|
38
|
+
discountChip: {
|
|
39
|
+
backgroundColor: theme.discountBackground || '#285AFF',
|
|
40
|
+
borderRadius: 4,
|
|
41
|
+
marginRight: 8,
|
|
42
|
+
paddingHorizontal: 8,
|
|
43
|
+
paddingVertical: 4
|
|
44
|
+
},
|
|
45
|
+
gap: {
|
|
46
|
+
marginBottom: 4
|
|
47
|
+
},
|
|
48
|
+
image: {
|
|
49
|
+
borderRadius: 14,
|
|
50
|
+
marginRight: 16
|
|
51
|
+
},
|
|
52
|
+
leftSection: {
|
|
53
|
+
alignItems: 'center',
|
|
54
|
+
display: 'flex',
|
|
55
|
+
flexDirection: 'row'
|
|
56
|
+
},
|
|
57
|
+
mainInfo: {
|
|
58
|
+
display: 'flex',
|
|
59
|
+
minWidth: 160
|
|
60
|
+
},
|
|
61
|
+
previousAmount: {
|
|
62
|
+
color: theme.previousAmountColor || 'gray',
|
|
63
|
+
textDecorationLine: 'line-through',
|
|
64
|
+
textDecorationStyle: 'solid'
|
|
65
|
+
},
|
|
66
|
+
rightSection: {
|
|
67
|
+
alignItems: 'flex-end',
|
|
68
|
+
display: 'flex',
|
|
69
|
+
justifyContent: 'center'
|
|
70
|
+
},
|
|
71
|
+
secondaryActionImage: {
|
|
72
|
+
marginHorizontal: 4
|
|
73
|
+
},
|
|
74
|
+
selectedQuantity: {
|
|
75
|
+
paddingHorizontal: 8
|
|
76
|
+
},
|
|
77
|
+
spaceBetween: {
|
|
78
|
+
justifyContent: 'space-between'
|
|
79
|
+
}
|
|
80
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import Title from './components/Title';
|
|
2
|
+
import AdditionalInfo from './components/AdditionalInfo';
|
|
3
|
+
import Discount from './components/Discount';
|
|
4
|
+
import Amount from './components/Amount';
|
|
5
|
+
|
|
6
|
+
export const leftSectionComponents = ({
|
|
7
|
+
additionalInfo,
|
|
8
|
+
amount,
|
|
9
|
+
discount,
|
|
10
|
+
previousAmount,
|
|
11
|
+
themedStyles,
|
|
12
|
+
title
|
|
13
|
+
}) =>
|
|
14
|
+
[
|
|
15
|
+
{ Component: Title, key: 'title', props: { themedStyles, title }, show: !!title },
|
|
16
|
+
{
|
|
17
|
+
Component: AdditionalInfo,
|
|
18
|
+
key: 'additionalInfo',
|
|
19
|
+
props: { additionalInfo, themedStyles },
|
|
20
|
+
show: !!additionalInfo
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
Component: Discount,
|
|
24
|
+
key: 'discount',
|
|
25
|
+
props: { discount, previousAmount, themedStyles },
|
|
26
|
+
show: !!discount
|
|
27
|
+
},
|
|
28
|
+
{ Component: Amount, key: 'amount', props: { amount, themedStyles }, show: !!amount }
|
|
29
|
+
].filter(elem => elem.show);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { string, func, bool } from 'prop-types';
|
|
3
3
|
import { View } from 'react-native';
|
|
4
|
-
import
|
|
4
|
+
import merge from 'lodash/merge';
|
|
5
5
|
|
|
6
6
|
import Button from '../../../../../../../Button';
|
|
7
7
|
import { useTheme } from '../../../../../../../../theming';
|
|
@@ -10,7 +10,7 @@ import ownStyles from './styles';
|
|
|
10
10
|
|
|
11
11
|
const ActionButton = ({ hidden, disabled, onPress, label, mode, style }) => {
|
|
12
12
|
const theme = useTheme();
|
|
13
|
-
const themedStyles =
|
|
13
|
+
const themedStyles = merge({}, ownStyles, theme?.UTWorkflowContainer?.actionButton, style);
|
|
14
14
|
|
|
15
15
|
return (
|
|
16
16
|
<View style={themedStyles.actionButton}>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
|
-
import
|
|
3
|
+
import merge from 'lodash/merge';
|
|
4
4
|
|
|
5
5
|
import Label from '../../../../../Label';
|
|
6
6
|
import Button from '../../../../../Button';
|
|
@@ -13,31 +13,31 @@ import ActionButtonPropTypes from './components/ActionButton/types';
|
|
|
13
13
|
import ownStyles, { ICON_SIZE } from './styles';
|
|
14
14
|
import { NEXT, RETURN } from './constants';
|
|
15
15
|
|
|
16
|
-
const BottomActions = ({ nextButton, returnButton, summary, message,
|
|
16
|
+
const BottomActions = ({ nextButton, returnButton, summary, message, style }) => {
|
|
17
17
|
const messageIcon = message?.icon;
|
|
18
18
|
const MESSAGE_ICON_SIZE = 16;
|
|
19
19
|
const checkboxProps = summary?.checkbox;
|
|
20
20
|
|
|
21
|
-
const themedStyles =
|
|
21
|
+
const themedStyles = merge({}, ownStyles, style);
|
|
22
22
|
const nextButtonEnabled = nextButton && !nextButton.hidden;
|
|
23
23
|
const returnButtonEnabled = returnButton && !returnButton.hidden;
|
|
24
24
|
|
|
25
25
|
return (
|
|
26
|
-
<View style={
|
|
26
|
+
<View style={themedStyles.bottomNav}>
|
|
27
27
|
{summary && (
|
|
28
|
-
<View style={[
|
|
28
|
+
<View style={[themedStyles.summary, checkboxProps && themedStyles.summaryCheckbox]}>
|
|
29
29
|
{checkboxProps ? (
|
|
30
30
|
<Checkbox {...checkboxProps} />
|
|
31
31
|
) : (
|
|
32
|
-
<View style={
|
|
33
|
-
<Label disabled medium style={
|
|
32
|
+
<View style={themedStyles.summaryTitles}>
|
|
33
|
+
<Label disabled medium style={themedStyles.summaryTitlesChild}>
|
|
34
34
|
{summary.title}
|
|
35
35
|
</Label>
|
|
36
36
|
<Label>{summary.mainInfo}</Label>
|
|
37
37
|
</View>
|
|
38
38
|
)}
|
|
39
39
|
{summary.actions && !checkboxProps && (
|
|
40
|
-
<View style={
|
|
40
|
+
<View style={themedStyles.summaryActions}>
|
|
41
41
|
{summary.actions.map((action, index) => (
|
|
42
42
|
<Button
|
|
43
43
|
key={action.name}
|
|
@@ -53,10 +53,12 @@ const BottomActions = ({ nextButton, returnButton, summary, message, theme }) =>
|
|
|
53
53
|
}
|
|
54
54
|
title={action.title}
|
|
55
55
|
labelColor={themedStyles.summaryActions?.labelColor || 'blue'}
|
|
56
|
-
containerStyle={
|
|
57
|
-
contentStyle={!action.title &&
|
|
56
|
+
containerStyle={themedStyles.summaryActionContainer}
|
|
57
|
+
contentStyle={!action.title && themedStyles.summaryActionButton}
|
|
58
58
|
onPress={action.onPress}
|
|
59
|
-
outerContainerStyles={
|
|
59
|
+
outerContainerStyles={
|
|
60
|
+
index !== summary.actions.length - 1 && themedStyles.summaryActionsChild
|
|
61
|
+
}
|
|
60
62
|
/>
|
|
61
63
|
))}
|
|
62
64
|
</View>
|
|
@@ -70,7 +72,7 @@ const BottomActions = ({ nextButton, returnButton, summary, message, theme }) =>
|
|
|
70
72
|
themedStyles[`message${message.variant?.charAt(0).toUpperCase()}${message.variant?.slice(1)}`]
|
|
71
73
|
]}
|
|
72
74
|
>
|
|
73
|
-
<Label white style={
|
|
75
|
+
<Label white style={themedStyles.messageChild}>
|
|
74
76
|
{message.title}
|
|
75
77
|
</Label>
|
|
76
78
|
{messageIcon && (
|
|
@@ -85,16 +87,31 @@ const BottomActions = ({ nextButton, returnButton, summary, message, theme }) =>
|
|
|
85
87
|
)}
|
|
86
88
|
</View>
|
|
87
89
|
)}
|
|
88
|
-
<View style={
|
|
90
|
+
<View style={themedStyles.actionsContainer}>
|
|
89
91
|
{returnButtonEnabled && (
|
|
90
92
|
<ActionButton
|
|
91
93
|
mode="text"
|
|
92
94
|
label={returnButton.label || RETURN}
|
|
93
|
-
style={
|
|
95
|
+
style={{
|
|
96
|
+
actionButton: {
|
|
97
|
+
...themedStyles.returnActionButton,
|
|
98
|
+
...(nextButtonEnabled ? themedStyles.actionsChild : {})
|
|
99
|
+
},
|
|
100
|
+
buttonContainer: themedStyles.returnButtonContainer
|
|
101
|
+
}}
|
|
94
102
|
{...returnButton}
|
|
95
103
|
/>
|
|
96
104
|
)}
|
|
97
|
-
{nextButtonEnabled &&
|
|
105
|
+
{nextButtonEnabled && (
|
|
106
|
+
<ActionButton
|
|
107
|
+
label={nextButton.label || NEXT}
|
|
108
|
+
style={{
|
|
109
|
+
actionButton: themedStyles.nextActionButton,
|
|
110
|
+
buttonContainer: themedStyles.nextButtonContainer
|
|
111
|
+
}}
|
|
112
|
+
{...nextButton}
|
|
113
|
+
/>
|
|
114
|
+
)}
|
|
98
115
|
</View>
|
|
99
116
|
</View>
|
|
100
117
|
);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useEffect } from 'react';
|
|
2
2
|
import { View, ScrollView } from 'react-native';
|
|
3
3
|
import { number, func, shape, bool, string, element } from 'prop-types';
|
|
4
|
+
import { merge } from 'lodash';
|
|
4
5
|
|
|
5
6
|
import { useTheme } from '../../../../theming';
|
|
6
7
|
import UTHeader from '../../../UTHeader';
|
|
@@ -26,6 +27,7 @@ const UTWorkflowContainer = ({
|
|
|
26
27
|
returnButton,
|
|
27
28
|
stages,
|
|
28
29
|
stepsCount,
|
|
30
|
+
style,
|
|
29
31
|
subtitle,
|
|
30
32
|
summary,
|
|
31
33
|
tagline,
|
|
@@ -35,17 +37,19 @@ const UTWorkflowContainer = ({
|
|
|
35
37
|
}) => {
|
|
36
38
|
useEffect(() => () => onExit?.(), []);
|
|
37
39
|
const theme = useTheme();
|
|
40
|
+
const themedStyles = merge({}, ownStyles, theme?.UTWorkflowContainer, style);
|
|
38
41
|
|
|
39
42
|
return (
|
|
40
|
-
<View style={
|
|
43
|
+
<View style={themedStyles.container}>
|
|
41
44
|
{topbar && <UTTopbar {...{ currentStage, currentStep, stages, stepsCount, theme, topbar }} />}
|
|
42
|
-
<ScrollView contentContainerStyle={
|
|
45
|
+
<ScrollView contentContainerStyle={themedStyles.content}>
|
|
43
46
|
{title && (
|
|
44
47
|
<UTHeader
|
|
45
48
|
{...{
|
|
46
49
|
banner,
|
|
47
50
|
helpText,
|
|
48
51
|
requiredFieldInfo,
|
|
52
|
+
style: themedStyles,
|
|
49
53
|
subtitle,
|
|
50
54
|
tagline,
|
|
51
55
|
title,
|
|
@@ -61,8 +65,8 @@ const UTWorkflowContainer = ({
|
|
|
61
65
|
message,
|
|
62
66
|
nextButton,
|
|
63
67
|
returnButton,
|
|
64
|
-
|
|
65
|
-
|
|
68
|
+
style: themedStyles,
|
|
69
|
+
summary
|
|
66
70
|
}}
|
|
67
71
|
/>
|
|
68
72
|
)}
|
package/lib/index.js
CHANGED
|
@@ -40,6 +40,7 @@ export { default as UTDetailDrawer } from './components/UTDetailDrawer';
|
|
|
40
40
|
export { default as UTImage } from './components/UTImage';
|
|
41
41
|
export { default as UTWorkflowContainer } from './components/UTWorkflowContainer';
|
|
42
42
|
export { default as UTSelectableCard } from './components/UTSelectableCard';
|
|
43
|
+
export { default as UTProductItem } from './components/UTProductItem';
|
|
43
44
|
export { default as UTProgressBar } from './components/UTProgressBar';
|
|
44
45
|
export { default as UTOnBoarding } from './components/UTOnBoarding';
|
|
45
46
|
export { default as UTRoundView } from './components/UTRoundView';
|
package/package.json
CHANGED