@shoutem/ui 9.0.5 → 9.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/helpers/device-selector.js +71 -3
- package/helpers/index.js +3 -0
- package/index.js +8 -1
- package/package.json +1 -1
- package/.claude/settings.local.json +0 -8
|
@@ -4,22 +4,37 @@ import { initialWindowMetrics } from 'react-native-safe-area-context';
|
|
|
4
4
|
|
|
5
5
|
export const NAVIGATION_HEADER_HEIGHT = 64;
|
|
6
6
|
|
|
7
|
+
// Fallback inset values used when initialWindowMetrics is null (race condition
|
|
8
|
+
// in large apps where JS evaluates before the safe-area native module inits).
|
|
9
|
+
// Bottom: 34pt — consistent across all notched iPhones since iPhone X (2017).
|
|
10
|
+
// Top: 59pt — matches Dynamic Island devices (iPhone 14+).
|
|
11
|
+
// Slightly too large for older notched devices (44–48pt), but using the
|
|
12
|
+
// largest one prevents content from being hidden under the notch/Dynamic Island.
|
|
13
|
+
const DEFAULT_IOS_TOP_INSET = 59;
|
|
14
|
+
const DEFAULT_IOS_BOTTOM_INSET = 34;
|
|
15
|
+
|
|
7
16
|
export const isNotchedAndroid =
|
|
8
17
|
Platform.OS === 'android' && DeviceInfo.hasNotch();
|
|
9
18
|
|
|
10
19
|
export const NAVIGATION_BAR_HEIGHT = Platform.select({
|
|
11
|
-
ios:
|
|
20
|
+
ios:
|
|
21
|
+
NAVIGATION_HEADER_HEIGHT +
|
|
22
|
+
(initialWindowMetrics?.insets?.top ?? DEFAULT_IOS_TOP_INSET),
|
|
12
23
|
android: isNotchedAndroid
|
|
13
24
|
? NAVIGATION_HEADER_HEIGHT + StatusBar.currentHeight
|
|
14
25
|
: NAVIGATION_HEADER_HEIGHT,
|
|
15
26
|
default: NAVIGATION_HEADER_HEIGHT,
|
|
16
27
|
});
|
|
17
28
|
|
|
29
|
+
// Bottom inset from the native safe-area module (home indicator on iOS,
|
|
30
|
+
// system nav bar on Android with edge-to-edge). Falls back to 34pt on iOS
|
|
31
|
+
// (race condition guard) or 0 on Android (no inset when edge-to-edge is off).
|
|
18
32
|
export const HOME_INDICATOR_PADDING =
|
|
19
|
-
|
|
33
|
+
initialWindowMetrics?.insets?.bottom ??
|
|
34
|
+
(Platform.OS === 'ios' ? DEFAULT_IOS_BOTTOM_INSET : 0);
|
|
20
35
|
|
|
21
36
|
export const NOTCH_AREA_HEIGHT = Platform.select({
|
|
22
|
-
ios: initialWindowMetrics?.insets?.top,
|
|
37
|
+
ios: initialWindowMetrics?.insets?.top ?? DEFAULT_IOS_TOP_INSET,
|
|
23
38
|
android: isNotchedAndroid ? StatusBar.currentHeight : 0,
|
|
24
39
|
default: 0,
|
|
25
40
|
});
|
|
@@ -30,3 +45,56 @@ export const Device = {
|
|
|
30
45
|
NOTCH_AREA_HEIGHT,
|
|
31
46
|
NAVIGATION_HEADER_HEIGHT,
|
|
32
47
|
};
|
|
48
|
+
|
|
49
|
+
// Lazy getters — resolve initialWindowMetrics on first render,
|
|
50
|
+
// when the native module is guaranteed to be ready.
|
|
51
|
+
let _topInset;
|
|
52
|
+
let _bottomInset;
|
|
53
|
+
|
|
54
|
+
const getTopInset = () => {
|
|
55
|
+
if (_topInset === undefined) {
|
|
56
|
+
// eslint-disable-next-line global-require
|
|
57
|
+
const metrics = require('react-native-safe-area-context')
|
|
58
|
+
.initialWindowMetrics;
|
|
59
|
+
_topInset = metrics?.insets?.top ?? DEFAULT_IOS_TOP_INSET;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return _topInset;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const getBottomInset = () => {
|
|
66
|
+
if (_bottomInset === undefined) {
|
|
67
|
+
// eslint-disable-next-line global-require
|
|
68
|
+
const metrics = require('react-native-safe-area-context')
|
|
69
|
+
.initialWindowMetrics;
|
|
70
|
+
|
|
71
|
+
// Use actual bottom inset if available. Fallback: 34pt on iOS (safe
|
|
72
|
+
// default for all notched iPhones), 0 on Android (no inset pre-RN 0.77).
|
|
73
|
+
_bottomInset =
|
|
74
|
+
metrics?.insets?.bottom ??
|
|
75
|
+
(Platform.OS === 'ios' ? DEFAULT_IOS_BOTTOM_INSET : 0);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return _bottomInset;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export const getNavigationBarHeight = () =>
|
|
82
|
+
Platform.select({
|
|
83
|
+
ios: NAVIGATION_HEADER_HEIGHT + getTopInset(),
|
|
84
|
+
android: isNotchedAndroid
|
|
85
|
+
? NAVIGATION_HEADER_HEIGHT + StatusBar.currentHeight
|
|
86
|
+
: NAVIGATION_HEADER_HEIGHT,
|
|
87
|
+
default: NAVIGATION_HEADER_HEIGHT,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Returns bottom safe area inset on both platforms. On iOS this is the home
|
|
91
|
+
// indicator area (34pt). On Android this is the system navigation bar height
|
|
92
|
+
// when edge-to-edge is enabled (RN 0.76+), or 0 on older RN versions.
|
|
93
|
+
export const getHomeIndicatorPadding = () => getBottomInset();
|
|
94
|
+
|
|
95
|
+
export const getNotchAreaHeight = () =>
|
|
96
|
+
Platform.select({
|
|
97
|
+
ios: getTopInset(),
|
|
98
|
+
android: isNotchedAndroid ? StatusBar.currentHeight : 0,
|
|
99
|
+
default: 0,
|
|
100
|
+
});
|
package/helpers/index.js
CHANGED
package/index.js
CHANGED
|
@@ -78,7 +78,14 @@ export { YearRangePicker } from './components/YearRangePicker';
|
|
|
78
78
|
export * from './hooks';
|
|
79
79
|
|
|
80
80
|
// Helpers
|
|
81
|
-
export {
|
|
81
|
+
export {
|
|
82
|
+
calculateKeyboardOffset,
|
|
83
|
+
Device,
|
|
84
|
+
getHomeIndicatorPadding,
|
|
85
|
+
getNavigationBarHeight,
|
|
86
|
+
getNotchAreaHeight,
|
|
87
|
+
Keyboard,
|
|
88
|
+
} from './helpers';
|
|
82
89
|
|
|
83
90
|
// HTML
|
|
84
91
|
export { Html } from './html';
|
package/package.json
CHANGED