intelicoreact 0.0.86 → 0.0.92

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 (35) hide show
  1. package/dist/Atomic/FormElements/Dropdown/Dropdown.js +44 -19
  2. package/dist/Atomic/FormElements/Dropdown/Dropdown.scss +12 -0
  3. package/dist/Atomic/FormElements/Dropdown/Dropdown.stories.js +35 -7
  4. package/dist/Atomic/FormElements/Dropdown/components/DropdownLoader.js +24 -0
  5. package/dist/Atomic/FormElements/Dropdown/components/Loader.scss +57 -0
  6. package/dist/Atomic/FormElements/Input/Input.js +30 -10
  7. package/dist/Atomic/FormElements/InputCalendar/InputCalendar.js +6 -4
  8. package/dist/Atomic/FormElements/InputCalendar/InputCalendar.stories.js +3 -2
  9. package/dist/Atomic/FormElements/InputDateRange/InputDateRange.js +8 -2
  10. package/dist/Atomic/FormElements/InputDateRange/InputDateRange.stories.js +2 -0
  11. package/dist/Atomic/FormElements/InputDateRange/components/Datepicker.js +35 -20
  12. package/dist/Atomic/FormElements/InputDateRange/components/OpenedPart.js +8 -2
  13. package/dist/Atomic/FormElements/InputDateRange/dependencies.js +1 -1
  14. package/dist/Atomic/FormElements/NumericInput/NumericInput.js +1 -0
  15. package/dist/Atomic/UI/Calendar/Calendar.js +89 -15
  16. package/dist/Atomic/UI/Calendar/Calendar.scss +52 -5
  17. package/dist/Atomic/UI/Calendar/Calendar.stories.js +20 -3
  18. package/package.json +1 -2
  19. package/src/Atomic/FormElements/Dropdown/Dropdown.js +72 -35
  20. package/src/Atomic/FormElements/Dropdown/Dropdown.scss +12 -0
  21. package/src/Atomic/FormElements/Dropdown/Dropdown.stories.js +23 -8
  22. package/src/Atomic/FormElements/Dropdown/components/DropdownLoader.js +17 -0
  23. package/src/Atomic/FormElements/Dropdown/components/Loader.scss +57 -0
  24. package/src/Atomic/FormElements/Input/Input.js +46 -33
  25. package/src/Atomic/FormElements/InputCalendar/InputCalendar.js +14 -8
  26. package/src/Atomic/FormElements/InputCalendar/InputCalendar.stories.js +7 -8
  27. package/src/Atomic/FormElements/InputDateRange/InputDateRange.js +5 -0
  28. package/src/Atomic/FormElements/InputDateRange/InputDateRange.stories.js +2 -0
  29. package/src/Atomic/FormElements/InputDateRange/components/Datepicker.js +41 -20
  30. package/src/Atomic/FormElements/InputDateRange/components/OpenedPart.js +5 -1
  31. package/src/Atomic/FormElements/InputDateRange/dependencies.js +1 -1
  32. package/src/Atomic/FormElements/NumericInput/NumericInput.js +1 -0
  33. package/src/Atomic/UI/Calendar/Calendar.js +80 -11
  34. package/src/Atomic/UI/Calendar/Calendar.scss +52 -5
  35. package/src/Atomic/UI/Calendar/Calendar.stories.js +9 -7
@@ -29,7 +29,7 @@ const Input = ({
29
29
  icon,
30
30
  symbolsLimit,
31
31
  blinkTime,
32
- isFocusDefault = false
32
+ isFocusDefault = false,
33
33
  }) => {
34
34
  const DEFAULT_BLINK_TIME = 100;
35
35
  // STATES
@@ -42,6 +42,8 @@ const Input = ({
42
42
 
43
43
  const { onlyNumbers, onlyString } = formatInput;
44
44
  const { addCommas, removeComma } = formatInput.priceInput;
45
+ const isUseErrorsBlink = !isNotBlinkErrors && !mask;
46
+
45
47
  // HANDLES
46
48
  const handle = {
47
49
  change: (e) => {
@@ -50,8 +52,7 @@ const Input = ({
50
52
  inputValue = inputValue.substring(0, +symbolsLimit);
51
53
  }
52
54
 
53
- if (isOnlyNumber && !isTwoDigitAfterDot)
54
- inputValue = onlyNumbers(inputValue);
55
+ if (isOnlyNumber && !isTwoDigitAfterDot) inputValue = onlyNumbers(inputValue);
55
56
  if (isTwoDigitAfterDot) inputValue = onlyNumbers(inputValue, true);
56
57
  if (isOnlyString) inputValue = onlyString(inputValue);
57
58
 
@@ -79,28 +80,47 @@ const Input = ({
79
80
  if (onBlur) onBlur(e);
80
81
  },
81
82
  keyUp: (e) => {
82
- if (!isNotBlinkErrors) {
83
+ if (isUseErrorsBlink) {
83
84
  const changedValue = '' + (value ?? '');
84
85
  const previousValue = '' + (previousValueRef.current ?? '');
85
- const currentSet = (() => {
86
- if (previousValue.length < changedValue.length)
87
- return value.slice(previousValue.length - changedValue.length);
88
- else return changedValue.includes(e.key) ? e.key : '';
89
- })();
90
-
91
- if (
92
- !KEYBOARD_SERVICE_KEYS.includes(e.key) &&
93
- changedValue === previousValue
94
- )
95
- setIsAttemptToChange(true);
96
-
97
- if (KEYBOARD_SERVICE_KEYS.includes(e.key) || !currentSet)
98
- previousValueRef.current = value;
99
- else previousValueRef.current = previousValue + currentSet[0];
86
+
87
+ const short = previousValue.length <= changedValue.length ? previousValue : changedValue;
88
+ const long = previousValue.length > changedValue.length ? previousValue : changedValue;
89
+
90
+ const infoAboutDifferencesSameness = short.split('').reduce(
91
+ (acc, symbol, idx) => {
92
+ if (acc.countOn && symbol === long[idx]) acc.same.push(symbol);
93
+ else {
94
+ acc.countOn = false;
95
+ acc.differences.push([idx, symbol]);
96
+ }
97
+ return acc;
98
+ },
99
+ { same: [], countOn: true, differences: [] }
100
+ );
101
+
102
+ const samePart = infoAboutDifferencesSameness.same.join('');
103
+ const differencesLength = infoAboutDifferencesSameness.differences.length;
104
+ const currentSet = changedValue.replace(samePart, '');
105
+
106
+ const getNext = (inputPartToAdd, correctedSamePart) => {
107
+ const partToAdd = inputPartToAdd || currentSet;
108
+ const currentSamePart = correctedSamePart || samePart;
109
+ return changedValue.includes(e.key) && e.key !== changedValue[changedValue.length - 1]
110
+ ? currentSamePart + (partToAdd[0] || '')
111
+ : changedValue;
112
+ };
113
+
114
+ if (!KEYBOARD_SERVICE_KEYS.includes(e.key) && changedValue === previousValue)
115
+ setIsAttemptToChange(!(!differencesLength && e.key === changedValue[changedValue.length - 2]));
116
+
117
+ if (!previousValueRef.current || KEYBOARD_SERVICE_KEYS.includes(e.key)) previousValueRef.current = getNext();
118
+ else if (changedValue === samePart) previousValueRef.current = getNext(changedValue, changedValue.slice(0, -1));
119
+ else previousValueRef.current = getNext();
100
120
  }
101
121
 
102
122
  if (onKeyUp) onKeyUp(e.keyCode, e);
103
- }
123
+ },
104
124
  };
105
125
 
106
126
  function cutOffsingleDot(value) {
@@ -121,7 +141,7 @@ const Input = ({
121
141
  onBlur: handle.blur,
122
142
  onKeyUp: handle.keyUp,
123
143
  ...(maskChar ? { maskChar } : {}),
124
- ...(formatChars ? { formatChars } : {})
144
+ ...(formatChars ? { formatChars } : {}),
125
145
  };
126
146
 
127
147
  function renderInput() {
@@ -129,13 +149,11 @@ const Input = ({
129
149
  return <InputMask {...uniProps} ref={inputRef} mask={mask} />;
130
150
  }
131
151
 
132
- return (
133
- <input {...uniProps} ref={inputRef} type={isPriceInput ? 'text' : type} />
134
- );
152
+ return <input {...uniProps} ref={inputRef} type={isPriceInput ? 'text' : type} />;
135
153
  }
136
154
 
137
155
  useEffect(() => {
138
- if (!isNotBlinkErrors && isAttemptToChange) {
156
+ if (isUseErrorsBlink && isAttemptToChange) {
139
157
  setIsAttemptToChange(null);
140
158
  setIsToHighlightError(true);
141
159
  setTimeout(() => {
@@ -145,8 +163,8 @@ const Input = ({
145
163
  }, [isAttemptToChange]);
146
164
 
147
165
  useEffect(() => {
148
- if (inputRef?.current && typeof isFocusDefault === 'boolean')
149
- setIsFocused(isFocusDefault);
166
+ if (inputRef?.current && typeof isFocusDefault === 'boolean') setIsFocused(isFocusDefault);
167
+ setEditing(isFocusDefault);
150
168
  }, [inputRef, isFocusDefault]);
151
169
 
152
170
  return (
@@ -160,12 +178,7 @@ const Input = ({
160
178
  >
161
179
  {renderInput()}
162
180
  {icon}
163
- {withDelete && (
164
- <span
165
- className={cn(`input__close`, { hidden: !value })}
166
- onClick={handle.toggleEdit}
167
- />
168
- )}
181
+ {withDelete && <span className={cn(`input__close`, { hidden: !value })} onClick={handle.toggleEdit} />}
169
182
  </div>
170
183
  );
171
184
  };
@@ -4,27 +4,27 @@ import InputMask from 'react-input-mask';
4
4
  import Calendar from '../../UI/Calendar/Calendar';
5
5
  import { useClickOutside } from '../../../Functions/useClickOutside';
6
6
 
7
- const InputCalendar = ({ value, minDate, maxDate, onChange, className = '', placeholder = 'mm/dd/yyyy', mask = '99/99/9999' }) => {
7
+ const InputCalendar = ({ value, minDate, maxDate, onChange, className = '', placeholder = 'mm/dd/yyyy', mask = '99/99/9999', dontLimitFuture }) => {
8
8
  const [isOpened, setIsOpened] = useState(false);
9
9
  const calendarRef = useRef(null);
10
10
 
11
11
  useClickOutside(calendarRef, () => setIsOpened(false));
12
12
 
13
- const changeInputValue = val => {
13
+ const changeInputValue = (val) => {
14
14
  if (onChange) onChange(val);
15
15
  };
16
16
 
17
- const changeCalendarDay = val => {
17
+ const changeCalendarDay = (val) => {
18
18
  if (onChange) onChange(val);
19
19
  };
20
20
 
21
21
  const getCalendarValue = (value) => {
22
22
  const date = moment(value).format('L');
23
23
 
24
- if(date !== "Invalid date") return date;
24
+ if (date !== 'Invalid date') return date;
25
25
 
26
26
  return moment(new Date()).format('L');
27
- }
27
+ };
28
28
 
29
29
  return (
30
30
  <div className={`input__wrap calendar-container ${className}`} ref={calendarRef}>
@@ -32,12 +32,18 @@ const InputCalendar = ({ value, minDate, maxDate, onChange, className = '', plac
32
32
  mask={mask}
33
33
  placeholder={placeholder}
34
34
  value={value}
35
- onChange={e => changeInputValue(e.target.value)}
35
+ onChange={(e) => changeInputValue(e.target.value)}
36
36
  className="calendar-dropdown"
37
37
  onFocus={() => setIsOpened(!isOpened)}
38
38
  />
39
- {console.log(value, getCalendarValue(value))}
40
- {isOpened ? <Calendar date={getCalendarValue(value)} setDate={newDate => changeCalendarDay(newDate)} params={{ minDate, maxDate }} /> : null}
39
+ {isOpened ? (
40
+ <Calendar
41
+ date={getCalendarValue(value)}
42
+ setDate={(newDate) => changeCalendarDay(newDate)}
43
+ params={{ minDate, maxDate }}
44
+ dontLimitFuture={dontLimitFuture}
45
+ />
46
+ ) : null}
41
47
  </div>
42
48
  );
43
49
  };
@@ -3,28 +3,27 @@ import InputCalendar from './InputCalendar';
3
3
 
4
4
  global.lng = 'en';
5
5
 
6
-
7
6
  export default {
8
7
  title: 'Form Elements/Input Calendar',
9
8
  component: InputCalendar,
10
9
  argTypes: {
11
10
  value: {
12
- description: 'string (mm.dd.yyyy)'
11
+ description: 'string (mm.dd.yyyy)',
13
12
  },
14
- }
13
+ },
15
14
  };
16
15
 
17
- const Template = args => {
16
+ const Template = (args) => {
18
17
  const [date, setDate] = useState('');
19
18
 
20
- return <InputCalendar {...args} value={date} onChange={val => setDate(val)} />;
19
+ return <InputCalendar {...args} value={date} onChange={(val) => setDate(val)} />;
21
20
  };
22
21
 
23
22
  export const CalendarTemplate = Template.bind({});
24
23
 
25
24
  CalendarTemplate.args = {
26
25
  value: '',
27
- minDate: '10/14/2020',
28
- maxDate: '10/14/2022',
29
-
26
+ // minDate: '10/14/2020',
27
+ // maxDate: '10/14/2022',
28
+ dontLimitFuture: true,
30
29
  };
@@ -24,6 +24,8 @@ const InputDateRange = props => {
24
24
  hideArrows = false,
25
25
  isOptionsRight,
26
26
  isUseAbs,
27
+ minDate = null,
28
+ maxDate = null,
27
29
  } = props;
28
30
 
29
31
  const actualValues = getActualDateRange(value);
@@ -35,6 +37,7 @@ const InputDateRange = props => {
35
37
  const internalContainerRef = useRef(null);
36
38
 
37
39
  const handleChange = input => {
40
+
38
41
  const newValue = getActualDateRange(input);
39
42
  const formatedValue = {
40
43
  intervalKey: newValue.intervalKey,
@@ -202,6 +205,8 @@ const InputDateRange = props => {
202
205
  setIsCompare={setIsCompare}
203
206
  toggleOff={toggleOff}
204
207
  onChange={handleChange}
208
+ minDate={minDate ? moment(minDate) : null}
209
+ maxDate={maxDate ? moment(maxDate) : null}
205
210
  />
206
211
  )}
207
212
  </div>
@@ -47,6 +47,8 @@ InputDateRangeTemplate.args = {
47
47
  error: false,
48
48
  disabled: false,
49
49
  isHoverable: false,
50
+ minDate: "",
51
+ maxDate: "",
50
52
  // short: true,
51
53
  isCompact: false,
52
54
  // isFocused: true,
@@ -41,7 +41,9 @@ const Datepicker = props => {
41
41
  limitRange,
42
42
  handleItemClick,
43
43
  setActiveInterval,
44
- isShortWeekNames
44
+ isShortWeekNames,
45
+ minDate = null,
46
+ maxDate = null
45
47
  } = props;
46
48
  const { start = null, end = null, compare = false } = values;
47
49
  const startDateInputRef = useRef(null);
@@ -191,7 +193,7 @@ const Datepicker = props => {
191
193
  const handleChangeStartHour = val => {
192
194
  setStartHour(+val);
193
195
  setStartDate(
194
- moment(startDate)
196
+ moment(startDate || moment())
195
197
  .set('hour', +val)
196
198
  .toDate(),
197
199
  );
@@ -200,14 +202,16 @@ const Datepicker = props => {
200
202
  const handleChangeEndHour = val => {
201
203
  const newHour = +val;
202
204
  setEndHour(newHour);
203
- let newEndDate;
204
- if (prevEndHour.current === 0 && newHour !== 0) {
205
- newEndDate = moment(endDate).subtract(1, 'days');
206
- } else if (prevEndHour.current !== 0 && newHour === 0) {
207
- newEndDate = moment(endDate).add(1, 'days');
208
- } else {
209
- newEndDate = endDate;
205
+ let newEndDate = moment();
206
+
207
+ if(endDate){
208
+ if (prevEndHour.current === 0 && newHour !== 0) {
209
+ newEndDate = moment(endDate).subtract(1, 'days');
210
+ } else if (prevEndHour.current !== 0 && newHour === 0) {
211
+ newEndDate = moment(endDate).add(1, 'days');
212
+ }
210
213
  }
214
+
211
215
  prevEndHour.current = newHour;
212
216
  setEndDate(moment(newEndDate).set('hour', newHour).toDate());
213
217
  };
@@ -256,13 +260,22 @@ const Datepicker = props => {
256
260
 
257
261
  const handleStartDateBlur = e => {
258
262
  let newDate;
259
- if (moment(startDateInput).isValid()) {
260
- newDate = moment(startDateInput).set('hour', parseInt(startHour, 10)).toDate();
261
- setStartDate(newDate);
263
+
264
+ if(!moment(startDateInput).isValid()){
265
+ newDate = startDate;
262
266
  } else {
263
- newDate = startDate;
264
- setStartDateInput(newDate);
267
+ if(minDate && !moment(startDateInput).isSameOrAfter(minDate)){
268
+ newDate = minDate;
269
+ } else if(maxDate && !moment(startDateInput).isSameOrBefore(maxDate)){
270
+ newDate = maxDate;
271
+ } else {
272
+ newDate = moment(startDateInput);
273
+ }
265
274
  }
275
+
276
+ setStartDateInput(newDate);
277
+ setStartDate(newDate.set('hour', parseInt(startHour, 10)).toDate());
278
+
266
279
  doBlur('start', e);
267
280
  setDate1(
268
281
  moment(newDate).isSameOrAfter(moment(date2), 'month') ? moment(date2).subtract(1, 'month') : moment(newDate),
@@ -277,16 +290,24 @@ const Datepicker = props => {
277
290
 
278
291
  const handleEndDateBlur = e => {
279
292
  let newDate;
280
- if (moment(endDateInput).isValid()) {
281
- newDate = moment(endDateInput).set('hour', parseInt(endHour, 10)).toDate();
282
- setEndDate(addDay(newDate));
293
+
294
+ if(!moment(endDateInput).isValid()){
295
+ newDate = endDate;
283
296
  } else {
284
- newDate = endDate;
285
- setEndDateInput(newDate);
297
+ if(minDate && !moment(endDateInput).isSameOrAfter(minDate)){
298
+ newDate = minDate;
299
+ } else if(maxDate && !moment(endDateInput).isSameOrBefore(maxDate)){
300
+ newDate = maxDate;
301
+ } else {
302
+ newDate = moment(endDateInput);
303
+ }
286
304
  }
305
+
306
+ setEndDate(addDay(newDate.set('hour', parseInt(endHour, 10)).toDate()));
307
+ setEndDateInput(newDate);
308
+
287
309
  doBlur('end', e);
288
310
  setDate2(newDate);
289
- setEndDateInput();
290
311
  };
291
312
 
292
313
  const handleKeyPressed = (code, e, type) => {
@@ -25,7 +25,9 @@ const OpenedPart = React.forwardRef((props, ref) => {
25
25
  isCompare,
26
26
  setIsCompare,
27
27
  toggleOff,
28
- isShortWeekNames
28
+ isShortWeekNames,
29
+ minDate = null,
30
+ maxDate = null
29
31
  } = props;
30
32
 
31
33
  const items = isCompact ? [...Object.keys(intervals)] : [...Object.keys(intervals), customKey];
@@ -105,6 +107,8 @@ const OpenedPart = React.forwardRef((props, ref) => {
105
107
  limitRange={limitRange}
106
108
  setActiveInterval={setActiveInterval}
107
109
  isShortWeekNames={isShortWeekNames}
110
+ minDate={minDate}
111
+ maxDate={maxDate}
108
112
  />
109
113
  )}
110
114
  </div>
@@ -89,7 +89,7 @@ export const INTERVALS = {
89
89
  end: () => moment().startOf('month'),
90
90
  },
91
91
  last6Months: {
92
- label: 'Last 6 Months',
92
+ label: '6 Months',
93
93
  start: () => moment().subtract(6, 'month').startOf('month'),
94
94
  end: () => moment().startOf('month'),
95
95
  },
@@ -192,6 +192,7 @@ const NumericInput = ({
192
192
  useEffect(() => {
193
193
  if (inputRef?.current && typeof isFocusDefault === 'boolean')
194
194
  setIsFocused(isFocusDefault);
195
+ setEditing(isFocusDefault)
195
196
  }, [inputRef, isFocusDefault]);
196
197
 
197
198
  function renderInput() {
@@ -1,22 +1,34 @@
1
+ import React, { useEffect, useMemo, useState, useRef } from 'react';
1
2
  import cn from 'classnames';
2
- import React, { useEffect, useMemo, useState } from 'react';
3
3
  import moment from 'moment';
4
+ import InputMask from 'react-input-mask';
4
5
  import { ChevronLeft, ChevronRight } from 'react-feather';
5
6
  import './Calendar.scss';
6
7
 
7
8
  export default function (props) {
8
- const { date, setDate, allowPrev = true, allowNext = true, params, className } = props;
9
- const { minDate = '01/01/1900', maxDate = moment().format('MM/DD/YYYY') } = params;
9
+ const { date, setDate, allowPrev = true, allowNext = true, params, className, dontLimitFuture } = props;
10
+ // const { minDate = '01/01/1900', maxDate = moment().format('MM/DD/YYYY') } = params;
11
+ const { minDate, maxDate } = params;
10
12
  const [days, setDays] = useState({});
11
13
  const [showDate, setShowDate] = useState(date);
14
+ const [isChangeYear, setIsChangeYear] = useState(false);
15
+ const [inputYearValue, setInputYearValue] = useState(moment(showDate).format('YYYY'));
16
+ const yearInputRef = useRef(null);
12
17
 
13
18
  const selectedDay = moment(showDate);
14
19
  const isError = 'Invalid date';
15
20
 
16
- const title = useMemo(
17
- () => (selectedDay.format('MMM') === isError ? isError : `${selectedDay.format('MMM')} ${moment(showDate).format('YYYY')}`),
18
- [date, showDate]
19
- );
21
+ // const title = useMemo(
22
+ // () => (selectedDay.format('MMM') === isError ? isError : `${selectedDay.format('MMM')} ${moment(showDate).format('YYYY')}`),
23
+ // [date, showDate]
24
+ // );
25
+
26
+ const showMonth = useMemo(() => moment(showDate).format('MMM'), [date, showDate]);
27
+ const showYear = useMemo(() => moment(showDate).format('YYYY'), [date, showDate]);
28
+
29
+ console.log('date - ', date);
30
+ console.log('showDate - ', showDate);
31
+
20
32
  useEffect(() => {
21
33
  const result = {};
22
34
  const day = selectedDay.startOf('month');
@@ -40,10 +52,13 @@ export default function (props) {
40
52
  const isFutureDay = day && maxDate ? moment(day.date).isAfter(moment(maxDate || ''), 'day') : moment(day.date).isAfter(moment(), 'day');
41
53
  const isBeforeDay = day && moment(day.date).isBefore(moment(minDate || ''), 'day');
42
54
 
55
+ console.log('isFutureDay - ', isFutureDay);
56
+ console.log('isBeforeDay - ', isBeforeDay);
57
+
43
58
  const classNames = cn(
44
59
  'calendar__day',
45
60
  { 'calendar__day--clickable': day },
46
- { 'calendar__day--disabled': isFutureDay },
61
+ { 'calendar__day--disabled': !dontLimitFuture && isFutureDay },
47
62
  { 'calendar__day--disabled': isBeforeDay },
48
63
  { 'calendar__day--selected': moment(date).format() === moment(day.date).format() }
49
64
  );
@@ -52,7 +67,7 @@ export default function (props) {
52
67
  <div
53
68
  key={`${week}_${dayOfWeek}`}
54
69
  className={classNames}
55
- onClick={day && !isFutureDay ? () => setDate(moment(day.date).format('L')) : null}
70
+ onClick={day && (dontLimitFuture || !isFutureDay) ? () => setDate(moment(day.date).format('L')) : null}
56
71
  // onMouseOver={day && !isFutureDay ? () => onHover(day.date) : null}
57
72
  // onMouseLeave={() => onHover(null)}
58
73
  >
@@ -69,8 +84,35 @@ export default function (props) {
69
84
  setShowDate(moment(showDate).add(1, 'month').format('L'));
70
85
  };
71
86
 
87
+ const closeYearInput = () => {
88
+ const newDate = (() => {
89
+ const dateArr = showDate.split('/');
90
+ const oldYear = dateArr[2];
91
+ dateArr[2] = inputYearValue;
92
+ return moment(dateArr.join('/')).format('MM/DD/YYYY') === isError ? showDate : moment(dateArr.join('/')).format('MM/DD/YYYY');
93
+ })();
94
+ let resultDate = newDate;
95
+ if (minDate && moment(minDate) > moment(newDate)) resultDate = moment(showDate).format('MM/DD/YYYY');
96
+ else if (maxDate && moment(maxDate) < moment(newDate)) resultDate = moment(showDate).format('MM/DD/YYYY');
97
+
98
+ setIsChangeYear(false);
99
+ setShowDate(resultDate);
100
+ setInputYearValue(resultDate);
101
+ };
102
+
103
+ useEffect(() => {
104
+ if (isChangeYear && yearInputRef.current) {
105
+ const input = yearInputRef.current.getElementsByTagName('input')[0];
106
+ setInputYearValue(showYear);
107
+ setTimeout(() => {
108
+ input.focus();
109
+ input.select();
110
+ }, 0);
111
+ }
112
+ }, [isChangeYear]);
113
+
72
114
  return (
73
- <div className={`calendar ${className ? className : ""}`}>
115
+ <div className={`calendar ${className ? className : ''}`}>
74
116
  <div className="calendar-header">
75
117
  <div className="calendar-header__prev">
76
118
  {allowPrev && (
@@ -79,7 +121,34 @@ export default function (props) {
79
121
  </div>
80
122
  )}
81
123
  </div>
82
- <div className="calendar-header__title">{title}</div>
124
+ <div className={cn('calendar-header__title')} ref={yearInputRef}>
125
+ <span className="calendar-header__title-month">{`${showMonth} `}</span>
126
+ <span
127
+ className={cn('calendar-header__title-year', {
128
+ 'calendar-header__title-year_change-mode': isChangeYear,
129
+ })}
130
+ onClick={() => setIsChangeYear(true)}
131
+ >
132
+ {isChangeYear ? (
133
+ <InputMask
134
+ className="calendar-header__title-year-change-input"
135
+ value={inputYearValue}
136
+ mask="9999"
137
+ onBlur={(e) => closeYearInput()}
138
+ onKeyUp={(e) => {
139
+ if (e.key === 'Escape') setIsChangeYear(false);
140
+ if (e.key === 'Enter') closeYearInput();
141
+ }}
142
+ onChange={(e) => {
143
+ console.log(e.target.value);
144
+ setInputYearValue(e.target.value);
145
+ }}
146
+ />
147
+ ) : (
148
+ `${showYear}`
149
+ )}
150
+ </span>
151
+ </div>
83
152
  <div className="calendar-header__next">
84
153
  {allowNext && (
85
154
  <div onClick={handleNext}>
@@ -431,17 +431,18 @@
431
431
  align-items: center;
432
432
 
433
433
  &__prev,
434
- &__next{
434
+ &__next {
435
435
  display: flex;
436
436
  height: auto;
437
+ cursor: pointer;
437
438
  }
438
439
  }
439
440
  .calendar {
440
441
  background: #ffffff;
441
- border: 1px solid #e2e5ec;
442
- box-shadow: 0 5px 20px rgb(0 0 0 / 15%);
443
- margin-top: 4px;
444
- padding: 5px 0;
442
+ border: 1px solid #e2e5ec;
443
+ box-shadow: 0 5px 20px rgb(0 0 0 / 15%);
444
+ margin-top: 4px;
445
+ padding: 5px 0;
445
446
 
446
447
  min-height: 195px;
447
448
  width: 260px;
@@ -449,6 +450,52 @@
449
450
  flex-direction: column;
450
451
  user-select: none;
451
452
 
453
+ &-header {
454
+ box-sizing: border-box;
455
+ &__title {
456
+ &-month {
457
+ margin-right: 5px;
458
+ }
459
+ &-year {
460
+ box-sizing: border-box;
461
+ width: 45px;
462
+ height: 100%;
463
+ padding: 0 5px;
464
+ cursor: pointer;
465
+ display: flex;
466
+ flex-flow: row nowrap;
467
+ justify-content: center;
468
+ align-items: center;
469
+
470
+ &:hover:not(.calendar-header__title-year_change-mode) {
471
+ text-decoration: underline;
472
+ }
473
+
474
+ &.calendar-header__title-year_change-mode {
475
+ height: 24px;
476
+ padding: 0 3px;
477
+ border-style: solid;
478
+ border-width: 1px;
479
+ border-color: inherit;
480
+ border-radius: var(--border-radius);
481
+ }
482
+
483
+ &-change-input {
484
+ box-sizing: border-box;
485
+ width: 100%;
486
+ border: none;
487
+ outline: none;
488
+ margin: 0;
489
+ padding: 0;
490
+ display: inline;
491
+ font-size: inherit;
492
+ line-height: inherit;
493
+ font-weight: inherit;
494
+ }
495
+ }
496
+ }
497
+ }
498
+
452
499
  &__week {
453
500
  display: flex;
454
501
  }
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useState } from 'react';
2
2
  import Calendar from './Calendar';
3
3
 
4
4
  global.lng = 'en';
@@ -8,16 +8,18 @@ export default {
8
8
  component: Calendar,
9
9
  };
10
10
 
11
- const Template = args => (
12
- <div style={{ width: '320px' }}>
13
- <Calendar {...args} />
14
- </div>
15
- );
11
+ const Template = args => {
12
+ const [date, setDate] = useState('12/03/2021');
13
+ return (
14
+ <div style={{ width: '320px' }}>
15
+ <Calendar {...args} date={date} setDate={setDate} />
16
+ </div>
17
+ );
18
+ };
16
19
 
17
20
  export const CalendarTemplate = Template.bind({});
18
21
 
19
22
  CalendarTemplate.args = {
20
- date: '12/03/2021',
21
23
  params: {},
22
24
  setDate: () => null,
23
25
  className: ''