MCPcopy Create free account
hub / github.com/bytebase/bytebase / MultiSearchableSelect

Function MultiSearchableSelect

frontend/src/react/components/ExprEditor.tsx:436–635  ·  view source on GitHub ↗
({
  value,
  optionConfig,
  disabled,
  placeholder,
  onChange,
}: {
  value: string[];
  optionConfig: OptionConfig;
  disabled?: boolean;
  placeholder?: string;
  onChange: (value: string[]) => void;
})

Source from the content-addressed store, hash-verified

434// ============================================================
435
436function MultiSearchableSelect({
437 value,
438 optionConfig,
439 disabled,
440 placeholder,
441 onChange,
442}: {
443 value: string[];
444 optionConfig: OptionConfig;
445 disabled?: boolean;
446 placeholder?: string;
447 onChange: (value: string[]) => void;
448}) {
449 const { t } = useTranslation();
450 const [search, setSearch] = useState("");
451 const [open, setOpen] = useState(false);
452 const [searchOptions, setSearchOptions] = useState<SearchableSelectOption[]>(
453 []
454 );
455 const [loading, setLoading] = useState(false);
456 const triggerRef = useRef<HTMLDivElement>(null);
457 const dropdownRef = useRef<HTMLDivElement>(null);
458 const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
459 const [knownOptions, setKnownOptions] = useState<SearchableSelectOption[]>(
460 []
461 );
462
463 const allOptions = useMemo(() => {
464 if (optionConfig.search) {
465 const merged = new Map<string, SearchableSelectOption>();
466 for (const o of knownOptions) merged.set(o.value, o);
467 for (const o of searchOptions) merged.set(o.value, o);
468 return Array.from(merged.values());
469 }
470 return optionConfig.options as SearchableSelectOption[];
471 }, [optionConfig, knownOptions, searchOptions]);
472
473 const getLabelForValue = useCallback(
474 (v: string) => {
475 const found = allOptions.find((o) => o.value === v);
476 if (found) return found.label;
477 if (optionConfig.fallback) return optionConfig.fallback(v)?.label ?? v;
478 return v;
479 },
480 [allOptions, optionConfig]
481 );
482
483 const doSearch = useCallback(
484 async (q: string) => {
485 if (!optionConfig.search) return;
486 setLoading(true);
487 try {
488 const resp = await optionConfig.search({
489 search: q,
490 pageToken: "",
491 pageSize: getDefaultPagination(),
492 });
493 setSearchOptions(resp.options as SearchableSelectOption[]);

Callers

nothing calls this directly

Calls 9

getDefaultPaginationFunction · 0.90
cnFunction · 0.90
getLabelForValueFunction · 0.85
removeValueFunction · 0.85
handleSearchChangeFunction · 0.85
toggleValueFunction · 0.85
useClickOutsideFunction · 0.70
tFunction · 0.50
setMethod · 0.45

Tested by

no test coverage detected