MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / FreeformCombobox

Function FreeformCombobox

packages/react/src/components/combobox.tsx:280–373  ·  view source on GitHub ↗
(props: {
  readonly value: string;
  readonly onValueChange: (value: string) => void;
  readonly options: readonly FreeformComboboxOption[];
  readonly placeholder?: string;
  readonly emptyLabel?: React.ReactNode;
  readonly className?: string;
  readonly inputClassName?: string;
  readonly disabled?: boolean;
  /** Forwarded to the underlying text input so a `<Label htmlFor>` can target it
   *  (and tests get a stable selector). */
  readonly id?: string;
})

Source from the content-addressed store, hash-verified

278const FREEFORM_COMBOBOX_LIMIT = 100;
279
280function FreeformCombobox(props: {
281 readonly value: string;
282 readonly onValueChange: (value: string) => void;
283 readonly options: readonly FreeformComboboxOption[];
284 readonly placeholder?: string;
285 readonly emptyLabel?: React.ReactNode;
286 readonly className?: string;
287 readonly inputClassName?: string;
288 readonly disabled?: boolean;
289 /** Forwarded to the underlying text input so a `<Label htmlFor>` can target it
290 * (and tests get a stable selector). */
291 readonly id?: string;
292}) {
293 const valueOption = props.value.trim();
294 const propsOptions = props.options;
295 const options = React.useMemo<readonly FreeformComboboxOption[]>(
296 () =>
297 valueOption.length > 0 && !propsOptions.some((option) => option.value === valueOption)
298 ? [{ value: valueOption, label: valueOption }, ...propsOptions]
299 : propsOptions,
300 [valueOption, propsOptions],
301 );
302 const selectedValue = options.some((option) => option.value === props.value) ? props.value : null;
303
304 const byValue = React.useMemo(() => {
305 const map = new Map<string, FreeformComboboxOption>();
306 for (const option of options) map.set(option.value, option);
307 return map;
308 }, [options]);
309 const items = React.useMemo(() => options.map((option) => option.value), [options]);
310
311 // base-ui only filters the popup when the list renders from `items` (the
312 // function-child / closed-template path below); a statically-mapped list never
313 // narrows as you type. Match the query against the value AND its string
314 // label/description, so typing a summary word or the human label finds the
315 // option, not just its raw id.
316 const filter = React.useCallback(
317 (item: string, query: string) => {
318 const needle = query.trim().toLowerCase();
319 if (needle === "") return true;
320 const option = byValue.get(item);
321 const haystacks = [
322 item,
323 typeof option?.label === "string" ? option.label : "",
324 typeof option?.description === "string" ? option.description : "",
325 ];
326 return haystacks.some((part) => part.toLowerCase().includes(needle));
327 },
328 [byValue],
329 );
330
331 return (
332 <Combobox
333 items={items}
334 inputValue={props.value}
335 value={selectedValue}
336 filter={filter}
337 limit={FREEFORM_COMBOBOX_LIMIT}

Callers

nothing calls this directly

Calls 2

setMethod · 0.80
getMethod · 0.65

Tested by

no test coverage detected