forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {
2 createContext,
3 useContext,
4 useEffect,
5 useId,
6 useMemo,
7 useRef,
8} from 'react'
9
10import {useDialogStateContext} from '#/state/dialogs'
11import {
12 type DialogContextProps,
13 type DialogControlRefProps,
14 type DialogOuterProps,
15} from '#/components/Dialog/types'
16import {IS_DEV} from '#/env'
17import {BottomSheetSnapPoint} from '../../../modules/bottom-sheet/src/BottomSheet.types'
18
19export const Context = createContext<DialogContextProps>({
20 close: () => {},
21 isNativeDialog: false,
22 nativeSnapPoint: BottomSheetSnapPoint.Hidden,
23 disableDrag: false,
24 setDisableDrag: () => {},
25 isWithinDialog: false,
26})
27Context.displayName = 'DialogContext'
28
29export function useDialogContext() {
30 return useContext(Context)
31}
32
33export function useDialogControl(): DialogOuterProps['control'] {
34 const id = useId()
35 const control = useRef<DialogControlRefProps>({
36 open: () => {},
37 close: () => {},
38 })
39 const {activeDialogs} = useDialogStateContext()
40
41 useEffect(() => {
42 activeDialogs.current.set(id, control)
43 return () => {
44 // eslint-disable-next-line react-hooks/exhaustive-deps
45 activeDialogs.current.delete(id)
46 }
47 }, [id, activeDialogs])
48
49 return useMemo<DialogOuterProps['control']>(
50 () => ({
51 id,
52 ref: control,
53 open: () => {
54 if (control.current) {
55 control.current.open()
56 } else {
57 if (IS_DEV) {
58 console.warn(
59 'Attemped to open a dialog control that was not attached to a dialog!\n' +
60 'Please ensure that the Dialog is mounted when calling open/close',
61 )
62 }
63 }
64 },
65 close: cb => {
66 if (control.current) {
67 control.current.close(cb)
68 } else {
69 if (IS_DEV) {
70 console.warn(
71 'Attemped to close a dialog control that was not attached to a dialog!\n' +
72 'Please ensure that the Dialog is mounted when calling open/close',
73 )
74 }
75 }
76 },
77 }),
78 [id, control],
79 )
80}