@storybook/react-native 6.5.0-rc.0 → 6.5.0-rc.1

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.
@@ -0,0 +1,22 @@
1
+ import type { StoryContext } from '@storybook/csf';
2
+ import type { ReactNativeFramework } from './types/types-6.0';
3
+ /**
4
+ * Hook that returns a function to set the current story context.
5
+ */
6
+ export declare function useSetStoryContext(): (args_0: StoryContext<ReactNativeFramework, import("@storybook/csf").Args> | ((prev: StoryContext<ReactNativeFramework, import("@storybook/csf").Args>) => StoryContext<ReactNativeFramework, import("@storybook/csf").Args>)) => void;
7
+ /**
8
+ * Hook to read the current story context.
9
+ */
10
+ export declare function useStoryContext(): StoryContext<ReactNativeFramework, import("@storybook/csf").Args>;
11
+ /**
12
+ * Hook that reads the value of a specific story context parameter.
13
+ */
14
+ export declare function useStoryContextParam<T = any>(name: string, defaultValue?: T): T;
15
+ /**
16
+ * Hook that indicates if `storyId` is the currently selected story.
17
+ */
18
+ export declare function useIsStorySelected(storyId: string): boolean;
19
+ /**
20
+ * Hook that indicates if `title` is the currently selected story section.
21
+ */
22
+ export declare function useIsStorySectionSelected(title: string): boolean;
package/dist/hooks.js ADDED
@@ -0,0 +1,35 @@
1
+ import { useMemo } from 'react';
2
+ import { atom, useAtomValue, useSetAtom } from 'jotai';
3
+ const storyContextAtom = atom(null);
4
+ /**
5
+ * Hook that returns a function to set the current story context.
6
+ */
7
+ export function useSetStoryContext() {
8
+ return useSetAtom(storyContextAtom);
9
+ }
10
+ /**
11
+ * Hook to read the current story context.
12
+ */
13
+ export function useStoryContext() {
14
+ return useAtomValue(storyContextAtom);
15
+ }
16
+ /**
17
+ * Hook that reads the value of a specific story context parameter.
18
+ */
19
+ export function useStoryContextParam(name, defaultValue) {
20
+ var _a;
21
+ const paramAtom = useMemo(() => atom(get => { var _a, _b; return (_b = (_a = get(storyContextAtom)) === null || _a === void 0 ? void 0 : _a.parameters) === null || _b === void 0 ? void 0 : _b[name]; }), [name]);
22
+ return (_a = useAtomValue(paramAtom)) !== null && _a !== void 0 ? _a : defaultValue;
23
+ }
24
+ /**
25
+ * Hook that indicates if `storyId` is the currently selected story.
26
+ */
27
+ export function useIsStorySelected(storyId) {
28
+ return useAtomValue(useMemo(() => atom(get => { var _a; return ((_a = get(storyContextAtom)) === null || _a === void 0 ? void 0 : _a.id) === storyId; }), [storyId]));
29
+ }
30
+ /**
31
+ * Hook that indicates if `title` is the currently selected story section.
32
+ */
33
+ export function useIsStorySectionSelected(title) {
34
+ return useAtomValue(useMemo(() => atom(get => { var _a; return ((_a = get(storyContextAtom)) === null || _a === void 0 ? void 0 : _a.title) === title; }), [title]));
35
+ }
@@ -7,12 +7,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import React, { useEffect, useState, useReducer } from 'react';
10
+ import React, { useEffect, useReducer } from 'react';
11
11
  import AsyncStorage from '@react-native-async-storage/async-storage';
12
12
  import { toId } from '@storybook/csf';
13
13
  import { addons } from '@storybook/addons';
14
14
  import { ThemeProvider } from 'emotion-theming';
15
15
  import { SafeAreaProvider } from 'react-native-safe-area-context';
16
+ import { useSetStoryContext } from '../hooks';
16
17
  import OnDeviceUI from './components/OnDeviceUI';
17
18
  import { theme } from './components/Shared/theme';
18
19
  import StoryView from './components/StoryView';
@@ -88,7 +89,7 @@ export class View {
88
89
  const self = this;
89
90
  const appliedTheme = Object.assign(Object.assign({}, theme), params.theme);
90
91
  return () => {
91
- const [context, setContext] = useState();
92
+ const setContext = useSetStoryContext();
92
93
  const [, forceUpdate] = useReducer((x) => x + 1, 0);
93
94
  useEffect(() => {
94
95
  self._setStory = (newStory) => {
@@ -104,14 +105,15 @@ export class View {
104
105
  self._preview.urlStore.selectionSpecifier = story;
105
106
  self._preview.selectSpecifiedStory();
106
107
  });
108
+ // eslint-disable-next-line react-hooks/exhaustive-deps
107
109
  }, []);
108
110
  if (onDeviceUI) {
109
111
  return (React.createElement(SafeAreaProvider, null,
110
112
  React.createElement(ThemeProvider, { theme: appliedTheme },
111
- React.createElement(OnDeviceUI, { context: context, storyIndex: self._storyIndex, isUIHidden: params.isUIHidden, tabOpen: params.tabOpen, shouldDisableKeyboardAvoidingView: params.shouldDisableKeyboardAvoidingView, keyboardAvoidingViewVerticalOffset: params.keyboardAvoidingViewVerticalOffset }))));
113
+ React.createElement(OnDeviceUI, { storyIndex: self._storyIndex, isUIHidden: params.isUIHidden, tabOpen: params.tabOpen, shouldDisableKeyboardAvoidingView: params.shouldDisableKeyboardAvoidingView, keyboardAvoidingViewVerticalOffset: params.keyboardAvoidingViewVerticalOffset }))));
112
114
  }
113
115
  else {
114
- return React.createElement(StoryView, { context: context });
116
+ return React.createElement(StoryView, null);
115
117
  }
116
118
  };
117
119
  };
@@ -1,10 +1,7 @@
1
1
  import { StoryIndex } from '@storybook/client-api';
2
2
  import React from 'react';
3
- import { StoryContext } from '@storybook/csf';
4
- import { ReactNativeFramework } from 'src/types/types-6.0';
5
3
  export declare const IS_EXPO: boolean;
6
4
  interface OnDeviceUIProps {
7
- context: StoryContext<ReactNativeFramework>;
8
5
  storyIndex: StoryIndex;
9
6
  url?: string;
10
7
  tabOpen?: number;
@@ -12,5 +9,5 @@ interface OnDeviceUIProps {
12
9
  shouldDisableKeyboardAvoidingView?: boolean;
13
10
  keyboardAvoidingViewVerticalOffset?: number;
14
11
  }
15
- declare const _default: React.MemoExoticComponent<({ context, storyIndex, isUIHidden, shouldDisableKeyboardAvoidingView, keyboardAvoidingViewVerticalOffset, tabOpen: initialTabOpen, }: OnDeviceUIProps) => JSX.Element>;
12
+ declare const _default: React.MemoExoticComponent<({ storyIndex, isUIHidden, shouldDisableKeyboardAvoidingView, keyboardAvoidingViewVerticalOffset, tabOpen: initialTabOpen, }: OnDeviceUIProps) => JSX.Element>;
16
13
  export default _default;
@@ -1,6 +1,7 @@
1
1
  import styled from '@emotion/native';
2
2
  import React, { useState, useRef } from 'react';
3
3
  import { Animated, Dimensions, Keyboard, KeyboardAvoidingView, Platform, SafeAreaView, TouchableOpacity, StatusBar, StyleSheet, View, } from 'react-native';
4
+ import { useStoryContextParam } from '../../../hooks';
4
5
  import StoryListView from '../StoryListView';
5
6
  import StoryView from '../StoryView';
6
7
  import AbsolutePositionedKeyboardAwareView from './absolute-positioned-keyboard-aware-view';
@@ -25,6 +26,8 @@ const Preview = styled.View(flex, ({ disabled, theme }) => ({
25
26
  borderRightWidth: disabled ? 0 : 1,
26
27
  borderBottomWidth: disabled ? 0 : 1,
27
28
  borderColor: disabled ? 'transparent' : theme.previewBorderColor,
29
+ borderRadius: disabled ? 0 : 12,
30
+ overflow: 'hidden',
28
31
  }));
29
32
  const absolutePosition = {
30
33
  position: 'absolute',
@@ -36,19 +39,18 @@ const absolutePosition = {
36
39
  const styles = StyleSheet.create({
37
40
  expoAndroidContainer: { paddingTop: StatusBar.currentHeight },
38
41
  });
39
- const OnDeviceUI = ({ context, storyIndex, isUIHidden, shouldDisableKeyboardAvoidingView, keyboardAvoidingViewVerticalOffset, tabOpen: initialTabOpen, }) => {
40
- var _a, _b;
42
+ const OnDeviceUI = ({ storyIndex, isUIHidden, shouldDisableKeyboardAvoidingView, keyboardAvoidingViewVerticalOffset, tabOpen: initialTabOpen, }) => {
41
43
  const [tabOpen, setTabOpen] = useState(initialTabOpen || PREVIEW);
42
44
  const [slideBetweenAnimation, setSlideBetweenAnimation] = useState(false);
43
- const [previewDimensions, setPreviewDimensions] = useState({
45
+ const [previewDimensions, setPreviewDimensions] = useState(() => ({
44
46
  width: Dimensions.get('window').width,
45
47
  height: Dimensions.get('window').height,
46
- });
48
+ }));
47
49
  const animatedValue = useRef(new Animated.Value(tabOpen));
48
50
  const wide = useWindowDimensions().width >= BREAKPOINT;
49
51
  const insets = useSafeAreaInsets();
50
52
  const [isUIVisible, setIsUIVisible] = useState(isUIHidden !== undefined ? !isUIHidden : true);
51
- const handleToggleTab = (newTabOpen) => {
53
+ const handleToggleTab = React.useCallback((newTabOpen) => {
52
54
  if (newTabOpen === tabOpen) {
53
55
  return;
54
56
  }
@@ -64,8 +66,8 @@ const OnDeviceUI = ({ context, storyIndex, isUIHidden, shouldDisableKeyboardAvoi
64
66
  if (newTabOpen === PREVIEW) {
65
67
  Keyboard.dismiss();
66
68
  }
67
- };
68
- const noSafeArea = (_b = (_a = context === null || context === void 0 ? void 0 : context.parameters) === null || _a === void 0 ? void 0 : _a.noSafeArea) !== null && _b !== void 0 ? _b : false;
69
+ }, [tabOpen]);
70
+ const noSafeArea = useStoryContextParam('noSafeArea', false);
69
71
  const previewWrapperStyles = [
70
72
  flex,
71
73
  getPreviewPosition({
@@ -88,10 +90,10 @@ const OnDeviceUI = ({ context, storyIndex, isUIHidden, shouldDisableKeyboardAvoi
88
90
  React.createElement(Animated.View, { style: previewStyles },
89
91
  React.createElement(Preview, { disabled: tabOpen === PREVIEW },
90
92
  React.createElement(WrapperView, { style: [flex, wrapperMargin] },
91
- React.createElement(StoryView, { context: context }))),
93
+ React.createElement(StoryView, null))),
92
94
  tabOpen !== PREVIEW ? (React.createElement(TouchableOpacity, { style: absolutePosition, onPress: () => handleToggleTab(PREVIEW) })) : null)),
93
95
  React.createElement(Panel, { style: getNavigatorPanelPosition(animatedValue.current, previewDimensions.width, wide) },
94
- React.createElement(StoryListView, { storyIndex: storyIndex, selectedStoryContext: context })),
96
+ React.createElement(StoryListView, { storyIndex: storyIndex })),
95
97
  React.createElement(Panel, { style: [
96
98
  getAddonPanelPosition(animatedValue.current, previewDimensions.width, wide),
97
99
  wrapperMargin,
@@ -4,10 +4,13 @@ import { View, StyleSheet } from 'react-native';
4
4
  // To avoid issues we use absolute positioned element with predefined screen size
5
5
  const AbsolutePositionedKeyboardAwareView = ({ onLayout, previewDimensions: { width, height }, children, }) => {
6
6
  const onLayoutHandler = ({ nativeEvent }) => {
7
- onLayout({
8
- height: nativeEvent.layout.height,
9
- width: nativeEvent.layout.width,
10
- });
7
+ const { height: layoutHeight, width: layoutWidth } = nativeEvent.layout;
8
+ if (layoutHeight !== height || layoutWidth !== width) {
9
+ onLayout({
10
+ height: layoutHeight,
11
+ width: layoutWidth,
12
+ });
13
+ }
11
14
  };
12
15
  return (React.createElement(View, { style: styles.container, onLayout: onLayoutHandler },
13
16
  React.createElement(View, { style: width === 0
@@ -3,3 +3,4 @@ export declare const GridIcon: () => JSX.Element;
3
3
  export declare const StoryIcon: ({ selected }: {
4
4
  selected: boolean;
5
5
  }) => JSX.Element;
6
+ export declare const SearchIcon: () => JSX.Element;
@@ -1,21 +1,34 @@
1
1
  import React from 'react';
2
2
  import { Image, StyleSheet } from 'react-native';
3
+ const iconSources = {
4
+ grid: { uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAMAAABHPGVmAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAALdQTFRFAAAAIJ//Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqj9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Haf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqb9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqj9Hqf9Hmz01QAAAD10Uk5TAAAEGjNefYqLXDUFAjSY0e79/9KZAghmyMkBQbz6vUIBBnD1cQcOo6Sp76qBePTHVOoC+RQTX4mCDZsBMmX5zDcAAAHcSURBVHic7ZrrcoIwEIVX8W5VpAiUaq33GyJqrfby/s9VacsCDojUJNNx9vzCTLLfZJdkHM4ChJTJSrl8oVj6s4qFckWqZiBed7V6Q24qV6op36uVVgxC042rAQh60LUIhPnY7rBCuOo8dZ9PGb3+gCXC1WA4CjPGE9YIV9NxiNHmwVCUWYAy4rIPV1PMmNnnxVCUoVf9LvOa+xp0f89HqCDzhbWMle3NsuPnWIt5MF7757zogfOxcqLOEGrtzVufm6U5Kz9iR3eHNgYObNWXc4svhQDs1C0GNTbHgZp/l6hnt5ECApqKQZu1471b93O1S1h6OQR2fsbqGcg28JeTtDIFBBwM28iCJON7lZSsVBAN3zFZCpRkkbgwDQQWWJQcvOK2LLYQCwPnoYDPS7aQJQYuwJ4/ZA8l/pASQQhCEIIQhCAEIQhBghB7nSj839xMnmtHQriJIAS5IYiQw3g7dxdBCEIQghCEIAQhyH+ECPmMLsQQKOMzY2vjgIHLYkwaIXaTEOMM+FuAIMbMhJYIW1aIwczaKj9EWuVCTH++7Quml8Qev0aMnl+qtxkfxnu4cYXLXiYhhpg2H4AP1g1L7a55ygDGrVdGZOuVKwFNZN/KSp/XtsPVpOpJ0C+2naE/XA0rpwAAAABJRU5ErkJggg==' },
5
+ storyWhite: { uri: 'data:image/png;base64,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' },
6
+ storyBlue: { uri: 'data:image/png;base64,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' },
7
+ search: { uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAABgWlDQ1BzUkdCIElFQzYxOTY2LTIuMQAAKJF1kd8rg1EYxz/baGLy88KFsjSuTEyJG2USamnNlOFme+2H2ubtfbe03Cq3K0rc+HXBX8Ctcq0UkZJbrokb1ut5t9Uke07PeT7ne87zdM5zwBpMKim9ZgBS6YwWmPI6F0KLTvsLVlqw00VrWNHVcb/fR1X7vMdixlu3Wav6uX+tYSWqK2CpEx5TVC0jPC3sW8+oJu8ItyuJ8IrwmXCfJhcUvjP1SIlfTY6X+NtkLRiYAGuzsDP+iyO/WEloKWF5Oa5UMquU72O+xBFNz89J7BbvRCfAFF6czDDJBMMMMirzMG489MuKKvkDxfxZ1iRXkVklh8YqcRJk6BM1K9WjEmOiR2UkyZn9/9tXPTbkKVV3eKH22TDee8C+DYW8YXwdGUbhGGxPcJmu5K8dwsiH6PmK5jqApk04v6pokV242IKORzWshYuSTdwai8HbKTSGoO0G6pdKPSvvc/IAwQ35qmvY24deOd+0/AMfDGfFB6WkFAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAqNJREFUWIXF2DmIFFEQBuBvVh3FC0EFdT3QaDORTUTFI9hQPAIRQxE0ETXwQBADD7zAaBEDTQxlIxExE4VFjTzYxQNFERUTr/VCvII3Q78Ze2Z6drvZH5ppmqq//q73XnXVlGRHFzZgJeZiDibjLd7gMa7gOr62wdsWStiEAfzNeH3HhYroXNGNu02CPsN9vMOfBjZHUc5DzBb8qAtwG7uxMMW+jB704kOd3w3MGImYg3WEQ9jehn8nrtVxPMeC4YjZ4v+3S8tIFmzD54jrnnAIMqNbWPcqwRFhU48EC/A04uzLyllSu4Fv5CCmimX4HXGvzeK0Se2eGe4yNcLpiH8QY1s5xHVmR85iYEJFSDXG5mbGXZHhnQLEVLEqinO5meGByHBPgYJKeF2J80XIWirimrGoQEFwLoq1PM2gQyhkhMr8vGBBg9H9nFaC3hYshtAVVNGZZtAhqZ5DhcupjTE+zaBDkplZhcthdnQ/kGbQIUnjTDm1Ck0QL9ODRoKeVO5LQjdYJFZXfj/hVSOjjZKj2FugmGn4WYlzq5nhJMlX/oMGxzEHHJa8+MlWxhcj46sFiFkiyc57TG/lME9tL7Q1RzFlYQNXuXdmdTweOX3C/JwEHYt4BzAuq2MZNyPnx1g6AiFlYer4FXH2tEsyEy8igl84of36tFgYkepHo2F1EwvxsI7oIVZk8J2KQ5INnHbta0bQqG+egktYV/f8lTAuDwoVfkj4HHRijVD44mw+ErLShbPR8/041UxYI7HrK6RZx+jq9RG71G7gvdrIVDOMFea1PuFPhEYiPqMfZ4S9mIaWotoddSYK81unUNHHC0f5AV5WgrTCXrXLNazlyxu5LV+eSBU1ZhQF9eObpFj2CIdh1BFn6s1oZqiKfqHtWYLz/wAUO/neFu9thgAAAABJRU5ErkJggg==' },
8
+ };
3
9
  export const GridIcon = () => {
4
- return (React.createElement(Image, { source: {
5
- uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAMAAABHPGVmAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAALdQTFRFAAAAIJ//Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqj9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Haf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqb9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqf9Hqj9Hqf9Hmz01QAAAD10Uk5TAAAEGjNefYqLXDUFAjSY0e79/9KZAghmyMkBQbz6vUIBBnD1cQcOo6Sp76qBePTHVOoC+RQTX4mCDZsBMmX5zDcAAAHcSURBVHic7ZrrcoIwEIVX8W5VpAiUaq33GyJqrfby/s9VacsCDojUJNNx9vzCTLLfZJdkHM4ChJTJSrl8oVj6s4qFckWqZiBed7V6Q24qV6op36uVVgxC042rAQh60LUIhPnY7rBCuOo8dZ9PGb3+gCXC1WA4CjPGE9YIV9NxiNHmwVCUWYAy4rIPV1PMmNnnxVCUoVf9LvOa+xp0f89HqCDzhbWMle3NsuPnWIt5MF7757zogfOxcqLOEGrtzVufm6U5Kz9iR3eHNgYObNWXc4svhQDs1C0GNTbHgZp/l6hnt5ECApqKQZu1471b93O1S1h6OQR2fsbqGcg28JeTtDIFBBwM28iCJON7lZSsVBAN3zFZCpRkkbgwDQQWWJQcvOK2LLYQCwPnoYDPS7aQJQYuwJ4/ZA8l/pASQQhCEIIQhCAEIQhBghB7nSj839xMnmtHQriJIAS5IYiQw3g7dxdBCEIQghCEIAQhyH+ECPmMLsQQKOMzY2vjgIHLYkwaIXaTEOMM+FuAIMbMhJYIW1aIwczaKj9EWuVCTH++7Quml8Qev0aMnl+qtxkfxnu4cYXLXiYhhpg2H4AP1g1L7a55ygDGrVdGZOuVKwFNZN/KSp/XtsPVpOpJ0C+2naE/XA0rpwAAAABJRU5ErkJggg==',
6
- }, style: styles.navigatorIcon }));
10
+ return (React.createElement(Image, { source: iconSources.grid, style: styles.sectionIcon }));
7
11
  };
8
- const whiteOutline = 'data:image/png;base64,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';
9
- const blueOutline = 'data:image/png;base64,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';
10
12
  export const StoryIcon = ({ selected }) => {
11
- return (React.createElement(Image, { source: {
12
- uri: selected ? whiteOutline : blueOutline,
13
- }, style: styles.navigatorIcon }));
13
+ return (React.createElement(Image, { source: selected ? iconSources.storyWhite : iconSources.storyBlue, style: styles.storyIcon }));
14
+ };
15
+ export const SearchIcon = () => {
16
+ return (React.createElement(Image, { source: iconSources.search, style: styles.searchIcon }));
14
17
  };
15
18
  const styles = StyleSheet.create({
16
- navigatorIcon: {
17
- width: 18,
18
- height: 18,
19
- marginRight: 5,
19
+ sectionIcon: {
20
+ width: 10,
21
+ height: 10,
22
+ marginRight: 6,
23
+ },
24
+ storyIcon: {
25
+ width: 12,
26
+ height: 12,
27
+ marginRight: 6,
28
+ },
29
+ searchIcon: {
30
+ opacity: 0.5,
31
+ width: 16,
32
+ height: 16,
20
33
  },
21
34
  });
@@ -1,11 +1,17 @@
1
1
  import styled from '@emotion/native';
2
2
  export const Header = styled.Text(({ theme }) => ({
3
- fontSize: 18,
3
+ fontSize: 16,
4
4
  color: theme.headerTextColor || 'black',
5
- }), ({ selected }) => (selected ? { fontWeight: 'bold' } : {}));
5
+ fontWeight: '500',
6
+ }));
6
7
  export const Name = styled.Text({
7
8
  fontSize: 16,
8
- }, ({ selected, theme }) => selected ? { fontWeight: 'bold', color: 'white' } : { color: theme.headerTextColor || 'black' });
9
+ }, ({ selected, theme }) => {
10
+ var _a, _b;
11
+ return selected
12
+ ? { fontWeight: '700', color: (_a = theme.listItemActiveTextColor) !== null && _a !== void 0 ? _a : 'white' }
13
+ : { color: (_b = theme.listItemTextColor) !== null && _b !== void 0 ? _b : 'black' };
14
+ });
9
15
  export const Label = styled.Text(({ theme }) => ({
10
16
  fontSize: 18,
11
17
  color: theme.labelColor || 'black',
@@ -1,8 +1,10 @@
1
1
  export declare const theme: {
2
2
  backgroundColor: string;
3
3
  storyListBackgroundColor: string;
4
+ listItemTextColor: string;
4
5
  listItemActiveColor: string;
5
6
  listItemActiveTextColor: string;
7
+ sectionActiveColor: string;
6
8
  headerTextColor: string;
7
9
  labelColor: string;
8
10
  borderColor: string;
@@ -1,8 +1,10 @@
1
1
  export const theme = {
2
2
  backgroundColor: 'white',
3
3
  storyListBackgroundColor: '#f6f9fc',
4
+ listItemTextColor: '#444444',
4
5
  listItemActiveColor: '#1ea7fd',
5
6
  listItemActiveTextColor: 'white',
7
+ sectionActiveColor: '#e0ebf5',
6
8
  headerTextColor: 'black',
7
9
  labelColor: 'black',
8
10
  borderColor: '#e6e6e6',
@@ -1,10 +1,7 @@
1
- /// <reference types="react" />
2
1
  import { StoryIndex } from '@storybook/client-api';
3
- import { StoryContext } from '@storybook/csf';
4
- import { ReactNativeFramework } from 'src/types/types-6.0';
2
+ import React from 'react';
5
3
  interface Props {
6
4
  storyIndex: StoryIndex;
7
- selectedStoryContext: StoryContext<ReactNativeFramework>;
8
5
  }
9
- declare const StoryListView: ({ selectedStoryContext, storyIndex }: Props) => JSX.Element;
10
- export default StoryListView;
6
+ declare const _default: React.MemoExoticComponent<({ storyIndex }: Props) => JSX.Element>;
7
+ export default _default;
@@ -2,28 +2,44 @@ import styled from '@emotion/native';
2
2
  import { addons } from '@storybook/addons';
3
3
  import Events from '@storybook/core-events';
4
4
  import React, { useMemo, useState } from 'react';
5
- import { SectionList, StyleSheet, View } from 'react-native';
5
+ import { SectionList, StyleSheet, View, } from 'react-native';
6
6
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
7
- import { GridIcon, StoryIcon } from '../Shared/icons';
7
+ import { GridIcon, SearchIcon, StoryIcon } from '../Shared/icons';
8
8
  import { Header, Name } from '../Shared/text';
9
- const SearchBar = styled.TextInput({
10
- borderRadius: 16,
11
- borderWidth: 2,
12
- fontSize: 16,
9
+ import { useIsStorySelected, useIsStorySectionSelected } from '../../../hooks';
10
+ const SearchInput = styled.TextInput(Object.assign({ fontSize: 16, padding: 0, paddingHorizontal: 36 }, StyleSheet.absoluteFillObject), ({ theme }) => ({
11
+ color: theme.buttonActiveTextColor,
12
+ }));
13
+ const SearchContainer = styled.View({
14
+ borderRadius: 100,
15
+ borderWidth: 1.5,
13
16
  marginVertical: 4,
14
17
  marginHorizontal: 8,
15
- paddingVertical: 8,
16
- paddingHorizontal: 15,
18
+ paddingVertical: 10,
19
+ paddingLeft: 12,
20
+ flexDirection: 'row',
21
+ alignItems: 'center',
17
22
  }, ({ theme }) => ({
18
23
  borderColor: theme.borderColor,
19
- color: theme.buttonActiveTextColor,
24
+ backgroundColor: theme.storyListBackgroundColor,
20
25
  }));
21
- const HeaderContainer = styled.View({
22
- paddingVertical: 5,
23
- paddingHorizontal: 5,
26
+ const SearchBar = (props) => {
27
+ return (React.createElement(SearchContainer, null,
28
+ React.createElement(SearchIcon, null),
29
+ React.createElement(SearchInput, Object.assign({}, props, { autoCapitalize: 'none', autoComplete: 'off', autoCorrect: false, spellCheck: false, clearButtonMode: "while-editing", disableFullscreenUI: true, placeholderTextColor: "#666", returnKeyType: "search" }))));
30
+ };
31
+ const HeaderContainer = styled.TouchableOpacity({
32
+ marginTop: 8,
33
+ marginHorizontal: 6,
34
+ padding: 6,
35
+ paddingHorizontal: 8,
36
+ borderTopLeftRadius: 6,
37
+ borderTopRightRadius: 6,
24
38
  flexDirection: 'row',
25
39
  alignItems: 'center',
26
- });
40
+ }, ({ selected, theme }) => ({
41
+ backgroundColor: selected ? theme.sectionActiveColor : undefined,
42
+ }));
27
43
  const StoryListContainer = styled.View(({ theme }) => (Object.assign(Object.assign({ top: 0 }, StyleSheet.absoluteFillObject), {
28
44
  // for this to work I need to get the top margin from safeareview context
29
45
  // shadowColor: '#000',
@@ -35,18 +51,37 @@ const StoryListContainer = styled.View(({ theme }) => (Object.assign(Object.assi
35
51
  // shadowRadius: 1.41,
36
52
  // elevation: 2,
37
53
  borderRightWidth: StyleSheet.hairlineWidth, borderRightColor: theme.borderColor, backgroundColor: theme.storyListBackgroundColor })));
38
- const SectionHeader = React.memo(({ title, selected }) => (React.createElement(HeaderContainer, { key: title },
39
- React.createElement(GridIcon, null),
40
- React.createElement(Header, { selected: selected }, title))));
54
+ const SectionHeader = React.memo(({ title, onPress }) => {
55
+ const selected = useIsStorySectionSelected(title);
56
+ return (React.createElement(HeaderContainer, { key: title, selected: selected, onPress: onPress, activeOpacity: 0.8 },
57
+ React.createElement(GridIcon, null),
58
+ React.createElement(Header, { selected: selected }, title)));
59
+ });
41
60
  const ItemTouchable = styled.TouchableOpacity({
42
- padding: 5,
43
- paddingLeft: 40,
61
+ marginHorizontal: 6,
62
+ padding: 6,
63
+ paddingLeft: 24,
44
64
  flexDirection: 'row',
45
65
  alignItems: 'center',
46
- }, ({ selected, theme }) => { var _a; return (selected ? { backgroundColor: (_a = theme === null || theme === void 0 ? void 0 : theme.listItemActiveColor) !== null && _a !== void 0 ? _a : '#1ea7fd' } : {}); });
47
- const ListItem = React.memo(({ kind, title, selected, onPress }) => (React.createElement(ItemTouchable, { key: title, onPress: onPress, activeOpacity: 0.8, testID: `Storybook.ListItem.${kind}.${title}`, accessibilityLabel: `Storybook.ListItem.${title}`, selected: selected },
48
- React.createElement(StoryIcon, { selected: selected }),
49
- React.createElement(Name, { selected: selected }, title))), (prevProps, nextProps) => prevProps.selected === nextProps.selected);
66
+ }, ({ selected, sectionSelected, isLastItem, theme }) => {
67
+ var _a;
68
+ return {
69
+ backgroundColor: selected
70
+ ? ((_a = theme === null || theme === void 0 ? void 0 : theme.listItemActiveColor) !== null && _a !== void 0 ? _a : '#1ea7fd')
71
+ : sectionSelected
72
+ ? theme === null || theme === void 0 ? void 0 : theme.sectionActiveColor
73
+ : undefined,
74
+ borderBottomLeftRadius: isLastItem ? 6 : undefined,
75
+ borderBottomRightRadius: isLastItem ? 6 : undefined,
76
+ };
77
+ });
78
+ const ListItem = React.memo(({ storyId, kind, title, isLastItem, onPress }) => {
79
+ const selected = useIsStorySelected(storyId);
80
+ const sectionSelected = useIsStorySectionSelected(kind);
81
+ return (React.createElement(ItemTouchable, { key: title, onPress: onPress, activeOpacity: 0.8, testID: `Storybook.ListItem.${kind}.${title}`, accessibilityLabel: `Storybook.ListItem.${title}`, selected: selected, sectionSelected: sectionSelected, isLastItem: isLastItem },
82
+ React.createElement(StoryIcon, { selected: selected }),
83
+ React.createElement(Name, { selected: selected }, title)));
84
+ }, (prevProps, nextProps) => prevProps.storyId === nextProps.storyId);
50
85
  const getStories = (storyIndex) => {
51
86
  if (!storyIndex) {
52
87
  return [];
@@ -63,9 +98,13 @@ const getStories = (storyIndex) => {
63
98
  };
64
99
  const styles = StyleSheet.create({
65
100
  sectionList: { flex: 1 },
101
+ sectionListContentContainer: { paddingBottom: 6 },
66
102
  });
67
103
  const tabBarHeight = 40;
68
- const StoryListView = ({ selectedStoryContext, storyIndex }) => {
104
+ function keyExtractor(item, index) {
105
+ return item.id + index;
106
+ }
107
+ const StoryListView = ({ storyIndex }) => {
69
108
  const insets = useSafeAreaInsets();
70
109
  const originalData = useMemo(() => getStories(storyIndex), [storyIndex]);
71
110
  const [data, setData] = useState(originalData);
@@ -92,14 +131,20 @@ const StoryListView = ({ selectedStoryContext, storyIndex }) => {
92
131
  const channel = addons.getChannel();
93
132
  channel.emit(Events.SET_CURRENT_STORY, { storyId });
94
133
  };
95
- const safeStyle = { flex: 1, marginTop: insets.top, paddingBottom: insets.bottom + tabBarHeight };
134
+ const safeStyle = React.useMemo(() => {
135
+ return { flex: 1, marginTop: insets.top, paddingBottom: insets.bottom + tabBarHeight };
136
+ }, [insets]);
137
+ const renderItem = React.useCallback(({ item, index, section }) => {
138
+ return (React.createElement(ListItem, { storyId: item.id, title: item.name, kind: item.title, isLastItem: index === section.data.length - 1, onPress: () => changeStory(item.id) }));
139
+ }, []);
140
+ const renderSectionHeader = React.useCallback(({ section: { title, data } }) => (React.createElement(SectionHeader, { title: title, onPress: () => changeStory(data[0].id) })), []);
96
141
  return (React.createElement(StoryListContainer, null,
97
142
  React.createElement(View, { style: safeStyle },
98
- React.createElement(SearchBar, { testID: "Storybook.ListView.SearchBar", clearButtonMode: "while-editing", disableFullscreenUI: true, onChangeText: handleChangeSearchText, placeholder: "Filter", returnKeyType: "search" }),
143
+ React.createElement(SearchBar, { testID: "Storybook.ListView.SearchBar", onChangeText: handleChangeSearchText, placeholder: "Find by name" }),
99
144
  React.createElement(SectionList
100
145
  // contentInset={{ bottom: insets.bottom, top: 0 }}
101
146
  , {
102
147
  // contentInset={{ bottom: insets.bottom, top: 0 }}
103
- style: styles.sectionList, testID: "Storybook.ListView", renderItem: ({ item }) => (React.createElement(ListItem, { title: item.name, kind: item.title, selected: selectedStoryContext && item.id === selectedStoryContext.id, onPress: () => changeStory(item.id) })), renderSectionHeader: ({ section: { title } }) => (React.createElement(SectionHeader, { title: title, selected: selectedStoryContext && title === selectedStoryContext.title })), keyExtractor: (item, index) => item.id + index, sections: data, stickySectionHeadersEnabled: false }))));
148
+ style: styles.sectionList, contentContainerStyle: styles.sectionListContentContainer, testID: "Storybook.ListView", renderItem: renderItem, renderSectionHeader: renderSectionHeader, keyExtractor: keyExtractor, sections: data, stickySectionHeadersEnabled: false }))));
104
149
  };
105
- export default StoryListView;
150
+ export default React.memo(StoryListView);
@@ -1,8 +1,3 @@
1
- /// <reference types="react" />
2
- import type { StoryContext } from '@storybook/csf';
3
- import { ReactNativeFramework } from 'src/types/types-6.0';
4
- interface Props {
5
- context?: StoryContext<ReactNativeFramework>;
6
- }
7
- declare const StoryView: ({ context }: Props) => JSX.Element;
8
- export default StoryView;
1
+ import React from 'react';
2
+ declare const _default: React.MemoExoticComponent<() => JSX.Element>;
3
+ export default _default;
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import { Text, View, StyleSheet } from 'react-native';
3
+ import { useStoryContext } from '../../../hooks';
3
4
  const styles = StyleSheet.create({
4
5
  container: { flex: 1 },
5
6
  helpContainer: {
@@ -10,7 +11,8 @@ const styles = StyleSheet.create({
10
11
  justifyContent: 'center',
11
12
  },
12
13
  });
13
- const StoryView = ({ context }) => {
14
+ const StoryView = () => {
15
+ const context = useStoryContext();
14
16
  const id = context === null || context === void 0 ? void 0 : context.id;
15
17
  if (context && context.unboundStoryFn) {
16
18
  const { unboundStoryFn: StoryComponent } = context;
@@ -19,4 +21,4 @@ const StoryView = ({ context }) => {
19
21
  return (React.createElement(View, { style: styles.helpContainer },
20
22
  React.createElement(Text, null, "Please open navigator and select a story to preview.")));
21
23
  };
22
- export default StoryView;
24
+ export default React.memo(StoryView);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storybook/react-native",
3
- "version": "6.5.0-rc.0",
3
+ "version": "6.5.0-rc.1",
4
4
  "description": "A better way to develop React Native Components for your app",
5
5
  "keywords": [
6
6
  "react",
@@ -63,6 +63,7 @@
63
63
  "commander": "^8.2.0",
64
64
  "emotion-theming": "^10.0.19",
65
65
  "glob": "^7.1.7",
66
+ "jotai": "^2.0.2",
66
67
  "prettier": "^2.4.1",
67
68
  "react-native-swipe-gestures": "^1.0.5",
68
69
  "util": "^0.12.4"
@@ -86,5 +87,5 @@
86
87
  "publishConfig": {
87
88
  "access": "public"
88
89
  },
89
- "gitHead": "9ce9d2794c2b7f1f3c177efb8563862255389f07"
90
+ "gitHead": "deada392ffc817d872b9e3fd7b00cbede4334e02"
90
91
  }
@@ -49,6 +49,55 @@ import \\"@storybook/addon-ondevice-actions/register\\";
49
49
  "
50
50
  `;
51
51
 
52
+ exports[`loader writeRequires when there is a configuration object writes the story imports 1`] = `
53
+ "
54
+ /* do not change this file, it is auto generated by storybook. */
55
+
56
+ import { configure, addDecorator, addParameters, addArgsEnhancer, clearDecorators } from '@storybook/react-native';
57
+
58
+ global.STORIES = [{\\"titlePrefix\\":\\"ComponentsPrefix\\",\\"files\\":\\"**/*.stories.tsx\\",\\"directory\\":\\"./scripts/mocks/configuration-objects/components\\",\\"importPathMatcher\\":\\"^\\\\\\\\.[\\\\\\\\\\\\\\\\/](?:scripts\\\\\\\\/mocks\\\\\\\\/configuration-objects\\\\\\\\/components(?:\\\\\\\\/(?!\\\\\\\\.)(?:(?:(?!(?:^|\\\\\\\\/)\\\\\\\\.).)*?)\\\\\\\\/|\\\\\\\\/|$)(?!\\\\\\\\.)(?=.)[^/]*?\\\\\\\\.stories\\\\\\\\.tsx)$\\"}]
59
+
60
+ import \\"@storybook/addon-ondevice-notes/register\\";
61
+ import \\"@storybook/addon-ondevice-controls/register\\";
62
+ import \\"@storybook/addon-ondevice-backgrounds/register\\";
63
+ import \\"@storybook/addon-ondevice-actions/register\\";
64
+
65
+ import { argsEnhancers } from \\"@storybook/addon-actions/dist/modern/preset/addArgs\\"
66
+
67
+
68
+ import { decorators, parameters } from './preview';
69
+
70
+ if (decorators) {
71
+ if(__DEV__){
72
+ // stops the warning from showing on every HMR
73
+ require('react-native').LogBox.ignoreLogs([
74
+ '\`clearDecorators\` is deprecated and will be removed in Storybook 7.0',
75
+ ]);
76
+ }
77
+ // workaround for global decorators getting infinitely applied on HMR, see https://github.com/storybookjs/react-native/issues/185
78
+ clearDecorators();
79
+ decorators.forEach((decorator) => addDecorator(decorator));
80
+ }
81
+
82
+ if (parameters) {
83
+ addParameters(parameters);
84
+ }
85
+
86
+
87
+
88
+ try {
89
+ argsEnhancers.forEach(enhancer => addArgsEnhancer(enhancer));
90
+ } catch{}
91
+
92
+
93
+ const getStories=() => {
94
+ return {\\"./scripts/mocks/configuration-objects/components/FakeStory.stories.tsx\\": require(\\"./components/FakeStory.stories.tsx\\")};
95
+ }
96
+
97
+ configure(getStories, module, false)
98
+ "
99
+ `;
100
+
52
101
  exports[`loader writeRequires when there is a story glob and exclude paths globs writes the story imports 1`] = `
53
102
  "
54
103
  /* do not change this file, it is auto generated by storybook. */
@@ -91,7 +140,7 @@ import \\"@storybook/addon-ondevice-actions/register\\";
91
140
 
92
141
 
93
142
  const getStories=() => {
94
- return {\\"./scripts/mocks/exclude-config-files/include-components/FakeStory.stories.tsx\\": require(\\"include-components/FakeStory.stories.tsx\\")};
143
+ return {\\"./scripts/mocks/exclude-config-files/include-components/FakeStory.stories.tsx\\": require(\\"./include-components/FakeStory.stories.tsx\\")};
95
144
  }
96
145
 
97
146
  configure(getStories, module, false)
package/scripts/loader.js CHANGED
@@ -72,6 +72,10 @@ function getPreviewExists({ configPath }) {
72
72
  return !!getFilePathExtension({ configPath }, 'preview');
73
73
  }
74
74
 
75
+ function ensureRelativePathHasDot(relativePath) {
76
+ return relativePath.startsWith('.') ? relativePath : `./${relativePath}`;
77
+ }
78
+
75
79
  function writeRequires({ configPath, absolute = false }) {
76
80
  const storybookRequiresLocation = path.resolve(cwd, configPath, 'storybook.requires.js');
77
81
 
@@ -81,13 +85,30 @@ function writeRequires({ configPath, absolute = false }) {
81
85
  const excludePaths = reactNativeOptions && reactNativeOptions.excludePaths;
82
86
  const normalizedExcludePaths = normalizeExcludePaths(excludePaths);
83
87
 
84
- const storyPaths = main.stories.reduce((acc, storyGlob) => {
85
- const paths = glob.sync(storyGlob, {
86
- cwd: path.resolve(cwd, configPath),
87
- absolute,
88
- // default to always ignore (exclude) anything in node_modules
89
- ignore: normalizedExcludePaths !== undefined ? normalizedExcludePaths : ['**/node_modules'],
90
- });
88
+ const storiesSpecifiers = normalizeStories(main.stories, {
89
+ configDir: configPath,
90
+ workingDir: cwd,
91
+ });
92
+
93
+ const storyRequires = storiesSpecifiers.reduce((acc, specifier) => {
94
+ const paths = glob
95
+ .sync(specifier.files, {
96
+ cwd: path.resolve(cwd, specifier.directory),
97
+ absolute,
98
+ // default to always ignore (exclude) anything in node_modules
99
+ ignore: normalizedExcludePaths !== undefined ? normalizedExcludePaths : ['**/node_modules'],
100
+ })
101
+ .map((storyPath) => {
102
+ const pathWithDirectory = path.join(specifier.directory, storyPath);
103
+ const requirePath = absolute
104
+ ? storyPath
105
+ : ensureRelativePathHasDot(path.relative(configPath, pathWithDirectory));
106
+
107
+ const absolutePath = absolute ? requirePath : path.resolve(configPath, requirePath);
108
+ const pathRelativeToCwd = path.relative(cwd, absolutePath);
109
+
110
+ return `"./${pathRelativeToCwd}": require("${requirePath}")`;
111
+ });
91
112
  return [...acc, ...paths];
92
113
  }, []);
93
114
 
@@ -97,15 +118,7 @@ function writeRequires({ configPath, absolute = false }) {
97
118
 
98
119
  let previewJs = previewExists ? previewImports : '';
99
120
 
100
- const storyRequires = storyPaths
101
- .map((storyPath) => {
102
- const storyPathToAbsolute = path.resolve(configPath, storyPath);
103
- const relative = path.relative(cwd, storyPathToAbsolute);
104
- return `"./${relative}": require("${storyPath}")`;
105
- })
106
- .join(',');
107
-
108
- const path_obj_str = `{${storyRequires}}`;
121
+ const path_obj_str = `{${storyRequires.join(',')}}`;
109
122
 
110
123
  const registerAddons = main.addons?.map((addon) => `import "${addon}/register";`).join('\n');
111
124
  let enhancersImport = '';
@@ -171,5 +171,15 @@ describe('loader', () => {
171
171
  );
172
172
  });
173
173
  });
174
+
175
+ describe('when there is a configuration object', () => {
176
+ it('writes the story imports', () => {
177
+ writeRequires({ configPath: 'scripts/mocks/configuration-objects' });
178
+ expect(pathMock).toEqual(
179
+ path.resolve(__dirname, 'mocks/configuration-objects/storybook.requires.js')
180
+ );
181
+ expect(fileContentMock).toMatchSnapshot();
182
+ });
183
+ });
174
184
  });
175
185
  });
@@ -0,0 +1 @@
1
+ export const FakeComponent = () => null;
@@ -0,0 +1,9 @@
1
+ import { FakeComponent } from './FakeComponent';
2
+
3
+ export default {
4
+ component: FakeComponent,
5
+ };
6
+
7
+ export const Basic = {
8
+ args: {},
9
+ };
@@ -0,0 +1,15 @@
1
+ module.exports = {
2
+ stories: [
3
+ {
4
+ files: '**/*.stories.tsx',
5
+ directory: './components',
6
+ titlePrefix: 'ComponentsPrefix',
7
+ },
8
+ ],
9
+ addons: [
10
+ '@storybook/addon-ondevice-notes',
11
+ '@storybook/addon-ondevice-controls',
12
+ '@storybook/addon-ondevice-backgrounds',
13
+ '@storybook/addon-ondevice-actions',
14
+ ],
15
+ };
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import { View, StyleSheet } from 'react-native';
3
+ import { withBackgrounds } from '@storybook/addon-ondevice-backgrounds';
4
+
5
+ export const decorators = [
6
+ (StoryFn) => (
7
+ <View style={styles.container}>
8
+ <StoryFn />
9
+ </View>
10
+ ),
11
+ withBackgrounds,
12
+ ];
13
+ export const parameters = {
14
+ my_param: 'anything',
15
+ backgrounds: [
16
+ { name: 'plain', value: 'white', default: true },
17
+ { name: 'warm', value: 'hotpink' },
18
+ { name: 'cool', value: 'deepskyblue' },
19
+ ],
20
+ };
21
+
22
+ const styles = StyleSheet.create({
23
+ container: { padding: 8, flex: 1 },
24
+ });