廓形仪rn版本-技术调研
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.
 
 

121 lines
3.1 KiB

import { Dimensions, useWindowDimensions } from 'react-native';
import { useEffect, useState } from 'react';
import resolveConfig from 'tailwindcss/resolveConfig';
import * as tailwindConfig from '@/tailwind.config';
const TailwindTheme = resolveConfig(tailwindConfig as any);
const screenSize = TailwindTheme.theme.screens;
type breakpoints = keyof typeof screenSize | 'default';
type MediaQueriesBreakpoints = {
key: breakpoints;
breakpoint: number;
isValid: boolean;
value?: unknown;
};
type BreakPointValue = Partial<Record<breakpoints, unknown>>;
const resolveScreenWidth: Record<breakpoints, number> = {
default: 0,
};
Object.entries(screenSize).forEach(([key, value]) => {
if (typeof value === 'string') {
resolveScreenWidth[key] = parseInt(value.replace('px', ''), 10);
}
});
export const getBreakPointValue = (
values: BreakPointValue,
width: number
): unknown => {
if (typeof values !== 'object') return values;
let finalBreakPointResolvedValue: unknown;
const mediaQueriesBreakpoints: Array<MediaQueriesBreakpoints> = [
{
key: 'default',
breakpoint: 0,
isValid: true,
},
];
Object.keys(resolveScreenWidth).forEach((key) => {
const isValid = isValidBreakpoint(resolveScreenWidth[key], width);
mediaQueriesBreakpoints.push({
key: key,
breakpoint: resolveScreenWidth[key],
isValid: isValid,
});
});
mediaQueriesBreakpoints.sort(
(a: MediaQueriesBreakpoints, b: MediaQueriesBreakpoints) =>
a.breakpoint - b.breakpoint
);
mediaQueriesBreakpoints.forEach(
(breakpoint: MediaQueriesBreakpoints, index: number) => {
breakpoint.value = values.hasOwnProperty(breakpoint.key)
? values[breakpoint.key]
: mediaQueriesBreakpoints[index - 1]?.value ||
mediaQueriesBreakpoints[0]?.value;
}
);
const lastValidObject = getLastValidObject(mediaQueriesBreakpoints);
if (!lastValidObject) {
finalBreakPointResolvedValue = values;
} else {
finalBreakPointResolvedValue = lastValidObject.value;
}
return finalBreakPointResolvedValue;
};
export function useBreakpointValue(values: BreakPointValue): unknown {
const { width } = useWindowDimensions();
const [currentBreakPointValue, setCurrentBreakPointValue] = useState<unknown>(
getBreakPointValue(values, width)
);
useEffect(() => {
if (typeof values === 'object') {
const finalBreakPointResolvedValue = getBreakPointValue(values, width);
setCurrentBreakPointValue(finalBreakPointResolvedValue);
}
}, [values, width]);
if (typeof values !== 'object') return values;
return currentBreakPointValue;
}
export function isValidBreakpoint(
breakPointWidth: number,
width: number = Dimensions.get('window')?.width || 0
) {
const windowWidth = width;
return windowWidth >= breakPointWidth;
}
function getLastValidObject(
mediaQueries: Array<{
key: breakpoints;
breakpoint: number;
isValid: boolean;
value?: unknown;
}>
) {
for (let i = mediaQueries.length - 1; i >= 0; i--) {
if (mediaQueries[i].isValid) {
return mediaQueries[i];
}
}
return null; // No valid object found
}