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,127 @@
import { AnimatableNumericValue, StyleSheet, View } from "react-native";
import { LinearGradientProps } from "../../LinearGradient/LinearGradient";
import MaskedView from "../../MaskedView/MaskedView";
import LinearGradient from "react-native-linear-gradient";
export type GradientProps = Omit<
LinearGradientProps,
"style" | "pointerEvents">;
export type RequiredGradientBorderProps = {
/**
* Props to be passed to the gradient component. See `react-native-linear-gradient` for full list. Requires "colors" prop.
*/
gradientProps: GradientProps;
};
type BorderProps = {
/**
* Width of border.
*/
borderWidth?: number;
/**
* Border applied to top of view, overrides borderWidth.
*/
borderTopWidth?: number;
/**
* Border applied to left side of view, overrides borderWidth.
*/
borderLeftWidth?: number;
/**
* Border applied to bottom side of view, overrides borderWidth.
*/
borderBottomWidth?: number;
/**
* Border appled to right side of view, overrides borderWidth.
*/
borderRightWidth?: number;
/**
* Border radius applied to each corner.
*/
borderRadius?: AnimatableNumericValue | string | undefined;
/**
* Border radius applied to top right corner, Overrides borderRadius.
*/
borderTopRightRadius?: AnimatableNumericValue | string | undefined;
/**
* Border radius applied to top left corner. Overrides borderRadius
*/
borderTopLeftRadius?: AnimatableNumericValue | string | undefined;
/**
* Border radius applied to bottom right corner. Overrides borderRadius
*/
borderBottomRightRadius?: AnimatableNumericValue | string | undefined;
/**
* Border radius applied to bottom left corner. Overrides borderRadius
*/
borderBottomLeftRadius?: AnimatableNumericValue | string | undefined;
};
/**
* A component that applies a gradient border to the parent.
* Should be placed as the last child of the parent so that it isn't overlapped.
* @example
* ```tsx
* <View>
* <GradientBorder
* borderWidth={2}
* gradientProps={{
* colors: ['red', 'blue']
* }}
* />
* </View>
* ```
*/
export default function GradientBorder({
gradientProps,
borderWidth,
borderRadius,
borderTopRightRadius,
borderTopLeftRadius,
borderBottomLeftRadius,
borderBottomRightRadius,
borderTopWidth,
borderLeftWidth,
borderRightWidth,
borderBottomWidth
}: RequiredGradientBorderProps & BorderProps) {
return (
<MaskedView
maskElement={
<View
pointerEvents="none"
style={[
{
borderWidth,
borderRadius,
borderTopLeftRadius,
borderTopRightRadius,
borderBottomLeftRadius,
borderBottomRightRadius,
borderTopWidth,
borderLeftWidth,
borderRightWidth,
borderBottomWidth
},
StyleSheet.absoluteFill]
}
collapsable={false} />
}
style={[StyleSheet.absoluteFill]}
pointerEvents="none">
<LinearGradient
style={StyleSheet.absoluteFill}
pointerEvents="none"
{...gradientProps} />
</MaskedView>);
}
@@ -0,0 +1,131 @@
import {
StyleProp,
StyleSheet,
View,
ViewProps,
ViewStyle,
} from "react-native";
import GradientBorder, { RequiredGradientBorderProps } from "./GradientBorder";
import omit from "lodash/omit";
type GradientBorderViewProps = Omit<
ViewStyle,
| "paddingLeft"
| "paddingRight"
| "paddingTop"
| "paddingBottom"
| "padding"
| "borderColor"
| "borderLeftColor"
| "borderRightColor"
| "borderTopColor"
| "borderBottomColor"
>;
export type GradientBorderViewStyle = StyleProp<
GradientBorderViewProps & {
paddingLeft?: number;
paddingRight?: number;
paddingTop?: number;
paddingBottom?: number;
padding?: number;
}
>;
/**
* A view that applies a gradient border. `gradientProps` is required and can be used to control the gradient (react-native-linear-gradient props),
* and `borderWidth` is required. See
* @example
* <GradientBorderView
* style={{borderWidth: 50, height: 100, width: 100,}}
* gradientProps={{
* colors: ['red', 'blue']
* }}
* />
*/
export const GradientBorderView = ({
gradientProps,
...props
}: Omit<ViewProps, "style"> & {
style?: GradientBorderViewStyle;
} & RequiredGradientBorderProps) => {
const styles = StyleSheet.flatten(props.style);
const userAllPadding = styles.padding ? styles.padding : 0;
const compensationAllPadding = styles.borderWidth ? styles.borderWidth : 0;
function calcPaddingForSide(
paddingName:
| "paddingLeft"
| "paddingRight"
| "paddingTop"
| "paddingBottom",
borderWidthName:
| "borderTopWidth"
| "borderBottomWidth"
| "borderLeftWidth"
| "borderRightWidth"
) {
const userPadding =
typeof styles[paddingName] !== "undefined"
? styles[paddingName]!
: userAllPadding;
const compensationPadding =
typeof styles[borderWidthName] !== "undefined"
? styles[borderWidthName]!
: compensationAllPadding;
return compensationPadding + userPadding;
}
if (
__DEV__ &&
!(
styles.borderWidth ||
styles.borderTopWidth ||
styles.borderLeftWidth ||
styles.borderRightWidth ||
styles.borderBottomWidth
)
) {
console.warn(
"No borderWidth was passed in the GradientBorderView style, no border will be shown."
);
}
return (
<View
{...props}
style={[
{
paddingLeft: calcPaddingForSide("paddingLeft", "borderLeftWidth"),
paddingRight: calcPaddingForSide("paddingRight", "borderRightWidth"),
paddingBottom: calcPaddingForSide(
"paddingBottom",
"borderBottomWidth"
),
paddingTop: calcPaddingForSide("paddingTop", "borderTopWidth"),
},
omit(styles, [
"borderWidth",
"borderTopWidth",
"borderLeftWidth",
"borderRightWidth",
"borderBottomWidth",
]),
]}
>
{props.children}
<GradientBorder
gradientProps={gradientProps}
borderRadius={styles.borderRadius}
borderWidth={styles.borderWidth}
borderBottomWidth={styles.borderBottomWidth}
borderRightWidth={styles.borderRightWidth}
borderLeftWidth={styles.borderLeftWidth}
borderTopWidth={styles.borderTopWidth}
borderTopLeftRadius={styles.borderTopLeftRadius}
borderTopRightRadius={styles.borderTopRightRadius}
borderBottomRightRadius={styles.borderBottomRightRadius}
borderBottomLeftRadius={styles.borderBottomLeftRadius}
/>
</View>
);
};
@@ -0,0 +1,8 @@
import {
GradientBorderView,
GradientBorderViewStyle,
} from "./components/GradientBorderView";
import { GradientProps } from "./components/GradientBorder";
export { GradientBorderView };
export type { GradientBorderViewStyle, GradientProps as GP };