/**
* Enhanced TextInput component with focus state support for focus: modifier
*
* This component wraps React Native's TextInput and manages focus state internally,
* allowing the style prop to be a function that receives { focused: boolean }.
*
* @example
* ```tsx
* import { TextInput } from '@mgcrea/react-native-tailwind';
*
*
* ```
*/
import { forwardRef, useCallback, useState } from "react";
import {
type BlurEvent,
type FocusEvent,
TextInput as RNTextInput,
type TextInputProps as RNTextInputProps,
} from "react-native";
import { type Simplify } from "../types/util";
export type TextInputProps = Simplify<
Omit & {
/**
* Style can be a static style object/array or a function that receives focus and disabled state
*/
style?:
| RNTextInputProps["style"]
| ((state: { focused: boolean; disabled: boolean }) => RNTextInputProps["style"]);
className?: string; // compile-time only
/**
* Convenience prop for disabled state (overrides editable if provided)
* When true, sets editable to false
*/
disabled?: boolean;
}
>;
/**
* Enhanced TextInput with focus and disabled state support
*
* Manages focus state internally and passes it to style functions,
* enabling the use of focus: and disabled: modifiers in className.
*
* Note: TextInput uses `editable` prop internally. You can pass either:
* - `disabled={true}` - convenience prop (sets editable to false)
* - `editable={false}` - React Native's native prop
* If both are provided, `disabled` takes precedence.
*/
export const TextInput = forwardRef(function TextInput(
{ style, onFocus, onBlur, disabled, editable = true, ...props },
ref,
) {
const [focused, setFocused] = useState(false);
const handleFocus = useCallback(
(e: FocusEvent) => {
setFocused(true);
onFocus?.(e);
},
[onFocus],
);
const handleBlur = useCallback(
(e: BlurEvent) => {
setFocused(false);
onBlur?.(e);
},
[onBlur],
);
// Resolve editable state: disabled prop overrides editable if provided
const isEditable = disabled !== undefined ? !disabled : editable;
const isDisabled = !isEditable;
// Resolve style - call function with focus and disabled state if needed
const resolvedStyle = typeof style === "function" ? style({ focused, disabled: isDisabled }) : style;
return (
);
});