@pareto-engineering/design-system 4.0.0-alpha.58 → 4.0.0-alpha.60
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/a/AnimatedBlobs/AnimatedBlobs.js +6 -6
- package/dist/cjs/a/AnimatedGradient/AnimatedGradient.js +7 -7
- package/dist/cjs/a/AppContext/Context.js +3 -4
- package/dist/cjs/a/AppContext/ContextProvider.js +6 -6
- package/dist/cjs/a/AppContext/useTheme.js +2 -3
- package/dist/cjs/a/BlurOverlay/BlurOverlay.js +6 -6
- package/dist/cjs/a/ContentTree/ContentTree.js +6 -6
- package/dist/cjs/a/ContentTree/common/Tree/Tree.js +8 -8
- package/dist/cjs/a/ContentTree/common/useContentTree.js +1 -2
- package/dist/cjs/a/ContentTree/common/useFirstVisibleNode.js +1 -2
- package/dist/cjs/a/Conversation/Context.js +3 -4
- package/dist/cjs/a/Conversation/Conversation.js +6 -6
- package/dist/cjs/a/Conversation/common/Message/Message.js +3 -4
- package/dist/cjs/a/DotInfo/DotInfo.js +6 -6
- package/dist/cjs/a/Figure/Figure.js +6 -6
- package/dist/cjs/a/HamburgerButton/HamburgerButton.js +6 -6
- package/dist/cjs/a/IconList/IconList.js +6 -6
- package/dist/cjs/a/IconList/common/Item/Item.js +3 -4
- package/dist/cjs/a/Label/Label.js +6 -6
- package/dist/cjs/a/LoadingCircle/LoadingCircle.js +6 -6
- package/dist/cjs/a/MetaCard/MetaCard.js +6 -6
- package/dist/cjs/a/People/People.js +6 -6
- package/dist/cjs/a/People/common/Person/Person.js +3 -4
- package/dist/cjs/a/Popover/Popover.js +7 -7
- package/dist/cjs/a/ProgressBar/ProgressBar.js +6 -6
- package/dist/cjs/a/Quote/Quote.js +6 -6
- package/dist/cjs/a/Removable/Removable.js +6 -6
- package/dist/cjs/a/SVG/SVG.js +7 -7
- package/dist/cjs/a/SVG/common/UseSVG/UseSVG.js +3 -4
- package/dist/cjs/a/SnapScroller/SnapScroller.js +38 -12
- package/dist/cjs/a/Spinner/Spinner.js +6 -6
- package/dist/cjs/a/TextSteps/TextSteps.js +6 -6
- package/dist/cjs/a/Timestamp/Timestamp.js +9 -9
- package/dist/cjs/a/Tip/Tip.js +6 -6
- package/dist/cjs/a/ToggleSwitch/ToggleSwitch.js +6 -6
- package/dist/cjs/b/Button/Button.js +6 -6
- package/dist/cjs/b/Button/common/Group/Group.js +6 -6
- package/dist/cjs/b/Card/Card.js +6 -6
- package/dist/cjs/b/Card/common/Group/Group.js +6 -6
- package/dist/cjs/b/Card/common/Section/Section.js +3 -4
- package/dist/cjs/b/Logo/Logo.js +7 -7
- package/dist/cjs/b/Page/Context.js +3 -4
- package/dist/cjs/b/Page/Page.js +7 -7
- package/dist/cjs/b/Page/common/PageHelmet/PageHelmet.js +6 -6
- package/dist/cjs/b/Page/common/Section/Section.js +3 -4
- package/dist/cjs/b/SocialMediaButton/SocialMediaButton.js +6 -6
- package/dist/cjs/b/ThemeSelector/ThemeSelector.js +7 -7
- package/dist/cjs/b/Title/Title.js +6 -6
- package/dist/cjs/c/ContentSlides/ContentSlides.js +8 -8
- package/dist/cjs/c/ContentSlides/Context.js +3 -4
- package/dist/cjs/c/ContentSlides/common/HorizontalMenu/HorizontalMenu.js +3 -4
- package/dist/cjs/c/ContentSlides/common/Navigator/Navigator.js +3 -4
- package/dist/cjs/c/ContentSlides/common/Sidebar/Sidebar.js +3 -4
- package/dist/cjs/c/ContentSlides/common/Slide/Slide.js +3 -4
- package/dist/cjs/c/Modal/Modal.js +6 -6
- package/dist/cjs/c/Modal/common/ModalHeader/ModalHeader.js +3 -4
- package/dist/cjs/c/Shortener/Shortener.js +7 -7
- package/dist/cjs/c/SocialMediaShareButton/SocialMediaShareButton.js +6 -6
- package/dist/cjs/f/FormInput/FormInput.js +6 -6
- package/dist/cjs/f/common/Debugger/Debugger.js +8 -8
- package/dist/cjs/f/common/Description/Description.js +6 -6
- package/dist/cjs/f/common/InputWrapper/InputWrapper.js +6 -6
- package/dist/cjs/f/common/Label/Label.js +6 -6
- package/dist/cjs/f/common/index.js +19 -1
- package/dist/cjs/f/common/utils/index.js +12 -0
- package/dist/cjs/f/common/utils/lookUpInputValueFromFetchedOptions.js +29 -0
- package/dist/cjs/f/fields/Checkbox/Checkbox.js +6 -6
- package/dist/cjs/f/fields/ChoicesInput/ChoicesInput.js +6 -6
- package/dist/cjs/f/fields/ChoicesInput/common/Choice/Choice.js +3 -4
- package/dist/cjs/f/fields/EditorInput/EditorInput.js +6 -6
- package/dist/cjs/f/fields/EditorInput/common/Toolbar.js +17 -17
- package/dist/cjs/f/fields/EditorInput/common/TreeViewPlugin.js +1 -2
- package/dist/cjs/f/fields/LinkInput/LinkInput.js +6 -6
- package/dist/cjs/f/fields/QueryChoices/QueryChoices.js +8 -8
- package/dist/cjs/f/fields/QueryCombobox/QueryCombobox.js +23 -12
- package/dist/cjs/f/fields/QueryCombobox/common/Combobox/Combobox.js +29 -11
- package/dist/cjs/f/fields/QueryCombobox/common/Menu/Menu.js +3 -4
- package/dist/cjs/f/fields/QueryCombobox/common/MultipleCombobox/MultipleCombobox.js +30 -12
- package/dist/cjs/f/fields/QuerySelect/QuerySelect.js +8 -8
- package/dist/cjs/f/fields/RatingsInput/RatingsInput.js +7 -7
- package/dist/cjs/f/fields/RatingsInput/common/Rating/Rating.js +3 -4
- package/dist/cjs/f/fields/SelectInput/SelectInput.js +6 -6
- package/dist/cjs/f/fields/TextInput/TextInput.js +6 -6
- package/dist/cjs/f/fields/TextareaInput/TextareaInput.js +6 -6
- package/dist/cjs/r/SwitchRouteMap/SwitchRouteMap.js +3 -4
- package/dist/cjs/r/common/PrivateRoute/PrivateRoute.js +6 -6
- package/dist/cjs/test/QueryLoader/QueryLoader.js +7 -7
- package/dist/cjs/test/QueryLoader/common/PreloadedTestData/PreloadedTestData.js +3 -4
- package/dist/cjs/utils/hooks/useDynamicPosition.js +1 -2
- package/dist/cjs/utils/hooks/useWindowSize.js +1 -2
- package/dist/es/a/SnapScroller/SnapScroller.js +33 -7
- package/dist/es/f/common/index.js +2 -1
- package/dist/es/f/common/utils/index.js +1 -0
- package/dist/es/f/common/utils/lookUpInputValueFromFetchedOptions.js +20 -0
- package/dist/es/f/fields/QueryCombobox/QueryCombobox.js +15 -4
- package/dist/es/f/fields/QueryCombobox/common/Combobox/Combobox.js +22 -4
- package/dist/es/f/fields/QueryCombobox/common/MultipleCombobox/MultipleCombobox.js +22 -4
- package/package.json +4 -3
- package/src/stories/f/QueryCombobox.stories.jsx +18 -0
- package/src/ui/a/SnapScroller/SnapScroller.jsx +27 -3
- package/src/ui/f/common/index.js +1 -0
- package/src/ui/f/common/utils/index.js +1 -0
- package/src/ui/f/common/utils/lookUpInputValueFromFetchedOptions.js +23 -0
- package/src/ui/f/fields/QueryCombobox/QueryCombobox.jsx +18 -6
- package/src/ui/f/fields/QueryCombobox/common/Combobox/Combobox.jsx +18 -2
- package/src/ui/f/fields/QueryCombobox/common/MultipleCombobox/MultipleCombobox.jsx +18 -1
- package/tests/__snapshots__/Storyshots.test.js.snap +281 -20
|
@@ -35,7 +35,9 @@ const QueryCombobox = ({
|
|
|
35
35
|
labelSpan,
|
|
36
36
|
desktopLabelSpan,
|
|
37
37
|
inputSpan,
|
|
38
|
-
desktopInputSpan
|
|
38
|
+
desktopInputSpan,
|
|
39
|
+
placeholder,
|
|
40
|
+
promptCreateNewOption
|
|
39
41
|
// ...otherProps
|
|
40
42
|
}) => {
|
|
41
43
|
useInsertionEffect(() => {
|
|
@@ -96,6 +98,7 @@ const QueryCombobox = ({
|
|
|
96
98
|
style,
|
|
97
99
|
options,
|
|
98
100
|
getOptions,
|
|
101
|
+
setOptions,
|
|
99
102
|
debounceMs,
|
|
100
103
|
disabled,
|
|
101
104
|
name,
|
|
@@ -113,7 +116,9 @@ const QueryCombobox = ({
|
|
|
113
116
|
labelSpan,
|
|
114
117
|
desktopLabelSpan,
|
|
115
118
|
inputSpan,
|
|
116
|
-
desktopInputSpan
|
|
119
|
+
desktopInputSpan,
|
|
120
|
+
placeholder,
|
|
121
|
+
promptCreateNewOption
|
|
117
122
|
};
|
|
118
123
|
const Input = multiple ? MultipleCombobox : Combobox;
|
|
119
124
|
return /*#__PURE__*/React.createElement(Input, comboboxProps);
|
|
@@ -217,7 +222,12 @@ QueryCombobox.propTypes = {
|
|
|
217
222
|
/**
|
|
218
223
|
* The number of columns the input should span on desktop
|
|
219
224
|
*/
|
|
220
|
-
desktopInputSpan: PropTypes.number
|
|
225
|
+
desktopInputSpan: PropTypes.number,
|
|
226
|
+
/**
|
|
227
|
+
* Whether to prompt the user to create a new option if the search input
|
|
228
|
+
* does not match any of the options
|
|
229
|
+
*/
|
|
230
|
+
promptCreateNewOption: PropTypes.bool
|
|
221
231
|
};
|
|
222
232
|
QueryCombobox.defaultProps = {
|
|
223
233
|
optionsKeyMap: {
|
|
@@ -229,6 +239,7 @@ QueryCombobox.defaultProps = {
|
|
|
229
239
|
searchVariable: 'search',
|
|
230
240
|
transformSearch: search => search,
|
|
231
241
|
minLength: 2,
|
|
232
|
-
disabled: false
|
|
242
|
+
disabled: false,
|
|
243
|
+
promptCreateNewOption: false
|
|
233
244
|
};
|
|
234
245
|
export default QueryCombobox;
|
|
@@ -8,7 +8,7 @@ import styleNames from '@pareto-engineering/bem/exports';
|
|
|
8
8
|
import { FormLabel, FormDescription } from "../../../..";
|
|
9
9
|
import { Popover, LoadingCircle } from "../../../../../a";
|
|
10
10
|
import { Button } from "../../../../../b";
|
|
11
|
-
import { InputWrapper } from "../../../../common";
|
|
11
|
+
import { InputWrapper, lookUpInputValueFromFetchedOptions } from "../../../../common";
|
|
12
12
|
|
|
13
13
|
// Local Definitions
|
|
14
14
|
|
|
@@ -28,6 +28,7 @@ const Combobox = ({
|
|
|
28
28
|
name,
|
|
29
29
|
options: items,
|
|
30
30
|
getOptions,
|
|
31
|
+
setOptions,
|
|
31
32
|
setValue,
|
|
32
33
|
description,
|
|
33
34
|
value,
|
|
@@ -40,7 +41,9 @@ const Combobox = ({
|
|
|
40
41
|
labelSpan,
|
|
41
42
|
desktopLabelSpan,
|
|
42
43
|
inputSpan,
|
|
43
|
-
desktopInputSpan
|
|
44
|
+
desktopInputSpan,
|
|
45
|
+
placeholder,
|
|
46
|
+
promptCreateNewOption
|
|
44
47
|
// ...otherProps
|
|
45
48
|
}) => {
|
|
46
49
|
const {
|
|
@@ -68,6 +71,16 @@ const Combobox = ({
|
|
|
68
71
|
}
|
|
69
72
|
}
|
|
70
73
|
});
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
if (promptCreateNewOption) {
|
|
76
|
+
lookUpInputValueFromFetchedOptions({
|
|
77
|
+
items,
|
|
78
|
+
inputValue,
|
|
79
|
+
setOptions,
|
|
80
|
+
minLength
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}, [inputValue, items, promptCreateNewOption]);
|
|
71
84
|
|
|
72
85
|
// If the user has selected an item, we'll set the value of the field
|
|
73
86
|
// or if the combobox state has a selected item, we'll set the value to the formik state
|
|
@@ -101,7 +114,8 @@ const Combobox = ({
|
|
|
101
114
|
desktopColumnSpan: desktopInputSpan
|
|
102
115
|
}), /*#__PURE__*/React.createElement("input", _extends({}, getInputProps(), {
|
|
103
116
|
className: "input",
|
|
104
|
-
disabled: disabled
|
|
117
|
+
disabled: disabled,
|
|
118
|
+
placeholder: placeholder
|
|
105
119
|
})), isFetching && /*#__PURE__*/React.createElement(LoadingCircle, {
|
|
106
120
|
className: "x-main"
|
|
107
121
|
}), inputValue.length > minLength && !isFetching && /*#__PURE__*/React.createElement(Button, {
|
|
@@ -212,7 +226,11 @@ Combobox.propTypes = {
|
|
|
212
226
|
/**
|
|
213
227
|
* Whether the input is optional or not
|
|
214
228
|
*/
|
|
215
|
-
optional: PropTypes.bool
|
|
229
|
+
optional: PropTypes.bool,
|
|
230
|
+
/**
|
|
231
|
+
* The placeholder text for the input
|
|
232
|
+
*/
|
|
233
|
+
placeholder: PropTypes.string
|
|
216
234
|
};
|
|
217
235
|
Combobox.defaultProps = {
|
|
218
236
|
// someProp: false
|
|
@@ -8,7 +8,7 @@ import { useCombobox, useMultipleSelection } from 'downshift';
|
|
|
8
8
|
import { Button } from "../../../../../b";
|
|
9
9
|
import { Popover, LoadingCircle } from "../../../../../a";
|
|
10
10
|
import { FormDescription, FormLabel } from "../../../..";
|
|
11
|
-
import { InputWrapper } from "../../../../common";
|
|
11
|
+
import { InputWrapper, lookUpInputValueFromFetchedOptions } from "../../../../common";
|
|
12
12
|
|
|
13
13
|
// Local Definitions
|
|
14
14
|
|
|
@@ -48,7 +48,10 @@ const MultipleCombobox = ({
|
|
|
48
48
|
labelSpan,
|
|
49
49
|
desktopLabelSpan,
|
|
50
50
|
inputSpan,
|
|
51
|
-
|
|
51
|
+
placeholder,
|
|
52
|
+
desktopInputSpan,
|
|
53
|
+
setOptions,
|
|
54
|
+
promptCreateNewOption
|
|
52
55
|
// ...otherProps
|
|
53
56
|
}) => {
|
|
54
57
|
const [searchInputValue, setSearchInputValue] = useState('');
|
|
@@ -136,6 +139,16 @@ const MultipleCombobox = ({
|
|
|
136
139
|
setValue(selectedItems);
|
|
137
140
|
}
|
|
138
141
|
}, [selectedItems]);
|
|
142
|
+
useEffect(() => {
|
|
143
|
+
if (promptCreateNewOption) {
|
|
144
|
+
lookUpInputValueFromFetchedOptions({
|
|
145
|
+
items,
|
|
146
|
+
inputValue,
|
|
147
|
+
setOptions,
|
|
148
|
+
minLength
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}, [inputValue, items, promptCreateNewOption]);
|
|
139
152
|
useEffect(() => {
|
|
140
153
|
if (value?.length > 0 && (testIfArraysAreUnique(value, selectedItems) || testIfArraysAreUnique(selectedItems, value))) {
|
|
141
154
|
setSelectedItems(value);
|
|
@@ -180,7 +193,8 @@ const MultipleCombobox = ({
|
|
|
180
193
|
preventKeyAction: isOpen
|
|
181
194
|
})), {
|
|
182
195
|
className: "input",
|
|
183
|
-
disabled: disabled
|
|
196
|
+
disabled: disabled,
|
|
197
|
+
placeholder: placeholder
|
|
184
198
|
})), isFetching && /*#__PURE__*/React.createElement(LoadingCircle, {
|
|
185
199
|
className: "x-main"
|
|
186
200
|
}), inputValue.length > minLength && !isFetching && /*#__PURE__*/React.createElement(Button, {
|
|
@@ -275,7 +289,11 @@ MultipleCombobox.propTypes = {
|
|
|
275
289
|
/**
|
|
276
290
|
* Whether the input is optional or not
|
|
277
291
|
*/
|
|
278
|
-
optional: PropTypes.bool
|
|
292
|
+
optional: PropTypes.bool,
|
|
293
|
+
/**
|
|
294
|
+
* The placeholder text for the input
|
|
295
|
+
*/
|
|
296
|
+
placeholder: PropTypes.string
|
|
279
297
|
};
|
|
280
298
|
MultipleCombobox.defaultProps = {
|
|
281
299
|
// someProp: false
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pareto-engineering/design-system",
|
|
3
|
-
"version": "4.0.0-alpha.
|
|
3
|
+
"version": "4.0.0-alpha.60",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/es/index.js",
|
|
@@ -51,13 +51,14 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@lexical/react": "^0.11.3",
|
|
54
|
-
"@pareto-engineering/assets": "^4.0.0-alpha.
|
|
54
|
+
"@pareto-engineering/assets": "^4.0.0-alpha.59",
|
|
55
55
|
"@pareto-engineering/bem": "^4.0.0-alpha.20",
|
|
56
56
|
"@pareto-engineering/styles": "^4.0.0-alpha.57",
|
|
57
57
|
"@pareto-engineering/utils": "^4.0.0-alpha.46",
|
|
58
58
|
"date-fns": "^2.29.3",
|
|
59
59
|
"downshift": "^6.1.12",
|
|
60
60
|
"formik": "^2.2.9",
|
|
61
|
+
"fuse.js": "^7.0.0",
|
|
61
62
|
"hamburgers": "^1.2.1",
|
|
62
63
|
"lexical": "^0.11.3",
|
|
63
64
|
"lodash": "^4.17.21",
|
|
@@ -70,5 +71,5 @@
|
|
|
70
71
|
"relay-test-utils": "^15.0.0"
|
|
71
72
|
},
|
|
72
73
|
"browserslist": "> 2%",
|
|
73
|
-
"gitHead": "
|
|
74
|
+
"gitHead": "15846b86650f5b59e0da2d6b904e381fe3f95fdf"
|
|
74
75
|
}
|
|
@@ -180,6 +180,17 @@ Optional.args = {
|
|
|
180
180
|
optional:true,
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
+
export const WithPlaceholder = ResolvedTemplate.bind({})
|
|
184
|
+
WithPlaceholder.args = {
|
|
185
|
+
placeholder:'Search for a team',
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export const WithPromptToCreateNewOption = ResolvedTemplate.bind({})
|
|
189
|
+
WithPromptToCreateNewOption.args = {
|
|
190
|
+
placeholder :'Search for a team',
|
|
191
|
+
promptCreateNewOption:true,
|
|
192
|
+
}
|
|
193
|
+
|
|
183
194
|
export const SingleSelect = ResolvedTemplate.bind({})
|
|
184
195
|
SingleSelect.args = {
|
|
185
196
|
multiple:false,
|
|
@@ -202,6 +213,13 @@ MultipleSelect.args = {
|
|
|
202
213
|
defaultFormikState:{ teams: [] },
|
|
203
214
|
}
|
|
204
215
|
|
|
216
|
+
export const MultipleSelectWithPromptForNewOptions = ResolvedTemplate.bind({})
|
|
217
|
+
MultipleSelectWithPromptForNewOptions.args = {
|
|
218
|
+
multiple :true,
|
|
219
|
+
promptCreateNewOption:true,
|
|
220
|
+
defaultFormikState :{ teams: [] },
|
|
221
|
+
}
|
|
222
|
+
|
|
205
223
|
export const MultipleSelectWithDefaultFormikState = ResolvedTemplate.bind({})
|
|
206
224
|
MultipleSelectWithDefaultFormikState.args = {
|
|
207
225
|
multiple :true,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* @pareto-engineering/generator-front 1.0.12 */
|
|
2
2
|
import * as React from 'react'
|
|
3
3
|
|
|
4
|
-
import { useInsertionEffect } from 'react'
|
|
4
|
+
import { useInsertionEffect, useState, useRef } from 'react'
|
|
5
5
|
|
|
6
6
|
import PropTypes from 'prop-types'
|
|
7
7
|
|
|
@@ -27,14 +27,34 @@ const SnapScroller = ({
|
|
|
27
27
|
useInsertionEffect(() => {
|
|
28
28
|
import('./styles.scss')
|
|
29
29
|
}, [])
|
|
30
|
+
const [isDragging, setIsDragging] = useState(false)
|
|
31
|
+
const [startX, setStartX] = useState(0)
|
|
32
|
+
const [startScrollX, setStartScrollX] = useState(0)
|
|
33
|
+
const ref = useRef(null)
|
|
34
|
+
|
|
35
|
+
const onMouseDown = (e) => {
|
|
36
|
+
setIsDragging(true)
|
|
37
|
+
setStartX(e.clientX)
|
|
38
|
+
setStartScrollX(ref.current.scrollLeft)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const onMouseUp = () => {
|
|
42
|
+
setIsDragging(false)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const onMouseMove = (e) => {
|
|
46
|
+
if (isDragging) {
|
|
47
|
+
const deltaX = e.clientX - startX
|
|
48
|
+
ref.current.scrollLeft = startScrollX - deltaX
|
|
49
|
+
}
|
|
50
|
+
}
|
|
30
51
|
|
|
31
52
|
return (
|
|
53
|
+
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
32
54
|
<div
|
|
33
55
|
id={id}
|
|
34
56
|
className={[
|
|
35
|
-
|
|
36
57
|
baseClassName,
|
|
37
|
-
|
|
38
58
|
componentClassName,
|
|
39
59
|
userClassName,
|
|
40
60
|
noScrollOnDesktop && 'desktop-no-scroll',
|
|
@@ -42,6 +62,10 @@ const SnapScroller = ({
|
|
|
42
62
|
.filter((e) => e)
|
|
43
63
|
.join(' ')}
|
|
44
64
|
style={style}
|
|
65
|
+
ref={ref}
|
|
66
|
+
onMouseDown={noScrollOnDesktop ? null : onMouseDown}
|
|
67
|
+
onMouseUp={noScrollOnDesktop ? null : onMouseUp}
|
|
68
|
+
onMouseMove={noScrollOnDesktop ? null : onMouseMove}
|
|
45
69
|
// {...otherProps}
|
|
46
70
|
>
|
|
47
71
|
{children}
|
package/src/ui/f/common/index.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { lookUpInputValueFromFetchedOptions } from './lookUpInputValueFromFetchedOptions'
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import Fuse from 'fuse.js'
|
|
2
|
+
|
|
3
|
+
const fuseOptions = {
|
|
4
|
+
findAllMatches:true,
|
|
5
|
+
keys :['label'],
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const lookUpInputValueFromFetchedOptions = ({
|
|
9
|
+
items, inputValue, setOptions, minLength,
|
|
10
|
+
}) => {
|
|
11
|
+
const fuseSearch = new Fuse(items, fuseOptions)
|
|
12
|
+
const result = fuseSearch.search(inputValue)
|
|
13
|
+
|
|
14
|
+
if (result.length === 0 && inputValue.length > minLength) {
|
|
15
|
+
setOptions((prevItems) => [
|
|
16
|
+
...prevItems,
|
|
17
|
+
{
|
|
18
|
+
label:`${inputValue} (Create new)`,
|
|
19
|
+
value:inputValue,
|
|
20
|
+
},
|
|
21
|
+
])
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -40,6 +40,8 @@ const QueryCombobox = ({
|
|
|
40
40
|
desktopLabelSpan,
|
|
41
41
|
inputSpan,
|
|
42
42
|
desktopInputSpan,
|
|
43
|
+
placeholder,
|
|
44
|
+
promptCreateNewOption,
|
|
43
45
|
// ...otherProps
|
|
44
46
|
}) => {
|
|
45
47
|
useInsertionEffect(() => {
|
|
@@ -102,6 +104,7 @@ const QueryCombobox = ({
|
|
|
102
104
|
style,
|
|
103
105
|
options,
|
|
104
106
|
getOptions,
|
|
107
|
+
setOptions,
|
|
105
108
|
debounceMs,
|
|
106
109
|
disabled,
|
|
107
110
|
name,
|
|
@@ -120,6 +123,8 @@ const QueryCombobox = ({
|
|
|
120
123
|
desktopLabelSpan,
|
|
121
124
|
inputSpan,
|
|
122
125
|
desktopInputSpan,
|
|
126
|
+
placeholder,
|
|
127
|
+
promptCreateNewOption,
|
|
123
128
|
}
|
|
124
129
|
|
|
125
130
|
const Input = multiple ? MultipleCombobox : Combobox
|
|
@@ -252,6 +257,12 @@ QueryCombobox.propTypes = {
|
|
|
252
257
|
* The number of columns the input should span on desktop
|
|
253
258
|
*/
|
|
254
259
|
desktopInputSpan:PropTypes.number,
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Whether to prompt the user to create a new option if the search input
|
|
263
|
+
* does not match any of the options
|
|
264
|
+
*/
|
|
265
|
+
promptCreateNewOption:PropTypes.bool,
|
|
255
266
|
}
|
|
256
267
|
|
|
257
268
|
QueryCombobox.defaultProps = {
|
|
@@ -259,12 +270,13 @@ QueryCombobox.defaultProps = {
|
|
|
259
270
|
value :'id',
|
|
260
271
|
getLabel:(node) => node.name,
|
|
261
272
|
},
|
|
262
|
-
multiple
|
|
263
|
-
color
|
|
264
|
-
searchVariable
|
|
265
|
-
transformSearch:(search) => search,
|
|
266
|
-
minLength
|
|
267
|
-
disabled
|
|
273
|
+
multiple :false,
|
|
274
|
+
color :'interactive',
|
|
275
|
+
searchVariable :'search',
|
|
276
|
+
transformSearch :(search) => search,
|
|
277
|
+
minLength :2,
|
|
278
|
+
disabled :false,
|
|
279
|
+
promptCreateNewOption:false,
|
|
268
280
|
}
|
|
269
281
|
|
|
270
282
|
export default QueryCombobox
|
|
@@ -15,7 +15,7 @@ import { Popover, LoadingCircle } from 'ui/a'
|
|
|
15
15
|
|
|
16
16
|
import { Button } from 'ui/b'
|
|
17
17
|
|
|
18
|
-
import { InputWrapper } from '../../../../common'
|
|
18
|
+
import { InputWrapper, lookUpInputValueFromFetchedOptions } from '../../../../common'
|
|
19
19
|
|
|
20
20
|
// Local Definitions
|
|
21
21
|
|
|
@@ -37,6 +37,7 @@ const Combobox = ({
|
|
|
37
37
|
name,
|
|
38
38
|
options:items,
|
|
39
39
|
getOptions,
|
|
40
|
+
setOptions,
|
|
40
41
|
setValue,
|
|
41
42
|
description,
|
|
42
43
|
value,
|
|
@@ -50,6 +51,8 @@ const Combobox = ({
|
|
|
50
51
|
desktopLabelSpan,
|
|
51
52
|
inputSpan,
|
|
52
53
|
desktopInputSpan,
|
|
54
|
+
placeholder,
|
|
55
|
+
promptCreateNewOption,
|
|
53
56
|
// ...otherProps
|
|
54
57
|
}) => {
|
|
55
58
|
const {
|
|
@@ -76,6 +79,14 @@ const Combobox = ({
|
|
|
76
79
|
},
|
|
77
80
|
})
|
|
78
81
|
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
if (promptCreateNewOption) {
|
|
84
|
+
lookUpInputValueFromFetchedOptions({
|
|
85
|
+
items, inputValue, setOptions, minLength,
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
}, [inputValue, items, promptCreateNewOption])
|
|
89
|
+
|
|
79
90
|
// If the user has selected an item, we'll set the value of the field
|
|
80
91
|
// or if the combobox state has a selected item, we'll set the value to the formik state
|
|
81
92
|
useEffect(() => {
|
|
@@ -124,7 +135,7 @@ const Combobox = ({
|
|
|
124
135
|
columnSpan={inputSpan}
|
|
125
136
|
desktopColumnSpan={desktopInputSpan}
|
|
126
137
|
>
|
|
127
|
-
<input {...getInputProps()} className="input" disabled={disabled} />
|
|
138
|
+
<input {...getInputProps()} className="input" disabled={disabled} placeholder={placeholder} />
|
|
128
139
|
{isFetching && (
|
|
129
140
|
<LoadingCircle className="x-main" />
|
|
130
141
|
)}
|
|
@@ -262,6 +273,11 @@ Combobox.propTypes = {
|
|
|
262
273
|
* Whether the input is optional or not
|
|
263
274
|
*/
|
|
264
275
|
optional:PropTypes.bool,
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* The placeholder text for the input
|
|
279
|
+
*/
|
|
280
|
+
placeholder:PropTypes.string,
|
|
265
281
|
}
|
|
266
282
|
|
|
267
283
|
Combobox.defaultProps = {
|
|
@@ -15,7 +15,7 @@ import { Popover, LoadingCircle } from 'ui/a'
|
|
|
15
15
|
|
|
16
16
|
import { FormDescription, FormLabel } from 'ui/f'
|
|
17
17
|
|
|
18
|
-
import { InputWrapper } from '../../../../common'
|
|
18
|
+
import { InputWrapper, lookUpInputValueFromFetchedOptions } from '../../../../common'
|
|
19
19
|
|
|
20
20
|
// Local Definitions
|
|
21
21
|
|
|
@@ -60,7 +60,10 @@ const MultipleCombobox = ({
|
|
|
60
60
|
labelSpan,
|
|
61
61
|
desktopLabelSpan,
|
|
62
62
|
inputSpan,
|
|
63
|
+
placeholder,
|
|
63
64
|
desktopInputSpan,
|
|
65
|
+
setOptions,
|
|
66
|
+
promptCreateNewOption,
|
|
64
67
|
// ...otherProps
|
|
65
68
|
}) => {
|
|
66
69
|
const [searchInputValue, setSearchInputValue] = useState('')
|
|
@@ -143,6 +146,14 @@ const MultipleCombobox = ({
|
|
|
143
146
|
}
|
|
144
147
|
}, [selectedItems])
|
|
145
148
|
|
|
149
|
+
useEffect(() => {
|
|
150
|
+
if (promptCreateNewOption) {
|
|
151
|
+
lookUpInputValueFromFetchedOptions({
|
|
152
|
+
items, inputValue, setOptions, minLength,
|
|
153
|
+
})
|
|
154
|
+
}
|
|
155
|
+
}, [inputValue, items, promptCreateNewOption])
|
|
156
|
+
|
|
146
157
|
useEffect(() => {
|
|
147
158
|
if (value?.length > 0 && (
|
|
148
159
|
testIfArraysAreUnique(value, selectedItems)
|
|
@@ -220,6 +231,7 @@ const MultipleCombobox = ({
|
|
|
220
231
|
)}
|
|
221
232
|
className="input"
|
|
222
233
|
disabled={disabled}
|
|
234
|
+
placeholder={placeholder}
|
|
223
235
|
/>
|
|
224
236
|
{isFetching && (
|
|
225
237
|
<LoadingCircle className="x-main" />
|
|
@@ -346,6 +358,11 @@ MultipleCombobox.propTypes = {
|
|
|
346
358
|
* Whether the input is optional or not
|
|
347
359
|
*/
|
|
348
360
|
optional:PropTypes.bool,
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* The placeholder text for the input
|
|
364
|
+
*/
|
|
365
|
+
placeholder:PropTypes.string,
|
|
349
366
|
}
|
|
350
367
|
|
|
351
368
|
MultipleCombobox.defaultProps = {
|