@raahimkhan23/react-native-responsive-utils
Version:
A lightweight utility package for making React Native apps responsive across different screen sizes. It allows you to scale widths, heights, fonts, and images based on a configurable base screen size, enabling consistent layouts on different devices. The
186 lines (165 loc) • 6.26 kB
JavaScript
;
/**
* imports relevant libraries
*/
import { Dimensions, PixelRatio } from 'react-native';
/**
* imports relevant types
*/
/**
* base screen width and height (iPhone 16 Pro Portrait mode)
*/
let BASE_SCREEN_WIDTH = 402;
let BASE_SCREEN_HEIGHT = 874;
/**
* retrieves and stores the device's initial screen dimensions (width and height)
*/
const {
width: initialScreenWidth,
height: initialScreenHeight
} = Dimensions.get('window');
let CURRENT_SCREEN_WIDTH = initialScreenWidth;
let CURRENT_SCREEN_HEIGHT = initialScreenHeight;
/**
* updates the base screen width and height used for scaling
* @param width - the new base screen width
* @param height - the new base screen height
*/
const setBaseScreenSize = (width, height) => {
BASE_SCREEN_WIDTH = width;
BASE_SCREEN_HEIGHT = height;
};
/**
* holds the subscription reference for the orientation change listener
*/
let orientationListenerSubscription;
/**
* listens for orientation changes and updates the orientation state accordingly
* @param setOrientation - React setState function to update orientation ('portrait' or 'landscape')
* @returns void
*/
const listenOrientationChange = setOrientation => {
orientationListenerSubscription = Dimensions.addEventListener('change', newDimensions => {
CURRENT_SCREEN_WIDTH = newDimensions.window.width;
CURRENT_SCREEN_HEIGHT = newDimensions.window.height;
setOrientation(CURRENT_SCREEN_WIDTH < CURRENT_SCREEN_HEIGHT ? 'portrait' : 'landscape');
});
};
/**
* removes the orientation change listener if it exists
* @returns void
*/
const removeOrientationListener = () => {
if (orientationListenerSubscription) {
orientationListenerSubscription.remove();
}
};
/**
* scales a given width based on the current screen width and base screen width
* @param width - the original width to scale
* @returns the scaled width
*/
const scaleWidth = width => {
return width * CURRENT_SCREEN_WIDTH / BASE_SCREEN_WIDTH;
};
/**
* scales a given height based on the current screen height and base screen height
* @param height - the original height to scale
* @returns the scaled height
*/
const scaleHeight = height => {
return height * CURRENT_SCREEN_HEIGHT / BASE_SCREEN_HEIGHT;
};
/**
* scales a given image width based on the current screen width and base screen width, rounded to the nearest pixel
* @param width - the original image width to scale
* @returns the scaled image width
*/
const scaleImageWidth = width => {
const scaledWidth = width * CURRENT_SCREEN_WIDTH / BASE_SCREEN_WIDTH;
return PixelRatio.roundToNearestPixel(scaledWidth);
};
/**
* scales a given image height based on the scaled image width and original aspect ratio, rounded to the nearest pixel
* @param width - the original image width (to determine the aspect ratio)
* @param height - the original image height to scale
* @returns the scaled image height
*/
const scaleImageHeight = (width, height) => {
// scale width first
const scaledWidth = scaleImageWidth(width);
// calculate aspect ratio
const aspectRatio = width / height;
// adjust height based on the aspect ratio
return PixelRatio.roundToNearestPixel(scaledWidth / aspectRatio);
};
/**
* minimum and maximum clamping values for font scaling
*/
let MIN_FONT_SCALE = 0;
let MAX_FONT_SCALE = 0;
/**
* updates the minimum and maximum limits for font scaling clamp values
* @param minFontScale - minimum scale clamp for fonts
* @param maxFontScale - maximum scale clamp for fonts
*/
const setFontScaleLimits = (minFontScale, maxFontScale) => {
MIN_FONT_SCALE = minFontScale;
MAX_FONT_SCALE = maxFontScale;
};
/**
* scales a given font size based on the smaller screen dimension with clamping, rounded to the nearest pixel
* @param fontSize - the original font size
* @returns the scaled and clamped font size
*/
const scaleFont = fontSize => {
// calculate the scale factor using the smaller dimension ratio of current and base screens
const scaleDimension = Math.min(CURRENT_SCREEN_WIDTH, CURRENT_SCREEN_HEIGHT) / Math.min(BASE_SCREEN_WIDTH, BASE_SCREEN_HEIGHT);
// scale the font size
const scaledSize = fontSize * scaleDimension;
// clamp the scaled font size
const scaledSizeWithClamp = Math.max(fontSize - MIN_FONT_SCALE, Math.min(fontSize + MAX_FONT_SCALE, scaledSize));
// return the scaled font size to the nearest pixel
return PixelRatio.roundToNearestPixel(scaledSizeWithClamp);
};
/**
* defines supported iPhone models for dimension comparison
*/
/**
* stores the longest side (height in portrait, width in landscape) for each iPhone model defined above
*/
const modelLongestSide = {
iPhoneSE: 667,
iPhone13Mini: 812,
iPhone16Pro: 874,
iPhone16ProMax: 956
};
/**
* checks if the current device's longest side matches the given iPhone model longest side
* @param model - the iPhone model name
* @returns true if current screen's longest side matches the given iPhone model's longest side, otherwise false
*/
const isIphoneModel = model => {
return (CURRENT_SCREEN_WIDTH < CURRENT_SCREEN_HEIGHT ? CURRENT_SCREEN_HEIGHT : CURRENT_SCREEN_WIDTH) === modelLongestSide[model];
};
/**
* converts the given width percentage to device independent pixels (dp)
* @param widthPercent - percentage of the screen's width (0 – 100)
* @returns the corresponding dp based on the current device's screen width
*/
const wp = widthPercent => {
return PixelRatio.roundToNearestPixel(CURRENT_SCREEN_WIDTH * widthPercent / 100);
};
/**
* converts the given height percentage to device independent pixels (dp)
* @param heightPercent - percentage of the screen's height (0 – 100)
* @returns the corresponding dp based on the current device's screen height
*/
const hp = heightPercent => {
return PixelRatio.roundToNearestPixel(CURRENT_SCREEN_HEIGHT * heightPercent / 100);
};
/**
* exports constants and utility functions
*/
export { BASE_SCREEN_WIDTH, BASE_SCREEN_HEIGHT, CURRENT_SCREEN_WIDTH, CURRENT_SCREEN_HEIGHT, MIN_FONT_SCALE, MAX_FONT_SCALE, setBaseScreenSize, listenOrientationChange, removeOrientationListener, scaleWidth, scaleHeight, scaleImageWidth, scaleImageHeight, setFontScaleLimits, scaleFont, isIphoneModel, wp, hp };
//# sourceMappingURL=index.js.map