Skip to content

Commit 44932f5

Browse files
authored
Merge pull request #218 from eccenca/feature/codemirror-upgrades-CMEM-5464
Enhance CodeEditor component by intent states and linter functionality
2 parents 5e65ccf + 85a1fca commit 44932f5

File tree

14 files changed

+630
-33
lines changed

14 files changed

+630
-33
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ This is a major release, and it might be not compatible with your current usage
6464
- `htmlContentBlockProps` can now be used to configure the wrapper around the Markdown content
6565
- `$eccgui-selector-text-spot-highlight` SCSS config variable to specify selector that is used to create shortly highlighted spots
6666
- it is highlighted when the selector is also active local anchor target or if it has the `.eccgui-typography--spothighlight` class attached to it
67+
- `<CodeEditor />`
68+
- implemented support for linting which is enabled via `useLinting` prop
69+
- `turtle` and `javascript` are currently supported languages for linting
70+
- editor is focused on load if `autoFocus` prop is set to `true`
71+
- implemented support for `disabled` state in code editor
72+
- implemented support for `intent` states in code editor
6773

6874
### Fixed
6975

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@
8181
"codemirror": "^6.0.1",
8282
"color": "^4.2.3",
8383
"compute-scroll-into-view": "^3.1.0",
84+
"jshint": "^2.13.6",
8485
"lodash": "^4.17.21",
86+
"n3": "^1.23.1",
8587
"re-resizable": "^6.10.1",
8688
"react": "^16.13.1",
8789
"react-dom": "^16.13.1",
@@ -126,7 +128,9 @@
126128
"@types/codemirror": "^5.60.15",
127129
"@types/color": "^3.0.6",
128130
"@types/jest": "^29.5.14",
131+
"@types/jshint": "^2.12.4",
129132
"@types/lodash": "^4.17.13",
133+
"@types/n3": "^1.21.1",
130134
"@types/react-syntax-highlighter": "^15.5.13",
131135
"@typescript-eslint/eslint-plugin": "^8.18.1",
132136
"@typescript-eslint/parser": "^8.18.1",

src/cmem/react-flow/StickyNoteModal/StickyNoteModal.tsx

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,16 @@ import getColorConfiguration from "../../../common/utils/getColorConfiguration";
44
import { CodeEditor } from "../../../extensions";
55
import { ReactFlowHotkeyContext } from "../extensions/ReactFlowHotkeyContext";
66

7-
import { Button, FieldItem, Icon, SimpleDialog, SimpleDialogProps, Tag, TagList } from "./../../../index";
7+
import {
8+
Button,
9+
CodeEditorProps,
10+
FieldItem,
11+
Icon,
12+
SimpleDialog,
13+
SimpleDialogProps,
14+
Tag,
15+
TagList,
16+
} from "./../../../index";
817

918
export type StickyNoteModalTranslationKeys = "modalTitle" | "noteLabel" | "colorLabel" | "saveButton" | "cancelButton";
1019

@@ -32,10 +41,14 @@ export interface StickyNoteModalProps {
3241
* Forward other properties to the `SimpleModal` element that is used for this dialog.
3342
*/
3443
simpleDialogProps?: Omit<SimpleDialogProps, "size" | "title" | "hasBorder" | "isOpen" | "onClose" | "actions">;
44+
/**
45+
* Code editor props
46+
*/
47+
codeEditorProps?: Omit<CodeEditorProps, "defaultValue" | "onChange" | "preventLinuNumbers" | "id" | "name">;
3548
}
3649

3750
export const StickyNoteModal: React.FC<StickyNoteModalProps> = React.memo(
38-
({ metaData, onClose, onSubmit, translate, simpleDialogProps }) => {
51+
({ metaData, onClose, onSubmit, translate, simpleDialogProps, codeEditorProps }) => {
3952
const refNote = React.useRef<string>(metaData?.note ?? "");
4053
const [color, setSelectedColor] = React.useState<string>(metaData?.color ?? "");
4154
const noteColors: [string, string][] = Object.entries(getColorConfiguration("stickynotes")).map(
@@ -123,6 +136,7 @@ export const StickyNoteModal: React.FC<StickyNoteModalProps> = React.memo(
123136
refNote.current = value;
124137
}}
125138
defaultValue={refNote.current}
139+
{...codeEditorProps}
126140
/>
127141
</FieldItem>
128142
<FieldItem

src/components/AutoSuggestion/ExtendedCodeEditor.tsx

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { EditorState } from "@codemirror/state";
44
import { EditorView, lineNumbers, Rect } from "@codemirror/view";
55

66
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
7-
import { CodeEditor } from "../../extensions/codemirror/CodeMirror";
7+
import { CodeEditor, CodeEditorProps } from "../../extensions/codemirror/CodeMirror";
88
//hooks
99
import { SupportedCodeEditorModes } from "../../extensions/codemirror/hooks/useCodemirrorModeExtension.hooks";
1010

@@ -15,23 +15,23 @@ export interface IRange {
1515

1616
export interface ExtendedCodeEditorProps {
1717
// Is called with the editor instance that allows access via the CodeMirror API
18-
setCM: (editor: EditorView | undefined) => any;
18+
setCM: (editor: EditorView | undefined) => void;
1919
// Called whenever the editor content changes
20-
onChange: (value: string) => any;
20+
onChange: (value: string) => void;
2121
// Called when the cursor position changes
22-
onCursorChange: (pos: number, coords: Rect, scrollinfo: HTMLElement, cm: EditorView) => any;
22+
onCursorChange: (pos: number, coords: Rect, scrollinfo: HTMLElement, cm: EditorView) => void;
2323
// The editor theme, e.g. "sparql"
2424
mode?: SupportedCodeEditorModes;
2525
// The initial value of the editor
2626
initialValue: string;
2727
// Called when the focus status changes
28-
onFocusChange: (focused: boolean) => any;
28+
onFocusChange: (focused: boolean) => void;
2929
// Called when the user presses a key
3030
onKeyDown: (event: KeyboardEvent) => boolean;
3131
// function invoked when any click occurs
3232
onMouseDown?: (view: EditorView) => void;
3333
// Called when the user selects text
34-
onSelection: (ranges: IRange[]) => any;
34+
onSelection: (ranges: IRange[]) => void;
3535
// If the <Tab> key is enabled as normal input, i.e. it won't have the behavior of changing to the next input element, expected in a web app.
3636
enableTab?: boolean;
3737
/** Placeholder to be shown when no text has been entered, yet. */
@@ -40,6 +40,27 @@ export interface ExtendedCodeEditorProps {
4040
showScrollBar?: boolean;
4141
/** allow multiline entries when new line characters are entered */
4242
multiline?: boolean;
43+
/**
44+
* Code editor props
45+
*/
46+
codeEditorProps?: Omit<
47+
CodeEditorProps,
48+
| "defaultValue"
49+
| "setEditorView"
50+
| "onChange"
51+
| "onCursorChange"
52+
| "onFocusChange"
53+
| "onKeyDown"
54+
| "onSelection"
55+
| "onMouseDown"
56+
| "shouldHaveMinimalSetup"
57+
| "preventLineNumbers"
58+
| "mode"
59+
| "name"
60+
| "enableTab"
61+
| "additionalExtensions"
62+
| "outerDivAttributes"
63+
>;
4364
}
4465

4566
export type IEditorProps = ExtendedCodeEditorProps;
@@ -58,6 +79,7 @@ export const ExtendedCodeEditor = ({
5879
placeholder,
5980
onCursorChange,
6081
onSelection,
82+
codeEditorProps,
6183
}: ExtendedCodeEditorProps) => {
6284
const initialContent = React.useRef(multiline ? initialValue : initialValue.replace(/[\r\n]/g, " "));
6385
const multilineExtensions = multiline
@@ -88,6 +110,7 @@ export const ExtendedCodeEditor = ({
88110
multiline ? "codeeditor" : `singlelinecodeeditor ${BlueprintClassNames.INPUT}`
89111
}`,
90112
}}
113+
{...codeEditorProps}
91114
/>
92115
);
93116
};

src/components/TextField/stories/TextField.stories.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Default.args = {
3131
fullWidth: false,
3232
placeholder: "placeholder text",
3333
readOnly: false,
34+
disabled: false,
3435
};
3536

3637
/** Text field with default value that contains a zero width/invisible character.
@@ -46,7 +47,7 @@ const invisibleCharacterWarningProps: TextFieldProps = {
4647
const codePointsString = [...Array.from(codePoints)]
4748
.map((n) => {
4849
const info = characters.invisibleZeroWidthCharacters.codePointMap.get(n);
49-
return info.fullLabel;
50+
return info?.fullLabel;
5051
})
5152
.join(", ");
5253
alert("Invisible character detected in input string. Code points: " + codePointsString);

src/extensions/codemirror/CodeMirror.stories.tsx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React from "react";
22
import { Meta, StoryFn } from "@storybook/react";
33

4+
import { helpersArgTypes } from "../../../.storybook/helpers";
5+
46
import { CodeEditor } from "./CodeMirror";
57

68
export default {
@@ -11,6 +13,9 @@ export default {
1113
onChange: {
1214
action: "value changed",
1315
},
16+
intent: {
17+
...helpersArgTypes.exampleIntent,
18+
},
1419
},
1520
} as Meta<typeof CodeEditor>;
1621

@@ -22,3 +27,28 @@ BasicExample.args = {
2227
mode: "markdown",
2328
defaultValue: "**test me**",
2429
};
30+
31+
export const LinterExample = TemplateFull.bind({});
32+
LinterExample.args = {
33+
name: "codeinput",
34+
defaultValue: "**test me**",
35+
mode: "javascript",
36+
useLinting: true,
37+
autoFocus: true,
38+
};
39+
40+
export const DisabledExample = TemplateFull.bind({});
41+
DisabledExample.args = {
42+
name: "codeinput",
43+
defaultValue: "**test me**",
44+
mode: "javascript",
45+
disabled: true,
46+
};
47+
48+
export const IntentExample = TemplateFull.bind({});
49+
IntentExample.args = {
50+
name: "codeinput",
51+
defaultValue: "**test me**",
52+
mode: "javascript",
53+
intent: "warning",
54+
};

0 commit comments

Comments
 (0)