@dhis2-ui/calendar 9.11.4 → 9.12.0-alpha.2
Sign up to get free protection for your applications and to get access to all the features.
- package/build/cjs/calendar/calendar-container.js +81 -0
- package/build/cjs/calendar/calendar-table-cell.js +5 -2
- package/build/cjs/calendar/calendar-table.js +9 -5
- package/build/cjs/calendar/calendar.js +26 -30
- package/build/cjs/calendar/navigation-container.js +36 -34
- package/build/cjs/calendar-input/__tests__/calendar-input.test.js +46 -0
- package/build/cjs/calendar-input/calendar-input.js +75 -30
- package/build/cjs/stories/calendar-input.prod.stories.js +21 -2
- package/build/es/calendar/calendar-container.js +72 -0
- package/build/es/calendar/calendar-table-cell.js +5 -2
- package/build/es/calendar/calendar-table.js +8 -4
- package/build/es/calendar/calendar.js +27 -31
- package/build/es/calendar/navigation-container.js +35 -33
- package/build/es/calendar-input/__tests__/calendar-input.test.js +43 -0
- package/build/es/calendar-input/calendar-input.js +78 -33
- package/build/es/stories/calendar-input.prod.stories.js +18 -1
- package/package.json +9 -9
@@ -0,0 +1,81 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
4
|
+
value: true
|
5
|
+
});
|
6
|
+
exports.CalendarContainer = void 0;
|
7
|
+
var _style = _interopRequireDefault(require("styled-jsx/style"));
|
8
|
+
var _uiConstants = require("@dhis2/ui-constants");
|
9
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
10
|
+
var _react = _interopRequireWildcard(require("react"));
|
11
|
+
var _calendarTable = require("./calendar-table.js");
|
12
|
+
var _navigationContainer = require("./navigation-container.js");
|
13
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
14
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
15
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
16
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
17
|
+
const wrapperBorderColor = _uiConstants.colors.grey300;
|
18
|
+
const backgroundColor = 'none';
|
19
|
+
const CalendarContainer = exports.CalendarContainer = /*#__PURE__*/_react.default.memo(function CalendarContainer(_ref) {
|
20
|
+
let {
|
21
|
+
date,
|
22
|
+
width,
|
23
|
+
cellSize,
|
24
|
+
calendarWeekDays,
|
25
|
+
weekDayLabels,
|
26
|
+
currMonth,
|
27
|
+
currYear,
|
28
|
+
nextMonth,
|
29
|
+
nextYear,
|
30
|
+
prevMonth,
|
31
|
+
prevYear,
|
32
|
+
languageDirection,
|
33
|
+
excludedRef,
|
34
|
+
unfocusable
|
35
|
+
} = _ref;
|
36
|
+
const navigationProps = (0, _react.useMemo)(() => {
|
37
|
+
return {
|
38
|
+
currMonth,
|
39
|
+
currYear,
|
40
|
+
nextMonth,
|
41
|
+
nextYear,
|
42
|
+
prevMonth,
|
43
|
+
prevYear,
|
44
|
+
languageDirection
|
45
|
+
};
|
46
|
+
}, [currMonth, currYear, languageDirection, nextMonth, nextYear, prevMonth, prevYear]);
|
47
|
+
return /*#__PURE__*/_react.default.createElement("div", {
|
48
|
+
className: _style.default.dynamic([["2823859047", [backgroundColor, wrapperBorderColor, width]]])
|
49
|
+
}, /*#__PURE__*/_react.default.createElement("div", {
|
50
|
+
dir: languageDirection,
|
51
|
+
"data-test": "calendar",
|
52
|
+
className: _style.default.dynamic([["2823859047", [backgroundColor, wrapperBorderColor, width]]]) + " " + "calendar-wrapper"
|
53
|
+
}, /*#__PURE__*/_react.default.createElement("div", {
|
54
|
+
ref: excludedRef,
|
55
|
+
className: _style.default.dynamic([["2823859047", [backgroundColor, wrapperBorderColor, width]]])
|
56
|
+
}, /*#__PURE__*/_react.default.createElement(_navigationContainer.NavigationContainer, _extends({}, navigationProps, {
|
57
|
+
unfocusable: unfocusable
|
58
|
+
})), /*#__PURE__*/_react.default.createElement(_calendarTable.CalendarTable, {
|
59
|
+
selectedDate: date,
|
60
|
+
calendarWeekDays: calendarWeekDays,
|
61
|
+
weekDayLabels: weekDayLabels,
|
62
|
+
cellSize: cellSize,
|
63
|
+
width: width,
|
64
|
+
unfocusable: unfocusable
|
65
|
+
}))), /*#__PURE__*/_react.default.createElement(_style.default, {
|
66
|
+
id: "2823859047",
|
67
|
+
dynamic: [backgroundColor, wrapperBorderColor, width]
|
68
|
+
}, [`.calendar-wrapper.__jsx-style-dynamic-selector{font-family:Roboto,sans-serif;font-weight:400;font-size:14px;background-color:${backgroundColor};display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;border:1px solid ${wrapperBorderColor};border-radius:3px;min-width:${width};width:-webkit-max-content;width:-moz-max-content;width:max-content;box-shadow:0px 4px 6px -2px #2129340d;box-shadow:0px 10px 15px -3px #2129341a;}`]));
|
69
|
+
});
|
70
|
+
CalendarContainer.defaultProps = {
|
71
|
+
cellSize: '32px',
|
72
|
+
width: '240px',
|
73
|
+
unfocusable: false
|
74
|
+
};
|
75
|
+
CalendarContainer.propTypes = {
|
76
|
+
/** the currently selected date using an iso-like format YYYY-MM-DD, in the calendar system provided (not iso8601) */
|
77
|
+
date: _propTypes.default.string,
|
78
|
+
unfocusable: _propTypes.default.bool,
|
79
|
+
..._calendarTable.CalendarTableProps,
|
80
|
+
..._navigationContainer.NavigationContainerProps
|
81
|
+
};
|
@@ -14,7 +14,8 @@ const CalendarTableCell = _ref => {
|
|
14
14
|
let {
|
15
15
|
day,
|
16
16
|
cellSize,
|
17
|
-
selectedDate
|
17
|
+
selectedDate,
|
18
|
+
unfocusable
|
18
19
|
} = _ref;
|
19
20
|
const dayHoverBackgroundColor = _uiConstants.colors.grey200;
|
20
21
|
const selectedDayBackgroundColor = _uiConstants.colors.teal700;
|
@@ -24,6 +25,7 @@ const CalendarTableCell = _ref => {
|
|
24
25
|
className: _style.default.dynamic([["2052411850", [cellSize, cellSize, cellSize, cellSize, _uiConstants.colors.grey900, dayHoverBackgroundColor, _uiConstants.colors.grey300, selectedDayBackgroundColor, _uiConstants.colors.teal600, _uiConstants.colors.teal200, _uiConstants.colors.grey600]]])
|
25
26
|
}, /*#__PURE__*/_react.default.createElement("button", {
|
26
27
|
name: "day",
|
28
|
+
tabIndex: unfocusable ? -1 : 0,
|
27
29
|
className: _style.default.dynamic([["2052411850", [cellSize, cellSize, cellSize, cellSize, _uiConstants.colors.grey900, dayHoverBackgroundColor, _uiConstants.colors.grey300, selectedDayBackgroundColor, _uiConstants.colors.teal600, _uiConstants.colors.teal200, _uiConstants.colors.grey600]]]) + " " + ((0, _classnames.default)('day', {
|
28
30
|
isSelected: selectedDate === (day === null || day === void 0 ? void 0 : day.calendarDate),
|
29
31
|
isToday: day.isToday,
|
@@ -45,5 +47,6 @@ CalendarTableCell.propTypes = {
|
|
45
47
|
label: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]),
|
46
48
|
onClick: _propTypes.default.func
|
47
49
|
}),
|
48
|
-
selectedDate: _propTypes.default.string
|
50
|
+
selectedDate: _propTypes.default.string,
|
51
|
+
unfocusable: _propTypes.default.bool
|
49
52
|
};
|
@@ -3,7 +3,7 @@
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
4
4
|
value: true
|
5
5
|
});
|
6
|
-
exports.CalendarTable = void 0;
|
6
|
+
exports.CalendarTableProps = exports.CalendarTable = void 0;
|
7
7
|
var _style = _interopRequireDefault(require("styled-jsx/style"));
|
8
8
|
var _uiConstants = require("@dhis2/ui-constants");
|
9
9
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
@@ -17,7 +17,8 @@ const CalendarTable = _ref => {
|
|
17
17
|
calendarWeekDays,
|
18
18
|
width,
|
19
19
|
cellSize,
|
20
|
-
selectedDate
|
20
|
+
selectedDate,
|
21
|
+
unfocusable
|
21
22
|
} = _ref;
|
22
23
|
return /*#__PURE__*/_react.default.createElement("div", {
|
23
24
|
className: _style.default.dynamic([["452536960", [_uiConstants.spacers.dp4, _uiConstants.spacers.dp4]]]) + " " + "calendar-table-wrapper"
|
@@ -35,14 +36,15 @@ const CalendarTable = _ref => {
|
|
35
36
|
day: day,
|
36
37
|
key: day === null || day === void 0 ? void 0 : day.calendarDate,
|
37
38
|
cellSize: cellSize,
|
38
|
-
width: width
|
39
|
+
width: width,
|
40
|
+
unfocusable: unfocusable
|
39
41
|
})))))), /*#__PURE__*/_react.default.createElement(_style.default, {
|
40
42
|
id: "452536960",
|
41
43
|
dynamic: [_uiConstants.spacers.dp4, _uiConstants.spacers.dp4]
|
42
44
|
}, [`.calendar-table.__jsx-style-dynamic-selector{border:none;border-collapse:collapse;width:100%;margin-block:${_uiConstants.spacers.dp4};}`, ".calendar-table.__jsx-style-dynamic-selector tr.__jsx-style-dynamic-selector,.calendar-table.__jsx-style-dynamic-selector td.__jsx-style-dynamic-selector{border:none;}", `.calendar-table-wrapper.__jsx-style-dynamic-selector{padding-inline:${_uiConstants.spacers.dp4};}`]));
|
43
45
|
};
|
44
46
|
exports.CalendarTable = CalendarTable;
|
45
|
-
|
47
|
+
const CalendarTableProps = exports.CalendarTableProps = {
|
46
48
|
calendarWeekDays: _propTypes.default.arrayOf(_propTypes.default.arrayOf(_propTypes.default.shape({
|
47
49
|
calendarDate: _propTypes.default.string,
|
48
50
|
isInCurrentMonth: _propTypes.default.bool,
|
@@ -54,6 +56,8 @@ CalendarTable.propTypes = {
|
|
54
56
|
}).isRequired).isRequired).isRequired,
|
55
57
|
cellSize: _propTypes.default.string,
|
56
58
|
selectedDate: _propTypes.default.string,
|
59
|
+
unfocusable: _propTypes.default.bool,
|
57
60
|
weekDayLabels: _propTypes.default.arrayOf(_propTypes.default.string),
|
58
61
|
width: _propTypes.default.string
|
59
|
-
};
|
62
|
+
};
|
63
|
+
CalendarTable.propTypes = CalendarTableProps;
|
@@ -4,13 +4,10 @@ Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
5
5
|
});
|
6
6
|
exports.CalendarProps = exports.Calendar = void 0;
|
7
|
-
var _style = _interopRequireDefault(require("styled-jsx/style"));
|
8
7
|
var _multiCalendarDates = require("@dhis2/multi-calendar-dates");
|
9
|
-
var _uiConstants = require("@dhis2/ui-constants");
|
10
8
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
11
9
|
var _react = _interopRequireWildcard(require("react"));
|
12
|
-
var
|
13
|
-
var _navigationContainer = require("./navigation-container.js");
|
10
|
+
var _calendarContainer = require("./calendar-container.js");
|
14
11
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
15
12
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
16
13
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
@@ -27,8 +24,6 @@ const Calendar = _ref => {
|
|
27
24
|
width,
|
28
25
|
cellSize
|
29
26
|
} = _ref;
|
30
|
-
const wrapperBorderColor = _uiConstants.colors.grey300;
|
31
|
-
const backgroundColor = 'none';
|
32
27
|
const [selectedDateString, setSelectedDateString] = (0, _react.useState)(date);
|
33
28
|
const languageDirection = (0, _multiCalendarDates.useResolvedDirection)(dir, locale);
|
34
29
|
const options = {
|
@@ -38,7 +33,7 @@ const Calendar = _ref => {
|
|
38
33
|
numberingSystem,
|
39
34
|
weekDayFormat
|
40
35
|
};
|
41
|
-
const
|
36
|
+
const pickerResults = (0, _multiCalendarDates.useDatePicker)({
|
42
37
|
onDateSelect: result => {
|
43
38
|
const {
|
44
39
|
calendarDateString
|
@@ -49,29 +44,30 @@ const Calendar = _ref => {
|
|
49
44
|
date: selectedDateString,
|
50
45
|
options
|
51
46
|
});
|
52
|
-
const {
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
}, [
|
47
|
+
const calendarProps = (0, _react.useMemo)(() => {
|
48
|
+
return {
|
49
|
+
date,
|
50
|
+
dir,
|
51
|
+
locale,
|
52
|
+
width,
|
53
|
+
cellSize,
|
54
|
+
// minDate,
|
55
|
+
// maxDate,
|
56
|
+
// validation, // todo: clarify how we use validation props (and format) in Calendar (not CalendarInput)
|
57
|
+
// format,
|
58
|
+
isValid: pickerResults.isValid,
|
59
|
+
calendarWeekDays: pickerResults.calendarWeekDays,
|
60
|
+
weekDayLabels: pickerResults.weekDayLabels,
|
61
|
+
currMonth: pickerResults.currMonth,
|
62
|
+
currYear: pickerResults.currYear,
|
63
|
+
nextMonth: pickerResults.nextMonth,
|
64
|
+
nextYear: pickerResults.nextYear,
|
65
|
+
prevMonth: pickerResults.prevMonth,
|
66
|
+
prevYear: pickerResults.prevYear,
|
67
|
+
languageDirection
|
68
|
+
};
|
69
|
+
}, [cellSize, date, dir, locale, pickerResults, width, languageDirection]);
|
70
|
+
return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_calendarContainer.CalendarContainer, calendarProps));
|
75
71
|
};
|
76
72
|
exports.Calendar = Calendar;
|
77
73
|
Calendar.defaultProps = {
|
@@ -3,7 +3,7 @@
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
4
4
|
value: true
|
5
5
|
});
|
6
|
-
exports.NavigationContainer = void 0;
|
6
|
+
exports.NavigationContainerProps = exports.NavigationContainer = void 0;
|
7
7
|
var _style = _interopRequireDefault(require("styled-jsx/style"));
|
8
8
|
var _uiConstants = require("@dhis2/ui-constants");
|
9
9
|
var _uiIcons = require("@dhis2/ui-icons");
|
@@ -17,18 +17,16 @@ const NavigationContainer = _ref => {
|
|
17
17
|
var _currYear$label;
|
18
18
|
let {
|
19
19
|
languageDirection,
|
20
|
-
pickerOptions
|
21
|
-
} = _ref;
|
22
|
-
const PreviousIcon = languageDirection === 'ltr' ? _uiIcons.IconChevronLeft16 : _uiIcons.IconChevronRight16;
|
23
|
-
const NextIcon = languageDirection === 'ltr' ? _uiIcons.IconChevronRight16 : _uiIcons.IconChevronLeft16;
|
24
|
-
const {
|
25
20
|
currMonth,
|
26
21
|
currYear,
|
27
22
|
nextMonth,
|
28
23
|
nextYear,
|
29
24
|
prevMonth,
|
30
|
-
prevYear
|
31
|
-
|
25
|
+
prevYear,
|
26
|
+
unfocusable
|
27
|
+
} = _ref;
|
28
|
+
const PreviousIcon = languageDirection === 'ltr' ? _uiIcons.IconChevronLeft16 : _uiIcons.IconChevronRight16;
|
29
|
+
const NextIcon = languageDirection === 'ltr' ? _uiIcons.IconChevronRight16 : _uiIcons.IconChevronLeft16;
|
32
30
|
|
33
31
|
// Ethiopic years - when localised to English - add the era (i.e. 2015 ERA1), which is redundant in practice (like writing AD for gregorian years)
|
34
32
|
// there is an ongoing discussion in JS-Temporal polyfill whether the era should be included or not, but for our case, it's safer to remove it
|
@@ -45,6 +43,7 @@ const NavigationContainer = _ref => {
|
|
45
43
|
"data-test": "calendar-previous-month",
|
46
44
|
"aria-label": `${_index.default.t(`Go to ${prevMonth.label}`)}`,
|
47
45
|
type: "button",
|
46
|
+
tabIndex: unfocusable ? -1 : 0,
|
48
47
|
className: _style.default.dynamic([["3883083596", [_uiConstants.spacers.dp4, _uiConstants.colors.grey600, _uiConstants.colors.grey200, _uiConstants.colors.grey900, _uiConstants.colors.grey300, _uiConstants.spacers.dp8, _uiConstants.spacers.dp4, wrapperBorderColor, headerBackground]]])
|
49
48
|
}, /*#__PURE__*/_react.default.createElement(PreviousIcon, {
|
50
49
|
className: _style.default.dynamic([["3883083596", [_uiConstants.spacers.dp4, _uiConstants.colors.grey600, _uiConstants.colors.grey200, _uiConstants.colors.grey900, _uiConstants.colors.grey300, _uiConstants.spacers.dp8, _uiConstants.spacers.dp4, wrapperBorderColor, headerBackground]]])
|
@@ -60,6 +59,7 @@ const NavigationContainer = _ref => {
|
|
60
59
|
name: "next-month",
|
61
60
|
"aria-label": `${_index.default.t(`Go to ${nextMonth.label}`)}`,
|
62
61
|
type: "button",
|
62
|
+
tabIndex: unfocusable ? -1 : 0,
|
63
63
|
className: _style.default.dynamic([["3883083596", [_uiConstants.spacers.dp4, _uiConstants.colors.grey600, _uiConstants.colors.grey200, _uiConstants.colors.grey900, _uiConstants.colors.grey300, _uiConstants.spacers.dp8, _uiConstants.spacers.dp4, wrapperBorderColor, headerBackground]]])
|
64
64
|
}, /*#__PURE__*/_react.default.createElement(NextIcon, {
|
65
65
|
className: _style.default.dynamic([["3883083596", [_uiConstants.spacers.dp4, _uiConstants.colors.grey600, _uiConstants.colors.grey200, _uiConstants.colors.grey900, _uiConstants.colors.grey300, _uiConstants.spacers.dp8, _uiConstants.spacers.dp4, wrapperBorderColor, headerBackground]]])
|
@@ -72,6 +72,7 @@ const NavigationContainer = _ref => {
|
|
72
72
|
name: "previous-year",
|
73
73
|
"aria-label": `${_index.default.t('Go to previous year')}`,
|
74
74
|
type: "button",
|
75
|
+
tabIndex: unfocusable ? -1 : 0,
|
75
76
|
className: _style.default.dynamic([["3883083596", [_uiConstants.spacers.dp4, _uiConstants.colors.grey600, _uiConstants.colors.grey200, _uiConstants.colors.grey900, _uiConstants.colors.grey300, _uiConstants.spacers.dp8, _uiConstants.spacers.dp4, wrapperBorderColor, headerBackground]]])
|
76
77
|
}, /*#__PURE__*/_react.default.createElement(PreviousIcon, {
|
77
78
|
className: _style.default.dynamic([["3883083596", [_uiConstants.spacers.dp4, _uiConstants.colors.grey600, _uiConstants.colors.grey200, _uiConstants.colors.grey900, _uiConstants.colors.grey300, _uiConstants.spacers.dp8, _uiConstants.spacers.dp4, wrapperBorderColor, headerBackground]]])
|
@@ -87,6 +88,7 @@ const NavigationContainer = _ref => {
|
|
87
88
|
name: "next-year",
|
88
89
|
"aria-label": `${_index.default.t('Go to next year')}`,
|
89
90
|
type: "button",
|
91
|
+
tabIndex: unfocusable ? -1 : 0,
|
90
92
|
className: _style.default.dynamic([["3883083596", [_uiConstants.spacers.dp4, _uiConstants.colors.grey600, _uiConstants.colors.grey200, _uiConstants.colors.grey900, _uiConstants.colors.grey300, _uiConstants.spacers.dp8, _uiConstants.spacers.dp4, wrapperBorderColor, headerBackground]]])
|
91
93
|
}, /*#__PURE__*/_react.default.createElement(NextIcon, {
|
92
94
|
className: _style.default.dynamic([["3883083596", [_uiConstants.spacers.dp4, _uiConstants.colors.grey600, _uiConstants.colors.grey200, _uiConstants.colors.grey900, _uiConstants.colors.grey300, _uiConstants.spacers.dp8, _uiConstants.spacers.dp4, wrapperBorderColor, headerBackground]]])
|
@@ -96,30 +98,30 @@ const NavigationContainer = _ref => {
|
|
96
98
|
}, ["button.__jsx-style-dynamic-selector{background:none;border:0;}", ".month.__jsx-style-dynamic-selector,.year.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;cursor:default;}", ".month.__jsx-style-dynamic-selector .curr.__jsx-style-dynamic-selector,.year.__jsx-style-dynamic-selector .curr.__jsx-style-dynamic-selector{-webkit-flex:2;-ms-flex:2;flex:2;white-space:nowrap;}", ".prev.__jsx-style-dynamic-selector,.next.__jsx-style-dynamic-selector{-webkit-flex:1;-ms-flex:1;flex:1;text-align:center;}", `.prev.__jsx-style-dynamic-selector button.__jsx-style-dynamic-selector,.next.__jsx-style-dynamic-selector button.__jsx-style-dynamic-selector{padding:${_uiConstants.spacers.dp4};height:24px;width:24px;color:${_uiConstants.colors.grey600};border-radius:3px;}`, ".prev.__jsx-style-dynamic-selector button.__jsx-style-dynamic-selector svg.__jsx-style-dynamic-selector,.next.__jsx-style-dynamic-selector button.__jsx-style-dynamic-selector svg.__jsx-style-dynamic-selector{width:16px;height:16px;}", `.prev.__jsx-style-dynamic-selector:hover button.__jsx-style-dynamic-selector,.next.__jsx-style-dynamic-selector:hover button.__jsx-style-dynamic-selector{background-color:${_uiConstants.colors.grey200};color:${_uiConstants.colors.grey900};cursor:pointer;}`, `.prev.__jsx-style-dynamic-selector button.__jsx-style-dynamic-selector:active,.next.__jsx-style-dynamic-selector button.__jsx-style-dynamic-selector:active{background-color:${_uiConstants.colors.grey300};}`, ".label.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding:4px 8px;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;min-height:16px;}", `.navigation-container.__jsx-style-dynamic-selector{gap:${_uiConstants.spacers.dp8};padding:${_uiConstants.spacers.dp4};display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;border-bottom:1px solid ${wrapperBorderColor};background-color:${headerBackground};font-size:1.08em;}`]));
|
97
99
|
};
|
98
100
|
exports.NavigationContainer = NavigationContainer;
|
99
|
-
|
101
|
+
const NavigationContainerProps = exports.NavigationContainerProps = {
|
102
|
+
currMonth: _propTypes.default.shape({
|
103
|
+
label: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number])
|
104
|
+
}),
|
105
|
+
currYear: _propTypes.default.shape({
|
106
|
+
label: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number])
|
107
|
+
}),
|
100
108
|
languageDirection: _propTypes.default.oneOf(['ltr', 'rtl']),
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
prevYear: _propTypes.default.shape({
|
121
|
-
label: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]),
|
122
|
-
navigateTo: _propTypes.default.func
|
123
|
-
})
|
124
|
-
})
|
125
|
-
};
|
109
|
+
nextMonth: _propTypes.default.shape({
|
110
|
+
label: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]),
|
111
|
+
navigateTo: _propTypes.default.func
|
112
|
+
}),
|
113
|
+
nextYear: _propTypes.default.shape({
|
114
|
+
label: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]),
|
115
|
+
navigateTo: _propTypes.default.func
|
116
|
+
}),
|
117
|
+
prevMonth: _propTypes.default.shape({
|
118
|
+
label: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]),
|
119
|
+
navigateTo: _propTypes.default.func
|
120
|
+
}),
|
121
|
+
prevYear: _propTypes.default.shape({
|
122
|
+
label: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]),
|
123
|
+
navigateTo: _propTypes.default.func
|
124
|
+
}),
|
125
|
+
unfocusable: _propTypes.default.bool
|
126
|
+
};
|
127
|
+
NavigationContainer.propTypes = NavigationContainerProps;
|
@@ -0,0 +1,46 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
var _react = require("@testing-library/react");
|
4
|
+
var _react2 = _interopRequireDefault(require("react"));
|
5
|
+
var _calendarInput = require("../calendar-input.js");
|
6
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
7
|
+
describe('Calendar Input', () => {
|
8
|
+
it('allow selection of a date through the calendar widget', async () => {
|
9
|
+
const onDateSelectMock = jest.fn();
|
10
|
+
const screen = (0, _react.render)( /*#__PURE__*/_react2.default.createElement(_calendarInput.CalendarInput, {
|
11
|
+
calendar: "gregory",
|
12
|
+
onDateSelect: onDateSelectMock
|
13
|
+
}));
|
14
|
+
const dateInput = (0, _react.within)(screen.getByTestId('dhis2-uicore-input')).getByRole('textbox');
|
15
|
+
_react.fireEvent.focus(dateInput);
|
16
|
+
const calendar = await screen.findByTestId('calendar');
|
17
|
+
expect(calendar).toBeInTheDocument();
|
18
|
+
const todayString = new Date().toISOString().slice(0, -14);
|
19
|
+
const today = (0, _react.within)(calendar).getByTestId(todayString);
|
20
|
+
_react.fireEvent.click(today);
|
21
|
+
await (0, _react.waitFor)(() => {
|
22
|
+
expect(calendar).not.toBeInTheDocument();
|
23
|
+
});
|
24
|
+
expect(onDateSelectMock).toHaveBeenCalledWith(expect.objectContaining({
|
25
|
+
calendarDateString: todayString
|
26
|
+
}));
|
27
|
+
});
|
28
|
+
it('allow selection of a date through the input', async () => {
|
29
|
+
const onDateSelectMock = jest.fn();
|
30
|
+
const screen = (0, _react.render)( /*#__PURE__*/_react2.default.createElement(_calendarInput.CalendarInput, {
|
31
|
+
calendar: "gregory",
|
32
|
+
onDateSelect: onDateSelectMock
|
33
|
+
}));
|
34
|
+
const dateInputString = '2024/10/12';
|
35
|
+
const dateInput = (0, _react.within)(screen.getByTestId('dhis2-uicore-input')).getByRole('textbox');
|
36
|
+
_react.fireEvent.change(dateInput, {
|
37
|
+
target: {
|
38
|
+
value: dateInputString
|
39
|
+
}
|
40
|
+
});
|
41
|
+
_react.fireEvent.blur(dateInput);
|
42
|
+
expect(onDateSelectMock).toHaveBeenCalledWith(expect.objectContaining({
|
43
|
+
calendarDateString: dateInputString
|
44
|
+
}));
|
45
|
+
});
|
46
|
+
});
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
});
|
6
6
|
exports.CalendarInput = void 0;
|
7
7
|
var _style = _interopRequireDefault(require("styled-jsx/style"));
|
8
|
+
var _multiCalendarDates = require("@dhis2/multi-calendar-dates");
|
8
9
|
var _button = require("@dhis2-ui/button");
|
9
10
|
var _card = require("@dhis2-ui/card");
|
10
11
|
var _input = require("@dhis2-ui/input");
|
@@ -12,6 +13,7 @@ var _layer = require("@dhis2-ui/layer");
|
|
12
13
|
var _popper = require("@dhis2-ui/popper");
|
13
14
|
var _classnames = _interopRequireDefault(require("classnames"));
|
14
15
|
var _react = _interopRequireWildcard(require("react"));
|
16
|
+
var _calendarContainer = require("../calendar/calendar-container.js");
|
15
17
|
var _calendar = require("../calendar/calendar.js");
|
16
18
|
var _index = _interopRequireDefault(require("../locales/index.js"));
|
17
19
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
@@ -26,7 +28,7 @@ const offsetModifier = {
|
|
26
28
|
};
|
27
29
|
const CalendarInput = function () {
|
28
30
|
let {
|
29
|
-
onDateSelect,
|
31
|
+
onDateSelect: parentOnDateSelect,
|
30
32
|
calendar,
|
31
33
|
date,
|
32
34
|
dir,
|
@@ -37,45 +39,86 @@ const CalendarInput = function () {
|
|
37
39
|
width,
|
38
40
|
cellSize,
|
39
41
|
clearable,
|
42
|
+
minDate,
|
43
|
+
maxDate,
|
44
|
+
format,
|
45
|
+
// todo: props and types for format and validation
|
46
|
+
strictValidation,
|
40
47
|
...rest
|
41
48
|
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
42
49
|
const ref = (0, _react.useRef)();
|
43
50
|
const [open, setOpen] = (0, _react.useState)(false);
|
44
|
-
const
|
45
|
-
|
51
|
+
const [partialDate, setPartialDate] = (0, _react.useState)(date);
|
52
|
+
const excludeRef = (0, _react.useRef)(null);
|
53
|
+
(0, _react.useEffect)(() => setPartialDate(date), [date]);
|
54
|
+
const useDatePickerOptions = (0, _react.useMemo)(() => ({
|
55
|
+
calendar,
|
56
|
+
locale,
|
57
|
+
timeZone,
|
58
|
+
// todo: we probably shouldn't have had timezone here in the first place
|
59
|
+
numberingSystem,
|
60
|
+
weekDayFormat
|
61
|
+
}), [calendar, locale, numberingSystem, timeZone, weekDayFormat]);
|
62
|
+
const pickerResults = (0, _multiCalendarDates.useDatePicker)({
|
63
|
+
onDateSelect: result => {
|
46
64
|
setOpen(false);
|
47
|
-
|
48
|
-
}
|
65
|
+
parentOnDateSelect === null || parentOnDateSelect === void 0 ? void 0 : parentOnDateSelect(result);
|
66
|
+
},
|
67
|
+
date,
|
68
|
+
minDate: minDate,
|
69
|
+
maxDate: maxDate,
|
70
|
+
strictValidation: strictValidation,
|
71
|
+
format: format,
|
72
|
+
options: useDatePickerOptions
|
73
|
+
});
|
74
|
+
const handleChange = e => {
|
75
|
+
setPartialDate(e.value);
|
76
|
+
};
|
77
|
+
const handleBlur = (_, e) => {
|
78
|
+
parentOnDateSelect === null || parentOnDateSelect === void 0 ? void 0 : parentOnDateSelect({
|
79
|
+
calendarDateString: partialDate
|
80
|
+
});
|
81
|
+
if (excludeRef.current && !excludeRef.current.contains(e.relatedTarget)) {
|
82
|
+
setOpen(false);
|
83
|
+
}
|
84
|
+
};
|
85
|
+
const onFocus = () => {
|
86
|
+
setOpen(true);
|
87
|
+
};
|
88
|
+
const languageDirection = (0, _multiCalendarDates.useResolvedDirection)(dir, locale);
|
89
|
+
const calendarProps = (0, _react.useMemo)(() => {
|
49
90
|
return {
|
50
|
-
onDateSelect: onDateSelectWrapper,
|
51
|
-
calendar,
|
52
91
|
date,
|
53
|
-
dir,
|
54
|
-
locale,
|
55
|
-
numberingSystem,
|
56
|
-
weekDayFormat,
|
57
|
-
timeZone,
|
58
92
|
width,
|
59
|
-
cellSize
|
93
|
+
cellSize,
|
94
|
+
isValid: pickerResults.isValid,
|
95
|
+
calendarWeekDays: pickerResults.calendarWeekDays,
|
96
|
+
weekDayLabels: pickerResults.weekDayLabels,
|
97
|
+
currMonth: pickerResults.currMonth,
|
98
|
+
currYear: pickerResults.currYear,
|
99
|
+
nextMonth: pickerResults.nextMonth,
|
100
|
+
nextYear: pickerResults.nextYear,
|
101
|
+
prevMonth: pickerResults.prevMonth,
|
102
|
+
prevYear: pickerResults.prevYear,
|
103
|
+
languageDirection
|
60
104
|
};
|
61
|
-
}, [
|
62
|
-
const onFocus = () => {
|
63
|
-
setOpen(true);
|
64
|
-
};
|
105
|
+
}, [cellSize, date, pickerResults, width, languageDirection]);
|
65
106
|
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
|
66
107
|
ref: ref,
|
67
|
-
className: "jsx-
|
108
|
+
className: "jsx-633677374" + " " + "calendar-input-wrapper"
|
68
109
|
}, /*#__PURE__*/_react.default.createElement(_input.InputField, _extends({
|
69
110
|
label: _index.default.t('Pick a date')
|
70
111
|
}, rest, {
|
71
112
|
type: "text",
|
72
113
|
onFocus: onFocus,
|
73
|
-
value:
|
114
|
+
value: partialDate,
|
115
|
+
onChange: handleChange,
|
116
|
+
onBlur: handleBlur,
|
117
|
+
validationText: pickerResults.errorMessage || pickerResults.warningMessage,
|
118
|
+
error: !!pickerResults.errorMessage,
|
119
|
+
warning: !!pickerResults.warningMessage
|
74
120
|
})), clearable && /*#__PURE__*/_react.default.createElement("div", {
|
75
|
-
className: "jsx-
|
76
|
-
// ToDo: this is a workaround to show the clear button in the correct place when an icon is shown.
|
77
|
-
// Long-term, we should abstract and share the logic multi-select uses for the input-wrapper
|
78
|
-
// https://dhis2.atlassian.net/browse/DHIS2-14848
|
121
|
+
className: "jsx-633677374" + " " + ((0, _classnames.default)('calendar-clear-button', {
|
79
122
|
'with-icon': rest.valid || rest.error || rest.warning || rest.loading,
|
80
123
|
'with-dense-wrapper': rest.dense
|
81
124
|
}) || "")
|
@@ -83,7 +126,9 @@ const CalendarInput = function () {
|
|
83
126
|
dataTest: "calendar-clear-button",
|
84
127
|
secondary: true,
|
85
128
|
small: true,
|
86
|
-
onClick: () =>
|
129
|
+
onClick: () => {
|
130
|
+
parentOnDateSelect === null || parentOnDateSelect === void 0 ? void 0 : parentOnDateSelect(null);
|
131
|
+
},
|
87
132
|
type: "button"
|
88
133
|
}, _index.default.t('Clear')))), open && /*#__PURE__*/_react.default.createElement(_layer.Layer, {
|
89
134
|
onBackdropClick: () => {
|
@@ -93,17 +138,17 @@ const CalendarInput = function () {
|
|
93
138
|
reference: ref,
|
94
139
|
placement: "bottom-start",
|
95
140
|
modifiers: [offsetModifier]
|
96
|
-
}, /*#__PURE__*/_react.default.createElement(_card.Card, null, /*#__PURE__*/_react.default.createElement(
|
97
|
-
|
141
|
+
}, /*#__PURE__*/_react.default.createElement(_card.Card, null, /*#__PURE__*/_react.default.createElement(_calendarContainer.CalendarContainer, _extends({}, calendarProps, {
|
142
|
+
excludedRef: excludeRef,
|
143
|
+
unfocusable: true
|
98
144
|
}))))), /*#__PURE__*/_react.default.createElement(_style.default, {
|
99
|
-
id: "
|
100
|
-
}, [".calendar-input-wrapper.jsx-
|
145
|
+
id: "633677374"
|
146
|
+
}, [".calendar-input-wrapper.jsx-633677374{position:relative;}", ".calendar-clear-button.jsx-633677374{position:absolute;inset-inline-end:6px;-webkit-inset-block-start:27px;-ms-intb-rlock-start:27px;inset-block-start:27px;}", ".calendar-clear-button.with-icon.jsx-633677374{inset-inline-end:36px;}", ".calendar-clear-button.with-dense-wrapper.jsx-633677374{-webkit-inset-block-start:23px;-ms-intb-rlock-start:23px;inset-block-start:23px;}"]));
|
101
147
|
};
|
102
148
|
exports.CalendarInput = CalendarInput;
|
103
149
|
CalendarInput.defaultProps = {
|
104
150
|
dataTest: 'dhis2-uiwidgets-calendar-inputfield'
|
105
151
|
};
|
106
152
|
CalendarInput.propTypes = {
|
107
|
-
..._calendar.CalendarProps
|
108
|
-
..._input.InputFieldProps
|
153
|
+
..._calendar.CalendarProps
|
109
154
|
};
|
@@ -3,7 +3,9 @@
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
4
4
|
value: true
|
5
5
|
});
|
6
|
-
exports.
|
6
|
+
exports.CalendarWithClearButton = void 0;
|
7
|
+
exports.CalendarWithEditiableInput = CalendarWithEditiableInput;
|
8
|
+
exports.default = exports.NepaliWithNepali = exports.NepaliWithEnglish = exports.IslamicWithArabic = exports.GregorianWithEnglish = exports.GregorianWithArabic = exports.EthiopicWithEnglish = exports.EthiopicWithAmharic = void 0;
|
7
9
|
var _react = _interopRequireWildcard(require("react"));
|
8
10
|
var _calendarInput = require("../calendar-input/calendar-input.js");
|
9
11
|
var _calendarStoryWrapper = require("./calendar-story-wrapper.js");
|
@@ -114,4 +116,21 @@ const CalendarWithClearButton = _ref2 => {
|
|
114
116
|
"data-test": "storybook-calendar-date-value"
|
115
117
|
}, date !== null && date !== void 0 ? date : 'undefined')));
|
116
118
|
};
|
117
|
-
exports.CalendarWithClearButton = CalendarWithClearButton;
|
119
|
+
exports.CalendarWithClearButton = CalendarWithClearButton;
|
120
|
+
function CalendarWithEditiableInput() {
|
121
|
+
const [date, setDate] = (0, _react.useState)('2020-07-03');
|
122
|
+
return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_calendarInput.CalendarInput, {
|
123
|
+
editable: true,
|
124
|
+
date: date,
|
125
|
+
calendar: "gregory",
|
126
|
+
onDateSelect: selectedDate => {
|
127
|
+
const date = selectedDate === null || selectedDate === void 0 ? void 0 : selectedDate.calendarDateString;
|
128
|
+
setDate(date);
|
129
|
+
},
|
130
|
+
width: '700px',
|
131
|
+
inputWidth: "900px",
|
132
|
+
timeZone: 'UTC',
|
133
|
+
minDate: '2020-07-01',
|
134
|
+
maxDate: '2020-07-09'
|
135
|
+
})));
|
136
|
+
}
|
@@ -0,0 +1,72 @@
|
|
1
|
+
import _JSXStyle from "styled-jsx/style";
|
2
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
3
|
+
import { colors } from '@dhis2/ui-constants';
|
4
|
+
import PropTypes from 'prop-types';
|
5
|
+
import React, { useMemo } from 'react';
|
6
|
+
import { CalendarTable, CalendarTableProps } from './calendar-table.js';
|
7
|
+
import { NavigationContainer, NavigationContainerProps } from './navigation-container.js';
|
8
|
+
const wrapperBorderColor = colors.grey300;
|
9
|
+
const backgroundColor = 'none';
|
10
|
+
export const CalendarContainer = /*#__PURE__*/React.memo(function CalendarContainer(_ref) {
|
11
|
+
let {
|
12
|
+
date,
|
13
|
+
width,
|
14
|
+
cellSize,
|
15
|
+
calendarWeekDays,
|
16
|
+
weekDayLabels,
|
17
|
+
currMonth,
|
18
|
+
currYear,
|
19
|
+
nextMonth,
|
20
|
+
nextYear,
|
21
|
+
prevMonth,
|
22
|
+
prevYear,
|
23
|
+
languageDirection,
|
24
|
+
excludedRef,
|
25
|
+
unfocusable
|
26
|
+
} = _ref;
|
27
|
+
const navigationProps = useMemo(() => {
|
28
|
+
return {
|
29
|
+
currMonth,
|
30
|
+
currYear,
|
31
|
+
nextMonth,
|
32
|
+
nextYear,
|
33
|
+
prevMonth,
|
34
|
+
prevYear,
|
35
|
+
languageDirection
|
36
|
+
};
|
37
|
+
}, [currMonth, currYear, languageDirection, nextMonth, nextYear, prevMonth, prevYear]);
|
38
|
+
return /*#__PURE__*/React.createElement("div", {
|
39
|
+
className: _JSXStyle.dynamic([["2823859047", [backgroundColor, wrapperBorderColor, width]]])
|
40
|
+
}, /*#__PURE__*/React.createElement("div", {
|
41
|
+
dir: languageDirection,
|
42
|
+
"data-test": "calendar",
|
43
|
+
className: _JSXStyle.dynamic([["2823859047", [backgroundColor, wrapperBorderColor, width]]]) + " " + "calendar-wrapper"
|
44
|
+
}, /*#__PURE__*/React.createElement("div", {
|
45
|
+
ref: excludedRef,
|
46
|
+
className: _JSXStyle.dynamic([["2823859047", [backgroundColor, wrapperBorderColor, width]]])
|
47
|
+
}, /*#__PURE__*/React.createElement(NavigationContainer, _extends({}, navigationProps, {
|
48
|
+
unfocusable: unfocusable
|
49
|
+
})), /*#__PURE__*/React.createElement(CalendarTable, {
|
50
|
+
selectedDate: date,
|
51
|
+
calendarWeekDays: calendarWeekDays,
|
52
|
+
weekDayLabels: weekDayLabels,
|
53
|
+
cellSize: cellSize,
|
54
|
+
width: width,
|
55
|
+
unfocusable: unfocusable
|
56
|
+
}))), /*#__PURE__*/React.createElement(_JSXStyle, {
|
57
|
+
id: "2823859047",
|
58
|
+
dynamic: [backgroundColor, wrapperBorderColor, width]
|
59
|
+
}, [`.calendar-wrapper.__jsx-style-dynamic-selector{font-family:Roboto,sans-serif;font-weight:400;font-size:14px;background-color:${backgroundColor};display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;border:1px solid ${wrapperBorderColor};border-radius:3px;min-width:${width};width:-webkit-max-content;width:-moz-max-content;width:max-content;box-shadow:0px 4px 6px -2px #2129340d;box-shadow:0px 10px 15px -3px #2129341a;}`]));
|
60
|
+
});
|
61
|
+
CalendarContainer.defaultProps = {
|
62
|
+
cellSize: '32px',
|
63
|
+
width: '240px',
|
64
|
+
unfocusable: false
|
65
|
+
};
|
66
|
+
CalendarContainer.propTypes = {
|
67
|
+
/** the currently selected date using an iso-like format YYYY-MM-DD, in the calendar system provided (not iso8601) */
|
68
|
+
date: PropTypes.string,
|
69
|
+
unfocusable: PropTypes.bool,
|
70
|
+
...CalendarTableProps,
|
71
|
+
...NavigationContainerProps
|
72
|
+
};
|
@@ -7,7 +7,8 @@ export const CalendarTableCell = _ref => {
|
|
7
7
|
let {
|
8
8
|
day,
|
9
9
|
cellSize,
|
10
|
-
selectedDate
|
10
|
+
selectedDate,
|
11
|
+
unfocusable
|
11
12
|
} = _ref;
|
12
13
|
const dayHoverBackgroundColor = colors.grey200;
|
13
14
|
const selectedDayBackgroundColor = colors.teal700;
|
@@ -17,6 +18,7 @@ export const CalendarTableCell = _ref => {
|
|
17
18
|
className: _JSXStyle.dynamic([["2052411850", [cellSize, cellSize, cellSize, cellSize, colors.grey900, dayHoverBackgroundColor, colors.grey300, selectedDayBackgroundColor, colors.teal600, colors.teal200, colors.grey600]]])
|
18
19
|
}, /*#__PURE__*/React.createElement("button", {
|
19
20
|
name: "day",
|
21
|
+
tabIndex: unfocusable ? -1 : 0,
|
20
22
|
className: _JSXStyle.dynamic([["2052411850", [cellSize, cellSize, cellSize, cellSize, colors.grey900, dayHoverBackgroundColor, colors.grey300, selectedDayBackgroundColor, colors.teal600, colors.teal200, colors.grey600]]]) + " " + (cx('day', {
|
21
23
|
isSelected: selectedDate === (day === null || day === void 0 ? void 0 : day.calendarDate),
|
22
24
|
isToday: day.isToday,
|
@@ -37,5 +39,6 @@ CalendarTableCell.propTypes = {
|
|
37
39
|
label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
38
40
|
onClick: PropTypes.func
|
39
41
|
}),
|
40
|
-
selectedDate: PropTypes.string
|
42
|
+
selectedDate: PropTypes.string,
|
43
|
+
unfocusable: PropTypes.bool
|
41
44
|
};
|
@@ -10,7 +10,8 @@ export const CalendarTable = _ref => {
|
|
10
10
|
calendarWeekDays,
|
11
11
|
width,
|
12
12
|
cellSize,
|
13
|
-
selectedDate
|
13
|
+
selectedDate,
|
14
|
+
unfocusable
|
14
15
|
} = _ref;
|
15
16
|
return /*#__PURE__*/React.createElement("div", {
|
16
17
|
className: _JSXStyle.dynamic([["452536960", [spacers.dp4, spacers.dp4]]]) + " " + "calendar-table-wrapper"
|
@@ -28,13 +29,14 @@ export const CalendarTable = _ref => {
|
|
28
29
|
day: day,
|
29
30
|
key: day === null || day === void 0 ? void 0 : day.calendarDate,
|
30
31
|
cellSize: cellSize,
|
31
|
-
width: width
|
32
|
+
width: width,
|
33
|
+
unfocusable: unfocusable
|
32
34
|
})))))), /*#__PURE__*/React.createElement(_JSXStyle, {
|
33
35
|
id: "452536960",
|
34
36
|
dynamic: [spacers.dp4, spacers.dp4]
|
35
37
|
}, [`.calendar-table.__jsx-style-dynamic-selector{border:none;border-collapse:collapse;width:100%;margin-block:${spacers.dp4};}`, ".calendar-table.__jsx-style-dynamic-selector tr.__jsx-style-dynamic-selector,.calendar-table.__jsx-style-dynamic-selector td.__jsx-style-dynamic-selector{border:none;}", `.calendar-table-wrapper.__jsx-style-dynamic-selector{padding-inline:${spacers.dp4};}`]));
|
36
38
|
};
|
37
|
-
|
39
|
+
export const CalendarTableProps = {
|
38
40
|
calendarWeekDays: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.shape({
|
39
41
|
calendarDate: PropTypes.string,
|
40
42
|
isInCurrentMonth: PropTypes.bool,
|
@@ -46,6 +48,8 @@ CalendarTable.propTypes = {
|
|
46
48
|
}).isRequired).isRequired).isRequired,
|
47
49
|
cellSize: PropTypes.string,
|
48
50
|
selectedDate: PropTypes.string,
|
51
|
+
unfocusable: PropTypes.bool,
|
49
52
|
weekDayLabels: PropTypes.arrayOf(PropTypes.string),
|
50
53
|
width: PropTypes.string
|
51
|
-
};
|
54
|
+
};
|
55
|
+
CalendarTable.propTypes = CalendarTableProps;
|
@@ -1,10 +1,7 @@
|
|
1
|
-
import _JSXStyle from "styled-jsx/style";
|
2
1
|
import { useDatePicker, useResolvedDirection } from '@dhis2/multi-calendar-dates';
|
3
|
-
import { colors } from '@dhis2/ui-constants';
|
4
2
|
import PropTypes from 'prop-types';
|
5
|
-
import React, { useState } from 'react';
|
6
|
-
import {
|
7
|
-
import { NavigationContainer } from './navigation-container.js';
|
3
|
+
import React, { useMemo, useState } from 'react';
|
4
|
+
import { CalendarContainer } from './calendar-container.js';
|
8
5
|
export const Calendar = _ref => {
|
9
6
|
let {
|
10
7
|
onDateSelect,
|
@@ -18,8 +15,6 @@ export const Calendar = _ref => {
|
|
18
15
|
width,
|
19
16
|
cellSize
|
20
17
|
} = _ref;
|
21
|
-
const wrapperBorderColor = colors.grey300;
|
22
|
-
const backgroundColor = 'none';
|
23
18
|
const [selectedDateString, setSelectedDateString] = useState(date);
|
24
19
|
const languageDirection = useResolvedDirection(dir, locale);
|
25
20
|
const options = {
|
@@ -29,7 +24,7 @@ export const Calendar = _ref => {
|
|
29
24
|
numberingSystem,
|
30
25
|
weekDayFormat
|
31
26
|
};
|
32
|
-
const
|
27
|
+
const pickerResults = useDatePicker({
|
33
28
|
onDateSelect: result => {
|
34
29
|
const {
|
35
30
|
calendarDateString
|
@@ -40,29 +35,30 @@ export const Calendar = _ref => {
|
|
40
35
|
date: selectedDateString,
|
41
36
|
options
|
42
37
|
});
|
43
|
-
const {
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
}, [
|
38
|
+
const calendarProps = useMemo(() => {
|
39
|
+
return {
|
40
|
+
date,
|
41
|
+
dir,
|
42
|
+
locale,
|
43
|
+
width,
|
44
|
+
cellSize,
|
45
|
+
// minDate,
|
46
|
+
// maxDate,
|
47
|
+
// validation, // todo: clarify how we use validation props (and format) in Calendar (not CalendarInput)
|
48
|
+
// format,
|
49
|
+
isValid: pickerResults.isValid,
|
50
|
+
calendarWeekDays: pickerResults.calendarWeekDays,
|
51
|
+
weekDayLabels: pickerResults.weekDayLabels,
|
52
|
+
currMonth: pickerResults.currMonth,
|
53
|
+
currYear: pickerResults.currYear,
|
54
|
+
nextMonth: pickerResults.nextMonth,
|
55
|
+
nextYear: pickerResults.nextYear,
|
56
|
+
prevMonth: pickerResults.prevMonth,
|
57
|
+
prevYear: pickerResults.prevYear,
|
58
|
+
languageDirection
|
59
|
+
};
|
60
|
+
}, [cellSize, date, dir, locale, pickerResults, width, languageDirection]);
|
61
|
+
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(CalendarContainer, calendarProps));
|
66
62
|
};
|
67
63
|
Calendar.defaultProps = {
|
68
64
|
cellSize: '32px',
|
@@ -10,18 +10,16 @@ export const NavigationContainer = _ref => {
|
|
10
10
|
var _currYear$label;
|
11
11
|
let {
|
12
12
|
languageDirection,
|
13
|
-
pickerOptions
|
14
|
-
} = _ref;
|
15
|
-
const PreviousIcon = languageDirection === 'ltr' ? IconChevronLeft16 : IconChevronRight16;
|
16
|
-
const NextIcon = languageDirection === 'ltr' ? IconChevronRight16 : IconChevronLeft16;
|
17
|
-
const {
|
18
13
|
currMonth,
|
19
14
|
currYear,
|
20
15
|
nextMonth,
|
21
16
|
nextYear,
|
22
17
|
prevMonth,
|
23
|
-
prevYear
|
24
|
-
|
18
|
+
prevYear,
|
19
|
+
unfocusable
|
20
|
+
} = _ref;
|
21
|
+
const PreviousIcon = languageDirection === 'ltr' ? IconChevronLeft16 : IconChevronRight16;
|
22
|
+
const NextIcon = languageDirection === 'ltr' ? IconChevronRight16 : IconChevronLeft16;
|
25
23
|
|
26
24
|
// Ethiopic years - when localised to English - add the era (i.e. 2015 ERA1), which is redundant in practice (like writing AD for gregorian years)
|
27
25
|
// there is an ongoing discussion in JS-Temporal polyfill whether the era should be included or not, but for our case, it's safer to remove it
|
@@ -38,6 +36,7 @@ export const NavigationContainer = _ref => {
|
|
38
36
|
"data-test": "calendar-previous-month",
|
39
37
|
"aria-label": `${i18n.t(`Go to ${prevMonth.label}`)}`,
|
40
38
|
type: "button",
|
39
|
+
tabIndex: unfocusable ? -1 : 0,
|
41
40
|
className: _JSXStyle.dynamic([["3883083596", [spacers.dp4, colors.grey600, colors.grey200, colors.grey900, colors.grey300, spacers.dp8, spacers.dp4, wrapperBorderColor, headerBackground]]])
|
42
41
|
}, /*#__PURE__*/React.createElement(PreviousIcon, {
|
43
42
|
className: _JSXStyle.dynamic([["3883083596", [spacers.dp4, colors.grey600, colors.grey200, colors.grey900, colors.grey300, spacers.dp8, spacers.dp4, wrapperBorderColor, headerBackground]]])
|
@@ -53,6 +52,7 @@ export const NavigationContainer = _ref => {
|
|
53
52
|
name: "next-month",
|
54
53
|
"aria-label": `${i18n.t(`Go to ${nextMonth.label}`)}`,
|
55
54
|
type: "button",
|
55
|
+
tabIndex: unfocusable ? -1 : 0,
|
56
56
|
className: _JSXStyle.dynamic([["3883083596", [spacers.dp4, colors.grey600, colors.grey200, colors.grey900, colors.grey300, spacers.dp8, spacers.dp4, wrapperBorderColor, headerBackground]]])
|
57
57
|
}, /*#__PURE__*/React.createElement(NextIcon, {
|
58
58
|
className: _JSXStyle.dynamic([["3883083596", [spacers.dp4, colors.grey600, colors.grey200, colors.grey900, colors.grey300, spacers.dp8, spacers.dp4, wrapperBorderColor, headerBackground]]])
|
@@ -65,6 +65,7 @@ export const NavigationContainer = _ref => {
|
|
65
65
|
name: "previous-year",
|
66
66
|
"aria-label": `${i18n.t('Go to previous year')}`,
|
67
67
|
type: "button",
|
68
|
+
tabIndex: unfocusable ? -1 : 0,
|
68
69
|
className: _JSXStyle.dynamic([["3883083596", [spacers.dp4, colors.grey600, colors.grey200, colors.grey900, colors.grey300, spacers.dp8, spacers.dp4, wrapperBorderColor, headerBackground]]])
|
69
70
|
}, /*#__PURE__*/React.createElement(PreviousIcon, {
|
70
71
|
className: _JSXStyle.dynamic([["3883083596", [spacers.dp4, colors.grey600, colors.grey200, colors.grey900, colors.grey300, spacers.dp8, spacers.dp4, wrapperBorderColor, headerBackground]]])
|
@@ -80,6 +81,7 @@ export const NavigationContainer = _ref => {
|
|
80
81
|
name: "next-year",
|
81
82
|
"aria-label": `${i18n.t('Go to next year')}`,
|
82
83
|
type: "button",
|
84
|
+
tabIndex: unfocusable ? -1 : 0,
|
83
85
|
className: _JSXStyle.dynamic([["3883083596", [spacers.dp4, colors.grey600, colors.grey200, colors.grey900, colors.grey300, spacers.dp8, spacers.dp4, wrapperBorderColor, headerBackground]]])
|
84
86
|
}, /*#__PURE__*/React.createElement(NextIcon, {
|
85
87
|
className: _JSXStyle.dynamic([["3883083596", [spacers.dp4, colors.grey600, colors.grey200, colors.grey900, colors.grey300, spacers.dp8, spacers.dp4, wrapperBorderColor, headerBackground]]])
|
@@ -88,30 +90,30 @@ export const NavigationContainer = _ref => {
|
|
88
90
|
dynamic: [spacers.dp4, colors.grey600, colors.grey200, colors.grey900, colors.grey300, spacers.dp8, spacers.dp4, wrapperBorderColor, headerBackground]
|
89
91
|
}, ["button.__jsx-style-dynamic-selector{background:none;border:0;}", ".month.__jsx-style-dynamic-selector,.year.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;cursor:default;}", ".month.__jsx-style-dynamic-selector .curr.__jsx-style-dynamic-selector,.year.__jsx-style-dynamic-selector .curr.__jsx-style-dynamic-selector{-webkit-flex:2;-ms-flex:2;flex:2;white-space:nowrap;}", ".prev.__jsx-style-dynamic-selector,.next.__jsx-style-dynamic-selector{-webkit-flex:1;-ms-flex:1;flex:1;text-align:center;}", `.prev.__jsx-style-dynamic-selector button.__jsx-style-dynamic-selector,.next.__jsx-style-dynamic-selector button.__jsx-style-dynamic-selector{padding:${spacers.dp4};height:24px;width:24px;color:${colors.grey600};border-radius:3px;}`, ".prev.__jsx-style-dynamic-selector button.__jsx-style-dynamic-selector svg.__jsx-style-dynamic-selector,.next.__jsx-style-dynamic-selector button.__jsx-style-dynamic-selector svg.__jsx-style-dynamic-selector{width:16px;height:16px;}", `.prev.__jsx-style-dynamic-selector:hover button.__jsx-style-dynamic-selector,.next.__jsx-style-dynamic-selector:hover button.__jsx-style-dynamic-selector{background-color:${colors.grey200};color:${colors.grey900};cursor:pointer;}`, `.prev.__jsx-style-dynamic-selector button.__jsx-style-dynamic-selector:active,.next.__jsx-style-dynamic-selector button.__jsx-style-dynamic-selector:active{background-color:${colors.grey300};}`, ".label.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding:4px 8px;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;min-height:16px;}", `.navigation-container.__jsx-style-dynamic-selector{gap:${spacers.dp8};padding:${spacers.dp4};display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;border-bottom:1px solid ${wrapperBorderColor};background-color:${headerBackground};font-size:1.08em;}`]));
|
90
92
|
};
|
91
|
-
|
93
|
+
export const NavigationContainerProps = {
|
94
|
+
currMonth: PropTypes.shape({
|
95
|
+
label: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
|
96
|
+
}),
|
97
|
+
currYear: PropTypes.shape({
|
98
|
+
label: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
|
99
|
+
}),
|
92
100
|
languageDirection: PropTypes.oneOf(['ltr', 'rtl']),
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
prevYear: PropTypes.shape({
|
113
|
-
label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
114
|
-
navigateTo: PropTypes.func
|
115
|
-
})
|
116
|
-
})
|
117
|
-
};
|
101
|
+
nextMonth: PropTypes.shape({
|
102
|
+
label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
103
|
+
navigateTo: PropTypes.func
|
104
|
+
}),
|
105
|
+
nextYear: PropTypes.shape({
|
106
|
+
label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
107
|
+
navigateTo: PropTypes.func
|
108
|
+
}),
|
109
|
+
prevMonth: PropTypes.shape({
|
110
|
+
label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
111
|
+
navigateTo: PropTypes.func
|
112
|
+
}),
|
113
|
+
prevYear: PropTypes.shape({
|
114
|
+
label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
115
|
+
navigateTo: PropTypes.func
|
116
|
+
}),
|
117
|
+
unfocusable: PropTypes.bool
|
118
|
+
};
|
119
|
+
NavigationContainer.propTypes = NavigationContainerProps;
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import { fireEvent, render, waitFor, within } from '@testing-library/react';
|
2
|
+
import React from 'react';
|
3
|
+
import { CalendarInput } from '../calendar-input.js';
|
4
|
+
describe('Calendar Input', () => {
|
5
|
+
it('allow selection of a date through the calendar widget', async () => {
|
6
|
+
const onDateSelectMock = jest.fn();
|
7
|
+
const screen = render( /*#__PURE__*/React.createElement(CalendarInput, {
|
8
|
+
calendar: "gregory",
|
9
|
+
onDateSelect: onDateSelectMock
|
10
|
+
}));
|
11
|
+
const dateInput = within(screen.getByTestId('dhis2-uicore-input')).getByRole('textbox');
|
12
|
+
fireEvent.focus(dateInput);
|
13
|
+
const calendar = await screen.findByTestId('calendar');
|
14
|
+
expect(calendar).toBeInTheDocument();
|
15
|
+
const todayString = new Date().toISOString().slice(0, -14);
|
16
|
+
const today = within(calendar).getByTestId(todayString);
|
17
|
+
fireEvent.click(today);
|
18
|
+
await waitFor(() => {
|
19
|
+
expect(calendar).not.toBeInTheDocument();
|
20
|
+
});
|
21
|
+
expect(onDateSelectMock).toHaveBeenCalledWith(expect.objectContaining({
|
22
|
+
calendarDateString: todayString
|
23
|
+
}));
|
24
|
+
});
|
25
|
+
it('allow selection of a date through the input', async () => {
|
26
|
+
const onDateSelectMock = jest.fn();
|
27
|
+
const screen = render( /*#__PURE__*/React.createElement(CalendarInput, {
|
28
|
+
calendar: "gregory",
|
29
|
+
onDateSelect: onDateSelectMock
|
30
|
+
}));
|
31
|
+
const dateInputString = '2024/10/12';
|
32
|
+
const dateInput = within(screen.getByTestId('dhis2-uicore-input')).getByRole('textbox');
|
33
|
+
fireEvent.change(dateInput, {
|
34
|
+
target: {
|
35
|
+
value: dateInputString
|
36
|
+
}
|
37
|
+
});
|
38
|
+
fireEvent.blur(dateInput);
|
39
|
+
expect(onDateSelectMock).toHaveBeenCalledWith(expect.objectContaining({
|
40
|
+
calendarDateString: dateInputString
|
41
|
+
}));
|
42
|
+
});
|
43
|
+
});
|
@@ -1,13 +1,15 @@
|
|
1
1
|
import _JSXStyle from "styled-jsx/style";
|
2
2
|
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
3
|
+
import { useDatePicker, useResolvedDirection } from '@dhis2/multi-calendar-dates';
|
3
4
|
import { Button } from '@dhis2-ui/button';
|
4
5
|
import { Card } from '@dhis2-ui/card';
|
5
|
-
import { InputField
|
6
|
+
import { InputField } from '@dhis2-ui/input';
|
6
7
|
import { Layer } from '@dhis2-ui/layer';
|
7
8
|
import { Popper } from '@dhis2-ui/popper';
|
8
9
|
import cx from 'classnames';
|
9
|
-
import React, { useRef, useState } from 'react';
|
10
|
-
import {
|
10
|
+
import React, { useRef, useState, useMemo, useEffect } from 'react';
|
11
|
+
import { CalendarContainer } from '../calendar/calendar-container.js';
|
12
|
+
import { CalendarProps } from '../calendar/calendar.js';
|
11
13
|
import i18n from '../locales/index.js';
|
12
14
|
const offsetModifier = {
|
13
15
|
name: 'offset',
|
@@ -17,7 +19,7 @@ const offsetModifier = {
|
|
17
19
|
};
|
18
20
|
export const CalendarInput = function () {
|
19
21
|
let {
|
20
|
-
onDateSelect,
|
22
|
+
onDateSelect: parentOnDateSelect,
|
21
23
|
calendar,
|
22
24
|
date,
|
23
25
|
dir,
|
@@ -28,45 +30,86 @@ export const CalendarInput = function () {
|
|
28
30
|
width,
|
29
31
|
cellSize,
|
30
32
|
clearable,
|
33
|
+
minDate,
|
34
|
+
maxDate,
|
35
|
+
format,
|
36
|
+
// todo: props and types for format and validation
|
37
|
+
strictValidation,
|
31
38
|
...rest
|
32
39
|
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
33
40
|
const ref = useRef();
|
34
41
|
const [open, setOpen] = useState(false);
|
35
|
-
const
|
36
|
-
|
42
|
+
const [partialDate, setPartialDate] = useState(date);
|
43
|
+
const excludeRef = useRef(null);
|
44
|
+
useEffect(() => setPartialDate(date), [date]);
|
45
|
+
const useDatePickerOptions = useMemo(() => ({
|
46
|
+
calendar,
|
47
|
+
locale,
|
48
|
+
timeZone,
|
49
|
+
// todo: we probably shouldn't have had timezone here in the first place
|
50
|
+
numberingSystem,
|
51
|
+
weekDayFormat
|
52
|
+
}), [calendar, locale, numberingSystem, timeZone, weekDayFormat]);
|
53
|
+
const pickerResults = useDatePicker({
|
54
|
+
onDateSelect: result => {
|
37
55
|
setOpen(false);
|
38
|
-
|
39
|
-
}
|
56
|
+
parentOnDateSelect === null || parentOnDateSelect === void 0 ? void 0 : parentOnDateSelect(result);
|
57
|
+
},
|
58
|
+
date,
|
59
|
+
minDate: minDate,
|
60
|
+
maxDate: maxDate,
|
61
|
+
strictValidation: strictValidation,
|
62
|
+
format: format,
|
63
|
+
options: useDatePickerOptions
|
64
|
+
});
|
65
|
+
const handleChange = e => {
|
66
|
+
setPartialDate(e.value);
|
67
|
+
};
|
68
|
+
const handleBlur = (_, e) => {
|
69
|
+
parentOnDateSelect === null || parentOnDateSelect === void 0 ? void 0 : parentOnDateSelect({
|
70
|
+
calendarDateString: partialDate
|
71
|
+
});
|
72
|
+
if (excludeRef.current && !excludeRef.current.contains(e.relatedTarget)) {
|
73
|
+
setOpen(false);
|
74
|
+
}
|
75
|
+
};
|
76
|
+
const onFocus = () => {
|
77
|
+
setOpen(true);
|
78
|
+
};
|
79
|
+
const languageDirection = useResolvedDirection(dir, locale);
|
80
|
+
const calendarProps = useMemo(() => {
|
40
81
|
return {
|
41
|
-
onDateSelect: onDateSelectWrapper,
|
42
|
-
calendar,
|
43
82
|
date,
|
44
|
-
dir,
|
45
|
-
locale,
|
46
|
-
numberingSystem,
|
47
|
-
weekDayFormat,
|
48
|
-
timeZone,
|
49
83
|
width,
|
50
|
-
cellSize
|
84
|
+
cellSize,
|
85
|
+
isValid: pickerResults.isValid,
|
86
|
+
calendarWeekDays: pickerResults.calendarWeekDays,
|
87
|
+
weekDayLabels: pickerResults.weekDayLabels,
|
88
|
+
currMonth: pickerResults.currMonth,
|
89
|
+
currYear: pickerResults.currYear,
|
90
|
+
nextMonth: pickerResults.nextMonth,
|
91
|
+
nextYear: pickerResults.nextYear,
|
92
|
+
prevMonth: pickerResults.prevMonth,
|
93
|
+
prevYear: pickerResults.prevYear,
|
94
|
+
languageDirection
|
51
95
|
};
|
52
|
-
}, [
|
53
|
-
const onFocus = () => {
|
54
|
-
setOpen(true);
|
55
|
-
};
|
96
|
+
}, [cellSize, date, pickerResults, width, languageDirection]);
|
56
97
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
57
98
|
ref: ref,
|
58
|
-
className: "jsx-
|
99
|
+
className: "jsx-633677374" + " " + "calendar-input-wrapper"
|
59
100
|
}, /*#__PURE__*/React.createElement(InputField, _extends({
|
60
101
|
label: i18n.t('Pick a date')
|
61
102
|
}, rest, {
|
62
103
|
type: "text",
|
63
104
|
onFocus: onFocus,
|
64
|
-
value:
|
105
|
+
value: partialDate,
|
106
|
+
onChange: handleChange,
|
107
|
+
onBlur: handleBlur,
|
108
|
+
validationText: pickerResults.errorMessage || pickerResults.warningMessage,
|
109
|
+
error: !!pickerResults.errorMessage,
|
110
|
+
warning: !!pickerResults.warningMessage
|
65
111
|
})), clearable && /*#__PURE__*/React.createElement("div", {
|
66
|
-
className: "jsx-
|
67
|
-
// ToDo: this is a workaround to show the clear button in the correct place when an icon is shown.
|
68
|
-
// Long-term, we should abstract and share the logic multi-select uses for the input-wrapper
|
69
|
-
// https://dhis2.atlassian.net/browse/DHIS2-14848
|
112
|
+
className: "jsx-633677374" + " " + (cx('calendar-clear-button', {
|
70
113
|
'with-icon': rest.valid || rest.error || rest.warning || rest.loading,
|
71
114
|
'with-dense-wrapper': rest.dense
|
72
115
|
}) || "")
|
@@ -74,7 +117,9 @@ export const CalendarInput = function () {
|
|
74
117
|
dataTest: "calendar-clear-button",
|
75
118
|
secondary: true,
|
76
119
|
small: true,
|
77
|
-
onClick: () =>
|
120
|
+
onClick: () => {
|
121
|
+
parentOnDateSelect === null || parentOnDateSelect === void 0 ? void 0 : parentOnDateSelect(null);
|
122
|
+
},
|
78
123
|
type: "button"
|
79
124
|
}, i18n.t('Clear')))), open && /*#__PURE__*/React.createElement(Layer, {
|
80
125
|
onBackdropClick: () => {
|
@@ -84,16 +129,16 @@ export const CalendarInput = function () {
|
|
84
129
|
reference: ref,
|
85
130
|
placement: "bottom-start",
|
86
131
|
modifiers: [offsetModifier]
|
87
|
-
}, /*#__PURE__*/React.createElement(Card, null, /*#__PURE__*/React.createElement(
|
88
|
-
|
132
|
+
}, /*#__PURE__*/React.createElement(Card, null, /*#__PURE__*/React.createElement(CalendarContainer, _extends({}, calendarProps, {
|
133
|
+
excludedRef: excludeRef,
|
134
|
+
unfocusable: true
|
89
135
|
}))))), /*#__PURE__*/React.createElement(_JSXStyle, {
|
90
|
-
id: "
|
91
|
-
}, [".calendar-input-wrapper.jsx-
|
136
|
+
id: "633677374"
|
137
|
+
}, [".calendar-input-wrapper.jsx-633677374{position:relative;}", ".calendar-clear-button.jsx-633677374{position:absolute;inset-inline-end:6px;-webkit-inset-block-start:27px;-ms-intb-rlock-start:27px;inset-block-start:27px;}", ".calendar-clear-button.with-icon.jsx-633677374{inset-inline-end:36px;}", ".calendar-clear-button.with-dense-wrapper.jsx-633677374{-webkit-inset-block-start:23px;-ms-intb-rlock-start:23px;inset-block-start:23px;}"]));
|
92
138
|
};
|
93
139
|
CalendarInput.defaultProps = {
|
94
140
|
dataTest: 'dhis2-uiwidgets-calendar-inputfield'
|
95
141
|
};
|
96
142
|
CalendarInput.propTypes = {
|
97
|
-
...CalendarProps
|
98
|
-
...InputFieldProps
|
143
|
+
...CalendarProps
|
99
144
|
};
|
@@ -104,4 +104,21 @@ export const CalendarWithClearButton = _ref2 => {
|
|
104
104
|
}), /*#__PURE__*/React.createElement("div", null, "value:", /*#__PURE__*/React.createElement("span", {
|
105
105
|
"data-test": "storybook-calendar-date-value"
|
106
106
|
}, date !== null && date !== void 0 ? date : 'undefined')));
|
107
|
-
};
|
107
|
+
};
|
108
|
+
export function CalendarWithEditiableInput() {
|
109
|
+
const [date, setDate] = useState('2020-07-03');
|
110
|
+
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(CalendarInput, {
|
111
|
+
editable: true,
|
112
|
+
date: date,
|
113
|
+
calendar: "gregory",
|
114
|
+
onDateSelect: selectedDate => {
|
115
|
+
const date = selectedDate === null || selectedDate === void 0 ? void 0 : selectedDate.calendarDateString;
|
116
|
+
setDate(date);
|
117
|
+
},
|
118
|
+
width: '700px',
|
119
|
+
inputWidth: "900px",
|
120
|
+
timeZone: 'UTC',
|
121
|
+
minDate: '2020-07-01',
|
122
|
+
maxDate: '2020-07-09'
|
123
|
+
})));
|
124
|
+
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@dhis2-ui/calendar",
|
3
|
-
"version": "9.
|
3
|
+
"version": "9.12.0-alpha.2",
|
4
4
|
"description": "UI Calendar",
|
5
5
|
"repository": {
|
6
6
|
"type": "git",
|
@@ -33,15 +33,15 @@
|
|
33
33
|
"styled-jsx": "^4"
|
34
34
|
},
|
35
35
|
"dependencies": {
|
36
|
-
"@dhis2-ui/button": "9.
|
37
|
-
"@dhis2-ui/card": "9.
|
38
|
-
"@dhis2-ui/input": "9.
|
39
|
-
"@dhis2-ui/layer": "9.
|
40
|
-
"@dhis2-ui/popper": "9.
|
41
|
-
"@dhis2/multi-calendar-dates": "
|
36
|
+
"@dhis2-ui/button": "9.12.0-alpha.2",
|
37
|
+
"@dhis2-ui/card": "9.12.0-alpha.2",
|
38
|
+
"@dhis2-ui/input": "9.12.0-alpha.2",
|
39
|
+
"@dhis2-ui/layer": "9.12.0-alpha.2",
|
40
|
+
"@dhis2-ui/popper": "9.12.0-alpha.2",
|
41
|
+
"@dhis2/multi-calendar-dates": "1.3.0",
|
42
42
|
"@dhis2/prop-types": "^3.1.2",
|
43
|
-
"@dhis2/ui-constants": "9.
|
44
|
-
"@dhis2/ui-icons": "9.
|
43
|
+
"@dhis2/ui-constants": "9.12.0-alpha.2",
|
44
|
+
"@dhis2/ui-icons": "9.12.0-alpha.2",
|
45
45
|
"classnames": "^2.3.1",
|
46
46
|
"prop-types": "^15.7.2"
|
47
47
|
},
|