-
Notifications
You must be signed in to change notification settings - Fork 41
Expand file tree
/
Copy pathuse-dialogs.tsx
More file actions
85 lines (77 loc) · 2.18 KB
/
use-dialogs.tsx
File metadata and controls
85 lines (77 loc) · 2.18 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
80
81
82
83
84
85
/**
* (c) 2021, Micro:bit Educational Foundation and contributors
*
* SPDX-License-Identifier: MIT
*/
import React, { ReactNode, useContext, useMemo } from "react";
import useRafState from "./use-raf-state";
import ProgressDialog, { ProgressDialogParameters } from "./ProgressDialog";
const DialogContext = React.createContext<Dialogs | undefined>(undefined);
interface DialogProviderProps {
children: ReactNode;
}
export const DialogProvider = ({ children }: DialogProviderProps) => {
const [dialogState, setDialogState] = useRafState<ReactNode | undefined>(
undefined
);
const [progressDialogState, setProgressDialogState] = useRafState<
ProgressDialogParameters | undefined
>(undefined);
const dialogs = useMemo(
() => new Dialogs(setDialogState, setProgressDialogState),
[setDialogState, setProgressDialogState]
);
return (
<DialogContext.Provider value={dialogs}>
<>
{dialogState}
{progressDialogState && (
<ProgressDialog isOpen {...progressDialogState} />
)}
{children}
</>
</DialogContext.Provider>
);
};
export class Dialogs {
constructor(
private dialogSetState: (node: ReactNode) => void,
private progressDialogSetState: (
options: ProgressDialogParameters | undefined
) => void
) {}
/**
* Show a dialog and wait until it calls the callback.
*
* @param dialogFactory Creates the dialog.
* @returns The value passed to the callback.
*/
show<T>(
dialogFactory: (callback: (result: T) => void) => ReactNode
): Promise<T> {
return new Promise<T>((_resolve) => {
const resolve = (result: T) => {
this.dialogSetState(undefined);
_resolve(result);
};
const dialog = dialogFactory(resolve);
this.dialogSetState(dialog);
});
}
progress(options: ProgressDialogParameters): void {
this.progressDialogSetState(options);
}
closeProgress(): void {
this.progressDialogSetState(undefined);
}
}
/**
* A hook providing common dialog functionality.
*/
export const useDialogs = () => {
const dialogs = useContext(DialogContext);
if (!dialogs) {
throw new Error("Missing provider!");
}
return dialogs;
};