164 lines
4.1 KiB
TypeScript
164 lines
4.1 KiB
TypeScript
/**
|
|
* Custom hook for easy theme access throughout the app
|
|
* Provides styled components and theme utilities
|
|
*/
|
|
|
|
import { useMemo } from "react";
|
|
import { StyleSheet, TextStyle, ViewStyle } from "react-native";
|
|
import { useThemeContext } from "@/hooks/use-theme-context";
|
|
|
|
export function useAppTheme() {
|
|
const { colors, colorScheme, themeMode, setThemeMode, getColor } =
|
|
useThemeContext();
|
|
|
|
// Common styled components
|
|
const styles = useMemo(
|
|
() =>
|
|
StyleSheet.create({
|
|
// Container styles
|
|
container: {
|
|
flex: 1,
|
|
backgroundColor: colors.background,
|
|
} as ViewStyle,
|
|
|
|
surface: {
|
|
backgroundColor: colors.surface,
|
|
borderRadius: 12,
|
|
padding: 16,
|
|
} as ViewStyle,
|
|
|
|
card: {
|
|
backgroundColor: colors.card,
|
|
borderRadius: 12,
|
|
padding: 16,
|
|
shadowColor: colors.text,
|
|
shadowOffset: { width: 0, height: 2 },
|
|
shadowOpacity: 0.1,
|
|
shadowRadius: 4,
|
|
elevation: 3,
|
|
} as ViewStyle,
|
|
|
|
// Button styles
|
|
primaryButton: {
|
|
backgroundColor: colors.primary,
|
|
paddingVertical: 14,
|
|
paddingHorizontal: 20,
|
|
borderRadius: 12,
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
} as ViewStyle,
|
|
|
|
secondaryButton: {
|
|
backgroundColor: colors.backgroundSecondary,
|
|
borderWidth: 1,
|
|
borderColor: colors.border,
|
|
paddingVertical: 14,
|
|
paddingHorizontal: 20,
|
|
borderRadius: 12,
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
} as ViewStyle,
|
|
|
|
// Text styles
|
|
primaryButtonText: {
|
|
color: "#ffffff",
|
|
fontSize: 16,
|
|
fontWeight: "600",
|
|
} as TextStyle,
|
|
|
|
secondaryButtonText: {
|
|
color: colors.text,
|
|
fontSize: 16,
|
|
fontWeight: "600",
|
|
} as TextStyle,
|
|
|
|
// Input styles
|
|
textInput: {
|
|
backgroundColor: colors.surface,
|
|
borderWidth: 1,
|
|
borderColor: colors.border,
|
|
borderRadius: 8,
|
|
paddingVertical: 12,
|
|
paddingHorizontal: 16,
|
|
fontSize: 16,
|
|
color: colors.text,
|
|
} as ViewStyle & TextStyle,
|
|
|
|
// Separator
|
|
separator: {
|
|
height: 1,
|
|
backgroundColor: colors.separator,
|
|
} as ViewStyle,
|
|
|
|
// Status styles
|
|
successContainer: {
|
|
backgroundColor: `${colors.success}20`,
|
|
borderColor: colors.success,
|
|
borderWidth: 1,
|
|
borderRadius: 8,
|
|
padding: 12,
|
|
} as ViewStyle,
|
|
|
|
warningContainer: {
|
|
backgroundColor: `${colors.warning}20`,
|
|
borderColor: colors.warning,
|
|
borderWidth: 1,
|
|
borderRadius: 8,
|
|
padding: 12,
|
|
} as ViewStyle,
|
|
|
|
errorContainer: {
|
|
backgroundColor: `${colors.error}20`,
|
|
borderColor: colors.error,
|
|
borderWidth: 1,
|
|
borderRadius: 8,
|
|
padding: 12,
|
|
} as ViewStyle,
|
|
}),
|
|
[colors]
|
|
);
|
|
|
|
// Theme utilities
|
|
const utils = useMemo(
|
|
() => ({
|
|
// Get opacity color
|
|
getOpacityColor: (
|
|
colorName: keyof typeof colors,
|
|
opacity: number = 0.1
|
|
) => {
|
|
const color = colors[colorName];
|
|
const hex = color.replace("#", "");
|
|
const r = parseInt(hex.substring(0, 2), 16);
|
|
const g = parseInt(hex.substring(2, 4), 16);
|
|
const b = parseInt(hex.substring(4, 6), 16);
|
|
return `rgba(${r}, ${g}, ${b}, ${opacity})`;
|
|
},
|
|
|
|
// Check if current theme is dark
|
|
isDark: colorScheme === "dark",
|
|
|
|
// Check if current theme is light
|
|
isLight: colorScheme === "light",
|
|
|
|
// Toggle between light and dark (ignoring system)
|
|
toggleTheme: () => {
|
|
const newMode = colorScheme === "dark" ? "light" : "dark";
|
|
setThemeMode(newMode);
|
|
},
|
|
}),
|
|
[colors, colorScheme, setThemeMode]
|
|
);
|
|
|
|
return {
|
|
colors,
|
|
styles,
|
|
utils,
|
|
colorScheme,
|
|
themeMode,
|
|
setThemeMode,
|
|
getColor,
|
|
};
|
|
}
|
|
|
|
export type AppTheme = ReturnType<typeof useAppTheme>;
|