@alfalab/core-components-date-input 4.3.17 → 4.3.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Component.js CHANGED
@@ -8,16 +8,13 @@ var mergeRefs = require('react-merge-refs');
8
8
  var coreComponentsInput = require('@alfalab/core-components-input');
9
9
  var utils_format = require('./utils/format.js');
10
10
  var utils_nativeSupports = require('./utils/native-supports.js');
11
- require('date-fns/format');
12
- require('date-fns/isValid');
13
- require('date-fns/parse');
14
11
 
15
12
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
16
13
 
17
14
  var React__default = /*#__PURE__*/_interopDefaultCompat(React);
18
15
  var mergeRefs__default = /*#__PURE__*/_interopDefaultCompat(mergeRefs);
19
16
 
20
- var styles = {"nativeInput":"date-input__nativeInput_1e6aw"};
17
+ var styles = {"nativeInput":"date-input__nativeInput_2k4is"};
21
18
  require('./index.css')
22
19
 
23
20
  /**
@@ -29,20 +26,41 @@ var DateInput = React.forwardRef(function (_a, ref) {
29
26
  var inputRef = React.useRef(null);
30
27
  var _d = React.useState(false), shouldRenderNative = _d[0], setShouldRenderNative = _d[1];
31
28
  var _e = React.useState(propValue || defaultValue), value = _e[0], setValue = _e[1];
32
- var handleChange = React.useCallback(function (event) {
29
+ var moveCaretTo = function (pos) {
30
+ requestAnimationFrame(function () {
31
+ var _a;
32
+ (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.setSelectionRange(pos, pos);
33
+ });
34
+ };
35
+ var handleChange = function (event) {
33
36
  var newValue = event.target.value;
37
+ var caretPos = event.target.selectionStart || 0;
34
38
  // Позволяем вводить только цифры и точки
35
39
  if (/[^\d.]/.test(newValue)) {
40
+ moveCaretTo(caretPos - 1);
36
41
  return;
37
42
  }
38
- var dots = newValue.match(/\./g);
39
43
  // Не даем вводить больше, чем 2 точки
40
- if (dots && dots.length > 2) {
44
+ if (getDotsCount(newValue) > 2) {
45
+ moveCaretTo(caretPos - 1);
41
46
  return;
42
47
  }
43
48
  // Форматируем введенное значение (добавляем точки)
44
49
  var formattedValue = utils_format.format(newValue);
45
50
  var date = utils_format.parseDateString(formattedValue);
51
+ // Управляем кареткой, если она находится не в конце инпута
52
+ if (caretPos !== newValue.length) {
53
+ if (formattedValue === value) {
54
+ moveCaretTo(caretPos);
55
+ }
56
+ else if (newValue.length - formattedValue.length === 1) {
57
+ moveCaretTo(caretPos);
58
+ }
59
+ else if (formattedValue.length - newValue.length === 1 &&
60
+ getDotsCount(formattedValue) > getDotsCount(newValue)) {
61
+ moveCaretTo(caretPos);
62
+ }
63
+ }
46
64
  setValue(formattedValue);
47
65
  if (onChange)
48
66
  onChange(event, { date: date, value: formattedValue });
@@ -53,8 +71,8 @@ var DateInput = React.forwardRef(function (_a, ref) {
53
71
  if (onComplete)
54
72
  onComplete(event, { date: date, value: formattedValue });
55
73
  }
56
- }, [onChange, onComplete]);
57
- var handleNativeInputChange = React.useCallback(function (event) {
74
+ };
75
+ var handleNativeInputChange = function (event) {
58
76
  var newDate = utils_format.parseDateString(event.target.value, utils_format.NATIVE_DATE_FORMAT);
59
77
  var newValue = event.target.value === '' ? '' : utils_format.formatDate(newDate);
60
78
  setValue(newValue);
@@ -62,11 +80,11 @@ var DateInput = React.forwardRef(function (_a, ref) {
62
80
  onComplete(event, { date: newDate, value: newValue });
63
81
  if (onChange)
64
82
  onChange(event, { date: newDate, value: newValue });
65
- }, [onComplete, onChange]);
66
- var handleBlur = React.useCallback(function (event) {
83
+ };
84
+ var handleBlur = function (event) {
67
85
  if (onBlur)
68
86
  onBlur(event);
69
- }, [onBlur]);
87
+ };
70
88
  React.useEffect(function () {
71
89
  if (mobileMode === 'native' && utils_nativeSupports.isInputDateSupported()) {
72
90
  setShouldRenderNative(true);
@@ -82,5 +100,8 @@ var DateInput = React.forwardRef(function (_a, ref) {
82
100
  rightAddons,
83
101
  shouldRenderNative && (React__default.default.createElement("input", { type: 'date', ref: ref, defaultValue: defaultValue, onChange: handleNativeInputChange, className: styles.nativeInput }))) })));
84
102
  });
103
+ function getDotsCount(value) {
104
+ return (value.match(/\./g) || []).length;
105
+ }
85
106
 
86
107
  exports.DateInput = DateInput;
package/cssm/Component.js CHANGED
@@ -9,9 +9,6 @@ var coreComponentsInput = require('@alfalab/core-components-input/cssm');
9
9
  var utils_format = require('./utils/format.js');
10
10
  var utils_nativeSupports = require('./utils/native-supports.js');
11
11
  var styles = require('./index.module.css');
12
- require('date-fns/format');
13
- require('date-fns/isValid');
14
- require('date-fns/parse');
15
12
 
16
13
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
17
14
 
@@ -28,20 +25,41 @@ var DateInput = React.forwardRef(function (_a, ref) {
28
25
  var inputRef = React.useRef(null);
29
26
  var _d = React.useState(false), shouldRenderNative = _d[0], setShouldRenderNative = _d[1];
30
27
  var _e = React.useState(propValue || defaultValue), value = _e[0], setValue = _e[1];
31
- var handleChange = React.useCallback(function (event) {
28
+ var moveCaretTo = function (pos) {
29
+ requestAnimationFrame(function () {
30
+ var _a;
31
+ (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.setSelectionRange(pos, pos);
32
+ });
33
+ };
34
+ var handleChange = function (event) {
32
35
  var newValue = event.target.value;
36
+ var caretPos = event.target.selectionStart || 0;
33
37
  // Позволяем вводить только цифры и точки
34
38
  if (/[^\d.]/.test(newValue)) {
39
+ moveCaretTo(caretPos - 1);
35
40
  return;
36
41
  }
37
- var dots = newValue.match(/\./g);
38
42
  // Не даем вводить больше, чем 2 точки
39
- if (dots && dots.length > 2) {
43
+ if (getDotsCount(newValue) > 2) {
44
+ moveCaretTo(caretPos - 1);
40
45
  return;
41
46
  }
42
47
  // Форматируем введенное значение (добавляем точки)
43
48
  var formattedValue = utils_format.format(newValue);
44
49
  var date = utils_format.parseDateString(formattedValue);
50
+ // Управляем кареткой, если она находится не в конце инпута
51
+ if (caretPos !== newValue.length) {
52
+ if (formattedValue === value) {
53
+ moveCaretTo(caretPos);
54
+ }
55
+ else if (newValue.length - formattedValue.length === 1) {
56
+ moveCaretTo(caretPos);
57
+ }
58
+ else if (formattedValue.length - newValue.length === 1 &&
59
+ getDotsCount(formattedValue) > getDotsCount(newValue)) {
60
+ moveCaretTo(caretPos);
61
+ }
62
+ }
45
63
  setValue(formattedValue);
46
64
  if (onChange)
47
65
  onChange(event, { date: date, value: formattedValue });
@@ -52,8 +70,8 @@ var DateInput = React.forwardRef(function (_a, ref) {
52
70
  if (onComplete)
53
71
  onComplete(event, { date: date, value: formattedValue });
54
72
  }
55
- }, [onChange, onComplete]);
56
- var handleNativeInputChange = React.useCallback(function (event) {
73
+ };
74
+ var handleNativeInputChange = function (event) {
57
75
  var newDate = utils_format.parseDateString(event.target.value, utils_format.NATIVE_DATE_FORMAT);
58
76
  var newValue = event.target.value === '' ? '' : utils_format.formatDate(newDate);
59
77
  setValue(newValue);
@@ -61,11 +79,11 @@ var DateInput = React.forwardRef(function (_a, ref) {
61
79
  onComplete(event, { date: newDate, value: newValue });
62
80
  if (onChange)
63
81
  onChange(event, { date: newDate, value: newValue });
64
- }, [onComplete, onChange]);
65
- var handleBlur = React.useCallback(function (event) {
82
+ };
83
+ var handleBlur = function (event) {
66
84
  if (onBlur)
67
85
  onBlur(event);
68
- }, [onBlur]);
86
+ };
69
87
  React.useEffect(function () {
70
88
  if (mobileMode === 'native' && utils_nativeSupports.isInputDateSupported()) {
71
89
  setShouldRenderNative(true);
@@ -81,5 +99,8 @@ var DateInput = React.forwardRef(function (_a, ref) {
81
99
  rightAddons,
82
100
  shouldRenderNative && (React__default.default.createElement("input", { type: 'date', ref: ref, defaultValue: defaultValue, onChange: handleNativeInputChange, className: styles__default.default.nativeInput }))) })));
83
101
  });
102
+ function getDotsCount(value) {
103
+ return (value.match(/\./g) || []).length;
104
+ }
84
105
 
85
106
  exports.DateInput = DateInput;
package/cssm/index.js CHANGED
@@ -5,14 +5,6 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var Component = require('./Component.js');
6
6
  var utils_format = require('./utils/format.js');
7
7
  var utils_nativeSupports = require('./utils/native-supports.js');
8
- require('tslib');
9
- require('react');
10
- require('react-merge-refs');
11
- require('@alfalab/core-components-input/cssm');
12
- require('./index.module.css');
13
- require('date-fns/format');
14
- require('date-fns/isValid');
15
- require('date-fns/parse');
16
8
 
17
9
 
18
10
 
@@ -4,9 +4,6 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var utils_format = require('./format.js');
6
6
  var utils_nativeSupports = require('./native-supports.js');
7
- require('date-fns/format');
8
- require('date-fns/isValid');
9
- require('date-fns/parse');
10
7
 
11
8
 
12
9
 
package/esm/Component.js CHANGED
@@ -1,14 +1,11 @@
1
1
  import { __rest, __assign } from 'tslib';
2
- import React, { forwardRef, useRef, useState, useCallback, useEffect } from 'react';
2
+ import React, { forwardRef, useRef, useState, useEffect } from 'react';
3
3
  import mergeRefs from 'react-merge-refs';
4
4
  import { Input } from '@alfalab/core-components-input/esm';
5
- import { format, parseDateString, isCompleteDateInput, isValid, formatDate, NATIVE_DATE_FORMAT } from './utils/format.js';
5
+ import { format, parseDateString, isCompleteDateInput, isValid, NATIVE_DATE_FORMAT, formatDate } from './utils/format.js';
6
6
  import { isInputDateSupported } from './utils/native-supports.js';
7
- import 'date-fns/format';
8
- import 'date-fns/isValid';
9
- import 'date-fns/parse';
10
7
 
11
- var styles = {"nativeInput":"date-input__nativeInput_1e6aw"};
8
+ var styles = {"nativeInput":"date-input__nativeInput_2k4is"};
12
9
  require('./index.css')
13
10
 
14
11
  /**
@@ -20,20 +17,41 @@ var DateInput = forwardRef(function (_a, ref) {
20
17
  var inputRef = useRef(null);
21
18
  var _d = useState(false), shouldRenderNative = _d[0], setShouldRenderNative = _d[1];
22
19
  var _e = useState(propValue || defaultValue), value = _e[0], setValue = _e[1];
23
- var handleChange = useCallback(function (event) {
20
+ var moveCaretTo = function (pos) {
21
+ requestAnimationFrame(function () {
22
+ var _a;
23
+ (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.setSelectionRange(pos, pos);
24
+ });
25
+ };
26
+ var handleChange = function (event) {
24
27
  var newValue = event.target.value;
28
+ var caretPos = event.target.selectionStart || 0;
25
29
  // Позволяем вводить только цифры и точки
26
30
  if (/[^\d.]/.test(newValue)) {
31
+ moveCaretTo(caretPos - 1);
27
32
  return;
28
33
  }
29
- var dots = newValue.match(/\./g);
30
34
  // Не даем вводить больше, чем 2 точки
31
- if (dots && dots.length > 2) {
35
+ if (getDotsCount(newValue) > 2) {
36
+ moveCaretTo(caretPos - 1);
32
37
  return;
33
38
  }
34
39
  // Форматируем введенное значение (добавляем точки)
35
40
  var formattedValue = format(newValue);
36
41
  var date = parseDateString(formattedValue);
42
+ // Управляем кареткой, если она находится не в конце инпута
43
+ if (caretPos !== newValue.length) {
44
+ if (formattedValue === value) {
45
+ moveCaretTo(caretPos);
46
+ }
47
+ else if (newValue.length - formattedValue.length === 1) {
48
+ moveCaretTo(caretPos);
49
+ }
50
+ else if (formattedValue.length - newValue.length === 1 &&
51
+ getDotsCount(formattedValue) > getDotsCount(newValue)) {
52
+ moveCaretTo(caretPos);
53
+ }
54
+ }
37
55
  setValue(formattedValue);
38
56
  if (onChange)
39
57
  onChange(event, { date: date, value: formattedValue });
@@ -44,8 +62,8 @@ var DateInput = forwardRef(function (_a, ref) {
44
62
  if (onComplete)
45
63
  onComplete(event, { date: date, value: formattedValue });
46
64
  }
47
- }, [onChange, onComplete]);
48
- var handleNativeInputChange = useCallback(function (event) {
65
+ };
66
+ var handleNativeInputChange = function (event) {
49
67
  var newDate = parseDateString(event.target.value, NATIVE_DATE_FORMAT);
50
68
  var newValue = event.target.value === '' ? '' : formatDate(newDate);
51
69
  setValue(newValue);
@@ -53,11 +71,11 @@ var DateInput = forwardRef(function (_a, ref) {
53
71
  onComplete(event, { date: newDate, value: newValue });
54
72
  if (onChange)
55
73
  onChange(event, { date: newDate, value: newValue });
56
- }, [onComplete, onChange]);
57
- var handleBlur = useCallback(function (event) {
74
+ };
75
+ var handleBlur = function (event) {
58
76
  if (onBlur)
59
77
  onBlur(event);
60
- }, [onBlur]);
78
+ };
61
79
  useEffect(function () {
62
80
  if (mobileMode === 'native' && isInputDateSupported()) {
63
81
  setShouldRenderNative(true);
@@ -73,5 +91,8 @@ var DateInput = forwardRef(function (_a, ref) {
73
91
  rightAddons,
74
92
  shouldRenderNative && (React.createElement("input", { type: 'date', ref: ref, defaultValue: defaultValue, onChange: handleNativeInputChange, className: styles.nativeInput }))) })));
75
93
  });
94
+ function getDotsCount(value) {
95
+ return (value.match(/\./g) || []).length;
96
+ }
76
97
 
77
98
  export { DateInput };
package/esm/index.css CHANGED
@@ -1,4 +1,4 @@
1
- /* hash: xx5u2 */
1
+ /* hash: 1hmiy */
2
2
  :root {
3
3
  } /* deprecated */ :root { /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */
4
4
  } :root { /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */
@@ -14,7 +14,7 @@
14
14
  } :root {
15
15
  } :root {
16
16
  } :root {
17
- } .date-input__nativeInput_1e6aw {
17
+ } .date-input__nativeInput_2k4is {
18
18
  opacity: 0;
19
19
  position: absolute;
20
20
  top: 0;
@@ -23,8 +23,8 @@
23
23
  height: 100%;
24
24
  appearance: none;
25
25
  z-index: 1
26
- } .date-input__nativeInput_1e6aw::-webkit-calendar-picker-indicator {
26
+ } .date-input__nativeInput_2k4is::-webkit-calendar-picker-indicator {
27
27
  display: none;
28
- } .date-input__nativeInput_1e6aw::-webkit-inner-spin-button {
28
+ } .date-input__nativeInput_2k4is::-webkit-inner-spin-button {
29
29
  display: none;
30
30
  }
package/esm/index.js CHANGED
@@ -1,10 +1,3 @@
1
1
  export { DateInput } from './Component.js';
2
2
  export { DATE_FORMAT, DATE_MASK, NATIVE_DATE_FORMAT, format, formatDate, isCompleteDateInput, isValid, parseDateString } from './utils/format.js';
3
3
  export { isInputDateSupported } from './utils/native-supports.js';
4
- import 'tslib';
5
- import 'react';
6
- import 'react-merge-refs';
7
- import '@alfalab/core-components-input/esm';
8
- import 'date-fns/format';
9
- import 'date-fns/isValid';
10
- import 'date-fns/parse';
@@ -1,5 +1,2 @@
1
1
  export { DATE_FORMAT, DATE_MASK, NATIVE_DATE_FORMAT, format, formatDate, isCompleteDateInput, isValid, parseDateString } from './format.js';
2
2
  export { isInputDateSupported } from './native-supports.js';
3
- import 'date-fns/format';
4
- import 'date-fns/isValid';
5
- import 'date-fns/parse';
package/index.css CHANGED
@@ -1,4 +1,4 @@
1
- /* hash: xx5u2 */
1
+ /* hash: 1hmiy */
2
2
  :root {
3
3
  } /* deprecated */ :root { /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */
4
4
  } :root { /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */
@@ -14,7 +14,7 @@
14
14
  } :root {
15
15
  } :root {
16
16
  } :root {
17
- } .date-input__nativeInput_1e6aw {
17
+ } .date-input__nativeInput_2k4is {
18
18
  opacity: 0;
19
19
  position: absolute;
20
20
  top: 0;
@@ -23,8 +23,8 @@
23
23
  height: 100%;
24
24
  appearance: none;
25
25
  z-index: 1
26
- } .date-input__nativeInput_1e6aw::-webkit-calendar-picker-indicator {
26
+ } .date-input__nativeInput_2k4is::-webkit-calendar-picker-indicator {
27
27
  display: none;
28
- } .date-input__nativeInput_1e6aw::-webkit-inner-spin-button {
28
+ } .date-input__nativeInput_2k4is::-webkit-inner-spin-button {
29
29
  display: none;
30
30
  }
package/index.js CHANGED
@@ -5,13 +5,6 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var Component = require('./Component.js');
6
6
  var utils_format = require('./utils/format.js');
7
7
  var utils_nativeSupports = require('./utils/native-supports.js');
8
- require('tslib');
9
- require('react');
10
- require('react-merge-refs');
11
- require('@alfalab/core-components-input');
12
- require('date-fns/format');
13
- require('date-fns/isValid');
14
- require('date-fns/parse');
15
8
 
16
9
 
17
10
 
@@ -1,13 +1,10 @@
1
- import React, { forwardRef, useRef, useState, useCallback, useEffect } from 'react';
1
+ import React, { forwardRef, useRef, useState, useEffect } from 'react';
2
2
  import mergeRefs from 'react-merge-refs';
3
3
  import { Input } from '@alfalab/core-components-input/modern';
4
- import { format, parseDateString, isCompleteDateInput, isValid, formatDate, NATIVE_DATE_FORMAT } from './utils/format.js';
4
+ import { format, parseDateString, isCompleteDateInput, isValid, NATIVE_DATE_FORMAT, formatDate } from './utils/format.js';
5
5
  import { isInputDateSupported } from './utils/native-supports.js';
6
- import 'date-fns/format';
7
- import 'date-fns/isValid';
8
- import 'date-fns/parse';
9
6
 
10
- const styles = {"nativeInput":"date-input__nativeInput_1e6aw"};
7
+ const styles = {"nativeInput":"date-input__nativeInput_2k4is"};
11
8
  require('./index.css')
12
9
 
13
10
  /**
@@ -18,20 +15,40 @@ const DateInput = forwardRef(({ mobileMode = 'input', defaultValue = '', rightAd
18
15
  const inputRef = useRef(null);
19
16
  const [shouldRenderNative, setShouldRenderNative] = useState(false);
20
17
  const [value, setValue] = useState(propValue || defaultValue);
21
- const handleChange = useCallback((event) => {
18
+ const moveCaretTo = (pos) => {
19
+ requestAnimationFrame(() => {
20
+ inputRef.current?.setSelectionRange(pos, pos);
21
+ });
22
+ };
23
+ const handleChange = (event) => {
22
24
  const { value: newValue } = event.target;
25
+ const caretPos = event.target.selectionStart || 0;
23
26
  // Позволяем вводить только цифры и точки
24
27
  if (/[^\d.]/.test(newValue)) {
28
+ moveCaretTo(caretPos - 1);
25
29
  return;
26
30
  }
27
- const dots = newValue.match(/\./g);
28
31
  // Не даем вводить больше, чем 2 точки
29
- if (dots && dots.length > 2) {
32
+ if (getDotsCount(newValue) > 2) {
33
+ moveCaretTo(caretPos - 1);
30
34
  return;
31
35
  }
32
36
  // Форматируем введенное значение (добавляем точки)
33
37
  const formattedValue = format(newValue);
34
38
  const date = parseDateString(formattedValue);
39
+ // Управляем кареткой, если она находится не в конце инпута
40
+ if (caretPos !== newValue.length) {
41
+ if (formattedValue === value) {
42
+ moveCaretTo(caretPos);
43
+ }
44
+ else if (newValue.length - formattedValue.length === 1) {
45
+ moveCaretTo(caretPos);
46
+ }
47
+ else if (formattedValue.length - newValue.length === 1 &&
48
+ getDotsCount(formattedValue) > getDotsCount(newValue)) {
49
+ moveCaretTo(caretPos);
50
+ }
51
+ }
35
52
  setValue(formattedValue);
36
53
  if (onChange)
37
54
  onChange(event, { date, value: formattedValue });
@@ -42,8 +59,8 @@ const DateInput = forwardRef(({ mobileMode = 'input', defaultValue = '', rightAd
42
59
  if (onComplete)
43
60
  onComplete(event, { date, value: formattedValue });
44
61
  }
45
- }, [onChange, onComplete]);
46
- const handleNativeInputChange = useCallback((event) => {
62
+ };
63
+ const handleNativeInputChange = (event) => {
47
64
  const newDate = parseDateString(event.target.value, NATIVE_DATE_FORMAT);
48
65
  const newValue = event.target.value === '' ? '' : formatDate(newDate);
49
66
  setValue(newValue);
@@ -51,11 +68,11 @@ const DateInput = forwardRef(({ mobileMode = 'input', defaultValue = '', rightAd
51
68
  onComplete(event, { date: newDate, value: newValue });
52
69
  if (onChange)
53
70
  onChange(event, { date: newDate, value: newValue });
54
- }, [onComplete, onChange]);
55
- const handleBlur = useCallback((event) => {
71
+ };
72
+ const handleBlur = (event) => {
56
73
  if (onBlur)
57
74
  onBlur(event);
58
- }, [onBlur]);
75
+ };
59
76
  useEffect(() => {
60
77
  if (mobileMode === 'native' && isInputDateSupported()) {
61
78
  setShouldRenderNative(true);
@@ -71,5 +88,8 @@ const DateInput = forwardRef(({ mobileMode = 'input', defaultValue = '', rightAd
71
88
  rightAddons,
72
89
  shouldRenderNative && (React.createElement("input", { type: 'date', ref: ref, defaultValue: defaultValue, onChange: handleNativeInputChange, className: styles.nativeInput }))) }));
73
90
  });
91
+ function getDotsCount(value) {
92
+ return (value.match(/\./g) || []).length;
93
+ }
74
94
 
75
95
  export { DateInput };
package/modern/index.css CHANGED
@@ -1,4 +1,4 @@
1
- /* hash: xx5u2 */
1
+ /* hash: 1hmiy */
2
2
  :root {
3
3
  } /* deprecated */ :root { /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */
4
4
  } :root { /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */ /* deprecated */
@@ -14,7 +14,7 @@
14
14
  } :root {
15
15
  } :root {
16
16
  } :root {
17
- } .date-input__nativeInput_1e6aw {
17
+ } .date-input__nativeInput_2k4is {
18
18
  opacity: 0;
19
19
  position: absolute;
20
20
  top: 0;
@@ -23,8 +23,8 @@
23
23
  height: 100%;
24
24
  appearance: none;
25
25
  z-index: 1
26
- } .date-input__nativeInput_1e6aw::-webkit-calendar-picker-indicator {
26
+ } .date-input__nativeInput_2k4is::-webkit-calendar-picker-indicator {
27
27
  display: none;
28
- } .date-input__nativeInput_1e6aw::-webkit-inner-spin-button {
28
+ } .date-input__nativeInput_2k4is::-webkit-inner-spin-button {
29
29
  display: none;
30
30
  }
package/modern/index.js CHANGED
@@ -1,9 +1,3 @@
1
1
  export { DateInput } from './Component.js';
2
2
  export { DATE_FORMAT, DATE_MASK, NATIVE_DATE_FORMAT, format, formatDate, isCompleteDateInput, isValid, parseDateString } from './utils/format.js';
3
3
  export { isInputDateSupported } from './utils/native-supports.js';
4
- import 'react';
5
- import 'react-merge-refs';
6
- import '@alfalab/core-components-input/modern';
7
- import 'date-fns/format';
8
- import 'date-fns/isValid';
9
- import 'date-fns/parse';
@@ -1,5 +1,2 @@
1
1
  export { DATE_FORMAT, DATE_MASK, NATIVE_DATE_FORMAT, format, formatDate, isCompleteDateInput, isValid, parseDateString } from './format.js';
2
2
  export { isInputDateSupported } from './native-supports.js';
3
- import 'date-fns/format';
4
- import 'date-fns/isValid';
5
- import 'date-fns/parse';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfalab/core-components-date-input",
3
- "version": "4.3.17",
3
+ "version": "4.3.19",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "license": "MIT",
@@ -14,7 +14,7 @@
14
14
  "react": "^16.9.0 || ^17.0.1 || ^18.0.0"
15
15
  },
16
16
  "dependencies": {
17
- "@alfalab/core-components-input": "^14.1.1",
17
+ "@alfalab/core-components-input": "^14.2.0",
18
18
  "date-fns": "^2.16.1",
19
19
  "react-merge-refs": "^1.1.0",
20
20
  "tslib": "^2.4.0"
package/src/Component.tsx CHANGED
@@ -1,12 +1,4 @@
1
- import React, {
2
- ChangeEvent,
3
- FocusEvent,
4
- forwardRef,
5
- useCallback,
6
- useEffect,
7
- useRef,
8
- useState,
9
- } from 'react';
1
+ import React, { ChangeEvent, FocusEvent, forwardRef, useEffect, useRef, useState } from 'react';
10
2
  import mergeRefs from 'react-merge-refs';
11
3
 
12
4
  import { Input, InputProps } from '@alfalab/core-components-input';
@@ -71,60 +63,74 @@ export const DateInput = forwardRef<HTMLInputElement, DateInputProps>(
71
63
 
72
64
  const [value, setValue] = useState(propValue || defaultValue);
73
65
 
74
- const handleChange = useCallback(
75
- (event: ChangeEvent<HTMLInputElement>) => {
76
- const { value: newValue } = event.target;
66
+ const moveCaretTo = (pos: number) => {
67
+ requestAnimationFrame(() => {
68
+ inputRef.current?.setSelectionRange(pos, pos);
69
+ });
70
+ };
77
71
 
78
- // Позволяем вводить только цифры и точки
79
- if (/[^\d.]/.test(newValue)) {
80
- return;
81
- }
72
+ const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
73
+ const { value: newValue } = event.target;
74
+ const caretPos = event.target.selectionStart || 0;
82
75
 
83
- const dots = newValue.match(/\./g);
76
+ // Позволяем вводить только цифры и точки
77
+ if (/[^\d.]/.test(newValue)) {
78
+ moveCaretTo(caretPos - 1);
84
79
 
85
- // Не даем вводить больше, чем 2 точки
86
- if (dots && dots.length > 2) {
87
- return;
88
- }
80
+ return;
81
+ }
89
82
 
90
- // Форматируем введенное значение (добавляем точки)
91
- const formattedValue = format(newValue);
92
- const date = parseDateString(formattedValue);
83
+ // Не даем вводить больше, чем 2 точки
84
+ if (getDotsCount(newValue) > 2) {
85
+ moveCaretTo(caretPos - 1);
93
86
 
94
- setValue(formattedValue);
87
+ return;
88
+ }
95
89
 
96
- if (onChange) onChange(event, { date, value: formattedValue });
90
+ // Форматируем введенное значение (добавляем точки)
91
+ const formattedValue = format(newValue);
92
+ const date = parseDateString(formattedValue);
93
+
94
+ // Управляем кареткой, если она находится не в конце инпута
95
+ if (caretPos !== newValue.length) {
96
+ if (formattedValue === value) {
97
+ moveCaretTo(caretPos);
98
+ } else if (newValue.length - formattedValue.length === 1) {
99
+ moveCaretTo(caretPos);
100
+ } else if (
101
+ formattedValue.length - newValue.length === 1 &&
102
+ getDotsCount(formattedValue) > getDotsCount(newValue)
103
+ ) {
104
+ moveCaretTo(caretPos);
105
+ }
106
+ }
97
107
 
98
- if (isCompleteDateInput(formattedValue)) {
99
- const valid = formattedValue.length > 0 && isValid(formattedValue);
108
+ setValue(formattedValue);
100
109
 
101
- if (!valid) return;
110
+ if (onChange) onChange(event, { date, value: formattedValue });
102
111
 
103
- if (onComplete) onComplete(event, { date, value: formattedValue });
104
- }
105
- },
106
- [onChange, onComplete],
107
- );
112
+ if (isCompleteDateInput(formattedValue)) {
113
+ const valid = formattedValue.length > 0 && isValid(formattedValue);
108
114
 
109
- const handleNativeInputChange = useCallback(
110
- (event: ChangeEvent<HTMLInputElement>) => {
111
- const newDate = parseDateString(event.target.value, NATIVE_DATE_FORMAT);
112
- const newValue = event.target.value === '' ? '' : formatDate(newDate);
115
+ if (!valid) return;
113
116
 
114
- setValue(newValue);
117
+ if (onComplete) onComplete(event, { date, value: formattedValue });
118
+ }
119
+ };
115
120
 
116
- if (onComplete) onComplete(event, { date: newDate, value: newValue });
117
- if (onChange) onChange(event, { date: newDate, value: newValue });
118
- },
119
- [onComplete, onChange],
120
- );
121
+ const handleNativeInputChange = (event: ChangeEvent<HTMLInputElement>) => {
122
+ const newDate = parseDateString(event.target.value, NATIVE_DATE_FORMAT);
123
+ const newValue = event.target.value === '' ? '' : formatDate(newDate);
121
124
 
122
- const handleBlur = useCallback(
123
- (event: FocusEvent<HTMLInputElement>) => {
124
- if (onBlur) onBlur(event);
125
- },
126
- [onBlur],
127
- );
125
+ setValue(newValue);
126
+
127
+ if (onComplete) onComplete(event, { date: newDate, value: newValue });
128
+ if (onChange) onChange(event, { date: newDate, value: newValue });
129
+ };
130
+
131
+ const handleBlur = (event: FocusEvent<HTMLInputElement>) => {
132
+ if (onBlur) onBlur(event);
133
+ };
128
134
 
129
135
  useEffect(() => {
130
136
  if (mobileMode === 'native' && isInputDateSupported()) {
@@ -169,3 +175,7 @@ export const DateInput = forwardRef<HTMLInputElement, DateInputProps>(
169
175
  );
170
176
  },
171
177
  );
178
+
179
+ function getDotsCount(value: string) {
180
+ return (value.match(/\./g) || []).length;
181
+ }
package/utils/index.js CHANGED
@@ -4,9 +4,6 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var utils_format = require('./format.js');
6
6
  var utils_nativeSupports = require('./native-supports.js');
7
- require('date-fns/format');
8
- require('date-fns/isValid');
9
- require('date-fns/parse');
10
7
 
11
8
 
12
9