@eccenca/gui-elements 24.1.0 → 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 +60 -0
- 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/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/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
|
@@ -40,8 +40,15 @@ export interface ContextMenuProps extends TestableComponent {
|
|
|
40
40
|
* Props to spread to `ContextOverlay` that is used to display the dropdown.
|
|
41
41
|
*/
|
|
42
42
|
contextOverlayProps?: Partial<Omit<ContextOverlayProps, "content" | "children" | "className">>;
|
|
43
|
-
/**
|
|
43
|
+
/**
|
|
44
|
+
* Disables the button to open the menu.
|
|
45
|
+
*/
|
|
44
46
|
disabled?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* We use the target as placeholder before the real `<ContextMenu /` is rendered on first hover or focus event.
|
|
49
|
+
* In case of problems set this property to `true`.
|
|
50
|
+
*/
|
|
51
|
+
preventPlaceholder?: boolean;
|
|
45
52
|
}
|
|
46
53
|
|
|
47
54
|
/**
|
|
@@ -58,27 +65,33 @@ export const ContextMenu = ({
|
|
|
58
65
|
/* FIXME: The Tooltip component can interfere with the opened menu, since it is implemented via portal and may cover the menu,
|
|
59
66
|
so by default we use the title attribute instead of Tooltip. */
|
|
60
67
|
tooltipAsTitle = true,
|
|
68
|
+
preventPlaceholder = false,
|
|
61
69
|
...restProps
|
|
62
70
|
}: ContextMenuProps) => {
|
|
71
|
+
const toggleButton =
|
|
72
|
+
typeof togglerElement === "string" ? (
|
|
73
|
+
<IconButton
|
|
74
|
+
tooltipAsTitle={tooltipAsTitle}
|
|
75
|
+
name={[togglerElement]}
|
|
76
|
+
text={togglerText}
|
|
77
|
+
large={togglerLarge}
|
|
78
|
+
disabled={!!disabled}
|
|
79
|
+
data-test-id={restProps["data-test-id"]}
|
|
80
|
+
/>
|
|
81
|
+
) : (
|
|
82
|
+
(togglerElement as ReactElement)
|
|
83
|
+
);
|
|
84
|
+
|
|
63
85
|
return (
|
|
64
86
|
<ContextOverlay
|
|
65
87
|
{...restProps}
|
|
66
88
|
{...contextOverlayProps}
|
|
67
89
|
className={`${eccgui}-contextmenu ` + className}
|
|
68
90
|
content={<Menu>{children}</Menu>}
|
|
91
|
+
disabled={!!disabled}
|
|
92
|
+
usePlaceholder={!preventPlaceholder}
|
|
69
93
|
>
|
|
70
|
-
{
|
|
71
|
-
<IconButton
|
|
72
|
-
tooltipAsTitle={tooltipAsTitle}
|
|
73
|
-
name={[togglerElement]}
|
|
74
|
-
text={togglerText}
|
|
75
|
-
large={togglerLarge}
|
|
76
|
-
disabled={!!disabled}
|
|
77
|
-
data-test-id={restProps["data-test-id"]}
|
|
78
|
-
/>
|
|
79
|
-
) : (
|
|
80
|
-
(togglerElement as ReactElement)
|
|
81
|
-
)}
|
|
94
|
+
{toggleButton}
|
|
82
95
|
</ContextOverlay>
|
|
83
96
|
);
|
|
84
97
|
};
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
Classes as BlueprintClasses,
|
|
4
|
+
Popover as BlueprintPopover,
|
|
5
|
+
PopoverProps as BlueprintPopoverProps,
|
|
6
|
+
Utils as BlueprintUtils,
|
|
7
|
+
} from "@blueprintjs/core";
|
|
3
8
|
|
|
4
9
|
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
|
|
5
10
|
|
|
@@ -13,6 +18,11 @@ export interface ContextOverlayProps extends Omit<BlueprintPopoverProps, "positi
|
|
|
13
18
|
* Use it when you need to display modal dialogs out of the context overlay.
|
|
14
19
|
*/
|
|
15
20
|
preventTopPosition?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Use the overlay target as placeholder before the real `<ContextOverlay /` is rendered on first hover or focus event.
|
|
23
|
+
* Currently experimental.
|
|
24
|
+
*/
|
|
25
|
+
usePlaceholder?: boolean;
|
|
16
26
|
}
|
|
17
27
|
|
|
18
28
|
/**
|
|
@@ -24,18 +34,86 @@ export const ContextOverlay = ({
|
|
|
24
34
|
portalClassName,
|
|
25
35
|
preventTopPosition,
|
|
26
36
|
className = "",
|
|
27
|
-
|
|
37
|
+
usePlaceholder = false,
|
|
38
|
+
...otherPopoverProps
|
|
28
39
|
}: ContextOverlayProps) => {
|
|
40
|
+
const placeholderRef = React.useRef(null);
|
|
41
|
+
const eventMemory = React.useRef<undefined | "afterhover" | "afterfocus">(undefined);
|
|
42
|
+
const [placeholder, setPlaceholder] = React.useState<boolean>(
|
|
43
|
+
// use placeholder only for "simple" overlays without special states
|
|
44
|
+
!otherPopoverProps.disabled &&
|
|
45
|
+
!otherPopoverProps.defaultIsOpen &&
|
|
46
|
+
!otherPopoverProps.isOpen &&
|
|
47
|
+
otherPopoverProps.renderTarget === undefined &&
|
|
48
|
+
usePlaceholder
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
React.useEffect(() => {
|
|
52
|
+
if (placeholderRef.current) {
|
|
53
|
+
const swap = (ev: MouseEvent | globalThis.FocusEvent) => {
|
|
54
|
+
eventMemory.current = ev.type === "focusin" ? "afterfocus" : "afterhover";
|
|
55
|
+
setPlaceholder(false);
|
|
56
|
+
};
|
|
57
|
+
(placeholderRef.current as HTMLElement).addEventListener("mouseenter", swap);
|
|
58
|
+
(placeholderRef.current as HTMLElement).addEventListener("focusin", swap);
|
|
59
|
+
return () => {
|
|
60
|
+
if (placeholderRef.current) {
|
|
61
|
+
(placeholderRef.current as HTMLElement).removeEventListener("mouseenter", swap);
|
|
62
|
+
(placeholderRef.current as HTMLElement).removeEventListener("focusin", swap);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return () => {};
|
|
67
|
+
}, [!!placeholderRef.current]);
|
|
68
|
+
|
|
69
|
+
const refocus = React.useCallback((node) => {
|
|
70
|
+
if (eventMemory.current === "afterfocus" && node) {
|
|
71
|
+
const target = node.targetRef.current.children[0];
|
|
72
|
+
if (target) {
|
|
73
|
+
target.focus();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}, []);
|
|
77
|
+
|
|
78
|
+
const targetClassName = `${eccgui}-contextoverlay` + (className ? ` ${className}` : "");
|
|
79
|
+
|
|
80
|
+
const displayPlaceholder = () => {
|
|
81
|
+
const PlaceholderElement = otherPopoverProps?.targetTagName ?? (otherPopoverProps?.fill ? "div" : "span");
|
|
82
|
+
const childTarget = BlueprintUtils.ensureElement(React.Children.toArray(children)[0]);
|
|
83
|
+
if (!childTarget) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
return React.createElement(
|
|
87
|
+
PlaceholderElement,
|
|
88
|
+
{
|
|
89
|
+
...otherPopoverProps?.targetProps,
|
|
90
|
+
className: `${BlueprintClasses.POPOVER_TARGET} ${targetClassName}`,
|
|
91
|
+
ref: placeholderRef,
|
|
92
|
+
},
|
|
93
|
+
React.cloneElement(childTarget, {
|
|
94
|
+
...childTarget.props,
|
|
95
|
+
className:
|
|
96
|
+
childTarget.props.className ?? "" + (otherPopoverProps.fill ? ` ${BlueprintClasses.FILL}` : ""),
|
|
97
|
+
tabIndex:
|
|
98
|
+
childTarget.props.tabIndex ??
|
|
99
|
+
(!otherPopoverProps?.disabled && otherPopoverProps?.openOnTargetFocus ? 0 : undefined),
|
|
100
|
+
})
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
|
|
29
104
|
const portalClassNameFinal =
|
|
30
105
|
(preventTopPosition ? `${eccgui}-contextoverlay__portal--lowertop` : "") +
|
|
31
106
|
(portalClassName ? ` ${portalClassName}` : "");
|
|
32
107
|
|
|
33
|
-
return (
|
|
108
|
+
return placeholder ? (
|
|
109
|
+
displayPlaceholder()
|
|
110
|
+
) : (
|
|
34
111
|
<BlueprintPopover
|
|
35
112
|
placement="bottom"
|
|
36
|
-
{...
|
|
37
|
-
className={
|
|
113
|
+
{...otherPopoverProps}
|
|
114
|
+
className={targetClassName}
|
|
38
115
|
portalClassName={portalClassNameFinal.trim() ?? undefined}
|
|
116
|
+
ref={refocus}
|
|
39
117
|
>
|
|
40
118
|
{children}
|
|
41
119
|
</BlueprintPopover>
|
|
@@ -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
|
};
|