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 isHeightConstrained: false,
27})
28Context.displayName = 'DialogContext'
29
30export function useDialogContext() {
31 return useContext(Context)
32}
33
34export function useDialogControl(): DialogOuterProps['control'] {
35 const id = useId()
36 const control = useRef<DialogControlRefProps>({
37 open: () => {},
38 close: () => {},
39 })
40 const {activeDialogs} = useDialogStateContext()
41
42 useEffect(() => {
43 activeDialogs.current.set(id, control)
44 return () => {
45 // eslint-disable-next-line react-hooks/exhaustive-deps
46 activeDialogs.current.delete(id)
47 }
48 }, [id, activeDialogs])
49
50 return useMemo<DialogOuterProps['control']>(
51 () => ({
52 id,
53 ref: control,
54 open: () => {
55 if (control.current) {
56 control.current.open()
57 } else {
58 if (IS_DEV) {
59 console.warn(
60 'Attemped to open a dialog control that was not attached to a dialog!\n' +
61 'Please ensure that the Dialog is mounted when calling open/close',
62 )
63 }
64 }
65 },
66 close: cb => {
67 if (control.current) {
68 control.current.close(cb)
69 } else {
70 if (IS_DEV) {
71 console.warn(
72 'Attemped to close a dialog control that was not attached to a dialog!\n' +
73 'Please ensure that the Dialog is mounted when calling open/close',
74 )
75 }
76 }
77 },
78 }),
79 [id, control],
80 )
81}