@storybook/react-native 9.0.0-beta.9 → 9.0.0-rc.4
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/index.d.ts +10 -8
- package/dist/index.js +60 -24
- package/dist/metro/withStorybook.d.ts +5 -0
- package/dist/metro/withStorybook.js +60 -49
- package/package.json +25 -10
- package/readme.md +12 -7
- package/scripts/__snapshots__/generate.test.js.snap +185 -166
- package/scripts/common.js +3 -3
- package/scripts/generate.js +46 -42
- package/scripts/generate.test.js +0 -6
- package/scripts/handle-args.js +1 -0
- package/scripts/mocks/preview-files/tsx/preview.tsx +6 -6
package/dist/index.d.ts
CHANGED
|
@@ -2,11 +2,12 @@ import * as storybook_internal_types from 'storybook/internal/types';
|
|
|
2
2
|
import { StoryIndex, PreparedStory, NormalizedStoriesSpecifier, Addon_StorySortParameterV7, StorybookConfig as StorybookConfig$1 } from 'storybook/internal/types';
|
|
3
3
|
import { ReactRenderer } from '@storybook/react';
|
|
4
4
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
|
-
import { Channel } from 'storybook/internal/channels';
|
|
6
|
-
import { PreviewWithSelection } from 'storybook/internal/preview-api';
|
|
7
5
|
import { StoryContext } from '@storybook/csf';
|
|
8
6
|
import { Theme } from '@storybook/react-native-theming';
|
|
9
7
|
export { Theme, darkTheme, theme } from '@storybook/react-native-theming';
|
|
8
|
+
import { SBUI } from '@storybook/react-native-ui-common';
|
|
9
|
+
import { Channel } from 'storybook/internal/channels';
|
|
10
|
+
import { PreviewWithSelection } from 'storybook/internal/preview-api';
|
|
10
11
|
|
|
11
12
|
interface Storage {
|
|
12
13
|
getItem: (key: string) => Promise<string | null>;
|
|
@@ -39,6 +40,7 @@ type Params = {
|
|
|
39
40
|
shouldPersistSelection?: boolean;
|
|
40
41
|
theme: ThemePartial;
|
|
41
42
|
storage?: Storage;
|
|
43
|
+
CustomUIComponent?: SBUI;
|
|
42
44
|
};
|
|
43
45
|
declare class View {
|
|
44
46
|
_storyIndex: StoryIndex;
|
|
@@ -70,9 +72,9 @@ interface ReactNativeOptions {
|
|
|
70
72
|
playFn?: boolean;
|
|
71
73
|
}
|
|
72
74
|
declare function prepareStories({ storyEntries, options, storySort, }: {
|
|
73
|
-
storyEntries:
|
|
75
|
+
storyEntries: (NormalizedStoriesSpecifier & {
|
|
74
76
|
req: any;
|
|
75
|
-
}
|
|
77
|
+
})[];
|
|
76
78
|
options?: ReactNativeOptions;
|
|
77
79
|
storySort?: Addon_StorySortParameterV7;
|
|
78
80
|
}): {
|
|
@@ -84,15 +86,15 @@ declare function prepareStories({ storyEntries, options, storySort, }: {
|
|
|
84
86
|
};
|
|
85
87
|
declare const getProjectAnnotations: (view: View, annotations: any[]) => () => Promise<storybook_internal_types.NormalizedProjectAnnotations<ReactRenderer>>;
|
|
86
88
|
declare function start({ annotations, storyEntries, options, }: {
|
|
87
|
-
storyEntries:
|
|
89
|
+
storyEntries: (NormalizedStoriesSpecifier & {
|
|
88
90
|
req: any;
|
|
89
|
-
}
|
|
91
|
+
})[];
|
|
90
92
|
annotations: any[];
|
|
91
93
|
options?: ReactNativeOptions;
|
|
92
94
|
}): View;
|
|
93
|
-
declare function updateView(viewInstance: View, annotations: any[], normalizedStories:
|
|
95
|
+
declare function updateView(viewInstance: View, annotations: any[], normalizedStories: (NormalizedStoriesSpecifier & {
|
|
94
96
|
req: any;
|
|
95
|
-
}
|
|
97
|
+
})[], options?: ReactNativeOptions): void;
|
|
96
98
|
|
|
97
99
|
interface StorybookConfig {
|
|
98
100
|
stories: StorybookConfig$1['stories'];
|
package/dist/index.js
CHANGED
|
@@ -47,20 +47,17 @@ var import_csf2 = require("@storybook/csf");
|
|
|
47
47
|
var import_channels2 = require("storybook/internal/channels");
|
|
48
48
|
|
|
49
49
|
// src/View.tsx
|
|
50
|
-
var
|
|
50
|
+
var import_csf = require("@storybook/csf");
|
|
51
|
+
var import_react_native_theming2 = require("@storybook/react-native-theming");
|
|
52
|
+
var import_react_native_ui_common = require("@storybook/react-native-ui-common");
|
|
51
53
|
var import_channels = require("storybook/internal/channels");
|
|
52
|
-
var import_core_events =
|
|
54
|
+
var import_core_events = require("storybook/internal/core-events");
|
|
53
55
|
var import_manager_api = require("storybook/internal/manager-api");
|
|
54
56
|
var import_preview_api = require("storybook/internal/preview-api");
|
|
55
|
-
var import_csf = require("@storybook/csf");
|
|
56
|
-
var import_react_native_theming2 = require("@storybook/react-native-theming");
|
|
57
|
-
var import_react_native_ui = require("@storybook/react-native-ui");
|
|
58
57
|
var import_dedent = __toESM(require("dedent"));
|
|
59
58
|
var import_deepmerge = __toESM(require("deepmerge"));
|
|
60
59
|
var import_react4 = require("react");
|
|
61
60
|
var import_react_native3 = require("react-native");
|
|
62
|
-
var import_react_native_gesture_handler = require("react-native-gesture-handler");
|
|
63
|
-
var import_react_native_safe_area_context = require("react-native-safe-area-context");
|
|
64
61
|
|
|
65
62
|
// src/components/StoryView/StoryView.tsx
|
|
66
63
|
var import_react_native_theming = require("@storybook/react-native-theming");
|
|
@@ -954,8 +951,22 @@ var View3 = class {
|
|
|
954
951
|
shouldPersistSelection = true,
|
|
955
952
|
onDeviceUI = true,
|
|
956
953
|
enableWebsockets = false,
|
|
957
|
-
storage
|
|
954
|
+
storage,
|
|
955
|
+
CustomUIComponent
|
|
958
956
|
} = params;
|
|
957
|
+
const getFullUI = (enabled) => {
|
|
958
|
+
if (enabled) {
|
|
959
|
+
try {
|
|
960
|
+
const { FullUI: FullUI2 } = require("@storybook/react-native-ui");
|
|
961
|
+
return FullUI2;
|
|
962
|
+
} catch (error) {
|
|
963
|
+
console.warn("storybook-log: error loading UI", error);
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
const PlaceholderUI = ({ children }) => children;
|
|
967
|
+
return PlaceholderUI;
|
|
968
|
+
};
|
|
969
|
+
const FullUI = getFullUI(onDeviceUI);
|
|
959
970
|
this._storage = storage;
|
|
960
971
|
const initialStory = this._getInitialStory(params);
|
|
961
972
|
if (enableWebsockets) {
|
|
@@ -965,7 +976,7 @@ var View3 = class {
|
|
|
965
976
|
this._channel = channel;
|
|
966
977
|
this._preview.channel = channel;
|
|
967
978
|
this._preview.setupListeners();
|
|
968
|
-
channel.emit(import_core_events.
|
|
979
|
+
channel.emit(import_core_events.CHANNEL_CREATED);
|
|
969
980
|
this._preview.ready().then(() => this._preview.onStoryIndexChanged());
|
|
970
981
|
}
|
|
971
982
|
import_manager_api.addons.loadAddons({
|
|
@@ -999,10 +1010,10 @@ var View3 = class {
|
|
|
999
1010
|
const urlObj = new URL(url);
|
|
1000
1011
|
const storyId = urlObj.searchParams.get("STORYBOOK_STORY_ID");
|
|
1001
1012
|
const hasStoryId = storyId && typeof storyId === "string";
|
|
1002
|
-
const storyExists = hasStoryId &&
|
|
1003
|
-
if (storyExists &&
|
|
1013
|
+
const storyExists = hasStoryId && self._storyIdExists(storyId);
|
|
1014
|
+
if (storyExists && self._ready) {
|
|
1004
1015
|
console.log(`STORYBOOK: Linking event received, navigating to story: ${storyId}`);
|
|
1005
|
-
|
|
1016
|
+
self._channel.emit(import_core_events.SET_CURRENT_STORY, { storyId });
|
|
1006
1017
|
}
|
|
1007
1018
|
if (hasStoryId && !storyExists) {
|
|
1008
1019
|
console.log(
|
|
@@ -1016,15 +1027,15 @@ var View3 = class {
|
|
|
1016
1027
|
};
|
|
1017
1028
|
}, []);
|
|
1018
1029
|
(0, import_react4.useEffect)(() => {
|
|
1019
|
-
|
|
1020
|
-
|
|
1030
|
+
self.createPreparedStoryMapping().then(() => {
|
|
1031
|
+
self._ready = true;
|
|
1021
1032
|
setReady(true);
|
|
1022
1033
|
return import_react_native3.Linking.getInitialURL().then((url) => {
|
|
1023
1034
|
if (url && typeof url === "string") {
|
|
1024
1035
|
const urlObj = new URL(url);
|
|
1025
1036
|
const storyId = urlObj.searchParams.get("STORYBOOK_STORY_ID");
|
|
1026
1037
|
const hasStoryId = storyId && typeof storyId === "string";
|
|
1027
|
-
const storyExists = hasStoryId &&
|
|
1038
|
+
const storyExists = hasStoryId && self._storyIdExists(storyId);
|
|
1028
1039
|
if (hasStoryId && !storyExists) {
|
|
1029
1040
|
console.log(
|
|
1030
1041
|
`STORYBOOK: Initial Linking event received, but story does not exist: ${storyId}`
|
|
@@ -1064,8 +1075,8 @@ var View3 = class {
|
|
|
1064
1075
|
});
|
|
1065
1076
|
`);
|
|
1066
1077
|
}
|
|
1067
|
-
if (shouldPersistSelection && !!
|
|
1068
|
-
|
|
1078
|
+
if (shouldPersistSelection && !!self._storage) {
|
|
1079
|
+
self._storage.setItem(STORAGE_KEY, newStory.id).catch((e) => {
|
|
1069
1080
|
console.warn("storybook-log: error writing to async storage", e);
|
|
1070
1081
|
});
|
|
1071
1082
|
}
|
|
@@ -1076,10 +1087,10 @@ var View3 = class {
|
|
|
1076
1087
|
if (!ready) {
|
|
1077
1088
|
return {};
|
|
1078
1089
|
}
|
|
1079
|
-
return (0,
|
|
1090
|
+
return (0, import_react_native_ui_common.transformStoryIndexToStoriesHash)(self._storyIndex, {
|
|
1080
1091
|
docsOptions: { docsMode: false, defaultName: "" },
|
|
1081
1092
|
filters: {},
|
|
1082
|
-
|
|
1093
|
+
allStatuses: {},
|
|
1083
1094
|
provider: {
|
|
1084
1095
|
handleAPI: () => ({}),
|
|
1085
1096
|
getConfig: () => ({})
|
|
@@ -1100,7 +1111,29 @@ var View3 = class {
|
|
|
1100
1111
|
);
|
|
1101
1112
|
}
|
|
1102
1113
|
if (onDeviceUI) {
|
|
1103
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1114
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1115
|
+
FullUI,
|
|
1116
|
+
{
|
|
1117
|
+
storage,
|
|
1118
|
+
theme: appliedTheme,
|
|
1119
|
+
storyHash,
|
|
1120
|
+
story,
|
|
1121
|
+
setStory: (newStoryId) => self._channel.emit(import_core_events.SET_CURRENT_STORY, { storyId: newStoryId }),
|
|
1122
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StoryView_default, {})
|
|
1123
|
+
}
|
|
1124
|
+
);
|
|
1125
|
+
} else if (CustomUIComponent) {
|
|
1126
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1127
|
+
CustomUIComponent,
|
|
1128
|
+
{
|
|
1129
|
+
story,
|
|
1130
|
+
storyHash,
|
|
1131
|
+
setStory: (newStoryId) => self._channel.emit(import_core_events.SET_CURRENT_STORY, { storyId: newStoryId }),
|
|
1132
|
+
storage,
|
|
1133
|
+
theme: appliedTheme,
|
|
1134
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StoryView_default, {})
|
|
1135
|
+
}
|
|
1136
|
+
);
|
|
1104
1137
|
} else {
|
|
1105
1138
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StoryView_default, {});
|
|
1106
1139
|
}
|
|
@@ -1218,10 +1251,13 @@ function prepareStories({
|
|
|
1218
1251
|
storySort,
|
|
1219
1252
|
Object.values(index.entries).map((entry) => entry.importPath)
|
|
1220
1253
|
);
|
|
1221
|
-
const sorted = sortableStories.reduce(
|
|
1222
|
-
acc
|
|
1223
|
-
|
|
1224
|
-
|
|
1254
|
+
const sorted = sortableStories.reduce(
|
|
1255
|
+
(acc, item) => {
|
|
1256
|
+
acc[item.id] = item;
|
|
1257
|
+
return acc;
|
|
1258
|
+
},
|
|
1259
|
+
{}
|
|
1260
|
+
);
|
|
1225
1261
|
return { index: { v: 5, entries: sorted }, importMap };
|
|
1226
1262
|
}
|
|
1227
1263
|
var getProjectAnnotations = (view, annotations) => async () => (0, import_preview_api2.composeConfigs)([
|
|
@@ -37,6 +37,10 @@ interface WithStorybookOptions {
|
|
|
37
37
|
* If enabled is false and onDisabledRemoveStorybook is true, we will attempt to remove storybook from the js bundle.
|
|
38
38
|
*/
|
|
39
39
|
onDisabledRemoveStorybook?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Whether to include doc tools in the storybook.requires file. Defaults to true.
|
|
42
|
+
*/
|
|
43
|
+
docTools?: boolean;
|
|
40
44
|
}
|
|
41
45
|
/**
|
|
42
46
|
* Configures Metro bundler to work with Storybook in React Native.
|
|
@@ -59,6 +63,7 @@ interface WithStorybookOptions {
|
|
|
59
63
|
* configPath: path.resolve(projectRoot, './.rnstorybook'),
|
|
60
64
|
* websockets: { port: 7007, host: 'localhost' },
|
|
61
65
|
* useJs: false,
|
|
66
|
+
* docTools: true,
|
|
62
67
|
* onDisabledRemoveStorybook: true,
|
|
63
68
|
* });
|
|
64
69
|
*/
|
|
@@ -75,14 +75,14 @@ var require_common = __commonJS({
|
|
|
75
75
|
const basePath = `${addon}/${file}`;
|
|
76
76
|
require.resolve(basePath);
|
|
77
77
|
return basePath;
|
|
78
|
-
} catch (
|
|
78
|
+
} catch (_error) {
|
|
79
79
|
}
|
|
80
80
|
for (const ext of extensions) {
|
|
81
81
|
try {
|
|
82
82
|
const filePath = `${addon}/${file}.${ext}`;
|
|
83
83
|
require.resolve(filePath);
|
|
84
84
|
return filePath;
|
|
85
|
-
} catch (
|
|
85
|
+
} catch (_error) {
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
if (addon.startsWith("./") || addon.startsWith("../")) {
|
|
@@ -91,7 +91,7 @@ var require_common = __commonJS({
|
|
|
91
91
|
if (extension) {
|
|
92
92
|
return `${addon}/${file}`;
|
|
93
93
|
}
|
|
94
|
-
} catch (
|
|
94
|
+
} catch (_error) {
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
return null;
|
|
@@ -130,10 +130,14 @@ var require_generate = __commonJS({
|
|
|
130
130
|
} = require_common();
|
|
131
131
|
var { normalizeStories, globToRegexp } = require("storybook/internal/common");
|
|
132
132
|
var fs = require("fs");
|
|
133
|
-
var prettier = require("prettier");
|
|
134
133
|
var path2 = require("path");
|
|
135
134
|
var cwd = process.cwd();
|
|
136
|
-
function generate2({
|
|
135
|
+
function generate2({
|
|
136
|
+
configPath,
|
|
137
|
+
/* absolute = false, */
|
|
138
|
+
useJs = false,
|
|
139
|
+
docTools = true
|
|
140
|
+
}) {
|
|
137
141
|
const storybookRequiresLocation = path2.resolve(
|
|
138
142
|
cwd,
|
|
139
143
|
configPath,
|
|
@@ -150,13 +154,13 @@ var require_generate = __commonJS({
|
|
|
150
154
|
const { path: p, recursive: r, match: m } = toRequireContext(specifier);
|
|
151
155
|
const pathToStory = ensureRelativePathHasDot(path2.posix.relative(configPath, p));
|
|
152
156
|
return `{
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
157
|
+
titlePrefix: "${specifier.titlePrefix}",
|
|
158
|
+
directory: "${specifier.directory}",
|
|
159
|
+
files: "${specifier.files}",
|
|
160
|
+
importPathMatcher: /${reg.source}/,
|
|
161
|
+
${useJs ? "" : "// @ts-ignore"}
|
|
162
|
+
req: require.context('${pathToStory}', ${r}, ${m})
|
|
163
|
+
}`;
|
|
160
164
|
});
|
|
161
165
|
let registerAddons = "";
|
|
162
166
|
for (const addon of main.addons) {
|
|
@@ -171,8 +175,11 @@ var require_generate = __commonJS({
|
|
|
171
175
|
`;
|
|
172
176
|
}
|
|
173
177
|
}
|
|
174
|
-
const
|
|
175
|
-
const enhancers = [
|
|
178
|
+
const docToolsAnnotation = 'require("@storybook/react-native/preview")';
|
|
179
|
+
const enhancers = [];
|
|
180
|
+
if (docTools) {
|
|
181
|
+
enhancers.push(docToolsAnnotation);
|
|
182
|
+
}
|
|
176
183
|
for (const addon of main.addons) {
|
|
177
184
|
const previewPath = resolveAddonFile(
|
|
178
185
|
getAddonName(addon),
|
|
@@ -189,54 +196,55 @@ var require_generate = __commonJS({
|
|
|
189
196
|
let optionsVar = "";
|
|
190
197
|
const reactNativeOptions = main.reactNative;
|
|
191
198
|
if (reactNativeOptions && typeof reactNativeOptions === "object") {
|
|
192
|
-
optionsVar = `const options = ${JSON.stringify(reactNativeOptions)}`;
|
|
199
|
+
optionsVar = `const options = ${JSON.stringify(reactNativeOptions, null, 4)}`;
|
|
193
200
|
options = "options";
|
|
194
201
|
}
|
|
195
202
|
const previewExists = getPreviewExists({ configPath });
|
|
196
203
|
if (previewExists) {
|
|
197
204
|
enhancers.unshift("require('./preview')");
|
|
198
205
|
}
|
|
199
|
-
const annotations = `[
|
|
206
|
+
const annotations = `[
|
|
207
|
+
${enhancers.join(",\n ")}
|
|
208
|
+
]`;
|
|
200
209
|
const globalTypes = `
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
210
|
+
declare global {
|
|
211
|
+
var view: View;
|
|
212
|
+
var STORIES: typeof normalizedStories;
|
|
213
|
+
}
|
|
205
214
|
`;
|
|
206
|
-
const fileContent =
|
|
207
|
-
|
|
215
|
+
const fileContent = `/* do not change this file, it is auto generated by storybook. */
|
|
216
|
+
import { start, updateView${useJs ? "" : ", View"} } from '@storybook/react-native';
|
|
208
217
|
|
|
209
|
-
|
|
218
|
+
${registerAddons}
|
|
210
219
|
|
|
211
|
-
|
|
220
|
+
const normalizedStories = [
|
|
221
|
+
${normalizedStories.join(",\n ")}
|
|
222
|
+
];
|
|
212
223
|
|
|
213
|
-
|
|
224
|
+
${useJs ? "" : globalTypes}
|
|
214
225
|
|
|
215
|
-
|
|
226
|
+
const annotations = ${annotations};
|
|
216
227
|
|
|
217
|
-
|
|
228
|
+
global.STORIES = normalizedStories;
|
|
218
229
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
${useJs ? "" : "// @ts-ignore"}
|
|
222
|
-
module?.hot?.accept?.();
|
|
230
|
+
${useJs ? "" : "// @ts-ignore"}
|
|
231
|
+
module?.hot?.accept?.();
|
|
223
232
|
|
|
224
|
-
|
|
233
|
+
${optionsVar}
|
|
225
234
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
+
if (!global.view) {
|
|
236
|
+
global.view = start({
|
|
237
|
+
annotations,
|
|
238
|
+
storyEntries: normalizedStories,
|
|
239
|
+
${options}
|
|
240
|
+
});
|
|
241
|
+
} else {
|
|
242
|
+
updateView(global.view, annotations, normalizedStories, ${options});
|
|
243
|
+
}
|
|
235
244
|
|
|
236
|
-
|
|
245
|
+
export const view${useJs ? "" : ": View"} = global.view;
|
|
237
246
|
`;
|
|
238
|
-
|
|
239
|
-
fs.writeFileSync(storybookRequiresLocation, formattedFileContent, {
|
|
247
|
+
fs.writeFileSync(storybookRequiresLocation, fileContent, {
|
|
240
248
|
encoding: "utf8",
|
|
241
249
|
flag: "w"
|
|
242
250
|
});
|
|
@@ -254,14 +262,16 @@ var import_ws = require("ws");
|
|
|
254
262
|
function withStorybook(config, options = {
|
|
255
263
|
enabled: true,
|
|
256
264
|
useJs: false,
|
|
257
|
-
onDisabledRemoveStorybook: false
|
|
265
|
+
onDisabledRemoveStorybook: false,
|
|
266
|
+
docTools: true
|
|
258
267
|
}) {
|
|
259
268
|
const {
|
|
260
269
|
configPath,
|
|
261
270
|
enabled = true,
|
|
262
271
|
websockets,
|
|
263
272
|
useJs = false,
|
|
264
|
-
onDisabledRemoveStorybook = false
|
|
273
|
+
onDisabledRemoveStorybook = false,
|
|
274
|
+
docTools = true
|
|
265
275
|
} = options;
|
|
266
276
|
if (!enabled) {
|
|
267
277
|
if (onDisabledRemoveStorybook) {
|
|
@@ -302,7 +312,8 @@ function withStorybook(config, options = {
|
|
|
302
312
|
}
|
|
303
313
|
(0, import_generate.generate)({
|
|
304
314
|
configPath: configPath ?? path.resolve(process.cwd(), "./.rnstorybook"),
|
|
305
|
-
useJs
|
|
315
|
+
useJs,
|
|
316
|
+
docTools
|
|
306
317
|
});
|
|
307
318
|
return {
|
|
308
319
|
...config,
|
|
@@ -314,8 +325,8 @@ function withStorybook(config, options = {
|
|
|
314
325
|
...config.resolver,
|
|
315
326
|
resolveRequest: (context, moduleName, platform) => {
|
|
316
327
|
const resolveFunction = config?.resolver?.resolveRequest ? config.resolver.resolveRequest : context.resolveRequest;
|
|
317
|
-
const
|
|
318
|
-
const theContext =
|
|
328
|
+
const shouldUseCustomResolveConfig = moduleName.startsWith("storybook") || moduleName.startsWith("@storybook") || moduleName.startsWith("uuid");
|
|
329
|
+
const theContext = shouldUseCustomResolveConfig ? {
|
|
319
330
|
...context,
|
|
320
331
|
unstable_enablePackageExports: true,
|
|
321
332
|
unstable_conditionNames: ["import"]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@storybook/react-native",
|
|
3
|
-
"version": "9.0.0-
|
|
3
|
+
"version": "9.0.0-rc.4",
|
|
4
4
|
"description": "A better way to develop React Native Components for your app",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -48,13 +48,13 @@
|
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@storybook/csf": "^0.1.13",
|
|
50
50
|
"@storybook/global": "^5.0.0",
|
|
51
|
-
"@storybook/react": "9.0.0-
|
|
52
|
-
"@storybook/react-native-theming": "^9.0.0-
|
|
53
|
-
"@storybook/react-native-ui": "^9.0.0-
|
|
51
|
+
"@storybook/react": "9.0.0-rc.4",
|
|
52
|
+
"@storybook/react-native-theming": "^9.0.0-rc.4",
|
|
53
|
+
"@storybook/react-native-ui": "^9.0.0-rc.4",
|
|
54
|
+
"@storybook/react-native-ui-common": "^9.0.0-rc.4",
|
|
54
55
|
"commander": "^8.2.0",
|
|
55
56
|
"dedent": "^1.5.1",
|
|
56
57
|
"deepmerge": "^4.3.0",
|
|
57
|
-
"prettier": "^2.4.1",
|
|
58
58
|
"react-native-url-polyfill": "^2.0.0",
|
|
59
59
|
"setimmediate": "^1.0.5",
|
|
60
60
|
"type-fest": "~2.19",
|
|
@@ -67,12 +67,12 @@
|
|
|
67
67
|
"babel-jest": "^29.7.0",
|
|
68
68
|
"babel-preset-expo": "^12.0.9",
|
|
69
69
|
"jest": "^29.7.0",
|
|
70
|
-
"jest-expo": "~53.0.
|
|
70
|
+
"jest-expo": "~53.0.5",
|
|
71
71
|
"jotai": "^2.6.2",
|
|
72
72
|
"react": "19.0.0",
|
|
73
|
-
"react-native": "0.79.
|
|
73
|
+
"react-native": "0.79.2",
|
|
74
74
|
"react-test-renderer": "^19.1.0",
|
|
75
|
-
"storybook": "9.0.0-
|
|
75
|
+
"storybook": "9.0.0-rc.4",
|
|
76
76
|
"tsup": "^7.2.0",
|
|
77
77
|
"typescript": "~5.8.3"
|
|
78
78
|
},
|
|
@@ -81,8 +81,23 @@
|
|
|
81
81
|
"react": "*",
|
|
82
82
|
"react-native": ">=0.72.0",
|
|
83
83
|
"react-native-gesture-handler": ">=2",
|
|
84
|
+
"react-native-reanimated": ">=2",
|
|
84
85
|
"react-native-safe-area-context": "*",
|
|
85
|
-
"storybook": "9.0.0-
|
|
86
|
+
"storybook": "9.0.0-rc.4"
|
|
87
|
+
},
|
|
88
|
+
"peerDependenciesMeta": {
|
|
89
|
+
"@gorhom/bottom-sheet": {
|
|
90
|
+
"optional": true
|
|
91
|
+
},
|
|
92
|
+
"react-native-gesture-handler": {
|
|
93
|
+
"optional": true
|
|
94
|
+
},
|
|
95
|
+
"react-native-reanimated": {
|
|
96
|
+
"optional": true
|
|
97
|
+
},
|
|
98
|
+
"react-native-safe-area-context": {
|
|
99
|
+
"optional": true
|
|
100
|
+
}
|
|
86
101
|
},
|
|
87
102
|
"engines": {
|
|
88
103
|
"node": ">=8.0.0"
|
|
@@ -90,5 +105,5 @@
|
|
|
90
105
|
"publishConfig": {
|
|
91
106
|
"access": "public"
|
|
92
107
|
},
|
|
93
|
-
"gitHead": "
|
|
108
|
+
"gitHead": "1d0249371caed6a6a90f42530d722040eb18c9dc"
|
|
94
109
|
}
|
package/readme.md
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
# Storybook for React Native
|
|
2
2
|
|
|
3
|
-
> [
|
|
4
|
-
> This readme is for v8, for v7 docs see the [v7.6 docs](https://github.com/storybookjs/react-native/tree/v7.6.20-stable).
|
|
3
|
+
> This readme is for v9 beta, for v8 docs see the [v8.6 docs](https://github.com/storybookjs/react-native/tree/v8.6.0-stable).
|
|
5
4
|
|
|
6
5
|
With Storybook for React Native you can design and develop individual React Native components without running your app.
|
|
7
6
|
|
|
8
|
-
If you are migrating from
|
|
7
|
+
If you are migrating from 8 to 9 you can find the migration guide [here](https://github.com/storybookjs/react-native/blob/next/MIGRATION.md#from-version-8-to-9)
|
|
9
8
|
|
|
10
9
|
For more information about storybook visit: [storybook.js.org](https://storybook.js.org)
|
|
11
10
|
|
|
12
|
-
>
|
|
13
|
-
> `@storybook/react-native` requires atleast 8.3.1, if you install other storybook core packages they should be `^8.3.1` or newer.
|
|
11
|
+
> Make sure you align your storybook dependencies to the same major version or you will see broken behaviour.
|
|
14
12
|
|
|
15
13
|

|
|
16
14
|
|
|
@@ -139,6 +137,15 @@ module.exports = withStorybook(finalConfig, {
|
|
|
139
137
|
});
|
|
140
138
|
```
|
|
141
139
|
|
|
140
|
+
#### Reanimated setup
|
|
141
|
+
|
|
142
|
+
Make sure you have `react-native-reanimated` in your project and the plugin setup in your babel config.
|
|
143
|
+
|
|
144
|
+
```js
|
|
145
|
+
// babel.config.js
|
|
146
|
+
plugins: ['react-native-reanimated/plugin'],
|
|
147
|
+
```
|
|
148
|
+
|
|
142
149
|
## Writing stories
|
|
143
150
|
|
|
144
151
|
In storybook we use a syntax called CSF that looks like this:
|
|
@@ -376,8 +383,6 @@ You can pass these parameters to getStorybookUI call in your storybook entry poi
|
|
|
376
383
|
storage?: Object (undefined)
|
|
377
384
|
-- {getItem: (key: string) => Promise<string | null>;setItem: (key: string, value: string) => Promise<void>;}
|
|
378
385
|
-- Custom storage to be used instead of AsyncStorage
|
|
379
|
-
shouldPersistSelection: Boolean (true)
|
|
380
|
-
-- Stores last selected story in your devices storage.
|
|
381
386
|
onDeviceUI?: boolean;
|
|
382
387
|
-- show the ondevice ui
|
|
383
388
|
enableWebsockets?: boolean;
|
|
@@ -1,251 +1,270 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
3
|
exports[`loader writeRequires when there are different file extensions writes the story imports 1`] = `
|
|
4
|
-
"
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import { start, updateView, View } from '@storybook/react-native';
|
|
4
|
+
"/* do not change this file, it is auto generated by storybook. */
|
|
5
|
+
import { start, updateView, View } from '@storybook/react-native';
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
import "@storybook/addon-ondevice-notes/register";
|
|
10
8
|
import "@storybook/addon-ondevice-controls/register";
|
|
11
9
|
import "@storybook/addon-ondevice-backgrounds/register";
|
|
12
10
|
import "@storybook/addon-ondevice-actions/register";
|
|
13
11
|
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
const normalizedStories = [
|
|
14
|
+
{
|
|
15
|
+
titlePrefix: "",
|
|
16
|
+
directory: "./scripts/mocks/file-extensions",
|
|
17
|
+
files: "FakeStory.stories.tsx",
|
|
18
|
+
importPathMatcher: /^\\.[\\\\/](?:FakeStory\\.stories\\.tsx)$/,
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
req: require.context('./', false, /^\\.[\\\\/](?:FakeStory\\.stories\\.tsx)$/)
|
|
21
|
+
}
|
|
22
|
+
];
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
|
|
25
|
+
declare global {
|
|
26
|
+
var view: View;
|
|
27
|
+
var STORIES: typeof normalizedStories;
|
|
28
|
+
}
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
const annotations = [
|
|
32
|
+
require('./preview'),
|
|
33
|
+
require("@storybook/react-native/preview"),
|
|
34
|
+
require('@storybook/addon-ondevice-actions/preview')
|
|
35
|
+
];
|
|
32
36
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
// @ts-ignore
|
|
36
|
-
module?.hot?.accept?.();
|
|
37
|
+
global.STORIES = normalizedStories;
|
|
37
38
|
|
|
38
|
-
|
|
39
|
+
// @ts-ignore
|
|
40
|
+
module?.hot?.accept?.();
|
|
39
41
|
|
|
40
|
-
if (!global.view) {
|
|
41
|
-
global.view = start({
|
|
42
|
-
annotations,
|
|
43
|
-
storyEntries: normalizedStories,
|
|
44
|
-
|
|
45
|
-
});
|
|
46
|
-
} else {
|
|
47
|
-
updateView(global.view, annotations, normalizedStories, );
|
|
48
|
-
}
|
|
49
42
|
|
|
50
|
-
|
|
43
|
+
|
|
44
|
+
if (!global.view) {
|
|
45
|
+
global.view = start({
|
|
46
|
+
annotations,
|
|
47
|
+
storyEntries: normalizedStories,
|
|
48
|
+
|
|
49
|
+
});
|
|
50
|
+
} else {
|
|
51
|
+
updateView(global.view, annotations, normalizedStories, );
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const view: View = global.view;
|
|
51
55
|
"
|
|
52
56
|
`;
|
|
53
57
|
|
|
54
58
|
exports[`loader writeRequires when there is a configuration object writes the story imports 1`] = `
|
|
55
|
-
"
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
import { start, updateView, View } from '@storybook/react-native';
|
|
59
|
+
"/* do not change this file, it is auto generated by storybook. */
|
|
60
|
+
import { start, updateView, View } from '@storybook/react-native';
|
|
59
61
|
|
|
60
|
-
|
|
62
|
+
import "@storybook/addon-ondevice-notes/register";
|
|
61
63
|
import "@storybook/addon-ondevice-controls/register";
|
|
62
64
|
import "@storybook/addon-ondevice-backgrounds/register";
|
|
63
65
|
import "@storybook/addon-ondevice-actions/register";
|
|
64
66
|
|
|
65
67
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
const normalizedStories = [
|
|
69
|
+
{
|
|
70
|
+
titlePrefix: "ComponentsPrefix",
|
|
71
|
+
directory: "./scripts/mocks/configuration-objects/components",
|
|
72
|
+
files: "**/*.stories.tsx",
|
|
73
|
+
importPathMatcher: /^\\.(?:(?:^|\\/|(?:(?:(?!(?:^|\\/)\\.).)*?)\\/)(?!\\.)(?=.)[^/]*?\\.stories\\.tsx)$/,
|
|
74
|
+
// @ts-ignore
|
|
75
|
+
req: require.context('./components', true, /^\\.(?:(?:^|\\/|(?:(?:(?!(?:^|\\/)\\.).)*?)\\/)(?!\\.)(?=.)[^/]*?\\.stories\\.tsx)$/)
|
|
76
|
+
}
|
|
77
|
+
];
|
|
78
|
+
|
|
74
79
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
+
declare global {
|
|
81
|
+
var view: View;
|
|
82
|
+
var STORIES: typeof normalizedStories;
|
|
83
|
+
}
|
|
80
84
|
|
|
81
85
|
|
|
82
|
-
|
|
86
|
+
const annotations = [
|
|
87
|
+
require('./preview'),
|
|
88
|
+
require("@storybook/react-native/preview"),
|
|
89
|
+
require('@storybook/addon-ondevice-actions/preview')
|
|
90
|
+
];
|
|
83
91
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
// @ts-ignore
|
|
87
|
-
module?.hot?.accept?.();
|
|
92
|
+
global.STORIES = normalizedStories;
|
|
88
93
|
|
|
89
|
-
|
|
94
|
+
// @ts-ignore
|
|
95
|
+
module?.hot?.accept?.();
|
|
90
96
|
|
|
91
|
-
if (!global.view) {
|
|
92
|
-
global.view = start({
|
|
93
|
-
annotations,
|
|
94
|
-
storyEntries: normalizedStories,
|
|
95
|
-
|
|
96
|
-
});
|
|
97
|
-
} else {
|
|
98
|
-
updateView(global.view, annotations, normalizedStories, );
|
|
99
|
-
}
|
|
100
97
|
|
|
101
|
-
|
|
98
|
+
|
|
99
|
+
if (!global.view) {
|
|
100
|
+
global.view = start({
|
|
101
|
+
annotations,
|
|
102
|
+
storyEntries: normalizedStories,
|
|
103
|
+
|
|
104
|
+
});
|
|
105
|
+
} else {
|
|
106
|
+
updateView(global.view, annotations, normalizedStories, );
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export const view: View = global.view;
|
|
102
110
|
"
|
|
103
111
|
`;
|
|
104
112
|
|
|
105
113
|
exports[`loader writeRequires when there is a story glob writes the story imports 1`] = `
|
|
106
|
-
"
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
import { start, updateView, View } from '@storybook/react-native';
|
|
114
|
+
"/* do not change this file, it is auto generated by storybook. */
|
|
115
|
+
import { start, updateView, View } from '@storybook/react-native';
|
|
110
116
|
|
|
111
|
-
|
|
117
|
+
import "@storybook/addon-ondevice-notes/register";
|
|
112
118
|
import "@storybook/addon-ondevice-controls/register";
|
|
113
119
|
import "@storybook/addon-ondevice-backgrounds/register";
|
|
114
120
|
import "@storybook/addon-ondevice-actions/register";
|
|
115
121
|
|
|
116
122
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
123
|
+
const normalizedStories = [
|
|
124
|
+
{
|
|
125
|
+
titlePrefix: "",
|
|
126
|
+
directory: "./scripts/mocks/all-config-files",
|
|
127
|
+
files: "FakeStory.stories.tsx",
|
|
128
|
+
importPathMatcher: /^\\.[\\\\/](?:FakeStory\\.stories\\.tsx)$/,
|
|
129
|
+
// @ts-ignore
|
|
130
|
+
req: require.context('./', false, /^\\.[\\\\/](?:FakeStory\\.stories\\.tsx)$/)
|
|
131
|
+
}
|
|
132
|
+
];
|
|
133
|
+
|
|
125
134
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
}
|
|
135
|
+
declare global {
|
|
136
|
+
var view: View;
|
|
137
|
+
var STORIES: typeof normalizedStories;
|
|
138
|
+
}
|
|
131
139
|
|
|
132
140
|
|
|
133
|
-
|
|
141
|
+
const annotations = [
|
|
142
|
+
require('./preview'),
|
|
143
|
+
require("@storybook/react-native/preview"),
|
|
144
|
+
require('@storybook/addon-ondevice-actions/preview')
|
|
145
|
+
];
|
|
134
146
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
// @ts-ignore
|
|
138
|
-
module?.hot?.accept?.();
|
|
147
|
+
global.STORIES = normalizedStories;
|
|
139
148
|
|
|
140
|
-
|
|
149
|
+
// @ts-ignore
|
|
150
|
+
module?.hot?.accept?.();
|
|
141
151
|
|
|
142
|
-
if (!global.view) {
|
|
143
|
-
global.view = start({
|
|
144
|
-
annotations,
|
|
145
|
-
storyEntries: normalizedStories,
|
|
146
|
-
|
|
147
|
-
});
|
|
148
|
-
} else {
|
|
149
|
-
updateView(global.view, annotations, normalizedStories, );
|
|
150
|
-
}
|
|
151
152
|
|
|
152
|
-
|
|
153
|
+
|
|
154
|
+
if (!global.view) {
|
|
155
|
+
global.view = start({
|
|
156
|
+
annotations,
|
|
157
|
+
storyEntries: normalizedStories,
|
|
158
|
+
|
|
159
|
+
});
|
|
160
|
+
} else {
|
|
161
|
+
updateView(global.view, annotations, normalizedStories, );
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export const view: View = global.view;
|
|
153
165
|
"
|
|
154
166
|
`;
|
|
155
167
|
|
|
156
168
|
exports[`loader writeRequires when there is no preview does not add preview related stuff 1`] = `
|
|
157
|
-
"
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
import { start, updateView, View } from '@storybook/react-native';
|
|
169
|
+
"/* do not change this file, it is auto generated by storybook. */
|
|
170
|
+
import { start, updateView, View } from '@storybook/react-native';
|
|
161
171
|
|
|
162
|
-
|
|
172
|
+
import "@storybook/addon-ondevice-notes/register";
|
|
163
173
|
import "@storybook/addon-ondevice-controls/register";
|
|
164
174
|
import "@storybook/addon-ondevice-backgrounds/register";
|
|
165
175
|
import "@storybook/addon-ondevice-actions/register";
|
|
166
176
|
|
|
167
177
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
178
|
+
const normalizedStories = [
|
|
179
|
+
{
|
|
180
|
+
titlePrefix: "",
|
|
181
|
+
directory: "./scripts/mocks/no-preview",
|
|
182
|
+
files: "FakeStory.stories.tsx",
|
|
183
|
+
importPathMatcher: /^\\.[\\\\/](?:FakeStory\\.stories\\.tsx)$/,
|
|
184
|
+
// @ts-ignore
|
|
185
|
+
req: require.context('./', false, /^\\.[\\\\/](?:FakeStory\\.stories\\.tsx)$/)
|
|
186
|
+
}
|
|
187
|
+
];
|
|
176
188
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
189
|
+
|
|
190
|
+
declare global {
|
|
191
|
+
var view: View;
|
|
192
|
+
var STORIES: typeof normalizedStories;
|
|
193
|
+
}
|
|
182
194
|
|
|
183
195
|
|
|
184
|
-
|
|
196
|
+
const annotations = [
|
|
197
|
+
require("@storybook/react-native/preview"),
|
|
198
|
+
require('@storybook/addon-ondevice-actions/preview')
|
|
199
|
+
];
|
|
185
200
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
201
|
+
global.STORIES = normalizedStories;
|
|
202
|
+
|
|
203
|
+
// @ts-ignore
|
|
204
|
+
module?.hot?.accept?.();
|
|
190
205
|
|
|
191
|
-
|
|
192
206
|
|
|
193
|
-
if (!global.view) {
|
|
194
|
-
global.view = start({
|
|
195
|
-
annotations,
|
|
196
|
-
storyEntries: normalizedStories,
|
|
197
|
-
|
|
198
|
-
});
|
|
199
|
-
} else {
|
|
200
|
-
updateView(global.view, annotations, normalizedStories, );
|
|
201
|
-
}
|
|
202
207
|
|
|
203
|
-
|
|
208
|
+
if (!global.view) {
|
|
209
|
+
global.view = start({
|
|
210
|
+
annotations,
|
|
211
|
+
storyEntries: normalizedStories,
|
|
212
|
+
|
|
213
|
+
});
|
|
214
|
+
} else {
|
|
215
|
+
updateView(global.view, annotations, normalizedStories, );
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export const view: View = global.view;
|
|
204
219
|
"
|
|
205
220
|
`;
|
|
206
221
|
|
|
207
222
|
exports[`loader writeRequires when using js writes the story imports without types 1`] = `
|
|
208
|
-
"
|
|
209
|
-
|
|
223
|
+
"/* do not change this file, it is auto generated by storybook. */
|
|
224
|
+
import { start, updateView } from '@storybook/react-native';
|
|
210
225
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
import "@storybook/addon-ondevice-notes/register";
|
|
226
|
+
import "@storybook/addon-ondevice-notes/register";
|
|
214
227
|
import "@storybook/addon-ondevice-controls/register";
|
|
215
228
|
import "@storybook/addon-ondevice-backgrounds/register";
|
|
216
229
|
import "@storybook/addon-ondevice-actions/register";
|
|
217
230
|
|
|
218
231
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
232
|
+
const normalizedStories = [
|
|
233
|
+
{
|
|
234
|
+
titlePrefix: "",
|
|
235
|
+
directory: "./scripts/mocks/all-config-files",
|
|
236
|
+
files: "FakeStory.stories.tsx",
|
|
237
|
+
importPathMatcher: /^\\.[\\\\/](?:FakeStory\\.stories\\.tsx)$/,
|
|
238
|
+
|
|
239
|
+
req: require.context('./', false, /^\\.[\\\\/](?:FakeStory\\.stories\\.tsx)$/)
|
|
240
|
+
}
|
|
241
|
+
];
|
|
227
242
|
|
|
228
|
-
|
|
229
243
|
|
|
230
|
-
const annotations = [require('./preview'), require("@storybook/react-native/preview"), require('@storybook/addon-ondevice-actions/preview')];
|
|
231
244
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
245
|
+
const annotations = [
|
|
246
|
+
require('./preview'),
|
|
247
|
+
require("@storybook/react-native/preview"),
|
|
248
|
+
require('@storybook/addon-ondevice-actions/preview')
|
|
249
|
+
];
|
|
236
250
|
|
|
237
|
-
|
|
251
|
+
global.STORIES = normalizedStories;
|
|
238
252
|
|
|
239
|
-
if (!global.view) {
|
|
240
|
-
global.view = start({
|
|
241
|
-
annotations,
|
|
242
|
-
storyEntries: normalizedStories,
|
|
243
|
-
|
|
244
|
-
});
|
|
245
|
-
} else {
|
|
246
|
-
updateView(global.view, annotations, normalizedStories, );
|
|
247
|
-
}
|
|
248
253
|
|
|
249
|
-
|
|
254
|
+
module?.hot?.accept?.();
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
if (!global.view) {
|
|
259
|
+
global.view = start({
|
|
260
|
+
annotations,
|
|
261
|
+
storyEntries: normalizedStories,
|
|
262
|
+
|
|
263
|
+
});
|
|
264
|
+
} else {
|
|
265
|
+
updateView(global.view, annotations, normalizedStories, );
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export const view = global.view;
|
|
250
269
|
"
|
|
251
270
|
`;
|
package/scripts/common.js
CHANGED
|
@@ -67,7 +67,7 @@ function resolveAddonFile(addon, file, extensions = ['js', 'mjs', 'ts'], configP
|
|
|
67
67
|
require.resolve(basePath);
|
|
68
68
|
|
|
69
69
|
return basePath;
|
|
70
|
-
} catch (
|
|
70
|
+
} catch (_error) {}
|
|
71
71
|
|
|
72
72
|
for (const ext of extensions) {
|
|
73
73
|
try {
|
|
@@ -76,7 +76,7 @@ function resolveAddonFile(addon, file, extensions = ['js', 'mjs', 'ts'], configP
|
|
|
76
76
|
require.resolve(filePath);
|
|
77
77
|
|
|
78
78
|
return filePath;
|
|
79
|
-
} catch (
|
|
79
|
+
} catch (_error) {}
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
// attempt to resolve as a relative path for local addons
|
|
@@ -87,7 +87,7 @@ function resolveAddonFile(addon, file, extensions = ['js', 'mjs', 'ts'], configP
|
|
|
87
87
|
if (extension) {
|
|
88
88
|
return `${addon}/${file}`;
|
|
89
89
|
}
|
|
90
|
-
} catch (
|
|
90
|
+
} catch (_error) {}
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
return null;
|
package/scripts/generate.js
CHANGED
|
@@ -8,12 +8,12 @@ const {
|
|
|
8
8
|
} = require('./common');
|
|
9
9
|
const { normalizeStories, globToRegexp } = require('storybook/internal/common');
|
|
10
10
|
const fs = require('fs');
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
const path = require('path');
|
|
13
13
|
|
|
14
14
|
const cwd = process.cwd();
|
|
15
15
|
|
|
16
|
-
function generate({ configPath, absolute = false, useJs = false }) {
|
|
16
|
+
function generate({ configPath, /* absolute = false, */ useJs = false, docTools = true }) {
|
|
17
17
|
const storybookRequiresLocation = path.resolve(
|
|
18
18
|
cwd,
|
|
19
19
|
configPath,
|
|
@@ -39,13 +39,13 @@ function generate({ configPath, absolute = false, useJs = false }) {
|
|
|
39
39
|
|
|
40
40
|
const pathToStory = ensureRelativePathHasDot(path.posix.relative(configPath, p));
|
|
41
41
|
return `{
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
42
|
+
titlePrefix: "${specifier.titlePrefix}",
|
|
43
|
+
directory: "${specifier.directory}",
|
|
44
|
+
files: "${specifier.files}",
|
|
45
|
+
importPathMatcher: /${reg.source}/,
|
|
46
|
+
${useJs ? '' : '// @ts-ignore'}
|
|
47
|
+
req: require.context('${pathToStory}', ${r}, ${m})
|
|
48
|
+
}`;
|
|
49
49
|
});
|
|
50
50
|
|
|
51
51
|
let registerAddons = '';
|
|
@@ -63,9 +63,13 @@ function generate({ configPath, absolute = false, useJs = false }) {
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
const
|
|
66
|
+
const docToolsAnnotation = 'require("@storybook/react-native/preview")';
|
|
67
|
+
|
|
68
|
+
const enhancers = [];
|
|
67
69
|
|
|
68
|
-
|
|
70
|
+
if (docTools) {
|
|
71
|
+
enhancers.push(docToolsAnnotation);
|
|
72
|
+
}
|
|
69
73
|
|
|
70
74
|
for (const addon of main.addons) {
|
|
71
75
|
const previewPath = resolveAddonFile(
|
|
@@ -86,7 +90,7 @@ function generate({ configPath, absolute = false, useJs = false }) {
|
|
|
86
90
|
const reactNativeOptions = main.reactNative;
|
|
87
91
|
|
|
88
92
|
if (reactNativeOptions && typeof reactNativeOptions === 'object') {
|
|
89
|
-
optionsVar = `const options = ${JSON.stringify(reactNativeOptions)}`;
|
|
93
|
+
optionsVar = `const options = ${JSON.stringify(reactNativeOptions, null, 4)}`;
|
|
90
94
|
options = 'options';
|
|
91
95
|
}
|
|
92
96
|
|
|
@@ -96,51 +100,51 @@ function generate({ configPath, absolute = false, useJs = false }) {
|
|
|
96
100
|
enhancers.unshift("require('./preview')");
|
|
97
101
|
}
|
|
98
102
|
|
|
99
|
-
const annotations = `[
|
|
103
|
+
const annotations = `[
|
|
104
|
+
${enhancers.join(',\n ')}
|
|
105
|
+
]`;
|
|
100
106
|
|
|
101
107
|
const globalTypes = `
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
108
|
+
declare global {
|
|
109
|
+
var view: View;
|
|
110
|
+
var STORIES: typeof normalizedStories;
|
|
111
|
+
}
|
|
106
112
|
`;
|
|
107
113
|
|
|
108
|
-
const fileContent =
|
|
109
|
-
|
|
114
|
+
const fileContent = `/* do not change this file, it is auto generated by storybook. */
|
|
115
|
+
import { start, updateView${useJs ? '' : ', View'} } from '@storybook/react-native';
|
|
110
116
|
|
|
111
|
-
|
|
117
|
+
${registerAddons}
|
|
112
118
|
|
|
113
|
-
|
|
119
|
+
const normalizedStories = [
|
|
120
|
+
${normalizedStories.join(',\n ')}
|
|
121
|
+
];
|
|
114
122
|
|
|
115
|
-
|
|
123
|
+
${useJs ? '' : globalTypes}
|
|
116
124
|
|
|
117
|
-
|
|
125
|
+
const annotations = ${annotations};
|
|
118
126
|
|
|
119
|
-
|
|
127
|
+
global.STORIES = normalizedStories;
|
|
120
128
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
${useJs ? '' : '// @ts-ignore'}
|
|
124
|
-
module?.hot?.accept?.();
|
|
129
|
+
${useJs ? '' : '// @ts-ignore'}
|
|
130
|
+
module?.hot?.accept?.();
|
|
125
131
|
|
|
126
|
-
|
|
132
|
+
${optionsVar}
|
|
127
133
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
134
|
+
if (!global.view) {
|
|
135
|
+
global.view = start({
|
|
136
|
+
annotations,
|
|
137
|
+
storyEntries: normalizedStories,
|
|
138
|
+
${options}
|
|
139
|
+
});
|
|
140
|
+
} else {
|
|
141
|
+
updateView(global.view, annotations, normalizedStories, ${options});
|
|
142
|
+
}
|
|
137
143
|
|
|
138
|
-
|
|
144
|
+
export const view${useJs ? '' : ': View'} = global.view;
|
|
139
145
|
`;
|
|
140
146
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
fs.writeFileSync(storybookRequiresLocation, formattedFileContent, {
|
|
147
|
+
fs.writeFileSync(storybookRequiresLocation, fileContent, {
|
|
144
148
|
encoding: 'utf8',
|
|
145
149
|
flag: 'w',
|
|
146
150
|
});
|
package/scripts/generate.test.js
CHANGED
package/scripts/handle-args.js
CHANGED
|
@@ -9,6 +9,7 @@ function getArguments() {
|
|
|
9
9
|
'./.rnstorybook'
|
|
10
10
|
)
|
|
11
11
|
.option('-js, --use-js', 'Use a js file for storybook.requires')
|
|
12
|
+
.option('-D, --no-doc-tools', 'Do not include doc tools in the storybook.requires file')
|
|
12
13
|
.option('-a, --absolute', 'Use absolute paths for story imports');
|
|
13
14
|
|
|
14
15
|
program.parse();
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export const decorators: any = [];
|
|
2
2
|
export const parameters = {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
9
|
};
|