98 lines
2.4 KiB
TypeScript
98 lines
2.4 KiB
TypeScript
import React, {
|
|
ReactNode,
|
|
createContext,
|
|
useContext,
|
|
useEffect,
|
|
useMemo,
|
|
useState,
|
|
} from 'react';
|
|
import { Dimensions, ScaledSize } from 'react-native';
|
|
|
|
const guidelineBaseWidth = 350;
|
|
const guidelineBaseHeight = 680;
|
|
|
|
enum ORIENTATION {
|
|
PORTRAIT = 'portrait',
|
|
LANDSCAPE = 'landscape',
|
|
}
|
|
|
|
interface ScaleFunctions {
|
|
horizontalScale: (size: number) => number;
|
|
verticalScale: (size: number) => number;
|
|
moderateHorizontalScale: (size: number, factor?: number) => number;
|
|
moderateVerticalScale: (size: number, factor?: number) => number;
|
|
}
|
|
|
|
interface DimensionsContext {
|
|
orientation: ORIENTATION;
|
|
dimensions: ScaledSize;
|
|
responsive: ScaleFunctions;
|
|
}
|
|
|
|
const createScaleFunctions = (dimensionsIn: ScaledSize) => {
|
|
const horizontalScale = (size: number) =>
|
|
(dimensionsIn.width / guidelineBaseWidth) * size;
|
|
const verticalScale = (size: number) =>
|
|
(dimensionsIn.height / guidelineBaseHeight) * size;
|
|
const moderateHorizontalScale = (size: number, factor = 0.5) =>
|
|
size + (horizontalScale(size) - size) * factor;
|
|
const moderateVerticalScale = (size: number, factor = 0.5) =>
|
|
size + (verticalScale(size) - size) * factor;
|
|
|
|
return {
|
|
horizontalScale,
|
|
verticalScale,
|
|
moderateHorizontalScale,
|
|
moderateVerticalScale,
|
|
};
|
|
};
|
|
|
|
const DimensionsContext = createContext<DimensionsContext | undefined>(
|
|
undefined,
|
|
);
|
|
|
|
const DimensionsProvider = ({ children }: { children: ReactNode }) => {
|
|
const [dimensions, setDimensions] = useState(Dimensions.get('window'));
|
|
|
|
const orientation = useMemo(() => {
|
|
return dimensions.width > dimensions.height
|
|
? ORIENTATION.LANDSCAPE
|
|
: ORIENTATION.PORTRAIT;
|
|
}, [dimensions]);
|
|
|
|
const responsiveScale = createScaleFunctions(dimensions);
|
|
|
|
useEffect(() => {
|
|
const onChange = ({ window }: { window: ScaledSize }) => {
|
|
setDimensions(window);
|
|
};
|
|
|
|
const subscription = Dimensions.addEventListener('change', onChange);
|
|
|
|
return () => {
|
|
subscription.remove();
|
|
};
|
|
}, []);
|
|
|
|
return (
|
|
<DimensionsContext.Provider
|
|
value={{
|
|
orientation,
|
|
dimensions,
|
|
responsive: responsiveScale,
|
|
}}>
|
|
{children}
|
|
</DimensionsContext.Provider>
|
|
);
|
|
};
|
|
|
|
const useDimensions = (): DimensionsContext => {
|
|
const context = useContext(DimensionsContext);
|
|
if (!context) {
|
|
throw new Error('useDimensions must be used within a DimensionsProvider');
|
|
}
|
|
return context;
|
|
};
|
|
|
|
export { ORIENTATION, DimensionsProvider, useDimensions };
|