@eccenca/gui-elements 24.4.1-featurepreparefinalnextcmem6943.2 → 25.0.0-bugfixcenterednodecontentmenuitemscmem7184.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 +93 -19
- package/dist/cjs/cmem/ActivityControl/SilkActivityControl.js +1 -3
- package/dist/cjs/cmem/ActivityControl/SilkActivityControl.js.map +1 -1
- package/dist/cjs/cmem/ContentBlobToggler/ContentBlobToggler.js +1 -0
- package/dist/cjs/cmem/ContentBlobToggler/ContentBlobToggler.js.map +1 -1
- package/dist/cjs/cmem/ContentBlobToggler/StringPreviewContentBlobToggler.js +34 -11
- package/dist/cjs/cmem/ContentBlobToggler/StringPreviewContentBlobToggler.js.map +1 -1
- package/dist/cjs/cmem/markdown/Markdown.js +1 -2
- package/dist/cjs/cmem/markdown/Markdown.js.map +1 -1
- package/dist/cjs/cmem/react-flow/ReactFlow/ReactFlowV12.js.map +1 -1
- package/dist/cjs/common/Intent/index.js +1 -1
- package/dist/cjs/common/Intent/index.js.map +1 -1
- package/dist/cjs/common/index.js +4 -0
- package/dist/cjs/common/index.js.map +1 -1
- package/dist/cjs/common/utils/reduceToText.js +94 -0
- package/dist/cjs/common/utils/reduceToText.js.map +1 -0
- package/dist/cjs/components/Application/ApplicationViewability.js +33 -0
- package/dist/cjs/components/Application/ApplicationViewability.js.map +1 -0
- package/dist/cjs/components/Application/index.js +1 -0
- package/dist/cjs/components/Application/index.js.map +1 -1
- package/dist/cjs/components/AutocompleteField/AutoCompleteField.js +1 -1
- package/dist/cjs/components/AutocompleteField/AutoCompleteField.js.map +1 -1
- package/dist/cjs/components/Button/Button.js +1 -1
- package/dist/cjs/components/Button/Button.js.map +1 -1
- package/dist/cjs/components/ContextOverlay/ContextMenu.js +2 -2
- package/dist/cjs/components/ContextOverlay/ContextMenu.js.map +1 -1
- package/dist/cjs/components/ContextOverlay/ContextOverlay.js +65 -18
- package/dist/cjs/components/ContextOverlay/ContextOverlay.js.map +1 -1
- package/dist/cjs/components/Dialog/Modal.js +15 -3
- package/dist/cjs/components/Dialog/Modal.js.map +1 -1
- package/dist/cjs/components/Dialog/ModalContext.js +51 -0
- package/dist/cjs/components/Dialog/ModalContext.js.map +1 -0
- package/dist/cjs/components/Dialog/index.js +1 -0
- package/dist/cjs/components/Dialog/index.js.map +1 -1
- package/dist/cjs/components/Icon/IconButton.js.map +1 -1
- package/dist/cjs/components/Icon/canonicalIconNames.js +25 -2
- package/dist/cjs/components/Icon/canonicalIconNames.js.map +1 -1
- package/dist/cjs/components/Spinner/Spinner.js +2 -1
- package/dist/cjs/components/Spinner/Spinner.js.map +1 -1
- package/dist/cjs/components/TextReducer/TextReducer.js +17 -63
- package/dist/cjs/components/TextReducer/TextReducer.js.map +1 -1
- package/dist/cjs/components/Typography/InlineText.js +29 -0
- package/dist/cjs/components/Typography/InlineText.js.map +1 -0
- package/dist/cjs/components/Typography/index.js +1 -0
- package/dist/cjs/components/Typography/index.js.map +1 -1
- package/dist/cjs/extensions/codemirror/CodeMirror.js +2 -2
- package/dist/cjs/extensions/codemirror/CodeMirror.js.map +1 -1
- package/dist/cjs/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.js +1 -1
- package/dist/cjs/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.js.map +1 -1
- package/dist/cjs/extensions/codemirror/tests/codemirrorTestHelper.js +2 -2
- package/dist/cjs/extensions/codemirror/tests/codemirrorTestHelper.js.map +1 -1
- package/dist/cjs/extensions/react-flow/edges/EdgeNew.js +1 -1
- package/dist/cjs/extensions/react-flow/edges/EdgeNew.js.map +1 -1
- package/dist/cjs/extensions/react-flow/handles/HandleDefault.js +1 -1
- package/dist/cjs/extensions/react-flow/handles/HandleDefault.js.map +1 -1
- package/dist/cjs/extensions/react-flow/minimap/MiniMap.js +1 -1
- package/dist/cjs/extensions/react-flow/minimap/MiniMap.js.map +1 -1
- package/dist/cjs/extensions/react-flow/minimap/MiniMapV12.js.map +1 -1
- package/dist/cjs/extensions/react-flow/nodes/NodeContent.js +2 -2
- package/dist/cjs/extensions/react-flow/nodes/NodeContent.js.map +1 -1
- package/dist/cjs/extensions/react-flow/nodes/nodeUtils.js.map +1 -1
- package/dist/esm/cmem/ActivityControl/SilkActivityControl.js +1 -3
- package/dist/esm/cmem/ActivityControl/SilkActivityControl.js.map +1 -1
- package/dist/esm/cmem/ContentBlobToggler/ContentBlobToggler.js +1 -0
- package/dist/esm/cmem/ContentBlobToggler/ContentBlobToggler.js.map +1 -1
- package/dist/esm/cmem/ContentBlobToggler/StringPreviewContentBlobToggler.js +32 -9
- package/dist/esm/cmem/ContentBlobToggler/StringPreviewContentBlobToggler.js.map +1 -1
- package/dist/esm/cmem/markdown/Markdown.js +1 -2
- package/dist/esm/cmem/markdown/Markdown.js.map +1 -1
- package/dist/esm/cmem/react-flow/ReactFlow/ReactFlowV12.js.map +1 -1
- package/dist/esm/common/Intent/index.js +1 -1
- package/dist/esm/common/Intent/index.js.map +1 -1
- package/dist/esm/common/index.js +4 -0
- package/dist/esm/common/index.js.map +1 -1
- package/dist/esm/common/utils/reduceToText.js +75 -0
- package/dist/esm/common/utils/reduceToText.js.map +1 -0
- package/dist/esm/components/Application/ApplicationViewability.js +28 -0
- package/dist/esm/components/Application/ApplicationViewability.js.map +1 -0
- package/dist/esm/components/Application/index.js +1 -0
- package/dist/esm/components/Application/index.js.map +1 -1
- package/dist/esm/components/AutocompleteField/AutoCompleteField.js +1 -1
- package/dist/esm/components/AutocompleteField/AutoCompleteField.js.map +1 -1
- package/dist/esm/components/Button/Button.js +1 -1
- package/dist/esm/components/Button/Button.js.map +1 -1
- package/dist/esm/components/ContextOverlay/ContextMenu.js +2 -2
- package/dist/esm/components/ContextOverlay/ContextMenu.js.map +1 -1
- package/dist/esm/components/ContextOverlay/ContextOverlay.js +69 -22
- package/dist/esm/components/ContextOverlay/ContextOverlay.js.map +1 -1
- package/dist/esm/components/Dialog/Modal.js +15 -3
- package/dist/esm/components/Dialog/Modal.js.map +1 -1
- package/dist/esm/components/Dialog/ModalContext.js +69 -0
- package/dist/esm/components/Dialog/ModalContext.js.map +1 -0
- package/dist/esm/components/Dialog/index.js +1 -0
- package/dist/esm/components/Dialog/index.js.map +1 -1
- package/dist/esm/components/Icon/IconButton.js.map +1 -1
- package/dist/esm/components/Icon/canonicalIconNames.js +25 -2
- package/dist/esm/components/Icon/canonicalIconNames.js.map +1 -1
- package/dist/esm/components/Spinner/Spinner.js +2 -1
- package/dist/esm/components/Spinner/Spinner.js.map +1 -1
- package/dist/esm/components/TextReducer/TextReducer.js +17 -41
- package/dist/esm/components/TextReducer/TextReducer.js.map +1 -1
- package/dist/esm/components/Typography/InlineText.js +33 -0
- package/dist/esm/components/Typography/InlineText.js.map +1 -0
- package/dist/esm/components/Typography/index.js +1 -0
- package/dist/esm/components/Typography/index.js.map +1 -1
- package/dist/esm/extensions/codemirror/CodeMirror.js +3 -3
- package/dist/esm/extensions/codemirror/CodeMirror.js.map +1 -1
- package/dist/esm/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.js +1 -1
- package/dist/esm/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.js.map +1 -1
- package/dist/esm/extensions/codemirror/tests/codemirrorTestHelper.js +3 -3
- package/dist/esm/extensions/codemirror/tests/codemirrorTestHelper.js.map +1 -1
- package/dist/esm/extensions/react-flow/edges/EdgeNew.js +1 -1
- package/dist/esm/extensions/react-flow/edges/EdgeNew.js.map +1 -1
- package/dist/esm/extensions/react-flow/handles/HandleDefault.js +1 -1
- package/dist/esm/extensions/react-flow/handles/HandleDefault.js.map +1 -1
- package/dist/esm/extensions/react-flow/minimap/MiniMap.js +1 -1
- package/dist/esm/extensions/react-flow/minimap/MiniMap.js.map +1 -1
- package/dist/esm/extensions/react-flow/minimap/MiniMapV12.js.map +1 -1
- package/dist/esm/extensions/react-flow/nodes/NodeContent.js +2 -2
- package/dist/esm/extensions/react-flow/nodes/NodeContent.js.map +1 -1
- package/dist/esm/extensions/react-flow/nodes/nodeUtils.js.map +1 -1
- package/dist/types/cmem/ContentBlobToggler/StringPreviewContentBlobToggler.d.ts +26 -10
- package/dist/types/cmem/react-flow/StickyNoteModal/StickyNoteModal.d.ts +1 -1
- package/dist/types/common/index.d.ts +3 -0
- package/dist/types/common/utils/reduceToText.d.ts +10 -0
- package/dist/types/components/Application/ApplicationViewability.d.ts +36 -0
- package/dist/types/components/Application/index.d.ts +1 -0
- package/dist/types/components/Button/Button.d.ts +14 -7
- package/dist/types/components/ContextOverlay/ContextMenu.d.ts +1 -1
- package/dist/types/components/Dialog/Modal.d.ts +9 -1
- package/dist/types/components/Dialog/ModalContext.d.ts +13 -0
- package/dist/types/components/Dialog/index.d.ts +1 -0
- package/dist/types/components/Icon/IconButton.d.ts +1 -1
- package/dist/types/components/Icon/canonicalIconNames.d.ts +23 -0
- package/dist/types/components/Spinner/Spinner.d.ts +11 -4
- package/dist/types/components/Structure/TitleSubsection.d.ts +1 -1
- package/dist/types/components/Tabs/Tab.d.ts +4 -4
- package/dist/types/components/TextReducer/TextReducer.d.ts +13 -1
- package/dist/types/components/Typography/InlineText.d.ts +13 -0
- package/dist/types/components/Typography/index.d.ts +1 -0
- package/dist/types/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.d.ts +1 -1
- package/dist/types/extensions/codemirror/tests/codemirrorTestHelper.d.ts +1 -1
- package/dist/types/extensions/react-flow/edges/EdgeLabel.d.ts +1 -1
- package/package.json +54 -53
- package/src/cmem/ActivityControl/SilkActivityControl.tsx +1 -1
- package/src/cmem/ContentBlobToggler/ContentBlobToggler.tsx +1 -1
- package/src/cmem/ContentBlobToggler/StringPreviewContentBlobToggler.tsx +65 -17
- package/src/cmem/ContentBlobToggler/stories/StringPreviewContentBlobToggler.stories.tsx +27 -0
- package/src/cmem/ContentBlobToggler/tests/StringPreviewContentBlobToggler.test.tsx +98 -0
- package/src/cmem/markdown/Markdown.tsx +1 -2
- package/src/cmem/react-flow/ReactFlow/ReactFlowV12.tsx +1 -0
- package/src/cmem/react-flow/StickyNoteModal/StickyNoteModal.tsx +1 -1
- package/src/cmem/react-flow/_minimap.scss +10 -0
- package/src/cmem/react-flow/configuration/_colors-graph.scss +12 -12
- package/src/cmem/react-flow/configuration/_colors-linking.scss +8 -8
- package/src/cmem/react-flow/configuration/_colors-workflow.scss +11 -11
- package/src/common/Intent/index.ts +2 -1
- package/src/common/index.ts +6 -0
- package/src/common/scss/_color-functions.scss +5 -0
- package/src/common/utils/reduceToText.tsx +82 -0
- package/src/components/Application/ApplicationViewability.tsx +61 -0
- package/src/components/Application/_content.scss +7 -0
- package/src/components/Application/_header.scss +12 -3
- package/src/components/Application/_viewability.scss +13 -0
- package/src/components/Application/application.scss +1 -0
- package/src/components/Application/index.ts +1 -0
- package/src/components/Application/stories/ApplicationViewability.stories.tsx +37 -0
- package/src/components/Application/tests/ApplicationViewability.test.tsx +43 -0
- package/src/components/AutoSuggestion/tests/ExtendedCodeEditor.test.tsx +1 -1
- package/src/components/AutocompleteField/AutoCompleteField.tsx +1 -0
- package/src/components/Button/Button.stories.tsx +7 -1
- package/src/components/Button/Button.tsx +16 -9
- package/src/components/Button/button.scss +86 -24
- package/src/components/Card/card.scss +6 -0
- package/src/components/Chat/stories/ChatField.stories.tsx +6 -1
- package/src/components/Checkbox/checkbox.scss +14 -2
- package/src/components/ContentGroup/_contentgroup.scss +9 -0
- package/src/components/ContextOverlay/ContextMenu.tsx +4 -1
- package/src/components/ContextOverlay/ContextOverlay.tsx +77 -18
- package/src/components/ContextOverlay/tests/ContextMenu.test.tsx +43 -0
- package/src/components/ContextOverlay/tests/ContextOverlay.test.tsx +71 -0
- package/src/components/Depiction/depiction.scss +6 -0
- package/src/components/Dialog/Modal.tsx +28 -3
- package/src/components/Dialog/ModalContext.tsx +56 -0
- package/src/components/Dialog/index.ts +1 -0
- package/src/components/Dialog/stories/Modal.stories.tsx +10 -7
- package/src/components/Dialog/stories/ModalContext.stories.tsx +153 -0
- package/src/components/FlexibleLayout/flexiblelayout.scss +16 -0
- package/src/components/Grid/grid.scss +17 -0
- package/src/components/Grid/stories/Grid.stories.tsx +10 -7
- package/src/components/Grid/stories/GridRow.stories.tsx +13 -7
- package/src/components/Icon/IconButton.tsx +1 -1
- package/src/components/Icon/canonicalIconNames.tsx +25 -2
- package/src/components/Icon/icon.scss +6 -0
- package/src/components/Icon/stories/Icon.stories.tsx +65 -5
- package/src/components/Icon/stories/IconButton.stories.tsx +2 -1
- package/src/components/Notification/Notification.stories.tsx +20 -6
- package/src/components/Notification/notification.scss +14 -3
- package/src/components/OverviewItem/overviewitem.scss +9 -0
- package/src/components/OverviewItem/stories/OverviewItem.stories.tsx +28 -0
- package/src/components/OverviewItem/stories/OverviewItemActions.stories.tsx +2 -2
- package/src/components/OverviewItem/stories/OverviewItemDescription.stories.tsx +1 -1
- package/src/components/OverviewItem/stories/OverviewItemLine.stories.tsx +1 -1
- package/src/components/ProgressBar/Stories/ProgressBar.stories.tsx +7 -1
- package/src/components/PropertyValuePair/propertyvalue.scss +23 -1
- package/src/components/Select/Select.stories.tsx +1 -1
- package/src/components/Separation/separation.scss +6 -0
- package/src/components/Spinner/Spinner.tsx +13 -3
- package/src/components/Spinner/Stories/spinner.stories.tsx +1 -1
- package/src/components/Spinner/spinner.scss +5 -1
- package/src/components/Table/table.scss +22 -0
- package/src/components/Tag/stories/TagList.stories.tsx +2 -2
- package/src/components/Tag/tag.scss +105 -74
- package/src/components/TextField/textfield.scss +23 -15
- package/src/components/TextReducer/TextReducer.stories.tsx +2 -1
- package/src/components/TextReducer/TextReducer.test.tsx +44 -0
- package/src/components/TextReducer/TextReducer.tsx +17 -44
- package/src/components/Typography/InlineText.tsx +24 -0
- package/src/components/Typography/index.ts +1 -0
- package/src/components/Typography/stories/InlineText.stories.tsx +27 -0
- package/src/components/Typography/typography.scss +23 -2
- package/src/components/VisualTour/stories/VisualTour.stories.tsx +1 -1
- package/src/configuration/_palettes.scss +2 -1
- package/src/extensions/codemirror/CodeMirror.tsx +4 -4
- package/src/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.ts +1 -2
- package/src/extensions/codemirror/tests/codemirrorTestHelper.ts +3 -3
- package/src/extensions/react-flow/_config.scss +8 -3
- package/src/extensions/react-flow/_react-flow_v12.scss +10 -14
- package/src/extensions/react-flow/edges/EdgeLabel.tsx +1 -1
- package/src/extensions/react-flow/edges/EdgeNew.tsx +2 -1
- package/src/extensions/react-flow/edges/_edges.scss +15 -7
- package/src/extensions/react-flow/edges/stories/EdgeDefault.stories.tsx +5 -5
- package/src/extensions/react-flow/handles/HandleDefault.tsx +2 -2
- package/src/extensions/react-flow/minimap/MiniMap.tsx +2 -1
- package/src/extensions/react-flow/minimap/MiniMapV12.tsx +1 -1
- package/src/extensions/react-flow/nodes/NodeContent.tsx +2 -2
- package/src/extensions/react-flow/nodes/_nodes.scss +4 -3
- package/src/extensions/react-flow/nodes/nodeUtils.tsx +1 -0
- package/src/extensions/react-flow/nodes/stories/NodeContent.stories.tsx +2 -2
|
@@ -66,6 +66,8 @@ export const ContextMenu = ({
|
|
|
66
66
|
so by default we use the title attribute instead of Tooltip. */
|
|
67
67
|
tooltipAsTitle = true,
|
|
68
68
|
preventPlaceholder = false,
|
|
69
|
+
"data-test-id": dataTestId,
|
|
70
|
+
"data-testid": dataTestid,
|
|
69
71
|
...restProps
|
|
70
72
|
}: ContextMenuProps) => {
|
|
71
73
|
const toggleButton =
|
|
@@ -76,7 +78,8 @@ export const ContextMenu = ({
|
|
|
76
78
|
text={togglerText}
|
|
77
79
|
large={togglerLarge}
|
|
78
80
|
disabled={!!disabled}
|
|
79
|
-
data-test-id={
|
|
81
|
+
data-test-id={dataTestId ?? undefined}
|
|
82
|
+
data-testid={dataTestid ?? undefined}
|
|
80
83
|
/>
|
|
81
84
|
) : (
|
|
82
85
|
(togglerElement as ReactElement)
|
|
@@ -2,6 +2,7 @@ import React from "react";
|
|
|
2
2
|
import {
|
|
3
3
|
Classes as BlueprintClasses,
|
|
4
4
|
Popover as BlueprintPopover,
|
|
5
|
+
PopoverInteractionKind as InteractionKind,
|
|
5
6
|
PopoverProps as BlueprintPopoverProps,
|
|
6
7
|
Utils as BlueprintUtils,
|
|
7
8
|
} from "@blueprintjs/core";
|
|
@@ -37,8 +38,11 @@ export const ContextOverlay = ({
|
|
|
37
38
|
usePlaceholder = false,
|
|
38
39
|
...otherPopoverProps
|
|
39
40
|
}: ContextOverlayProps) => {
|
|
40
|
-
const placeholderRef = React.useRef(null);
|
|
41
|
-
const eventMemory = React.useRef<undefined | "
|
|
41
|
+
const placeholderRef = React.useRef<HTMLElement>(null);
|
|
42
|
+
const eventMemory = React.useRef<undefined | "mouseenter" | "focusin" | "click">(undefined);
|
|
43
|
+
const swapDelay = React.useRef<null | NodeJS.Timeout>(null);
|
|
44
|
+
const interactionKind = React.useRef<InteractionKind>(otherPopoverProps.interactionKind ?? InteractionKind.CLICK);
|
|
45
|
+
const swapDelayTime = 15;
|
|
42
46
|
const [placeholder, setPlaceholder] = React.useState<boolean>(
|
|
43
47
|
// use placeholder only for "simple" overlays without special states
|
|
44
48
|
!otherPopoverProps.disabled &&
|
|
@@ -48,30 +52,85 @@ export const ContextOverlay = ({
|
|
|
48
52
|
usePlaceholder
|
|
49
53
|
);
|
|
50
54
|
|
|
55
|
+
const swap = (ev: MouseEvent | globalThis.FocusEvent) => {
|
|
56
|
+
const waitForClick =
|
|
57
|
+
interactionKind.current === InteractionKind.CLICK ||
|
|
58
|
+
interactionKind.current === InteractionKind.CLICK_TARGET_ONLY;
|
|
59
|
+
|
|
60
|
+
if (swapDelay.current) {
|
|
61
|
+
clearTimeout(swapDelay.current);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const replacePlaceholder = () => {
|
|
65
|
+
eventMemory.current = ev.type as "mouseenter" | "focusin" | "click";
|
|
66
|
+
setPlaceholder(false);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
if (waitForClick) {
|
|
70
|
+
ev.stopImmediatePropagation();
|
|
71
|
+
replacePlaceholder();
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
swapDelay.current = setTimeout(
|
|
76
|
+
replacePlaceholder,
|
|
77
|
+
// we delay the swap for hover/focus to prevent unwanted effects
|
|
78
|
+
// (e.g. event hickup after replacing elements when it is not really necessary)
|
|
79
|
+
swapDelayTime
|
|
80
|
+
);
|
|
81
|
+
};
|
|
82
|
+
|
|
51
83
|
React.useEffect(() => {
|
|
84
|
+
interactionKind.current = otherPopoverProps.interactionKind ?? InteractionKind.CLICK;
|
|
85
|
+
const waitForClick =
|
|
86
|
+
interactionKind.current === InteractionKind.CLICK ||
|
|
87
|
+
interactionKind.current === InteractionKind.CLICK_TARGET_ONLY;
|
|
88
|
+
const removeEvents = () => {
|
|
89
|
+
if (placeholderRef.current) {
|
|
90
|
+
placeholderRef.current.removeEventListener("click", swap);
|
|
91
|
+
placeholderRef.current.removeEventListener("mouseenter", swap);
|
|
92
|
+
placeholderRef.current.removeEventListener("focusin", swap);
|
|
93
|
+
}
|
|
94
|
+
return;
|
|
95
|
+
};
|
|
52
96
|
if (placeholderRef.current) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
97
|
+
removeEvents(); // remove events in case of interaction kind changed during existence
|
|
98
|
+
if (waitForClick) {
|
|
99
|
+
placeholderRef.current.addEventListener("click", swap);
|
|
100
|
+
} else {
|
|
101
|
+
placeholderRef.current.addEventListener("mouseenter", swap);
|
|
102
|
+
placeholderRef.current.addEventListener("focusin", swap);
|
|
103
|
+
}
|
|
59
104
|
return () => {
|
|
60
|
-
|
|
61
|
-
(placeholderRef.current as HTMLElement).removeEventListener("mouseenter", swap);
|
|
62
|
-
(placeholderRef.current as HTMLElement).removeEventListener("focusin", swap);
|
|
63
|
-
}
|
|
105
|
+
removeEvents();
|
|
64
106
|
};
|
|
65
107
|
}
|
|
66
108
|
return () => {};
|
|
67
|
-
}, [!!placeholderRef.current]);
|
|
109
|
+
}, [!!placeholderRef.current, otherPopoverProps.interactionKind]);
|
|
68
110
|
|
|
69
111
|
const refocus = React.useCallback((node) => {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
112
|
+
const target = node?.targetRef.current.children[0];
|
|
113
|
+
if (!eventMemory.current || !target) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
switch (eventMemory.current) {
|
|
117
|
+
case "focusin":
|
|
73
118
|
target.focus();
|
|
74
|
-
|
|
119
|
+
break;
|
|
120
|
+
case "click":
|
|
121
|
+
target.click();
|
|
122
|
+
break;
|
|
123
|
+
case "mouseenter":
|
|
124
|
+
// re-check if the cursor is still over the element after swapping the placeholder before triggering the event to bubble up
|
|
125
|
+
(target as HTMLElement).addEventListener(
|
|
126
|
+
"mouseover",
|
|
127
|
+
() => (target as HTMLElement).dispatchEvent(new MouseEvent("mouseover", { bubbles: true })),
|
|
128
|
+
{
|
|
129
|
+
capture: true,
|
|
130
|
+
once: true,
|
|
131
|
+
}
|
|
132
|
+
);
|
|
133
|
+
break;
|
|
75
134
|
}
|
|
76
135
|
}, []);
|
|
77
136
|
|
|
@@ -87,7 +146,7 @@ export const ContextOverlay = ({
|
|
|
87
146
|
PlaceholderElement,
|
|
88
147
|
{
|
|
89
148
|
...otherPopoverProps?.targetProps,
|
|
90
|
-
className: `${BlueprintClasses.POPOVER_TARGET} ${targetClassName}`,
|
|
149
|
+
className: `${BlueprintClasses.POPOVER_TARGET} ${targetClassName} ${eccgui}-contextoverlay__wrapper--placeholder`,
|
|
91
150
|
ref: placeholderRef,
|
|
92
151
|
},
|
|
93
152
|
React.cloneElement(childTarget, {
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
3
|
+
|
|
4
|
+
import "@testing-library/jest-dom";
|
|
5
|
+
|
|
6
|
+
import { CLASSPREFIX as eccgui } from "../../../configuration/constants";
|
|
7
|
+
|
|
8
|
+
import ContextMenu from "./../ContextMenu";
|
|
9
|
+
import { Default as ContextMenuStory } from "./../ContextMenu.stories";
|
|
10
|
+
|
|
11
|
+
const overlayWrapper = `${eccgui}-contextoverlay`;
|
|
12
|
+
const placeholderClass = `${overlayWrapper}__wrapper--placeholder`;
|
|
13
|
+
|
|
14
|
+
const checkForPlaceholderClass = (container: HTMLElement, tobe: number) => {
|
|
15
|
+
expect(container.getElementsByClassName(placeholderClass).length).toBe(tobe);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
describe("ContextMenu", () => {
|
|
19
|
+
it("should render placeholder automatically", () => {
|
|
20
|
+
const { container } = render(<ContextMenu {...ContextMenuStory.args} />);
|
|
21
|
+
checkForPlaceholderClass(container, 1);
|
|
22
|
+
});
|
|
23
|
+
it("should not render placeholder when `preventPlaceholder===true`", () => {
|
|
24
|
+
const { container } = render(<ContextMenu {...ContextMenuStory.args} preventPlaceholder={true} />);
|
|
25
|
+
checkForPlaceholderClass(container, 0);
|
|
26
|
+
});
|
|
27
|
+
it("should render placeholder when `preventPlaceholder===false`", () => {
|
|
28
|
+
const { container } = render(<ContextMenu {...ContextMenuStory.args} preventPlaceholder={false} />);
|
|
29
|
+
checkForPlaceholderClass(container, 1);
|
|
30
|
+
});
|
|
31
|
+
it("if no placeholder is used the menu should be displayed on click", async () => {
|
|
32
|
+
const { container } = render(<ContextMenu {...ContextMenuStory.args} preventPlaceholder={true} />);
|
|
33
|
+
checkForPlaceholderClass(container, 0);
|
|
34
|
+
fireEvent.click(container.getElementsByClassName(overlayWrapper)[0]);
|
|
35
|
+
expect(await screen.findByText("First option")).toBeVisible();
|
|
36
|
+
});
|
|
37
|
+
it("if placeholder is used the menu should be displayed on click", async () => {
|
|
38
|
+
const { container } = render(<ContextMenu {...ContextMenuStory.args} preventPlaceholder={false} />);
|
|
39
|
+
checkForPlaceholderClass(container, 1);
|
|
40
|
+
fireEvent.click(container.getElementsByClassName(overlayWrapper)[0]);
|
|
41
|
+
expect(await screen.findByText("First option")).toBeVisible();
|
|
42
|
+
});
|
|
43
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { PopoverInteractionKind } from "@blueprintjs/core";
|
|
3
|
+
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
|
4
|
+
|
|
5
|
+
import "@testing-library/jest-dom";
|
|
6
|
+
|
|
7
|
+
import { CLASSPREFIX as eccgui } from "../../../configuration/constants";
|
|
8
|
+
|
|
9
|
+
import ContextOverlay from "./../ContextOverlay";
|
|
10
|
+
import { Default as ContextOverlayStory } from "./../ContextOverlay.stories";
|
|
11
|
+
|
|
12
|
+
const overlayWrapper = `${eccgui}-contextoverlay`;
|
|
13
|
+
const placeholderClass = `${overlayWrapper}__wrapper--placeholder`;
|
|
14
|
+
|
|
15
|
+
const checkForPlaceholderClass = (container: HTMLElement, tobe: number) => {
|
|
16
|
+
expect(container.getElementsByClassName(placeholderClass).length).toBe(tobe);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
describe("ContextOverlay", () => {
|
|
20
|
+
it("should not render placeholder automatically", () => {
|
|
21
|
+
const { container } = render(<ContextOverlay {...ContextOverlayStory.args} />);
|
|
22
|
+
checkForPlaceholderClass(container, 0);
|
|
23
|
+
});
|
|
24
|
+
it("should render placeholder when `usePlaceholder===true`", () => {
|
|
25
|
+
const { container } = render(<ContextOverlay {...ContextOverlayStory.args} usePlaceholder={true} />);
|
|
26
|
+
checkForPlaceholderClass(container, 1);
|
|
27
|
+
});
|
|
28
|
+
it("should render no placeholder when `usePlaceholder===false`", () => {
|
|
29
|
+
const { container } = render(<ContextOverlay {...ContextOverlayStory.args} usePlaceholder={false} />);
|
|
30
|
+
checkForPlaceholderClass(container, 0);
|
|
31
|
+
});
|
|
32
|
+
it("if no placeholder is used the overlay should be displayed on click", async () => {
|
|
33
|
+
const { container } = render(<ContextOverlay {...ContextOverlayStory.args} usePlaceholder={false} />);
|
|
34
|
+
fireEvent.click(container.getElementsByClassName(overlayWrapper)[0]);
|
|
35
|
+
expect(await screen.findByText("Overlay:")).toBeVisible();
|
|
36
|
+
});
|
|
37
|
+
it("if no placeholder is used the overlay should be displayed on hover (hover interactionKind)", async () => {
|
|
38
|
+
const { container } = render(
|
|
39
|
+
<ContextOverlay
|
|
40
|
+
{...ContextOverlayStory.args}
|
|
41
|
+
usePlaceholder={false}
|
|
42
|
+
interactionKind={PopoverInteractionKind.HOVER}
|
|
43
|
+
/>
|
|
44
|
+
);
|
|
45
|
+
fireEvent.mouseEnter(container.getElementsByClassName(overlayWrapper)[0]);
|
|
46
|
+
expect(await screen.findByText("Overlay:")).toBeVisible();
|
|
47
|
+
});
|
|
48
|
+
it("if placeholder is used the overlay should be displayed on click", async () => {
|
|
49
|
+
const { container } = render(<ContextOverlay {...ContextOverlayStory.args} usePlaceholder={true} />);
|
|
50
|
+
fireEvent.click(container.getElementsByClassName(overlayWrapper)[0]);
|
|
51
|
+
expect(await screen.findByText("Overlay:")).toBeVisible();
|
|
52
|
+
});
|
|
53
|
+
it("if placeholder is used the overlay should be displayed on hover (hover interactionKind)", async () => {
|
|
54
|
+
const { container } = render(
|
|
55
|
+
<ContextOverlay
|
|
56
|
+
{...ContextOverlayStory.args}
|
|
57
|
+
usePlaceholder={true}
|
|
58
|
+
interactionKind={PopoverInteractionKind.HOVER}
|
|
59
|
+
/>
|
|
60
|
+
);
|
|
61
|
+
checkForPlaceholderClass(container, 1);
|
|
62
|
+
fireEvent.mouseEnter(container.getElementsByClassName(overlayWrapper)[0]);
|
|
63
|
+
await waitFor(async () => {
|
|
64
|
+
expect(screen.queryByDisplayValue("Overlay:")).toBeNull();
|
|
65
|
+
checkForPlaceholderClass(container, 0);
|
|
66
|
+
// we need to emulate another mouseover to simulate real user behaviour
|
|
67
|
+
fireEvent.mouseOver(container.getElementsByClassName(overlayWrapper)[0]);
|
|
68
|
+
expect(await screen.findByText("Overlay:")).toBeVisible();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -5,12 +5,13 @@ import {
|
|
|
5
5
|
Overlay2Props as BlueprintOverlayProps,
|
|
6
6
|
} from "@blueprintjs/core";
|
|
7
7
|
|
|
8
|
+
import { preventReactFlowActionsClasses } from "../../cmem";
|
|
8
9
|
import { utils } from "../../common";
|
|
9
10
|
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
|
|
10
11
|
import { TestableComponent } from "../interfaces";
|
|
11
12
|
|
|
12
13
|
import { Card } from "./../Card";
|
|
13
|
-
import {
|
|
14
|
+
import { ModalContext } from "./ModalContext";
|
|
14
15
|
|
|
15
16
|
export interface ModalProps extends TestableComponent, BlueprintOverlayProps {
|
|
16
17
|
children: React.ReactNode | React.ReactNode[];
|
|
@@ -43,9 +44,17 @@ export interface ModalProps extends TestableComponent, BlueprintOverlayProps {
|
|
|
43
44
|
* If this option is used inflationary then this could harm the visibility of other overlays.
|
|
44
45
|
*/
|
|
45
46
|
forceTopPosition?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Modal ID that should be globally unique. If a ModalContext is provided this can be used to track opening/closing of this modal.
|
|
49
|
+
*/
|
|
50
|
+
modalId?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Prevents that pan and zooming actions of an existing react-flow instance are triggered while this Modal is open.
|
|
53
|
+
*/
|
|
54
|
+
preventReactFlowEvents?: boolean;
|
|
46
55
|
}
|
|
47
56
|
|
|
48
|
-
export type ModalSize = "tiny" | "small" | "regular" | "large" | "xlarge" | "fullscreen"
|
|
57
|
+
export type ModalSize = "tiny" | "small" | "regular" | "large" | "xlarge" | "fullscreen";
|
|
49
58
|
|
|
50
59
|
/**
|
|
51
60
|
* Displays contents on top of other elements, used to create dialogs.
|
|
@@ -68,8 +77,24 @@ export const Modal = ({
|
|
|
68
77
|
onOpening,
|
|
69
78
|
"data-test-id": dataTestId,
|
|
70
79
|
"data-testid": dataTestid,
|
|
80
|
+
modalId,
|
|
81
|
+
preventReactFlowEvents = true,
|
|
71
82
|
...otherProps
|
|
72
83
|
}: ModalProps) => {
|
|
84
|
+
const modalContext = React.useContext(ModalContext)
|
|
85
|
+
const uniqueModalId = React.useRef<string>(modalId ?? Date.now().toString(36) + Math.random().toString(36).substring(2))
|
|
86
|
+
|
|
87
|
+
React.useEffect(() => {
|
|
88
|
+
return () => {
|
|
89
|
+
// Make sure to always remove flag when modal is removed
|
|
90
|
+
modalContext.setModalOpen(uniqueModalId.current, false)
|
|
91
|
+
}
|
|
92
|
+
}, [])
|
|
93
|
+
|
|
94
|
+
React.useEffect(() => {
|
|
95
|
+
modalContext.setModalOpen(uniqueModalId.current, otherProps.isOpen)
|
|
96
|
+
}, [otherProps.isOpen])
|
|
97
|
+
|
|
73
98
|
const backdropProps: React.HTMLProps<HTMLDivElement> | undefined =
|
|
74
99
|
!canOutsideClickClose && canEscapeKeyClose
|
|
75
100
|
? {
|
|
@@ -117,7 +142,7 @@ export const Modal = ({
|
|
|
117
142
|
<BlueprintOverlay
|
|
118
143
|
{...otherProps}
|
|
119
144
|
backdropProps={backdropProps}
|
|
120
|
-
className={`${overlayClassName} ${preventReactFlowActionsClasses}`}
|
|
145
|
+
className={`${overlayClassName} ${preventReactFlowEvents ? preventReactFlowActionsClasses : ""}`}
|
|
121
146
|
backdropClassName={`${eccgui}-dialog__backdrop`}
|
|
122
147
|
canOutsideClickClose={canOutsideClickClose}
|
|
123
148
|
canEscapeKeyClose={canEscapeKeyClose}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
export interface ModalContextProps {
|
|
4
|
+
/** Set that a specific modal is currently being open (or closed) */
|
|
5
|
+
setModalOpen: (modalId: string, isOpen: boolean) => void;
|
|
6
|
+
|
|
7
|
+
/** The currently opened modals ordered by when they have been opened. Oldest coming first. */
|
|
8
|
+
openModalStack(): string[] | undefined;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Can be provided in the application to react to modal related changes. */
|
|
12
|
+
export const ModalContext = React.createContext<ModalContextProps>({
|
|
13
|
+
setModalOpen: () => {},
|
|
14
|
+
openModalStack: () => [],
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
/** Default implementation for modal context props.
|
|
18
|
+
* Tracks open modals in a stack representation.
|
|
19
|
+
**/
|
|
20
|
+
export const useModalContext = (): ModalContextProps => {
|
|
21
|
+
// A stack of modal IDs. These should reflect a stacked opening of modals on top of each other.
|
|
22
|
+
const currentOpenModalStack = React.useRef<string[]>([]);
|
|
23
|
+
|
|
24
|
+
const setOpenModalStack = ((stackUpdateFunction: (old: string[]) => string[]) => {
|
|
25
|
+
currentOpenModalStack.current = stackUpdateFunction([...currentOpenModalStack.current])
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const setModalOpen = React.useCallback((modalId: string, isOpen: boolean) => {
|
|
29
|
+
setOpenModalStack(old => {
|
|
30
|
+
if (isOpen) {
|
|
31
|
+
return [...old, modalId];
|
|
32
|
+
} else {
|
|
33
|
+
const idx = old.findIndex((id) => modalId === id);
|
|
34
|
+
switch (idx) {
|
|
35
|
+
case -1:
|
|
36
|
+
// Trying to close modal that has not been registered as open!
|
|
37
|
+
return old;
|
|
38
|
+
case old.length - 1:
|
|
39
|
+
return old.slice(0, idx);
|
|
40
|
+
default:
|
|
41
|
+
// Modal in between is closed. Consider all modals after it also as closed.
|
|
42
|
+
return old.slice(0, idx);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}, []);
|
|
47
|
+
|
|
48
|
+
const openModalStack = React.useCallback(() => {
|
|
49
|
+
return currentOpenModalStack.current.length ? [...currentOpenModalStack.current] : undefined
|
|
50
|
+
}, [])
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
openModalStack,
|
|
54
|
+
setModalOpen,
|
|
55
|
+
};
|
|
56
|
+
};
|
|
@@ -15,15 +15,18 @@ export default {
|
|
|
15
15
|
control: false,
|
|
16
16
|
},
|
|
17
17
|
},
|
|
18
|
+
decorators: [
|
|
19
|
+
(Story) => (
|
|
20
|
+
<OverlaysProvider>
|
|
21
|
+
<div style={{ height: "400px" }}>
|
|
22
|
+
<Story />
|
|
23
|
+
</div>
|
|
24
|
+
</OverlaysProvider>
|
|
25
|
+
),
|
|
26
|
+
],
|
|
18
27
|
} as Meta<typeof Modal>;
|
|
19
28
|
|
|
20
|
-
const Template: StoryFn<typeof Modal> = (args) =>
|
|
21
|
-
<OverlaysProvider>
|
|
22
|
-
<div style={{ height: "400px" }}>
|
|
23
|
-
<Modal {...args} />
|
|
24
|
-
</div>
|
|
25
|
-
</OverlaysProvider>
|
|
26
|
-
);
|
|
29
|
+
const Template: StoryFn<typeof Modal> = (args) => <Modal {...args} />;
|
|
27
30
|
|
|
28
31
|
export const Default = Template.bind({});
|
|
29
32
|
Default.args = {
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Classes, OverlaysProvider } from "@blueprintjs/core";
|
|
3
|
+
import { Meta } from "@storybook/react";
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
Button,
|
|
7
|
+
Card,
|
|
8
|
+
CardContent,
|
|
9
|
+
Modal,
|
|
10
|
+
ModalContext,
|
|
11
|
+
ModalContextProps,
|
|
12
|
+
ModalSize,
|
|
13
|
+
Spacing,
|
|
14
|
+
useModalContext,
|
|
15
|
+
} from "./../../../../index";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* `ModalContext` can be used as provider to track a stack of modals.
|
|
19
|
+
*
|
|
20
|
+
* ```(Javascript)
|
|
21
|
+
* import { ModalContext, SimpleDialog } from "@eccenca/gui-elements";
|
|
22
|
+
*
|
|
23
|
+
* const ContextTemplate = () => {
|
|
24
|
+
* const { setModalOpen, openModalStack } = useModalContext();
|
|
25
|
+
* return (
|
|
26
|
+
* <ModalContext.Provider value={{ setModalOpen, openModalStack }}>
|
|
27
|
+
* <SimpleDialog size="large" isOpen>
|
|
28
|
+
* <OtherModal />
|
|
29
|
+
* </SimpleDialog>
|
|
30
|
+
* </ModalContext.Provider>
|
|
31
|
+
* );
|
|
32
|
+
* };
|
|
33
|
+
*
|
|
34
|
+
* const OtherModal = () => {
|
|
35
|
+
* const modalContext = React.useContext(ModalContext);
|
|
36
|
+
* return (
|
|
37
|
+
* <SimpleDialog size="small">
|
|
38
|
+
* <ul>
|
|
39
|
+
* {(modalContext.openModalStack ?? []).map((modalId, idx) => (
|
|
40
|
+
* <li key={modalId}>
|
|
41
|
+
* {idx + 1}. {modalId}
|
|
42
|
+
* </li>
|
|
43
|
+
* ))}
|
|
44
|
+
* </ul>
|
|
45
|
+
* </SimpleDialog>
|
|
46
|
+
* );
|
|
47
|
+
* };
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export default {
|
|
51
|
+
title: "Components/Dialog/ModalContext",
|
|
52
|
+
decorators: [
|
|
53
|
+
(Story) => (
|
|
54
|
+
<OverlaysProvider>
|
|
55
|
+
<div style={{ height: "70vh", position: "relative" }} id={"modalPortal"}>
|
|
56
|
+
<Story />
|
|
57
|
+
</div>
|
|
58
|
+
</OverlaysProvider>
|
|
59
|
+
),
|
|
60
|
+
],
|
|
61
|
+
} as Meta<ModalContextProps>;
|
|
62
|
+
|
|
63
|
+
export const Usage = () => {
|
|
64
|
+
const { setModalOpen, openModalStack } = useModalContext();
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<ModalContext.Provider value={{ setModalOpen, openModalStack }}>
|
|
68
|
+
<ExampleModal id="rootModal" size="large">
|
|
69
|
+
<MiddleModal />
|
|
70
|
+
</ExampleModal>
|
|
71
|
+
</ModalContext.Provider>
|
|
72
|
+
);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const ModalContent = ({ children }: React.HTMLAttributes<HTMLDivElement>) => {
|
|
76
|
+
return (
|
|
77
|
+
<Card style={{ height: "100%" }}>
|
|
78
|
+
<CardContent>{children}</CardContent>
|
|
79
|
+
</Card>
|
|
80
|
+
);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/** Component for nested modals. */
|
|
84
|
+
const ExampleModal = ({
|
|
85
|
+
id,
|
|
86
|
+
size,
|
|
87
|
+
children,
|
|
88
|
+
}: {
|
|
89
|
+
id?: string;
|
|
90
|
+
size: ModalSize;
|
|
91
|
+
children?: React.HTMLAttributes<HTMLDivElement>["children"];
|
|
92
|
+
}) => {
|
|
93
|
+
const [isOpen, setIsOpen] = React.useState(true);
|
|
94
|
+
const [portalElement, setPortalElement] = React.useState<HTMLElement | undefined>();
|
|
95
|
+
|
|
96
|
+
React.useEffect(() => {
|
|
97
|
+
setPortalElement(document.getElementById("modalPortal")!);
|
|
98
|
+
}, []);
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<Modal
|
|
102
|
+
modalId={id}
|
|
103
|
+
size={size}
|
|
104
|
+
isOpen={isOpen}
|
|
105
|
+
usePortal={true}
|
|
106
|
+
portalContainer={portalElement}
|
|
107
|
+
hasBackdrop={true}
|
|
108
|
+
onOpened={() => {
|
|
109
|
+
// workaround, Blueprint attach a class to body tht prevents scrolling, probably it is attached to the wrong portal
|
|
110
|
+
document.body.classList.remove(Classes.OVERLAY_OPEN);
|
|
111
|
+
}}
|
|
112
|
+
>
|
|
113
|
+
<ModalContent>
|
|
114
|
+
Modal with constant modal ID "{id}".
|
|
115
|
+
<Spacing />
|
|
116
|
+
<TrackingContent />
|
|
117
|
+
<Spacing />
|
|
118
|
+
{children}
|
|
119
|
+
<Spacing />
|
|
120
|
+
<Button key={"close"} onClick={() => setIsOpen(false)}>
|
|
121
|
+
Close
|
|
122
|
+
</Button>
|
|
123
|
+
</ModalContent>
|
|
124
|
+
</Modal>
|
|
125
|
+
);
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const InnerModal = () => {
|
|
129
|
+
return <ExampleModal id="innerModal" size="small" />;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const MiddleModal = () => {
|
|
133
|
+
return (
|
|
134
|
+
<ExampleModal id="middleModal" size="regular">
|
|
135
|
+
<InnerModal />
|
|
136
|
+
</ExampleModal>
|
|
137
|
+
);
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
/** Shows the current stack of open modals. */
|
|
141
|
+
const TrackingContent = () => {
|
|
142
|
+
const modalContext = React.useContext(ModalContext);
|
|
143
|
+
|
|
144
|
+
return (
|
|
145
|
+
<ul>
|
|
146
|
+
{(modalContext.openModalStack() ?? []).map((modalId, idx) => (
|
|
147
|
+
<li key={modalId}>
|
|
148
|
+
{idx + 1}. {modalId}
|
|
149
|
+
</li>
|
|
150
|
+
))}
|
|
151
|
+
</ul>
|
|
152
|
+
);
|
|
153
|
+
};
|
|
@@ -46,3 +46,19 @@
|
|
|
46
46
|
flex-basis: auto;
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
+
|
|
50
|
+
@media print {
|
|
51
|
+
.#{$eccgui}-flexible__container,
|
|
52
|
+
.#{$eccgui}-flexible__item {
|
|
53
|
+
position: relative;
|
|
54
|
+
display: block;
|
|
55
|
+
width: auto;
|
|
56
|
+
height: auto;
|
|
57
|
+
padding: 0;
|
|
58
|
+
margin: 0;
|
|
59
|
+
|
|
60
|
+
&:is(.#{$eccgui}-flexible__item) {
|
|
61
|
+
margin-bottom: $eccgui-size-block-whitespace;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -86,3 +86,20 @@ $grid-gutter: rem($eccgui-size-grid-gutter);
|
|
|
86
86
|
flex-wrap: nowrap;
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
|
+
|
|
90
|
+
@media print {
|
|
91
|
+
.#{$eccgui}-grid,
|
|
92
|
+
.#{$eccgui}-grid__row,
|
|
93
|
+
.#{$eccgui}-grid__column {
|
|
94
|
+
position: relative;
|
|
95
|
+
display: block;
|
|
96
|
+
width: auto;
|
|
97
|
+
height: auto;
|
|
98
|
+
padding: 0;
|
|
99
|
+
margin: 0;
|
|
100
|
+
|
|
101
|
+
&:is(.#{$eccgui}-grid__column) {
|
|
102
|
+
margin-bottom: $eccgui-size-block-whitespace;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -11,19 +11,22 @@ export default {
|
|
|
11
11
|
subcomponents: { GridRow, GridColumn },
|
|
12
12
|
argTypes: {
|
|
13
13
|
children: {
|
|
14
|
-
control:
|
|
14
|
+
control: false,
|
|
15
15
|
},
|
|
16
16
|
},
|
|
17
|
+
decorators: [
|
|
18
|
+
(Story) => (
|
|
19
|
+
<div style={{ minHeight: "30vh", position: "relative" }}>
|
|
20
|
+
<Story />
|
|
21
|
+
</div>
|
|
22
|
+
),
|
|
23
|
+
],
|
|
17
24
|
} as Meta<typeof Grid>;
|
|
18
25
|
|
|
19
|
-
const Template: StoryFn<typeof Grid> = (args) =>
|
|
20
|
-
<div style={{ minHeight: "30vh", position: "relative" }}>
|
|
21
|
-
<Grid {...args} />
|
|
22
|
-
</div>
|
|
23
|
-
);
|
|
26
|
+
const Template: StoryFn<typeof Grid> = (args) => <Grid {...args} />;
|
|
24
27
|
|
|
25
28
|
export const Default = Template.bind({});
|
|
26
29
|
Default.args = {
|
|
27
|
-
children: <GridRow {...RowExample.args} verticalStretched />,
|
|
30
|
+
children: [<GridRow {...RowExample.args} verticalStretched />, <GridRow {...RowExample.args} verticalStretched />],
|
|
28
31
|
verticalStretchable: true,
|
|
29
32
|
};
|