This repository has been archived on 2025-07-31. You can view files and clone it, but cannot push or open issues or pull requests.
Files
terminally-online/src/contexts/dimensions.tsx
Nikolaos Karaolidis fa0a89f324 Fix layout bugs
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
2023-07-22 12:28:02 +03:00

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 };