import React, {useContext, useMemo} from 'react'
import {GestureResponderEvent, StyleProp, View, ViewStyle} from 'react-native'
import {HITSLOP_10} from '#/lib/constants'
import {atoms as a, useTheme} from '#/alf'
import * as Button from '#/components/Button'
import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRightIcon} from '#/components/icons/Chevron'
import {Link, LinkProps} from '#/components/Link'
import {createPortalGroup} from '#/components/Portal'
import {Text} from '#/components/Typography'
const ItemContext = React.createContext({
destructive: false,
withinGroup: false,
})
const Portal = createPortalGroup()
export function Container({children}: {children: React.ReactNode}) {
return {children}
}
/**
* This uses `Portal` magic ✨ to render the icons and title correctly. ItemIcon and ItemText components
* get teleported to the top row, leaving the rest of the children in the bottom row.
*/
export function Group({
children,
destructive = false,
iconInset = true,
style,
contentContainerStyle,
}: {
children: React.ReactNode
destructive?: boolean
iconInset?: boolean
style?: StyleProp
contentContainerStyle?: StyleProp
}) {
const context = useMemo(
() => ({destructive, withinGroup: true}),
[destructive],
)
return (
-
-
{children}
)
}
export function Item({
children,
destructive,
iconInset = false,
style,
}: {
children?: React.ReactNode
destructive?: boolean
/**
* Adds left padding so that the content will be aligned with other Items that contain icons
* @default false
*/
iconInset?: boolean
style?: StyleProp
}) {
const context = useContext(ItemContext)
const childContext = useMemo(() => {
if (typeof destructive !== 'boolean') return context
return {...context, destructive}
}, [context, destructive])
return (
{children}
)
}
export function LinkItem({
children,
destructive = false,
contentContainerStyle,
chevronColor,
...props
}: LinkProps & {
contentContainerStyle?: StyleProp
destructive?: boolean
chevronColor?: string
}) {
const t = useTheme()
return (
{args => (
-
{typeof children === 'function' ? children(args) : children}
)}
)
}
export function PressableItem({
children,
destructive = false,
contentContainerStyle,
hoverStyle,
...props
}: Button.ButtonProps & {
contentContainerStyle?: StyleProp
destructive?: boolean
}) {
const t = useTheme()
return (
{args => (
-
{typeof children === 'function' ? children(args) : children}
)}
)
}
export function ItemIcon({
icon: Comp,
size = 'xl',
color: colorProp,
}: Omit, 'position'> & {
color?: string
}) {
const t = useTheme()
const {destructive, withinGroup} = useContext(ItemContext)
/*
* Copied here from icons/common.tsx so we can tweak if we need to, but
* also so that we can calculate transforms.
*/
const iconSize = {
xs: 12,
sm: 16,
md: 20,
lg: 24,
xl: 28,
'2xl': 32,
}[size]
const color =
colorProp ?? (destructive ? t.palette.negative_500 : t.atoms.text.color)
const content = (
)
if (withinGroup) {
return {content}
} else {
return content
}
}
export function ItemText({
// eslint-disable-next-line react/prop-types
style,
...props
}: React.ComponentProps) {
const t = useTheme()
const {destructive, withinGroup} = useContext(ItemContext)
const content = (
)
if (withinGroup) {
return {content}
} else {
return content
}
}
export function Divider() {
const t = useTheme()
return (
)
}
export function Chevron({color: colorProp}: {color?: string}) {
const {destructive} = useContext(ItemContext)
const t = useTheme()
const color =
colorProp ?? (destructive ? t.palette.negative_500 : t.palette.contrast_500)
return
}
export function BadgeText({children}: {children: React.ReactNode}) {
const t = useTheme()
return (
{children}
)
}
export function BadgeButton({
label,
onPress,
}: {
label: string
onPress: (evt: GestureResponderEvent) => void
}) {
const t = useTheme()
return (
{({pressed}) => (
{label}
)}
)
}