@widergy/mobile-ui 2.16.0 → 2.17.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 +18 -3
- package/lib/components/UTBanner/README.md +124 -11
- package/lib/components/UTBanner/constants.js +5 -0
- package/lib/components/UTBanner/index.js +119 -52
- package/lib/components/UTBanner/proptypes.js +36 -13
- package/lib/components/UTBanner/theme.js +137 -11
- package/lib/components/UTBottomSheet/index.js +35 -32
- package/lib/components/UTBottomSheet/styles.js +4 -3
- package/lib/components/UTDatePicker/README.md +73 -0
- package/lib/components/UTDatePicker/components/Calendar/constants.js +3 -0
- package/lib/components/UTDatePicker/components/Calendar/index.js +197 -0
- package/lib/components/UTDatePicker/components/Day/index.js +44 -0
- package/lib/components/UTDatePicker/components/Day/styles.js +8 -0
- package/lib/components/UTDatePicker/components/PickerColumn/index.js +57 -0
- package/lib/components/UTDatePicker/constants.js +48 -0
- package/lib/components/UTDatePicker/index.js +135 -0
- package/lib/components/UTDatePicker/layout.js +108 -0
- package/lib/components/UTDatePicker/proptypes.js +20 -0
- package/lib/components/UTDatePicker/styles.js +63 -0
- package/lib/components/UTDatePicker/theme.js +18 -0
- package/lib/components/UTDatePicker/utils.js +52 -0
- package/lib/constants/testIds.js +13 -0
- package/lib/index.js +1 -0
- package/package.json +5 -4
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Pressable, View } from 'react-native';
|
|
3
|
+
import { array, bool, func, object, string } from 'prop-types';
|
|
4
|
+
|
|
5
|
+
import UTBaseInputField from '../UTBaseInputField';
|
|
6
|
+
import UTBottomSheet from '../UTBottomSheet';
|
|
7
|
+
import UTFieldLabel from '../UTFieldLabel';
|
|
8
|
+
import UTLabel from '../UTLabel';
|
|
9
|
+
import UTValidation from '../UTValidation';
|
|
10
|
+
import { TEST_IDS } from '../../constants/testIds';
|
|
11
|
+
|
|
12
|
+
import Calendar from './components/Calendar';
|
|
13
|
+
import { VARIANTS } from './constants';
|
|
14
|
+
import styles from './styles';
|
|
15
|
+
|
|
16
|
+
const { UTDatePicker: datePickerTestIds } = TEST_IDS;
|
|
17
|
+
|
|
18
|
+
const UTDatePickerLayout = ({
|
|
19
|
+
disabled,
|
|
20
|
+
displayPlaceholder,
|
|
21
|
+
displayValue,
|
|
22
|
+
errorMessage,
|
|
23
|
+
handleClose,
|
|
24
|
+
handleDaySelect,
|
|
25
|
+
hasError,
|
|
26
|
+
helpText,
|
|
27
|
+
inputStyle,
|
|
28
|
+
isOpen,
|
|
29
|
+
maxDate,
|
|
30
|
+
minDate,
|
|
31
|
+
modalProps,
|
|
32
|
+
onPress,
|
|
33
|
+
pickedDate,
|
|
34
|
+
readOnly,
|
|
35
|
+
required,
|
|
36
|
+
rightAdornments,
|
|
37
|
+
style,
|
|
38
|
+
title,
|
|
39
|
+
variant
|
|
40
|
+
}) => (
|
|
41
|
+
<View style={[styles.root, style?.root]} testID={datePickerTestIds.root}>
|
|
42
|
+
{!!title && <UTFieldLabel required={required}>{title}</UTFieldLabel>}
|
|
43
|
+
|
|
44
|
+
<Pressable onPress={onPress} style={styles.pressable}>
|
|
45
|
+
<UTBaseInputField
|
|
46
|
+
alwaysShowPlaceholder
|
|
47
|
+
dataTestId={datePickerTestIds.input}
|
|
48
|
+
disabled={disabled}
|
|
49
|
+
editable={false}
|
|
50
|
+
error={hasError}
|
|
51
|
+
placeholder={displayPlaceholder}
|
|
52
|
+
readOnly={readOnly}
|
|
53
|
+
rightAdornments={rightAdornments}
|
|
54
|
+
style={inputStyle}
|
|
55
|
+
value={displayValue}
|
|
56
|
+
/>
|
|
57
|
+
</Pressable>
|
|
58
|
+
|
|
59
|
+
{!!helpText && (
|
|
60
|
+
<UTLabel colorTheme="gray" variant="small">
|
|
61
|
+
{helpText}
|
|
62
|
+
</UTLabel>
|
|
63
|
+
)}
|
|
64
|
+
|
|
65
|
+
{variant === VARIANTS.select && !!errorMessage && (
|
|
66
|
+
<UTValidation
|
|
67
|
+
dataTestId={datePickerTestIds.errorMessage}
|
|
68
|
+
validationData={[{ items: [{ status: 'error', text: errorMessage }] }]}
|
|
69
|
+
/>
|
|
70
|
+
)}
|
|
71
|
+
|
|
72
|
+
<UTBottomSheet
|
|
73
|
+
adjustableHeight
|
|
74
|
+
onClose={handleClose}
|
|
75
|
+
visible={isOpen}
|
|
76
|
+
withBodyPadding={false}
|
|
77
|
+
{...modalProps}
|
|
78
|
+
>
|
|
79
|
+
<Calendar maxDate={maxDate} minDate={minDate} onDaySelect={handleDaySelect} pickedDate={pickedDate} />
|
|
80
|
+
</UTBottomSheet>
|
|
81
|
+
</View>
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
UTDatePickerLayout.propTypes = {
|
|
85
|
+
disabled: bool,
|
|
86
|
+
displayPlaceholder: string,
|
|
87
|
+
displayValue: string,
|
|
88
|
+
errorMessage: string,
|
|
89
|
+
handleClose: func,
|
|
90
|
+
handleDaySelect: func,
|
|
91
|
+
hasError: bool,
|
|
92
|
+
helpText: string,
|
|
93
|
+
inputStyle: object,
|
|
94
|
+
isOpen: bool,
|
|
95
|
+
maxDate: string,
|
|
96
|
+
minDate: string,
|
|
97
|
+
modalProps: object,
|
|
98
|
+
onPress: func,
|
|
99
|
+
pickedDate: object,
|
|
100
|
+
readOnly: bool,
|
|
101
|
+
required: bool,
|
|
102
|
+
rightAdornments: array,
|
|
103
|
+
style: object,
|
|
104
|
+
title: string,
|
|
105
|
+
variant: string
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export default UTDatePickerLayout;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { bool, elementType, func, object, oneOf, shape, string } from 'prop-types';
|
|
2
|
+
|
|
3
|
+
export const propTypes = {
|
|
4
|
+
clearable: bool,
|
|
5
|
+
CustomIcon: elementType,
|
|
6
|
+
disabled: bool,
|
|
7
|
+
error: string,
|
|
8
|
+
helpText: string,
|
|
9
|
+
modalProps: object,
|
|
10
|
+
onChange: func,
|
|
11
|
+
placeholder: string,
|
|
12
|
+
range: shape({ maxDate: string, minDate: string }),
|
|
13
|
+
readOnly: bool,
|
|
14
|
+
required: bool,
|
|
15
|
+
size: oneOf(['sm', 'md']),
|
|
16
|
+
style: shape({ root: object }),
|
|
17
|
+
title: string,
|
|
18
|
+
value: string,
|
|
19
|
+
variant: oneOf(['select', 'picker'])
|
|
20
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
|
|
3
|
+
const styles = StyleSheet.create({
|
|
4
|
+
calendarRoot: {
|
|
5
|
+
paddingHorizontal: 24,
|
|
6
|
+
paddingTop: 16
|
|
7
|
+
},
|
|
8
|
+
dayCell: {
|
|
9
|
+
flex: 1,
|
|
10
|
+
paddingVertical: 2,
|
|
11
|
+
textAlign: 'center'
|
|
12
|
+
},
|
|
13
|
+
month: {
|
|
14
|
+
gap: 2,
|
|
15
|
+
minHeight: 260
|
|
16
|
+
},
|
|
17
|
+
nav: {
|
|
18
|
+
alignItems: 'center',
|
|
19
|
+
flexDirection: 'row',
|
|
20
|
+
justifyContent: 'space-between',
|
|
21
|
+
marginBottom: 24
|
|
22
|
+
},
|
|
23
|
+
navLabel: {
|
|
24
|
+
flex: 1,
|
|
25
|
+
textAlign: 'center'
|
|
26
|
+
},
|
|
27
|
+
navSpacer: {
|
|
28
|
+
width: 36
|
|
29
|
+
},
|
|
30
|
+
pickerColumn: {
|
|
31
|
+
flex: 1,
|
|
32
|
+
overflow: 'hidden'
|
|
33
|
+
},
|
|
34
|
+
pickerContainer: {
|
|
35
|
+
flexDirection: 'row',
|
|
36
|
+
gap: 8,
|
|
37
|
+
height: 260
|
|
38
|
+
},
|
|
39
|
+
pickerScroll: {
|
|
40
|
+
height: 260
|
|
41
|
+
},
|
|
42
|
+
pickerScrollContent: {
|
|
43
|
+
paddingBottom: 220
|
|
44
|
+
},
|
|
45
|
+
pressable: {
|
|
46
|
+
width: '100%'
|
|
47
|
+
},
|
|
48
|
+
root: {
|
|
49
|
+
gap: 8
|
|
50
|
+
},
|
|
51
|
+
week: {
|
|
52
|
+
flexDirection: 'row'
|
|
53
|
+
},
|
|
54
|
+
yearItem: {
|
|
55
|
+
alignItems: 'center',
|
|
56
|
+
borderRadius: 8,
|
|
57
|
+
height: 40,
|
|
58
|
+
justifyContent: 'center',
|
|
59
|
+
width: '100%'
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
export default styles;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const getDayCellButtonStyle = (selected, theme) => ({
|
|
2
|
+
root: {
|
|
3
|
+
alignItems: 'center',
|
|
4
|
+
flex: 1,
|
|
5
|
+
height: 36,
|
|
6
|
+
justifyContent: 'center',
|
|
7
|
+
paddingHorizontal: 0,
|
|
8
|
+
paddingVertical: 0,
|
|
9
|
+
...(selected && {
|
|
10
|
+
backgroundColor: theme.Palette.accent['04'],
|
|
11
|
+
borderRadius: 18
|
|
12
|
+
})
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export const getYearItemStyle = (selected, theme) => ({
|
|
17
|
+
backgroundColor: selected ? theme.Palette.accent['04'] : undefined
|
|
18
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import dayjs from 'dayjs';
|
|
2
|
+
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
|
3
|
+
|
|
4
|
+
import { DAY_UNIT, MONTH_UNIT, OUTPUT_LABEL_MASK, YEAR_RANGE_AFTER, YEAR_RANGE_BEFORE } from './constants';
|
|
5
|
+
|
|
6
|
+
dayjs.extend(customParseFormat);
|
|
7
|
+
|
|
8
|
+
export const isSelected = (date, selectedDate) => selectedDate && date.isSame(selectedDate, DAY_UNIT);
|
|
9
|
+
|
|
10
|
+
export const dateMatchesFormat = (date, targetFormat) => dayjs(date, targetFormat, true).isValid();
|
|
11
|
+
|
|
12
|
+
export const getFinalDate = ({ date, maxDate, minDate }) => {
|
|
13
|
+
const formattedDate = dayjs(date);
|
|
14
|
+
if (maxDate && formattedDate?.isAfter(dayjs(maxDate, OUTPUT_LABEL_MASK)))
|
|
15
|
+
return dayjs(maxDate, OUTPUT_LABEL_MASK);
|
|
16
|
+
if (minDate && formattedDate?.isBefore(dayjs(minDate, OUTPUT_LABEL_MASK)))
|
|
17
|
+
return dayjs(minDate, OUTPUT_LABEL_MASK);
|
|
18
|
+
return formattedDate;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const getWeeks = month => {
|
|
22
|
+
const firstDay = month.startOf(MONTH_UNIT);
|
|
23
|
+
const lastDay = month.endOf(MONTH_UNIT);
|
|
24
|
+
const startDate = firstDay.subtract(firstDay.day(), DAY_UNIT);
|
|
25
|
+
|
|
26
|
+
const weeks = [];
|
|
27
|
+
let current = startDate;
|
|
28
|
+
|
|
29
|
+
do {
|
|
30
|
+
const weekStart = current;
|
|
31
|
+
weeks.push(Array.from({ length: 7 }, (_, i) => weekStart.add(i, DAY_UNIT)));
|
|
32
|
+
current = current.add(7, DAY_UNIT);
|
|
33
|
+
} while (current.isBefore(lastDay) || current.isSame(lastDay, DAY_UNIT));
|
|
34
|
+
|
|
35
|
+
return weeks;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const getYearRange = (minDateStr, maxDateStr) => {
|
|
39
|
+
const currentYear = dayjs().year();
|
|
40
|
+
const minYear = minDateStr ? dayjs(minDateStr, OUTPUT_LABEL_MASK).year() : currentYear - YEAR_RANGE_BEFORE;
|
|
41
|
+
const maxYear = maxDateStr ? dayjs(maxDateStr, OUTPUT_LABEL_MASK).year() : currentYear + YEAR_RANGE_AFTER;
|
|
42
|
+
const years = [];
|
|
43
|
+
for (let y = maxYear; y >= minYear; y--) years.push(y);
|
|
44
|
+
return years;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const autoFormatDate = val => {
|
|
48
|
+
const digits = val.replace(/\D/g, '').slice(0, 8);
|
|
49
|
+
if (digits.length <= 2) return digits;
|
|
50
|
+
if (digits.length <= 4) return `${digits.slice(0, 2)}/${digits.slice(2)}`;
|
|
51
|
+
return `${digits.slice(0, 2)}/${digits.slice(2, 4)}/${digits.slice(4)}`;
|
|
52
|
+
};
|
package/lib/constants/testIds.js
CHANGED
|
@@ -44,6 +44,19 @@ export const TEST_ID_CONSTANTS = {
|
|
|
44
44
|
|
|
45
45
|
export const TEST_IDS = {
|
|
46
46
|
modal: 'modal',
|
|
47
|
+
UTDatePicker: {
|
|
48
|
+
calendar: 'UTDatePicker.calendar',
|
|
49
|
+
calendarMonthYear: 'UTDatePicker.calendar.monthYear',
|
|
50
|
+
calendarNextBtn: 'UTDatePicker.calendar.nextBtn',
|
|
51
|
+
calendarPrevBtn: 'UTDatePicker.calendar.prevBtn',
|
|
52
|
+
errorMessage: 'UTDatePicker.errorMessage',
|
|
53
|
+
input: 'UTDatePicker.input',
|
|
54
|
+
monthItem: 'UTDatePicker.monthItem',
|
|
55
|
+
monthView: 'UTDatePicker.monthView',
|
|
56
|
+
root: 'UTDatePicker.root',
|
|
57
|
+
yearItem: 'UTDatePicker.yearItem',
|
|
58
|
+
yearView: 'UTDatePicker.yearView'
|
|
59
|
+
},
|
|
47
60
|
roundView: 'roundView',
|
|
48
61
|
skeletonLoader: 'skeletonLoader',
|
|
49
62
|
topbar: {
|
package/lib/index.js
CHANGED
|
@@ -49,6 +49,7 @@ export { default as UTCuit } from './components/UTCuit';
|
|
|
49
49
|
export { default as UTCheckList } from './components/UTCheckList';
|
|
50
50
|
export { default as UTDataCategory } from './components/UTDataCategory';
|
|
51
51
|
export { default as UTDataElement } from './components/UTDataElement';
|
|
52
|
+
export { default as UTDatePicker } from './components/UTDatePicker';
|
|
52
53
|
export { default as UTDetailDrawer } from './components/UTDetailDrawer';
|
|
53
54
|
export { default as UTIcon } from './components/UTIcon';
|
|
54
55
|
export { default as UTImage } from './components/UTImage';
|
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": "2.
|
|
5
|
+
"version": "2.17.1",
|
|
6
6
|
"repository": "https://github.com/widergy/mobile-ui.git",
|
|
7
7
|
"main": "lib/index.js",
|
|
8
8
|
"files": [
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"@tabler/icons-react-native": "^3.34.1",
|
|
44
44
|
"@widergy/web-utils": "^2.0.0",
|
|
45
45
|
"core-js": "3",
|
|
46
|
+
"dayjs": "^1.11.10",
|
|
46
47
|
"deprecated-react-native-prop-types": "^5.0.0",
|
|
47
48
|
"expo-document-picker": "^13.1.6",
|
|
48
49
|
"expo-image-manipulator": "^13.1.7",
|
|
@@ -73,12 +74,12 @@
|
|
|
73
74
|
"@commitlint/config-conventional": "^17.7.0",
|
|
74
75
|
"@eslint/compat": "^1.4.0",
|
|
75
76
|
"@eslint/eslintrc": "^3.3.0",
|
|
76
|
-
"@widergy/semantic-release-package-config": "^1.0.0",
|
|
77
|
-
"@widergy/eslint-config": "^1.0.0",
|
|
78
77
|
"@react-native/babel-preset": "0.73.0",
|
|
78
|
+
"@widergy/eslint-config": "^1.0.0",
|
|
79
|
+
"@widergy/semantic-release-package-config": "^1.0.0",
|
|
80
|
+
"babel-jest": "^29.6.2",
|
|
79
81
|
"babel-plugin-import-glob": "^2.0.0",
|
|
80
82
|
"babel-plugin-module-resolver": "^5.0.0",
|
|
81
|
-
"babel-jest": "^29.6.2",
|
|
82
83
|
"babel-preset-minify": "^0.5.2",
|
|
83
84
|
"eslint": "^9.38.0",
|
|
84
85
|
"eslint-config-airbnb": "^19.0.4",
|