Skip to content

Commit

Permalink
refactor(SwipeCell): new SwipeCell (#663)
Browse files Browse the repository at this point in the history
* 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
nined9 authored May 19, 2023
1 parent 2ea34ac commit fc2fff9
Show file tree
Hide file tree
Showing 27 changed files with 2,420 additions and 2,806 deletions.
98 changes: 98 additions & 0 deletions src/shared/useClickAway/index.ts
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());
}
Loading

0 comments on commit fc2fff9

Please sign in to comment.