mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-27 21:58:51 +01:00
* WIP: dynamic settings * WIP: update tests and validations * refactor(SidePanel): use hook for Links * WIP: dynamic settings, slider implemented * feat(useDebouncedInput): dynamic typing with generic * refactor(generate): add `custom` optionType to be non-conforming to conversation schema * feat: DynamicDropdown * refactor(DynamicSlider): custom optionType handling and useEffect for conversation updates elsewhere * refactor(Panel): add more test cases * chore(DynamicSlider): note * refactor(useDebouncedInput): import defaultDebouncedDelay from ~/common` * WIP: implement remaining ComponentTypes * chore: add com_sidepanel_parameters * refactor: add langCode handling for dynamic settings * chore(useOriginNavigate): change path to '/c/' * refactor: explicit textarea focus on new convo, share textarea idea via ~/common * refactor: useParameterEffects: reset if convo or preset Ids change, share and maintain statefulness in side panel * wip: combobox * chore: minor styling for Select components * wip: combobox select styling for side panel * feat: complete combobox * refactor: model select for side panel switcher * refactor(Combobox): add portal * chore: comment out dynamic parameters panel for future PR and delete prompt files * refactor(Combobox): add icon field for options, change hover bg-color, add displayValue * fix(useNewConvo): proper textarea focus with setTimeout * refactor(AssistantSwitcher): use Combobox * refactor(ModelSwitcher): add textarea focus on model switch
54 lines
1.8 KiB
TypeScript
54 lines
1.8 KiB
TypeScript
import debounce from 'lodash/debounce';
|
|
import React, { useState, useCallback } from 'react';
|
|
import type { SetterOrUpdater } from 'recoil';
|
|
import type { TSetOption } from '~/common';
|
|
import { defaultDebouncedDelay } from '~/common';
|
|
|
|
/** A custom hook that accepts a setOption function and an option key (e.g., 'title').
|
|
It manages a local state for the option value, a debounced setter function for that value,
|
|
and returns the local state value, its setter, and an onChange handler suitable for inputs. */
|
|
function useDebouncedInput<T = unknown>({
|
|
setOption,
|
|
setter,
|
|
optionKey,
|
|
initialValue,
|
|
delay = defaultDebouncedDelay,
|
|
}: {
|
|
setOption?: TSetOption;
|
|
setter?: SetterOrUpdater<T>;
|
|
optionKey?: string | number;
|
|
initialValue: T;
|
|
delay?: number;
|
|
}): [
|
|
(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement> | T) => void,
|
|
T,
|
|
SetterOrUpdater<T>,
|
|
// (newValue: string) => void,
|
|
] {
|
|
const [value, setValue] = useState<T>(initialValue);
|
|
|
|
/** A debounced function to call the passed setOption with the optionKey and new value.
|
|
*
|
|
Note: We use useCallback to ensure our debounced function is stable across renders. */
|
|
const setDebouncedOption = useCallback(
|
|
debounce(setOption && optionKey ? setOption(optionKey) : setter, delay),
|
|
[],
|
|
);
|
|
|
|
/** An onChange handler that updates the local state and the debounced option */
|
|
const onChange = useCallback(
|
|
(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement> | T) => {
|
|
const newValue: T =
|
|
typeof e !== 'object'
|
|
? e
|
|
: ((e as React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>)?.target
|
|
.value as unknown as T);
|
|
setValue(newValue);
|
|
setDebouncedOption(newValue);
|
|
},
|
|
[setDebouncedOption],
|
|
);
|
|
return [onChange, value, setValue];
|
|
}
|
|
|
|
export default useDebouncedInput;
|