@spaced-out/ui-design-system 0.1.93 → 0.1.94-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/lib/components/ChartWrapper/ChartWrapper.js +8 -2
  3. package/lib/components/ChartWrapper/ChartWrapper.js.flow +31 -15
  4. package/lib/components/ChartWrapper/ChartWrapper.module.css +8 -1
  5. package/lib/components/Charts/index.js +11 -0
  6. package/lib/components/Charts/index.js.flow +1 -0
  7. package/lib/components/ColumnChart/ColumnChart.js +2 -0
  8. package/lib/components/ColumnChart/ColumnChart.js.flow +9 -6
  9. package/lib/components/DateRangePicker/Calendar.js +7 -3
  10. package/lib/components/DateRangePicker/Calendar.js.flow +5 -3
  11. package/lib/components/DateRangePicker/DateRangePicker.js +23 -37
  12. package/lib/components/DateRangePicker/DateRangePicker.js.flow +53 -55
  13. package/lib/components/DateRangePicker/DateRangeWrapper.js +15 -10
  14. package/lib/components/DateRangePicker/DateRangeWrapper.js.flow +20 -16
  15. package/lib/components/DateRangePicker/Day.js +5 -7
  16. package/lib/components/DateRangePicker/Day.js.flow +4 -10
  17. package/lib/components/DateRangePicker/Day.module.css +7 -20
  18. package/lib/components/DateRangePicker/index.js.flow +1 -0
  19. package/lib/components/DateRangePicker/utils.js +87 -72
  20. package/lib/components/DateRangePicker/utils.js.flow +111 -103
  21. package/lib/components/DonutChart/DonutChart.js +5 -3
  22. package/lib/components/DonutChart/DonutChart.js.flow +6 -6
  23. package/lib/components/Dropdown/Dropdown.js +6 -0
  24. package/lib/components/Dropdown/Dropdown.js.flow +6 -0
  25. package/lib/components/Dropdown/SimpleDropdown.js +2 -0
  26. package/lib/components/Dropdown/SimpleDropdown.js.flow +4 -1
  27. package/lib/components/LineChart/LineChart.js +2 -0
  28. package/lib/components/LineChart/LineChart.js.flow +7 -4
  29. package/lib/components/Menu/Menu.js +48 -4
  30. package/lib/components/Menu/Menu.js.flow +79 -13
  31. package/lib/components/Menu/MenuOptionButton.js +3 -1
  32. package/lib/components/Menu/MenuOptionButton.js.flow +3 -0
  33. package/lib/components/SpiderChart/SpiderChart.js +2 -0
  34. package/lib/components/SpiderChart/SpiderChart.js.flow +5 -14
  35. package/lib/components/StickyBar/StickyBar.module.css +2 -2
  36. package/lib/types/charts.js.flow +47 -2
  37. package/lib/utils/charts/charts.js +8 -3
  38. package/lib/utils/charts/charts.js.flow +8 -3
  39. package/lib/utils/charts/donutChart.js +2 -7
  40. package/lib/utils/charts/donutChart.js.flow +2 -21
  41. package/package.json +3 -2
package/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
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.94-beta.1](https://github.com/spaced-out/ui-design-system/compare/v0.1.94-beta.0...v0.1.94-beta.1) (2024-05-13)
6
+
7
+
8
+ ### Features
9
+
10
+ * **charts:** added loading prop to handle loading state for charts ([#201](https://github.com/spaced-out/ui-design-system/issues/201)) ([3d41fc1](https://github.com/spaced-out/ui-design-system/commit/3d41fc1b4ab64b97e80c09ba29f6b664e1b15465))
11
+
12
+ ### [0.1.94-beta.0](https://github.com/spaced-out/ui-design-system/compare/v0.1.93...v0.1.94-beta.0) (2024-05-13)
13
+
14
+
15
+ ### Features
16
+
17
+ * [GDS-338, GDS-349, GDS-372] virtualization in Menu Component ([#178](https://github.com/spaced-out/ui-design-system/issues/178)) ([81e5c69](https://github.com/spaced-out/ui-design-system/commit/81e5c69064e64ef7d18b3f2c02eb92e1cded8bfe))
18
+
5
19
  ### [0.1.93](https://github.com/spaced-out/ui-design-system/compare/v0.1.93-beta.1...v0.1.93) (2024-05-08)
6
20
 
7
21
 
@@ -13,6 +13,7 @@ var _size = require("../../styles/variables/_size");
13
13
  var _classify = _interopRequireDefault(require("../../utils/classify"));
14
14
  var _ButtonDropdown = require("../ButtonDropdown");
15
15
  var _Card = require("../Card");
16
+ var _CircularLoader = require("../CircularLoader");
16
17
  var _ChartWrapperModule = _interopRequireDefault(require("./ChartWrapper.module.css"));
17
18
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18
19
  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); }
@@ -82,6 +83,7 @@ const CustomExportButton = /*#__PURE__*/React.forwardRef((_ref, ref) => {
82
83
  }
83
84
  };
84
85
  return /*#__PURE__*/React.createElement(_ButtonDropdown.ButtonDropdown, {
86
+ ariaLabel: "Export Chart Menu",
85
87
  menu: {
86
88
  isFluid: true,
87
89
  menuDisabled: false,
@@ -98,6 +100,7 @@ const CustomExportButton = /*#__PURE__*/React.forwardRef((_ref, ref) => {
98
100
  });
99
101
  const ChartWrapper = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
100
102
  let {
103
+ isLoading,
101
104
  title,
102
105
  children,
103
106
  classNames,
@@ -108,7 +111,10 @@ const ChartWrapper = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
108
111
  classNames: {
109
112
  wrapper: (0, _classify.default)(_ChartWrapperModule.default.wrapper, classNames?.wrapper)
110
113
  }
111
- }, /*#__PURE__*/React.createElement(_Card.CardHeader, {
114
+ }, isLoading ? /*#__PURE__*/React.createElement(_CircularLoader.CircularLoader, {
115
+ size: "large",
116
+ className: (0, _classify.default)(_ChartWrapperModule.default.loader, classNames?.loader)
117
+ }) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(_Card.CardHeader, {
112
118
  className: classNames?.header
113
119
  }, /*#__PURE__*/React.createElement(_Card.CardTitle, {
114
120
  className: classNames?.title
@@ -119,6 +125,6 @@ const ChartWrapper = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
119
125
  customExportOptions: customExportOptions
120
126
  }), headerActions ? headerActions : null)), /*#__PURE__*/React.createElement(_Card.CardContent, {
121
127
  className: (0, _classify.default)(_ChartWrapperModule.default.chartContent, classNames?.content)
122
- }, children));
128
+ }, children)));
123
129
  });
124
130
  exports.ChartWrapper = ChartWrapper;
@@ -14,6 +14,7 @@ import {size180} from '../../styles/variables/_size';
14
14
  import classify from '../../utils/classify';
15
15
  import {ANCHOR_POSITION_TYPE, ButtonDropdown} from '../ButtonDropdown';
16
16
  import {Card, CardActions, CardContent, CardHeader, CardTitle} from '../Card';
17
+ import {CircularLoader} from '../CircularLoader';
17
18
  import type {MenuOption} from '../Menu';
18
19
 
19
20
  import css from './ChartWrapper.module.css';
@@ -89,6 +90,7 @@ const CustomExportButton = React.forwardRef<
89
90
 
90
91
  return (
91
92
  <ButtonDropdown
93
+ ariaLabel="Export Chart Menu"
92
94
  menu={{
93
95
  isFluid: true,
94
96
  menuDisabled: false,
@@ -111,9 +113,11 @@ export type ChartWrapperClassNames = $ReadOnly<{
111
113
  title?: string,
112
114
  actions?: string,
113
115
  content?: string,
116
+ loader?: string,
114
117
  }>;
115
118
 
116
119
  type ChartWrapperProps = {
120
+ isLoading?: boolean,
117
121
  title: React.Node,
118
122
  children?: React.Node,
119
123
  classNames?: ChartWrapperClassNames,
@@ -127,6 +131,7 @@ export const ChartWrapper: React$AbstractComponent<
127
131
  > = React.forwardRef<ChartWrapperProps, HTMLDivElement>(
128
132
  (
129
133
  {
134
+ isLoading,
130
135
  title,
131
136
  children,
132
137
  classNames,
@@ -136,21 +141,32 @@ export const ChartWrapper: React$AbstractComponent<
136
141
  ref,
137
142
  ): React.Node => (
138
143
  <Card classNames={{wrapper: classify(css.wrapper, classNames?.wrapper)}}>
139
- <CardHeader className={classNames?.header}>
140
- <CardTitle className={classNames?.title}>{title}</CardTitle>
141
- <CardActions
142
- className={classify(css.chartCardActions, classNames?.actions)}
143
- >
144
- <CustomExportButton
145
- ref={ref}
146
- customExportOptions={customExportOptions}
147
- />
148
- {headerActions ? headerActions : null}
149
- </CardActions>
150
- </CardHeader>
151
- <CardContent className={classify(css.chartContent, classNames?.content)}>
152
- {children}
153
- </CardContent>
144
+ {isLoading ? (
145
+ <CircularLoader
146
+ size="large"
147
+ className={classify(css.loader, classNames?.loader)}
148
+ />
149
+ ) : (
150
+ <>
151
+ <CardHeader className={classNames?.header}>
152
+ <CardTitle className={classNames?.title}>{title}</CardTitle>
153
+ <CardActions
154
+ className={classify(css.chartCardActions, classNames?.actions)}
155
+ >
156
+ <CustomExportButton
157
+ ref={ref}
158
+ customExportOptions={customExportOptions}
159
+ />
160
+ {headerActions ? headerActions : null}
161
+ </CardActions>
162
+ </CardHeader>
163
+ <CardContent
164
+ className={classify(css.chartContent, classNames?.content)}
165
+ >
166
+ {children}
167
+ </CardContent>
168
+ </>
169
+ )}
154
170
  </Card>
155
171
  ),
156
172
  );
@@ -1,5 +1,5 @@
1
1
  @value (spaceXSmall) from '../../styles/variables/_space.css';
2
- @value (size960) from '../../styles/variables/_size.css';
2
+ @value (size4,size5,size50,size400,size960) from '../../styles/variables/_size.css';
3
3
 
4
4
  .wrapper {
5
5
  display: flex;
@@ -17,3 +17,10 @@
17
17
  overflow-x: auto;
18
18
  display: flex;
19
19
  }
20
+
21
+ .loader {
22
+ display: flex;
23
+ align-items: center;
24
+ justify-content: center;
25
+ height: calc(size4 + size5 + size50 + size400);
26
+ }
@@ -3,6 +3,17 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ var _charts = require("../../types/charts");
7
+ Object.keys(_charts).forEach(function (key) {
8
+ if (key === "default" || key === "__esModule") return;
9
+ if (key in exports && exports[key] === _charts[key]) return;
10
+ Object.defineProperty(exports, key, {
11
+ enumerable: true,
12
+ get: function () {
13
+ return _charts[key];
14
+ }
15
+ });
16
+ });
6
17
  var _ChartWrapper = require("../ChartWrapper");
7
18
  Object.keys(_ChartWrapper).forEach(function (key) {
8
19
  if (key === "default" || key === "__esModule") return;
@@ -1,5 +1,6 @@
1
1
  // @flow strict
2
2
 
3
+ export * from '../../types/charts';
3
4
  export * from '../ChartWrapper';
4
5
  export * from '../ColumnChart';
5
6
  export * from '../DonutChart';
@@ -21,6 +21,7 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
21
21
 
22
22
  const ColumnChart = _ref => {
23
23
  let {
24
+ isLoading,
24
25
  classNames,
25
26
  cardTitle,
26
27
  customExportOptions,
@@ -65,6 +66,7 @@ const ColumnChart = _ref => {
65
66
  ...wrapperClassNames
66
67
  } = classNames || {};
67
68
  return /*#__PURE__*/React.createElement(_ChartWrapper.ChartWrapper, {
69
+ isLoading: isLoading,
68
70
  title: cardTitle,
69
71
  ref: chartRef,
70
72
  classNames: wrapperClassNames,
@@ -6,7 +6,7 @@ import Highcharts from 'highcharts';
6
6
  //$FlowFixMe[untyped-import]
7
7
  import HighchartsReact from 'highcharts-react-official';
8
8
 
9
- import type {Drilldown} from '../../types/charts';
9
+ import type {DataOptionsType, Drilldown} from '../../types/charts';
10
10
  import {
11
11
  columnPlotWidth,
12
12
  getColumnChartOptions,
@@ -25,22 +25,24 @@ type ClassNames = $ReadOnly<{
25
25
  highChart?: string,
26
26
  }>;
27
27
 
28
- type ColumnSeriesItem = {
28
+ type ColumnSeries = {
29
29
  name: string,
30
- data: [],
30
+ data: DataOptionsType[],
31
31
  };
32
32
 
33
33
  export type ColumnChartProps = {
34
+ isLoading?: boolean,
34
35
  classNames?: ClassNames,
35
- cardTitle?: string,
36
+ cardTitle?: React.Node,
36
37
  customExportOptions?: Array<ExportOptionType> | null,
37
- series: Array<ColumnSeriesItem>,
38
- drilldown: Drilldown,
38
+ series: Array<ColumnSeries>,
39
+ drilldown?: Drilldown,
39
40
  headerActions?: React.Node,
40
41
  ...
41
42
  };
42
43
 
43
44
  export const ColumnChart = ({
45
+ isLoading,
44
46
  classNames,
45
47
  cardTitle,
46
48
  customExportOptions,
@@ -90,6 +92,7 @@ export const ColumnChart = ({
90
92
 
91
93
  return (
92
94
  <ChartWrapper
95
+ isLoading={isLoading}
93
96
  title={cardTitle}
94
97
  ref={chartRef}
95
98
  classNames={wrapperClassNames}
@@ -52,16 +52,20 @@ const Calendar = _ref => {
52
52
  key: week[index],
53
53
  className: _CalendarModule.default.calendarRow
54
54
  }, week.map(date => {
55
+ const isRangeValid = (0, _utils.isStartDateEndDateSame)(dateRange);
55
56
  const isStart = (0, _utils.isStartOfRange)(dateRange, date);
56
57
  const isEnd = (0, _utils.isEndOfRange)(dateRange, date);
57
- const isRangeValid = (0, _utils.isStartDateEndDateSame)(dateRange);
58
58
  const highlighted = (0, _utils.inDateRange)(dateRange, date) || inHoverRange(date);
59
+ const {
60
+ onDayClick,
61
+ onDayHover
62
+ } = handlers;
59
63
  return /*#__PURE__*/React.createElement(_Day.Day, {
60
64
  key: date,
61
65
  date: date,
62
66
  filled: isStart || isEnd,
63
- onClick: () => handlers.onDayClick(date),
64
- onHover: () => handlers.onDayHover(date),
67
+ onClick: () => onDayClick(date),
68
+ onHover: () => onDayHover(date),
65
69
  outlined: (0, _momentTimezone.default)(date).isSame((0, _momentTimezone.default)(), 'd'),
66
70
  disabled: (0, _momentTimezone.default)(date).isAfter((0, _utils.formatIsoDate)()) || !(0, _momentTimezone.default)(date).isSame((0, _momentTimezone.default)(value), 'month'),
67
71
  endOfRange: isEnd && !isRangeValid,
@@ -82,18 +82,20 @@ export const Calendar = ({
82
82
  {getDaysInMonth(value).map((week, index) => (
83
83
  <div key={week[index]} className={css.calendarRow}>
84
84
  {week.map((date) => {
85
+ const isRangeValid = isStartDateEndDateSame(dateRange);
85
86
  const isStart = isStartOfRange(dateRange, date);
86
87
  const isEnd = isEndOfRange(dateRange, date);
87
- const isRangeValid = isStartDateEndDateSame(dateRange);
88
88
  const highlighted =
89
89
  inDateRange(dateRange, date) || inHoverRange(date);
90
+ const {onDayClick, onDayHover} = handlers;
91
+
90
92
  return (
91
93
  <Day
92
94
  key={date}
93
95
  date={date}
94
96
  filled={isStart || isEnd}
95
- onClick={() => handlers.onDayClick(date)}
96
- onHover={() => handlers.onDayHover(date)}
97
+ onClick={() => onDayClick(date)}
98
+ onHover={() => onDayHover(date)}
97
99
  outlined={moment(date).isSame(moment(), 'd')}
98
100
  disabled={
99
101
  moment(date).isAfter(formatIsoDate()) ||
@@ -21,48 +21,37 @@ const DateRangePicker = /*#__PURE__*/React.forwardRef((_ref, ref) => {
21
21
  onApply,
22
22
  onCancel,
23
23
  classNames,
24
- initialDateRange
24
+ initialDateRange = {}
25
25
  } = _ref;
26
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);
27
+ const currentTimezone = _momentTimezone.default.tz.guess();
28
+ const {
29
+ dateRange: initialRange,
30
+ monthRange
31
+ } = (0, _utils.getInitialDates)(initialDateRange);
32
+ const [dateRange, setDateRange] = React.useState(initialRange);
33
+ const [timeZone, setTimeZone] = React.useState(currentTimezone);
34
+ const [rangeStartMonth, setRangeStartMonth] = React.useState(monthRange.rangeStartMonth);
35
+ const [rangeEndMonth, setRangeEndMonth] = React.useState(monthRange.rangeEndMonth);
48
36
  const [hoverDay, setHoverDay] = React.useState('');
49
- const [timeZone, setTimeZone] = React.useState(_momentTimezone.default.tz.guess());
50
37
  const {
51
38
  startDate,
52
39
  endDate
53
40
  } = dateRange;
54
41
  const setRangeStartMonthValidated = date => {
55
- if ((0, _momentTimezone.default)(date).isBefore(rangeEndMonth)) {
56
- setRangeStartMonth(date);
42
+ if ((0, _momentTimezone.default)(date).isBefore(rangeEndMonth) && (0, _momentTimezone.default)(date).isBefore(today)) {
43
+ setRangeStartMonth((0, _utils.getMonthStartDate)(date));
57
44
  } else {
58
- setRangeStartMonth((0, _utils.getSubtractedDate)(rangeEndMonth, 1, 'M'));
45
+ setRangeStartMonth((0, _utils.getMonthStartDate)((0, _utils.getSubtractedDate)(rangeEndMonth, 1, 'M')));
59
46
  }
60
47
  };
61
48
  const setRangeEndMonthValidated = date => {
62
- if ((0, _momentTimezone.default)(date).isAfter(rangeStartMonth)) {
63
- setRangeEndMonth(date);
49
+ if ((0, _momentTimezone.default)(date).isAfter(rangeStartMonth) && (0, _momentTimezone.default)(date).isBefore(today)) {
50
+ setRangeEndMonth((0, _utils.getMonthStartDate)(date));
51
+ } else if ((0, _momentTimezone.default)(date).isAfter(rangeStartMonth)) {
52
+ setRangeEndMonth((0, _utils.getMonthStartDate)(today));
64
53
  } else {
65
- setRangeEndMonth((0, _utils.getAddedDate)(rangeStartMonth, 1, 'M'));
54
+ setRangeEndMonth((0, _utils.getMonthStartDate)((0, _utils.getAddedDate)(rangeStartMonth, 1, 'M')));
66
55
  }
67
56
  };
68
57
  const onDayClick = day => {
@@ -73,15 +62,14 @@ const DateRangePicker = /*#__PURE__*/React.forwardRef((_ref, ref) => {
73
62
  });
74
63
  } else {
75
64
  setDateRange({
76
- startDate: day,
77
- endDate: undefined
65
+ startDate: day
78
66
  });
79
67
  }
80
68
  setHoverDay(day);
81
69
  };
82
70
  const onMonthNavigate = (marker, action) => {
83
71
  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');
72
+ const newMonth = action === _utils.NAVIGATION_ACTION.NEXT ? (0, _utils.getMonthStartDate)((0, _utils.getAddedDate)(firstMonth, 1, 'M')) : (0, _utils.getMonthStartDate)((0, _utils.getSubtractedDate)(firstMonth, 1, 'M'));
85
73
  const isRangeStartMonth = marker === _utils.MARKERS.DATE_RANGE_START;
86
74
  const isBeforeCurrentMonth = (0, _momentTimezone.default)(newMonth).isBefore((0, _momentTimezone.default)());
87
75
  const isValidMonth = isRangeStartMonth ? (0, _momentTimezone.default)(newMonth).isBefore((0, _momentTimezone.default)(secondMonth)) : (0, _momentTimezone.default)(secondMonth).isBefore((0, _momentTimezone.default)(newMonth));
@@ -89,12 +77,10 @@ const DateRangePicker = /*#__PURE__*/React.forwardRef((_ref, ref) => {
89
77
  isRangeStartMonth ? setRangeStartMonth(newMonth) : setRangeEndMonth(newMonth);
90
78
  }
91
79
  };
80
+ 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), null, '[]'));
92
81
  const onDayHover = date => {
93
- if (startDate && !endDate && (!hoverDay || date !== hoverDay)) {
94
- setHoverDay(date);
95
- }
82
+ setHoverDay(date);
96
83
  };
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
84
  const handlers = {
99
85
  onDayClick,
100
86
  onDayHover,
@@ -108,8 +94,8 @@ const DateRangePicker = /*#__PURE__*/React.forwardRef((_ref, ref) => {
108
94
  onCancel: onCancel,
109
95
  timeZone: timeZone,
110
96
  dateRange: dateRange,
111
- rangeStartMonth: rangeStartMonth,
112
97
  setTimeZone: setTimeZone,
98
+ rangeStartMonth: rangeStartMonth,
113
99
  rangeEndMonth: rangeEndMonth,
114
100
  inHoverRange: inHoverRange,
115
101
  setRangeStartMonth: setRangeStartMonthValidated,
@@ -7,11 +7,12 @@ import moment from 'moment-timezone';
7
7
  import classify from '../../utils/classify';
8
8
 
9
9
  import {DateRangeWrapper} from './DateRangeWrapper';
10
+ import type {DateRange, DateRangeWithTimezone} from './utils';
10
11
  import {
11
- type DatePickerSelectedRange,
12
- type DateRange,
13
12
  formatIsoDate,
14
13
  getAddedDate,
14
+ getInitialDates,
15
+ getMonthStartDate,
15
16
  getSubtractedDate,
16
17
  MARKERS,
17
18
  NAVIGATION_ACTION,
@@ -25,7 +26,7 @@ type ClassNames = $ReadOnly<{wrapper?: string}>;
25
26
  export type DateRangePickerProps = {
26
27
  classNames?: ClassNames,
27
28
  initialDateRange?: DateRange,
28
- onApply: (datePickerSelectedRange: DatePickerSelectedRange) => void,
29
+ onApply: (datePickerSelectedRange: DateRangeWithTimezone) => void,
29
30
  onCancel: () => void,
30
31
  };
31
32
 
@@ -34,63 +35,57 @@ export const DateRangePicker: React$AbstractComponent<
34
35
  HTMLDivElement,
35
36
  > = React.forwardRef<DateRangePickerProps, HTMLDivElement>(
36
37
  (
37
- {onApply, onCancel, classNames, initialDateRange}: DateRangePickerProps,
38
+ {
39
+ onApply,
40
+ onCancel,
41
+ classNames,
42
+ initialDateRange = {},
43
+ }: DateRangePickerProps,
38
44
  ref,
39
45
  ): React.Node => {
40
46
  const today = formatIsoDate();
47
+ const currentTimezone = moment.tz.guess();
41
48
 
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);
49
+ const {dateRange: initialRange, monthRange} =
50
+ getInitialDates(initialDateRange);
75
51
 
52
+ const [dateRange, setDateRange] = React.useState<DateRange>(initialRange);
53
+ const [timeZone, setTimeZone] = React.useState<string>(currentTimezone);
54
+ const [rangeStartMonth, setRangeStartMonth] = React.useState<string>(
55
+ monthRange.rangeStartMonth,
56
+ );
57
+ const [rangeEndMonth, setRangeEndMonth] = React.useState<string>(
58
+ monthRange.rangeEndMonth,
59
+ );
76
60
  const [hoverDay, setHoverDay] = React.useState<string>('');
77
- const [timeZone, setTimeZone] = React.useState<string>(moment.tz.guess());
78
61
 
79
62
  const {startDate, endDate} = dateRange;
80
63
 
81
64
  const setRangeStartMonthValidated = (date: string) => {
82
- if (moment(date).isBefore(rangeEndMonth)) {
83
- setRangeStartMonth(date);
65
+ if (
66
+ moment(date).isBefore(rangeEndMonth) &&
67
+ moment(date).isBefore(today)
68
+ ) {
69
+ setRangeStartMonth(getMonthStartDate(date));
84
70
  } else {
85
- setRangeStartMonth(getSubtractedDate(rangeEndMonth, 1, 'M'));
71
+ setRangeStartMonth(
72
+ getMonthStartDate(getSubtractedDate(rangeEndMonth, 1, 'M')),
73
+ );
86
74
  }
87
75
  };
88
76
 
89
77
  const setRangeEndMonthValidated = (date: string) => {
90
- if (moment(date).isAfter(rangeStartMonth)) {
91
- setRangeEndMonth(date);
78
+ if (
79
+ moment(date).isAfter(rangeStartMonth) &&
80
+ moment(date).isBefore(today)
81
+ ) {
82
+ setRangeEndMonth(getMonthStartDate(date));
83
+ } else if (moment(date).isAfter(rangeStartMonth)) {
84
+ setRangeEndMonth(getMonthStartDate(today));
92
85
  } else {
93
- setRangeEndMonth(getAddedDate(rangeStartMonth, 1, 'M'));
86
+ setRangeEndMonth(
87
+ getMonthStartDate(getAddedDate(rangeStartMonth, 1, 'M')),
88
+ );
94
89
  }
95
90
  };
96
91
 
@@ -98,7 +93,7 @@ export const DateRangePicker: React$AbstractComponent<
98
93
  if (startDate && !endDate && moment(day).isSameOrAfter(startDate)) {
99
94
  setDateRange({startDate, endDate: day});
100
95
  } else {
101
- setDateRange({startDate: day, endDate: undefined});
96
+ setDateRange({startDate: day});
102
97
  }
103
98
  setHoverDay(day);
104
99
  };
@@ -114,8 +109,8 @@ export const DateRangePicker: React$AbstractComponent<
114
109
 
115
110
  const newMonth =
116
111
  action === NAVIGATION_ACTION.NEXT
117
- ? getAddedDate(firstMonth, 1, 'M')
118
- : getSubtractedDate(firstMonth, 1, 'M');
112
+ ? getMonthStartDate(getAddedDate(firstMonth, 1, 'M'))
113
+ : getMonthStartDate(getSubtractedDate(firstMonth, 1, 'M'));
119
114
 
120
115
  const isRangeStartMonth = marker === MARKERS.DATE_RANGE_START;
121
116
  const isBeforeCurrentMonth = moment(newMonth).isBefore(moment());
@@ -130,21 +125,24 @@ export const DateRangePicker: React$AbstractComponent<
130
125
  }
131
126
  };
132
127
 
133
- const onDayHover = (date: string) => {
134
- if (startDate && !endDate && (!hoverDay || date !== hoverDay)) {
135
- setHoverDay(date);
136
- }
137
- };
138
-
139
128
  const inHoverRange = (day: string): boolean =>
140
129
  Boolean(
141
130
  startDate &&
142
131
  !endDate &&
143
132
  hoverDay &&
144
133
  moment(hoverDay).isAfter(moment(startDate)) &&
145
- moment(day).isBetween(moment(startDate), moment(hoverDay)),
134
+ moment(day).isBetween(
135
+ moment(startDate),
136
+ moment(hoverDay),
137
+ null,
138
+ '[]',
139
+ ),
146
140
  );
147
141
 
142
+ const onDayHover = (date: string) => {
143
+ setHoverDay(date);
144
+ };
145
+
148
146
  const handlers = {
149
147
  onDayClick,
150
148
  onDayHover,
@@ -160,8 +158,8 @@ export const DateRangePicker: React$AbstractComponent<
160
158
  onCancel={onCancel}
161
159
  timeZone={timeZone}
162
160
  dateRange={dateRange}
163
- rangeStartMonth={rangeStartMonth}
164
161
  setTimeZone={setTimeZone}
162
+ rangeStartMonth={rangeStartMonth}
165
163
  rangeEndMonth={rangeEndMonth}
166
164
  inHoverRange={inHoverRange}
167
165
  setRangeStartMonth={setRangeStartMonthValidated}