@eccenca/gui-elements 23.2.0 → 23.3.0-rc.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 (114) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/cjs/cmem/react-flow/ReactFlow/ReactFlow.js +5 -1
  3. package/dist/cjs/cmem/react-flow/ReactFlow/ReactFlow.js.map +1 -1
  4. package/dist/cjs/cmem/react-flow/StickyNoteModal/StickyNoteModal.js +9 -11
  5. package/dist/cjs/cmem/react-flow/StickyNoteModal/StickyNoteModal.js.map +1 -1
  6. package/dist/cjs/cmem/react-flow/extensions/ReactFlowHotkeyContext.js +12 -0
  7. package/dist/cjs/cmem/react-flow/extensions/ReactFlowHotkeyContext.js.map +1 -0
  8. package/dist/cjs/components/Application/ApplicationHeader.js +2 -3
  9. package/dist/cjs/components/Application/ApplicationHeader.js.map +1 -1
  10. package/dist/cjs/components/Dialog/Modal.js +17 -8
  11. package/dist/cjs/components/Dialog/Modal.js.map +1 -1
  12. package/dist/cjs/components/Dialog/SimpleDialog.js +15 -2
  13. package/dist/cjs/components/Dialog/SimpleDialog.js.map +1 -1
  14. package/dist/cjs/components/Icon/IconButton.js +1 -1
  15. package/dist/cjs/components/Icon/IconButton.js.map +1 -1
  16. package/dist/cjs/components/Icon/canonicalIconNames.js +1 -0
  17. package/dist/cjs/components/Icon/canonicalIconNames.js.map +1 -1
  18. package/dist/cjs/components/OverviewItem/OverviewItemDepiction.js +3 -6
  19. package/dist/cjs/components/OverviewItem/OverviewItemDepiction.js.map +1 -1
  20. package/dist/cjs/components/PropertyValuePair/PropertyName.js +3 -3
  21. package/dist/cjs/components/PropertyValuePair/PropertyName.js.map +1 -1
  22. package/dist/cjs/components/Separation/Spacing.js +18 -4
  23. package/dist/cjs/components/Separation/Spacing.js.map +1 -1
  24. package/dist/cjs/components/TextField/TextField.js +23 -3
  25. package/dist/cjs/components/TextField/TextField.js.map +1 -1
  26. package/dist/cjs/extensions/codemirror/CodeMirror.js +39 -7
  27. package/dist/cjs/extensions/codemirror/CodeMirror.js.map +1 -1
  28. package/dist/cjs/extensions/react-flow/handles/HandleDefault.js +26 -5
  29. package/dist/cjs/extensions/react-flow/handles/HandleDefault.js.map +1 -1
  30. package/dist/cjs/extensions/react-flow/handles/HandleTools.js +27 -0
  31. package/dist/cjs/extensions/react-flow/handles/HandleTools.js.map +1 -0
  32. package/dist/cjs/extensions/react-flow/index.js +2 -0
  33. package/dist/cjs/extensions/react-flow/index.js.map +1 -1
  34. package/dist/cjs/extensions/react-flow/nodes/NodeContent.js +25 -5
  35. package/dist/cjs/extensions/react-flow/nodes/NodeContent.js.map +1 -1
  36. package/dist/esm/cmem/markdown/Markdown.js +1 -1
  37. package/dist/esm/cmem/react-flow/ReactFlow/ReactFlow.js +5 -1
  38. package/dist/esm/cmem/react-flow/ReactFlow/ReactFlow.js.map +1 -1
  39. package/dist/esm/cmem/react-flow/StickyNoteModal/StickyNoteModal.js +9 -11
  40. package/dist/esm/cmem/react-flow/StickyNoteModal/StickyNoteModal.js.map +1 -1
  41. package/dist/esm/cmem/react-flow/extensions/ReactFlowHotkeyContext.js +6 -0
  42. package/dist/esm/cmem/react-flow/extensions/ReactFlowHotkeyContext.js.map +1 -0
  43. package/dist/esm/components/Application/ApplicationHeader.js +2 -3
  44. package/dist/esm/components/Application/ApplicationHeader.js.map +1 -1
  45. package/dist/esm/components/Dialog/Modal.js +18 -9
  46. package/dist/esm/components/Dialog/Modal.js.map +1 -1
  47. package/dist/esm/components/Dialog/SimpleDialog.js +14 -1
  48. package/dist/esm/components/Dialog/SimpleDialog.js.map +1 -1
  49. package/dist/esm/components/Icon/IconButton.js +1 -1
  50. package/dist/esm/components/Icon/IconButton.js.map +1 -1
  51. package/dist/esm/components/Icon/canonicalIconNames.js +1 -0
  52. package/dist/esm/components/Icon/canonicalIconNames.js.map +1 -1
  53. package/dist/esm/components/OverviewItem/OverviewItemDepiction.js +3 -6
  54. package/dist/esm/components/OverviewItem/OverviewItemDepiction.js.map +1 -1
  55. package/dist/esm/components/PropertyValuePair/PropertyName.js +3 -3
  56. package/dist/esm/components/PropertyValuePair/PropertyName.js.map +1 -1
  57. package/dist/esm/components/Separation/Spacing.js +28 -4
  58. package/dist/esm/components/Separation/Spacing.js.map +1 -1
  59. package/dist/esm/components/TextField/TextField.js +25 -5
  60. package/dist/esm/components/TextField/TextField.js.map +1 -1
  61. package/dist/esm/extensions/codemirror/CodeMirror.js +49 -6
  62. package/dist/esm/extensions/codemirror/CodeMirror.js.map +1 -1
  63. package/dist/esm/extensions/react-flow/handles/HandleDefault.js +45 -8
  64. package/dist/esm/extensions/react-flow/handles/HandleDefault.js.map +1 -1
  65. package/dist/esm/extensions/react-flow/handles/HandleTools.js +31 -0
  66. package/dist/esm/extensions/react-flow/handles/HandleTools.js.map +1 -0
  67. package/dist/esm/extensions/react-flow/index.js +2 -0
  68. package/dist/esm/extensions/react-flow/index.js.map +1 -1
  69. package/dist/esm/extensions/react-flow/nodes/NodeContent.js +32 -12
  70. package/dist/esm/extensions/react-flow/nodes/NodeContent.js.map +1 -1
  71. package/dist/types/cmem/react-flow/extensions/ReactFlowHotkeyContext.d.ts +8 -0
  72. package/dist/types/components/Application/ApplicationHeader.d.ts +1 -2
  73. package/dist/types/components/Dialog/Modal.d.ts +13 -6
  74. package/dist/types/components/Dialog/SimpleDialog.d.ts +12 -1
  75. package/dist/types/components/Icon/canonicalIconNames.d.ts +1 -1
  76. package/dist/types/components/PropertyValuePair/PropertyName.d.ts +7 -1
  77. package/dist/types/components/Separation/Spacing.d.ts +2 -2
  78. package/dist/types/components/TextField/TextField.d.ts +4 -2
  79. package/dist/types/extensions/codemirror/CodeMirror.d.ts +17 -3
  80. package/dist/types/extensions/react-flow/handles/HandleDefault.d.ts +2 -2
  81. package/dist/types/extensions/react-flow/handles/HandleTools.d.ts +6 -0
  82. package/dist/types/extensions/react-flow/index.d.ts +2 -0
  83. package/dist/types/extensions/react-flow/nodes/NodeContent.d.ts +21 -1
  84. package/package.json +14 -12
  85. package/scripts/compile-sass.ts +1 -1
  86. package/src/cmem/react-flow/ReactFlow/ReactFlow.tsx +10 -0
  87. package/src/cmem/react-flow/StickyNoteModal/StickyNoteModal.tsx +10 -12
  88. package/src/cmem/react-flow/extensions/ReactFlowHotkeyContext.ts +14 -0
  89. package/src/components/Application/ApplicationHeader.tsx +8 -13
  90. package/src/components/Application/_header.scss +17 -17
  91. package/src/components/Application/_toolbar.scss +22 -33
  92. package/src/components/AutoSuggestion/tests/AutoSuggestion.test.tsx +34 -21
  93. package/src/components/AutoSuggestion/tests/SingleLineCodeEditor.test.tsx +20 -9
  94. package/src/components/Dialog/Modal.tsx +62 -37
  95. package/src/components/Dialog/SimpleDialog.tsx +19 -1
  96. package/src/components/Dialog/dialog.scss +29 -17
  97. package/src/components/Icon/IconButton.tsx +1 -1
  98. package/src/components/Icon/canonicalIconNames.tsx +2 -0
  99. package/src/components/OverviewItem/OverviewItemDepiction.tsx +8 -16
  100. package/src/components/PropertyValuePair/PropertyName.tsx +15 -4
  101. package/src/components/Separation/Spacing.tsx +12 -8
  102. package/src/components/TextField/TextField.tsx +32 -6
  103. package/src/components/Tooltip/tooltip.scss +15 -1
  104. package/src/extensions/codemirror/CodeMirror.tsx +62 -8
  105. package/src/extensions/codemirror/_codemirror.scss +53 -8
  106. package/src/extensions/react-flow/edges/stories/EdgeDefault.stories.tsx +43 -44
  107. package/src/extensions/react-flow/handles/HandleDefault.tsx +40 -33
  108. package/src/extensions/react-flow/handles/HandleTools.tsx +22 -0
  109. package/src/extensions/react-flow/handles/_handles.scss +64 -44
  110. package/src/extensions/react-flow/handles/stories/HandleDefault.stories.tsx +33 -27
  111. package/src/extensions/react-flow/index.ts +2 -0
  112. package/src/extensions/react-flow/nodes/NodeContent.tsx +62 -2
  113. package/src/extensions/react-flow/nodes/_nodes.scss +170 -110
  114. package/src/extensions/react-flow/nodes/stories/NodeDefault.stories.tsx +32 -34
@@ -1,38 +1,42 @@
1
1
  import React from "react";
2
+
2
3
  import { CLASSPREFIX as eccgui } from "../../configuration/constants";
3
4
 
4
- export interface SpacingProps {
5
+ export interface SpacingProps extends React.HTMLAttributes<HTMLDivElement> {
5
6
  /**
6
7
  * Set the amount of white space that separates two elements.
7
8
  */
8
- size?: "tiny" | "small" | "medium" | "large" | "xlarge"
9
+ size?: "tiny" | "small" | "medium" | "large" | "xlarge";
9
10
  /**
10
11
  * If set then is a ruler displayed in the middle of the spacing area.
11
12
  * The direction of the ruler is used from the spacing.
12
13
  */
13
- hasDivider?: boolean
14
+ hasDivider?: boolean;
14
15
  /**
15
16
  * If set then the spacing separates two elements on the horizontal axis.
16
17
  * The spacing area then is created on a vertical axis.
17
18
  */
18
- vertical?: boolean
19
+ vertical?: boolean;
19
20
  }
20
21
 
21
22
  /**
22
23
  * Adds horizontal or vertical space between neighbouring elements.
23
24
  * It also can add a visual ruler inside.
24
25
  */
25
- export const Spacing = ({ size = "medium", hasDivider = false, vertical = false }: SpacingProps) => {
26
+ export const Spacing = ({ size = "medium", hasDivider = false, vertical = false, ...otherDivProps }: SpacingProps) => {
26
27
  const direction = vertical ? "vertical" : "horizontal";
27
28
  return (
28
29
  <div
29
30
  className={
30
- `${eccgui}-separation__spacing-` + direction +
31
- ` ${eccgui}-separation__spacing--` + size +
31
+ `${eccgui}-separation__spacing-` +
32
+ direction +
33
+ ` ${eccgui}-separation__spacing--` +
34
+ size +
32
35
  (hasDivider ? ` ${eccgui}-separation__spacing--hasdivider` : "")
33
36
  }
37
+ {...otherDivProps}
34
38
  />
35
39
  );
36
- }
40
+ };
37
41
 
38
42
  export default Spacing;
@@ -1,15 +1,15 @@
1
- import React from "react";
1
+ import React, {KeyboardEventHandler, RefObject} from "react";
2
2
  import {
3
- InputGroup as BlueprintInputGroup,
4
3
  Classes as BlueprintClassNames,
5
- Intent as BlueprintIntent,
6
- MaybeElement,
7
4
  HTMLInputProps,
5
+ InputGroup as BlueprintInputGroup,
8
6
  InputGroupProps2,
7
+ Intent as BlueprintIntent,
8
+ MaybeElement,
9
9
  } from "@blueprintjs/core";
10
- import { IntentTypes, Definitions as IntentDefinitions } from "../../common/Intent";
10
+ import {Definitions as IntentDefinitions, IntentTypes} from "../../common/Intent";
11
11
  import Icon from "../Icon/Icon";
12
- import { CLASSPREFIX as eccgui } from "../../configuration/constants";
12
+ import {CLASSPREFIX as eccgui} from "../../configuration/constants";
13
13
  import {ValidIconName} from "../Icon/canonicalIconNames";
14
14
  import {InvisibleCharacterWarningProps, useTextValidation} from "./useTextValidation";
15
15
 
@@ -50,6 +50,9 @@ export interface TextFieldProps extends Partial<Omit<InputGroupProps2, "intent"
50
50
  * If set, allows to be informed of invisible, hard to spot characters in the string value.
51
51
  */
52
52
  invisibleCharacterWarning?: InvisibleCharacterWarningProps
53
+
54
+ /** If true pressing the Escape key will blur/de-focus the input field. Default: false */
55
+ escapeToBlur?: boolean
53
56
  }
54
57
 
55
58
  /**
@@ -64,8 +67,10 @@ export const TextField = ({
64
67
  fullWidth = true,
65
68
  leftIcon,
66
69
  invisibleCharacterWarning,
70
+ escapeToBlur = false,
67
71
  ...otherProps
68
72
  }: TextFieldProps) => {
73
+ const inputRef = React.useRef<HTMLInputElement | null>(null)
69
74
  let deprecatedIntent;
70
75
  switch (true) {
71
76
  case hasStatePrimary:
@@ -84,6 +89,25 @@ export const TextField = ({
84
89
  break;
85
90
  }
86
91
 
92
+ const handleLabelEscape = React.useCallback(() => {
93
+ inputRef.current?.blur()
94
+ if(otherProps.inputRef) {
95
+ const otherInputRef = otherProps.inputRef as RefObject<HTMLInputElement>
96
+ if(otherInputRef.current) {
97
+ otherInputRef.current.blur()
98
+ }
99
+ }
100
+ }, [])
101
+
102
+ const onKeyDown: KeyboardEventHandler<HTMLInputElement> = React.useCallback((event) => {
103
+ if(escapeToBlur && event.key === "Escape") {
104
+ event.preventDefault()
105
+ handleLabelEscape()
106
+ return false
107
+ }
108
+ return otherProps.onKeyDown?.(event)
109
+ }, [otherProps.onKeyDown, escapeToBlur])
110
+
87
111
  const {
88
112
  intent = deprecatedIntent,
89
113
  ...otherBlueprintInputGroupProps
@@ -110,6 +134,7 @@ export const TextField = ({
110
134
 
111
135
  return (
112
136
  <BlueprintInputGroup
137
+ inputRef={inputRef}
113
138
  className={
114
139
  `${eccgui}-textfield` +
115
140
  (intent ? ` ${eccgui}-intent--${intent}` : "") +
@@ -133,6 +158,7 @@ export const TextField = ({
133
158
  }
134
159
  dir={"auto"}
135
160
  onChange={maybeWrappedOnChange}
161
+ onKeyDown={otherProps.onKeyDown || escapeToBlur ? onKeyDown : undefined}
136
162
  />
137
163
  );
138
164
  }
@@ -2,6 +2,7 @@
2
2
  $eccgui-size-typo-tooltip: $eccgui-size-typo-caption !default;
3
3
  $eccgui-size-typo-tooltip-lineheight: $eccgui-size-typo-caption-lineheight !default;
4
4
  $eccgui-size-tooltip-width: 20em !default;
5
+
5
6
  // library vars
6
7
  $tooltip2-background-color: $eccgui-color-applicationheader-text; // !default;
7
8
  $tooltip2-text-color: $eccgui-color-applicationheader-background; // !default;
@@ -15,8 +16,8 @@ $tooltip2-padding-horizontal: $eccgui-size-block-whitespace * 0.5; // !default;
15
16
  .#{$ns}-tooltip2 {
16
17
  font-size: $eccgui-size-typo-tooltip;
17
18
  line-height: $eccgui-size-typo-tooltip-lineheight;
18
- white-space: normal;
19
19
  overflow-wrap: break-word;
20
+ white-space: normal;
20
21
  }
21
22
 
22
23
  .#{$eccgui}-tooltip--small {
@@ -39,3 +40,16 @@ $tooltip2-padding-horizontal: $eccgui-size-block-whitespace * 0.5; // !default;
39
40
  text-decoration: none;
40
41
  }
41
42
  }
43
+
44
+ .#{$prefix}--tooltip-content {
45
+ max-width: $eccgui-size-tooltip-width;
46
+ padding: 0.25 * $eccgui-size-block-whitespace 0.5 * $eccgui-size-block-whitespace;
47
+ // align Carbon tooltips, they are used automatically by a few carbon based elements, e.g. pagination buttons
48
+ font-size: $eccgui-size-typo-tooltip;
49
+ line-height: $eccgui-size-typo-tooltip-lineheight;
50
+ overflow-wrap: break-word;
51
+ white-space: normal;
52
+
53
+ --cds-popover-background-color: #{$tooltip2-background-color};
54
+ --cds-popover-text-color: #{$tooltip2-text-color};
55
+ }
@@ -1,12 +1,32 @@
1
- import React, { useEffect, useRef } from "react";
2
- import CodeMirror from "codemirror";
3
- import { CLASSPREFIX as eccgui } from "../../configuration/constants";
1
+ import React, { TextareaHTMLAttributes, useEffect, useRef } from "react";
2
+ import CodeMirror, { ModeSpec, ModeSpecOptions } from "codemirror";
3
+
4
4
  import "codemirror/mode/markdown/markdown.js";
5
5
  import "codemirror/mode/python/python.js";
6
6
  import "codemirror/mode/sparql/sparql.js";
7
7
  import "codemirror/mode/sql/sql.js";
8
8
  import "codemirror/mode/turtle/turtle.js";
9
9
  import "codemirror/mode/xml/xml.js";
10
+ import "codemirror/mode/jinja2/jinja2.js";
11
+ import "codemirror/mode/yaml/yaml.js";
12
+ import "codemirror/mode/javascript/javascript.js";
13
+
14
+ import { CLASSPREFIX as eccgui } from "../../configuration/constants";
15
+
16
+ export const supportedCodeEditorModes = [
17
+ "markdown",
18
+ "python",
19
+ "sparql",
20
+ "sql",
21
+ "turtle",
22
+ "xml",
23
+ "jinja2",
24
+ "yaml",
25
+ "json",
26
+ "undefined",
27
+ ] as const;
28
+ type SupportedModesTuple = typeof supportedCodeEditorModes;
29
+ export type SupportedCodeEditorModes = SupportedModesTuple[number];
10
30
 
11
31
  export interface CodeEditorProps {
12
32
  /**
@@ -26,7 +46,7 @@ export interface CodeEditorProps {
26
46
  /**
27
47
  * Syntax mode of the code editor.
28
48
  */
29
- mode?: "markdown" | "python" | "sparql" | "sql" | "turtle" | "xml" | "undefined";
49
+ mode?: SupportedCodeEditorModes;
30
50
  /**
31
51
  * Default value used first when the editor is instanciated.
32
52
  */
@@ -35,6 +55,17 @@ export interface CodeEditorProps {
35
55
  * If enabled the code editor won't show numbers before each line.
36
56
  */
37
57
  preventLineNumbers?: boolean;
58
+
59
+ /** Set read-only mode. Default: false */
60
+ readOnly?: boolean;
61
+
62
+ /** Optional height of the component */
63
+ height?: number | string;
64
+
65
+ /** Long lines are wrapped and displayed on multiple lines */
66
+ wrapLines?: boolean;
67
+
68
+ outerDivAttributes?: Partial<TextareaHTMLAttributes<HTMLDivElement>>;
38
69
  }
39
70
 
40
71
  /**
@@ -47,29 +78,38 @@ export const CodeEditor = ({
47
78
  mode = "undefined",
48
79
  preventLineNumbers = false,
49
80
  defaultValue,
81
+ readOnly = false,
82
+ height,
83
+ wrapLines = false,
84
+ outerDivAttributes,
50
85
  }: CodeEditorProps) => {
51
86
  const domRef = useRef<HTMLTextAreaElement>(null);
52
87
 
53
88
  useEffect(() => {
54
89
  const editorInstance = CodeMirror.fromTextArea(domRef.current!, {
55
- mode: mode === "undefined" ? undefined : mode,
56
- lineWrapping: true,
90
+ mode: convertMode(mode),
91
+ lineWrapping: wrapLines,
57
92
  lineNumbers: !preventLineNumbers,
58
93
  tabSize: 2,
59
94
  theme: "xq-light",
95
+ readOnly: readOnly,
60
96
  });
61
97
 
62
98
  editorInstance.on("change", (api) => {
63
99
  onChange(api.getValue());
64
100
  });
65
101
 
102
+ if (height) {
103
+ editorInstance.setSize(null, height);
104
+ }
105
+
66
106
  return function cleanup() {
67
107
  editorInstance.toTextArea();
68
108
  };
69
109
  }, [onChange, mode, preventLineNumbers]);
70
110
 
71
111
  return (
72
- <div className={`${eccgui}-codeeditor`}>
112
+ <div {...outerDivAttributes} className={`${eccgui}-codeeditor`}>
73
113
  <textarea
74
114
  ref={domRef}
75
115
  /**
@@ -78,10 +118,24 @@ export const CodeEditor = ({
78
118
  * unchanged from the code what was took over here.
79
119
  */
80
120
  data-test-id="codemirror-wrapper"
81
- id={!!id ? id : `codemirror-${name}`}
121
+ id={id ? id : `codemirror-${name}`}
82
122
  name={name}
83
123
  defaultValue={defaultValue}
84
124
  />
85
125
  </div>
86
126
  );
87
127
  };
128
+
129
+ const convertMode = (mode: SupportedCodeEditorModes | undefined): string | ModeSpec<ModeSpecOptions> | undefined => {
130
+ switch (mode) {
131
+ case "undefined":
132
+ return undefined;
133
+ case "json":
134
+ return {
135
+ name: "javascript",
136
+ json: true,
137
+ };
138
+ default:
139
+ return mode;
140
+ }
141
+ };
@@ -2,31 +2,76 @@
2
2
  @import "~codemirror/theme/xq-light";
3
3
 
4
4
  // adjustments
5
-
5
+ // stylelint-disable selector-class-pattern
6
6
  .#{$eccgui}-codeeditor {
7
+ max-width: 100%;
8
+
7
9
  .CodeMirror {
8
- border-radius: $pt-border-radius;
9
10
  clip-path: unset !important; // we may check later why they set inset(0) now
11
+ border-radius: $pt-border-radius;
10
12
 
11
13
  // get them a "border" like input boxes from blueprintjs
12
14
  box-shadow: input-transition-shadow($input-shadow-color-focus), $pt-input-box-shadow;
15
+
13
16
  &.CodeMirror-focused {
14
17
  box-shadow: input-transition-shadow($input-shadow-color-focus, true), $input-box-shadow-focus;
15
18
  }
16
19
 
17
- .CodeMirror-gutters {
18
- // allow "borders" to shine through
19
- background-color: rgba(0,0,0,0.05);
20
- }
21
-
22
20
  .CodeMirror-scroll {
21
+ width: calc(100% - 2px);
22
+ height: calc(100% - 2px);
23
+
24
+ // fix size to prevent wrong calculation of other elements
25
+ padding: 0;
26
+ margin: 1px;
23
27
  cursor: text;
28
+
29
+ // remove scrollbars, codemirrow has own elements to fake them
30
+ scrollbar-width: none; // Firefox
31
+ -ms-overflow-style: none; // IE, Edge
32
+ &::-webkit-scrollbar {
33
+ display: none; // Chrome, Safari and Opera
34
+ }
35
+ }
36
+
37
+ .CodeMirror-hscrollbar {
38
+ bottom: 1px;
39
+ height: $eccgui-size-inline-whitespace !important;
40
+ }
41
+
42
+ .CodeMirror-vscrollbar {
43
+ top: 1px;
44
+ right: 1px;
45
+ width: $eccgui-size-inline-whitespace !important;
46
+ }
47
+
48
+ .CodeMirror-scrollbar-filler {
49
+ right: 1px;
50
+ bottom: 1px;
51
+ }
52
+
53
+ .CodeMirror-sizer {
54
+ border-right-width: $eccgui-size-inline-whitespace !important;
24
55
  }
25
56
  }
26
57
  }
27
58
 
28
59
  .#{$prefix}--accordion__content {
29
- .CodeMirror-scroll, .CodeMirror-sizer, .CodeMirror-gutter, .CodeMirror-gutters, .CodeMirror-linenumber {
60
+ .CodeMirror-scroll,
61
+ .CodeMirror-sizer,
62
+ .CodeMirror-gutter,
63
+ .CodeMirror-gutters,
64
+ .CodeMirror-linenumber {
30
65
  box-sizing: content-box;
31
66
  }
32
67
  }
68
+
69
+ // fix a few xq-light colors regarding bad contrasts
70
+
71
+ .cm-s-xq-light {
72
+ // add other classes if necessary
73
+ .cm-meta {
74
+ filter: invert(1);
75
+ }
76
+ }
77
+ // stylelint-enable selector-class-pattern
@@ -1,24 +1,24 @@
1
- import React, { useState, useEffect, useCallback } from "react";
2
- import { ComponentStory, ComponentMeta } from "@storybook/react";
3
- import { ReactFlow, EdgeLabel, EdgeLabelObject } from "./../../../../../index";
4
- import { ArrowHeadType, Elements, getMarkerEnd, ReactFlowProvider } from 'react-flow-renderer';
1
+ import React, { useCallback, useEffect, useState } from "react";
2
+ import { ArrowHeadType, Elements, getMarkerEnd, ReactFlowProvider } from "react-flow-renderer";
3
+ import { ComponentMeta, ComponentStory } from "@storybook/react";
5
4
 
5
+ import { EdgeLabel, EdgeLabelObject, ReactFlow } from "./../../../../../index";
6
6
  import { EdgeDefault, EdgeDefaultDataProps as EdgeData } from "./../EdgeDefault";
7
7
  import { edgeTypes } from "./../edgeTypes";
8
8
 
9
9
  const EdgeDefaultDataProps = (data: EdgeData) => {
10
10
  // this is only a mock to get it as sub element in the table
11
11
  return <></>;
12
- }
12
+ };
13
13
 
14
14
  export default {
15
- title: "Extensions/React Flow/Default Edge",
15
+ title: "Extensions/React Flow/Edge",
16
16
  component: EdgeDefault,
17
17
  subcomponents: { EdgeDefaultDataProps },
18
18
  argTypes: {
19
19
  type: {
20
20
  control: "select",
21
- options: [...(Object.keys(edgeTypes))],
21
+ options: [...Object.keys(edgeTypes)],
22
22
  },
23
23
  },
24
24
  } as ComponentMeta<typeof EdgeDefault>;
@@ -33,7 +33,9 @@ const EdgeDefaultExample = (args: any) => {
33
33
  id: args.source,
34
34
  type: "default",
35
35
  data: {
36
- label: "Default ", content: "Example content.", minimalShape: "none",
36
+ label: "Default ",
37
+ content: "Example content.",
38
+ minimalShape: "none",
37
39
  },
38
40
  position: { x: 50, y: 200 },
39
41
  },
@@ -41,13 +43,15 @@ const EdgeDefaultExample = (args: any) => {
41
43
  id: args.target,
42
44
  type: "default",
43
45
  data: {
44
- label: "Default ", content: "Example content.", minimalShape: "none",
46
+ label: "Default ",
47
+ content: "Example content.",
48
+ minimalShape: "none",
45
49
  },
46
50
  position: { x: 600, y: 200 },
47
51
  },
48
52
  {
49
- ...args
50
- }
53
+ ...args,
54
+ },
51
55
  ] as Elements);
52
56
  }, [args]);
53
57
 
@@ -60,31 +64,30 @@ const EdgeDefaultExample = (args: any) => {
60
64
  [reactflowInstance]
61
65
  );
62
66
 
63
- return <ReactFlowProvider>
64
- <ReactFlow
65
- elements={elements}
66
- style={{ height: '400px' }}
67
- onLoad={onLoad}
68
- edgeTypes={ edgeTypes }
69
- defaultZoom={1}
70
- />
71
- </ReactFlowProvider>
72
- }
67
+ return (
68
+ <ReactFlowProvider>
69
+ <ReactFlow
70
+ elements={elements}
71
+ style={{ height: "400px" }}
72
+ onLoad={onLoad}
73
+ edgeTypes={edgeTypes}
74
+ defaultZoom={1}
75
+ />
76
+ </ReactFlowProvider>
77
+ );
78
+ };
73
79
 
74
- const Template: ComponentStory<typeof EdgeDefault> = (args) => (
75
- <EdgeDefaultExample {...args} />
76
- );
80
+ const Template: ComponentStory<typeof EdgeDefault> = (args) => <EdgeDefaultExample {...args} />;
77
81
 
78
82
  export const Default = Template.bind({});
79
83
  Default.args = {
80
- id: 'default',
81
- type: 'dangerStep',
84
+ id: "default",
85
+ type: "dangerStep",
82
86
  label: "edge",
83
87
  arrowHeadType: "arrowclosed",
84
- source: 'node-1',
85
- target: 'node-2',
86
- data: {
87
- }
88
+ source: "node-1",
89
+ target: "node-2",
90
+ data: {},
88
91
  };
89
92
 
90
93
  export const CustomLabel = Template.bind({});
@@ -94,14 +97,12 @@ CustomLabel.args = {
94
97
  arrowHeadType: undefined,
95
98
  label: undefined,
96
99
  data: {
97
- renderLabel: (
98
- edgeCenter: [number, number, number, number]
99
- ) => (
100
+ renderLabel: (edgeCenter: [number, number, number, number]) => (
100
101
  <EdgeLabelObject edgeCenter={edgeCenter}>
101
- <EdgeLabel text="Custom label that is very long" />
102
+ <EdgeLabel text="Custom label that is very long" />
102
103
  </EdgeLabelObject>
103
- )
104
- }
104
+ ),
105
+ },
105
106
  };
106
107
 
107
108
  export const InverseEdge = Template.bind({});
@@ -111,10 +112,8 @@ InverseEdge.args = {
111
112
  arrowHeadType: undefined,
112
113
  data: {
113
114
  inversePath: true,
114
- markerStart: getMarkerEnd(
115
- `${ArrowHeadType.ArrowClosed}-inverse` as ArrowHeadType
116
- ),
117
- }
115
+ markerStart: getMarkerEnd(`${ArrowHeadType.ArrowClosed}-inverse` as ArrowHeadType),
116
+ },
118
117
  };
119
118
 
120
119
  export const AdjustStrokeType = Template.bind({});
@@ -122,7 +121,7 @@ AdjustStrokeType.args = {
122
121
  ...Default.args,
123
122
  data: {
124
123
  strokeType: "double",
125
- }
124
+ },
126
125
  };
127
126
 
128
127
  export const AdjustIntent = Template.bind({});
@@ -130,13 +129,13 @@ AdjustIntent.args = {
130
129
  ...Default.args,
131
130
  data: {
132
131
  intent: "warning",
133
- }
132
+ },
134
133
  };
135
134
 
136
135
  export const AdjustHighlight = Template.bind({});
137
136
  AdjustHighlight.args = {
138
137
  ...Default.args,
139
138
  data: {
140
- highlightColor: ["default", "alternate"]
141
- }
139
+ highlightColor: ["default", "alternate"],
140
+ },
142
141
  };
@@ -1,15 +1,13 @@
1
- import React, {memo} from 'react';
2
- import {
3
- HandleProps as ReactFlowHandleLegacyProps,
4
- Handle as HandleLegacy,
5
- } from "react-flow-renderer";
6
- import {
7
- HandleProps as ReactFlowHandleNextProps,
8
- Handle as HandleNext,
9
- } from "react-flow-renderer-lts";
10
- import { HandleContent, HandleContentProps } from "./HandleContent";
1
+ import React, { memo } from "react";
2
+ import { Handle as HandleLegacy, HandleProps as ReactFlowHandleLegacyProps } from "react-flow-renderer";
3
+ import { Handle as HandleNext, HandleProps as ReactFlowHandleNextProps } from "react-flow-renderer-lts";
4
+ import { PopoverInteractionKind as BlueprintPopoverInteractionKind } from "@blueprintjs/core";
5
+
11
6
  import { ReacFlowVersionSupportProps, useReactFlowVersion } from "../versionsupport";
12
7
 
8
+ import { HandleContent, HandleContentProps } from "./HandleContent";
9
+ import { HandleTools } from "./HandleTools";
10
+
13
11
  interface HandleExtensionProps extends ReacFlowVersionSupportProps {
14
12
  /**
15
13
  * Extended handle data.
@@ -28,37 +26,46 @@ export interface HandleNextProps extends HandleExtensionProps, ReactFlowHandleNe
28
26
 
29
27
  export type HandleDefaultProps = HandleProps | HandleNextProps;
30
28
 
31
- export const HandleDefault = memo(({
32
- flowVersion,
33
- data,
34
- tooltip,
35
- children,
36
- ...handleProps
37
- }: HandleDefaultProps) => {
29
+ export const HandleDefault = memo(({ flowVersion, data, tooltip, children, ...handleProps }: HandleDefaultProps) => {
38
30
  const evaluateFlowVersion = useReactFlowVersion();
39
31
  const flowVersionCheck = flowVersion || evaluateFlowVersion;
32
+ const [toolsDisplayed, setToolsDisplayed] = React.useState<boolean>(false);
33
+
34
+ const handleClosing = () => {
35
+ setToolsDisplayed(false);
36
+ };
40
37
 
41
- const tooltipTitle = !!tooltip ? { title: tooltip } : {};
38
+ const tooltipTitle = tooltip ? { title: tooltip } : {};
39
+ const configToolsOn = {
40
+ defaultIsOpen: true,
41
+ autoFocus: true,
42
+ interactionKind: BlueprintPopoverInteractionKind.HOVER,
43
+ onClosing: handleClosing,
44
+ };
45
+
46
+ const isToolsContent = children && typeof children !== "string" && children.type === HandleTools;
47
+ let handleContent = <HandleContent {...data}>{children}</HandleContent>;
48
+
49
+ if (isToolsContent && toolsDisplayed) {
50
+ handleContent = <HandleContent {...data}>{React.cloneElement(children ?? <></>, configToolsOn)}</HandleContent>;
51
+ }
52
+ if (isToolsContent && !toolsDisplayed) {
53
+ handleContent = <HandleContent {...data}></HandleContent>;
54
+ }
55
+ const handleClick = React.useCallback(() => setToolsDisplayed(!toolsDisplayed), []);
42
56
 
43
- const handleContent = (
44
- <HandleContent {...data}>
45
- { children }
46
- </HandleContent>
47
- );
57
+ const handleConfig = {
58
+ ...handleProps,
59
+ ...tooltipTitle,
60
+ className: isToolsContent ? "clickable" : undefined,
61
+ onClick: isToolsContent ? handleClick : undefined,
62
+ };
48
63
 
49
64
  switch (flowVersionCheck) {
50
65
  case "legacy":
51
- return (
52
- <HandleLegacy {...handleProps} {...tooltipTitle}>
53
- { handleContent }
54
- </HandleLegacy>
55
- );
66
+ return <HandleLegacy {...handleConfig}>{handleContent}</HandleLegacy>;
56
67
  case "next":
57
- return (
58
- <HandleNext {...handleProps} {...tooltipTitle}>
59
- { handleContent }
60
- </HandleNext>
61
- );
68
+ return <HandleNext {...handleConfig}>{handleContent}</HandleNext>;
62
69
  default:
63
70
  return <></>;
64
71
  }
@@ -0,0 +1,22 @@
1
+ import React from "react";
2
+
3
+ import { CLASSPREFIX as eccgui } from "../../../configuration/constants";
4
+ import { ContextOverlay } from "../../../index";
5
+
6
+ import { ContextOverlayProps } from "./../../../components/ContextOverlay/ContextOverlay";
7
+
8
+ export interface HandleToolsProps extends Omit<ContextOverlayProps, "children" | "content" | "popoverClassName"> {
9
+ children: string | JSX.Element | JSX.Element[];
10
+ }
11
+
12
+ export const HandleTools = ({ children, ...otherContextOverlayProps }: HandleToolsProps) => {
13
+ return (
14
+ <ContextOverlay
15
+ {...otherContextOverlayProps}
16
+ content={<div className={`${eccgui}-graphviz__handletools-content`}>{children}</div>}
17
+ popoverClassName={`${eccgui}-graphviz__handletools-overlay`}
18
+ >
19
+ <div className={`${eccgui}-graphviz__handletools-target`} />
20
+ </ContextOverlay>
21
+ );
22
+ };