@storybook/react-native 6.0.1-beta.0 → 6.0.1-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/dist/document-polyfill/DOM/Document.d.ts +14 -0
- package/dist/document-polyfill/DOM/Document.js +37 -0
- package/dist/document-polyfill/DOM/Element.d.ts +37 -0
- package/dist/document-polyfill/DOM/Element.js +58 -0
- package/dist/document-polyfill/DOM/HTMLCanvasElement.d.ts +4 -0
- package/dist/document-polyfill/DOM/HTMLCanvasElement.js +4 -0
- package/dist/document-polyfill/DOM/HTMLImageElement.d.ts +4 -0
- package/dist/document-polyfill/DOM/HTMLImageElement.js +4 -0
- package/dist/document-polyfill/DOM/HTMLVideoElement.d.ts +4 -0
- package/dist/document-polyfill/DOM/HTMLVideoElement.js +4 -0
- package/dist/document-polyfill/DOM/Node.d.ts +26 -0
- package/dist/document-polyfill/DOM/Node.js +33 -0
- package/dist/{preview/global.js → document-polyfill/index.d.ts} +0 -0
- package/dist/document-polyfill/index.js +3 -0
- package/dist/document-polyfill/module.d.ts +0 -0
- package/dist/document-polyfill/module.js +1 -0
- package/dist/{types-6.0.js → document-polyfill/module.native.d.ts} +0 -0
- package/dist/document-polyfill/module.native.js +2 -0
- package/dist/index.d.ts +16 -13
- package/dist/index.js +18 -18
- package/dist/preview/View.d.ts +40 -0
- package/dist/preview/View.js +90 -0
- package/dist/preview/components/OnDeviceUI/OnDeviceUI.d.ts +6 -3
- package/dist/preview/components/OnDeviceUI/OnDeviceUI.js +33 -38
- package/dist/preview/components/OnDeviceUI/Panel.js +1 -0
- package/dist/preview/components/OnDeviceUI/animation.d.ts +16 -6
- package/dist/preview/components/OnDeviceUI/animation.js +4 -3
- package/dist/preview/components/OnDeviceUI/navigation/Bar.d.ts +3 -1
- package/dist/preview/components/OnDeviceUI/navigation/Bar.js +1 -1
- package/dist/preview/components/OnDeviceUI/navigation/Navigation.d.ts +4 -3
- package/dist/preview/components/OnDeviceUI/navigation/Navigation.js +15 -10
- package/dist/preview/components/OnDeviceUI/navigation/VisibilityButton.d.ts +3 -1
- package/dist/preview/components/OnDeviceUI/navigation/VisibilityButton.js +34 -5
- package/dist/preview/components/Shared/icons.d.ts +5 -0
- package/dist/preview/components/Shared/icons.js +21 -0
- package/dist/preview/components/Shared/text.d.ts +3 -32
- package/dist/preview/components/Shared/text.js +3 -4
- package/dist/preview/components/Shared/theme.d.ts +4 -0
- package/dist/preview/components/Shared/theme.js +4 -0
- package/dist/preview/components/StoryListView/StoryListView.d.ts +7 -4
- package/dist/preview/components/StoryListView/StoryListView.js +46 -27
- package/dist/preview/components/StoryView/StoryView.d.ts +5 -3
- package/dist/preview/components/StoryView/StoryView.js +6 -24
- package/dist/preview/executeLoadable.d.ts +24 -0
- package/dist/preview/executeLoadable.js +79 -0
- package/dist/preview/rn-host-detect.d.ts +1 -0
- package/dist/preview/rn-host-detect.js +62 -0
- package/dist/preview/start.d.ts +16 -0
- package/dist/preview/start.js +83 -0
- package/dist/types/types-6.0.d.ts +72 -0
- package/dist/types/types-6.0.js +1 -0
- package/dist/types/types.d.ts +14 -0
- package/dist/types/types.js +1 -0
- package/package.json +16 -13
- package/scripts/__snapshots__/loader.test.js.snap +82 -7
- package/scripts/loader.js +40 -10
- package/scripts/loader.test.js +47 -5
- package/scripts/mocks/file-extensions/FakeComponent.tsx +1 -0
- package/scripts/mocks/file-extensions/FakeStory.stories.tsx +10 -0
- package/scripts/mocks/file-extensions/main.ts +13 -0
- package/scripts/mocks/file-extensions/preview.tsx +23 -0
- package/scripts/mocks/preview-files/js/preview.js +24 -0
- package/scripts/mocks/preview-files/jsx/preview.jsx +24 -0
- package/scripts/mocks/preview-files/ts/preview.ts +9 -0
- package/scripts/mocks/preview-files/tsx/preview.tsx +9 -0
- package/scripts/mocks/wrong-extension-preview/FakeComponent.tsx +1 -0
- package/scripts/mocks/wrong-extension-preview/FakeStory.stories.tsx +10 -0
- package/scripts/mocks/wrong-extension-preview/main.js +9 -0
- package/scripts/mocks/wrong-extension-preview/preview.txt +24 -0
- package/scripts/watcher.js +7 -4
- package/dist/preview/Preview.d.ts +0 -55
- package/dist/preview/Preview.js +0 -117
- package/dist/preview/global.d.ts +0 -8
- package/dist/preview/index.d.ts +0 -1
- package/dist/preview/index.js +0 -1
- package/dist/preview/loadCsf.d.ts +0 -16
- package/dist/preview/loadCsf.js +0 -175
- package/dist/types-6.0.d.ts +0 -34
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function getHost(hostname: any): any;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/*
|
|
3
|
+
* It only for Debug Remotely mode for Android
|
|
4
|
+
* When __DEV__ === false, we can't use window.require('NativeModules')
|
|
5
|
+
*/
|
|
6
|
+
function getByRemoteConfig(hostname) {
|
|
7
|
+
var remoteModuleConfig = typeof window !== 'undefined' &&
|
|
8
|
+
window.__fbBatchedBridgeConfig &&
|
|
9
|
+
window.__fbBatchedBridgeConfig.remoteModuleConfig;
|
|
10
|
+
if (!Array.isArray(remoteModuleConfig) ||
|
|
11
|
+
(hostname !== 'localhost' && hostname !== '127.0.0.1')) {
|
|
12
|
+
return { hostname: hostname, passed: false };
|
|
13
|
+
}
|
|
14
|
+
var constants = (remoteModuleConfig.find(getConstants) || [])[1];
|
|
15
|
+
if (constants) {
|
|
16
|
+
var serverHost = constants.ServerHost || hostname;
|
|
17
|
+
return { hostname: serverHost.split(':')[0], passed: true };
|
|
18
|
+
}
|
|
19
|
+
return { hostname: hostname, passed: false };
|
|
20
|
+
}
|
|
21
|
+
function getConstants(config) {
|
|
22
|
+
return config && (config[0] === 'AndroidConstants' || config[0] === 'PlatformConstants');
|
|
23
|
+
}
|
|
24
|
+
function getByRNRequirePolyfill(hostname) {
|
|
25
|
+
var NativeModules;
|
|
26
|
+
var PlatformConstants;
|
|
27
|
+
var AndroidConstants;
|
|
28
|
+
if (typeof window === 'undefined' ||
|
|
29
|
+
!window.__DEV__ ||
|
|
30
|
+
typeof window.require !== 'function' ||
|
|
31
|
+
// RN >= 0.56
|
|
32
|
+
// TODO: Get NativeModules for RN >= 0.56
|
|
33
|
+
window.require.name === 'metroRequire') {
|
|
34
|
+
return hostname;
|
|
35
|
+
}
|
|
36
|
+
NativeModules = window.require('NativeModules');
|
|
37
|
+
if (!NativeModules || (!NativeModules.PlatformConstants && !NativeModules.AndroidConstants)) {
|
|
38
|
+
return hostname;
|
|
39
|
+
}
|
|
40
|
+
PlatformConstants = NativeModules.PlatformConstants;
|
|
41
|
+
AndroidConstants = NativeModules.AndroidConstants;
|
|
42
|
+
var serverHost = (PlatformConstants ? PlatformConstants.ServerHost : AndroidConstants.ServerHost) || hostname;
|
|
43
|
+
return serverHost.split(':')[0];
|
|
44
|
+
}
|
|
45
|
+
/*
|
|
46
|
+
* Get React Native server IP if hostname is `localhost`
|
|
47
|
+
* On Android emulator, the IP of host is `10.0.2.2` (Genymotion: 10.0.3.2)
|
|
48
|
+
*/
|
|
49
|
+
export default function getHost(hostname) {
|
|
50
|
+
// Check if it in React Native environment
|
|
51
|
+
if (typeof __fbBatchedBridge !== 'object' ||
|
|
52
|
+
(hostname !== 'localhost' && hostname !== '127.0.0.1')) {
|
|
53
|
+
return hostname;
|
|
54
|
+
}
|
|
55
|
+
var result = getByRemoteConfig(hostname);
|
|
56
|
+
// Leave if get hostname by remote config successful
|
|
57
|
+
if (result.passed) {
|
|
58
|
+
return result.hostname;
|
|
59
|
+
}
|
|
60
|
+
// Otherwise, use RN's require polyfill
|
|
61
|
+
return getByRNRequirePolyfill(hostname);
|
|
62
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/// <reference types="webpack-env" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import { Loadable } from '@storybook/core-client';
|
|
4
|
+
import { PreviewWeb } from '@storybook/preview-web';
|
|
5
|
+
import { ClientApi } from '@storybook/client-api';
|
|
6
|
+
import type { ReactNativeFramework } from '../types/types-6.0';
|
|
7
|
+
import { View } from './View';
|
|
8
|
+
import type { ArgsStoryFn } from '@storybook/csf';
|
|
9
|
+
export declare const render: ArgsStoryFn<ReactNativeFramework>;
|
|
10
|
+
export declare function start(): {
|
|
11
|
+
view: View;
|
|
12
|
+
forceReRender: () => void;
|
|
13
|
+
clientApi: ClientApi<ReactNativeFramework>;
|
|
14
|
+
preview: PreviewWeb<ReactNativeFramework>;
|
|
15
|
+
configure(loadable: Loadable, m: NodeModule): void;
|
|
16
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Channel from '@storybook/channels';
|
|
3
|
+
import { addons } from '@storybook/addons';
|
|
4
|
+
import Events from '@storybook/core-events';
|
|
5
|
+
import { PreviewWeb } from '@storybook/preview-web';
|
|
6
|
+
import { ClientApi, setGlobalRender } from '@storybook/client-api';
|
|
7
|
+
import { View } from './View';
|
|
8
|
+
import { executeLoadableForChanges } from './executeLoadable';
|
|
9
|
+
export const render = (args, context) => {
|
|
10
|
+
const { id, component: Component } = context;
|
|
11
|
+
if (!Component) {
|
|
12
|
+
throw new Error(`Unable to render story ${id} as the component annotation is missing from the default export`);
|
|
13
|
+
}
|
|
14
|
+
return React.createElement(Component, Object.assign({}, args));
|
|
15
|
+
};
|
|
16
|
+
export function start() {
|
|
17
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
18
|
+
const channel = new Channel({ async: true });
|
|
19
|
+
addons.setChannel(channel);
|
|
20
|
+
const clientApi = new ClientApi();
|
|
21
|
+
const preview = new PreviewWeb();
|
|
22
|
+
clientApi.storyStore = preview.storyStore;
|
|
23
|
+
setGlobalRender(render);
|
|
24
|
+
preview.urlStore = {
|
|
25
|
+
selection: { storyId: '', viewMode: 'story' },
|
|
26
|
+
selectionSpecifier: null,
|
|
27
|
+
setQueryParams: () => { },
|
|
28
|
+
setSelection: (selection) => {
|
|
29
|
+
preview.urlStore.selection = selection;
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
preview.view = Object.assign(Object.assign({}, preview.view), { prepareForStory: () => null, showNoPreview: () => { }, showPreparingStory: () => { }, applyLayout: () => { }, showErrorDisplay: (e) => {
|
|
33
|
+
console.log(e);
|
|
34
|
+
}, showStoryDuringRender: () => { }, showMain: () => { },
|
|
35
|
+
// these are just to make typescript happy
|
|
36
|
+
showDocs: (_a = preview.view) === null || _a === void 0 ? void 0 : _a.showDocs, storyRoot: (_b = preview.view) === null || _b === void 0 ? void 0 : _b.storyRoot, prepareForDocs: (_c = preview.view) === null || _c === void 0 ? void 0 : _c.prepareForDocs, docsRoot: (_d = preview.view) === null || _d === void 0 ? void 0 : _d.docsRoot, checkIfLayoutExists: (_e = preview.view) === null || _e === void 0 ? void 0 : _e.checkIfLayoutExists, showMode: (_f = preview.view) === null || _f === void 0 ? void 0 : _f.showMode, showPreparingDocs: (_g = preview.view) === null || _g === void 0 ? void 0 : _g.showPreparingDocs, showStory: (_h = preview.view) === null || _h === void 0 ? void 0 : _h.showStory });
|
|
37
|
+
let initialized = false;
|
|
38
|
+
function onStoriesChanged() {
|
|
39
|
+
const storyIndex = clientApi.getStoryIndex();
|
|
40
|
+
preview.onStoriesChanged({ storyIndex });
|
|
41
|
+
view._storyIndex = storyIndex;
|
|
42
|
+
}
|
|
43
|
+
const view = new View(preview);
|
|
44
|
+
return {
|
|
45
|
+
view,
|
|
46
|
+
forceReRender: () => channel.emit(Events.FORCE_RE_RENDER),
|
|
47
|
+
clientApi,
|
|
48
|
+
preview,
|
|
49
|
+
// This gets called each time the user calls configure (i.e. once per HMR)
|
|
50
|
+
// The first time, it constructs the preview, subsequently it updates it
|
|
51
|
+
configure(loadable, m) {
|
|
52
|
+
clientApi.addParameters({ framework: 'react-native' });
|
|
53
|
+
// We need to run the `executeLoadableForChanges` function *inside* the `getProjectAnnotations
|
|
54
|
+
// function in case it throws. So we also need to process its output there also
|
|
55
|
+
const getProjectAnnotations = () => {
|
|
56
|
+
const { added, removed } = executeLoadableForChanges(loadable, m);
|
|
57
|
+
Array.from(added.entries()).forEach(([fileName, fileExports]) => clientApi.facade.addStoriesFromExports(fileName, fileExports));
|
|
58
|
+
Array.from(removed.entries()).forEach(([fileName]) => clientApi.facade.clearFilenameExports(fileName));
|
|
59
|
+
return Object.assign(Object.assign({}, clientApi.facade.projectAnnotations), { renderToDOM: (context) => {
|
|
60
|
+
view._setStory(context.storyContext);
|
|
61
|
+
} });
|
|
62
|
+
};
|
|
63
|
+
const importFn = (path) => clientApi.importFn(path);
|
|
64
|
+
if (!initialized) {
|
|
65
|
+
preview.initialize({
|
|
66
|
+
getStoryIndex: () => {
|
|
67
|
+
const index = clientApi.getStoryIndex();
|
|
68
|
+
view._storyIndex = index;
|
|
69
|
+
return index;
|
|
70
|
+
},
|
|
71
|
+
importFn,
|
|
72
|
+
getProjectAnnotations,
|
|
73
|
+
});
|
|
74
|
+
initialized = true;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
// TODO -- why don't we care about the new annotations?
|
|
78
|
+
getProjectAnnotations();
|
|
79
|
+
onStoriesChanged();
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { ComponentProps, ComponentType, JSXElementConstructor, ReactElement } from 'react';
|
|
2
|
+
import type { Args, ComponentAnnotations, StoryAnnotations, AnnotatedStoryFn } from '@storybook/csf';
|
|
3
|
+
export declare type StoryFnReactReturnType = ReactElement<unknown>;
|
|
4
|
+
export type { Args, ArgTypes, Parameters, StoryContext } from '@storybook/addons';
|
|
5
|
+
export declare type ReactNativeFramework = {
|
|
6
|
+
component: ComponentType<any>;
|
|
7
|
+
storyResult: StoryFnReactReturnType;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* For the common case where a component's stories are simple components that receives args as props:
|
|
11
|
+
*
|
|
12
|
+
* ```tsx
|
|
13
|
+
* export default { ... } as ComponentMeta<typeof Button>;
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare type ComponentMeta<T extends keyof JSX.IntrinsicElements | JSXElementConstructor<any>> = Meta<ComponentProps<T>>;
|
|
17
|
+
/**
|
|
18
|
+
* For the common case where a (CSFv2) story is a simple component that receives args as props:
|
|
19
|
+
*
|
|
20
|
+
* ```tsx
|
|
21
|
+
* const Template: ComponentStory<typeof Button> = (args) => <Button {...args} />
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare type ComponentStoryFn<T extends keyof JSX.IntrinsicElements | JSXElementConstructor<any>> = StoryFn<ComponentProps<T>>;
|
|
25
|
+
/**
|
|
26
|
+
* For the common case where a (CSFv3) story is a simple component that receives args as props:
|
|
27
|
+
*
|
|
28
|
+
* ```tsx
|
|
29
|
+
* const MyStory: ComponentStory<typeof Button> = {
|
|
30
|
+
* args: { buttonArg1: 'val' },
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare type ComponentStoryObj<T extends keyof JSX.IntrinsicElements | JSXElementConstructor<any>> = StoryObj<ComponentProps<T>>;
|
|
35
|
+
/**
|
|
36
|
+
* For the common case where a (CSFv2) story is a simple component that receives args as props:
|
|
37
|
+
*
|
|
38
|
+
* ```tsx
|
|
39
|
+
* const Template: ComponentStory<typeof Button> = (args) => <Button {...args} />
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* NOTE: this is an alias for `ComponentStoryFn`.
|
|
43
|
+
* In Storybook v7, `ComponentStory` will alias `ComponentStoryObj`
|
|
44
|
+
*/
|
|
45
|
+
export declare type ComponentStory<T extends keyof JSX.IntrinsicElements | JSXElementConstructor<any>> = Story<ComponentProps<T>>;
|
|
46
|
+
/**
|
|
47
|
+
* Metadata to configure the stories for a component.
|
|
48
|
+
*
|
|
49
|
+
* @see [Default export](https://storybook.js.org/docs/formats/component-story-format/#default-export)
|
|
50
|
+
*/
|
|
51
|
+
export declare type Meta<TArgs = Args> = ComponentAnnotations<ReactNativeFramework, TArgs>;
|
|
52
|
+
/**
|
|
53
|
+
* Story function that represents a CSFv2 component example.
|
|
54
|
+
*
|
|
55
|
+
* @see [Named Story exports](https://storybook.js.org/docs/formats/component-story-format/#named-story-exports)
|
|
56
|
+
*/
|
|
57
|
+
export declare type StoryFn<TArgs = Args> = AnnotatedStoryFn<ReactNativeFramework, TArgs>;
|
|
58
|
+
/**
|
|
59
|
+
* Story function that represents a CSFv3 component example.
|
|
60
|
+
*
|
|
61
|
+
* @see [Named Story exports](https://storybook.js.org/docs/formats/component-story-format/#named-story-exports)
|
|
62
|
+
*/
|
|
63
|
+
export declare type StoryObj<TArgs = Args> = StoryAnnotations<ReactNativeFramework, TArgs>;
|
|
64
|
+
/**
|
|
65
|
+
* Story function that represents a CSFv2 component example.
|
|
66
|
+
*
|
|
67
|
+
* @see [Named Story exports](https://storybook.js.org/docs/formats/component-story-format/#named-story-exports)
|
|
68
|
+
*
|
|
69
|
+
* NOTE that in Storybook 7.0, this type will be renamed to `StoryFn` and replaced by the current `StoryObj` type.
|
|
70
|
+
*
|
|
71
|
+
*/
|
|
72
|
+
export declare type Story<TArgs = Args> = StoryFn<TArgs>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { RenderContext, RenderContextWithoutStoryContext } from '@storybook/client-api';
|
|
2
|
+
export interface PreviewError {
|
|
3
|
+
message?: string;
|
|
4
|
+
stack?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface RequireContext {
|
|
7
|
+
keys: () => string[];
|
|
8
|
+
(id: string): any;
|
|
9
|
+
resolve(id: string): string;
|
|
10
|
+
}
|
|
11
|
+
export declare type LoaderFunction = () => void | any[];
|
|
12
|
+
export declare type Loadable = RequireContext | RequireContext[] | LoaderFunction;
|
|
13
|
+
export type { RenderContext, RenderContextWithoutStoryContext };
|
|
14
|
+
export declare type RenderStoryFunction = (context: RenderContext) => void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@storybook/react-native",
|
|
3
|
-
"version": "6.0.1-beta.
|
|
3
|
+
"version": "6.0.1-beta.10",
|
|
4
4
|
"description": "A better way to develop React Native Components for your app",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -49,14 +49,15 @@
|
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@emotion/core": "^10.0.20",
|
|
51
51
|
"@emotion/native": "^10.0.14",
|
|
52
|
-
"@storybook/addons": "
|
|
53
|
-
"@storybook/channel-websocket": "
|
|
54
|
-
"@storybook/channels": "
|
|
55
|
-
"@storybook/client-api": "
|
|
56
|
-
"@storybook/client-logger": "
|
|
57
|
-
"@storybook/core-client": "
|
|
58
|
-
"@storybook/core-events": "
|
|
59
|
-
"@storybook/csf": "0.0.
|
|
52
|
+
"@storybook/addons": "^6.5",
|
|
53
|
+
"@storybook/channel-websocket": "^6.5",
|
|
54
|
+
"@storybook/channels": "^6.5",
|
|
55
|
+
"@storybook/client-api": "^6.5",
|
|
56
|
+
"@storybook/client-logger": "^6.5",
|
|
57
|
+
"@storybook/core-client": "^6.5",
|
|
58
|
+
"@storybook/core-events": "^6.5",
|
|
59
|
+
"@storybook/csf": "0.0.2--canary.7c6c115.0",
|
|
60
|
+
"@storybook/preview-web": "^6.5",
|
|
60
61
|
"chokidar": "^3.5.1",
|
|
61
62
|
"commander": "^8.2.0",
|
|
62
63
|
"emotion-theming": "^10.0.19",
|
|
@@ -66,15 +67,17 @@
|
|
|
66
67
|
"util": "^0.12.4"
|
|
67
68
|
},
|
|
68
69
|
"devDependencies": {
|
|
69
|
-
"@types/react
|
|
70
|
+
"@types/react": "^18.0.21",
|
|
71
|
+
"@types/react-native": "^0.70.4",
|
|
70
72
|
"babel-jest": "^26.6.3",
|
|
71
73
|
"jest": "^26.6.3",
|
|
72
|
-
"react-test-renderer": "
|
|
74
|
+
"react-test-renderer": "18.2.0"
|
|
73
75
|
},
|
|
74
76
|
"peerDependencies": {
|
|
75
77
|
"@react-native-async-storage/async-storage": ">=1",
|
|
76
78
|
"react": "*",
|
|
77
|
-
"react-native": ">=0.57.0"
|
|
79
|
+
"react-native": ">=0.57.0",
|
|
80
|
+
"react-native-safe-area-context": "*"
|
|
78
81
|
},
|
|
79
82
|
"engines": {
|
|
80
83
|
"node": ">=8.0.0"
|
|
@@ -82,5 +85,5 @@
|
|
|
82
85
|
"publishConfig": {
|
|
83
86
|
"access": "public"
|
|
84
87
|
},
|
|
85
|
-
"gitHead": "
|
|
88
|
+
"gitHead": "0288f6d0728b0f29698435b5cd2d46dc7dde57fc"
|
|
86
89
|
}
|
|
@@ -1,10 +1,57 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
|
+
exports[`loader writeRequires when there are different file extensions writes the story imports 1`] = `
|
|
4
|
+
"
|
|
5
|
+
/* do not change this file, it is auto generated by storybook. */
|
|
6
|
+
|
|
7
|
+
import { configure, addDecorator, addParameters, addArgsEnhancer, clearDecorators } from '@storybook/react-native';
|
|
8
|
+
|
|
9
|
+
import \\"@storybook/addon-ondevice-notes/register\\";
|
|
10
|
+
import \\"@storybook/addon-ondevice-controls/register\\";
|
|
11
|
+
import \\"@storybook/addon-ondevice-backgrounds/register\\";
|
|
12
|
+
import \\"@storybook/addon-ondevice-actions/register\\";
|
|
13
|
+
|
|
14
|
+
import { argsEnhancers } from \\"@storybook/addon-actions/dist/modern/preset/addArgs\\"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
import { decorators, parameters } from './preview';
|
|
18
|
+
|
|
19
|
+
if (decorators) {
|
|
20
|
+
if(__DEV__){
|
|
21
|
+
// stops the warning from showing on every HMR
|
|
22
|
+
require('react-native').LogBox.ignoreLogs([
|
|
23
|
+
'\`clearDecorators\` is deprecated and will be removed in Storybook 7.0',
|
|
24
|
+
]);
|
|
25
|
+
}
|
|
26
|
+
// workaround for global decorators getting infinitely applied on HMR, see https://github.com/storybookjs/react-native/issues/185
|
|
27
|
+
clearDecorators();
|
|
28
|
+
decorators.forEach((decorator) => addDecorator(decorator));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (parameters) {
|
|
32
|
+
addParameters(parameters);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
argsEnhancers.forEach(enhancer => addArgsEnhancer(enhancer));
|
|
39
|
+
} catch{}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
const getStories=() => {
|
|
43
|
+
return [require(\\"./FakeStory.stories.tsx\\")];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
configure(getStories, module, false)
|
|
47
|
+
"
|
|
48
|
+
`;
|
|
49
|
+
|
|
3
50
|
exports[`loader writeRequires when there is a story glob and exclude paths globs writes the story imports 1`] = `
|
|
4
51
|
"
|
|
5
52
|
/* do not change this file, it is auto generated by storybook. */
|
|
6
53
|
|
|
7
|
-
import { configure, addDecorator, addParameters, addArgsEnhancer } from '@storybook/react-native';
|
|
54
|
+
import { configure, addDecorator, addParameters, addArgsEnhancer, clearDecorators } from '@storybook/react-native';
|
|
8
55
|
|
|
9
56
|
import \\"@storybook/addon-ondevice-notes/register\\";
|
|
10
57
|
import \\"@storybook/addon-ondevice-controls/register\\";
|
|
@@ -17,6 +64,14 @@ import \\"@storybook/addon-ondevice-actions/register\\";
|
|
|
17
64
|
import { decorators, parameters } from './preview';
|
|
18
65
|
|
|
19
66
|
if (decorators) {
|
|
67
|
+
if(__DEV__){
|
|
68
|
+
// stops the warning from showing on every HMR
|
|
69
|
+
require('react-native').LogBox.ignoreLogs([
|
|
70
|
+
'\`clearDecorators\` is deprecated and will be removed in Storybook 7.0',
|
|
71
|
+
]);
|
|
72
|
+
}
|
|
73
|
+
// workaround for global decorators getting infinitely applied on HMR, see https://github.com/storybookjs/react-native/issues/185
|
|
74
|
+
clearDecorators();
|
|
20
75
|
decorators.forEach((decorator) => addDecorator(decorator));
|
|
21
76
|
}
|
|
22
77
|
|
|
@@ -25,7 +80,11 @@ import \\"@storybook/addon-ondevice-actions/register\\";
|
|
|
25
80
|
}
|
|
26
81
|
|
|
27
82
|
|
|
28
|
-
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
argsEnhancers.forEach(enhancer => addArgsEnhancer(enhancer));
|
|
86
|
+
} catch{}
|
|
87
|
+
|
|
29
88
|
|
|
30
89
|
const getStories=() => {
|
|
31
90
|
return [require(\\"include-components/FakeStory.stories.tsx\\")];
|
|
@@ -39,7 +98,7 @@ exports[`loader writeRequires when there is a story glob writes the story import
|
|
|
39
98
|
"
|
|
40
99
|
/* do not change this file, it is auto generated by storybook. */
|
|
41
100
|
|
|
42
|
-
import { configure, addDecorator, addParameters, addArgsEnhancer } from '@storybook/react-native';
|
|
101
|
+
import { configure, addDecorator, addParameters, addArgsEnhancer, clearDecorators } from '@storybook/react-native';
|
|
43
102
|
|
|
44
103
|
import \\"@storybook/addon-ondevice-notes/register\\";
|
|
45
104
|
import \\"@storybook/addon-ondevice-controls/register\\";
|
|
@@ -52,6 +111,14 @@ import \\"@storybook/addon-ondevice-actions/register\\";
|
|
|
52
111
|
import { decorators, parameters } from './preview';
|
|
53
112
|
|
|
54
113
|
if (decorators) {
|
|
114
|
+
if(__DEV__){
|
|
115
|
+
// stops the warning from showing on every HMR
|
|
116
|
+
require('react-native').LogBox.ignoreLogs([
|
|
117
|
+
'\`clearDecorators\` is deprecated and will be removed in Storybook 7.0',
|
|
118
|
+
]);
|
|
119
|
+
}
|
|
120
|
+
// workaround for global decorators getting infinitely applied on HMR, see https://github.com/storybookjs/react-native/issues/185
|
|
121
|
+
clearDecorators();
|
|
55
122
|
decorators.forEach((decorator) => addDecorator(decorator));
|
|
56
123
|
}
|
|
57
124
|
|
|
@@ -60,7 +127,11 @@ import \\"@storybook/addon-ondevice-actions/register\\";
|
|
|
60
127
|
}
|
|
61
128
|
|
|
62
129
|
|
|
63
|
-
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
argsEnhancers.forEach(enhancer => addArgsEnhancer(enhancer));
|
|
133
|
+
} catch{}
|
|
134
|
+
|
|
64
135
|
|
|
65
136
|
const getStories=() => {
|
|
66
137
|
return [require(\\"./FakeStory.stories.tsx\\")];
|
|
@@ -74,7 +145,7 @@ exports[`loader writeRequires when there is no preview does not add preview rela
|
|
|
74
145
|
"
|
|
75
146
|
/* do not change this file, it is auto generated by storybook. */
|
|
76
147
|
|
|
77
|
-
import { configure, addDecorator, addParameters, addArgsEnhancer } from '@storybook/react-native';
|
|
148
|
+
import { configure, addDecorator, addParameters, addArgsEnhancer, clearDecorators } from '@storybook/react-native';
|
|
78
149
|
|
|
79
150
|
import \\"@storybook/addon-ondevice-notes/register\\";
|
|
80
151
|
import \\"@storybook/addon-ondevice-controls/register\\";
|
|
@@ -85,7 +156,11 @@ import \\"@storybook/addon-ondevice-actions/register\\";
|
|
|
85
156
|
|
|
86
157
|
|
|
87
158
|
|
|
88
|
-
|
|
159
|
+
|
|
160
|
+
try {
|
|
161
|
+
argsEnhancers.forEach(enhancer => addArgsEnhancer(enhancer));
|
|
162
|
+
} catch{}
|
|
163
|
+
|
|
89
164
|
|
|
90
165
|
const getStories=() => {
|
|
91
166
|
return [require(\\"./FakeStory.stories.tsx\\")];
|
|
@@ -99,7 +174,7 @@ exports[`loader writeRequires when there is no story glob or addons writes no st
|
|
|
99
174
|
"
|
|
100
175
|
/* do not change this file, it is auto generated by storybook. */
|
|
101
176
|
|
|
102
|
-
import { configure, addDecorator, addParameters, addArgsEnhancer } from '@storybook/react-native';
|
|
177
|
+
import { configure, addDecorator, addParameters, addArgsEnhancer, clearDecorators } from '@storybook/react-native';
|
|
103
178
|
|
|
104
179
|
|
|
105
180
|
|
package/scripts/loader.js
CHANGED
|
@@ -4,11 +4,21 @@ const glob = require('glob');
|
|
|
4
4
|
const prettier = require('prettier');
|
|
5
5
|
|
|
6
6
|
const cwd = process.cwd();
|
|
7
|
+
const supportedExtensions = ['js', 'jsx', 'ts', 'tsx', 'cjs', 'mjs'];
|
|
7
8
|
|
|
9
|
+
// we clear decorators as a workaround for global decorators getting infinitely applied on HMR
|
|
8
10
|
const previewImports = `
|
|
9
11
|
import { decorators, parameters } from './preview';
|
|
10
12
|
|
|
11
13
|
if (decorators) {
|
|
14
|
+
if(__DEV__){
|
|
15
|
+
// stops the warning from showing on every HMR
|
|
16
|
+
require('react-native').LogBox.ignoreLogs([
|
|
17
|
+
'\`clearDecorators\` is deprecated and will be removed in Storybook 7.0',
|
|
18
|
+
]);
|
|
19
|
+
}
|
|
20
|
+
// workaround for global decorators getting infinitely applied on HMR, see https://github.com/storybookjs/react-native/issues/185
|
|
21
|
+
clearDecorators();
|
|
12
22
|
decorators.forEach((decorator) => addDecorator(decorator));
|
|
13
23
|
}
|
|
14
24
|
|
|
@@ -38,19 +48,34 @@ function requireUncached(module) {
|
|
|
38
48
|
}
|
|
39
49
|
|
|
40
50
|
function getMain({ configPath }) {
|
|
41
|
-
const
|
|
51
|
+
const fileExtension = getFilePathExtension({ configPath }, 'main');
|
|
52
|
+
if (fileExtension === null) {
|
|
53
|
+
throw new Error('main config file not found');
|
|
54
|
+
}
|
|
55
|
+
const mainPath = path.resolve(cwd, configPath, `main.${fileExtension}`);
|
|
56
|
+
|
|
42
57
|
return requireUncached(mainPath);
|
|
43
58
|
}
|
|
44
59
|
|
|
60
|
+
function getFilePathExtension({ configPath }, fileName) {
|
|
61
|
+
for (const ext of supportedExtensions) {
|
|
62
|
+
const filePath = path.resolve(cwd, configPath, `${fileName}.${ext}`);
|
|
63
|
+
if (fs.existsSync(filePath)) {
|
|
64
|
+
return ext;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
|
|
45
70
|
function getPreviewExists({ configPath }) {
|
|
46
|
-
|
|
47
|
-
return fs.existsSync(previewPath);
|
|
71
|
+
return !!getFilePathExtension({ configPath }, 'preview');
|
|
48
72
|
}
|
|
49
73
|
|
|
50
74
|
function writeRequires({ configPath, absolute = false }) {
|
|
51
75
|
const storybookRequiresLocation = path.resolve(cwd, configPath, 'storybook.requires.js');
|
|
52
76
|
|
|
53
|
-
const
|
|
77
|
+
const mainImport = getMain({ configPath });
|
|
78
|
+
const main = mainImport.default ?? mainImport;
|
|
54
79
|
const reactNativeOptions = main.reactNativeOptions;
|
|
55
80
|
const excludePaths = reactNativeOptions && reactNativeOptions.excludePaths;
|
|
56
81
|
const normalizedExcludePaths = normalizeExcludePaths(excludePaths);
|
|
@@ -60,9 +85,7 @@ function writeRequires({ configPath, absolute = false }) {
|
|
|
60
85
|
cwd: path.resolve(cwd, configPath),
|
|
61
86
|
absolute,
|
|
62
87
|
// default to always ignore (exclude) anything in node_modules
|
|
63
|
-
ignore: normalizedExcludePaths !== undefined
|
|
64
|
-
? normalizedExcludePaths
|
|
65
|
-
: ['**/node_modules'],
|
|
88
|
+
ignore: normalizedExcludePaths !== undefined ? normalizedExcludePaths : ['**/node_modules'],
|
|
66
89
|
});
|
|
67
90
|
return [...acc, ...paths];
|
|
68
91
|
}, []);
|
|
@@ -76,7 +99,7 @@ function writeRequires({ configPath, absolute = false }) {
|
|
|
76
99
|
const storyRequires = storyPaths.map((storyPath) => `require("${storyPath}")`).join(',');
|
|
77
100
|
const path_array_str = `[${storyRequires}]`;
|
|
78
101
|
|
|
79
|
-
const registerAddons = main.addons
|
|
102
|
+
const registerAddons = main.addons?.map((addon) => `import "${addon}/register";`).join('\n');
|
|
80
103
|
let enhancersImport = '';
|
|
81
104
|
let enhancers = '';
|
|
82
105
|
|
|
@@ -84,13 +107,19 @@ function writeRequires({ configPath, absolute = false }) {
|
|
|
84
107
|
if (main.addons.includes('@storybook/addon-ondevice-actions')) {
|
|
85
108
|
enhancersImport =
|
|
86
109
|
'import { argsEnhancers } from "@storybook/addon-actions/dist/modern/preset/addArgs"';
|
|
87
|
-
|
|
110
|
+
|
|
111
|
+
// try/catch is a temporary fix for https://github.com/storybookjs/react-native/issues/327 until a fix is found
|
|
112
|
+
enhancers = `
|
|
113
|
+
try {
|
|
114
|
+
argsEnhancers.forEach(enhancer => addArgsEnhancer(enhancer));
|
|
115
|
+
} catch{}
|
|
116
|
+
`;
|
|
88
117
|
}
|
|
89
118
|
|
|
90
119
|
const fileContent = `
|
|
91
120
|
/* do not change this file, it is auto generated by storybook. */
|
|
92
121
|
|
|
93
|
-
import { configure, addDecorator, addParameters, addArgsEnhancer } from '@storybook/react-native';
|
|
122
|
+
import { configure, addDecorator, addParameters, addArgsEnhancer, clearDecorators } from '@storybook/react-native';
|
|
94
123
|
|
|
95
124
|
${registerAddons}
|
|
96
125
|
|
|
@@ -119,4 +148,5 @@ module.exports = {
|
|
|
119
148
|
writeRequires,
|
|
120
149
|
getMain,
|
|
121
150
|
getPreviewExists,
|
|
151
|
+
getFilePathExtension,
|
|
122
152
|
};
|
package/scripts/loader.test.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const { writeRequires, getMain, getPreviewExists } = require('./loader');
|
|
3
|
-
const glob = require('glob');
|
|
4
3
|
|
|
5
4
|
let pathMock;
|
|
6
5
|
let fileContentMock;
|
|
@@ -47,24 +46,51 @@ describe('loader', () => {
|
|
|
47
46
|
],
|
|
48
47
|
});
|
|
49
48
|
});
|
|
49
|
+
it('should work for any supported file extension', () => {
|
|
50
|
+
const main = getMain({ configPath: './scripts/mocks/file-extensions' });
|
|
51
|
+
expect(main).toEqual({
|
|
52
|
+
default: {
|
|
53
|
+
stories: ['./FakeStory.stories.tsx'],
|
|
54
|
+
addons: [
|
|
55
|
+
'@storybook/addon-ondevice-notes',
|
|
56
|
+
'@storybook/addon-ondevice-controls',
|
|
57
|
+
'@storybook/addon-ondevice-backgrounds',
|
|
58
|
+
'@storybook/addon-ondevice-actions',
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
});
|
|
50
63
|
});
|
|
51
64
|
|
|
52
65
|
describe('getPreviewExists', () => {
|
|
66
|
+
const supportedExtensions = ['js', 'jsx', 'ts', 'tsx'];
|
|
53
67
|
describe('when using a relative path', () => {
|
|
54
68
|
it('should return true if the preview exists', () => {
|
|
55
|
-
|
|
69
|
+
supportedExtensions.forEach((ext) => {
|
|
70
|
+
expect(getPreviewExists({ configPath: `scripts/mocks/preview-files/${ext}` })).toBe(true);
|
|
71
|
+
});
|
|
56
72
|
});
|
|
57
73
|
|
|
58
74
|
it('should return false if the preview does not exist', () => {
|
|
59
75
|
expect(getPreviewExists({ configPath: './scripts/mocks/no-preview' })).toBe(false);
|
|
60
76
|
});
|
|
77
|
+
|
|
78
|
+
it('should return false if the preview does not match any of supportedExtensions values', () => {
|
|
79
|
+
expect(getPreviewExists({ configPath: './scripts/mocks/wrong-extension-preview' })).toBe(
|
|
80
|
+
false
|
|
81
|
+
);
|
|
82
|
+
});
|
|
61
83
|
});
|
|
62
84
|
|
|
63
85
|
describe('when using an absolute path', () => {
|
|
64
86
|
it('should return true if the preview exists', () => {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
87
|
+
supportedExtensions.forEach((ext) => {
|
|
88
|
+
expect(
|
|
89
|
+
getPreviewExists({
|
|
90
|
+
configPath: path.resolve(__dirname, `mocks/preview-files/${ext}`),
|
|
91
|
+
})
|
|
92
|
+
).toBe(true);
|
|
93
|
+
});
|
|
68
94
|
});
|
|
69
95
|
|
|
70
96
|
it('should return false if the preview does not exist', () => {
|
|
@@ -72,6 +98,12 @@ describe('loader', () => {
|
|
|
72
98
|
false
|
|
73
99
|
);
|
|
74
100
|
});
|
|
101
|
+
|
|
102
|
+
it('should return false if the preview does not match any of supportedExtensions values', () => {
|
|
103
|
+
expect(
|
|
104
|
+
getPreviewExists({ configPath: path.resolve(__dirname, 'mocks/wrong-extension-preview') })
|
|
105
|
+
).toBe(false);
|
|
106
|
+
});
|
|
75
107
|
});
|
|
76
108
|
});
|
|
77
109
|
|
|
@@ -86,6 +118,16 @@ describe('loader', () => {
|
|
|
86
118
|
});
|
|
87
119
|
});
|
|
88
120
|
|
|
121
|
+
describe('when there are different file extensions', () => {
|
|
122
|
+
it('writes the story imports', () => {
|
|
123
|
+
writeRequires({ configPath: 'scripts/mocks/file-extensions' });
|
|
124
|
+
expect(pathMock).toEqual(
|
|
125
|
+
path.resolve(__dirname, 'mocks/file-extensions/storybook.requires.js')
|
|
126
|
+
);
|
|
127
|
+
expect(fileContentMock).toMatchSnapshot();
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
89
131
|
describe('when there is a story glob and exclude paths globs', () => {
|
|
90
132
|
it('writes the story imports', () => {
|
|
91
133
|
writeRequires({ configPath: 'scripts/mocks/exclude-config-files' });
|