Something went wrong. Try again.
hardened bluesky app fork with microcosm
Something went wrong. Try again.
6.4 kB · 265 lines
TSX
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266import {createContext, useCallback, useContext, useId, useMemo} from 'react'import {type GestureResponderEvent, View} from 'react-native'import {useLingui} from '@lingui/react/macro'
import {atoms as a, type TextStyleProp, useTheme, web} from '#/alf'import { Button, type ButtonColor, ButtonIcon, ButtonText,} from '#/components/Button'import * as Dialog from '#/components/Dialog'import {type Props as SVGIconProps} from '#/components/icons/common'import {Text} from '#/components/Typography'import {type BottomSheetViewProps} from '../../modules/bottom-sheet'
export { type DialogControlProps as PromptControlProps, useDialogControl as usePromptControl,} from '#/components/Dialog'
const Context = createContext<{ titleId: string descriptionId: string}>({ titleId: '', descriptionId: '',})Context.displayName = 'PromptContext'
export function Outer({ children, control, testID, nativeOptions, webOptions, onClose,}: React.PropsWithChildren<{ control: Dialog.DialogControlProps testID?: string /** * Native-specific options for the prompt. Extends `BottomSheetViewProps` */ nativeOptions?: Omit<BottomSheetViewProps, 'children'> /** * Web-specific options for the prompt */ webOptions?: { onBackgroundPress?: (e: GestureResponderEvent) => void } onClose?: () => void}>) { const titleId = useId() const descriptionId = useId()
const context = useMemo( () => ({titleId, descriptionId}), [titleId, descriptionId], )
return ( <Dialog.Outer control={control} testID={testID} onClose={onClose} webOptions={{alignCenter: true, ...webOptions}} nativeOptions={{preventExpansion: true, ...nativeOptions}}> <Dialog.Handle /> <Context.Provider value={context}> <Dialog.ScrollableInner accessibilityLabelledBy={titleId} accessibilityDescribedBy={descriptionId} style={web([{maxWidth: 320, borderRadius: 36}])}> {children} </Dialog.ScrollableInner> </Context.Provider> </Dialog.Outer> )}
export function TitleText({ children, style,}: React.PropsWithChildren<TextStyleProp>) { const {titleId} = useContext(Context) return ( <Text nativeID={titleId} style={[ a.flex_1, a.text_2xl, a.font_semi_bold, a.pb_xs, a.leading_snug, style, ]}> {children} </Text> )}
export function DescriptionText({ children, selectable, style,}: React.PropsWithChildren<{selectable?: boolean} & TextStyleProp>) { const t = useTheme() const {descriptionId} = useContext(Context) return ( <Text nativeID={descriptionId} selectable={selectable} style={[ a.text_md, a.leading_snug, t.atoms.text_contrast_high, a.pb_lg, style, ]}> {children} </Text> )}
export function Actions({children}: {children: React.ReactNode}) { return <View style={[a.w_full, a.gap_sm, a.justify_end]}>{children}</View>}
export function Content({children}: {children: React.ReactNode}) { return <View style={[a.pb_sm]}>{children}</View>}
export function Cancel({ cta,}: { /** * Optional i18n string. If undefined, it will default to "Cancel". */ cta?: string}) { const {t: l} = useLingui() const {close} = Dialog.useDialogContext() const onPress = useCallback(() => { close() }, [close])
return ( <Button variant="solid" color="secondary" size="large" label={cta || l`Cancel`} onPress={onPress}> <ButtonText>{cta || l`Cancel`}</ButtonText> </Button> )}
export function Action({ onPress, color = 'primary', cta, disabled = false, icon, shouldCloseOnPress = true, testID,}: { /** * Callback to run when the action is pressed. The method is called _after_ * the dialog closes. * * Note: The dialog will close automatically when the action is pressed, you * should NOT close the dialog as a side effect of this method. */ onPress: (e: GestureResponderEvent) => void color?: ButtonColor /** * Optional i18n string. If undefined, it will default to "Confirm". */ cta?: string /** * If undefined, it will default to false. */ disabled?: boolean icon?: React.ComponentType<SVGIconProps> /** * Optionally close dialog automatically on press. If undefined, it will * default to true. */ shouldCloseOnPress?: boolean testID?: string}) { const {t: l} = useLingui() const {close} = Dialog.useDialogContext() const handleOnPress = useCallback( (e: GestureResponderEvent) => { if (shouldCloseOnPress) { close(() => onPress?.(e)) } else { onPress?.(e) } }, [close, onPress, shouldCloseOnPress], )
return ( <Button color={color} disabled={disabled} size="large" label={cta || l`Confirm`} onPress={handleOnPress} testID={testID}> <ButtonText>{cta || l`Confirm`}</ButtonText> {icon && <ButtonIcon icon={icon} />} </Button> )}
export function Basic({ control, title, description, cancelButtonCta, confirmButtonCta, onConfirm, onClose, confirmButtonColor, showCancel = true,}: React.PropsWithChildren<{ control: Dialog.DialogOuterProps['control'] title: string description?: string cancelButtonCta?: string confirmButtonCta?: string /** * Callback to run when the Confirm button is pressed. The method is called * _after_ the dialog closes. * * Note: The dialog will close automatically when the action is pressed, you * should NOT close the dialog as a side effect of this method. */ onConfirm: (e: GestureResponderEvent) => void onClose?: () => void confirmButtonColor?: ButtonColor showCancel?: boolean}>) { return ( <Outer control={control} testID="confirmModal" onClose={onClose}> <Content> <TitleText>{title}</TitleText> {description && <DescriptionText>{description}</DescriptionText>} </Content> <Actions> <Action cta={confirmButtonCta} onPress={onConfirm} color={confirmButtonColor} testID="confirmBtn" /> {showCancel && <Cancel cta={cancelButtonCta} />} </Actions> </Outer> )}