@elliemae/ds-controlled-form 2.4.2-rc.0 → 2.4.2-rc.1

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 (104) hide show
  1. package/cjs/autocomplete/config/useAutocomplete.js +1 -3
  2. package/cjs/checkbox/ControlledCheckbox.js +49 -33
  3. package/cjs/checkbox/exported-related/data-test-ids.js +10 -0
  4. package/cjs/checkbox/exported-related/index.js +12 -0
  5. package/cjs/checkbox/exported-related/theming.js +13 -0
  6. package/cjs/checkbox/react-desc-prop-types.js +0 -1
  7. package/cjs/checkbox/styles.js +26 -15
  8. package/cjs/combobox/ComboBoxCTX.js +1 -1
  9. package/cjs/combobox/ComboboxDataTestids.js +1 -1
  10. package/cjs/combobox/config/useComboBox.js +6 -4
  11. package/cjs/combobox/index.js +5 -0
  12. package/cjs/combobox/parts/DropdownIndicator.js +2 -2
  13. package/cjs/combobox/parts/container/Container.js +5 -5
  14. package/cjs/combobox/parts/container/styled.js +13 -7
  15. package/cjs/combobox/parts/controls/Controls.js +14 -4
  16. package/cjs/combobox/parts/controls/styled.js +22 -13
  17. package/cjs/combobox/parts/controls-input/ControlsInput.js +1 -1
  18. package/cjs/combobox/parts/controls-input/styled.js +7 -3
  19. package/cjs/combobox/parts/controls-input/useControlsInput.js +3 -4
  20. package/cjs/combobox/parts/controls-input/useKeyboardNavigation.js +30 -15
  21. package/cjs/combobox/parts/header-list/HeaderList.js +4 -3
  22. package/cjs/combobox/parts/header-list/useHeaderListHandlers.js +9 -5
  23. package/cjs/combobox/parts/menu-list/MenuList.js +5 -2
  24. package/cjs/combobox/parts/menu-list/styled.js +12 -7
  25. package/cjs/combobox/parts/menu-list/useItemRenderer.js +5 -4
  26. package/cjs/combobox/parts/multi-selected-values-container/MultiSelectedValuesContainer.js +1 -1
  27. package/cjs/combobox/parts/multi-selected-values-container/RemovableSelectedValuePill.js +2 -0
  28. package/cjs/combobox/parts/multi-selected-values-container/useGroupPills.js +13 -10
  29. package/cjs/combobox/theming.js +13 -0
  30. package/cjs/combobox/utils/listHelper.js +2 -1
  31. package/cjs/index.js +16 -7
  32. package/cjs/input-group/InputGroup.js +69 -0
  33. package/cjs/input-group/InputGroupDataTestIds.js +12 -0
  34. package/cjs/input-group/index.js +12 -0
  35. package/cjs/input-group/react-desc-prop-types.js +14 -0
  36. package/cjs/input-group/styled.js +46 -0
  37. package/cjs/mask-hook/hooks/index.js +0 -1
  38. package/cjs/mask-hook/hooks/usePhoneMask.js +2 -2
  39. package/cjs/mask-hook/hooks/useRegExpMask.js +0 -1
  40. package/cjs/mask-hook/index.js +0 -1
  41. package/cjs/text-input/styled/borders.js +1 -1
  42. package/esm/autocomplete/config/useAutocomplete.js +1 -3
  43. package/esm/checkbox/ControlledCheckbox.js +52 -36
  44. package/esm/checkbox/exported-related/data-test-ids.js +6 -0
  45. package/esm/checkbox/exported-related/index.js +2 -0
  46. package/esm/checkbox/exported-related/theming.js +8 -0
  47. package/esm/checkbox/react-desc-prop-types.js +0 -1
  48. package/esm/checkbox/styles.js +25 -15
  49. package/esm/combobox/ComboBoxCTX.js +1 -1
  50. package/esm/combobox/ComboboxDataTestids.js +1 -1
  51. package/esm/combobox/config/useComboBox.js +6 -4
  52. package/esm/combobox/index.js +2 -0
  53. package/esm/combobox/parts/DropdownIndicator.js +2 -2
  54. package/esm/combobox/parts/container/Container.js +7 -7
  55. package/esm/combobox/parts/container/styled.js +13 -6
  56. package/esm/combobox/parts/controls/Controls.js +14 -4
  57. package/esm/combobox/parts/controls/styled.js +22 -13
  58. package/esm/combobox/parts/controls-input/ControlsInput.js +1 -1
  59. package/esm/combobox/parts/controls-input/styled.js +7 -3
  60. package/esm/combobox/parts/controls-input/useControlsInput.js +3 -4
  61. package/esm/combobox/parts/controls-input/useKeyboardNavigation.js +30 -15
  62. package/esm/combobox/parts/header-list/HeaderList.js +4 -3
  63. package/esm/combobox/parts/header-list/useHeaderListHandlers.js +9 -5
  64. package/esm/combobox/parts/menu-list/MenuList.js +5 -2
  65. package/esm/combobox/parts/menu-list/styled.js +12 -7
  66. package/esm/combobox/parts/menu-list/useItemRenderer.js +5 -4
  67. package/esm/combobox/parts/multi-selected-values-container/MultiSelectedValuesContainer.js +1 -1
  68. package/esm/combobox/parts/multi-selected-values-container/RemovableSelectedValuePill.js +2 -0
  69. package/esm/combobox/parts/multi-selected-values-container/useGroupPills.js +13 -10
  70. package/esm/combobox/theming.js +8 -0
  71. package/esm/combobox/utils/listHelper.js +2 -1
  72. package/esm/index.js +5 -1
  73. package/esm/input-group/InputGroup.js +59 -0
  74. package/esm/input-group/InputGroupDataTestIds.js +8 -0
  75. package/esm/input-group/index.js +2 -0
  76. package/esm/input-group/react-desc-prop-types.js +10 -0
  77. package/esm/input-group/styled.js +35 -0
  78. package/esm/mask-hook/hooks/index.js +1 -1
  79. package/esm/mask-hook/hooks/usePhoneMask.js +2 -2
  80. package/esm/mask-hook/hooks/useRegExpMask.js +1 -1
  81. package/esm/mask-hook/index.js +1 -1
  82. package/esm/text-input/styled/borders.js +1 -1
  83. package/package.json +51 -19
  84. package/types/checkbox/exported-related/data-test-ids.d.ts +4 -0
  85. package/types/checkbox/exported-related/index.d.ts +2 -0
  86. package/types/checkbox/exported-related/theming.d.ts +6 -0
  87. package/types/checkbox/react-desc-prop-types.d.ts +3 -3
  88. package/types/checkbox/styles.d.ts +5 -5
  89. package/types/combobox/ComboboxDataTestids.d.ts +1 -1
  90. package/types/combobox/index.d.ts +2 -0
  91. package/types/combobox/parts/container/styled.d.ts +1 -2
  92. package/types/combobox/theming.d.ts +6 -0
  93. package/types/index.d.ts +1 -0
  94. package/types/input-group/InputGroup.d.ts +5 -0
  95. package/types/input-group/InputGroupDataTestIds.d.ts +6 -0
  96. package/types/input-group/index.d.ts +2 -0
  97. package/types/input-group/react-desc-prop-types.d.ts +19 -0
  98. package/types/input-group/styled.d.ts +7 -0
  99. package/types/input-group/tests/DSInputGroup.test.d.ts +1 -0
  100. package/types/mask-hook/hooks/useRegExpMask.d.ts +0 -1
  101. package/types/text-input/config/useInputText.d.ts +5 -5
  102. package/cjs/combobox/parts/menu-list/useMenuListSetFocusOption.js +0 -51
  103. package/esm/combobox/parts/menu-list/useMenuListSetFocusOption.js +0 -47
  104. package/types/combobox/parts/menu-list/useMenuListSetFocusOption.d.ts +0 -1
@@ -28,6 +28,7 @@ const useKeyboardNavigation = () => {
28
28
  inputValue,
29
29
  showPopover,
30
30
  focusOptionIdx,
31
+ listRef,
31
32
  selectAllCheckboxRef,
32
33
  toggleSelectionButtonRef,
33
34
  setShowPopover,
@@ -47,6 +48,14 @@ const useKeyboardNavigation = () => {
47
48
 
48
49
  if (['ArrowDown', 'ArrowUp', 'Enter', 'Spacebar'].includes(e.key) || e.keyCode >= 48 && e.keyCode <= 90) {
49
50
  setShowPopover(true);
51
+ window.requestAnimationFrame(() => {
52
+ if (listRef.current && window.scrollY < listRef.current.offsetHeight) {
53
+ window.scrollTo({
54
+ top: listRef.current.offsetHeight,
55
+ behavior: 'smooth'
56
+ });
57
+ }
58
+ });
50
59
  } // =============================================================================
51
60
  // ESCAPE
52
61
  // =============================================================================
@@ -67,7 +76,7 @@ const useKeyboardNavigation = () => {
67
76
 
68
77
 
69
78
  if (e.key === 'Enter' && (currentItem === null || currentItem === void 0 ? void 0 : currentItem.type) === INTERNAL_MENU_OPTION_TYPES.CREATABLE && onCreate) {
70
- onCreate(inputValue); //blank active item to force search last one
79
+ onCreate(inputValue); // blank active item to force search last one
71
80
 
72
81
  setFocusOptionIdx('');
73
82
  if (onFilter) onFilter(allOptions, '');
@@ -110,9 +119,12 @@ const useKeyboardNavigation = () => {
110
119
  e.stopPropagation();
111
120
 
112
121
  if ((showPopover || inline) && selectableOptions.length) {
113
- const nextItemIndex = findInCircularList(filteredOptions, currentItemIndex, isOptionFocuseable);
114
- setFocusOptionIdx(filteredOptions[nextItemIndex].dsId);
115
- scrollOptionIntoView(filteredOptions[nextItemIndex].dsId);
122
+ const nextItemIndexIndex = findInCircularList(filteredOptions, currentItemIndex, isOptionFocuseable);
123
+
124
+ if (nextItemIndexIndex > -1) {
125
+ setFocusOptionIdx(filteredOptions[nextItemIndexIndex].dsId);
126
+ scrollOptionIntoView(filteredOptions[nextItemIndexIndex].dsId);
127
+ }
116
128
  }
117
129
  }
118
130
 
@@ -122,16 +134,19 @@ const useKeyboardNavigation = () => {
122
134
  if (!selectableOptions.length) return;
123
135
  const prevItemIndex = findInCircularList(filteredOptions, currentItemIndex, isOptionFocuseable, -1);
124
136
 
125
- if (showPopover || inline) {
126
- setFocusOptionIdx(filteredOptions[prevItemIndex].dsId);
127
- scrollOptionIntoView(filteredOptions[prevItemIndex].dsId);
128
- } else {
129
- setShowPopover(true);
130
- setTimeout(() => {
131
- const prevItem = findInCircularList(filteredOptions, 0, isOptionFocuseable, -1);
132
- setFocusOptionIdx(filteredOptions[prevItem].dsId);
133
- scrollOptionIntoView(filteredOptions[prevItem].dsId);
134
- });
137
+ if (prevItemIndex > -1) {
138
+ if (showPopover || inline) {
139
+ setFocusOptionIdx(filteredOptions[prevItemIndex].dsId);
140
+ scrollOptionIntoView(filteredOptions[prevItemIndex].dsId);
141
+ } else {
142
+ // open menu and search last item to focused
143
+ setShowPopover(true);
144
+ const lastItemIndex = findInCircularList(filteredOptions, 0, isOptionFocuseable, -1);
145
+ setFocusOptionIdx(filteredOptions[lastItemIndex].dsId);
146
+ setTimeout(() => {
147
+ scrollOptionIntoView(filteredOptions[lastItemIndex].dsId);
148
+ });
149
+ }
135
150
  }
136
151
  } // =============================================================================
137
152
  // BACKSPACE
@@ -163,7 +178,7 @@ const useKeyboardNavigation = () => {
163
178
  setShowPopover(false);
164
179
  }
165
180
  }, // eslint-disable-next-line react-hooks/exhaustive-deps
166
- [onKeyDown, currentItem, onCreate, multiple, inputValue, inline, withoutPortal, setShowPopover, onCancel, onFilter, setInputValue, focusOptionIdx, showPopover, selectableOptions.length, filteredOptions, currentItemIndex, setFocusOptionIdx, selectedValues, onChange, selectAllCheckboxRef, toggleSelectionButtonRef]);
181
+ [onKeyDown, currentItem, onCreate, multiple, inputValue, inline, withoutPortal, setShowPopover, onCancel, onFilter, setInputValue, listRef, focusOptionIdx, showPopover, selectableOptions.length, filteredOptions, currentItemIndex, setFocusOptionIdx, selectedValues, onChange, selectAllCheckboxRef, toggleSelectionButtonRef]);
167
182
  return {
168
183
  onInputKeyDown
169
184
  };
@@ -14,6 +14,7 @@ const HeaderList = () => {
14
14
  const {
15
15
  props: {
16
16
  selectedValues,
17
+ filteredOptions,
17
18
  onSelectAll
18
19
  },
19
20
  showSelectedOptions,
@@ -32,15 +33,15 @@ const HeaderList = () => {
32
33
  } = useHeaderListHandlers();
33
34
  return /*#__PURE__*/_jsx(StyledHeaderListWrapper, {
34
35
  onKeyDown: handleKeyDown,
35
- onMouseDown: handleOnMouseDown
36
+ onMouseDown: handleOnMouseDown,
37
+ "data-testid": ComboboxDataTestid.MULTISELECT.HEADER_LIST
36
38
  }, void 0, /*#__PURE__*/_jsx(StyledSelectAllCheckbox, {}, void 0, onSelectAll && /*#__PURE__*/_jsx(DSControlledCheckbox, {
37
39
  checked: checkboxStatus,
38
- "aria-controls": checkboxStatus === 'mixed' ? multiSelectedValues.map(item => item.dsId).join(' ') : '',
40
+ "aria-controls": filteredOptions.map(item => item.dsId).join(' '),
39
41
  name: "select-all-checkbox",
40
42
  "aria-label": "Select/Unselect All Items",
41
43
  id: "select-all-checkbox",
42
44
  onChange: handleSelectAllCheckboxChange,
43
- "data-testid": ComboboxDataTestid.MULTISELECT.SELECT_ALL_CHECKBOX,
44
45
  onKeyDown: handleCheckAllOnTab,
45
46
  innerRef: selectAllCheckboxRef
46
47
  })), /*#__PURE__*/_jsx(StyledSelectedItems, {}, void 0, multiSelectedValues.length > 0 ? /*#__PURE__*/_jsx(StyledButtonSelection, {
@@ -51,27 +51,31 @@ const useHeaderListHandlers = () => {
51
51
  e.preventDefault();
52
52
  setShowSelectedOptions(!showSelectedOptions);
53
53
  }, [setShowSelectedOptions, showSelectedOptions]); // when pressing escape on each header list button we close the menu
54
+ // and set focus on input
54
55
 
55
56
  const handleKeyDown = useCallback(e => {
56
57
  if (e.key === 'Escape') {
58
+ var _innerRef$current;
59
+
57
60
  setShowPopover(false);
61
+ (_innerRef$current = innerRef.current) === null || _innerRef$current === void 0 ? void 0 : _innerRef$current.focus();
58
62
  }
59
- }, [setShowPopover]); // when hitting tab on selected values button filter we target the input again
63
+ }, [setShowPopover, innerRef]); // when hitting tab on selected values button filter we target the input again
60
64
 
61
65
  const handleFilterSelectionBtnOnTab = useCallback(e => {
62
66
  if (e.key === 'Tab' && !e.shiftKey) {
63
- var _innerRef$current;
67
+ var _innerRef$current2;
64
68
 
65
69
  e.preventDefault();
66
- (_innerRef$current = innerRef.current) === null || _innerRef$current === void 0 ? void 0 : _innerRef$current.focus();
70
+ (_innerRef$current2 = innerRef.current) === null || _innerRef$current2 === void 0 ? void 0 : _innerRef$current2.focus();
67
71
  }
68
72
  }, [innerRef]);
69
73
  const handleCheckAllOnTab = useCallback(e => {
70
74
  if (e.key === 'Tab' && !e.shiftKey && multiSelectedValues.length === 0) {
71
- var _innerRef$current2;
75
+ var _innerRef$current3;
72
76
 
73
77
  e.preventDefault();
74
- (_innerRef$current2 = innerRef.current) === null || _innerRef$current2 === void 0 ? void 0 : _innerRef$current2.focus();
78
+ (_innerRef$current3 = innerRef.current) === null || _innerRef$current3 === void 0 ? void 0 : _innerRef$current3.focus();
75
79
  }
76
80
  }, [innerRef, multiSelectedValues]);
77
81
  useEffect(() => {
@@ -40,7 +40,9 @@ const MenuList = () => {
40
40
  inline: inline,
41
41
  onMouseDown: preventLoseInputFocus,
42
42
  width: width,
43
- minWidth: menuMinWidth,
43
+ minWidth: menuMinWidth // we use width as key to force react virtual re-render on window resize
44
+ // and update the item height accordly
45
+ ,
44
46
  children: [withHeader && (_HeaderList || (_HeaderList = /*#__PURE__*/_jsx(HeaderList, {}))), filteredOptions.length > 0 || onCreate ? /*#__PURE__*/jsx(StyledVirtualListWrapper, {
45
47
  inline: inline,
46
48
  maxHeight: menuMaxHeight,
@@ -56,9 +58,10 @@ const MenuList = () => {
56
58
  }
57
59
  }, void 0, ItemRenderer)
58
60
  }) : _StyledNoResultsWrapp || (_StyledNoResultsWrapp = /*#__PURE__*/_jsx(StyledNoResultsWrapper, {
61
+ role: "alert",
59
62
  "aria-live": "polite"
60
63
  }, void 0, "No matches found"))]
61
- }), [wrapperListRef, inline, preventLoseInputFocus, width, menuMinWidth, withHeader, filteredOptions.length, onCreate, menuMaxHeight, listRef, virtualListHelpers === null || virtualListHelpers === void 0 ? void 0 : virtualListHelpers.totalSize, ItemRenderer]);
64
+ }, width), [wrapperListRef, inline, preventLoseInputFocus, menuMinWidth, withHeader, filteredOptions.length, onCreate, menuMaxHeight, listRef, virtualListHelpers === null || virtualListHelpers === void 0 ? void 0 : virtualListHelpers.totalSize, ItemRenderer, width]);
62
65
  };
63
66
 
64
67
  export { MenuList };
@@ -2,7 +2,7 @@ import _taggedTemplateLiteral from '@babel/runtime/helpers/esm/taggedTemplateLit
2
2
  import { styled } from '@elliemae/ds-system';
3
3
 
4
4
  var _templateObject, _templateObject2, _templateObject3, _templateObject4, _templateObject5;
5
- const StyledListWrapper = styled.div(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n min-width: ", ";\n width: ", ";\n background-color: #ffffff;\n"])), _ref => {
5
+ const StyledListWrapper = styled.div(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n min-width: ", ";\n width: ", ";\n background-color: #ffffff;\n max-height: ", ";\n z-index: 100;\n"])), _ref => {
6
6
  let {
7
7
  inline,
8
8
  minWidth
@@ -13,18 +13,23 @@ const StyledListWrapper = styled.div(_templateObject || (_templateObject = _tagg
13
13
  width
14
14
  } = _ref2;
15
15
  return "".concat(width, "px");
16
+ }, _ref3 => {
17
+ let {
18
+ maxHeight
19
+ } = _ref3;
20
+ return "".concat(maxHeight, "px");
16
21
  });
17
- const StyledList = styled.ul(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n position: relative;\n padding: 0;\n"])));
18
- const StyledVirtualListWrapper = styled.div(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n overflow-y: auto;\n margin-top: ", ";\n\n max-height: ", ";\n"])), _ref3 => {
22
+ const StyledList = styled.ul(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n position: relative;\n padding: 0;\n background-color: #ffffff;\n"])));
23
+ const StyledVirtualListWrapper = styled.div(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n overflow-y: auto;\n margin-top: ", ";\n max-height: ", ";\n"])), _ref4 => {
19
24
  let {
20
25
  withHeader
21
- } = _ref3;
26
+ } = _ref4;
22
27
  return withHeader ? '28px' : '';
23
- }, _ref4 => {
28
+ }, _ref5 => {
24
29
  let {
25
30
  maxHeight
26
- } = _ref4;
27
- return !maxHeight ? '400px' : "".concat(maxHeight, "px");
31
+ } = _ref5;
32
+ return maxHeight ? "".concat(maxHeight, "px") : '300px';
28
33
  });
29
34
  const StyledCreatableLabel = styled.span(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral(["\n font-weight: bold;\n font-style: italic;\n"])));
30
35
  const StyledNoResultsWrapper = styled.div(_templateObject5 || (_templateObject5 = _taggedTemplateLiteral(["\n padding: 16px;\n"])));
@@ -78,9 +78,10 @@ const useItemRenderer = () => {
78
78
  const generalProps = {
79
79
  wrapperStyles: {
80
80
  position: 'absolute',
81
- top: vItem.start,
81
+ top: 0,
82
82
  left: 0,
83
- width: '100%'
83
+ width: '100%',
84
+ transform: "translateY(".concat(vItem.start, "px)")
84
85
  },
85
86
  key: "".concat(option.dsId),
86
87
  innerRef: vItem.measureRef
@@ -105,8 +106,8 @@ const useItemRenderer = () => {
105
106
  onClick: e => handleClick(option, e),
106
107
  onMouseDown: handleOnMouseDown,
107
108
  isActive: option.dsId === focusOptionIdx,
108
- isSelected: isSelected(selectedValues, option),
109
- tabIndex: -1
109
+ isSelected: isSelected(selectedValues, option) //tabIndex={-1}
110
+
110
111
  }));
111
112
  }
112
113
 
@@ -21,7 +21,7 @@ const MultiSelectedValuesContainer = () => {
21
21
  const correctPillsToShow = useGroupPills();
22
22
  return useMemo(() => /*#__PURE__*/_jsx("div", {
23
23
  style: {
24
- width: 'max-content'
24
+ width: multiSelectedValue.length > 0 ? 'max-content' : '0px'
25
25
  },
26
26
  "data-testid": ComboboxDataTestid.SELECTED_VALUES
27
27
  }, void 0, /*#__PURE__*/_jsx(DSPillGroupV2, {
@@ -25,6 +25,8 @@ const RemovableSelectedValuePill = props => {
25
25
  onRemove: e => {
26
26
  var _innerRef$current;
27
27
 
28
+ // preventing the menu to be opened
29
+ e.stopPropagation();
28
30
  onChange(getSuggestedValueOnChange(pill, selectedValues), pill, e);
29
31
  (_innerRef$current = innerRef.current) === null || _innerRef$current === void 0 ? void 0 : _innerRef$current.focus();
30
32
  }
@@ -25,8 +25,11 @@ const useGroupPills = () => {
25
25
  controlsWrapperRef,
26
26
  pillGroupRef
27
27
  } = useContext(ComboBoxContext);
28
- const multiSelectedValues = selectedValues;
29
- const [pillsToShow, setPillsToShow] = useState(multiSelectedValues.length);
28
+ const multiSelectedValues = selectedValues; // 30 represent 30 pills maximum to calculate the grouped pill. this fix the load time issue
29
+ // when combobox is receiving a huge amount of options.
30
+
31
+ const selectedValuesLength = Math.min(30, multiSelectedValues.length);
32
+ const [pillsToShow, setPillsToShow] = useState(selectedValuesLength);
30
33
  const {
31
34
  width
32
35
  } = useOnElementResize(controlsWrapperRef);
@@ -34,28 +37,28 @@ const useGroupPills = () => {
34
37
  width: widthInput
35
38
  } = useOnElementResize(innerRef || null);
36
39
  useEffect(() => {
37
- if (multiSelectedValues.length !== pillsToShow) {
38
- setPillsToShow(multiSelectedValues.length);
40
+ if (selectedValuesLength !== pillsToShow) {
41
+ setPillsToShow(selectedValuesLength);
39
42
  } // eslint-disable-next-line react-hooks/exhaustive-deps
40
43
 
41
- }, [multiSelectedValues.length, width, widthInput]);
44
+ }, [selectedValuesLength, width, widthInput]);
42
45
  useLayoutEffect(() => {
43
- if (selectedOptionsRef.current) {
46
+ if (selectedOptionsRef.current && pillGroupRef.current) {
44
47
  if (pillGroupRef.current) pillGroupRef.current.style.width = 'max-content';
45
48
  let lastPillFit = -1;
46
49
  let currentWidth = 0;
47
50
  const referenceWidth = selectedOptionsRef.current.offsetWidth;
48
- const pills = [...selectedOptionsRef.current.querySelectorAll(disabled ? '.ds-pill-wrapper-value' : '.ds-pill-wrapper-removable')];
51
+ const pills = [...pillGroupRef.current.querySelectorAll(disabled ? '.ds-pill-wrapper-value' : '.ds-pill-wrapper-removable')];
49
52
  const pillsWidth = pills.map(pill => pill === null || pill === void 0 ? void 0 : pill.offsetWidth);
50
53
  pillsWidth.forEach((pillWidth, idx) => {
51
54
  currentWidth += pillWidth;
52
55
 
53
- if (currentWidth + getGroupedPillWidth(multiSelectedValues.length - idx - 1) <= referenceWidth) {
56
+ if (currentWidth + getGroupedPillWidth(selectedValuesLength - idx - 1) <= referenceWidth) {
54
57
  lastPillFit = idx;
55
58
  }
56
59
  });
57
60
 
58
- if (!(multiSelectedValues.length > 0 && pillsToShow !== multiSelectedValues.length)) {
61
+ if (!(selectedValuesLength > 0 && pillsToShow !== selectedValuesLength)) {
59
62
  const nextPillsToShow = lastPillFit + 1;
60
63
 
61
64
  if (nextPillsToShow !== pillsToShow) {
@@ -65,7 +68,7 @@ const useGroupPills = () => {
65
68
 
66
69
  if (pillGroupRef.current) pillGroupRef.current.style.width = 'fit-content';
67
70
  }
68
- }, [selectedOptionsRef, innerRef, multiSelectedValues, pillsToShow, pillGroupRef, width, widthInput, disabled]);
71
+ }, [selectedOptionsRef, innerRef, multiSelectedValues, pillsToShow, pillGroupRef, width, widthInput, disabled, selectedValuesLength]);
69
72
  return pillsToShow || 1;
70
73
  };
71
74
 
@@ -0,0 +1,8 @@
1
+ const DSComboBoxName = 'ds-combobox';
2
+ const DSComboboxSlots = {
3
+ CONTAINER: 'root',
4
+ INPUT_WRAPPER: 'input-wrapper',
5
+ INPUT: 'input'
6
+ };
7
+
8
+ export { DSComboBoxName, DSComboboxSlots };
@@ -47,7 +47,8 @@ const getFirstOption = (options, selectedValues, inputValue) => {
47
47
 
48
48
  for (let i = 0; i < options.length; i += 1) if (!['section', 'separator'].includes(options[i].type) && !options[i].disabled) {
49
49
  return options[i].dsId;
50
- }
50
+ } // list of disabled item results return ''
51
+
51
52
 
52
53
  return '';
53
54
  };
package/esm/index.js CHANGED
@@ -1,6 +1,10 @@
1
1
  export { DSAutocomplete, DSAutocompleteWithSchema } from './autocomplete/Autocomplete.js';
2
+ export { DSInputGroup, DSInputGroupWithSchema } from './input-group/InputGroup.js';
3
+ export { InputGroupDataTestIds } from './input-group/InputGroupDataTestIds.js';
2
4
  export { DSControlledCheckbox, DSControlledCheckboxWithSchema } from './checkbox/ControlledCheckbox.js';
3
5
  export { DSComboBox, DSComboBox as DSComboBoxV3, DSComboBoxWithSchema } from './combobox/ComboBox.js';
6
+ export { DSComboBoxName, DSComboboxSlots } from './combobox/theming.js';
7
+ export { ComboboxDataTestid } from './combobox/ComboboxDataTestids.js';
4
8
  export { DSControlledDateRangePicker, DSControlledDateRangePickerWithSchema } from './date-range-picker/ControlledDateRangePicker.js';
5
9
  export { ControlledDateRangePickerDatatestid } from './date-range-picker/ControlledDateRangePickerDatatestid.js';
6
10
  export { CONTROLLED_DATE_RANGE_PICKER_TYPES } from './date-range-picker/ControlledDateRangePickerTypes.js';
@@ -14,7 +18,7 @@ export { getValidationTimeStringMetaInfo } from './date-time-picker/utils/timeHe
14
18
  export { UsePhoneMaskWithSchema, getPhoneMaskedValue, usePhoneMask } from './mask-hook/hooks/usePhoneMask.js';
15
19
  export { UseNumberMaskWithSchema, getNumberMaskedValue, useNumberMask } from './mask-hook/hooks/useNumberMask.js';
16
20
  export { UseSSNMaskWithSchema, getSSNMaskedValue, useSSNMask } from './mask-hook/hooks/useSSNMask.js';
17
- export { UseRegExpMaskWithSchema, isRegExp, useRegExpMask } from './mask-hook/hooks/useRegExpMask.js';
21
+ export { UseRegExpMaskWithSchema, useRegExpMask } from './mask-hook/hooks/useRegExpMask.js';
18
22
  export { UseZipCodeMaskWithSchema, getUseZipMaskedValue, useZipCodeMask } from './mask-hook/hooks/useZipCodeMask.js';
19
23
  export { DSInputText, DSInputTextWithSchema } from './text-input/DSInputText.js';
20
24
  export { DSInputTextDataTestIds } from './text-input/exported-related/data-test-ids.js';
@@ -0,0 +1,59 @@
1
+ import 'core-js/modules/esnext.async-iterator.filter.js';
2
+ import 'core-js/modules/esnext.iterator.constructor.js';
3
+ import 'core-js/modules/esnext.iterator.filter.js';
4
+ import 'core-js/modules/esnext.async-iterator.for-each.js';
5
+ import 'core-js/modules/esnext.iterator.for-each.js';
6
+ import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
7
+ import _jsx from '@babel/runtime/helpers/esm/jsx';
8
+ import { useMemo } from 'react';
9
+ import { describe, useValidateTypescriptPropTypes, useGetGlobalAttributes } from '@elliemae/ds-props-helpers';
10
+ import { StyledContainer, StyledLeftAddon, StyledInput, StyledRightAddon } from './styled.js';
11
+ import { propTypes } from './react-desc-prop-types.js';
12
+ import { InputGroupDataTestIds } from './InputGroupDataTestIds.js';
13
+ import { jsxs } from 'react/jsx-runtime';
14
+
15
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
16
+
17
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
18
+
19
+ const DSInputGroup = props => {
20
+ useValidateTypescriptPropTypes(props, propTypes);
21
+ const {
22
+ children,
23
+ leftAddon,
24
+ rightAddon
25
+ } = props;
26
+ const globals = useGetGlobalAttributes(props);
27
+ const cols = useMemo(() => {
28
+ if (leftAddon && rightAddon) {
29
+ return ['max-content', 'auto', 'max-content'];
30
+ }
31
+
32
+ if (leftAddon && !rightAddon) {
33
+ return ['max-content', 'auto'];
34
+ }
35
+
36
+ if (!leftAddon && rightAddon) {
37
+ return ['auto', 'max-content'];
38
+ }
39
+
40
+ return ['auto'];
41
+ }, [leftAddon, rightAddon]);
42
+ return /*#__PURE__*/jsxs(StyledContainer, _objectSpread(_objectSpread({
43
+ cols: cols,
44
+ "data-testid": InputGroupDataTestIds.CONTAINER
45
+ }, globals), {}, {
46
+ children: [leftAddon && /*#__PURE__*/_jsx(StyledLeftAddon, {
47
+ "data-testid": InputGroupDataTestIds.LEFTADDON
48
+ }, void 0, leftAddon), /*#__PURE__*/_jsx(StyledInput, {
49
+ "data-testid": InputGroupDataTestIds.INPUTCONTAINER
50
+ }, void 0, children), rightAddon && /*#__PURE__*/_jsx(StyledRightAddon, {
51
+ "data-testid": InputGroupDataTestIds.RIGHTADDON
52
+ }, void 0, rightAddon)]
53
+ }));
54
+ };
55
+
56
+ const DSInputGroupWithSchema = describe(DSInputGroup);
57
+ DSInputGroupWithSchema.propTypes = propTypes;
58
+
59
+ export { DSInputGroup, DSInputGroupWithSchema };
@@ -0,0 +1,8 @@
1
+ const InputGroupDataTestIds = {
2
+ CONTAINER: 'ds-input-group-container',
3
+ LEFTADDON: 'ds-input-group-left-addon',
4
+ RIGHTADDON: 'ds-input-group-right-addon',
5
+ INPUTCONTAINER: 'ds-input-group-input-container'
6
+ };
7
+
8
+ export { InputGroupDataTestIds };
@@ -0,0 +1,2 @@
1
+ export { DSInputGroup, DSInputGroupWithSchema } from './InputGroup.js';
2
+ export { InputGroupDataTestIds } from './InputGroupDataTestIds.js';
@@ -0,0 +1,10 @@
1
+ import { PropTypes } from '@elliemae/ds-props-helpers';
2
+
3
+ /* eslint-disable @typescript-eslint/no-unused-vars */
4
+ const propTypes = {
5
+ leftAddon: PropTypes.element.description('Component to be added at the left side of the input'),
6
+ rightAddon: PropTypes.element.description('Component to be added at the right side of the input'),
7
+ children: PropTypes.node.isRequired.description('React component to apply autocomplete functionality').defaultValue('')
8
+ };
9
+
10
+ export { propTypes };
@@ -0,0 +1,35 @@
1
+ import styled from 'styled-components';
2
+ import { Grid } from '@elliemae/ds-grid';
3
+ import '../text-input/DSInputText.js';
4
+ import { DSInputTextName, DSInputTextSlots } from '../text-input/exported-related/theming.js';
5
+ import '../combobox/ComboBox.js';
6
+ import { DSComboBoxName, DSComboboxSlots } from '../combobox/theming.js';
7
+
8
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
9
+ const StyledContainer = /*#__PURE__*/styled(Grid).withConfig({
10
+ componentId: "sc-12elcva-0"
11
+ })(["width:100%;height:28px;& > div:nth-child(1){.", "-", ",.", "-", ",.", "-", "{border-top-right-radius:0;border-bottom-right-radius:0;}}& > div:nth-child(2):nth-last-child(2){.", "-", ",.", "-", ",.", "-", "{border-radius:0;}}& > div:nth-child(2):nth-last-child(1){.", "-", ",.", "-", ",.", "-", "{border-top-left-radius:0;border-bottom-left-radius:0;}}"], DSInputTextName, DSInputTextSlots.INPUT_WRAPPER, DSInputTextName, DSInputTextSlots.INPUT, DSComboBoxName, DSComboboxSlots.INPUT_WRAPPER, DSInputTextName, DSInputTextSlots.INPUT_WRAPPER, DSInputTextName, DSInputTextSlots.INPUT, DSComboBoxName, DSComboboxSlots.INPUT_WRAPPER, DSInputTextName, DSInputTextSlots.INPUT_WRAPPER, DSInputTextName, DSInputTextSlots.INPUT, DSComboBoxName, DSComboboxSlots.INPUT_WRAPPER);
12
+ const StyledAddon = /*#__PURE__*/styled.div.withConfig({
13
+ componentId: "sc-12elcva-1"
14
+ })(["outline:1px solid ", ";outline-offset:-1px;height:inherit;display:flex;button{border-width:1px;}&:hover{z-index:1;button:not(:disabled){border:1px solid ", ";}}&:focus-within{z-index:1;}"], _ref => {
15
+ let {
16
+ theme
17
+ } = _ref;
18
+ return theme.colors.neutral['400'];
19
+ }, _ref2 => {
20
+ let {
21
+ theme
22
+ } = _ref2;
23
+ return theme.colors.brand['700'];
24
+ });
25
+ const StyledLeftAddon = /*#__PURE__*/styled(StyledAddon).withConfig({
26
+ componentId: "sc-12elcva-2"
27
+ })(["border-top-left-radius:2px;border-bottom-left-radius:2px;margin-right:-1px;&:hover{button:not(:disabled){border-top-right-radius:0px;border-bottom-right-radius:0px;}}"]);
28
+ const StyledRightAddon = /*#__PURE__*/styled(StyledAddon).withConfig({
29
+ componentId: "sc-12elcva-3"
30
+ })(["border-top-right-radius:2px;border-bottom-right-radius:2px;margin-left:-1px;&:hover{button:not(:disabled){border-top-left-radius:0px;border-bottom-left-radius:0px;}}"]);
31
+ const StyledInput = /*#__PURE__*/styled.div.withConfig({
32
+ componentId: "sc-12elcva-4"
33
+ })(["&:focus-within,&:hover{z-index:1;}"]);
34
+
35
+ export { StyledContainer, StyledInput, StyledLeftAddon, StyledRightAddon };
@@ -1,5 +1,5 @@
1
1
  export { UsePhoneMaskWithSchema, getPhoneMaskedValue, usePhoneMask } from './usePhoneMask.js';
2
2
  export { UseNumberMaskWithSchema, getNumberMaskedValue, useNumberMask } from './useNumberMask.js';
3
3
  export { UseSSNMaskWithSchema, getSSNMaskedValue, useSSNMask } from './useSSNMask.js';
4
- export { UseRegExpMaskWithSchema, isRegExp, useRegExpMask } from './useRegExpMask.js';
4
+ export { UseRegExpMaskWithSchema, useRegExpMask } from './useRegExpMask.js';
5
5
  export { UseZipCodeMaskWithSchema, getUseZipMaskedValue, useZipCodeMask } from './useZipCodeMask.js';
@@ -14,8 +14,8 @@ import 'core-js/modules/esnext.iterator.reduce.js';
14
14
  import { DSMaskPhoneHookPropsTypes, DSMaskPhoneHookDefaultProps } from '../react-desc-prop-types.js';
15
15
 
16
16
  const _excluded = ["valueSetter", "onChange", "onKeyDown", "onBlur"];
17
- const phoneSpecialChars = [['(', 0], [') ', 4], ['-', 9]];
18
- const internationalPhoneSpecialChars = [['+1 (', 0], [') ', 7], ['-', 12]];
17
+ const phoneSpecialChars = [['(', 0], [') ', 4], [' - ', 9]];
18
+ const internationalPhoneSpecialChars = [['+1 (', 0], [') ', 7], [' - ', 12]];
19
19
 
20
20
  const conformValue = (rawValue, cursorPos, lastKeyCode, opts) => {
21
21
  const characters = rawValue.split(''); // Work with digits only
@@ -113,4 +113,4 @@ const useRegExpMask = props => {
113
113
  const UseRegExpMaskWithSchema = describe(useRegExpMask);
114
114
  UseRegExpMaskWithSchema.propTypes = DSMaskRegExpHookPropsTypes;
115
115
 
116
- export { UseRegExpMaskWithSchema, isRegExp, useRegExpMask };
116
+ export { UseRegExpMaskWithSchema, useRegExpMask };
@@ -1,5 +1,5 @@
1
1
  export { UsePhoneMaskWithSchema, getPhoneMaskedValue, usePhoneMask } from './hooks/usePhoneMask.js';
2
2
  export { UseNumberMaskWithSchema, getNumberMaskedValue, useNumberMask } from './hooks/useNumberMask.js';
3
3
  export { UseSSNMaskWithSchema, getSSNMaskedValue, useSSNMask } from './hooks/useSSNMask.js';
4
- export { UseRegExpMaskWithSchema, isRegExp, useRegExpMask } from './hooks/useRegExpMask.js';
4
+ export { UseRegExpMaskWithSchema, useRegExpMask } from './hooks/useRegExpMask.js';
5
5
  export { UseZipCodeMaskWithSchema, getUseZipMaskedValue, useZipCodeMask } from './hooks/useZipCodeMask.js';
@@ -7,7 +7,7 @@ const readOnlyBorderCss = css(_templateObject2 || (_templateObject2 = _taggedTem
7
7
  const disabledBorderCss = commonBorderCss;
8
8
  const hasErrorBorderCss = css(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n border: 1px solid ", ";\n"])), th.color('danger-900'));
9
9
  const hoverBorderCss = css(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral(["\n border: 1px solid ", ";\n"])), th.color('brand-700'));
10
- const focusBorderCss = css(_templateObject5 || (_templateObject5 = _taggedTemplateLiteral(["\n border: 1px solid transparent;\n outline: 2px solid ", ";\n outline-offset: -1px;\n"])), th.color('brand-700'));
10
+ const focusBorderCss = css(_templateObject5 || (_templateObject5 = _taggedTemplateLiteral(["\n border: 1px solid transparent;\n outline: 2px solid ", ";\n outline-offset: -2px;\n"])), th.color('brand-700'));
11
11
  const getBorderCss = props => {
12
12
  if (props.isDisabled) return disabledBorderCss;
13
13
  if (props.hasFocus) return focusBorderCss;