import { tag, WeElement, classNames, h } from 'omi' import * as css from './index.scss' //@ts-ignore import '../theme.ts' interface Props { show: boolean; x: number, y: number, direction: string, target: string | HTMLElement } @tag('m-popover') export default class Popover extends WeElement { static css = css static defaultProps = { x: 0, y: 0 } static propTypes = { show: Boolean, x: Number, y: Number, direction: String, target: String } close = () => { this.fire('close') } confirm = () => { this.fire('confirm') } left = 0 top = 0 _docClickHandler = () => { //omi mode if(this['__omiattr_']){ this.props.show = false this['__omiattr_'].show = false } //html element mode this.removeAttribute('show') this.fire('close') } uninstall() { document.removeEventListener('mousedown', this._docClickHandler) } mouseDownHandler = (evt) => { evt.stopPropagation() } updated() { this._setPosition() } installed() { document.addEventListener('mousedown', this._docClickHandler) this._setPosition() } getScopeRoot(current) { while (true) { const p = current.parentNode if (p) { current = p } else { return current } } } _setPosition() { if (this.props.show) { const rectA = this.shadowRoot.querySelector('.m-popover').getBoundingClientRect() const rectB = (typeof this.props.target === 'string' ? this.getScopeRoot(this).querySelector(this.props.target):this.props.target).getBoundingClientRect() let tempLeft, tempTop let st = document.documentElement.scrollTop || document.body.scrollTop let sl = document.documentElement.scrollLeft || document.body.scrollLeft switch (this.props.direction) { case 'top-left': tempLeft = rectB.left tempTop = (rectB.top - rectA.height - 10) break case 'top': tempLeft = rectB.left + (rectB.width / 2 - rectA.width / 2) tempTop = (rectB.top - rectA.height - 10) break case 'top-right': tempLeft = rectB.left + rectB.width - rectA.width tempTop = (rectB.top - rectA.height - 10) break case 'left': tempLeft = rectB.left - rectA.width - 10 tempTop = rectB.top + (rectB.height - rectA.height) / 2 break case 'left-top': tempLeft = rectB.left - rectA.width - 10 tempTop = rectB.top break case 'left-bottom': tempLeft = rectB.left - rectA.width - 10 tempTop = rectB.top + (rectB.height - rectA.height) break case 'bottom-left': tempLeft = rectB.left tempTop = (rectB.top + rectB.height + 10) break case 'bottom': tempLeft = rectB.left + (rectB.width / 2 - rectA.width / 2) tempTop = (rectB.top + rectB.height + 10) break case 'bottom-right': tempLeft = rectB.left + rectB.width - rectA.width tempTop = (rectB.top + rectB.height + 10) break case 'right': tempLeft = rectB.left + rectB.width + 10 tempTop = rectB.top + (rectB.height - rectA.height) / 2 break case 'right-top': tempLeft = rectB.left + rectB.width + 10 tempTop = rectB.top break case 'right-bottom': tempLeft = rectB.left + rectB.width + 10 tempTop = rectB.top + (rectB.height - rectA.height) break } tempLeft = tempLeft + this.props.x + sl +'px' tempTop = tempTop + this.props.y + st + 'px' if (this.left !== tempLeft || this.top !== tempTop) { this.left = tempLeft this.top = tempTop this.update() } } } render(props) { if (!props.show) return const cls = classNames('_arrow', '_' + props.direction) const { style, ...other } = props return (
) } }