popover.tsx 4.5 KB
Newer Older
L
lzzwoniu 已提交
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 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
import React, {
  CSSProperties,
  FunctionComponent,
  MouseEventHandler,
  useEffect,
  useRef,
  useState,
} from 'react'
import Trigger from './Trigger'
import ReactDOM from 'react-dom'
import Icon from '@/packages/icon'
export interface PopoverProps {
  list: Array<any>
  theme: string
  location: string
  visible: boolean
  className: string
  style?: CSSProperties
  onClick: (e: MouseEvent) => void
}
export function findDOMNode<T = HTMLElement>(node: React.ReactInstance | HTMLElement): T {
  if (node instanceof HTMLElement) {
    return node as unknown as T
  }
  return ReactDOM.findDOMNode(node) as unknown as T
}
const getEleAttr = (ele: HTMLElement | Element) => {
  if (ele && ele.getBoundingClientRect) {
    return ele.getBoundingClientRect()
  }
  return null
}
export type PopoverType = 'default' | 'primary' | 'success' | 'warning' | 'danger'
const defaultProps = {
  list: [],
  theme: 'light',
  location: 'bottom',
  visible: false,
  className: '',
  onClick: (e: MouseEvent) => {},
} as PopoverProps
export const Popover: FunctionComponent<Partial<PopoverProps>> = (props) => {
  const { children, list, theme, location, visible, className, style, onClick, ...reset } = {
    ...defaultProps,
    ...props,
  }
  const goodItem = useRef(null)
  let aa = goodItem.current && findDOMNode(goodItem.current)
  setTimeout(() => {
    if (aa) {
      setElWidth((getEleAttr(aa) as any).width)
      setElHeight((getEleAttr(aa) as any).height)
    }
  })
  const [classes, setClasses] = useState('')
  const [elWidth, setElWidth] = useState(0)
  const [elHeight, setElHeight] = useState(0)
  const [popoverContent, setPopoverContent] = useState('')
  const [popoverArrow, setPopoverArrow] = useState('')
  useEffect(() => {
    setClasses(classes_self())
    setPopoverContent(popoverContent_self())
    setPopoverArrow(popoverArrow_self())
  }, [list, theme])
  const getStyle = () => {
    const style: CSSProperties = {}
    if (location == 'top') {
      style.bottom = elHeight + 20
      style.left = 0
    } else if (location == 'right') {
      style.top = 0
      style.right = -elWidth - 20
    } else if (location == 'left') {
      style.top = 0
      style.left = -elWidth - 20
    } else {
      style.top = elHeight + 20
      style.left = 0
    }
    style.top = style.top + 'px'
    style.left = style.left + 'px'
    style.bottom = style.bottom + 'px'
    style.right = style.right + 'px'
    return style
  }
  const getArrowStyle = () => {
    const style: CSSProperties = {}
    if (location == 'top') {
      style.bottom = -20
      style.left = elWidth / 2
    } else if (location == 'right') {
      style.top = 20
      style.left = -20
    } else if (location == 'left') {
      style.top = 20
      style.right = -20
    } else {
      style.left = elWidth / 2
      style.top = -20
    }
    style.top = style.top + 'px'
    style.left = style.left + 'px'
    style.bottom = style.bottom + 'px'
    style.right = style.right + 'px'
    return style
  }

  const classes_self = () => {
    const prefixCls = 'nut-popover'
    return `${prefixCls}
    ${theme ? `${prefixCls}--${theme}` : ''}`
  }
  const popoverContent_self = () => {
    const prefixCls = 'popoverContent'
    return `${prefixCls}
    ${location ? `${prefixCls}--${location}` : ''}`
  }
  const popoverArrow_self = () => {
    const prefixCls = 'popoverArrow'
    return `${prefixCls}
    ${location ? `${prefixCls}--${location}` : ''}`
  }

  // const showPopup = props.visible
  const handleClick = (e: any) => {
    if (props.onClick) {
      props.onClick(e)
    }
  }
  return (
    <div className={`${classes} ${className}`} style={{ ...style }} {...reset}>
      <Trigger forwardedRef={goodItem}>
        <div onClick={(e) => handleClick(e)}>
          {Array.isArray(children) ? children[0] : children}
          {visible ? (
            <div className={`${popoverContent}`} style={getStyle()}>
              <div className={`${popoverArrow}`} style={getArrowStyle()}>
                {' '}
              </div>
              {Array.isArray(children) ? children[1] : ''}
              {list.map((item) => {
                return (
                  <div key={item.name} className={`title-item ${item.disabled ? 'disabled' : ''}`}>
                    {item.icon ? <Icon className="item-img" name={item.icon}></Icon> : ''}
                    <div className="title-name">{item.name}</div>
                  </div>
                )
              })}
            </div>
          ) : null}
        </div>
      </Trigger>
    </div>
  )
}

Popover.defaultProps = defaultProps
Popover.displayName = 'NutPopover'