intelicoreact 0.0.4 → 0.0.8

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 (147) 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/DateTime/DateTime.stories.js +1 -1
  5. package/dist/Atomic/FormElements/Dropdown/Dropdown.js +64 -32
  6. package/dist/Atomic/FormElements/Dropdown/Dropdown.scss +26 -3
  7. package/dist/Atomic/FormElements/Dropdown/Dropdown.stories.js +40 -9
  8. package/dist/Atomic/FormElements/Input/Input.js +141 -97
  9. package/dist/Atomic/FormElements/Input/Input.scss +18 -15
  10. package/dist/Atomic/FormElements/Input/Input.stories.js +46 -29
  11. package/dist/Atomic/FormElements/InputCalendar/InputCalendar.js +89 -0
  12. package/dist/Atomic/FormElements/{Calendar/Calendar.stories.js → InputCalendar/InputCalendar.stories.js} +19 -20
  13. package/dist/Atomic/FormElements/InputDateRange/InputDateRange.js +234 -0
  14. package/dist/Atomic/FormElements/InputDateRange/InputDateRange.scss +626 -0
  15. package/dist/Atomic/FormElements/InputDateRange/InputDateRange.stories.js +91 -0
  16. package/dist/Atomic/FormElements/InputDateRange/components/Datepicker.js +491 -0
  17. package/dist/Atomic/FormElements/InputDateRange/components/OpenedPart.js +156 -0
  18. package/dist/Atomic/FormElements/InputDateRange/components/SelectItem.js +46 -0
  19. package/dist/Atomic/FormElements/InputDateRange/dependencies.js +249 -0
  20. package/dist/Atomic/FormElements/Label/Label.js +3 -10
  21. package/dist/Atomic/FormElements/Label/Label.scss +2 -0
  22. package/dist/Atomic/FormElements/Label/Label.stories.js +5 -4
  23. package/dist/Atomic/FormElements/Modal/Modal.stories.js +64 -18
  24. package/dist/Atomic/FormElements/NumericInput/NumericInput.js +254 -0
  25. package/dist/Atomic/FormElements/NumericInput/NumericInput.scss +135 -0
  26. package/dist/Atomic/FormElements/NumericInput/NumericInput.stories.js +121 -0
  27. package/dist/Atomic/FormElements/RangeCalendar/RangeCalendar.js +167 -0
  28. package/dist/Atomic/FormElements/RangeCalendar/RangeCalendar.scss +101 -0
  29. package/dist/Atomic/FormElements/RangeCalendar/RangeCalendar.stories.js +81 -0
  30. package/dist/Atomic/FormElements/Table/Table.scss +1 -1
  31. package/dist/Atomic/FormElements/Textarea/Textarea.scss +1 -1
  32. package/dist/Atomic/MainMenu/MainMenu.scss +2 -2
  33. package/dist/Atomic/UI/Accordion/Accordion.scss +2 -2
  34. package/dist/Atomic/UI/Arrow/Arrow.js +80 -0
  35. package/dist/Atomic/UI/Arrow/Arrow.scss +19 -0
  36. package/dist/Atomic/UI/Arrow/Arrow.stories.js +46 -0
  37. package/dist/Atomic/UI/Button/Button.js +4 -2
  38. package/dist/Atomic/UI/Button/Button.scss +26 -0
  39. package/dist/Atomic/UI/Button/Button.stories.js +2 -2
  40. package/dist/Atomic/UI/Calendar/Calendar.js +146 -0
  41. package/dist/Atomic/UI/Calendar/Calendar.scss +544 -0
  42. package/dist/Atomic/UI/Calendar/Calendar.stories.js +38 -0
  43. package/dist/Atomic/UI/Price/Price.js +1 -0
  44. package/dist/Atomic/UI/Status/Status.scss +1 -1
  45. package/dist/Constants/index.constants.js +8 -0
  46. package/dist/Functions/inputExecutor.js +58 -0
  47. package/dist/Functions/useClickOutside.js +25 -0
  48. package/dist/Functions/utils.js +10 -2
  49. package/dist/Molecular/Datepicker/Datepicker.js +451 -0
  50. package/dist/Molecular/Datepicker/Datepicker.scss +8 -0
  51. package/dist/Molecular/Datepicker/Datepicker.stories.js +44 -0
  52. package/dist/Molecular/Datepicker/components/Calendar.js +156 -0
  53. package/dist/Molecular/FormElements/FormElement.js +40 -0
  54. package/dist/Molecular/FormElements/FormElement.scss +8 -0
  55. package/dist/Molecular/FormElements/FormElement.stories.js +73 -0
  56. package/dist/scss/_vars.scss +3 -1
  57. package/dist/scss/main.scss +3 -3
  58. package/package.json +9 -4
  59. package/src/Atomic/FormElements/CheckboxInput/CheckboxInput.js +12 -2
  60. package/src/Atomic/FormElements/CheckboxInput/CheckboxInput.scss +91 -60
  61. package/src/Atomic/FormElements/CheckboxInput/CheckboxInput.stories.js +4 -3
  62. package/src/Atomic/FormElements/DateTime/DateTime.stories.js +1 -1
  63. package/src/Atomic/FormElements/Dropdown/Dropdown.js +57 -19
  64. package/src/Atomic/FormElements/Dropdown/Dropdown.scss +26 -3
  65. package/src/Atomic/FormElements/Dropdown/Dropdown.stories.js +37 -15
  66. package/src/Atomic/FormElements/Input/Input.js +136 -79
  67. package/src/Atomic/FormElements/Input/Input.scss +18 -15
  68. package/src/Atomic/FormElements/Input/Input.stories.js +48 -31
  69. package/src/Atomic/FormElements/InputCalendar/InputCalendar.js +43 -0
  70. package/src/Atomic/FormElements/InputCalendar/InputCalendar.stories.js +27 -0
  71. package/src/Atomic/FormElements/InputDateRange/InputDateRange.js +214 -0
  72. package/src/Atomic/FormElements/InputDateRange/InputDateRange.scss +626 -0
  73. package/src/Atomic/FormElements/InputDateRange/InputDateRange.stories.js +61 -0
  74. package/src/Atomic/FormElements/InputDateRange/components/Datepicker.js +412 -0
  75. package/src/Atomic/FormElements/InputDateRange/components/OpenedPart.js +114 -0
  76. package/src/Atomic/FormElements/InputDateRange/components/SelectItem.js +24 -0
  77. package/src/Atomic/FormElements/InputDateRange/dependencies.js +161 -0
  78. package/src/Atomic/FormElements/Label/Label.js +3 -4
  79. package/src/Atomic/FormElements/Label/Label.scss +2 -0
  80. package/src/Atomic/FormElements/Label/Label.stories.js +5 -4
  81. package/src/Atomic/FormElements/Modal/Modal.stories.js +60 -15
  82. package/src/Atomic/FormElements/NumericInput/NumericInput.js +220 -0
  83. package/src/Atomic/FormElements/NumericInput/NumericInput.scss +135 -0
  84. package/src/Atomic/FormElements/NumericInput/NumericInput.stories.js +94 -0
  85. package/src/Atomic/FormElements/RangeCalendar/RangeCalendar.js +146 -0
  86. package/src/Atomic/FormElements/RangeCalendar/RangeCalendar.scss +101 -0
  87. package/src/Atomic/FormElements/RangeCalendar/RangeCalendar.stories.js +54 -0
  88. package/src/Atomic/FormElements/Table/Table.scss +1 -1
  89. package/src/Atomic/FormElements/Textarea/Textarea.scss +1 -1
  90. package/src/Atomic/MainMenu/MainMenu.scss +2 -2
  91. package/src/Atomic/UI/Accordion/Accordion.scss +2 -2
  92. package/src/Atomic/UI/Arrow/Arrow.js +41 -0
  93. package/src/Atomic/UI/Arrow/Arrow.scss +19 -0
  94. package/src/Atomic/UI/Arrow/Arrow.stories.js +32 -0
  95. package/src/Atomic/UI/Button/Button.js +3 -3
  96. package/src/Atomic/UI/Button/Button.scss +26 -0
  97. package/src/Atomic/UI/Button/Button.stories.js +4 -3
  98. package/src/Atomic/{FormElements → UI}/Calendar/Calendar.js +26 -23
  99. package/src/Atomic/UI/Calendar/Calendar.scss +544 -0
  100. package/src/Atomic/UI/Calendar/Calendar.stories.js +24 -0
  101. package/src/Atomic/UI/Price/Price.js +1 -0
  102. package/src/Atomic/UI/Status/Status.scss +1 -1
  103. package/src/Constants/index.constants.js +41 -0
  104. package/src/Functions/inputExecutor.js +62 -0
  105. package/src/Functions/useClickOutside.js +15 -0
  106. package/src/Functions/utils.js +10 -1
  107. package/src/Molecular/Datepicker/Datepicker.js +346 -0
  108. package/src/Molecular/Datepicker/Datepicker.scss +8 -0
  109. package/src/Molecular/Datepicker/Datepicker.stories.js +27 -0
  110. package/src/Molecular/Datepicker/components/Calendar.js +118 -0
  111. package/src/Molecular/FormElements/FormElement.js +18 -0
  112. package/src/Molecular/FormElements/FormElement.scss +8 -0
  113. package/src/Molecular/FormElements/FormElement.stories.js +59 -0
  114. package/src/scss/_vars.scss +3 -1
  115. package/src/scss/main.scss +3 -3
  116. package/dist/Atomic/FormElements/Calendar/Calendar.js +0 -127
  117. package/dist/Atomic/FormElements/Calendar/Calendar.scss +0 -498
  118. package/dist/scss/anme/_anme-bootstrap-grid.scss +0 -748
  119. package/dist/scss/anme/_anme-elements.scss +0 -269
  120. package/dist/scss/anme/_anme-grid.scss +0 -111
  121. package/dist/scss/anme/_anme-justify.scss +0 -111
  122. package/dist/scss/anme/_anme-mixins-media.scss +0 -116
  123. package/dist/scss/anme/_anme-mixins.scss +0 -166
  124. package/dist/scss/anme/_anme-normalize.scss +0 -8
  125. package/dist/scss/anme/_anme-overall.scss +0 -34
  126. package/dist/scss/anme/_anme-padding-margins.scss +0 -419
  127. package/dist/scss/anme/_anme-table.scss +0 -81
  128. package/dist/scss/anme/_anme-theme.scss +0 -275
  129. package/dist/scss/anme/_anme-vars.scss +0 -91
  130. package/dist/scss/anme/_code-styling.scss +0 -23
  131. package/dist/scss/anme/styles.scss +0 -12
  132. package/src/Atomic/FormElements/Calendar/Calendar.scss +0 -498
  133. package/src/Atomic/FormElements/Calendar/Calendar.stories.js +0 -26
  134. package/src/scss/anme/_anme-bootstrap-grid.scss +0 -748
  135. package/src/scss/anme/_anme-elements.scss +0 -269
  136. package/src/scss/anme/_anme-grid.scss +0 -111
  137. package/src/scss/anme/_anme-justify.scss +0 -111
  138. package/src/scss/anme/_anme-mixins-media.scss +0 -116
  139. package/src/scss/anme/_anme-mixins.scss +0 -166
  140. package/src/scss/anme/_anme-normalize.scss +0 -8
  141. package/src/scss/anme/_anme-overall.scss +0 -34
  142. package/src/scss/anme/_anme-padding-margins.scss +0 -419
  143. package/src/scss/anme/_anme-table.scss +0 -81
  144. package/src/scss/anme/_anme-theme.scss +0 -275
  145. package/src/scss/anme/_anme-vars.scss +0 -91
  146. package/src/scss/anme/_code-styling.scss +0 -23
  147. package/src/scss/anme/styles.scss +0 -12
@@ -0,0 +1,41 @@
1
+
2
+ export const KEYBOARD_SERVICE_KEYS = [
3
+ 'Escape',
4
+ 'F1',
5
+ 'F2',
6
+ 'F3',
7
+ 'F4',
8
+ 'F5',
9
+ 'F6',
10
+ 'F7',
11
+ 'F8',
12
+ 'F9',
13
+ 'F10',
14
+ 'F11',
15
+ 'F12',
16
+ 'Tab',
17
+ 'CapsLock',
18
+ 'Shift',
19
+ 'Control',
20
+ 'Meta',
21
+ 'Option',
22
+ 'Alt',
23
+ 'ContextMenu',
24
+ 'ArrowLeft',
25
+ 'ArrowRight',
26
+ 'ArrowUp',
27
+ 'ArrowDown',
28
+ 'NumLock',
29
+ 'Backspace',
30
+ 'Delete',
31
+ 'Enter',
32
+ 'Return',
33
+ 'Insert',
34
+ 'Home',
35
+ 'End',
36
+ 'PageUp',
37
+ 'PageDown',
38
+ 'PrintScreen',
39
+ 'ScrollLock',
40
+ 'Pause'
41
+ ];
@@ -0,0 +1,62 @@
1
+ export const formatInput = {
2
+ priceInput: {
3
+ addCommas: (value) => {
4
+ value = value.toString();
5
+ const isFraction = value.includes('.');
6
+
7
+ const valueBeforeDot = isFraction
8
+ ? value.slice(0, value.indexOf('.'))
9
+ : value;
10
+
11
+ const intPart = valueBeforeDot
12
+ .split('')
13
+ .reverse()
14
+ .reduce(
15
+ (acc, item, idx) =>
16
+ idx % 3 === 0 && idx !== 0 ? [...acc, ',', item] : [...acc, item],
17
+ []
18
+ )
19
+ .reverse()
20
+ .join('');
21
+
22
+ return isFraction ? intPart + value.slice(value.indexOf('.')) : intPart;
23
+ },
24
+ removeComma: (value) => {
25
+ return parseFloat(value.toString().replace(/\,/g, ''));
26
+ }
27
+ },
28
+ onlyNumbers: (value, isDot = false) => {
29
+ const val =
30
+ value.slice(0, 1) !== '0' && value.slice(0, 1) !== '.'
31
+ ? value
32
+ : value.slice(1);
33
+ if (isDot) return twoDigitAfterDot(val.replace(/[^0-9.]/g, ''));
34
+ else return +val.toString().replace(/\D/g, '');
35
+ },
36
+ onlyString: (value) => {
37
+ return value.toString().replace(/[^a-z]/gi, '');
38
+ }
39
+ };
40
+
41
+ //обрезает числа после точки до 2х
42
+ // 342.23423432 -> 342.23
43
+ const twoDigitAfterDot = (value) => {
44
+ if (value.includes('.')) {
45
+ const valueAfterDot = value.slice(0, value.indexOf('.') + 3);
46
+ let rest = value.slice(value.indexOf('.') + 1, value.indexOf('.') + 3);
47
+
48
+ return allButTheFirstDotCutter(valueAfterDot);
49
+ } else {
50
+ return value;
51
+ }
52
+ };
53
+
54
+ //обрезает все точки кроме первой.
55
+ //для фомата "2 цифры после точки"
56
+ // нельзя = 123...
57
+ // можно 123.99
58
+ function allButTheFirstDotCutter(str) {
59
+ return str.replace(/^([^.]*\.)(.*)$/, function (a, b, c) {
60
+ return b + c.replace(/\./g, '');
61
+ });
62
+ }
@@ -0,0 +1,15 @@
1
+ import { useEffect } from 'react';
2
+
3
+ export const useClickOutside = (ref, setOut, open) => {
4
+ function handleClickOutside(event) {
5
+ if (ref.current && !ref.current.contains(event.target)) {
6
+ setOut(open);
7
+ }
8
+ }
9
+ useEffect(() => {
10
+ document.addEventListener('mousedown', handleClickOutside);
11
+ return () => {
12
+ document.removeEventListener('mousedown', handleClickOutside);
13
+ };
14
+ }, [ref]);
15
+ };
@@ -5,7 +5,10 @@ export const handleObjectChange =
5
5
  (data, prop = '', isNumber) => {
6
6
  let value;
7
7
  if (data?.target) {
8
- value = data.target.type === 'checkbox' ? data.target.checked : data.target.value;
8
+ value =
9
+ data.target.type === 'checkbox'
10
+ ? data.target.checked
11
+ : data.target.value;
9
12
  } else value = data;
10
13
 
11
14
  value = isNumber ? +value : value;
@@ -40,3 +43,9 @@ export const logout = () => {
40
43
  window.localStorage.removeItem('tokenExpires');
41
44
  window.location.reload();
42
45
  };
46
+
47
+ export const getStyles = (el, prop) => {
48
+ if (!el) return null;
49
+ if (!prop) return window.getComputedStyle(el);
50
+ return window.getComputedStyle(el).getPropertyValue(prop);
51
+ };
@@ -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;
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import cn from 'classnames';
3
+ import Label from '../../Atomic/FormElements/Label/Label';
4
+ import './FormElement.scss';
5
+
6
+ const RC = 'form-element';
7
+
8
+ const FormElement = ({ label, required, children, error, className, hint }) => {
9
+ return (
10
+ <div className={cn(className, RC)}>
11
+ {label && <Label className={`${RC}__label`} label={label} hint={hint} isRequired={required} />}
12
+ {children}
13
+ {error && <span className={`${RC}__error`}>{error}</span>}
14
+ </div>
15
+ );
16
+ };
17
+
18
+ export default FormElement;
@@ -0,0 +1,8 @@
1
+ .form-element__error {
2
+ margin-top: 2px;
3
+ margin-left: 1px;
4
+ position: absolute;
5
+ display: block;
6
+ font-size: 10px;
7
+ color: #f06d8d;
8
+ }