@react-navigation/elements 2.0.4 → 2.1.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.
@@ -165,7 +165,6 @@ export function Header(props: Props) {
165
165
  borderTopStartRadius,
166
166
  borderTopWidth,
167
167
  borderWidth,
168
- // @ts-expect-error: web support for shadow
169
168
  boxShadow,
170
169
  elevation,
171
170
  shadowColor,
@@ -207,7 +206,6 @@ export function Header(props: Props) {
207
206
  borderTopStartRadius,
208
207
  borderTopWidth,
209
208
  borderWidth,
210
- // @ts-expect-error: boxShadow is only for Web
211
209
  boxShadow,
212
210
  elevation,
213
211
  shadowColor,
@@ -17,11 +17,11 @@ import closeIcon from '../assets/close-icon.png';
17
17
  import searchIcon from '../assets/search-icon.png';
18
18
  import { PlatformPressable } from '../PlatformPressable';
19
19
  import { Text } from '../Text';
20
- import type { HeaderOptions } from '../types';
20
+ import type { HeaderSearchBarOptions, HeaderSearchBarRef } from '../types';
21
21
  import { HeaderButton } from './HeaderButton';
22
22
  import { HeaderIcon } from './HeaderIcon';
23
23
 
24
- type Props = HeaderOptions['headerSearchBarOptions'] & {
24
+ type Props = Omit<HeaderSearchBarOptions, 'ref'> & {
25
25
  visible: boolean;
26
26
  onClose: () => void;
27
27
  style?: Animated.WithAnimatedValue<StyleProp<ViewStyle>>;
@@ -34,17 +34,20 @@ const INPUT_TYPE_TO_MODE = {
34
34
  email: 'email',
35
35
  } as const;
36
36
 
37
- export function HeaderSearchBar({
38
- visible,
39
- inputType,
40
- autoFocus = true,
41
- placeholder = 'Search',
42
- cancelButtonText = 'Cancel',
43
- onChangeText,
44
- onClose,
45
- style,
46
- ...rest
47
- }: Props) {
37
+ function HeaderSearchBarInternal(
38
+ {
39
+ visible,
40
+ inputType,
41
+ autoFocus = true,
42
+ placeholder = 'Search',
43
+ cancelButtonText = 'Cancel',
44
+ onChangeText,
45
+ onClose,
46
+ style,
47
+ ...rest
48
+ }: Props,
49
+ ref: React.ForwardedRef<HeaderSearchBarRef>
50
+ ) {
48
51
  const navigation = useNavigation();
49
52
  const { dark, colors, fonts } = useTheme();
50
53
  const [value, setValue] = React.useState('');
@@ -98,22 +101,46 @@ export function HeaderSearchBar({
98
101
  });
99
102
  }, [clearVisibleAnim, hasText]);
100
103
 
101
- const onClear = React.useCallback(() => {
104
+ const clearText = React.useCallback(() => {
102
105
  inputRef.current?.clear();
103
106
  inputRef.current?.focus();
104
107
  setValue('');
108
+ }, []);
109
+
110
+ const onClear = React.useCallback(() => {
111
+ clearText();
105
112
  // FIXME: figure out how to create a SyntheticEvent
106
113
  // @ts-expect-error: we don't have the native event here
107
114
  onChangeText?.({ nativeEvent: { text: '' } });
108
- }, [onChangeText]);
115
+ }, [clearText, onChangeText]);
116
+
117
+ const cancelSearch = React.useCallback(() => {
118
+ onClear();
119
+ onClose();
120
+ }, [onClear, onClose]);
109
121
 
110
122
  React.useEffect(
111
- () =>
112
- navigation?.addListener('blur', () => {
113
- onClear();
114
- onClose();
115
- }),
116
- [navigation, onClear, onClose]
123
+ () => navigation?.addListener('blur', cancelSearch),
124
+ [cancelSearch, navigation]
125
+ );
126
+
127
+ React.useImperativeHandle(
128
+ ref,
129
+ () => ({
130
+ focus: () => {
131
+ inputRef.current?.focus();
132
+ },
133
+ blur: () => {
134
+ inputRef.current?.blur();
135
+ },
136
+ setText: (text: string) => {
137
+ inputRef.current?.setNativeProps({ text });
138
+ setValue(text);
139
+ },
140
+ clearText,
141
+ cancelSearch,
142
+ }),
143
+ [cancelSearch, clearText]
117
144
  );
118
145
 
119
146
  if (!visible && !rendered) {
@@ -189,13 +216,7 @@ export function HeaderSearchBar({
189
216
  </HeaderButton>
190
217
  ) : null}
191
218
  {Platform.OS === 'ios' ? (
192
- <PlatformPressable
193
- onPress={() => {
194
- onClear();
195
- onClose();
196
- }}
197
- style={styles.cancelButton}
198
- >
219
+ <PlatformPressable onPress={cancelSearch} style={styles.cancelButton}>
199
220
  <Text
200
221
  style={[
201
222
  fonts.regular,
@@ -281,3 +302,5 @@ const styles = StyleSheet.create({
281
302
  },
282
303
  }),
283
304
  });
305
+
306
+ export const HeaderSearchBar = React.forwardRef(HeaderSearchBarInternal);
package/src/types.tsx CHANGED
@@ -11,7 +11,26 @@ export type HeaderBackButtonDisplayMode = 'default' | 'generic' | 'minimal';
11
11
 
12
12
  export type Layout = { width: number; height: number };
13
13
 
14
- type HeaderSearchBarOptions = {
14
+ export type HeaderSearchBarRef = {
15
+ focus: () => void;
16
+ blur: () => void;
17
+ setText: (text: string) => void;
18
+ clearText: () => void;
19
+ cancelSearch: () => void;
20
+ };
21
+
22
+ export type HeaderSearchBarOptions = {
23
+ /**
24
+ * Ref to imperatively update the search bar.
25
+ *
26
+ * Supported operations:
27
+ * - `focus` - focuses the search bar
28
+ * - `blur` - removes focus from the search bar
29
+ * - `setText` - sets the search bar's content to given value
30
+ * - `clearText` - removes any text present in the search bar input field
31
+ * - `cancelSearch` - cancel the search and close the search bar
32
+ */
33
+ ref?: React.Ref<HeaderSearchBarRef>;
15
34
  /**
16
35
  * The auto-capitalization behavior
17
36
  */