@coinbase/ui-mobile-playground 4.5.7 → 4.5.8

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/CHANGELOG.md CHANGED
@@ -8,6 +8,12 @@ All notable changes to this project will be documented in this file.
8
8
 
9
9
  <!-- template-start -->
10
10
 
11
+ ## 4.5.8 (12/1/2025 PST)
12
+
13
+ #### 🐞 Fixes
14
+
15
+ - Chore: QOL improvements for searching/navigating example component routes. [[#199](https://github.com/coinbase/cds/pull/199)]
16
+
11
17
  ## 4.5.7 (11/19/2025 PST)
12
18
 
13
19
  #### 🐞 Fixes
@@ -1 +1 @@
1
- {"version":3,"file":"ExamplesListScreen.d.ts","sourceRoot":"","sources":["../../src/components/ExamplesListScreen.tsx"],"names":[],"mappings":"AAeA,wBAAgB,kBAAkB,4CAkDjC"}
1
+ {"version":3,"file":"ExamplesListScreen.d.ts","sourceRoot":"","sources":["../../src/components/ExamplesListScreen.tsx"],"names":[],"mappings":"AAeA,wBAAgB,kBAAkB,4CAgDjC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useExampleNavigatorProps.d.ts","sourceRoot":"","sources":["../../src/components/useExampleNavigatorProps.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAInD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAUnE,OAAO,KAAK,EAAoB,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAKxF,KAAK,+BAA+B,GAAG;IACrC,cAAc,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,CAAC;CACpE,CAAC;AASF,wBAAgB,wBAAwB,CAAC,EAAE,cAAc,EAAE,EAAE,+BAA+B;;;EAsH3F"}
1
+ {"version":3,"file":"useExampleNavigatorProps.d.ts","sourceRoot":"","sources":["../../src/components/useExampleNavigatorProps.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAGnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAUnE,OAAO,KAAK,EAAoB,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAKxF,KAAK,+BAA+B,GAAG;IACrC,cAAc,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,CAAC;CACpE,CAAC;AAIF,wBAAgB,wBAAwB,CAAC,EAAE,cAAc,EAAE,EAAE,+BAA+B;;;EA+G3F"}
@@ -4,7 +4,7 @@ import { ListCell } from '@coinbase/cds-mobile/cells/ListCell';
4
4
  import { Box } from '@coinbase/cds-mobile/layout/Box';
5
5
  import { useNavigation, useRoute } from '@react-navigation/native';
6
6
  import includes from 'lodash/includes';
7
- import { SearchFilterContext, SetSearchFilterContext } from './ExamplesSearchProvider';
7
+ import { SearchFilterContext } from './ExamplesSearchProvider';
8
8
  import { keyToRouteName } from './keyToRouteName';
9
9
  import { initialRouteKey, searchRouteKey } from './staticRoutes';
10
10
  import { jsx as _jsx } from "react/jsx-runtime";
@@ -14,7 +14,6 @@ const innerSpacingConfig = {
14
14
  export function ExamplesListScreen() {
15
15
  var _routeKeys, _useRoute$params;
16
16
  const searchFilter = useContext(SearchFilterContext);
17
- const setFilter = useContext(SetSearchFilterContext);
18
17
 
19
18
  // React Navigation Route Param typing is not clean because our routes are dynamic
20
19
  const routeKeys = (_routeKeys = (_useRoute$params = useRoute().params) === null || _useRoute$params === void 0 ? void 0 : _useRoute$params.routeKeys) !== null && _routeKeys !== void 0 ? _routeKeys : [];
@@ -26,7 +25,6 @@ export function ExamplesListScreen() {
26
25
  item
27
26
  } = _ref;
28
27
  const handlePress = () => {
29
- setFilter('');
30
28
  // typing not clean due to dynamic routes
31
29
  navigate(keyToRouteName(item));
32
30
  };
@@ -37,7 +35,7 @@ export function ExamplesListScreen() {
37
35
  onPress: handlePress,
38
36
  title: item
39
37
  });
40
- }, [navigate, setFilter]);
38
+ }, [navigate]);
41
39
  const data = [...routeKeys, 'IconSheet'].sort().filter(key => key !== initialRouteKey && key !== searchRouteKey).filter(key => {
42
40
  if (searchFilter !== '') {
43
41
  return includes(key.toLowerCase(), searchFilter.toLowerCase());
@@ -9,13 +9,9 @@ import { Box } from '@coinbase/cds-mobile/layout/Box';
9
9
  import { HStack } from '@coinbase/cds-mobile/layout/HStack';
10
10
  import { Spacer } from '@coinbase/cds-mobile/layout/Spacer';
11
11
  import { TextHeadline } from '@coinbase/cds-mobile/typography/TextHeadline';
12
- import { SetSearchFilterContext } from './ExamplesSearchProvider';
12
+ import { SearchFilterContext, SetSearchFilterContext } from './ExamplesSearchProvider';
13
13
  import { initialRouteName, searchRouteName } from './staticRoutes';
14
14
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
15
- const invisiblePressableStyle = {
16
- width: 40,
17
- height: 40
18
- };
19
15
  const iconButtonHeight = interactableHeight.regular;
20
16
  export function useExampleNavigatorProps(_ref) {
21
17
  let {
@@ -26,6 +22,7 @@ export function useExampleNavigatorProps(_ref) {
26
22
  top
27
23
  } = useSafeAreaInsets();
28
24
  const [headerSize, onLayout] = useLayout();
25
+ const searchFilter = useContext(SearchFilterContext);
29
26
  const setFilter = useContext(SetSearchFilterContext);
30
27
  const style = useMemo(() => ({
31
28
  marginTop: top
@@ -35,35 +32,21 @@ export function useExampleNavigatorProps(_ref) {
35
32
  let {
36
33
  navigation,
37
34
  route,
38
- options,
39
- progress,
40
- styleInterpolator
35
+ options
41
36
  } = _ref2;
42
37
  const isFocused = navigation.isFocused();
43
38
  const canGoBack = navigation.canGoBack();
44
39
  const goBack = () => {
45
40
  navigation.goBack();
41
+ };
42
+ const goBackFromSearch = () => {
46
43
  setFilter('');
44
+ navigation.goBack();
47
45
  };
48
46
  const goToSearch = () => navigation.navigate(searchRouteName);
49
47
  const routeName = route.name;
50
48
  const titleForScene = options.title;
51
49
  const isSearch = routeName === searchRouteName;
52
- const {
53
- titleStyle
54
- } = styleInterpolator({
55
- current: {
56
- progress: progress.current
57
- },
58
- next: progress.next && {
59
- progress: progress.next
60
- },
61
- layouts: {
62
- header: headerSize,
63
- title: headerSize,
64
- screen: headerSize
65
- }
66
- });
67
50
  const showBackButton = isFocused && canGoBack && !isSearch;
68
51
  const showSearch = routeName === initialRouteName;
69
52
  const iconButtonPlaceholder = /*#__PURE__*/_jsx(Box, {
@@ -118,25 +101,23 @@ export function useExampleNavigatorProps(_ref) {
118
101
  start: /*#__PURE__*/_jsx(IconButton, {
119
102
  transparent: true,
120
103
  name: "backArrow",
121
- onPress: goBack
122
- })
104
+ onPress: goBackFromSearch
105
+ }),
106
+ value: searchFilter
123
107
  }) : /*#__PURE__*/_jsx(TextHeadline, {
124
- animated: true,
125
108
  align: "center",
126
- style: titleStyle,
127
109
  children: titleForScene
128
110
  })
129
111
  }), /*#__PURE__*/_jsx(Spacer, {}), rightHeaderButton]
130
112
  })
131
113
  });
132
114
  };
133
- }, [headerSize, onLayout, setFilter, style, theme.activeColorScheme, setColorScheme]);
115
+ }, [onLayout, searchFilter, setFilter, style, theme.activeColorScheme, setColorScheme]);
134
116
  return useMemo(() => {
135
117
  const screenOptions = {
136
118
  headerBackAllowFontScaling: false,
137
119
  headerBackTitleVisible: false,
138
120
  headerTitleAllowFontScaling: false,
139
- headerMode: 'float',
140
121
  headerStyle: {
141
122
  backgroundColor: theme.color.bg,
142
123
  borderWidth: 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coinbase/ui-mobile-playground",
3
- "version": "4.5.7",
3
+ "version": "4.5.8",
4
4
  "description": "Mobile UI Components in a Playground",
5
5
  "repository": {
6
6
  "type": "git",
@@ -34,9 +34,9 @@
34
34
  "CHANGELOG"
35
35
  ],
36
36
  "peerDependencies": {
37
- "@coinbase/cds-common": "^8.21.5",
38
- "@coinbase/cds-mobile": "^8.21.5",
39
- "@coinbase/cds-mobile-visualization": "^3.4.0-beta.5",
37
+ "@coinbase/cds-common": "^8.25.1",
38
+ "@coinbase/cds-mobile": "^8.25.1",
39
+ "@coinbase/cds-mobile-visualization": "^3.4.0-beta.6",
40
40
  "@react-navigation/elements": "^1.3.17",
41
41
  "@react-navigation/native": "^6.1.6",
42
42
  "@react-navigation/stack": "^6.3.16",
@@ -7,7 +7,7 @@ import { Box } from '@coinbase/cds-mobile/layout/Box';
7
7
  import { useNavigation, useRoute } from '@react-navigation/native';
8
8
  import includes from 'lodash/includes';
9
9
 
10
- import { SearchFilterContext, SetSearchFilterContext } from './ExamplesSearchProvider';
10
+ import { SearchFilterContext } from './ExamplesSearchProvider';
11
11
  import { keyToRouteName } from './keyToRouteName';
12
12
  import { initialRouteKey, searchRouteKey } from './staticRoutes';
13
13
 
@@ -15,7 +15,6 @@ const innerSpacingConfig: CellSpacing = { paddingX: 1 };
15
15
 
16
16
  export function ExamplesListScreen() {
17
17
  const searchFilter = useContext(SearchFilterContext);
18
- const setFilter = useContext(SetSearchFilterContext);
19
18
 
20
19
  // React Navigation Route Param typing is not clean because our routes are dynamic
21
20
  const routeKeys = (useRoute().params as { routeKeys: string[] } | undefined)?.routeKeys ?? [];
@@ -24,7 +23,6 @@ export function ExamplesListScreen() {
24
23
  const renderItem: ListRenderItem<string> = useCallback(
25
24
  ({ item }) => {
26
25
  const handlePress = () => {
27
- setFilter('');
28
26
  // typing not clean due to dynamic routes
29
27
  navigate(keyToRouteName(item) as never);
30
28
  };
@@ -39,7 +37,7 @@ export function ExamplesListScreen() {
39
37
  />
40
38
  );
41
39
  },
42
- [navigate, setFilter],
40
+ [navigate],
43
41
  );
44
42
 
45
43
  const data = [...routeKeys, 'IconSheet']
@@ -1,5 +1,4 @@
1
1
  import React, { useContext, useMemo } from 'react';
2
- import { Pressable } from 'react-native';
3
2
  import type { NativeSyntheticEvent, TextInputChangeEventData } from 'react-native';
4
3
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
5
4
  import type { ColorScheme } from '@coinbase/cds-common/core/theme';
@@ -14,49 +13,39 @@ import { Spacer } from '@coinbase/cds-mobile/layout/Spacer';
14
13
  import { TextHeadline } from '@coinbase/cds-mobile/typography/TextHeadline';
15
14
  import type { StackHeaderProps, StackNavigationOptions } from '@react-navigation/stack';
16
15
 
17
- import { SetSearchFilterContext } from './ExamplesSearchProvider';
16
+ import { SearchFilterContext, SetSearchFilterContext } from './ExamplesSearchProvider';
18
17
  import { initialRouteName, searchRouteName } from './staticRoutes';
19
18
 
20
19
  type UseExampleNavigatorPropsOptions = {
21
20
  setColorScheme?: React.Dispatch<React.SetStateAction<ColorScheme>>;
22
21
  };
23
22
 
24
- const invisiblePressableStyle = {
25
- width: 40,
26
- height: 40,
27
- };
28
-
29
23
  const iconButtonHeight = interactableHeight.regular;
30
24
 
31
25
  export function useExampleNavigatorProps({ setColorScheme }: UseExampleNavigatorPropsOptions) {
32
26
  const theme = useTheme();
33
27
  const { top } = useSafeAreaInsets();
34
28
  const [headerSize, onLayout] = useLayout();
29
+ const searchFilter = useContext(SearchFilterContext);
35
30
  const setFilter = useContext(SetSearchFilterContext);
36
31
 
37
32
  const style = useMemo(() => ({ marginTop: top }), [top]);
38
33
 
39
34
  const header = useMemo(() => {
40
- return ({ navigation, route, options, progress, styleInterpolator }: StackHeaderProps) => {
35
+ return ({ navigation, route, options }: StackHeaderProps) => {
41
36
  const isFocused = navigation.isFocused();
42
37
  const canGoBack = navigation.canGoBack();
43
38
  const goBack = () => {
44
39
  navigation.goBack();
40
+ };
41
+ const goBackFromSearch = () => {
45
42
  setFilter('');
43
+ navigation.goBack();
46
44
  };
47
45
  const goToSearch = () => navigation.navigate(searchRouteName);
48
46
  const routeName = route.name;
49
47
  const titleForScene = options.title;
50
48
  const isSearch = routeName === searchRouteName;
51
- const { titleStyle } = styleInterpolator({
52
- current: { progress: progress.current },
53
- next: progress.next && { progress: progress.next },
54
- layouts: {
55
- header: headerSize,
56
- title: headerSize,
57
- screen: headerSize,
58
- },
59
- });
60
49
  const showBackButton = isFocused && canGoBack && !isSearch;
61
50
  const showSearch = routeName === initialRouteName;
62
51
 
@@ -109,12 +98,11 @@ export function useExampleNavigatorProps({ setColorScheme }: UseExampleNavigator
109
98
  label=""
110
99
  onChange={handleSearch}
111
100
  placeholder="Search"
112
- start={<IconButton transparent name="backArrow" onPress={goBack} />}
101
+ start={<IconButton transparent name="backArrow" onPress={goBackFromSearch} />}
102
+ value={searchFilter}
113
103
  />
114
104
  ) : (
115
- <TextHeadline animated align="center" style={titleStyle}>
116
- {titleForScene}
117
- </TextHeadline>
105
+ <TextHeadline align="center">{titleForScene}</TextHeadline>
118
106
  )}
119
107
  </Box>
120
108
  <Spacer />
@@ -123,14 +111,13 @@ export function useExampleNavigatorProps({ setColorScheme }: UseExampleNavigator
123
111
  </Box>
124
112
  );
125
113
  };
126
- }, [headerSize, onLayout, setFilter, style, theme.activeColorScheme, setColorScheme]);
114
+ }, [onLayout, searchFilter, setFilter, style, theme.activeColorScheme, setColorScheme]);
127
115
 
128
116
  return useMemo(() => {
129
117
  const screenOptions: StackNavigationOptions = {
130
118
  headerBackAllowFontScaling: false,
131
119
  headerBackTitleVisible: false,
132
120
  headerTitleAllowFontScaling: false,
133
- headerMode: 'float',
134
121
  headerStyle: {
135
122
  backgroundColor: theme.color.bg,
136
123
  borderWidth: 0,