@geekyhawks/react-native-ui-components
Version:
A lightweight and reusable React Native UI components library with customizable Text, TextInput, FloatingLabelTextInput, Button, and more. Built with TypeScript, fully typed, and designed for easy integration into any React Native project.
166 lines • 9.9 kB
JavaScript
"use strict";
/**
* TextInput
*
* A customizable wrapper around React Native's `TextInput` component.
* Provides support for predefined style variants (outline, filled, underline),
* size variants (sm, md, lg), and theme integration.
*
* Author: Geeky Hawks FZE LLC
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
const react_1 = __importStar(require("react"));
const react_native_1 = require("react-native");
const theme_1 = require("../../theme");
const Text_1 = require("../Text");
const resolveThemeColor_1 = require("../../theme/utils/resolveThemeColor");
/** Animated Text */
const AnimatedText = react_native_1.Animated.createAnimatedComponent(Text_1.Text);
/**
* TextInput
*
* A customizable wrapper around React Native's `TextInput`.
* Applies default styleVariants, sizeVariants, theme colors, and error/helper text handling.
*/
const TextInput = (_a) => {
var _b, _c, _d, _e, _f, _g, _h;
var { accessible = true, accessibilityLabel, accessibilityState, containerStyle, disabled = false, error, errorPosition = "left", errorTextStyle, fontFamily, fullWidth = true, helperText, helperTextStyle, inputContainerStyle, inputStyle, label, labelStyle, leftIcon, loading = false, multiline = false, numberOfLines = 1, passwordToggleIcons, placeholderTextColor, rightIcon, secureTextEntry, size = "md", variant = "outline" } = _a, rest = __rest(_a, ["accessible", "accessibilityLabel", "accessibilityState", "containerStyle", "disabled", "error", "errorPosition", "errorTextStyle", "fontFamily", "fullWidth", "helperText", "helperTextStyle", "inputContainerStyle", "inputStyle", "label", "labelStyle", "leftIcon", "loading", "multiline", "numberOfLines", "passwordToggleIcons", "placeholderTextColor", "rightIcon", "secureTextEntry", "size", "variant"]);
const { theme, textInputStyleVariants, textInputSizeVariants } = (0, theme_1.useTheme)();
const [isFocused, setFocused] = (0, react_1.useState)(false);
const [showPassword, setShowPassword] = (0, react_1.useState)(false);
const sizeVariant = textInputSizeVariants[size] || textInputSizeVariants.md;
const styleVariant = textInputStyleVariants[variant] || textInputStyleVariants.outline;
const isError = !!error;
const focusAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(0)).current;
const initialBorderColor = (_c = (0, resolveThemeColor_1.resolveThemeColor)((_b = styleVariant.container) === null || _b === void 0 ? void 0 : _b.borderColor, theme)) !== null && _c !== void 0 ? _c : theme.colors.border;
const focusedBorderColor = (isError ? theme.colors.error : theme.colors.primary);
const containerBackgroundColor = (_e = (0, resolveThemeColor_1.resolveThemeColor)((_d = styleVariant.container) === null || _d === void 0 ? void 0 : _d.backgroundColor, theme)) !== null && _e !== void 0 ? _e : "transparent";
const inputTextColor = (_g = (0, resolveThemeColor_1.resolveThemeColor)((_f = styleVariant.input) === null || _f === void 0 ? void 0 : _f.color, theme)) !== null && _g !== void 0 ? _g : theme.colors.text;
const _j = (_h = styleVariant.input) !== null && _h !== void 0 ? _h : {}, { color: _discardColor } = _j, inputStyleVariant = __rest(_j, ["color"]);
// Animate border color
const borderColor = focusAnim.interpolate({
inputRange: [0, 1],
outputRange: [initialBorderColor, focusedBorderColor],
});
// Animate label color
const labelColor = focusAnim.interpolate({
inputRange: [0, 1],
outputRange: [
theme.colors.text,
isError ? theme.colors.error : theme.colors.primary,
],
});
// Animated style
const containerStyles = [
styleVariant.container,
{
flexDirection: "row",
alignItems: "center",
backgroundColor: containerBackgroundColor,
},
{ borderColor, opacity: disabled ? 0.6 : 1 },
fullWidth && { width: "100%" },
inputContainerStyle,
];
(0, react_1.useEffect)(() => {
react_native_1.Animated.timing(focusAnim, {
toValue: isFocused || isError ? 1 : 0,
duration: 200,
useNativeDriver: false,
}).start();
}, [isFocused, isError]);
return (react_1.default.createElement(react_native_1.View, { style: [{ width: fullWidth ? "100%" : undefined }, containerStyle], accessible: accessible, accessibilityLabel: label || rest.placeholder, accessibilityState: Object.assign({ disabled }, (error ? { invalid: true } : {})) },
label ? (react_1.default.createElement(AnimatedText, { variant: "body", style: [
{ marginBottom: 4, fontWeight: "bold" },
{ color: labelColor },
fontFamily ? { fontFamily } : {},
labelStyle,
] }, label)) : null,
react_1.default.createElement(react_native_1.Animated.View, { style: [{ flexDirection: "row", alignItems: "center" }, containerStyles] },
leftIcon ? react_1.default.createElement(react_native_1.View, { style: { marginRight: 8 } }, leftIcon) : null,
react_1.default.createElement(react_native_1.TextInput, Object.assign({}, rest, { style: [
{ flex: 1, color: theme.colors.text, fontFamily: theme.fontFamily },
{
fontSize: sizeVariant.fontSize,
paddingVertical: sizeVariant.paddingVertical,
textAlignVertical: multiline ? "top" : "center",
minHeight: multiline
? (sizeVariant.fontSize + sizeVariant.paddingVertical * 2) * (numberOfLines || 1)
: undefined,
},
inputStyleVariant,
{ color: inputTextColor },
fontFamily ? { fontFamily } : {},
inputStyle,
], secureTextEntry: secureTextEntry && !showPassword, placeholderTextColor: placeholderTextColor !== null && placeholderTextColor !== void 0 ? placeholderTextColor : theme.colors.muted, editable: !disabled && !loading, multiline: multiline, numberOfLines: numberOfLines, onFocus: (e) => {
var _a;
setFocused(true);
(_a = rest.onFocus) === null || _a === void 0 ? void 0 : _a.call(rest, e);
}, onBlur: (e) => {
var _a;
setFocused(false);
(_a = rest.onBlur) === null || _a === void 0 ? void 0 : _a.call(rest, e);
} })),
!loading && secureTextEntry ? (react_1.default.createElement(react_native_1.TouchableOpacity, { onPress: () => setShowPassword((prev) => !prev), style: { marginLeft: 8 } }, passwordToggleIcons ? (showPassword
? passwordToggleIcons.hide || null
: passwordToggleIcons.show || null) : (react_1.default.createElement(Text_1.Text, { variant: "caption", color: theme.colors.primary, style: [
fontFamily ? { fontFamily } : {}
] }, showPassword ? "Hide" : "Show")))) : null,
rightIcon ? react_1.default.createElement(react_native_1.View, { style: { marginLeft: 8 } }, rightIcon) : null,
loading && (react_1.default.createElement(react_native_1.ActivityIndicator, { size: "small", color: theme.colors.primary, style: { marginLeft: 8 } }))),
isError ? (react_1.default.createElement(Text_1.Text, { variant: "caption", color: theme.colors.error, style: [
{ marginTop: 4, textAlign: errorPosition },
fontFamily ? { fontFamily } : {},
errorTextStyle
] }, error)) : helperText ? (react_1.default.createElement(Text_1.Text, { variant: "caption", color: theme.colors.muted, style: [
{ marginTop: 4 },
fontFamily ? { fontFamily } : {},
helperTextStyle
] }, helperText)) : null));
};
exports.default = TextInput;
//# sourceMappingURL=TextInput.js.map