feature
deskripsi: - portofolio: detail bisnis, maps, media social - new component divide # No Issue
This commit is contained in:
186
components/Divider/DividerCustom.tsx
Normal file
186
components/Divider/DividerCustom.tsx
Normal 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;
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user