-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(components/popover): 拆分 useShowController 处理类型
- Loading branch information
1 parent
a52e400
commit 37c5d87
Showing
4 changed files
with
148 additions
and
103 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,60 @@ | ||
import { | ||
AsyncSubject, | ||
fromEvent, | ||
switchMap, | ||
takeUntil, | ||
takeWhile, | ||
filter, | ||
delay, | ||
merge, | ||
take, | ||
tap, | ||
} from 'rxjs'; | ||
import { fromOuterEvent } from '@pkg/shared'; | ||
import { MutableRefObject } from 'react'; | ||
|
||
export function handleClick( | ||
triggerEl: HTMLElement, | ||
close: () => void, | ||
show: boolean, | ||
balloonElRef: MutableRefObject<HTMLElement | undefined>, | ||
toggle: () => AsyncSubject<boolean>, | ||
): () => void { | ||
// 点击触发元素 | ||
const triggerClick$ = fromEvent(triggerEl, 'click').pipe( | ||
// 因为 react 的合成事件是使用的事件委托机制,比直接监听 dom 的事件回调执行的要慢一步,所以加上延迟 | ||
delay(0), | ||
// 排除被拦截的事件 | ||
filter((e) => !e.defaultPrevented), | ||
); | ||
// 按下 Esc 键 | ||
const keydownEscape$ = fromEvent<KeyboardEvent>(window, 'keydown').pipe( | ||
filter((e) => e.code === 'Escape'), | ||
); | ||
// 点击除触发器与窗体之外的dom | ||
const outerClick$ = fromOuterEvent( | ||
() => [triggerEl, balloonElRef.current], | ||
'click', | ||
); | ||
// 关闭序列 | ||
const closeWaiter$ = merge(outerClick$, keydownEscape$).pipe( | ||
tap(close), | ||
takeUntil(triggerClick$), | ||
take(1), | ||
); | ||
// 开启序列 | ||
const openWaiter$ = triggerClick$.pipe( | ||
switchMap(() => | ||
// 监听 show 的变化,当 show 为 true 时结束监听并把控制权交给下一位 | ||
toggle().pipe(takeWhile((v) => v)), | ||
), | ||
switchMap(() => closeWaiter$), | ||
); | ||
// 当弹窗已经打开时(例如Button loading时会刷新该effect),添加点击和外部点击订阅 | ||
// 不然只有点击触发器才能外部点击订阅,否则如果很多popover的话会有一堆外部点击订阅 | ||
const clickSub = ( | ||
show ? merge(closeWaiter$, openWaiter$) : openWaiter$ | ||
).subscribe(); | ||
|
||
return () => clickSub.unsubscribe(); | ||
} |
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,23 @@ | ||
import { fromEvent, take, tap } from 'rxjs'; | ||
|
||
export function handleFocus( | ||
triggerEl: HTMLElement, | ||
close: () => void, | ||
open: () => void, | ||
show: boolean, | ||
): () => void { | ||
// 按下 Esc 键 | ||
// const escape$ = fromEvent<KeyboardEvent>(window, 'keydown').pipe( | ||
// filter((e) => e.code === 'Escape'), | ||
// tap(() => el.blur()), | ||
// ); | ||
const blur$ = fromEvent(triggerEl, 'blur'); | ||
const focus$ = fromEvent(triggerEl, 'focus'); | ||
|
||
const openWaiter$ = focus$.pipe(tap(open), take(1)); | ||
// const closeWaiter$ = merge(blur$, escape$).pipe(tap(close), take(1)); | ||
const closeWaiter$ = blur$.pipe(tap(close), take(1)); | ||
|
||
const focusSub = (show ? closeWaiter$ : openWaiter$).subscribe(); | ||
return () => focusSub.unsubscribe(); | ||
} |
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,57 @@ | ||
import { | ||
fromEvent, | ||
switchMap, | ||
takeUntil, | ||
Subject, | ||
delay, | ||
merge, | ||
take, | ||
tap, | ||
of, | ||
} from 'rxjs'; | ||
import React from 'react'; | ||
|
||
export function handleHover( | ||
triggerEl: HTMLElement, | ||
open: () => void, | ||
close: () => void, | ||
enterDelay: number, | ||
leaveDelay: number, | ||
show: boolean, | ||
enterBalloonSubject: React.MutableRefObject<Subject<void>>, | ||
leaveBalloonSubject: React.MutableRefObject<Subject<void>>, | ||
): () => void { | ||
const triggerEnterEvent = fromEvent(triggerEl, 'mouseenter'); | ||
const triggerMoveEvent = fromEvent(triggerEl, 'mousemove'); | ||
const triggerLeaveEvent = fromEvent(triggerEl, 'mouseleave'); | ||
|
||
const leaveEvent = merge( | ||
triggerLeaveEvent, | ||
leaveBalloonSubject.current.asObservable(), | ||
) | ||
.pipe( | ||
switchMap(() => | ||
of(null).pipe( | ||
delay(leaveDelay), | ||
takeUntil(triggerMoveEvent), | ||
takeUntil(enterBalloonSubject.current.asObservable()), | ||
), | ||
), | ||
takeUntil(triggerEnterEvent), | ||
take(1), | ||
) | ||
.pipe(tap(close)); | ||
|
||
const enterEvent = triggerEnterEvent.pipe( | ||
switchMap(() => | ||
enterDelay | ||
? of(null).pipe(delay(enterDelay), takeUntil(triggerLeaveEvent)) | ||
: of(null), | ||
), | ||
tap(open), | ||
switchMap(() => leaveEvent), | ||
); | ||
|
||
const sub = (show ? merge(leaveEvent, enterEvent) : enterEvent).subscribe(); | ||
return () => sub.unsubscribe(); | ||
} |
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