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
@@ -13,12 +13,14 @@ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers
13
13
 
14
14
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
15
15
 
16
- var _classnames = _interopRequireDefault(require("classnames"));
17
-
18
16
  var _react = _interopRequireWildcard(require("react"));
19
17
 
18
+ var _classnames = _interopRequireDefault(require("classnames"));
19
+
20
20
  var _moment = _interopRequireDefault(require("moment"));
21
21
 
22
+ var _reactInputMask = _interopRequireDefault(require("react-input-mask"));
23
+
22
24
  var _reactFeather = require("react-feather");
23
25
 
24
26
  require("./Calendar.scss");
@@ -35,11 +37,11 @@ function _default(props) {
35
37
  _props$allowNext = props.allowNext,
36
38
  allowNext = _props$allowNext === void 0 ? true : _props$allowNext,
37
39
  params = props.params,
38
- className = props.className;
39
- var _params$minDate = params.minDate,
40
- minDate = _params$minDate === void 0 ? '01/01/1900' : _params$minDate,
41
- _params$maxDate = params.maxDate,
42
- maxDate = _params$maxDate === void 0 ? (0, _moment.default)().format('MM/DD/YYYY') : _params$maxDate;
40
+ className = props.className,
41
+ dontLimitFuture = props.dontLimitFuture; // const { minDate = '01/01/1900', maxDate = moment().format('MM/DD/YYYY') } = params;
42
+
43
+ var minDate = params.minDate,
44
+ maxDate = params.maxDate;
43
45
 
44
46
  var _useState = (0, _react.useState)({}),
45
47
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
@@ -51,11 +53,31 @@ function _default(props) {
51
53
  showDate = _useState4[0],
52
54
  setShowDate = _useState4[1];
53
55
 
56
+ var _useState5 = (0, _react.useState)(false),
57
+ _useState6 = (0, _slicedToArray2.default)(_useState5, 2),
58
+ isChangeYear = _useState6[0],
59
+ setIsChangeYear = _useState6[1];
60
+
61
+ var _useState7 = (0, _react.useState)((0, _moment.default)(showDate).format('YYYY')),
62
+ _useState8 = (0, _slicedToArray2.default)(_useState7, 2),
63
+ inputYearValue = _useState8[0],
64
+ setInputYearValue = _useState8[1];
65
+
66
+ var yearInputRef = (0, _react.useRef)(null);
54
67
  var selectedDay = (0, _moment.default)(showDate);
55
- var isError = 'Invalid date';
56
- var title = (0, _react.useMemo)(function () {
57
- return selectedDay.format('MMM') === isError ? isError : "".concat(selectedDay.format('MMM'), " ").concat((0, _moment.default)(showDate).format('YYYY'));
68
+ var isError = 'Invalid date'; // const title = useMemo(
69
+ // () => (selectedDay.format('MMM') === isError ? isError : `${selectedDay.format('MMM')} ${moment(showDate).format('YYYY')}`),
70
+ // [date, showDate]
71
+ // );
72
+
73
+ var showMonth = (0, _react.useMemo)(function () {
74
+ return (0, _moment.default)(showDate).format('MMM');
75
+ }, [date, showDate]);
76
+ var showYear = (0, _react.useMemo)(function () {
77
+ return (0, _moment.default)(showDate).format('YYYY');
58
78
  }, [date, showDate]);
79
+ console.log('date - ', date);
80
+ console.log('showDate - ', showDate);
59
81
  (0, _react.useEffect)(function () {
60
82
  var result = {};
61
83
  var day = selectedDay.startOf('month');
@@ -86,10 +108,12 @@ function _default(props) {
86
108
  });
87
109
  var isFutureDay = day && maxDate ? (0, _moment.default)(day.date).isAfter((0, _moment.default)(maxDate || ''), 'day') : (0, _moment.default)(day.date).isAfter((0, _moment.default)(), 'day');
88
110
  var isBeforeDay = day && (0, _moment.default)(day.date).isBefore((0, _moment.default)(minDate || ''), 'day');
111
+ console.log('isFutureDay - ', isFutureDay);
112
+ console.log('isBeforeDay - ', isBeforeDay);
89
113
  var classNames = (0, _classnames.default)('calendar__day', {
90
114
  'calendar__day--clickable': day
91
115
  }, {
92
- 'calendar__day--disabled': isFutureDay
116
+ 'calendar__day--disabled': !dontLimitFuture && isFutureDay
93
117
  }, {
94
118
  'calendar__day--disabled': isBeforeDay
95
119
  }, {
@@ -98,7 +122,7 @@ function _default(props) {
98
122
  return /*#__PURE__*/_react.default.createElement("div", {
99
123
  key: "".concat(week, "_").concat(dayOfWeek),
100
124
  className: classNames,
101
- onClick: day && !isFutureDay ? function () {
125
+ onClick: day && (dontLimitFuture || !isFutureDay) ? function () {
102
126
  return setDate((0, _moment.default)(day.date).format('L'));
103
127
  } : null // onMouseOver={day && !isFutureDay ? () => onHover(day.date) : null}
104
128
  // onMouseLeave={() => onHover(null)}
@@ -114,8 +138,33 @@ function _default(props) {
114
138
  setShowDate((0, _moment.default)(showDate).add(1, 'month').format('L'));
115
139
  };
116
140
 
141
+ var closeYearInput = function closeYearInput() {
142
+ var newDate = function () {
143
+ var dateArr = showDate.split('/');
144
+ var oldYear = dateArr[2];
145
+ dateArr[2] = inputYearValue;
146
+ return (0, _moment.default)(dateArr.join('/')).format('MM/DD/YYYY') === isError ? showDate : (0, _moment.default)(dateArr.join('/')).format('MM/DD/YYYY');
147
+ }();
148
+
149
+ var resultDate = newDate;
150
+ if (minDate && (0, _moment.default)(minDate) > (0, _moment.default)(newDate)) resultDate = (0, _moment.default)(showDate).format('MM/DD/YYYY');else if (maxDate && (0, _moment.default)(maxDate) < (0, _moment.default)(newDate)) resultDate = (0, _moment.default)(showDate).format('MM/DD/YYYY');
151
+ setIsChangeYear(false);
152
+ setShowDate(resultDate);
153
+ setInputYearValue(resultDate);
154
+ };
155
+
156
+ (0, _react.useEffect)(function () {
157
+ if (isChangeYear && yearInputRef.current) {
158
+ var input = yearInputRef.current.getElementsByTagName('input')[0];
159
+ setInputYearValue(showYear);
160
+ setTimeout(function () {
161
+ input.focus();
162
+ input.select();
163
+ }, 0);
164
+ }
165
+ }, [isChangeYear]);
117
166
  return /*#__PURE__*/_react.default.createElement("div", {
118
- className: "calendar ".concat(className ? className : "")
167
+ className: "calendar ".concat(className ? className : '')
119
168
  }, /*#__PURE__*/_react.default.createElement("div", {
120
169
  className: "calendar-header"
121
170
  }, /*#__PURE__*/_react.default.createElement("div", {
@@ -123,8 +172,33 @@ function _default(props) {
123
172
  }, allowPrev && /*#__PURE__*/_react.default.createElement("div", {
124
173
  onClick: handlePrev
125
174
  }, /*#__PURE__*/_react.default.createElement(_reactFeather.ChevronLeft, null))), /*#__PURE__*/_react.default.createElement("div", {
126
- className: "calendar-header__title"
127
- }, title), /*#__PURE__*/_react.default.createElement("div", {
175
+ className: (0, _classnames.default)('calendar-header__title'),
176
+ ref: yearInputRef
177
+ }, /*#__PURE__*/_react.default.createElement("span", {
178
+ className: "calendar-header__title-month"
179
+ }, "".concat(showMonth, " ")), /*#__PURE__*/_react.default.createElement("span", {
180
+ className: (0, _classnames.default)('calendar-header__title-year', {
181
+ 'calendar-header__title-year_change-mode': isChangeYear
182
+ }),
183
+ onClick: function onClick() {
184
+ return setIsChangeYear(true);
185
+ }
186
+ }, isChangeYear ? /*#__PURE__*/_react.default.createElement(_reactInputMask.default, {
187
+ className: "calendar-header__title-year-change-input",
188
+ value: inputYearValue,
189
+ mask: "9999",
190
+ onBlur: function onBlur(e) {
191
+ return closeYearInput();
192
+ },
193
+ onKeyUp: function onKeyUp(e) {
194
+ if (e.key === 'Escape') setIsChangeYear(false);
195
+ if (e.key === 'Enter') closeYearInput();
196
+ },
197
+ onChange: function onChange(e) {
198
+ console.log(e.target.value);
199
+ setInputYearValue(e.target.value);
200
+ }
201
+ }) : "".concat(showYear))), /*#__PURE__*/_react.default.createElement("div", {
128
202
  className: "calendar-header__next"
129
203
  }, allowNext && /*#__PURE__*/_react.default.createElement("div", {
130
204
  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
  }
@@ -2,15 +2,25 @@
2
2
 
3
3
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
4
 
5
+ var _typeof = require("@babel/runtime/helpers/typeof");
6
+
5
7
  Object.defineProperty(exports, "__esModule", {
6
8
  value: true
7
9
  });
8
10
  exports.CalendarTemplate = exports.default = void 0;
9
11
 
10
- var _react = _interopRequireDefault(require("react"));
12
+ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
13
+
14
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
15
+
16
+ var _react = _interopRequireWildcard(require("react"));
11
17
 
12
18
  var _Calendar = _interopRequireDefault(require("./Calendar"));
13
19
 
20
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
21
+
22
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
23
+
14
24
  global.lng = 'en';
15
25
  var _default = {
16
26
  title: 'Calendar',
@@ -19,17 +29,24 @@ var _default = {
19
29
  exports.default = _default;
20
30
 
21
31
  var Template = function Template(args) {
32
+ var _useState = (0, _react.useState)('12/03/2021'),
33
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
34
+ date = _useState2[0],
35
+ setDate = _useState2[1];
36
+
22
37
  return /*#__PURE__*/_react.default.createElement("div", {
23
38
  style: {
24
39
  width: '320px'
25
40
  }
26
- }, /*#__PURE__*/_react.default.createElement(_Calendar.default, args));
41
+ }, /*#__PURE__*/_react.default.createElement(_Calendar.default, (0, _extends2.default)({}, args, {
42
+ date: date,
43
+ setDate: setDate
44
+ })));
27
45
  };
28
46
 
29
47
  var CalendarTemplate = Template.bind({});
30
48
  exports.CalendarTemplate = CalendarTemplate;
31
49
  CalendarTemplate.args = {
32
- date: '12/03/2021',
33
50
  params: {},
34
51
  setDate: function setDate() {
35
52
  return null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "intelicoreact",
3
- "version": "0.0.86",
3
+ "version": "0.0.92",
4
4
  "description": "fix input-calendar",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -23,6 +23,5 @@
23
23
  "@babel/polyfill": "^7.12.1",
24
24
  "@babel/preset-env": "^7.15.6",
25
25
  "anme": "^1.0.0"
26
-
27
26
  }
28
27
  }
@@ -1,36 +1,40 @@
1
- import React, { useState, useRef, useEffect } from 'react';
1
+ import React, { useState, useRef, useEffect, useCallback } from 'react';
2
2
  import cn from 'classnames';
3
3
  import { Check, ChevronDown, ChevronUp } from 'react-feather';
4
4
 
5
+ import DropdownLoader from './components/DropdownLoader';
6
+
5
7
  import './Dropdown.scss';
6
8
 
7
9
  const RC = 'dropdown';
8
10
 
9
- const Dropdown = ({ options = [], value, error, onChange, placeholder, className, isSearchable, entity }) => {
11
+ const Dropdown = ({ options = [], value, error, disabled, onChange, placeholder, className, isSearchable, entity, scrollReactionObj, isListTop }) => {
10
12
  const [isOpen, setIsOpen] = useState(false);
11
- const [searchValue, setSearchValue] = useState('');
13
+ const [searchValue, setSearchValue] = useState();
12
14
  const dropdownRef = useRef(null);
15
+ const dropdownListRef = useRef(null);
16
+
13
17
  if (!options) return null;
14
18
  const filteredGroups = options
15
- .filter(item => item.items?.length)
16
- .map(item => ({ ...item, items: item.items.filter(el => el?.label?.toLowerCase().includes(searchValue?.toLowerCase() || '')) }))
17
- .filter(item => item.items?.length > 0);
19
+ .filter((item) => item.items?.length)
20
+ .map((item) => ({ ...item, items: item.items.filter((el) => el?.label?.toLowerCase().includes(searchValue?.toLowerCase() || '')) }))
21
+ .filter((item) => item.items?.length > 0);
18
22
 
19
23
  const filteredItems = options
20
- .filter(item => !item.items?.length)
21
- .filter(item => item?.label?.toLowerCase().includes(searchValue?.toLowerCase() || ''));
24
+ .filter((item) => !item.items?.length)
25
+ .filter((item) => item?.label?.toLowerCase().includes(searchValue?.toLowerCase() || ''));
22
26
 
23
27
  const filteredOptions = [...filteredItems, ...filteredGroups];
24
28
 
25
29
  const modalBtnTrigger = entity && entity !== '' && typeof entity === 'string';
26
- const onChangeHandler = item => {
30
+ const onChangeHandler = (item) => {
27
31
  setIsOpen(false);
28
32
  setSearchValue(null);
29
33
  onChange(item.value);
30
34
  };
31
35
  // decorator
32
- const getDepends = getDependsTrigger => {
33
- const newOnChange = e => {
36
+ const getDepends = (getDependsTrigger) => {
37
+ const newOnChange = (e) => {
34
38
  if (e.value === 'open_modal') {
35
39
  onChange('open_modal');
36
40
  } else {
@@ -43,34 +47,34 @@ const Dropdown = ({ options = [], value, error, onChange, placeholder, className
43
47
  {
44
48
  label: `New ${entity}`,
45
49
  value: 'open_modal',
46
- className: 'dropdown__list-item--modal'
50
+ className: 'dropdown__list-item--modal',
47
51
  },
48
- ...filteredOptions
52
+ ...filteredOptions,
49
53
  ];
50
54
 
51
55
  return {
52
- onChange: changeItem => (getDependsTrigger ? newOnChange(changeItem) : onChangeHandler(changeItem)),
53
- options: getDependsTrigger ? newOptions : options
56
+ onChange: (changeItem) => (getDependsTrigger ? newOnChange(changeItem) : onChangeHandler(changeItem)),
57
+ options: getDependsTrigger ? newOptions : options,
54
58
  };
55
59
  };
56
60
 
57
- const handleClickOutside = event => {
61
+ const handleClickOutside = (event) => {
58
62
  if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
59
63
  setIsOpen(false);
60
64
  setSearchValue(null);
61
65
  }
62
66
  };
63
67
 
64
- const onSearchHandler = name => {
68
+ const onSearchHandler = (name) => {
65
69
  setSearchValue(name);
66
70
  };
67
71
 
68
- const hightlightedText = text =>
69
- searchValue ? text?.replace(new RegExp(searchValue, 'i'), match => `<span class="bg--yellow">${match}</span>`) : text;
72
+ const hightlightedText = (text) =>
73
+ searchValue ? text?.replace(new RegExp(searchValue, 'i'), (match) => `<span class="bg--yellow">${match}</span>`) : text;
70
74
 
71
75
  const depend = getDepends(modalBtnTrigger);
72
76
 
73
- const getMarkupForElement = item =>
77
+ const getMarkupForElement = (item) =>
74
78
  item.label.toLowerCase().includes(searchValue?.toLowerCase() || '') ? (
75
79
  <button
76
80
  key={item.value}
@@ -84,25 +88,51 @@ const Dropdown = ({ options = [], value, error, onChange, placeholder, className
84
88
  </button>
85
89
  ) : null;
86
90
 
87
- useEffect(() => {
88
- if (!value) setSearchValue(null);
89
- document.addEventListener('click', handleClickOutside, true);
90
- return () => document.removeEventListener('click', handleClickOutside, true);
91
- }, [value]);
92
-
93
- const filteredOptionList = filteredOption =>
91
+ const filteredOptionList = (filteredOption) =>
94
92
  filteredOption.items?.length > 0 ? (
95
93
  <div key={filteredOption.value} className={`${RC}-group`}>
96
94
  <div className={`${RC}-group__name`}>{filteredOption.label}</div>
97
- {filteredOption.items.map(el => getMarkupForElement(el))}
95
+ {filteredOption.items.map((el) => getMarkupForElement(el))}
98
96
  </div>
99
97
  ) : null;
100
98
 
101
99
  const selectedLabel =
102
- options.find(el => el.value === value)?.label || options.reduce((acc, item) => acc || item.items?.find(el => el.value === value)?.label, null);
100
+ options.find((el) => el.value === value)?.label ||
101
+ options.reduce((acc, item) => acc || item.items?.find((el) => el.value === value)?.label, null);
102
+
103
+ const doScrollCallback = useCallback(
104
+ (e) => {
105
+ const { callback, isWithAnyScrolling } = scrollReactionObj;
106
+ if (callback && typeof callback === 'function') {
107
+ if (isWithAnyScrolling) callback(e);
108
+ else if (e.target.clientHeight + e.target.scrollTop >= e.target.scrollHeight) callback(e);
109
+ }
110
+ },
111
+ [filteredOptions]
112
+ );
113
+
114
+ useEffect(() => {
115
+ if (!value) setSearchValue(null);
116
+ document.addEventListener('click', handleClickOutside, true);
117
+ return () => document.removeEventListener('click', handleClickOutside, true);
118
+ }, [value]);
119
+
120
+ useEffect(() => {
121
+ if (scrollReactionObj && typeof scrollReactionObj === 'object' && isOpen && dropdownListRef && dropdownListRef.current) {
122
+ dropdownListRef.current.addEventListener('scroll', doScrollCallback);
123
+ }
124
+ return () => {
125
+ if (scrollReactionObj && typeof scrollReactionObj === 'object') removeEventListener('scroll', doScrollCallback);
126
+ };
127
+ }, [isOpen, dropdownListRef]);
103
128
 
104
129
  return (
105
- <div className={cn(RC, className)} ref={dropdownRef}>
130
+ <div
131
+ className={cn(RC, className, {
132
+ disabled: disabled,
133
+ })}
134
+ ref={dropdownRef}
135
+ >
106
136
  <button
107
137
  className={`${RC}__trigger input__wrap ${!value ? 'placeholder' : ''} ${error ? 'error' : ''}`}
108
138
  onClick={() => (!isSearchable ? setIsOpen(!isOpen) : null)}
@@ -110,12 +140,12 @@ const Dropdown = ({ options = [], value, error, onChange, placeholder, className
110
140
  {isSearchable ? (
111
141
  <input
112
142
  className={`${RC}__input`}
113
- value={searchValue || filteredOptions.find(el => el.value === value)?.label || ''}
114
- onChange={e => {
143
+ value={searchValue || selectedLabel || ''}
144
+ onChange={(e) => {
115
145
  onSearchHandler(e.target.value);
116
146
  }}
117
147
  placeholder={placeholder}
118
- onFocus={e => {
148
+ onFocus={(e) => {
119
149
  e.target.select();
120
150
  setIsOpen(true);
121
151
  }}
@@ -127,11 +157,18 @@ const Dropdown = ({ options = [], value, error, onChange, placeholder, className
127
157
  {isOpen ? <ChevronUp /> : <ChevronDown />}
128
158
  </span>
129
159
  </button>
160
+
130
161
  {isOpen && filteredOptions.length > 0 && (
131
- <div className={`${RC}__list`}>
132
- {depend.options.map(filteredOption =>
162
+ <div
163
+ className={cn(`${RC}__list`, {
164
+ [`${RC}__list-top`]: isListTop,
165
+ })}
166
+ ref={dropdownListRef}
167
+ >
168
+ {depend.options.map((filteredOption) =>
133
169
  filteredOption.items?.length ? filteredOptionList(filteredOption) : getMarkupForElement(filteredOption)
134
170
  )}
171
+ {disabled && isOpen && <DropdownLoader />}
135
172
  </div>
136
173
  )}
137
174
  </div>
@@ -45,6 +45,7 @@
45
45
  }
46
46
 
47
47
  &__list {
48
+ position: relative;
48
49
  background: #ffffff;
49
50
  border: 1px solid #e2e5ec;
50
51
  box-shadow: 0 5px 20px rgb(0 0 0 / 15%);
@@ -70,6 +71,12 @@
70
71
  border-radius: 4px;
71
72
  }
72
73
 
74
+ &-top {
75
+ bottom: calc(100% + 4px);
76
+ top: auto;
77
+ box-shadow: 0 -3px 10px rgb(0 0 0 / 15%);
78
+ }
79
+
73
80
  &-item {
74
81
  display: flex;
75
82
  align-items: center;
@@ -177,4 +184,9 @@
177
184
  font-size: 10px;
178
185
  color: $color--secondary;
179
186
  }
187
+
188
+ &.disabled {
189
+ pointer-events: none;
190
+ opacity: 0.5;
191
+ }
180
192
  }
@@ -20,26 +20,41 @@ export default {
20
20
  },
21
21
  };
22
22
 
23
- const buttonStyles={
23
+ const blockStyles = {
24
+ display: 'flex',
25
+ flexFlow: 'row no-wrap',
26
+ alignItems: 'center',
27
+ };
28
+
29
+ const buttonStyles = {
24
30
  border: 'solid 1px #000',
25
- padding: '5px'
31
+ padding: '5px',
32
+ margin: '0 0 0 50px',
26
33
  };
27
34
 
28
35
  const Template = (args) => {
29
- const [value, setValue] = useState('');
36
+ const [value, setValue] = useState(args.value);
37
+ const [disabled, setDisabled] = useState(false);
30
38
  return (
31
- <>
32
- <div style={{ width: 200 }}>
33
- <Dropdown {...args} value={value} onChange={setValue} />
39
+ <div style={blockStyles}>
40
+ <div key="dropdown" style={{ width: 200 }}>
41
+ <Dropdown {...args} value={value} onChange={setValue} disabled={disabled} scrollReactionObj={{ callback: (e) => setDisabled(true) }} />
34
42
  </div>
35
- <button style={buttonStyles} className='mt10' onClick={() => {console.log('click!'); setValue('')}} >Reset</button>
36
- </>
43
+ <button key="reset" style={buttonStyles} className="mt10" onClick={() => setValue('')}>
44
+ Reset
45
+ </button>
46
+
47
+ <button key="enable/disable" style={buttonStyles} className="mt10" onClick={() => setDisabled(!disabled)}>
48
+ {disabled ? 'enable' : 'disable'}
49
+ </button>
50
+ </div>
37
51
  );
38
52
  };
39
53
 
40
54
  export const DropdownTemplate = Template.bind({});
41
55
 
42
56
  DropdownTemplate.args = {
57
+ isListTop: true,
43
58
  entity: 'entity',
44
59
  value: 'drop6',
45
60
  placeholder: 'Placeholder',
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import './Loader.scss';
3
+
4
+ const DropdownLoader = function ({ variant }) {
5
+ return (
6
+ <div className="dropdown-loader-box j5">
7
+ <div className={`lds-ring${variant === 'little' ? ' lds-ring_little' : ''}`}>
8
+ <div />
9
+ <div />
10
+ <div />
11
+ <div />
12
+ </div>
13
+ </div>
14
+ );
15
+ };
16
+
17
+ export default DropdownLoader;
@@ -0,0 +1,57 @@
1
+ @mixin fill-parent {
2
+ left: 0;
3
+ top: 0;
4
+ width: 100%;
5
+ height: 100%;
6
+ }
7
+
8
+ .dropdown-loader-box {
9
+ position: absolute;
10
+ @include fill-parent;
11
+ background: #fff;
12
+ opacity: 0.1;
13
+ z-index: 100;
14
+ }
15
+ .lds-ring {
16
+ display: inline-block;
17
+ position: relative;
18
+ width: 100px;
19
+ height: 100px;
20
+ }
21
+ .lds-ring.lds-ring_little {
22
+ width: 20px;
23
+ height: 20px;
24
+ }
25
+ .lds-ring div {
26
+ box-sizing: border-box;
27
+ display: block;
28
+ position: absolute;
29
+ width: 84px;
30
+ height: 84px;
31
+ margin: 8px;
32
+ border: 8px solid #000;
33
+ border-radius: 50%;
34
+ animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
35
+ border-color: #000 transparent transparent transparent;
36
+ }
37
+ .lds-ring_little div {
38
+ width: 20px;
39
+ height: 20px;
40
+ }
41
+ .lds-ring div:nth-child(1) {
42
+ animation-delay: -0.45s;
43
+ }
44
+ .lds-ring div:nth-child(2) {
45
+ animation-delay: -0.3s;
46
+ }
47
+ .lds-ring div:nth-child(3) {
48
+ animation-delay: -0.15s;
49
+ }
50
+ @keyframes lds-ring {
51
+ 0% {
52
+ transform: rotate(0deg);
53
+ }
54
+ 100% {
55
+ transform: rotate(360deg);
56
+ }
57
+ }