Skip to content

Commit cb75fef

Browse files
authored
Merge pull request #388 from eccenca/feature/improvedDependentParameterHandling-CMEM-6746
Add intent property to CodeAutocompleteField
2 parents 11d26cf + fad4a1c commit cb75fef

4 files changed

Lines changed: 43 additions & 12 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
88

99
### Added
1010

11+
- `<CodeAutocompleteField />`
12+
- Add `intent` property.
1113
- new icons:
1214
- `state-confirmed-all`
1315

src/components/AutoSuggestion/AutoSuggestion.tsx

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Classes as BlueprintClassNames } from "@blueprintjs/core";
44
import { EditorView, Rect } from "@codemirror/view";
55
import { debounce } from "lodash";
66

7+
import { IntentTypes } from "../../common/Intent";
78
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
89
import { SupportedCodeEditorModes } from "../../extensions/codemirror/hooks/useCodemirrorModeExtension.hooks";
910

@@ -154,6 +155,8 @@ export interface CodeAutocompleteFieldProps {
154155
readOnly?: boolean;
155156
/** Properties that should be added to the outer div container. */
156157
outerDivAttributes?: Omit<React.HTMLAttributes<HTMLDivElement>, "id" | "data-test-id">;
158+
/** Intent state of the input field. Validation errors override this. */
159+
intent?: IntentTypes;
157160
}
158161

159162
// Meta data regarding a request
@@ -192,6 +195,7 @@ export const CodeAutocompleteField = ({
192195
height,
193196
readOnly,
194197
outerDivAttributes,
198+
intent,
195199
}: CodeAutocompleteFieldProps) => {
196200
const value = React.useRef<string>(initialValue);
197201
const cursorPosition = React.useRef(0);
@@ -630,6 +634,12 @@ export const CodeAutocompleteField = ({
630634
[]
631635
);
632636

637+
const hasError = !!value.current && !pathIsValid && !pathValidationPending;
638+
const effectiveIntent = hasError ? "danger" : intent;
639+
const blueprintIntent =
640+
effectiveIntent && !["info", "accent", "neutral"].includes(effectiveIntent) ? effectiveIntent : undefined;
641+
const inputIntentClass = effectiveIntent ? ` ${eccgui}-intent--${effectiveIntent}` : "";
642+
633643
const codeEditor = React.useMemo(() => {
634644
return (
635645
<ExtendedCodeEditor
@@ -661,9 +671,8 @@ export const CodeAutocompleteField = ({
661671
multiline,
662672
handleInputMouseDown,
663673
readOnly,
674+
effectiveIntent,
664675
]);
665-
666-
const hasError = !!value.current && !pathIsValid && !pathValidationPending;
667676
const autoSuggestionInput = (
668677
<div
669678
id={id}
@@ -674,7 +683,7 @@ export const CodeAutocompleteField = ({
674683
<div
675684
className={` ${eccgui}-autosuggestion__inputfield ${BlueprintClassNames.INPUT_GROUP} ${
676685
BlueprintClassNames.FILL
677-
} ${hasError ? BlueprintClassNames.INTENT_DANGER : ""}`}
686+
} ${blueprintIntent ? BlueprintClassNames.intentClass(blueprintIntent as any) : ""}${inputIntentClass}`}
678687
>
679688
<ContextOverlay
680689
minimal
@@ -734,13 +743,11 @@ export const CodeAutocompleteField = ({
734743
<>
735744
{label}
736745
&nbsp;
737-
{(pathValidationPending || suggestionsPending) && (
738-
<Spinner size="tiny" position="inline" />
739-
)}
746+
{(pathValidationPending || suggestionsPending) && <Spinner size="tiny" position="inline" />}
740747
</>
741748
),
742749
}}
743-
intent={hasError ? "danger" : undefined}
750+
intent={effectiveIntent}
744751
messageText={hasError ? validationErrorText : undefined}
745752
>
746753
{withRightElement}

src/components/CodeAutocompleteField/CodeAutocompleteField.stories.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,19 @@ import { OverlaysProvider } from "@blueprintjs/core";
33
import { Meta, StoryFn } from "@storybook/react";
44
import { fn } from "@storybook/test";
55

6+
import { helpersArgTypes } from "../../../.storybook/helpers";
67
import { CodeAutocompleteField, CodeAutocompleteFieldProps } from "../../../index";
78
import { CodeAutocompleteFieldPartialAutoCompleteResult } from "../AutoSuggestion/AutoSuggestion";
89

910
export default {
1011
title: "Forms/CodeAutocompleteField",
1112
component: CodeAutocompleteField,
12-
argTypes: {},
13+
argTypes: {
14+
intent: {
15+
...helpersArgTypes.exampleIntent,
16+
options: ["UNDEFINED", "primary", "accent", "success", "warning", "danger"],
17+
},
18+
},
1319
args: {
1420
onInputChecked: fn(),
1521
},

src/extensions/codemirror/CodeMirror.tsx

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,20 @@ export const CodeEditor = ({
326326
];
327327
}
328328

329+
const syncIntentClass = React.useCallback((editorView: EditorView | undefined, nextIntent?: CodeEditorProps["intent"]) => {
330+
if (!editorView?.dom) {
331+
return;
332+
}
333+
334+
Array.from(editorView.dom.classList)
335+
.filter((className) => className.startsWith(`${eccgui}-intent--`))
336+
.forEach((className) => editorView.dom.classList.remove(className));
337+
338+
if (nextIntent) {
339+
editorView.dom.classList.add(`${eccgui}-intent--${nextIntent}`);
340+
}
341+
}, []);
342+
329343
React.useEffect(() => {
330344
const domEventHandlers = {
331345
...addHandlersFor(!!onScroll, "scroll", onScroll),
@@ -360,7 +374,7 @@ export const CodeEditor = ({
360374
onSelection(v.state.selection.ranges.filter((r) => !r.empty).map(({ from, to }) => ({ from, to })));
361375

362376
if (onFocusChange && currentIntent.current && !v.view.dom.classList?.contains(`${eccgui}-intent--${currentIntent.current}`)) {
363-
v.view.dom.classList.add(`${eccgui}-intent--${currentIntent.current}`);
377+
syncIntentClass(v.view, currentIntent.current);
364378
}
365379

366380
if (onCursorChange) {
@@ -410,9 +424,7 @@ export const CodeEditor = ({
410424
view.dom.classList.add(`${eccgui}-disabled`);
411425
}
412426

413-
if (currentIntent.current) {
414-
view.dom.className += ` ${eccgui}-intent--${currentIntent.current}`;
415-
}
427+
syncIntentClass(view, currentIntent.current);
416428

417429
if (autoFocus) {
418430
view.focus();
@@ -472,6 +484,10 @@ export const CodeEditor = ({
472484
}
473485
}, [disabled])
474486

487+
React.useEffect(() => {
488+
syncIntentClass(view, intent);
489+
}, [intent, view, syncIntentClass]);
490+
475491
React.useEffect(() => {
476492
setEditorAppearance({
477493
...editorAppearance,

0 commit comments

Comments
 (0)