@eccenca/gui-elements 24.1.0-rc.6 → 24.2.0-featuresupportprojectvariableautocompletioncmem5572.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.
- package/CHANGELOG.md +78 -18
- package/README.md +10 -7
- package/dist/cjs/cmem/markdown/Markdown.js +13 -11
- package/dist/cjs/cmem/markdown/Markdown.js.map +1 -1
- package/dist/cjs/cmem/markdown/highlightSearchWords.js +6 -1
- package/dist/cjs/cmem/markdown/highlightSearchWords.js.map +1 -1
- package/dist/cjs/common/Intent/index.js +4 -11
- package/dist/cjs/common/Intent/index.js.map +1 -1
- package/dist/cjs/components/AutoSuggestion/AutoSuggestion.js +37 -26
- package/dist/cjs/components/AutoSuggestion/AutoSuggestion.js.map +1 -1
- package/dist/cjs/components/AutoSuggestion/ExtendedCodeEditor.js +2 -2
- package/dist/cjs/components/AutoSuggestion/ExtendedCodeEditor.js.map +1 -1
- package/dist/cjs/components/Button/Button.js +2 -2
- package/dist/cjs/components/Button/Button.js.map +1 -1
- package/dist/cjs/components/ContextOverlay/ContextMenu.js +3 -2
- package/dist/cjs/components/ContextOverlay/ContextMenu.js.map +1 -1
- package/dist/cjs/components/ContextOverlay/ContextOverlay.js +46 -2
- package/dist/cjs/components/ContextOverlay/ContextOverlay.js.map +1 -1
- package/dist/cjs/components/Form/FieldItem.js +3 -2
- package/dist/cjs/components/Form/FieldItem.js.map +1 -1
- package/dist/cjs/components/Form/FieldSet.js +3 -2
- package/dist/cjs/components/Form/FieldSet.js.map +1 -1
- package/dist/cjs/components/Icon/canonicalIconNames.js +1 -0
- package/dist/cjs/components/Icon/canonicalIconNames.js.map +1 -1
- package/dist/cjs/components/MultiSelect/MultiSelect.js +18 -14
- package/dist/cjs/components/MultiSelect/MultiSelect.js.map +1 -1
- package/dist/cjs/components/Notification/Notification.js +7 -4
- package/dist/cjs/components/Notification/Notification.js.map +1 -1
- package/dist/cjs/components/OverviewItem/OverviewItemActions.js +9 -2
- package/dist/cjs/components/OverviewItem/OverviewItemActions.js.map +1 -1
- package/dist/cjs/components/Spinner/Spinner.js +7 -5
- package/dist/cjs/components/Spinner/Spinner.js.map +1 -1
- package/dist/cjs/components/Tooltip/Tooltip.js +75 -7
- package/dist/cjs/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/cjs/extensions/react-flow/nodes/NodeContent.js +17 -13
- package/dist/cjs/extensions/react-flow/nodes/NodeContent.js.map +1 -1
- package/dist/esm/cmem/markdown/Markdown.js +13 -11
- package/dist/esm/cmem/markdown/Markdown.js.map +1 -1
- package/dist/esm/cmem/markdown/highlightSearchWords.js +6 -1
- package/dist/esm/cmem/markdown/highlightSearchWords.js.map +1 -1
- package/dist/esm/common/Intent/index.js +14 -10
- package/dist/esm/common/Intent/index.js.map +1 -1
- package/dist/esm/components/AutoSuggestion/AutoSuggestion.js +42 -33
- package/dist/esm/components/AutoSuggestion/AutoSuggestion.js.map +1 -1
- package/dist/esm/components/AutoSuggestion/ExtendedCodeEditor.js +2 -2
- package/dist/esm/components/AutoSuggestion/ExtendedCodeEditor.js.map +1 -1
- package/dist/esm/components/Button/Button.js +2 -2
- package/dist/esm/components/Button/Button.js.map +1 -1
- package/dist/esm/components/ContextOverlay/ContextMenu.js +3 -2
- package/dist/esm/components/ContextOverlay/ContextMenu.js.map +1 -1
- package/dist/esm/components/ContextOverlay/ContextOverlay.js +63 -3
- package/dist/esm/components/ContextOverlay/ContextOverlay.js.map +1 -1
- package/dist/esm/components/Form/FieldItem.js +3 -2
- package/dist/esm/components/Form/FieldItem.js.map +1 -1
- package/dist/esm/components/Form/FieldSet.js +3 -2
- package/dist/esm/components/Form/FieldSet.js.map +1 -1
- package/dist/esm/components/Icon/canonicalIconNames.js +1 -0
- package/dist/esm/components/Icon/canonicalIconNames.js.map +1 -1
- package/dist/esm/components/MultiSelect/MultiSelect.js +18 -14
- package/dist/esm/components/MultiSelect/MultiSelect.js.map +1 -1
- package/dist/esm/components/Notification/Notification.js +7 -4
- package/dist/esm/components/Notification/Notification.js.map +1 -1
- package/dist/esm/components/OverviewItem/OverviewItemActions.js +25 -2
- package/dist/esm/components/OverviewItem/OverviewItemActions.js.map +1 -1
- package/dist/esm/components/Spinner/Spinner.js +9 -5
- package/dist/esm/components/Spinner/Spinner.js.map +1 -1
- package/dist/esm/components/Tooltip/Tooltip.js +92 -8
- package/dist/esm/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/esm/extensions/react-flow/nodes/NodeContent.js +17 -13
- package/dist/esm/extensions/react-flow/nodes/NodeContent.js.map +1 -1
- package/dist/types/cmem/markdown/Markdown.d.ts +8 -1
- package/dist/types/common/Intent/index.d.ts +10 -1
- package/dist/types/components/AutoSuggestion/AutoSuggestion.d.ts +5 -1
- package/dist/types/components/AutoSuggestion/ExtendedCodeEditor.d.ts +5 -1
- package/dist/types/components/Button/Button.d.ts +5 -1
- package/dist/types/components/ContextOverlay/ContextMenu.d.ts +9 -2
- package/dist/types/components/ContextOverlay/ContextOverlay.d.ts +6 -1
- package/dist/types/components/Form/FieldItem.d.ts +10 -1
- package/dist/types/components/Form/FieldSet.d.ts +10 -1
- package/dist/types/components/Icon/canonicalIconNames.d.ts +1 -0
- package/dist/types/components/MultiSelect/MultiSelect.d.ts +12 -4
- package/dist/types/components/Notification/Notification.d.ts +10 -1
- package/dist/types/components/OverviewItem/OverviewItemActions.d.ts +13 -1
- package/dist/types/components/ProgressBar/ProgressBar.d.ts +2 -2
- package/dist/types/components/Spinner/Spinner.d.ts +8 -3
- package/dist/types/components/Structure/TitleSubsection.d.ts +7 -0
- package/dist/types/components/Table/TableContainer.d.ts +2 -2
- package/dist/types/components/Table/TableExpandRow.d.ts +1 -1
- package/dist/types/components/Table/index.d.ts +1 -0
- package/dist/types/components/Tabs/Tab.d.ts +14 -0
- package/dist/types/components/Tooltip/Tooltip.d.ts +9 -1
- package/package.json +47 -48
- package/src/cmem/markdown/Markdown.tsx +25 -14
- package/src/cmem/markdown/highlightSearchWords.test.ts +8 -2
- package/src/cmem/markdown/highlightSearchWords.ts +6 -1
- package/src/common/Intent/index.ts +6 -6
- package/src/components/AutoSuggestion/AutoSuggestion.tsx +50 -32
- package/src/components/AutoSuggestion/ExtendedCodeEditor.tsx +8 -0
- package/src/components/Button/Button.stories.tsx +10 -6
- package/src/components/Button/Button.tsx +7 -2
- package/src/components/ContextOverlay/ContextMenu.stories.tsx +1 -1
- package/src/components/ContextOverlay/ContextMenu.tsx +26 -13
- package/src/components/ContextOverlay/ContextOverlay.tsx +83 -5
- package/src/components/Form/FieldItem.tsx +14 -3
- package/src/components/Form/FieldSet.tsx +13 -2
- package/src/components/Form/Stories/FieldItem.stories.tsx +4 -0
- package/src/components/Form/Stories/FieldSet.stories.tsx +4 -0
- package/src/components/Icon/canonicalIconNames.tsx +1 -0
- package/src/components/MultiSelect/MultiSelect.tsx +27 -15
- package/src/components/MultiSuggestField/MultiSuggestField.stories.tsx +6 -0
- package/src/components/Notification/Notification.stories.tsx +4 -0
- package/src/components/Notification/Notification.tsx +17 -4
- package/src/components/OverviewItem/OverviewItemActions.tsx +24 -1
- package/src/components/OverviewItem/stories/OverviewItemList.stories.tsx +2 -7
- package/src/components/OverviewItem/stories/OverviewItemListPerformance.tsx +174 -0
- package/src/components/OverviewItem/stories/OverviewItemPerformance.stories.tsx +19 -0
- package/src/components/Spinner/Spinner.tsx +13 -5
- package/src/components/Spinner/Stories/spinner.stories.tsx +6 -1
- package/src/components/Table/TableContainer.tsx +2 -2
- package/src/components/Table/TableExpandRow.tsx +1 -1
- package/src/components/Table/index.tsx +1 -0
- package/src/components/Tooltip/Tooltip.stories.tsx +3 -2
- package/src/components/Tooltip/Tooltip.tsx +121 -10
- package/src/extensions/react-flow/nodes/NodeContent.tsx +18 -14
- package/src/extensions/react-flow/nodes/_nodes.scss +1 -1
- package/src/extensions/react-flow/nodes/stories/NodeContent.stories.tsx +45 -9
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
|
-
import { ClassNames as IntentClassNames } from "../../common/Intent";
|
|
3
|
+
import { ClassNames as IntentClassNames, IntentTypes } from "../../common/Intent";
|
|
4
4
|
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
|
|
5
5
|
import { TestableComponent } from "../interfaces";
|
|
6
6
|
import Label, { LabelProps } from "../Label/Label";
|
|
@@ -18,23 +18,31 @@ export interface FieldItemProps extends React.HTMLAttributes<HTMLDivElement>, Te
|
|
|
18
18
|
/**
|
|
19
19
|
* Set primary state.
|
|
20
20
|
* This is not routed through automatically.
|
|
21
|
+
* @deprecated (v25) use `intent="primary"` instead.
|
|
21
22
|
*/
|
|
22
23
|
hasStatePrimary?: boolean;
|
|
23
24
|
/**
|
|
24
25
|
* Set success state.
|
|
25
26
|
* This is not routed through automatically.
|
|
27
|
+
* @deprecated (v25) use `intent="success"` instead.
|
|
26
28
|
*/
|
|
27
29
|
hasStateSuccess?: boolean;
|
|
28
30
|
/**
|
|
29
31
|
* Set warning state.
|
|
30
32
|
* This is not routed through automatically.
|
|
33
|
+
* @deprecated (v25) use `intent="warning"` instead.
|
|
31
34
|
*/
|
|
32
35
|
hasStateWarning?: boolean;
|
|
33
36
|
/**
|
|
34
37
|
* Set danger state.
|
|
35
38
|
* This is not routed through automatically.
|
|
39
|
+
* @deprecated (v25) use `intent="danger"` instead.
|
|
36
40
|
*/
|
|
37
41
|
hasStateDanger?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Intent state of the field item.
|
|
44
|
+
*/
|
|
45
|
+
intent?: IntentTypes;
|
|
38
46
|
/**
|
|
39
47
|
* Is disabled.
|
|
40
48
|
* The included inout element nedd to set disabled directly itself.
|
|
@@ -71,6 +79,7 @@ export const FieldItem = ({
|
|
|
71
79
|
labelProps,
|
|
72
80
|
helperText,
|
|
73
81
|
messageText,
|
|
82
|
+
intent,
|
|
74
83
|
...otherProps
|
|
75
84
|
}: FieldItemProps) => {
|
|
76
85
|
let classIntent = "";
|
|
@@ -91,6 +100,8 @@ export const FieldItem = ({
|
|
|
91
100
|
break;
|
|
92
101
|
}
|
|
93
102
|
|
|
103
|
+
const intentClass = intent ? " " + IntentClassNames[intent.toUpperCase()] : "";
|
|
104
|
+
|
|
94
105
|
const label = <Label {...labelProps} disabled={disabled} />;
|
|
95
106
|
|
|
96
107
|
const userhelp =
|
|
@@ -106,9 +117,9 @@ export const FieldItem = ({
|
|
|
106
117
|
const notification =
|
|
107
118
|
messageText &&
|
|
108
119
|
(typeof messageText === "string" ? (
|
|
109
|
-
<p className={`${eccgui}-fielditem__message` + classIntent}>{messageText}</p>
|
|
120
|
+
<p className={`${eccgui}-fielditem__message` + (intentClass || classIntent)}>{messageText}</p>
|
|
110
121
|
) : (
|
|
111
|
-
<div className={`${eccgui}-fielditem__message` + classIntent}>{messageText}</div>
|
|
122
|
+
<div className={`${eccgui}-fielditem__message` + (intentClass || classIntent)}>{messageText}</div>
|
|
112
123
|
));
|
|
113
124
|
|
|
114
125
|
return (
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
|
-
import { ClassNames as IntentClassNames } from "../../common/Intent";
|
|
3
|
+
import { ClassNames as IntentClassNames, IntentTypes } from "../../common/Intent";
|
|
4
4
|
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
|
|
5
5
|
|
|
6
6
|
export interface FieldSetProps extends Omit<React.FieldsetHTMLAttributes<HTMLFieldSetElement>, "title"> {
|
|
@@ -11,20 +11,28 @@ export interface FieldSetProps extends Omit<React.FieldsetHTMLAttributes<HTMLFie
|
|
|
11
11
|
boxed?: boolean;
|
|
12
12
|
/**
|
|
13
13
|
* The fieldsetsection is displayed with primary color scheme.
|
|
14
|
+
* @deprecated (v25) use `intent="primary"` instead.
|
|
14
15
|
*/
|
|
15
16
|
hasStatePrimary?: boolean;
|
|
16
17
|
/**
|
|
17
18
|
* The fieldset section is displayed with success (some type of green) color scheme.
|
|
19
|
+
* @deprecated (v25) use `intent="success"` instead.
|
|
18
20
|
*/
|
|
19
21
|
hasStateSuccess?: boolean;
|
|
20
22
|
/**
|
|
21
23
|
* The fieldset section is displayed with warning (some type of orange) color scheme.
|
|
24
|
+
* @deprecated (v25) use `intent="warning"` instead.
|
|
22
25
|
*/
|
|
23
26
|
hasStateWarning?: boolean;
|
|
24
27
|
/**
|
|
25
28
|
* The fieldsetsection is displayed with danger (some type of red) color scheme.
|
|
29
|
+
* @deprecated (v25) use `intent="danger"` instead.
|
|
26
30
|
*/
|
|
27
31
|
hasStateDanger?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Intent state of the field item.
|
|
34
|
+
*/
|
|
35
|
+
intent?: IntentTypes;
|
|
28
36
|
/**
|
|
29
37
|
* Optional helper text. If given then it is displayed after the title.
|
|
30
38
|
*/
|
|
@@ -52,6 +60,7 @@ export const FieldSet = ({
|
|
|
52
60
|
hasStateSuccess = false,
|
|
53
61
|
hasStateWarning = false,
|
|
54
62
|
hasStateDanger = false,
|
|
63
|
+
intent,
|
|
55
64
|
helperText,
|
|
56
65
|
messageText,
|
|
57
66
|
title,
|
|
@@ -75,6 +84,8 @@ export const FieldSet = ({
|
|
|
75
84
|
break;
|
|
76
85
|
}
|
|
77
86
|
|
|
87
|
+
const intentClass = intent ? " " + IntentClassNames[intent.toUpperCase()] : "";
|
|
88
|
+
|
|
78
89
|
const userhelp =
|
|
79
90
|
helperText &&
|
|
80
91
|
(typeof helperText === "string" ? (
|
|
@@ -98,7 +109,7 @@ export const FieldSet = ({
|
|
|
98
109
|
className={
|
|
99
110
|
`${eccgui}-fieldset` +
|
|
100
111
|
(className ? " " + className : "") +
|
|
101
|
-
classIntent +
|
|
112
|
+
(intentClass || classIntent) +
|
|
102
113
|
(boxed ? ` ${eccgui}-fieldset--boxed` : "")
|
|
103
114
|
}
|
|
104
115
|
{...otherProps}
|
|
@@ -2,6 +2,7 @@ import React from "react";
|
|
|
2
2
|
import { LoremIpsum } from "react-lorem-ipsum";
|
|
3
3
|
import { Meta, StoryFn } from "@storybook/react";
|
|
4
4
|
|
|
5
|
+
import { helpersArgTypes } from "../../../../.storybook/helpers";
|
|
5
6
|
import { FieldItem, TextField } from "../../../../index";
|
|
6
7
|
|
|
7
8
|
export default {
|
|
@@ -11,6 +12,9 @@ export default {
|
|
|
11
12
|
children: {
|
|
12
13
|
control: "none",
|
|
13
14
|
},
|
|
15
|
+
intent: {
|
|
16
|
+
...helpersArgTypes.exampleIntent,
|
|
17
|
+
},
|
|
14
18
|
},
|
|
15
19
|
} as Meta<typeof FieldItem>;
|
|
16
20
|
|
|
@@ -2,6 +2,7 @@ import React from "react";
|
|
|
2
2
|
import { LoremIpsum } from "react-lorem-ipsum";
|
|
3
3
|
import { Meta, StoryFn } from "@storybook/react";
|
|
4
4
|
|
|
5
|
+
import { helpersArgTypes } from "../../../../.storybook/helpers";
|
|
5
6
|
import { FieldItem, FieldItemRow, FieldSet, TitleSubsection } from "../../../../index";
|
|
6
7
|
|
|
7
8
|
import { Default as SimpleFieldItemExample } from "./FieldItem.stories";
|
|
@@ -14,6 +15,9 @@ export default {
|
|
|
14
15
|
children: {
|
|
15
16
|
control: "none",
|
|
16
17
|
},
|
|
18
|
+
intent: {
|
|
19
|
+
...helpersArgTypes.exampleIntent,
|
|
20
|
+
},
|
|
17
21
|
},
|
|
18
22
|
} as Meta<typeof FieldSet>;
|
|
19
23
|
|
|
@@ -129,6 +129,7 @@ const canonicalIcons = {
|
|
|
129
129
|
"operation-filteredit": icons.FilterEdit,
|
|
130
130
|
"operation-filterremove": icons.FilterRemove,
|
|
131
131
|
"operation-filter": icons.Filter,
|
|
132
|
+
"operation-focus": icons.CenterSquare,
|
|
132
133
|
"operation-format-codeblock": icons.CodeBlock,
|
|
133
134
|
"operation-format-text-code": icons.Code,
|
|
134
135
|
"operation-format-text-bold": icons.TextBold,
|
|
@@ -78,20 +78,28 @@ interface MultiSelectCommonProps<T>
|
|
|
78
78
|
* Items that were newly created and not taken from the list will be post-fixed with this string.
|
|
79
79
|
*/
|
|
80
80
|
newItemPostfix?: string;
|
|
81
|
+
/**
|
|
82
|
+
* Intent state of the multi select.
|
|
83
|
+
*/
|
|
84
|
+
intent?: BlueprintIntent;
|
|
81
85
|
/**
|
|
82
86
|
* The input element is displayed with primary color scheme.
|
|
87
|
+
* @deprecated (v25) use `intent="primary"` instead.
|
|
83
88
|
*/
|
|
84
89
|
hasStatePrimary?: boolean;
|
|
85
90
|
/**
|
|
86
91
|
* The input element is displayed with success (some type of green) color scheme.
|
|
92
|
+
* @deprecated (v25) use `intent="success"` instead.
|
|
87
93
|
*/
|
|
88
94
|
hasStateSuccess?: boolean;
|
|
89
95
|
/**
|
|
90
|
-
* The input element is displayed with
|
|
96
|
+
* The input element is displayed with warning (some type of orange) color scheme.
|
|
97
|
+
* @deprecated (v25) use `intent="warning"` instead.
|
|
91
98
|
*/
|
|
92
99
|
hasStateWarning?: boolean;
|
|
93
100
|
/**
|
|
94
|
-
* The input element is displayed with
|
|
101
|
+
* The input element is displayed with danger (some type of red) color scheme.
|
|
102
|
+
* @deprecated (v25) use `intent="danger"` instead.
|
|
95
103
|
*/
|
|
96
104
|
hasStateDanger?: boolean;
|
|
97
105
|
/**
|
|
@@ -179,6 +187,7 @@ function MultiSelect<T>({
|
|
|
179
187
|
wrapperProps,
|
|
180
188
|
searchPredicate,
|
|
181
189
|
limitHeightOpened,
|
|
190
|
+
intent,
|
|
182
191
|
...otherMultiSelectProps
|
|
183
192
|
}: MultiSelectProps<T>) {
|
|
184
193
|
// Options created by a user
|
|
@@ -203,19 +212,19 @@ function MultiSelect<T>({
|
|
|
203
212
|
timeoutId?: number;
|
|
204
213
|
}>({});
|
|
205
214
|
|
|
206
|
-
let
|
|
215
|
+
let stateIntent;
|
|
207
216
|
switch (true) {
|
|
208
217
|
case hasStatePrimary:
|
|
209
|
-
|
|
218
|
+
stateIntent = BlueprintIntent.PRIMARY;
|
|
210
219
|
break;
|
|
211
220
|
case hasStateSuccess:
|
|
212
|
-
|
|
221
|
+
stateIntent = BlueprintIntent.SUCCESS;
|
|
213
222
|
break;
|
|
214
223
|
case hasStateWarning:
|
|
215
|
-
|
|
224
|
+
stateIntent = BlueprintIntent.WARNING;
|
|
216
225
|
break;
|
|
217
226
|
case hasStateDanger:
|
|
218
|
-
|
|
227
|
+
stateIntent = BlueprintIntent.DANGER;
|
|
219
228
|
break;
|
|
220
229
|
default:
|
|
221
230
|
break;
|
|
@@ -230,12 +239,11 @@ function MultiSelect<T>({
|
|
|
230
239
|
}, [items.map((item) => itemId(item)).join("|")]);
|
|
231
240
|
|
|
232
241
|
React.useEffect(() => {
|
|
233
|
-
onSelection
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
});
|
|
242
|
+
onSelection?.({
|
|
243
|
+
newlySelected: selectedItems.slice(-1)[0],
|
|
244
|
+
createdItems: createdItems.current,
|
|
245
|
+
selectedItems,
|
|
246
|
+
});
|
|
239
247
|
}, [
|
|
240
248
|
onSelection,
|
|
241
249
|
selectedItems.map((item) => itemId(item)).join("|"),
|
|
@@ -430,7 +438,11 @@ function MultiSelect<T>({
|
|
|
430
438
|
const handleOnKeyDown = (event: React.KeyboardEvent<HTMLElement>) => {
|
|
431
439
|
if (event.key === "Tab" && !!requestState.current.query) {
|
|
432
440
|
event.preventDefault();
|
|
433
|
-
|
|
441
|
+
if (focusedItem) {
|
|
442
|
+
onItemSelect(focusedItem);
|
|
443
|
+
} else {
|
|
444
|
+
onItemSelect(createNewItem(requestState.current.query));
|
|
445
|
+
}
|
|
434
446
|
requestState.current.query = "";
|
|
435
447
|
setTimeout(() => inputRef.current?.focus());
|
|
436
448
|
}
|
|
@@ -511,7 +523,7 @@ function MultiSelect<T>({
|
|
|
511
523
|
className: `${eccgui}-multiselect` + (className ? ` ${className}` : ""),
|
|
512
524
|
fill: fullWidth,
|
|
513
525
|
inputRef: inputRef,
|
|
514
|
-
intent,
|
|
526
|
+
intent: intent || stateIntent,
|
|
515
527
|
addOnBlur: true,
|
|
516
528
|
onKeyDown: handleOnKeyDown,
|
|
517
529
|
onKeyUp: handleOnKeyUp,
|
|
@@ -4,6 +4,8 @@ import { OverlaysProvider } from "@blueprintjs/core";
|
|
|
4
4
|
import { Meta, StoryFn } from "@storybook/react";
|
|
5
5
|
import { fn } from "@storybook/test";
|
|
6
6
|
|
|
7
|
+
import { helpersArgTypes } from "../../../.storybook/helpers";
|
|
8
|
+
|
|
7
9
|
import { MultiSuggestField, MultiSuggestFieldSelectionProps, SimpleDialog } from "./../../../index";
|
|
8
10
|
|
|
9
11
|
const testLabels = loremIpsum({
|
|
@@ -29,6 +31,10 @@ export default {
|
|
|
29
31
|
items: {
|
|
30
32
|
control: "none",
|
|
31
33
|
},
|
|
34
|
+
intent: {
|
|
35
|
+
...helpersArgTypes.exampleIntent,
|
|
36
|
+
options: ["UNDEFINED", "primary", "success", "warning", "danger"],
|
|
37
|
+
},
|
|
32
38
|
},
|
|
33
39
|
args: {
|
|
34
40
|
onSelection: fn(),
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
ToastProps as BlueprintToastProps,
|
|
6
6
|
} from "@blueprintjs/core";
|
|
7
7
|
|
|
8
|
-
import { ClassNames as IntentClassNames } from "../../common/Intent";
|
|
8
|
+
import { ClassNames as IntentClassNames, IntentTypes } from "../../common/Intent";
|
|
9
9
|
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
|
|
10
10
|
import { TestableComponent } from "../interfaces";
|
|
11
11
|
|
|
@@ -25,23 +25,31 @@ export interface NotificationProps
|
|
|
25
25
|
* Notification message that can be used as alternative to children elements.
|
|
26
26
|
*/
|
|
27
27
|
message?: JSX.Element | string;
|
|
28
|
+
/**
|
|
29
|
+
* Intent state of the notification.
|
|
30
|
+
*/
|
|
31
|
+
intent?: Extract<IntentTypes, "neutral" | "success" | "warning" | "danger" | "info">;
|
|
28
32
|
/**
|
|
29
33
|
* Notification has a neutral color scheme.
|
|
34
|
+
* @deprecated (v25) use `intent="neutral"` instead.
|
|
30
35
|
*/
|
|
31
36
|
neutral?: boolean;
|
|
32
37
|
/**
|
|
33
38
|
* Notification is a success info.
|
|
34
39
|
* This defines the colorization and the icon symbol.
|
|
40
|
+
* @deprecated (v25) use `intent="success"` instead.
|
|
35
41
|
*/
|
|
36
42
|
success?: boolean;
|
|
37
43
|
/**
|
|
38
44
|
* Notification is a warning alert.
|
|
39
45
|
* This defines the colorization and the icon symbol.
|
|
46
|
+
* @deprecated (v25) use `intent="warning"` instead.
|
|
40
47
|
*/
|
|
41
48
|
warning?: boolean;
|
|
42
49
|
/**
|
|
43
50
|
* Notification is a danger alert.
|
|
44
51
|
* This defines the colorization and the icon symbol.
|
|
52
|
+
* @deprecated (v25) use `intent="danger"` instead.
|
|
45
53
|
*/
|
|
46
54
|
danger?: boolean;
|
|
47
55
|
/**
|
|
@@ -81,6 +89,7 @@ export const Notification = ({
|
|
|
81
89
|
wrapperProps,
|
|
82
90
|
"data-test-id": dataTestId,
|
|
83
91
|
"data-testid": dataTestid,
|
|
92
|
+
intent,
|
|
84
93
|
...otherProps
|
|
85
94
|
}: NotificationProps) => {
|
|
86
95
|
let intentLevel: string = IntentClassNames.INFO;
|
|
@@ -103,9 +112,13 @@ export const Notification = ({
|
|
|
103
112
|
break;
|
|
104
113
|
}
|
|
105
114
|
|
|
115
|
+
const intents: Array<NotificationProps["intent"]> = ["info", "success", "warning", "danger"];
|
|
116
|
+
const intentClass = intent ? " " + IntentClassNames[intent.toUpperCase()] : "";
|
|
117
|
+
const intentIconSymbol = intents.includes(intent) ? `state-${intent}` : iconSymbol;
|
|
118
|
+
|
|
106
119
|
let notificationIcon = icon !== false ? icon : undefined;
|
|
107
|
-
if (icon !== false && !notificationIcon && !!
|
|
108
|
-
notificationIcon = <Icon name={
|
|
120
|
+
if (icon !== false && !notificationIcon && !!intentIconSymbol) {
|
|
121
|
+
notificationIcon = <Icon name={intentIconSymbol as ValidIconName} />;
|
|
109
122
|
}
|
|
110
123
|
|
|
111
124
|
const content = actions ? (
|
|
@@ -123,7 +136,7 @@ export const Notification = ({
|
|
|
123
136
|
<BlueprintToast
|
|
124
137
|
className={
|
|
125
138
|
`${eccgui}-notification ` +
|
|
126
|
-
intentLevel +
|
|
139
|
+
(intentClass || intentLevel) +
|
|
127
140
|
(className ? ` ${className}` : "") +
|
|
128
141
|
(flexWidth ? ` ${eccgui}-notification--flexwidth` : "") +
|
|
129
142
|
(otherProps.onDismiss ? "" : ` ${eccgui}-notification--static`)
|
|
@@ -7,6 +7,18 @@ export interface OverviewItemActionsProps extends React.HTMLAttributes<HTMLDivEl
|
|
|
7
7
|
* Display it only when the parent `OverviewItem` is hovered or focused.
|
|
8
8
|
*/
|
|
9
9
|
hiddenInteractions?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Delay the rendering of the children by a time in milliseconds.
|
|
12
|
+
* Could be used to prevent browser freezes for the initial `OverviewItem` rendering.
|
|
13
|
+
* In general, it is better to fix the cause, i.e. action elements that are expensive to initialize/render should be
|
|
14
|
+
* optimized or replaced etc. This workaround only prevents the browser from getting blocked completely and does NOT
|
|
15
|
+
* solve the actual performance issue.
|
|
16
|
+
*/
|
|
17
|
+
delayDisplayChildren?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Display element while the rendering of the actual children is delayed.
|
|
20
|
+
*/
|
|
21
|
+
delaySkeleton?: JSX.Element;
|
|
10
22
|
}
|
|
11
23
|
|
|
12
24
|
/**
|
|
@@ -17,8 +29,19 @@ export const OverviewItemActions = ({
|
|
|
17
29
|
children,
|
|
18
30
|
className = "",
|
|
19
31
|
hiddenInteractions = false,
|
|
32
|
+
delayDisplayChildren = 0,
|
|
33
|
+
delaySkeleton = <></>,
|
|
20
34
|
...restProps
|
|
21
35
|
}: OverviewItemActionsProps) => {
|
|
36
|
+
const [showActions, setShowActions] = React.useState(!(delayDisplayChildren > 0));
|
|
37
|
+
|
|
38
|
+
React.useEffect(() => {
|
|
39
|
+
// Delay rendering of item actions when they are hidden anyways, because rendering interaction elements like context menus currently has a large performance impact.
|
|
40
|
+
if (!showActions && delayDisplayChildren > 0) {
|
|
41
|
+
setTimeout(() => setShowActions(true), delayDisplayChildren);
|
|
42
|
+
}
|
|
43
|
+
}, []);
|
|
44
|
+
|
|
22
45
|
return (
|
|
23
46
|
<div
|
|
24
47
|
{...restProps}
|
|
@@ -28,7 +51,7 @@ export const OverviewItemActions = ({
|
|
|
28
51
|
(className ? ` ${className}` : "")
|
|
29
52
|
}
|
|
30
53
|
>
|
|
31
|
-
{children}
|
|
54
|
+
{showActions ? children : delaySkeleton}
|
|
32
55
|
</div>
|
|
33
56
|
);
|
|
34
57
|
};
|
|
@@ -12,7 +12,7 @@ export default {
|
|
|
12
12
|
},
|
|
13
13
|
argTypes: {
|
|
14
14
|
children: {
|
|
15
|
-
control:
|
|
15
|
+
control: false,
|
|
16
16
|
description: "Should contain only `OverviewItem` elements, maybe wrapped inside cards.",
|
|
17
17
|
},
|
|
18
18
|
},
|
|
@@ -26,10 +26,5 @@ ItemList.args = {
|
|
|
26
26
|
hasDivider: true,
|
|
27
27
|
densityHigh: false,
|
|
28
28
|
columns: 1,
|
|
29
|
-
children:
|
|
30
|
-
<OverviewItem {...ItemExample.args} />,
|
|
31
|
-
<OverviewItem {...ItemExample.args} />,
|
|
32
|
-
<OverviewItem {...ItemExample.args} />,
|
|
33
|
-
<OverviewItem {...ItemExample.args} />,
|
|
34
|
-
],
|
|
29
|
+
children: Array(4).fill(<OverviewItem {...ItemExample.args} />),
|
|
35
30
|
};
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { loremIpsum } from "react-lorem-ipsum";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
ApplicationContainer,
|
|
6
|
+
Button,
|
|
7
|
+
ContextMenu,
|
|
8
|
+
Depiction,
|
|
9
|
+
Icon,
|
|
10
|
+
IconButton,
|
|
11
|
+
OverflowText,
|
|
12
|
+
OverviewItem,
|
|
13
|
+
OverviewItemActions,
|
|
14
|
+
OverviewItemDescription,
|
|
15
|
+
OverviewItemLine,
|
|
16
|
+
OverviewItemList,
|
|
17
|
+
Spinner,
|
|
18
|
+
Tooltip,
|
|
19
|
+
} from "./../../../../index";
|
|
20
|
+
import { Default as ContextMenuExample } from "./../../ContextOverlay/ContextMenu.stories";
|
|
21
|
+
import canonicalIcons, { ValidIconName } from "./../../Icon/canonicalIconNames";
|
|
22
|
+
|
|
23
|
+
interface OverviewItemListPerformanceProps {
|
|
24
|
+
/** list length */
|
|
25
|
+
length: number;
|
|
26
|
+
/** include `OverviewItem` elements in list */
|
|
27
|
+
useOverviewitem: boolean;
|
|
28
|
+
/** include depiction */
|
|
29
|
+
withDepiction: boolean;
|
|
30
|
+
/** include description */
|
|
31
|
+
withDescription: boolean;
|
|
32
|
+
/** include icon button in hidden actions */
|
|
33
|
+
withIconButtonInHiddenActions: boolean;
|
|
34
|
+
/** include button in actions */
|
|
35
|
+
withButtonInActions: boolean;
|
|
36
|
+
/** inlcude context menu in actions */
|
|
37
|
+
withContextMenuInActions: boolean;
|
|
38
|
+
/** include tooltips on all elments that can have one */
|
|
39
|
+
withTooltips: boolean;
|
|
40
|
+
/** delay rendering of action items */
|
|
41
|
+
delayActions: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const createTextArray = (items: number, length: number) => {
|
|
45
|
+
return loremIpsum({
|
|
46
|
+
p: 1,
|
|
47
|
+
avgWordsPerSentence: length,
|
|
48
|
+
avgSentencesPerParagraph: items,
|
|
49
|
+
startWithLoremIpsum: false,
|
|
50
|
+
random: false,
|
|
51
|
+
})[0].split(". ");
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const textShort = createTextArray(100, 3);
|
|
55
|
+
const textLong = createTextArray(100, 25);
|
|
56
|
+
|
|
57
|
+
export const OverviewItemListPerformance = ({
|
|
58
|
+
length = 500,
|
|
59
|
+
useOverviewitem = false,
|
|
60
|
+
withDepiction = false,
|
|
61
|
+
withDescription = true,
|
|
62
|
+
withButtonInActions = false,
|
|
63
|
+
withIconButtonInHiddenActions = false,
|
|
64
|
+
withTooltips = false,
|
|
65
|
+
withContextMenuInActions = false,
|
|
66
|
+
delayActions = 1,
|
|
67
|
+
}: OverviewItemListPerformanceProps) => {
|
|
68
|
+
const renderStart = new Date();
|
|
69
|
+
const containerRef = React.useRef(null);
|
|
70
|
+
const observerRef = React.useRef<MutationObserver | undefined>(undefined);
|
|
71
|
+
|
|
72
|
+
const iconNames = Object.keys(canonicalIcons);
|
|
73
|
+
|
|
74
|
+
const ItemWrapper = useOverviewitem ? OverviewItem : "div";
|
|
75
|
+
const ItemDescription = useOverviewitem ? OverviewItemDescription : "div";
|
|
76
|
+
const ItemLine = useOverviewitem ? OverviewItemLine : "div";
|
|
77
|
+
const ItemActions = useOverviewitem ? OverviewItemActions : "span";
|
|
78
|
+
|
|
79
|
+
const actionsProps = useOverviewitem
|
|
80
|
+
? { delayDisplayChildren: delayActions, delaySkeleton: <Spinner position="inline" size="tiny" /> }
|
|
81
|
+
: {};
|
|
82
|
+
const hiddenActionsProps = useOverviewitem ? { ...actionsProps, hiddenInteractions: true } : {};
|
|
83
|
+
|
|
84
|
+
React.useEffect(() => {
|
|
85
|
+
const renderEnd = new Date();
|
|
86
|
+
// eslint-disable-next-line no-console
|
|
87
|
+
console.log(
|
|
88
|
+
"OverviewItemListPerformance Rendering time (s)",
|
|
89
|
+
(renderEnd.getTime() - renderStart.getTime()) / 1000
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
if (containerRef.current) {
|
|
93
|
+
let changeCount = 0;
|
|
94
|
+
const changeReporter = () => {
|
|
95
|
+
const renderChange = new Date();
|
|
96
|
+
// eslint-disable-next-line no-console
|
|
97
|
+
console.log(
|
|
98
|
+
`Change ${++changeCount} after time (s)`,
|
|
99
|
+
(renderChange.getTime() - renderEnd.getTime()) / 1000
|
|
100
|
+
);
|
|
101
|
+
};
|
|
102
|
+
if (observerRef.current) {
|
|
103
|
+
observerRef.current.disconnect();
|
|
104
|
+
}
|
|
105
|
+
observerRef.current = new MutationObserver(changeReporter);
|
|
106
|
+
observerRef.current.observe(containerRef.current, { childList: true, subtree: true });
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<div ref={containerRef}>
|
|
112
|
+
<ApplicationContainer>
|
|
113
|
+
<OverviewItemList hasDivider hasSpacing columns={useOverviewitem ? 2 : 1}>
|
|
114
|
+
{Array(length)
|
|
115
|
+
.fill("x")
|
|
116
|
+
.map((_, id) => {
|
|
117
|
+
return (
|
|
118
|
+
<ItemWrapper key={id}>
|
|
119
|
+
{withDepiction && (
|
|
120
|
+
<Depiction
|
|
121
|
+
size="small"
|
|
122
|
+
image={<Icon name={iconNames[id % iconNames.length] as ValidIconName} />}
|
|
123
|
+
caption={withTooltips ? textShort[(id + 10) % textShort.length] : undefined}
|
|
124
|
+
captionPosition={withTooltips ? "tooltip" : "none"}
|
|
125
|
+
/>
|
|
126
|
+
)}
|
|
127
|
+
{withDescription && (
|
|
128
|
+
<ItemDescription>
|
|
129
|
+
<ItemLine large={useOverviewitem ? true : undefined}>
|
|
130
|
+
{textShort[id % textShort.length]}
|
|
131
|
+
</ItemLine>
|
|
132
|
+
<ItemLine small={useOverviewitem ? true : undefined}>
|
|
133
|
+
{withTooltips ? (
|
|
134
|
+
<Tooltip content={textLong[id % textLong.length]}>
|
|
135
|
+
<OverflowText>{textLong[id % textLong.length]}</OverflowText>
|
|
136
|
+
</Tooltip>
|
|
137
|
+
) : (
|
|
138
|
+
<OverflowText>{textLong[id % textLong.length]}</OverflowText>
|
|
139
|
+
)}
|
|
140
|
+
</ItemLine>
|
|
141
|
+
</ItemDescription>
|
|
142
|
+
)}
|
|
143
|
+
{withIconButtonInHiddenActions && (
|
|
144
|
+
<ItemActions {...hiddenActionsProps}>
|
|
145
|
+
<IconButton
|
|
146
|
+
name={iconNames[(id + 23) % iconNames.length] as ValidIconName}
|
|
147
|
+
text={textShort[(id + 27) % textShort.length]}
|
|
148
|
+
tooltipAsTitle={!withTooltips}
|
|
149
|
+
/>
|
|
150
|
+
</ItemActions>
|
|
151
|
+
)}
|
|
152
|
+
{(withButtonInActions || withContextMenuInActions) && (
|
|
153
|
+
<ItemActions {...actionsProps}>
|
|
154
|
+
{withButtonInActions && (
|
|
155
|
+
<Button onClick={() => alert("Button clicked")}>
|
|
156
|
+
{textShort[(id + 77) % textShort.length]}
|
|
157
|
+
</Button>
|
|
158
|
+
)}
|
|
159
|
+
{withContextMenuInActions && (
|
|
160
|
+
<ContextMenu
|
|
161
|
+
{...ContextMenuExample.args}
|
|
162
|
+
tooltipAsTitle={!withTooltips}
|
|
163
|
+
/>
|
|
164
|
+
)}
|
|
165
|
+
</ItemActions>
|
|
166
|
+
)}
|
|
167
|
+
</ItemWrapper>
|
|
168
|
+
);
|
|
169
|
+
})}
|
|
170
|
+
</OverviewItemList>
|
|
171
|
+
</ApplicationContainer>
|
|
172
|
+
</div>
|
|
173
|
+
);
|
|
174
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Meta, StoryFn } from "@storybook/react";
|
|
3
|
+
|
|
4
|
+
import { OverviewItemListPerformance } from "./OverviewItemListPerformance";
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
title: "Components/OverviewItem",
|
|
8
|
+
component: OverviewItemListPerformance,
|
|
9
|
+
argTypes: {},
|
|
10
|
+
} as Meta<typeof OverviewItemListPerformance>;
|
|
11
|
+
|
|
12
|
+
const Template: StoryFn<typeof OverviewItemListPerformance> = (args) => (
|
|
13
|
+
<OverviewItemListPerformance {...args}></OverviewItemListPerformance>
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
export const ListPerformance = Template.bind({});
|
|
17
|
+
ListPerformance.args = {
|
|
18
|
+
useOverviewitem: true,
|
|
19
|
+
};
|