import { Portal } from "solid-js/web"; import usePortal from "../utils/usePortal"; import useAlignPostion from "../utils/useAlignPostion"; import { createSignal, createUniqueId, onCleanup, onMount } from "solid-js"; import { useClassList } from "../utils/useProps"; import { useClickOutside } from "../utils/useClickOutside"; import createModel from "../utils/createModel"; import usezIndex from "../utils/usezIndex"; import { useTransition } from "../utils/useTransition"; import { createComputed } from "solid-js"; import { Button } from "../Button"; import { Space } from "../Layout"; export interface PopoverProps { classList?: any class?: string align?: 'top'|'bottom'|'left'|'right'|'topLeft'|'topRight'|'bottomLeft'|'bottomRight'|'leftTop'|'leftBottom'|'rightTop'|'rightBottom' trigger?: 'hover'|'click' disabled?: boolean arrow?: boolean theme?: string hideDelay?: number onOpen?: Function children?: any content?: any visible?: any ref?: any confirm?: boolean okText?: any cancleText?: any style?: any onOk?: Function, onCancel?: Function, } export function Popover (props: PopoverProps) { const [visible, setVisible] = createModel(props, 'visible', false); const [opened, setOpened] = createSignal(visible()); const [_, update] = createSignal(createUniqueId()); const [buttonLoading, setButtonLoading] = createSignal(false); let inner: any; let removeClickOutside: Function; let wrap: any; const align = () => props.align || 'right'; const trigger = () => props.confirm ? 'click' : props.trigger || 'hover'; const zindex = usezIndex(); let timer: any = null; const hideDelay = props.hideDelay || 200; const clearDelayTimer = () => { if (timer) { clearTimeout(timer); timer = null; } } const onMouseEnter = () => { if (props.disabled) { return; } if (trigger() === 'hover') { clearDelayTimer(); setVisible(true); props.onOpen && props.onOpen(true); } } const onMouseLeave = () => { if (props.disabled) { return; } if (trigger() === 'hover') { timer = setTimeout( () => { setVisible(false); props.onOpen && props.onOpen(false); }, hideDelay); } } const onClick = (e: any) => { if (props.disabled) { return; } e.preventDefault(); e.stopPropagation(); if (trigger() === 'click') { const show = visible(); setVisible(!show); props.onOpen && props.onOpen(!show); } } const classList = () => useClassList(props, 'cm-popover-inner', { // 'cm-popover-inner-show': visible(), 'cm-popover-with-arrow': props.arrow, 'cm-popover-confirm': props.confirm, [`cm-popover-${props.theme}`]: props.theme }); const transition = useTransition({ el: ()=> wrap, startClass: 'cm-popover-inner-visible', activeClass: 'cm-popover-inner-show', onLeave: () => { setOpened(false); }, onEnter: () => { setOpened(true); } }) createComputed(() => { const v = visible(); if (v) { transition.enter(); } else { transition.leave(); } }) const posStyle = () => { opened() _(); if (inner && inner.nextElementSibling) { const pos: any = useAlignPostion(align(), inner.nextElementSibling); pos.top = pos.top + document.documentElement.scrollTop + 'px'; pos.left = pos.left + document.documentElement.scrollLeft + 'px'; pos['z-index'] = zindex; Object.assign(pos, props.style || {}); return pos; } }; const onOk = async () => { if (props.onOk) { setButtonLoading(true); const ret = await props.onOk(); setButtonLoading(false); if (ret === undefined || ret === true) { setVisible(false); props.onOpen && props.onOpen(false); } } } const onCancel = () => { props.onCancel && props.onCancel(); setVisible(false); props.onOpen && props.onOpen(false); } onMount (() => { if (inner.nextElementSibling) { if (trigger() === 'hover') { inner.nextElementSibling.addEventListener('mouseenter', onMouseEnter, false); inner.nextElementSibling.addEventListener('mouseleave', onMouseLeave, false); } if (trigger() === 'click') { inner.nextElementSibling.addEventListener('click', onClick, false); removeClickOutside = useClickOutside([wrap, inner.nextElementSibling], () => { setVisible(false); }); } } }) onCleanup (() => { if (inner.nextElementSibling) { if (trigger() === 'hover') { inner.nextElementSibling.removeEventListener('mouseenter', onMouseEnter); inner.nextElementSibling.removeEventListener('mouseleave', onMouseLeave); } if (trigger() === 'click') { inner.nextElementSibling.removeEventListener('click', onClick); } } removeClickOutside && removeClickOutside(); }); const id = 'cm-popover-portal'; props.ref && props.ref({ updatePosition () { update(createUniqueId()); } }); const okText = props.okText ?? '确 定'; const cancleText = props.cancleText ?? '取 消'; return <> {props.children}
{props.content}
{ props.confirm ? : null } { props.arrow ? : null }
}