All files / src/tagselect TagSelectBox.tsx

27.78% Statements 5/18
33.33% Branches 3/9
28.57% Functions 2/7
27.78% Lines 5/18

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117                                                                                                                                                                                                            6x 6x     6x 12x             6x    
import React, { useLayoutEffect } from "react";
import { DropdownBox } from "../dropdown";
import {
  VirtualizedList as List,
  VirtualizedListProps,
} from "../list/VirtualizedList";
import { SelectOption } from "../select/SelectOption";
import { StyledProps } from "../_type";
import { SelectProps } from "../select/Select";
 
export interface TagSelectBoxProps extends StyledProps {
  items: ListItem[];
  width: number;
  onChange: (
    value: string,
    context: { event: React.MouseEvent; option: SelectOption }
  ) => void;
  scheduleUpdate: () => void;
  tips: React.ReactNode;
  currentIndex: number;
  listRef: VirtualizedListProps["virtualizedRef"];
  itemRefContent: VirtualizedListProps["itemRefContent"];
  onScrollBottom: VirtualizedListProps["onScrollBottom"];
}
 
export function TagSelectBox({
  listRef,
  items,
  onChange,
  width,
  scheduleUpdate,
  className,
  style = {},
  currentIndex,
  itemRefContent,
  onScrollBottom,
}: TagSelectBoxProps) {
  useLayoutEffect(() => {
    scheduleUpdate();
  }, [scheduleUpdate]);
 
  const count = items.length;
  if (count === 0) {
    return null;
  }
 
  return (
    <DropdownBox
      onClick={e => e.stopPropagation()}
      className={className}
      style={{ ...style, width }}
    >
      <List
        virtualizedRef={listRef}
        type="option"
        itemCount={count}
        itemRefContent={itemRefContent}
        onScrollBottom={onScrollBottom}
      >
        {({ index, style }) => {
          const { type, text, key, option } = items[index];
          if (type === "tips") {
            return (
              <List.StatusTip style={style} key={key}>
                {text}
              </List.StatusTip>
            );
          }
          return (
            <List.Item
              key={key}
              disabled={option.disabled}
              current={currentIndex % count === index}
              onClick={event => {
                onChange(option.value, {
                  event,
                  option,
                });
              }}
              tooltip={option.tooltip}
              style={style}
            >
              {text}
            </List.Item>
          );
        }}
      </List>
    </DropdownBox>
  );
}
 
interface ListItem {
  type: "tips" | "option" | "group";
  key: string;
  text: React.ReactNode;
  option?: SelectOption;
}
 
export function getListItems({
  tips,
  options,
}: Pick<SelectProps, "tips" | "options">): ListItem[] {
  const items: ListItem[] = [];
  Iif (tips) {
    items.push({ type: "tips", key: "__select_tips", text: tips });
  }
  options.forEach(opt => {
    items.push({
      type: "option",
      key: opt.value,
      text: typeof opt.text === "undefined" ? opt.value : opt.text,
      option: opt,
    });
  });
  return items;
}