@widergy/mobile-ui 1.12.0 → 1.12.2

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 CHANGED
@@ -1,3 +1,17 @@
1
+ ## [1.12.2](https://github.com/widergy/mobile-ui/compare/v1.12.1...v1.12.2) (2024-06-28)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * standarize shadows ([#298](https://github.com/widergy/mobile-ui/issues/298)) ([cf60c53](https://github.com/widergy/mobile-ui/commit/cf60c53635cd91e8362db5ea26b8850062ebe1c5))
7
+
8
+ ## [1.12.1](https://github.com/widergy/mobile-ui/compare/v1.12.0...v1.12.1) (2024-06-26)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * utworkflow scrollable config ([#297](https://github.com/widergy/mobile-ui/issues/297)) ([c8b64a8](https://github.com/widergy/mobile-ui/commit/c8b64a8c37af6f834d1485386e4b0cfaa7d8e613))
14
+
1
15
  # [1.12.0](https://github.com/widergy/mobile-ui/compare/v1.11.6...v1.12.0) (2024-06-26)
2
16
 
3
17
 
@@ -2,13 +2,15 @@ import React from 'react';
2
2
  import { Animated, StyleSheet } from 'react-native';
3
3
 
4
4
  import { getShadow } from '../../utils/styleUtils';
5
+ import { useTheme } from '../../theming';
5
6
 
6
7
  import { DEFAULT_ELEVATION } from './constants';
7
8
  import propTypes from './propTypes';
8
9
  import styles from './styles';
9
10
 
10
- const Surface = ({ children, elevation, style, ...props }) => {
11
- const shadow = getShadow(elevation);
11
+ const Surface = ({ children, elevation = 1, position = 'bottom', style, ...props }) => {
12
+ const theme = useTheme();
13
+ const shadow = getShadow({ level: elevation, position, theme });
12
14
  const flatStyles = style ? StyleSheet.flatten(style) : {};
13
15
  return (
14
16
  <Animated.View style={[styles.container, flatStyles, shadow]} {...props}>
@@ -1,5 +1,5 @@
1
- export const ELEVATION = 3;
2
- export const PRESSED_ELEVATION = 6;
1
+ export const ELEVATION = 2;
2
+ export const PRESSED_ELEVATION = 2;
3
3
 
4
4
  export const SIZES = {
5
5
  small: 'small',
@@ -39,8 +39,8 @@ const variantsColorTheme = (theme, colorTheme, variant) => {
39
39
  const actionTheme = theme.Palette[colorName];
40
40
  const negativeTheme = theme.Palette[COLORS_MAPPER.negative];
41
41
  const neutralTheme = theme.Palette[COLORS_MAPPER.secondary];
42
- const shadow = getShadow(ELEVATION);
43
- const pressedShadow = getShadow(PRESSED_ELEVATION);
42
+ const shadow = getShadow({ level: ELEVATION, theme });
43
+ const pressedShadow = getShadow({ level: PRESSED_ELEVATION, theme });
44
44
 
45
45
  const definition = {
46
46
  filled: {
@@ -5,6 +5,7 @@ import { bool, element, number, oneOf, shape, string } from 'prop-types';
5
5
  import isEmpty from 'lodash/isEmpty';
6
6
 
7
7
  import ImageIcon from '../ImageIcon';
8
+ import Surface from '../Surface';
8
9
  import { useTheme } from '../../theming';
9
10
  import UTLabel from '../UTLabel';
10
11
 
@@ -20,6 +21,7 @@ const UTProductItem = ({
20
21
  counter,
21
22
  counterLabelProps = {},
22
23
  discount,
24
+ elevation = 0,
23
25
  imageProps,
24
26
  previousAmount,
25
27
  quantity,
@@ -35,7 +37,7 @@ const UTProductItem = ({
35
37
  const IMAGE_SIZE = 70;
36
38
 
37
39
  return (
38
- <View style={themedStyles.container}>
40
+ <Surface elevation={elevation} style={themedStyles.container}>
39
41
  <View style={themedStyles.leftSection}>
40
42
  {!isEmpty(imageProps) && <ImageIcon style={themedStyles.image} size={IMAGE_SIZE} {...imageProps} />}
41
43
  <View style={themedStyles.mainInfo}>
@@ -70,7 +72,7 @@ const UTProductItem = ({
70
72
  <QuantitySelector {...{ action, secondaryAction, selectedQuantity, themedStyles }} />
71
73
  </View>
72
74
  </View>
73
- </View>
75
+ </Surface>
74
76
  );
75
77
  };
76
78
 
@@ -81,6 +83,7 @@ UTProductItem.propTypes = {
81
83
  counter: shape({ current: number, limit: number }),
82
84
  counterLabelProps: shape({}),
83
85
  discount: number,
86
+ elevation: number,
84
87
  imageProps: shape({ image: oneOf([string, element]), withUri: bool }),
85
88
  previousAmount: number,
86
89
  quantity: number,
@@ -5,6 +5,7 @@ import merge from 'lodash/merge';
5
5
  import { isEmpty } from 'lodash';
6
6
 
7
7
  import Touchable from '../Touchable';
8
+ import Surface from '../Surface';
8
9
  import UTTooltip from '../UTTooltip';
9
10
  import Label from '../Label';
10
11
  import { useTheme } from '../../theming';
@@ -37,85 +38,88 @@ const UTSelectableCard = ({
37
38
  const { selectedColor = 'royalblue', disabledColor = 'gray', baseColor = 'black' } = themedStyles;
38
39
 
39
40
  return (
40
- <Touchable
41
- disabled={disabled}
42
- onPress={() => onPress?.()}
43
- style={[
44
- themedStyles.outerContainer,
45
- themedStyles[`${appearance}Appearance`],
46
- selected && themedStyles[`${appearance}SelectedContainer`],
47
- disabled && themedStyles[`${appearance}DisabledContainer`],
48
- themedStyles[`${size}Size`]
49
- ]}
50
- >
51
- <View style={themedStyles.container}>
52
- {!isEmpty(icon) && (
53
- <Icon
54
- name={icon.name}
55
- type={icon.type}
56
- size={ICON_SIZE}
57
- width={ICON_SIZE}
58
- height={ICON_SIZE}
59
- color={selected ? selectedColor : disabled ? disabledColor : baseColor}
60
- style={themedStyles.icon}
61
- />
62
- )}
63
- <View style={themedStyles.textContainer}>
64
- <View style={themedStyles.column}>
65
- <View style={[themedStyles.titleAndTooltip, selected && themedStyles.selectedTitleAndTooltip]}>
66
- <Label
67
- color={selected ? selectedColor : disabled ? disabledColor : baseColor}
68
- style={tooltip && themedStyles.titleMargin}
69
- >
70
- {titleText}
71
- </Label>
72
- {tooltip && (
73
- <UTTooltip position="top" content={<Label>{tooltip}</Label>}>
74
- <Icon
75
- name="help-outline"
76
- color={selected ? selectedColor : disabled ? disabledColor : baseColor}
77
- />
78
- </UTTooltip>
79
- )}
80
- </View>
81
- {description && (
82
- <Label
83
- medium
84
- style={themedStyles.description}
85
- color={selected ? selectedColor : disabled ? disabledColor : baseColor}
86
- >
87
- {description}
88
- </Label>
89
- )}
90
- </View>
91
- {!isEmpty(additionalInfo) && (
41
+ <Surface style={themedStyles.outerContainer}>
42
+ <Touchable
43
+ disabled={disabled}
44
+ onPress={() => onPress?.()}
45
+ style={[
46
+ themedStyles[`${appearance}Appearance`],
47
+ selected && themedStyles[`${appearance}SelectedContainer`],
48
+ disabled && themedStyles[`${appearance}DisabledContainer`],
49
+ themedStyles[`${size}Size`]
50
+ ]}
51
+ >
52
+ <View style={themedStyles.container}>
53
+ {!isEmpty(icon) && (
54
+ <Icon
55
+ color={selected ? selectedColor : disabled ? disabledColor : baseColor}
56
+ height={ICON_SIZE}
57
+ name={icon.name}
58
+ size={ICON_SIZE}
59
+ style={themedStyles.icon}
60
+ type={icon.type}
61
+ width={ICON_SIZE}
62
+ />
63
+ )}
64
+ <View style={themedStyles.textContainer}>
92
65
  <View style={themedStyles.column}>
93
- {!!additionalInfo.title && (
66
+ <View style={[themedStyles.titleAndTooltip, selected && themedStyles.selectedTitleAndTooltip]}>
94
67
  <Label
95
- right
96
- medium
97
- bold
98
68
  color={selected ? selectedColor : disabled ? disabledColor : baseColor}
69
+ style={tooltip && themedStyles.titleMargin}
99
70
  >
100
- {additionalInfo.title}
71
+ {titleText}
101
72
  </Label>
102
- )}
103
- {!!additionalInfo.description && (
73
+ {tooltip && (
74
+ <UTTooltip content={<Label>{tooltip}</Label>} position="top">
75
+ <Icon
76
+ color={selected ? selectedColor : disabled ? disabledColor : baseColor}
77
+ name="help-outline"
78
+ />
79
+ </UTTooltip>
80
+ )}
81
+ </View>
82
+ {description && (
104
83
  <Label
105
- right
84
+ color={selected ? selectedColor : disabled ? disabledColor : baseColor}
106
85
  medium
107
86
  style={themedStyles.description}
108
- color={selected ? selectedColor : disabled ? disabledColor : baseColor}
109
87
  >
110
- {additionalInfo.description}
88
+ {description}
111
89
  </Label>
112
90
  )}
113
91
  </View>
92
+ {!isEmpty(additionalInfo) && (
93
+ <View style={themedStyles.column}>
94
+ {!!additionalInfo.title && (
95
+ <Label
96
+ bold
97
+ color={selected ? selectedColor : disabled ? disabledColor : baseColor}
98
+ medium
99
+ right
100
+ >
101
+ {additionalInfo.title}
102
+ </Label>
103
+ )}
104
+ {!!additionalInfo.description && (
105
+ <Label
106
+ color={selected ? selectedColor : disabled ? disabledColor : baseColor}
107
+ medium
108
+ right
109
+ style={themedStyles.description}
110
+ >
111
+ {additionalInfo.description}
112
+ </Label>
113
+ )}
114
+ </View>
115
+ )}
116
+ </View>
117
+ {checkIcon && selected && (
118
+ <Icon color={selectedColor} name="check" style={themedStyles.checkIcon} />
114
119
  )}
115
120
  </View>
116
- {checkIcon && selected && <Icon name="check" color={selectedColor} style={themedStyles.checkIcon} />}
117
- </View>
118
- </Touchable>
121
+ </Touchable>
122
+ </Surface>
119
123
  );
120
124
  };
121
125
 
@@ -24,22 +24,22 @@ export const getUTSelectableCardStyles = (theme = {}) =>
24
24
  outerContainer: {
25
25
  borderRadius: 4
26
26
  },
27
+ selectedTitleAndTooltip: {
28
+ maxWidth: 300
29
+ },
27
30
  textContainer: {
28
31
  display: 'flex',
29
32
  flexDirection: 'row',
30
33
  flexGrow: 1,
31
34
  justifyContent: 'space-between'
32
35
  },
33
- titleMargin: {
34
- marginRight: 8
35
- },
36
36
  titleAndTooltip: {
37
37
  alignItems: 'center',
38
38
  display: 'flex',
39
39
  flexDirection: 'row'
40
40
  },
41
- selectedTitleAndTooltip: {
42
- maxWidth: 300
41
+ titleMargin: {
42
+ marginRight: 8
43
43
  },
44
44
 
45
45
  // Sizes
@@ -53,20 +53,17 @@ export const getUTSelectableCardStyles = (theme = {}) =>
53
53
  // White
54
54
  whiteAppearance: {
55
55
  backgroundColor: theme.whiteBackground || 'white',
56
- borderWidth: 2,
57
56
  borderColor: 'transparent',
58
- elevation: 4
57
+ borderWidth: 2
59
58
  },
60
59
  whiteDisabledContainer: {
61
60
  backgroundColor: theme.whiteDisabledBackground || 'lightgray',
62
- borderWidth: 2,
63
61
  borderColor: 'transparent',
64
- elevation: 0
62
+ borderWidth: 2
65
63
  },
66
64
  whiteSelectedContainer: {
67
65
  borderColor: theme.whiteSelectedBorder || 'royalblue',
68
- borderWidth: 2,
69
- elevation: 0
66
+ borderWidth: 2
70
67
  },
71
68
 
72
69
  // Gray
@@ -3,6 +3,7 @@ import { View } from 'react-native';
3
3
  import merge from 'lodash/merge';
4
4
 
5
5
  import Label from '../../../../../Label';
6
+ import Surface from '../../../../../Surface';
6
7
  import Button from '../../../../../Button';
7
8
  import Icon from '../../../../../Icon';
8
9
  import Checkbox from '../../../../../Checkbox';
@@ -23,7 +24,7 @@ const BottomActions = ({ nextButton, returnButton, summary, message, style }) =>
23
24
  const returnButtonEnabled = returnButton && !returnButton.hidden;
24
25
 
25
26
  return (
26
- <View style={themedStyles.bottomNav}>
27
+ <Surface position="top" style={themedStyles.bottomNav}>
27
28
  {summary && (
28
29
  <View style={[themedStyles.summary, checkboxProps && themedStyles.summaryCheckbox]}>
29
30
  {checkboxProps ? (
@@ -40,8 +41,9 @@ const BottomActions = ({ nextButton, returnButton, summary, message, style }) =>
40
41
  <View style={themedStyles.summaryActions}>
41
42
  {summary.actions.map((action, index) => (
42
43
  <Button
43
- key={action.name}
44
- secondary
44
+ containerStyle={themedStyles.summaryActionContainer}
45
+ contentStyle={!action.title && themedStyles.summaryActionButton}
46
+ elevation={action.elevation}
45
47
  icon={
46
48
  action.icon && {
47
49
  height: action.icon.height || ICON_SIZE,
@@ -51,14 +53,14 @@ const BottomActions = ({ nextButton, returnButton, summary, message, style }) =>
51
53
  width: action.icon.width || ICON_SIZE
52
54
  }
53
55
  }
54
- title={action.title}
56
+ key={action.name}
55
57
  labelColor={themedStyles.summaryActions?.labelColor || 'blue'}
56
- containerStyle={themedStyles.summaryActionContainer}
57
- contentStyle={!action.title && themedStyles.summaryActionButton}
58
58
  onPress={action.onPress}
59
59
  outerContainerStyles={
60
60
  index !== summary.actions.length - 1 && themedStyles.summaryActionsChild
61
61
  }
62
+ secondary
63
+ title={action.title}
62
64
  />
63
65
  ))}
64
66
  </View>
@@ -72,17 +74,17 @@ const BottomActions = ({ nextButton, returnButton, summary, message, style }) =>
72
74
  themedStyles[`message${message.variant?.charAt(0).toUpperCase()}${message.variant?.slice(1)}`]
73
75
  ]}
74
76
  >
75
- <Label white style={themedStyles.messageChild}>
77
+ <Label style={themedStyles.messageChild} white>
76
78
  {message.title}
77
79
  </Label>
78
80
  {messageIcon && (
79
81
  <Icon
82
+ color="white"
83
+ height={MESSAGE_ICON_SIZE}
80
84
  name={messageIcon.name}
81
- type={messageIcon.type}
82
85
  size={MESSAGE_ICON_SIZE}
86
+ type={messageIcon.type}
83
87
  width={MESSAGE_ICON_SIZE}
84
- height={MESSAGE_ICON_SIZE}
85
- color="white"
86
88
  />
87
89
  )}
88
90
  </View>
@@ -90,8 +92,8 @@ const BottomActions = ({ nextButton, returnButton, summary, message, style }) =>
90
92
  <View style={themedStyles.actionsContainer}>
91
93
  {returnButtonEnabled && (
92
94
  <ActionButton
93
- mode="text"
94
95
  label={returnButton.label || RETURN}
96
+ mode="text"
95
97
  style={{
96
98
  actionButton: {
97
99
  ...themedStyles.returnActionButton,
@@ -113,7 +115,7 @@ const BottomActions = ({ nextButton, returnButton, summary, message, style }) =>
113
115
  />
114
116
  )}
115
117
  </View>
116
- </View>
118
+ </Surface>
117
119
  );
118
120
  };
119
121
 
@@ -15,12 +15,7 @@ export default StyleSheet.create({
15
15
  width: '100%'
16
16
  },
17
17
  bottomNav: {
18
- backgroundColor: 'white',
19
- shadowColor: 'black',
20
- shadowOffset: { width: 0, height: -3 },
21
- shadowOpacity: 0.1,
22
- shadowRadius: 4,
23
- elevation: 2
18
+ backgroundColor: 'white'
24
19
  },
25
20
  message: {
26
21
  alignItems: 'center',
@@ -25,6 +25,7 @@ const UTWorkflowContainer = ({
25
25
  onExit,
26
26
  requiredFieldInfo,
27
27
  returnButton,
28
+ scrollable = true,
28
29
  stages,
29
30
  stepsCount,
30
31
  style,
@@ -42,7 +43,11 @@ const UTWorkflowContainer = ({
42
43
  return (
43
44
  <SafeAreaView style={themedStyles.container}>
44
45
  {topbar && <UTTopbar {...{ currentStage, currentStep, stages, stepsCount, theme, topbar }} />}
45
- <ScrollView contentContainerStyle={themedStyles.content} keyboardShouldPersistTaps="handled">
46
+ <ScrollView
47
+ contentContainerStyle={themedStyles.content}
48
+ keyboardShouldPersistTaps="handled"
49
+ scrollEnabled={scrollable}
50
+ >
46
51
  {title && (
47
52
  <UTHeader
48
53
  {...{
@@ -86,6 +91,7 @@ UTWorkflowContainer.propTypes = {
86
91
  onExit: func,
87
92
  requiredFieldInfo: string,
88
93
  returnButton: ActionButtonPropTypes,
94
+ scrollable: bool,
89
95
  stages: StagesPropTypes,
90
96
  stepsCount: number.isRequired,
91
97
  subtitle: string,
@@ -1,45 +1,63 @@
1
- import { IS_ANDROID } from '../platformUtils/constants';
2
-
3
- export const SHADOW_COLOR = 'black';
4
- export const SHADOW_OPACITY = 0.24;
5
-
6
- export const calculateShadow = elevation => {
7
- let height;
8
- let radius;
9
- switch (elevation) {
10
- case 1:
11
- height = 0.5;
12
- radius = 0.75;
1
+ export const SHADOW_OPACITY = 0.1;
2
+
3
+ const shadowLevels = {
4
+ 1: {
5
+ elevation: 6,
6
+ height: 3,
7
+ shadowRadius: 6
8
+ },
9
+ 2: {
10
+ elevation: 12,
11
+ height: 6,
12
+ shadowRadius: 12
13
+ },
14
+ 3: {
15
+ elevation: 12,
16
+ height: 24,
17
+ shadowRadius: 24
18
+ }
19
+ };
20
+
21
+ export const getShadow = ({ level, theme, position }) => {
22
+ if (!level) {
23
+ return {};
24
+ }
25
+
26
+ const defaultValues = { elevation: 12 + level * 6, height: 24 + level * 6, shadowRadius: 24 + level * 6 };
27
+ const { height, shadowRadius, elevation } = shadowLevels[level] || defaultValues;
28
+
29
+ let adjustedHeight = height;
30
+ switch (position) {
31
+ case 'top':
32
+ adjustedHeight = -adjustedHeight;
13
33
  break;
14
- case 2:
15
- height = 0.75;
16
- radius = 1.5;
34
+ case 'center':
35
+ adjustedHeight = 0;
17
36
  break;
18
37
  default:
19
- height = elevation - 1;
20
- radius = elevation;
38
+ break;
21
39
  }
40
+
22
41
  return {
23
- shadowColor: SHADOW_COLOR,
42
+ elevation,
43
+ shadowColor: theme.Palette.dark['05'],
24
44
  shadowOffset: {
25
- width: 0,
26
- height
45
+ height: adjustedHeight,
46
+ width: 0
27
47
  },
28
48
  shadowOpacity: SHADOW_OPACITY,
29
- shadowRadius: radius
49
+ shadowRadius
30
50
  };
31
51
  };
32
52
 
33
- export const getShadow = elevation => (IS_ANDROID ? { elevation } : calculateShadow(elevation));
34
-
35
53
  // this is used to quickly build layout related objects in any measure callback or onLayout event
36
54
  export const generateLayoutMeasuresObject = (x, y, width, height) => ({
55
+ bottom: height + y,
56
+ height,
37
57
  left: x,
38
58
  right: width + x,
39
59
  top: y,
40
- bottom: height + y,
41
- width,
42
- height
60
+ width
43
61
  });
44
62
 
45
63
  export const getCustomStyles = (variants, props, styles, stylePrefix = '') =>
@@ -48,7 +66,6 @@ export const getCustomStyles = (variants, props, styles, stylePrefix = '') =>
48
66
  .filter(style => style !== null);
49
67
 
50
68
  export default {
51
- calculateShadow,
52
69
  generateLayoutMeasuresObject,
53
70
  getCustomStyles
54
71
  };
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.12.0",
5
+ "version": "1.12.2",
6
6
  "repository": "https://github.com/widergy/mobile-ui.git",
7
7
  "main": "lib/index.js",
8
8
  "files": [