mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React from 'react'
2import {View} from 'react-native'
3import {msg} from '@lingui/macro'
4import {useLingui} from '@lingui/react'
5
6import {atoms as a, useBreakpoints, useTheme} from '#/alf'
7import {Button, ButtonColor, ButtonText} from '#/components/Button'
8import * as Dialog from '#/components/Dialog'
9import {Text} from '#/components/Typography'
10
11export {useDialogControl as usePromptControl} from '#/components/Dialog'
12
13const Context = React.createContext<{
14 titleId: string
15 descriptionId: string
16}>({
17 titleId: '',
18 descriptionId: '',
19})
20
21export function Outer({
22 children,
23 control,
24 testID,
25}: React.PropsWithChildren<{
26 control: Dialog.DialogOuterProps['control']
27 testID?: string
28}>) {
29 const {gtMobile} = useBreakpoints()
30 const titleId = React.useId()
31 const descriptionId = React.useId()
32
33 const context = React.useMemo(
34 () => ({titleId, descriptionId}),
35 [titleId, descriptionId],
36 )
37
38 return (
39 <Dialog.Outer control={control} testID={testID}>
40 <Context.Provider value={context}>
41 <Dialog.Handle />
42
43 <Dialog.ScrollableInner
44 accessibilityLabelledBy={titleId}
45 accessibilityDescribedBy={descriptionId}
46 style={[
47 gtMobile ? {width: 'auto', maxWidth: 400, minWidth: 200} : a.w_full,
48 ]}>
49 {children}
50 </Dialog.ScrollableInner>
51 </Context.Provider>
52 </Dialog.Outer>
53 )
54}
55
56export function TitleText({children}: React.PropsWithChildren<{}>) {
57 const {titleId} = React.useContext(Context)
58 return (
59 <Text nativeID={titleId} style={[a.text_2xl, a.font_bold, a.pb_sm]}>
60 {children}
61 </Text>
62 )
63}
64
65export function DescriptionText({
66 children,
67 selectable,
68}: React.PropsWithChildren<{selectable?: boolean}>) {
69 const t = useTheme()
70 const {descriptionId} = React.useContext(Context)
71 return (
72 <Text
73 nativeID={descriptionId}
74 selectable={selectable}
75 style={[a.text_md, a.leading_snug, t.atoms.text_contrast_high, a.pb_lg]}>
76 {children}
77 </Text>
78 )
79}
80
81export function Actions({children}: React.PropsWithChildren<{}>) {
82 const {gtMobile} = useBreakpoints()
83
84 return (
85 <View
86 style={[
87 a.w_full,
88 a.gap_md,
89 a.justify_end,
90 gtMobile
91 ? [a.flex_row, a.flex_row_reverse, a.justify_start]
92 : [a.flex_col],
93 ]}>
94 {children}
95 </View>
96 )
97}
98
99export function Cancel({
100 cta,
101}: {
102 /**
103 * Optional i18n string. If undefined, it will default to "Cancel".
104 */
105 cta?: string
106}) {
107 const {_} = useLingui()
108 const {gtMobile} = useBreakpoints()
109 const {close} = Dialog.useDialogContext()
110 const onPress = React.useCallback(() => {
111 close()
112 }, [close])
113
114 return (
115 <Button
116 variant="solid"
117 color="secondary"
118 size={gtMobile ? 'small' : 'medium'}
119 label={cta || _(msg`Cancel`)}
120 onPress={onPress}>
121 <ButtonText>{cta || _(msg`Cancel`)}</ButtonText>
122 </Button>
123 )
124}
125
126export function Action({
127 onPress,
128 color = 'primary',
129 cta,
130 testID,
131}: {
132 /**
133 * Callback to run when the action is pressed. The method is called _after_
134 * the dialog closes.
135 *
136 * Note: The dialog will close automatically when the action is pressed, you
137 * should NOT close the dialog as a side effect of this method.
138 */
139 onPress: () => void
140 color?: ButtonColor
141 /**
142 * Optional i18n string. If undefined, it will default to "Confirm".
143 */
144 cta?: string
145 testID?: string
146}) {
147 const {_} = useLingui()
148 const {gtMobile} = useBreakpoints()
149 const {close} = Dialog.useDialogContext()
150 const handleOnPress = React.useCallback(() => {
151 close(onPress)
152 }, [close, onPress])
153
154 return (
155 <Button
156 variant="solid"
157 color={color}
158 size={gtMobile ? 'small' : 'medium'}
159 label={cta || _(msg`Confirm`)}
160 onPress={handleOnPress}
161 testID={testID}>
162 <ButtonText>{cta || _(msg`Confirm`)}</ButtonText>
163 </Button>
164 )
165}
166
167export function Basic({
168 control,
169 title,
170 description,
171 cancelButtonCta,
172 confirmButtonCta,
173 onConfirm,
174 confirmButtonColor,
175 showCancel = true,
176}: React.PropsWithChildren<{
177 control: Dialog.DialogOuterProps['control']
178 title: string
179 description: string
180 cancelButtonCta?: string
181 confirmButtonCta?: string
182 /**
183 * Callback to run when the Confirm button is pressed. The method is called
184 * _after_ the dialog closes.
185 *
186 * Note: The dialog will close automatically when the action is pressed, you
187 * should NOT close the dialog as a side effect of this method.
188 */
189 onConfirm: () => void
190 confirmButtonColor?: ButtonColor
191 showCancel?: boolean
192}>) {
193 return (
194 <Outer control={control} testID="confirmModal">
195 <TitleText>{title}</TitleText>
196 <DescriptionText>{description}</DescriptionText>
197 <Actions>
198 <Action
199 cta={confirmButtonCta}
200 onPress={onConfirm}
201 color={confirmButtonColor}
202 testID="confirmBtn"
203 />
204 {showCancel && <Cancel cta={cancelButtonCta} />}
205 </Actions>
206 </Outer>
207 )
208}