@gradient-border/react-native-gradient-button
Version:
A powerful React Native gradient button component with support for gradient borders, text, and customizable styles. Perfect for creating beautiful, modern UI elements with minimal effort.
199 lines (198 loc) • 9.3 kB
JavaScript
;
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;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var react_1 = __importStar(require("react"));
var react_native_1 = require("react-native");
var masked_view_1 = __importDefault(require("@react-native-masked-view/masked-view"));
var react_native_linear_gradient_1 = __importDefault(require("react-native-linear-gradient"));
/**
* A customizable gradient button component for React Native
*
* @example
* ```tsx
* <GradientButton
* text="Submit"
* onPress={() => console.log('pressed')}
* colors={['#FF0000', '#00FF00']}
* style={{ borderRadius: 8 }}
* />
* ```
*
* @property {string} text - The text to display on the button
* @property {() => void} onPress - Function to call when button is pressed
* @property {string[]} colors - Array of at least 2 colors for the gradient
* @property {StyleProp<ViewStyle>} [style] - Optional styles for the button
* @property {StyleProp<TextStyle>} [textStyle] - Optional styles for the button text
* ...
*/
var GradientButton = function (_a) {
var
// Required props
text = _a.text, colors = _a.colors, onPress = _a.onPress,
// Optional props
style = _a.style, textStyle = _a.textStyle, _b = _a.loading, loading = _b === void 0 ? false : _b, _c = _a.loadingColor, loadingColor = _c === void 0 ? '#FFFFFF' : _c, _d = _a.loadingSize, loadingSize = _d === void 0 ? 'small' : _d,
// LinearGradient props
_e = _a.start,
// LinearGradient props
start = _e === void 0 ? { x: 0, y: 0 } : _e, _f = _a.end, end = _f === void 0 ? { x: 1, y: 0 } : _f, locations = _a.locations, _g = _a.useAngle, useAngle = _g === void 0 ? false : _g, _h = _a.angle, angle = _h === void 0 ? 0 : _h, angleCenter = _a.angleCenter,
// TouchableOpacity props
_j = _a.disabled,
// TouchableOpacity props
disabled = _j === void 0 ? false : _j, _k = _a.activeOpacity, activeOpacity = _k === void 0 ? 0.7 : _k,
// Accessibility props
_l = _a.accessibilityRole,
// Accessibility props
accessibilityRole = _l === void 0 ? 'button' : _l, accessibilityLabel = _a.accessibilityLabel, accessibilityHint = _a.accessibilityHint, touchableProps = __rest(_a, ["text", "colors", "onPress", "style", "textStyle", "loading", "loadingColor", "loadingSize", "start", "end", "locations", "useAngle", "angle", "angleCenter", "disabled", "activeOpacity", "accessibilityRole", "accessibilityLabel", "accessibilityHint"]);
if (!text) {
throw new Error('GradientButton: text prop is required');
}
if (!colors || !Array.isArray(colors) || colors.length < 2) {
throw new Error('GradientButton: colors prop is required and must be an array of at least 2 colors');
}
// Validate color format
colors.forEach(function (color, index) {
if (typeof color !== 'string') {
throw new Error("GradientButton: colors[".concat(index, "] must be a string"));
}
});
// Add validation for textStyle color properties
if (textStyle && typeof textStyle === 'object') {
var textStyleObj_1 = textStyle;
var restrictedTextProps = [
'color',
'textDecorationColor',
'textShadowColor'
];
restrictedTextProps.forEach(function (prop) {
if (prop in textStyleObj_1) {
console.warn("GradientButton: \"".concat(prop, "\" in textStyle prop is not allowed."));
delete textStyleObj_1[prop];
}
});
}
// Utility function to split and filter styles
var splitStyle = function (style) {
var outerStyle = {};
var innerStyle = {};
if (style && typeof style === 'object' && !Array.isArray(style)) {
// Type assertion to handle ViewStyle indexing
var styleObj = style;
Object.entries(styleObj).forEach(function (_a) {
var key = _a[0], value = _a[1];
if (['backgroundColor', 'borderColor', 'shadowColor', 'color'].includes(key)) {
console.warn("The property \"".concat(key, "\" is not allowed in the style prop."));
}
else if ([
'width',
'height',
'margin',
'marginTop',
'marginBottom',
'marginLeft',
'marginRight',
'marginHorizontal',
'marginVertical',
'padding',
'paddingTop',
'paddingBottom',
'paddingLeft',
'paddingRight',
'paddingHorizontal',
'paddingVertical',
].includes(key)) {
outerStyle[key] = value;
}
else {
innerStyle[key] = value;
}
});
}
return { outerStyle: outerStyle, innerStyle: innerStyle };
};
var _m = splitStyle(style), outerStyle = _m.outerStyle, innerStyle = _m.innerStyle;
var _o = (0, react_1.useState)(0), Height = _o[0], setHeight = _o[1];
var st = styles(Height / 10);
return (<react_native_1.View style={outerStyle}>
<react_native_1.TouchableOpacity onPress={onPress} disabled={disabled || loading} activeOpacity={activeOpacity} accessibilityRole={accessibilityRole} accessibilityLabel={accessibilityLabel || text} accessibilityHint={accessibilityHint} {...touchableProps} style={st.button}>
<react_native_1.View style={st.buttonContent}>
<masked_view_1.default maskElement={<react_native_1.View pointerEvents="none" style={[st.maskContainer, innerStyle]} collapsable={false}>
{loading ? (<react_native_1.ActivityIndicator color={loadingColor} size={loadingSize}/>) : (<react_native_1.Text style={[st.buttonText, textStyle]}>
{text}
</react_native_1.Text>)}
</react_native_1.View>} style={react_native_1.StyleSheet.absoluteFill} pointerEvents="none">
<react_native_linear_gradient_1.default style={react_native_1.StyleSheet.absoluteFill} pointerEvents="none" colors={colors} start={start} end={end} locations={locations} useAngle={useAngle} angle={angle} angleCenter={angleCenter}/>
</masked_view_1.default>
</react_native_1.View>
</react_native_1.TouchableOpacity>
</react_native_1.View>);
};
var styles = function (height) { return react_native_1.StyleSheet.create({
button: {
width: '100%',
},
buttonContent: {
width: '100%', //should not be changed
height: '100%', //should not be changed
},
maskContainer: {
width: '100%', //should not be changed
height: '100%', //should not be changed
padding: height / 10,
},
innerButton: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
},
buttonText: {
color: '#000000', // required for the gradient to work
textShadowColor: '#000000', // required for the gradient shadow to work
},
}); };
exports.default = GradientButton;