+40
-32
src/lib/hooks/modal-close.ts
+40
-32
src/lib/hooks/modal-close.ts
···
4
4
5
5
const isCloseWatcherAvailable = typeof CloseWatcher !== 'undefined';
6
6
7
-
export const useModalClose = (container: HTMLElement, callback: () => void, enabled: () => boolean) => {
7
+
export const useModalClose = (
8
+
container: HTMLElement | null,
9
+
callback: () => void,
10
+
enabled: () => boolean,
11
+
) => {
8
12
createEffect(() => {
9
13
if (!enabled()) {
10
14
return;
11
15
}
12
16
13
-
// Close modal if clicks happen outside of container
14
-
let initialTarget: HTMLElement | null = null;
17
+
if (container !== null) {
18
+
// Close modal if clicks happen outside of container
19
+
let initialTarget: HTMLElement | null = null;
15
20
16
-
createEventListener(document, 'pointerdown', (ev) => {
17
-
// We'd like to know where the click initially started from, not where the
18
-
// click ended up, this prevents closing the modal prematurely from the
19
-
// user (accidentally) overshooting their mouse cursor.
21
+
createEventListener(document, 'pointerdown', (ev) => {
22
+
// We'd like to know where the click initially started from, not where the
23
+
// click ended up, this prevents closing the modal prematurely from the
24
+
// user (accidentally) overshooting their mouse cursor.
20
25
21
-
initialTarget = ev.target as HTMLElement | null;
22
-
});
26
+
initialTarget = ev.target as HTMLElement | null;
27
+
});
23
28
24
-
createEventListener(
25
-
document,
26
-
'click',
27
-
() => {
28
-
// Don't do anything if `initialTarget` is somehow missing
29
-
if (!initialTarget) {
30
-
return;
31
-
}
29
+
createEventListener(
30
+
document,
31
+
'click',
32
+
() => {
33
+
// Don't do anything if `initialTarget` is somehow missing
34
+
if (!initialTarget) {
35
+
return;
36
+
}
32
37
33
-
// Unset `initialTarget` now that we're here
34
-
const target = initialTarget;
35
-
initialTarget = null;
38
+
// Unset `initialTarget` now that we're here
39
+
const target = initialTarget;
40
+
initialTarget = null;
36
41
37
-
// Don't do anything if `target` is inside `container`
38
-
if (container.contains(target)) {
39
-
return;
40
-
}
42
+
// Don't do anything if `target` is inside `container`
43
+
if (container.contains(target)) {
44
+
return;
45
+
}
41
46
42
-
// Call back since this click happened outside `container`.
43
-
callback();
44
-
},
45
-
true,
46
-
);
47
+
// Call back since this click happened outside `container`.
48
+
callback();
49
+
},
50
+
true,
51
+
);
52
+
}
47
53
48
54
// Start a close watcher if available, otherwise, listen to Escape key only
49
55
if (isCloseWatcherAvailable) {
···
59
65
if (ev.key === 'Escape' && !ev.defaultPrevented) {
60
66
ev.preventDefault();
61
67
62
-
const focused = document.activeElement;
63
-
if (focused !== null && focused !== document.body) {
64
-
(focused as any).blur();
68
+
if (container !== null) {
69
+
const focused = document.activeElement;
70
+
if (focused !== null && focused !== document.body) {
71
+
(focused as any).blur();
72
+
}
65
73
}
66
74
67
75
callback();
+8
-5
src/views/main/explore.tsx
+8
-5
src/views/main/explore.tsx
···
2
2
3
3
import { Freeze } from '@mary/solid-freeze';
4
4
5
+
import { hasModals } from '~/globals/modals';
5
6
import { history } from '~/globals/navigation';
6
7
8
+
import { useModalClose } from '~/lib/hooks/modal-close';
7
9
import { createFocusEffect, useTitle } from '~/lib/navigation/router';
8
10
9
11
import MyFeedsSection from '~/components/explore/my-feeds-section';
···
28
30
createEffect(() => {
29
31
if (isInputFocused()) {
30
32
window.scrollTo({ top: 0, behavior: 'instant' });
33
+
34
+
useModalClose(
35
+
null,
36
+
() => setIsInputFocused(false),
37
+
() => !hasModals(),
38
+
);
31
39
}
32
40
});
33
41
···
59
67
setIsInputFocused(true);
60
68
}}
61
69
onClick={() => setIsInputFocused(true)}
62
-
onKeyDown={(ev) => {
63
-
if (ev.key === 'Escape') {
64
-
setIsInputFocused(false);
65
-
}
66
-
}}
67
70
onSubmit={() => {
68
71
const $query = query();
69
72
if ($query.trim() === '') {
+9
-5
src/views/search.tsx
+9
-5
src/views/search.tsx
···
2
2
3
3
import { Freeze, ShowFreeze } from '@mary/solid-freeze';
4
4
5
+
import { hasModals } from '~/globals/modals';
6
+
5
7
import { tokenizeSearchQuery } from '~/lib/bsky/search';
6
8
import { createDerivedSignal } from '~/lib/hooks/derived-signal';
9
+
import { useModalClose } from '~/lib/hooks/modal-close';
7
10
import { asString, asStringUnion, useSearchParams } from '~/lib/hooks/search-params';
8
11
import { createFocusEffect, useTitle } from '~/lib/navigation/router';
9
12
···
39
42
createEffect(() => {
40
43
if (isInputFocused()) {
41
44
window.scrollTo({ top: 0, behavior: 'instant' });
45
+
46
+
useModalClose(
47
+
null,
48
+
() => setIsInputFocused(false),
49
+
() => !hasModals(),
50
+
);
42
51
}
43
52
});
44
53
···
70
79
setIsInputFocused(true);
71
80
}}
72
81
onClick={() => setIsInputFocused(true)}
73
-
onKeyDown={(ev) => {
74
-
if (ev.key === 'Escape') {
75
-
setIsInputFocused(false);
76
-
}
77
-
}}
78
82
onSubmit={() => {
79
83
const $query = query();
80
84
if ($query.trim() === '') {