@eccenca/gui-elements 24.0.1 → 24.1.0-rc.1

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 (68) hide show
  1. package/CHANGELOG.md +15 -6
  2. package/dist/cjs/cmem/react-flow/StickyNoteModal/StickyNoteModal.js +3 -3
  3. package/dist/cjs/cmem/react-flow/StickyNoteModal/StickyNoteModal.js.map +1 -1
  4. package/dist/cjs/components/AutoSuggestion/ExtendedCodeEditor.js +3 -3
  5. package/dist/cjs/components/AutoSuggestion/ExtendedCodeEditor.js.map +1 -1
  6. package/dist/cjs/components/ContentGroup/ContentGroup.js +95 -0
  7. package/dist/cjs/components/ContentGroup/ContentGroup.js.map +1 -0
  8. package/dist/cjs/components/index.js +1 -0
  9. package/dist/cjs/components/index.js.map +1 -1
  10. package/dist/cjs/extensions/codemirror/CodeMirror.js +58 -6
  11. package/dist/cjs/extensions/codemirror/CodeMirror.js.map +1 -1
  12. package/dist/cjs/extensions/codemirror/debouncedLinter.js +18 -0
  13. package/dist/cjs/extensions/codemirror/debouncedLinter.js.map +1 -0
  14. package/dist/cjs/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.js +9 -18
  15. package/dist/cjs/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.js.map +1 -1
  16. package/dist/cjs/extensions/codemirror/linters/jsLinter.js +36 -0
  17. package/dist/cjs/extensions/codemirror/linters/jsLinter.js.map +1 -0
  18. package/dist/cjs/extensions/codemirror/linters/turtleLinter.js +81 -0
  19. package/dist/cjs/extensions/codemirror/linters/turtleLinter.js.map +1 -0
  20. package/dist/cjs/extensions/codemirror/types.js +3 -0
  21. package/dist/cjs/extensions/codemirror/types.js.map +1 -0
  22. package/dist/esm/cmem/react-flow/StickyNoteModal/StickyNoteModal.js +4 -4
  23. package/dist/esm/cmem/react-flow/StickyNoteModal/StickyNoteModal.js.map +1 -1
  24. package/dist/esm/components/AutoSuggestion/ExtendedCodeEditor.js +14 -3
  25. package/dist/esm/components/AutoSuggestion/ExtendedCodeEditor.js.map +1 -1
  26. package/dist/esm/components/ContentGroup/ContentGroup.js +100 -0
  27. package/dist/esm/components/ContentGroup/ContentGroup.js.map +1 -0
  28. package/dist/esm/components/index.js +1 -0
  29. package/dist/esm/components/index.js.map +1 -1
  30. package/dist/esm/extensions/codemirror/CodeMirror.js +58 -7
  31. package/dist/esm/extensions/codemirror/CodeMirror.js.map +1 -1
  32. package/dist/esm/extensions/codemirror/debouncedLinter.js +15 -0
  33. package/dist/esm/extensions/codemirror/debouncedLinter.js.map +1 -0
  34. package/dist/esm/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.js +6 -15
  35. package/dist/esm/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.js.map +1 -1
  36. package/dist/esm/extensions/codemirror/linters/jsLinter.js +32 -0
  37. package/dist/esm/extensions/codemirror/linters/jsLinter.js.map +1 -0
  38. package/dist/esm/extensions/codemirror/linters/turtleLinter.js +77 -0
  39. package/dist/esm/extensions/codemirror/linters/turtleLinter.js.map +1 -0
  40. package/dist/esm/extensions/codemirror/types.js +2 -0
  41. package/dist/esm/extensions/codemirror/types.js.map +1 -0
  42. package/dist/types/cmem/react-flow/StickyNoteModal/StickyNoteModal.d.ts +5 -1
  43. package/dist/types/components/AutoSuggestion/ExtendedCodeEditor.d.ts +11 -6
  44. package/dist/types/components/ContentGroup/ContentGroup.d.ts +78 -0
  45. package/dist/types/components/index.d.ts +1 -0
  46. package/dist/types/extensions/codemirror/CodeMirror.d.ts +23 -5
  47. package/dist/types/extensions/codemirror/debouncedLinter.d.ts +4 -0
  48. package/dist/types/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.d.ts +3 -5
  49. package/dist/types/extensions/codemirror/linters/jsLinter.d.ts +5 -0
  50. package/dist/types/extensions/codemirror/linters/turtleLinter.d.ts +5 -0
  51. package/dist/types/extensions/codemirror/types.d.ts +5 -0
  52. package/package.json +7 -5
  53. package/src/cmem/react-flow/StickyNoteModal/StickyNoteModal.tsx +16 -2
  54. package/src/components/AutoSuggestion/ExtendedCodeEditor.tsx +29 -6
  55. package/src/components/ContentGroup/ContentGroup.stories.tsx +47 -0
  56. package/src/components/ContentGroup/ContentGroup.tsx +256 -0
  57. package/src/components/ContentGroup/_contentgroup.scss +56 -0
  58. package/src/components/TextField/stories/TextField.stories.tsx +2 -1
  59. package/src/components/index.scss +1 -0
  60. package/src/components/index.ts +1 -0
  61. package/src/extensions/codemirror/CodeMirror.stories.tsx +30 -0
  62. package/src/extensions/codemirror/CodeMirror.tsx +86 -9
  63. package/src/extensions/codemirror/_codemirror.scss +96 -0
  64. package/src/extensions/codemirror/debouncedLinter.ts +26 -0
  65. package/src/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.ts +6 -16
  66. package/src/extensions/codemirror/linters/jsLinter.ts +38 -0
  67. package/src/extensions/codemirror/linters/turtleLinter.ts +102 -0
  68. package/src/extensions/codemirror/types.ts +7 -0
@@ -1,3 +1,5 @@
1
+ @use "sass:color";
2
+
1
3
  // own vars
2
4
  $eccgui-color-codeeditor-background: $eccgui-color-textfield-background !default;
3
5
 
@@ -22,6 +24,63 @@ $eccgui-color-codeeditor-background: $eccgui-color-textfield-background !default
22
24
  // get them a "border" like input boxes from blueprintjs
23
25
  box-shadow: input-transition-shadow($input-shadow-color-focus), $pt-input-box-shadow;
24
26
 
27
+ &.#{eccgui}-disabled {
28
+ @extend .#{$ns}-input, .#{$ns}-disabled;
29
+
30
+ height: 290px;
31
+ padding: 0;
32
+ }
33
+
34
+ &[class*="#{$eccgui}-intent--"] {
35
+ animation-duration: 1s;
36
+ animation-delay: 0.5s;
37
+ }
38
+
39
+ @each $each-intent, $each-bgcolor in $eccgui-map-intent-bgcolors {
40
+ &.#{eccgui}-intent--#{$each-intent} {
41
+ background-color: color.mix($each-bgcolor, $eccgui-color-textfield-background, 24%);
42
+ animation-name: intent-state-flash-#{$each-intent};
43
+ }
44
+ }
45
+
46
+ &.#{eccgui}-intent--warning {
47
+ @include pt-input-intent($eccgui-color-warning-text);
48
+ }
49
+
50
+ &.#{eccgui}-intent--success {
51
+ @include pt-input-intent($eccgui-color-success-text);
52
+ }
53
+
54
+ &.#{eccgui}-intent--danger {
55
+ @include pt-input-intent($eccgui-color-danger-text);
56
+ }
57
+
58
+ &.#{eccgui}-intent--primary {
59
+ @include pt-input-intent($eccgui-color-info-text);
60
+ }
61
+
62
+ &.#{eccgui}-intent--info {
63
+ @include pt-input-intent($eccgui-color-info-text);
64
+ }
65
+
66
+ &.#{eccgui}-intent--accent {
67
+ @include pt-input-intent($eccgui-color-primary);
68
+ }
69
+
70
+ &.#{eccgui}-intent--neutral {
71
+ @include pt-input-intent($eccgui-color-workspace-text);
72
+ }
73
+
74
+ &.#{eccgui}-intent--edited {
75
+ @include pt-input-intent($eccgui-color-info-text);
76
+ }
77
+
78
+ &.#{eccgui}-intent--removed {
79
+ @include pt-input-intent($eccgui-color-danger-text);
80
+
81
+ text-decoration: line-through $eccgui-color-danger-text 2px;
82
+ }
83
+
25
84
  .cm-scroller {
26
85
  width: calc(100% - 2px);
27
86
  height: calc(100% - 2px);
@@ -34,6 +93,43 @@ $eccgui-color-codeeditor-background: $eccgui-color-textfield-background !default
34
93
  &.cm-focused {
35
94
  outline: none;
36
95
  box-shadow: input-transition-shadow($input-shadow-color-focus, true), $input-box-shadow-focus;
96
+
97
+ &.#{eccgui}-intent--warning {
98
+ box-shadow: input-transition-shadow($eccgui-color-warning-text, true), $input-box-shadow-focus;
99
+ }
100
+
101
+ &.#{eccgui}-intent--success {
102
+ box-shadow: input-transition-shadow($eccgui-color-success-text, true), $input-box-shadow-focus;
103
+ }
104
+
105
+ &.#{eccgui}-intent--danger {
106
+ box-shadow: input-transition-shadow($eccgui-color-danger-text, true), $input-box-shadow-focus;
107
+ }
108
+
109
+ &.#{eccgui}-intent--primary {
110
+ box-shadow: input-transition-shadow($eccgui-color-info-text, true), $input-box-shadow-focus;
111
+ }
112
+
113
+ &.#{eccgui}-intent--info {
114
+ box-shadow: input-transition-shadow($eccgui-color-info-text, true), $input-box-shadow-focus;
115
+ }
116
+
117
+ &.#{eccgui}-intent--accent {
118
+ box-shadow: input-transition-shadow($eccgui-color-warning-text, true), $input-box-shadow-focus;
119
+ }
120
+
121
+ &.#{eccgui}-intent--neutral {
122
+ box-shadow: input-transition-shadow($eccgui-color-workspace-text, true), $input-box-shadow-focus;
123
+ }
124
+
125
+ &.#{eccgui}-intent--edited {
126
+ box-shadow: input-transition-shadow($eccgui-color-info-text, true), $input-box-shadow-focus;
127
+ }
128
+
129
+ &.#{eccgui}-intent--removed {
130
+ text-decoration: line-through $eccgui-color-danger-text 2px;
131
+ box-shadow: input-transition-shadow($eccgui-color-danger-text, true), $input-box-shadow-focus;
132
+ }
37
133
  }
38
134
 
39
135
  .CodeMirror-hscrollbar {
@@ -0,0 +1,26 @@
1
+ import { Diagnostic } from "@codemirror/lint";
2
+ import { EditorView } from "@codemirror/view";
3
+ import { debounce } from "lodash";
4
+
5
+ import { Linter } from "./types";
6
+
7
+ const DEBOUNCE_TIME = 500;
8
+
9
+ export const debouncedLinter = (lintFunction: Linter, time = DEBOUNCE_TIME) => {
10
+ const debouncedFn = debounce(
11
+ (
12
+ view: EditorView,
13
+ resolve: (diagnostics: ReadonlyArray<Diagnostic> | Promise<ReadonlyArray<Diagnostic>>) => void
14
+ ) => {
15
+ const diagnostics = lintFunction(view);
16
+ resolve(diagnostics);
17
+ },
18
+ time
19
+ );
20
+
21
+ return (view: EditorView) => {
22
+ return new Promise<ReadonlyArray<Diagnostic>>((resolve) => {
23
+ debouncedFn(view, resolve);
24
+ });
25
+ };
26
+ };
@@ -1,18 +1,17 @@
1
- //adapted v6 modes imports
2
- import { javascript } from "@codemirror/lang-javascript";
3
1
  import { json } from "@codemirror/lang-json";
2
+ //modes imports
4
3
  import { markdown } from "@codemirror/lang-markdown";
5
- import { sql } from "@codemirror/lang-sql";
6
4
  import { xml } from "@codemirror/lang-xml";
7
- import { yaml } from "@codemirror/lang-yaml";
8
5
  import { defaultHighlightStyle, LanguageSupport, StreamLanguage, StreamParser } from "@codemirror/language";
9
- //legacy mode imports
6
+ import { javascript } from "@codemirror/legacy-modes/mode/javascript";
10
7
  import { jinja2 } from "@codemirror/legacy-modes/mode/jinja2";
11
8
  import { mathematica } from "@codemirror/legacy-modes/mode/mathematica";
12
9
  import { ntriples } from "@codemirror/legacy-modes/mode/ntriples";
13
10
  import { python } from "@codemirror/legacy-modes/mode/python";
14
11
  import { sparql } from "@codemirror/legacy-modes/mode/sparql";
12
+ import { sql } from "@codemirror/legacy-modes/mode/sql";
15
13
  import { turtle } from "@codemirror/legacy-modes/mode/turtle";
14
+ import { yaml } from "@codemirror/legacy-modes/mode/yaml";
16
15
 
17
16
  //adaptations
18
17
  import { adaptedSyntaxHighlighting } from "../tests/codemirrorTestHelper";
@@ -35,19 +34,10 @@ const supportedModes = {
35
34
  export const supportedCodeEditorModes = Object.keys(supportedModes) as Array<keyof typeof supportedModes>;
36
35
  export type SupportedCodeEditorModes = (typeof supportedCodeEditorModes)[number];
37
36
 
38
- const v6AdaptedModes: ReadonlyMap<SupportedCodeEditorModes, boolean> = new Map([
39
- ["json", true],
40
- ["markdown", true],
41
- ["xml", true],
42
- ["sql", true],
43
- ["yaml", true],
44
- ["javascript", true],
45
- ]);
46
-
47
37
  export const useCodeMirrorModeExtension = (mode?: SupportedCodeEditorModes) => {
48
38
  return !mode
49
39
  ? adaptedSyntaxHighlighting(defaultHighlightStyle)
50
- : v6AdaptedModes.has(mode)
51
- ? ((typeof supportedModes[mode] === "function" ? supportedModes[mode] : () => {}) as () => LanguageSupport)()
40
+ : ["json", "markdown", "xml"].includes(mode)
41
+ ? ((typeof supportedModes[mode] === "function" ? supportedModes[mode] : () => null) as () => LanguageSupport)()
52
42
  : StreamLanguage?.define(supportedModes[mode] as StreamParser<unknown>);
53
43
  };
@@ -0,0 +1,38 @@
1
+ import { Diagnostic, linter } from "@codemirror/lint";
2
+ import { JSHINT as jshint } from "jshint";
3
+
4
+ import { ExtensionCreator } from "../types";
5
+
6
+ const lintOptions = {
7
+ esversion: 11,
8
+ browser: true,
9
+ };
10
+
11
+ /**
12
+ * Sets up the javascript linter. Documentation: https://codemirror.net/examples/lint/
13
+ */
14
+ export const jsLinter: ExtensionCreator = () => {
15
+ return linter((view) => {
16
+ const diagnostics: Array<Diagnostic> = [];
17
+ const codeText = view.state.doc.toJSON();
18
+ jshint(codeText, lintOptions);
19
+ const errors = jshint?.data()?.errors;
20
+
21
+ if (errors && errors.length > 0) {
22
+ errors.forEach((error) => {
23
+ const selectedLine = view.state.doc.line(error.line);
24
+
25
+ const diagnostic: Diagnostic = {
26
+ from: selectedLine.from,
27
+ to: selectedLine.to,
28
+ severity: "error",
29
+ message: error.reason,
30
+ };
31
+
32
+ diagnostics.push(diagnostic);
33
+ });
34
+ }
35
+
36
+ return diagnostics;
37
+ });
38
+ };
@@ -0,0 +1,102 @@
1
+ import { Diagnostic, linter } from "@codemirror/lint";
2
+ import { EditorView } from "@codemirror/view";
3
+ import { Parser } from "n3";
4
+
5
+ import { debouncedLinter } from "../debouncedLinter";
6
+ import { ExtensionCreator, Linter } from "../types";
7
+
8
+ const parser = new Parser();
9
+
10
+ const EMPTY_RESOURCE = "<>";
11
+
12
+ const getError = (message: string, view: EditorView) => {
13
+ const lineMatch = message.match(/(?<=line )\d{1,}/);
14
+ const valueMatch = message.match(/"([^"]*)"/);
15
+
16
+ const lineNumber = lineMatch ? Number(lineMatch[0]) : 1;
17
+ // the [1] index is used to get the caputre group
18
+ const errorContent = valueMatch && valueMatch[1];
19
+
20
+ const line = view.state.doc.line(lineNumber);
21
+ const position = line.text.search(errorContent ?? /\S/);
22
+
23
+ const from = line.from + position;
24
+ const errorLength = errorContent?.length;
25
+
26
+ return { from, to: errorLength ? from + errorLength : line.to };
27
+ };
28
+
29
+ const getQuadError = (view: EditorView) => {
30
+ const lines = view.state.doc.toJSON();
31
+
32
+ for (let i = 0; i < lines.length; i += 1) {
33
+ const input = lines[i].trim();
34
+
35
+ if (!input) {
36
+ continue;
37
+ }
38
+
39
+ if (input.includes(EMPTY_RESOURCE)) {
40
+ // i + 1 is used here because the codemirror uses 1-indexes
41
+ const line = view.state.doc.line(i + 1);
42
+ const position = line.text.search(EMPTY_RESOURCE);
43
+
44
+ const from = line.from + position;
45
+
46
+ return {
47
+ from,
48
+ to: from + EMPTY_RESOURCE.length,
49
+ };
50
+ }
51
+ }
52
+
53
+ return { from: 0, to: view.state.doc.length };
54
+ };
55
+
56
+ const n3Linter: Linter = (view) => {
57
+ const diagnostics: Array<Diagnostic> = [];
58
+ const value = view.state.doc.toString();
59
+
60
+ try {
61
+ const quads = parser.parse(value);
62
+
63
+ quads.forEach((quad) => {
64
+ if (!quad.subject || !quad.predicate || !quad.object) {
65
+ const { from, to } = getQuadError(view);
66
+
67
+ view.dispatch({
68
+ scrollIntoView: true,
69
+ });
70
+
71
+ diagnostics.push({
72
+ from,
73
+ to,
74
+ severity: "error",
75
+ message: `Invalid RDF quad:\n\nsubject: ${quad.subject}\npredicate: ${quad.predicate}\nobject: ${quad.object}`,
76
+ });
77
+ }
78
+ });
79
+ } catch (error) {
80
+ const { message } = error as Error;
81
+
82
+ const { from, to } = getError(message, view);
83
+
84
+ view.dispatch({
85
+ scrollIntoView: true,
86
+ });
87
+
88
+ diagnostics.push({
89
+ from,
90
+ to,
91
+ severity: "error",
92
+ message: (error as Error).message,
93
+ });
94
+ }
95
+
96
+ return diagnostics;
97
+ };
98
+
99
+ /**
100
+ * Sets up the turtle linter. Documentation: https://codemirror.net/examples/lint/
101
+ */
102
+ export const turtleLinter: ExtensionCreator = () => linter(debouncedLinter(n3Linter));
@@ -0,0 +1,7 @@
1
+ import { Diagnostic } from "@codemirror/lint";
2
+ import { Extension } from "@codemirror/state";
3
+ import { EditorView } from "@codemirror/view";
4
+
5
+ export type Linter = (view: EditorView) => ReadonlyArray<Diagnostic> | Promise<ReadonlyArray<Diagnostic>>;
6
+
7
+ export type ExtensionCreator<T = unknown> = (options?: T) => Extension;