@react-native-ohos/elements 2.3.9-rc.1

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 (222) hide show
  1. package/LICENSE +21 -0
  2. package/README.OpenSource +11 -0
  3. package/README.md +9 -0
  4. package/lib/module/Background.js +22 -0
  5. package/lib/module/Background.js.map +1 -0
  6. package/lib/module/Button.js +106 -0
  7. package/lib/module/Button.js.map +1 -0
  8. package/lib/module/Header/Header.js +338 -0
  9. package/lib/module/Header/Header.js.map +1 -0
  10. package/lib/module/Header/HeaderBackButton.js +188 -0
  11. package/lib/module/Header/HeaderBackButton.js.map +1 -0
  12. package/lib/module/Header/HeaderBackContext.js +5 -0
  13. package/lib/module/Header/HeaderBackContext.js.map +1 -0
  14. package/lib/module/Header/HeaderBackground.js +47 -0
  15. package/lib/module/Header/HeaderBackground.js.map +1 -0
  16. package/lib/module/Header/HeaderButton.js +56 -0
  17. package/lib/module/Header/HeaderButton.js.map +1 -0
  18. package/lib/module/Header/HeaderHeightContext.js +5 -0
  19. package/lib/module/Header/HeaderHeightContext.js.map +1 -0
  20. package/lib/module/Header/HeaderIcon.js +38 -0
  21. package/lib/module/Header/HeaderIcon.js.map +1 -0
  22. package/lib/module/Header/HeaderSearchBar.js +288 -0
  23. package/lib/module/Header/HeaderSearchBar.js.map +1 -0
  24. package/lib/module/Header/HeaderShownContext.js +5 -0
  25. package/lib/module/Header/HeaderShownContext.js.map +1 -0
  26. package/lib/module/Header/HeaderTitle.js +41 -0
  27. package/lib/module/Header/HeaderTitle.js.map +1 -0
  28. package/lib/module/Header/getDefaultHeaderHeight.js +45 -0
  29. package/lib/module/Header/getDefaultHeaderHeight.js.map +1 -0
  30. package/lib/module/Header/getHeaderTitle.js +6 -0
  31. package/lib/module/Header/getHeaderTitle.js.map +1 -0
  32. package/lib/module/Header/useHeaderHeight.js +12 -0
  33. package/lib/module/Header/useHeaderHeight.js.map +1 -0
  34. package/lib/module/Label/Label.js +25 -0
  35. package/lib/module/Label/Label.js.map +1 -0
  36. package/lib/module/Label/getLabel.js +6 -0
  37. package/lib/module/Label/getLabel.js.map +1 -0
  38. package/lib/module/MaskedView.android.js +4 -0
  39. package/lib/module/MaskedView.android.js.map +1 -0
  40. package/lib/module/MaskedView.ios.js +4 -0
  41. package/lib/module/MaskedView.ios.js.map +1 -0
  42. package/lib/module/MaskedView.js +12 -0
  43. package/lib/module/MaskedView.js.map +1 -0
  44. package/lib/module/MaskedViewNative.js +30 -0
  45. package/lib/module/MaskedViewNative.js.map +1 -0
  46. package/lib/module/MissingIcon.js +24 -0
  47. package/lib/module/MissingIcon.js.map +1 -0
  48. package/lib/module/PlatformPressable.js +141 -0
  49. package/lib/module/PlatformPressable.js.map +1 -0
  50. package/lib/module/ResourceSavingView.js +57 -0
  51. package/lib/module/ResourceSavingView.js.map +1 -0
  52. package/lib/module/SafeAreaProviderCompat.js +58 -0
  53. package/lib/module/SafeAreaProviderCompat.js.map +1 -0
  54. package/lib/module/Screen.js +83 -0
  55. package/lib/module/Screen.js.map +1 -0
  56. package/lib/module/Text.js +22 -0
  57. package/lib/module/Text.js.map +1 -0
  58. package/lib/module/assets/back-icon-mask.png +0 -0
  59. package/lib/module/assets/back-icon.png +0 -0
  60. package/lib/module/assets/back-icon@1x.android.png +0 -0
  61. package/lib/module/assets/back-icon@1x.ios.png +0 -0
  62. package/lib/module/assets/back-icon@2x.android.png +0 -0
  63. package/lib/module/assets/back-icon@2x.ios.png +0 -0
  64. package/lib/module/assets/back-icon@3x.android.png +0 -0
  65. package/lib/module/assets/back-icon@3x.ios.png +0 -0
  66. package/lib/module/assets/back-icon@4x.android.png +0 -0
  67. package/lib/module/assets/back-icon@4x.ios.png +0 -0
  68. package/lib/module/assets/clear-icon.png +0 -0
  69. package/lib/module/assets/clear-icon@1x.png +0 -0
  70. package/lib/module/assets/clear-icon@2x.png +0 -0
  71. package/lib/module/assets/clear-icon@3x.png +0 -0
  72. package/lib/module/assets/clear-icon@4x.png +0 -0
  73. package/lib/module/assets/close-icon.png +0 -0
  74. package/lib/module/assets/close-icon@1x.png +0 -0
  75. package/lib/module/assets/close-icon@2x.png +0 -0
  76. package/lib/module/assets/close-icon@3x.png +0 -0
  77. package/lib/module/assets/close-icon@4x.png +0 -0
  78. package/lib/module/assets/search-icon.png +0 -0
  79. package/lib/module/assets/search-icon@1x.android.png +0 -0
  80. package/lib/module/assets/search-icon@1x.ios.png +0 -0
  81. package/lib/module/assets/search-icon@2x.android.png +0 -0
  82. package/lib/module/assets/search-icon@2x.ios.png +0 -0
  83. package/lib/module/assets/search-icon@3x.android.png +0 -0
  84. package/lib/module/assets/search-icon@3x.ios.png +0 -0
  85. package/lib/module/assets/search-icon@4x.android.png +0 -0
  86. package/lib/module/assets/search-icon@4x.ios.png +0 -0
  87. package/lib/module/getDefaultSidebarWidth.js +18 -0
  88. package/lib/module/getDefaultSidebarWidth.js.map +1 -0
  89. package/lib/module/getNamedContext.js +17 -0
  90. package/lib/module/getNamedContext.js.map +1 -0
  91. package/lib/module/index.js +32 -0
  92. package/lib/module/index.js.map +1 -0
  93. package/lib/module/package.json +1 -0
  94. package/lib/module/types.js +4 -0
  95. package/lib/module/types.js.map +1 -0
  96. package/lib/typescript/package.json +1 -0
  97. package/lib/typescript/src/Background.d.ts +9 -0
  98. package/lib/typescript/src/Background.d.ts.map +1 -0
  99. package/lib/typescript/src/Button.d.ts +13 -0
  100. package/lib/typescript/src/Button.d.ts.map +1 -0
  101. package/lib/typescript/src/Header/Header.d.ts +31 -0
  102. package/lib/typescript/src/Header/Header.d.ts.map +1 -0
  103. package/lib/typescript/src/Header/HeaderBackButton.d.ts +3 -0
  104. package/lib/typescript/src/Header/HeaderBackButton.d.ts.map +1 -0
  105. package/lib/typescript/src/Header/HeaderBackContext.d.ts +5 -0
  106. package/lib/typescript/src/Header/HeaderBackContext.d.ts.map +1 -0
  107. package/lib/typescript/src/Header/HeaderBackground.d.ts +9 -0
  108. package/lib/typescript/src/Header/HeaderBackground.d.ts.map +1 -0
  109. package/lib/typescript/src/Header/HeaderButton.d.ts +3 -0
  110. package/lib/typescript/src/Header/HeaderButton.d.ts.map +1 -0
  111. package/lib/typescript/src/Header/HeaderHeightContext.d.ts +2 -0
  112. package/lib/typescript/src/Header/HeaderHeightContext.d.ts.map +1 -0
  113. package/lib/typescript/src/Header/HeaderIcon.d.ts +5 -0
  114. package/lib/typescript/src/Header/HeaderIcon.d.ts.map +1 -0
  115. package/lib/typescript/src/Header/HeaderSearchBar.d.ts +10 -0
  116. package/lib/typescript/src/Header/HeaderSearchBar.d.ts.map +1 -0
  117. package/lib/typescript/src/Header/HeaderShownContext.d.ts +2 -0
  118. package/lib/typescript/src/Header/HeaderShownContext.d.ts.map +1 -0
  119. package/lib/typescript/src/Header/HeaderTitle.d.ts +9 -0
  120. package/lib/typescript/src/Header/HeaderTitle.d.ts.map +1 -0
  121. package/lib/typescript/src/Header/getDefaultHeaderHeight.d.ts +3 -0
  122. package/lib/typescript/src/Header/getDefaultHeaderHeight.d.ts.map +1 -0
  123. package/lib/typescript/src/Header/getHeaderTitle.d.ts +6 -0
  124. package/lib/typescript/src/Header/getHeaderTitle.d.ts.map +1 -0
  125. package/lib/typescript/src/Header/useHeaderHeight.d.ts +2 -0
  126. package/lib/typescript/src/Header/useHeaderHeight.d.ts.map +1 -0
  127. package/lib/typescript/src/Label/Label.d.ts +9 -0
  128. package/lib/typescript/src/Label/Label.d.ts.map +1 -0
  129. package/lib/typescript/src/Label/getLabel.d.ts +5 -0
  130. package/lib/typescript/src/Label/getLabel.d.ts.map +1 -0
  131. package/lib/typescript/src/MaskedView.android.d.ts +2 -0
  132. package/lib/typescript/src/MaskedView.android.d.ts.map +1 -0
  133. package/lib/typescript/src/MaskedView.d.ts +11 -0
  134. package/lib/typescript/src/MaskedView.d.ts.map +1 -0
  135. package/lib/typescript/src/MaskedView.ios.d.ts +2 -0
  136. package/lib/typescript/src/MaskedView.ios.d.ts.map +1 -0
  137. package/lib/typescript/src/MaskedViewNative.d.ts +11 -0
  138. package/lib/typescript/src/MaskedViewNative.d.ts.map +1 -0
  139. package/lib/typescript/src/MissingIcon.d.ts +9 -0
  140. package/lib/typescript/src/MissingIcon.d.ts.map +1 -0
  141. package/lib/typescript/src/PlatformPressable.d.ts +21 -0
  142. package/lib/typescript/src/PlatformPressable.d.ts.map +1 -0
  143. package/lib/typescript/src/ResourceSavingView.d.ts +10 -0
  144. package/lib/typescript/src/ResourceSavingView.d.ts.map +1 -0
  145. package/lib/typescript/src/SafeAreaProviderCompat.d.ts +12 -0
  146. package/lib/typescript/src/SafeAreaProviderCompat.d.ts.map +1 -0
  147. package/lib/typescript/src/Screen.d.ts +18 -0
  148. package/lib/typescript/src/Screen.d.ts.map +1 -0
  149. package/lib/typescript/src/Text.d.ts +3 -0
  150. package/lib/typescript/src/Text.d.ts.map +1 -0
  151. package/lib/typescript/src/__tests__/PlatformPressable.test.d.ts +2 -0
  152. package/lib/typescript/src/__tests__/PlatformPressable.test.d.ts.map +1 -0
  153. package/lib/typescript/src/getDefaultSidebarWidth.d.ts +4 -0
  154. package/lib/typescript/src/getDefaultSidebarWidth.d.ts.map +1 -0
  155. package/lib/typescript/src/getNamedContext.d.ts +6 -0
  156. package/lib/typescript/src/getNamedContext.d.ts.map +1 -0
  157. package/lib/typescript/src/index.d.ts +25 -0
  158. package/lib/typescript/src/index.d.ts.map +1 -0
  159. package/lib/typescript/src/types.d.ts +325 -0
  160. package/lib/typescript/src/types.d.ts.map +1 -0
  161. package/package.json +83 -0
  162. package/src/Background.tsx +24 -0
  163. package/src/Button.tsx +120 -0
  164. package/src/Header/Header.tsx +450 -0
  165. package/src/Header/HeaderBackButton.tsx +249 -0
  166. package/src/Header/HeaderBackContext.tsx +5 -0
  167. package/src/Header/HeaderBackground.tsx +60 -0
  168. package/src/Header/HeaderButton.tsx +55 -0
  169. package/src/Header/HeaderHeightContext.tsx +6 -0
  170. package/src/Header/HeaderIcon.tsx +32 -0
  171. package/src/Header/HeaderSearchBar.tsx +323 -0
  172. package/src/Header/HeaderShownContext.tsx +3 -0
  173. package/src/Header/HeaderTitle.tsx +48 -0
  174. package/src/Header/getDefaultHeaderHeight.tsx +54 -0
  175. package/src/Header/getHeaderTitle.tsx +12 -0
  176. package/src/Header/useHeaderHeight.tsx +15 -0
  177. package/src/Label/Label.tsx +31 -0
  178. package/src/Label/getLabel.tsx +10 -0
  179. package/src/MaskedView.android.tsx +1 -0
  180. package/src/MaskedView.ios.tsx +1 -0
  181. package/src/MaskedView.tsx +13 -0
  182. package/src/MaskedViewNative.tsx +33 -0
  183. package/src/MissingIcon.tsx +19 -0
  184. package/src/PlatformPressable.tsx +196 -0
  185. package/src/ResourceSavingView.tsx +76 -0
  186. package/src/SafeAreaProviderCompat.tsx +61 -0
  187. package/src/Screen.tsx +123 -0
  188. package/src/Text.tsx +14 -0
  189. package/src/__tests__/PlatformPressable.test.tsx +81 -0
  190. package/src/assets/back-icon-mask.png +0 -0
  191. package/src/assets/back-icon.png +0 -0
  192. package/src/assets/back-icon@1x.android.png +0 -0
  193. package/src/assets/back-icon@1x.ios.png +0 -0
  194. package/src/assets/back-icon@2x.android.png +0 -0
  195. package/src/assets/back-icon@2x.ios.png +0 -0
  196. package/src/assets/back-icon@3x.android.png +0 -0
  197. package/src/assets/back-icon@3x.ios.png +0 -0
  198. package/src/assets/back-icon@4x.android.png +0 -0
  199. package/src/assets/back-icon@4x.ios.png +0 -0
  200. package/src/assets/clear-icon.png +0 -0
  201. package/src/assets/clear-icon@1x.png +0 -0
  202. package/src/assets/clear-icon@2x.png +0 -0
  203. package/src/assets/clear-icon@3x.png +0 -0
  204. package/src/assets/clear-icon@4x.png +0 -0
  205. package/src/assets/close-icon.png +0 -0
  206. package/src/assets/close-icon@1x.png +0 -0
  207. package/src/assets/close-icon@2x.png +0 -0
  208. package/src/assets/close-icon@3x.png +0 -0
  209. package/src/assets/close-icon@4x.png +0 -0
  210. package/src/assets/search-icon.png +0 -0
  211. package/src/assets/search-icon@1x.android.png +0 -0
  212. package/src/assets/search-icon@1x.ios.png +0 -0
  213. package/src/assets/search-icon@2x.android.png +0 -0
  214. package/src/assets/search-icon@2x.ios.png +0 -0
  215. package/src/assets/search-icon@3x.android.png +0 -0
  216. package/src/assets/search-icon@3x.ios.png +0 -0
  217. package/src/assets/search-icon@4x.android.png +0 -0
  218. package/src/assets/search-icon@4x.ios.png +0 -0
  219. package/src/getDefaultSidebarWidth.tsx +15 -0
  220. package/src/getNamedContext.tsx +30 -0
  221. package/src/index.tsx +38 -0
  222. package/src/types.tsx +338 -0
@@ -0,0 +1,323 @@
1
+ import { useNavigation, useTheme } from '@react-navigation/native';
2
+ import Color from 'color';
3
+ import * as React from 'react';
4
+ import {
5
+ Animated,
6
+ Image,
7
+ Platform,
8
+ type StyleProp,
9
+ StyleSheet,
10
+ TextInput,
11
+ View,
12
+ type ViewStyle,
13
+ } from 'react-native';
14
+
15
+ import clearIcon from '../assets/clear-icon.png';
16
+ import closeIcon from '../assets/close-icon.png';
17
+ import searchIcon from '../assets/search-icon.png';
18
+ import { PlatformPressable } from '../PlatformPressable';
19
+ import { Text } from '../Text';
20
+ import type { HeaderSearchBarOptions, HeaderSearchBarRef } from '../types';
21
+ import { HeaderButton } from './HeaderButton';
22
+ import { HeaderIcon } from './HeaderIcon';
23
+
24
+ type Props = Omit<HeaderSearchBarOptions, 'ref'> & {
25
+ visible: boolean;
26
+ onClose: () => void;
27
+ tintColor?: string;
28
+ style?: Animated.WithAnimatedValue<StyleProp<ViewStyle>>;
29
+ };
30
+
31
+ const INPUT_TYPE_TO_MODE = {
32
+ text: 'text',
33
+ number: 'numeric',
34
+ phone: 'tel',
35
+ email: 'email',
36
+ } as const;
37
+
38
+ const useNativeDriver = Platform.OS !== 'web';
39
+
40
+ function HeaderSearchBarInternal(
41
+ {
42
+ visible,
43
+ inputType,
44
+ autoFocus = true,
45
+ placeholder = 'Search',
46
+ cancelButtonText = 'Cancel',
47
+ enterKeyHint = 'search',
48
+ onChangeText,
49
+ onClose,
50
+ tintColor,
51
+ style,
52
+ ...rest
53
+ }: Props,
54
+ ref: React.ForwardedRef<HeaderSearchBarRef>
55
+ ) {
56
+ const navigation = useNavigation();
57
+ const { dark, colors, fonts } = useTheme();
58
+ const [value, setValue] = React.useState('');
59
+ const [rendered, setRendered] = React.useState(visible);
60
+ const [visibleAnim] = React.useState(
61
+ () => new Animated.Value(visible ? 1 : 0)
62
+ );
63
+ const [clearVisibleAnim] = React.useState(() => new Animated.Value(0));
64
+
65
+ const visibleValueRef = React.useRef(visible);
66
+ const clearVisibleValueRef = React.useRef(false);
67
+ const inputRef = React.useRef<TextInput>(null);
68
+
69
+ React.useEffect(() => {
70
+ // Avoid act warning in tests just by rendering header
71
+ if (visible === visibleValueRef.current) {
72
+ return;
73
+ }
74
+
75
+ Animated.timing(visibleAnim, {
76
+ toValue: visible ? 1 : 0,
77
+ duration: 100,
78
+ useNativeDriver,
79
+ }).start(({ finished }) => {
80
+ if (finished) {
81
+ setRendered(visible);
82
+ visibleValueRef.current = visible;
83
+ }
84
+ });
85
+
86
+ return () => {
87
+ visibleAnim.stopAnimation();
88
+ };
89
+ }, [visible, visibleAnim]);
90
+
91
+ const hasText = value !== '';
92
+
93
+ React.useEffect(() => {
94
+ if (clearVisibleValueRef.current === hasText) {
95
+ return;
96
+ }
97
+
98
+ Animated.timing(clearVisibleAnim, {
99
+ toValue: hasText ? 1 : 0,
100
+ duration: 100,
101
+ useNativeDriver,
102
+ }).start(({ finished }) => {
103
+ if (finished) {
104
+ clearVisibleValueRef.current = hasText;
105
+ }
106
+ });
107
+ }, [clearVisibleAnim, hasText]);
108
+
109
+ const clearText = React.useCallback(() => {
110
+ inputRef.current?.clear();
111
+ inputRef.current?.focus();
112
+ setValue('');
113
+ }, []);
114
+
115
+ const onClear = React.useCallback(() => {
116
+ clearText();
117
+ // FIXME: figure out how to create a SyntheticEvent
118
+ // @ts-expect-error: we don't have the native event here
119
+ onChangeText?.({ nativeEvent: { text: '' } });
120
+ }, [clearText, onChangeText]);
121
+
122
+ const cancelSearch = React.useCallback(() => {
123
+ onClear();
124
+ onClose();
125
+ }, [onClear, onClose]);
126
+
127
+ React.useEffect(
128
+ () => navigation?.addListener('blur', cancelSearch),
129
+ [cancelSearch, navigation]
130
+ );
131
+
132
+ React.useImperativeHandle(
133
+ ref,
134
+ () => ({
135
+ focus: () => {
136
+ inputRef.current?.focus();
137
+ },
138
+ blur: () => {
139
+ inputRef.current?.blur();
140
+ },
141
+ setText: (text: string) => {
142
+ inputRef.current?.setNativeProps({ text });
143
+ setValue(text);
144
+ },
145
+ clearText,
146
+ cancelSearch,
147
+ }),
148
+ [cancelSearch, clearText]
149
+ );
150
+
151
+ if (!visible && !rendered) {
152
+ return null;
153
+ }
154
+
155
+ const textColor = tintColor ?? colors.text;
156
+
157
+ return (
158
+ <Animated.View
159
+ pointerEvents={visible ? 'auto' : 'none'}
160
+ accessibilityLiveRegion="polite"
161
+ accessibilityElementsHidden={!visible}
162
+ importantForAccessibility={visible ? 'auto' : 'no-hide-descendants'}
163
+ style={[styles.container, { opacity: visibleAnim }, style]}
164
+ >
165
+ <View style={styles.searchbarContainer}>
166
+ <HeaderIcon
167
+ source={searchIcon}
168
+ tintColor={textColor}
169
+ style={styles.inputSearchIcon}
170
+ />
171
+ <TextInput
172
+ {...rest}
173
+ ref={inputRef}
174
+ onChange={onChangeText}
175
+ onChangeText={setValue}
176
+ autoFocus={autoFocus}
177
+ inputMode={INPUT_TYPE_TO_MODE[inputType ?? 'text']}
178
+ enterKeyHint={enterKeyHint}
179
+ placeholder={placeholder}
180
+ placeholderTextColor={Color(textColor).alpha(0.5).string()}
181
+ cursorColor={colors.primary}
182
+ selectionHandleColor={colors.primary}
183
+ selectionColor={Color(colors.primary).alpha(0.3).string()}
184
+ style={[
185
+ fonts.regular,
186
+ styles.searchbar,
187
+ {
188
+ backgroundColor: Platform.select({
189
+ ios: dark ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)',
190
+ default: 'transparent',
191
+ }),
192
+ color: textColor,
193
+ borderBottomColor: Color(textColor).alpha(0.2).string(),
194
+ },
195
+ ]}
196
+ />
197
+ {Platform.OS === 'ios' ||
198
+ // @ts-ignore
199
+ Platform.OS === 'harmony' ? (
200
+ <PlatformPressable
201
+ onPress={onClear}
202
+ style={[
203
+ {
204
+ opacity: clearVisibleAnim,
205
+ transform: [{ scale: clearVisibleAnim }],
206
+ },
207
+ styles.clearButton,
208
+ ]}
209
+ >
210
+ <Image
211
+ source={clearIcon}
212
+ resizeMode="contain"
213
+ tintColor={textColor}
214
+ style={styles.clearIcon}
215
+ />
216
+ </PlatformPressable>
217
+ ) : null}
218
+ </View>
219
+ {Platform.OS !== 'ios' &&
220
+ // @ts-ignore
221
+ Platform.OS !== 'harmony' ? (
222
+ <HeaderButton
223
+ onPress={() => {
224
+ if (value) {
225
+ onClear();
226
+ } else {
227
+ onClose();
228
+ }
229
+ }}
230
+ style={styles.closeButton}
231
+ >
232
+ <HeaderIcon source={closeIcon} tintColor={textColor} />
233
+ </HeaderButton>
234
+ ) : null}
235
+ {Platform.OS === 'ios' ? (
236
+ <PlatformPressable onPress={cancelSearch} style={styles.cancelButton}>
237
+ <Text
238
+ style={[
239
+ fonts.regular,
240
+ { color: tintColor ?? colors.primary },
241
+ styles.cancelText,
242
+ ]}
243
+ >
244
+ {cancelButtonText}
245
+ </Text>
246
+ </PlatformPressable>
247
+ ) : null}
248
+ </Animated.View>
249
+ );
250
+ }
251
+
252
+ const styles = StyleSheet.create({
253
+ container: {
254
+ flex: 1,
255
+ flexDirection: 'row',
256
+ alignItems: 'stretch',
257
+ },
258
+ inputSearchIcon: {
259
+ position: 'absolute',
260
+ opacity: 0.5,
261
+ left: Platform.select({ ios: 16, default: 4 }),
262
+ top: Platform.select({ ios: -1, default: 17 }),
263
+ ...Platform.select({
264
+ ios: {
265
+ height: 18,
266
+ width: 18,
267
+ },
268
+ default: {},
269
+ }),
270
+ },
271
+ closeButton: {
272
+ position: 'absolute',
273
+ opacity: 0.5,
274
+ right: Platform.select({ ios: 0, default: 8 }),
275
+ top: Platform.select({ ios: -2, default: 17 }),
276
+ },
277
+ clearButton: {
278
+ position: 'absolute',
279
+ right: 0,
280
+ top: -7,
281
+ bottom: 0,
282
+ justifyContent: 'center',
283
+ padding: 8,
284
+ },
285
+ clearIcon: {
286
+ height: 16,
287
+ width: 16,
288
+ opacity: 0.5,
289
+ },
290
+ cancelButton: {
291
+ alignSelf: 'center',
292
+ top: -4,
293
+ },
294
+ cancelText: {
295
+ fontSize: 17,
296
+ marginHorizontal: 12,
297
+ },
298
+ searchbarContainer: {
299
+ flex: 1,
300
+ },
301
+ searchbar: Platform.select({
302
+ ios: {
303
+ flex: 1,
304
+ fontSize: 17,
305
+ paddingHorizontal: 32,
306
+ marginLeft: 16,
307
+ marginTop: -1,
308
+ marginBottom: 4,
309
+ borderRadius: 8,
310
+ },
311
+ default: {
312
+ flex: 1,
313
+ fontSize: 18,
314
+ paddingHorizontal: 36,
315
+ marginRight: 8,
316
+ marginTop: 8,
317
+ marginBottom: 8,
318
+ borderBottomWidth: 1,
319
+ },
320
+ }),
321
+ });
322
+
323
+ export const HeaderSearchBar = React.forwardRef(HeaderSearchBarInternal);
@@ -0,0 +1,3 @@
1
+ import { getNamedContext } from '../getNamedContext';
2
+
3
+ export const HeaderShownContext = getNamedContext('HeaderShownContext', false);
@@ -0,0 +1,48 @@
1
+ import { useTheme } from '@react-navigation/native';
2
+ import {
3
+ Animated,
4
+ Platform,
5
+ type StyleProp,
6
+ StyleSheet,
7
+ type TextProps,
8
+ type TextStyle,
9
+ } from 'react-native';
10
+
11
+ type Props = Omit<TextProps, 'style'> & {
12
+ tintColor?: string;
13
+ children?: string;
14
+ style?: Animated.WithAnimatedValue<StyleProp<TextStyle>>;
15
+ };
16
+
17
+ export function HeaderTitle({ tintColor, style, ...rest }: Props) {
18
+ const { colors, fonts } = useTheme();
19
+
20
+ return (
21
+ <Animated.Text
22
+ accessibilityRole="header"
23
+ aria-level="1"
24
+ numberOfLines={1}
25
+ {...rest}
26
+ style={[
27
+ { color: tintColor === undefined ? colors.text : tintColor },
28
+ Platform.select({ ios: fonts.bold, default: fonts.medium }),
29
+ styles.title,
30
+ style,
31
+ ]}
32
+ />
33
+ );
34
+ }
35
+
36
+ const styles = StyleSheet.create({
37
+ title: Platform.select({
38
+ ios: {
39
+ fontSize: 17,
40
+ },
41
+ android: {
42
+ fontSize: 20,
43
+ },
44
+ default: {
45
+ fontSize: 18,
46
+ },
47
+ }),
48
+ });
@@ -0,0 +1,54 @@
1
+ import { PixelRatio, Platform } from 'react-native';
2
+
3
+ import type { Layout } from '../types';
4
+
5
+ export function getDefaultHeaderHeight(
6
+ layout: Layout,
7
+ modalPresentation: boolean,
8
+ topInset: number
9
+ ): number {
10
+ let headerHeight;
11
+
12
+ // On models with Dynamic Island the status bar height is smaller than the safe area top inset.
13
+ const hasDynamicIsland = Platform.OS === 'ios' && topInset > 50;
14
+ const statusBarHeight = hasDynamicIsland
15
+ ? topInset - (5 + 1 / PixelRatio.get())
16
+ : topInset;
17
+
18
+ const isLandscape = layout.width > layout.height;
19
+
20
+ if (Platform.OS === 'ios') {
21
+ if (Platform.isPad || Platform.isTV) {
22
+ if (modalPresentation) {
23
+ headerHeight = 56;
24
+ } else {
25
+ headerHeight = 50;
26
+ }
27
+ // @ts-ignore
28
+ } else if (Platform.OS === 'harmony') {
29
+ if (isLandscape) {
30
+ headerHeight = 32;
31
+ } else {
32
+ if (modalPresentation) {
33
+ headerHeight = 56;
34
+ } else {
35
+ headerHeight = 44;
36
+ }
37
+ }
38
+ } else {
39
+ if (isLandscape) {
40
+ headerHeight = 32;
41
+ } else {
42
+ if (modalPresentation) {
43
+ headerHeight = 56;
44
+ } else {
45
+ headerHeight = 44;
46
+ }
47
+ }
48
+ }
49
+ } else {
50
+ headerHeight = 64;
51
+ }
52
+
53
+ return headerHeight + statusBarHeight;
54
+ }
@@ -0,0 +1,12 @@
1
+ import type { HeaderOptions } from '../types';
2
+
3
+ export function getHeaderTitle(
4
+ options: { title?: string; headerTitle?: HeaderOptions['headerTitle'] },
5
+ fallback: string
6
+ ): string {
7
+ return typeof options.headerTitle === 'string'
8
+ ? options.headerTitle
9
+ : options.title !== undefined
10
+ ? options.title
11
+ : fallback;
12
+ }
@@ -0,0 +1,15 @@
1
+ import * as React from 'react';
2
+
3
+ import { HeaderHeightContext } from './HeaderHeightContext';
4
+
5
+ export function useHeaderHeight() {
6
+ const height = React.useContext(HeaderHeightContext);
7
+
8
+ if (height === undefined) {
9
+ throw new Error(
10
+ "Couldn't find the header height. Are you inside a screen in a navigator with a header?"
11
+ );
12
+ }
13
+
14
+ return height;
15
+ }
@@ -0,0 +1,31 @@
1
+ import {
2
+ type StyleProp,
3
+ StyleSheet,
4
+ type TextProps,
5
+ type TextStyle,
6
+ } from 'react-native';
7
+
8
+ import { Text } from '../Text';
9
+
10
+ type Props = Omit<TextProps, 'style'> & {
11
+ tintColor?: string;
12
+ children?: string;
13
+ style?: StyleProp<TextStyle>;
14
+ };
15
+
16
+ export function Label({ tintColor, style, ...rest }: Props) {
17
+ return (
18
+ <Text
19
+ numberOfLines={1}
20
+ {...rest}
21
+ style={[styles.label, tintColor != null && { color: tintColor }, style]}
22
+ />
23
+ );
24
+ }
25
+
26
+ const styles = StyleSheet.create({
27
+ label: {
28
+ textAlign: 'center',
29
+ backgroundColor: 'transparent',
30
+ },
31
+ });
@@ -0,0 +1,10 @@
1
+ export function getLabel(
2
+ options: { label?: string; title?: string },
3
+ fallback: string
4
+ ): string {
5
+ return options.label !== undefined
6
+ ? options.label
7
+ : options.title !== undefined
8
+ ? options.title
9
+ : fallback;
10
+ }
@@ -0,0 +1 @@
1
+ export { MaskedView } from './MaskedViewNative';
@@ -0,0 +1 @@
1
+ export { MaskedView } from './MaskedViewNative';
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Use a stub for MaskedView on all Platforms that don't support it.
3
+ */
4
+ import type * as React from 'react';
5
+
6
+ type Props = {
7
+ maskElement: React.ReactElement;
8
+ children: React.ReactElement;
9
+ };
10
+
11
+ export function MaskedView({ children }: Props) {
12
+ return children;
13
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The native MaskedView that we explicitly re-export for supported platforms: Android, iOS.
3
+ */
4
+ import * as React from 'react';
5
+ import { UIManager } from 'react-native';
6
+
7
+ type MaskedViewType =
8
+ typeof import('@react-native-masked-view/masked-view').default;
9
+
10
+ type Props = React.ComponentProps<MaskedViewType> & {
11
+ children: React.ReactElement;
12
+ };
13
+
14
+ let RNCMaskedView: MaskedViewType | undefined;
15
+
16
+ try {
17
+ // Add try/catch to support usage even if it's not installed, since it's optional.
18
+ // Newer versions of Metro will handle it properly.
19
+ RNCMaskedView = require('@react-native-masked-view/masked-view').default;
20
+ } catch (e) {
21
+ // Ignore
22
+ }
23
+
24
+ const isMaskedViewAvailable =
25
+ UIManager.getViewManagerConfig('RNCMaskedView') != null;
26
+
27
+ export function MaskedView({ children, ...rest }: Props) {
28
+ if (isMaskedViewAvailable && RNCMaskedView) {
29
+ return <RNCMaskedView {...rest}>{children}</RNCMaskedView>;
30
+ }
31
+
32
+ return children;
33
+ }
@@ -0,0 +1,19 @@
1
+ import { type StyleProp, StyleSheet, type TextStyle } from 'react-native';
2
+
3
+ import { Text } from './Text';
4
+
5
+ type Props = {
6
+ color?: string;
7
+ size?: number;
8
+ style?: StyleProp<TextStyle>;
9
+ };
10
+
11
+ export function MissingIcon({ color, size, style }: Props) {
12
+ return <Text style={[styles.icon, { color, fontSize: size }, style]}>⏷</Text>;
13
+ }
14
+
15
+ const styles = StyleSheet.create({
16
+ icon: {
17
+ backgroundColor: 'transparent',
18
+ },
19
+ });