intelicoreact 0.0.64 → 0.0.72

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 (89) hide show
  1. package/dist/Atomic/FormElements/CheckboxInput/CheckboxInput.js +6 -2
  2. package/dist/Atomic/FormElements/CheckboxInput/CheckboxInput.scss +91 -60
  3. package/dist/Atomic/FormElements/CheckboxInput/CheckboxInput.stories.js +2 -1
  4. package/dist/Atomic/FormElements/Dropdown/Dropdown.js +48 -17
  5. package/dist/Atomic/FormElements/Dropdown/Dropdown.scss +21 -3
  6. package/dist/Atomic/FormElements/Dropdown/Dropdown.stories.js +22 -6
  7. package/dist/Atomic/FormElements/Input/Input.js +15 -4
  8. package/dist/Atomic/FormElements/Input/Input.stories.js +7 -1
  9. package/dist/Atomic/FormElements/InputDateRange/InputDateRange.js +17 -50
  10. package/dist/Atomic/FormElements/InputDateRange/InputDateRange.scss +98 -73
  11. package/dist/Atomic/FormElements/InputDateRange/InputDateRange.stories.js +5 -157
  12. package/dist/Atomic/FormElements/InputDateRange/components/Datepicker.js +17 -12
  13. package/dist/Atomic/FormElements/InputDateRange/components/OpenedPart.js +5 -3
  14. package/dist/Atomic/FormElements/InputDateRange/components/SelectItem.js +3 -3
  15. package/dist/Atomic/FormElements/InputDateRange/dependencies.js +7 -7
  16. package/dist/Atomic/FormElements/RangeCalendar/RangeCalendar.js +7 -2
  17. package/dist/Atomic/FormElements/Table/Table.scss +1 -1
  18. package/dist/Atomic/FormElements/Textarea/Textarea.scss +1 -1
  19. package/dist/Atomic/MainMenu/MainMenu.scss +2 -2
  20. package/dist/Atomic/UI/Accordion/Accordion.scss +2 -2
  21. package/dist/Atomic/UI/Arrow/Arrow.js +7 -8
  22. package/dist/Atomic/UI/Calendar/Calendar.js +3 -2
  23. package/dist/Atomic/UI/Calendar/Calendar.stories.js +3 -2
  24. package/dist/Atomic/UI/Status/Status.scss +1 -1
  25. package/dist/Molecular/Datepicker/Datepicker.js +451 -0
  26. package/dist/Molecular/Datepicker/Datepicker.scss +8 -0
  27. package/dist/Molecular/Datepicker/Datepicker.stories.js +44 -0
  28. package/dist/Molecular/Datepicker/components/Calendar.js +156 -0
  29. package/dist/scss/_vars.scss +3 -1
  30. package/dist/scss/main.scss +1 -1
  31. package/package.json +6 -4
  32. package/src/Atomic/FormElements/CheckboxInput/CheckboxInput.js +12 -2
  33. package/src/Atomic/FormElements/CheckboxInput/CheckboxInput.scss +91 -60
  34. package/src/Atomic/FormElements/CheckboxInput/CheckboxInput.stories.js +4 -3
  35. package/src/Atomic/FormElements/Dropdown/Dropdown.js +53 -19
  36. package/src/Atomic/FormElements/Dropdown/Dropdown.scss +21 -3
  37. package/src/Atomic/FormElements/Dropdown/Dropdown.stories.js +28 -15
  38. package/src/Atomic/FormElements/Input/Input.js +4 -0
  39. package/src/Atomic/FormElements/Input/Input.stories.js +7 -1
  40. package/src/Atomic/FormElements/InputDateRange/InputDateRange.js +187 -220
  41. package/src/Atomic/FormElements/InputDateRange/InputDateRange.scss +98 -73
  42. package/src/Atomic/FormElements/InputDateRange/InputDateRange.stories.js +35 -122
  43. package/src/Atomic/FormElements/InputDateRange/components/Datepicker.js +14 -8
  44. package/src/Atomic/FormElements/InputDateRange/components/OpenedPart.js +6 -4
  45. package/src/Atomic/FormElements/InputDateRange/components/SelectItem.js +1 -1
  46. package/src/Atomic/FormElements/InputDateRange/dependencies.js +6 -6
  47. package/src/Atomic/FormElements/RangeCalendar/RangeCalendar.js +5 -2
  48. package/src/Atomic/FormElements/Table/Table.scss +1 -1
  49. package/src/Atomic/FormElements/Textarea/Textarea.scss +1 -1
  50. package/src/Atomic/MainMenu/MainMenu.scss +2 -2
  51. package/src/Atomic/UI/Accordion/Accordion.scss +2 -2
  52. package/src/Atomic/UI/Arrow/Arrow.js +5 -5
  53. package/src/Atomic/UI/Calendar/Calendar.js +2 -2
  54. package/src/Atomic/UI/Calendar/Calendar.stories.js +2 -1
  55. package/src/Atomic/UI/Status/Status.scss +1 -1
  56. package/src/Molecular/Datepicker/Datepicker.js +346 -0
  57. package/src/Molecular/Datepicker/Datepicker.scss +8 -0
  58. package/src/Molecular/Datepicker/Datepicker.stories.js +27 -0
  59. package/src/Molecular/Datepicker/components/Calendar.js +118 -0
  60. package/src/scss/_vars.scss +3 -1
  61. package/src/scss/main.scss +1 -1
  62. package/dist/scss/anme/_anme-bootstrap-grid.scss +0 -748
  63. package/dist/scss/anme/_anme-elements.scss +0 -269
  64. package/dist/scss/anme/_anme-grid.scss +0 -111
  65. package/dist/scss/anme/_anme-justify.scss +0 -111
  66. package/dist/scss/anme/_anme-mixins-media.scss +0 -116
  67. package/dist/scss/anme/_anme-mixins.scss +0 -166
  68. package/dist/scss/anme/_anme-normalize.scss +0 -8
  69. package/dist/scss/anme/_anme-overall.scss +0 -34
  70. package/dist/scss/anme/_anme-padding-margins.scss +0 -419
  71. package/dist/scss/anme/_anme-table.scss +0 -81
  72. package/dist/scss/anme/_anme-theme.scss +0 -275
  73. package/dist/scss/anme/_anme-vars.scss +0 -91
  74. package/dist/scss/anme/_code-styling.scss +0 -23
  75. package/dist/scss/anme/styles.scss +0 -12
  76. package/src/scss/anme/_anme-bootstrap-grid.scss +0 -748
  77. package/src/scss/anme/_anme-elements.scss +0 -269
  78. package/src/scss/anme/_anme-grid.scss +0 -111
  79. package/src/scss/anme/_anme-justify.scss +0 -111
  80. package/src/scss/anme/_anme-mixins-media.scss +0 -116
  81. package/src/scss/anme/_anme-mixins.scss +0 -166
  82. package/src/scss/anme/_anme-normalize.scss +0 -8
  83. package/src/scss/anme/_anme-overall.scss +0 -34
  84. package/src/scss/anme/_anme-padding-margins.scss +0 -419
  85. package/src/scss/anme/_anme-table.scss +0 -81
  86. package/src/scss/anme/_anme-theme.scss +0 -275
  87. package/src/scss/anme/_anme-vars.scss +0 -91
  88. package/src/scss/anme/_code-styling.scss +0 -23
  89. package/src/scss/anme/styles.scss +0 -12
@@ -115,10 +115,9 @@ export const CUSTOM_INTERVAL_KEY_TEXT = 'Custom Date';
115
115
 
116
116
  export const getActualDateRange = inputDateRange => {
117
117
  const actualIntervalKey = (() => {
118
- if (inputDateRange.intervalKey && inputDateRange.intervalKey !== CUSTOM_INTERVAL_KEY) {
118
+ if (inputDateRange.intervalKey && Object.keys(INTERVALS).includes(inputDateRange.intervalKey)) {
119
119
  return inputDateRange.intervalKey;
120
- }
121
- if (inputDateRange.start && inputDateRange.end) {
120
+ } else if (inputDateRange.start && inputDateRange.end) {
122
121
  for (const [key, interval] of Object.entries(INTERVALS)) {
123
122
  if (
124
123
  moment(inputDateRange.start).isSame(interval.start()) &&
@@ -127,8 +126,9 @@ export const getActualDateRange = inputDateRange => {
127
126
  return key;
128
127
  }
129
128
  }
129
+ return CUSTOM_INTERVAL_KEY;
130
130
  }
131
- return null;
131
+ return ALL_TIME_KEY;
132
132
  })();
133
133
  if (actualIntervalKey === ALL_TIME_KEY) return {
134
134
  intervalKey: ALL_TIME_KEY,
@@ -144,11 +144,11 @@ export const getActualDateRange = inputDateRange => {
144
144
  start:
145
145
  inputDateRange.intervalKey === CUSTOM_INTERVAL_KEY
146
146
  ? inputDateRange?.start
147
- : INTERVALS[inputDateRange.intervalKey]?.start()?.toDate(),
147
+ : INTERVALS[inputDateRange.intervalKey]?.start()?.format('YYYY-MM-DDTHH:mm'),
148
148
  end:
149
149
  inputDateRange.intervalKey === CUSTOM_INTERVAL_KEY
150
150
  ? inputDateRange?.end
151
- : INTERVALS[inputDateRange.intervalKey]?.end()?.toDate(),
151
+ : INTERVALS[inputDateRange.intervalKey]?.end()?.format('YYYY-MM-DDTHH:mm'),
152
152
  compare: inputDateRange.compare,
153
153
  };
154
154
 
@@ -19,7 +19,8 @@ const RangeCalendar = props => {
19
19
  onHover = () => {},
20
20
  startPrevDate,
21
21
  endPrevDate,
22
- limitRange
22
+ limitRange,
23
+ isShortWeekNames
23
24
  } = props;
24
25
 
25
26
  const [days, setDays] = useState({});
@@ -100,6 +101,8 @@ const RangeCalendar = props => {
100
101
  setDate(moment(date).add(1, 'month').toDate());
101
102
  };
102
103
 
104
+ const getFormatedWeekName = input => isShortWeekNames ? input.charAt(0) : input;
105
+
103
106
  return (
104
107
  <div className={cn('range-calendar', className)}>
105
108
  <div className="range-calendar-header">
@@ -126,7 +129,7 @@ const RangeCalendar = props => {
126
129
  {[...Array(7).keys()].map(dayOfWeek => {
127
130
  return (
128
131
  <div key={`day-of-week_${dayOfWeek}`} className="range-calendar__day range-calendar__day--title">
129
- {moment().weekday(dayOfWeek).format('dd').charAt(0)}
132
+ {getFormatedWeekName(moment().weekday(dayOfWeek).format('dd'))}
130
133
  </div>
131
134
  );
132
135
  })}
@@ -1,4 +1,4 @@
1
- @import '../../../scss/anme/anme-vars';
1
+ @import '~anme/scss/anme-vars';
2
2
 
3
3
  .table-header {
4
4
  &--weight-actions {
@@ -1,5 +1,5 @@
1
1
  @import "../../../scss/vars";
2
- @import "../../../scss/anme/anme-mixins";
2
+ @import "~anme/scss/anme-mixins";
3
3
 
4
4
  .textarea {
5
5
  border: 1px solid #e2e5ec;
@@ -1,5 +1,5 @@
1
- @import "../../scss/anme/anme-vars";
2
- @import "../../scss/anme/anme-mixins";
1
+ @import "~anme/scss/anme-vars";
2
+ @import "~anme/scss/anme-mixins";
3
3
 
4
4
  .main-menu {
5
5
  display: flex;
@@ -1,5 +1,5 @@
1
- @import '../../../scss/anme/anme-vars';
2
- @import '../../../scss/anme/anme-mixins';
1
+ @import '~anme/scss/anme-vars';
2
+ @import '~anme/scss/anme-mixins';
3
3
 
4
4
  .accordion {
5
5
  &--item {
@@ -12,25 +12,25 @@ const Arrow = ({type, className, onClick, disabled}) => {
12
12
 
13
13
  useEffect(() => {
14
14
  if (ref.current) {
15
- setColor(getStyles(ref.current, 'color'));
15
+ //setColor(getStyles(ref.current, 'color'));
16
16
  };
17
17
  }, [ref.current]);
18
18
 
19
19
  return (
20
- <div
20
+ <div
21
21
  ref={ref}
22
22
  className={cn('arrow', `arrow_${type}`, className, {
23
23
  'arrow_disabled': disabled
24
24
  })}
25
25
  onClick={onClick} >
26
- {type !== 'right'
26
+ {type !== 'right'
27
27
  ? (
28
28
  <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
29
- <path d="M15 18L9 12L15 6" stroke={color} stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
29
+ <path d="M15 18L9 12L15 6" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
30
30
  </svg>
31
31
  ) : (
32
32
  <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
33
- <path d="M9 18L15 12L9 6" stroke={color} stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
33
+ <path d="M9 18L15 12L9 6" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
34
34
  </svg>
35
35
  )
36
36
  }
@@ -5,7 +5,7 @@ import { ChevronLeft, ChevronRight } from 'react-feather';
5
5
  import './Calendar.scss';
6
6
 
7
7
  export default function (props) {
8
- const { date, setDate, allowPrev = true, allowNext = true, params } = props;
8
+ const { date, setDate, allowPrev = true, allowNext = true, params, className } = props;
9
9
  const { minDate, maxDate } = params;
10
10
  const [days, setDays] = useState({});
11
11
  const [showDate, setShowDate] = useState(date);
@@ -70,7 +70,7 @@ export default function (props) {
70
70
  };
71
71
 
72
72
  return (
73
- <div className="calendar">
73
+ <div className={`calendar ${className}`}>
74
74
  <div className="calendar-header">
75
75
  <div className="calendar-header__prev">
76
76
  {allowPrev && (
@@ -4,7 +4,7 @@ import Calendar from './Calendar';
4
4
  global.lng = 'en';
5
5
 
6
6
  export default {
7
- title: 'UI/Calendar',
7
+ title: 'Calendar',
8
8
  component: Calendar,
9
9
  };
10
10
 
@@ -20,4 +20,5 @@ CalendarTemplate.args = {
20
20
  date: '12/03/2021',
21
21
  params: {},
22
22
  setDate: () => null,
23
+ className: ''
23
24
  };
@@ -1,4 +1,4 @@
1
- @import "../../../scss/anme/anme-vars";
1
+ @import "~anme/scss/anme-vars";
2
2
 
3
3
  .status {
4
4
  display: inline-flex;
@@ -0,0 +1,346 @@
1
+ import React, { useEffect, useMemo, useRef, useState } from 'react';
2
+ import { useClickOutside } from '../../Functions/useClickOutside';
3
+ import InputMask from 'react-input-mask';
4
+ import moment from 'moment';
5
+ import cn from 'classnames';
6
+
7
+ import Langs from '../../../../Langs';
8
+ import Button from '../../Atomic/UI/Button/Button';
9
+ import Calendar from './components/Calendar';
10
+
11
+ const padTime = (time) => {
12
+ return `${time.toString().padStart(2, '0')}:00`;
13
+ };
14
+
15
+ import './Datepicker.scss';
16
+ import Switcher from '../../Atomic/FormElements/Switcher/Switcher';
17
+ import Dropdown from '../../Atomic/FormElements/Dropdown/Dropdown';
18
+ import Input from '../../Atomic/FormElements/Input/Input';
19
+
20
+ const Datepicker = (props) => {
21
+ const { values = {}, onChange, onChangeCompare, onCancel, getSelectedMode = () => {}, onChangeInterval, isCompareHidden, limitRange } = props;
22
+ const { start = null, end = null, compare = false } = values;
23
+ const txt = Langs[global.lng];
24
+ const startDateInputRef = useRef(null);
25
+ const endDateInputRef = useRef(null);
26
+
27
+ const [startDate, setStartDate] = useState(start);
28
+ const [endDate, setEndDate] = useState(end);
29
+ const dateInterval = getSelectedMode({ start: startDate, end: endDate });
30
+
31
+ const [startDateInput, setStartDateInput] = useState(start);
32
+ const [endDateInput, setEndDateInput] = useState(end);
33
+ const [startHour, setStartHour] = useState(start ? moment(start).hour() : 0);
34
+ const [endHour, setEndHour] = useState(end ? moment(end).hour() : 0);
35
+ // eslint-disable-next-line no-unused-vars
36
+ const [isCompare, setIsCompare] = useState(compare);
37
+ const [date1, setDate1] = useState(start ? moment(start).toDate() : moment().subtract(1, 'month').toDate());
38
+ const [date2, setDate2] = useState(end ? moment(end).toDate() : moment().toDate());
39
+ const [isStartFocused, setIsStartFocused] = useState(false);
40
+ const [isEndFocused, setIsEndFocused] = useState(false);
41
+ const [hoverStatus, setHoverStatus] = useState(null);
42
+
43
+ const isNearby = useMemo(() => moment(date2).subtract(1, 'month').isSame(moment(date1), 'month'), [date1, date2]);
44
+
45
+ const isPreviousPeriodShowed = useMemo(() => isCompare && !isCompareHidden && startDate && endDate, [startDate, endDate, isCompare]);
46
+
47
+ const prevEndHour = useRef(endHour);
48
+
49
+ const getStartHourItems = () =>
50
+ [...Array(24).keys()].map((hour) => ({
51
+ label: padTime(hour),
52
+ value: hour,
53
+ disabled: moment(startDate).isSame(endDate, 'day') && endHour <= hour,
54
+ }));
55
+ const getEndHourItems = () =>
56
+ [...Array(24).keys()].map((hour) => ({
57
+ label: padTime(hour + 1),
58
+ value: hour === 23 ? 0 : hour + 1,
59
+ disabled:
60
+ (moment(startDate).isSame(endDate, 'day') || (moment(startDate).isSame(moment(endDate).subtract(1, 'days'), 'day') && endHour === 0)) &&
61
+ hour < startHour,
62
+ }));
63
+
64
+ const startPrevDate = useMemo(() => {
65
+ if (isPreviousPeriodShowed) {
66
+ const intervalHoursCount = moment(endDate).diff(startDate, 'hours');
67
+ return moment(startDate).subtract(intervalHoursCount, 'hours').toDate();
68
+ } else return null;
69
+ }, [startDate, endDate, isCompare]);
70
+
71
+ const endPrevDate = useMemo(() => {
72
+ if (isPreviousPeriodShowed) {
73
+ return startDate;
74
+ } else return null;
75
+ }, [startDate, endDate, isCompare]);
76
+
77
+ const title = useMemo(() => {
78
+ if (isCompare && !isCompareHidden && startDate && endDate) {
79
+ return `${moment(startPrevDate).format('ll')} (${moment(startPrevDate).format('HH:mm')}) - ${moment(endPrevDate).format('ll')} (${moment(
80
+ endPrevDate
81
+ ).format('HH:mm')})`;
82
+ } else return '';
83
+ }, [startDate, endDate, isCompare]);
84
+
85
+ const subtractDay = (date) => (endHour === 0 ? moment(date).subtract(1, 'days') : date);
86
+ const addDay = (date) => (endHour === 0 ? moment(date).add(1, 'days') : date);
87
+
88
+ useEffect(() => {
89
+ if (moment(startDate).isSameOrAfter(endDate)) {
90
+ setStartDate(moment(endDate).subtract(1, 'd').toDate());
91
+ setDate1(moment(endDate).subtract(1, 'd'));
92
+ }
93
+ }, [startDate]);
94
+
95
+ useEffect(() => {
96
+ if (moment(endDate).isSameOrBefore(startDate)) {
97
+ setEndDate(moment(startDate).add(1, 'd').toDate());
98
+ setDate2(moment(startDate).add(1, 'd'));
99
+ }
100
+ }, [endDate]);
101
+
102
+ useEffect(() => {
103
+ setStartDateInput(startDate);
104
+ setEndDateInput(endDate);
105
+ if (moment(startDate).isBefore(moment(endDate), 'month')) {
106
+ setDate1(moment(startDate));
107
+ setDate2(moment(endDate));
108
+ }
109
+ }, [startDate, endDate]);
110
+
111
+ useEffect(() => {
112
+ if (moment(date1).isSameOrAfter(moment(date2), 'month')) {
113
+ setDate1(moment(date2).subtract(1, 'month'));
114
+ }
115
+ }, [date1, date2]);
116
+
117
+ useEffect(() => {
118
+ onChangeInterval(dateInterval);
119
+ }, [dateInterval]);
120
+
121
+ const handleClick = (date) => {
122
+ prevEndHour.current = 0;
123
+ if (!startDate || (startDate && endDate && !(moment(startDate).add(1, 'd').isSame(endDate, 'day') && endHour === 0))) {
124
+ setStartDate(moment(date).startOf('day').toDate());
125
+ setEndDate(moment(date).add(1, 'd').startOf('day').toDate());
126
+ setStartHour(0);
127
+ setEndHour(0);
128
+ } else if (moment(date).isBefore(moment(startDate), 'day')) {
129
+ setEndDate(moment(startDate).add(1, 'd').startOf('day').toDate());
130
+ setStartDate(moment(date).set('hour', parseInt(startHour, 10)).toDate());
131
+ } else if (moment(date).isAfter(moment(startDate), 'day')) {
132
+ setEndDate(moment(date).add(1, 'd').startOf('day').toDate());
133
+ }
134
+ setHoverStatus(null);
135
+ };
136
+
137
+ let timerId;
138
+
139
+ const handleHover = (date) => {
140
+ if (!date) {
141
+ timerId = setTimeout(() => {
142
+ setHoverStatus(null);
143
+ }, 400);
144
+ return;
145
+ }
146
+ if (timerId) clearTimeout(timerId);
147
+ if (moment(startDate).add(1, 'd').isSame(endDate, 'day') && endHour === 0) {
148
+ if (moment(date).isAfter(moment(startDate), 'day')) setHoverStatus('end');
149
+ else if (moment(date).isBefore(moment(startDate), 'day')) setHoverStatus('start');
150
+ else setHoverStatus(null);
151
+ } else {
152
+ setHoverStatus('start');
153
+ }
154
+ };
155
+
156
+ const handleChangeStartHour = ({ target: { value: val } }) => {
157
+ setStartHour(+val);
158
+ setStartDate(
159
+ moment(startDate)
160
+ .set('hour', +val)
161
+ .toDate()
162
+ );
163
+ };
164
+
165
+ const handleChangeEndHour = ({ target: { value: val } }) => {
166
+ const newHour = +val;
167
+ setEndHour(newHour);
168
+ let newEndDate;
169
+ if (prevEndHour.current === 0 && newHour !== 0) {
170
+ newEndDate = moment(endDate).subtract(1, 'days');
171
+ } else if (prevEndHour.current !== 0 && newHour === 0) {
172
+ newEndDate = moment(endDate).add(1, 'days');
173
+ } else {
174
+ newEndDate = endDate;
175
+ }
176
+ prevEndHour.current = newHour;
177
+ setEndDate(moment(newEndDate).set('hour', newHour).toDate());
178
+ };
179
+
180
+ const renderButtons = () => (
181
+ <>
182
+ <Button className="plr15 mr5" onClick={() => onCancel()}>
183
+ {txt.buttons.cancel}
184
+ </Button>
185
+ <Button
186
+ className="plr20"
187
+ type="filled"
188
+ disabled={!startDate || !endDate}
189
+ onClick={() =>
190
+ onChange({
191
+ start: startDate,
192
+ end: endDate,
193
+ startPrevDate,
194
+ endPrevDate,
195
+ compare: isCompare,
196
+ })
197
+ }
198
+ >
199
+ {txt.buttons.apply}
200
+ </Button>
201
+ </>
202
+ );
203
+
204
+ const renderPreviousPeriod = () => (
205
+ <>
206
+ {txt.labels.previousPeriod}: <span className="date-picker__previous-period-interval">{title}</span>
207
+ </>
208
+ );
209
+
210
+ const handleStartDateFocus = () => {
211
+ setIsStartFocused(true);
212
+ setStartDateInput(moment(startDate).format('L'));
213
+ };
214
+
215
+ const handleStartDateBlur = () => {
216
+ let newDate;
217
+ if (moment(startDateInput).isValid()) {
218
+ newDate = moment(startDateInput).set('hour', parseInt(startHour, 10)).toDate();
219
+ setStartDate(newDate);
220
+ } else {
221
+ newDate = startDate;
222
+ setStartDateInput(newDate);
223
+ }
224
+ setIsStartFocused(false);
225
+ startDateInputRef.current.blur();
226
+ setDate1(moment(newDate).isSameOrAfter(moment(date2), 'month') ? moment(date2).subtract(1, 'month') : moment(newDate));
227
+ };
228
+
229
+ const handleEndDateFocus = () => {
230
+ setIsEndFocused(true);
231
+ setEndDateInput(moment(subtractDay(endDateInput)).format('L'));
232
+ };
233
+
234
+ const handleEndDateBlur = () => {
235
+ let newDate;
236
+ if (moment(endDateInput).isValid()) {
237
+ newDate = moment(endDateInput).set('hour', parseInt(endHour, 10)).toDate();
238
+ setEndDate(addDay(newDate));
239
+ } else {
240
+ newDate = endDate;
241
+ setEndDateInput(newDate);
242
+ }
243
+ setIsEndFocused(false);
244
+ endDateInputRef.current.blur();
245
+ setDate2(newDate);
246
+ setEndDateInput();
247
+ };
248
+
249
+ const handleKeyPressed = (e, handleDateBlur) => {
250
+ if (e.key === 'Enter') handleDateBlur();
251
+ };
252
+
253
+ return (
254
+ <div className="date-picker">
255
+ <div className="date-picker__header">
256
+ <Input
257
+ dataTest="datepicker_start-date-input"
258
+ className={cn('mr5', { 'date-picker-text-input--active': hoverStatus === 'start' })}
259
+ value={isStartFocused ? startDateInput : moment(startDate).format('ll')}
260
+ disabled={!startDate}
261
+ onChange={(e) => setStartDateInput(e.target.value)}
262
+ onFocus={handleStartDateFocus}
263
+ onBlur={handleStartDateBlur}
264
+ onKeyPress={(e) => handleKeyPressed(e, handleStartDateBlur)}
265
+ ref={startDateInputRef}
266
+ />
267
+ <Dropdown
268
+ dataTest="datepicker_start-hour-select-input"
269
+ onChange={handleChangeStartHour}
270
+ value={startHour}
271
+ items={getStartHourItems()}
272
+ disabled={!startDate}
273
+ short
274
+ />
275
+ <div className="pl5 pr5 date-picker__header--gray">—</div>
276
+ <Input
277
+ dataTest="datepicker_end-date-input"
278
+ className={cn('mr5', { 'date-picker-text-input--active': hoverStatus === 'end' })}
279
+ value={isEndFocused ? endDateInput : moment(subtractDay(endDate)).format('ll')}
280
+ disabled={!endDate}
281
+ onChange={(e) => setEndDateInput(e.target.value)}
282
+ onFocus={handleEndDateFocus}
283
+ onBlur={handleEndDateBlur}
284
+ onKeyPress={(e) => handleKeyPressed(e, handleEndDateBlur)}
285
+ ref={endDateInputRef}
286
+ />
287
+ <Dropdown
288
+ dataTest="datepicker_end-hour-select-input"
289
+ onChange={handleChangeEndHour}
290
+ value={endHour}
291
+ items={getEndHourItems()}
292
+ disabled={!endDate}
293
+ short
294
+ />
295
+ </div>
296
+ <div className="date-picker__previous-period">{isCompare && !isCompareHidden && startDate && endDate && renderPreviousPeriod()}</div>
297
+ <div className="date-picker__calendars">
298
+ <Calendar
299
+ date={date1}
300
+ setDate={setDate1}
301
+ allowNext={!isNearby}
302
+ startDate={startDate}
303
+ endDate={endDate}
304
+ startPrevDate={startPrevDate}
305
+ endPrevDate={endPrevDate}
306
+ onClick={handleClick}
307
+ onHover={handleHover}
308
+ limitRange={limitRange}
309
+ />
310
+ <Calendar
311
+ date={date2}
312
+ setDate={setDate2}
313
+ allowPrev={!isNearby}
314
+ startDate={startDate}
315
+ endDate={endDate}
316
+ startPrevDate={startPrevDate}
317
+ endPrevDate={endPrevDate}
318
+ onClick={handleClick}
319
+ onHover={handleHover}
320
+ />
321
+ </div>
322
+ <div className="date-picker__footer j46">
323
+ {!isCompareHidden ? (
324
+ <div className="j4">
325
+ <div className="mr5">
326
+ <Switcher
327
+ dataTest="datepicker_compare"
328
+ label={txt.labels.compare}
329
+ isSwitchOn={isCompare}
330
+ onChange={() => {
331
+ onChangeCompare(!isCompare);
332
+ setIsCompare((state) => !state);
333
+ }}
334
+ />
335
+ </div>
336
+ </div>
337
+ ) : (
338
+ <div />
339
+ )}
340
+ <div>{renderButtons()}</div>
341
+ </div>
342
+ </div>
343
+ );
344
+ };
345
+
346
+ export default Datepicker;
@@ -0,0 +1,8 @@
1
+ .test {
2
+ width: 380px;
3
+ }
4
+
5
+ .testing {
6
+ border: none;
7
+ box-shadow: none;
8
+ }
@@ -0,0 +1,27 @@
1
+ import React, { useRef, useState } from 'react';
2
+ import { ref } from 'yup';
3
+ import Datepicker from './Datepicker';
4
+
5
+ global.lng = 'en';
6
+
7
+ // export default {
8
+ // title: 'Form Elements/Datepicker',
9
+ // component: Datepicker,
10
+ // };
11
+
12
+ const Template = (args) => {
13
+ const params = {
14
+ minDate: args?.minDate,
15
+ maxDate: args?.maxDate,
16
+ };
17
+
18
+ return <Datepicker data={args.date} params={params} />;
19
+ };
20
+
21
+ export const DatepickerTemplate = Template.bind({});
22
+
23
+ DatepickerTemplate.args = {
24
+ date: '10/14/2021',
25
+ minDate: '10/11/2021',
26
+ maxDate: '10/25/2021',
27
+ };
@@ -0,0 +1,118 @@
1
+ import cn from 'classnames';
2
+ import moment from 'moment';
3
+ import React, { useEffect, useMemo, useState } from 'react';
4
+ import * as Icon from 'react-feather';
5
+
6
+ const Calendar = (props) => {
7
+ const { date, setDate, startDate, endDate, allowPrev = true, allowNext = true, onClick, onHover, startPrevDate, endPrevDate, limitRange } = props;
8
+
9
+ const [days, setDays] = useState({});
10
+
11
+ const title = useMemo(() => `${moment(date).format('MMM')} ${moment(date).format('YYYY')}`, [date]);
12
+
13
+ useEffect(() => {
14
+ const result = {};
15
+ const day = moment(date).startOf('month');
16
+ const daysInMonth = day.daysInMonth();
17
+ for (let d = 0; d < daysInMonth; d += 1) {
18
+ let week = day.week();
19
+ if (day.month() === 11 && week === 1) week = 53;
20
+ if (day.month() === 0 && week === 53) week = 0;
21
+ if (!Object.prototype.hasOwnProperty.call(result, week)) {
22
+ result[week] = {};
23
+ }
24
+ result[week][day.weekday()] = { date: day.toDate() };
25
+ day.add(1, 'd');
26
+ }
27
+ setDays(result);
28
+ }, [date]);
29
+
30
+ const renderDay = (week, dayOfWeek) => {
31
+ const day = days[week][dayOfWeek];
32
+ const isFutureDay = day && moment(day.date).isAfter(moment(), 'day');
33
+ const isPastDay = limitRange ? day && moment(day.date).isBefore(moment().subtract(limitRange, 'days'), 'day') : null;
34
+ const isRangeEnd = day && (moment(day.date).isSame(startDate, 'day') || moment(day.date).isSame(moment(endDate).subtract(1, 'hour'), 'day'));
35
+ const isRangeInside =
36
+ day &&
37
+ startDate &&
38
+ endDate &&
39
+ moment(day.date).isAfter(startDate, 'day') &&
40
+ moment(day.date).isBefore(moment(endDate).subtract(1, 'hour'), 'day');
41
+ const isPrevRangeEnd =
42
+ day && (moment(day.date).isSame(startPrevDate, 'day') || moment(day.date).isSame(moment(endPrevDate).subtract(1, 'day'), 'day'));
43
+ const isPrevRangeInside =
44
+ day &&
45
+ startPrevDate &&
46
+ endPrevDate &&
47
+ moment(day.date).isAfter(startPrevDate, 'day') &&
48
+ moment(day.date).isBefore(moment(endPrevDate).subtract(1, 'day'), 'day');
49
+ const classNames = cn(
50
+ 'calendar__day',
51
+ { 'calendar__day--clickable': day },
52
+ { 'calendar__day--disabled': isFutureDay },
53
+ { 'calendar__day--disabled': isPastDay },
54
+ { 'calendar__day--range-end': isRangeEnd },
55
+ { 'calendar__day--range-inside': isRangeInside },
56
+ { 'calendar__day--prev-range-end': isPrevRangeEnd },
57
+ { 'calendar__day--prev-range-inside': isPrevRangeInside }
58
+ );
59
+
60
+ return (
61
+ <div
62
+ key={`${week}_${dayOfWeek}`}
63
+ className={classNames}
64
+ onClick={day && !isFutureDay ? () => onClick(day.date) : null}
65
+ onMouseOver={day && !isFutureDay ? () => onHover(day.date) : null}
66
+ onMouseLeave={() => onHover(null)}
67
+ >
68
+ {day && day.date.getDate()}
69
+ </div>
70
+ );
71
+ };
72
+
73
+ const handlePrev = () => {
74
+ setDate(moment(date).subtract(1, 'month').toDate());
75
+ };
76
+
77
+ const handleNext = () => {
78
+ setDate(moment(date).add(1, 'month').toDate());
79
+ };
80
+
81
+ return (
82
+ <div className="calendar">
83
+ <div className="calendar-header">
84
+ <div className="calendar-header__prev">
85
+ {allowPrev && (
86
+ <div onClick={handlePrev}>
87
+ <Icon.ChevronLeft size={16} />
88
+ </div>
89
+ )}
90
+ </div>
91
+ <div className="calendar-header__title">{title}</div>
92
+ <div className="calendar-header__next">
93
+ {allowNext && (
94
+ <div onClick={handleNext}>
95
+ <Icon.ChevronRight size={16} />
96
+ </div>
97
+ )}
98
+ </div>
99
+ </div>
100
+ <div className="calendar__week">
101
+ {[...Array(7).keys()].map((dayOfWeek) => {
102
+ return (
103
+ <div key={`day-of-week_${dayOfWeek}`} className="calendar__day calendar__day--title">
104
+ {moment().weekday(dayOfWeek).format('dd').charAt(0)}
105
+ </div>
106
+ );
107
+ })}
108
+ </div>
109
+ {Object.keys(days).map((week, index) => (
110
+ <div key={`week_${index}`} className="calendar__week">
111
+ {[...Array(7).keys()].map((dayOfWeek) => renderDay(week, dayOfWeek))}
112
+ </div>
113
+ ))}
114
+ </div>
115
+ );
116
+ };
117
+
118
+ export default Calendar;