-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add SiteSearch Type-Ahead #332
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking great. I am not opposed to everything residing in this module, as-is. One exception is buildDebounder
. I suppose it can go in /packages/libs/web-common/src/util
; or even a new package, /packages/libs/utils
.
if (ulReference.current?.firstElementChild === e.currentTarget) { | ||
props.inputReference.current?.focus(); | ||
} else { | ||
(e.currentTarget.previousElementSibling as HTMLLIElement | null)?.focus(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, I did not know about this property (or nextElementSibling
)!
// region Debouncer | ||
|
||
/** | ||
* Debouncer Function Type. | ||
* | ||
* Represents a function that may be used to build a "debounced" or "debouncing" | ||
* function by passing in a target function that takes a value of type `T` and | ||
* returns nothing. | ||
* | ||
* The return value of a Debouncer function call will be a new function that | ||
* wraps the given target function with debouncing. | ||
* | ||
* @param T Type of the value consumed by the function wrapped by and returned | ||
* by the Debouncer function. | ||
*/ | ||
type Debouncer<T> = (func: (value: T) => void) => (value: T) => void; | ||
|
||
|
||
/** | ||
* Builds a new `Debouncer` function that may be used to build one or more | ||
* functions that debounce on the same timer. | ||
* | ||
* @param delay Debouncing delay. | ||
* | ||
* @return A `Debouncer` function that may be used to build one or more | ||
* functions that debounce on the same timer. | ||
*/ | ||
function buildDebouncer<T>(delay: number): Debouncer<T> { | ||
let timer: any; | ||
|
||
return (func: (value: T) => any) => { | ||
return (value: T) => { | ||
clearTimeout(timer); | ||
timer = setTimeout(() => func(value), delay); | ||
}; | ||
}; | ||
} | ||
|
||
// endregion Debouncer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a very useful implementation of a debouncer. Since it allows different functions to use the same timer, it works really well with react components, where a new function is created in every "render" phase.
I've typically used lodash's debounce
function, which has the behavior that a new timer is created each time debounce
is called.
Something to note is that, since buildDebouncer
is invoked at the module scope, if we had multiple TypeAheadInput
's on a page, they could potentially cancel one another. That is unlikely to be an issue in this case, but if we were to generalize this, it could be an issue. We would likely want to wrap this in a hook, and use a Ref
to hold on the to "timer" value.
/** | ||
* Wrapper for the SiteSearch Type-Ahead HTTP API. | ||
*/ | ||
class TypeAheadAPI { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See https://github.com/VEuPathDB/web-monorepo/blob/main/packages/libs/http-utils/src/FetchClient.ts, for a base class you can use to implement this. Note that you can use it with https://github.com/VEuPathDB/web-monorepo/blob/main/packages/libs/http-utils/src/ioTransformer.ts to build run-time validation.
See an example of how it's used here: https://github.com/VEuPathDB/web-monorepo/blob/main/packages/libs/eda/src/lib/core/api/SubsettingClient/index.ts.
Also, note that API methods return a Promise<T>
, rather than taking a callback, so you would also have to modify the caller of typeahead
, if you go this route.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes look good!
* Add search history menu to site search input * Only save up to 10 searches
Replaces the SiteSearch text input box with a type-ahead component that offers word completion suggestions based on the user's input.
ETA This can't be merged until r51683 is completed.