-
-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathModalProvider.tsx
51 lines (46 loc) · 1.38 KB
/
ModalProvider.tsx
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
import { Component, Show, createContext, createEffect, createSignal, onMount, useContext } from "solid-js"
import { optionExpect } from "../core/core"
import { Dynamic, Portal } from "solid-js/web"
type ModalProps<P = {}> = {
component: Component
props: P
}
const makeModalContext = () => {
const [modal, setModal] = createSignal<ModalProps>()
return { modal, setModal, clearModal: () => setModal(undefined) } as const
}
type ModalContextType = ReturnType<typeof makeModalContext>
export const ModalContext = createContext<ModalContextType>()
export const useModal = () => {
let ctx = useContext(ModalContext)
return optionExpect(ctx, "modal was undefined")
}
export const ModalProvider = (props: any) => {
return (
<ModalContext.Provider value={makeModalContext()}>
{props.children}
</ModalContext.Provider>
)
}
export const Modal: Component = () => {
let dialog: HTMLDialogElement | undefined
let { modal, clearModal } = useModal()
onMount(() => {
dialog?.addEventListener("cancel", () => clearModal())
})
createEffect(_ => {
dialog?.close()
if (modal() !== undefined) {
dialog?.showModal();
}
})
return (
<Portal>
<dialog ref={dialog} class="modal backdrop-blur">
<Show when={modal()} keyed>
{modal => <Dynamic component={modal.component} {...modal.props} />}
</Show>
</dialog>
</Portal>
)
}