diff --git a/CHANGELOG.md b/CHANGELOG.md
index 59ee9c4f..06cba516 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
### Added
+- ``
+ - Add `intent` property.
- new icons:
- `state-confirmed-all`
diff --git a/src/components/AutoSuggestion/AutoSuggestion.tsx b/src/components/AutoSuggestion/AutoSuggestion.tsx
index 057164e2..431da665 100644
--- a/src/components/AutoSuggestion/AutoSuggestion.tsx
+++ b/src/components/AutoSuggestion/AutoSuggestion.tsx
@@ -4,6 +4,7 @@ import { Classes as BlueprintClassNames } from "@blueprintjs/core";
import { EditorView, Rect } from "@codemirror/view";
import { debounce } from "lodash";
+import { IntentTypes } from "../../common/Intent";
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
import { SupportedCodeEditorModes } from "../../extensions/codemirror/hooks/useCodemirrorModeExtension.hooks";
@@ -154,6 +155,8 @@ export interface CodeAutocompleteFieldProps {
readOnly?: boolean;
/** Properties that should be added to the outer div container. */
outerDivAttributes?: Omit, "id" | "data-test-id">;
+ /** Intent state of the input field. Validation errors override this. */
+ intent?: IntentTypes;
}
// Meta data regarding a request
@@ -192,6 +195,7 @@ export const CodeAutocompleteField = ({
height,
readOnly,
outerDivAttributes,
+ intent,
}: CodeAutocompleteFieldProps) => {
const value = React.useRef(initialValue);
const cursorPosition = React.useRef(0);
@@ -630,6 +634,12 @@ export const CodeAutocompleteField = ({
[]
);
+ const hasError = !!value.current && !pathIsValid && !pathValidationPending;
+ const effectiveIntent = hasError ? "danger" : intent;
+ const blueprintIntent =
+ effectiveIntent && !["info", "accent", "neutral"].includes(effectiveIntent) ? effectiveIntent : undefined;
+ const inputIntentClass = effectiveIntent ? ` ${eccgui}-intent--${effectiveIntent}` : "";
+
const codeEditor = React.useMemo(() => {
return (
{label}
- {(pathValidationPending || suggestionsPending) && (
-
- )}
+ {(pathValidationPending || suggestionsPending) && }
>
),
}}
- intent={hasError ? "danger" : undefined}
+ intent={effectiveIntent}
messageText={hasError ? validationErrorText : undefined}
>
{withRightElement}
diff --git a/src/components/CodeAutocompleteField/CodeAutocompleteField.stories.tsx b/src/components/CodeAutocompleteField/CodeAutocompleteField.stories.tsx
index 2cb97db3..4e79857e 100644
--- a/src/components/CodeAutocompleteField/CodeAutocompleteField.stories.tsx
+++ b/src/components/CodeAutocompleteField/CodeAutocompleteField.stories.tsx
@@ -3,13 +3,19 @@ import { OverlaysProvider } from "@blueprintjs/core";
import { Meta, StoryFn } from "@storybook/react";
import { fn } from "@storybook/test";
+import { helpersArgTypes } from "../../../.storybook/helpers";
import { CodeAutocompleteField, CodeAutocompleteFieldProps } from "../../../index";
import { CodeAutocompleteFieldPartialAutoCompleteResult } from "../AutoSuggestion/AutoSuggestion";
export default {
title: "Forms/CodeAutocompleteField",
component: CodeAutocompleteField,
- argTypes: {},
+ argTypes: {
+ intent: {
+ ...helpersArgTypes.exampleIntent,
+ options: ["UNDEFINED", "primary", "accent", "success", "warning", "danger"],
+ },
+ },
args: {
onInputChecked: fn(),
},
diff --git a/src/extensions/codemirror/CodeMirror.tsx b/src/extensions/codemirror/CodeMirror.tsx
index 0e58642f..8d1adbff 100644
--- a/src/extensions/codemirror/CodeMirror.tsx
+++ b/src/extensions/codemirror/CodeMirror.tsx
@@ -326,6 +326,20 @@ export const CodeEditor = ({
];
}
+ const syncIntentClass = React.useCallback((editorView: EditorView | undefined, nextIntent?: CodeEditorProps["intent"]) => {
+ if (!editorView?.dom) {
+ return;
+ }
+
+ Array.from(editorView.dom.classList)
+ .filter((className) => className.startsWith(`${eccgui}-intent--`))
+ .forEach((className) => editorView.dom.classList.remove(className));
+
+ if (nextIntent) {
+ editorView.dom.classList.add(`${eccgui}-intent--${nextIntent}`);
+ }
+ }, []);
+
React.useEffect(() => {
const domEventHandlers = {
...addHandlersFor(!!onScroll, "scroll", onScroll),
@@ -360,7 +374,7 @@ export const CodeEditor = ({
onSelection(v.state.selection.ranges.filter((r) => !r.empty).map(({ from, to }) => ({ from, to })));
if (onFocusChange && currentIntent.current && !v.view.dom.classList?.contains(`${eccgui}-intent--${currentIntent.current}`)) {
- v.view.dom.classList.add(`${eccgui}-intent--${currentIntent.current}`);
+ syncIntentClass(v.view, currentIntent.current);
}
if (onCursorChange) {
@@ -410,9 +424,7 @@ export const CodeEditor = ({
view.dom.classList.add(`${eccgui}-disabled`);
}
- if (currentIntent.current) {
- view.dom.className += ` ${eccgui}-intent--${currentIntent.current}`;
- }
+ syncIntentClass(view, currentIntent.current);
if (autoFocus) {
view.focus();
@@ -472,6 +484,10 @@ export const CodeEditor = ({
}
}, [disabled])
+ React.useEffect(() => {
+ syncIntentClass(view, intent);
+ }, [intent, view, syncIntentClass]);
+
React.useEffect(() => {
setEditorAppearance({
...editorAppearance,