index.tsx 2.68 KB
import { DownOutlined, UpOutlined } from '@ant-design/icons';
import { useSetState } from 'ahooks';
import { Dropdown, Input } from 'antd';
import type { InputProps } from 'antd/lib/input';
import cls from 'classnames';
import React, { useImperativeHandle } from 'react';
import type {
  DropdownContentOptions,
  DropdownContentProps,
} from './dropdown-content';
import DropdownContent from './dropdown-content';

import './styles.less';

const prefix = 'qx-input-select';

/**
 * 下拉选择
 */
export const QxInputSelect = React.forwardRef<any, InputSelectProps>(
  (props, ref) => {
    const {
      className,
      options = [],
      dropdownProps,
      onChange,
      disabled,
      ...rest
    } = props;

    const [state, setState] = useSetState<InputSelectState>({
      visible: false,
    });

    const inputSuffix = (
      <div className={`${prefix}__input-suffix`}>
        {state.visible ? <UpOutlined /> : <DownOutlined />}
      </div>
    );

    const handleChange = (val: DropdownContentOptions) => {
      onChange?.(val);
      setState({ visible: false });
    };

    /**
     * 菜单显示状态改变时调用
     */
    const onVisibleChange = (visible: boolean) => {
      setState({ visible });
    };

    useImperativeHandle(ref, () => ({
      closeDropdown: () => {
        setState({ visible: false });
      },
      openDropdown: () => {
        setState({ visible: true });
      },
    }));

    return (
      <div className={cls(prefix, className)}>
        <Dropdown
          open={state.visible}
          destroyPopupOnHide
          trigger={['click']}
          className={`${prefix}__dropdown`}
          dropdownRender={() => (
            <DropdownContent
              options={options}
              onChange={handleChange}
              {...dropdownProps}
            />
          )}
          getPopupContainer={(triggerNode) => {
            if (props?.popupOnBody) {
              return document.body;
            } else {
              return triggerNode;
            }
          }}
          onOpenChange={onVisibleChange}
          disabled={disabled}
        >
          <Input
            placeholder="请选择"
            readOnly
            suffix={inputSuffix}
            onClick={() => setState({ visible: !state.visible })}
            {...rest}
            className={`${prefix}__input`}
          />
        </Dropdown>
      </div>
    );
  },
);

export interface InputSelectProps extends Omit<InputProps, 'onChange'> {
  onChange?: (args: DropdownContentOptions) => void;
  options?: DropdownContentOptions[];
  dropdownProps?: DropdownContentProps;
  disabled?: boolean;
  popupOnBody?: boolean;
}
export interface InputSelectState {
  visible: boolean;
}