@storybook/react-native-ui 8.0.0-alpha.3

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 (43) hide show
  1. package/LICENSE +21 -0
  2. package/dist/index.d.ts +492 -0
  3. package/dist/index.js +2860 -0
  4. package/package.json +85 -0
  5. package/src/Button.stories.tsx +134 -0
  6. package/src/Button.tsx +243 -0
  7. package/src/Explorer.stories.tsx +46 -0
  8. package/src/Explorer.tsx +54 -0
  9. package/src/IconButton.tsx +11 -0
  10. package/src/Layout.stories.tsx +38 -0
  11. package/src/Layout.tsx +103 -0
  12. package/src/LayoutProvider.tsx +90 -0
  13. package/src/MobileAddonsPanel.tsx +166 -0
  14. package/src/MobileMenuDrawer.tsx +75 -0
  15. package/src/Refs.tsx +142 -0
  16. package/src/Search.tsx +336 -0
  17. package/src/SearchResults.tsx +315 -0
  18. package/src/Sidebar.stories.tsx +262 -0
  19. package/src/Sidebar.tsx +200 -0
  20. package/src/Tree.stories.tsx +139 -0
  21. package/src/Tree.tsx +441 -0
  22. package/src/TreeNode.stories.tsx +122 -0
  23. package/src/TreeNode.tsx +146 -0
  24. package/src/constants.ts +4 -0
  25. package/src/icon/BottomBarToggleIcon.tsx +23 -0
  26. package/src/icon/CloseIcon.tsx +22 -0
  27. package/src/icon/CollapseAllIcon.tsx +17 -0
  28. package/src/icon/CollapseIcon.tsx +39 -0
  29. package/src/icon/ComponentIcon.tsx +14 -0
  30. package/src/icon/ExpandAllIcon.tsx +17 -0
  31. package/src/icon/FaceHappyIcon.tsx +18 -0
  32. package/src/icon/GroupIcon.tsx +14 -0
  33. package/src/icon/MenuIcon.tsx +18 -0
  34. package/src/icon/SearchIcon.tsx +17 -0
  35. package/src/icon/StoryIcon.tsx +14 -0
  36. package/src/index.tsx +9 -0
  37. package/src/mockdata.large.ts +25217 -0
  38. package/src/mockdata.ts +287 -0
  39. package/src/types.ts +78 -0
  40. package/src/useExpanded.ts +130 -0
  41. package/src/useLastViewed.ts +48 -0
  42. package/src/util/status.tsx +70 -0
  43. package/src/util/tree.ts +91 -0
package/src/Layout.tsx ADDED
@@ -0,0 +1,103 @@
1
+ import { SET_CURRENT_STORY } from '@storybook/core-events';
2
+ import { addons } from '@storybook/manager-api';
3
+ import { styled, useTheme } from '@storybook/react-native-theming';
4
+ import { type API_IndexHash, type Args, type StoryContext } from '@storybook/types';
5
+ import { ReactNode, useRef } from 'react';
6
+ import { Text, View } from 'react-native';
7
+ import { useSafeAreaInsets } from 'react-native-safe-area-context';
8
+ import { IconButton } from './IconButton';
9
+ import { Sidebar } from './Sidebar';
10
+ import { DEFAULT_REF_ID } from './constants';
11
+ import { BottomBarToggleIcon } from './icon/BottomBarToggleIcon';
12
+ import { MenuIcon } from './icon/MenuIcon';
13
+
14
+ import { ReactRenderer } from '@storybook/react';
15
+ import { MobileMenuDrawer, MobileMenuDrawerRef } from './MobileMenuDrawer';
16
+ import { MobileAddonsPanel, MobileAddonsPanelRef } from './MobileAddonsPanel';
17
+
18
+ export const Layout = ({
19
+ storyHash,
20
+ story,
21
+ children,
22
+ }: {
23
+ storyHash: API_IndexHash | undefined;
24
+ story?: StoryContext<ReactRenderer, Args>;
25
+ children: ReactNode | ReactNode[];
26
+ }) => {
27
+ const theme = useTheme();
28
+ const mobileMenuDrawerRef = useRef<MobileMenuDrawerRef>(null);
29
+ const addonPanelRef = useRef<MobileAddonsPanelRef>(null);
30
+ const insets = useSafeAreaInsets();
31
+
32
+ return (
33
+ <View style={{ flex: 1, paddingTop: insets.top }}>
34
+ <View style={{ flex: 1 }}>{children}</View>
35
+ <MobileMenuDrawer ref={mobileMenuDrawerRef}>
36
+ <Sidebar
37
+ extra={[]}
38
+ previewInitialized
39
+ indexError={undefined}
40
+ refs={{}}
41
+ setSelection={({ storyId: newStoryId }) => {
42
+ const channel = addons.getChannel();
43
+
44
+ channel.emit(SET_CURRENT_STORY, { storyId: newStoryId });
45
+ }}
46
+ status={{}}
47
+ index={storyHash}
48
+ storyId={story?.id}
49
+ refId={DEFAULT_REF_ID}
50
+ />
51
+ </MobileMenuDrawer>
52
+ <MobileAddonsPanel ref={addonPanelRef} storyId={story.id} />
53
+ <Container style={{ marginBottom: insets.bottom }}>
54
+ <Nav>
55
+ <Button
56
+ hitSlop={{ bottom: 10, left: 10, right: 10, top: 10 }}
57
+ onPress={() => mobileMenuDrawerRef.current.setMobileMenuOpen(true)}
58
+ >
59
+ <MenuIcon color={theme.color.mediumdark} />
60
+ <Text>
61
+ {story.title}/{story.name}
62
+ </Text>
63
+ </Button>
64
+
65
+ <IconButton
66
+ onPress={() => addonPanelRef.current.setAddonsPanelOpen(true)}
67
+ Icon={BottomBarToggleIcon}
68
+ />
69
+ </Nav>
70
+ </Container>
71
+ </View>
72
+ );
73
+ };
74
+
75
+ const Nav = styled.View({
76
+ display: 'flex',
77
+ flexDirection: 'row',
78
+ alignItems: 'center',
79
+ justifyContent: 'space-between',
80
+ width: '100%',
81
+ height: 40,
82
+ paddingHorizontal: 12,
83
+ });
84
+
85
+ const Container = styled.View(({ theme }) => ({
86
+ alignSelf: 'flex-end',
87
+ width: '100%',
88
+ zIndex: 10,
89
+ background: theme.barBg,
90
+ borderTopColor: theme.appBorderColor,
91
+ borderTopWidth: 1,
92
+ }));
93
+
94
+ const Button = styled.TouchableOpacity(({ theme }) => ({
95
+ display: 'flex',
96
+ flexDirection: 'row',
97
+ alignItems: 'center',
98
+ gap: 10,
99
+ color: theme.color.mediumdark,
100
+ fontSize: theme.typography.size?.s2 - 1,
101
+ paddingHorizontal: 7,
102
+ fontWeight: theme.typography.weight.bold,
103
+ }));
@@ -0,0 +1,90 @@
1
+ import type { FC, PropsWithChildren } from 'react';
2
+ import React, { createContext, useCallback, useContext, useMemo, useRef } from 'react';
3
+ import { BREAKPOINT } from './constants';
4
+ import { useWindowDimensions } from 'react-native';
5
+ // import {
6
+ // BottomSheetModal,
7
+ // BottomSheetModalProvider,
8
+ // BottomSheetScrollView,
9
+ // } from '@gorhom/bottom-sheet';
10
+
11
+ type LayoutContextType = {
12
+ // isMobileMenuOpen: boolean;
13
+ openMobileMenu: () => void;
14
+ closeMobileMenu: () => void;
15
+ // isMobileAboutOpen: boolean;
16
+ // setMobileAboutOpen: React.Dispatch<React.SetStateAction<boolean>>;
17
+ // isMobilePanelOpen: boolean;
18
+ // setMobilePanelOpen: React.Dispatch<React.SetStateAction<boolean>>;
19
+ isDesktop: boolean;
20
+ isMobile: boolean;
21
+ };
22
+
23
+ const LayoutContext = createContext<LayoutContextType>({
24
+ // isMobileMenuOpen: false,
25
+
26
+ openMobileMenu: () => {},
27
+ closeMobileMenu: () => {},
28
+ // isMobileAboutOpen: false,
29
+ // setMobileAboutOpen: () => {},
30
+ // isMobilePanelOpen: false,
31
+ // setMobilePanelOpen: () => {},
32
+
33
+ isDesktop: false,
34
+ isMobile: false,
35
+ });
36
+
37
+ export const LayoutProvider: FC<PropsWithChildren> = ({ children }) => {
38
+ // const [isMobileMenuOpen, setMobileMenuOpen] = useState(false);
39
+ // const [isMobileAboutOpen, setMobileAboutOpen] = useState(false);
40
+ // const [isMobilePanelOpen, setMobilePanelOpen] = useState(false);
41
+ const { width } = useWindowDimensions();
42
+ const isDesktop = width >= BREAKPOINT;
43
+ const isMobile = !isDesktop;
44
+ // const bottomSheetModalRef = useRef<BottomSheetModal>(null);
45
+
46
+ const openMobileMenu = useCallback(() => {
47
+ // bottomSheetModalRef.current?.present();
48
+ }, []);
49
+ const closeMobileMenu = useCallback(() => {
50
+ // bottomSheetModalRef.current?.dismiss();
51
+ }, []);
52
+
53
+ const contextValue = useMemo(
54
+ () => ({
55
+ // isMobileMenuOpen,
56
+ openMobileMenu,
57
+ closeMobileMenu,
58
+ // isMobileAboutOpen,
59
+ // setMobileAboutOpen,
60
+ // isMobilePanelOpen,
61
+ // setMobilePanelOpen,
62
+ isDesktop,
63
+ isMobile,
64
+ }),
65
+ [
66
+ // isMobileMenuOpen,
67
+ openMobileMenu,
68
+ closeMobileMenu,
69
+ // // isMobileAboutOpen,
70
+ // setMobileAboutOpen,
71
+ // isMobilePanelOpen,
72
+ // setMobilePanelOpen,
73
+ isDesktop,
74
+ isMobile,
75
+ ]
76
+ );
77
+
78
+ return (
79
+ // <BottomSheetModalProvider>
80
+ <>
81
+ <LayoutContext.Provider value={contextValue}>{children}</LayoutContext.Provider>
82
+ {/* <BottomSheetModal ref={bottomSheetModalRef} snapPoints={['70%', '50%']}>
83
+ <BottomSheetScrollView>bla</BottomSheetScrollView>
84
+ </BottomSheetModal> */}
85
+ </>
86
+ // </BottomSheetModalProvider>
87
+ );
88
+ };
89
+
90
+ export const useLayout = () => useContext(LayoutContext);
@@ -0,0 +1,166 @@
1
+ import { BottomSheetModal, BottomSheetScrollView } from '@gorhom/bottom-sheet';
2
+ import { addons } from '@storybook/manager-api';
3
+ import { styled } from '@storybook/react-native-theming';
4
+ import { Addon_TypesEnum } from '@storybook/types';
5
+ import { forwardRef, useImperativeHandle, useRef, useState } from 'react';
6
+ import { Text, View } from 'react-native';
7
+ import { ScrollView } from 'react-native-gesture-handler';
8
+ import { useReducedMotion } from 'react-native-reanimated';
9
+ import { useSafeAreaInsets } from 'react-native-safe-area-context';
10
+
11
+ import { IconButton } from './IconButton';
12
+ import { CloseIcon } from './icon/CloseIcon';
13
+
14
+ export interface MobileAddonsPanelRef {
15
+ isAddonsPanelOpen: boolean;
16
+ setAddonsPanelOpen: (isOpen: boolean) => void;
17
+ }
18
+
19
+ export const MobileAddonsPanel = forwardRef<MobileAddonsPanelRef, { storyId?: string }>(
20
+ ({ storyId }, ref) => {
21
+ const [isAddonsPanelOpen, setAddonsPanelOpen] = useState(false);
22
+ const reducedMotion = useReducedMotion();
23
+
24
+ const addonsPanelBottomSheetRef = useRef<BottomSheetModal>(null);
25
+ const insets = useSafeAreaInsets();
26
+
27
+ const panels = addons.getElements(Addon_TypesEnum.PANEL);
28
+ const [addonSelected, setAddonSelected] = useState(Object.keys(panels)[0]);
29
+
30
+ useImperativeHandle(ref, () => ({
31
+ isAddonsPanelOpen,
32
+ setAddonsPanelOpen: (open: boolean) => {
33
+ if (open) {
34
+ setAddonsPanelOpen(true);
35
+ addonsPanelBottomSheetRef.current?.present();
36
+ } else {
37
+ setAddonsPanelOpen(false);
38
+ addonsPanelBottomSheetRef.current?.dismiss();
39
+ }
40
+ },
41
+ }));
42
+
43
+ return (
44
+ <BottomSheetModal
45
+ ref={addonsPanelBottomSheetRef}
46
+ index={1}
47
+ animateOnMount={!reducedMotion}
48
+ onDismiss={() => {
49
+ setAddonsPanelOpen(false);
50
+ }}
51
+ snapPoints={['25%', '50%']}
52
+ style={{
53
+ paddingTop: 8,
54
+ }}
55
+ containerStyle={{}}
56
+ backgroundStyle={{
57
+ borderRadius: 0,
58
+ borderTopColor: 'lightgrey',
59
+ borderTopWidth: 1,
60
+ }}
61
+ keyboardBehavior="interactive"
62
+ keyboardBlurBehavior="restore"
63
+ enableDismissOnClose
64
+ enableHandlePanningGesture={true}
65
+ enableContentPanningGesture={true}
66
+ // enablePanDownToClose={false}
67
+ stackBehavior="replace"
68
+ >
69
+ <View style={{ flex: 1 }}>
70
+ <View style={{ flexDirection: 'row' }}>
71
+ <ScrollView
72
+ horizontal
73
+ showsHorizontalScrollIndicator={false}
74
+ contentContainerStyle={{
75
+ paddingHorizontal: 8,
76
+ // alignItems: 'center',
77
+ justifyContent: 'center',
78
+ }}
79
+ >
80
+ {Object.values(panels).map(({ id, title }) => {
81
+ const resolvedTitle = typeof title === 'function' ? title({}) : title;
82
+
83
+ return (
84
+ <Tab
85
+ key={id}
86
+ active={id === addonSelected}
87
+ onPress={() => setAddonSelected(id)}
88
+ text={resolvedTitle}
89
+ />
90
+ );
91
+ })}
92
+ </ScrollView>
93
+ <IconButton
94
+ style={{
95
+ marginRight: 4,
96
+ marginBottom: 4,
97
+ alignItems: 'center',
98
+ justifyContent: 'center',
99
+ }}
100
+ hitSlop={{ top: 10, right: 10, bottom: 10, left: 10 }}
101
+ Icon={CloseIcon}
102
+ onPress={() => {
103
+ setAddonsPanelOpen(false);
104
+ addonsPanelBottomSheetRef.current?.dismiss();
105
+ }}
106
+ />
107
+ </View>
108
+ <BottomSheetScrollView
109
+ keyboardShouldPersistTaps="handled"
110
+ contentContainerStyle={{
111
+ paddingBottom: insets.bottom + 16,
112
+ marginTop: 10,
113
+ paddingHorizontal: 16,
114
+ }}
115
+ >
116
+ {(() => {
117
+ if (!storyId) {
118
+ return (
119
+ <View style={{ alignItems: 'center', justifyContent: 'center' }}>
120
+ <Text>No Story Selected</Text>
121
+ </View>
122
+ );
123
+ }
124
+
125
+ if (Object.keys(panels).length === 0) {
126
+ return (
127
+ <View style={{ alignItems: 'center', justifyContent: 'center' }}>
128
+ <Text>No addons loaded.</Text>
129
+ </View>
130
+ );
131
+ }
132
+
133
+ return panels[addonSelected].render({ active: true });
134
+ })()}
135
+ </BottomSheetScrollView>
136
+ </View>
137
+ </BottomSheetModal>
138
+ );
139
+ }
140
+ );
141
+
142
+ const Tab = ({ active, onPress, text }: { active: boolean; onPress: () => void; text: string }) => {
143
+ return (
144
+ <TabButton active={active} onPress={onPress}>
145
+ <TabText active={active}>{text}</TabText>
146
+ </TabButton>
147
+ );
148
+ };
149
+
150
+ const TabButton = styled.TouchableOpacity<{ active: boolean }>(({ theme, active }) => ({
151
+ borderBottomWidth: active ? 2 : 0,
152
+ borderBottomColor: active ? theme.barSelectedColor : undefined,
153
+
154
+ overflow: 'hidden',
155
+ paddingHorizontal: 15,
156
+ justifyContent: 'center',
157
+ alignItems: 'center',
158
+ }));
159
+
160
+ const TabText = styled.Text<{ active: boolean }>(({ theme, active }) => ({
161
+ color: active ? theme.barSelectedColor : theme.color.mediumdark,
162
+ textAlign: 'center',
163
+ fontWeight: 'bold',
164
+ fontSize: 13,
165
+ lineHeight: 12,
166
+ }));
@@ -0,0 +1,75 @@
1
+ import {
2
+ BottomSheetBackdropProps,
3
+ BottomSheetModal,
4
+ BottomSheetScrollView,
5
+ BottomSheetBackdrop,
6
+ } from '@gorhom/bottom-sheet';
7
+ import { ReactNode, forwardRef, useImperativeHandle, useRef, useState } from 'react';
8
+ import { Keyboard } from 'react-native';
9
+ import { useReducedMotion } from 'react-native-reanimated';
10
+
11
+ interface MobileMenuDrawerProps {
12
+ children: ReactNode | ReactNode[];
13
+ }
14
+
15
+ export interface MobileMenuDrawerRef {
16
+ isMobileMenuOpen: boolean;
17
+ setMobileMenuOpen: (isOpen: boolean) => void;
18
+ }
19
+
20
+ export const BottomSheetBackdropComponent = (backdropComponentProps: BottomSheetBackdropProps) => (
21
+ <BottomSheetBackdrop
22
+ {...backdropComponentProps}
23
+ appearsOnIndex={0}
24
+ disappearsOnIndex={-1}
25
+ pressBehavior={'close'}
26
+ style={[backdropComponentProps.style, { backgroundColor: 'rgba(0,0,0,0.5)' }]}
27
+ />
28
+ );
29
+
30
+ export const MobileMenuDrawer = forwardRef<MobileMenuDrawerRef, MobileMenuDrawerProps>(
31
+ ({ children }, ref) => {
32
+ const [isMobileMenuOpen, setMobileMenuOpen] = useState(false);
33
+ const reducedMotion = useReducedMotion();
34
+
35
+ const menuBottomSheetRef = useRef<BottomSheetModal>(null);
36
+
37
+ useImperativeHandle(ref, () => ({
38
+ isMobileMenuOpen,
39
+ setMobileMenuOpen: (open: boolean) => {
40
+ if (open) {
41
+ setMobileMenuOpen(true);
42
+
43
+ menuBottomSheetRef.current?.present();
44
+ } else {
45
+ Keyboard.dismiss();
46
+ setMobileMenuOpen(false);
47
+ menuBottomSheetRef.current?.dismiss();
48
+ }
49
+ },
50
+ }));
51
+
52
+ return (
53
+ <BottomSheetModal
54
+ ref={menuBottomSheetRef}
55
+ index={1}
56
+ animateOnMount={!reducedMotion}
57
+ onDismiss={() => {
58
+ setMobileMenuOpen(false);
59
+ }}
60
+ snapPoints={['50%', '75%']}
61
+ enableDismissOnClose
62
+ enableHandlePanningGesture
63
+ enableContentPanningGesture
64
+ keyboardBehavior="extend"
65
+ keyboardBlurBehavior="restore"
66
+ stackBehavior="replace"
67
+ backdropComponent={BottomSheetBackdropComponent}
68
+ >
69
+ <BottomSheetScrollView keyboardShouldPersistTaps="handled">
70
+ {children}
71
+ </BottomSheetScrollView>
72
+ </BottomSheetModal>
73
+ );
74
+ }
75
+ );
package/src/Refs.tsx ADDED
@@ -0,0 +1,142 @@
1
+ import type { FC } from 'react';
2
+ import React, { useMemo, useCallback, useEffect, useState } from 'react';
3
+ import type { State } from '@storybook/manager-api';
4
+ import { useStorybookApi, useStorybookState } from '@storybook/manager-api';
5
+ import { styled } from '@storybook/react-native-theming';
6
+ // import { transparentize } from 'polished';
7
+
8
+ // import { AuthBlock, ErrorBlock, LoaderBlock, EmptyBlock } from './RefBlocks';
9
+
10
+ // import { RefIndicator } from './RefIndicator';
11
+
12
+ import { Tree } from './Tree';
13
+
14
+ import type { RefType } from './types';
15
+ import { getStateType } from './util/tree';
16
+ import { DEFAULT_REF_ID } from './constants';
17
+
18
+ // import { CollapseIcon } from './icon/CollapseIcon';
19
+
20
+ // import { getStateType } from '../../utils/tree';
21
+ // import { CollapseIcon } from './components/CollapseIcon';
22
+
23
+ export interface RefProps {
24
+ isLoading: boolean;
25
+ isBrowsing: boolean;
26
+ selectedStoryId: string | null;
27
+ setSelection: (selection: { refId: string; storyId: string }) => void;
28
+ // highlightedRef: MutableRefObject<Highlight>;
29
+ // setHighlighted: (highlight: Highlight) => void;
30
+ }
31
+
32
+ const Wrapper = styled.View<{ isMain: boolean }>(({}) => ({
33
+ position: 'relative',
34
+ }));
35
+
36
+ // const RefHead = styled.View(({ theme }) => ({
37
+ // display: 'flex',
38
+ // alignItems: 'center',
39
+ // justifyContent: 'space-between',
40
+ // background: 'transparent',
41
+
42
+ // width: '100%',
43
+ // marginTop: 20,
44
+ // paddingTop: 16,
45
+ // paddingBottom: 12,
46
+ // borderTopColor: theme.appBorderColor,
47
+ // borderTopWidth: 1,
48
+ // }));
49
+
50
+ // const RefTitle = styled.Text(({ theme }) => ({
51
+ // // textOverflow: 'ellipsis',
52
+ // // whiteSpace: 'nowrap',
53
+ // flex: 1,
54
+ // flexDirection: 'row',
55
+ // overflow: 'hidden',
56
+ // marginLeft: 2,
57
+ // fontWeight: theme.typography.weight.bold,
58
+ // fontSize: theme.typography.size.s2,
59
+ // lineHeight: 16,
60
+ // color:
61
+ // theme.base === 'light' ? theme.color.defaultText : transparentize(0.2, theme.color.defaultText),
62
+ // }));
63
+
64
+ // const CollapseButton = styled.TouchableOpacity(({}) => ({
65
+ // display: 'flex',
66
+ // flexDirection: 'row',
67
+ // paddingVertical: 0,
68
+ // paddingHorizontal: 8,
69
+ // gap: 6,
70
+ // alignItems: 'center',
71
+ // cursor: 'pointer',
72
+ // overflow: 'hidden',
73
+ // }));
74
+
75
+ export const Ref: FC<RefType & RefProps & { status?: State['status'] }> = React.memo(function Ref(
76
+ props
77
+ ) {
78
+ const { docsOptions } = useStorybookState();
79
+ const api = useStorybookApi();
80
+ const {
81
+ index,
82
+ id: refId,
83
+ title = refId,
84
+ isLoading: isLoadingMain,
85
+ isBrowsing,
86
+ selectedStoryId,
87
+ // highlightedRef,
88
+ // setHighlighted,
89
+ loginUrl,
90
+ type,
91
+ expanded = true,
92
+ indexError,
93
+ previewInitialized,
94
+ setSelection,
95
+ } = props;
96
+ const length = useMemo(() => (index ? Object.keys(index).length : 0), [index]);
97
+
98
+ const isLoadingInjected =
99
+ (type === 'auto-inject' && !previewInitialized) || type === 'server-checked';
100
+ const isLoading = isLoadingMain || isLoadingInjected || type === 'unknown';
101
+ const isError = !!indexError;
102
+ const isEmpty = !isLoading && length === 0;
103
+ const isAuthRequired = !!loginUrl && length === 0;
104
+
105
+ const state = getStateType(isLoading, isAuthRequired, isError, isEmpty);
106
+ const [isExpanded, setExpanded] = useState<boolean>(expanded);
107
+
108
+ useEffect(() => {
109
+ if (index && selectedStoryId && index[selectedStoryId]) {
110
+ setExpanded(true);
111
+ }
112
+ }, [setExpanded, index, selectedStoryId]);
113
+
114
+ const onSelectStoryId = useCallback(
115
+ (storyId: string) => {
116
+ setSelection({ refId, storyId });
117
+ return api && api.selectStory(storyId, DEFAULT_REF_ID);
118
+ },
119
+ [api, refId, setSelection]
120
+ );
121
+
122
+ return (
123
+ <>
124
+ {isExpanded && (
125
+ <Wrapper data-title={title} isMain={true}>
126
+ {state === 'ready' && (
127
+ <Tree
128
+ status={props.status}
129
+ isBrowsing={isBrowsing}
130
+ isMain={true}
131
+ refId={refId}
132
+ data={index}
133
+ docsMode={docsOptions?.docsMode}
134
+ selectedStoryId={selectedStoryId}
135
+ onSelectStoryId={onSelectStoryId}
136
+ />
137
+ )}
138
+ </Wrapper>
139
+ )}
140
+ </>
141
+ );
142
+ });