@storybook/react-native 6.0.1-beta.7 → 6.0.1-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/document-polyfill/DOM/Document.d.ts +14 -0
  2. package/dist/document-polyfill/DOM/Document.js +37 -0
  3. package/dist/document-polyfill/DOM/Element.d.ts +37 -0
  4. package/dist/document-polyfill/DOM/Element.js +58 -0
  5. package/dist/document-polyfill/DOM/HTMLCanvasElement.d.ts +4 -0
  6. package/dist/document-polyfill/DOM/HTMLCanvasElement.js +4 -0
  7. package/dist/document-polyfill/DOM/HTMLImageElement.d.ts +4 -0
  8. package/dist/document-polyfill/DOM/HTMLImageElement.js +4 -0
  9. package/dist/document-polyfill/DOM/HTMLVideoElement.d.ts +4 -0
  10. package/dist/document-polyfill/DOM/HTMLVideoElement.js +4 -0
  11. package/dist/document-polyfill/DOM/Node.d.ts +26 -0
  12. package/dist/document-polyfill/DOM/Node.js +33 -0
  13. package/dist/{preview/global.js → document-polyfill/index.d.ts} +0 -0
  14. package/dist/document-polyfill/index.js +3 -0
  15. package/dist/document-polyfill/module.d.ts +0 -0
  16. package/dist/document-polyfill/module.js +1 -0
  17. package/dist/{types-6.0.js → document-polyfill/module.native.d.ts} +0 -0
  18. package/dist/document-polyfill/module.native.js +2 -0
  19. package/dist/index.d.ts +13 -12
  20. package/dist/index.js +13 -17
  21. package/dist/preview/View.d.ts +40 -0
  22. package/dist/preview/View.js +90 -0
  23. package/dist/preview/components/OnDeviceUI/OnDeviceUI.d.ts +6 -3
  24. package/dist/preview/components/OnDeviceUI/OnDeviceUI.js +26 -37
  25. package/dist/preview/components/OnDeviceUI/Panel.js +1 -0
  26. package/dist/preview/components/OnDeviceUI/animation.d.ts +5 -5
  27. package/dist/preview/components/OnDeviceUI/navigation/Bar.d.ts +3 -1
  28. package/dist/preview/components/OnDeviceUI/navigation/Bar.js +1 -1
  29. package/dist/preview/components/OnDeviceUI/navigation/Navigation.d.ts +4 -3
  30. package/dist/preview/components/OnDeviceUI/navigation/Navigation.js +15 -10
  31. package/dist/preview/components/OnDeviceUI/navigation/VisibilityButton.d.ts +3 -1
  32. package/dist/preview/components/OnDeviceUI/navigation/VisibilityButton.js +34 -5
  33. package/dist/preview/components/Shared/icons.d.ts +1 -0
  34. package/dist/preview/components/Shared/text.d.ts +3 -44
  35. package/dist/preview/components/StoryListView/StoryListView.d.ts +7 -4
  36. package/dist/preview/components/StoryListView/StoryListView.js +24 -15
  37. package/dist/preview/components/StoryView/StoryView.d.ts +5 -3
  38. package/dist/preview/components/StoryView/StoryView.js +6 -24
  39. package/dist/preview/executeLoadable.d.ts +24 -0
  40. package/dist/preview/executeLoadable.js +82 -0
  41. package/dist/preview/rn-host-detect.d.ts +1 -0
  42. package/dist/preview/rn-host-detect.js +62 -0
  43. package/dist/preview/start.d.ts +13 -0
  44. package/dist/preview/start.js +75 -0
  45. package/dist/{types-6.0.d.ts → types/types-6.0.d.ts} +4 -0
  46. package/dist/types/types-6.0.js +1 -0
  47. package/dist/types/types.d.ts +14 -0
  48. package/dist/types/types.js +1 -0
  49. package/package.json +16 -13
  50. package/scripts/loader.js +11 -2
  51. package/scripts/loader.test.js +23 -5
  52. package/scripts/mocks/preview-files/js/preview.js +24 -0
  53. package/scripts/mocks/preview-files/jsx/preview.jsx +24 -0
  54. package/scripts/mocks/preview-files/ts/preview.ts +9 -0
  55. package/scripts/mocks/preview-files/tsx/preview.tsx +9 -0
  56. package/scripts/mocks/wrong-extension-preview/FakeComponent.tsx +1 -0
  57. package/scripts/mocks/wrong-extension-preview/FakeStory.stories.tsx +10 -0
  58. package/scripts/mocks/wrong-extension-preview/main.js +9 -0
  59. package/scripts/mocks/wrong-extension-preview/preview.txt +24 -0
  60. package/dist/preview/Preview.d.ts +0 -57
  61. package/dist/preview/Preview.js +0 -119
  62. package/dist/preview/global.d.ts +0 -8
  63. package/dist/preview/index.d.ts +0 -1
  64. package/dist/preview/index.js +0 -1
  65. package/dist/preview/loadCsf.d.ts +0 -16
  66. package/dist/preview/loadCsf.js +0 -180
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storybook/react-native",
3
- "version": "6.0.1-beta.7",
3
+ "version": "6.0.1-canary.0",
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": "~6.3",
53
- "@storybook/channel-websocket": "~6.3",
54
- "@storybook/channels": "~6.3",
55
- "@storybook/client-api": "~6.3",
56
- "@storybook/client-logger": "~6.3",
57
- "@storybook/core-client": "~6.3",
58
- "@storybook/core-events": "~6.3",
59
- "@storybook/csf": "0.0.1",
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-native": "^0.66.15",
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": "17.0.2"
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": "8eb7ea7834e59194bc72376725af56960ffffcaf"
88
+ "gitHead": "2aa26caa5afbee685a7a9eb673ef0afd9b3ad857"
86
89
  }
package/scripts/loader.js CHANGED
@@ -43,8 +43,17 @@ function getMain({ configPath }) {
43
43
  }
44
44
 
45
45
  function getPreviewExists({ configPath }) {
46
- const previewPath = path.resolve(cwd, configPath, 'preview.js');
47
- return fs.existsSync(previewPath);
46
+ const supportedExtensions = ['js', 'jsx', 'ts', 'tsx'];
47
+
48
+ for (const ext of supportedExtensions) {
49
+ const previewPath = path.resolve(cwd, configPath, `preview.${ext}`);
50
+
51
+ if (fs.existsSync(previewPath)) {
52
+ return true;
53
+ }
54
+ }
55
+
56
+ return false;
48
57
  }
49
58
 
50
59
  function writeRequires({ configPath, absolute = false }) {
@@ -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;
@@ -50,21 +49,34 @@ describe('loader', () => {
50
49
  });
51
50
 
52
51
  describe('getPreviewExists', () => {
52
+ const supportedExtensions = ['js', 'jsx', 'ts', 'tsx'];
53
53
  describe('when using a relative path', () => {
54
54
  it('should return true if the preview exists', () => {
55
- expect(getPreviewExists({ configPath: 'scripts/mocks/all-config-files' })).toBe(true);
55
+ supportedExtensions.forEach((ext) => {
56
+ expect(getPreviewExists({ configPath: `scripts/mocks/preview-files/${ext}` })).toBe(true);
57
+ });
56
58
  });
57
59
 
58
60
  it('should return false if the preview does not exist', () => {
59
61
  expect(getPreviewExists({ configPath: './scripts/mocks/no-preview' })).toBe(false);
60
62
  });
63
+
64
+ it('should return false if the preview does not match any of supportedExtensions values', () => {
65
+ expect(getPreviewExists({ configPath: './scripts/mocks/wrong-extension-preview' })).toBe(
66
+ false
67
+ );
68
+ });
61
69
  });
62
70
 
63
71
  describe('when using an absolute path', () => {
64
72
  it('should return true if the preview exists', () => {
65
- expect(
66
- getPreviewExists({ configPath: path.resolve(__dirname, 'mocks/all-config-files') })
67
- ).toBe(true);
73
+ supportedExtensions.forEach((ext) => {
74
+ expect(
75
+ getPreviewExists({
76
+ configPath: path.resolve(__dirname, `mocks/preview-files/${ext}`),
77
+ })
78
+ ).toBe(true);
79
+ });
68
80
  });
69
81
 
70
82
  it('should return false if the preview does not exist', () => {
@@ -72,6 +84,12 @@ describe('loader', () => {
72
84
  false
73
85
  );
74
86
  });
87
+
88
+ it('should return false if the preview does not match any of supportedExtensions values', () => {
89
+ expect(
90
+ getPreviewExists({ configPath: path.resolve(__dirname, 'mocks/wrong-extension-preview') })
91
+ ).toBe(false);
92
+ });
75
93
  });
76
94
  });
77
95
 
@@ -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
+ });
@@ -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
+ });
@@ -0,0 +1,9 @@
1
+ export const decorators: any = [];
2
+ export const parameters = {
3
+ my_param: 'anything',
4
+ backgrounds: [
5
+ { name: 'plain', value: 'white', default: true },
6
+ { name: 'warm', value: 'hotpink' },
7
+ { name: 'cool', value: 'deepskyblue' },
8
+ ],
9
+ };
@@ -0,0 +1,9 @@
1
+ export const decorators: any = [];
2
+ export const parameters = {
3
+ my_param: 'anything',
4
+ backgrounds: [
5
+ { name: 'plain', value: 'white', default: true },
6
+ { name: 'warm', value: 'hotpink' },
7
+ { name: 'cool', value: 'deepskyblue' },
8
+ ],
9
+ };
@@ -0,0 +1 @@
1
+ export const FakeComponent = () => null;
@@ -0,0 +1,10 @@
1
+ import { FakeComponent } from './FakeComponent';
2
+
3
+ export default {
4
+ title: 'components/FakeComponent',
5
+ component: FakeComponent,
6
+ };
7
+
8
+ export const Basic = {
9
+ args: {},
10
+ };
@@ -0,0 +1,9 @@
1
+ module.exports = {
2
+ stories: ['./FakeStory.stories.tsx'],
3
+ addons: [
4
+ '@storybook/addon-ondevice-notes',
5
+ '@storybook/addon-ondevice-controls',
6
+ '@storybook/addon-ondevice-backgrounds',
7
+ '@storybook/addon-ondevice-actions',
8
+ ],
9
+ };
@@ -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
+ });
@@ -1,57 +0,0 @@
1
- /// <reference types="webpack-env" />
2
- /// <reference types="node" />
3
- import Channel from '@storybook/channels';
4
- import { ClientApi, ConfigApi, StoryStore } from '@storybook/client-api';
5
- import { Loadable } from '@storybook/core-client';
6
- import { theme } from './components/Shared/theme';
7
- declare type StoryKind = string;
8
- declare type StoryName = string;
9
- declare type InitialSelection = `${StoryKind}--${StoryName}` | {
10
- /**
11
- * Kind is the default export name or the storiesOf("name") name
12
- */
13
- kind: StoryKind;
14
- /**
15
- * Name is the named export or the .add("name") name
16
- */
17
- name: StoryName;
18
- };
19
- export declare type Params = {
20
- onDeviceUI?: boolean;
21
- resetStorybook?: boolean;
22
- disableWebsockets?: boolean;
23
- query?: string;
24
- host?: string;
25
- port?: number;
26
- secured?: boolean;
27
- initialSelection?: InitialSelection;
28
- shouldPersistSelection?: boolean;
29
- tabOpen?: number;
30
- isUIHidden?: boolean;
31
- shouldDisableKeyboardAvoidingView?: boolean;
32
- keyboardAvoidingViewVerticalOffset?: number;
33
- } & {
34
- theme?: typeof theme;
35
- };
36
- export default class Preview {
37
- _clientApi: ClientApi;
38
- _storyStore: StoryStore;
39
- _addons: any;
40
- _channel: Channel;
41
- _decorators: any[];
42
- _asyncStorageStoryId: string;
43
- _configApi: ConfigApi;
44
- configure: (loadable: Loadable, m: NodeModule, showDeprecationWarning: boolean) => void;
45
- constructor();
46
- api: () => ClientApi;
47
- getStorybookUI: (params?: Partial<Params>) => () => JSX.Element;
48
- _setInitialStory: (initialSelection?: InitialSelection, shouldPersistSelection?: boolean) => Promise<void>;
49
- _getInitialStory: (initialSelection?: InitialSelection, shouldPersistSelection?: boolean) => Promise<import("@storybook/client-api").PublishedStoreItem>;
50
- _getStory(storyId: string): import("@storybook/client-api").PublishedStoreItem;
51
- _selectStoryEvent({ storyId }: {
52
- storyId: string;
53
- }, shouldPersistSelection: any): void;
54
- _selectStory(story: any): void;
55
- _checkStory(storyId: string): import("@storybook/client-api").PublishedStoreItem;
56
- }
57
- export {};
@@ -1,119 +0,0 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- import AsyncStorage from '@react-native-async-storage/async-storage';
11
- import { addons } from '@storybook/addons';
12
- import Channel from '@storybook/channels';
13
- import { ClientApi, ConfigApi, StoryStore } from '@storybook/client-api';
14
- import Events from '@storybook/core-events';
15
- import { toId } from '@storybook/csf';
16
- import { ThemeProvider } from 'emotion-theming';
17
- import React from 'react';
18
- import OnDeviceUI from './components/OnDeviceUI';
19
- import { theme } from './components/Shared/theme';
20
- import { loadCsf } from './loadCsf';
21
- const STORAGE_KEY = 'lastOpenedStory';
22
- export default class Preview {
23
- constructor() {
24
- this.api = () => {
25
- return this._clientApi;
26
- };
27
- this.getStorybookUI = (params = {}) => {
28
- const { initialSelection, shouldPersistSelection = true } = params;
29
- this._setInitialStory(initialSelection, shouldPersistSelection);
30
- this._channel.on(Events.SET_CURRENT_STORY, (d) => {
31
- this._selectStoryEvent(d, shouldPersistSelection);
32
- });
33
- const { _storyStore } = this;
34
- addons.loadAddons(this._clientApi);
35
- const appliedTheme = Object.assign(Object.assign({}, theme), params.theme);
36
- return () => (React.createElement(ThemeProvider, { theme: appliedTheme },
37
- React.createElement(OnDeviceUI, { storyStore: _storyStore, isUIHidden: params.isUIHidden, tabOpen: params.tabOpen, shouldDisableKeyboardAvoidingView: params.shouldDisableKeyboardAvoidingView, keyboardAvoidingViewVerticalOffset: params.keyboardAvoidingViewVerticalOffset })));
38
- };
39
- this._setInitialStory = (initialSelection, shouldPersistSelection = true) => __awaiter(this, void 0, void 0, function* () {
40
- const story = yield this._getInitialStory(initialSelection, shouldPersistSelection);
41
- if (story) {
42
- this._selectStory(story);
43
- }
44
- });
45
- this._getInitialStory = (initialSelection, shouldPersistSelection = true) => __awaiter(this, void 0, void 0, function* () {
46
- let story = null;
47
- const initialSelectionId = initialSelection === undefined
48
- ? undefined
49
- : typeof initialSelection === 'string'
50
- ? initialSelection
51
- : toId(initialSelection.kind, initialSelection.name);
52
- if (initialSelectionId !== undefined && this._checkStory(initialSelectionId)) {
53
- story = initialSelectionId;
54
- }
55
- else if (shouldPersistSelection) {
56
- try {
57
- let value = this._asyncStorageStoryId;
58
- if (!value) {
59
- value = JSON.parse(yield AsyncStorage.getItem(STORAGE_KEY));
60
- this._asyncStorageStoryId = value;
61
- }
62
- if (this._checkStory(value)) {
63
- story = value;
64
- }
65
- }
66
- catch (e) {
67
- //
68
- }
69
- }
70
- if (story) {
71
- return this._getStory(story);
72
- }
73
- const stories = this._storyStore.raw();
74
- if (stories && stories.length) {
75
- return this._getStory(stories[0].id);
76
- }
77
- return null;
78
- });
79
- const channel = new Channel({ async: true });
80
- this._decorators = [];
81
- this._storyStore = new StoryStore({ channel });
82
- this._clientApi = new ClientApi({ storyStore: this._storyStore });
83
- this._configApi = new ConfigApi({ storyStore: this._storyStore });
84
- this._channel = channel;
85
- const configure = loadCsf({
86
- clientApi: this._clientApi,
87
- storyStore: this._storyStore,
88
- configApi: this._configApi,
89
- });
90
- this.configure = (...args) => configure('react-native', ...args);
91
- addons.setChannel(channel);
92
- }
93
- _getStory(storyId) {
94
- return this._storyStore.fromId(storyId);
95
- }
96
- _selectStoryEvent({ storyId }, shouldPersistSelection) {
97
- if (storyId) {
98
- if (shouldPersistSelection) {
99
- AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(storyId)).catch(() => { });
100
- }
101
- const story = this._getStory(storyId);
102
- this._selectStory(story);
103
- }
104
- }
105
- _selectStory(story) {
106
- this._storyStore.setSelection({ storyId: story.id, viewMode: 'story' });
107
- this._channel.emit(Events.SELECT_STORY, story);
108
- }
109
- _checkStory(storyId) {
110
- if (!storyId) {
111
- return null;
112
- }
113
- const story = this._getStory(storyId);
114
- if (story === null || story.storyFn === null) {
115
- return null;
116
- }
117
- return story;
118
- }
119
- }
@@ -1,8 +0,0 @@
1
- export {};
2
- declare global {
3
- namespace NodeJS {
4
- interface Global {
5
- previousExports: Map<any, string>;
6
- }
7
- }
8
- }
@@ -1 +0,0 @@
1
- export { default } from './Preview';
@@ -1 +0,0 @@
1
- export { default } from './Preview';
@@ -1,16 +0,0 @@
1
- /// <reference types="webpack-env" />
2
- /// <reference types="node" />
3
- import { ClientApi, ConfigApi, StoryStore } from '@storybook/client-api';
4
- import './global';
5
- export interface RequireContext {
6
- keys: () => string[];
7
- (id: string): any;
8
- resolve(id: string): string;
9
- }
10
- export declare type LoadableFunction = () => void | any[];
11
- export declare type Loadable = RequireContext | RequireContext[] | LoadableFunction;
12
- export declare const loadCsf: ({ clientApi, storyStore, configApi, }: {
13
- clientApi: ClientApi;
14
- storyStore: StoryStore;
15
- configApi: ConfigApi;
16
- }) => (framework: string, loadable: Loadable, m: NodeModule, showDeprecationWarning?: boolean) => void;
@@ -1,180 +0,0 @@
1
- var __rest = (this && this.__rest) || function (s, e) {
2
- var t = {};
3
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
- t[p] = s[p];
5
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
- t[p[i]] = s[p[i]];
9
- }
10
- return t;
11
- };
12
- import { logger } from '@storybook/client-logger';
13
- import { isExportStory, storyNameFromExport, toId } from '@storybook/csf';
14
- import './global';
15
- const deprecatedStoryAnnotationWarning = () => logger.log(`
16
- CSF .story annotations deprecated; annotate story functions directly:
17
- - StoryFn.story.name => StoryFn.storyName
18
- - StoryFn.story.(parameters|decorators) => StoryFn.(parameters|decorators)
19
- See https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#hoisted-csf-annotations for details and codemod.
20
- `);
21
- const duplicateKindWarning = (kindName) => {
22
- logger.warn(`Duplicate title: '${kindName}'
23
- Duplicate title used in multiple files; use unique titles or a primary file for a component with re-exported stories.
24
-
25
- https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#deprecated-support-for-duplicate-kinds
26
- `);
27
- };
28
- global.previousExports = new Map();
29
- const loadStories = (loadable, framework, { clientApi, storyStore }) => () => {
30
- // Make sure we don't try to define a kind more than once within the same load
31
- const loadedKinds = new Set();
32
- let reqs = null;
33
- // todo discuss / improve type check
34
- if (Array.isArray(loadable)) {
35
- reqs = loadable;
36
- }
37
- else if (loadable.keys) {
38
- reqs = [loadable];
39
- }
40
- let currentExports = new Map();
41
- // reqs is not null when require context is used,
42
- // this comes from storybook core client and will never be true in RN
43
- // keeping this here only to get an idea how the core version could be re-used
44
- if (reqs) {
45
- reqs.forEach((req) => {
46
- req.keys().forEach((filename) => {
47
- try {
48
- const fileExports = req(filename);
49
- currentExports.set(fileExports,
50
- // todo discuss: types infer that this is RequireContext; no checks needed?
51
- // NOTE: turns out `babel-plugin-require-context-hook` doesn't implement this (yet)
52
- typeof req.resolve === 'function' ? req.resolve(filename) : filename);
53
- }
54
- catch (error) {
55
- logger.warn(`Unexpected error while loading ${filename}: ${error}`);
56
- }
57
- });
58
- });
59
- }
60
- else {
61
- try {
62
- const exported = loadable();
63
- if (Array.isArray(exported)) {
64
- const csfExports = exported.filter((obj) => obj.default != null);
65
- currentExports = new Map(csfExports.map((fileExports) => [fileExports, null]));
66
- }
67
- else {
68
- logger.warn(`Loader function passed to 'configure' should return void or an array of module exports that all contain a 'default' export. Received: ${JSON.stringify(exported)}`);
69
- }
70
- }
71
- catch (error) {
72
- logger.warn(`Unexpected error while loading stories: ${error}`);
73
- }
74
- }
75
- const removed = Array.from(global.previousExports.keys()).filter((exp) => !currentExports.has(exp));
76
- removed.forEach((exp) => {
77
- if (exp.default) {
78
- storyStore.removeStoryKind(exp.default.title);
79
- }
80
- });
81
- const added = Array.from(currentExports.keys()).filter((exp) => !global.previousExports.has(exp));
82
- added.forEach((fileExports) => {
83
- // An old-style story file
84
- if (!fileExports.default) {
85
- return;
86
- }
87
- if (!fileExports.default.title) {
88
- throw new Error(`Unexpected default export without title: ${JSON.stringify(fileExports.default)}`);
89
- }
90
- const { default: meta, __namedExportsOrder } = fileExports, namedExports = __rest(fileExports, ["default", "__namedExportsOrder"]);
91
- let exports = namedExports;
92
- // prefer a user/loader provided `__namedExportsOrder` array if supplied
93
- // we do this as es module exports are always ordered alphabetically
94
- // see https://github.com/storybookjs/storybook/issues/9136
95
- if (Array.isArray(__namedExportsOrder)) {
96
- exports = {};
97
- __namedExportsOrder.forEach((name) => {
98
- if (namedExports[name]) {
99
- exports[name] = namedExports[name];
100
- }
101
- });
102
- }
103
- const { title: kindName, id: componentId, parameters: kindParameters, decorators: kindDecorators, loaders: kindLoaders = [], component, subcomponents, args: kindArgs, argTypes: kindArgTypes, } = meta;
104
- if (loadedKinds.has(kindName)) {
105
- duplicateKindWarning(kindName);
106
- }
107
- loadedKinds.add(kindName);
108
- // We pass true here to avoid the warning about HMR. It's cool clientApi, we got this
109
- // todo discuss: TS now wants a NodeModule; should we fix this differently?
110
- const kind = clientApi.storiesOf(kindName, true);
111
- // we should always have a framework, rest optional
112
- kind.addParameters(Object.assign(Object.assign({ framework,
113
- component,
114
- subcomponents, fileName: currentExports.get(fileExports) }, kindParameters), { args: kindArgs, argTypes: kindArgTypes }));
115
- // todo add type
116
- (kindDecorators || []).forEach((decorator) => {
117
- kind.addDecorator(decorator);
118
- });
119
- kindLoaders.forEach((loader) => {
120
- kind.addLoader(loader);
121
- });
122
- const storyExports = Object.keys(exports);
123
- if (storyExports.length === 0) {
124
- logger.warn(`
125
- Found a story file for "${kindName}" but no exported stories.
126
- Check the docs for reference: https://storybook.js.org/docs/formats/component-story-format/
127
- `);
128
- return;
129
- }
130
- storyExports.forEach((key) => {
131
- if (isExportStory(key, meta)) {
132
- const storyFn = exports[key];
133
- const { story } = storyFn;
134
- const name = story === null || story === void 0 ? void 0 : story.name;
135
- const { storyName = name } = storyFn;
136
- // storyFn.x and storyFn.story.x get merged with
137
- // storyFn.x taking precedence in the merge
138
- const parameters = Object.assign(Object.assign({}, story === null || story === void 0 ? void 0 : story.parameters), storyFn.parameters);
139
- const decorators = [...(storyFn.decorators || []), ...((story === null || story === void 0 ? void 0 : story.decorators) || [])];
140
- const loaders = [...(storyFn.loaders || []), ...((story === null || story === void 0 ? void 0 : story.loaders) || [])];
141
- const args = Object.assign(Object.assign({}, story === null || story === void 0 ? void 0 : story.args), storyFn.args);
142
- const argTypes = Object.assign(Object.assign({}, story === null || story === void 0 ? void 0 : story.argTypes), storyFn.argTypes);
143
- if (story) {
144
- logger.debug('deprecated story', story);
145
- deprecatedStoryAnnotationWarning();
146
- }
147
- const exportName = storyNameFromExport(key);
148
- const storyParams = Object.assign(Object.assign({}, parameters), { __id: toId(componentId || kindName, exportName), decorators,
149
- loaders,
150
- args,
151
- argTypes });
152
- kind.add(storyName || exportName, storyFn, storyParams);
153
- }
154
- });
155
- });
156
- global.previousExports = currentExports;
157
- };
158
- const configureDeprecationWarning = () => logger.log(`\`configure()\` is deprecated and will be removed in Storybook 7.0.
159
- Please use the \`stories\` field of \`main.js\` to load stories.
160
- Read more at https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#deprecated-configure`);
161
- export const loadCsf = ({ clientApi, storyStore, configApi, }) =>
162
- /**
163
- * Load a collection of stories. If it has a default export, assume that it is a module-style
164
- * file and process its named exports as stories. If not, assume it's an old-style
165
- * storiesof file and require it.
166
- *
167
- * @param {*} framework - name of framework in use, e.g. "react"
168
- * @param {*} loadable a require.context `req`, an array of `req`s, or a loader function that returns void or an array of exports
169
- * @param {*} m - ES module object for hot-module-reloading (HMR)
170
- * @param {boolean} showDeprecationWarning - show the deprecation warning (default true)
171
- */
172
- (framework, loadable, m, showDeprecationWarning = true) => {
173
- if (showDeprecationWarning) {
174
- configureDeprecationWarning();
175
- }
176
- if (typeof m === 'string') {
177
- throw new Error(`Invalid module '${m}'. Did you forget to pass \`module\` as the second argument to \`configure\`"?`);
178
- }
179
- configApi.configure(loadStories(loadable, framework, { clientApi, storyStore }), m);
180
- };