@pareto-engineering/design-system 2.0.0-alpha.45 → 2.0.0-alpha.48
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.
- package/dist/cjs/f/FormInput/FormInput.js +8 -1
- package/dist/cjs/f/fields/QueryCombobox/QueryCombobox.js +29 -6
- package/dist/cjs/f/fields/QueryCombobox/common/Combobox/Combobox.js +29 -5
- package/dist/cjs/f/fields/QueryCombobox/common/MultipleCombobox/MultipleCombobox.js +101 -26
- package/dist/cjs/f/fields/QueryCombobox/common/index.js +9 -1
- package/dist/cjs/f/fields/QueryCombobox/styles.scss +24 -5
- package/dist/es/f/FormInput/FormInput.js +9 -2
- package/dist/es/f/fields/QueryCombobox/QueryCombobox.js +30 -7
- package/dist/es/f/fields/QueryCombobox/common/Combobox/Combobox.js +30 -6
- package/dist/es/f/fields/QueryCombobox/common/MultipleCombobox/MultipleCombobox.js +101 -27
- package/dist/es/f/fields/QueryCombobox/common/index.js +2 -1
- package/dist/es/f/fields/QueryCombobox/styles.scss +24 -5
- package/package.json +2 -2
- package/src/__snapshots__/Storyshots.test.js.snap +379 -14
- package/src/local.scss +3 -3
- package/src/stories/f/FormInput.stories.jsx +115 -0
- package/src/stories/f/QueryCombobox.stories.jsx +55 -8
- package/src/stories/f/__generated__/FormInputAllTeamsQuery.graphql.js +139 -0
- package/src/ui/f/FormInput/FormInput.jsx +11 -0
- package/src/ui/f/fields/QueryCombobox/QueryCombobox.jsx +29 -6
- package/src/ui/f/fields/QueryCombobox/common/Combobox/Combobox.jsx +27 -3
- package/src/ui/f/fields/QueryCombobox/common/MultipleCombobox/MultipleCombobox.jsx +318 -0
- package/src/ui/f/fields/QueryCombobox/common/MultipleCombobox/index.js +2 -0
- package/src/ui/f/fields/QueryCombobox/common/index.js +1 -0
- package/src/ui/f/fields/QueryCombobox/styles.scss +24 -5
|
@@ -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,34 @@ const MultipleCombobox = ({
|
|
|
23
33
|
label,
|
|
24
34
|
name,
|
|
25
35
|
options: items,
|
|
26
|
-
|
|
36
|
+
getOptions,
|
|
27
37
|
setValue,
|
|
28
38
|
error,
|
|
29
|
-
description
|
|
39
|
+
description,
|
|
40
|
+
value,
|
|
41
|
+
color,
|
|
42
|
+
isFetching,
|
|
43
|
+
minLength,
|
|
44
|
+
transformSearch // ...otherProps
|
|
30
45
|
|
|
31
46
|
}) => {
|
|
32
|
-
const [
|
|
47
|
+
const [searchInputValue, setSearchInputValue] = useState('');
|
|
33
48
|
const {
|
|
34
49
|
getSelectedItemProps,
|
|
35
50
|
getDropdownProps,
|
|
36
51
|
addSelectedItem,
|
|
37
52
|
removeSelectedItem,
|
|
53
|
+
setSelectedItems,
|
|
38
54
|
selectedItems
|
|
39
|
-
} = useMultipleSelection(
|
|
55
|
+
} = useMultipleSelection({
|
|
56
|
+
initialSelectedItems: value || []
|
|
57
|
+
});
|
|
58
|
+
/**
|
|
59
|
+
* @returns {Boolean} - Unique items from the options array so that the combobox
|
|
60
|
+
* shows only the options that are not yet selected.
|
|
61
|
+
*/
|
|
40
62
|
|
|
41
|
-
const getFilteredItems = () => items.filter(item => selectedItems.findIndex(e => e.label === item.label) < 0
|
|
63
|
+
const getFilteredItems = () => items.filter(item => selectedItems.findIndex(e => e.label === item.label) < 0);
|
|
42
64
|
|
|
43
65
|
const {
|
|
44
66
|
isOpen,
|
|
@@ -49,7 +71,7 @@ const MultipleCombobox = ({
|
|
|
49
71
|
highlightedIndex,
|
|
50
72
|
getItemProps
|
|
51
73
|
} = useCombobox({
|
|
52
|
-
|
|
74
|
+
searchInputValue,
|
|
53
75
|
defaultHighlightedIndex: 0,
|
|
54
76
|
// after selection, highlight the first item.
|
|
55
77
|
selectedItem: null,
|
|
@@ -76,21 +98,28 @@ const MultipleCombobox = ({
|
|
|
76
98
|
return changes;
|
|
77
99
|
},
|
|
78
100
|
onStateChange: ({
|
|
79
|
-
inputValue:
|
|
101
|
+
inputValue: newSearchInputValue,
|
|
80
102
|
type,
|
|
81
103
|
selectedItem
|
|
82
104
|
}) => {
|
|
83
105
|
switch (type) {
|
|
84
106
|
case useCombobox.stateChangeTypes.InputChange:
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
107
|
+
{
|
|
108
|
+
const transformedInput = transformSearch(newSearchInputValue);
|
|
109
|
+
|
|
110
|
+
if (transformedInput.length > minLength) {
|
|
111
|
+
getOptions(transformedInput);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
setSearchInputValue(newSearchInputValue);
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
88
117
|
|
|
89
118
|
case useCombobox.stateChangeTypes.InputKeyDownEnter:
|
|
90
119
|
case useCombobox.stateChangeTypes.ItemClick:
|
|
91
120
|
case useCombobox.stateChangeTypes.InputBlur:
|
|
92
121
|
if (selectedItem) {
|
|
93
|
-
|
|
122
|
+
setSearchInputValue('');
|
|
94
123
|
addSelectedItem(selectedItem);
|
|
95
124
|
}
|
|
96
125
|
|
|
@@ -102,43 +131,60 @@ const MultipleCombobox = ({
|
|
|
102
131
|
}
|
|
103
132
|
});
|
|
104
133
|
useEffect(() => {
|
|
105
|
-
if (selectedItems.length > 0) {
|
|
106
|
-
setValue(selectedItems
|
|
134
|
+
if ((selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.length) > 0) {
|
|
135
|
+
setValue(selectedItems);
|
|
107
136
|
}
|
|
108
137
|
}, [selectedItems]);
|
|
138
|
+
useEffect(() => {
|
|
139
|
+
if ((value === null || value === void 0 ? void 0 : value.length) > 0 && (testIfArraysAreUnique(value, selectedItems) || testIfArraysAreUnique(selectedItems, value))) {
|
|
140
|
+
setSelectedItems(value);
|
|
141
|
+
}
|
|
142
|
+
}, [value]);
|
|
143
|
+
const parentRef = useRef(null);
|
|
109
144
|
return /*#__PURE__*/React.createElement("div", {
|
|
110
145
|
id: id,
|
|
111
|
-
className: [baseClassName, componentClassName, userClassName].filter(e => e).join(' '),
|
|
146
|
+
className: [baseClassName, componentClassName, userClassName, `y-${color}`].filter(e => e).join(' '),
|
|
112
147
|
style: style
|
|
113
148
|
}, /*#__PURE__*/React.createElement(FormLabel, _extends({}, getLabelProps(), {
|
|
114
|
-
className: "input-label",
|
|
115
149
|
name: name
|
|
116
|
-
}), label), /*#__PURE__*/React.createElement("div", {
|
|
150
|
+
}), label), (selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.length) > 0 && /*#__PURE__*/React.createElement("div", {
|
|
117
151
|
className: "selected-items"
|
|
118
|
-
}, selectedItems
|
|
152
|
+
}, selectedItems.map((selectedItem, index) => /*#__PURE__*/React.createElement("div", _extends({
|
|
119
153
|
key: selectedItem.label
|
|
120
154
|
}, getSelectedItemProps({
|
|
121
155
|
selectedItem,
|
|
122
156
|
index
|
|
123
|
-
})
|
|
124
|
-
className: "
|
|
157
|
+
}), {
|
|
158
|
+
className: "item"
|
|
159
|
+
}), /*#__PURE__*/React.createElement(Button, {
|
|
125
160
|
onClick: e => {
|
|
126
161
|
e.stopPropagation();
|
|
127
162
|
removeSelectedItem(selectedItem);
|
|
128
163
|
},
|
|
129
164
|
isCompact: true,
|
|
130
165
|
isSimple: true,
|
|
131
|
-
color:
|
|
132
|
-
},
|
|
166
|
+
color: color
|
|
167
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
168
|
+
className: "v25 mr-v"
|
|
169
|
+
}, selectedItem.label), /*#__PURE__*/React.createElement("span", {
|
|
170
|
+
className: "f-icons close"
|
|
171
|
+
}, "Y"))))), /*#__PURE__*/React.createElement("div", _extends({}, getComboboxProps(), {
|
|
172
|
+
className: "input-wrapper"
|
|
173
|
+
}), /*#__PURE__*/React.createElement("input", _extends({}, getInputProps(getDropdownProps({
|
|
133
174
|
preventKeyAction: isOpen
|
|
134
175
|
})), {
|
|
135
176
|
className: "input"
|
|
136
|
-
}))
|
|
177
|
+
})), isFetching && /*#__PURE__*/React.createElement(LoadingCircle, {
|
|
178
|
+
className: "x-main2"
|
|
179
|
+
})), /*#__PURE__*/React.createElement(Popover, {
|
|
180
|
+
isOpen: isOpen,
|
|
181
|
+
parentRef: parentRef
|
|
182
|
+
}, /*#__PURE__*/React.createElement(Menu, _extends({
|
|
137
183
|
isOpen: isOpen,
|
|
138
184
|
getItemProps: getItemProps,
|
|
139
185
|
highlightedIndex: highlightedIndex,
|
|
140
186
|
items: getFilteredItems()
|
|
141
|
-
}, getMenuProps())), (description || error) && /*#__PURE__*/React.createElement(FormDescription, {
|
|
187
|
+
}, getMenuProps()))), (description || error) && /*#__PURE__*/React.createElement(FormDescription, {
|
|
142
188
|
isError: !!error
|
|
143
189
|
}, error || description));
|
|
144
190
|
};
|
|
@@ -180,7 +226,7 @@ MultipleCombobox.propTypes = {
|
|
|
180
226
|
/**
|
|
181
227
|
* The function to fetch the options from the backend
|
|
182
228
|
*/
|
|
183
|
-
|
|
229
|
+
getOptions: PropTypes.func,
|
|
184
230
|
|
|
185
231
|
/**
|
|
186
232
|
* The function to set the value of the custom select input
|
|
@@ -195,8 +241,36 @@ MultipleCombobox.propTypes = {
|
|
|
195
241
|
/**
|
|
196
242
|
* The error object
|
|
197
243
|
*/
|
|
198
|
-
error: PropTypes.objectOf(PropTypes.string)
|
|
244
|
+
error: PropTypes.objectOf(PropTypes.string),
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* The value of the custom select input
|
|
248
|
+
*/
|
|
249
|
+
value: PropTypes.arrayOf(PropTypes.shape({
|
|
250
|
+
value: PropTypes.string,
|
|
251
|
+
label: PropTypes.string
|
|
252
|
+
})),
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* The base color of the custom select input
|
|
256
|
+
*/
|
|
257
|
+
color: PropTypes.string,
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Whether the query getting the combobox options is inFlight
|
|
261
|
+
*/
|
|
262
|
+
isFetching: PropTypes.bool.isRequired,
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* The minimum length of the search input to start fetching the options
|
|
266
|
+
*/
|
|
267
|
+
minLength: PropTypes.number,
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* The function to transform the search input
|
|
271
|
+
*/
|
|
272
|
+
transformSearch: PropTypes.func
|
|
199
273
|
};
|
|
200
|
-
MultipleCombobox.defaultProps = {// someProp:false
|
|
274
|
+
MultipleCombobox.defaultProps = {// someProp: false
|
|
201
275
|
};
|
|
202
276
|
export default MultipleCombobox;
|
|
@@ -5,11 +5,17 @@
|
|
|
5
5
|
$default-input-padding: .75em .75em .55em;
|
|
6
6
|
$default-padding: 1em;
|
|
7
7
|
$default-margin: 1em;
|
|
8
|
+
$default-gap: 1em;
|
|
9
|
+
$default-loading-circle-displacement: 1em;
|
|
8
10
|
|
|
9
11
|
.#{bem.$base}.combobox,
|
|
10
12
|
.#{bem.$base}.multiple-combobox {
|
|
11
13
|
position: relative;
|
|
12
14
|
|
|
15
|
+
.#{bem.$base}.label {
|
|
16
|
+
margin-bottom: $default-margin
|
|
17
|
+
}
|
|
18
|
+
|
|
13
19
|
.#{bem.$base}.popover {
|
|
14
20
|
width: 100%;
|
|
15
21
|
|
|
@@ -30,6 +36,14 @@ $default-margin: 1em;
|
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
>.input-wrapper {
|
|
39
|
+
position: relative;
|
|
40
|
+
|
|
41
|
+
>.#{bem.$base}.loading-circle {
|
|
42
|
+
position: absolute;
|
|
43
|
+
top: $default-loading-circle-displacement;
|
|
44
|
+
right: $default-loading-circle-displacement;
|
|
45
|
+
}
|
|
46
|
+
|
|
33
47
|
>.input {
|
|
34
48
|
background: var(--light-y);
|
|
35
49
|
border: var(--theme-border-style) var(--dark-y);
|
|
@@ -60,12 +74,17 @@ $default-margin: 1em;
|
|
|
60
74
|
.#{bem.$base}.multiple-combobox {
|
|
61
75
|
>.selected-items {
|
|
62
76
|
display: flex;
|
|
77
|
+
gap: $default-gap / 2;
|
|
78
|
+
flex-wrap: wrap;
|
|
79
|
+
margin-bottom: $default-margin / 2;
|
|
63
80
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
81
|
+
>.item {
|
|
82
|
+
background-color: var(--main2);
|
|
83
|
+
padding: $default-padding / 4;
|
|
68
84
|
|
|
69
|
-
|
|
85
|
+
.close {
|
|
86
|
+
font-size: calc(var(--s-3) * 1em);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
70
89
|
}
|
|
71
90
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pareto-engineering/design-system",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.48",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/es/index.js",
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"stylelint-config-palantir": "^5.1.0"
|
|
89
89
|
},
|
|
90
90
|
"dependencies": {
|
|
91
|
-
"@pareto-engineering/assets": "^2.0.0-alpha.
|
|
91
|
+
"@pareto-engineering/assets": "^2.0.0-alpha.22",
|
|
92
92
|
"@pareto-engineering/bem": "^0.1.5",
|
|
93
93
|
"@pareto-engineering/styles": "^2.0.0-alpha.8",
|
|
94
94
|
"date-fns": "^2.22.1",
|