@storybook/react-native 8.0.0-alpha.1 → 8.0.0-alpha.2

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.
@@ -21,6 +21,90 @@ declare global {
21
21
  }
22
22
  }
23
23
 
24
+ /**
25
+ @see Simplify
26
+ */
27
+ interface SimplifyOptions {
28
+ /**
29
+ Do the simplification recursively.
30
+
31
+ @default false
32
+ */
33
+ deep?: boolean;
34
+ }
35
+
36
+ // Flatten a type without worrying about the result.
37
+ type Flatten<
38
+ AnyType,
39
+ Options extends SimplifyOptions = {},
40
+ > = Options['deep'] extends true
41
+ ? {[KeyType in keyof AnyType]: Simplify<AnyType[KeyType], Options>}
42
+ : {[KeyType in keyof AnyType]: AnyType[KeyType]};
43
+
44
+ /**
45
+ Useful to flatten the type output to improve type hints shown in editors. And also to transform an interface into a type to aide with assignability.
46
+
47
+ @example
48
+ ```
49
+ import type {Simplify} from 'type-fest';
50
+
51
+ type PositionProps = {
52
+ top: number;
53
+ left: number;
54
+ };
55
+
56
+ type SizeProps = {
57
+ width: number;
58
+ height: number;
59
+ };
60
+
61
+ // In your editor, hovering over `Props` will show a flattened object with all the properties.
62
+ type Props = Simplify<PositionProps & SizeProps>;
63
+ ```
64
+
65
+ Sometimes it is desired to pass a value as a function argument that has a different type. At first inspection it may seem assignable, and then you discover it is not because the `value`'s type definition was defined as an interface. In the following example, `fn` requires an argument of type `Record<string, unknown>`. If the value is defined as a literal, then it is assignable. And if the `value` is defined as type using the `Simplify` utility the value is assignable. But if the `value` is defined as an interface, it is not assignable because the interface is not sealed and elsewhere a non-string property could be added to the interface.
66
+
67
+ If the type definition must be an interface (perhaps it was defined in a third-party npm package), then the `value` can be defined as `const value: Simplify<SomeInterface> = ...`. Then `value` will be assignable to the `fn` argument. Or the `value` can be cast as `Simplify<SomeInterface>` if you can't re-declare the `value`.
68
+
69
+ @example
70
+ ```
71
+ import type {Simplify} from 'type-fest';
72
+
73
+ interface SomeInterface {
74
+ foo: number;
75
+ bar?: string;
76
+ baz: number | undefined;
77
+ }
78
+
79
+ type SomeType = {
80
+ foo: number;
81
+ bar?: string;
82
+ baz: number | undefined;
83
+ };
84
+
85
+ const literal = {foo: 123, bar: 'hello', baz: 456};
86
+ const someType: SomeType = literal;
87
+ const someInterface: SomeInterface = literal;
88
+
89
+ function fn(object: Record<string, unknown>): void {}
90
+
91
+ fn(literal); // Good: literal object type is sealed
92
+ fn(someType); // Good: type is sealed
93
+ fn(someInterface); // Error: Index signature for type 'string' is missing in type 'someInterface'. Because `interface` can be re-opened
94
+ fn(someInterface as Simplify<SomeInterface>); // Good: transform an `interface` into a `type`
95
+ ```
96
+
97
+ @link https://github.com/microsoft/TypeScript/issues/15300
98
+
99
+ @category Object
100
+ */
101
+ type Simplify<
102
+ AnyType,
103
+ Options extends SimplifyOptions = {},
104
+ > = Flatten<AnyType> extends AnyType
105
+ ? Flatten<AnyType, Options>
106
+ : AnyType;
107
+
24
108
  /**
25
109
  Allows creating a union type by combining primitive types and literal types without sacrificing auto-completion in IDEs for the literal type part of the union.
26
110
 
@@ -799,12 +883,18 @@ interface StrictInputType extends InputType {
799
883
  interface Args {
800
884
  [name: string]: any;
801
885
  }
886
+ type ArgTypes<TArgs = Args> = {
887
+ [name in keyof TArgs]: InputType;
888
+ };
802
889
  type StrictArgTypes<TArgs = Args> = {
803
890
  [name in keyof TArgs]: StrictInputType;
804
891
  };
805
892
  interface Globals {
806
893
  [name: string]: any;
807
894
  }
895
+ interface GlobalTypes {
896
+ [name: string]: InputType;
897
+ }
808
898
  type Renderer = {
809
899
  /** What is the type of the `component` annotation in this renderer? */
810
900
  component: unknown;
@@ -825,6 +915,10 @@ interface StoryContextForEnhancers<TRenderer extends Renderer = Renderer, TArgs
825
915
  initialArgs: TArgs;
826
916
  argTypes: StrictArgTypes<TArgs>;
827
917
  }
918
+ type ArgsEnhancer<TRenderer extends Renderer = Renderer, TArgs = Args> = (context: StoryContextForEnhancers<TRenderer, TArgs>) => TArgs;
919
+ type ArgTypesEnhancer<TRenderer extends Renderer = Renderer, TArgs = Args> = ((context: StoryContextForEnhancers<TRenderer, TArgs>) => StrictArgTypes<TArgs>) & {
920
+ secondPass?: boolean;
921
+ };
828
922
  interface StoryContextUpdate<TArgs = Args> {
829
923
  args?: TArgs;
830
924
  globals?: Globals;
@@ -836,16 +930,68 @@ interface StoryContextForLoaders<TRenderer extends Renderer = Renderer, TArgs =
836
930
  viewMode: ViewMode$1;
837
931
  originalStoryFn: StoryFn<TRenderer>;
838
932
  }
933
+ type LoaderFunction<TRenderer extends Renderer = Renderer, TArgs = Args> = (context: StoryContextForLoaders<TRenderer, TArgs>) => Promise<Record<string, any> | void> | Record<string, any> | void;
839
934
  interface StoryContext<TRenderer extends Renderer = Renderer, TArgs = Args> extends StoryContextForLoaders<TRenderer, TArgs> {
840
935
  loaded: Record<string, any>;
841
936
  abortSignal: AbortSignal;
842
937
  canvasElement: TRenderer['canvasElement'];
843
938
  }
939
+ type StepLabel = string;
940
+ type StepFunction<TRenderer extends Renderer = Renderer, TArgs = Args> = (label: StepLabel, play: PlayFunction<TRenderer, TArgs>) => Promise<void> | void;
941
+ type PlayFunctionContext<TRenderer extends Renderer = Renderer, TArgs = Args> = StoryContext<TRenderer, TArgs> & {
942
+ step: StepFunction<TRenderer, TArgs>;
943
+ };
944
+ type PlayFunction<TRenderer extends Renderer = Renderer, TArgs = Args> = (context: PlayFunctionContext<TRenderer, TArgs>) => Promise<void> | void;
945
+ type PartialStoryFn<TRenderer extends Renderer = Renderer, TArgs = Args> = (update?: StoryContextUpdate<Partial<TArgs>>) => TRenderer['storyResult'];
844
946
  type LegacyStoryFn<TRenderer extends Renderer = Renderer, TArgs = Args> = (context: StoryContext<TRenderer, TArgs>) => TRenderer['storyResult'];
845
947
  type ArgsStoryFn<TRenderer extends Renderer = Renderer, TArgs = Args> = (args: TArgs, context: StoryContext<TRenderer, TArgs>) => (TRenderer & {
846
948
  T: TArgs;
847
949
  })['storyResult'];
848
950
  type StoryFn<TRenderer extends Renderer = Renderer, TArgs = Args> = LegacyStoryFn<TRenderer, TArgs> | ArgsStoryFn<TRenderer, TArgs>;
951
+ type DecoratorFunction<TRenderer extends Renderer = Renderer, TArgs = Args> = (fn: PartialStoryFn<TRenderer, TArgs>, c: StoryContext<TRenderer, TArgs>) => TRenderer['storyResult'];
952
+ type DecoratorApplicator<TRenderer extends Renderer = Renderer, TArgs = Args> = (storyFn: LegacyStoryFn<TRenderer, TArgs>, decorators: DecoratorFunction<TRenderer, TArgs>[]) => LegacyStoryFn<TRenderer, TArgs>;
953
+ type StepRunner<TRenderer extends Renderer = Renderer, TArgs = Args> = (label: StepLabel, play: PlayFunction<TRenderer, TArgs>, context: PlayFunctionContext<TRenderer, TArgs>) => Promise<void>;
954
+ type BaseAnnotations<TRenderer extends Renderer = Renderer, TArgs = Args> = {
955
+ /**
956
+ * Wrapper components or Storybook decorators that wrap a story.
957
+ *
958
+ * Decorators defined in Meta will be applied to every story variation.
959
+ * @see [Decorators](https://storybook.js.org/docs/addons/introduction/#1-decorators)
960
+ */
961
+ decorators?: DecoratorFunction<TRenderer, Simplify<TArgs>>[] | DecoratorFunction<TRenderer, Simplify<TArgs>>;
962
+ /**
963
+ * Custom metadata for a story.
964
+ * @see [Parameters](https://storybook.js.org/docs/basics/writing-stories/#parameters)
965
+ */
966
+ parameters?: Parameters;
967
+ /**
968
+ * Dynamic data that are provided (and possibly updated by) Storybook and its addons.
969
+ * @see [Arg story inputs](https://storybook.js.org/docs/react/api/csf#args-story-inputs)
970
+ */
971
+ args?: Partial<TArgs>;
972
+ /**
973
+ * ArgTypes encode basic metadata for args, such as `name`, `description`, `defaultValue` for an arg. These get automatically filled in by Storybook Docs.
974
+ * @see [Control annotations](https://github.com/storybookjs/storybook/blob/91e9dee33faa8eff0b342a366845de7100415367/addons/controls/README.md#control-annotations)
975
+ */
976
+ argTypes?: Partial<ArgTypes<TArgs>>;
977
+ /**
978
+ * Asynchronous functions which provide data for a story.
979
+ * @see [Loaders](https://storybook.js.org/docs/react/writing-stories/loaders)
980
+ */
981
+ loaders?: LoaderFunction<TRenderer, TArgs>[] | LoaderFunction<TRenderer, TArgs>;
982
+ /**
983
+ * Define a custom render function for the story(ies). If not passed, a default render function by the renderer will be used.
984
+ */
985
+ render?: ArgsStoryFn<TRenderer, TArgs>;
986
+ };
987
+ type ProjectAnnotations$1<TRenderer extends Renderer = Renderer, TArgs = Args> = BaseAnnotations<TRenderer, TArgs> & {
988
+ argsEnhancers?: ArgsEnhancer<TRenderer, Args>[];
989
+ argTypesEnhancers?: ArgTypesEnhancer<TRenderer, Args>[];
990
+ globals?: Globals;
991
+ globalTypes?: GlobalTypes;
992
+ applyDecorators?: DecoratorApplicator<TRenderer, Args>;
993
+ runStep?: StepRunner<TRenderer, TArgs>;
994
+ };
849
995
 
850
996
  interface Options$1 {
851
997
  allowRegExp: boolean;
@@ -1341,6 +1487,13 @@ interface StorybookConfig {
1341
1487
  type PresetValue<T> = T | ((config: T, options: Options) => T | Promise<T>);
1342
1488
  type Path = string;
1343
1489
  type ModuleExport = any;
1490
+ type MaybePromise<T> = Promise<T> | T;
1491
+ type TeardownRenderToCanvas = () => MaybePromise<void>;
1492
+ type RenderToCanvas<TRenderer extends Renderer> = (context: RenderContext<TRenderer>, element: TRenderer['canvasElement']) => MaybePromise<void | TeardownRenderToCanvas>;
1493
+ type ProjectAnnotations<TRenderer extends Renderer> = ProjectAnnotations$1<TRenderer> & {
1494
+ renderToCanvas?: RenderToCanvas<TRenderer>;
1495
+ renderToDOM?: RenderToCanvas<TRenderer>;
1496
+ };
1344
1497
  type PreparedStory<TRenderer extends Renderer = Renderer> = StoryContextForEnhancers<TRenderer> & {
1345
1498
  moduleExport: ModuleExport;
1346
1499
  originalStoryFn: StoryFn<TRenderer>;
@@ -1351,5 +1504,17 @@ type PreparedStory<TRenderer extends Renderer = Renderer> = StoryContextForEnhan
1351
1504
  }>;
1352
1505
  playFunction?: (context: StoryContext<TRenderer>) => Promise<void> | void;
1353
1506
  };
1507
+ declare type RenderContext<TRenderer extends Renderer = Renderer> = StoryIdentifier & {
1508
+ showMain: () => void;
1509
+ showError: (error: {
1510
+ title: string;
1511
+ description: string;
1512
+ }) => void;
1513
+ showException: (err: Error) => void;
1514
+ forceRemount: boolean;
1515
+ storyContext: StoryContext<TRenderer>;
1516
+ storyFn: PartialStoryFn<TRenderer>;
1517
+ unboundStoryFn: LegacyStoryFn<TRenderer>;
1518
+ };
1354
1519
 
1355
- export { Args as A, NormalizedStoriesSpecifier as N, PreparedStory as P, Renderer as R, StoryIndex as S, StorybookConfig as a, StoryContextForEnhancers as b, StrictArgTypes as c };
1520
+ export { Args as A, NormalizedStoriesSpecifier as N, PreparedStory as P, Renderer as R, StoryIndex as S, ProjectAnnotations as a, StorybookConfig as b, StoryContextForEnhancers as c, StrictArgTypes as d };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { S as StoryIndex, P as PreparedStory, N as NormalizedStoriesSpecifier, a as StorybookConfig$1 } from './index.d-ab512c60.js';
1
+ import { S as StoryIndex, P as PreparedStory, N as NormalizedStoriesSpecifier, a as ProjectAnnotations, b as StorybookConfig$1 } from './index.d-3fb25d8d.js';
2
2
  import { Theme } from '@storybook/react-native-theming';
3
3
  export { Theme, darkTheme, theme } from '@storybook/react-native-theming';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
@@ -66,6 +66,18 @@ declare class View {
66
66
  getStorybookUI: (params?: Partial<Params>) => () => react_jsx_runtime.JSX.Element;
67
67
  }
68
68
 
69
+ declare function prepareStories({ storyEntries, }: {
70
+ storyEntries: Array<NormalizedStoriesSpecifier & {
71
+ req: any;
72
+ }>;
73
+ }): {
74
+ index: {
75
+ v: number;
76
+ entries: {};
77
+ };
78
+ importMap: {};
79
+ };
80
+ declare const getProjectAnnotations: (view: View, annotations: any[]) => () => Promise<ProjectAnnotations<ReactRenderer>>;
69
81
  declare function start({ annotations, storyEntries, }: {
70
82
  storyEntries: Array<NormalizedStoriesSpecifier & {
71
83
  req: any;
@@ -78,4 +90,4 @@ interface StorybookConfig {
78
90
  addons: string[];
79
91
  }
80
92
 
81
- export { StorybookConfig, start };
93
+ export { StorybookConfig, getProjectAnnotations, prepareStories, start };
package/dist/index.js CHANGED
@@ -59,6 +59,8 @@ var require_dist = __commonJS({
59
59
  var src_exports = {};
60
60
  __export(src_exports, {
61
61
  darkTheme: () => import_react_native_theming13.darkTheme,
62
+ getProjectAnnotations: () => getProjectAnnotations,
63
+ prepareStories: () => prepareStories,
62
64
  start: () => start,
63
65
  theme: () => import_react_native_theming13.theme
64
66
  });
@@ -2262,6 +2264,23 @@ function prepareStories({
2262
2264
  });
2263
2265
  return { index, importMap };
2264
2266
  }
2267
+ var getProjectAnnotations = (view, annotations) => async () => (0, import_preview_api3.composeConfigs)([
2268
+ {
2269
+ renderToCanvas: (context) => {
2270
+ view._setStory(context.storyContext);
2271
+ },
2272
+ render: (args, context) => {
2273
+ const { id, component: Component } = context;
2274
+ if (!Component) {
2275
+ throw new Error(
2276
+ `Unable to render story ${id} as the component annotation is missing from the default export`
2277
+ );
2278
+ }
2279
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Component, { ...args });
2280
+ }
2281
+ },
2282
+ ...annotations
2283
+ ]);
2265
2284
  function start({
2266
2285
  annotations,
2267
2286
  storyEntries
@@ -2304,7 +2323,7 @@ function start({
2304
2323
  preview.selectionStore.selection = selection;
2305
2324
  }
2306
2325
  };
2307
- const getProjectAnnotations = async () => (0, import_preview_api3.composeConfigs)([
2326
+ const getProjectAnnotationsInitial = async () => (0, import_preview_api3.composeConfigs)([
2308
2327
  {
2309
2328
  renderToCanvas: (context) => {
2310
2329
  view._setStory(context.storyContext);
@@ -2323,7 +2342,7 @@ function start({
2323
2342
  ]);
2324
2343
  const preview = new import_preview_api3.PreviewWithSelection(
2325
2344
  async (importPath) => importMap[importPath],
2326
- getProjectAnnotations,
2345
+ getProjectAnnotationsInitial,
2327
2346
  selectionStore,
2328
2347
  previewView
2329
2348
  );
@@ -2339,6 +2358,8 @@ function start({
2339
2358
  // Annotate the CommonJS export names for ESM import in node:
2340
2359
  0 && (module.exports = {
2341
2360
  darkTheme,
2361
+ getProjectAnnotations,
2362
+ prepareStories,
2342
2363
  start,
2343
2364
  theme
2344
2365
  });
package/dist/preview.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _storybook_docs_tools from '@storybook/docs-tools';
2
- import { R as Renderer, b as StoryContextForEnhancers, A as Args, c as StrictArgTypes } from './index.d-ab512c60.js';
2
+ import { R as Renderer, c as StoryContextForEnhancers, A as Args, d as StrictArgTypes } from './index.d-3fb25d8d.js';
3
3
  import 'file-system-cache';
4
4
  import 'http';
5
5
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storybook/react-native",
3
- "version": "8.0.0-alpha.1",
3
+ "version": "8.0.0-alpha.2",
4
4
  "description": "A better way to develop React Native Components for your app",
5
5
  "keywords": [
6
6
  "react",
@@ -62,7 +62,7 @@
62
62
  "@storybook/manager-api": "8.0.0-rc.1",
63
63
  "@storybook/preview-api": "8.0.0-rc.1",
64
64
  "@storybook/react": "8.0.0-rc.1",
65
- "@storybook/react-native-theming": "^8.0.0-alpha.1",
65
+ "@storybook/react-native-theming": "^8.0.0-alpha.2",
66
66
  "chokidar": "^3.5.1",
67
67
  "commander": "^8.2.0",
68
68
  "dedent": "^1.5.1",
@@ -96,5 +96,5 @@
96
96
  "publishConfig": {
97
97
  "access": "public"
98
98
  },
99
- "gitHead": "1865884a1c866ff61bacd82d02fdc18e845e4132"
99
+ "gitHead": "6f189532af5cbfbdd4bc968faab66721407c84ca"
100
100
  }
@@ -3,8 +3,8 @@
3
3
  exports[`loader writeRequires when there are different file extensions writes the story imports 1`] = `
4
4
  "
5
5
  /* do not change this file, it is auto generated by storybook. */
6
-
7
- import { start } from '@storybook/react-native';
6
+
7
+ import { start, prepareStories, getProjectAnnotations } from '@storybook/react-native';
8
8
 
9
9
  import "@storybook/addon-ondevice-notes/register";
10
10
  import "@storybook/addon-ondevice-controls/register";
@@ -18,23 +18,48 @@ import "@storybook/addon-ondevice-actions/register";
18
18
  importPathMatcher: /^\\.[\\\\/](?:FakeStory\\.stories\\.tsx)$/,
19
19
  // @ts-ignore
20
20
  req: require.context('./', false, /^\\.[\\\\/](?:FakeStory\\.stories\\.tsx)$/)
21
- }]
21
+ }];
22
22
 
23
- // @ts-ignore
24
- global.STORIES = normalizedStories;
23
+
24
+ declare global {
25
+ var view: ReturnType<typeof start>;
26
+ var STORIES: typeof normalizedStories;
27
+ }
28
+
29
+
30
+ const annotations = [require('./preview'),require("@storybook/react-native/dist/preview"), require('@storybook/addon-actions/preview')];
25
31
 
26
- export const view = start({
27
- annotations: [require('./preview'),require("@storybook/react-native/dist/preview"), require('@storybook/addon-actions/preview')],
28
- storyEntries: normalizedStories
29
- });
32
+ global.STORIES = normalizedStories;
33
+
34
+ // @ts-ignore
35
+ module?.hot?.accept?.();
36
+
37
+ if (!global.view) {
38
+ global.view = start({
39
+ annotations,
40
+ storyEntries: normalizedStories
41
+ });
42
+ } else {
43
+ const { importMap } = prepareStories({ storyEntries: normalizedStories });
44
+
45
+ global.view._preview.onStoriesChanged({
46
+ importFn: async (importPath: string) => importMap[importPath],
47
+ });
48
+
49
+ global.view._preview.onGetProjectAnnotationsChanged({
50
+ getProjectAnnotations: getProjectAnnotations(global.view, annotations),
51
+ });
52
+ }
53
+
54
+ export const view = global.view;
30
55
  "
31
56
  `;
32
57
 
33
58
  exports[`loader writeRequires when there is a configuration object writes the story imports 1`] = `
34
59
  "
35
60
  /* do not change this file, it is auto generated by storybook. */
36
-
37
- import { start } from '@storybook/react-native';
61
+
62
+ import { start, prepareStories, getProjectAnnotations } from '@storybook/react-native';
38
63
 
39
64
  import "@storybook/addon-ondevice-notes/register";
40
65
  import "@storybook/addon-ondevice-controls/register";
@@ -48,23 +73,48 @@ import "@storybook/addon-ondevice-actions/register";
48
73
  importPathMatcher: /^\\.(?:(?:^|\\/|(?:(?:(?!(?:^|\\/)\\.).)*?)\\/)(?!\\.)(?=.)[^/]*?\\.stories\\.tsx)$/,
49
74
  // @ts-ignore
50
75
  req: require.context('./components', true, /^\\.(?:(?:^|\\/|(?:(?:(?!(?:^|\\/)\\.).)*?)\\/)(?!\\.)(?=.)[^/]*?\\.stories\\.tsx)$/)
51
- }]
76
+ }];
52
77
 
53
- // @ts-ignore
54
- global.STORIES = normalizedStories;
78
+
79
+ declare global {
80
+ var view: ReturnType<typeof start>;
81
+ var STORIES: typeof normalizedStories;
82
+ }
83
+
84
+
85
+ const annotations = [require('./preview'),require("@storybook/react-native/dist/preview"), require('@storybook/addon-actions/preview')];
55
86
 
56
- export const view = start({
57
- annotations: [require('./preview'),require("@storybook/react-native/dist/preview"), require('@storybook/addon-actions/preview')],
58
- storyEntries: normalizedStories
59
- });
87
+ global.STORIES = normalizedStories;
88
+
89
+ // @ts-ignore
90
+ module?.hot?.accept?.();
91
+
92
+ if (!global.view) {
93
+ global.view = start({
94
+ annotations,
95
+ storyEntries: normalizedStories
96
+ });
97
+ } else {
98
+ const { importMap } = prepareStories({ storyEntries: normalizedStories });
99
+
100
+ global.view._preview.onStoriesChanged({
101
+ importFn: async (importPath: string) => importMap[importPath],
102
+ });
103
+
104
+ global.view._preview.onGetProjectAnnotationsChanged({
105
+ getProjectAnnotations: getProjectAnnotations(global.view, annotations),
106
+ });
107
+ }
108
+
109
+ export const view = global.view;
60
110
  "
61
111
  `;
62
112
 
63
113
  exports[`loader writeRequires when there is a story glob writes the story imports 1`] = `
64
114
  "
65
115
  /* do not change this file, it is auto generated by storybook. */
66
-
67
- import { start } from '@storybook/react-native';
116
+
117
+ import { start, prepareStories, getProjectAnnotations } from '@storybook/react-native';
68
118
 
69
119
  import "@storybook/addon-ondevice-notes/register";
70
120
  import "@storybook/addon-ondevice-controls/register";
@@ -78,23 +128,48 @@ import "@storybook/addon-ondevice-actions/register";
78
128
  importPathMatcher: /^\\.[\\\\/](?:FakeStory\\.stories\\.tsx)$/,
79
129
  // @ts-ignore
80
130
  req: require.context('./', false, /^\\.[\\\\/](?:FakeStory\\.stories\\.tsx)$/)
81
- }]
131
+ }];
82
132
 
83
- // @ts-ignore
84
- global.STORIES = normalizedStories;
133
+
134
+ declare global {
135
+ var view: ReturnType<typeof start>;
136
+ var STORIES: typeof normalizedStories;
137
+ }
138
+
139
+
140
+ const annotations = [require('./preview'),require("@storybook/react-native/dist/preview"), require('@storybook/addon-actions/preview')];
85
141
 
86
- export const view = start({
87
- annotations: [require('./preview'),require("@storybook/react-native/dist/preview"), require('@storybook/addon-actions/preview')],
88
- storyEntries: normalizedStories
89
- });
142
+ global.STORIES = normalizedStories;
143
+
144
+ // @ts-ignore
145
+ module?.hot?.accept?.();
146
+
147
+ if (!global.view) {
148
+ global.view = start({
149
+ annotations,
150
+ storyEntries: normalizedStories
151
+ });
152
+ } else {
153
+ const { importMap } = prepareStories({ storyEntries: normalizedStories });
154
+
155
+ global.view._preview.onStoriesChanged({
156
+ importFn: async (importPath: string) => importMap[importPath],
157
+ });
158
+
159
+ global.view._preview.onGetProjectAnnotationsChanged({
160
+ getProjectAnnotations: getProjectAnnotations(global.view, annotations),
161
+ });
162
+ }
163
+
164
+ export const view = global.view;
90
165
  "
91
166
  `;
92
167
 
93
168
  exports[`loader writeRequires when there is no preview does not add preview related stuff 1`] = `
94
169
  "
95
170
  /* do not change this file, it is auto generated by storybook. */
96
-
97
- import { start } from '@storybook/react-native';
171
+
172
+ import { start, prepareStories, getProjectAnnotations } from '@storybook/react-native';
98
173
 
99
174
  import "@storybook/addon-ondevice-notes/register";
100
175
  import "@storybook/addon-ondevice-controls/register";
@@ -108,14 +183,39 @@ import "@storybook/addon-ondevice-actions/register";
108
183
  importPathMatcher: /^\\.[\\\\/](?:FakeStory\\.stories\\.tsx)$/,
109
184
  // @ts-ignore
110
185
  req: require.context('./', false, /^\\.[\\\\/](?:FakeStory\\.stories\\.tsx)$/)
111
- }]
186
+ }];
112
187
 
113
- // @ts-ignore
114
- global.STORIES = normalizedStories;
188
+
189
+ declare global {
190
+ var view: ReturnType<typeof start>;
191
+ var STORIES: typeof normalizedStories;
192
+ }
193
+
194
+
195
+ const annotations = [require("@storybook/react-native/dist/preview"), require('@storybook/addon-actions/preview')];
115
196
 
116
- export const view = start({
117
- annotations: [require("@storybook/react-native/dist/preview"), require('@storybook/addon-actions/preview')],
118
- storyEntries: normalizedStories
119
- });
197
+ global.STORIES = normalizedStories;
198
+
199
+ // @ts-ignore
200
+ module?.hot?.accept?.();
201
+
202
+ if (!global.view) {
203
+ global.view = start({
204
+ annotations,
205
+ storyEntries: normalizedStories
206
+ });
207
+ } else {
208
+ const { importMap } = prepareStories({ storyEntries: normalizedStories });
209
+
210
+ global.view._preview.onStoriesChanged({
211
+ importFn: async (importPath: string) => importMap[importPath],
212
+ });
213
+
214
+ global.view._preview.onGetProjectAnnotationsChanged({
215
+ getProjectAnnotations: getProjectAnnotations(global.view, annotations),
216
+ });
217
+ }
218
+
219
+ export const view = global.view;
120
220
  "
121
221
  `;
@@ -59,25 +59,52 @@ function generate({ configPath, absolute = false, useJs = false }) {
59
59
 
60
60
  const annotations = `[${previewExists ? "require('./preview')," : ''}${doctools}, ${enhancer}]`;
61
61
 
62
+ const globalTypes = `
63
+ declare global {
64
+ var view: ReturnType<typeof start>;
65
+ var STORIES: typeof normalizedStories;
66
+ }
67
+ `;
68
+
62
69
  const fileContent = `
63
70
  /* do not change this file, it is auto generated by storybook. */
64
-
65
- import { start } from '@storybook/react-native';
71
+
72
+ import { start, prepareStories, getProjectAnnotations } from '@storybook/react-native';
66
73
 
67
74
  ${registerAddons}
68
75
 
69
- const normalizedStories = [${normalizedStories.join(',')}]
76
+ const normalizedStories = [${normalizedStories.join(',')}];
70
77
 
71
- // @ts-ignore
72
- global.STORIES = normalizedStories;
78
+ ${useJs ? '' : globalTypes}
73
79
 
74
- export const view = start({
75
- annotations: ${annotations},
76
- storyEntries: normalizedStories
77
- });
80
+ const annotations = ${annotations};
81
+
82
+ global.STORIES = normalizedStories;
83
+
84
+ // @ts-ignore
85
+ module?.hot?.accept?.();
86
+
87
+ if (!global.view) {
88
+ global.view = start({
89
+ annotations,
90
+ storyEntries: normalizedStories
91
+ });
92
+ } else {
93
+ const { importMap } = prepareStories({ storyEntries: normalizedStories });
94
+
95
+ global.view._preview.onStoriesChanged({
96
+ importFn: async (importPath: string) => importMap[importPath],
97
+ });
98
+
99
+ global.view._preview.onGetProjectAnnotationsChanged({
100
+ getProjectAnnotations: getProjectAnnotations(global.view, annotations),
101
+ });
102
+ }
103
+
104
+ export const view = global.view;
78
105
  `;
79
106
 
80
- const formattedFileContent = prettier.format(fileContent, { parser: 'babel' });
107
+ const formattedFileContent = prettier.format(fileContent, { parser: 'babel-ts' });
81
108
 
82
109
  fs.writeFileSync(storybookRequiresLocation, formattedFileContent, {
83
110
  encoding: 'utf8',
@@ -88,16 +115,3 @@ function generate({ configPath, absolute = false, useJs = false }) {
88
115
  module.exports = {
89
116
  generate,
90
117
  };
91
-
92
- // TODO evaluate if this is needed
93
- // if (import.meta.webpackHot) {
94
- // import.meta.webpackHot.accept('./{{storiesFilename}}', () => {
95
- // // importFn has changed so we need to patch the new one in
96
- // preview.onStoriesChanged({ importFn });
97
- // });
98
-
99
- // import.meta.webpackHot.accept([{{#each previewAnnotations}}'{{this}}',{{/each}}], () => {
100
- // // getProjectAnnotations has changed so we need to patch the new one in
101
- // preview.onGetProjectAnnotationsChanged({ getProjectAnnotations });
102
- // });
103
- // }