Files
frontend/src/utils/responsive.ts

168 lines
3.6 KiB
TypeScript
Raw Normal View History

/**
*
*
*/
import { ViewStyle } from 'react-native';
import { BREAKPOINTS } from '../presentation/hooks/responsive';
/**
*
*/
export type ResponsiveBreakpoint = 'mobile' | 'tablet' | 'desktop' | 'wide';
/**
*
*/
export type ResponsiveValues<T> = {
mobile?: T;
tablet?: T;
desktop?: T;
wide?: T;
};
/**
*
*/
export type ResponsiveStyles = {
mobile?: ViewStyle;
tablet?: ViewStyle;
desktop?: ViewStyle;
wide?: ViewStyle;
};
/**
*
*
* @param breakpoint -
* @param values -
* @returns undefined
*
* @example
* const fontSize = responsiveValue('tablet', {
* mobile: 14,
* tablet: 16,
* desktop: 18,
* wide: 20
* });
*/
export function responsiveValue<T>(
breakpoint: string,
values: ResponsiveValues<T>
): T | undefined {
// 按断点优先级顺序查找
const breakpoints: ResponsiveBreakpoint[] = ['wide', 'desktop', 'tablet', 'mobile'];
for (const bp of breakpoints) {
if (breakpoint === bp && values[bp] !== undefined) {
return values[bp];
}
}
return undefined;
}
/**
*
*
*
* @param breakpoint -
* @param styles -
* @returns
*
* @example
* const containerStyle = createResponsiveStyles(breakpoint, {
* mobile: { padding: 12 },
* tablet: { padding: 24 },
* desktop: { padding: 32 },
* wide: { padding: 48 }
* });
*/
export function createResponsiveStyles(
breakpoint: string,
styles: ResponsiveStyles
): ViewStyle {
const result: ViewStyle = {};
// 按断点优先级从低到高合并样式
const breakpoints: ResponsiveBreakpoint[] = ['mobile', 'tablet', 'desktop', 'wide'];
for (const bp of breakpoints) {
const style = styles[bp];
if (style) {
Object.assign(result, style);
}
// 到达当前断点后停止合并
if (breakpoint === bp) {
break;
}
}
return result;
}
/**
*
*
*
* @param width -
* @param config -
* @returns
*
* @example
* const padding = getResponsiveValue(screenWidth, {
* mobile: 12,
* tablet: 16,
* desktop: 24,
* wide: 32
* });
*/
export function getResponsiveValue(
width: number,
config: ResponsiveValues<number>
): number | undefined {
if (width >= BREAKPOINTS.wide && config.wide !== undefined) {
return config.wide;
}
if (width >= BREAKPOINTS.desktop && config.desktop !== undefined) {
return config.desktop;
}
if (width >= BREAKPOINTS.tablet && config.tablet !== undefined) {
return config.tablet;
}
if (config.mobile !== undefined) {
return config.mobile;
}
return undefined;
}
/**
*
*
* @param width -
* @returns tablet
*/
export function isWideScreen(width: number): boolean {
return width >= BREAKPOINTS.tablet;
}
/**
*
*
* @param width -
* @returns desktop
*/
export function isDesktop(width: number): boolean {
return width >= BREAKPOINTS.desktop;
}
/**
*
*
* @param width -
* @returns wide
*/
export function isWide(width: number): boolean {
return width >= BREAKPOINTS.wide;
}