You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
282 lines
6.2 KiB
282 lines
6.2 KiB
/** |
|
* 主题样式工厂 |
|
* |
|
* 提供创建主题感知样式的工具函数 |
|
* |
|
* React Native 不支持 CSS 类名,但可以通过样式工厂函数实现类似效果 |
|
*/ |
|
|
|
import { StyleSheet, TextStyle, ViewStyle } from 'react-native'; |
|
import { Colors } from '@/theme'; |
|
import { ThemeEnum } from '@/constants/theme'; |
|
|
|
/** |
|
* 主题样式类型 |
|
*/ |
|
export type ThemeStyles = { |
|
[ThemeEnum.LIGHT]: any; |
|
[ThemeEnum.DARK]: any; |
|
[ThemeEnum.ORANGE]: 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 & typeof Colors.dark & typeof Colors.orange) => T |
|
): ThemeStyles { |
|
return { |
|
light: StyleSheet.create(createStyles(Colors.light)), |
|
dark: StyleSheet.create(createStyles(Colors.dark)), |
|
orange: StyleSheet.create(createStyles(Colors.orange)), |
|
}; |
|
} |
|
|
|
/** |
|
* 创建响应式主题样式 |
|
* |
|
* 允许为不同主题定义完全不同的样式 |
|
* |
|
* @param lightStyles - 浅色主题样式 |
|
* @param darkStyles - 深色主题样式 |
|
* @param orangeStyles - 橙色主题样式 |
|
* @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, |
|
orangeStyles: T |
|
): ThemeStyles { |
|
return { |
|
light: StyleSheet.create(lightStyles), |
|
dark: StyleSheet.create(darkStyles), |
|
orange: StyleSheet.create(orangeStyles), |
|
}; |
|
} |
|
|
|
/** |
|
* 预定义的通用样式类 |
|
* |
|
* 类似于 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, |
|
|
|
ghostButton: { |
|
backgroundColor: 'transparent', |
|
paddingVertical: 12, |
|
paddingHorizontal: 24, |
|
borderRadius: 6, |
|
alignItems: 'center', |
|
justifyContent: 'center', |
|
borderWidth: 1, |
|
borderColor: colors.border, |
|
} as ViewStyle, |
|
ghostButtonText: { |
|
color: '#FFFFFF', |
|
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: ThemeEnum): T { |
|
return styles[theme]; |
|
}
|
|
|