@dhis2-ui/select 10.17.0 → 10.19.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 (32) hide show
  1. package/build/cjs/simple-single-select/__stories__/WithMenuMaxWidth.js +34 -0
  2. package/build/cjs/simple-single-select/__stories__/WithMenuMinWidth.js +37 -0
  3. package/build/cjs/simple-single-select/menu/menu.js +17 -8
  4. package/build/cjs/simple-single-select/simple-single-select.js +19 -9
  5. package/build/cjs/simple-single-select/simple-single-select.prod.stories.js +14 -0
  6. package/build/cjs/simple-single-select/simple-single-select.test.js +62 -0
  7. package/build/cjs/simple-single-select-field/simple-single-select-field.js +4 -0
  8. package/build/cjs/simple-single-select-field/simple-single-select-field.prod.stories.js +53 -2
  9. package/build/cjs/simple-single-select-field/simple-single-select-field.test.js +4 -0
  10. package/build/cjs/single-select-option/single-select-option.js +4 -4
  11. package/build/es/simple-single-select/__stories__/WithMenuMaxWidth.js +26 -0
  12. package/build/es/simple-single-select/__stories__/WithMenuMinWidth.js +29 -0
  13. package/build/es/simple-single-select/menu/menu.js +17 -8
  14. package/build/es/simple-single-select/simple-single-select.js +19 -9
  15. package/build/es/simple-single-select/simple-single-select.prod.stories.js +2 -0
  16. package/build/es/simple-single-select/simple-single-select.test.js +62 -0
  17. package/build/es/simple-single-select-field/simple-single-select-field.js +4 -0
  18. package/build/es/simple-single-select-field/simple-single-select-field.prod.stories.js +49 -0
  19. package/build/es/simple-single-select-field/simple-single-select-field.test.js +4 -0
  20. package/build/es/single-select-option/single-select-option.js +4 -4
  21. package/package.json +15 -15
  22. package/src/simple-single-select/__stories__/WithMenuMaxWidth.js +24 -0
  23. package/src/simple-single-select/__stories__/WithMenuMinWidth.js +25 -0
  24. package/src/simple-single-select/menu/menu.js +26 -8
  25. package/src/simple-single-select/simple-single-select.js +19 -6
  26. package/src/simple-single-select/simple-single-select.prod.stories.js +2 -0
  27. package/src/simple-single-select/simple-single-select.test.js +68 -0
  28. package/src/simple-single-select-field/simple-single-select-field.js +6 -0
  29. package/src/simple-single-select-field/simple-single-select-field.prod.stories.js +49 -0
  30. package/src/simple-single-select-field/simple-single-select-field.test.js +4 -0
  31. package/src/single-select-option/single-select-option.js +5 -3
  32. package/types/index.d.ts +45 -1
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.WithMenuMaxWidth = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _simpleSingleSelect = require("../simple-single-select.js");
9
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
10
+ const options = [{
11
+ value: '1',
12
+ label: 'option one'
13
+ }, {
14
+ value: '2',
15
+ label: 'option two'
16
+ }, {
17
+ value: '3',
18
+ label: 'A much longer option label that gets clamped'
19
+ }];
20
+ const WithMenuMaxWidth = () => {
21
+ const [selected, setSelected] = (0, _react.useState)(null);
22
+ return /*#__PURE__*/_react.default.createElement("div", {
23
+ style: {
24
+ width: 120
25
+ }
26
+ }, /*#__PURE__*/_react.default.createElement(_simpleSingleSelect.SimpleSingleSelect, {
27
+ name: "simple",
28
+ selected: selected,
29
+ onChange: setSelected,
30
+ options: options,
31
+ menuMaxWidth: "200px"
32
+ }));
33
+ };
34
+ exports.WithMenuMaxWidth = WithMenuMaxWidth;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.WithMenuMinWidth = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _simpleSingleSelect = require("../simple-single-select.js");
9
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
10
+ const options = [{
11
+ value: '1',
12
+ label: 'option one'
13
+ }, {
14
+ value: '2',
15
+ label: 'option two'
16
+ }, {
17
+ value: '3',
18
+ label: 'option three'
19
+ }, {
20
+ value: '4',
21
+ label: 'A longer option that exceeds the minimum'
22
+ }];
23
+ const WithMenuMinWidth = () => {
24
+ const [selected, setSelected] = (0, _react.useState)(null);
25
+ return /*#__PURE__*/_react.default.createElement("div", {
26
+ style: {
27
+ width: 120
28
+ }
29
+ }, /*#__PURE__*/_react.default.createElement(_simpleSingleSelect.SimpleSingleSelect, {
30
+ name: "simple",
31
+ selected: selected,
32
+ onChange: setSelected,
33
+ options: options,
34
+ menuMinWidth: "240px"
35
+ }));
36
+ };
37
+ exports.WithMenuMinWidth = WithMenuMinWidth;
@@ -34,6 +34,8 @@ function Menu({
34
34
  loading,
35
35
  loadingText,
36
36
  maxHeight,
37
+ maxWidth,
38
+ minWidth,
37
39
  noMatchText,
38
40
  optionUpdateStrategy,
39
41
  selectRef,
@@ -42,17 +44,16 @@ function Menu({
42
44
  onClose,
43
45
  onEndReached
44
46
  }) {
45
- const [menuWidth, setWidth] = (0, _react.useState)('auto');
47
+ const [selectWidth, setSelectWidth] = (0, _react.useState)();
46
48
  const dataTestPrefix = `${dataTest}-menu`;
49
+
50
+ // Re-measuring whenever `hidden` changes keeps the width current when the
51
+ // select's container has been resized since the menu was last opened
47
52
  (0, _react.useEffect)(() => {
48
53
  if (selectRef) {
49
- const callback = () => setWidth(`${selectRef.offsetWidth}px`);
50
- callback(); // We want to know the width as soon as the
51
-
52
- selectRef.addEventListener('resize', callback);
53
- return () => selectRef.removeEventListener('resize', callback);
54
+ setSelectWidth(`${selectRef.offsetWidth}px`);
54
55
  }
55
- }, [selectRef]);
56
+ }, [selectRef, hidden]);
56
57
  if (hidden) {
57
58
  return null;
58
59
  }
@@ -61,6 +62,10 @@ function Menu({
61
62
  // we're in the process of loading options
62
63
  !loading;
63
64
  const isEmpty = !options.length && !filterValue;
65
+ const flexible = Boolean(minWidth || maxWidth);
66
+ // We never want the menu narrower than the select, so a maxWidth below
67
+ // the select's width intentionally has no effect
68
+ const flexibleMinWidth = minWidth && selectWidth ? `max(${selectWidth}, ${minWidth})` : minWidth || selectWidth;
64
69
  return /*#__PURE__*/_react.default.createElement(_layer.Layer, {
65
70
  onBackdropClick: onClose,
66
71
  transparent: true
@@ -70,7 +75,9 @@ function Menu({
70
75
  observeReferenceResize: true
71
76
  }, /*#__PURE__*/_react.default.createElement("div", {
72
77
  style: {
73
- width: menuWidth,
78
+ width: flexible ? 'fit-content' : selectWidth,
79
+ minWidth: flexible ? flexibleMinWidth : undefined,
80
+ maxWidth,
74
81
  maxHeight
75
82
  },
76
83
  className: _style.default.dynamic([["2949029222", [_uiConstants.colors.white, _uiConstants.colors.grey200, _uiConstants.elevations.e300]]]) + " " + "menu"
@@ -121,6 +128,8 @@ Menu.propTypes = {
121
128
  loading: _propTypes.default.bool,
122
129
  loadingText: _propTypes.default.string,
123
130
  maxHeight: _propTypes.default.string,
131
+ maxWidth: _propTypes.default.string,
132
+ minWidth: _propTypes.default.string,
124
133
  noMatchText: _propTypes.default.string,
125
134
  optionComponent: _propTypes.default.elementType,
126
135
  optionUpdateStrategy: _propTypes.default.oneOf(['off', 'polite', 'assertive']),
@@ -16,6 +16,11 @@ var _sharedPropTypes = require("./shared-prop-types.js");
16
16
  var _index4 = require("./use-handle-key-press/index.js");
17
17
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
18
18
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
19
+ const defaultSelected = {
20
+ label: '',
21
+ value: ''
22
+ };
23
+ const noop = () => undefined;
19
24
  function useFocussedOptionIndex({
20
25
  filterable,
21
26
  filterValue,
@@ -73,22 +78,21 @@ function SimpleSingleSelect({
73
78
  loading = false,
74
79
  menuLoadingText: _menuLoadingText = '',
75
80
  menuMaxHeight = '288px',
81
+ menuMaxWidth,
82
+ menuMinWidth,
76
83
  noMatchText: _noMatchText = '',
77
84
  optionUpdateStrategy = 'polite',
78
85
  placeholder = '',
79
86
  prefix = '',
80
- selected = {
81
- label: '',
82
- value: ''
83
- },
87
+ selected = defaultSelected,
84
88
  tabIndex = '0',
85
89
  valid = false,
86
90
  warning = false,
87
- onBlur = () => undefined,
88
- onClear = () => undefined,
89
- onEndReached = () => undefined,
90
- onFilterChange = () => undefined,
91
- onFocus = () => undefined
91
+ onBlur = noop,
92
+ onClear = noop,
93
+ onEndReached = noop,
94
+ onFilterChange = noop,
95
+ onFocus = noop
92
96
  }) {
93
97
  // We can't translate with default props as the translation function would
94
98
  // be called before we get any translations from the consuming app/lib
@@ -238,6 +242,8 @@ function SimpleSingleSelect({
238
242
  loading: loading,
239
243
  loadingText: menuLoadingText,
240
244
  maxHeight: menuMaxHeight,
245
+ maxWidth: menuMaxWidth,
246
+ minWidth: menuMinWidth,
241
247
  noMatchText: noMatchText,
242
248
  optionUpdateStrategy: optionUpdateStrategy,
243
249
  options: options,
@@ -295,6 +301,10 @@ SimpleSingleSelect.propTypes = {
295
301
  menuLoadingText: _propTypes2.default.string,
296
302
  /** Allows to modify the max height of the menu **/
297
303
  menuMaxHeight: _propTypes2.default.string,
304
+ /** See [dropdown menu width](https://developers.dhis2.org/docs/ui/components/select#dropdown-menu-width) **/
305
+ menuMaxWidth: _propTypes2.default.string,
306
+ /** See [dropdown menu width](https://developers.dhis2.org/docs/ui/components/select#dropdown-menu-width) **/
307
+ menuMinWidth: _propTypes2.default.string,
298
308
  /** String that will be displayed when the select is being filtered but the options array is empty **/
299
309
  noMatchText: (0, _propTypes.requiredIf)(props => props.filterable, _propTypes2.default.string),
300
310
  /** Allows to override what's rendered inside the `button[role="option"]`.
@@ -99,6 +99,18 @@ Object.defineProperty(exports, "WithManyOptions", {
99
99
  return _WithManyOptions.WithManyOptions;
100
100
  }
101
101
  });
102
+ Object.defineProperty(exports, "WithMenuMaxWidth", {
103
+ enumerable: true,
104
+ get: function () {
105
+ return _WithMenuMaxWidth.WithMenuMaxWidth;
106
+ }
107
+ });
108
+ Object.defineProperty(exports, "WithMenuMinWidth", {
109
+ enumerable: true,
110
+ get: function () {
111
+ return _WithMenuMinWidth.WithMenuMinWidth;
112
+ }
113
+ });
102
114
  Object.defineProperty(exports, "WithMultipleSelectsAndScrollableParent", {
103
115
  enumerable: true,
104
116
  get: function () {
@@ -226,6 +238,8 @@ var _WithOptionsAndLoadingText = require("./__stories__/WithOptionsAndLoadingTex
226
238
  var _WithoutOptionsAndLoading = require("./__stories__/WithoutOptionsAndLoading.js");
227
239
  var _WithManyOptions = require("./__stories__/WithManyOptions.js");
228
240
  var _WithCustomLowMaxHeight = require("./__stories__/WithCustomLowMaxHeight.js");
241
+ var _WithMenuMinWidth = require("./__stories__/WithMenuMinWidth.js");
242
+ var _WithMenuMaxWidth = require("./__stories__/WithMenuMaxWidth.js");
229
243
  var _WithOptionsAndDisabled = require("./__stories__/WithOptionsAndDisabled.js");
230
244
  var _WithSelectionAndDisabled = require("./__stories__/WithSelectionAndDisabled.js");
231
245
  var _WithPrefix = require("./__stories__/WithPrefix.js");
@@ -5,6 +5,7 @@ var _react = require("@testing-library/react");
5
5
  var _react2 = _interopRequireWildcard(require("react"));
6
6
  var _simpleSingleSelect = require("./simple-single-select.js");
7
7
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
8
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
8
9
  describe('<SimpleSingleSelect />', () => {
9
10
  beforeAll(() => {
10
11
  const consoleError = console.error;
@@ -145,6 +146,67 @@ describe('<SimpleSingleSelect />', () => {
145
146
  const menu = listbox.parentNode.parentNode.parentNode;
146
147
  expect(menu.style.maxHeight).toBe('100px');
147
148
  });
149
+ describe('dropdown menu width', () => {
150
+ let offsetWidth;
151
+ beforeEach(() => {
152
+ // The menu's width is derived from the select's measured width,
153
+ // which is always 0 in jsdom
154
+ offsetWidth = jest.spyOn(HTMLElement.prototype, 'offsetWidth', 'get').mockReturnValue(120);
155
+ });
156
+ afterEach(() => {
157
+ offsetWidth.mockRestore();
158
+ });
159
+ const renderAndOpen = props => {
160
+ (0, _react.render)(/*#__PURE__*/_react2.default.createElement(_simpleSingleSelect.SimpleSingleSelect, _extends({
161
+ name: "simple",
162
+ selected: {
163
+ value: 'foo',
164
+ label: 'Foo'
165
+ },
166
+ onChange: () => null,
167
+ options: [{
168
+ value: 'foo',
169
+ label: 'Foo'
170
+ }]
171
+ }, props)));
172
+ _react.fireEvent.click(_react.screen.getByRole('combobox'));
173
+ const listbox = _react.screen.getByRole('listbox');
174
+ return listbox.parentNode.parentNode.parentNode;
175
+ };
176
+ it('should match the width of the select by default', () => {
177
+ const menu = renderAndOpen();
178
+ expect(menu.style.width).toBe('120px');
179
+ });
180
+ it('should not be narrower than menuMinWidth or the select', () => {
181
+ const menu = renderAndOpen({
182
+ menuMinWidth: '240px'
183
+ });
184
+ expect(menu.style.minWidth).toBe('max(120px, 240px)');
185
+ });
186
+ it('should not be wider than menuMaxWidth', () => {
187
+ const menu = renderAndOpen({
188
+ menuMaxWidth: '200px'
189
+ });
190
+ expect(menu.style.maxWidth).toBe('200px');
191
+ expect(menu.style.minWidth).toBe('120px');
192
+ });
193
+ it('should re-measure the select when the menu is reopened', () => {
194
+ renderAndOpen({
195
+ menuMinWidth: '240px'
196
+ });
197
+ const comboBox = _react.screen.getByRole('combobox');
198
+
199
+ // close the menu
200
+ _react.fireEvent.click(comboBox);
201
+
202
+ // widen the select while the menu is closed, then reopen it
203
+ offsetWidth.mockReturnValue(300);
204
+ _react.fireEvent.click(comboBox);
205
+ const listbox = _react.screen.getByRole('listbox');
206
+ const menu = listbox.parentNode.parentNode.parentNode;
207
+ expect(menu.style.minWidth).toBe('max(300px, 240px)');
208
+ });
209
+ });
148
210
  it('should accept a placeholder', () => {
149
211
  (0, _react.render)(/*#__PURE__*/_react2.default.createElement(_simpleSingleSelect.SimpleSingleSelect, {
150
212
  name: "simple",
@@ -108,6 +108,10 @@ SimpleSingleSelectField.propTypes = {
108
108
  menuLoadingText: _propTypes2.default.string,
109
109
  /** Allows to modify the max height of the menu **/
110
110
  menuMaxHeight: _propTypes2.default.string,
111
+ /** See [dropdown menu width](https://developers.dhis2.org/docs/ui/components/select#dropdown-menu-width) **/
112
+ menuMaxWidth: _propTypes2.default.string,
113
+ /** See [dropdown menu width](https://developers.dhis2.org/docs/ui/components/select#dropdown-menu-width) **/
114
+ menuMinWidth: _propTypes2.default.string,
111
115
  /** String that will be displayed when the select is being filtered but the options array is empty **/
112
116
  noMatchText: (0, _propTypes.requiredIf)(props => props.filterable, _propTypes2.default.string),
113
117
  /** Allows to override what's rendered inside the `button[role="option"]`.
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = exports.WithHelpText = exports.StatusWarning = exports.StatusValid = exports.StatusError = exports.StatusDisabled = exports.Required = exports.InputWidth = exports.Default = void 0;
6
+ exports.default = exports.WithMenuMinWidth = exports.WithMenuMaxWidth = exports.WithHelpText = exports.StatusWarning = exports.StatusValid = exports.StatusError = exports.StatusDisabled = exports.Required = exports.InputWidth = exports.Default = void 0;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
8
  var _index = require("./index.js");
9
9
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
@@ -49,6 +49,19 @@ const options = [{
49
49
  value: '10',
50
50
  label: 'ten'
51
51
  }];
52
+ const longOptions = [{
53
+ value: '1',
54
+ label: 'option one'
55
+ }, {
56
+ value: '2',
57
+ label: 'option two'
58
+ }, {
59
+ value: '3',
60
+ label: 'option three'
61
+ }, {
62
+ value: '4',
63
+ label: 'A longer option that exceeds the minimum'
64
+ }];
52
65
  var _default = exports.default = {
53
66
  title: 'SimpleSingleSelectField',
54
67
  component: _index.SimpleSingleSelectField,
@@ -184,4 +197,42 @@ const InputWidth = () => {
184
197
  options: options
185
198
  }));
186
199
  };
187
- exports.InputWidth = InputWidth;
200
+ exports.InputWidth = InputWidth;
201
+ const WithMenuMinWidth = () => {
202
+ var _longOptions$find;
203
+ const [value, setValue] = (0, _react.useState)('');
204
+ const valueLabel = value ? (_longOptions$find = longOptions.find(option => option.value === value)) === null || _longOptions$find === void 0 ? void 0 : _longOptions$find.label : '';
205
+ return /*#__PURE__*/_react.default.createElement("div", {
206
+ style: {
207
+ width: 120
208
+ }
209
+ }, /*#__PURE__*/_react.default.createElement(_index.SimpleSingleSelectField, {
210
+ name: "simple",
211
+ label: "This is the label",
212
+ value: value,
213
+ valueLabel: valueLabel,
214
+ onChange: nextValue => setValue(nextValue),
215
+ options: longOptions,
216
+ menuMinWidth: "240px"
217
+ }));
218
+ };
219
+ exports.WithMenuMinWidth = WithMenuMinWidth;
220
+ const WithMenuMaxWidth = () => {
221
+ var _longOptions$find2;
222
+ const [value, setValue] = (0, _react.useState)('');
223
+ const valueLabel = value ? (_longOptions$find2 = longOptions.find(option => option.value === value)) === null || _longOptions$find2 === void 0 ? void 0 : _longOptions$find2.label : '';
224
+ return /*#__PURE__*/_react.default.createElement("div", {
225
+ style: {
226
+ width: 120
227
+ }
228
+ }, /*#__PURE__*/_react.default.createElement(_index.SimpleSingleSelectField, {
229
+ name: "simple",
230
+ label: "This is the label",
231
+ value: value,
232
+ valueLabel: valueLabel,
233
+ onChange: nextValue => setValue(nextValue),
234
+ options: longOptions,
235
+ menuMaxWidth: "200px"
236
+ }));
237
+ };
238
+ exports.WithMenuMaxWidth = WithMenuMaxWidth;
@@ -52,6 +52,8 @@ describe('<SimpleSingleSelectField />', () => {
52
52
  loading: false,
53
53
  menuLoadingText: "",
54
54
  menuMaxHeight: "",
55
+ menuMaxWidth: "400px",
56
+ menuMinWidth: "240px",
55
57
  noMatchText: "",
56
58
  optionUpdateStrategy: "off",
57
59
  placeholder: "",
@@ -89,6 +91,8 @@ describe('<SimpleSingleSelectField />', () => {
89
91
  expect(_simpleSingleSelect.SimpleSingleSelect.mock.calls[0][0].loading).toBe(false);
90
92
  expect(_simpleSingleSelect.SimpleSingleSelect.mock.calls[0][0].menuLoadingText).toBe('');
91
93
  expect(_simpleSingleSelect.SimpleSingleSelect.mock.calls[0][0].menuMaxHeight).toBe('');
94
+ expect(_simpleSingleSelect.SimpleSingleSelect.mock.calls[0][0].menuMaxWidth).toBe('400px');
95
+ expect(_simpleSingleSelect.SimpleSingleSelect.mock.calls[0][0].menuMinWidth).toBe('240px');
92
96
  expect(_simpleSingleSelect.SimpleSingleSelect.mock.calls[0][0].noMatchText).toBe('');
93
97
  expect(_simpleSingleSelect.SimpleSingleSelect.mock.calls[0][0].optionUpdateStrategy).toBe('off');
94
98
  expect(_simpleSingleSelect.SimpleSingleSelect.mock.calls[0][0].placeholder).toBe('');
@@ -23,17 +23,17 @@ const SingleSelectOption = ({
23
23
  "data-test": dataTest,
24
24
  "data-value": value,
25
25
  "data-label": label,
26
- className: _style.default.dynamic([["1307386342", [_uiConstants.colors.grey900, _uiConstants.spacers.dp8, _uiConstants.spacers.dp12, _uiConstants.colors.grey200, _uiConstants.colors.teal050, _uiConstants.colors.grey500, active ? `url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTMuNjMyMDkgNy44MzIxNEMzLjI3MjA5IDcuNDcyMTQgMi43MjAwOSA3LjQ3MjE0IDIuMzYwMDkgNy44MzIxNEMyLjAwMDA5IDguMTkyMTQgMi4wMDAwOSA4Ljc0NDE0IDIuMzYwMDkgOS4xMDQxNEw1LjYyNDA5IDEyLjM2ODFDNS45ODQwOSAxMi43MjgxIDYuNTM2MDkgMTIuNzI4MSA2Ljg5NjA5IDEyLjM2ODFMMTQuNjQ4MSA0LjY0MDE0QzE1LjAwODEgNC4yODAxNCAxNS4wMDgxIDMuNzI4MTQgMTQuNjQ4MSAzLjM2ODE0QzE0LjI4ODEgMy4wMDgxNCAxMy43MzYxIDMuMDA4MTQgMTMuMzUyMSAzLjM2ODE0TDYuMjcyMDkgMTAuNDcyMUwzLjYzMjA5IDcuODMyMTRaIiBmaWxsPSIjMDA2OTVDIi8+Cjwvc3ZnPgo=')` : 'none']]]) + " " + ((0, _classnames.default)(className, {
26
+ className: _style.default.dynamic([["556453451", [_uiConstants.colors.grey900, _uiConstants.spacers.dp8, _uiConstants.spacers.dp12, _uiConstants.colors.grey200, _uiConstants.colors.teal050, _uiConstants.colors.grey500, active ? `url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTMuNjMyMDkgNy44MzIxNEMzLjI3MjA5IDcuNDcyMTQgMi43MjAwOSA3LjQ3MjE0IDIuMzYwMDkgNy44MzIxNEMyLjAwMDA5IDguMTkyMTQgMi4wMDAwOSA4Ljc0NDE0IDIuMzYwMDkgOS4xMDQxNEw1LjYyNDA5IDEyLjM2ODFDNS45ODQwOSAxMi43MjgxIDYuNTM2MDkgMTIuNzI4MSA2Ljg5NjA5IDEyLjM2ODFMMTQuNjQ4MSA0LjY0MDE0QzE1LjAwODEgNC4yODAxNCAxNS4wMDgxIDMuNzI4MTQgMTQuNjQ4MSAzLjM2ODE0QzE0LjI4ODEgMy4wMDgxNCAxMy43MzYxIDMuMDA4MTQgMTMuMzUyMSAzLjM2ODE0TDYuMjcyMDkgMTAuNDcyMUwzLjYzMjA5IDcuODMyMTRaIiBmaWxsPSIjMDA2OTVDIi8+Cjwvc3ZnPgo=')` : 'none']]]) + " " + ((0, _classnames.default)(className, {
27
27
  disabled,
28
28
  active
29
29
  }) || "")
30
30
  }, /*#__PURE__*/_react.default.createElement("span", {
31
31
  "aria-hidden": "true",
32
- className: _style.default.dynamic([["1307386342", [_uiConstants.colors.grey900, _uiConstants.spacers.dp8, _uiConstants.spacers.dp12, _uiConstants.colors.grey200, _uiConstants.colors.teal050, _uiConstants.colors.grey500, active ? `url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTMuNjMyMDkgNy44MzIxNEMzLjI3MjA5IDcuNDcyMTQgMi43MjAwOSA3LjQ3MjE0IDIuMzYwMDkgNy44MzIxNEMyLjAwMDA5IDguMTkyMTQgMi4wMDAwOSA4Ljc0NDE0IDIuMzYwMDkgOS4xMDQxNEw1LjYyNDA5IDEyLjM2ODFDNS45ODQwOSAxMi43MjgxIDYuNTM2MDkgMTIuNzI4MSA2Ljg5NjA5IDEyLjM2ODFMMTQuNjQ4MSA0LjY0MDE0QzE1LjAwODEgNC4yODAxNCAxNS4wMDgxIDMuNzI4MTQgMTQuNjQ4MSAzLjM2ODE0QzE0LjI4ODEgMy4wMDgxNCAxMy43MzYxIDMuMDA4MTQgMTMuMzUyMSAzLjM2ODE0TDYuMjcyMDkgMTAuNDcyMUwzLjYzMjA5IDcuODMyMTRaIiBmaWxsPSIjMDA2OTVDIi8+Cjwvc3ZnPgo=')` : 'none']]]) + " " + "checkmark"
32
+ className: _style.default.dynamic([["556453451", [_uiConstants.colors.grey900, _uiConstants.spacers.dp8, _uiConstants.spacers.dp12, _uiConstants.colors.grey200, _uiConstants.colors.teal050, _uiConstants.colors.grey500, active ? `url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTMuNjMyMDkgNy44MzIxNEMzLjI3MjA5IDcuNDcyMTQgMi43MjAwOSA3LjQ3MjE0IDIuMzYwMDkgNy44MzIxNEMyLjAwMDA5IDguMTkyMTQgMi4wMDAwOSA4Ljc0NDE0IDIuMzYwMDkgOS4xMDQxNEw1LjYyNDA5IDEyLjM2ODFDNS45ODQwOSAxMi43MjgxIDYuNTM2MDkgMTIuNzI4MSA2Ljg5NjA5IDEyLjM2ODFMMTQuNjQ4MSA0LjY0MDE0QzE1LjAwODEgNC4yODAxNCAxNS4wMDgxIDMuNzI4MTQgMTQuNjQ4MSAzLjM2ODE0QzE0LjI4ODEgMy4wMDgxNCAxMy43MzYxIDMuMDA4MTQgMTMuMzUyMSAzLjM2ODE0TDYuMjcyMDkgMTAuNDcyMUwzLjYzMjA5IDcuODMyMTRaIiBmaWxsPSIjMDA2OTVDIi8+Cjwvc3ZnPgo=')` : 'none']]]) + " " + "checkmark"
33
33
  }), /*#__PURE__*/_react.default.createElement("span", {
34
- className: _style.default.dynamic([["1307386342", [_uiConstants.colors.grey900, _uiConstants.spacers.dp8, _uiConstants.spacers.dp12, _uiConstants.colors.grey200, _uiConstants.colors.teal050, _uiConstants.colors.grey500, active ? `url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTMuNjMyMDkgNy44MzIxNEMzLjI3MjA5IDcuNDcyMTQgMi43MjAwOSA3LjQ3MjE0IDIuMzYwMDkgNy44MzIxNEMyLjAwMDA5IDguMTkyMTQgMi4wMDAwOSA4Ljc0NDE0IDIuMzYwMDkgOS4xMDQxNEw1LjYyNDA5IDEyLjM2ODFDNS45ODQwOSAxMi43MjgxIDYuNTM2MDkgMTIuNzI4MSA2Ljg5NjA5IDEyLjM2ODFMMTQuNjQ4MSA0LjY0MDE0QzE1LjAwODEgNC4yODAxNCAxNS4wMDgxIDMuNzI4MTQgMTQuNjQ4MSAzLjM2ODE0QzE0LjI4ODEgMy4wMDgxNCAxMy43MzYxIDMuMDA4MTQgMTMuMzUyMSAzLjM2ODE0TDYuMjcyMDkgMTAuNDcyMUwzLjYzMjA5IDcuODMyMTRaIiBmaWxsPSIjMDA2OTVDIi8+Cjwvc3ZnPgo=')` : 'none']]]) + " " + "content"
34
+ className: _style.default.dynamic([["556453451", [_uiConstants.colors.grey900, _uiConstants.spacers.dp8, _uiConstants.spacers.dp12, _uiConstants.colors.grey200, _uiConstants.colors.teal050, _uiConstants.colors.grey500, active ? `url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTMuNjMyMDkgNy44MzIxNEMzLjI3MjA5IDcuNDcyMTQgMi43MjAwOSA3LjQ3MjE0IDIuMzYwMDkgNy44MzIxNEMyLjAwMDA5IDguMTkyMTQgMi4wMDAwOSA4Ljc0NDE0IDIuMzYwMDkgOS4xMDQxNEw1LjYyNDA5IDEyLjM2ODFDNS45ODQwOSAxMi43MjgxIDYuNTM2MDkgMTIuNzI4MSA2Ljg5NjA5IDEyLjM2ODFMMTQuNjQ4MSA0LjY0MDE0QzE1LjAwODEgNC4yODAxNCAxNS4wMDgxIDMuNzI4MTQgMTQuNjQ4MSAzLjM2ODE0QzE0LjI4ODEgMy4wMDgxNCAxMy43MzYxIDMuMDA4MTQgMTMuMzUyMSAzLjM2ODE0TDYuMjcyMDkgMTAuNDcyMUwzLjYzMjA5IDcuODMyMTRaIiBmaWxsPSIjMDA2OTVDIi8+Cjwvc3ZnPgo=')` : 'none']]]) + " " + "content"
35
35
  }, label), /*#__PURE__*/_react.default.createElement(_style.default, {
36
- id: "1307386342",
36
+ id: "556453451",
37
37
  dynamic: [_uiConstants.colors.grey900, _uiConstants.spacers.dp8, _uiConstants.spacers.dp12, _uiConstants.colors.grey200, _uiConstants.colors.teal050, _uiConstants.colors.grey500, active ? `url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTMuNjMyMDkgNy44MzIxNEMzLjI3MjA5IDcuNDcyMTQgMi43MjAwOSA3LjQ3MjE0IDIuMzYwMDkgNy44MzIxNEMyLjAwMDA5IDguMTkyMTQgMi4wMDAwOSA4Ljc0NDE0IDIuMzYwMDkgOS4xMDQxNEw1LjYyNDA5IDEyLjM2ODFDNS45ODQwOSAxMi43MjgxIDYuNTM2MDkgMTIuNzI4MSA2Ljg5NjA5IDEyLjM2ODFMMTQuNjQ4MSA0LjY0MDE0QzE1LjAwODEgNC4yODAxNCAxNS4wMDgxIDMuNzI4MTQgMTQuNjQ4MSAzLjM2ODE0QzE0LjI4ODEgMy4wMDgxNCAxMy43MzYxIDMuMDA4MTQgMTMuMzUyMSAzLjM2ODE0TDYuMjcyMDkgMTAuNDcyMUwzLjYzMjA5IDcuODMyMTRaIiBmaWxsPSIjMDA2OTVDIi8+Cjwvc3ZnPgo=')` : 'none']
38
38
  }, [`div.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;cursor:pointer;font-size:14px;-webkit-text-decoration:none;text-decoration:none;color:${_uiConstants.colors.grey900};padding-block:${_uiConstants.spacers.dp8};padding-inline:6px ${_uiConstants.spacers.dp12};}`, `div.__jsx-style-dynamic-selector:hover{background-color:${_uiConstants.colors.grey200};}`, `div.__jsx-style-dynamic-selector:active,div.active.__jsx-style-dynamic-selector{background-color:${_uiConstants.colors.teal050};cursor:auto;}`, `div.disabled.__jsx-style-dynamic-selector{color:${_uiConstants.colors.grey500};cursor:not-allowed;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}`, "div.disabled.__jsx-style-dynamic-selector:hover{background-color:initial;}", `div.__jsx-style-dynamic-selector .checkmark.__jsx-style-dynamic-selector{width:16px;height:16px;margin-inline-end:6px;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;background-size:contain;background-repeat:no-repeat;background-image:${active ? `url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTMuNjMyMDkgNy44MzIxNEMzLjI3MjA5IDcuNDcyMTQgMi43MjAwOSA3LjQ3MjE0IDIuMzYwMDkgNy44MzIxNEMyLjAwMDA5IDguMTkyMTQgMi4wMDAwOSA4Ljc0NDE0IDIuMzYwMDkgOS4xMDQxNEw1LjYyNDA5IDEyLjM2ODFDNS45ODQwOSAxMi43MjgxIDYuNTM2MDkgMTIuNzI4MSA2Ljg5NjA5IDEyLjM2ODFMMTQuNjQ4MSA0LjY0MDE0QzE1LjAwODEgNC4yODAxNCAxNS4wMDgxIDMuNzI4MTQgMTQuNjQ4MSAzLjM2ODE0QzE0LjI4ODEgMy4wMDgxNCAxMy43MzYxIDMuMDA4MTQgMTMuMzUyMSAzLjM2ODE0TDYuMjcyMDkgMTAuNDcyMUwzLjYzMjA5IDcuODMyMTRaIiBmaWxsPSIjMDA2OTVDIi8+Cjwvc3ZnPgo=')` : 'none'};}`]));
39
39
  exports.SingleSelectOption = SingleSelectOption;
@@ -0,0 +1,26 @@
1
+ import React, { useState } from 'react';
2
+ import { SimpleSingleSelect } from '../simple-single-select.js';
3
+ const options = [{
4
+ value: '1',
5
+ label: 'option one'
6
+ }, {
7
+ value: '2',
8
+ label: 'option two'
9
+ }, {
10
+ value: '3',
11
+ label: 'A much longer option label that gets clamped'
12
+ }];
13
+ export const WithMenuMaxWidth = () => {
14
+ const [selected, setSelected] = useState(null);
15
+ return /*#__PURE__*/React.createElement("div", {
16
+ style: {
17
+ width: 120
18
+ }
19
+ }, /*#__PURE__*/React.createElement(SimpleSingleSelect, {
20
+ name: "simple",
21
+ selected: selected,
22
+ onChange: setSelected,
23
+ options: options,
24
+ menuMaxWidth: "200px"
25
+ }));
26
+ };
@@ -0,0 +1,29 @@
1
+ import React, { useState } from 'react';
2
+ import { SimpleSingleSelect } from '../simple-single-select.js';
3
+ const options = [{
4
+ value: '1',
5
+ label: 'option one'
6
+ }, {
7
+ value: '2',
8
+ label: 'option two'
9
+ }, {
10
+ value: '3',
11
+ label: 'option three'
12
+ }, {
13
+ value: '4',
14
+ label: 'A longer option that exceeds the minimum'
15
+ }];
16
+ export const WithMenuMinWidth = () => {
17
+ const [selected, setSelected] = useState(null);
18
+ return /*#__PURE__*/React.createElement("div", {
19
+ style: {
20
+ width: 120
21
+ }
22
+ }, /*#__PURE__*/React.createElement(SimpleSingleSelect, {
23
+ name: "simple",
24
+ selected: selected,
25
+ onChange: setSelected,
26
+ options: options,
27
+ menuMinWidth: "240px"
28
+ }));
29
+ };
@@ -26,6 +26,8 @@ export function Menu({
26
26
  loading,
27
27
  loadingText,
28
28
  maxHeight,
29
+ maxWidth,
30
+ minWidth,
29
31
  noMatchText,
30
32
  optionUpdateStrategy,
31
33
  selectRef,
@@ -34,17 +36,16 @@ export function Menu({
34
36
  onClose,
35
37
  onEndReached
36
38
  }) {
37
- const [menuWidth, setWidth] = useState('auto');
39
+ const [selectWidth, setSelectWidth] = useState();
38
40
  const dataTestPrefix = `${dataTest}-menu`;
41
+
42
+ // Re-measuring whenever `hidden` changes keeps the width current when the
43
+ // select's container has been resized since the menu was last opened
39
44
  useEffect(() => {
40
45
  if (selectRef) {
41
- const callback = () => setWidth(`${selectRef.offsetWidth}px`);
42
- callback(); // We want to know the width as soon as the
43
-
44
- selectRef.addEventListener('resize', callback);
45
- return () => selectRef.removeEventListener('resize', callback);
46
+ setSelectWidth(`${selectRef.offsetWidth}px`);
46
47
  }
47
- }, [selectRef]);
48
+ }, [selectRef, hidden]);
48
49
  if (hidden) {
49
50
  return null;
50
51
  }
@@ -53,6 +54,10 @@ export function Menu({
53
54
  // we're in the process of loading options
54
55
  !loading;
55
56
  const isEmpty = !options.length && !filterValue;
57
+ const flexible = Boolean(minWidth || maxWidth);
58
+ // We never want the menu narrower than the select, so a maxWidth below
59
+ // the select's width intentionally has no effect
60
+ const flexibleMinWidth = minWidth && selectWidth ? `max(${selectWidth}, ${minWidth})` : minWidth || selectWidth;
56
61
  return /*#__PURE__*/React.createElement(Layer, {
57
62
  onBackdropClick: onClose,
58
63
  transparent: true
@@ -62,7 +67,9 @@ export function Menu({
62
67
  observeReferenceResize: true
63
68
  }, /*#__PURE__*/React.createElement("div", {
64
69
  style: {
65
- width: menuWidth,
70
+ width: flexible ? 'fit-content' : selectWidth,
71
+ minWidth: flexible ? flexibleMinWidth : undefined,
72
+ maxWidth,
66
73
  maxHeight
67
74
  },
68
75
  className: _JSXStyle.dynamic([["2949029222", [colors.white, colors.grey200, elevations.e300]]]) + " " + "menu"
@@ -113,6 +120,8 @@ Menu.propTypes = {
113
120
  loading: PropTypes.bool,
114
121
  loadingText: PropTypes.string,
115
122
  maxHeight: PropTypes.string,
123
+ maxWidth: PropTypes.string,
124
+ minWidth: PropTypes.string,
116
125
  noMatchText: PropTypes.string,
117
126
  optionComponent: PropTypes.elementType,
118
127
  optionUpdateStrategy: PropTypes.oneOf(['off', 'polite', 'assertive']),
@@ -8,6 +8,11 @@ import { Menu } from './menu/index.js';
8
8
  import { SelectedValue } from './selected-value/index.js';
9
9
  import { optionProp } from './shared-prop-types.js';
10
10
  import { useHandleKeyPressOnCombobox, useHandleKeyPressOnFilterInput } from './use-handle-key-press/index.js';
11
+ const defaultSelected = {
12
+ label: '',
13
+ value: ''
14
+ };
15
+ const noop = () => undefined;
11
16
  function useFocussedOptionIndex({
12
17
  filterable,
13
18
  filterValue,
@@ -65,22 +70,21 @@ export function SimpleSingleSelect({
65
70
  loading = false,
66
71
  menuLoadingText: _menuLoadingText = '',
67
72
  menuMaxHeight = '288px',
73
+ menuMaxWidth,
74
+ menuMinWidth,
68
75
  noMatchText: _noMatchText = '',
69
76
  optionUpdateStrategy = 'polite',
70
77
  placeholder = '',
71
78
  prefix = '',
72
- selected = {
73
- label: '',
74
- value: ''
75
- },
79
+ selected = defaultSelected,
76
80
  tabIndex = '0',
77
81
  valid = false,
78
82
  warning = false,
79
- onBlur = () => undefined,
80
- onClear = () => undefined,
81
- onEndReached = () => undefined,
82
- onFilterChange = () => undefined,
83
- onFocus = () => undefined
83
+ onBlur = noop,
84
+ onClear = noop,
85
+ onEndReached = noop,
86
+ onFilterChange = noop,
87
+ onFocus = noop
84
88
  }) {
85
89
  // We can't translate with default props as the translation function would
86
90
  // be called before we get any translations from the consuming app/lib
@@ -230,6 +234,8 @@ export function SimpleSingleSelect({
230
234
  loading: loading,
231
235
  loadingText: menuLoadingText,
232
236
  maxHeight: menuMaxHeight,
237
+ maxWidth: menuMaxWidth,
238
+ minWidth: menuMinWidth,
233
239
  noMatchText: noMatchText,
234
240
  optionUpdateStrategy: optionUpdateStrategy,
235
241
  options: options,
@@ -287,6 +293,10 @@ SimpleSingleSelect.propTypes = {
287
293
  menuLoadingText: PropTypes.string,
288
294
  /** Allows to modify the max height of the menu **/
289
295
  menuMaxHeight: PropTypes.string,
296
+ /** See [dropdown menu width](https://developers.dhis2.org/docs/ui/components/select#dropdown-menu-width) **/
297
+ menuMaxWidth: PropTypes.string,
298
+ /** See [dropdown menu width](https://developers.dhis2.org/docs/ui/components/select#dropdown-menu-width) **/
299
+ menuMinWidth: PropTypes.string,
290
300
  /** String that will be displayed when the select is being filtered but the options array is empty **/
291
301
  noMatchText: requiredIf(props => props.filterable, PropTypes.string),
292
302
  /** Allows to override what's rendered inside the `button[role="option"]`.
@@ -20,6 +20,8 @@ export { WithOptionsAndLoadingText } from './__stories__/WithOptionsAndLoadingTe
20
20
  export { WithoutOptionsAndLoading } from './__stories__/WithoutOptionsAndLoading.js';
21
21
  export { WithManyOptions } from './__stories__/WithManyOptions.js';
22
22
  export { WithCustomLowMaxHeight } from './__stories__/WithCustomLowMaxHeight.js';
23
+ export { WithMenuMinWidth } from './__stories__/WithMenuMinWidth.js';
24
+ export { WithMenuMaxWidth } from './__stories__/WithMenuMaxWidth.js';
23
25
  export { WithOptionsAndDisabled } from './__stories__/WithOptionsAndDisabled.js';
24
26
  export { WithSelectionAndDisabled } from './__stories__/WithSelectionAndDisabled.js';
25
27
  export { WithPrefix } from './__stories__/WithPrefix.js';