@spaced-out/ui-design-system 0.1.92 → 0.1.93-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cspell/custom-words.txt +41 -0
- package/CHANGELOG.md +12 -0
- package/lib/components/DateRangePicker/Calendar.js +75 -0
- package/lib/components/DateRangePicker/Calendar.js.flow +113 -0
- package/lib/components/DateRangePicker/Calendar.module.css +49 -0
- package/lib/components/DateRangePicker/DateRangePicker.js +120 -0
- package/lib/components/DateRangePicker/DateRangePicker.js.flow +173 -0
- package/lib/components/DateRangePicker/DateRangePicker.module.css +8 -0
- package/lib/components/DateRangePicker/DateRangeWrapper.js +175 -0
- package/lib/components/DateRangePicker/DateRangeWrapper.js.flow +282 -0
- package/lib/components/DateRangePicker/DateRangeWrapper.module.css +64 -0
- package/lib/components/DateRangePicker/Day.js +65 -0
- package/lib/components/DateRangePicker/Day.js.flow +80 -0
- package/lib/components/DateRangePicker/Day.module.css +91 -0
- package/lib/components/DateRangePicker/index.js +16 -0
- package/lib/components/DateRangePicker/index.js.flow +3 -0
- package/lib/components/DateRangePicker/timezones.js +262 -0
- package/lib/components/DateRangePicker/timezones.js.flow +256 -0
- package/lib/components/DateRangePicker/utils.js +218 -0
- package/lib/components/DateRangePicker/utils.js.flow +231 -0
- package/lib/components/Dropdown/Dropdown.js +7 -1
- package/lib/components/Dropdown/Dropdown.js.flow +7 -0
- package/lib/components/SpiderChart/SpiderChart.js +1 -20
- package/lib/components/SpiderChart/SpiderChart.js.flow +0 -20
- package/lib/components/index.js +11 -0
- package/lib/components/index.js.flow +1 -0
- package/lib/types/charts.js.flow +1 -0
- package/lib/utils/charts/charts.js +3 -0
- package/lib/utils/charts/charts.js.flow +3 -0
- package/lib/utils/charts/columnChart.js +1 -0
- package/lib/utils/charts/columnChart.js.flow +1 -0
- package/lib/utils/charts/lineChart.js +1 -0
- package/lib/utils/charts/lineChart.js.flow +1 -0
- package/lib/utils/charts/spiderChart.js +3 -1
- package/lib/utils/charts/spiderChart.js.flow +4 -17
- package/lib/utils/charts/typography.js +2 -3
- package/lib/utils/charts/typography.js.flow +1 -3
- package/package.json +2 -1
package/.cspell/custom-words.txt
CHANGED
|
@@ -70,3 +70,44 @@ VishalBarnawal
|
|
|
70
70
|
xmark
|
|
71
71
|
yourcomponentname
|
|
72
72
|
yxxx
|
|
73
|
+
Pago
|
|
74
|
+
Rica
|
|
75
|
+
Cuiaba
|
|
76
|
+
Branco
|
|
77
|
+
Manaus
|
|
78
|
+
Velho
|
|
79
|
+
Santo
|
|
80
|
+
Araguaina
|
|
81
|
+
Paulo
|
|
82
|
+
Rothera
|
|
83
|
+
Noronha
|
|
84
|
+
Scoresbysund
|
|
85
|
+
Aaiun
|
|
86
|
+
Danmarkshavn
|
|
87
|
+
Syowa
|
|
88
|
+
Mahe
|
|
89
|
+
Aqtau
|
|
90
|
+
Aqtobe
|
|
91
|
+
Hovd
|
|
92
|
+
Minh
|
|
93
|
+
Choibalsan
|
|
94
|
+
Kuala
|
|
95
|
+
Lumpur
|
|
96
|
+
Tongatapu
|
|
97
|
+
Kiritimati
|
|
98
|
+
Fakaofo
|
|
99
|
+
Enderbury
|
|
100
|
+
Kamchatskiy
|
|
101
|
+
Pohnpei
|
|
102
|
+
Kosrae
|
|
103
|
+
Efate
|
|
104
|
+
Moresby
|
|
105
|
+
Chuuk
|
|
106
|
+
Sakhalin
|
|
107
|
+
Ulaanbaatar
|
|
108
|
+
Dumont
|
|
109
|
+
Dili
|
|
110
|
+
Urville
|
|
111
|
+
D'Urville
|
|
112
|
+
Magadan
|
|
113
|
+
Yuzhno
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [0.1.93-beta.0](https://github.com/spaced-out/ui-design-system/compare/v0.1.92...v0.1.93-beta.0) (2024-04-29)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* [GDS-367] Date Range Picker ([#195](https://github.com/spaced-out/ui-design-system/issues/195)) ([19626ca](https://github.com/spaced-out/ui-design-system/commit/19626ca27c6f2129a2a414bb7018c7e6127ae22e))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* **SpiderChart.js:** added categories in the chart ([#196](https://github.com/spaced-out/ui-design-system/issues/196)) ([7cf85d6](https://github.com/spaced-out/ui-design-system/commit/7cf85d6984b4830ad4751598218a522e68446309))
|
|
16
|
+
|
|
5
17
|
### [0.1.92](https://github.com/spaced-out/ui-design-system/compare/v0.1.91...v0.1.92) (2024-04-28)
|
|
6
18
|
|
|
7
19
|
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.Calendar = void 0;
|
|
7
|
+
var React = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _momentTimezone = _interopRequireDefault(require("moment-timezone"));
|
|
9
|
+
var _Text = require("../Text");
|
|
10
|
+
var _Day = require("./Day");
|
|
11
|
+
var _utils = require("./utils");
|
|
12
|
+
var _CalendarModule = _interopRequireDefault(require("./Calendar.module.css"));
|
|
13
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
14
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
15
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
16
|
+
|
|
17
|
+
// $FlowFixMe[untyped-import]
|
|
18
|
+
|
|
19
|
+
const getFormattedDate = (marker, dateRange) => {
|
|
20
|
+
const {
|
|
21
|
+
startDate,
|
|
22
|
+
endDate
|
|
23
|
+
} = dateRange;
|
|
24
|
+
switch (marker) {
|
|
25
|
+
case _utils.MARKERS.DATE_RANGE_START:
|
|
26
|
+
return startDate ? (0, _momentTimezone.default)(startDate).format('MMMM D, YYYY') : 'Start Date';
|
|
27
|
+
default:
|
|
28
|
+
return endDate ? (0, _momentTimezone.default)(endDate).format('MMMM D, YYYY') : 'End Date';
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const Calendar = _ref => {
|
|
32
|
+
let {
|
|
33
|
+
value,
|
|
34
|
+
marker,
|
|
35
|
+
handlers,
|
|
36
|
+
hoverDay,
|
|
37
|
+
dateRange,
|
|
38
|
+
inHoverRange
|
|
39
|
+
} = _ref;
|
|
40
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
41
|
+
className: _CalendarModule.default.calendar
|
|
42
|
+
}, /*#__PURE__*/React.createElement(_Text.SubTitleExtraSmall, {
|
|
43
|
+
className: _CalendarModule.default.selectedDate,
|
|
44
|
+
color: _Text.TEXT_COLORS.secondary
|
|
45
|
+
}, getFormattedDate(marker, dateRange)), /*#__PURE__*/React.createElement("div", {
|
|
46
|
+
className: _CalendarModule.default.calendarRow
|
|
47
|
+
}, _utils.WEEKDAYS.map(day => /*#__PURE__*/React.createElement(_Text.BodySmall, {
|
|
48
|
+
key: day,
|
|
49
|
+
className: _CalendarModule.default.calendarRowItem,
|
|
50
|
+
color: _Text.TEXT_COLORS.tertiary
|
|
51
|
+
}, day))), (0, _utils.getDaysInMonth)(value).map((week, index) => /*#__PURE__*/React.createElement("div", {
|
|
52
|
+
key: week[index],
|
|
53
|
+
className: _CalendarModule.default.calendarRow
|
|
54
|
+
}, week.map(date => {
|
|
55
|
+
const isStart = (0, _utils.isStartOfRange)(dateRange, date);
|
|
56
|
+
const isEnd = (0, _utils.isEndOfRange)(dateRange, date);
|
|
57
|
+
const isRangeValid = (0, _utils.isStartDateEndDateSame)(dateRange);
|
|
58
|
+
const highlighted = (0, _utils.inDateRange)(dateRange, date) || inHoverRange(date);
|
|
59
|
+
return /*#__PURE__*/React.createElement(_Day.Day, {
|
|
60
|
+
key: date,
|
|
61
|
+
date: date,
|
|
62
|
+
filled: isStart || isEnd,
|
|
63
|
+
onClick: () => handlers.onDayClick(date),
|
|
64
|
+
onHover: () => handlers.onDayHover(date),
|
|
65
|
+
outlined: (0, _momentTimezone.default)(date).isSame((0, _momentTimezone.default)(), 'd'),
|
|
66
|
+
disabled: (0, _momentTimezone.default)(date).isAfter((0, _utils.formatIsoDate)()) || !(0, _momentTimezone.default)(date).isSame((0, _momentTimezone.default)(value), 'month'),
|
|
67
|
+
endOfRange: isEnd && !isRangeValid,
|
|
68
|
+
highlighted: highlighted && !isRangeValid,
|
|
69
|
+
startOfRange: isStart && !isRangeValid,
|
|
70
|
+
value: (0, _momentTimezone.default)(date).date(),
|
|
71
|
+
hoverDay: hoverDay
|
|
72
|
+
});
|
|
73
|
+
}))));
|
|
74
|
+
};
|
|
75
|
+
exports.Calendar = Calendar;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// @flow strict
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
// $FlowFixMe[untyped-import]
|
|
5
|
+
import moment from 'moment-timezone';
|
|
6
|
+
|
|
7
|
+
import {BodySmall, SubTitleExtraSmall, TEXT_COLORS} from '../Text';
|
|
8
|
+
|
|
9
|
+
import {Day} from './Day';
|
|
10
|
+
import {
|
|
11
|
+
type DateRange,
|
|
12
|
+
formatIsoDate,
|
|
13
|
+
getDaysInMonth,
|
|
14
|
+
inDateRange,
|
|
15
|
+
isEndOfRange,
|
|
16
|
+
isStartDateEndDateSame,
|
|
17
|
+
isStartOfRange,
|
|
18
|
+
MARKERS,
|
|
19
|
+
NAVIGATION_ACTION,
|
|
20
|
+
WEEKDAYS,
|
|
21
|
+
} from './utils';
|
|
22
|
+
|
|
23
|
+
import css from './Calendar.module.css';
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
type CalendarProps = {
|
|
27
|
+
value: string,
|
|
28
|
+
marker: $Values<typeof MARKERS>,
|
|
29
|
+
hoverDay: string,
|
|
30
|
+
dateRange: DateRange,
|
|
31
|
+
inHoverRange: (day: string) => boolean,
|
|
32
|
+
handlers: {
|
|
33
|
+
onDayClick: (day: string) => void,
|
|
34
|
+
onDayHover: (day: string) => void,
|
|
35
|
+
onMonthNavigate: (
|
|
36
|
+
marker: $Values<typeof MARKERS>,
|
|
37
|
+
action: $Values<typeof NAVIGATION_ACTION>,
|
|
38
|
+
) => void,
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const getFormattedDate = (marker: string, dateRange: DateRange) => {
|
|
43
|
+
const {startDate, endDate} = dateRange;
|
|
44
|
+
switch (marker) {
|
|
45
|
+
case MARKERS.DATE_RANGE_START:
|
|
46
|
+
return startDate
|
|
47
|
+
? moment(startDate).format('MMMM D, YYYY')
|
|
48
|
+
: 'Start Date';
|
|
49
|
+
default:
|
|
50
|
+
return endDate ? moment(endDate).format('MMMM D, YYYY') : 'End Date';
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const Calendar = ({
|
|
55
|
+
value,
|
|
56
|
+
marker,
|
|
57
|
+
handlers,
|
|
58
|
+
hoverDay,
|
|
59
|
+
dateRange,
|
|
60
|
+
inHoverRange,
|
|
61
|
+
}: CalendarProps): React.Node => (
|
|
62
|
+
<div className={css.calendar}>
|
|
63
|
+
<SubTitleExtraSmall
|
|
64
|
+
className={css.selectedDate}
|
|
65
|
+
color={TEXT_COLORS.secondary}
|
|
66
|
+
>
|
|
67
|
+
{getFormattedDate(marker, dateRange)}
|
|
68
|
+
</SubTitleExtraSmall>
|
|
69
|
+
|
|
70
|
+
<div className={css.calendarRow}>
|
|
71
|
+
{WEEKDAYS.map((day) => (
|
|
72
|
+
<BodySmall
|
|
73
|
+
key={day}
|
|
74
|
+
className={css.calendarRowItem}
|
|
75
|
+
color={TEXT_COLORS.tertiary}
|
|
76
|
+
>
|
|
77
|
+
{day}
|
|
78
|
+
</BodySmall>
|
|
79
|
+
))}
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
{getDaysInMonth(value).map((week, index) => (
|
|
83
|
+
<div key={week[index]} className={css.calendarRow}>
|
|
84
|
+
{week.map((date) => {
|
|
85
|
+
const isStart = isStartOfRange(dateRange, date);
|
|
86
|
+
const isEnd = isEndOfRange(dateRange, date);
|
|
87
|
+
const isRangeValid = isStartDateEndDateSame(dateRange);
|
|
88
|
+
const highlighted =
|
|
89
|
+
inDateRange(dateRange, date) || inHoverRange(date);
|
|
90
|
+
return (
|
|
91
|
+
<Day
|
|
92
|
+
key={date}
|
|
93
|
+
date={date}
|
|
94
|
+
filled={isStart || isEnd}
|
|
95
|
+
onClick={() => handlers.onDayClick(date)}
|
|
96
|
+
onHover={() => handlers.onDayHover(date)}
|
|
97
|
+
outlined={moment(date).isSame(moment(), 'd')}
|
|
98
|
+
disabled={
|
|
99
|
+
moment(date).isAfter(formatIsoDate()) ||
|
|
100
|
+
!moment(date).isSame(moment(value), 'month')
|
|
101
|
+
}
|
|
102
|
+
endOfRange={isEnd && !isRangeValid}
|
|
103
|
+
highlighted={highlighted && !isRangeValid}
|
|
104
|
+
startOfRange={isStart && !isRangeValid}
|
|
105
|
+
value={moment(date).date()}
|
|
106
|
+
hoverDay={hoverDay}
|
|
107
|
+
/>
|
|
108
|
+
);
|
|
109
|
+
})}
|
|
110
|
+
</div>
|
|
111
|
+
))}
|
|
112
|
+
</div>
|
|
113
|
+
);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
@value (
|
|
2
|
+
size5,
|
|
3
|
+
size30
|
|
4
|
+
) from '../../styles/variables/_size.css';
|
|
5
|
+
@value (
|
|
6
|
+
spaceNone,
|
|
7
|
+
spaceSmall,
|
|
8
|
+
spaceLarge,
|
|
9
|
+
spaceFluid,
|
|
10
|
+
spaceXSmall,
|
|
11
|
+
spaceHalfFluid
|
|
12
|
+
) from '../../styles/variables/_space.css';
|
|
13
|
+
@value (
|
|
14
|
+
borderRadiusCircle
|
|
15
|
+
) from '../../styles/variables/_border.css';
|
|
16
|
+
|
|
17
|
+
.calendar {
|
|
18
|
+
display: flex;
|
|
19
|
+
flex-direction: column;
|
|
20
|
+
justify-content: flex-start;
|
|
21
|
+
width: spaceHalfFluid;
|
|
22
|
+
padding: spaceXSmall spaceLarge;
|
|
23
|
+
gap: spaceNone;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.calendarRow {
|
|
27
|
+
display: grid;
|
|
28
|
+
grid-template-columns: repeat(7, 1fr);
|
|
29
|
+
height: calc(size30 + size2);
|
|
30
|
+
box-sizing: border-box;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.calendarRowItem {
|
|
34
|
+
justify-content: center;
|
|
35
|
+
align-self: center;
|
|
36
|
+
width: spaceFluid;
|
|
37
|
+
padding: size5;
|
|
38
|
+
cursor: pointer;
|
|
39
|
+
border-radius: borderRadiusCircle;
|
|
40
|
+
box-sizing: border-box;
|
|
41
|
+
width: calc(size30 + size2);
|
|
42
|
+
height: calc(size30 + size2);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.selectedDate {
|
|
46
|
+
display: flex;
|
|
47
|
+
justify-content: center;
|
|
48
|
+
margin: spaceSmall spaceNone;
|
|
49
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.DateRangePicker = void 0;
|
|
7
|
+
var React = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _momentTimezone = _interopRequireDefault(require("moment-timezone"));
|
|
9
|
+
var _classify = _interopRequireDefault(require("../../utils/classify"));
|
|
10
|
+
var _DateRangeWrapper = require("./DateRangeWrapper");
|
|
11
|
+
var _utils = require("./utils");
|
|
12
|
+
var _DateRangePickerModule = _interopRequireDefault(require("./DateRangePicker.module.css"));
|
|
13
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
14
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
15
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
16
|
+
|
|
17
|
+
// $FlowFixMe[untyped-import]
|
|
18
|
+
|
|
19
|
+
const DateRangePicker = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
20
|
+
let {
|
|
21
|
+
onApply,
|
|
22
|
+
onCancel,
|
|
23
|
+
classNames,
|
|
24
|
+
initialDateRange
|
|
25
|
+
} = _ref;
|
|
26
|
+
const today = (0, _utils.formatIsoDate)();
|
|
27
|
+
let initialFirstMonth = (0, _utils.getSubtractedDate)(today, 1, 'M'),
|
|
28
|
+
initialSecondMonth = today,
|
|
29
|
+
initialRangeStart = '',
|
|
30
|
+
initialRangeEnd = '';
|
|
31
|
+
if (initialDateRange?.startDate && initialDateRange.endDate) {
|
|
32
|
+
initialRangeStart = initialFirstMonth = (0, _utils.formatIsoDate)((0, _momentTimezone.default)(initialDateRange.startDate));
|
|
33
|
+
initialRangeEnd = initialSecondMonth = (0, _utils.formatIsoDate)((0, _momentTimezone.default)(initialDateRange.endDate));
|
|
34
|
+
|
|
35
|
+
// If start and end dates are in the same current month, render them in the second calendar since next month isn't enabled yet.
|
|
36
|
+
if ((0, _momentTimezone.default)(initialRangeStart).isSame((0, _momentTimezone.default)(initialRangeEnd), 'M') && (0, _momentTimezone.default)(initialRangeStart).isSame((0, _momentTimezone.default)(today), 'M')) {
|
|
37
|
+
initialFirstMonth = (0, _utils.getSubtractedDate)(initialSecondMonth, 1, 'M');
|
|
38
|
+
} else {
|
|
39
|
+
initialSecondMonth = (0, _utils.getAddedDate)(initialFirstMonth, 1, 'M');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const [dateRange, setDateRange] = React.useState({
|
|
43
|
+
startDate: initialRangeStart,
|
|
44
|
+
endDate: initialRangeEnd
|
|
45
|
+
});
|
|
46
|
+
const [rangeStartMonth, setRangeStartMonth] = React.useState(initialFirstMonth);
|
|
47
|
+
const [rangeEndMonth, setRangeEndMonth] = React.useState(initialSecondMonth);
|
|
48
|
+
const [hoverDay, setHoverDay] = React.useState('');
|
|
49
|
+
const [timeZone, setTimeZone] = React.useState(_momentTimezone.default.tz.guess());
|
|
50
|
+
const {
|
|
51
|
+
startDate,
|
|
52
|
+
endDate
|
|
53
|
+
} = dateRange;
|
|
54
|
+
const setRangeStartMonthValidated = date => {
|
|
55
|
+
if ((0, _momentTimezone.default)(date).isBefore(rangeEndMonth)) {
|
|
56
|
+
setRangeStartMonth(date);
|
|
57
|
+
} else {
|
|
58
|
+
setRangeStartMonth((0, _utils.getSubtractedDate)(rangeEndMonth, 1, 'M'));
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const setRangeEndMonthValidated = date => {
|
|
62
|
+
if ((0, _momentTimezone.default)(date).isAfter(rangeStartMonth)) {
|
|
63
|
+
setRangeEndMonth(date);
|
|
64
|
+
} else {
|
|
65
|
+
setRangeEndMonth((0, _utils.getAddedDate)(rangeStartMonth, 1, 'M'));
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
const onDayClick = day => {
|
|
69
|
+
if (startDate && !endDate && (0, _momentTimezone.default)(day).isSameOrAfter(startDate)) {
|
|
70
|
+
setDateRange({
|
|
71
|
+
startDate,
|
|
72
|
+
endDate: day
|
|
73
|
+
});
|
|
74
|
+
} else {
|
|
75
|
+
setDateRange({
|
|
76
|
+
startDate: day,
|
|
77
|
+
endDate: undefined
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
setHoverDay(day);
|
|
81
|
+
};
|
|
82
|
+
const onMonthNavigate = (marker, action) => {
|
|
83
|
+
const [firstMonth, secondMonth] = marker === _utils.MARKERS.DATE_RANGE_START ? [rangeStartMonth, rangeEndMonth] : [rangeEndMonth, rangeStartMonth];
|
|
84
|
+
const newMonth = action === _utils.NAVIGATION_ACTION.NEXT ? (0, _utils.getAddedDate)(firstMonth, 1, 'M') : (0, _utils.getSubtractedDate)(firstMonth, 1, 'M');
|
|
85
|
+
const isRangeStartMonth = marker === _utils.MARKERS.DATE_RANGE_START;
|
|
86
|
+
const isBeforeCurrentMonth = (0, _momentTimezone.default)(newMonth).isBefore((0, _momentTimezone.default)());
|
|
87
|
+
const isValidMonth = isRangeStartMonth ? (0, _momentTimezone.default)(newMonth).isBefore((0, _momentTimezone.default)(secondMonth)) : (0, _momentTimezone.default)(secondMonth).isBefore((0, _momentTimezone.default)(newMonth));
|
|
88
|
+
if (isBeforeCurrentMonth && isValidMonth) {
|
|
89
|
+
isRangeStartMonth ? setRangeStartMonth(newMonth) : setRangeEndMonth(newMonth);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
const onDayHover = date => {
|
|
93
|
+
if (startDate && !endDate && (!hoverDay || date !== hoverDay)) {
|
|
94
|
+
setHoverDay(date);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
const inHoverRange = day => Boolean(startDate && !endDate && hoverDay && (0, _momentTimezone.default)(hoverDay).isAfter((0, _momentTimezone.default)(startDate)) && (0, _momentTimezone.default)(day).isBetween((0, _momentTimezone.default)(startDate), (0, _momentTimezone.default)(hoverDay)));
|
|
98
|
+
const handlers = {
|
|
99
|
+
onDayClick,
|
|
100
|
+
onDayHover,
|
|
101
|
+
onMonthNavigate
|
|
102
|
+
};
|
|
103
|
+
return /*#__PURE__*/React.createElement(_DateRangeWrapper.DateRangeWrapper, {
|
|
104
|
+
ref: ref,
|
|
105
|
+
onApply: onApply,
|
|
106
|
+
handlers: handlers,
|
|
107
|
+
hoverDay: hoverDay,
|
|
108
|
+
onCancel: onCancel,
|
|
109
|
+
timeZone: timeZone,
|
|
110
|
+
dateRange: dateRange,
|
|
111
|
+
rangeStartMonth: rangeStartMonth,
|
|
112
|
+
setTimeZone: setTimeZone,
|
|
113
|
+
rangeEndMonth: rangeEndMonth,
|
|
114
|
+
inHoverRange: inHoverRange,
|
|
115
|
+
setRangeStartMonth: setRangeStartMonthValidated,
|
|
116
|
+
setRangeEndMonth: setRangeEndMonthValidated,
|
|
117
|
+
cardWrapperClass: (0, _classify.default)(_DateRangePickerModule.default.container, classNames?.wrapper)
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
exports.DateRangePicker = DateRangePicker;
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
// @flow strict
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
// $FlowFixMe[untyped-import]
|
|
5
|
+
import moment from 'moment-timezone';
|
|
6
|
+
|
|
7
|
+
import classify from '../../utils/classify';
|
|
8
|
+
|
|
9
|
+
import {DateRangeWrapper} from './DateRangeWrapper';
|
|
10
|
+
import {
|
|
11
|
+
type DatePickerSelectedRange,
|
|
12
|
+
type DateRange,
|
|
13
|
+
formatIsoDate,
|
|
14
|
+
getAddedDate,
|
|
15
|
+
getSubtractedDate,
|
|
16
|
+
MARKERS,
|
|
17
|
+
NAVIGATION_ACTION,
|
|
18
|
+
} from './utils';
|
|
19
|
+
|
|
20
|
+
import css from './DateRangePicker.module.css';
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
type ClassNames = $ReadOnly<{wrapper?: string}>;
|
|
24
|
+
|
|
25
|
+
export type DateRangePickerProps = {
|
|
26
|
+
classNames?: ClassNames,
|
|
27
|
+
initialDateRange?: DateRange,
|
|
28
|
+
onApply: (datePickerSelectedRange: DatePickerSelectedRange) => void,
|
|
29
|
+
onCancel: () => void,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const DateRangePicker: React$AbstractComponent<
|
|
33
|
+
DateRangePickerProps,
|
|
34
|
+
HTMLDivElement,
|
|
35
|
+
> = React.forwardRef<DateRangePickerProps, HTMLDivElement>(
|
|
36
|
+
(
|
|
37
|
+
{onApply, onCancel, classNames, initialDateRange}: DateRangePickerProps,
|
|
38
|
+
ref,
|
|
39
|
+
): React.Node => {
|
|
40
|
+
const today = formatIsoDate();
|
|
41
|
+
|
|
42
|
+
let initialFirstMonth = getSubtractedDate(today, 1, 'M'),
|
|
43
|
+
initialSecondMonth = today,
|
|
44
|
+
initialRangeStart = '',
|
|
45
|
+
initialRangeEnd = '';
|
|
46
|
+
|
|
47
|
+
if (initialDateRange?.startDate && initialDateRange.endDate) {
|
|
48
|
+
initialRangeStart = initialFirstMonth = formatIsoDate(
|
|
49
|
+
moment(initialDateRange.startDate),
|
|
50
|
+
);
|
|
51
|
+
initialRangeEnd = initialSecondMonth = formatIsoDate(
|
|
52
|
+
moment(initialDateRange.endDate),
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
// If start and end dates are in the same current month, render them in the second calendar since next month isn't enabled yet.
|
|
56
|
+
if (
|
|
57
|
+
moment(initialRangeStart).isSame(moment(initialRangeEnd), 'M') &&
|
|
58
|
+
moment(initialRangeStart).isSame(moment(today), 'M')
|
|
59
|
+
) {
|
|
60
|
+
initialFirstMonth = getSubtractedDate(initialSecondMonth, 1, 'M');
|
|
61
|
+
} else {
|
|
62
|
+
initialSecondMonth = getAddedDate(initialFirstMonth, 1, 'M');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const [dateRange, setDateRange] = React.useState<DateRange>({
|
|
67
|
+
startDate: initialRangeStart,
|
|
68
|
+
endDate: initialRangeEnd,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const [rangeStartMonth, setRangeStartMonth] =
|
|
72
|
+
React.useState<string>(initialFirstMonth);
|
|
73
|
+
const [rangeEndMonth, setRangeEndMonth] =
|
|
74
|
+
React.useState<string>(initialSecondMonth);
|
|
75
|
+
|
|
76
|
+
const [hoverDay, setHoverDay] = React.useState<string>('');
|
|
77
|
+
const [timeZone, setTimeZone] = React.useState<string>(moment.tz.guess());
|
|
78
|
+
|
|
79
|
+
const {startDate, endDate} = dateRange;
|
|
80
|
+
|
|
81
|
+
const setRangeStartMonthValidated = (date: string) => {
|
|
82
|
+
if (moment(date).isBefore(rangeEndMonth)) {
|
|
83
|
+
setRangeStartMonth(date);
|
|
84
|
+
} else {
|
|
85
|
+
setRangeStartMonth(getSubtractedDate(rangeEndMonth, 1, 'M'));
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const setRangeEndMonthValidated = (date: string) => {
|
|
90
|
+
if (moment(date).isAfter(rangeStartMonth)) {
|
|
91
|
+
setRangeEndMonth(date);
|
|
92
|
+
} else {
|
|
93
|
+
setRangeEndMonth(getAddedDate(rangeStartMonth, 1, 'M'));
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const onDayClick = (day: string) => {
|
|
98
|
+
if (startDate && !endDate && moment(day).isSameOrAfter(startDate)) {
|
|
99
|
+
setDateRange({startDate, endDate: day});
|
|
100
|
+
} else {
|
|
101
|
+
setDateRange({startDate: day, endDate: undefined});
|
|
102
|
+
}
|
|
103
|
+
setHoverDay(day);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const onMonthNavigate = (
|
|
107
|
+
marker: $Values<typeof MARKERS>,
|
|
108
|
+
action: $Values<typeof NAVIGATION_ACTION>,
|
|
109
|
+
) => {
|
|
110
|
+
const [firstMonth, secondMonth] =
|
|
111
|
+
marker === MARKERS.DATE_RANGE_START
|
|
112
|
+
? [rangeStartMonth, rangeEndMonth]
|
|
113
|
+
: [rangeEndMonth, rangeStartMonth];
|
|
114
|
+
|
|
115
|
+
const newMonth =
|
|
116
|
+
action === NAVIGATION_ACTION.NEXT
|
|
117
|
+
? getAddedDate(firstMonth, 1, 'M')
|
|
118
|
+
: getSubtractedDate(firstMonth, 1, 'M');
|
|
119
|
+
|
|
120
|
+
const isRangeStartMonth = marker === MARKERS.DATE_RANGE_START;
|
|
121
|
+
const isBeforeCurrentMonth = moment(newMonth).isBefore(moment());
|
|
122
|
+
const isValidMonth = isRangeStartMonth
|
|
123
|
+
? moment(newMonth).isBefore(moment(secondMonth))
|
|
124
|
+
: moment(secondMonth).isBefore(moment(newMonth));
|
|
125
|
+
|
|
126
|
+
if (isBeforeCurrentMonth && isValidMonth) {
|
|
127
|
+
isRangeStartMonth
|
|
128
|
+
? setRangeStartMonth(newMonth)
|
|
129
|
+
: setRangeEndMonth(newMonth);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const onDayHover = (date: string) => {
|
|
134
|
+
if (startDate && !endDate && (!hoverDay || date !== hoverDay)) {
|
|
135
|
+
setHoverDay(date);
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const inHoverRange = (day: string): boolean =>
|
|
140
|
+
Boolean(
|
|
141
|
+
startDate &&
|
|
142
|
+
!endDate &&
|
|
143
|
+
hoverDay &&
|
|
144
|
+
moment(hoverDay).isAfter(moment(startDate)) &&
|
|
145
|
+
moment(day).isBetween(moment(startDate), moment(hoverDay)),
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
const handlers = {
|
|
149
|
+
onDayClick,
|
|
150
|
+
onDayHover,
|
|
151
|
+
onMonthNavigate,
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
return (
|
|
155
|
+
<DateRangeWrapper
|
|
156
|
+
ref={ref}
|
|
157
|
+
onApply={onApply}
|
|
158
|
+
handlers={handlers}
|
|
159
|
+
hoverDay={hoverDay}
|
|
160
|
+
onCancel={onCancel}
|
|
161
|
+
timeZone={timeZone}
|
|
162
|
+
dateRange={dateRange}
|
|
163
|
+
rangeStartMonth={rangeStartMonth}
|
|
164
|
+
setTimeZone={setTimeZone}
|
|
165
|
+
rangeEndMonth={rangeEndMonth}
|
|
166
|
+
inHoverRange={inHoverRange}
|
|
167
|
+
setRangeStartMonth={setRangeStartMonthValidated}
|
|
168
|
+
setRangeEndMonth={setRangeEndMonthValidated}
|
|
169
|
+
cardWrapperClass={classify(css.container, classNames?.wrapper)}
|
|
170
|
+
/>
|
|
171
|
+
);
|
|
172
|
+
},
|
|
173
|
+
);
|