feat: update

This commit is contained in:
2025-11-06 16:37:01 +08:00
parent c0d54b8513
commit 855f289579
59 changed files with 3398 additions and 572 deletions

36
theme/index.ts Normal file
View File

@@ -0,0 +1,36 @@
/**
* 主题系统统一导出
*
* 提供主题配置、工具函数和类型定义
*/
// 导出颜色配置
export { default as Colors } from '@/constants/Colors';
// 导出主题 Hooks
export {
useColorScheme,
useThemeColor,
useThemeColors,
useThemeInfo,
} from '@/hooks/useTheme';
// 导出主题组件
export {
ThemedText,
ThemedView,
Text as ThemeText,
View as ThemeView,
} from '@/components/Themed';
export type {
ThemedTextProps,
ThemedViewProps,
TextProps as ThemeTextProps,
ViewProps as ThemeViewProps,
} from '@/components/Themed';
// 导出主题工具函数
export * from './utils';
export * from './styles';

261
theme/styles.ts Normal file
View File

@@ -0,0 +1,261 @@
/**
* 主题样式工厂
*
* 提供创建主题感知样式的工具函数
*
* React Native 不支持 CSS 类名,但可以通过样式工厂函数实现类似效果
*/
import { StyleSheet, TextStyle, ViewStyle } from 'react-native';
import Colors from '@/constants/Colors';
/**
* 主题样式类型
*/
export type ThemeStyles = {
light: any;
dark: any;
};
/**
* 创建主题样式
*
* 类似于 CSS 类名的概念,但使用函数式方法
*
* @param createStyles - 样式创建函数,接收颜色对象
* @returns 主题样式对象
*
* @example
* ```tsx
* const styles = createThemeStyles((colors) => ({
* container: {
* backgroundColor: colors.background,
* padding: 16,
* },
* text: {
* color: colors.text,
* fontSize: 16,
* },
* }));
*
* // 使用
* const theme = useColorScheme();
* <View style={styles[theme].container}>
* <Text style={styles[theme].text}>Hello</Text>
* </View>
* ```
*/
export function createThemeStyles<T extends StyleSheet.NamedStyles<T>>(
createStyles: (colors: typeof Colors.light) => T
): ThemeStyles {
return {
light: StyleSheet.create(createStyles(Colors.light)),
dark: StyleSheet.create(createStyles(Colors.dark)),
};
}
/**
* 创建响应式主题样式
*
* 允许为不同主题定义完全不同的样式
*
* @param lightStyles - 浅色主题样式
* @param darkStyles - 深色主题样式
* @returns 主题样式对象
*
* @example
* ```tsx
* const styles = createResponsiveThemeStyles(
* {
* container: { backgroundColor: '#fff', padding: 16 },
* text: { color: '#000', fontSize: 14 },
* },
* {
* container: { backgroundColor: '#000', padding: 20 },
* text: { color: '#fff', fontSize: 16 },
* }
* );
* ```
*/
export function createResponsiveThemeStyles<T extends StyleSheet.NamedStyles<T>>(
lightStyles: T,
darkStyles: T
): ThemeStyles {
return {
light: StyleSheet.create(lightStyles),
dark: StyleSheet.create(darkStyles),
};
}
/**
* 预定义的通用样式类
*
* 类似于 Tailwind CSS 的工具类
*/
export const commonStyles = createThemeStyles((colors) => ({
// 容器样式
container: {
flex: 1,
backgroundColor: colors.background,
},
containerPadded: {
flex: 1,
backgroundColor: colors.background,
padding: 16,
},
containerCentered: {
flex: 1,
backgroundColor: colors.background,
justifyContent: 'center',
alignItems: 'center',
},
// 卡片样式
card: {
backgroundColor: colors.card,
borderRadius: 8,
padding: 16,
borderWidth: 1,
borderColor: colors.border,
},
cardElevated: {
backgroundColor: colors.card,
borderRadius: 8,
padding: 16,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
elevation: 3,
},
// 文本样式
textPrimary: {
color: colors.text,
fontSize: 16,
} as TextStyle,
textSecondary: {
color: colors.textSecondary,
fontSize: 14,
} as TextStyle,
textTertiary: {
color: colors.textTertiary,
fontSize: 12,
} as TextStyle,
textTitle: {
color: colors.text,
fontSize: 24,
fontWeight: 'bold',
} as TextStyle,
textSubtitle: {
color: colors.text,
fontSize: 18,
fontWeight: '600',
} as TextStyle,
// 按钮样式
button: {
backgroundColor: colors.buttonPrimary,
paddingVertical: 12,
paddingHorizontal: 24,
borderRadius: 8,
alignItems: 'center',
justifyContent: 'center',
} as ViewStyle,
buttonOutline: {
backgroundColor: 'transparent',
paddingVertical: 12,
paddingHorizontal: 24,
borderRadius: 8,
borderWidth: 1,
borderColor: colors.buttonPrimary,
alignItems: 'center',
justifyContent: 'center',
} as ViewStyle,
buttonText: {
color: '#FFFFFF',
fontSize: 16,
fontWeight: '600',
} as TextStyle,
buttonTextOutline: {
color: colors.buttonPrimary,
fontSize: 16,
fontWeight: '600',
} as TextStyle,
// 输入框样式
input: {
backgroundColor: colors.inputBackground,
borderWidth: 1,
borderColor: colors.inputBorder,
borderRadius: 8,
paddingVertical: 12,
paddingHorizontal: 16,
fontSize: 16,
color: colors.text,
} as TextStyle,
inputFocused: {
backgroundColor: colors.inputBackground,
borderWidth: 2,
borderColor: colors.primary,
borderRadius: 8,
paddingVertical: 12,
paddingHorizontal: 16,
fontSize: 16,
color: colors.text,
} as TextStyle,
// 分隔线
separator: {
height: 1,
backgroundColor: colors.separator,
} as ViewStyle,
separatorVertical: {
width: 1,
backgroundColor: colors.separator,
} as ViewStyle,
// 间距
spacingXs: { height: 4 } as ViewStyle,
spacingSm: { height: 8 } as ViewStyle,
spacingMd: { height: 16 } as ViewStyle,
spacingLg: { height: 24 } as ViewStyle,
spacingXl: { height: 32 } as ViewStyle,
// 布局
row: {
flexDirection: 'row',
alignItems: 'center',
} as ViewStyle,
rowBetween: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
} as ViewStyle,
column: {
flexDirection: 'column',
} as ViewStyle,
center: {
justifyContent: 'center',
alignItems: 'center',
} as ViewStyle,
}));
/**
* 获取主题样式
*
* @param styles - 主题样式对象
* @param theme - 当前主题
* @returns 当前主题的样式
*
* @example
* ```tsx
* const theme = useColorScheme();
* const style = getThemeStyle(styles, theme);
* <View style={style.container} />
* ```
*/
export function getThemeStyle<T>(styles: ThemeStyles, theme: 'light' | 'dark'): T {
return styles[theme];
}

122
theme/utils.ts Normal file
View File

@@ -0,0 +1,122 @@
/**
* 主题工具函数
*
* 提供主题相关的辅助函数
*/
import Colors from '@/constants/Colors';
/**
* 根据主题获取颜色
*
* @param theme - 主题类型 'light' | 'dark'
* @param colorName - 颜色名称
* @returns 颜色值
*/
export function getThemeColor(
theme: 'light' | 'dark',
colorName: keyof typeof Colors.light & keyof typeof Colors.dark
): string {
return Colors[theme][colorName];
}
/**
* 根据主题获取所有颜色
*
* @param theme - 主题类型 'light' | 'dark'
* @returns 颜色对象
*/
export function getThemeColors(theme: 'light' | 'dark') {
return Colors[theme];
}
/**
* 创建主题感知的样式
*
* @param lightStyle - 浅色主题样式
* @param darkStyle - 深色主题样式
* @param theme - 当前主题
* @returns 合并后的样式
*
* @example
* ```tsx
* const style = createThemedStyle(
* { backgroundColor: '#fff' },
* { backgroundColor: '#000' },
* theme
* );
* ```
*/
export function createThemedStyle<T>(
lightStyle: T,
darkStyle: T,
theme: 'light' | 'dark'
): T {
return theme === 'dark' ? darkStyle : lightStyle;
}
/**
* 根据主题选择值
*
* @param lightValue - 浅色主题值
* @param darkValue - 深色主题值
* @param theme - 当前主题
* @returns 选中的值
*
* @example
* ```tsx
* const fontSize = selectByTheme(14, 16, theme);
* ```
*/
export function selectByTheme<T>(
lightValue: T,
darkValue: T,
theme: 'light' | 'dark'
): T {
return theme === 'dark' ? darkValue : lightValue;
}
/**
* 颜色透明度调整
*
* @param color - 十六进制颜色值
* @param opacity - 透明度 0-1
* @returns 带透明度的颜色值
*
* @example
* ```tsx
* const color = withOpacity('#000000', 0.5); // rgba(0, 0, 0, 0.5)
* ```
*/
export function withOpacity(color: string, opacity: number): string {
// 移除 # 号
const hex = color.replace('#', '');
// 转换为 RGB
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})`;
}
/**
* 判断是否为深色主题
*
* @param theme - 主题类型
* @returns 是否为深色主题
*/
export function isDarkTheme(theme: 'light' | 'dark'): boolean {
return theme === 'dark';
}
/**
* 判断是否为浅色主题
*
* @param theme - 主题类型
* @returns 是否为浅色主题
*/
export function isLightTheme(theme: 'light' | 'dark'): boolean {
return theme === 'light';
}