@storybook/react-native-ui 8.5.2-alpha.1 → 8.5.2-alpha.2
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/dist/index.js +420 -346
- package/package.json +3 -3
- package/src/Layout.tsx +147 -87
- package/src/MobileAddonsPanel.tsx +96 -49
- package/src/MobileMenuDrawer.tsx +25 -13
- package/src/Search.tsx +3 -1
- package/src/StorybookLogo.tsx +5 -2
- package/src/TreeNode.tsx +17 -12
- package/src/icon/CloseFullscreenIcon.tsx +6 -8
- package/src/icon/CollapseAllIcon.tsx +6 -1
- package/src/icon/ExpandAllIcon.tsx +7 -1
- package/src/icon/FullscreenIcon.tsx +6 -1
- package/src/util/status.tsx +7 -7
- package/src/util/useStyle.ts +28 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@storybook/react-native-ui",
|
|
3
|
-
"version": "8.5.2-alpha.
|
|
3
|
+
"version": "8.5.2-alpha.2",
|
|
4
4
|
"description": "ui components for react native storybook",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"@storybook/core": "^8.4.2",
|
|
62
62
|
"@storybook/react": "^8.4.2",
|
|
63
|
-
"@storybook/react-native-theming": "^8.5.2-alpha.
|
|
63
|
+
"@storybook/react-native-theming": "^8.5.2-alpha.2",
|
|
64
64
|
"fuse.js": "^7.0.0",
|
|
65
65
|
"memoizerific": "^1.11.3",
|
|
66
66
|
"polished": "^4.3.1",
|
|
@@ -81,5 +81,5 @@
|
|
|
81
81
|
"publishConfig": {
|
|
82
82
|
"access": "public"
|
|
83
83
|
},
|
|
84
|
-
"gitHead": "
|
|
84
|
+
"gitHead": "051e4d60e1274baab7bd81afd8414d55a5c41f4b"
|
|
85
85
|
}
|
package/src/Layout.tsx
CHANGED
|
@@ -3,8 +3,8 @@ import { addons } from '@storybook/core/manager-api';
|
|
|
3
3
|
import { type API_IndexHash, type Args, type StoryContext } from '@storybook/core/types';
|
|
4
4
|
import type { ReactRenderer } from '@storybook/react';
|
|
5
5
|
import { styled, useTheme } from '@storybook/react-native-theming';
|
|
6
|
-
import { ReactNode, useRef, useState } from 'react';
|
|
7
|
-
import { ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
|
6
|
+
import { ReactNode, useRef, useState, useCallback } from 'react';
|
|
7
|
+
import { ScrollView, Text, TouchableOpacity, View, ViewStyle } from 'react-native';
|
|
8
8
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
9
9
|
import { IconButton } from './IconButton';
|
|
10
10
|
import { useLayout } from './LayoutProvider';
|
|
@@ -18,6 +18,39 @@ import { BottomBarToggleIcon } from './icon/BottomBarToggleIcon';
|
|
|
18
18
|
import { CloseFullscreenIcon } from './icon/CloseFullscreenIcon';
|
|
19
19
|
import { FullscreenIcon } from './icon/FullscreenIcon';
|
|
20
20
|
import { MenuIcon } from './icon/MenuIcon';
|
|
21
|
+
import { useStyle } from './util/useStyle';
|
|
22
|
+
|
|
23
|
+
const desktopLogoContainer = {
|
|
24
|
+
flexDirection: 'row',
|
|
25
|
+
alignItems: 'center',
|
|
26
|
+
paddingTop: 10,
|
|
27
|
+
paddingLeft: 16,
|
|
28
|
+
paddingBottom: 4,
|
|
29
|
+
paddingRight: 10,
|
|
30
|
+
justifyContent: 'space-between',
|
|
31
|
+
} satisfies ViewStyle;
|
|
32
|
+
|
|
33
|
+
const desktopContentContainerStyle = { flex: 1 } satisfies ViewStyle;
|
|
34
|
+
|
|
35
|
+
const desktopContentStyle = { flex: 1, overflow: 'hidden' } satisfies ViewStyle;
|
|
36
|
+
|
|
37
|
+
const mobileContentStyle = { flex: 1, overflow: 'hidden' } satisfies ViewStyle;
|
|
38
|
+
|
|
39
|
+
const placeholderObject = {};
|
|
40
|
+
|
|
41
|
+
const placeholderArray = [];
|
|
42
|
+
|
|
43
|
+
const iconFloatRightStyle = { marginLeft: 'auto' } satisfies ViewStyle;
|
|
44
|
+
|
|
45
|
+
const navButtonStyle = { flexShrink: 1 } satisfies ViewStyle;
|
|
46
|
+
|
|
47
|
+
const navButtonHitSlop = { bottom: 10, left: 10, right: 10, top: 10 };
|
|
48
|
+
|
|
49
|
+
const mobileMenuDrawerContentStyle = {
|
|
50
|
+
paddingLeft: 16,
|
|
51
|
+
paddingTop: 4,
|
|
52
|
+
paddingBottom: 4,
|
|
53
|
+
} satisfies ViewStyle;
|
|
21
54
|
|
|
22
55
|
export const Layout = ({
|
|
23
56
|
storyHash,
|
|
@@ -46,58 +79,114 @@ export const Layout = ({
|
|
|
46
79
|
|
|
47
80
|
const [uiHidden, setUiHidden] = useState(false);
|
|
48
81
|
|
|
82
|
+
const desktopContainerStyle = useStyle(
|
|
83
|
+
() => ({
|
|
84
|
+
flex: 1,
|
|
85
|
+
paddingTop: insets.top,
|
|
86
|
+
backgroundColor: theme.background.content,
|
|
87
|
+
flexDirection: 'row',
|
|
88
|
+
}),
|
|
89
|
+
[theme.background.content, insets.top]
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
const desktopSidebarStyle = useStyle(
|
|
93
|
+
() => ({
|
|
94
|
+
width: desktopSidebarOpen ? 240 : undefined,
|
|
95
|
+
padding: desktopSidebarOpen ? 0 : 10,
|
|
96
|
+
borderColor: theme.appBorderColor,
|
|
97
|
+
borderRightWidth: 1,
|
|
98
|
+
}),
|
|
99
|
+
[desktopSidebarOpen, theme.appBorderColor]
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
const desktopScrollViewContentContainerStyle = useStyle(
|
|
103
|
+
() => ({
|
|
104
|
+
paddingBottom: insets.bottom,
|
|
105
|
+
}),
|
|
106
|
+
[insets.bottom]
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
const desktopAddonsPanelStyle = useStyle(
|
|
110
|
+
() => ({
|
|
111
|
+
height: desktopAddonsPanelOpen ? 300 : undefined,
|
|
112
|
+
borderTopWidth: 1,
|
|
113
|
+
borderColor: theme.appBorderColor,
|
|
114
|
+
paddingTop: desktopAddonsPanelOpen ? 4 : 0,
|
|
115
|
+
padding: desktopAddonsPanelOpen ? 0 : 10,
|
|
116
|
+
}),
|
|
117
|
+
[desktopAddonsPanelOpen, theme.appBorderColor]
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
const mobileContainerStyle = useStyle(
|
|
121
|
+
() => ({
|
|
122
|
+
flex: 1,
|
|
123
|
+
paddingTop: story?.parameters?.noSafeArea ? 0 : insets.top,
|
|
124
|
+
backgroundColor: theme.background.content,
|
|
125
|
+
}),
|
|
126
|
+
[theme.background.content, insets.top, story?.parameters?.noSafeArea]
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
const fullScreenButtonStyle = useStyle(
|
|
130
|
+
() => ({
|
|
131
|
+
position: 'absolute',
|
|
132
|
+
bottom: uiHidden ? 56 + insets.bottom : 16,
|
|
133
|
+
right: 16,
|
|
134
|
+
backgroundColor: theme.background.content,
|
|
135
|
+
padding: 4,
|
|
136
|
+
borderRadius: 4,
|
|
137
|
+
borderWidth: 1,
|
|
138
|
+
borderColor: theme.appBorderColor,
|
|
139
|
+
}),
|
|
140
|
+
[uiHidden, insets.bottom, theme.background.content, theme.appBorderColor]
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
const containerStyle = useStyle(
|
|
144
|
+
() => ({
|
|
145
|
+
marginBottom: insets.bottom,
|
|
146
|
+
}),
|
|
147
|
+
[insets.bottom]
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
const navButtonTextStyle = useStyle(
|
|
151
|
+
() => ({
|
|
152
|
+
flexShrink: 1,
|
|
153
|
+
color: theme.color.defaultText,
|
|
154
|
+
}),
|
|
155
|
+
[theme.color.defaultText]
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
const openMobileMenu = useCallback(() => {
|
|
159
|
+
mobileMenuDrawerRef.current.setMobileMenuOpen(true);
|
|
160
|
+
}, [mobileMenuDrawerRef]);
|
|
161
|
+
|
|
162
|
+
const setSelection = useCallback(({ storyId: newStoryId }: { storyId: string }) => {
|
|
163
|
+
const channel = addons.getChannel();
|
|
164
|
+
|
|
165
|
+
channel.emit(SET_CURRENT_STORY, { storyId: newStoryId });
|
|
166
|
+
}, []);
|
|
167
|
+
|
|
49
168
|
if (isDesktop) {
|
|
50
169
|
return (
|
|
51
|
-
<View
|
|
52
|
-
style={
|
|
53
|
-
flex: 1,
|
|
54
|
-
paddingTop: insets.top,
|
|
55
|
-
backgroundColor: theme.background.content,
|
|
56
|
-
flexDirection: 'row',
|
|
57
|
-
}}
|
|
58
|
-
>
|
|
59
|
-
<View
|
|
60
|
-
style={{
|
|
61
|
-
width: desktopSidebarOpen ? 240 : undefined,
|
|
62
|
-
padding: desktopSidebarOpen ? 0 : 10,
|
|
63
|
-
borderColor: theme.appBorderColor,
|
|
64
|
-
borderRightWidth: 1,
|
|
65
|
-
}}
|
|
66
|
-
>
|
|
170
|
+
<View style={desktopContainerStyle}>
|
|
171
|
+
<View style={desktopSidebarStyle}>
|
|
67
172
|
{desktopSidebarOpen ? (
|
|
68
173
|
<ScrollView
|
|
69
174
|
keyboardShouldPersistTaps="handled"
|
|
70
|
-
contentContainerStyle={
|
|
71
|
-
paddingBottom: insets.bottom,
|
|
72
|
-
}}
|
|
175
|
+
contentContainerStyle={desktopScrollViewContentContainerStyle}
|
|
73
176
|
>
|
|
74
|
-
<View
|
|
75
|
-
style={{
|
|
76
|
-
flexDirection: 'row',
|
|
77
|
-
alignItems: 'center',
|
|
78
|
-
paddingTop: 10,
|
|
79
|
-
paddingLeft: 16,
|
|
80
|
-
paddingBottom: 4,
|
|
81
|
-
paddingRight: 10,
|
|
82
|
-
justifyContent: 'space-between',
|
|
83
|
-
}}
|
|
84
|
-
>
|
|
177
|
+
<View style={desktopLogoContainer}>
|
|
85
178
|
<StorybookLogo theme={theme} />
|
|
86
179
|
|
|
87
180
|
<IconButton onPress={() => setDesktopSidebarOpen(false)} Icon={MenuIcon} />
|
|
88
181
|
</View>
|
|
89
182
|
|
|
90
183
|
<Sidebar
|
|
91
|
-
extra={
|
|
184
|
+
extra={placeholderArray}
|
|
92
185
|
previewInitialized
|
|
93
186
|
indexError={undefined}
|
|
94
|
-
refs={
|
|
95
|
-
setSelection={
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
channel.emit(SET_CURRENT_STORY, { storyId: newStoryId });
|
|
99
|
-
}}
|
|
100
|
-
status={{}}
|
|
187
|
+
refs={placeholderObject}
|
|
188
|
+
setSelection={setSelection}
|
|
189
|
+
status={placeholderObject}
|
|
101
190
|
index={storyHash}
|
|
102
191
|
storyId={story?.id}
|
|
103
192
|
refId={DEFAULT_REF_ID}
|
|
@@ -108,23 +197,15 @@ export const Layout = ({
|
|
|
108
197
|
)}
|
|
109
198
|
</View>
|
|
110
199
|
|
|
111
|
-
<View style={
|
|
112
|
-
<View style={
|
|
113
|
-
|
|
114
|
-
<View
|
|
115
|
-
style={{
|
|
116
|
-
height: desktopAddonsPanelOpen ? 300 : undefined,
|
|
117
|
-
borderTopWidth: 1,
|
|
118
|
-
borderColor: theme.appBorderColor,
|
|
119
|
-
paddingTop: desktopAddonsPanelOpen ? 4 : 0,
|
|
120
|
-
padding: desktopAddonsPanelOpen ? 0 : 10,
|
|
121
|
-
}}
|
|
122
|
-
>
|
|
200
|
+
<View style={desktopContentContainerStyle}>
|
|
201
|
+
<View style={desktopContentStyle}>{children}</View>
|
|
202
|
+
|
|
203
|
+
<View style={desktopAddonsPanelStyle}>
|
|
123
204
|
{desktopAddonsPanelOpen ? (
|
|
124
205
|
<AddonsTabs storyId={story?.id} onClose={() => setDesktopAddonsPanelOpen(false)} />
|
|
125
206
|
) : (
|
|
126
207
|
<IconButton
|
|
127
|
-
style={
|
|
208
|
+
style={iconFloatRightStyle}
|
|
128
209
|
onPress={() => setDesktopAddonsPanelOpen(true)}
|
|
129
210
|
Icon={BottomBarToggleIcon}
|
|
130
211
|
/>
|
|
@@ -136,28 +217,13 @@ export const Layout = ({
|
|
|
136
217
|
}
|
|
137
218
|
|
|
138
219
|
return (
|
|
139
|
-
<View
|
|
140
|
-
style={
|
|
141
|
-
flex: 1,
|
|
142
|
-
paddingTop: story?.parameters?.noSafeArea ? 0 : insets.top,
|
|
143
|
-
backgroundColor: theme.background.content,
|
|
144
|
-
}}
|
|
145
|
-
>
|
|
146
|
-
<View style={{ flex: 1, overflow: 'hidden' }}>
|
|
220
|
+
<View style={mobileContainerStyle}>
|
|
221
|
+
<View style={mobileContentStyle}>
|
|
147
222
|
{children}
|
|
148
223
|
|
|
149
224
|
{story?.parameters?.hideFullScreenButton ? null : (
|
|
150
225
|
<TouchableOpacity
|
|
151
|
-
style={
|
|
152
|
-
position: 'absolute',
|
|
153
|
-
bottom: uiHidden ? 56 + insets.bottom : 16,
|
|
154
|
-
right: 16,
|
|
155
|
-
backgroundColor: theme.background.content,
|
|
156
|
-
padding: 4,
|
|
157
|
-
borderRadius: 4,
|
|
158
|
-
borderWidth: 1,
|
|
159
|
-
borderColor: theme.appBorderColor,
|
|
160
|
-
}}
|
|
226
|
+
style={fullScreenButtonStyle}
|
|
161
227
|
onPress={() => setUiHidden((prev) => !prev)}
|
|
162
228
|
>
|
|
163
229
|
{uiHidden ? (
|
|
@@ -170,18 +236,16 @@ export const Layout = ({
|
|
|
170
236
|
</View>
|
|
171
237
|
|
|
172
238
|
{!uiHidden ? (
|
|
173
|
-
<Container style={
|
|
239
|
+
<Container style={containerStyle}>
|
|
174
240
|
<Nav>
|
|
175
241
|
<Button
|
|
176
242
|
testID="mobile-menu-button"
|
|
177
|
-
style={
|
|
178
|
-
hitSlop={
|
|
179
|
-
onPress={
|
|
180
|
-
mobileMenuDrawerRef.current.setMobileMenuOpen(true);
|
|
181
|
-
}}
|
|
243
|
+
style={navButtonStyle}
|
|
244
|
+
hitSlop={navButtonHitSlop}
|
|
245
|
+
onPress={openMobileMenu}
|
|
182
246
|
>
|
|
183
247
|
<MenuIcon color={theme.color.mediumdark} />
|
|
184
|
-
<Text style={
|
|
248
|
+
<Text style={navButtonTextStyle} numberOfLines={1}>
|
|
185
249
|
{story?.title}/{story?.name}
|
|
186
250
|
</Text>
|
|
187
251
|
</Button>
|
|
@@ -196,21 +260,17 @@ export const Layout = ({
|
|
|
196
260
|
) : null}
|
|
197
261
|
|
|
198
262
|
<MobileMenuDrawer ref={mobileMenuDrawerRef}>
|
|
199
|
-
<View style={
|
|
263
|
+
<View style={mobileMenuDrawerContentStyle}>
|
|
200
264
|
<StorybookLogo theme={theme} />
|
|
201
265
|
</View>
|
|
202
266
|
|
|
203
267
|
<Sidebar
|
|
204
|
-
extra={
|
|
268
|
+
extra={placeholderArray}
|
|
205
269
|
previewInitialized
|
|
206
270
|
indexError={undefined}
|
|
207
|
-
refs={
|
|
208
|
-
setSelection={
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
channel.emit(SET_CURRENT_STORY, { storyId: newStoryId });
|
|
212
|
-
}}
|
|
213
|
-
status={{}}
|
|
271
|
+
refs={placeholderObject}
|
|
272
|
+
setSelection={setSelection}
|
|
273
|
+
status={placeholderObject}
|
|
214
274
|
index={storyHash}
|
|
215
275
|
storyId={story?.id}
|
|
216
276
|
refId={DEFAULT_REF_ID}
|
|
@@ -2,8 +2,8 @@ import { BottomSheetModal } from '@gorhom/bottom-sheet';
|
|
|
2
2
|
import { addons } from '@storybook/core/manager-api';
|
|
3
3
|
import { styled } from '@storybook/react-native-theming';
|
|
4
4
|
import { Addon_TypesEnum } from '@storybook/core/types';
|
|
5
|
-
import { forwardRef, useImperativeHandle, useRef, useState } from 'react';
|
|
6
|
-
import { Platform, Text, View, useWindowDimensions } from 'react-native';
|
|
5
|
+
import { forwardRef, useImperativeHandle, useMemo, useRef, useState } from 'react';
|
|
6
|
+
import { Platform, StyleProp, Text, View, ViewStyle, useWindowDimensions } from 'react-native';
|
|
7
7
|
import { ScrollView } from 'react-native-gesture-handler';
|
|
8
8
|
import Animated, {
|
|
9
9
|
useAnimatedKeyboard,
|
|
@@ -15,11 +15,20 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
|
15
15
|
import { useTheme } from '@storybook/react-native-theming';
|
|
16
16
|
import { IconButton } from './IconButton';
|
|
17
17
|
import { CloseIcon } from './icon/CloseIcon';
|
|
18
|
+
import { useStyle } from './util/useStyle';
|
|
18
19
|
|
|
19
20
|
export interface MobileAddonsPanelRef {
|
|
20
21
|
setAddonsPanelOpen: (isOpen: boolean) => void;
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
const bottomSheetStyle = {
|
|
25
|
+
paddingTop: 8,
|
|
26
|
+
} satisfies StyleProp<ViewStyle>;
|
|
27
|
+
|
|
28
|
+
const contentStyle = {
|
|
29
|
+
flex: 1,
|
|
30
|
+
} satisfies StyleProp<ViewStyle>;
|
|
31
|
+
|
|
23
32
|
export const MobileAddonsPanel = forwardRef<MobileAddonsPanelRef, { storyId?: string }>(
|
|
24
33
|
({ storyId }, ref) => {
|
|
25
34
|
const theme = useTheme();
|
|
@@ -53,24 +62,31 @@ export const MobileAddonsPanel = forwardRef<MobileAddonsPanelRef, { storyId?: st
|
|
|
53
62
|
};
|
|
54
63
|
}, [animatedPosition, height, insets.bottom]);
|
|
55
64
|
|
|
65
|
+
const backgroundStyle = useStyle(() => {
|
|
66
|
+
return {
|
|
67
|
+
borderRadius: 0,
|
|
68
|
+
borderTopColor: theme.appBorderColor,
|
|
69
|
+
borderTopWidth: 1,
|
|
70
|
+
backgroundColor: theme.background.content,
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const handleIndicatorStyle = useStyle(() => {
|
|
75
|
+
return {
|
|
76
|
+
backgroundColor: theme.textMutedColor,
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
|
|
56
80
|
return (
|
|
57
81
|
<BottomSheetModal
|
|
58
82
|
ref={addonsPanelBottomSheetRef}
|
|
59
83
|
index={1}
|
|
60
84
|
animateOnMount={!reducedMotion}
|
|
61
85
|
snapPoints={['25%', '50%', '75%']}
|
|
62
|
-
style={
|
|
63
|
-
paddingTop: 8,
|
|
64
|
-
}}
|
|
86
|
+
style={bottomSheetStyle}
|
|
65
87
|
animatedPosition={animatedPosition}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
borderRadius: 0,
|
|
69
|
-
borderTopColor: theme.appBorderColor,
|
|
70
|
-
borderTopWidth: 1,
|
|
71
|
-
backgroundColor: theme.background.content,
|
|
72
|
-
}}
|
|
73
|
-
handleIndicatorStyle={{ backgroundColor: theme.textMutedColor }}
|
|
88
|
+
backgroundStyle={backgroundStyle}
|
|
89
|
+
handleIndicatorStyle={handleIndicatorStyle}
|
|
74
90
|
keyboardBehavior="extend"
|
|
75
91
|
// keyboardBlurBehavior="restore"
|
|
76
92
|
enableDismissOnClose
|
|
@@ -79,7 +95,7 @@ export const MobileAddonsPanel = forwardRef<MobileAddonsPanelRef, { storyId?: st
|
|
|
79
95
|
stackBehavior="replace"
|
|
80
96
|
enableDynamicSizing={false}
|
|
81
97
|
>
|
|
82
|
-
<Animated.View style={[
|
|
98
|
+
<Animated.View style={[contentStyle, adjustedBottomSheetSize]}>
|
|
83
99
|
<AddonsTabs
|
|
84
100
|
onClose={() => {
|
|
85
101
|
addonsPanelBottomSheetRef.current?.dismiss();
|
|
@@ -92,6 +108,38 @@ export const MobileAddonsPanel = forwardRef<MobileAddonsPanelRef, { storyId?: st
|
|
|
92
108
|
}
|
|
93
109
|
);
|
|
94
110
|
|
|
111
|
+
const addonsTabsContainerStyle = {
|
|
112
|
+
flex: 1,
|
|
113
|
+
} satisfies StyleProp<ViewStyle>;
|
|
114
|
+
|
|
115
|
+
const addonsTabsStyle = {
|
|
116
|
+
flexDirection: 'row',
|
|
117
|
+
borderBottomWidth: 1,
|
|
118
|
+
borderBottomColor: 'lightgrey',
|
|
119
|
+
} satisfies StyleProp<ViewStyle>;
|
|
120
|
+
|
|
121
|
+
const addonsTabsContentContainerStyle = {
|
|
122
|
+
justifyContent: 'center',
|
|
123
|
+
} satisfies StyleProp<ViewStyle>;
|
|
124
|
+
|
|
125
|
+
const closeIconStyle = {
|
|
126
|
+
marginRight: 4,
|
|
127
|
+
marginBottom: 4,
|
|
128
|
+
alignItems: 'center',
|
|
129
|
+
justifyContent: 'center',
|
|
130
|
+
} satisfies StyleProp<ViewStyle>;
|
|
131
|
+
|
|
132
|
+
const addonsScrollStyle = {
|
|
133
|
+
flex: 1,
|
|
134
|
+
} satisfies StyleProp<ViewStyle>;
|
|
135
|
+
|
|
136
|
+
const centeredStyle = {
|
|
137
|
+
alignItems: 'center',
|
|
138
|
+
justifyContent: 'center',
|
|
139
|
+
} satisfies StyleProp<ViewStyle>;
|
|
140
|
+
|
|
141
|
+
const hitSlop = { top: 10, right: 10, bottom: 10, left: 10 };
|
|
142
|
+
|
|
95
143
|
export const AddonsTabs = ({ onClose, storyId }: { onClose?: () => void; storyId?: string }) => {
|
|
96
144
|
const panels = addons.getElements(Addon_TypesEnum.PANEL);
|
|
97
145
|
|
|
@@ -99,15 +147,39 @@ export const AddonsTabs = ({ onClose, storyId }: { onClose?: () => void; storyId
|
|
|
99
147
|
|
|
100
148
|
const insets = useSafeAreaInsets();
|
|
101
149
|
|
|
150
|
+
const scrollContentContainerStyle = useStyle(() => {
|
|
151
|
+
return {
|
|
152
|
+
paddingBottom: insets.bottom + 16,
|
|
153
|
+
};
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
const panel = useMemo(() => {
|
|
157
|
+
if (!storyId) {
|
|
158
|
+
return (
|
|
159
|
+
<View style={centeredStyle}>
|
|
160
|
+
<Text>No Story Selected</Text>
|
|
161
|
+
</View>
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (Object.keys(panels).length === 0) {
|
|
166
|
+
return (
|
|
167
|
+
<View style={centeredStyle}>
|
|
168
|
+
<Text>No addons loaded.</Text>
|
|
169
|
+
</View>
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return panels[addonSelected].render({ active: true });
|
|
174
|
+
}, [addonSelected, panels, storyId]);
|
|
175
|
+
|
|
102
176
|
return (
|
|
103
|
-
<View style={
|
|
104
|
-
<View style={
|
|
177
|
+
<View style={addonsTabsContainerStyle}>
|
|
178
|
+
<View style={addonsTabsStyle}>
|
|
105
179
|
<ScrollView
|
|
106
180
|
horizontal
|
|
107
181
|
showsHorizontalScrollIndicator={false}
|
|
108
|
-
contentContainerStyle={
|
|
109
|
-
justifyContent: 'center',
|
|
110
|
-
}}
|
|
182
|
+
contentContainerStyle={addonsTabsContentContainerStyle}
|
|
111
183
|
>
|
|
112
184
|
{Object.values(panels).map(({ id, title }) => {
|
|
113
185
|
const resolvedTitle = typeof title === 'function' ? title({}) : title;
|
|
@@ -124,43 +196,18 @@ export const AddonsTabs = ({ onClose, storyId }: { onClose?: () => void; storyId
|
|
|
124
196
|
</ScrollView>
|
|
125
197
|
|
|
126
198
|
<IconButton
|
|
127
|
-
style={
|
|
128
|
-
|
|
129
|
-
marginBottom: 4,
|
|
130
|
-
alignItems: 'center',
|
|
131
|
-
justifyContent: 'center',
|
|
132
|
-
}}
|
|
133
|
-
hitSlop={{ top: 10, right: 10, bottom: 10, left: 10 }}
|
|
199
|
+
style={closeIconStyle}
|
|
200
|
+
hitSlop={hitSlop}
|
|
134
201
|
Icon={CloseIcon}
|
|
135
202
|
onPress={() => onClose?.()}
|
|
136
203
|
/>
|
|
137
204
|
</View>
|
|
138
205
|
<ScrollView
|
|
139
|
-
style={
|
|
206
|
+
style={addonsScrollStyle}
|
|
140
207
|
// keyboardShouldPersistTaps="handled"
|
|
141
|
-
contentContainerStyle={
|
|
142
|
-
paddingBottom: insets.bottom + 16,
|
|
143
|
-
}}
|
|
208
|
+
contentContainerStyle={scrollContentContainerStyle}
|
|
144
209
|
>
|
|
145
|
-
{
|
|
146
|
-
if (!storyId) {
|
|
147
|
-
return (
|
|
148
|
-
<View style={{ alignItems: 'center', justifyContent: 'center' }}>
|
|
149
|
-
<Text>No Story Selected</Text>
|
|
150
|
-
</View>
|
|
151
|
-
);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (Object.keys(panels).length === 0) {
|
|
155
|
-
return (
|
|
156
|
-
<View style={{ alignItems: 'center', justifyContent: 'center' }}>
|
|
157
|
-
<Text>No addons loaded.</Text>
|
|
158
|
-
</View>
|
|
159
|
-
);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
return panels[addonSelected].render({ active: true });
|
|
163
|
-
})()}
|
|
210
|
+
{panel}
|
|
164
211
|
</ScrollView>
|
|
165
212
|
</View>
|
|
166
213
|
);
|
package/src/MobileMenuDrawer.tsx
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import BottomSheet, {
|
|
2
2
|
BottomSheetBackdrop,
|
|
3
3
|
BottomSheetBackdropProps,
|
|
4
|
-
BottomSheetModal,
|
|
5
4
|
BottomSheetScrollView,
|
|
6
5
|
} from '@gorhom/bottom-sheet';
|
|
7
|
-
import { ReactNode, forwardRef, useImperativeHandle, useRef } from 'react';
|
|
6
|
+
import { ReactNode, forwardRef, memo, useImperativeHandle, useMemo, useRef } from 'react';
|
|
8
7
|
import { Keyboard } from 'react-native';
|
|
9
8
|
import { useReducedMotion } from 'react-native-reanimated';
|
|
10
9
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
@@ -28,19 +27,21 @@ export const BottomSheetBackdropComponent = (backdropComponentProps: BottomSheet
|
|
|
28
27
|
/>
|
|
29
28
|
);
|
|
30
29
|
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
const snapPoints = ['50%', '75%'];
|
|
31
|
+
|
|
32
|
+
export const MobileMenuDrawer = memo(
|
|
33
|
+
forwardRef<MobileMenuDrawerRef, MobileMenuDrawerProps>(({ children }, ref) => {
|
|
33
34
|
const reducedMotion = useReducedMotion();
|
|
34
35
|
const insets = useSafeAreaInsets();
|
|
35
36
|
const theme = useTheme();
|
|
36
37
|
|
|
37
|
-
const menuBottomSheetRef = useRef<
|
|
38
|
+
const menuBottomSheetRef = useRef<BottomSheet>(null);
|
|
38
39
|
|
|
39
40
|
useImperativeHandle(ref, () => ({
|
|
40
41
|
setMobileMenuOpen: (open: boolean) => {
|
|
41
42
|
if (open) {
|
|
42
43
|
// menuBottomSheetRef.current?.present();
|
|
43
|
-
menuBottomSheetRef.current?.
|
|
44
|
+
menuBottomSheetRef.current?.snapToIndex(1);
|
|
44
45
|
} else {
|
|
45
46
|
Keyboard.dismiss();
|
|
46
47
|
|
|
@@ -50,32 +51,43 @@ export const MobileMenuDrawer = forwardRef<MobileMenuDrawerRef, MobileMenuDrawer
|
|
|
50
51
|
},
|
|
51
52
|
}));
|
|
52
53
|
|
|
54
|
+
const bgColorStyle = useMemo(() => {
|
|
55
|
+
return { backgroundColor: theme.background.content };
|
|
56
|
+
}, [theme.background.content]);
|
|
57
|
+
|
|
58
|
+
const handleIndicatorStyle = useMemo(() => {
|
|
59
|
+
return { backgroundColor: theme.textMutedColor };
|
|
60
|
+
}, [theme.textMutedColor]);
|
|
61
|
+
|
|
62
|
+
const contentContainerStyle = useMemo(() => {
|
|
63
|
+
return { paddingBottom: insets.bottom };
|
|
64
|
+
}, [insets.bottom]);
|
|
65
|
+
|
|
53
66
|
return (
|
|
54
67
|
<BottomSheet
|
|
55
68
|
ref={menuBottomSheetRef}
|
|
56
69
|
index={-1}
|
|
57
70
|
animateOnMount={!reducedMotion}
|
|
58
|
-
snapPoints={
|
|
71
|
+
snapPoints={snapPoints}
|
|
59
72
|
// enableDismissOnClose
|
|
60
73
|
enableHandlePanningGesture
|
|
61
74
|
enableContentPanningGesture
|
|
62
75
|
enableDynamicSizing={false}
|
|
63
76
|
keyboardBehavior="extend"
|
|
64
77
|
keyboardBlurBehavior="restore"
|
|
78
|
+
enablePanDownToClose
|
|
65
79
|
// stackBehavior="replace"
|
|
66
80
|
backdropComponent={BottomSheetBackdropComponent}
|
|
67
|
-
backgroundStyle={
|
|
68
|
-
handleIndicatorStyle={
|
|
81
|
+
backgroundStyle={bgColorStyle}
|
|
82
|
+
handleIndicatorStyle={handleIndicatorStyle}
|
|
69
83
|
>
|
|
70
84
|
<BottomSheetScrollView
|
|
71
85
|
keyboardShouldPersistTaps="handled"
|
|
72
|
-
contentContainerStyle={
|
|
73
|
-
paddingBottom: insets.bottom,
|
|
74
|
-
}}
|
|
86
|
+
contentContainerStyle={contentContainerStyle}
|
|
75
87
|
>
|
|
76
88
|
{children}
|
|
77
89
|
</BottomSheetScrollView>
|
|
78
90
|
</BottomSheet>
|
|
79
91
|
);
|
|
80
|
-
}
|
|
92
|
+
})
|
|
81
93
|
);
|
package/src/Search.tsx
CHANGED
|
@@ -3,7 +3,7 @@ import { styled } from '@storybook/react-native-theming';
|
|
|
3
3
|
import type { IFuseOptions } from 'fuse.js';
|
|
4
4
|
import Fuse from 'fuse.js';
|
|
5
5
|
import React, { useCallback, useDeferredValue, useRef, useState } from 'react';
|
|
6
|
-
import { TextInput, View } from 'react-native';
|
|
6
|
+
import { Platform, TextInput, View } from 'react-native';
|
|
7
7
|
import { CloseIcon } from './icon/CloseIcon';
|
|
8
8
|
import { SearchIcon } from './icon/SearchIcon';
|
|
9
9
|
import { useLayout } from './LayoutProvider';
|
|
@@ -61,6 +61,8 @@ const BottomSheetInput = styled(BottomSheetTextInput)(({ theme }) => ({
|
|
|
61
61
|
height: 32,
|
|
62
62
|
paddingLeft: 28,
|
|
63
63
|
paddingRight: 28,
|
|
64
|
+
paddingTop: Platform.OS === 'android' ? 0 : undefined,
|
|
65
|
+
paddingBottom: Platform.OS === 'android' ? 0 : undefined,
|
|
64
66
|
borderWidth: 1,
|
|
65
67
|
borderColor: theme.appBorderColor,
|
|
66
68
|
backgroundColor: 'transparent',
|
package/src/StorybookLogo.tsx
CHANGED
|
@@ -96,9 +96,12 @@ const BrandTitle: FC<{ theme: Theme }> = ({ theme }) => {
|
|
|
96
96
|
};
|
|
97
97
|
|
|
98
98
|
export const StorybookLogo: FC<{ theme: Theme }> = ({ theme }) => {
|
|
99
|
-
|
|
99
|
+
const image = useMemo(() => theme.brand?.image, [theme.brand?.image]);
|
|
100
|
+
const title = useMemo(() => theme.brand?.title, [theme.brand?.title]);
|
|
101
|
+
|
|
102
|
+
if (image) {
|
|
100
103
|
return <BrandLogo theme={theme} />;
|
|
101
|
-
} else if (
|
|
104
|
+
} else if (title) {
|
|
102
105
|
return <BrandTitle theme={theme} />;
|
|
103
106
|
} else {
|
|
104
107
|
return <NoBrandLogo theme={theme} />;
|