Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 62 additions & 3 deletions helpers/device-selector.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,35 @@ import { initialWindowMetrics } from 'react-native-safe-area-context';

export const NAVIGATION_HEADER_HEIGHT = 64;

// Fallback inset values used when initialWindowMetrics is null (race condition
// in large apps where JS evaluates before the safe-area native module inits).
// Bottom: 34pt — consistent across all notched iPhones since iPhone X (2017).
// Top: 59pt — matches Dynamic Island devices (iPhone 14+).
// Slightly too large for older notched devices (44–48pt), but using the
// largest one prevents content from being hidden under the notch/Dynamic Island.
const DEFAULT_IOS_TOP_INSET = 59;
const DEFAULT_IOS_BOTTOM_INSET = 34;

export const isNotchedAndroid =
Platform.OS === 'android' && DeviceInfo.hasNotch();

export const NAVIGATION_BAR_HEIGHT = Platform.select({
ios: NAVIGATION_HEADER_HEIGHT + initialWindowMetrics?.insets?.top,
ios:
NAVIGATION_HEADER_HEIGHT +
(initialWindowMetrics?.insets?.top ?? DEFAULT_IOS_TOP_INSET),
android: isNotchedAndroid
? NAVIGATION_HEADER_HEIGHT + StatusBar.currentHeight
: NAVIGATION_HEADER_HEIGHT,
default: NAVIGATION_HEADER_HEIGHT,
});

export const HOME_INDICATOR_PADDING =
Platform.OS === 'ios' ? initialWindowMetrics?.insets?.bottom : 0;
Platform.OS === 'ios'
? initialWindowMetrics?.insets?.bottom ?? DEFAULT_IOS_BOTTOM_INSET
: 0;

export const NOTCH_AREA_HEIGHT = Platform.select({
ios: initialWindowMetrics?.insets?.top,
ios: initialWindowMetrics?.insets?.top ?? DEFAULT_IOS_TOP_INSET,
android: isNotchedAndroid ? StatusBar.currentHeight : 0,
default: 0,
});
Expand All @@ -30,3 +43,49 @@ export const Device = {
NOTCH_AREA_HEIGHT,
NAVIGATION_HEADER_HEIGHT,
};

// Lazy getters — resolve initialWindowMetrics on first render,
// when the native module is guaranteed to be ready.
let _topInset;
let _bottomInset;

const getTopInset = () => {
if (_topInset === undefined) {
// eslint-disable-next-line global-require
const metrics = require('react-native-safe-area-context')
.initialWindowMetrics;
_topInset = metrics?.insets?.top ?? DEFAULT_IOS_TOP_INSET;
}

return _topInset;
};

const getBottomInset = () => {
if (_bottomInset === undefined) {
// eslint-disable-next-line global-require
const metrics = require('react-native-safe-area-context')
.initialWindowMetrics;
_bottomInset = metrics?.insets?.bottom ?? DEFAULT_IOS_BOTTOM_INSET;
}

return _bottomInset;
};

export const getNavigationBarHeight = () =>
Platform.select({
ios: NAVIGATION_HEADER_HEIGHT + getTopInset(),
android: isNotchedAndroid
? NAVIGATION_HEADER_HEIGHT + StatusBar.currentHeight
: NAVIGATION_HEADER_HEIGHT,
default: NAVIGATION_HEADER_HEIGHT,
});

export const getHomeIndicatorPadding = () =>
Platform.OS === 'ios' ? getBottomInset() : 0;

export const getNotchAreaHeight = () =>
Platform.select({
ios: getTopInset(),
android: isNotchedAndroid ? StatusBar.currentHeight : 0,
default: 0,
});
3 changes: 3 additions & 0 deletions helpers/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
export {
Device,
getHomeIndicatorPadding,
getNavigationBarHeight,
getNotchAreaHeight,
HOME_INDICATOR_PADDING,
isNotchedAndroid,
NAVIGATION_BAR_HEIGHT,
Expand Down
9 changes: 8 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,14 @@ export { YearRangePicker } from './components/YearRangePicker';
export * from './hooks';

// Helpers
export { calculateKeyboardOffset, Device, Keyboard } from './helpers';
export {
calculateKeyboardOffset,
Device,
getHomeIndicatorPadding,
getNavigationBarHeight,
getNotchAreaHeight,
Keyboard,
} from './helpers';

// HTML
export { Html } from './html';
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@shoutem/ui",
"version": "9.0.4",
"version": "9.0.5",
"description": "Styleable set of components for React Native applications",
"scripts": {
"lint": "eslint .",
Expand Down