Skip to content

Instantly share code, notes, and snippets.

@eabald
Created February 6, 2022 19:38
import React, { useState, useEffect, useCallback } from 'react';
import {
controller as StandardController,
Cell as StandardCell,
CardValue as StandardCardValue,
} from '@keystone-6/core/fields/types/text/views';
import { FieldProps } from '@keystone-6/core/types';
import { FieldContainer, FieldLabel, TextInput } from '@keystone-ui/fields';
import { styles } from './styles';
export const Cell = StandardCell;
export const CardValue = StandardCardValue;
export const controller = StandardController;
export const Field = (props: FieldProps<typeof StandardController>) => {
const [visible, setVisible] = useState(false);
const [suggestions, setSuggestions] = useState<{ [key: string]: string }[]>([]);
const initialGetSuggestions = useCallback(async () => {
if (props.value.inner.kind === 'value' && props.value.inner.value) {
const currentSuggestions = await getSuggestions(props.value.inner.value);
setSuggestions(currentSuggestions);
setTimeout(() => setVisible(false), 300);
}
useEffect(() => {
initialGetSuggestions();
}, []);
useEffect(() => {
setVisible(!!suggestions.length);
}, [suggestions]);
const getSuggestions = async (query: string) => {
const res = await fetch(`/autocomplete/${props.field.path}?q=${query}`);
const json = await res.json();
return await json.hits;
};
const setOnChange = (value: string) => {
if (props.onChange) {
props.onChange({
...props.value,
inner: { kind: 'value', value },
});
}
}
const onChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
setOnChange(event.target.value);
if (event.target.value.length > 3) {
const currentSuggestions = await getSuggestions(event.target.value);
setSuggestions(currentSuggestions);
} else {
setSuggestions([]);
}
};
const onSuggestionClick = (suggestion: string) => {
setOnChange(suggestion);
};
return (
<FieldContainer className={styles.wrapper}>
<FieldLabel htmlFor={props.field.path}>{props.field.label}</FieldLabel>
<TextInput
autoComplete="off"
id={props.field.path}
autoFocus={props.autoFocus}
onFocus={() => setVisible(true)}
onBlur={() => setTimeout(() => setVisible(false), 300)}
onChange={onChange}
value={
props.value.inner.kind === 'null' ? '' : props.value.inner.value
}
/>
{visible && (
<ul className={styles.list.ul}>
{suggestions.map((suggestion, i) => (
<li
className={styles.list.li}
key={`${props.field.path}-${i}`}
onClick={() => onSuggestionClick(suggestion[props.field.path])}
>
{suggestion[props.field.path]}
</li>
))}
</ul>
)}
</FieldContainer>
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment