-
Notifications
You must be signed in to change notification settings - Fork 159
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(SwipeCell): new SwipeCell (#663)
* refactor(swipe-cell): new swipe-cell * feat: add sure confirm * feat: update docs and optimize sliding * fix: spell * feat: update new docs and optimize sliding area
- Loading branch information
Showing
27 changed files
with
2,420 additions
and
2,806 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import { MaybeElementRef, UnRefElementReturn, unrefElement, useEventListener } from '@vueuse/core'; | ||
import { isArray } from 'lodash'; | ||
import { inBrowser } from '../util'; | ||
|
||
export interface UseClickAwayOptions { | ||
/** | ||
* The name of the trigger event. | ||
* @default 'touchstart' | ||
*/ | ||
eventName?: string; | ||
/** | ||
* Use capturing phase for internal event listener. | ||
* @default true | ||
*/ | ||
capture?: boolean; | ||
/** | ||
* List of elements that should not trigger the event. | ||
*/ | ||
ignore?: Array<MaybeElementRef>; | ||
/** | ||
* Run handler function if focus moves to an iframe. | ||
* @default false | ||
*/ | ||
detectIframe?: boolean; | ||
} | ||
|
||
export type UseClickAwayHandler< | ||
T extends { detectIframe: UseClickAwayOptions['detectIframe'] } = { detectIframe: false }, | ||
> = (evt: T['detectIframe'] extends true ? PointerEvent | FocusEvent : PointerEvent) => void; | ||
|
||
/** | ||
* Listen for clicks outside of a collection of elements. | ||
* @param target | ||
* @param fn | ||
* @param options | ||
*/ | ||
export function useClickAway<T extends UseClickAwayOptions>( | ||
target: MaybeElementRef | Array<MaybeElementRef>, | ||
fn: UseClickAwayHandler<{ detectIframe: T['detectIframe'] }>, | ||
options: T = {} as T, | ||
) { | ||
if (!inBrowser) return; | ||
|
||
const { eventName = 'touchstart', capture = true, ignore = [], detectIframe = false } = options; | ||
|
||
const listenerOptions = { | ||
passive: true, | ||
capture, | ||
}; | ||
|
||
// el是否包含在event.target | ||
const checkElInEvtTarget = (el: UnRefElementReturn, event: PointerEvent) => { | ||
return el && (event.target === el || event.composedPath().includes(el)); | ||
}; | ||
|
||
const shouldIgnore = (event: PointerEvent) => { | ||
return ignore.some((ignoreTarget) => checkElInEvtTarget(unrefElement(ignoreTarget), event)); | ||
}; | ||
|
||
const eventHandler = (event: PointerEvent) => { | ||
const targets = isArray(target) ? [...target] : [target]; | ||
|
||
let shouldTrigger = targets.every((targetItem) => !checkElInEvtTarget(unrefElement(targetItem), event)); | ||
|
||
if (!shouldTrigger) return; | ||
|
||
shouldTrigger = !shouldIgnore(event); | ||
|
||
if (!shouldTrigger) return; | ||
|
||
fn(event); | ||
}; | ||
|
||
const cleanup = [useEventListener(window, eventName, eventHandler, listenerOptions)]; | ||
|
||
if (detectIframe) { | ||
cleanup.push( | ||
useEventListener(window, 'blur', (event: PointerEvent) => { | ||
setTimeout(() => { | ||
const targets = isArray(target) ? [...target] : [target]; | ||
|
||
if ( | ||
targets.every((targetItem) => { | ||
const el = unrefElement(targetItem); | ||
return ( | ||
window.document.activeElement?.tagName === 'IFRAME' && !el?.contains(window.document.activeElement) | ||
); | ||
}) | ||
) { | ||
fn(event); | ||
} | ||
}, 0); | ||
}), | ||
); | ||
} | ||
|
||
return () => cleanup.forEach((clean) => clean()); | ||
} |
Oops, something went wrong.