@pareto-engineering/design-system 2.0.0-alpha.45 → 2.0.0-alpha.46

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.
@@ -67,6 +67,13 @@ var FormInput = _ref => {
67
67
  }, otherProps));
68
68
  }
69
69
 
70
+ if (type === 'query-combobox') {
71
+ return /*#__PURE__*/React.createElement(_fields.QueryCombobox, _extends({
72
+ className: newClassName,
73
+ disabled: disabled
74
+ }, otherProps));
75
+ }
76
+
70
77
  if (extraTypes !== null && extraTypes !== void 0 && extraTypes[type]) {
71
78
  var Component = extraTypes[type];
72
79
  return /*#__PURE__*/React.createElement(Component, _extends({
@@ -91,7 +98,7 @@ FormInput.propTypes = {
91
98
  /**
92
99
  * The HTML class names for this element
93
100
  */
94
- type: _propTypes.default.oneOf(['text', 'email', 'password', 'number', 'date', 'datetime', 'month', 'tel', 'hidden', 'select', 'choices', 'textarea', // to be removed
101
+ type: _propTypes.default.oneOf(['text', 'email', 'password', 'number', 'date', 'datetime', 'month', 'tel', 'hidden', 'select', 'choices', 'textarea', 'query-combobox', // to be removed
95
102
  'extendedTypeInput']),
96
103
 
97
104
  /**
@@ -32,6 +32,9 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
32
32
  */
33
33
  var QueryCombobox = _ref => {
34
34
  var {
35
+ id,
36
+ style,
37
+ className,
35
38
  query,
36
39
  // multiple,
37
40
  name,
@@ -98,6 +101,8 @@ var QueryCombobox = _ref => {
98
101
  };
99
102
 
100
103
  var comboboxProps = {
104
+ id,
105
+ style,
101
106
  options,
102
107
  getOptions,
103
108
  debounceMs,
@@ -108,7 +113,9 @@ var QueryCombobox = _ref => {
108
113
  setValue,
109
114
  error,
110
115
  value,
111
- color
116
+ color,
117
+ isFetching,
118
+ className
112
119
  };
113
120
  var Input = _common.Combobox;
114
121
  return /*#__PURE__*/React.createElement(Input, comboboxProps);
@@ -46,7 +46,9 @@ var Combobox = _ref => {
46
46
  error,
47
47
  description,
48
48
  value,
49
- color // ...otherProps
49
+ color,
50
+ loadingCircleColor,
51
+ isFetching // ...otherProps
50
52
 
51
53
  } = _ref;
52
54
  var {
@@ -86,7 +88,7 @@ var Combobox = _ref => {
86
88
  var parentRef = (0, React.useRef)(null);
87
89
  return /*#__PURE__*/React.createElement("div", {
88
90
  id: id,
89
- className: [baseClassName, componentClassName, userClassName, "y-".concat(color)].filter(e => e).join(' '),
91
+ className: [baseClassName, componentClassName, userClassName, "y-".concat(color), "x-".concat(loadingCircleColor)].filter(e => e).join(' '),
90
92
  style: style,
91
93
  ref: parentRef
92
94
  }, /*#__PURE__*/React.createElement(_.FormLabel, _extends({}, getLabelProps(), {
@@ -95,7 +97,7 @@ var Combobox = _ref => {
95
97
  className: "input-wrapper"
96
98
  }), /*#__PURE__*/React.createElement("input", _extends({}, getInputProps(), {
97
99
  className: "input"
98
- }))), /*#__PURE__*/React.createElement(_a.Popover, {
100
+ })), isFetching && /*#__PURE__*/React.createElement(_a.LoadingCircle, null)), /*#__PURE__*/React.createElement(_a.Popover, {
99
101
  isOpen: isOpen,
100
102
  parentRef: parentRef
101
103
  }, /*#__PURE__*/React.createElement(_Menu.Menu, _extends({
@@ -173,9 +175,20 @@ Combobox.propTypes = {
173
175
  /**
174
176
  * The base color of the combobox custom select input
175
177
  */
176
- color: _propTypes.default.string
178
+ color: _propTypes.default.string,
179
+
180
+ /**
181
+ * Whether the query getting the combobox options is inFlight
182
+ */
183
+ isFetching: _propTypes.default.bool.isRequired,
184
+
185
+ /**
186
+ * The loading circle color
187
+ */
188
+ loadingCircleColor: _propTypes.default.string
177
189
  };
178
- Combobox.defaultProps = {// someProp:false
190
+ Combobox.defaultProps = {
191
+ loadingCircleColor: 'main2'
179
192
  };
180
193
  var _default = Combobox;
181
194
  exports.default = _default;
@@ -15,6 +15,8 @@ var _downshift = require("downshift");
15
15
 
16
16
  var _b = require("../../../../../b");
17
17
 
18
+ var _a = require("../../../../../a");
19
+
18
20
  var _ = require("../../../..");
19
21
 
20
22
  var _Menu = require("../Menu");
@@ -35,10 +37,19 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
35
37
 
36
38
  var baseClassName = _bem.default.base;
37
39
  var componentClassName = 'multiple-combobox';
40
+ /**
41
+ * @param {Array[Object]} first - first array to check if it has an item not in the second array.
42
+ * @param {Array[Object]} second - second array to check against the first array.
43
+ *
44
+ * @returns {Boolean} - true if the first array has an item not in the second array.
45
+ */
46
+
47
+ var testIfArraysAreUnique = (first, second) => first.filter(objInFirstArray => !second.some(objInSecondArray => objInFirstArray.value === objInSecondArray.value)).length > 0;
38
48
  /**
39
49
  * This is the component description.
40
50
  */
41
51
 
52
+
42
53
  var MultipleCombobox = _ref => {
43
54
  var {
44
55
  id,
@@ -47,22 +58,29 @@ var MultipleCombobox = _ref => {
47
58
  label,
48
59
  name,
49
60
  options: items,
50
- fetchOptions,
61
+ getOptions,
51
62
  setValue,
52
63
  error,
53
- description // ...otherProps
64
+ description,
65
+ value,
66
+ color,
67
+ isFetching,
68
+ loadingCircleColor // ...otherProps
54
69
 
55
70
  } = _ref;
56
- var [inputValue, setInputValue] = (0, React.useState)('');
71
+ var [searchInputValue, setSearchInputValue] = (0, React.useState)('');
57
72
  var {
58
73
  getSelectedItemProps,
59
74
  getDropdownProps,
60
75
  addSelectedItem,
61
76
  removeSelectedItem,
77
+ setSelectedItems,
62
78
  selectedItems
63
- } = (0, _downshift.useMultipleSelection)();
79
+ } = (0, _downshift.useMultipleSelection)({
80
+ initialSelectedItems: value || []
81
+ });
64
82
 
65
- var getFilteredItems = () => items.filter(item => selectedItems.findIndex(e => e.label === item.label) < 0 && item.label.toLowerCase().startsWith(inputValue.toLowerCase()));
83
+ var getFilteredItems = () => items.filter(item => selectedItems.findIndex(e => e.label === item.label) < 0 && item.label.toLowerCase().startsWith(searchInputValue.toLowerCase()));
66
84
 
67
85
  var {
68
86
  isOpen,
@@ -73,7 +91,7 @@ var MultipleCombobox = _ref => {
73
91
  highlightedIndex,
74
92
  getItemProps
75
93
  } = (0, _downshift.useCombobox)({
76
- inputValue,
94
+ searchInputValue,
77
95
  defaultHighlightedIndex: 0,
78
96
  // after selection, highlight the first item.
79
97
  selectedItem: null,
@@ -101,22 +119,22 @@ var MultipleCombobox = _ref => {
101
119
  },
102
120
  onStateChange: _ref2 => {
103
121
  var {
104
- inputValue: newInputValue,
122
+ inputValue: newSearchInputValue,
105
123
  type,
106
124
  selectedItem
107
125
  } = _ref2;
108
126
 
109
127
  switch (type) {
110
128
  case _downshift.useCombobox.stateChangeTypes.InputChange:
111
- fetchOptions(newInputValue);
112
- setInputValue(newInputValue);
129
+ getOptions(newSearchInputValue);
130
+ setSearchInputValue(newSearchInputValue);
113
131
  break;
114
132
 
115
133
  case _downshift.useCombobox.stateChangeTypes.InputKeyDownEnter:
116
134
  case _downshift.useCombobox.stateChangeTypes.ItemClick:
117
135
  case _downshift.useCombobox.stateChangeTypes.InputBlur:
118
136
  if (selectedItem) {
119
- setInputValue('');
137
+ setSearchInputValue('');
120
138
  addSelectedItem(selectedItem);
121
139
  }
122
140
 
@@ -128,16 +146,21 @@ var MultipleCombobox = _ref => {
128
146
  }
129
147
  });
130
148
  (0, React.useEffect)(() => {
131
- if (selectedItems.length > 0) {
132
- setValue(selectedItems.map(e => e.value));
149
+ if ((selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.length) > 0) {
150
+ setValue(selectedItems);
133
151
  }
134
152
  }, [selectedItems]);
153
+ (0, React.useEffect)(() => {
154
+ if ((value === null || value === void 0 ? void 0 : value.length) > 0 && (testIfArraysAreUnique(value, selectedItems) || testIfArraysAreUnique(selectedItems, value))) {
155
+ setSelectedItems(value);
156
+ }
157
+ }, [value]);
158
+ var parentRef = (0, React.useRef)(null);
135
159
  return /*#__PURE__*/React.createElement("div", {
136
160
  id: id,
137
- className: [baseClassName, componentClassName, userClassName].filter(e => e).join(' '),
161
+ className: [baseClassName, componentClassName, userClassName, "y-".concat(color), "x-".concat(loadingCircleColor)].filter(e => e).join(' '),
138
162
  style: style
139
163
  }, /*#__PURE__*/React.createElement(_.FormLabel, _extends({}, getLabelProps(), {
140
- className: "input-label",
141
164
  name: name
142
165
  }), label), /*#__PURE__*/React.createElement("div", {
143
166
  className: "selected-items"
@@ -155,16 +178,21 @@ var MultipleCombobox = _ref => {
155
178
  isCompact: true,
156
179
  isSimple: true,
157
180
  color: "main2"
158
- }, "X")))), /*#__PURE__*/React.createElement("div", getComboboxProps(), /*#__PURE__*/React.createElement("input", _extends({}, getInputProps(getDropdownProps({
181
+ }, "X")))), /*#__PURE__*/React.createElement("div", _extends({}, getComboboxProps(), {
182
+ className: "input-wrapper"
183
+ }), /*#__PURE__*/React.createElement("input", _extends({}, getInputProps(getDropdownProps({
159
184
  preventKeyAction: isOpen
160
185
  })), {
161
186
  className: "input"
162
- }))), /*#__PURE__*/React.createElement(_Menu.Menu, _extends({
187
+ })), isFetching && /*#__PURE__*/React.createElement(_a.LoadingCircle, null)), /*#__PURE__*/React.createElement(_a.Popover, {
188
+ isOpen: isOpen,
189
+ parentRef: parentRef
190
+ }, /*#__PURE__*/React.createElement(_Menu.Menu, _extends({
163
191
  isOpen: isOpen,
164
192
  getItemProps: getItemProps,
165
193
  highlightedIndex: highlightedIndex,
166
194
  items: getFilteredItems()
167
- }, getMenuProps())), (description || error) && /*#__PURE__*/React.createElement(_.FormDescription, {
195
+ }, getMenuProps()))), (description || error) && /*#__PURE__*/React.createElement(_.FormDescription, {
168
196
  isError: !!error
169
197
  }, error || description));
170
198
  };
@@ -206,7 +234,7 @@ MultipleCombobox.propTypes = {
206
234
  /**
207
235
  * The function to fetch the options from the backend
208
236
  */
209
- fetchOptions: _propTypes.default.func,
237
+ getOptions: _propTypes.default.func,
210
238
 
211
239
  /**
212
240
  * The function to set the value of the custom select input
@@ -221,9 +249,33 @@ MultipleCombobox.propTypes = {
221
249
  /**
222
250
  * The error object
223
251
  */
224
- error: _propTypes.default.objectOf(_propTypes.default.string)
252
+ error: _propTypes.default.objectOf(_propTypes.default.string),
253
+
254
+ /**
255
+ * The value of the custom select input
256
+ */
257
+ value: _propTypes.default.arrayOf(_propTypes.default.shape({
258
+ value: _propTypes.default.string,
259
+ label: _propTypes.default.string
260
+ })),
261
+
262
+ /**
263
+ * The base color of the custom select input
264
+ */
265
+ color: _propTypes.default.string,
266
+
267
+ /**
268
+ * Whether the query getting the combobox options is inFlight
269
+ */
270
+ isFetching: _propTypes.default.bool.isRequired,
271
+
272
+ /**
273
+ * The loading circle color
274
+ */
275
+ loadingCircleColor: _propTypes.default.string
225
276
  };
226
- MultipleCombobox.defaultProps = {// someProp:false
277
+ MultipleCombobox.defaultProps = {
278
+ loadingCircleColor: 'main2'
227
279
  };
228
280
  var _default = MultipleCombobox;
229
281
  exports.default = _default;
@@ -5,11 +5,16 @@
5
5
  $default-input-padding: .75em .75em .55em;
6
6
  $default-padding: 1em;
7
7
  $default-margin: 1em;
8
+ $default-loading-circle-displacement: 1em;
8
9
 
9
10
  .#{bem.$base}.combobox,
10
11
  .#{bem.$base}.multiple-combobox {
11
12
  position: relative;
12
13
 
14
+ .#{bem.$base}.label {
15
+ margin-bottom: $default-margin
16
+ }
17
+
13
18
  .#{bem.$base}.popover {
14
19
  width: 100%;
15
20
 
@@ -30,6 +35,14 @@ $default-margin: 1em;
30
35
  }
31
36
 
32
37
  >.input-wrapper {
38
+ position: relative;
39
+
40
+ >.#{bem.$base}.loading-circle {
41
+ position: absolute;
42
+ top: $default-loading-circle-displacement;
43
+ right: $default-loading-circle-displacement;
44
+ }
45
+
33
46
  >.input {
34
47
  background: var(--light-y);
35
48
  border: var(--theme-border-style) var(--dark-y);
@@ -4,7 +4,7 @@ function _extends() { _extends = Object.assign || function (target) { for (var i
4
4
  import * as React from 'react';
5
5
  import { memo, useLayoutEffect } from 'react';
6
6
  import PropTypes from 'prop-types';
7
- import { TextInput, TextareaInput, ChoicesInput, SelectInput } from "../fields"; // Local Definitions
7
+ import { TextInput, TextareaInput, ChoicesInput, SelectInput, QueryCombobox } from "../fields"; // Local Definitions
8
8
  // const baseClassName = styleNames.base
9
9
 
10
10
  const componentClassName = 'form-input';
@@ -45,6 +45,13 @@ const FormInput = ({
45
45
  }, otherProps));
46
46
  }
47
47
 
48
+ if (type === 'query-combobox') {
49
+ return /*#__PURE__*/React.createElement(QueryCombobox, _extends({
50
+ className: newClassName,
51
+ disabled: disabled
52
+ }, otherProps));
53
+ }
54
+
48
55
  if (extraTypes !== null && extraTypes !== void 0 && extraTypes[type]) {
49
56
  const Component = extraTypes[type];
50
57
  return /*#__PURE__*/React.createElement(Component, _extends({
@@ -69,7 +76,7 @@ FormInput.propTypes = {
69
76
  /**
70
77
  * The HTML class names for this element
71
78
  */
72
- type: PropTypes.oneOf(['text', 'email', 'password', 'number', 'date', 'datetime', 'month', 'tel', 'hidden', 'select', 'choices', 'textarea', // to be removed
79
+ type: PropTypes.oneOf(['text', 'email', 'password', 'number', 'date', 'datetime', 'month', 'tel', 'hidden', 'select', 'choices', 'textarea', 'query-combobox', // to be removed
73
80
  'extendedTypeInput']),
74
81
 
75
82
  /**
@@ -11,6 +11,9 @@ import { Combobox } from "./common";
11
11
  */
12
12
 
13
13
  const QueryCombobox = ({
14
+ id,
15
+ style,
16
+ className,
14
17
  query,
15
18
  // multiple,
16
19
  name,
@@ -76,6 +79,8 @@ const QueryCombobox = ({
76
79
  };
77
80
 
78
81
  const comboboxProps = {
82
+ id,
83
+ style,
79
84
  options,
80
85
  getOptions,
81
86
  debounceMs,
@@ -86,7 +91,9 @@ const QueryCombobox = ({
86
91
  setValue,
87
92
  error,
88
93
  value,
89
- color
94
+ color,
95
+ isFetching,
96
+ className
90
97
  };
91
98
  const Input = Combobox;
92
99
  return /*#__PURE__*/React.createElement(Input, comboboxProps);
@@ -7,7 +7,7 @@ import PropTypes from 'prop-types';
7
7
  import { useCombobox } from 'downshift';
8
8
  import styleNames from '@pareto-engineering/bem';
9
9
  import { FormLabel, FormDescription } from "../../../..";
10
- import { Popover } from "../../../../../a"; // Local Definitions
10
+ import { Popover, LoadingCircle } from "../../../../../a"; // Local Definitions
11
11
 
12
12
  import { Menu } from "../Menu";
13
13
  const baseClassName = styleNames.base;
@@ -28,7 +28,9 @@ const Combobox = ({
28
28
  error,
29
29
  description,
30
30
  value,
31
- color // ...otherProps
31
+ color,
32
+ loadingCircleColor,
33
+ isFetching // ...otherProps
32
34
 
33
35
  }) => {
34
36
  const {
@@ -67,7 +69,7 @@ const Combobox = ({
67
69
  const parentRef = useRef(null);
68
70
  return /*#__PURE__*/React.createElement("div", {
69
71
  id: id,
70
- className: [baseClassName, componentClassName, userClassName, `y-${color}`].filter(e => e).join(' '),
72
+ className: [baseClassName, componentClassName, userClassName, `y-${color}`, `x-${loadingCircleColor}`].filter(e => e).join(' '),
71
73
  style: style,
72
74
  ref: parentRef
73
75
  }, /*#__PURE__*/React.createElement(FormLabel, _extends({}, getLabelProps(), {
@@ -76,7 +78,7 @@ const Combobox = ({
76
78
  className: "input-wrapper"
77
79
  }), /*#__PURE__*/React.createElement("input", _extends({}, getInputProps(), {
78
80
  className: "input"
79
- }))), /*#__PURE__*/React.createElement(Popover, {
81
+ })), isFetching && /*#__PURE__*/React.createElement(LoadingCircle, null)), /*#__PURE__*/React.createElement(Popover, {
80
82
  isOpen: isOpen,
81
83
  parentRef: parentRef
82
84
  }, /*#__PURE__*/React.createElement(Menu, _extends({
@@ -154,8 +156,19 @@ Combobox.propTypes = {
154
156
  /**
155
157
  * The base color of the combobox custom select input
156
158
  */
157
- color: PropTypes.string
159
+ color: PropTypes.string,
160
+
161
+ /**
162
+ * Whether the query getting the combobox options is inFlight
163
+ */
164
+ isFetching: PropTypes.bool.isRequired,
165
+
166
+ /**
167
+ * The loading circle color
168
+ */
169
+ loadingCircleColor: PropTypes.string
158
170
  };
159
- Combobox.defaultProps = {// someProp:false
171
+ Combobox.defaultProps = {
172
+ loadingCircleColor: 'main2'
160
173
  };
161
174
  export default Combobox;
@@ -2,20 +2,30 @@ function _extends() { _extends = Object.assign || function (target) { for (var i
2
2
 
3
3
  /* @pareto-engineering/generator-front 1.0.12 */
4
4
  import * as React from 'react';
5
- import { useState, useEffect } from 'react';
5
+ import { useState, useEffect, useRef } from 'react';
6
6
  import PropTypes from 'prop-types';
7
7
  import styleNames from '@pareto-engineering/bem';
8
8
  import { useCombobox, useMultipleSelection } from 'downshift';
9
9
  import { Button } from "../../../../../b";
10
+ import { Popover, LoadingCircle } from "../../../../../a";
10
11
  import { FormDescription, FormLabel } from "../../../.."; // Local Definitions
11
12
 
12
13
  import { Menu } from "../Menu";
13
14
  const baseClassName = styleNames.base;
14
15
  const componentClassName = 'multiple-combobox';
16
+ /**
17
+ * @param {Array[Object]} first - first array to check if it has an item not in the second array.
18
+ * @param {Array[Object]} second - second array to check against the first array.
19
+ *
20
+ * @returns {Boolean} - true if the first array has an item not in the second array.
21
+ */
22
+
23
+ const testIfArraysAreUnique = (first, second) => first.filter(objInFirstArray => !second.some(objInSecondArray => objInFirstArray.value === objInSecondArray.value)).length > 0;
15
24
  /**
16
25
  * This is the component description.
17
26
  */
18
27
 
28
+
19
29
  const MultipleCombobox = ({
20
30
  id,
21
31
  className: userClassName,
@@ -23,22 +33,29 @@ const MultipleCombobox = ({
23
33
  label,
24
34
  name,
25
35
  options: items,
26
- fetchOptions,
36
+ getOptions,
27
37
  setValue,
28
38
  error,
29
- description // ...otherProps
39
+ description,
40
+ value,
41
+ color,
42
+ isFetching,
43
+ loadingCircleColor // ...otherProps
30
44
 
31
45
  }) => {
32
- const [inputValue, setInputValue] = useState('');
46
+ const [searchInputValue, setSearchInputValue] = useState('');
33
47
  const {
34
48
  getSelectedItemProps,
35
49
  getDropdownProps,
36
50
  addSelectedItem,
37
51
  removeSelectedItem,
52
+ setSelectedItems,
38
53
  selectedItems
39
- } = useMultipleSelection();
54
+ } = useMultipleSelection({
55
+ initialSelectedItems: value || []
56
+ });
40
57
 
41
- const getFilteredItems = () => items.filter(item => selectedItems.findIndex(e => e.label === item.label) < 0 && item.label.toLowerCase().startsWith(inputValue.toLowerCase()));
58
+ const getFilteredItems = () => items.filter(item => selectedItems.findIndex(e => e.label === item.label) < 0 && item.label.toLowerCase().startsWith(searchInputValue.toLowerCase()));
42
59
 
43
60
  const {
44
61
  isOpen,
@@ -49,7 +66,7 @@ const MultipleCombobox = ({
49
66
  highlightedIndex,
50
67
  getItemProps
51
68
  } = useCombobox({
52
- inputValue,
69
+ searchInputValue,
53
70
  defaultHighlightedIndex: 0,
54
71
  // after selection, highlight the first item.
55
72
  selectedItem: null,
@@ -76,21 +93,21 @@ const MultipleCombobox = ({
76
93
  return changes;
77
94
  },
78
95
  onStateChange: ({
79
- inputValue: newInputValue,
96
+ inputValue: newSearchInputValue,
80
97
  type,
81
98
  selectedItem
82
99
  }) => {
83
100
  switch (type) {
84
101
  case useCombobox.stateChangeTypes.InputChange:
85
- fetchOptions(newInputValue);
86
- setInputValue(newInputValue);
102
+ getOptions(newSearchInputValue);
103
+ setSearchInputValue(newSearchInputValue);
87
104
  break;
88
105
 
89
106
  case useCombobox.stateChangeTypes.InputKeyDownEnter:
90
107
  case useCombobox.stateChangeTypes.ItemClick:
91
108
  case useCombobox.stateChangeTypes.InputBlur:
92
109
  if (selectedItem) {
93
- setInputValue('');
110
+ setSearchInputValue('');
94
111
  addSelectedItem(selectedItem);
95
112
  }
96
113
 
@@ -102,16 +119,21 @@ const MultipleCombobox = ({
102
119
  }
103
120
  });
104
121
  useEffect(() => {
105
- if (selectedItems.length > 0) {
106
- setValue(selectedItems.map(e => e.value));
122
+ if ((selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.length) > 0) {
123
+ setValue(selectedItems);
107
124
  }
108
125
  }, [selectedItems]);
126
+ useEffect(() => {
127
+ if ((value === null || value === void 0 ? void 0 : value.length) > 0 && (testIfArraysAreUnique(value, selectedItems) || testIfArraysAreUnique(selectedItems, value))) {
128
+ setSelectedItems(value);
129
+ }
130
+ }, [value]);
131
+ const parentRef = useRef(null);
109
132
  return /*#__PURE__*/React.createElement("div", {
110
133
  id: id,
111
- className: [baseClassName, componentClassName, userClassName].filter(e => e).join(' '),
134
+ className: [baseClassName, componentClassName, userClassName, `y-${color}`, `x-${loadingCircleColor}`].filter(e => e).join(' '),
112
135
  style: style
113
136
  }, /*#__PURE__*/React.createElement(FormLabel, _extends({}, getLabelProps(), {
114
- className: "input-label",
115
137
  name: name
116
138
  }), label), /*#__PURE__*/React.createElement("div", {
117
139
  className: "selected-items"
@@ -129,16 +151,21 @@ const MultipleCombobox = ({
129
151
  isCompact: true,
130
152
  isSimple: true,
131
153
  color: "main2"
132
- }, "X")))), /*#__PURE__*/React.createElement("div", getComboboxProps(), /*#__PURE__*/React.createElement("input", _extends({}, getInputProps(getDropdownProps({
154
+ }, "X")))), /*#__PURE__*/React.createElement("div", _extends({}, getComboboxProps(), {
155
+ className: "input-wrapper"
156
+ }), /*#__PURE__*/React.createElement("input", _extends({}, getInputProps(getDropdownProps({
133
157
  preventKeyAction: isOpen
134
158
  })), {
135
159
  className: "input"
136
- }))), /*#__PURE__*/React.createElement(Menu, _extends({
160
+ })), isFetching && /*#__PURE__*/React.createElement(LoadingCircle, null)), /*#__PURE__*/React.createElement(Popover, {
161
+ isOpen: isOpen,
162
+ parentRef: parentRef
163
+ }, /*#__PURE__*/React.createElement(Menu, _extends({
137
164
  isOpen: isOpen,
138
165
  getItemProps: getItemProps,
139
166
  highlightedIndex: highlightedIndex,
140
167
  items: getFilteredItems()
141
- }, getMenuProps())), (description || error) && /*#__PURE__*/React.createElement(FormDescription, {
168
+ }, getMenuProps()))), (description || error) && /*#__PURE__*/React.createElement(FormDescription, {
142
169
  isError: !!error
143
170
  }, error || description));
144
171
  };
@@ -180,7 +207,7 @@ MultipleCombobox.propTypes = {
180
207
  /**
181
208
  * The function to fetch the options from the backend
182
209
  */
183
- fetchOptions: PropTypes.func,
210
+ getOptions: PropTypes.func,
184
211
 
185
212
  /**
186
213
  * The function to set the value of the custom select input
@@ -195,8 +222,32 @@ MultipleCombobox.propTypes = {
195
222
  /**
196
223
  * The error object
197
224
  */
198
- error: PropTypes.objectOf(PropTypes.string)
225
+ error: PropTypes.objectOf(PropTypes.string),
226
+
227
+ /**
228
+ * The value of the custom select input
229
+ */
230
+ value: PropTypes.arrayOf(PropTypes.shape({
231
+ value: PropTypes.string,
232
+ label: PropTypes.string
233
+ })),
234
+
235
+ /**
236
+ * The base color of the custom select input
237
+ */
238
+ color: PropTypes.string,
239
+
240
+ /**
241
+ * Whether the query getting the combobox options is inFlight
242
+ */
243
+ isFetching: PropTypes.bool.isRequired,
244
+
245
+ /**
246
+ * The loading circle color
247
+ */
248
+ loadingCircleColor: PropTypes.string
199
249
  };
200
- MultipleCombobox.defaultProps = {// someProp:false
250
+ MultipleCombobox.defaultProps = {
251
+ loadingCircleColor: 'main2'
201
252
  };
202
253
  export default MultipleCombobox;
@@ -5,11 +5,16 @@
5
5
  $default-input-padding: .75em .75em .55em;
6
6
  $default-padding: 1em;
7
7
  $default-margin: 1em;
8
+ $default-loading-circle-displacement: 1em;
8
9
 
9
10
  .#{bem.$base}.combobox,
10
11
  .#{bem.$base}.multiple-combobox {
11
12
  position: relative;
12
13
 
14
+ .#{bem.$base}.label {
15
+ margin-bottom: $default-margin
16
+ }
17
+
13
18
  .#{bem.$base}.popover {
14
19
  width: 100%;
15
20
 
@@ -30,6 +35,14 @@ $default-margin: 1em;
30
35
  }
31
36
 
32
37
  >.input-wrapper {
38
+ position: relative;
39
+
40
+ >.#{bem.$base}.loading-circle {
41
+ position: absolute;
42
+ top: $default-loading-circle-displacement;
43
+ right: $default-loading-circle-displacement;
44
+ }
45
+
33
46
  >.input {
34
47
  background: var(--light-y);
35
48
  border: var(--theme-border-style) var(--dark-y);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pareto-engineering/design-system",
3
- "version": "2.0.0-alpha.45",
3
+ "version": "2.0.0-alpha.46",
4
4
  "description": "",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/es/index.js",
@@ -10637,6 +10637,161 @@ exports[`Storyshots f/FormInput Extensible Form Input 1`] = `
10637
10637
  </form>
10638
10638
  `;
10639
10639
 
10640
+ exports[`Storyshots f/FormInput With Query Combobox 1`] = `
10641
+ <form
10642
+ action="#"
10643
+ onReset={[Function]}
10644
+ onSubmit={[Function]}
10645
+ >
10646
+ <div
10647
+ className="base text-input form-input y-background2"
10648
+ >
10649
+ <label
10650
+ className="base label v50 mb-v x-main2"
10651
+ htmlFor="firstName"
10652
+ >
10653
+ What's your first name ?
10654
+ </label>
10655
+ <input
10656
+ className="input"
10657
+ disabled={false}
10658
+ id="firstName"
10659
+ name="firstName"
10660
+ onBlur={[Function]}
10661
+ onChange={[Function]}
10662
+ type="text"
10663
+ value="Test"
10664
+ />
10665
+ </div>
10666
+ <div
10667
+ className="base choices-input form-input x-background2 y-main2"
10668
+ style={
10669
+ Object {
10670
+ "--grid-columns-desktop": 3,
10671
+ "--grid-columns-mobile": 2,
10672
+ }
10673
+ }
10674
+ >
10675
+ <p
10676
+ className="base label x-main2"
10677
+ >
10678
+ What are your favourite colors ?
10679
+ </p>
10680
+ <div
10681
+ className="choices"
10682
+ >
10683
+ <div
10684
+ className="base choice"
10685
+ >
10686
+ <input
10687
+ disabled={false}
10688
+ id="undefined-red"
10689
+ name="colors"
10690
+ onBlur={[Function]}
10691
+ onChange={[Function]}
10692
+ type="radio"
10693
+ value="red"
10694
+ />
10695
+ <label
10696
+ htmlFor="undefined-red"
10697
+ >
10698
+ Color Red
10699
+ </label>
10700
+ </div>
10701
+ <div
10702
+ className="base choice"
10703
+ >
10704
+ <input
10705
+ disabled={false}
10706
+ id="undefined-blue"
10707
+ name="colors"
10708
+ onBlur={[Function]}
10709
+ onChange={[Function]}
10710
+ type="radio"
10711
+ value="blue"
10712
+ />
10713
+ <label
10714
+ htmlFor="undefined-blue"
10715
+ >
10716
+ Color Blue
10717
+ </label>
10718
+ </div>
10719
+ <div
10720
+ className="base choice"
10721
+ >
10722
+ <input
10723
+ disabled={false}
10724
+ id="undefined-green"
10725
+ name="colors"
10726
+ onBlur={[Function]}
10727
+ onChange={[Function]}
10728
+ type="radio"
10729
+ value="green"
10730
+ />
10731
+ <label
10732
+ htmlFor="undefined-green"
10733
+ >
10734
+ Color Green
10735
+ </label>
10736
+ </div>
10737
+ </div>
10738
+ </div>
10739
+ <div
10740
+ className="base combobox form-input y-background2 x-main2"
10741
+ >
10742
+ <label
10743
+ className="base label x-main2"
10744
+ htmlFor="team"
10745
+ id="downshift-0-label"
10746
+ >
10747
+ Search for a team
10748
+ </label>
10749
+ <div
10750
+ aria-expanded={false}
10751
+ aria-haspopup="listbox"
10752
+ aria-owns="downshift-0-menu"
10753
+ className="input-wrapper"
10754
+ role="combobox"
10755
+ >
10756
+ <input
10757
+ aria-autocomplete="list"
10758
+ aria-controls="downshift-0-menu"
10759
+ aria-labelledby="downshift-0-label"
10760
+ autoComplete="off"
10761
+ className="input"
10762
+ id="downshift-0-input"
10763
+ onBlur={[Function]}
10764
+ onChange={[Function]}
10765
+ onKeyDown={[Function]}
10766
+ value=""
10767
+ />
10768
+ </div>
10769
+ <div
10770
+ className="base popover x-background1 bottom left"
10771
+ >
10772
+ <ul
10773
+ aria-labelledby="downshift-0-label"
10774
+ className="base menu"
10775
+ id="downshift-0-menu"
10776
+ onMouseLeave={[Function]}
10777
+ role="listbox"
10778
+ />
10779
+ </div>
10780
+ </div>
10781
+ <div
10782
+ className="debugger"
10783
+ >
10784
+ <button
10785
+ className="base button x-main2"
10786
+ onClick={[Function]}
10787
+ type="button"
10788
+ >
10789
+ Open FormDebugger
10790
+ </button>
10791
+ </div>
10792
+ </form>
10793
+ `;
10794
+
10640
10795
  exports[`Storyshots f/common/Description Base 1`] = `
10641
10796
  <div
10642
10797
  className="base description x-metadata"
@@ -11205,29 +11360,29 @@ exports[`Storyshots f/fields/QueryCombobox Single Select 1`] = `
11205
11360
  onSubmit={[Function]}
11206
11361
  >
11207
11362
  <div
11208
- className="base combobox y-background2"
11363
+ className="base combobox y-background2 x-main2"
11209
11364
  >
11210
11365
  <label
11211
11366
  className="base label x-main2"
11212
11367
  htmlFor="team"
11213
- id="downshift-0-label"
11368
+ id="downshift-1-label"
11214
11369
  >
11215
11370
  Search for a team
11216
11371
  </label>
11217
11372
  <div
11218
11373
  aria-expanded={false}
11219
11374
  aria-haspopup="listbox"
11220
- aria-owns="downshift-0-menu"
11375
+ aria-owns="downshift-1-menu"
11221
11376
  className="input-wrapper"
11222
11377
  role="combobox"
11223
11378
  >
11224
11379
  <input
11225
11380
  aria-autocomplete="list"
11226
- aria-controls="downshift-0-menu"
11227
- aria-labelledby="downshift-0-label"
11381
+ aria-controls="downshift-1-menu"
11382
+ aria-labelledby="downshift-1-label"
11228
11383
  autoComplete="off"
11229
11384
  className="input"
11230
- id="downshift-0-input"
11385
+ id="downshift-1-input"
11231
11386
  onBlur={[Function]}
11232
11387
  onChange={[Function]}
11233
11388
  onKeyDown={[Function]}
@@ -11238,9 +11393,9 @@ exports[`Storyshots f/fields/QueryCombobox Single Select 1`] = `
11238
11393
  className="base popover x-background1 bottom left"
11239
11394
  >
11240
11395
  <ul
11241
- aria-labelledby="downshift-0-label"
11396
+ aria-labelledby="downshift-1-label"
11242
11397
  className="base menu"
11243
- id="downshift-0-menu"
11398
+ id="downshift-1-menu"
11244
11399
  onMouseLeave={[Function]}
11245
11400
  role="listbox"
11246
11401
  />
@@ -11284,29 +11439,29 @@ exports[`Storyshots f/fields/QueryCombobox Single Select With Default Formik Sta
11284
11439
  onSubmit={[Function]}
11285
11440
  >
11286
11441
  <div
11287
- className="base combobox y-background2"
11442
+ className="base combobox y-background2 x-main2"
11288
11443
  >
11289
11444
  <label
11290
11445
  className="base label x-main2"
11291
11446
  htmlFor="team"
11292
- id="downshift-1-label"
11447
+ id="downshift-2-label"
11293
11448
  >
11294
11449
  Search for a team
11295
11450
  </label>
11296
11451
  <div
11297
11452
  aria-expanded={false}
11298
11453
  aria-haspopup="listbox"
11299
- aria-owns="downshift-1-menu"
11454
+ aria-owns="downshift-2-menu"
11300
11455
  className="input-wrapper"
11301
11456
  role="combobox"
11302
11457
  >
11303
11458
  <input
11304
11459
  aria-autocomplete="list"
11305
- aria-controls="downshift-1-menu"
11306
- aria-labelledby="downshift-1-label"
11460
+ aria-controls="downshift-2-menu"
11461
+ aria-labelledby="downshift-2-label"
11307
11462
  autoComplete="off"
11308
11463
  className="input"
11309
- id="downshift-1-input"
11464
+ id="downshift-2-input"
11310
11465
  onBlur={[Function]}
11311
11466
  onChange={[Function]}
11312
11467
  onKeyDown={[Function]}
@@ -11317,9 +11472,9 @@ exports[`Storyshots f/fields/QueryCombobox Single Select With Default Formik Sta
11317
11472
  className="base popover x-background1 bottom left"
11318
11473
  >
11319
11474
  <ul
11320
- aria-labelledby="downshift-1-label"
11475
+ aria-labelledby="downshift-2-label"
11321
11476
  className="base menu"
11322
- id="downshift-1-menu"
11477
+ id="downshift-2-menu"
11323
11478
  onMouseLeave={[Function]}
11324
11479
  role="listbox"
11325
11480
  />
@@ -8,6 +8,15 @@ import {
8
8
  FormDebugger,
9
9
  } from 'ui'
10
10
 
11
+ import { fruits } from '../utils/testData'
12
+
13
+ import {
14
+ RelayEnvironmentProvider,
15
+ mockRelayOperation,
16
+ } from '../utils/relay'
17
+
18
+ import generateNodeId from '../utils/generateNodeId'
19
+
11
20
  export default {
12
21
  title :'f/FormInput',
13
22
  component :FormInput,
@@ -25,6 +34,11 @@ export default {
25
34
  </Form>
26
35
  </Formik>
27
36
  ),
37
+ (storyfn) => (
38
+ <RelayEnvironmentProvider>
39
+ { storyfn() }
40
+ </RelayEnvironmentProvider>
41
+ ),
28
42
  ],
29
43
  argTypes:{
30
44
  backgroundColor:{ control: 'color' },
@@ -99,6 +113,107 @@ export const Base = () => {
99
113
  )
100
114
  }
101
115
 
116
+ const allTeamsMockData = {
117
+ PageInfo() {
118
+ return {
119
+ hasNextPage :true,
120
+ hasPreviousPage:true,
121
+ }
122
+ },
123
+ TeamNodeConnection:(args) => {
124
+ const edges = fruits.map((fruit) => ({
125
+ node:{
126
+ id :generateNodeId('TeamNode'),
127
+ name:fruit,
128
+ },
129
+ }))
130
+
131
+ // eslint-disable-next-line camelcase
132
+ const { name_Icontains } = args?.args || {}
133
+
134
+ return ({
135
+ pageInfo:{
136
+ hasNextPage :true,
137
+ hasPreviousPage:true,
138
+ },
139
+ // eslint-disable-next-line camelcase
140
+ edges:name_Icontains?.trim()
141
+ ? edges.filter(({ node }) => node.name
142
+ .toLowerCase()
143
+ .includes(name_Icontains.toLowerCase()))
144
+ : [],
145
+ })
146
+ },
147
+ }
148
+
149
+ const FETCH_TEAMS_QUERY = graphql`
150
+ query FormInputAllTeamsQuery($name_Icontains: String) {
151
+ allTeams(name_Icontains: $name_Icontains) {
152
+ edges {
153
+ node {
154
+ id
155
+ name
156
+ }
157
+ }
158
+ }
159
+ }
160
+ `
161
+
162
+ export const WithQueryCombobox = () => {
163
+ const inputMap = [
164
+ {
165
+ type :'text',
166
+ name :'firstName',
167
+ label:"What's your first name ?",
168
+ },
169
+ {
170
+ type :'choices',
171
+ name :'colors',
172
+ label :'What are your favourite colors ?',
173
+ options:[
174
+ {
175
+ value:'red',
176
+ label:'Color Red',
177
+ },
178
+ {
179
+ value:'blue',
180
+ label:'Color Blue',
181
+ },
182
+ {
183
+ value:'green',
184
+ label:'Color Green',
185
+ },
186
+ ],
187
+ },
188
+ {
189
+ type :'query-combobox',
190
+ name :'team',
191
+ query :FETCH_TEAMS_QUERY,
192
+ label :'Search for a team',
193
+ optionsKeyMap:{
194
+ value:'id',
195
+ label:'name',
196
+ },
197
+ graphQlNode :'allTeams',
198
+ searchVariable:'name_Icontains',
199
+ },
200
+ ]
201
+
202
+ mockRelayOperation(allTeamsMockData)
203
+ mockRelayOperation(allTeamsMockData)
204
+ mockRelayOperation(allTeamsMockData)
205
+
206
+ return (
207
+ <>
208
+ {
209
+ inputMap.map((input) => <FormInput {...input} key={input.name} />)
210
+ }
211
+ <FormDebugger />
212
+
213
+ </>
214
+ )
215
+ }
216
+
102
217
  export const ExtensibleFormInput = () => {
103
218
  const ExtendedTextInput = (props) => (
104
219
  <TextInput
@@ -0,0 +1,139 @@
1
+ /**
2
+ * @flow
3
+ */
4
+
5
+ /* eslint-disable */
6
+
7
+ 'use strict';
8
+
9
+ /*::
10
+ import type { ConcreteRequest } from 'relay-runtime';
11
+ export type FormInputAllTeamsQueryVariables = {|
12
+ name_Icontains?: ?string
13
+ |};
14
+ export type FormInputAllTeamsQueryResponse = {|
15
+ +allTeams: ?{|
16
+ +edges: $ReadOnlyArray<?{|
17
+ +node: ?{|
18
+ +id: string,
19
+ +name: string,
20
+ |}
21
+ |}>
22
+ |}
23
+ |};
24
+ export type FormInputAllTeamsQuery = {|
25
+ variables: FormInputAllTeamsQueryVariables,
26
+ response: FormInputAllTeamsQueryResponse,
27
+ |};
28
+ */
29
+
30
+
31
+ /*
32
+ query FormInputAllTeamsQuery(
33
+ $name_Icontains: String
34
+ ) {
35
+ allTeams(name_Icontains: $name_Icontains) {
36
+ edges {
37
+ node {
38
+ id
39
+ name
40
+ }
41
+ }
42
+ }
43
+ }
44
+ */
45
+
46
+ const node/*: ConcreteRequest*/ = (function(){
47
+ var v0 = [
48
+ {
49
+ "defaultValue": null,
50
+ "kind": "LocalArgument",
51
+ "name": "name_Icontains"
52
+ }
53
+ ],
54
+ v1 = [
55
+ {
56
+ "alias": null,
57
+ "args": [
58
+ {
59
+ "kind": "Variable",
60
+ "name": "name_Icontains",
61
+ "variableName": "name_Icontains"
62
+ }
63
+ ],
64
+ "concreteType": "TeamNodeConnection",
65
+ "kind": "LinkedField",
66
+ "name": "allTeams",
67
+ "plural": false,
68
+ "selections": [
69
+ {
70
+ "alias": null,
71
+ "args": null,
72
+ "concreteType": "TeamNodeEdge",
73
+ "kind": "LinkedField",
74
+ "name": "edges",
75
+ "plural": true,
76
+ "selections": [
77
+ {
78
+ "alias": null,
79
+ "args": null,
80
+ "concreteType": "TeamNode",
81
+ "kind": "LinkedField",
82
+ "name": "node",
83
+ "plural": false,
84
+ "selections": [
85
+ {
86
+ "alias": null,
87
+ "args": null,
88
+ "kind": "ScalarField",
89
+ "name": "id",
90
+ "storageKey": null
91
+ },
92
+ {
93
+ "alias": null,
94
+ "args": null,
95
+ "kind": "ScalarField",
96
+ "name": "name",
97
+ "storageKey": null
98
+ }
99
+ ],
100
+ "storageKey": null
101
+ }
102
+ ],
103
+ "storageKey": null
104
+ }
105
+ ],
106
+ "storageKey": null
107
+ }
108
+ ];
109
+ return {
110
+ "fragment": {
111
+ "argumentDefinitions": (v0/*: any*/),
112
+ "kind": "Fragment",
113
+ "metadata": null,
114
+ "name": "FormInputAllTeamsQuery",
115
+ "selections": (v1/*: any*/),
116
+ "type": "Query",
117
+ "abstractKey": null
118
+ },
119
+ "kind": "Request",
120
+ "operation": {
121
+ "argumentDefinitions": (v0/*: any*/),
122
+ "kind": "Operation",
123
+ "name": "FormInputAllTeamsQuery",
124
+ "selections": (v1/*: any*/)
125
+ },
126
+ "params": {
127
+ "cacheID": "dc9287c6d087d0f0e1be2e8ef405cb1f",
128
+ "id": null,
129
+ "metadata": {},
130
+ "name": "FormInputAllTeamsQuery",
131
+ "operationKind": "query",
132
+ "text": "query FormInputAllTeamsQuery(\n $name_Icontains: String\n) {\n allTeams(name_Icontains: $name_Icontains) {\n edges {\n node {\n id\n name\n }\n }\n }\n}\n"
133
+ }
134
+ };
135
+ })();
136
+ // prettier-ignore
137
+ (node/*: any*/).hash = 'c76b6f84436895e8a6d0725bdd41cfe0';
138
+
139
+ module.exports = node;
@@ -10,6 +10,7 @@ import {
10
10
  TextareaInput,
11
11
  ChoicesInput,
12
12
  SelectInput,
13
+ QueryCombobox,
13
14
  } from '../fields'
14
15
 
15
16
  // Local Definitions
@@ -64,6 +65,15 @@ const FormInput = ({
64
65
  />
65
66
  )
66
67
  }
68
+ if (type === 'query-combobox') {
69
+ return (
70
+ <QueryCombobox
71
+ className={newClassName}
72
+ disabled={disabled}
73
+ {...otherProps}
74
+ />
75
+ )
76
+ }
67
77
  if (extraTypes?.[type]) {
68
78
  const Component = extraTypes[type]
69
79
  return (
@@ -106,6 +116,7 @@ FormInput.propTypes = {
106
116
  'select',
107
117
  'choices',
108
118
  'textarea',
119
+ 'query-combobox',
109
120
  // to be removed
110
121
  'extendedTypeInput',
111
122
  ]),
@@ -17,6 +17,9 @@ import { Combobox } from './common'
17
17
  * This is the component description.
18
18
  */
19
19
  const QueryCombobox = ({
20
+ id,
21
+ style,
22
+ className,
20
23
  query,
21
24
  // multiple,
22
25
  name,
@@ -85,6 +88,8 @@ const QueryCombobox = ({
85
88
  }
86
89
 
87
90
  const comboboxProps = {
91
+ id,
92
+ style,
88
93
  options,
89
94
  getOptions,
90
95
  debounceMs,
@@ -96,6 +101,8 @@ const QueryCombobox = ({
96
101
  error,
97
102
  value,
98
103
  color,
104
+ isFetching,
105
+ className,
99
106
  }
100
107
 
101
108
  const Input = Combobox
@@ -11,7 +11,7 @@ import styleNames from '@pareto-engineering/bem'
11
11
 
12
12
  import { FormLabel, FormDescription } from 'ui/f'
13
13
 
14
- import { Popover } from 'ui/a'
14
+ import { Popover, LoadingCircle } from 'ui/a'
15
15
 
16
16
  // Local Definitions
17
17
 
@@ -37,6 +37,8 @@ const Combobox = ({
37
37
  description,
38
38
  value,
39
39
  color,
40
+ loadingCircleColor,
41
+ isFetching,
40
42
  // ...otherProps
41
43
  }) => {
42
44
  const {
@@ -85,6 +87,7 @@ const Combobox = ({
85
87
  componentClassName,
86
88
  userClassName,
87
89
  `y-${color}`,
90
+ `x-${loadingCircleColor}`,
88
91
  ]
89
92
  .filter((e) => e)
90
93
  .join(' ')}
@@ -97,6 +100,9 @@ const Combobox = ({
97
100
 
98
101
  <div {...getComboboxProps()} className="input-wrapper">
99
102
  <input {...getInputProps()} className="input" />
103
+ {isFetching && (
104
+ <LoadingCircle />
105
+ )}
100
106
  </div>
101
107
 
102
108
  <Popover
@@ -189,10 +195,20 @@ Combobox.propTypes = {
189
195
  * The base color of the combobox custom select input
190
196
  */
191
197
  color:PropTypes.string,
198
+
199
+ /**
200
+ * Whether the query getting the combobox options is inFlight
201
+ */
202
+ isFetching:PropTypes.bool.isRequired,
203
+
204
+ /**
205
+ * The loading circle color
206
+ */
207
+ loadingCircleColor:PropTypes.string,
192
208
  }
193
209
 
194
210
  Combobox.defaultProps = {
195
- // someProp:false
211
+ loadingCircleColor:'main2',
196
212
  }
197
213
 
198
214
  export default Combobox
@@ -5,11 +5,16 @@
5
5
  $default-input-padding: .75em .75em .55em;
6
6
  $default-padding: 1em;
7
7
  $default-margin: 1em;
8
+ $default-loading-circle-displacement: 1em;
8
9
 
9
10
  .#{bem.$base}.combobox,
10
11
  .#{bem.$base}.multiple-combobox {
11
12
  position: relative;
12
13
 
14
+ .#{bem.$base}.label {
15
+ margin-bottom: $default-margin
16
+ }
17
+
13
18
  .#{bem.$base}.popover {
14
19
  width: 100%;
15
20
 
@@ -30,6 +35,14 @@ $default-margin: 1em;
30
35
  }
31
36
 
32
37
  >.input-wrapper {
38
+ position: relative;
39
+
40
+ >.#{bem.$base}.loading-circle {
41
+ position: absolute;
42
+ top: $default-loading-circle-displacement;
43
+ right: $default-loading-circle-displacement;
44
+ }
45
+
33
46
  >.input {
34
47
  background: var(--light-y);
35
48
  border: var(--theme-border-style) var(--dark-y);