deskripsi:
- portofolio: detail bisnis, maps, media social
- new component divide
# No Issue
This commit is contained in:
2025-07-10 11:58:23 +08:00
parent 71ea0ca5f2
commit 862af44c03
8 changed files with 485 additions and 21 deletions

View File

@@ -0,0 +1,186 @@
import React from "react";
import {
View,
Text,
StyleSheet,
StyleProp,
ViewStyle,
TextStyle,
} from "react-native";
// Define types for props
type Orientation = "horizontal" | "vertical";
type HorizontalLabelPosition = "center" | "left" | "right";
type VerticalLabelPosition = "center" | "top" | "bottom";
type LabelPosition = HorizontalLabelPosition | VerticalLabelPosition;
type Size = number | "xs" | "sm" | "md" | "lg" | "xl";
interface DividerProps {
orientation?: Orientation;
color?: string;
size?: Size;
label?: React.ReactNode;
labelPosition?: LabelPosition;
labelStyle?: StyleProp<TextStyle>;
style?: StyleProp<ViewStyle>;
}
const Divider: React.FC<DividerProps> = ({
orientation = "horizontal",
color = "#DADADA",
size = "xs",
label,
labelPosition = "center",
labelStyle,
style,
}) => {
const isHorizontal = orientation === "horizontal";
// Convert size to actual dimensions
const getSize = (): number => {
if (typeof size === "number") return size;
switch (size) {
case "xs":
return 1;
case "sm":
return 2;
case "md":
return 3;
case "lg":
return 4;
case "xl":
return 5;
default:
return 1; // Default size
}
};
const thickness = getSize();
const capitalize = (str: string): string =>
str.charAt(0).toUpperCase() + str.slice(1);
const renderLabel = () => {
if (!label) return null;
return (
<View
style={[
styles.labelContainer,
isHorizontal
? styles[
`label${capitalize(
labelPosition as string
)}` as keyof typeof styles
]
: styles[
`label${capitalize(
labelPosition as string
)}` as keyof typeof styles
],
]}
>
<Text style={[styles.labelText, labelStyle]}>{label}</Text>
</View>
);
};
return (
<View
style={[
isHorizontal ? styles.horizontalDivider : styles.verticalDivider,
{ backgroundColor: color },
style,
]}
>
{isHorizontal ? (
labelPosition !== "center" ? (
<View style={{ flex: 1, flexDirection: "row", alignItems: "center" }}>
{labelPosition === "left" && renderLabel()}
<View
style={{ flex: 1, backgroundColor: color, height: thickness }}
/>
{labelPosition === "right" && renderLabel()}
</View>
) : (
<>
{renderLabel()}
<View style={{ flex: 1 }} />
</>
)
) : labelPosition !== "center" && !isHorizontal ? (
<View
style={{ flex: 1, flexDirection: "column", justifyContent: "center" }}
>
{labelPosition === "top" && renderLabel()}
<View style={{ flex: 1, backgroundColor: color, width: thickness }} />
{labelPosition === "bottom" && renderLabel()}
</View>
) : (
<>
{renderLabel()}
<View style={{ flex: 1 }} />
</>
)}
</View>
);
};
const styles = StyleSheet.create({
horizontalDivider: {
flexDirection: "row",
alignItems: "center",
marginVertical: 8,
position: "relative",
},
verticalDivider: {
flexDirection: "column",
justifyContent: "center",
marginHorizontal: 8,
position: "relative",
},
labelText: {
fontSize: 14,
fontWeight: "500",
color: "#666",
marginHorizontal: 12,
marginVertical: 4,
backgroundColor: "white",
paddingHorizontal: 8,
},
labelContainer: {
position: "absolute",
left: 0,
right: 0,
justifyContent: "center",
alignItems: "center",
},
labelLeft: {
left: 12,
right: null,
alignItems: "flex-start",
},
labelRight: {
right: 12,
left: null,
alignItems: "flex-end",
},
labelCenter: {
justifyContent: "center",
alignItems: "center",
},
labelTop: {
top: 12,
bottom: null,
justifyContent: "flex-start",
},
labelBottom: {
bottom: 12,
top: null,
justifyContent: "flex-end",
},
});
export default Divider;

View File

@@ -5,7 +5,13 @@ import {
TEXT_SIZE_SMALL,
} from "@/constants/constans-value";
import React from "react";
import { Text as RNText, StyleProp, StyleSheet, TextStyle, TouchableOpacity } from "react-native";
import {
Text as RNText,
StyleProp,
StyleSheet,
TextStyle,
TouchableOpacity,
} from "react-native";
// Tambahkan type TextAlignProps agar lebih type-safe
type TextAlign = "left" | "center" | "right";
@@ -62,20 +68,8 @@ const TextCustom: React.FC<TextCustomProps> = ({
return selectedStyles;
};
return (
onPress ? (
<TouchableOpacity onPress={onPress}>
<RNText
numberOfLines={
typeof truncate === "number" ? truncate : truncate ? 1 : undefined
}
ellipsizeMode="tail"
style={getStyle()}
>
{children}
</RNText>
</TouchableOpacity>
) : (
return onPress ? (
<TouchableOpacity onPress={onPress}>
<RNText
numberOfLines={
typeof truncate === "number" ? truncate : truncate ? 1 : undefined
@@ -85,7 +79,17 @@ const TextCustom: React.FC<TextCustomProps> = ({
>
{children}
</RNText>
)
</TouchableOpacity>
) : (
<RNText
numberOfLines={
typeof truncate === "number" ? truncate : truncate ? 1 : undefined
}
ellipsizeMode="tail"
style={getStyle()}
>
{children}
</RNText>
);
};
@@ -96,6 +100,7 @@ export const styles = StyleSheet.create({
fontSize: TEXT_SIZE_MEDIUM,
color: MainColor.white,
fontFamily: "Poppins-Regular",
lineHeight: 20,
},
bold: {
fontFamily: "Poppins-Bold",