@eccenca/gui-elements 23.2.0-rc.0 → 23.2.0-rc.1
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/CHANGELOG.md +28 -3
- package/dist/cjs/components/AutoSuggestion/AutoSuggestion.js +24 -20
- package/dist/cjs/components/AutoSuggestion/AutoSuggestion.js.map +1 -1
- package/dist/cjs/components/AutocompleteField/AutoCompleteField.js +59 -50
- package/dist/cjs/components/AutocompleteField/AutoCompleteField.js.map +1 -1
- package/dist/cjs/components/AutocompleteField/autoCompleteFieldUtils.js +3 -3
- package/dist/cjs/components/AutocompleteField/autoCompleteFieldUtils.js.map +1 -1
- package/dist/cjs/components/Breadcrumb/BreadcrumbItem.js +9 -6
- package/dist/cjs/components/Breadcrumb/BreadcrumbItem.js.map +1 -1
- package/dist/cjs/components/CodeAutocompleteField/CodeAutocompleteField.js +33 -0
- package/dist/cjs/components/CodeAutocompleteField/CodeAutocompleteField.js.map +1 -0
- package/dist/cjs/components/CodeAutocompleteField/index.js +14 -0
- package/dist/cjs/components/CodeAutocompleteField/index.js.map +1 -0
- package/dist/cjs/components/Depiction/Depiction.js +13 -13
- package/dist/cjs/components/Depiction/Depiction.js.map +1 -1
- package/dist/cjs/components/Icon/IconButton.js +9 -3
- package/dist/cjs/components/Icon/IconButton.js.map +1 -1
- package/dist/cjs/components/Icon/canonicalIconNames.js +2 -0
- package/dist/cjs/components/Icon/canonicalIconNames.js.map +1 -1
- package/dist/cjs/components/MultiSelect/MultiSelect.js +45 -17
- package/dist/cjs/components/MultiSelect/MultiSelect.js.map +1 -1
- package/dist/cjs/components/MultiSuggestField/MultiSuggestField.js +33 -0
- package/dist/cjs/components/MultiSuggestField/MultiSuggestField.js.map +1 -0
- package/dist/cjs/components/OverviewItem/OverviewItem.js +8 -10
- package/dist/cjs/components/OverviewItem/OverviewItem.js.map +1 -1
- package/dist/cjs/components/PropertyValuePair/PropertyName.js +4 -3
- package/dist/cjs/components/PropertyValuePair/PropertyName.js.map +1 -1
- package/dist/cjs/components/Select/Select.js +17 -3
- package/dist/cjs/components/Select/Select.js.map +1 -1
- package/dist/cjs/components/SuggestField/SuggestField.js +39 -0
- package/dist/cjs/components/SuggestField/SuggestField.js.map +1 -0
- package/dist/cjs/components/SuggestField/index.js +19 -0
- package/dist/cjs/components/SuggestField/index.js.map +1 -0
- package/dist/cjs/components/index.js +3 -0
- package/dist/cjs/components/index.js.map +1 -1
- package/dist/cjs/extensions/react-flow/nodes/NodeContent.js +54 -41
- package/dist/cjs/extensions/react-flow/nodes/NodeContent.js.map +1 -1
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/components/AutoSuggestion/AutoSuggestion.js +23 -18
- package/dist/esm/components/AutoSuggestion/AutoSuggestion.js.map +1 -1
- package/dist/esm/components/AutocompleteField/AutoCompleteField.js +68 -59
- package/dist/esm/components/AutocompleteField/AutoCompleteField.js.map +1 -1
- package/dist/esm/components/AutocompleteField/autoCompleteFieldUtils.js +3 -3
- package/dist/esm/components/AutocompleteField/autoCompleteFieldUtils.js.map +1 -1
- package/dist/esm/components/Breadcrumb/BreadcrumbItem.js +9 -6
- package/dist/esm/components/Breadcrumb/BreadcrumbItem.js.map +1 -1
- package/dist/esm/components/CodeAutocompleteField/CodeAutocompleteField.js +37 -0
- package/dist/esm/components/CodeAutocompleteField/CodeAutocompleteField.js.map +1 -0
- package/dist/esm/components/CodeAutocompleteField/index.js +2 -0
- package/dist/esm/components/CodeAutocompleteField/index.js.map +1 -0
- package/dist/esm/components/Depiction/Depiction.js +12 -12
- package/dist/esm/components/Depiction/Depiction.js.map +1 -1
- package/dist/esm/components/Icon/IconButton.js +10 -4
- package/dist/esm/components/Icon/IconButton.js.map +1 -1
- package/dist/esm/components/Icon/canonicalIconNames.js +2 -0
- package/dist/esm/components/Icon/canonicalIconNames.js.map +1 -1
- package/dist/esm/components/MultiSelect/MultiSelect.js +52 -22
- package/dist/esm/components/MultiSelect/MultiSelect.js.map +1 -1
- package/dist/esm/components/MultiSuggestField/MultiSuggestField.js +37 -0
- package/dist/esm/components/MultiSuggestField/MultiSuggestField.js.map +1 -0
- package/dist/esm/components/OverviewItem/OverviewItem.js +8 -10
- package/dist/esm/components/OverviewItem/OverviewItem.js.map +1 -1
- package/dist/esm/components/PropertyValuePair/PropertyName.js +4 -3
- package/dist/esm/components/PropertyValuePair/PropertyName.js.map +1 -1
- package/dist/esm/components/Select/Select.js +18 -4
- package/dist/esm/components/Select/Select.js.map +1 -1
- package/dist/esm/components/SuggestField/SuggestField.js +43 -0
- package/dist/esm/components/SuggestField/SuggestField.js.map +1 -0
- package/dist/esm/components/SuggestField/index.js +6 -0
- package/dist/esm/components/SuggestField/index.js.map +1 -0
- package/dist/esm/components/index.js +3 -0
- package/dist/esm/components/index.js.map +1 -1
- package/dist/esm/extensions/react-flow/nodes/NodeContent.js +51 -39
- package/dist/esm/extensions/react-flow/nodes/NodeContent.js.map +1 -1
- package/dist/esm/index.js +2 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/types/components/AutoSuggestion/AutoSuggestion.d.ts +35 -4
- package/dist/types/components/AutocompleteField/AutoCompleteField.d.ts +23 -6
- package/dist/types/components/AutocompleteField/autoCompleteFieldUtils.d.ts +3 -3
- package/dist/types/components/AutocompleteField/index.d.ts +1 -1
- package/dist/types/components/AutocompleteField/interfaces.d.ts +1 -1
- package/dist/types/components/CodeAutocompleteField/CodeAutocompleteField.d.ts +10 -0
- package/dist/types/components/CodeAutocompleteField/index.d.ts +1 -0
- package/dist/types/components/Icon/IconButton.d.ts +2 -2
- package/dist/types/components/Icon/canonicalIconNames.d.ts +1 -1
- package/dist/types/components/MultiSelect/MultiSelect.d.ts +20 -2
- package/dist/types/components/MultiSuggestField/MultiSuggestField.d.ts +10 -0
- package/dist/types/components/PropertyValuePair/PropertyName.d.ts +5 -1
- package/dist/types/components/Select/Select.d.ts +28 -9
- package/dist/types/components/SuggestField/SuggestField.d.ts +16 -0
- package/dist/types/components/SuggestField/index.d.ts +5 -0
- package/dist/types/components/index.d.ts +3 -0
- package/dist/types/extensions/react-flow/nodes/NodeContent.d.ts +7 -7
- package/dist/types/index.d.ts +2 -1
- package/package.json +1 -1
- package/src/components/AutoSuggestion/AutoSuggestion.stories.tsx +14 -0
- package/src/components/AutoSuggestion/AutoSuggestion.tsx +280 -221
- package/src/components/AutocompleteField/AutoCompleteField.stories.tsx +14 -0
- package/src/components/AutocompleteField/AutoCompleteField.tsx +157 -121
- package/src/components/AutocompleteField/autoCompleteFieldUtils.tsx +10 -16
- package/src/components/AutocompleteField/interfaces.ts +5 -6
- package/src/components/Breadcrumb/BreadcrumbItem.tsx +19 -18
- package/src/components/Breadcrumb/breadcrumb.scss +18 -16
- package/src/components/Breadcrumb/stories/BreadcrumbList.stories.tsx +18 -15
- package/src/components/CodeAutocompleteField/CodeAutocompleteField.stories.tsx +89 -0
- package/src/components/CodeAutocompleteField/CodeAutocompleteField.tsx +22 -0
- package/src/components/CodeAutocompleteField/index.ts +1 -0
- package/src/components/ContextOverlay/contextoverlay.scss +10 -2
- package/src/components/Depiction/Depiction.tsx +57 -55
- package/src/components/Icon/IconButton.tsx +25 -11
- package/src/components/Icon/canonicalIconNames.tsx +4 -0
- package/src/components/MultiSelect/MultiSelect.stories.tsx +9 -47
- package/src/components/MultiSelect/MultiSelect.tsx +110 -66
- package/src/components/MultiSuggestField/MultiSuggestField.stories.tsx +58 -0
- package/src/components/MultiSuggestField/MultiSuggestField.tsx +22 -0
- package/src/components/Notification/notification.scss +20 -17
- package/src/components/OverviewItem/OverviewItem.tsx +11 -20
- package/src/components/PropertyValuePair/PropertyName.tsx +17 -4
- package/src/components/PropertyValuePair/propertyvalue.scss +17 -1
- package/src/components/Select/Select.stories.tsx +49 -20
- package/src/components/Select/Select.tsx +93 -18
- package/src/components/Select/_select.scss +13 -1
- package/src/components/SuggestField/SuggestField.stories.tsx +99 -0
- package/src/components/SuggestField/SuggestField.tsx +28 -0
- package/src/components/SuggestField/index.ts +5 -0
- package/src/components/TagInput/taginput.scss +14 -0
- package/src/components/index.scss +1 -1
- package/src/components/index.ts +3 -0
- package/src/extensions/react-flow/nodes/NodeContent.tsx +105 -87
- package/src/index.ts +2 -5
- package/src/components/AutoSuggestion/stories/AutoSuggestion.stories.tsx +0 -83
- package/src/components/AutocompleteField/stories/AutoCompleteField.stories.tsx +0 -86
|
@@ -1,23 +1,15 @@
|
|
|
1
|
-
import React, {useRef} from "react";
|
|
2
|
-
import {
|
|
3
|
-
Intent as BlueprintIntent,
|
|
4
|
-
HTMLInputProps as BlueprintHTMLInputProps
|
|
5
|
-
} from "@blueprintjs/core";
|
|
1
|
+
import React, { useRef } from "react";
|
|
2
|
+
import { HTMLInputProps as BlueprintHTMLInputProps, Intent as BlueprintIntent } from "@blueprintjs/core";
|
|
6
3
|
import {
|
|
7
4
|
ItemRendererProps as BlueprintItemRendererProps,
|
|
8
5
|
MultiSelect2 as BlueprintMultiSelect,
|
|
9
|
-
MultiSelect2Props as BlueprintMultiSelectProps
|
|
6
|
+
MultiSelect2Props as BlueprintMultiSelectProps,
|
|
10
7
|
} from "@blueprintjs/select";
|
|
11
|
-
import {
|
|
12
|
-
MenuItem,
|
|
13
|
-
Highlighter,
|
|
14
|
-
Button,
|
|
15
|
-
OverflowText,
|
|
16
|
-
ContextOverlayProps,
|
|
17
|
-
Spinner,
|
|
18
|
-
} from "./../../index";
|
|
19
8
|
|
|
20
|
-
import {removeExtraSpaces} from "../../common/utils/stringUtils";
|
|
9
|
+
import { removeExtraSpaces } from "../../common/utils/stringUtils";
|
|
10
|
+
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
|
|
11
|
+
|
|
12
|
+
import { ContextOverlayProps, Highlighter, IconButton, MenuItem, OverflowText, Spinner } from "./../../index";
|
|
21
13
|
|
|
22
14
|
export interface MultiSelectSelectionProps<T> {
|
|
23
15
|
newlySelected: T;
|
|
@@ -28,7 +20,12 @@ export interface MultiSelectSelectionProps<T> {
|
|
|
28
20
|
// @deprecated use `MultiSelectSelectionProps<T>`
|
|
29
21
|
export type SelectedParamsType<T> = MultiSelectSelectionProps<T>;
|
|
30
22
|
|
|
31
|
-
export interface MultiSelectProps<T>
|
|
23
|
+
export interface MultiSelectProps<T>
|
|
24
|
+
extends Pick<BlueprintMultiSelectProps<T>, "items" | "placeholder" | "openOnKeyDown"> {
|
|
25
|
+
/**
|
|
26
|
+
* Additional class name, space separated.
|
|
27
|
+
*/
|
|
28
|
+
className?: string;
|
|
32
29
|
/**
|
|
33
30
|
* Returns the unique ID of an item. This will be used for equality of items.
|
|
34
31
|
*/
|
|
@@ -80,11 +77,11 @@ export interface MultiSelectProps<T> extends Pick<BlueprintMultiSelectProps<T>,
|
|
|
80
77
|
/**
|
|
81
78
|
* Allows to creates new item from a given query. If this is not provided then no new items can be created.
|
|
82
79
|
*/
|
|
83
|
-
createNewItemFromQuery?: (query: string) => T
|
|
80
|
+
createNewItemFromQuery?: (query: string) => T;
|
|
84
81
|
/**
|
|
85
82
|
* Items that were newly created and not taken from the list will be post-fixed with this string.
|
|
86
83
|
*/
|
|
87
|
-
newItemPostfix?: string
|
|
84
|
+
newItemPostfix?: string;
|
|
88
85
|
/**
|
|
89
86
|
* The input element is displayed with primary color scheme.
|
|
90
87
|
*/
|
|
@@ -106,10 +103,25 @@ export interface MultiSelectProps<T> extends Pick<BlueprintMultiSelectProps<T>,
|
|
|
106
103
|
*/
|
|
107
104
|
disabled?: boolean;
|
|
108
105
|
|
|
109
|
-
/**
|
|
110
|
-
|
|
106
|
+
/**
|
|
107
|
+
* Delay in ms how long the request for the given query should be delayed.
|
|
108
|
+
*/
|
|
109
|
+
requestDelay?: number;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Clear query when an option is selected or unselected.
|
|
113
|
+
* The query is empty then and the user need to enter a new query.
|
|
114
|
+
*/
|
|
115
|
+
clearQueryOnSelection?: boolean;
|
|
111
116
|
}
|
|
112
117
|
|
|
118
|
+
/**
|
|
119
|
+
* **Element is deprecated for the current type of usage.**
|
|
120
|
+
* Use `MultiSuggestField` as replacement.
|
|
121
|
+
*
|
|
122
|
+
* This component will be re-implemented later as a `Select` allowing multiple selections.
|
|
123
|
+
* @deprecated
|
|
124
|
+
*/
|
|
113
125
|
export function MultiSelect<T>({
|
|
114
126
|
items,
|
|
115
127
|
prePopulateWithItems,
|
|
@@ -131,6 +143,8 @@ export function MultiSelect<T>({
|
|
|
131
143
|
disabled,
|
|
132
144
|
createNewItemFromQuery,
|
|
133
145
|
requestDelay = 0,
|
|
146
|
+
clearQueryOnSelection = false,
|
|
147
|
+
className,
|
|
134
148
|
...otherProps
|
|
135
149
|
}: MultiSelectProps<T>) {
|
|
136
150
|
const [createdItems, setCreatedItems] = React.useState<T[]>([]);
|
|
@@ -140,12 +154,12 @@ export function MultiSelect<T>({
|
|
|
140
154
|
const [selectedItems, setSelectedItems] = React.useState<T[]>(() => (prePopulateWithItems ? [...items] : []));
|
|
141
155
|
//currently focused element in popover list
|
|
142
156
|
const [focusedItem, setFocusedItem] = React.useState<T | null>(null);
|
|
143
|
-
const [showSpinner, setShowSpinner] = React.useState(false)
|
|
157
|
+
const [showSpinner, setShowSpinner] = React.useState(false);
|
|
144
158
|
const inputRef = React.useRef<HTMLInputElement>(null);
|
|
145
159
|
const requestState = useRef<{
|
|
146
|
-
query?: string
|
|
147
|
-
timeoutId?: number
|
|
148
|
-
}>({})
|
|
160
|
+
query?: string;
|
|
161
|
+
timeoutId?: number;
|
|
162
|
+
}>({});
|
|
149
163
|
|
|
150
164
|
let intent;
|
|
151
165
|
switch (true) {
|
|
@@ -171,7 +185,6 @@ export function MultiSelect<T>({
|
|
|
171
185
|
React.useEffect(() => {
|
|
172
186
|
setItemsCopy([...items, ...createdItems]);
|
|
173
187
|
setFilteredItemList([...items, ...createdItems]);
|
|
174
|
-
/* eslint-disable react-hooks/exhaustive-deps */
|
|
175
188
|
}, [items.map((item) => itemId(item)).join("|")]);
|
|
176
189
|
|
|
177
190
|
React.useEffect(() => {
|
|
@@ -181,7 +194,6 @@ export function MultiSelect<T>({
|
|
|
181
194
|
createdItems: createdSelectedItems,
|
|
182
195
|
selectedItems,
|
|
183
196
|
});
|
|
184
|
-
/* eslint-disable react-hooks/exhaustive-deps */
|
|
185
197
|
}, [
|
|
186
198
|
onSelection,
|
|
187
199
|
selectedItems.map((item) => itemId(item)).join("|"),
|
|
@@ -205,15 +217,12 @@ export function MultiSelect<T>({
|
|
|
205
217
|
setSelectedItems((items) => items.filter((item) => itemId(item) !== matcher));
|
|
206
218
|
};
|
|
207
219
|
|
|
208
|
-
|
|
209
|
-
|
|
210
220
|
/**
|
|
211
221
|
* selects and deselects an item from selection list
|
|
212
222
|
* if the item exists it removes it instead
|
|
213
223
|
* @param item
|
|
214
224
|
*/
|
|
215
225
|
const onItemSelect = (item: T) => {
|
|
216
|
-
|
|
217
226
|
if (itemHasBeenSelectedAlready(itemId(item))) {
|
|
218
227
|
removeItemSelection(itemId(item));
|
|
219
228
|
} else {
|
|
@@ -222,17 +231,24 @@ export function MultiSelect<T>({
|
|
|
222
231
|
|
|
223
232
|
//remove if already exist
|
|
224
233
|
if (createdSelectedItems.find((t) => itemLabel(t) === itemLabel(item))) {
|
|
225
|
-
|
|
226
|
-
|
|
234
|
+
setCreatedSelectedItems((prevItems) =>
|
|
235
|
+
prevItems.filter((prevItem) => itemLabel(prevItem) !== itemLabel(item))
|
|
236
|
+
);
|
|
237
|
+
} else {
|
|
227
238
|
const wasNewlyCreated = createdItems.find((t) => itemLabel(t) === itemLabel(item));
|
|
228
239
|
//only add to createdSelectedItems if it was previously created and not
|
|
229
240
|
// from the initial items or a possible query response
|
|
230
|
-
if(wasNewlyCreated){
|
|
231
|
-
|
|
241
|
+
if (wasNewlyCreated) {
|
|
242
|
+
setCreatedSelectedItems((prevItems) => [...prevItems, item]);
|
|
232
243
|
}
|
|
233
244
|
}
|
|
234
245
|
|
|
235
|
-
|
|
246
|
+
if (clearQueryOnSelection) {
|
|
247
|
+
requestState.current.query = "";
|
|
248
|
+
inputRef.current?.focus();
|
|
249
|
+
} else {
|
|
250
|
+
inputRef.current?.select();
|
|
251
|
+
}
|
|
236
252
|
};
|
|
237
253
|
|
|
238
254
|
/**
|
|
@@ -241,25 +257,25 @@ export function MultiSelect<T>({
|
|
|
241
257
|
*/
|
|
242
258
|
const onQueryChange = (query: string) => {
|
|
243
259
|
if (query.length && query !== requestState.current.query) {
|
|
244
|
-
requestState.current.query = query
|
|
245
|
-
if(requestState.current.timeoutId) {
|
|
246
|
-
clearTimeout(requestState.current.timeoutId)
|
|
260
|
+
requestState.current.query = query;
|
|
261
|
+
if (requestState.current.timeoutId) {
|
|
262
|
+
clearTimeout(requestState.current.timeoutId);
|
|
247
263
|
}
|
|
248
264
|
const fn = async () => {
|
|
249
|
-
setShowSpinner(true)
|
|
250
|
-
setFilteredItemList([])
|
|
265
|
+
setShowSpinner(true);
|
|
266
|
+
setFilteredItemList([]);
|
|
251
267
|
const resultFromQuery = runOnQueryChange && (await runOnQueryChange(removeExtraSpaces(query)));
|
|
252
268
|
if (requestState.current.query === query) {
|
|
253
269
|
// Only use most recent request
|
|
254
270
|
setFilteredItemList(() =>
|
|
255
|
-
[...(resultFromQuery ?? itemsCopy), ...createdItems].filter(item =>
|
|
271
|
+
[...(resultFromQuery ?? itemsCopy), ...createdItems].filter((item) =>
|
|
256
272
|
itemLabel(item).toLowerCase().includes(query.toLowerCase())
|
|
257
273
|
)
|
|
258
274
|
);
|
|
259
|
-
setShowSpinner(false)
|
|
275
|
+
setShowSpinner(false);
|
|
260
276
|
}
|
|
261
|
-
}
|
|
262
|
-
requestState.current.timeoutId = window.setTimeout(fn, requestDelay && requestDelay > 0 ? requestDelay : 0)
|
|
277
|
+
};
|
|
278
|
+
requestState.current.timeoutId = window.setTimeout(fn, requestDelay && requestDelay > 0 ? requestDelay : 0);
|
|
263
279
|
}
|
|
264
280
|
};
|
|
265
281
|
|
|
@@ -275,9 +291,9 @@ export function MultiSelect<T>({
|
|
|
275
291
|
if (!modifiers.matchesPredicate) {
|
|
276
292
|
return null;
|
|
277
293
|
}
|
|
278
|
-
let label = itemLabel(item)
|
|
279
|
-
if(createdItems.find(created => itemId(created) === itemId(item))) {
|
|
280
|
-
label += newItemPostfix
|
|
294
|
+
let label = itemLabel(item);
|
|
295
|
+
if (createdItems.find((created) => itemId(created) === itemId(item))) {
|
|
296
|
+
label += newItemPostfix;
|
|
281
297
|
}
|
|
282
298
|
return (
|
|
283
299
|
<MenuItem
|
|
@@ -295,6 +311,7 @@ export function MultiSelect<T>({
|
|
|
295
311
|
* clear all selected items in the multi-select input
|
|
296
312
|
*/
|
|
297
313
|
const handleClear = () => {
|
|
314
|
+
requestState.current.query = "";
|
|
298
315
|
setSelectedItems([]);
|
|
299
316
|
setFilteredItemList(itemsCopy);
|
|
300
317
|
};
|
|
@@ -306,18 +323,18 @@ export function MultiSelect<T>({
|
|
|
306
323
|
*/
|
|
307
324
|
const removeTagFromSelectionViaIndex = (label: React.ReactNode, index: number) => {
|
|
308
325
|
setSelectedItems([...selectedItems.slice(0, index), ...selectedItems.slice(index + 1)]);
|
|
309
|
-
setCreatedSelectedItems(items => items.filter(item => itemLabel(item) !== label));
|
|
326
|
+
setCreatedSelectedItems((items) => items.filter((item) => itemLabel(item) !== label));
|
|
310
327
|
};
|
|
311
328
|
|
|
312
329
|
/**
|
|
313
330
|
* Utility function to create a new Item. createNewItemFromQuery is assumed to be defined!
|
|
314
331
|
*/
|
|
315
332
|
const createNewItem = (query: string): T => {
|
|
316
|
-
const newItem = createNewItemFromQuery
|
|
333
|
+
const newItem = createNewItemFromQuery!(query);
|
|
317
334
|
//set new items
|
|
318
335
|
setCreatedItems((items) => [...items, newItem]);
|
|
319
|
-
setCreatedSelectedItems((items) => [...items, newItem])
|
|
320
|
-
requestState.current.query = ""
|
|
336
|
+
setCreatedSelectedItems((items) => [...items, newItem]);
|
|
337
|
+
requestState.current.query = "";
|
|
321
338
|
return newItem;
|
|
322
339
|
};
|
|
323
340
|
|
|
@@ -326,7 +343,12 @@ export function MultiSelect<T>({
|
|
|
326
343
|
* @param event
|
|
327
344
|
*/
|
|
328
345
|
const handleOnKeyUp = (event: React.KeyboardEvent<HTMLElement>) => {
|
|
329
|
-
if (
|
|
346
|
+
if (
|
|
347
|
+
event.key === "Enter" &&
|
|
348
|
+
!filteredItemList.length &&
|
|
349
|
+
!!requestState.current.query &&
|
|
350
|
+
createNewItemFromQuery
|
|
351
|
+
) {
|
|
330
352
|
createNewItem(requestState.current.query);
|
|
331
353
|
}
|
|
332
354
|
inputRef.current?.focus();
|
|
@@ -374,17 +396,19 @@ export function MultiSelect<T>({
|
|
|
374
396
|
// Clear button and spinner are both shown as "right element"
|
|
375
397
|
const clearButton =
|
|
376
398
|
selectedItems.length > 0 ? (
|
|
377
|
-
<
|
|
399
|
+
<IconButton
|
|
400
|
+
disabled={disabled}
|
|
401
|
+
name="operation-clear"
|
|
402
|
+
data-test-id="clear-all-items"
|
|
403
|
+
onClick={handleClear}
|
|
404
|
+
/>
|
|
378
405
|
) : undefined;
|
|
379
406
|
|
|
380
|
-
const spinnerProps = showSpinner
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
</>
|
|
386
|
-
)
|
|
387
|
-
} : {}
|
|
407
|
+
const spinnerProps = showSpinner
|
|
408
|
+
? {
|
|
409
|
+
rightElement: <Spinner position={"inline"} size={"tiny"} />,
|
|
410
|
+
}
|
|
411
|
+
: {};
|
|
388
412
|
|
|
389
413
|
return (
|
|
390
414
|
<BlueprintMultiSelect<T>
|
|
@@ -397,7 +421,7 @@ export function MultiSelect<T>({
|
|
|
397
421
|
itemsEqual={(a: T, b: T) => itemId(a) === itemId(b)}
|
|
398
422
|
selectedItems={selectedItems}
|
|
399
423
|
noResults={<MenuItem disabled={true} text={noResultText} />}
|
|
400
|
-
tagRenderer={item => itemLabel(item)}
|
|
424
|
+
tagRenderer={(item) => itemLabel(item)}
|
|
401
425
|
createNewItemRenderer={newItemRenderer}
|
|
402
426
|
onActiveItemChange={(activeItem) => setFocusedItem(activeItem)}
|
|
403
427
|
fill={fullWidth}
|
|
@@ -406,31 +430,51 @@ export function MultiSelect<T>({
|
|
|
406
430
|
inputProps: {
|
|
407
431
|
id: "item",
|
|
408
432
|
autoComplete: "off",
|
|
409
|
-
...inputProps
|
|
433
|
+
...inputProps,
|
|
410
434
|
},
|
|
435
|
+
className: `${eccgui}-multiselect` + (className ? ` ${className}` : ""),
|
|
436
|
+
fill: fullWidth,
|
|
411
437
|
inputRef: inputRef,
|
|
412
438
|
intent,
|
|
413
439
|
addOnBlur: true,
|
|
414
440
|
onKeyDown: handleOnKeyDown,
|
|
415
441
|
onKeyUp: handleOnKeyUp,
|
|
416
442
|
onRemove: removeTagFromSelectionViaIndex,
|
|
417
|
-
rightElement:
|
|
443
|
+
rightElement: (
|
|
444
|
+
<>
|
|
445
|
+
{clearButton ?? null}
|
|
446
|
+
{otherProps.openOnKeyDown !== true && (
|
|
447
|
+
<IconButton disabled={disabled} name={"toggler-caretdown"} />
|
|
448
|
+
)}
|
|
449
|
+
</>
|
|
450
|
+
),
|
|
418
451
|
tagProps: { minimal: true },
|
|
419
452
|
disabled,
|
|
420
453
|
...tagInputProps,
|
|
421
|
-
...spinnerProps
|
|
454
|
+
...spinnerProps,
|
|
455
|
+
}}
|
|
456
|
+
popoverTargetProps={{
|
|
457
|
+
className: `${eccgui}-multiselect__target`,
|
|
422
458
|
}}
|
|
423
|
-
|
|
424
459
|
popoverProps={{
|
|
425
460
|
minimal: true,
|
|
426
461
|
placement: "bottom-start",
|
|
427
|
-
|
|
462
|
+
matchTargetWidth: fullWidth,
|
|
428
463
|
...contextOverlayProps,
|
|
429
464
|
}}
|
|
430
465
|
/>
|
|
431
466
|
);
|
|
432
467
|
}
|
|
433
468
|
|
|
469
|
+
/** @deprecated */
|
|
470
|
+
/*
|
|
471
|
+
function ofType<U>() {
|
|
472
|
+
return (props: MultiSelectProps<U>) => <MultiSelect<U> {...props} />;
|
|
473
|
+
}
|
|
474
|
+
// */
|
|
475
|
+
|
|
476
|
+
// we still return the BLueprint element here because it was already used like that
|
|
477
|
+
// MultiSelect.ofType = ofType;
|
|
434
478
|
MultiSelect.ofType = BlueprintMultiSelect.ofType;
|
|
435
479
|
|
|
436
480
|
export default MultiSelect;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { loremIpsum } from "react-lorem-ipsum";
|
|
2
|
+
import { Meta, StoryFn } from "@storybook/react";
|
|
3
|
+
|
|
4
|
+
import { MultiSuggestField } from "./../../../index";
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
title: "Forms/MultiSuggestField",
|
|
8
|
+
component: MultiSuggestField,
|
|
9
|
+
argTypes: {
|
|
10
|
+
items: {
|
|
11
|
+
control: "none",
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
} as Meta<typeof MultiSuggestField>;
|
|
15
|
+
|
|
16
|
+
const Template: StoryFn<typeof MultiSuggestField> = (args) => (
|
|
17
|
+
<div>
|
|
18
|
+
<MultiSuggestField {...args} />
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
const testLabels = loremIpsum({
|
|
23
|
+
p: 1,
|
|
24
|
+
avgSentencesPerParagraph: 5,
|
|
25
|
+
avgWordsPerSentence: 1,
|
|
26
|
+
startWithLoremIpsum: false,
|
|
27
|
+
random: false,
|
|
28
|
+
})
|
|
29
|
+
.toString()
|
|
30
|
+
.split(".");
|
|
31
|
+
|
|
32
|
+
const items = new Array(5).fill(undefined).map((_, id) => {
|
|
33
|
+
const testLabel = testLabels[id];
|
|
34
|
+
return { testLabel, testId: `${testLabel}-id` };
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export const Default = Template.bind({});
|
|
38
|
+
Default.args = {
|
|
39
|
+
items,
|
|
40
|
+
canCreateNewItem: true,
|
|
41
|
+
prePopulateWithItems: false,
|
|
42
|
+
itemId: (item) => item.testId,
|
|
43
|
+
itemLabel: (item) => item.testLabel,
|
|
44
|
+
openOnKeyDown: true,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Display always the dropdown after the element was clicked on.
|
|
49
|
+
* Do not wait until the query input was startet.
|
|
50
|
+
*/
|
|
51
|
+
export const dropdownOnFocus = Template.bind({});
|
|
52
|
+
dropdownOnFocus.args = {
|
|
53
|
+
items,
|
|
54
|
+
canCreateNewItem: true,
|
|
55
|
+
prePopulateWithItems: false,
|
|
56
|
+
itemId: (item) => item.testId,
|
|
57
|
+
itemLabel: (item) => item.testLabel,
|
|
58
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
|
|
4
|
+
import { MultiSelect, MultiSelectProps } from "../MultiSelect/MultiSelect";
|
|
5
|
+
|
|
6
|
+
export type MultiSuggestFieldProps<T> = MultiSelectProps<T>;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Element behaves very similar to `SuggestField` but allows multiple selections.
|
|
10
|
+
* Its value does not represent a string but a stack of objects.
|
|
11
|
+
*
|
|
12
|
+
* Example usage: input field for user created tags.
|
|
13
|
+
*/
|
|
14
|
+
export function MultiSuggestField<T>({ className, ...otherProps }: MultiSuggestFieldProps<T>) {
|
|
15
|
+
// Currently this works only as an alias element for `MultiSelect`.
|
|
16
|
+
return (
|
|
17
|
+
<MultiSelect<T>
|
|
18
|
+
className={`${eccgui}-multisuggestfield` + (className ? ` ${className}` : "")}
|
|
19
|
+
{...otherProps}
|
|
20
|
+
/>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
// TODO: add vars and process them
|
|
2
2
|
|
|
3
3
|
@use "sass:math";
|
|
4
|
-
|
|
5
4
|
@import "~@blueprintjs/core/src/components/toast/toast";
|
|
6
5
|
|
|
7
6
|
.#{$eccgui}-notification {
|
|
8
|
-
border-style: solid;
|
|
9
|
-
border-width: 1px 1px 1px 0.25rem;
|
|
10
|
-
border-color: $eccgui-color-application-text;
|
|
11
|
-
color: $eccgui-color-application-text;
|
|
12
|
-
background-color: $eccgui-color-application-background;
|
|
13
|
-
font-size: 1rem;
|
|
14
|
-
line-height: $eccgui-size-typo-base-lineheight;
|
|
15
|
-
min-width: math.div(4, 16) * 100vw;
|
|
16
7
|
width: 100%;
|
|
8
|
+
min-width: math.div(4, 16) * 100vw;
|
|
17
9
|
max-width: 40rem;
|
|
18
10
|
margin-top: $eccgui-size-block-whitespace;
|
|
11
|
+
font-size: 1rem;
|
|
12
|
+
line-height: $eccgui-size-typo-base-lineheight;
|
|
13
|
+
color: $eccgui-color-application-text;
|
|
14
|
+
background-color: $eccgui-color-application-background;
|
|
15
|
+
border-color: $eccgui-color-application-text;
|
|
16
|
+
border-style: solid;
|
|
17
|
+
border-width: 1px 1px 1px 0.25rem;
|
|
19
18
|
|
|
20
19
|
& > .#{$eccgui}-icon {
|
|
21
|
-
color: inherit;
|
|
22
20
|
flex-grow: 0;
|
|
23
21
|
flex-shrink: 0;
|
|
22
|
+
color: inherit;
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
&.#{$eccgui}-notification--static > .#{$ns}-button-group {
|
|
@@ -31,29 +30,33 @@
|
|
|
31
30
|
|
|
32
31
|
&:not(.#{$eccgui}-notification--toast) {
|
|
33
32
|
max-width: none;
|
|
34
|
-
box-shadow: none;
|
|
35
33
|
margin-top: 0;
|
|
34
|
+
box-shadow: none;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.#{$eccgui}-card__content & {
|
|
38
|
+
min-width: unset;
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
&.#{$eccgui}-intent--info {
|
|
39
|
-
border-color: $eccgui-color-info-text;
|
|
40
42
|
color: $eccgui-color-info-text;
|
|
41
43
|
background-color: $eccgui-color-info-background;
|
|
44
|
+
border-color: $eccgui-color-info-text;
|
|
42
45
|
}
|
|
43
46
|
&.#{$eccgui}-intent--success {
|
|
44
|
-
border-color: $eccgui-color-success-text;
|
|
45
47
|
color: $eccgui-color-success-text;
|
|
46
48
|
background-color: $eccgui-color-success-background;
|
|
49
|
+
border-color: $eccgui-color-success-text;
|
|
47
50
|
}
|
|
48
51
|
&.#{$eccgui}-intent--warning {
|
|
49
|
-
border-color: $eccgui-color-warning-text;
|
|
50
52
|
color: $eccgui-color-warning-text;
|
|
51
53
|
background-color: $eccgui-color-warning-background;
|
|
54
|
+
border-color: $eccgui-color-warning-text;
|
|
52
55
|
}
|
|
53
56
|
&.#{$eccgui}-intent--danger {
|
|
54
|
-
border-color: $eccgui-color-danger-text;
|
|
55
57
|
color: $eccgui-color-danger-text;
|
|
56
58
|
background-color: $eccgui-color-danger-background;
|
|
59
|
+
border-color: $eccgui-color-danger-text;
|
|
57
60
|
}
|
|
58
61
|
}
|
|
59
62
|
|
|
@@ -65,15 +68,15 @@
|
|
|
65
68
|
|
|
66
69
|
.#{$eccgui}-notification__content {
|
|
67
70
|
display: flex;
|
|
68
|
-
justify-content: space-between;
|
|
69
71
|
align-items: baseline;
|
|
72
|
+
justify-content: space-between;
|
|
70
73
|
margin: -10px; // TODO: use blueprint var ofr toast padding here
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
.#{$eccgui}-notification__messagebody {
|
|
74
|
-
padding: 10px; // TODO: use blueprint var ofr toast padding here
|
|
75
77
|
flex-grow: 1;
|
|
76
78
|
flex-shrink: 1;
|
|
79
|
+
padding: 10px; // TODO: use blueprint var ofr toast padding here
|
|
77
80
|
}
|
|
78
81
|
|
|
79
82
|
.#{$eccgui}-notification__actions {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
|
|
2
3
|
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
|
|
3
4
|
|
|
4
5
|
export interface OverviewItemProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
@@ -18,19 +19,18 @@ export interface OverviewItemProps extends React.HTMLAttributes<HTMLDivElement>
|
|
|
18
19
|
*/
|
|
19
20
|
export const OverviewItem = ({
|
|
20
21
|
children,
|
|
21
|
-
className =
|
|
22
|
+
className = "",
|
|
22
23
|
densityHigh = false,
|
|
23
24
|
hasSpacing = false,
|
|
24
25
|
...otherProps
|
|
25
26
|
}: OverviewItemProps) => {
|
|
26
|
-
|
|
27
27
|
const item = (
|
|
28
28
|
<div
|
|
29
29
|
{...otherProps}
|
|
30
30
|
className={
|
|
31
31
|
`${eccgui}-overviewitem__item ` +
|
|
32
|
-
(densityHigh ? `${eccgui}-overviewitem__item--highdensity ` :
|
|
33
|
-
(hasSpacing ? `${eccgui}-overviewitem__item--hasspacing ` :
|
|
32
|
+
(densityHigh ? `${eccgui}-overviewitem__item--highdensity ` : "") +
|
|
33
|
+
(hasSpacing ? `${eccgui}-overviewitem__item--hasspacing ` : "") +
|
|
34
34
|
className
|
|
35
35
|
}
|
|
36
36
|
>
|
|
@@ -38,24 +38,15 @@ export const OverviewItem = ({
|
|
|
38
38
|
</div>
|
|
39
39
|
);
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
if (
|
|
43
|
-
|
|
44
|
-
typeof otherProps.onKeyDown !== 'undefined'
|
|
45
|
-
) {
|
|
46
|
-
accessibilityParameters['tabIndex'] = 0;
|
|
41
|
+
const accessibilityParameters: { [key: string]: any } = Object.create(null);
|
|
42
|
+
if (typeof otherProps.onClick !== "undefined" || typeof otherProps.onKeyDown !== "undefined") {
|
|
43
|
+
accessibilityParameters["tabIndex"] = 0;
|
|
47
44
|
}
|
|
48
|
-
if (
|
|
49
|
-
|
|
50
|
-
typeof otherProps.onKeyDown !== 'undefined'
|
|
51
|
-
) {
|
|
52
|
-
accessibilityParameters['role'] = "button";
|
|
45
|
+
if (typeof otherProps.onClick !== "undefined" && typeof otherProps.onKeyDown !== "undefined") {
|
|
46
|
+
accessibilityParameters["role"] = "button";
|
|
53
47
|
}
|
|
54
48
|
|
|
55
|
-
return React.cloneElement(
|
|
56
|
-
|
|
57
|
-
accessibilityParameters
|
|
58
|
-
);
|
|
59
|
-
}
|
|
49
|
+
return React.cloneElement(item, accessibilityParameters);
|
|
50
|
+
};
|
|
60
51
|
|
|
61
52
|
export default OverviewItem;
|
|
@@ -1,15 +1,28 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
|
|
2
3
|
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
|
|
3
4
|
import Label from "../Label/Label";
|
|
4
5
|
|
|
5
|
-
export interface PropertyNameProps extends React.HTMLAttributes<HTMLElement> {
|
|
6
|
+
export interface PropertyNameProps extends React.HTMLAttributes<HTMLElement> {
|
|
7
|
+
/**
|
|
8
|
+
* Increase or decrease the width used for the property name.
|
|
9
|
+
*/
|
|
10
|
+
size?: "small" | "medium" | "large";
|
|
11
|
+
}
|
|
6
12
|
|
|
7
|
-
export const PropertyName = ({ className = "", children, ...otherProps }: PropertyNameProps) => {
|
|
13
|
+
export const PropertyName = ({ className = "", size, children, ...otherProps }: PropertyNameProps) => {
|
|
8
14
|
return (
|
|
9
|
-
<dt
|
|
15
|
+
<dt
|
|
16
|
+
className={
|
|
17
|
+
`${eccgui}-propertyvalue__property` +
|
|
18
|
+
(size ? ` ${eccgui}-propertyvalue__property--${size}` : "") +
|
|
19
|
+
(className ? " " + className : "")
|
|
20
|
+
}
|
|
21
|
+
{...otherProps}
|
|
22
|
+
>
|
|
10
23
|
<div>{typeof children === "string" ? <Label text={children} isLayoutForElement="span" /> : children}</div>
|
|
11
24
|
</dt>
|
|
12
25
|
);
|
|
13
|
-
}
|
|
26
|
+
};
|
|
14
27
|
|
|
15
28
|
export default PropertyName;
|
|
@@ -46,9 +46,25 @@
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
.#{$eccgui}-propertyvalue__property--small {
|
|
50
|
+
width: math.div(2, 16) * 100%;
|
|
51
|
+
|
|
52
|
+
& + .#{$eccgui}-propertyvalue__value {
|
|
53
|
+
margin-left: math.div(2, 16) * 100%;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.#{$eccgui}-propertyvalue__property--large {
|
|
58
|
+
width: math.div(5, 16) * 100%;
|
|
59
|
+
|
|
60
|
+
& + .#{$eccgui}-propertyvalue__value {
|
|
61
|
+
margin-left: math.div(5, 16) * 100%;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
49
65
|
.#{$eccgui}-propertyvalue__value {
|
|
50
|
-
margin-left: math.div(3, 16) * 100%;
|
|
51
66
|
box-sizing: content-box;
|
|
67
|
+
margin-left: math.div(3, 16) * 100%;
|
|
52
68
|
|
|
53
69
|
&:not(:last-child) {
|
|
54
70
|
.#{$eccgui}-propertyvalue__pair--hasdivider > & {
|