@dhis2-ui/select 10.13.0-alpha.1 → 10.13.0

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 (28) hide show
  1. package/build/cjs/locales/en/translations.json +2 -0
  2. package/build/cjs/multi-select/input.js +20 -11
  3. package/build/cjs/multi-select/multi-select.js +5 -1
  4. package/build/cjs/multi-select/multi-select.prod.stories.js +42 -1
  5. package/build/cjs/simple-single-select/menu/filter.js +23 -36
  6. package/build/cjs/simple-single-select/menu/menu.js +4 -36
  7. package/build/cjs/simple-single-select/menu/options-list.js +5 -13
  8. package/build/cjs/simple-single-select/selected-value/selected-value.js +26 -1
  9. package/build/cjs/simple-single-select/simple-single-select.js +20 -16
  10. package/build/cjs/simple-single-select/use-handle-key-press/use-handle-key-press-on-combobox.js +24 -15
  11. package/build/cjs/simple-single-select/use-handle-key-press/use-handle-key-press-on-filter-input.js +1 -3
  12. package/build/cjs/simple-single-select-field/simple-single-select-field.js +23 -3
  13. package/build/cjs/simple-single-select-field/simple-single-select-field.test.js +5 -2
  14. package/build/es/locales/en/translations.json +2 -0
  15. package/build/es/multi-select/input.js +16 -7
  16. package/build/es/multi-select/multi-select.js +5 -1
  17. package/build/es/multi-select/multi-select.prod.stories.js +40 -0
  18. package/build/es/simple-single-select/menu/filter.js +22 -33
  19. package/build/es/simple-single-select/menu/menu.js +4 -36
  20. package/build/es/simple-single-select/menu/options-list.js +5 -13
  21. package/build/es/simple-single-select/selected-value/selected-value.js +26 -1
  22. package/build/es/simple-single-select/simple-single-select.js +20 -16
  23. package/build/es/simple-single-select/use-handle-key-press/use-handle-key-press-on-combobox.js +24 -15
  24. package/build/es/simple-single-select/use-handle-key-press/use-handle-key-press-on-filter-input.js +1 -3
  25. package/build/es/simple-single-select-field/simple-single-select-field.js +23 -3
  26. package/build/es/simple-single-select-field/simple-single-select-field.test.js +5 -2
  27. package/package.json +15 -15
  28. package/types/index.d.ts +4 -0
@@ -58,7 +58,6 @@ export function SimpleSingleSelect(_ref2) {
58
58
  disabled = false,
59
59
  empty: _empty = false,
60
60
  error = false,
61
- filterHelpText = '',
62
61
  filterLabel = '',
63
62
  filterPlaceholder: _filterPlaceholder = '',
64
63
  filterValue = '',
@@ -95,7 +94,7 @@ export function SimpleSingleSelect(_ref2) {
95
94
  const comboBoxId = `${name}-combo`;
96
95
  const comboBoxRef = useRef();
97
96
  const listBoxRef = useRef();
98
- const filterRef = useRef();
97
+ const filterInputRef = useRef();
99
98
  const [focussedOptionIndex, setFocussedOptionIndex] = useFocussedOptionIndex({
100
99
  filterable,
101
100
  filterValue,
@@ -103,6 +102,14 @@ export function SimpleSingleSelect(_ref2) {
103
102
  });
104
103
  const [selectRef, setSelectRef] = useState();
105
104
  const [expanded, setExpanded] = useState(false);
105
+ useEffect(() => {
106
+ if (expanded && filterable) {
107
+ requestAnimationFrame(() => {
108
+ var _filterInputRef$curre;
109
+ (_filterInputRef$curre = filterInputRef.current) === null || _filterInputRef$curre === void 0 ? void 0 : _filterInputRef$curre.focus();
110
+ });
111
+ }
112
+ }, [expanded, filterable]);
106
113
  const closeMenu = useCallback(() => setExpanded(false), []);
107
114
  const selectedValue = (selected === null || selected === void 0 ? void 0 : selected.value) || '';
108
115
  const selectedLabel = (selected === null || selected === void 0 ? void 0 : selected.label) || '';
@@ -146,9 +153,10 @@ export function SimpleSingleSelect(_ref2) {
146
153
  focussedOptionIndex,
147
154
  setFocussedOptionIndex,
148
155
  selectFocussedOption,
149
- filterRef,
150
156
  clearable,
151
- onClear
157
+ onClear,
158
+ filterable,
159
+ onFilterChange
152
160
  });
153
161
  const handleKeyDownOnFilterInput = useHandleKeyPressOnFilterInput({
154
162
  value: selectedValue,
@@ -188,6 +196,11 @@ export function SimpleSingleSelect(_ref2) {
188
196
  disabled: disabled,
189
197
  error: error,
190
198
  expanded: expanded,
199
+ filterLabel: filterLabel,
200
+ filterPlaceholder: filterPlaceholder,
201
+ filterRef: filterInputRef,
202
+ filterable: filterable,
203
+ filterValue: filterValue,
191
204
  hasSelection: !!selectedValue,
192
205
  inputMaxHeight: inputMaxHeight,
193
206
  labelledBy: labelledBy,
@@ -201,6 +214,8 @@ export function SimpleSingleSelect(_ref2) {
201
214
  onBlur: onBlur,
202
215
  onClear: onClear,
203
216
  onClick: toggleMenu,
217
+ onFilterChange: onFilterChange,
218
+ onFilterInputKeyDown: handleKeyDownOnFilterInput,
204
219
  onFocus: onFocus,
205
220
  onKeyDown: handleKeyDown
206
221
  }), /*#__PURE__*/React.createElement(Menu, {
@@ -208,13 +223,8 @@ export function SimpleSingleSelect(_ref2) {
208
223
  optionComponent: optionComponent,
209
224
  disabled: disabled,
210
225
  empty: empty,
211
- filterHelpText: filterHelpText,
212
- filterLabel: filterLabel,
213
- filterable: filterable,
214
226
  filterValue: filterValue,
215
- filterPlaceholder: filterPlaceholder,
216
227
  focussedOptionIndex: focussedOptionIndex,
217
- onFilterInputKeyDown: handleKeyDownOnFilterInput,
218
228
  hidden: !expanded,
219
229
  name: name,
220
230
  labelledBy: labelledBy,
@@ -227,17 +237,13 @@ export function SimpleSingleSelect(_ref2) {
227
237
  options: options,
228
238
  selectRef: selectRef,
229
239
  selectedValue: selectedValue,
230
- tabIndex: tabIndex.toString(),
231
240
  onBlur: onBlur,
232
241
  onChange: nextValue => {
233
242
  onChange(nextValue);
234
243
  closeMenu();
235
244
  },
236
245
  onClose: closeMenu,
237
- onEndReached: onEndReached,
238
- onFilterChange: onFilterChange,
239
- filterRef: filterRef,
240
- onOptionsKeyDown: handleKeyDown
246
+ onEndReached: onEndReached
241
247
  }));
242
248
  }
243
249
  SimpleSingleSelect.propTypes = {
@@ -265,8 +271,6 @@ SimpleSingleSelect.propTypes = {
265
271
  empty: PropTypes.node,
266
272
  /** Applies 'error' appearance for validation feedback. Mutually exclusive with `warning` and `valid` props **/
267
273
  error: sharedPropTypes.statusPropType,
268
- /** Help text that will be displayed below the input **/
269
- filterHelpText: PropTypes.string,
270
274
  /** Value will be used as aria-label attribute on the filter input **/
271
275
  filterLabel: PropTypes.string,
272
276
  /** Placeholder for the filter input **/
@@ -4,12 +4,21 @@ import { useHandleTyping } from './use-handle-typing.js';
4
4
  import { usePageDown } from './use-page-down.js';
5
5
  import { usePageUp } from './use-page-up.js';
6
6
  import { findNextOptionIndex, findPrevOptionIndex, findFirstOptionIndex, findLastOptionIndex } from './utils.js';
7
- function useSelectOption(findIndexCallback, _ref) {
7
+ function isUnmodifiedCharacterKey(_ref) {
8
+ let {
9
+ key,
10
+ altKey,
11
+ ctrlKey,
12
+ metaKey
13
+ } = _ref;
14
+ return key.length === 1 && key !== ' ' && !altKey && !ctrlKey && !metaKey;
15
+ }
16
+ function useSelectOption(findIndexCallback, _ref2) {
8
17
  let {
9
18
  options,
10
19
  onChange,
11
20
  value
12
- } = _ref;
21
+ } = _ref2;
13
22
  return useCallback(() => {
14
23
  const currentOptionIndex = options.findIndex(option => option.value === value);
15
24
  const nextSelectedOptionIndex = findIndexCallback({
@@ -26,7 +35,7 @@ function useSelectOption(findIndexCallback, _ref) {
26
35
  });
27
36
  }, [findIndexCallback, options, onChange, value]);
28
37
  }
29
- export function useHandleKeyPressOnCombobox(_ref2) {
38
+ export function useHandleKeyPressOnCombobox(_ref3) {
30
39
  let {
31
40
  value,
32
41
  disabled,
@@ -40,10 +49,11 @@ export function useHandleKeyPressOnCombobox(_ref2) {
40
49
  setFocussedOptionIndex,
41
50
  selectFocussedOption,
42
51
  onChange,
43
- filterRef,
44
52
  clearable,
45
- onClear
46
- } = _ref2;
53
+ onClear,
54
+ filterable,
55
+ onFilterChange
56
+ } = _ref3;
47
57
  const {
48
58
  onTyping,
49
59
  typing
@@ -98,9 +108,7 @@ export function useHandleKeyPressOnCombobox(_ref2) {
98
108
  const handleKeyPress = useCallback(event => {
99
109
  const {
100
110
  key,
101
- altKey,
102
- ctrlKey,
103
- metaKey
111
+ altKey
104
112
  } = event;
105
113
  if (disabled || loading) {
106
114
  return;
@@ -154,10 +162,6 @@ export function useHandleKeyPressOnCombobox(_ref2) {
154
162
  return;
155
163
  }
156
164
  if (key === 'ArrowUp') {
157
- if (filterRef !== null && filterRef !== void 0 && filterRef.current && focussedOptionIndex === 0) {
158
- filterRef.current.focus();
159
- return;
160
- }
161
165
  focusPrevOption();
162
166
  return;
163
167
  }
@@ -169,7 +173,12 @@ export function useHandleKeyPressOnCombobox(_ref2) {
169
173
  focusLastOption();
170
174
  return;
171
175
  }
172
- if (key === 'Backspace' || key === 'Clear' || key.length === 1 && key !== ' ' && !altKey && !ctrlKey && !metaKey || key === ' ' && typing) {
176
+ if (filterable && !expanded && isUnmodifiedCharacterKey(event)) {
177
+ openMenu();
178
+ onFilterChange === null || onFilterChange === void 0 ? void 0 : onFilterChange(key);
179
+ return;
180
+ }
181
+ if (key === 'Backspace' || key === 'Clear' || isUnmodifiedCharacterKey(event) || key === ' ' && typing) {
173
182
  onTyping(key);
174
183
  return;
175
184
  }
@@ -183,6 +192,6 @@ export function useHandleKeyPressOnCombobox(_ref2) {
183
192
  }
184
193
 
185
194
  // Do nothing
186
- }, [closeMenu, disabled, expanded, loading, openMenu, options, value, typing, focussedOptionIndex, selectFocussedOption, selectNextOption, selectPrevOption, focusNextOption, focusPrevOption, focusFirstOption, focusLastOption, pageDown, pageUp, onTyping, filterRef]);
195
+ }, [closeMenu, disabled, expanded, loading, openMenu, options, value, typing, focussedOptionIndex, selectFocussedOption, selectNextOption, selectPrevOption, focusNextOption, focusPrevOption, focusFirstOption, focusLastOption, pageDown, pageUp, onTyping, filterable, onFilterChange]);
187
196
  return handleKeyPress;
188
197
  }
@@ -66,10 +66,8 @@ export function useHandleKeyPressOnFilterInput(_ref) {
66
66
  return;
67
67
  }
68
68
  if (key === 'ArrowDown') {
69
- var _listBoxRef$current;
70
69
  e.preventDefault(); // Disable moving cursor to end
71
70
  focusNextOption();
72
- (_listBoxRef$current = listBoxRef.current) === null || _listBoxRef$current === void 0 ? void 0 : _listBoxRef$current.focus();
73
71
  return;
74
72
  }
75
73
  if (key === 'ArrowUp') {
@@ -97,6 +95,6 @@ export function useHandleKeyPressOnFilterInput(_ref) {
97
95
  }
98
96
 
99
97
  // Do nothing
100
- }, [closeMenu, options, value, loading, focussedOptionIndex, selectFocussedOption, focusComboBox, focusNextOption, focusPrevOption, focusFirstOption, focusLastOption, pageDown, pageUp, listBoxRef]);
98
+ }, [closeMenu, options, value, loading, focussedOptionIndex, selectFocussedOption, focusComboBox, focusNextOption, focusPrevOption, focusFirstOption, focusLastOption, pageDown, pageUp]);
101
99
  return handleKeyPress;
102
100
  }
@@ -6,6 +6,7 @@ import PropTypes from 'prop-types';
6
6
  import React from 'react';
7
7
  import { SimpleSingleSelect, optionProp } from '../simple-single-select/index.js';
8
8
  export function SimpleSingleSelectField(props) {
9
+ var _ref, _selectedOption$label;
9
10
  const {
10
11
  className,
11
12
  dataTest,
@@ -14,12 +15,28 @@ export function SimpleSingleSelectField(props) {
14
15
  helpText,
15
16
  label,
16
17
  name,
18
+ onChange,
19
+ options,
17
20
  required,
18
21
  valid,
19
22
  validationText,
23
+ value,
24
+ valueLabel,
20
25
  warning
21
26
  } = props;
22
27
  const labelId = `${name}-label`;
28
+ const selectedOption = options.find(opt => opt.value === value);
29
+ const selected = value != null && value !== '' ? {
30
+ value,
31
+ label: (_ref = (_selectedOption$label = selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.label) !== null && _selectedOption$label !== void 0 ? _selectedOption$label : valueLabel) !== null && _ref !== void 0 ? _ref : ''
32
+ } : undefined;
33
+ const handleChange = option => {
34
+ var _option$value;
35
+ onChange((_option$value = option === null || option === void 0 ? void 0 : option.value) !== null && _option$value !== void 0 ? _option$value : '');
36
+ };
37
+ const handleClear = () => {
38
+ onChange('');
39
+ };
23
40
  return /*#__PURE__*/React.createElement(Field, {
24
41
  className: className,
25
42
  dataTest: dataTest,
@@ -33,7 +50,10 @@ export function SimpleSingleSelectField(props) {
33
50
  warning: warning,
34
51
  valid: valid
35
52
  }, /*#__PURE__*/React.createElement(SimpleSingleSelect, _extends({}, props, {
36
- labelledBy: labelId
53
+ labelledBy: labelId,
54
+ selected: selected,
55
+ onChange: handleChange,
56
+ onClear: handleClear
37
57
  })));
38
58
  }
39
59
  SimpleSingleSelectField.propTypes = {
@@ -108,10 +128,10 @@ SimpleSingleSelectField.propTypes = {
108
128
  * be used to supply the text to be shown.
109
129
  **/
110
130
  valueLabel: requiredIf(props => {
111
- if (props.options.find(_ref => {
131
+ if (props.options.find(_ref2 => {
112
132
  let {
113
133
  value
114
- } = _ref;
134
+ } = _ref2;
115
135
  return props.value === value;
116
136
  })) {
117
137
  return false;
@@ -23,7 +23,7 @@ describe('<SimpleSingleSelectField />', () => {
23
23
  it('should forward props to the SimpleSingleSelect component', () => {
24
24
  const options = [];
25
25
  const optionComponent = () => null;
26
- const onChange = () => null;
26
+ const onChange = jest.fn();
27
27
  const onBlur = () => null;
28
28
  const onEndReached = () => null;
29
29
  const onFilterChange = () => null;
@@ -67,7 +67,10 @@ describe('<SimpleSingleSelectField />', () => {
67
67
  }));
68
68
  expect(SimpleSingleSelect.mock.calls[0][0].name).toBe('foo');
69
69
  expect(SimpleSingleSelect.mock.calls[0][0].options).toBe(options);
70
- expect(SimpleSingleSelect.mock.calls[0][0].onChange).toBe(onChange);
70
+ SimpleSingleSelect.mock.calls[0][0].onChange({
71
+ value: 'test'
72
+ });
73
+ expect(onChange).toHaveBeenCalledWith('test');
71
74
  expect(SimpleSingleSelect.mock.calls[0][0].autoFocus).toBe(false);
72
75
  expect(SimpleSingleSelect.mock.calls[0][0].className).toBe('');
73
76
  expect(SimpleSingleSelect.mock.calls[0][0].clearText).toBe('');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhis2-ui/select",
3
- "version": "10.13.0-alpha.1",
3
+ "version": "10.13.0",
4
4
  "description": "UI Select",
5
5
  "repository": {
6
6
  "type": "git",
@@ -33,21 +33,21 @@
33
33
  "styled-jsx": "^4"
34
34
  },
35
35
  "dependencies": {
36
- "@dhis2-ui/box": "10.13.0-alpha.1",
37
- "@dhis2-ui/button": "10.13.0-alpha.1",
38
- "@dhis2-ui/card": "10.13.0-alpha.1",
39
- "@dhis2-ui/checkbox": "10.13.0-alpha.1",
40
- "@dhis2-ui/chip": "10.13.0-alpha.1",
41
- "@dhis2-ui/field": "10.13.0-alpha.1",
42
- "@dhis2-ui/input": "10.13.0-alpha.1",
43
- "@dhis2-ui/layer": "10.13.0-alpha.1",
44
- "@dhis2-ui/loader": "10.13.0-alpha.1",
45
- "@dhis2-ui/popper": "10.13.0-alpha.1",
46
- "@dhis2-ui/status-icon": "10.13.0-alpha.1",
47
- "@dhis2-ui/tooltip": "10.13.0-alpha.1",
36
+ "@dhis2-ui/box": "10.13.0",
37
+ "@dhis2-ui/button": "10.13.0",
38
+ "@dhis2-ui/card": "10.13.0",
39
+ "@dhis2-ui/checkbox": "10.13.0",
40
+ "@dhis2-ui/chip": "10.13.0",
41
+ "@dhis2-ui/field": "10.13.0",
42
+ "@dhis2-ui/input": "10.13.0",
43
+ "@dhis2-ui/layer": "10.13.0",
44
+ "@dhis2-ui/loader": "10.13.0",
45
+ "@dhis2-ui/popper": "10.13.0",
46
+ "@dhis2-ui/status-icon": "10.13.0",
47
+ "@dhis2-ui/tooltip": "10.13.0",
48
48
  "@dhis2/prop-types": "^3.1.2",
49
- "@dhis2/ui-constants": "10.13.0-alpha.1",
50
- "@dhis2/ui-icons": "10.13.0-alpha.1",
49
+ "@dhis2/ui-constants": "10.13.0",
50
+ "@dhis2/ui-icons": "10.13.0",
51
51
  "classnames": "^2.3.1",
52
52
  "prop-types": "^15.7.2"
53
53
  },
package/types/index.d.ts CHANGED
@@ -51,6 +51,10 @@ export interface MultiSelectProps {
51
51
  * Adds a 'clear' option to the menu
52
52
  */
53
53
  clearable?: boolean
54
+ /**
55
+ * When the number of selected items exceeds this threshold, chips are replaced with "X selected" text
56
+ */
57
+ collapseSelectionAfter?: number
54
58
  dataTest?: string
55
59
  dense?: boolean
56
60
  disabled?: boolean