@storybook/react-native-ui 9.0.0-beta.1 → 9.0.0-beta.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storybook/react-native-ui",
3
- "version": "9.0.0-beta.1",
3
+ "version": "9.0.0-beta.10",
4
4
  "description": "ui components for react native storybook",
5
5
  "keywords": [
6
6
  "react",
@@ -49,17 +49,17 @@
49
49
  },
50
50
  "devDependencies": {
51
51
  "@types/jest": "^29.4.3",
52
- "@types/react": "~18.3.12",
52
+ "@types/react": "~19.0.10",
53
53
  "babel-jest": "^29.7.0",
54
54
  "jest": "^29.7.0",
55
- "react-test-renderer": "^18.3.1",
55
+ "react-test-renderer": "^19.1.0",
56
56
  "ts-dedent": "^2.2.0",
57
57
  "tsup": "^7.2.0",
58
- "typescript": "^5.3.3"
58
+ "typescript": "~5.8.3"
59
59
  },
60
60
  "dependencies": {
61
- "@storybook/react": "9.0.0-beta.4",
62
- "@storybook/react-native-theming": "^9.0.0-beta.1",
61
+ "@storybook/react": "9.0.0-beta.10",
62
+ "@storybook/react-native-theming": "^9.0.0-beta.10",
63
63
  "fuse.js": "^7.0.0",
64
64
  "memoizerific": "^1.11.3",
65
65
  "polished": "^4.3.1",
@@ -73,7 +73,7 @@
73
73
  "react-native-reanimated": ">=3",
74
74
  "react-native-safe-area-context": "*",
75
75
  "react-native-svg": ">=14",
76
- "storybook": "9.0.0-beta.4"
76
+ "storybook": "9.0.0-beta.10"
77
77
  },
78
78
  "engines": {
79
79
  "node": ">=18.0.0"
@@ -81,5 +81,5 @@
81
81
  "publishConfig": {
82
82
  "access": "public"
83
83
  },
84
- "gitHead": "41dd93e39512d4df2258fd68055b54fc361962f3"
84
+ "gitHead": "bce7f35509d03e5a5efabb8862e993ea98e201d6"
85
85
  }
@@ -1,6 +1,6 @@
1
1
  import { BottomSheetModal } from '@gorhom/bottom-sheet';
2
2
  import { addons } from 'storybook/internal/manager-api';
3
- import { styled } from '@storybook/react-native-theming';
3
+ import { styled, useTheme } from '@storybook/react-native-theming';
4
4
  import { Addon_TypesEnum } from 'storybook/internal/types';
5
5
  import { forwardRef, useImperativeHandle, useMemo, useRef, useState } from 'react';
6
6
  import { Platform, StyleProp, Text, View, ViewStyle, useWindowDimensions } from 'react-native';
@@ -12,7 +12,6 @@ import Animated, {
12
12
  useSharedValue,
13
13
  } from 'react-native-reanimated';
14
14
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
15
- import { useTheme } from '@storybook/react-native-theming';
16
15
  import { IconButton } from './IconButton';
17
16
  import { CloseIcon } from './icon/CloseIcon';
18
17
  import { useStyle } from './util/useStyle';
@@ -108,6 +107,8 @@ export const MobileAddonsPanel = forwardRef<MobileAddonsPanelRef, { storyId?: st
108
107
  }
109
108
  );
110
109
 
110
+ MobileAddonsPanel.displayName = 'MobileAddonsPanel';
111
+
111
112
  const addonsTabsContainerStyle = {
112
113
  flex: 1,
113
114
  } satisfies StyleProp<ViewStyle>;
package/src/Refs.tsx CHANGED
@@ -13,70 +13,70 @@ export interface RefProps {
13
13
  setSelection: (selection: { refId: string; storyId: string }) => void;
14
14
  }
15
15
 
16
- const Wrapper = styled.View<{ isMain: boolean }>(({}) => ({
16
+ const Wrapper = styled.View<{ isMain: boolean }>(() => ({
17
17
  position: 'relative',
18
18
  }));
19
19
 
20
- export const Ref: FC<RefType & RefProps & { status?: State['status'] }> = React.memo(function Ref(
21
- props
22
- ) {
23
- const {
24
- index,
25
- id: refId,
26
- title = refId,
27
- isLoading: isLoadingMain,
28
- isBrowsing,
29
- selectedStoryId,
30
- loginUrl,
31
- type,
32
- expanded = true,
33
- indexError,
34
- previewInitialized,
35
- setSelection,
36
- } = props;
37
- const length = useMemo(() => (index ? Object.keys(index).length : 0), [index]);
20
+ export const Ref: FC<RefType & RefProps & { status?: State['status'] }> = React.memo(
21
+ function Ref(props) {
22
+ const {
23
+ index,
24
+ id: refId,
25
+ title = refId,
26
+ isLoading: isLoadingMain,
27
+ isBrowsing,
28
+ selectedStoryId,
29
+ loginUrl,
30
+ type,
31
+ expanded = true,
32
+ indexError,
33
+ previewInitialized,
34
+ setSelection,
35
+ } = props;
36
+ const length = useMemo(() => (index ? Object.keys(index).length : 0), [index]);
38
37
 
39
- const isLoadingInjected =
40
- (type === 'auto-inject' && !previewInitialized) || type === 'server-checked';
41
- const isLoading = isLoadingMain || isLoadingInjected || type === 'unknown';
42
- const isError = !!indexError;
43
- const isEmpty = !isLoading && length === 0;
44
- const isAuthRequired = !!loginUrl && length === 0;
38
+ const isLoadingInjected =
39
+ (type === 'auto-inject' && !previewInitialized) || type === 'server-checked';
40
+ const isLoading = isLoadingMain || isLoadingInjected || type === 'unknown';
41
+ const isError = !!indexError;
42
+ const isEmpty = !isLoading && length === 0;
43
+ const isAuthRequired = !!loginUrl && length === 0;
45
44
 
46
- const state = getStateType(isLoading, isAuthRequired, isError, isEmpty);
47
- const [isExpanded, setExpanded] = useState<boolean>(expanded);
45
+ const state = getStateType(isLoading, isAuthRequired, isError, isEmpty);
46
+ const [isExpanded, setExpanded] = useState<boolean>(expanded);
48
47
 
49
- useEffect(() => {
50
- if (index && selectedStoryId && index[selectedStoryId]) {
51
- setExpanded(true);
52
- }
53
- }, [setExpanded, index, selectedStoryId]);
48
+ useEffect(() => {
49
+ if (index && selectedStoryId && index[selectedStoryId]) {
50
+ setExpanded(true);
51
+ }
52
+ }, [setExpanded, index, selectedStoryId]);
54
53
 
55
- const onSelectStoryId = useCallback(
56
- (storyId: string) => {
57
- setSelection({ refId, storyId });
58
- },
59
- [refId, setSelection]
60
- );
54
+ const onSelectStoryId = useCallback(
55
+ (storyId: string) => {
56
+ setSelection({ refId, storyId });
57
+ },
58
+ [refId, setSelection]
59
+ );
61
60
 
62
- return (
63
- <>
64
- {isExpanded && (
65
- <Wrapper data-title={title} isMain={true}>
66
- {state === 'ready' && (
67
- <Tree
68
- status={props.status}
69
- isBrowsing={isBrowsing}
70
- isMain={true}
71
- refId={refId}
72
- data={index}
73
- docsMode={false}
74
- selectedStoryId={selectedStoryId}
75
- onSelectStoryId={onSelectStoryId}
76
- />
77
- )}
78
- </Wrapper>
79
- )}
80
- </>
81
- );
82
- });
61
+ return (
62
+ <>
63
+ {isExpanded && (
64
+ <Wrapper data-title={title} isMain={true}>
65
+ {state === 'ready' && (
66
+ <Tree
67
+ status={props.status}
68
+ isBrowsing={isBrowsing}
69
+ isMain={true}
70
+ refId={refId}
71
+ data={index}
72
+ docsMode={false}
73
+ selectedStoryId={selectedStoryId}
74
+ onSelectStoryId={onSelectStoryId}
75
+ />
76
+ )}
77
+ </Wrapper>
78
+ )}
79
+ </>
80
+ );
81
+ }
82
+ );
package/src/Search.tsx CHANGED
@@ -2,11 +2,11 @@ import { BottomSheetTextInput, useBottomSheetInternal } from '@gorhom/bottom-she
2
2
  import { styled } from '@storybook/react-native-theming';
3
3
  import type { IFuseOptions } from 'fuse.js';
4
4
  import Fuse from 'fuse.js';
5
- import React, { useCallback, useContext, useDeferredValue, useRef, useState } from 'react';
5
+ import React, { useCallback, useDeferredValue, useRef, useState } from 'react';
6
6
  import { Platform, TextInput, View } from 'react-native';
7
7
  import { CloseIcon } from './icon/CloseIcon';
8
8
  import { SearchIcon } from './icon/SearchIcon';
9
- import { useLayout } from './LayoutProvider';
9
+ import { useSelectedNode } from './SelectedNodeProvider';
10
10
  import {
11
11
  type CombinedDataset,
12
12
  type GetSearchItemProps,
@@ -17,7 +17,6 @@ import {
17
17
  type Selection,
18
18
  } from './types';
19
19
  import { searchItem } from './util/tree';
20
- import { useSelectedNode } from './SelectedNodeProvider';
21
20
 
22
21
  const DEFAULT_MAX_SEARCH_RESULTS = 50;
23
22
 
@@ -112,7 +111,7 @@ export const Search = React.memo<{
112
111
  const [inputValue, setInputValue] = useState(initialQuery);
113
112
  const [isOpen, setIsOpen] = useState(false);
114
113
  const [allComponents, showAllComponents] = useState(false);
115
- const { isMobile } = useLayout();
114
+ // const { isMobile } = useLayout();
116
115
  const { scrollToSelectedNode } = useSelectedNode();
117
116
 
118
117
  const selectStory = useCallback(
@@ -36,7 +36,8 @@ export const SelectedNodeProvider: FC<PropsWithChildren> = ({ children }) => {
36
36
  nodeRef.current.measureLayout?.(scrollRef.current as any, (_x, y) => {
37
37
  scrollRef.current?.scrollTo({ y: y - 100, animated: true });
38
38
  });
39
- } catch (error) {}
39
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
40
+ } catch (_error) {}
40
41
  }
41
42
  }, 500);
42
43
  }, []);
package/src/Tree.tsx CHANGED
@@ -16,7 +16,6 @@ import { ExpandAllIcon } from './icon/ExpandAllIcon';
16
16
  import { Item } from './types';
17
17
  import type { ExpandAction, ExpandedState } from './hooks/useExpanded';
18
18
  import { useExpanded } from './hooks/useExpanded';
19
- import { getGroupStatus, statusMapping } from './util/status';
20
19
  import { createId, getAncestorIds, getDescendantIds, isStoryHoistable } from './util/tree';
21
20
  import { useSelectedNode } from './SelectedNodeProvider';
22
21
 
@@ -158,7 +157,7 @@ export const LeafNodeStyleWrapper = styled.View(({ theme }) => ({
158
157
  borderRadius: 4,
159
158
  }));
160
159
 
161
- export const RootNode = styled.View(({}) => ({
160
+ export const RootNode = styled.View(() => ({
162
161
  display: 'flex',
163
162
  flexDirection: 'row',
164
163
  alignItems: 'center',
@@ -177,7 +176,7 @@ export const RootNodeText = styled.Text(({ theme }) => ({
177
176
  textTransform: 'uppercase',
178
177
  }));
179
178
 
180
- const CollapseButton = styled.TouchableOpacity(({}) => ({
179
+ const CollapseButton = styled.TouchableOpacity(() => ({
181
180
  display: 'flex',
182
181
  flexDirection: 'row',
183
182
  paddingVertical: 0,
package/src/TreeNode.tsx CHANGED
@@ -3,10 +3,9 @@ import { ComponentIcon } from './icon/ComponentIcon';
3
3
  import { GroupIcon } from './icon/GroupIcon';
4
4
  import { StoryIcon } from './icon/StoryIcon';
5
5
  import { CollapseIcon } from './icon/CollapseIcon';
6
- import { ComponentProps, FC, forwardRef, useMemo } from 'react';
6
+ import React, { ComponentProps, FC, forwardRef, useMemo } from 'react';
7
7
  import { transparentize } from 'polished';
8
8
  import { View } from 'react-native';
9
- import React from 'react';
10
9
 
11
10
  export interface NodeProps {
12
11
  children: React.ReactNode | React.ReactNode[];
@@ -1,5 +1,5 @@
1
1
  import type { StoriesHash } from 'storybook/internal/manager-api';
2
- import type { Dispatch, Reducer } from 'react';
2
+ import type { Dispatch } from 'react';
3
3
  import { useCallback, useEffect, useReducer } from 'react';
4
4
  import { getAncestorIds } from '../util/tree';
5
5
 
@@ -44,16 +44,8 @@ export const useExpanded = ({
44
44
  }: ExpandedProps): [ExpandedState, Dispatch<ExpandAction>] => {
45
45
  // Track the set of currently expanded nodes within this tree.
46
46
  // Root nodes are expanded by default.
47
- const [expanded, setExpanded] = useReducer<
48
- Reducer<ExpandedState, ExpandAction>,
49
- {
50
- refId: string;
51
- data: StoriesHash;
52
- rootIds: string[];
53
- initialExpanded: ExpandedState;
54
- }
55
- >(
56
- (state, { ids, value }) =>
47
+ const [expanded, setExpanded] = useReducer(
48
+ (state: ExpandedState, { ids, value }: ExpandAction) =>
57
49
  ids.reduce((acc, id) => Object.assign(acc, { [id]: value }), { ...state }),
58
50
  { refId, data, rootIds, initialExpanded },
59
51
  initializeExpanded
@@ -17,6 +17,10 @@ import type {
17
17
  } from 'storybook/internal/types';
18
18
  import countBy from 'lodash/countBy.js';
19
19
  import { dedent } from 'ts-dedent';
20
+ import isEqual from 'lodash/isEqual.js';
21
+ import mergeWith from 'lodash/mergeWith.js';
22
+ import { logger } from 'storybook/internal/client-logger';
23
+
20
24
  type ToStoriesHashOptions = {
21
25
  provider: API_Provider<API>;
22
26
  docsOptions: DocsOptions;
@@ -24,11 +28,6 @@ type ToStoriesHashOptions = {
24
28
  status: State['status'];
25
29
  };
26
30
 
27
- import isEqual from 'lodash/isEqual.js';
28
- import mergeWith from 'lodash/mergeWith.js';
29
-
30
- import { logger } from 'storybook/internal/client-logger';
31
-
32
31
  const merge = <TObj = any>(a: TObj, b: Partial<TObj>) =>
33
32
  mergeWith({}, a, b, (objValue: TObj, srcValue: Partial<TObj>) => {
34
33
  if (Array.isArray(srcValue) && Array.isArray(objValue)) {
@@ -202,16 +201,19 @@ export const transformStoryIndexToStoriesHash = (
202
201
  export const transformStoryIndexV2toV3 = (index: StoryIndexV2): StoryIndexV3 => {
203
202
  return {
204
203
  v: 3,
205
- stories: Object.values(index.stories).reduce((acc, entry) => {
206
- acc[entry.id] = {
207
- ...entry,
208
- title: entry.kind,
209
- name: entry.name || entry.story,
210
- importPath: entry.parameters.fileName || '',
211
- };
212
-
213
- return acc;
214
- }, {} as StoryIndexV3['stories']),
204
+ stories: Object.values(index.stories).reduce(
205
+ (acc, entry) => {
206
+ acc[entry.id] = {
207
+ ...entry,
208
+ title: entry.kind,
209
+ name: entry.name || entry.story,
210
+ importPath: entry.parameters.fileName || '',
211
+ };
212
+
213
+ return acc;
214
+ },
215
+ {} as StoryIndexV3['stories']
216
+ ),
215
217
  };
216
218
  };
217
219
 
@@ -219,26 +221,29 @@ export const transformStoryIndexV3toV4 = (index: StoryIndexV3): API_PreparedStor
219
221
  const countByTitle = countBy(Object.values(index.stories), 'title');
220
222
  return {
221
223
  v: 4,
222
- entries: Object.values(index.stories).reduce((acc, entry: any) => {
223
- let type: IndexEntry['type'] = 'story';
224
- if (
225
- entry.parameters?.docsOnly ||
226
- (entry.name === 'Page' && countByTitle[entry.title] === 1)
227
- ) {
228
- type = 'docs';
229
- }
230
- acc[entry.id] = {
231
- type,
232
- ...(type === 'docs' && { tags: ['stories-mdx'], storiesImports: [] }),
233
- ...entry,
234
- };
235
-
236
- // @ts-expect-error (we're removing something that should not be there)
237
- delete acc[entry.id].story;
238
- // @ts-expect-error (we're removing something that should not be there)
239
- delete acc[entry.id].kind;
240
-
241
- return acc;
242
- }, {} as API_PreparedStoryIndex['entries']),
224
+ entries: Object.values(index.stories).reduce(
225
+ (acc, entry: any) => {
226
+ let type: IndexEntry['type'] = 'story';
227
+ if (
228
+ entry.parameters?.docsOnly ||
229
+ (entry.name === 'Page' && countByTitle[entry.title] === 1)
230
+ ) {
231
+ type = 'docs';
232
+ }
233
+ acc[entry.id] = {
234
+ type,
235
+ ...(type === 'docs' && { tags: ['stories-mdx'], storiesImports: [] }),
236
+ ...entry,
237
+ };
238
+
239
+ // @ts-expect-error (we're removing something that should not be there)
240
+ delete acc[entry.id].story;
241
+ // @ts-expect-error (we're removing something that should not be there)
242
+ delete acc[entry.id].kind;
243
+
244
+ return acc;
245
+ },
246
+ {} as API_PreparedStoryIndex['entries']
247
+ ),
243
248
  };
244
249
  };
package/src/util/tree.ts CHANGED
@@ -29,18 +29,20 @@ export const getAncestorIds = memoize(1000)((data: IndexHash, id: string): strin
29
29
  getParents(id, data).map((item) => item.id)
30
30
  );
31
31
 
32
- export const getDescendantIds = memoize(1000)(
33
- (data: IndexHash, id: string, skipLeafs: boolean): string[] => {
34
- const entry = data[id];
35
- const children = entry.type === 'story' || entry.type === 'docs' ? [] : entry.children;
36
- return children.reduce((acc, childId) => {
37
- const child = data[childId];
38
- if (!child || (skipLeafs && (child.type === 'story' || child.type === 'docs'))) return acc;
39
- acc.push(childId, ...getDescendantIds(data, childId, skipLeafs));
40
- return acc;
41
- }, []);
42
- }
43
- );
32
+ export const getDescendantIds = memoize(1000)((
33
+ data: IndexHash,
34
+ id: string,
35
+ skipLeafs: boolean
36
+ ): string[] => {
37
+ const entry = data[id];
38
+ const children = entry.type === 'story' || entry.type === 'docs' ? [] : entry.children;
39
+ return children.reduce((acc, childId) => {
40
+ const child = data[childId];
41
+ if (!child || (skipLeafs && (child.type === 'story' || child.type === 'docs'))) return acc;
42
+ acc.push(childId, ...getDescendantIds(data, childId, skipLeafs));
43
+ return acc;
44
+ }, []);
45
+ });
44
46
 
45
47
  export function getPath(item: Item, ref: RefType): string[] {
46
48
  const parent = item.type !== 'root' && item.parent ? ref.index[item.parent] : null;
@@ -19,7 +19,7 @@ import { ImageStyle, StyleProp, TextStyle, ViewStyle } from 'react-native';
19
19
  */
20
20
  export const useStyle = <
21
21
  TStyle extends ViewStyle | TextStyle | ImageStyle,
22
- TOutput extends StyleProp<TStyle>
22
+ TOutput extends StyleProp<TStyle>,
23
23
  >(
24
24
  styleFactory: () => TOutput,
25
25
  deps?: DependencyList