@storybook/react-native-ui-lite 9.0.0-beta.11

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 (42) hide show
  1. package/LICENSE +21 -0
  2. package/dist/index.d.ts +94 -0
  3. package/dist/index.js +5437 -0
  4. package/package.json +80 -0
  5. package/src/Button.stories.tsx +134 -0
  6. package/src/Button.tsx +172 -0
  7. package/src/Explorer.stories.tsx +40 -0
  8. package/src/Explorer.tsx +38 -0
  9. package/src/IconButton.tsx +10 -0
  10. package/src/Layout.stories.tsx +70 -0
  11. package/src/Layout.tsx +310 -0
  12. package/src/LayoutProvider.tsx +32 -0
  13. package/src/MobileAddonsPanel.tsx +195 -0
  14. package/src/MobileMenuDrawer.tsx +90 -0
  15. package/src/Refs.tsx +82 -0
  16. package/src/Search.tsx +234 -0
  17. package/src/SearchResults.stories.tsx +102 -0
  18. package/src/SearchResults.tsx +254 -0
  19. package/src/SelectedNodeProvider.tsx +58 -0
  20. package/src/Sidebar.stories.tsx +188 -0
  21. package/src/Sidebar.tsx +131 -0
  22. package/src/StorageProvider.tsx +21 -0
  23. package/src/StorybookLogo.stories.tsx +76 -0
  24. package/src/StorybookLogo.tsx +108 -0
  25. package/src/Tree.stories.tsx +177 -0
  26. package/src/Tree.tsx +390 -0
  27. package/src/TreeNode.stories.tsx +117 -0
  28. package/src/TreeNode.tsx +154 -0
  29. package/src/assets/react-native-logo.png +0 -0
  30. package/src/constants.ts +4 -0
  31. package/src/hooks/useExpanded.ts +64 -0
  32. package/src/hooks/useLastViewed.ts +48 -0
  33. package/src/hooks/useStoreState.ts +27 -0
  34. package/src/icon/iconDataUris.tsx +365 -0
  35. package/src/index.tsx +11 -0
  36. package/src/mockdata.large.ts +25217 -0
  37. package/src/mockdata.ts +287 -0
  38. package/src/types.ts +66 -0
  39. package/src/util/StoryHash.ts +249 -0
  40. package/src/util/status.tsx +87 -0
  41. package/src/util/tree.ts +93 -0
  42. package/src/util/useStyle.ts +28 -0
@@ -0,0 +1,188 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import React from 'react';
3
+ import type { IndexHash, State } from 'storybook/internal/manager-api';
4
+ import { Button } from './Button';
5
+ import { LayoutProvider } from './LayoutProvider';
6
+ import { Sidebar } from './Sidebar';
7
+ import { DEFAULT_REF_ID } from './constants';
8
+ import { mockDataset } from './mockdata';
9
+ import type { RefType } from './types';
10
+
11
+ const index = mockDataset.withRoot as IndexHash;
12
+ const storyId = 'root-1-child-a2--grandchild-a1-1';
13
+
14
+ const meta = {
15
+ component: Sidebar,
16
+ title: 'UI/Sidebar/Sidebar',
17
+ excludeStories: /.*Data$/,
18
+ parameters: { layout: 'fullscreen' },
19
+ args: {
20
+ previewInitialized: true,
21
+ index: index,
22
+ storyId,
23
+ refId: DEFAULT_REF_ID,
24
+ refs: {},
25
+ status: {},
26
+ setSelection: () => {},
27
+ },
28
+ decorators: [(storyFn) => <LayoutProvider>{storyFn()}</LayoutProvider>],
29
+ } satisfies Meta<typeof Sidebar>;
30
+
31
+ export default meta;
32
+
33
+ type Story = StoryObj<typeof meta>;
34
+
35
+ const refs: Record<string, RefType> = {
36
+ optimized: {
37
+ id: 'optimized',
38
+ title: 'This is a ref',
39
+ url: 'https://example.com',
40
+ type: 'lazy',
41
+ index,
42
+ previewInitialized: true,
43
+ },
44
+ };
45
+
46
+ const indexError = new Error('Failed to load index');
47
+
48
+ const refsError = {
49
+ optimized: {
50
+ ...refs.optimized,
51
+ index: undefined as IndexHash,
52
+ indexError,
53
+ },
54
+ };
55
+
56
+ const refsEmpty = {
57
+ optimized: {
58
+ ...refs.optimized,
59
+ index: {} as IndexHash,
60
+ },
61
+ };
62
+
63
+ export const Simple: Story = {};
64
+
65
+ export const Loading: Story = {
66
+ args: {
67
+ previewInitialized: false,
68
+ index: undefined,
69
+ },
70
+ };
71
+
72
+ export const Empty: Story = {
73
+ args: {
74
+ index: {},
75
+ },
76
+ };
77
+
78
+ export const IndexError: Story = {
79
+ args: {
80
+ indexError,
81
+ },
82
+ };
83
+
84
+ export const WithRefs: Story = {
85
+ args: {
86
+ refs,
87
+ },
88
+ };
89
+
90
+ export const LoadingWithRefs: Story = {
91
+ args: {
92
+ ...Loading.args,
93
+ refs,
94
+ },
95
+ };
96
+
97
+ export const LoadingWithRefError: Story = {
98
+ args: {
99
+ ...Loading.args,
100
+ refs: refsError,
101
+ },
102
+ };
103
+
104
+ export const WithRefEmpty: Story = {
105
+ args: {
106
+ ...Empty.args,
107
+ refs: refsEmpty,
108
+ },
109
+ };
110
+
111
+ export const StatusesCollapsed: Story = {
112
+ args: {
113
+ status: Object.entries(index).reduce<State['status']>((acc, [id, item]) => {
114
+ if (item.type !== 'story') {
115
+ return acc;
116
+ }
117
+
118
+ if (item.name.includes('B')) {
119
+ return {
120
+ ...acc,
121
+ [id]: {
122
+ addonA: { status: 'warn', title: 'Addon A', description: 'We just wanted you to know' },
123
+ addonB: { status: 'error', title: 'Addon B', description: 'This is a big deal!' },
124
+ },
125
+ };
126
+ }
127
+ return acc;
128
+ }, {}),
129
+ },
130
+ };
131
+
132
+ export const StatusesOpen: Story = {
133
+ ...StatusesCollapsed,
134
+ args: {
135
+ ...StatusesCollapsed.args,
136
+ status: Object.entries(index).reduce<State['status']>((acc, [id, item]) => {
137
+ if (item.type !== 'story') {
138
+ return acc;
139
+ }
140
+
141
+ return {
142
+ ...acc,
143
+ [id]: {
144
+ addonA: { status: 'warn', title: 'Addon A', description: 'We just wanted you to know' },
145
+ addonB: { status: 'error', title: 'Addon B', description: 'This is a big deal!' },
146
+ },
147
+ };
148
+ }, {}),
149
+ },
150
+ };
151
+
152
+ export const Searching: Story = {
153
+ ...StatusesOpen,
154
+ parameters: { chromatic: { delay: 2200 } },
155
+ };
156
+
157
+ /**
158
+ * Given the following sequence of events:
159
+ * 1. Story is selected at the top of the sidebar
160
+ * 2. The sidebar is scrolled to the bottom
161
+ * 3. Some re-rendering happens because of a changed state/prop
162
+ * The sidebar should remain scrolled to the bottom
163
+ */
164
+ export const Scrolled: Story = {
165
+ parameters: {
166
+ // we need a very short viewport
167
+ viewport: {
168
+ defaultViewport: 'mobile1',
169
+ defaultOrientation: 'landscape',
170
+ },
171
+ },
172
+ args: {
173
+ storyId: 'group-1--child-b1',
174
+ },
175
+ render: function Render(args) {
176
+ const [, setState] = React.useState(0);
177
+ return (
178
+ <>
179
+ <Button
180
+ style={{ position: 'absolute', zIndex: 10 }}
181
+ onPress={() => setState(() => Math.random())}
182
+ text="Change state"
183
+ />
184
+ <Sidebar {...args} />
185
+ </>
186
+ );
187
+ },
188
+ };
@@ -0,0 +1,131 @@
1
+ import React, { useMemo } from 'react';
2
+ import { styled } from '@storybook/react-native-theming';
3
+ import type { State } from 'storybook/internal/manager-api';
4
+ import type { API_LoadedRefData } from 'storybook/internal/types';
5
+ import { Explorer } from './Explorer';
6
+ import { Search } from './Search';
7
+ import { SearchResults } from './SearchResults';
8
+ import type { CombinedDataset, Selection } from './types';
9
+ import { useLastViewed } from './hooks/useLastViewed';
10
+ import { DEFAULT_REF_ID } from './constants';
11
+ import { View } from 'react-native';
12
+
13
+ const Container = styled.View(({ theme }) => ({
14
+ width: '100%',
15
+ height: '100%',
16
+ display: 'flex',
17
+ flexDirection: 'column',
18
+ backgroundColor: theme.background.content,
19
+ }));
20
+
21
+ const Top = styled.View({
22
+ paddingLeft: 4,
23
+ paddingRight: 4,
24
+ paddingTop: 16,
25
+ flex: 1,
26
+ flexDirection: 'row',
27
+ });
28
+
29
+ const Swap = React.memo(function Swap({
30
+ children,
31
+ condition,
32
+ }: {
33
+ children: React.ReactNode;
34
+ condition: boolean;
35
+ }) {
36
+ const [a, b] = React.Children.toArray(children);
37
+ return (
38
+ <>
39
+ <View style={{ display: condition ? 'flex' : 'none' }}>{a}</View>
40
+ <View style={{ display: condition ? 'none' : 'flex' }}>{b}</View>
41
+ </>
42
+ );
43
+ });
44
+
45
+ export const useCombination = (
46
+ index: SidebarProps['index'],
47
+ indexError: SidebarProps['indexError'],
48
+ previewInitialized: SidebarProps['previewInitialized'],
49
+ status: SidebarProps['status'],
50
+ refs: SidebarProps['refs']
51
+ ): CombinedDataset => {
52
+ const hash = useMemo(
53
+ () => ({
54
+ [DEFAULT_REF_ID]: {
55
+ index,
56
+ indexError,
57
+ previewInitialized,
58
+ status,
59
+ title: null,
60
+ id: DEFAULT_REF_ID,
61
+ url: 'iframe.html',
62
+ },
63
+ ...refs,
64
+ }),
65
+ [refs, index, indexError, previewInitialized, status]
66
+ );
67
+ return useMemo(() => ({ hash, entries: Object.entries(hash) }), [hash]);
68
+ };
69
+
70
+ export interface SidebarProps extends API_LoadedRefData {
71
+ refs: State['refs'];
72
+ status: State['status'];
73
+ storyId?: string;
74
+ refId?: string;
75
+ menuHighlighted?: boolean;
76
+ setSelection: (selection: Selection) => void;
77
+ }
78
+
79
+ export const Sidebar = React.memo(function Sidebar({
80
+ storyId = null,
81
+ refId = DEFAULT_REF_ID,
82
+ index,
83
+ indexError,
84
+ status,
85
+ previewInitialized,
86
+ refs = {},
87
+ setSelection,
88
+ }: SidebarProps) {
89
+ const selected: Selection = useMemo(() => storyId && { storyId, refId }, [storyId, refId]);
90
+ const dataset = useCombination(index, indexError, previewInitialized, status, refs);
91
+ const lastViewedProps = useLastViewed(selected);
92
+
93
+ return (
94
+ <Container style={{ paddingHorizontal: 10 }}>
95
+ <Top>
96
+ {/* <Heading
97
+ className="sidebar-header"
98
+ menuHighlighted={menuHighlighted}
99
+ menu={menu}
100
+ extra={extra}
101
+ skipLinkHref="#storybook-preview-wrapper"
102
+ isLoading={isLoading}
103
+ onMenuClick={onMenuClick}
104
+ /> */}
105
+ <Search dataset={dataset} setSelection={setSelection} {...lastViewedProps}>
106
+ {({ query, results, isBrowsing, closeMenu, getItemProps, highlightedIndex }) => (
107
+ <Swap condition={isBrowsing}>
108
+ <Explorer
109
+ dataset={dataset}
110
+ selected={selected}
111
+ isLoading={false}
112
+ isBrowsing={isBrowsing} //todo check me
113
+ setSelection={setSelection}
114
+ />
115
+
116
+ <SearchResults
117
+ query={query}
118
+ results={results}
119
+ closeMenu={closeMenu}
120
+ getItemProps={getItemProps}
121
+ highlightedIndex={highlightedIndex}
122
+ isLoading={false}
123
+ clearLastViewed={lastViewedProps.clearLastViewed}
124
+ />
125
+ </Swap>
126
+ )}
127
+ </Search>
128
+ </Top>
129
+ </Container>
130
+ );
131
+ });
@@ -0,0 +1,21 @@
1
+ import type { FC, PropsWithChildren } from 'react';
2
+ import { createContext, useContext } from 'react';
3
+
4
+ export interface Storage {
5
+ getItem: (key: string) => Promise<string | null>;
6
+ setItem: (key: string, value: string) => Promise<void>;
7
+ }
8
+
9
+ const StorageContext = createContext<Storage>({
10
+ getItem: async () => null,
11
+ setItem: async () => {},
12
+ });
13
+
14
+ export const StorageProvider: FC<PropsWithChildren<{ storage: Storage }>> = ({
15
+ storage,
16
+ children,
17
+ }) => {
18
+ return <StorageContext.Provider value={storage}>{children}</StorageContext.Provider>;
19
+ };
20
+
21
+ export const useStorage = () => useContext(StorageContext);
@@ -0,0 +1,76 @@
1
+ import type { StoryObj, Meta } from '@storybook/react';
2
+ import { StorybookLogo } from './StorybookLogo';
3
+ import { Theme, theme } from '@storybook/react-native-theming';
4
+ import { Text } from 'react-native';
5
+
6
+ const meta = {
7
+ component: StorybookLogo,
8
+ title: 'UI/StorybookLogo',
9
+ args: {
10
+ theme: null,
11
+ },
12
+ } satisfies Meta<typeof StorybookLogo>;
13
+
14
+ export default meta;
15
+
16
+ type Story = StoryObj<typeof meta>;
17
+
18
+ export const TitleLogo: Story = {
19
+ args: {
20
+ theme: {
21
+ ...theme,
22
+ brand: { title: 'React Native' },
23
+ } satisfies Theme,
24
+ },
25
+ };
26
+
27
+ export const ImageLogo: Story = {
28
+ args: {
29
+ theme: {
30
+ ...theme,
31
+ brand: {
32
+ image: {
33
+ uri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/React-icon.svg/512px-React-icon.svg.png',
34
+ height: 25,
35
+ width: 25,
36
+ },
37
+ },
38
+ } satisfies Theme,
39
+ },
40
+ };
41
+
42
+ export const ImageUrlLogo: Story = {
43
+ args: {
44
+ theme: {
45
+ ...theme,
46
+ brand: {
47
+ image: {
48
+ uri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/React-icon.svg/512px-React-icon.svg.png',
49
+ width: 25,
50
+ height: 25,
51
+ },
52
+ title: 'React Native',
53
+ url: 'https://reactnative.dev',
54
+ },
55
+ } satisfies Theme,
56
+ },
57
+ };
58
+
59
+ export const ImageSourceLogo: Story = {
60
+ args: {
61
+ theme: {
62
+ ...theme,
63
+ brand: {
64
+ image: require('./assets/react-native-logo.png'),
65
+ resizeMode: 'contain',
66
+ url: 'https://reactnative.dev',
67
+ },
68
+ } satisfies Theme,
69
+ },
70
+ };
71
+
72
+ export const ImageElementLogo: Story = {
73
+ args: {
74
+ theme: { ...theme, brand: { image: <Text>Element</Text> } } satisfies Theme,
75
+ },
76
+ };
@@ -0,0 +1,108 @@
1
+ import { Theme } from '@storybook/react-native-theming';
2
+ import { FC, isValidElement, ReactElement, useEffect, useMemo } from 'react';
3
+ import { Image, Linking, StyleProp, Text, TextStyle, TouchableOpacity } from 'react-native';
4
+ import { DarkLogo, Logo } from './icon/iconDataUris';
5
+
6
+ const WIDTH = 125;
7
+ const HEIGHT = 25;
8
+
9
+ const NoBrandLogo: FC<{ theme: Theme }> = ({ theme }) =>
10
+ theme.base === 'light' ? (
11
+ <Logo height={HEIGHT} width={WIDTH} />
12
+ ) : (
13
+ <DarkLogo height={HEIGHT} width={WIDTH} />
14
+ );
15
+
16
+ function isElement(value: unknown): value is ReactElement {
17
+ return isValidElement(value);
18
+ }
19
+
20
+ const BrandLogo: FC<{ theme: Theme }> = ({ theme }) => {
21
+ const imageHasNoWidthOrHeight =
22
+ typeof theme.brand.image === 'object' &&
23
+ typeof theme.brand.image === 'object' &&
24
+ 'uri' in theme.brand.image &&
25
+ (!('height' in theme.brand.image) || !('width' in theme.brand.image));
26
+
27
+ useEffect(() => {
28
+ if (imageHasNoWidthOrHeight) {
29
+ console.warn(
30
+ "STORYBOOK: When using a remote image as the brand logo, you must also set the width and height.\nFor example: brand: { image: { uri: 'https://sb.com/img.png', height: 25, width: 25}}"
31
+ );
32
+ }
33
+ }, [imageHasNoWidthOrHeight]);
34
+
35
+ if (!theme.brand.image) {
36
+ return null;
37
+ }
38
+
39
+ if (isElement(theme.brand.image)) {
40
+ return theme.brand.image;
41
+ }
42
+
43
+ const image = (
44
+ <Image
45
+ source={theme.brand.image}
46
+ resizeMode={theme.brand.resizeMode ?? 'contain'}
47
+ style={imageHasNoWidthOrHeight ? { width: WIDTH, height: HEIGHT } : undefined}
48
+ />
49
+ );
50
+
51
+ if (theme.brand.url) {
52
+ return (
53
+ <TouchableOpacity
54
+ onPress={() => {
55
+ if (theme.brand.url) Linking.openURL(theme.brand.url);
56
+ }}
57
+ >
58
+ {image}
59
+ </TouchableOpacity>
60
+ );
61
+ } else {
62
+ return image;
63
+ }
64
+ };
65
+
66
+ const BrandTitle: FC<{ theme: Theme }> = ({ theme }) => {
67
+ const brandTitleStyle = useMemo<StyleProp<TextStyle>>(() => {
68
+ return {
69
+ width: WIDTH,
70
+ height: HEIGHT,
71
+ color: theme.color.defaultText,
72
+ fontSize: theme.typography.size.m1,
73
+ };
74
+ }, [theme]);
75
+
76
+ const title = (
77
+ <Text style={brandTitleStyle} numberOfLines={1} ellipsizeMode="tail">
78
+ {theme.brand.title}
79
+ </Text>
80
+ );
81
+
82
+ if (theme.brand.url) {
83
+ return (
84
+ <TouchableOpacity
85
+ onPress={() => {
86
+ if (theme.brand.url) Linking.openURL(theme.brand.url);
87
+ }}
88
+ >
89
+ {title}
90
+ </TouchableOpacity>
91
+ );
92
+ } else {
93
+ return title;
94
+ }
95
+ };
96
+
97
+ export const StorybookLogo: FC<{ theme: Theme }> = ({ theme }) => {
98
+ const image = useMemo(() => theme.brand?.image, [theme.brand?.image]);
99
+ const title = useMemo(() => theme.brand?.title, [theme.brand?.title]);
100
+
101
+ if (image) {
102
+ return <BrandLogo theme={theme} />;
103
+ } else if (title) {
104
+ return <BrandTitle theme={theme} />;
105
+ } else {
106
+ return <NoBrandLogo theme={theme} />;
107
+ }
108
+ };
@@ -0,0 +1,177 @@
1
+ import { useState } from 'react';
2
+ import type { ComponentEntry, IndexHash } from 'storybook/internal/manager-api';
3
+ import type { StoryObj, Meta } from '@storybook/react';
4
+ import { Tree } from './Tree';
5
+ import type { Dataset } from './types';
6
+ import { index } from './mockdata.large';
7
+ import { DEFAULT_REF_ID } from './constants';
8
+ import { ScrollView, Text } from 'react-native';
9
+
10
+ const customViewports = {
11
+ sized: {
12
+ name: 'Sized',
13
+ styles: {
14
+ width: '380px',
15
+ height: '90%',
16
+ },
17
+ },
18
+ };
19
+
20
+ const meta = {
21
+ component: Tree,
22
+ title: 'UI/Sidebar/Tree',
23
+ excludeStories: /.*Data$/,
24
+ parameters: {
25
+ layout: 'fullscreen',
26
+ theme: 'light',
27
+ viewport: {
28
+ defaultViewport: 'sized',
29
+ viewports: customViewports,
30
+ },
31
+ },
32
+ decorators: [
33
+ (Story) => (
34
+ <ScrollView>
35
+ <Story />
36
+ </ScrollView>
37
+ ),
38
+ ],
39
+ } satisfies Meta<typeof Tree>;
40
+
41
+ export default meta;
42
+
43
+ const storyId = Object.values(index).find((story) => story.type === 'story').id;
44
+
45
+ type Story = StoryObj<typeof meta>;
46
+
47
+ export const Full: Story = {
48
+ args: {
49
+ docsMode: false,
50
+ isBrowsing: true,
51
+ isMain: true,
52
+ refId: DEFAULT_REF_ID,
53
+ data: undefined,
54
+ onSelectStoryId: () => {},
55
+ selectedStoryId: storyId,
56
+ status: undefined,
57
+ },
58
+ render: function Render(args) {
59
+ const [selectedId, setSelectedId] = useState(storyId);
60
+ return (
61
+ <Tree {...args} data={index} selectedStoryId={selectedId} onSelectStoryId={setSelectedId} />
62
+ );
63
+ },
64
+ };
65
+ export const Dark: Story = {
66
+ ...Full,
67
+ parameters: { theme: 'dark' },
68
+ };
69
+
70
+ export const SingleStoryComponents: Story = {
71
+ args: {
72
+ docsMode: false,
73
+ isBrowsing: true,
74
+ isMain: true,
75
+ refId: DEFAULT_REF_ID,
76
+ data: undefined,
77
+ onSelectStoryId: () => {},
78
+ selectedStoryId: storyId,
79
+ status: undefined,
80
+ },
81
+ render: function Render(args) {
82
+ const [selectedId, setSelectedId] = useState('tooltip-tooltipbuildlist--default');
83
+ return (
84
+ <Tree
85
+ {...args}
86
+ data={{
87
+ ...{
88
+ single: {
89
+ tags: [],
90
+ type: 'component',
91
+ name: 'Single',
92
+ id: 'single',
93
+ parent: null,
94
+ depth: 0,
95
+ children: ['single--single'],
96
+ renderLabel: () => <Text>🔥 Single</Text>,
97
+ },
98
+ 'single--single': {
99
+ type: 'story',
100
+ id: 'single--single',
101
+ title: 'Single',
102
+ name: 'Single',
103
+ tags: [],
104
+ prepared: true,
105
+ args: {},
106
+ argTypes: {},
107
+ initialArgs: {},
108
+ depth: 1,
109
+ parent: 'single',
110
+ renderLabel: () => <Text>🔥 Single</Text>,
111
+ importPath: './single.stories.js',
112
+ },
113
+ },
114
+ ...Object.keys(index).reduce((acc, key) => {
115
+ if (key === 'tooltip-tooltipselect--default') {
116
+ acc['tooltip-tooltipselect--tooltipselect'] = {
117
+ ...index[key],
118
+ id: 'tooltip-tooltipselect--tooltipselect',
119
+ name: 'TooltipSelect',
120
+ };
121
+ return acc;
122
+ }
123
+ if (key === 'tooltip-tooltipselect') {
124
+ acc[key] = {
125
+ ...(index[key] as ComponentEntry),
126
+ children: ['tooltip-tooltipselect--tooltipselect'],
127
+ };
128
+ return acc;
129
+ }
130
+ if (key.startsWith('tooltip')) {
131
+ acc[key] = index[key];
132
+ }
133
+ return acc;
134
+ }, {} as IndexHash),
135
+ }}
136
+ selectedStoryId={selectedId}
137
+ onSelectStoryId={setSelectedId}
138
+ />
139
+ );
140
+ },
141
+ };
142
+
143
+ const dataWithStoryName: Dataset = {
144
+ images: {
145
+ name: 'Testing storyNames support',
146
+ id: 'images',
147
+ depth: 0,
148
+ children: [],
149
+ type: 'component',
150
+ tags: [],
151
+ },
152
+ };
153
+
154
+ export const WithStoryNames: Story = {
155
+ name: 'Story with a storyName',
156
+ args: {
157
+ docsMode: false,
158
+ isBrowsing: true,
159
+ isMain: true,
160
+ refId: DEFAULT_REF_ID,
161
+ data: undefined,
162
+ onSelectStoryId: () => {},
163
+ selectedStoryId: 'some-component',
164
+ status: undefined,
165
+ },
166
+ render: function Render(args) {
167
+ const [selectedId, setSelectedId] = useState(storyId);
168
+ return (
169
+ <Tree
170
+ {...args}
171
+ data={dataWithStoryName}
172
+ selectedStoryId={selectedId}
173
+ onSelectStoryId={setSelectedId}
174
+ />
175
+ );
176
+ },
177
+ };