@eccenca/gui-elements 23.2.0-rc.0 → 23.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/CHANGELOG.md +32 -3
  2. package/dist/cjs/components/AutoSuggestion/AutoSuggestion.js +24 -20
  3. package/dist/cjs/components/AutoSuggestion/AutoSuggestion.js.map +1 -1
  4. package/dist/cjs/components/AutocompleteField/AutoCompleteField.js +59 -50
  5. package/dist/cjs/components/AutocompleteField/AutoCompleteField.js.map +1 -1
  6. package/dist/cjs/components/AutocompleteField/autoCompleteFieldUtils.js +3 -3
  7. package/dist/cjs/components/AutocompleteField/autoCompleteFieldUtils.js.map +1 -1
  8. package/dist/cjs/components/Breadcrumb/BreadcrumbItem.js +9 -6
  9. package/dist/cjs/components/Breadcrumb/BreadcrumbItem.js.map +1 -1
  10. package/dist/cjs/components/CodeAutocompleteField/CodeAutocompleteField.js +33 -0
  11. package/dist/cjs/components/CodeAutocompleteField/CodeAutocompleteField.js.map +1 -0
  12. package/dist/cjs/components/CodeAutocompleteField/index.js +14 -0
  13. package/dist/cjs/components/CodeAutocompleteField/index.js.map +1 -0
  14. package/dist/cjs/components/Depiction/Depiction.js +13 -13
  15. package/dist/cjs/components/Depiction/Depiction.js.map +1 -1
  16. package/dist/cjs/components/Dialog/SimpleDialog.js +5 -5
  17. package/dist/cjs/components/Dialog/SimpleDialog.js.map +1 -1
  18. package/dist/cjs/components/Icon/IconButton.js +9 -3
  19. package/dist/cjs/components/Icon/IconButton.js.map +1 -1
  20. package/dist/cjs/components/Icon/canonicalIconNames.js +2 -0
  21. package/dist/cjs/components/Icon/canonicalIconNames.js.map +1 -1
  22. package/dist/cjs/components/MultiSelect/MultiSelect.js +45 -17
  23. package/dist/cjs/components/MultiSelect/MultiSelect.js.map +1 -1
  24. package/dist/cjs/components/MultiSuggestField/MultiSuggestField.js +33 -0
  25. package/dist/cjs/components/MultiSuggestField/MultiSuggestField.js.map +1 -0
  26. package/dist/cjs/components/OverviewItem/OverviewItem.js +8 -10
  27. package/dist/cjs/components/OverviewItem/OverviewItem.js.map +1 -1
  28. package/dist/cjs/components/PropertyValuePair/PropertyName.js +4 -3
  29. package/dist/cjs/components/PropertyValuePair/PropertyName.js.map +1 -1
  30. package/dist/cjs/components/Select/Select.js +18 -3
  31. package/dist/cjs/components/Select/Select.js.map +1 -1
  32. package/dist/cjs/components/SuggestField/SuggestField.js +39 -0
  33. package/dist/cjs/components/SuggestField/SuggestField.js.map +1 -0
  34. package/dist/cjs/components/SuggestField/index.js +19 -0
  35. package/dist/cjs/components/SuggestField/index.js.map +1 -0
  36. package/dist/cjs/components/index.js +3 -0
  37. package/dist/cjs/components/index.js.map +1 -1
  38. package/dist/cjs/extensions/react-flow/nodes/NodeContent.js +54 -41
  39. package/dist/cjs/extensions/react-flow/nodes/NodeContent.js.map +1 -1
  40. package/dist/cjs/index.js +1 -0
  41. package/dist/cjs/index.js.map +1 -1
  42. package/dist/esm/components/AutoSuggestion/AutoSuggestion.js +23 -18
  43. package/dist/esm/components/AutoSuggestion/AutoSuggestion.js.map +1 -1
  44. package/dist/esm/components/AutocompleteField/AutoCompleteField.js +68 -59
  45. package/dist/esm/components/AutocompleteField/AutoCompleteField.js.map +1 -1
  46. package/dist/esm/components/AutocompleteField/autoCompleteFieldUtils.js +3 -3
  47. package/dist/esm/components/AutocompleteField/autoCompleteFieldUtils.js.map +1 -1
  48. package/dist/esm/components/Breadcrumb/BreadcrumbItem.js +9 -6
  49. package/dist/esm/components/Breadcrumb/BreadcrumbItem.js.map +1 -1
  50. package/dist/esm/components/CodeAutocompleteField/CodeAutocompleteField.js +37 -0
  51. package/dist/esm/components/CodeAutocompleteField/CodeAutocompleteField.js.map +1 -0
  52. package/dist/esm/components/CodeAutocompleteField/index.js +2 -0
  53. package/dist/esm/components/CodeAutocompleteField/index.js.map +1 -0
  54. package/dist/esm/components/Depiction/Depiction.js +12 -12
  55. package/dist/esm/components/Depiction/Depiction.js.map +1 -1
  56. package/dist/esm/components/Dialog/SimpleDialog.js +7 -7
  57. package/dist/esm/components/Dialog/SimpleDialog.js.map +1 -1
  58. package/dist/esm/components/Icon/IconButton.js +10 -4
  59. package/dist/esm/components/Icon/IconButton.js.map +1 -1
  60. package/dist/esm/components/Icon/canonicalIconNames.js +2 -0
  61. package/dist/esm/components/Icon/canonicalIconNames.js.map +1 -1
  62. package/dist/esm/components/MultiSelect/MultiSelect.js +52 -22
  63. package/dist/esm/components/MultiSelect/MultiSelect.js.map +1 -1
  64. package/dist/esm/components/MultiSuggestField/MultiSuggestField.js +37 -0
  65. package/dist/esm/components/MultiSuggestField/MultiSuggestField.js.map +1 -0
  66. package/dist/esm/components/OverviewItem/OverviewItem.js +8 -10
  67. package/dist/esm/components/OverviewItem/OverviewItem.js.map +1 -1
  68. package/dist/esm/components/PropertyValuePair/PropertyName.js +4 -3
  69. package/dist/esm/components/PropertyValuePair/PropertyName.js.map +1 -1
  70. package/dist/esm/components/Select/Select.js +19 -4
  71. package/dist/esm/components/Select/Select.js.map +1 -1
  72. package/dist/esm/components/SuggestField/SuggestField.js +43 -0
  73. package/dist/esm/components/SuggestField/SuggestField.js.map +1 -0
  74. package/dist/esm/components/SuggestField/index.js +6 -0
  75. package/dist/esm/components/SuggestField/index.js.map +1 -0
  76. package/dist/esm/components/index.js +3 -0
  77. package/dist/esm/components/index.js.map +1 -1
  78. package/dist/esm/extensions/react-flow/nodes/NodeContent.js +51 -39
  79. package/dist/esm/extensions/react-flow/nodes/NodeContent.js.map +1 -1
  80. package/dist/esm/index.js +2 -1
  81. package/dist/esm/index.js.map +1 -1
  82. package/dist/types/components/AutoSuggestion/AutoSuggestion.d.ts +35 -4
  83. package/dist/types/components/AutocompleteField/AutoCompleteField.d.ts +23 -6
  84. package/dist/types/components/AutocompleteField/autoCompleteFieldUtils.d.ts +3 -3
  85. package/dist/types/components/AutocompleteField/index.d.ts +1 -1
  86. package/dist/types/components/AutocompleteField/interfaces.d.ts +1 -1
  87. package/dist/types/components/CodeAutocompleteField/CodeAutocompleteField.d.ts +10 -0
  88. package/dist/types/components/CodeAutocompleteField/index.d.ts +1 -0
  89. package/dist/types/components/Dialog/SimpleDialog.d.ts +2 -2
  90. package/dist/types/components/Icon/IconButton.d.ts +2 -2
  91. package/dist/types/components/Icon/canonicalIconNames.d.ts +1 -1
  92. package/dist/types/components/MultiSelect/MultiSelect.d.ts +20 -2
  93. package/dist/types/components/MultiSuggestField/MultiSuggestField.d.ts +10 -0
  94. package/dist/types/components/PropertyValuePair/PropertyName.d.ts +5 -1
  95. package/dist/types/components/Select/Select.d.ts +28 -9
  96. package/dist/types/components/SuggestField/SuggestField.d.ts +16 -0
  97. package/dist/types/components/SuggestField/index.d.ts +5 -0
  98. package/dist/types/components/index.d.ts +3 -0
  99. package/dist/types/extensions/react-flow/nodes/NodeContent.d.ts +7 -7
  100. package/dist/types/index.d.ts +2 -1
  101. package/package.json +1 -1
  102. package/src/components/Application/_header.scss +49 -58
  103. package/src/components/AutoSuggestion/AutoSuggestion.stories.tsx +14 -0
  104. package/src/components/AutoSuggestion/AutoSuggestion.tsx +280 -221
  105. package/src/components/AutocompleteField/AutoCompleteField.stories.tsx +14 -0
  106. package/src/components/AutocompleteField/AutoCompleteField.tsx +157 -121
  107. package/src/components/AutocompleteField/autoCompleteFieldUtils.tsx +10 -16
  108. package/src/components/AutocompleteField/interfaces.ts +5 -6
  109. package/src/components/Breadcrumb/BreadcrumbItem.tsx +19 -18
  110. package/src/components/Breadcrumb/breadcrumb.scss +18 -16
  111. package/src/components/Breadcrumb/stories/BreadcrumbList.stories.tsx +18 -15
  112. package/src/components/CodeAutocompleteField/CodeAutocompleteField.stories.tsx +89 -0
  113. package/src/components/CodeAutocompleteField/CodeAutocompleteField.tsx +22 -0
  114. package/src/components/CodeAutocompleteField/index.ts +1 -0
  115. package/src/components/ContextOverlay/contextoverlay.scss +10 -2
  116. package/src/components/Depiction/Depiction.tsx +57 -55
  117. package/src/components/Dialog/SimpleDialog.tsx +20 -33
  118. package/src/components/Icon/IconButton.tsx +25 -11
  119. package/src/components/Icon/canonicalIconNames.tsx +4 -0
  120. package/src/components/MultiSelect/MultiSelect.stories.tsx +9 -47
  121. package/src/components/MultiSelect/MultiSelect.tsx +110 -66
  122. package/src/components/MultiSuggestField/MultiSuggestField.stories.tsx +58 -0
  123. package/src/components/MultiSuggestField/MultiSuggestField.tsx +22 -0
  124. package/src/components/Notification/notification.scss +20 -17
  125. package/src/components/OverviewItem/OverviewItem.tsx +11 -20
  126. package/src/components/PropertyValuePair/PropertyName.tsx +17 -4
  127. package/src/components/PropertyValuePair/propertyvalue.scss +17 -1
  128. package/src/components/Select/Select.stories.tsx +49 -20
  129. package/src/components/Select/Select.tsx +96 -18
  130. package/src/components/Select/_select.scss +13 -1
  131. package/src/components/SuggestField/SuggestField.stories.tsx +99 -0
  132. package/src/components/SuggestField/SuggestField.tsx +28 -0
  133. package/src/components/SuggestField/index.ts +5 -0
  134. package/src/components/TagInput/taginput.scss +14 -0
  135. package/src/components/index.scss +1 -1
  136. package/src/components/index.ts +3 -0
  137. package/src/extensions/react-flow/nodes/NodeContent.tsx +105 -87
  138. package/src/index.ts +2 -5
  139. package/src/components/AutoSuggestion/stories/AutoSuggestion.stories.tsx +0 -83
  140. package/src/components/AutocompleteField/stories/AutoCompleteField.stories.tsx +0 -86
@@ -0,0 +1,14 @@
1
+ import { Meta } from "@storybook/react";
2
+
3
+ import { AutoCompleteField } from "./../../../index";
4
+ export { Default } from "../SuggestField/SuggestField.stories";
5
+
6
+ export default {
7
+ title: "Forms/AutoCompleteField",
8
+ component: AutoCompleteField,
9
+ parameters: {
10
+ controls: {
11
+ exclude: /.*/g,
12
+ },
13
+ },
14
+ } as Meta<typeof AutoCompleteField>;
@@ -1,41 +1,42 @@
1
- import React, {useEffect, useRef, useState} from "react";
1
+ import React, { useEffect, useState } from "react";
2
2
  import {
3
3
  HTMLInputProps as BlueprintHTMLInputProps,
4
4
  InputGroupProps2 as BlueprintInputGroupProps,
5
5
  } from "@blueprintjs/core";
6
+ import { Suggest2 as BlueprintSuggest } from "@blueprintjs/select";
7
+
8
+ import { CLASSPREFIX as eccgui } from "../../configuration/constants";
6
9
  import {
7
- Suggest2 as Suggest
8
- } from "@blueprintjs/select";
9
- import {
10
+ ContextOverlayProps,
10
11
  Highlighter,
11
12
  IconButton,
12
13
  Menu,
13
- Notification,
14
14
  MenuItem,
15
+ Notification,
15
16
  OverflowText,
16
17
  Spinner,
17
- ContextOverlayProps,
18
18
  } from "../../index";
19
- import {
20
- IElementWidth as IElementWidthOrig,
21
- IRenderModifiers as IRenderModifiersOrig
22
- } from "./interfaces";
23
- import {CLASSPREFIX as eccgui} from "../../configuration/constants";
19
+
20
+ import { IElementWidth as IElementWidthOrig, IRenderModifiers as IRenderModifiersOrig } from "./interfaces";
24
21
 
25
22
  // @deprecated import from `src/components/AutocompleteField/interfaces`
26
23
  export type IElementWidth = IElementWidthOrig;
27
24
  // @deprecated import from `src/components/AutocompleteField/interfaces`
28
25
  export type IRenderModifiers = IRenderModifiersOrig;
29
26
 
30
- type SearchFunction<T extends any> = (value: string) => T[];
31
- type AsyncSearchFunction<T extends any> = (value: string) => Promise<T[]>;
27
+ type SearchFunction<T> = (value: string) => T[];
28
+ type AsyncSearchFunction<T> = (value: string) => Promise<T[]>;
32
29
 
33
30
  /**
34
31
  * Parameters for the auto-complete field parameterized by T and U.
35
32
  * @param T is the input data structure/type of the items that can be selected.
36
33
  * @param UPDATE_VALUE The value type that will be pushed into the onChange callback.
37
34
  */
38
- export interface AutoCompleteFieldProps<T extends any, UPDATE_VALUE extends any> {
35
+ export interface AutoCompleteFieldProps<T, UPDATE_VALUE> {
36
+ /**
37
+ * Additional class names.
38
+ */
39
+ className?: string;
39
40
  /**
40
41
  * Fired when text is typed into the input field. Returns a list of items of type T.
41
42
  */
@@ -76,10 +77,10 @@ export interface AutoCompleteFieldProps<T extends any, UPDATE_VALUE extends any>
76
77
  itemValueSelector(item: T): UPDATE_VALUE;
77
78
 
78
79
  /** The string representation of the actual value, i.e. without meta data etc. This will be used to compare if values are equal. */
79
- itemValueString(item: T): string
80
+ itemValueString(item: T): string;
80
81
 
81
82
  /** The text that should be displayed when no search result has been found and no custom entry can be created. */
82
- noResultText: string
83
+ noResultText: string;
83
84
 
84
85
  /**
85
86
  * Props to spread to the underlying input field. This is BlueprintJs specific. To control this input, use
@@ -91,7 +92,7 @@ export interface AutoCompleteFieldProps<T extends any, UPDATE_VALUE extends any>
91
92
  /**
92
93
  * Optional props of the internally used `<ContextOverlay/>` element..
93
94
  */
94
- contextOverlayProps?: Partial<Omit<ContextOverlayProps, "content" | "children">>
95
+ contextOverlayProps?: Partial<Omit<ContextOverlayProps, "content" | "children">>;
95
96
 
96
97
  /** Defines if a value can be reset, i.e. a reset icon is shown and the value is set to a specific value.
97
98
  * When undefined, a value cannot be reset.
@@ -105,7 +106,7 @@ export interface AutoCompleteFieldProps<T extends any, UPDATE_VALUE extends any>
105
106
  resetValue: UPDATE_VALUE;
106
107
 
107
108
  /** The reset button text that is shown on hovering over the reset icon. */
108
- resetButtonText: string
109
+ resetButtonText: string;
109
110
  };
110
111
 
111
112
  /** If enabled the auto completion component will auto focus. */
@@ -126,7 +127,7 @@ export interface AutoCompleteFieldProps<T extends any, UPDATE_VALUE extends any>
126
127
  /** If the new item option will always be shown as the first entry in the suggestion list, else it will be the last entry.
127
128
  * @default false
128
129
  */
129
- showNewItemOptionFirst?: boolean
130
+ showNewItemOptionFirst?: boolean;
130
131
  };
131
132
 
132
133
  /** Dropdown is only rendered when the query has a value (input field is not empty). */
@@ -140,38 +141,47 @@ export interface AutoCompleteFieldProps<T extends any, UPDATE_VALUE extends any>
140
141
  *
141
142
  * @param selectedValue The currently selected value.
142
143
  */
143
- resetQueryToValue?(selectedValue: T): string
144
+ resetQueryToValue?(selectedValue: T): string;
144
145
 
145
146
  /** If an error occurs during the auto-completion request, the error details will be prefixed with this string. */
146
- requestErrorPrefix?: string
147
+ requestErrorPrefix?: string;
147
148
 
148
149
  /** Creates a backdrop when the popover is shown that captures outside clicks in order to close the popover.
149
150
  * This is needed if other components on the same page are swallowing events, e.g. the react-flow canvas.
150
151
  * hasBackDrop should then be set to true in these cases otherwise the popover won't close when clicking those other components.
151
152
  **/
152
- hasBackDrop?: boolean
153
+ hasBackDrop?: boolean;
154
+
155
+ /**
156
+ * Use the full available width of the parent container.
157
+ */
158
+ fill?: boolean;
153
159
  }
154
160
 
155
- export type IAutoCompleteFieldProps<T extends any, UPDATE_VALUE extends any> = AutoCompleteFieldProps<T, UPDATE_VALUE>;
161
+ export type IAutoCompleteFieldProps<T, UPDATE_VALUE> = AutoCompleteFieldProps<T, UPDATE_VALUE>;
156
162
 
157
163
  AutoCompleteField.defaultProps = {
158
164
  autoFocus: false,
159
165
  disabled: false,
166
+ onlyDropdownWithQuery: false, // FIXME: this should be `true` by default, otherwise similarity to `<Select />` is very close
167
+ fill: true,
168
+ requestErrorPrefix: "",
169
+ hasBackDrop: false,
160
170
  };
161
171
 
162
- /** Hook that returns the element width of the given ref.*/
163
- const elementWidth = (elRef: React.RefObject<HTMLInputElement> | null): IElementWidth => {
164
- const minWidth = (elRef && elRef.current) ? elRef.current.offsetWidth + "px" : "20rem";
165
- return { minWidth, maxWidth: "90vw" };
166
- }
167
-
168
- /** Auto-complete input widget. */
169
- export function AutoCompleteField<T extends any, UPDATE_VALUE extends any>(props: AutoCompleteFieldProps<T, UPDATE_VALUE>) {
172
+ /**
173
+ * **Element is deprecated.**
174
+ * Use `SuggestField` as replacement.
175
+ *
176
+ * @deprecated
177
+ */
178
+ export function AutoCompleteField<T, UPDATE_VALUE>(props: AutoCompleteFieldProps<T, UPDATE_VALUE>) {
170
179
  const {
180
+ className,
171
181
  reset,
172
182
  noResultText,
173
183
  disabled,
174
- onlyDropdownWithQuery = false,
184
+ onlyDropdownWithQuery,
175
185
  itemValueSelector,
176
186
  itemRenderer,
177
187
  onSearch,
@@ -182,8 +192,9 @@ export function AutoCompleteField<T extends any, UPDATE_VALUE extends any>(props
182
192
  itemValueRenderer,
183
193
  resetQueryToValue,
184
194
  itemValueString,
185
- requestErrorPrefix = "",
186
- hasBackDrop = false,
195
+ requestErrorPrefix,
196
+ hasBackDrop,
197
+ fill,
187
198
  ...otherProps
188
199
  } = props;
189
200
  const [selectedItem, setSelectedItem] = useState<T | undefined>(initialValue);
@@ -194,29 +205,26 @@ export function AutoCompleteField<T extends any, UPDATE_VALUE extends any>(props
194
205
  // If the input field has focus
195
206
  const [inputHasFocus, setInputHasFocus] = useState<boolean>(false);
196
207
  const [highlightingEnabled, setHighlightingEnabled] = useState<boolean>(true);
197
- const [requestError, setRequestError] = useState<string | undefined>(undefined)
208
+ const [requestError, setRequestError] = useState<string | undefined>(undefined);
198
209
 
199
210
  // The suggestions that match the user's input
200
211
  const [filtered, setFiltered] = useState<T[]>([]);
201
212
 
202
- const BlueprintSuggestAutocomplete = Suggest.ofType<T>();
203
- const readOnly = !!otherProps.inputProps?.readOnly
213
+ const readOnly = !!otherProps.inputProps?.readOnly;
204
214
 
205
215
  // Sets the query to the item value if it has a valid string value
206
216
  const setQueryToSelectedValue = (item?: T) => {
207
217
  if (item) {
208
218
  // If new values can be created, always reset the query value to the actual value of the selected item.
209
219
  // This e.g. prevents that the "create new" option will be shown, since an item with the same value already exists.
210
- const defaultResetValue: string = createNewItem ? (
211
- itemValueString(item) as string
212
- ) : itemValueRenderer(item)
213
- const resetVal = resetQueryToValue ? resetQueryToValue(item) : defaultResetValue
214
- setQuery(resetVal)
220
+ const defaultResetValue: string = createNewItem
221
+ ? (itemValueString(item) as string)
222
+ : itemValueRenderer(item);
223
+ const resetVal = resetQueryToValue ? resetQueryToValue(item) : defaultResetValue;
224
+ setQuery(resetVal);
215
225
  }
216
226
  };
217
227
 
218
- const fieldRef = useRef(null)
219
-
220
228
  // The key for the option elements
221
229
  const itemKey = (item: T): string => {
222
230
  return itemValueString(item);
@@ -224,10 +232,7 @@ export function AutoCompleteField<T extends any, UPDATE_VALUE extends any>(props
224
232
 
225
233
  useEffect(() => {
226
234
  setQueryToSelectedValue(selectedItem);
227
- },
228
- // eslint-disable-next-line react-hooks/exhaustive-deps
229
- [selectedItem]
230
- );
235
+ }, [selectedItem]);
231
236
 
232
237
  useEffect(() => {
233
238
  if (!disabled && !readOnly && inputHasFocus) {
@@ -241,12 +246,7 @@ export function AutoCompleteField<T extends any, UPDATE_VALUE extends any>(props
241
246
  };
242
247
  }
243
248
  return;
244
- },
245
- // eslint-disable-next-line react-hooks/exhaustive-deps
246
- [inputHasFocus, query]
247
- );
248
-
249
- const fieldWidthLimits = elementWidth(fieldRef);
249
+ }, [inputHasFocus, query]);
250
250
 
251
251
  // We need to fire some actions when the auto-complete widget gets or loses focus
252
252
  const handleOnFocusIn = () => {
@@ -263,7 +263,7 @@ export function AutoCompleteField<T extends any, UPDATE_VALUE extends any>(props
263
263
  setQueryToSelectedValue(selectedItem);
264
264
  // Reset option list when the popover closes, so next use there is not displayed a stale list
265
265
  setFiltered([]);
266
- }
266
+ };
267
267
 
268
268
  // Triggered when an item from the selection list gets selected
269
269
  const onSelectionChange = (value: any, e: any) => {
@@ -289,11 +289,14 @@ export function AutoCompleteField<T extends any, UPDATE_VALUE extends any>(props
289
289
  // Fetches the results for the given query
290
290
  const fetchQueryResults = async (input: string) => {
291
291
  setListLoading(true);
292
- setRequestError(undefined)
292
+ setRequestError(undefined);
293
293
  try {
294
294
  let result = await onSearch(input);
295
- const onlySelectItemReturned = result.length <= 1 && selectedItem && input.length > 0 &&
296
- (itemValueRenderer(selectedItem) === input || itemValueString(selectedItem) === input)
295
+ const onlySelectItemReturned =
296
+ result.length <= 1 &&
297
+ selectedItem &&
298
+ input.length > 0 &&
299
+ (itemValueRenderer(selectedItem) === input || itemValueString(selectedItem) === input);
297
300
  let enableHighlighting = true;
298
301
  if (onlySelectItemReturned) {
299
302
  // If the auto-completion only returns no suggestion or the selected item itself, query with empty string.
@@ -302,7 +305,7 @@ export function AutoCompleteField<T extends any, UPDATE_VALUE extends any>(props
302
305
  enableHighlighting = false;
303
306
  // Put selected item at the top if it is not in the result list
304
307
  if (!!selectedItem && itemIndexOf(emptyStringResults, selectedItem) > -1) {
305
- emptyStringResults.splice(itemIndexOf(emptyStringResults, selectedItem), 1)
308
+ emptyStringResults.splice(itemIndexOf(emptyStringResults, selectedItem), 1);
306
309
  result = [selectedItem, ...emptyStringResults];
307
310
  } else {
308
311
  result = emptyStringResults;
@@ -311,24 +314,26 @@ export function AutoCompleteField<T extends any, UPDATE_VALUE extends any>(props
311
314
  setHighlightingEnabled(enableHighlighting);
312
315
  setFiltered(result);
313
316
  } catch (e: any) {
314
- const details = e?.message ?? ""
315
- setRequestError(requestErrorPrefix + details)
317
+ const details = e?.message ?? "";
318
+ setRequestError(requestErrorPrefix + details);
316
319
  } finally {
317
320
  setListLoading(false);
318
321
  }
319
322
  };
320
323
 
321
324
  // Renders the item in the selection list
322
- const optionRenderer = (item: any, { handleClick, modifiers, query }: {handleClick: any, modifiers: any, query: any}) => {
325
+ const optionRenderer = (
326
+ item: any,
327
+ { handleClick, modifiers, query }: { handleClick: any; modifiers: any; query: any }
328
+ ) => {
323
329
  if (!modifiers.matchesPredicate) {
324
330
  return null;
325
331
  }
326
332
  const relevantModifiers: IRenderModifiers = {
327
333
  active: modifiers.active,
328
334
  disabled: modifiers.disabled,
329
- styleWidth: fieldWidthLimits,
330
335
  highlightingEnabled: highlightingEnabled,
331
- }
336
+ };
332
337
  const renderedItem = itemRenderer(item, query, relevantModifiers, handleClick);
333
338
  if (typeof renderedItem === "string") {
334
339
  return (
@@ -338,8 +343,12 @@ export function AutoCompleteField<T extends any, UPDATE_VALUE extends any>(props
338
343
  key={itemKey(item)}
339
344
  onClick={handleClick}
340
345
  text={
341
- <OverflowText style={fieldWidthLimits}>
342
- {!highlightingEnabled ? renderedItem : <Highlighter label={renderedItem} searchValue={query} />}
346
+ <OverflowText>
347
+ {!highlightingEnabled ? (
348
+ renderedItem
349
+ ) : (
350
+ <Highlighter label={renderedItem} searchValue={query} />
351
+ )}
343
352
  </OverflowText>
344
353
  }
345
354
  />
@@ -355,12 +364,11 @@ export function AutoCompleteField<T extends any, UPDATE_VALUE extends any>(props
355
364
  setQuery("");
356
365
  };
357
366
  const requestErrorRenderer = () => {
358
- return <Notification danger={true} message={requestError} />
359
- }
367
+ return <Notification danger={true} message={requestError} />;
368
+ };
360
369
  // Optional clear button to reset the selected value
361
- const clearButton = !readOnly && !disabled && reset &&
362
- selectedItem != null &&
363
- reset.resettableValue(selectedItem) ? (
370
+ const clearButton =
371
+ !readOnly && !disabled && reset && selectedItem != null && reset.resettableValue(selectedItem) ? (
364
372
  <IconButton
365
373
  data-test-id={
366
374
  (otherProps.inputProps?.id ? `${otherProps.inputProps.id}-` : "") + "auto-complete-clear-btn"
@@ -372,72 +380,100 @@ export function AutoCompleteField<T extends any, UPDATE_VALUE extends any>(props
372
380
  ) : undefined;
373
381
  // Additional properties for the input element of the auto-completion widget
374
382
  const updatedInputProps: BlueprintInputGroupProps & BlueprintHTMLInputProps = {
375
- rightElement: clearButton,
383
+ rightElement:
384
+ clearButton || onlyDropdownWithQuery === false ? (
385
+ <>
386
+ {clearButton}
387
+ {onlyDropdownWithQuery === false && (
388
+ <IconButton
389
+ name={"toggler-caretdown"}
390
+ onClick={(e) => {
391
+ const target = e.currentTarget
392
+ .closest(`.${eccgui}-autocompletefield__input`)
393
+ ?.querySelector("input");
394
+ (target as HTMLElement).focus();
395
+ e.stopPropagation();
396
+ }}
397
+ />
398
+ )}
399
+ </>
400
+ ) : undefined,
376
401
  autoFocus: autoFocus,
377
402
  onBlur: handleOnFocusOut,
378
403
  onFocus: handleOnFocusIn,
379
404
  ...otherProps.inputProps,
380
- title: (selectedItem !== undefined && (readOnly || disabled)) ? itemValueString(selectedItem) : otherProps.inputProps?.title,
405
+ title:
406
+ selectedItem !== undefined && (readOnly || disabled)
407
+ ? itemValueString(selectedItem)
408
+ : otherProps.inputProps?.title,
381
409
  };
382
- const preventOverlayOnReadonly = readOnly ? { isOpen: false } : {}
410
+ const preventOverlayOnReadonly = readOnly ? { isOpen: false } : {};
383
411
  const updatedContextOverlayProps: Partial<Omit<ContextOverlayProps, "content" | "children">> = {
384
412
  minimal: true,
385
- placement: "bottom-start",
413
+ matchTargetWidth: fill,
386
414
  popoverClassName: `${eccgui}-autocompletefield__options`,
387
- rootBoundary: "viewport",
388
415
  onClosed: onPopoverClose,
389
416
  ...otherProps.contextOverlayProps,
390
417
  ...preventOverlayOnReadonly,
391
418
  // Needed to capture clicks outside of the popover, e.g. in order to close it.
392
- hasBackdrop: hasBackDrop
393
- }
394
- if(selectedItem !== undefined) {
419
+ hasBackdrop: hasBackDrop,
420
+ };
421
+ if (selectedItem !== undefined) {
395
422
  // Makes sure that even when an empty string is selected, the placeholder won't be shown.
396
- updatedInputProps.placeholder = ""
423
+ updatedInputProps.placeholder = "";
397
424
  }
398
425
  // For some reason Typescript is not able to infer the union type from the ternary expression
399
- const createNewItemPosition: "first" | "last" = createNewItem?.showNewItemOptionFirst ? "first" : "last"
400
- const createNewItemProps = createNewItem ? {
401
- createNewItemFromQuery: createNewItem.itemFromQuery,
402
- createNewItemRenderer: (query: string, active: boolean, handleClick: React.MouseEventHandler<HTMLElement>) => {
403
- if(selectedItem && query === itemValueString(selectedItem)) {
404
- // Never show create new item option if the same item is already selected
405
- return undefined
406
- } else {
407
- return createNewItem!!.itemRenderer(query, {active, styleWidth: fieldWidthLimits, highlightingEnabled: false}, handleClick)
408
- }
409
- },
410
- createNewItemPosition
411
- } : {}
426
+ const createNewItemPosition: "first" | "last" = createNewItem?.showNewItemOptionFirst ? "first" : "last";
427
+ const createNewItemProps = createNewItem
428
+ ? {
429
+ createNewItemFromQuery: createNewItem.itemFromQuery,
430
+ createNewItemRenderer: (
431
+ query: string,
432
+ active: boolean,
433
+ handleClick: React.MouseEventHandler<HTMLElement>
434
+ ) => {
435
+ if (selectedItem && query === itemValueString(selectedItem)) {
436
+ // Never show create new item option if the same item is already selected
437
+ return undefined;
438
+ } else {
439
+ return createNewItem!.itemRenderer(query, { active, highlightingEnabled: false }, handleClick);
440
+ }
441
+ },
442
+ createNewItemPosition,
443
+ }
444
+ : {};
412
445
  return (
413
- <div ref={fieldRef}>
414
- <BlueprintSuggestAutocomplete
415
- className={`${eccgui}-autocompletefield__input`}
416
- disabled={disabled}
417
- // Need to display error messages in list
418
- items={requestError ?
419
- [requestError as T] :
420
- filtered
421
- }
422
- initialContent={onlyDropdownWithQuery ? null : undefined}
423
- inputValueRenderer={selectedItem !== undefined ? itemValueRenderer : () => ""}
424
- itemRenderer={requestError ? requestErrorRenderer : optionRenderer}
425
- itemsEqual={areEqualItems}
426
- noResults={<MenuItem disabled={true} text={noResultText} style={fieldWidthLimits} />}
427
- onItemSelect={onSelectionChange}
428
- onQueryChange={(q) => setQuery(q)}
429
- closeOnSelect={true}
430
- query={query}
431
- // This leads to odd compile errors without "as any"
432
- popoverProps={updatedContextOverlayProps as any}
433
- selectedItem={selectedItem}
434
- fill
435
- {...createNewItemProps}
436
- // This leads to odd compile errors without "as any"
437
- inputProps={updatedInputProps as any}
438
- itemListRenderer={listLoading ? () => <Menu><MenuItem disabled={true} text={<Spinner position={"inline"} />} style={fieldWidthLimits} /></Menu> : undefined}
439
- />
440
- </div>
446
+ <BlueprintSuggest<T>
447
+ className={`${eccgui}-autocompletefield__input` + (className ? ` ${className}` : "")}
448
+ disabled={disabled}
449
+ // Need to display error messages in list
450
+ items={requestError ? [requestError as unknown as T] : filtered}
451
+ initialContent={onlyDropdownWithQuery ? null : undefined}
452
+ inputValueRenderer={selectedItem !== undefined ? itemValueRenderer : () => ""}
453
+ itemRenderer={requestError ? requestErrorRenderer : optionRenderer}
454
+ itemsEqual={areEqualItems}
455
+ noResults={<MenuItem disabled={true} text={noResultText} />}
456
+ onItemSelect={onSelectionChange}
457
+ onQueryChange={(q) => setQuery(q)}
458
+ closeOnSelect={true}
459
+ query={query}
460
+ // This leads to odd compile errors without "as any"
461
+ popoverProps={updatedContextOverlayProps as any}
462
+ selectedItem={selectedItem}
463
+ fill={fill}
464
+ {...createNewItemProps}
465
+ // This leads to odd compile errors without "as any"
466
+ inputProps={updatedInputProps as any}
467
+ itemListRenderer={
468
+ listLoading
469
+ ? () => (
470
+ <Menu>
471
+ <MenuItem disabled={true} text={<Spinner position={"inline"} />} />
472
+ </Menu>
473
+ )
474
+ : undefined
475
+ }
476
+ />
441
477
  );
442
478
  }
443
479
 
@@ -1,9 +1,11 @@
1
1
  import React from "react";
2
- import { IElementWidth, IRenderModifiers } from "./interfaces";
3
- import OverflowText from "../Typography/OverflowText";
2
+
3
+ import { ValidIconName } from "../Icon/canonicalIconNames";
4
4
  import MenuItem from "../Menu/MenuItem";
5
+ import OverflowText from "../Typography/OverflowText";
6
+
5
7
  import { TestIconProps } from "./../Icon/TestIcon";
6
- import { ValidIconName } from "../Icon/canonicalIconNames";
8
+ import { IRenderModifiers } from "./interfaces";
7
9
 
8
10
  /**
9
11
  * Returns a function to be used in an AutoComplete widget for rendering custom elements based on the query string.
@@ -12,27 +14,19 @@ import { ValidIconName } from "../Icon/canonicalIconNames";
12
14
  * @param iconName Optional icon to show left to the text.
13
15
  */
14
16
  export const createNewItemRendererFactory = (
15
- itemTextRenderer: (query: string, styleWidth: IElementWidth) => string | JSX.Element,
17
+ itemTextRenderer: (query: string) => string | JSX.Element,
16
18
  iconName?: ValidIconName | React.ReactElement<TestIconProps>
17
19
  ) => {
18
20
  // Return custom render function
19
21
  return (query: string, modifiers: IRenderModifiers, handleClick: React.MouseEventHandler<HTMLElement>) => {
20
- let textElement = itemTextRenderer(query, modifiers.styleWidth)
22
+ let textElement = itemTextRenderer(query);
21
23
  if (typeof textElement === "string") {
22
24
  textElement = (
23
- <OverflowText style={modifiers.styleWidth}>
24
- {textElement.trim() !== "" ? textElement : `Create option '${query}'`}
25
- </OverflowText>
26
- )
25
+ <OverflowText>{textElement.trim() !== "" ? textElement : `Create option '${query}'`}</OverflowText>
26
+ );
27
27
  }
28
28
  return (
29
- <MenuItem
30
- icon={iconName}
31
- active={modifiers.active}
32
- key={query}
33
- onClick={handleClick}
34
- text={textElement}
35
- />
29
+ <MenuItem icon={iconName} active={modifiers.active} key={query} onClick={handleClick} text={textElement} />
36
30
  );
37
31
  };
38
32
  };
@@ -1,14 +1,13 @@
1
1
  export interface IRenderModifiers {
2
- active: boolean
3
- disabled?: boolean
2
+ active: boolean;
3
+ disabled?: boolean;
4
4
  // The width styles that should be given to the rendered option items
5
- styleWidth: IElementWidth
6
- highlightingEnabled: boolean
5
+ styleWidth?: IElementWidth;
6
+ highlightingEnabled: boolean;
7
7
  }
8
8
 
9
9
  /** Style object to be used in menu option items. */
10
10
  export interface IElementWidth {
11
11
  minWidth: string;
12
- //width: string
13
- maxWidth: string
12
+ maxWidth: string;
14
13
  }
@@ -4,17 +4,15 @@ import {
4
4
  Breadcrumb as BlueprintBreadcrumbItem,
5
5
  BreadcrumbProps as BlueprintBreadcrumbItemProps,
6
6
  } from "@blueprintjs/core";
7
- import { CLASSPREFIX as eccgui } from "../../configuration/constants";
7
+
8
8
  import { openInNewTab } from "../../common/utils/openInNewTab";
9
+ import { CLASSPREFIX as eccgui } from "../../configuration/constants";
9
10
 
10
11
  // FIXME: enforce href and remove onClick later
11
12
  export type BreadcrumbItemProps = Omit<
12
13
  BlueprintBreadcrumbItemProps,
13
14
  // we remove some properties that are currently not necessary, required usage should be discussed
14
- "icon" |
15
- "iconTitle" |
16
- "intent" |
17
- "target"
15
+ "icon" | "iconTitle" | "intent" | "target"
18
16
  >;
19
17
 
20
18
  /**
@@ -28,7 +26,6 @@ export const BreadcrumbItem = ({
28
26
  //itemDivider='',
29
27
  ...otherBlueprintBreadcrumbProps
30
28
  }: BreadcrumbItemProps) => {
31
-
32
29
  /*
33
30
  FIXME: adding `data-divider` does not work this way because BlueprintJS
34
31
  breadcrumb component does not support (and forward) it on HTML element
@@ -37,19 +34,23 @@ export const BreadcrumbItem = ({
37
34
  with slash char.
38
35
  */
39
36
 
40
- const allowActions = !otherBlueprintBreadcrumbProps.current && !otherBlueprintBreadcrumbProps.disabled;
41
- const actions = allowActions ? {
42
- href,
43
- onClick: (e:React.MouseEvent<HTMLAnchorElement>) => openInNewTab(e, onClick, href),
44
- } : {};
37
+ const actionIsSet = !!onClick || !!href;
38
+ const allowActions =
39
+ !otherBlueprintBreadcrumbProps.current && !otherBlueprintBreadcrumbProps.disabled && actionIsSet;
40
+ const actions = allowActions
41
+ ? {
42
+ href,
43
+ onClick: (e: React.MouseEvent<HTMLAnchorElement>) => openInNewTab(e, onClick, href),
44
+ }
45
+ : {};
45
46
  return (
46
- <BlueprintBreadcrumbItem
47
- {...otherBlueprintBreadcrumbProps}
48
- {...actions}
49
- className={`${eccgui}-breadcrumb__item ` + className}
50
- /* data-divider={itemDivider ? itemDivider : ''} */
51
- />
47
+ <BlueprintBreadcrumbItem
48
+ {...otherBlueprintBreadcrumbProps}
49
+ {...actions}
50
+ className={`${eccgui}-breadcrumb__item ` + className}
51
+ /* data-divider={itemDivider ? itemDivider : ''} */
52
+ />
52
53
  );
53
- }
54
+ };
54
55
 
55
56
  export default BreadcrumbItem;