@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 +6 -0
- package/dts/components/ExamplesListScreen.d.ts.map +1 -1
- package/dts/components/useExampleNavigatorProps.d.ts.map +1 -1
- package/esm/components/ExamplesListScreen.js +2 -4
- package/esm/components/useExampleNavigatorProps.js +10 -29
- package/package.json +4 -4
- package/src/components/ExamplesListScreen.tsx +2 -4
- package/src/components/useExampleNavigatorProps.tsx +10 -23
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,
|
|
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;
|
|
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
|
|
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
|
|
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:
|
|
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
|
-
}, [
|
|
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.
|
|
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.
|
|
38
|
-
"@coinbase/cds-mobile": "^8.
|
|
39
|
-
"@coinbase/cds-mobile-visualization": "^3.4.0-beta.
|
|
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
|
|
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
|
|
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
|
|
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={
|
|
101
|
+
start={<IconButton transparent name="backArrow" onPress={goBackFromSearch} />}
|
|
102
|
+
value={searchFilter}
|
|
113
103
|
/>
|
|
114
104
|
) : (
|
|
115
|
-
<TextHeadline
|
|
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
|
-
}, [
|
|
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,
|