-
Notifications
You must be signed in to change notification settings - Fork 296
Expand file tree
/
Copy pathuseDialog.ts
More file actions
79 lines (65 loc) · 2.4 KB
/
useDialog.ts
File metadata and controls
79 lines (65 loc) · 2.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import { useCallback, useEffect } from 'react';
import {
modalDialogManagerId,
useDialogManager,
useNearestDialogManagerContext,
} from '../../../context';
import { useStateStore } from '../../../store';
import type {
DialogManagerState,
GetOrCreateDialogParams,
} from '../service/DialogManager';
export type UseDialogParams = GetOrCreateDialogParams & {
dialogManagerId?: string;
};
export const useDialog = ({
closeOnClickOutside,
dialogManagerId,
id,
}: UseDialogParams) => {
const { dialogManager } = useDialogManager({ dialogManagerId });
useEffect(() => {
dialogManager.cancelPendingRemoval(id);
return () => {
// Since this cleanup can run even if the component is still mounted
// and dialog id is unchanged (e.g. in <StrictMode />), it's safer to
// mark state as unused and only remove it after a timeout, rather than
// to remove it immediately.
dialogManager.markForRemoval(id);
};
}, [dialogManager, id]);
return dialogManager.getOrCreate({ closeOnClickOutside, id });
};
export const useDialogOnNearestManager = ({ id }: Pick<UseDialogParams, 'id'>) => {
const { dialogManager } = useNearestDialogManagerContext() ?? {};
const dialog = useDialog({ dialogManagerId: dialogManager?.id, id });
return {
dialog,
dialogManager,
};
};
export const modalDialogId = 'modal-dialog' as const;
export const useModalDialog = () =>
useDialog({ dialogManagerId: modalDialogManagerId, id: modalDialogId });
export const useDialogIsOpen = (id: string, dialogManagerId?: string) => {
const { dialogManager } = useDialogManager({ dialogManagerId });
const dialogIsOpenSelector = useCallback(
({ dialogsById }: DialogManagerState) => ({ isOpen: !!dialogsById[id]?.isOpen }),
[id],
);
return useStateStore(dialogManager.state, dialogIsOpenSelector).isOpen;
};
export const useModalDialogIsOpen = () =>
useDialogIsOpen(modalDialogId, modalDialogManagerId);
const openedDialogCountSelector = (nextValue: DialogManagerState) => ({
openedDialogCount: Object.values(nextValue.dialogsById).reduce((count, dialog) => {
if (dialog.isOpen) return count + 1;
return count;
}, 0),
});
export const useOpenedDialogCount = ({
dialogManagerId,
}: { dialogManagerId?: string } = {}) => {
const { dialogManager } = useDialogManager({ dialogManagerId });
return useStateStore(dialogManager.state, openedDialogCountSelector).openedDialogCount;
};