Add: - screens/Invesment/ComponentBoxOnBottomDetail.tsx - screens/Invesment/ButtonInvestasiSection.tsx - app/(application)/(user)/investment/[id]/investor.tsx - app/(application)/(user)/investment/[id]/(news)/list-of-news.tsx Fix: - screens/Invesment/BoxDetailDataSection.tsx - app/(application)/(user)/investment/[id]/[status]/detail.tsx - app/(application)/(user)/_layout.tsx ## No Issue
115 lines
2.5 KiB
TypeScript
115 lines
2.5 KiB
TypeScript
import React, { createContext, useContext, useMemo } from "react";
|
|
import { StyleSheet, useWindowDimensions, View, ViewStyle } from "react-native";
|
|
|
|
// Tipe untuk span
|
|
type SpanValue = {
|
|
base?: number;
|
|
md?: number;
|
|
lg?: number;
|
|
};
|
|
|
|
// Props untuk Grid.Col
|
|
interface ColProps {
|
|
children: React.ReactNode;
|
|
span?: number | SpanValue;
|
|
style?: ViewStyle;
|
|
}
|
|
|
|
// Props untuk Grid
|
|
interface GridProps {
|
|
children: React.ReactNode;
|
|
gap?: number;
|
|
columns?: number;
|
|
containerStyle?: ViewStyle;
|
|
}
|
|
|
|
// Context untuk menyimpan konfigurasi grid
|
|
type GridContextType = {
|
|
gap: number;
|
|
columns: number;
|
|
};
|
|
|
|
const GridContext = createContext<GridContextType>({
|
|
gap: 0,
|
|
columns: 12,
|
|
});
|
|
|
|
const useGrid = () => useContext(GridContext);
|
|
|
|
// Helper untuk menentukan span berdasarkan lebar layar
|
|
const getSpan = (
|
|
spanProp: number | SpanValue | undefined,
|
|
width: number
|
|
): number => {
|
|
if (typeof spanProp === "number") return spanProp;
|
|
|
|
const span = spanProp || { base: 12 };
|
|
|
|
if (width >= 992 && span.lg) return span.lg;
|
|
if (width >= 768 && span.md) return span.md;
|
|
return span.base ?? 12;
|
|
};
|
|
|
|
// Grid Component
|
|
const GridComponent: React.FC<GridProps> = ({
|
|
children,
|
|
gap = 6,
|
|
columns = 12,
|
|
containerStyle,
|
|
}) => {
|
|
const contextValue = useMemo(() => ({ gap, columns }), [gap, columns]);
|
|
|
|
return (
|
|
<GridContext.Provider value={contextValue}>
|
|
<View
|
|
style={[
|
|
styles.container,
|
|
{ marginHorizontal: -gap / 2 },
|
|
containerStyle,
|
|
]}
|
|
>
|
|
{React.Children.map(children, (child) =>
|
|
React.isValidElement(child)
|
|
? React.cloneElement(child as React.ReactElement<ColProps>, {})
|
|
: child
|
|
)}
|
|
</View>
|
|
</GridContext.Provider>
|
|
);
|
|
};
|
|
|
|
// Grid.Col Component
|
|
const Col: React.FC<ColProps> = ({ children, span, style }) => {
|
|
const { gap, columns } = useGrid();
|
|
const { width } = useWindowDimensions();
|
|
|
|
const colSpan = getSpan(span, width);
|
|
const margin = gap / 2;
|
|
|
|
const styles = StyleSheet.create({
|
|
col: {
|
|
flexBasis: `${(100 / columns) * colSpan}%`,
|
|
paddingVertical: margin,
|
|
marginBottom: gap,
|
|
// marginBlock: gap,
|
|
},
|
|
});
|
|
|
|
return <View style={[styles.col, style]}>{children}</View>;
|
|
};
|
|
|
|
// Export bersama-sama
|
|
const Grid = Object.assign(GridComponent, { Col });
|
|
|
|
export default Grid;
|
|
|
|
// Styles
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flexDirection: "row",
|
|
flexWrap: "wrap",
|
|
justifyContent: "flex-start",
|
|
marginInline: 0.1
|
|
},
|
|
});
|