@storybook/react-native-ui 9.0.0-alpha.1 → 9.0.0-alpha.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storybook/react-native-ui",
3
- "version": "9.0.0-alpha.1",
3
+ "version": "9.0.0-alpha.8",
4
4
  "description": "ui components for react native storybook",
5
5
  "keywords": [
6
6
  "react",
@@ -58,8 +58,8 @@
58
58
  "typescript": "^5.3.3"
59
59
  },
60
60
  "dependencies": {
61
- "@storybook/react": "9.0.0-alpha.3",
62
- "@storybook/react-native-theming": "^9.0.0-alpha.1",
61
+ "@storybook/react": "9.0.0-alpha.8",
62
+ "@storybook/react-native-theming": "^9.0.0-alpha.8",
63
63
  "fuse.js": "^7.0.0",
64
64
  "memoizerific": "^1.11.3",
65
65
  "polished": "^4.3.1",
@@ -72,7 +72,8 @@
72
72
  "react-native-gesture-handler": ">=2",
73
73
  "react-native-reanimated": ">=3",
74
74
  "react-native-safe-area-context": "*",
75
- "react-native-svg": ">=14"
75
+ "react-native-svg": ">=14",
76
+ "storybook": "9.0.0-alpha.8"
76
77
  },
77
78
  "engines": {
78
79
  "node": ">=18.0.0"
@@ -80,5 +81,5 @@
80
81
  "publishConfig": {
81
82
  "access": "public"
82
83
  },
83
- "gitHead": "ec42eef3ebdf389ebf9cf669d425712db99f9e37"
84
+ "gitHead": "16659266d8aa9816490af41d0a840579a2f96805"
84
85
  }
package/src/Search.tsx CHANGED
@@ -1,8 +1,8 @@
1
- import { BottomSheetTextInput } from '@gorhom/bottom-sheet';
1
+ import { BottomSheetTextInput, useBottomSheetInternal } from '@gorhom/bottom-sheet';
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, useDeferredValue, useRef, useState } from 'react';
5
+ import React, { useCallback, useContext, 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';
@@ -16,7 +16,6 @@ import {
16
16
  type SearchResult,
17
17
  type Selection,
18
18
  } from './types';
19
- import { getGroupStatus, getHighestStatus } from './util/status';
20
19
  import { searchItem } from './util/tree';
21
20
  import { useSelectedNode } from './SelectedNodeProvider';
22
21
 
@@ -106,6 +105,9 @@ export const Search = React.memo<{
106
105
  getLastViewed: () => Selection[];
107
106
  initialQuery?: string;
108
107
  }>(function Search({ children, dataset, setSelection, getLastViewed, initialQuery = '' }) {
108
+ const context = useBottomSheetInternal(true);
109
+ const isBottomSheet = context !== null;
110
+
109
111
  const inputRef = useRef<TextInput>(null);
110
112
  const [inputValue, setInputValue] = useState(initialQuery);
111
113
  const [isOpen, setIsOpen] = useState(false);
@@ -153,20 +155,11 @@ export const Search = React.memo<{
153
155
  );
154
156
 
155
157
  const makeFuse = useCallback(() => {
156
- const list = dataset.entries.reduce<SearchItem[]>((acc, [refId, { index, status }]) => {
157
- const groupStatus = getGroupStatus(index || {}, status);
158
-
158
+ const list = dataset.entries.reduce<SearchItem[]>((acc, [refId, { index }]) => {
159
159
  if (index) {
160
160
  acc.push(
161
161
  ...Object.values(index).map((item) => {
162
- const statusValue =
163
- status && status[item.id]
164
- ? getHighestStatus(Object.values(status[item.id] || {}).map((s) => s.status))
165
- : null;
166
- return {
167
- ...searchItem(item, dataset.hash[refId]),
168
- status: statusValue || groupStatus[item.id] || null,
169
- };
162
+ return searchItem(item, dataset.hash[refId]);
170
163
  })
171
164
  );
172
165
  }
@@ -235,7 +228,7 @@ export const Search = React.memo<{
235
228
  <SearchIcon />
236
229
  </SearchIconWrapper>
237
230
 
238
- {isMobile ? (
231
+ {isBottomSheet ? (
239
232
  <BottomSheetInput
240
233
  ref={inputRef as any} // TODO find solution for this
241
234
  onChangeText={setInputValue}
@@ -2,6 +2,7 @@ import { useState } from 'react';
2
2
  import type { ComponentEntry, IndexHash } from 'storybook/internal/manager-api';
3
3
  import type { StoryObj, Meta } from '@storybook/react';
4
4
  import { Tree } from './Tree';
5
+ import type { Dataset } from './types';
5
6
  import { index } from './mockdata.large';
6
7
  import { DEFAULT_REF_ID } from './constants';
7
8
  import { ScrollView, Text } from 'react-native';
@@ -138,3 +139,39 @@ export const SingleStoryComponents: Story = {
138
139
  );
139
140
  },
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
+ };
package/src/Tree.tsx CHANGED
@@ -299,8 +299,6 @@ export const Tree = React.memo<{
299
299
  onSelectStoryId,
300
300
  });
301
301
 
302
- const groupStatus = useMemo(() => getGroupStatus(collapsedData, status), [collapsedData, status]);
303
-
304
302
  const treeItems = useMemo(() => {
305
303
  return collapsedItems.map((itemId) => {
306
304
  const item = collapsedData[itemId];
@@ -330,7 +328,6 @@ export const Tree = React.memo<{
330
328
  }
331
329
 
332
330
  const isDisplayed = !item.parent || ancestry[itemId].every((a: string) => expanded[a]);
333
- const color = groupStatus[itemId] ? statusMapping[groupStatus[itemId]][1] : null;
334
331
 
335
332
  return (
336
333
  <Node
@@ -338,7 +335,7 @@ export const Tree = React.memo<{
338
335
  item={item}
339
336
  status={status?.[itemId]}
340
337
  refId={refId}
341
- color={color}
338
+ color={null}
342
339
  docsMode={docsMode}
343
340
  isOrphan={orphanIds.some((oid) => itemId === oid || itemId.startsWith(`${oid}-`))}
344
341
  isDisplayed={isDisplayed}
@@ -356,7 +353,6 @@ export const Tree = React.memo<{
356
353
  docsMode,
357
354
  expandableDescendants,
358
355
  expanded,
359
- groupStatus,
360
356
  onSelectStoryId,
361
357
  orphanIds,
362
358
  refId,
package/src/types.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import type { StoriesHash, State } from 'storybook/internal/manager-api';
2
- import type { API_StatusState, API_StatusValue } from 'storybook/internal/types';
2
+ import type { StatusValue, StatusesByStoryIdAndTypeId } from 'storybook/internal/types';
3
3
  import * as Fuse from 'fuse.js';
4
4
  import { PressableProps } from 'react-native';
5
5
 
6
6
  export type Refs = State['refs'];
7
- export type RefType = Refs[keyof Refs] & { status?: API_StatusState };
7
+ export type RefType = Refs[keyof Refs] & { allStatuses?: StatusesByStoryIdAndTypeId };
8
8
  export type Item = StoriesHash[keyof StoriesHash];
9
9
  export type Dataset = Record<string, Item>;
10
10
 
@@ -38,7 +38,7 @@ export interface ExpandType {
38
38
  export type SearchItem = Item & {
39
39
  refId: string;
40
40
  path: string[];
41
- status?: API_StatusValue;
41
+ status?: StatusValue;
42
42
  showAll?: () => void;
43
43
  };
44
44
 
@@ -1,5 +1,9 @@
1
1
  import { useMemo, type ReactElement } from 'react';
2
- import type { API_HashEntry, API_StatusState, API_StatusValue } from 'storybook/internal/types';
2
+ import type {
3
+ API_HashEntry,
4
+ StatusValue,
5
+ StatusesByStoryIdAndTypeId,
6
+ } from 'storybook/internal/types';
3
7
 
4
8
  import { useTheme } from '@storybook/react-native-theming';
5
9
 
@@ -29,19 +33,33 @@ function LoadingIcons(props: SvgProps) {
29
33
  return <SmallIcons color={color} {...props} />;
30
34
  }
31
35
 
32
- export const statusPriority: API_StatusValue[] = ['unknown', 'pending', 'success', 'warn', 'error'];
33
- export const statusMapping: Record<API_StatusValue, [ReactElement | null, string | null]> = {
34
- unknown: [null, null],
35
- pending: [<LoadingIcons key="icon" />, 'currentColor'],
36
- success: [<SmallIcons key="icon" color="green" />, 'currentColor'],
37
- warn: [<SmallIcons key="icon" color="orange" />, '#A15C20'],
38
- error: [<SmallIcons key="icon" color="red" />, 'brown'],
36
+ export const statusMapping: Record<StatusValue, [ReactElement | null, string | null]> = {
37
+ ['status-value:unknown']: [null, null],
38
+ ['status-value:pending']: [<LoadingIcons key="icon" />, 'currentColor'],
39
+ ['status-value:success']: [<SmallIcons key="icon" color="green" />, 'currentColor'],
40
+ ['status-value:warning']: [<SmallIcons key="icon" color="orange" />, '#A15C20'],
41
+ ['status-value:error']: [<SmallIcons key="icon" color="red" />, 'brown'],
39
42
  };
40
43
 
41
- export const getHighestStatus = (statuses: API_StatusValue[]): API_StatusValue => {
44
+ // export const getHighestStatus = (statuses: API_StatusValue[]): API_StatusValue => {
45
+ // return statusPriority.reduce(
46
+ // (acc, status) => (statuses.includes(status) ? status : acc),
47
+ // 'unknown'
48
+ // );
49
+ // };
50
+
51
+ export const statusPriority: StatusValue[] = [
52
+ 'status-value:unknown',
53
+ 'status-value:pending',
54
+ 'status-value:success',
55
+ 'status-value:warning',
56
+ 'status-value:error',
57
+ ];
58
+
59
+ export const getMostCriticalStatusValue = (statusValues: StatusValue[]): StatusValue => {
42
60
  return statusPriority.reduce(
43
- (acc, status) => (statuses.includes(status) ? status : acc),
44
- 'unknown'
61
+ (acc, value) => (statusValues.includes(value) ? value : acc),
62
+ 'status-value:unknown'
45
63
  );
46
64
  };
47
65
 
@@ -49,16 +67,16 @@ export function getGroupStatus(
49
67
  collapsedData: {
50
68
  [x: string]: Partial<API_HashEntry>;
51
69
  },
52
- status: API_StatusState
53
- ): Record<string, API_StatusValue> {
54
- return Object.values(collapsedData).reduce<Record<string, API_StatusValue>>((acc, item) => {
70
+ allStatuses: StatusesByStoryIdAndTypeId
71
+ ): Record<string, StatusValue> {
72
+ return Object.values(collapsedData).reduce<Record<string, StatusValue>>((acc, item) => {
55
73
  if (item.type === 'group' || item.type === 'component') {
56
74
  const leafs = getDescendantIds(collapsedData as any, item.id, false)
57
75
  .map((id) => collapsedData[id])
58
76
  .filter((i) => i.type === 'story');
59
77
 
60
- const combinedStatus = getHighestStatus(
61
- leafs.flatMap((story) => Object.values(status?.[story.id] || {})).map((s) => s.status)
78
+ const combinedStatus = getMostCriticalStatusValue(
79
+ leafs.flatMap((story) => Object.values(allStatuses[story.id] || {})).map((s) => s.value)
62
80
  );
63
81
 
64
82
  if (combinedStatus) {