Skip to content

Commit

Permalink
Add save on blur option to SelectionAutoCompleteInput (#28079)
Browse files Browse the repository at this point in the history
## Summary & Motivation

As titled

## How I Tested These Changes

Need to build a complex mock for codemirror to test this with jest so
just manually tested for now by using it in cloud
  • Loading branch information
salazarm authored Feb 27, 2025
1 parent d1800c0 commit 02d8f33
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const textDecoration = (underline: Underline) => {
`;
case 'hover':
return css`
&:hover {
&:hover:not(:disabled) {
text-decoration: underline;
& > ${Box} {
text-decoration: underline;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export interface AssetSelectionInputProps {
useAssetSelectionAutoComplete?: (
assets: AssetGraphQueryItem[],
) => Pick<SelectionAutoCompleteProvider, 'useAutoComplete'>;
saveOnBlur?: boolean;
}

const defaultLinter = createSelectionLinter({
Expand All @@ -32,6 +33,7 @@ export const AssetSelectionInput = ({
assets,
linter = defaultLinter,
useAssetSelectionAutoComplete = defaultUseAssetSelectionAutoCompleteProvider,
saveOnBlur = false,
}: AssetSelectionInputProps) => {
const {useAutoComplete} = useAssetSelectionAutoComplete(assets);

Expand All @@ -43,6 +45,7 @@ export const AssetSelectionInput = ({
linter={linter}
value={value}
onChange={onChange}
saveOnBlur={saveOnBlur}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type SelectionAutoCompleteInputProps = {
value: string;
onChange: (value: string) => void;
useAutoComplete: SelectionAutoCompleteProvider['useAutoComplete'];
saveOnBlur?: boolean;
};

export const SelectionAutoCompleteInput = ({
Expand All @@ -36,6 +37,7 @@ export const SelectionAutoCompleteInput = ({
onChange,
linter,
useAutoComplete,
saveOnBlur = false,
}: SelectionAutoCompleteInputProps) => {
const trackEvent = useTrackEvent();

Expand Down Expand Up @@ -244,6 +246,8 @@ export const SelectionAutoCompleteInput = ({
const handleKeyDown = useCallback(
(e: KeyboardEvent<HTMLDivElement>) => {
if (e.key === 'Enter') {
e.stopPropagation();
e.preventDefault();
onSelectionChange(innerValueRef.current);
setShowResults({current: false});
}
Expand All @@ -252,22 +256,26 @@ export const SelectionAutoCompleteInput = ({
}
if (e.key === 'ArrowDown' && !e.shiftKey && !e.ctrlKey) {
e.preventDefault();
e.stopPropagation();
setSelectedIndex((prev) => ({
current: (prev.current + 1) % (autoCompleteResults?.list.length ?? 0),
}));
} else if (e.key === 'ArrowUp' && !e.shiftKey && !e.ctrlKey) {
e.preventDefault();
e.stopPropagation();
setSelectedIndex((prev) => ({
current:
prev.current - 1 < 0 ? (autoCompleteResults?.list.length ?? 1) - 1 : prev.current - 1,
}));
} else if (e.key === 'Tab') {
e.preventDefault();
e.stopPropagation();
if (selectedItem) {
onSelect(selectedItem);
}
} else if (e.key === 'Escape') {
e.preventDefault();
e.stopPropagation();
setShowResults({current: false});
}
},
Expand All @@ -284,7 +292,7 @@ export const SelectionAutoCompleteInput = ({
/**
* Popover doesn't seem to support canOutsideClickClose, so we have to do this ourselves.
*/
React.useLayoutEffect(() => {
useLayoutEffect(() => {
const listener = (e: MouseEvent) => {
if (
inputRef.current?.contains(e.target as Node) ||
Expand All @@ -308,23 +316,29 @@ export const SelectionAutoCompleteInput = ({
});
}, [adjustHeight, isEmpty]);

const onBlur = useCallback((ev: React.FocusEvent<HTMLDivElement>) => {
const current = ev.relatedTarget;
const hintsVisible = !!hintContainerRef.current?.querySelector('.CodeMirror-hints');
if (
inputRef.current?.contains(current) ||
editorRef.current?.contains(current) ||
hintContainerRef.current?.contains(current) ||
hintsVisible
) {
ev.preventDefault();
return;
}
focusRef.current = false;
cmInstance.current?.setOption('lineWrapping', false);
cmInstance.current?.setSize('100%', '20px');
setCurrentHeight(20);
}, []);
const onBlur = useCallback(
(ev: React.FocusEvent<HTMLDivElement>) => {
const current = ev.relatedTarget;
const hintsVisible = !!hintContainerRef.current?.querySelector('.CodeMirror-hints');
if (saveOnBlur) {
onSelectionChange(innerValueRef.current);
}
if (
inputRef.current?.contains(current) ||
editorRef.current?.contains(current) ||
hintContainerRef.current?.contains(current) ||
hintsVisible
) {
ev.preventDefault();
return;
}
focusRef.current = false;
cmInstance.current?.setOption('lineWrapping', false);
cmInstance.current?.setSize('100%', '20px');
setCurrentHeight(20);
},
[saveOnBlur, onSelectionChange, innerValueRef],
);

useResizeObserver(inputRef, adjustHeight);

Expand Down

2 comments on commit 02d8f33

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy preview for dagit-storybook ready!

✅ Preview
https://dagit-storybook-nxt4hfjq1-elementl.vercel.app

Built with commit 02d8f33.
This pull request is being automatically deployed with vercel-action

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy preview for dagit-core-storybook ready!

✅ Preview
https://dagit-core-storybook-biiuxl841-elementl.vercel.app

Built with commit 02d8f33.
This pull request is being automatically deployed with vercel-action

Please sign in to comment.