@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.
Files changed (126) hide show
  1. package/CHANGELOG.md +78 -18
  2. package/README.md +10 -7
  3. package/dist/cjs/cmem/markdown/Markdown.js +13 -11
  4. package/dist/cjs/cmem/markdown/Markdown.js.map +1 -1
  5. package/dist/cjs/cmem/markdown/highlightSearchWords.js +6 -1
  6. package/dist/cjs/cmem/markdown/highlightSearchWords.js.map +1 -1
  7. package/dist/cjs/common/Intent/index.js +4 -11
  8. package/dist/cjs/common/Intent/index.js.map +1 -1
  9. package/dist/cjs/components/AutoSuggestion/AutoSuggestion.js +37 -26
  10. package/dist/cjs/components/AutoSuggestion/AutoSuggestion.js.map +1 -1
  11. package/dist/cjs/components/AutoSuggestion/ExtendedCodeEditor.js +2 -2
  12. package/dist/cjs/components/AutoSuggestion/ExtendedCodeEditor.js.map +1 -1
  13. package/dist/cjs/components/Button/Button.js +2 -2
  14. package/dist/cjs/components/Button/Button.js.map +1 -1
  15. package/dist/cjs/components/ContextOverlay/ContextMenu.js +3 -2
  16. package/dist/cjs/components/ContextOverlay/ContextMenu.js.map +1 -1
  17. package/dist/cjs/components/ContextOverlay/ContextOverlay.js +46 -2
  18. package/dist/cjs/components/ContextOverlay/ContextOverlay.js.map +1 -1
  19. package/dist/cjs/components/Form/FieldItem.js +3 -2
  20. package/dist/cjs/components/Form/FieldItem.js.map +1 -1
  21. package/dist/cjs/components/Form/FieldSet.js +3 -2
  22. package/dist/cjs/components/Form/FieldSet.js.map +1 -1
  23. package/dist/cjs/components/Icon/canonicalIconNames.js +1 -0
  24. package/dist/cjs/components/Icon/canonicalIconNames.js.map +1 -1
  25. package/dist/cjs/components/MultiSelect/MultiSelect.js +18 -14
  26. package/dist/cjs/components/MultiSelect/MultiSelect.js.map +1 -1
  27. package/dist/cjs/components/Notification/Notification.js +7 -4
  28. package/dist/cjs/components/Notification/Notification.js.map +1 -1
  29. package/dist/cjs/components/OverviewItem/OverviewItemActions.js +9 -2
  30. package/dist/cjs/components/OverviewItem/OverviewItemActions.js.map +1 -1
  31. package/dist/cjs/components/Spinner/Spinner.js +7 -5
  32. package/dist/cjs/components/Spinner/Spinner.js.map +1 -1
  33. package/dist/cjs/components/Tooltip/Tooltip.js +75 -7
  34. package/dist/cjs/components/Tooltip/Tooltip.js.map +1 -1
  35. package/dist/cjs/extensions/react-flow/nodes/NodeContent.js +17 -13
  36. package/dist/cjs/extensions/react-flow/nodes/NodeContent.js.map +1 -1
  37. package/dist/esm/cmem/markdown/Markdown.js +13 -11
  38. package/dist/esm/cmem/markdown/Markdown.js.map +1 -1
  39. package/dist/esm/cmem/markdown/highlightSearchWords.js +6 -1
  40. package/dist/esm/cmem/markdown/highlightSearchWords.js.map +1 -1
  41. package/dist/esm/common/Intent/index.js +14 -10
  42. package/dist/esm/common/Intent/index.js.map +1 -1
  43. package/dist/esm/components/AutoSuggestion/AutoSuggestion.js +42 -33
  44. package/dist/esm/components/AutoSuggestion/AutoSuggestion.js.map +1 -1
  45. package/dist/esm/components/AutoSuggestion/ExtendedCodeEditor.js +2 -2
  46. package/dist/esm/components/AutoSuggestion/ExtendedCodeEditor.js.map +1 -1
  47. package/dist/esm/components/Button/Button.js +2 -2
  48. package/dist/esm/components/Button/Button.js.map +1 -1
  49. package/dist/esm/components/ContextOverlay/ContextMenu.js +3 -2
  50. package/dist/esm/components/ContextOverlay/ContextMenu.js.map +1 -1
  51. package/dist/esm/components/ContextOverlay/ContextOverlay.js +63 -3
  52. package/dist/esm/components/ContextOverlay/ContextOverlay.js.map +1 -1
  53. package/dist/esm/components/Form/FieldItem.js +3 -2
  54. package/dist/esm/components/Form/FieldItem.js.map +1 -1
  55. package/dist/esm/components/Form/FieldSet.js +3 -2
  56. package/dist/esm/components/Form/FieldSet.js.map +1 -1
  57. package/dist/esm/components/Icon/canonicalIconNames.js +1 -0
  58. package/dist/esm/components/Icon/canonicalIconNames.js.map +1 -1
  59. package/dist/esm/components/MultiSelect/MultiSelect.js +18 -14
  60. package/dist/esm/components/MultiSelect/MultiSelect.js.map +1 -1
  61. package/dist/esm/components/Notification/Notification.js +7 -4
  62. package/dist/esm/components/Notification/Notification.js.map +1 -1
  63. package/dist/esm/components/OverviewItem/OverviewItemActions.js +25 -2
  64. package/dist/esm/components/OverviewItem/OverviewItemActions.js.map +1 -1
  65. package/dist/esm/components/Spinner/Spinner.js +9 -5
  66. package/dist/esm/components/Spinner/Spinner.js.map +1 -1
  67. package/dist/esm/components/Tooltip/Tooltip.js +92 -8
  68. package/dist/esm/components/Tooltip/Tooltip.js.map +1 -1
  69. package/dist/esm/extensions/react-flow/nodes/NodeContent.js +17 -13
  70. package/dist/esm/extensions/react-flow/nodes/NodeContent.js.map +1 -1
  71. package/dist/types/cmem/markdown/Markdown.d.ts +8 -1
  72. package/dist/types/common/Intent/index.d.ts +10 -1
  73. package/dist/types/components/AutoSuggestion/AutoSuggestion.d.ts +5 -1
  74. package/dist/types/components/AutoSuggestion/ExtendedCodeEditor.d.ts +5 -1
  75. package/dist/types/components/Button/Button.d.ts +5 -1
  76. package/dist/types/components/ContextOverlay/ContextMenu.d.ts +9 -2
  77. package/dist/types/components/ContextOverlay/ContextOverlay.d.ts +6 -1
  78. package/dist/types/components/Form/FieldItem.d.ts +10 -1
  79. package/dist/types/components/Form/FieldSet.d.ts +10 -1
  80. package/dist/types/components/Icon/canonicalIconNames.d.ts +1 -0
  81. package/dist/types/components/MultiSelect/MultiSelect.d.ts +12 -4
  82. package/dist/types/components/Notification/Notification.d.ts +10 -1
  83. package/dist/types/components/OverviewItem/OverviewItemActions.d.ts +13 -1
  84. package/dist/types/components/ProgressBar/ProgressBar.d.ts +2 -2
  85. package/dist/types/components/Spinner/Spinner.d.ts +8 -3
  86. package/dist/types/components/Structure/TitleSubsection.d.ts +7 -0
  87. package/dist/types/components/Table/TableContainer.d.ts +2 -2
  88. package/dist/types/components/Table/TableExpandRow.d.ts +1 -1
  89. package/dist/types/components/Table/index.d.ts +1 -0
  90. package/dist/types/components/Tabs/Tab.d.ts +14 -0
  91. package/dist/types/components/Tooltip/Tooltip.d.ts +9 -1
  92. package/package.json +47 -48
  93. package/src/cmem/markdown/Markdown.tsx +25 -14
  94. package/src/cmem/markdown/highlightSearchWords.test.ts +8 -2
  95. package/src/cmem/markdown/highlightSearchWords.ts +6 -1
  96. package/src/common/Intent/index.ts +6 -6
  97. package/src/components/AutoSuggestion/AutoSuggestion.tsx +50 -32
  98. package/src/components/AutoSuggestion/ExtendedCodeEditor.tsx +8 -0
  99. package/src/components/Button/Button.stories.tsx +10 -6
  100. package/src/components/Button/Button.tsx +7 -2
  101. package/src/components/ContextOverlay/ContextMenu.stories.tsx +1 -1
  102. package/src/components/ContextOverlay/ContextMenu.tsx +26 -13
  103. package/src/components/ContextOverlay/ContextOverlay.tsx +83 -5
  104. package/src/components/Form/FieldItem.tsx +14 -3
  105. package/src/components/Form/FieldSet.tsx +13 -2
  106. package/src/components/Form/Stories/FieldItem.stories.tsx +4 -0
  107. package/src/components/Form/Stories/FieldSet.stories.tsx +4 -0
  108. package/src/components/Icon/canonicalIconNames.tsx +1 -0
  109. package/src/components/MultiSelect/MultiSelect.tsx +27 -15
  110. package/src/components/MultiSuggestField/MultiSuggestField.stories.tsx +6 -0
  111. package/src/components/Notification/Notification.stories.tsx +4 -0
  112. package/src/components/Notification/Notification.tsx +17 -4
  113. package/src/components/OverviewItem/OverviewItemActions.tsx +24 -1
  114. package/src/components/OverviewItem/stories/OverviewItemList.stories.tsx +2 -7
  115. package/src/components/OverviewItem/stories/OverviewItemListPerformance.tsx +174 -0
  116. package/src/components/OverviewItem/stories/OverviewItemPerformance.stories.tsx +19 -0
  117. package/src/components/Spinner/Spinner.tsx +13 -5
  118. package/src/components/Spinner/Stories/spinner.stories.tsx +6 -1
  119. package/src/components/Table/TableContainer.tsx +2 -2
  120. package/src/components/Table/TableExpandRow.tsx +1 -1
  121. package/src/components/Table/index.tsx +1 -0
  122. package/src/components/Tooltip/Tooltip.stories.tsx +3 -2
  123. package/src/components/Tooltip/Tooltip.tsx +121 -10
  124. package/src/extensions/react-flow/nodes/NodeContent.tsx +18 -14
  125. package/src/extensions/react-flow/nodes/_nodes.scss +1 -1
  126. 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 success (some type of orange) color scheme.
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 success (some type of red) color scheme.
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 intent;
215
+ let stateIntent;
207
216
  switch (true) {
208
217
  case hasStatePrimary:
209
- intent = BlueprintIntent.PRIMARY;
218
+ stateIntent = BlueprintIntent.PRIMARY;
210
219
  break;
211
220
  case hasStateSuccess:
212
- intent = BlueprintIntent.SUCCESS;
221
+ stateIntent = BlueprintIntent.SUCCESS;
213
222
  break;
214
223
  case hasStateWarning:
215
- intent = BlueprintIntent.WARNING;
224
+ stateIntent = BlueprintIntent.WARNING;
216
225
  break;
217
226
  case hasStateDanger:
218
- intent = BlueprintIntent.DANGER;
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
- onSelection({
235
- newlySelected: selectedItems.slice(-1)[0],
236
- createdItems: createdItems.current,
237
- selectedItems,
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
- focusedItem ? onItemSelect(focusedItem) : onItemSelect(createNewItem(requestState.current.query));
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(),
@@ -15,6 +15,10 @@ export default {
15
15
  icon: {
16
16
  ...helpersArgTypes.exampleIcon,
17
17
  },
18
+ intent: {
19
+ ...helpersArgTypes.exampleIntent,
20
+ options: ["UNDEFINED", "success", "warning", "danger", "neutral", "info"],
21
+ },
18
22
  },
19
23
  } as Meta<typeof Notification>;
20
24
 
@@ -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 && !!iconSymbol) {
108
- notificationIcon = <Icon name={iconSymbol as ValidIconName} />;
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: "none",
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
+ };