介绍

Combobox组件构建于Popover组件之上. Combobox组件被设计用于构建具有下拉选项列表的复合输入组件的低级组件.

@rtdui/core中的Select,AutoComplete,MultiSelect组件都基于Combobox组件实现.

Combobox组件预定义一组独立的子组件, 可以自由的控制渲染和逻辑:

Combobox.Target - 用于包裹触发下拉的组件, 如Input组件. 注意: 并不是必须为input元素.
Combobox.Dropdown - 用于包裹下拉框的组件.
Combobox.Options - 用于包裹Option的组件
Combobox.Option - 用于包括自定义选项的组件
Combobox.Search - 用于在下拉框中提供额外的过滤组件
Combobox.Empty - 用于未匹配过滤条件时下拉框内容
Combobox.Chevron - 用于Target右侧的下拉指示图表
Combobox.Header - 用于为下拉提供固定的头部组件
Combobox.Footer - 用于为下拉提供固定的底部组件
Combobox.EventsTarget - 当下拉定位目标和事件目标不同时, 用于包括事件目标, 作为下拉框的事件目标, 同一Combobox下可以有多个.
Combobox.DropdownTarget - 当下拉定位目标和事件目标不同时, 用于包裹下拉目标, 作为下拉框的定位目标, 同一Combobox下最多只能有一个.
Combobox.Group - 用于选项组的组件
Combobox.ClearButton - 用于清除选择的按钮组件
Combobox.HiddenInput - 隐藏的表单域, 用于存储选择的实际值用于表单提交.

你完全可以使用Combobox及其子组件自定义实现你自己的Select,AutoComplete,MultiSelect组件

基本使用

useCombobox hook

useCombobox 钩子用于创建 combobox 的存储对象. 该存储对象包含了组件的当前状态和更新处理函数. 创建的存储必须传递给Combobox的store属性:

import { Combobox, useCombobox } from "@rtdui/core";

function Demo() {
  const combobox = useCombobox();
  return <Combobox store={combobox}>{/* Your implementation */}</Combobox>;
}

useCombobox 选项参数

interface UseComboboxOptions {
  /** Default value for `dropdownOpened`, `false` by default */
  defaultOpened?: boolean;

  /** Controlled `dropdownOpened` state */
  opened?: boolean;

  /** Called when `dropdownOpened` state changes */
  onOpenedChange?(opened: boolean): void;

  /** Called when dropdown closes with event source: keyboard, mouse or unknown */
  onDropdownClose?(eventSource: ComboboxDropdownEventSource): void;

  /** Called when dropdown opens with event source: keyboard, mouse or unknown */
  onDropdownOpen?(eventSource: ComboboxDropdownEventSource): void;

  /** Determines whether arrow key presses should loop though items (first to last and last to first), `true` by default */
  loop?: boolean;

  /** `behavior` passed down to `element.scrollIntoView`, `'instant'` by default */
  scrollBehavior?: ScrollBehavior;
}

你可以从@rtdui/core导入UseComboboxOptions类型:

import type { UseComboboxOptions } from "@rtdui/core";

Combobox 存储对象类型

interface ComboboxStore {
  /** Current dropdown opened state */
  dropdownOpened: boolean;

  /** Opens dropdown */
  openDropdown(eventSource?: "keyboard" | "mouse" | "unknown"): void;

  /** Closes dropdown */
  closeDropdown(eventSource?: "keyboard" | "mouse" | "unknown"): void;

  /** Toggles dropdown opened state */
  toggleDropdown(eventSource?: "keyboard" | "mouse" | "unknown"): void;

  /** Selected option index */
  selectedOptionIndex: number;

  /** Selects `Combobox.Option` by index */
  selectOption(index: number): void;

  /** Selects first `Combobox.Option` with `active` prop.
   *  If there are no such options, the function does nothing.
   */
  selectActiveOption(): string | null;

  /** Selects first `Combobox.Option` that is not disabled.
   *  If there are no such options, the function does nothing.
   * */
  selectFirstOption(): string | null;

  /** Selects next `Combobox.Option` that is not disabled.
   *  If the current option is the last one, the function selects first option, if `loop` is true.
   */
  selectNextOption(): string | null;

  /** Selects previous `Combobox.Option` that is not disabled.
   *  If the current option is the first one, the function selects last option, if `loop` is true.
   * */
  selectPreviousOption(): string | null;

  /** Resets selected option index to -1, removes `data-combobox-selected` from selected option */
  resetSelectedOption(): void;

  /** Triggers `onClick` event of selected option.
   *  If there is no selected option, the function does nothing.
   */
  clickSelectedOption(): void;

  /** Updates selected option index to currently selected or active option.
   *  The function is required to be used with searchable components to update selected option index
   *  when options list changes based on search query.
   */
  updateSelectedOptionIndex(target?: "active" | "selected"): void;

  /** List id, used for `aria-*` attributes */
  listId: string | null;

  /** Sets list id */
  setListId(id: string): void;

  /** Ref of `Combobox.Search` input */
  searchRef: React.MutableRefObject<HTMLInputElement | null>;

  /** Moves focus to `Combobox.Search` input */
  focusSearchInput(): void;

  /** Ref of the target element */
  targetRef: React.MutableRefObject<HTMLElement | null>;

  /** Moves focus to the target element */
  focusTarget(): void;
}

可以从 @rtdui/core导入ComboboxStore类型 :

import type { ComboboxStore } from "@rtdui/core";

可以在useCombobox的选项参数中使用存储中的处理函数, 如:

import { Combobox, useCombobox } from "@rtdui/core";

function Demo() {
  const combobox = useCombobox({
    onDropdownOpen: () => combobox.selectFirstOption(),
    onDropdownClose: () => combobox.resetSelectedOption(),
  });

  return <Combobox store={combobox}>{/* Your implementation */}</Combobox>;
}

包含所有组件的例子