This commit is contained in:
Philip Cesar Garay
2025-07-31 21:25:33 +08:00
parent 5cfbc81e3a
commit 84fc719a10
307 changed files with 46470 additions and 0 deletions
@@ -0,0 +1,26 @@
import { StyleSheet, View } from "react-native";
import { GradientBorderView } from "../GradientBorderView";
const BorderGradient = ({ children, gradientProps, ...props }) => {
return (
<GradientBorderView
gradientProps={{
start: { x: 0, y: 0 },
end: { x: 1, y: 0 },
...gradientProps
}}
{...props}>
<View style={styles.innerContainer}>{children}</View>
</GradientBorderView>);
};
export default BorderGradient;
const styles = StyleSheet.create({
innerContainer: {
flex: 1,
}
});
@@ -0,0 +1,135 @@
import { StyleSheet, View } from "react-native";
import { useState } from "react";
const BorderGradient = ({ children, gradientProps, ...props }) => {
const defaultGradientProps = {
start: {
x: 0.5,
y: 0
},
end: {
x: 0.5,
y: 1
},
locations: [],
colors: [],
useAngle: false,
angle: 0
};
const { locations, end, start, useAngle, angle, onLayout, colors } =
gradientProps;
const {
style,
borderWidth,
borderRadius,
borderTopRightRadius,
borderTopLeftRadius,
borderBottomLeftRadius,
borderBottomRightRadius,
borderTopWidth,
borderLeftWidth,
borderRightWidth,
borderBottomWidth
} = props;
const propStart = start ?? defaultGradientProps?.start;
const propEnd = end ?? defaultGradientProps?.end;
const [state, setState] = useState({
width: 1,
height: 1
});
const measure = (event) => {
setState({
width: event.nativeEvent.layout.width,
height: event.nativeEvent.layout.height
});
if (onLayout) {
onLayout(event);
}
};
const getAngle = () => {
if (useAngle) {
return angle + "deg";
}
// Math.atan2 handles Infinity
const _angle =
Math.atan2(
state.width * (propEnd.y - propStart.y),
state.height * (propEnd.x - propStart.x)
) +
Math.PI / 2;
return _angle + "rad";
};
const getColors = () =>
colors.
map((color, index) => {
const location = locations?.[index] ?? defaultGradientProps.locations;
let locationStyle = "";
if (location) {
locationStyle = " " + location * 100 + "%";
}
return color + locationStyle;
}).
join(",");
return (
<View
style={{
position: "relative"
}}>
<View
onLayout={measure}
style={[
style,
{
borderWidth,
borderRadius,
borderTopLeftRadius,
borderTopRightRadius,
borderBottomLeftRadius,
borderBottomRightRadius,
borderTopWidth,
borderLeftWidth,
borderRightWidth,
borderBottomWidth,
borderStyle: "solid",
borderColor: "transparent",
// borderImage: `linear-gradient(${getAngle()},${getColors()}) 1`,
background: `linear-gradient(${getAngle()},${getColors()}) border-box`,
WebkitMask:
"linear-gradient(#fff 0 0) padding-box,linear-gradient(#fff 0 0)",
WebkitMaskComposite: "xor",
maskComposite: "exclude",
overflow: "hidden"
}]
}>
</View>
<View style={styles.innerContainer}>{children}</View>
</View>);
};
export default BorderGradient;
const styles = StyleSheet.create({
innerContainer: {
flex: 1,
margin: 5, // <-- Border Width
position: "absolute",
top: 0,
bottom: 0,
alignItems: "center",
justifyContent: "center",
right: 0,
left: 0,
overflow: "hidden"
}
});