@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.
211 lines • 9.82 kB
JavaScript
"use strict";
/**
* Button
*
* A customizable wrapper around React Native's `Pressable` component.
* Provides built-in support for variants, sizes, color schemes, loading states,
* and optional left/right icons.
*
* 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");
/**
* Button
*
* A customizable wrapper around React Native's `Pressable`.
* Applies default button variants, sizeVariants, theme colors,
* and supports loading and icon states.
*/
const Button = (_a) => {
var { accessibilityHint, accessibilityLabel, animation = "scale", buttonStyle, children, colorScheme = "primary", containerStyle, disabled = false, fontFamily, fullWidth = false, leftIcon, leftIconStyle, loading = false, loadingIndicator, loadingText, loadingTextPosition = "right", loadingTextStyle, onPress, rightIcon, rightIconStyle, shape = "md", size = "md", textStyle, variant = "solid" } = _a, rest = __rest(_a, ["accessibilityHint", "accessibilityLabel", "animation", "buttonStyle", "children", "colorScheme", "containerStyle", "disabled", "fontFamily", "fullWidth", "leftIcon", "leftIconStyle", "loading", "loadingIndicator", "loadingText", "loadingTextPosition", "loadingTextStyle", "onPress", "rightIcon", "rightIconStyle", "shape", "size", "textStyle", "variant"]);
const { theme, buttonSizeVariants, buttonShapeVariants, textVariants } = (0, theme_1.useTheme)();
const colors = theme.colors;
const backgroundColor = variant === "solid" ? colors[colorScheme] : "transparent";
const borderColor = variant === "outline" ? colors[colorScheme] : "transparent";
const textColor = variant === "solid" ? colors.background : colors[colorScheme];
const sizeVariant = buttonSizeVariants[size] || buttonSizeVariants.md;
const shapeVariant = buttonShapeVariants[shape] || buttonShapeVariants.md;
const hasText = !!children;
const hasLeft = !!leftIcon;
const hasRight = !!rightIcon;
const isIconOnly = !hasText && (hasLeft !== hasRight);
const scaleAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(1)).current;
const opacityAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(1)).current;
const shadowAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(2)).current;
const handlePressIn = () => {
if (animation === "scale" || animation === "scaleOpacity") {
react_native_1.Animated.spring(scaleAnim, {
toValue: 0.96,
useNativeDriver: true,
speed: 50,
bounciness: 0,
}).start();
}
if (animation === "opacity" || animation === "scaleOpacity") {
react_native_1.Animated.timing(opacityAnim, {
toValue: 0.6,
duration: 150,
useNativeDriver: true,
}).start();
}
if (animation === "shadow") {
react_native_1.Animated.timing(shadowAnim, {
toValue: 8,
duration: 150,
useNativeDriver: false,
}).start();
}
};
const handlePressOut = () => {
if (animation === "scale" || animation === "scaleOpacity") {
react_native_1.Animated.spring(scaleAnim, {
toValue: 1,
useNativeDriver: true,
speed: 20,
bounciness: 6,
}).start();
}
if (animation === "opacity" || animation === "scaleOpacity") {
react_native_1.Animated.timing(opacityAnim, {
toValue: 1,
duration: 150,
useNativeDriver: true,
}).start();
}
if (animation === "shadow") {
react_native_1.Animated.timing(shadowAnim, {
toValue: 2,
duration: 150,
useNativeDriver: false,
}).start();
}
};
const shadowStyle = {
shadowColor: "#000",
shadowOffset: { width: 0, height: shadowAnim },
shadowOpacity: shadowAnim.interpolate({
inputRange: [2, 8],
outputRange: [0.2, 0.35],
}),
shadowRadius: shadowAnim.interpolate({
inputRange: [2, 8],
outputRange: [2, 6],
}),
elevation: shadowAnim,
};
return (react_1.default.createElement(react_native_1.Pressable, Object.assign({ onPress: onPress, onPressIn: handlePressIn, onPressOut: handlePressOut, disabled: disabled || loading, accessibilityRole: "button", accessibilityLabel: accessibilityLabel || (typeof children === "string" ? children : "Button"), accessibilityHint: accessibilityHint, style: [
{ alignSelf: fullWidth ? "stretch" : "flex-start" },
containerStyle,
] }, rest),
react_1.default.createElement(react_native_1.Animated.View, { style: [
styles.base,
{ backgroundColor, borderColor },
isIconOnly && !fullWidth
? sizeVariant.iconOnlyContainer || sizeVariant.container
: sizeVariant.container,
shapeVariant,
(animation === "scale" || animation === "scaleOpacity") && {
transform: [{ scale: scaleAnim }],
},
(animation === "opacity" || animation === "scaleOpacity") && {
opacity: opacityAnim,
},
animation === "shadow" && shadowStyle,
disabled && styles.disabled,
buttonStyle,
] },
react_1.default.createElement(react_native_1.View, { style: { justifyContent: "center", alignItems: "center" } },
loading ? (react_1.default.createElement(react_native_1.View, { style: {
position: "absolute",
flexDirection: loadingTextPosition === "left" ? "row-reverse" : "row",
alignItems: "center",
gap: 8,
} }, loadingIndicator ? (loadingIndicator) : (react_1.default.createElement(react_1.default.Fragment, null,
react_1.default.createElement(react_native_1.ActivityIndicator, { color: textColor }),
loadingText ? (react_1.default.createElement(Text_1.Text, { color: textColor, style: [
textVariants.caption,
fontFamily ? { fontFamily } : {},
loadingTextStyle
] }, loadingText)) : null)))) : null,
react_1.default.createElement(react_native_1.View, { style: [
styles.content,
loading && { opacity: 0 },
] },
leftIcon && (react_1.default.createElement(react_native_1.View, { style: leftIconStyle }, leftIcon)),
!!children && (react_1.default.createElement(Text_1.Text, { color: textColor, style: [
styles.text,
sizeVariant.text,
fontFamily ? { fontFamily } : {},
textStyle,
] }, children)),
rightIcon && (react_1.default.createElement(react_native_1.View, { style: rightIconStyle }, rightIcon)))))));
};
const styles = react_native_1.StyleSheet.create({
base: {
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
borderWidth: 1,
},
content: {
flexDirection: "row",
alignItems: "center",
gap: 8,
},
text: {
fontWeight: "600",
},
disabled: {
opacity: 0.5,
},
});
exports.default = Button;
//# sourceMappingURL=Button.js.map