import React from 'react'; import { ChevronDown } from 'lucide-react'; import { YStack, XStack } from '@tamagui/stacks'; import { SizableText as Text } from '@tamagui/text'; import { Input, TextArea } from 'tamagui'; import { Select } from '@tamagui/select'; import { withAlpha } from './colors'; import { useAdminTheme } from '../theme'; type FieldProps = { label: React.ReactNode; hint?: string; error?: string | null; children: React.ReactNode; }; export function MobileField({ label, hint, error, children }: FieldProps) { const { text, muted, danger } = useAdminTheme(); return ( {typeof label === 'string' || typeof label === 'number' ? ( {label} ) : ( label )} {children} {hint ? ( {hint} ) : null} {error ? ( {error} ) : null} ); } type ControlProps = { hasError?: boolean; compact?: boolean; }; type MobileSelectProps = React.ComponentPropsWithoutRef<'select'> & ControlProps & { placeholder?: string; containerStyle?: React.CSSProperties; }; export const MobileColorInput = React.forwardRef< HTMLInputElement, React.ComponentPropsWithoutRef<'input'> & { size?: number } >(function MobileColorInput({ size = 52, style, ...props }, ref) { const { border, surface } = useAdminTheme(); return ( ); }); export const MobileFileInput = React.forwardRef>( function MobileFileInput({ style, ...props }, ref) { return ( ); }, ); export const MobileDateTimeInput = React.forwardRef< HTMLInputElement, React.ComponentPropsWithoutRef<'input'> & ControlProps >(function MobileDateTimeInput({ hasError = false, style, ...props }, ref) { const { border, surface, text, primary, danger } = useAdminTheme(); const ringColor = hasError ? withAlpha(danger, 0.18) : withAlpha(primary, 0.18); const borderColor = hasError ? danger : border; return ( { event.currentTarget.style.boxShadow = `0 0 0 3px ${ringColor}`; props.onFocus?.(event); }} onBlur={(event) => { event.currentTarget.style.boxShadow = `0 0 0 0 ${ringColor}`; props.onBlur?.(event); }} /> ); }); export const MobileDateInput = React.forwardRef< HTMLInputElement, React.ComponentPropsWithoutRef<'input'> & ControlProps >(function MobileDateInput({ hasError = false, style, ...props }, ref) { const { border, surface, text, primary, danger } = useAdminTheme(); const ringColor = hasError ? withAlpha(danger, 0.18) : withAlpha(primary, 0.18); const borderColor = hasError ? danger : border; return ( { event.currentTarget.style.boxShadow = `0 0 0 3px ${ringColor}`; props.onFocus?.(event); }} onBlur={(event) => { event.currentTarget.style.boxShadow = `0 0 0 0 ${ringColor}`; props.onBlur?.(event); }} /> ); }); export const MobileInput = React.forwardRef & ControlProps>( function MobileInput({ hasError = false, compact = false, style, onChange, type, ...props }, ref) { const { border, surface, text, primary, danger } = useAdminTheme(); const borderColor = hasError ? danger : border; const ringColor = hasError ? withAlpha(danger, 0.18) : withAlpha(primary, 0.18); const isPassword = type === 'password'; return ( } {...props} {...({ type } as any)} secureTextEntry={isPassword} onChangeText={(value: string) => { onChange?.({ target: { value } } as React.ChangeEvent); }} size={compact ? '$3' : '$4'} height={compact ? 36 : 44} paddingHorizontal="$3" borderRadius={12} width="100%" fontSize={compact ? 13 : 14} backgroundColor={surface} color={text} borderColor={borderColor} focusStyle={{ borderColor: hasError ? danger : primary, boxShadow: `0 0 0 3px ${ringColor}`, } as any} hoverStyle={{ borderColor, } as any} style={style as any} /> ); }, ); export const MobileTextArea = React.forwardRef< HTMLTextAreaElement, React.ComponentPropsWithoutRef<'textarea'> & ControlProps >(function MobileTextArea({ hasError = false, compact = false, style, onChange, ...props }, ref) { const { border, surface, text, primary, danger } = useAdminTheme(); const borderColor = hasError ? danger : border; const ringColor = hasError ? withAlpha(danger, 0.18) : withAlpha(primary, 0.18); return (