react-native-terra-ui 0.11.12 → 0.11.13

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.
Files changed (25) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/TerraUI.podspec +16 -0
  3. package/ios/TerraHeaderInsetsComponentView.h +4 -0
  4. package/ios/TerraHeaderInsetsComponentView.mm +93 -0
  5. package/lib/module/components/header/parts/HeaderBar.js +21 -3
  6. package/lib/module/components/header/parts/HeaderBar.js.map +1 -1
  7. package/lib/module/components/header/parts/HeaderWindowInsets.ios.js +29 -0
  8. package/lib/module/components/header/parts/HeaderWindowInsets.ios.js.map +1 -0
  9. package/lib/module/components/header/parts/HeaderWindowInsets.js +7 -0
  10. package/lib/module/components/header/parts/HeaderWindowInsets.js.map +1 -0
  11. package/lib/module/specs/TerraHeaderInsetsNativeComponent.ts +12 -0
  12. package/lib/typescript/src/components/header/parts/HeaderBar.d.ts +1 -1
  13. package/lib/typescript/src/components/header/parts/HeaderBar.d.ts.map +1 -1
  14. package/lib/typescript/src/components/header/parts/HeaderWindowInsets.d.ts +9 -0
  15. package/lib/typescript/src/components/header/parts/HeaderWindowInsets.d.ts.map +1 -0
  16. package/lib/typescript/src/components/header/parts/HeaderWindowInsets.ios.d.ts +3 -0
  17. package/lib/typescript/src/components/header/parts/HeaderWindowInsets.ios.d.ts.map +1 -0
  18. package/lib/typescript/src/specs/TerraHeaderInsetsNativeComponent.d.ts +10 -0
  19. package/lib/typescript/src/specs/TerraHeaderInsetsNativeComponent.d.ts.map +1 -0
  20. package/package.json +14 -1
  21. package/react-native.config.js +7 -0
  22. package/src/components/header/parts/HeaderBar.tsx +18 -4
  23. package/src/components/header/parts/HeaderWindowInsets.ios.tsx +24 -0
  24. package/src/components/header/parts/HeaderWindowInsets.tsx +8 -0
  25. package/src/specs/TerraHeaderInsetsNativeComponent.ts +12 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.11.13](https://github.com/earthlin9/react-native-terra-ui/compare/v0.11.12...v0.11.13) (2026-09-18)
4
+
5
+ ### Bug Fixes
6
+
7
+ * **ui:** [header] avoid iPad window controls ([#26](https://github.com/earthlin9/react-native-terra-ui/issues/26)) ([f11697a](https://github.com/earthlin9/react-native-terra-ui/commit/f11697a4d12b89ee20c71436bc82100216dbe624))
8
+
3
9
  ## [0.11.12](https://github.com/earthlin9/react-native-terra-ui/compare/v0.11.11...v0.11.12) (2026-09-17)
4
10
 
5
11
  ### Features
@@ -0,0 +1,16 @@
1
+ require "json"
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = "TerraUI"
7
+ s.version = package["version"]
8
+ s.summary = package["description"]
9
+ s.homepage = package["homepage"]
10
+ s.license = package["license"]
11
+ s.author = package["author"]
12
+ s.source = { :git => "https://github.com/earthling-std/react-native-terra-ui.git", :tag => "v#{s.version}" }
13
+ s.platforms = { :ios => "15.1" }
14
+ s.source_files = "ios/**/*.{h,mm}"
15
+ install_modules_dependencies(s)
16
+ end
@@ -0,0 +1,4 @@
1
+ #import <React/RCTViewComponentView.h>
2
+
3
+ @interface TerraHeaderInsetsComponentView : RCTViewComponentView
4
+ @end
@@ -0,0 +1,93 @@
1
+ #import "TerraHeaderInsetsComponentView.h"
2
+
3
+ #import <react/renderer/components/TerraUISpec/ComponentDescriptors.h>
4
+ #import <react/renderer/components/TerraUISpec/EventEmitters.h>
5
+ #import <react/renderer/components/TerraUISpec/Props.h>
6
+
7
+ using namespace facebook::react;
8
+
9
+ @implementation TerraHeaderInsetsComponentView {
10
+ UIEdgeInsets _lastInsets;
11
+ BOOL _sentInsets;
12
+ }
13
+
14
+ + (ComponentDescriptorProvider)componentDescriptorProvider
15
+ {
16
+ return concreteComponentDescriptorProvider<TerraHeaderInsetsComponentDescriptor>();
17
+ }
18
+
19
+ - (instancetype)initWithFrame:(CGRect)frame
20
+ {
21
+ if (self = [super initWithFrame:frame]) {
22
+ _props = std::make_shared<const TerraHeaderInsetsProps>();
23
+ }
24
+ return self;
25
+ }
26
+
27
+ - (void)layoutSubviews
28
+ {
29
+ [super layoutSubviews];
30
+ [self reportInsets];
31
+ }
32
+
33
+ - (void)safeAreaInsetsDidChange
34
+ {
35
+ [super safeAreaInsetsDidChange];
36
+ [self setNeedsLayout];
37
+ }
38
+
39
+ - (void)didMoveToWindow
40
+ {
41
+ [super didMoveToWindow];
42
+ [self setNeedsLayout];
43
+ }
44
+
45
+ - (void)layoutMarginsDidChange
46
+ {
47
+ [super layoutMarginsDidChange];
48
+ [self setNeedsLayout];
49
+ }
50
+
51
+ - (void)updateEventEmitter:(EventEmitter::Shared const &)eventEmitter
52
+ {
53
+ [super updateEventEmitter:eventEmitter];
54
+ [self setNeedsLayout];
55
+ }
56
+
57
+ - (void)prepareForRecycle
58
+ {
59
+ [super prepareForRecycle];
60
+ _sentInsets = NO;
61
+ _lastInsets = UIEdgeInsetsZero;
62
+ }
63
+
64
+ - (void)reportInsets
65
+ {
66
+ if (!self.window || !_eventEmitter || CGRectIsEmpty(self.bounds)) {
67
+ return;
68
+ }
69
+
70
+ UIEdgeInsets insets = UIEdgeInsetsZero;
71
+ #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 260000
72
+ if (@available(iOS 26.0, *)) {
73
+ if (self.traitCollection.userInterfaceIdiom == UIUserInterfaceIdiomPad) {
74
+ // Measure at the bar's actual position, including inside sheets. Using
75
+ // safeArea rather than margins leaves Terra's spacing tokens in charge.
76
+ UIViewLayoutRegion *region = [UIViewLayoutRegion
77
+ safeAreaLayoutRegionWithCornerAdaptation:UIViewLayoutRegionAdaptivityAxisHorizontal];
78
+ insets = [self edgeInsetsForLayoutRegion:region];
79
+ }
80
+ }
81
+ #endif
82
+ insets.top = 0;
83
+ insets.bottom = 0;
84
+ if (_sentInsets && UIEdgeInsetsEqualToEdgeInsets(insets, _lastInsets)) {
85
+ return;
86
+ }
87
+ _sentInsets = YES;
88
+ _lastInsets = insets;
89
+ const auto emitter = std::static_pointer_cast<const TerraHeaderInsetsEventEmitter>(_eventEmitter);
90
+ emitter->onInsetsChange({.left = insets.left, .right = insets.right});
91
+ }
92
+
93
+ @end
@@ -2,13 +2,16 @@
2
2
 
3
3
  import { View } from "react-native-unistyles/components/native/View";
4
4
  import { Text } from "react-native-unistyles/components/native/Text";
5
+ import { useState } from "react";
5
6
  import Animated from "react-native-reanimated";
6
7
  import { StyleSheet, useUnistyles } from "react-native-unistyles";
7
8
  import { FONT_WEIGHT_VALUE } from "../../../utils/typography.js";
9
+ import { resolveScreenPadding } from "../../../theme/screen-padding.js";
8
10
  import { Toolbar } from "../../toolbar/index.js";
9
11
  import { HeaderDismissButton } from "../header-buttons.js";
10
12
  import { isCustomTitle, isTextTitle } from "../utils.js";
11
13
  import { HeaderSurface } from "./HeaderSurface.js";
14
+ import { HeaderWindowInsets } from "./HeaderWindowInsets";
12
15
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
16
  /** Shared compact bar. Only the title and background animate; actions stay interactive. */
14
17
  export function HeaderBar({
@@ -26,6 +29,10 @@ export function HeaderBar({
26
29
  const {
27
30
  theme
28
31
  } = useUnistyles();
32
+ const [windowInsets, setWindowInsets] = useState({
33
+ left: 0,
34
+ right: 0
35
+ });
29
36
  const _styles = styles;
30
37
  {
31
38
  const styles = _styles.useVariants({
@@ -37,14 +44,16 @@ export function HeaderBar({
37
44
  onDismiss: onDismiss
38
45
  });
39
46
  return /*#__PURE__*/_jsxs(View, {
40
- style: styles.bar,
47
+ style: [styles.bar, styles.windowInsets(windowInsets.left, windowInsets.right)],
41
48
  children: [/*#__PURE__*/_jsx(HeaderSurface, {
42
49
  color: color,
43
50
  animatedStyle: surfaceStyle
51
+ }), /*#__PURE__*/_jsx(HeaderWindowInsets, {
52
+ onInsetsChange: setWindowInsets
44
53
  }), (leading != null || dismissAction === "back") && /*#__PURE__*/_jsxs(Toolbar, {
45
54
  children: [dismissAction === "back" && dismiss, leading]
46
55
  }), /*#__PURE__*/_jsx(Animated.View, {
47
- style: [styles.titleContainer, titleStyle],
56
+ style: [styles.titleContainer, styles.titleInsets(windowInsets.left, windowInsets.right, titleAlignment), titleStyle],
48
57
  pointerEvents: isCustomTitle(title) ? "box-none" : "none",
49
58
  children: isTextTitle(title) ? String(title).trim().length > 0 && /*#__PURE__*/_jsx(Text, {
50
59
  style: styles.title,
@@ -58,7 +67,16 @@ export function HeaderBar({
58
67
  });
59
68
  }
60
69
  }
61
- const styles = StyleSheet.create(theme => ({
70
+ const styles = StyleSheet.create((theme, runtime) => ({
71
+ windowInsets: (left, right) => ({
72
+ paddingLeft: Math.max(resolveScreenPadding(theme, runtime.breakpoint).x, left),
73
+ paddingRight: Math.max(resolveScreenPadding(theme, runtime.breakpoint).x, right),
74
+ uni__dependencies: [0, 3]
75
+ }),
76
+ titleInsets: (left, right, alignment) => alignment === "center" ? {
77
+ left,
78
+ right
79
+ } : {},
62
80
  bar: {
63
81
  height: theme.layout.header.height,
64
82
  flexDirection: "row",
@@ -1 +1 @@
1
- {"version":3,"names":["Animated","StyleSheet","useUnistyles","FONT_WEIGHT_VALUE","Toolbar","HeaderDismissButton","isCustomTitle","isTextTitle","HeaderSurface","jsx","_jsx","jsxs","_jsxs","HeaderBar","title","leading","trailing","titleAlignment","color","surfaceStyle","titleStyle","dismissAction","navigation","onDismiss","theme","_styles","styles","useVariants","dismiss","View","style","bar","children","animatedStyle","titleContainer","pointerEvents","String","trim","length","Text","maxFontSizeMultiplier","typography","variants","create","height","layout","header","flexDirection","alignItems","paddingHorizontal","screen","padding","x","gap","spacing","justifyContent","uni__dependencies","center","marginLeft","left","position","right","flex","fontSize","lineHeight","letterSpacing","fontWeight","textAlign"],"sourceRoot":"../../../../../src","sources":["components/header/parts/HeaderBar.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["useState","Animated","StyleSheet","useUnistyles","FONT_WEIGHT_VALUE","resolveScreenPadding","Toolbar","HeaderDismissButton","isCustomTitle","isTextTitle","HeaderSurface","HeaderWindowInsets","jsx","_jsx","jsxs","_jsxs","HeaderBar","title","leading","trailing","titleAlignment","color","surfaceStyle","titleStyle","dismissAction","navigation","onDismiss","theme","windowInsets","setWindowInsets","left","right","_styles","styles","useVariants","dismiss","View","style","bar","children","animatedStyle","onInsetsChange","titleContainer","titleInsets","pointerEvents","String","trim","length","Text","maxFontSizeMultiplier","typography","variants","create","runtime","paddingLeft","Math","max","breakpoint","x","paddingRight","uni__dependencies","alignment","height","layout","header","flexDirection","alignItems","paddingHorizontal","screen","padding","gap","spacing","justifyContent","center","marginLeft","position","flex","fontSize","lineHeight","letterSpacing","fontWeight","textAlign"],"sourceRoot":"../../../../../src","sources":["components/header/parts/HeaderBar.tsx"],"mappings":";;;;AAAA,SAA8CA,QAAQ,QAAQ,OAAO;AAGrE,OAAOC,QAAQ,MAAM,yBAAyB;AAC9C,SAASC,UAAU,EAAEC,YAAY,QAAQ,wBAAwB;AAEjE,SAASC,iBAAiB;AAC1B,SAASC,oBAAoB;AAC7B,SAASC,OAAO;AAChB,SAASC,mBAAmB;AAC5B,SAASC,aAAa,EAAEC,WAAW;AACnC,SAASC,aAAa;AACtB,SAASC,kBAAkB;AAA+B,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAY1D;AACA,OAAO,SAASC,SAASA,CAAC;EACxBC,KAAK;EACLC,OAAO;EACPC,QAAQ;EACRC,cAAc;EACdC,KAAK;EACLC,YAAY;EACZC,UAAU;EACVC,aAAa,GAAG,MAAM;EACtBC,UAAU;EACVC;AACc,CAAC,EAAE;EACjB,MAAM;IAAEC;EAAM,CAAC,GAAGxB,YAAY,CAAC,CAAC;EAChC,MAAM,CAACyB,YAAY,EAAEC,eAAe,CAAC,GAAG7B,QAAQ,CAAC;IAAE8B,IAAI,EAAE,CAAC;IAAEC,KAAK,EAAE;EAAE,CAAC,CAAC;EAAC,MAAAC,OAAA,GAAAC,MAAA;EAAA;IAAA,MAAAA,MAAA,GAAAD,OAAA,CAAAE,WAAA,CACrD;MAAEd;IAAe,CAAC;IACrC,MAAMe,OAAO,gBACXtB,IAAA,CAACN,mBAAmB;MAACiB,aAAa,EAAEA,aAAc;MAACC,UAAU,EAAEA,UAAW;MAACC,SAAS,EAAEA;IAAU,CAAE,CACnG;IACD,oBACEX,KAAA,CAACqB,IAAI;MAACC,KAAK,EAAE,CAACJ,MAAM,CAACK,GAAG,EAAEL,MAAM,CAACL,YAAY,CAACA,YAAY,CAACE,IAAI,EAAEF,YAAY,CAACG,KAAK,CAAC,CAAE;MAAAQ,QAAA,gBACpF1B,IAAA,CAACH,aAAa;QAACW,KAAK,EAAEA,KAAM;QAACmB,aAAa,EAAElB;MAAa,CAAE,CAAC,eAC5DT,IAAA,CAACF,kBAAkB;QAAC8B,cAAc,EAAEZ;MAAgB,CAAE,CAAC,EACtD,CAACX,OAAO,IAAI,IAAI,IAAIM,aAAa,KAAK,MAAM,kBAC3CT,KAAA,CAACT,OAAO;QAAAiC,QAAA,GACLf,aAAa,KAAK,MAAM,IAAIW,OAAO,EACnCjB,OAAO;MAAA,CACD,CACV,eACDL,IAAA,CAACZ,QAAQ,CAACmC,IAAI;QACZC,KAAK,EAAE,CACLJ,MAAM,CAACS,cAAc,EACrBT,MAAM,CAACU,WAAW,CAACf,YAAY,CAACE,IAAI,EAAEF,YAAY,CAACG,KAAK,EAAEX,cAAc,CAAC,EACzEG,UAAU,CACV;QACFqB,aAAa,EAAEpC,aAAa,CAACS,KAAK,CAAC,GAAG,UAAU,GAAG,MAAO;QAAAsB,QAAA,EAEzD9B,WAAW,CAACQ,KAAK,CAAC,GACf4B,MAAM,CAAC5B,KAAK,CAAC,CAAC6B,IAAI,CAAC,CAAC,CAACC,MAAM,GAAG,CAAC,iBAC7BlC,IAAA,CAACmC,IAAI;UACHX,KAAK,EAAEJ,MAAM,CAAChB,KAAM;UACpBgC,qBAAqB,EAAEtB,KAAK,CAACuB,UAAU,CAACC,QAAQ,CAAC,UAAU,CAAC,CAACF,qBAAsB;UAAAV,QAAA,EAElFtB;QAAK,CACF,CACP,GACDA;MAAK,CACI,CAAC,EACf,CAACE,QAAQ,IAAI,IAAI,IAAIK,aAAa,KAAK,OAAO,kBAC7CT,KAAA,CAACT,OAAO;QAAC+B,KAAK,EAAEJ,MAAM,CAACd,QAAS;QAAAoB,QAAA,GAC7Bf,aAAa,KAAK,OAAO,IAAIW,OAAO,EACpChB,QAAQ;MAAA,CACF,CACV;IAAA,CACG,CAAC;EACP;AACJ;AAEA,MAAMc,MAAM,GAAG/B,UAAU,CAACkD,MAAM,CAAC,CAACzB,KAAK,EAAE0B,OAAO,MAAM;EACpDzB,YAAY,EAAEA,CAACE,IAAY,EAAEC,KAAa,MAAM;IAC9CuB,WAAW,EAAEC,IAAI,CAACC,GAAG,CAACnD,oBAAoB,CAACsB,KAAK,EAAE0B,OAAO,CAACI,UAAU,CAAC,CAACC,CAAC,EAAE5B,IAAI,CAAC;IAC9E6B,YAAY,EAAEJ,IAAI,CAACC,GAAG,CAACnD,oBAAoB,CAACsB,KAAK,EAAE0B,OAAO,CAACI,UAAU,CAAC,CAACC,CAAC,EAAE3B,KAAK,CAAC;IAAA6B,iBAAA;EAClF,CAAC,CAAC;EACFjB,WAAW,EAAEA,CAACb,IAAY,EAAEC,KAAa,EAAE8B,SAA4B,KACrEA,SAAS,KAAK,QAAQ,GAAG;IAAE/B,IAAI;IAAEC;EAAM,CAAC,GAAG,CAAC,CAAC;EAC/CO,GAAG,EAAE;IACHwB,MAAM,EAAEnC,KAAK,CAACoC,MAAM,CAACC,MAAM,CAACF,MAAM;IAClCG,aAAa,EAAE,KAAK;IACpBC,UAAU,EAAE,QAAQ;IACpBC,iBAAiB,EAAExC,KAAK,CAACoC,MAAM,CAACK,MAAM,CAACC,OAAO,CAACX,CAAC;IAChDY,GAAG,EAAE3C,KAAK,CAAC4C,OAAO,CAAC,GAAG,CAAC;IACvBC,cAAc,EAAE,eAAe;IAAAZ,iBAAA;EACjC,CAAC;EACD;EACA;EACA;EACAzC,QAAQ,EAAE;IACRqD,cAAc,EAAE,UAAU;IAC1BrB,QAAQ,EAAE;MACR/B,cAAc,EAAE;QACdqD,MAAM,EAAE;UAAEC,UAAU,EAAE;QAAO,CAAC;QAC9B5C,IAAI,EAAE,CAAC;MACT;IACF,CAAC;IAAA8B,iBAAA;EACH,CAAC;EACDlB,cAAc,EAAE;IACdS,QAAQ,EAAE;MACR/B,cAAc,EAAE;QACdqD,MAAM,EAAE;UACNE,QAAQ,EAAE,UAAU;UACpB7C,IAAI,EAAE,CAAC;UACPC,KAAK,EAAE,CAAC;UACRmC,UAAU,EAAE;QACd,CAAC;QACDpC,IAAI,EAAE;UACJ8C,IAAI,EAAE,CAAC;UACPV,UAAU,EAAE;QACd;MACF;IACF,CAAC;IAAAN,iBAAA;EACH,CAAC;EACD3C,KAAK,EAAE;IACL4D,QAAQ,EAAElD,KAAK,CAACuB,UAAU,CAACC,QAAQ,CAAC,UAAU,CAAC,CAAC0B,QAAQ;IACxDC,UAAU,EAAEnD,KAAK,CAACuB,UAAU,CAACC,QAAQ,CAAC,UAAU,CAAC,CAAC2B,UAAU;IAC5DC,aAAa,EAAEpD,KAAK,CAACuB,UAAU,CAACC,QAAQ,CAAC,UAAU,CAAC,CAAC4B,aAAa;IAClEC,UAAU,EAAE5E,iBAAiB,CAACuB,KAAK,CAACuB,UAAU,CAACC,QAAQ,CAAC,UAAU,CAAC,CAAC6B,UAAU,CAAC;IAC/E3D,KAAK,EAAGM,KAAK,CAACN,KAAK,CAAmD,cAAc,CAAC,IAAI,EAAE;IAC3F8B,QAAQ,EAAE;MACR/B,cAAc,EAAE;QACdqD,MAAM,EAAE;UAAEQ,SAAS,EAAE;QAAS,CAAC;QAC/BnD,IAAI,EAAE;UAAEmD,SAAS,EAAE;QAAO;MAC5B;IACF,CAAC;IAAArB,iBAAA;EACH;AACF,CAAC,CAAC,CAAC","ignoreList":[]}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+
3
+ import { Platform } from "react-native";
4
+ import { StyleSheet } from "react-native-unistyles";
5
+ import TerraHeaderInsets from "../../../specs/TerraHeaderInsetsNativeComponent";
6
+ import { jsx as _jsx } from "react/jsx-runtime";
7
+ export function HeaderWindowInsets({
8
+ onInsetsChange
9
+ }) {
10
+ if (Platform.OS !== "ios" || !Platform.isPad || Number.parseInt(String(Platform.Version), 10) < 26) return null;
11
+ return /*#__PURE__*/_jsx(TerraHeaderInsets, {
12
+ style: styles.probe,
13
+ pointerEvents: "none",
14
+ accessible: false,
15
+ onInsetsChange: ({
16
+ nativeEvent
17
+ }) => onInsetsChange(nativeEvent)
18
+ });
19
+ }
20
+ const styles = StyleSheet.create(() => ({
21
+ probe: {
22
+ position: "absolute",
23
+ top: 0,
24
+ left: 0,
25
+ right: 0,
26
+ bottom: 0
27
+ }
28
+ }));
29
+ //# sourceMappingURL=HeaderWindowInsets.ios.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Platform","StyleSheet","TerraHeaderInsets","jsx","_jsx","HeaderWindowInsets","onInsetsChange","OS","isPad","Number","parseInt","String","Version","style","styles","probe","pointerEvents","accessible","nativeEvent","create","position","top","left","right","bottom"],"sourceRoot":"../../../../../src","sources":["components/header/parts/HeaderWindowInsets.ios.tsx"],"mappings":";;AAAA,SAASA,QAAQ,QAAQ,cAAc;AAEvC,SAASC,UAAU,QAAQ,wBAAwB;AAEnD,OAAOC,iBAAiB;AAAwD,SAAAC,GAAA,IAAAC,IAAA;AAGhF,OAAO,SAASC,kBAAkBA,CAAC;EAAEC;AAAwC,CAAC,EAAE;EAC9E,IAAIN,QAAQ,CAACO,EAAE,KAAK,KAAK,IAAI,CAACP,QAAQ,CAACQ,KAAK,IAAIC,MAAM,CAACC,QAAQ,CAACC,MAAM,CAACX,QAAQ,CAACY,OAAO,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,EAChG,OAAO,IAAI;EAEb,oBACER,IAAA,CAACF,iBAAiB;IAChBW,KAAK,EAAEC,MAAM,CAACC,KAAM;IACpBC,aAAa,EAAC,MAAM;IACpBC,UAAU,EAAE,KAAM;IAClBX,cAAc,EAAEA,CAAC;MAAEY;IAAY,CAAC,KAAKZ,cAAc,CAACY,WAAW;EAAE,CAClE,CAAC;AAEN;AAEA,MAAMJ,MAAM,GAAGb,UAAU,CAACkB,MAAM,CAAC,OAAO;EACtCJ,KAAK,EAAE;IAAEK,QAAQ,EAAE,UAAU;IAAEC,GAAG,EAAE,CAAC;IAAEC,IAAI,EAAE,CAAC;IAAEC,KAAK,EAAE,CAAC;IAAEC,MAAM,EAAE;EAAE;AACtE,CAAC,CAAC,CAAC","ignoreList":[]}
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+
3
+ /** Only iPadOS needs the native window-control measurement. */
4
+ export function HeaderWindowInsets(_) {
5
+ return null;
6
+ }
7
+ //# sourceMappingURL=HeaderWindowInsets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["HeaderWindowInsets","_"],"sourceRoot":"../../../../../src","sources":["components/header/parts/HeaderWindowInsets.tsx"],"mappings":";;AAIA;AACA,OAAO,SAASA,kBAAkBA,CAACC,CAA0B,EAAE;EAC7D,OAAO,IAAI;AACb","ignoreList":[]}
@@ -0,0 +1,12 @@
1
+ import type { CodegenTypes, ViewProps } from "react-native";
2
+ import { codegenNativeComponent } from "react-native";
3
+
4
+ export interface NativeProps extends ViewProps {
5
+ onInsetsChange?: CodegenTypes.DirectEventHandler<
6
+ Readonly<{ left: CodegenTypes.Double; right: CodegenTypes.Double }>
7
+ >;
8
+ }
9
+
10
+ export default codegenNativeComponent<NativeProps>("TerraHeaderInsets", {
11
+ excludedPlatforms: ["android"],
12
+ });
@@ -1,4 +1,4 @@
1
- import type { ComponentProps, ReactNode } from "react";
1
+ import { type ComponentProps, type ReactNode } from "react";
2
2
  import Animated from "react-native-reanimated";
3
3
  import { type HeaderDismissProps } from "../header-buttons.js";
4
4
  import { type HeaderSurfaceProps } from "./HeaderSurface.js";
@@ -1 +1 @@
1
- {"version":3,"file":"HeaderBar.d.ts","sourceRoot":"","sources":["../../../../../../src/components/header/parts/HeaderBar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvD,OAAO,QAAQ,MAAM,yBAAyB,CAAC;AAK/C,OAAO,EAAuB,KAAK,kBAAkB,EAAE,MAAM,sBAAmB,CAAC;AAEjF,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,oBAAiB,CAAC;AAEzE,UAAU,cAAe,SAAQ,kBAAkB;IACjD,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,cAAc,EAAE,QAAQ,GAAG,MAAM,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,kBAAkB,CAAC,eAAe,CAAC,CAAC;IACnD,UAAU,CAAC,EAAE,cAAc,CAAC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC;CAC5D;AAED,2FAA2F;AAC3F,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,OAAO,EACP,QAAQ,EACR,cAAc,EACd,KAAK,EACL,YAAY,EACZ,UAAU,EACV,aAAsB,EACtB,UAAU,EACV,SAAS,GACV,EAAE,cAAc,+BAsChB"}
1
+ {"version":3,"file":"HeaderBar.d.ts","sourceRoot":"","sources":["../../../../../../src/components/header/parts/HeaderBar.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAY,MAAM,OAAO,CAAC;AAGtE,OAAO,QAAQ,MAAM,yBAAyB,CAAC;AAM/C,OAAO,EAAuB,KAAK,kBAAkB,EAAE,MAAM,sBAAmB,CAAC;AAEjF,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,oBAAiB,CAAC;AAGzE,UAAU,cAAe,SAAQ,kBAAkB;IACjD,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,cAAc,EAAE,QAAQ,GAAG,MAAM,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,kBAAkB,CAAC,eAAe,CAAC,CAAC;IACnD,UAAU,CAAC,EAAE,cAAc,CAAC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC;CAC5D;AAED,2FAA2F;AAC3F,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,OAAO,EACP,QAAQ,EACR,cAAc,EACd,KAAK,EACL,YAAY,EACZ,UAAU,EACV,aAAsB,EACtB,UAAU,EACV,SAAS,GACV,EAAE,cAAc,+BA4ChB"}
@@ -0,0 +1,9 @@
1
+ export interface HeaderWindowInsetsProps {
2
+ onInsetsChange: (insets: {
3
+ left: number;
4
+ right: number;
5
+ }) => void;
6
+ }
7
+ /** Only iPadOS needs the native window-control measurement. */
8
+ export declare function HeaderWindowInsets(_: HeaderWindowInsetsProps): null;
9
+ //# sourceMappingURL=HeaderWindowInsets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HeaderWindowInsets.d.ts","sourceRoot":"","sources":["../../../../../../src/components/header/parts/HeaderWindowInsets.tsx"],"names":[],"mappings":"AAAA,MAAM,WAAW,uBAAuB;IACtC,cAAc,EAAE,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACnE;AAED,+DAA+D;AAC/D,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,uBAAuB,QAE5D"}
@@ -0,0 +1,3 @@
1
+ import type { HeaderWindowInsetsProps } from "./HeaderWindowInsets";
2
+ export declare function HeaderWindowInsets({ onInsetsChange }: HeaderWindowInsetsProps): import("react").JSX.Element | null;
3
+ //# sourceMappingURL=HeaderWindowInsets.ios.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HeaderWindowInsets.ios.d.ts","sourceRoot":"","sources":["../../../../../../src/components/header/parts/HeaderWindowInsets.ios.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAEpE,wBAAgB,kBAAkB,CAAC,EAAE,cAAc,EAAE,EAAE,uBAAuB,sCAY7E"}
@@ -0,0 +1,10 @@
1
+ import type { CodegenTypes, ViewProps } from "react-native";
2
+ export interface NativeProps extends ViewProps {
3
+ onInsetsChange?: CodegenTypes.DirectEventHandler<Readonly<{
4
+ left: CodegenTypes.Double;
5
+ right: CodegenTypes.Double;
6
+ }>>;
7
+ }
8
+ declare const _default: import("react-native/types_generated/Libraries/Utilities/codegenNativeComponent").NativeComponentType<NativeProps>;
9
+ export default _default;
10
+ //# sourceMappingURL=TerraHeaderInsetsNativeComponent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TerraHeaderInsetsNativeComponent.d.ts","sourceRoot":"","sources":["../../../../src/specs/TerraHeaderInsetsNativeComponent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAG5D,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,cAAc,CAAC,EAAE,YAAY,CAAC,kBAAkB,CAC9C,QAAQ,CAAC;QAAE,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC;QAAC,KAAK,EAAE,YAAY,CAAC,MAAM,CAAA;KAAE,CAAC,CACpE,CAAC;CACH;;AAED,wBAEG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-terra-ui",
3
- "version": "0.11.12",
3
+ "version": "0.11.13",
4
4
  "description": "Themeable React Native UI components built on react-native-unistyles",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -21,6 +21,9 @@
21
21
  "files": [
22
22
  "src",
23
23
  "lib",
24
+ "ios",
25
+ "TerraUI.podspec",
26
+ "react-native.config.js",
24
27
  "CHANGELOG.md",
25
28
  "!**/__tests__",
26
29
  "!**/__fixtures__",
@@ -136,6 +139,16 @@
136
139
  }
137
140
  }
138
141
  },
142
+ "codegenConfig": {
143
+ "name": "TerraUISpec",
144
+ "type": "components",
145
+ "jsSrcsDir": "src/specs",
146
+ "ios": {
147
+ "componentProvider": {
148
+ "TerraHeaderInsets": "TerraHeaderInsetsComponentView"
149
+ }
150
+ }
151
+ },
139
152
  "create-react-native-library": {
140
153
  "type": "library",
141
154
  "languages": "js",
@@ -0,0 +1,7 @@
1
+ module.exports = {
2
+ dependency: {
3
+ platforms: {
4
+ android: null,
5
+ },
6
+ },
7
+ };
@@ -1,14 +1,16 @@
1
- import type { ComponentProps, ReactNode } from "react";
1
+ import { type ComponentProps, type ReactNode, useState } from "react";
2
2
  import { Text, View } from "react-native";
3
3
 
4
4
  import Animated from "react-native-reanimated";
5
5
  import { StyleSheet, useUnistyles } from "react-native-unistyles";
6
6
 
7
7
  import { FONT_WEIGHT_VALUE } from "#utils/typography";
8
+ import { resolveScreenPadding } from "../../../theme/screen-padding";
8
9
  import { Toolbar } from "../../toolbar";
9
10
  import { HeaderDismissButton, type HeaderDismissProps } from "../header-buttons";
10
11
  import { isCustomTitle, isTextTitle } from "../utils";
11
12
  import { HeaderSurface, type HeaderSurfaceProps } from "./HeaderSurface";
13
+ import { HeaderWindowInsets } from "./HeaderWindowInsets";
12
14
 
13
15
  interface HeaderBarProps extends HeaderDismissProps {
14
16
  title?: ReactNode;
@@ -34,13 +36,15 @@ export function HeaderBar({
34
36
  onDismiss,
35
37
  }: HeaderBarProps) {
36
38
  const { theme } = useUnistyles();
39
+ const [windowInsets, setWindowInsets] = useState({ left: 0, right: 0 });
37
40
  styles.useVariants({ titleAlignment });
38
41
  const dismiss = (
39
42
  <HeaderDismissButton dismissAction={dismissAction} navigation={navigation} onDismiss={onDismiss} />
40
43
  );
41
44
  return (
42
- <View style={styles.bar}>
45
+ <View style={[styles.bar, styles.windowInsets(windowInsets.left, windowInsets.right)]}>
43
46
  <HeaderSurface color={color} animatedStyle={surfaceStyle} />
47
+ <HeaderWindowInsets onInsetsChange={setWindowInsets} />
44
48
  {(leading != null || dismissAction === "back") && (
45
49
  <Toolbar>
46
50
  {dismissAction === "back" && dismiss}
@@ -48,7 +52,11 @@ export function HeaderBar({
48
52
  </Toolbar>
49
53
  )}
50
54
  <Animated.View
51
- style={[styles.titleContainer, titleStyle]}
55
+ style={[
56
+ styles.titleContainer,
57
+ styles.titleInsets(windowInsets.left, windowInsets.right, titleAlignment),
58
+ titleStyle,
59
+ ]}
52
60
  pointerEvents={isCustomTitle(title) ? "box-none" : "none"}
53
61
  >
54
62
  {isTextTitle(title)
@@ -72,7 +80,13 @@ export function HeaderBar({
72
80
  );
73
81
  }
74
82
 
75
- const styles = StyleSheet.create((theme) => ({
83
+ const styles = StyleSheet.create((theme, runtime) => ({
84
+ windowInsets: (left: number, right: number) => ({
85
+ paddingLeft: Math.max(resolveScreenPadding(theme, runtime.breakpoint).x, left),
86
+ paddingRight: Math.max(resolveScreenPadding(theme, runtime.breakpoint).x, right),
87
+ }),
88
+ titleInsets: (left: number, right: number, alignment: "center" | "left") =>
89
+ alignment === "center" ? { left, right } : {},
76
90
  bar: {
77
91
  height: theme.layout.header.height,
78
92
  flexDirection: "row",
@@ -0,0 +1,24 @@
1
+ import { Platform } from "react-native";
2
+
3
+ import { StyleSheet } from "react-native-unistyles";
4
+
5
+ import TerraHeaderInsets from "../../../specs/TerraHeaderInsetsNativeComponent";
6
+ import type { HeaderWindowInsetsProps } from "./HeaderWindowInsets";
7
+
8
+ export function HeaderWindowInsets({ onInsetsChange }: HeaderWindowInsetsProps) {
9
+ if (Platform.OS !== "ios" || !Platform.isPad || Number.parseInt(String(Platform.Version), 10) < 26)
10
+ return null;
11
+
12
+ return (
13
+ <TerraHeaderInsets
14
+ style={styles.probe}
15
+ pointerEvents="none"
16
+ accessible={false}
17
+ onInsetsChange={({ nativeEvent }) => onInsetsChange(nativeEvent)}
18
+ />
19
+ );
20
+ }
21
+
22
+ const styles = StyleSheet.create(() => ({
23
+ probe: { position: "absolute", top: 0, left: 0, right: 0, bottom: 0 },
24
+ }));
@@ -0,0 +1,8 @@
1
+ export interface HeaderWindowInsetsProps {
2
+ onInsetsChange: (insets: { left: number; right: number }) => void;
3
+ }
4
+
5
+ /** Only iPadOS needs the native window-control measurement. */
6
+ export function HeaderWindowInsets(_: HeaderWindowInsetsProps) {
7
+ return null;
8
+ }
@@ -0,0 +1,12 @@
1
+ import type { CodegenTypes, ViewProps } from "react-native";
2
+ import { codegenNativeComponent } from "react-native";
3
+
4
+ export interface NativeProps extends ViewProps {
5
+ onInsetsChange?: CodegenTypes.DirectEventHandler<
6
+ Readonly<{ left: CodegenTypes.Double; right: CodegenTypes.Double }>
7
+ >;
8
+ }
9
+
10
+ export default codegenNativeComponent<NativeProps>("TerraHeaderInsets", {
11
+ excludedPlatforms: ["android"],
12
+ });