storybook 10.1.0-alpha.10 → 10.1.0-alpha.12

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 (192) hide show
  1. package/dist/_browser-chunks/Color-FTG7SQDA.js +1097 -0
  2. package/dist/_browser-chunks/WithTooltip-LMROHDUP.js +1651 -0
  3. package/dist/_browser-chunks/chunk-2FRVAXCZ.js +7 -0
  4. package/dist/_browser-chunks/chunk-3IAH5M2U.js +171 -0
  5. package/dist/_browser-chunks/chunk-3OXGAGBE.js +779 -0
  6. package/dist/_browser-chunks/{chunk-TMDZCWME.js → chunk-3PJE6VLG.js} +1 -3
  7. package/dist/_browser-chunks/{chunk-VAMFPZY3.js → chunk-45UGUKRX.js} +2 -7
  8. package/dist/_browser-chunks/chunk-6XWLIJQL.js +11 -0
  9. package/dist/_browser-chunks/{chunk-FDWKXLBI.js → chunk-74YHFU5B.js} +44 -109
  10. package/dist/_browser-chunks/{chunk-MM7DTO55.js → chunk-A242L54C.js} +10 -16
  11. package/dist/_browser-chunks/chunk-AIOS4NGK.js +252 -0
  12. package/dist/_browser-chunks/chunk-AS2HQEYC.js +14 -0
  13. package/dist/_browser-chunks/chunk-AXG2BOBL.js +836 -0
  14. package/dist/_browser-chunks/chunk-BE2DAXKJ.js +2966 -0
  15. package/dist/_browser-chunks/{chunk-MH6AXFXB.js → chunk-CHUV5WSW.js} +0 -5
  16. package/dist/_browser-chunks/chunk-EBHB6RPS.js +61 -0
  17. package/dist/_browser-chunks/chunk-EUVGDK4H.js +93 -0
  18. package/dist/_browser-chunks/chunk-EZSQOHRI.js +18 -0
  19. package/dist/_browser-chunks/{chunk-CADGRH3P.js → chunk-FNXWN6IK.js} +3 -8
  20. package/dist/_browser-chunks/chunk-GFLS4VP3.js +64 -0
  21. package/dist/_browser-chunks/{chunk-L2D73C6Z.js → chunk-H6XK3RSC.js} +13 -21
  22. package/dist/_browser-chunks/chunk-IPA5A322.js +71 -0
  23. package/dist/_browser-chunks/chunk-JP7NCOJX.js +37 -0
  24. package/dist/_browser-chunks/chunk-KJHJLCBK.js +11 -0
  25. package/dist/_browser-chunks/{chunk-QMY4G4R2.js → chunk-L4RMQ7D7.js} +17 -64
  26. package/dist/_browser-chunks/{chunk-AB7OOPUX.js → chunk-QKODTO7K.js} +0 -5
  27. package/dist/_browser-chunks/chunk-RP5RXKFU.js +2491 -0
  28. package/dist/_browser-chunks/chunk-SL75JR6Y.js +9 -0
  29. package/dist/_browser-chunks/chunk-UD6FQLAF.js +1481 -0
  30. package/dist/_browser-chunks/chunk-VYJQ7RU5.js +2853 -0
  31. package/dist/_browser-chunks/chunk-WJYERY3R.js +136 -0
  32. package/dist/_browser-chunks/chunk-WXP2XJ3O.js +950 -0
  33. package/dist/_browser-chunks/chunk-X3DUQ5RA.js +47 -0
  34. package/dist/_browser-chunks/chunk-XJNX76GA.js +85 -0
  35. package/dist/_browser-chunks/{chunk-F4Q6SGTB.js → chunk-YKE5S47A.js} +177 -399
  36. package/dist/_browser-chunks/{chunk-SN4J4IQ3.js → chunk-ZUWEVLDX.js} +1 -7
  37. package/dist/_browser-chunks/{formatter-OMEEQ6HG.js → formatter-QJ4M4OGQ.js} +4 -9
  38. package/dist/_browser-chunks/{syntaxhighlighter-RJZASWHL.js → syntaxhighlighter-WKBQ5RC7.js} +704 -1848
  39. package/dist/_node-chunks/{builder-manager-HA7CYFCK.js → builder-manager-YUOHSIUB.js} +475 -1013
  40. package/dist/_node-chunks/camelcase-JREIL7NV.js +18 -0
  41. package/dist/_node-chunks/{chunk-RMHAL25C.js → chunk-2D2IODUU.js} +88 -228
  42. package/dist/_node-chunks/chunk-2DMESZFJ.js +943 -0
  43. package/dist/_node-chunks/chunk-4FT2DHGE.js +3009 -0
  44. package/dist/_node-chunks/chunk-5HV3B5OP.js +45571 -0
  45. package/dist/_node-chunks/{chunk-OVXB5GGT.js → chunk-5KLIDWFN.js} +292 -688
  46. package/dist/_node-chunks/chunk-A4APXFQ2.js +759 -0
  47. package/dist/_node-chunks/chunk-B6JWY6PC.js +37 -0
  48. package/dist/_node-chunks/chunk-CZ5GHJCC.js +603 -0
  49. package/dist/_node-chunks/chunk-DUXPWBOK.js +61 -0
  50. package/dist/_node-chunks/chunk-DWXTZT3D.js +58 -0
  51. package/dist/_node-chunks/chunk-E5FJS66Z.js +20 -0
  52. package/dist/_node-chunks/chunk-EZWWR7AR.js +936 -0
  53. package/dist/_node-chunks/chunk-FDXFVHIL.js +1114 -0
  54. package/dist/_node-chunks/{chunk-F3XOPI6H.js → chunk-FZLRAH4N.js} +469 -983
  55. package/dist/_node-chunks/chunk-HZG65SU3.js +34 -0
  56. package/dist/_node-chunks/chunk-IXVYNBMD.js +18 -0
  57. package/dist/_node-chunks/chunk-JARUEMEP.js +4523 -0
  58. package/dist/_node-chunks/chunk-LIH7MTP7.js +3214 -0
  59. package/dist/_node-chunks/chunk-N5GIRUP5.js +1047 -0
  60. package/dist/_node-chunks/{chunk-X4XU27M6.js → chunk-NAOYEL54.js} +15 -24
  61. package/dist/_node-chunks/chunk-O5DA7YLO.js +3171 -0
  62. package/dist/_node-chunks/chunk-OP3INKUD.js +54 -0
  63. package/dist/_node-chunks/chunk-QCO2ZM7F.js +209 -0
  64. package/dist/_node-chunks/chunk-QYQIZBS6.js +26 -0
  65. package/dist/_node-chunks/chunk-SEMIAAWG.js +1564 -0
  66. package/dist/_node-chunks/chunk-TS2UUH2J.js +301 -0
  67. package/dist/_node-chunks/chunk-WA6KZQZ2.js +119 -0
  68. package/dist/_node-chunks/{chunk-ZHSCUGNP.js → chunk-WFLWJO24.js} +3799 -7849
  69. package/dist/_node-chunks/chunk-WUXQMQCB.js +72 -0
  70. package/dist/_node-chunks/{chunk-VPR5IBMG.js → chunk-XXPJ7XR3.js} +8 -10
  71. package/dist/_node-chunks/chunk-Y4E6IGQF.js +61 -0
  72. package/dist/_node-chunks/chunk-ZL3AFKRX.js +1029 -0
  73. package/dist/_node-chunks/chunk-ZXSD6L3S.js +756 -0
  74. package/dist/_node-chunks/dist-DS2B5A3J.js +121 -0
  75. package/dist/_node-chunks/globby-6THB7HVX.js +3452 -0
  76. package/dist/_node-chunks/lib-5NKX4YGG.js +366 -0
  77. package/dist/_node-chunks/mdx-N42X6CFJ-ZLT3QOFF.js +14329 -0
  78. package/dist/_node-chunks/p-limit-PDMWNG7W.js +116 -0
  79. package/dist/_node-chunks/plugin-6XMWOGPO.js +123 -0
  80. package/dist/_node-chunks/{plugin-6ZPCS4LI.js → plugin-LTOXVT6A.js} +36 -56
  81. package/dist/_node-chunks/webpack-inject-mocker-runtime-plugin-2SFE5LQS.js +46582 -0
  82. package/dist/_node-chunks/webpack-mock-plugin-CX5J2U56.js +92 -0
  83. package/dist/actions/decorator.js +21 -42
  84. package/dist/actions/index.js +3 -3
  85. package/dist/babel/index.d.ts +671 -335
  86. package/dist/babel/index.js +11 -11
  87. package/dist/bin/core.js +592 -1546
  88. package/dist/bin/dispatcher.js +26 -37
  89. package/dist/bin/loader.js +23 -34
  90. package/dist/channels/index.js +98 -234
  91. package/dist/cli/index.js +1951 -5308
  92. package/dist/client-logger/index.js +31 -61
  93. package/dist/common/index.js +20 -20
  94. package/dist/components/index.js +4211 -8586
  95. package/dist/core-events/index.js +2 -66
  96. package/dist/core-server/index.js +3054 -7290
  97. package/dist/core-server/presets/common-manager.css +2 -2
  98. package/dist/core-server/presets/common-manager.js +1806 -3427
  99. package/dist/core-server/presets/common-override-preset.js +31 -60
  100. package/dist/core-server/presets/common-preset.js +434 -924
  101. package/dist/core-server/presets/webpack/loaders/storybook-mock-transform-loader.js +15 -19
  102. package/dist/core-server/presets/webpack/loaders/webpack-automock-loader.js +12 -17
  103. package/dist/csf/index.js +534 -1179
  104. package/dist/csf-tools/index.js +9 -9
  105. package/dist/docs-tools/index.js +6 -6
  106. package/dist/highlight/index.js +2 -2
  107. package/dist/instrumenter/index.js +199 -415
  108. package/dist/manager/globals-runtime.js +24150 -47364
  109. package/dist/manager/globals.js +2 -3
  110. package/dist/manager/runtime.js +3961 -8373
  111. package/dist/manager-api/index.js +1231 -2425
  112. package/dist/manager-errors.d.ts +3 -0
  113. package/dist/manager-errors.js +3 -3
  114. package/dist/node-logger/index.js +1253 -2601
  115. package/dist/preview/globals.js +2 -3
  116. package/dist/preview/runtime.js +10364 -21990
  117. package/dist/preview-api/index.d.ts +67 -68
  118. package/dist/preview-api/index.js +13 -13
  119. package/dist/preview-errors.d.ts +3 -0
  120. package/dist/preview-errors.js +4 -4
  121. package/dist/router/index.js +347 -899
  122. package/dist/server-errors.d.ts +3 -0
  123. package/dist/server-errors.js +10 -10
  124. package/dist/telemetry/index.js +24 -24
  125. package/dist/test/index.js +5860 -11645
  126. package/dist/theming/create.js +4 -4
  127. package/dist/theming/index.d.ts +3363 -2597
  128. package/dist/theming/index.js +490 -1086
  129. package/dist/types/index.js +2 -11
  130. package/dist/viewport/index.js +3 -3
  131. package/package.json +5 -5
  132. package/dist/_browser-chunks/Color-FQNEU7YS.js +0 -1695
  133. package/dist/_browser-chunks/WithTooltip-6NHN2GXF.js +0 -2343
  134. package/dist/_browser-chunks/chunk-6A7OIVEL.js +0 -66
  135. package/dist/_browser-chunks/chunk-AW46NMGV.js +0 -1308
  136. package/dist/_browser-chunks/chunk-B4A3ADP3.js +0 -3816
  137. package/dist/_browser-chunks/chunk-FSBVR7H5.js +0 -106
  138. package/dist/_browser-chunks/chunk-FUOHXXZT.js +0 -23
  139. package/dist/_browser-chunks/chunk-GTKOCWCT.js +0 -17
  140. package/dist/_browser-chunks/chunk-HHW4FUMO.js +0 -12
  141. package/dist/_browser-chunks/chunk-JVSKG4YS.js +0 -4052
  142. package/dist/_browser-chunks/chunk-LASUB7TL.js +0 -76
  143. package/dist/_browser-chunks/chunk-LYCSRYYR.js +0 -101
  144. package/dist/_browser-chunks/chunk-NVV6MIOE.js +0 -243
  145. package/dist/_browser-chunks/chunk-OBXWFEPB.js +0 -852
  146. package/dist/_browser-chunks/chunk-OPCDBBL3.js +0 -48
  147. package/dist/_browser-chunks/chunk-PB6FZ3WE.js +0 -130
  148. package/dist/_browser-chunks/chunk-RW5PKMWM.js +0 -4182
  149. package/dist/_browser-chunks/chunk-SYS437NN.js +0 -122
  150. package/dist/_browser-chunks/chunk-U46RQHA4.js +0 -12
  151. package/dist/_browser-chunks/chunk-UTNZYD2N.js +0 -311
  152. package/dist/_browser-chunks/chunk-VUAFL5XK.js +0 -20
  153. package/dist/_browser-chunks/chunk-XDGMHOV7.js +0 -2197
  154. package/dist/_browser-chunks/chunk-XW6KSYKF.js +0 -16
  155. package/dist/_browser-chunks/chunk-Y3M7TW6K.js +0 -1041
  156. package/dist/_browser-chunks/chunk-ZNRFDIVA.js +0 -233
  157. package/dist/_node-chunks/camelcase-QALD4XFE.js +0 -18
  158. package/dist/_node-chunks/chunk-2XY53ALL.js +0 -420
  159. package/dist/_node-chunks/chunk-3CBQMG2A.js +0 -6712
  160. package/dist/_node-chunks/chunk-3WDAPZYQ.js +0 -28
  161. package/dist/_node-chunks/chunk-4ZB555EJ.js +0 -697
  162. package/dist/_node-chunks/chunk-52DXKXY3.js +0 -4272
  163. package/dist/_node-chunks/chunk-5OVB4A6F.js +0 -69
  164. package/dist/_node-chunks/chunk-AGHGNXGH.js +0 -18
  165. package/dist/_node-chunks/chunk-B23X5ZCK.js +0 -1531
  166. package/dist/_node-chunks/chunk-B2DAHWJK.js +0 -220
  167. package/dist/_node-chunks/chunk-CC4PW5MJ.js +0 -34
  168. package/dist/_node-chunks/chunk-D7NIZELR.js +0 -2256
  169. package/dist/_node-chunks/chunk-DO5Q3H4L.js +0 -1250
  170. package/dist/_node-chunks/chunk-ECK7WVFX.js +0 -304
  171. package/dist/_node-chunks/chunk-EUH3NHXA.js +0 -79
  172. package/dist/_node-chunks/chunk-FOQHPHCV.js +0 -1657
  173. package/dist/_node-chunks/chunk-G6EL47NS.js +0 -111
  174. package/dist/_node-chunks/chunk-GFLS4TJB.js +0 -90
  175. package/dist/_node-chunks/chunk-J3XZKWHE.js +0 -1586
  176. package/dist/_node-chunks/chunk-LE63EHJ5.js +0 -1518
  177. package/dist/_node-chunks/chunk-M47XA42S.js +0 -4741
  178. package/dist/_node-chunks/chunk-OOI74AL3.js +0 -61
  179. package/dist/_node-chunks/chunk-PRJHT3GJ.js +0 -61
  180. package/dist/_node-chunks/chunk-Q52PVUSU.js +0 -101
  181. package/dist/_node-chunks/chunk-SDCF5RNN.js +0 -1198
  182. package/dist/_node-chunks/chunk-UJ5SJ23M.js +0 -5029
  183. package/dist/_node-chunks/chunk-UPHK4ETU.js +0 -64658
  184. package/dist/_node-chunks/chunk-V7VURIPB.js +0 -1544
  185. package/dist/_node-chunks/dist-6TXHNR5C.js +0 -175
  186. package/dist/_node-chunks/globby-PBTV6PX6.js +0 -5222
  187. package/dist/_node-chunks/lib-4RTDZVGX.js +0 -518
  188. package/dist/_node-chunks/mdx-N42X6CFJ-COWEH7KR.js +0 -22017
  189. package/dist/_node-chunks/p-limit-PBVZQOFY.js +0 -168
  190. package/dist/_node-chunks/plugin-EOZKYZAG.js +0 -159
  191. package/dist/_node-chunks/webpack-inject-mocker-runtime-plugin-35HMSMR5.js +0 -69102
  192. package/dist/_node-chunks/webpack-mock-plugin-GT3MA5E2.js +0 -124
@@ -1,4182 +0,0 @@
1
- import {
2
- isTestEnvironment,
3
- pauseAnimations,
4
- waitForAnimations
5
- } from "./chunk-LYCSRYYR.js";
6
- import {
7
- require_main
8
- } from "./chunk-Y3M7TW6K.js";
9
- import {
10
- SNIPPET_RENDERED,
11
- combineParameters
12
- } from "./chunk-B4A3ADP3.js";
13
- import {
14
- isEqual
15
- } from "./chunk-ZNRFDIVA.js";
16
- import {
17
- invariant
18
- } from "./chunk-FUOHXXZT.js";
19
- import {
20
- require_ansi_to_html
21
- } from "./chunk-F4Q6SGTB.js";
22
- import {
23
- mapValues,
24
- pickBy
25
- } from "./chunk-UTNZYD2N.js";
26
- import {
27
- isPlainObject
28
- } from "./chunk-FSBVR7H5.js";
29
- import {
30
- require_memoizerific
31
- } from "./chunk-NVV6MIOE.js";
32
- import {
33
- dedent
34
- } from "./chunk-OPCDBBL3.js";
35
- import {
36
- __name,
37
- __toESM
38
- } from "./chunk-MM7DTO55.js";
39
-
40
- // src/preview-api/modules/addons/main.ts
41
- import { global } from "@storybook/global";
42
-
43
- // src/preview-api/modules/addons/storybook-channel-mock.ts
44
- import { Channel } from "storybook/internal/channels";
45
- function mockChannel() {
46
- const transport = {
47
- setHandler: /* @__PURE__ */ __name(() => {
48
- }, "setHandler"),
49
- send: /* @__PURE__ */ __name(() => {
50
- }, "send")
51
- };
52
- return new Channel({ transport });
53
- }
54
- __name(mockChannel, "mockChannel");
55
-
56
- // src/preview-api/modules/addons/main.ts
57
- var _AddonStore = class _AddonStore {
58
- constructor() {
59
- this.getChannel = /* @__PURE__ */ __name(() => {
60
- if (!this.channel) {
61
- const channel = mockChannel();
62
- this.setChannel(channel);
63
- return channel;
64
- }
65
- return this.channel;
66
- }, "getChannel");
67
- this.ready = /* @__PURE__ */ __name(() => this.promise, "ready");
68
- this.hasChannel = /* @__PURE__ */ __name(() => !!this.channel, "hasChannel");
69
- this.setChannel = /* @__PURE__ */ __name((channel) => {
70
- this.channel = channel;
71
- this.resolve();
72
- }, "setChannel");
73
- this.promise = new Promise((res) => {
74
- this.resolve = () => res(this.getChannel());
75
- });
76
- }
77
- };
78
- __name(_AddonStore, "AddonStore");
79
- var AddonStore = _AddonStore;
80
- var KEY = "__STORYBOOK_ADDONS_PREVIEW";
81
- function getAddonsStore() {
82
- if (!global[KEY]) {
83
- global[KEY] = new AddonStore();
84
- }
85
- return global[KEY];
86
- }
87
- __name(getAddonsStore, "getAddonsStore");
88
- var addons = getAddonsStore();
89
-
90
- // src/preview-api/modules/addons/hooks.ts
91
- import { logger } from "storybook/internal/client-logger";
92
- import {
93
- FORCE_RE_RENDER,
94
- RESET_STORY_ARGS,
95
- STORY_RENDERED,
96
- UPDATE_GLOBALS,
97
- UPDATE_STORY_ARGS
98
- } from "storybook/internal/core-events";
99
- import { global as global2 } from "@storybook/global";
100
- var _HooksContext = class _HooksContext {
101
- constructor() {
102
- this.hookListsMap = void 0;
103
- this.mountedDecorators = void 0;
104
- this.prevMountedDecorators = void 0;
105
- this.currentHooks = void 0;
106
- this.nextHookIndex = void 0;
107
- this.currentPhase = void 0;
108
- this.currentEffects = void 0;
109
- this.prevEffects = void 0;
110
- this.currentDecoratorName = void 0;
111
- this.hasUpdates = void 0;
112
- this.currentContext = void 0;
113
- this.renderListener = /* @__PURE__ */ __name((storyId) => {
114
- if (storyId !== this.currentContext?.id) {
115
- return;
116
- }
117
- this.triggerEffects();
118
- this.currentContext = null;
119
- this.removeRenderListeners();
120
- }, "renderListener");
121
- this.init();
122
- }
123
- init() {
124
- this.hookListsMap = /* @__PURE__ */ new WeakMap();
125
- this.mountedDecorators = /* @__PURE__ */ new Set();
126
- this.prevMountedDecorators = /* @__PURE__ */ new Set();
127
- this.currentHooks = [];
128
- this.nextHookIndex = 0;
129
- this.currentPhase = "NONE";
130
- this.currentEffects = [];
131
- this.prevEffects = [];
132
- this.currentDecoratorName = null;
133
- this.hasUpdates = false;
134
- this.currentContext = null;
135
- }
136
- clean() {
137
- this.prevEffects.forEach((effect) => {
138
- if (effect.destroy) {
139
- effect.destroy();
140
- }
141
- });
142
- this.init();
143
- this.removeRenderListeners();
144
- }
145
- getNextHook() {
146
- const hook = this.currentHooks[this.nextHookIndex];
147
- this.nextHookIndex += 1;
148
- return hook;
149
- }
150
- triggerEffects() {
151
- this.prevEffects.forEach((effect) => {
152
- if (!this.currentEffects.includes(effect) && effect.destroy) {
153
- effect.destroy();
154
- }
155
- });
156
- this.currentEffects.forEach((effect) => {
157
- if (!this.prevEffects.includes(effect)) {
158
- effect.destroy = effect.create();
159
- }
160
- });
161
- this.prevEffects = this.currentEffects;
162
- this.currentEffects = [];
163
- }
164
- addRenderListeners() {
165
- this.removeRenderListeners();
166
- const channel = addons.getChannel();
167
- channel.on(STORY_RENDERED, this.renderListener);
168
- }
169
- removeRenderListeners() {
170
- const channel = addons.getChannel();
171
- channel.removeListener(STORY_RENDERED, this.renderListener);
172
- }
173
- };
174
- __name(_HooksContext, "HooksContext");
175
- var HooksContext = _HooksContext;
176
- function hookify(fn) {
177
- const hookified = /* @__PURE__ */ __name((...args) => {
178
- const { hooks } = typeof args[0] === "function" ? args[1] : args[0];
179
- const prevPhase = hooks.currentPhase;
180
- const prevHooks = hooks.currentHooks;
181
- const prevNextHookIndex = hooks.nextHookIndex;
182
- const prevDecoratorName = hooks.currentDecoratorName;
183
- hooks.currentDecoratorName = fn.name;
184
- if (hooks.prevMountedDecorators.has(fn)) {
185
- hooks.currentPhase = "UPDATE";
186
- hooks.currentHooks = hooks.hookListsMap.get(fn) || [];
187
- } else {
188
- hooks.currentPhase = "MOUNT";
189
- hooks.currentHooks = [];
190
- hooks.hookListsMap.set(fn, hooks.currentHooks);
191
- hooks.prevMountedDecorators.add(fn);
192
- }
193
- hooks.nextHookIndex = 0;
194
- const prevContext = global2.STORYBOOK_HOOKS_CONTEXT;
195
- global2.STORYBOOK_HOOKS_CONTEXT = hooks;
196
- const result = fn(...args);
197
- global2.STORYBOOK_HOOKS_CONTEXT = prevContext;
198
- if (hooks.currentPhase === "UPDATE" && hooks.getNextHook() != null) {
199
- throw new Error(
200
- "Rendered fewer hooks than expected. This may be caused by an accidental early return statement."
201
- );
202
- }
203
- hooks.currentPhase = prevPhase;
204
- hooks.currentHooks = prevHooks;
205
- hooks.nextHookIndex = prevNextHookIndex;
206
- hooks.currentDecoratorName = prevDecoratorName;
207
- return result;
208
- }, "hookified");
209
- hookified.originalFn = fn;
210
- return hookified;
211
- }
212
- __name(hookify, "hookify");
213
- var numberOfRenders = 0;
214
- var RENDER_LIMIT = 25;
215
- var applyHooks = /* @__PURE__ */ __name((applyDecorators) => (storyFn, decorators) => {
216
- const decorated = applyDecorators(
217
- hookify(storyFn),
218
- decorators.map((decorator) => hookify(decorator))
219
- );
220
- return (context) => {
221
- const { hooks } = context;
222
- hooks.prevMountedDecorators ??= /* @__PURE__ */ new Set();
223
- hooks.mountedDecorators = /* @__PURE__ */ new Set([storyFn, ...decorators]);
224
- hooks.currentContext = context;
225
- hooks.hasUpdates = false;
226
- let result = decorated(context);
227
- numberOfRenders = 1;
228
- while (hooks.hasUpdates) {
229
- hooks.hasUpdates = false;
230
- hooks.currentEffects = [];
231
- result = decorated(context);
232
- numberOfRenders += 1;
233
- if (numberOfRenders > RENDER_LIMIT) {
234
- throw new Error(
235
- "Too many re-renders. Storybook limits the number of renders to prevent an infinite loop."
236
- );
237
- }
238
- }
239
- hooks.addRenderListeners();
240
- return result;
241
- };
242
- }, "applyHooks");
243
- var areDepsEqual = /* @__PURE__ */ __name((deps, nextDeps) => deps.length === nextDeps.length && deps.every((dep, i) => dep === nextDeps[i]), "areDepsEqual");
244
- var invalidHooksError = /* @__PURE__ */ __name(() => new Error("Storybook preview hooks can only be called inside decorators and story functions."), "invalidHooksError");
245
- function getHooksContextOrNull() {
246
- return global2.STORYBOOK_HOOKS_CONTEXT || null;
247
- }
248
- __name(getHooksContextOrNull, "getHooksContextOrNull");
249
- function getHooksContextOrThrow() {
250
- const hooks = getHooksContextOrNull();
251
- if (hooks == null) {
252
- throw invalidHooksError();
253
- }
254
- return hooks;
255
- }
256
- __name(getHooksContextOrThrow, "getHooksContextOrThrow");
257
- function useHook(name, callback, deps) {
258
- const hooks = getHooksContextOrThrow();
259
- if (hooks.currentPhase === "MOUNT") {
260
- if (deps != null && !Array.isArray(deps)) {
261
- logger.warn(
262
- `${name} received a final argument that is not an array (instead, received ${deps}). When specified, the final argument must be an array.`
263
- );
264
- }
265
- const hook = { name, deps };
266
- hooks.currentHooks.push(hook);
267
- callback(hook);
268
- return hook;
269
- }
270
- if (hooks.currentPhase === "UPDATE") {
271
- const hook = hooks.getNextHook();
272
- if (hook == null) {
273
- throw new Error("Rendered more hooks than during the previous render.");
274
- }
275
- if (hook.name !== name) {
276
- logger.warn(
277
- `Storybook has detected a change in the order of Hooks${hooks.currentDecoratorName ? ` called by ${hooks.currentDecoratorName}` : ""}. This will lead to bugs and errors if not fixed.`
278
- );
279
- }
280
- if (deps != null && hook.deps == null) {
281
- logger.warn(
282
- `${name} received a final argument during this render, but not during the previous render. Even though the final argument is optional, its type cannot change between renders.`
283
- );
284
- }
285
- if (deps != null && hook.deps != null && deps.length !== hook.deps.length) {
286
- logger.warn(`The final argument passed to ${name} changed size between renders. The order and size of this array must remain constant.
287
- Previous: ${hook.deps}
288
- Incoming: ${deps}`);
289
- }
290
- if (deps == null || hook.deps == null || !areDepsEqual(deps, hook.deps)) {
291
- callback(hook);
292
- hook.deps = deps;
293
- }
294
- return hook;
295
- }
296
- throw invalidHooksError();
297
- }
298
- __name(useHook, "useHook");
299
- function useMemoLike(name, nextCreate, deps) {
300
- const { memoizedState } = useHook(
301
- name,
302
- (hook) => {
303
- hook.memoizedState = nextCreate();
304
- },
305
- deps
306
- );
307
- return memoizedState;
308
- }
309
- __name(useMemoLike, "useMemoLike");
310
- function useMemo(nextCreate, deps) {
311
- return useMemoLike("useMemo", nextCreate, deps);
312
- }
313
- __name(useMemo, "useMemo");
314
- function useCallback(callback, deps) {
315
- return useMemoLike("useCallback", () => callback, deps);
316
- }
317
- __name(useCallback, "useCallback");
318
- function useRefLike(name, initialValue) {
319
- return useMemoLike(name, () => ({ current: initialValue }), []);
320
- }
321
- __name(useRefLike, "useRefLike");
322
- function useRef(initialValue) {
323
- return useRefLike("useRef", initialValue);
324
- }
325
- __name(useRef, "useRef");
326
- function triggerUpdate() {
327
- const hooks = getHooksContextOrNull();
328
- if (hooks != null && hooks.currentPhase !== "NONE") {
329
- hooks.hasUpdates = true;
330
- } else {
331
- try {
332
- addons.getChannel().emit(FORCE_RE_RENDER);
333
- } catch (e) {
334
- logger.warn("State updates of Storybook preview hooks work only in browser");
335
- }
336
- }
337
- }
338
- __name(triggerUpdate, "triggerUpdate");
339
- function useStateLike(name, initialState) {
340
- const stateRef = useRefLike(
341
- name,
342
- // @ts-expect-error S type should never be function, but there's no way to tell that to TypeScript
343
- typeof initialState === "function" ? initialState() : initialState
344
- );
345
- const setState = /* @__PURE__ */ __name((update) => {
346
- stateRef.current = typeof update === "function" ? update(stateRef.current) : update;
347
- triggerUpdate();
348
- }, "setState");
349
- return [stateRef.current, setState];
350
- }
351
- __name(useStateLike, "useStateLike");
352
- function useState(initialState) {
353
- return useStateLike("useState", initialState);
354
- }
355
- __name(useState, "useState");
356
- function useReducer(reducer, initialArg, init) {
357
- const initialState = init != null ? () => init(initialArg) : initialArg;
358
- const [state, setState] = useStateLike("useReducer", initialState);
359
- const dispatch = /* @__PURE__ */ __name((action) => setState((prevState) => reducer(prevState, action)), "dispatch");
360
- return [state, dispatch];
361
- }
362
- __name(useReducer, "useReducer");
363
- function useEffect(create, deps) {
364
- const hooks = getHooksContextOrThrow();
365
- const effect = useMemoLike("useEffect", () => ({ create }), deps);
366
- if (!hooks.currentEffects.includes(effect)) {
367
- hooks.currentEffects.push(effect);
368
- }
369
- }
370
- __name(useEffect, "useEffect");
371
- function useChannel(eventMap, deps = []) {
372
- const channel = addons.getChannel();
373
- useEffect(() => {
374
- Object.entries(eventMap).forEach(([type, listener]) => channel.on(type, listener));
375
- return () => {
376
- Object.entries(eventMap).forEach(
377
- ([type, listener]) => channel.removeListener(type, listener)
378
- );
379
- };
380
- }, [...Object.keys(eventMap), ...deps]);
381
- return useCallback(channel.emit.bind(channel), [channel]);
382
- }
383
- __name(useChannel, "useChannel");
384
- function useStoryContext() {
385
- const { currentContext } = getHooksContextOrThrow();
386
- if (currentContext == null) {
387
- throw invalidHooksError();
388
- }
389
- return currentContext;
390
- }
391
- __name(useStoryContext, "useStoryContext");
392
- function useParameter(parameterKey, defaultValue) {
393
- const { parameters } = useStoryContext();
394
- if (parameterKey) {
395
- return parameters[parameterKey] ?? defaultValue;
396
- }
397
- return void 0;
398
- }
399
- __name(useParameter, "useParameter");
400
- function useArgs() {
401
- const channel = addons.getChannel();
402
- const { id: storyId, args } = useStoryContext();
403
- const updateArgs = useCallback(
404
- (updatedArgs) => channel.emit(UPDATE_STORY_ARGS, { storyId, updatedArgs }),
405
- [channel, storyId]
406
- );
407
- const resetArgs = useCallback(
408
- (argNames) => channel.emit(RESET_STORY_ARGS, { storyId, argNames }),
409
- [channel, storyId]
410
- );
411
- return [args, updateArgs, resetArgs];
412
- }
413
- __name(useArgs, "useArgs");
414
- function useGlobals() {
415
- const channel = addons.getChannel();
416
- const { globals } = useStoryContext();
417
- const updateGlobals = useCallback(
418
- (newGlobals) => channel.emit(UPDATE_GLOBALS, { globals: newGlobals }),
419
- [channel]
420
- );
421
- return [globals, updateGlobals];
422
- }
423
- __name(useGlobals, "useGlobals");
424
-
425
- // src/preview-api/modules/addons/make-decorator.ts
426
- var makeDecorator = /* @__PURE__ */ __name(({
427
- name,
428
- parameterName,
429
- wrapper,
430
- skipIfNoParametersOrOptions = false
431
- }) => {
432
- const decorator = /* @__PURE__ */ __name((options) => (storyFn, context) => {
433
- const parameters = context.parameters && context.parameters[parameterName];
434
- if (parameters && parameters.disable) {
435
- return storyFn(context);
436
- }
437
- if (skipIfNoParametersOrOptions && !options && !parameters) {
438
- return storyFn(context);
439
- }
440
- return wrapper(storyFn, context, {
441
- options,
442
- parameters
443
- });
444
- }, "decorator");
445
- return (...args) => {
446
- if (typeof args[0] === "function") {
447
- return decorator()(...args);
448
- }
449
- return (...innerArgs) => {
450
- if (innerArgs.length > 1) {
451
- if (args.length > 1) {
452
- return decorator(args)(...innerArgs);
453
- }
454
- return decorator(...args)(...innerArgs);
455
- }
456
- throw new Error(
457
- `Passing stories directly into ${name}() is not allowed,
458
- instead use addDecorator(${name}) and pass options with the '${parameterName}' parameter`
459
- );
460
- };
461
- };
462
- }, "makeDecorator");
463
-
464
- // src/preview-api/modules/store/StoryStore.ts
465
- import { getCoreAnnotations as getCoreAnnotations2 } from "storybook/internal/csf";
466
- import {
467
- CalledExtractOnStoreError,
468
- MissingStoryFromCsfFileError
469
- } from "storybook/internal/preview-errors";
470
- var import_memoizerific2 = __toESM(require_memoizerific(), 1);
471
-
472
- // src/preview-api/modules/store/args.ts
473
- import { once } from "storybook/internal/client-logger";
474
- var INCOMPATIBLE = Symbol("incompatible");
475
- var map = /* @__PURE__ */ __name((arg, argType) => {
476
- const type = argType.type;
477
- if (arg === void 0 || arg === null || !type) {
478
- return arg;
479
- }
480
- if (argType.mapping) {
481
- return arg;
482
- }
483
- switch (type.name) {
484
- case "string":
485
- return String(arg);
486
- case "enum":
487
- return arg;
488
- case "number":
489
- return Number(arg);
490
- case "boolean":
491
- return String(arg) === "true";
492
- case "array":
493
- if (!type.value || !Array.isArray(arg)) {
494
- return INCOMPATIBLE;
495
- }
496
- return arg.reduce((acc, item, index) => {
497
- const mapped = map(item, { type: type.value });
498
- if (mapped !== INCOMPATIBLE) {
499
- acc[index] = mapped;
500
- }
501
- return acc;
502
- }, new Array(arg.length));
503
- case "object":
504
- if (typeof arg === "string" || typeof arg === "number") {
505
- return arg;
506
- }
507
- if (!type.value || typeof arg !== "object") {
508
- return INCOMPATIBLE;
509
- }
510
- return Object.entries(arg).reduce((acc, [key, val]) => {
511
- const mapped = map(val, { type: type.value[key] });
512
- return mapped === INCOMPATIBLE ? acc : Object.assign(acc, { [key]: mapped });
513
- }, {});
514
- case "other": {
515
- const isPrimitiveArg = typeof arg === "string" || typeof arg === "number" || typeof arg === "boolean";
516
- if (type.value === "ReactNode" && isPrimitiveArg) {
517
- return arg;
518
- }
519
- return INCOMPATIBLE;
520
- }
521
- default:
522
- return INCOMPATIBLE;
523
- }
524
- }, "map");
525
- var mapArgsToTypes = /* @__PURE__ */ __name((args, argTypes) => {
526
- return Object.entries(args).reduce((acc, [key, value]) => {
527
- if (!argTypes[key]) {
528
- return acc;
529
- }
530
- const mapped = map(value, argTypes[key]);
531
- return mapped === INCOMPATIBLE ? acc : Object.assign(acc, { [key]: mapped });
532
- }, {});
533
- }, "mapArgsToTypes");
534
- var combineArgs = /* @__PURE__ */ __name((value, update) => {
535
- if (Array.isArray(value) && Array.isArray(update)) {
536
- return update.reduce(
537
- (acc, upd, index) => {
538
- acc[index] = combineArgs(value[index], update[index]);
539
- return acc;
540
- },
541
- [...value]
542
- ).filter((v) => v !== void 0);
543
- }
544
- if (!isPlainObject(value) || !isPlainObject(update)) {
545
- return update;
546
- }
547
- return Object.keys({ ...value, ...update }).reduce((acc, key) => {
548
- if (key in update) {
549
- const combined = combineArgs(value[key], update[key]);
550
- if (combined !== void 0) {
551
- acc[key] = combined;
552
- }
553
- } else {
554
- acc[key] = value[key];
555
- }
556
- return acc;
557
- }, {});
558
- }, "combineArgs");
559
- var validateOptions = /* @__PURE__ */ __name((args, argTypes) => {
560
- return Object.entries(argTypes).reduce((acc, [key, { options }]) => {
561
- function allowArg() {
562
- if (key in args) {
563
- acc[key] = args[key];
564
- }
565
- return acc;
566
- }
567
- __name(allowArg, "allowArg");
568
- if (!options) {
569
- return allowArg();
570
- }
571
- if (!Array.isArray(options)) {
572
- once.error(dedent`
573
- Invalid argType: '${key}.options' should be an array.
574
-
575
- More info: https://storybook.js.org/docs/api/arg-types?ref=error
576
- `);
577
- return allowArg();
578
- }
579
- if (options.some((opt) => opt && ["object", "function"].includes(typeof opt))) {
580
- once.error(dedent`
581
- Invalid argType: '${key}.options' should only contain primitives. Use a 'mapping' for complex values.
582
-
583
- More info: https://storybook.js.org/docs/writing-stories/args?ref=error#mapping-to-complex-arg-values
584
- `);
585
- return allowArg();
586
- }
587
- const isArray = Array.isArray(args[key]);
588
- const invalidIndex = isArray && args[key].findIndex((val) => !options.includes(val));
589
- const isValidArray = isArray && invalidIndex === -1;
590
- if (args[key] === void 0 || options.includes(args[key]) || isValidArray) {
591
- return allowArg();
592
- }
593
- const field = isArray ? `${key}[${invalidIndex}]` : key;
594
- const supportedOptions = options.map((opt) => typeof opt === "string" ? `'${opt}'` : String(opt)).join(", ");
595
- once.warn(`Received illegal value for '${field}'. Supported options: ${supportedOptions}`);
596
- return acc;
597
- }, {});
598
- }, "validateOptions");
599
- var DEEPLY_EQUAL = Symbol("Deeply equal");
600
- var deepDiff = /* @__PURE__ */ __name((value, update) => {
601
- if (typeof value !== typeof update) {
602
- return update;
603
- }
604
- if (isEqual(value, update)) {
605
- return DEEPLY_EQUAL;
606
- }
607
- if (Array.isArray(value) && Array.isArray(update)) {
608
- const res = update.reduce((acc, upd, index) => {
609
- const diff = deepDiff(value[index], upd);
610
- if (diff !== DEEPLY_EQUAL) {
611
- acc[index] = diff;
612
- }
613
- return acc;
614
- }, new Array(update.length));
615
- if (update.length >= value.length) {
616
- return res;
617
- }
618
- return res.concat(new Array(value.length - update.length).fill(void 0));
619
- }
620
- if (isPlainObject(value) && isPlainObject(update)) {
621
- return Object.keys({ ...value, ...update }).reduce((acc, key) => {
622
- const diff = deepDiff(value?.[key], update?.[key]);
623
- return diff === DEEPLY_EQUAL ? acc : Object.assign(acc, { [key]: diff });
624
- }, {});
625
- }
626
- return update;
627
- }, "deepDiff");
628
- var UNTARGETED = "UNTARGETED";
629
- function groupArgsByTarget({
630
- args,
631
- argTypes
632
- }) {
633
- const groupedArgs = {};
634
- Object.entries(args).forEach(([name, value]) => {
635
- const { target = UNTARGETED } = argTypes[name] || {};
636
- groupedArgs[target] = groupedArgs[target] || {};
637
- groupedArgs[target][name] = value;
638
- });
639
- return groupedArgs;
640
- }
641
- __name(groupArgsByTarget, "groupArgsByTarget");
642
-
643
- // src/preview-api/modules/store/ArgsStore.ts
644
- function deleteUndefined(obj) {
645
- Object.keys(obj).forEach((key) => obj[key] === void 0 && delete obj[key]);
646
- return obj;
647
- }
648
- __name(deleteUndefined, "deleteUndefined");
649
- var _ArgsStore = class _ArgsStore {
650
- constructor() {
651
- this.initialArgsByStoryId = {};
652
- this.argsByStoryId = {};
653
- }
654
- get(storyId) {
655
- if (!(storyId in this.argsByStoryId)) {
656
- throw new Error(`No args known for ${storyId} -- has it been rendered yet?`);
657
- }
658
- return this.argsByStoryId[storyId];
659
- }
660
- setInitial(story) {
661
- if (!this.initialArgsByStoryId[story.id]) {
662
- this.initialArgsByStoryId[story.id] = story.initialArgs;
663
- this.argsByStoryId[story.id] = story.initialArgs;
664
- } else if (this.initialArgsByStoryId[story.id] !== story.initialArgs) {
665
- const delta = deepDiff(this.initialArgsByStoryId[story.id], this.argsByStoryId[story.id]);
666
- this.initialArgsByStoryId[story.id] = story.initialArgs;
667
- this.argsByStoryId[story.id] = story.initialArgs;
668
- if (delta !== DEEPLY_EQUAL) {
669
- this.updateFromDelta(story, delta);
670
- }
671
- }
672
- }
673
- updateFromDelta(story, delta) {
674
- const validatedDelta = validateOptions(delta, story.argTypes);
675
- this.argsByStoryId[story.id] = combineArgs(this.argsByStoryId[story.id], validatedDelta);
676
- }
677
- updateFromPersisted(story, persisted) {
678
- const mappedPersisted = mapArgsToTypes(persisted, story.argTypes);
679
- return this.updateFromDelta(story, mappedPersisted);
680
- }
681
- update(storyId, argsUpdate) {
682
- if (!(storyId in this.argsByStoryId)) {
683
- throw new Error(`No args known for ${storyId} -- has it been rendered yet?`);
684
- }
685
- this.argsByStoryId[storyId] = deleteUndefined({
686
- ...this.argsByStoryId[storyId],
687
- ...argsUpdate
688
- });
689
- }
690
- };
691
- __name(_ArgsStore, "ArgsStore");
692
- var ArgsStore = _ArgsStore;
693
-
694
- // src/preview-api/modules/store/GlobalsStore.ts
695
- import { logger as logger2 } from "storybook/internal/client-logger";
696
-
697
- // src/preview-api/modules/store/csf/getValuesFromArgTypes.ts
698
- var getValuesFromArgTypes = /* @__PURE__ */ __name((argTypes = {}) => Object.entries(argTypes).reduce((acc, [arg, { defaultValue }]) => {
699
- if (typeof defaultValue !== "undefined") {
700
- acc[arg] = defaultValue;
701
- }
702
- return acc;
703
- }, {}), "getValuesFromArgTypes");
704
-
705
- // src/preview-api/modules/store/GlobalsStore.ts
706
- var _GlobalsStore = class _GlobalsStore {
707
- constructor({
708
- globals = {},
709
- globalTypes = {}
710
- }) {
711
- this.set({ globals, globalTypes });
712
- }
713
- set({ globals = {}, globalTypes = {} }) {
714
- const delta = this.initialGlobals && deepDiff(this.initialGlobals, this.globals);
715
- this.allowedGlobalNames = /* @__PURE__ */ new Set([...Object.keys(globals), ...Object.keys(globalTypes)]);
716
- const defaultGlobals = getValuesFromArgTypes(globalTypes);
717
- this.initialGlobals = { ...defaultGlobals, ...globals };
718
- this.globals = this.initialGlobals;
719
- if (delta && delta !== DEEPLY_EQUAL) {
720
- this.updateFromPersisted(delta);
721
- }
722
- }
723
- filterAllowedGlobals(globals) {
724
- return Object.entries(globals).reduce((acc, [key, value]) => {
725
- if (this.allowedGlobalNames.has(key)) {
726
- acc[key] = value;
727
- } else {
728
- logger2.warn(
729
- `Attempted to set a global (${key}) that is not defined in initial globals or globalTypes`
730
- );
731
- }
732
- return acc;
733
- }, {});
734
- }
735
- updateFromPersisted(persisted) {
736
- const allowedUrlGlobals = this.filterAllowedGlobals(persisted);
737
- this.globals = { ...this.globals, ...allowedUrlGlobals };
738
- }
739
- get() {
740
- return this.globals;
741
- }
742
- update(newGlobals) {
743
- this.globals = { ...this.globals, ...this.filterAllowedGlobals(newGlobals) };
744
- for (const key in newGlobals) {
745
- if (newGlobals[key] === void 0) {
746
- this.globals[key] = this.initialGlobals[key];
747
- }
748
- }
749
- }
750
- };
751
- __name(_GlobalsStore, "GlobalsStore");
752
- var GlobalsStore = _GlobalsStore;
753
-
754
- // src/preview-api/modules/store/StoryIndexStore.ts
755
- var import_memoizerific = __toESM(require_memoizerific(), 1);
756
- import { MissingStoryAfterHmrError } from "storybook/internal/preview-errors";
757
- var getImportPathMap = (0, import_memoizerific.default)(1)(
758
- (entries) => Object.values(entries).reduce(
759
- (acc, entry) => {
760
- acc[entry.importPath] = acc[entry.importPath] || entry;
761
- return acc;
762
- },
763
- {}
764
- )
765
- );
766
- var _StoryIndexStore = class _StoryIndexStore {
767
- constructor({ entries } = { v: 5, entries: {} }) {
768
- this.entries = entries;
769
- }
770
- entryFromSpecifier(specifier) {
771
- const entries = Object.values(this.entries);
772
- if (specifier === "*") {
773
- return entries[0];
774
- }
775
- if (typeof specifier === "string") {
776
- if (this.entries[specifier]) {
777
- return this.entries[specifier];
778
- }
779
- return entries.find((entry) => entry.id.startsWith(specifier));
780
- }
781
- const { name, title } = specifier;
782
- return entries.find((entry) => entry.name === name && entry.title === title);
783
- }
784
- storyIdToEntry(storyId) {
785
- const storyEntry = this.entries[storyId];
786
- if (!storyEntry) {
787
- throw new MissingStoryAfterHmrError({ storyId });
788
- }
789
- return storyEntry;
790
- }
791
- importPathToEntry(importPath) {
792
- return getImportPathMap(this.entries)[importPath];
793
- }
794
- };
795
- __name(_StoryIndexStore, "StoryIndexStore");
796
- var StoryIndexStore = _StoryIndexStore;
797
-
798
- // src/preview-api/modules/store/csf/normalizeInputTypes.ts
799
- var normalizeType = /* @__PURE__ */ __name((type) => {
800
- return typeof type === "string" ? { name: type } : type;
801
- }, "normalizeType");
802
- var normalizeControl = /* @__PURE__ */ __name((control) => typeof control === "string" ? { type: control } : control, "normalizeControl");
803
- var normalizeInputType = /* @__PURE__ */ __name((inputType, key) => {
804
- const { type, control, ...rest } = inputType;
805
- const normalized = {
806
- name: key,
807
- ...rest
808
- };
809
- if (type) {
810
- normalized.type = normalizeType(type);
811
- }
812
- if (control) {
813
- normalized.control = normalizeControl(control);
814
- } else if (control === false) {
815
- normalized.control = { disable: true };
816
- }
817
- return normalized;
818
- }, "normalizeInputType");
819
- var normalizeInputTypes = /* @__PURE__ */ __name((inputTypes) => mapValues(inputTypes, normalizeInputType), "normalizeInputTypes");
820
-
821
- // src/preview-api/modules/store/csf/normalizeStory.ts
822
- import { deprecate, logger as logger3 } from "storybook/internal/client-logger";
823
- import { storyNameFromExport, toId } from "storybook/internal/csf";
824
-
825
- // src/preview-api/modules/store/csf/normalizeArrays.ts
826
- var normalizeArrays = /* @__PURE__ */ __name((array) => {
827
- if (Array.isArray(array)) {
828
- return array;
829
- }
830
- return array ? [array] : [];
831
- }, "normalizeArrays");
832
-
833
- // src/preview-api/modules/store/csf/normalizeStory.ts
834
- var deprecatedStoryAnnotation = dedent`
835
- CSF .story annotations deprecated; annotate story functions directly:
836
- - StoryFn.story.name => StoryFn.storyName
837
- - StoryFn.story.(parameters|decorators) => StoryFn.(parameters|decorators)
838
- See https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#hoisted-csf-annotations for details and codemod.
839
- `;
840
- function normalizeStory(key, storyAnnotations, meta) {
841
- const storyObject = storyAnnotations;
842
- const userStoryFn = typeof storyAnnotations === "function" ? storyAnnotations : null;
843
- const { story } = storyObject;
844
- if (story) {
845
- logger3.debug("deprecated story", story);
846
- deprecate(deprecatedStoryAnnotation);
847
- }
848
- const exportName = storyNameFromExport(key);
849
- const name = typeof storyObject !== "function" && storyObject.name || storyObject.storyName || story?.name || exportName;
850
- const decorators = [
851
- ...normalizeArrays(storyObject.decorators),
852
- ...normalizeArrays(story?.decorators)
853
- ];
854
- const parameters = { ...story?.parameters, ...storyObject.parameters };
855
- const args = { ...story?.args, ...storyObject.args };
856
- const argTypes = { ...story?.argTypes, ...storyObject.argTypes };
857
- const loaders = [...normalizeArrays(storyObject.loaders), ...normalizeArrays(story?.loaders)];
858
- const beforeEach = [
859
- ...normalizeArrays(storyObject.beforeEach),
860
- ...normalizeArrays(story?.beforeEach)
861
- ];
862
- const afterEach = [
863
- ...normalizeArrays(storyObject.afterEach),
864
- ...normalizeArrays(story?.afterEach)
865
- ];
866
- const { render, play, tags = [], globals = {} } = storyObject;
867
- const id = parameters.__id || toId(meta.id, exportName);
868
- return {
869
- moduleExport: storyAnnotations,
870
- id,
871
- name,
872
- tags,
873
- decorators,
874
- parameters,
875
- args,
876
- argTypes: normalizeInputTypes(argTypes),
877
- loaders,
878
- beforeEach,
879
- afterEach,
880
- globals,
881
- ...render && { render },
882
- ...userStoryFn && { userStoryFn },
883
- ...play && { play }
884
- };
885
- }
886
- __name(normalizeStory, "normalizeStory");
887
-
888
- // src/preview-api/modules/store/csf/processCSFFile.ts
889
- import { logger as logger4 } from "storybook/internal/client-logger";
890
- import { getStoryChildren, isExportStory, isStory, toTestId } from "storybook/internal/csf";
891
-
892
- // src/preview-api/modules/store/csf/normalizeComponentAnnotations.ts
893
- import { sanitize } from "storybook/internal/csf";
894
- function normalizeComponentAnnotations(defaultExport, title = defaultExport.title, importPath) {
895
- const { id, argTypes } = defaultExport;
896
- return {
897
- id: sanitize(id || title),
898
- ...defaultExport,
899
- title,
900
- ...argTypes && { argTypes: normalizeInputTypes(argTypes) },
901
- parameters: {
902
- fileName: importPath,
903
- ...defaultExport.parameters
904
- }
905
- };
906
- }
907
- __name(normalizeComponentAnnotations, "normalizeComponentAnnotations");
908
-
909
- // src/preview-api/modules/store/csf/processCSFFile.ts
910
- var checkGlobals = /* @__PURE__ */ __name((parameters) => {
911
- const { globals, globalTypes } = parameters;
912
- if (globals || globalTypes) {
913
- logger4.error(
914
- "Global args/argTypes can only be set globally",
915
- JSON.stringify({
916
- globals,
917
- globalTypes
918
- })
919
- );
920
- }
921
- }, "checkGlobals");
922
- var checkStorySort = /* @__PURE__ */ __name((parameters) => {
923
- const { options } = parameters;
924
- if (options?.storySort) {
925
- logger4.error("The storySort option parameter can only be set globally");
926
- }
927
- }, "checkStorySort");
928
- var checkDisallowedParameters = /* @__PURE__ */ __name((parameters) => {
929
- if (!parameters) {
930
- return;
931
- }
932
- checkGlobals(parameters);
933
- checkStorySort(parameters);
934
- }, "checkDisallowedParameters");
935
- function processCSFFile(moduleExports, importPath, title) {
936
- const { default: defaultExport, __namedExportsOrder, ...namedExports } = moduleExports;
937
- const firstStory = Object.values(namedExports)[0];
938
- if (isStory(firstStory)) {
939
- const meta2 = normalizeComponentAnnotations(firstStory.meta.input, title, importPath);
940
- checkDisallowedParameters(meta2.parameters);
941
- const csfFile2 = { meta: meta2, stories: {}, moduleExports };
942
- Object.keys(namedExports).forEach((key) => {
943
- if (isExportStory(key, meta2)) {
944
- const story = namedExports[key];
945
- const storyMeta = normalizeStory(key, story.input, meta2);
946
- checkDisallowedParameters(storyMeta.parameters);
947
- csfFile2.stories[storyMeta.id] = storyMeta;
948
- getStoryChildren(story).forEach((child) => {
949
- const name = child.input.name;
950
- const childId = toTestId(storyMeta.id, name);
951
- child.input.parameters ??= {};
952
- child.input.parameters.__id = childId;
953
- csfFile2.stories[childId] = normalizeStory(name, child.input, meta2);
954
- });
955
- }
956
- });
957
- csfFile2.projectAnnotations = firstStory.meta.preview.composed;
958
- return csfFile2;
959
- }
960
- const meta = normalizeComponentAnnotations(
961
- defaultExport,
962
- title,
963
- importPath
964
- );
965
- checkDisallowedParameters(meta.parameters);
966
- const csfFile = { meta, stories: {}, moduleExports };
967
- Object.keys(namedExports).forEach((key) => {
968
- if (isExportStory(key, meta)) {
969
- const storyMeta = normalizeStory(key, namedExports[key], meta);
970
- checkDisallowedParameters(storyMeta.parameters);
971
- csfFile.stories[storyMeta.id] = storyMeta;
972
- }
973
- });
974
- return csfFile;
975
- }
976
- __name(processCSFFile, "processCSFFile");
977
-
978
- // src/preview-api/modules/store/csf/prepareStory.ts
979
- import { combineTags, includeConditionalArg } from "storybook/internal/csf";
980
- import { NoRenderFunctionError } from "storybook/internal/preview-errors";
981
- import { global as global3 } from "@storybook/global";
982
- import { global as globalThis2 } from "@storybook/global";
983
-
984
- // src/preview-api/modules/preview-web/render/mount-utils.ts
985
- function mountDestructured(playFunction) {
986
- return playFunction != null && getUsedProps(playFunction).includes("mount");
987
- }
988
- __name(mountDestructured, "mountDestructured");
989
- function getUsedProps(fn) {
990
- const match = fn.toString().match(/[^(]*\(([^)]*)/);
991
- if (!match) {
992
- return [];
993
- }
994
- const args = splitByComma(match[1]);
995
- if (!args.length) {
996
- return [];
997
- }
998
- const first = args[0];
999
- if (!(first.startsWith("{") && first.endsWith("}"))) {
1000
- return [];
1001
- }
1002
- const props = splitByComma(first.slice(1, -1).replace(/\s/g, "")).map((prop) => {
1003
- return prop.replace(/:.*|=.*/g, "");
1004
- });
1005
- return props;
1006
- }
1007
- __name(getUsedProps, "getUsedProps");
1008
- function splitByComma(s) {
1009
- const result = [];
1010
- const stack = [];
1011
- let start = 0;
1012
- for (let i = 0; i < s.length; i++) {
1013
- if (s[i] === "{" || s[i] === "[") {
1014
- stack.push(s[i] === "{" ? "}" : "]");
1015
- } else if (s[i] === stack[stack.length - 1]) {
1016
- stack.pop();
1017
- } else if (!stack.length && s[i] === ",") {
1018
- const token = s.substring(start, i).trim();
1019
- if (token) {
1020
- result.push(token);
1021
- }
1022
- start = i + 1;
1023
- }
1024
- }
1025
- const lastToken = s.substring(start).trim();
1026
- if (lastToken) {
1027
- result.push(lastToken);
1028
- }
1029
- return result;
1030
- }
1031
- __name(splitByComma, "splitByComma");
1032
-
1033
- // src/preview-api/modules/store/decorators.ts
1034
- function decorateStory(storyFn, decorator, bindWithContext) {
1035
- const boundStoryFunction = bindWithContext(storyFn);
1036
- return (context) => decorator(boundStoryFunction, context);
1037
- }
1038
- __name(decorateStory, "decorateStory");
1039
- function sanitizeStoryContextUpdate({
1040
- componentId,
1041
- title,
1042
- kind,
1043
- id,
1044
- name,
1045
- story,
1046
- parameters,
1047
- initialArgs,
1048
- argTypes,
1049
- ...update
1050
- } = {}) {
1051
- return update;
1052
- }
1053
- __name(sanitizeStoryContextUpdate, "sanitizeStoryContextUpdate");
1054
- function defaultDecorateStory(storyFn, decorators) {
1055
- const contextStore = {};
1056
- const bindWithContext = /* @__PURE__ */ __name((decoratedStoryFn) => (update) => {
1057
- if (!contextStore.value) {
1058
- throw new Error("Decorated function called without init");
1059
- }
1060
- contextStore.value = {
1061
- ...contextStore.value,
1062
- ...sanitizeStoryContextUpdate(update)
1063
- };
1064
- return decoratedStoryFn(contextStore.value);
1065
- }, "bindWithContext");
1066
- const decoratedWithContextStore = decorators.reduce(
1067
- (story, decorator) => decorateStory(story, decorator, bindWithContext),
1068
- storyFn
1069
- );
1070
- return (context) => {
1071
- contextStore.value = context;
1072
- return decoratedWithContextStore(context);
1073
- };
1074
- }
1075
- __name(defaultDecorateStory, "defaultDecorateStory");
1076
-
1077
- // src/preview-api/modules/store/csf/prepareStory.ts
1078
- function prepareStory(storyAnnotations, componentAnnotations, projectAnnotations) {
1079
- const { moduleExport, id, name } = storyAnnotations || {};
1080
- const partialAnnotations = preparePartialAnnotations(
1081
- storyAnnotations,
1082
- componentAnnotations,
1083
- projectAnnotations
1084
- );
1085
- const applyLoaders = /* @__PURE__ */ __name(async (context) => {
1086
- const loaded = {};
1087
- for (const loaders of [
1088
- normalizeArrays(projectAnnotations.loaders),
1089
- normalizeArrays(componentAnnotations.loaders),
1090
- normalizeArrays(storyAnnotations.loaders)
1091
- ]) {
1092
- if (context.abortSignal.aborted) {
1093
- return loaded;
1094
- }
1095
- const loadResults = await Promise.all(loaders.map((loader) => loader(context)));
1096
- Object.assign(loaded, ...loadResults);
1097
- }
1098
- return loaded;
1099
- }, "applyLoaders");
1100
- const applyBeforeEach = /* @__PURE__ */ __name(async (context) => {
1101
- const cleanupCallbacks = new Array();
1102
- for (const beforeEach of [
1103
- ...normalizeArrays(projectAnnotations.beforeEach),
1104
- ...normalizeArrays(componentAnnotations.beforeEach),
1105
- ...normalizeArrays(storyAnnotations.beforeEach)
1106
- ]) {
1107
- if (context.abortSignal.aborted) {
1108
- return cleanupCallbacks;
1109
- }
1110
- const cleanup = await beforeEach(context);
1111
- if (cleanup) {
1112
- cleanupCallbacks.push(cleanup);
1113
- }
1114
- }
1115
- return cleanupCallbacks;
1116
- }, "applyBeforeEach");
1117
- const applyAfterEach = /* @__PURE__ */ __name(async (context) => {
1118
- const reversedFinalizers = [
1119
- ...normalizeArrays(projectAnnotations.afterEach),
1120
- ...normalizeArrays(componentAnnotations.afterEach),
1121
- ...normalizeArrays(storyAnnotations.afterEach)
1122
- ].reverse();
1123
- for (const finalizer of reversedFinalizers) {
1124
- if (context.abortSignal.aborted) {
1125
- return;
1126
- }
1127
- await finalizer(context);
1128
- }
1129
- }, "applyAfterEach");
1130
- const undecoratedStoryFn = /* @__PURE__ */ __name((context) => context.originalStoryFn(context.args, context), "undecoratedStoryFn");
1131
- const { applyDecorators = defaultDecorateStory, runStep } = projectAnnotations;
1132
- const decorators = [
1133
- ...normalizeArrays(storyAnnotations?.decorators),
1134
- ...normalizeArrays(componentAnnotations?.decorators),
1135
- ...normalizeArrays(projectAnnotations?.decorators)
1136
- ];
1137
- const render = storyAnnotations?.userStoryFn || storyAnnotations?.render || componentAnnotations.render || projectAnnotations.render;
1138
- const decoratedStoryFn = applyHooks(applyDecorators)(undecoratedStoryFn, decorators);
1139
- const unboundStoryFn = /* @__PURE__ */ __name((context) => decoratedStoryFn(context), "unboundStoryFn");
1140
- const playFunction = storyAnnotations?.play ?? componentAnnotations?.play;
1141
- const usesMount = mountDestructured(playFunction);
1142
- if (!render && !usesMount) {
1143
- throw new NoRenderFunctionError({ id });
1144
- }
1145
- const defaultMount = /* @__PURE__ */ __name((context) => {
1146
- return async () => {
1147
- await context.renderToCanvas();
1148
- return context.canvas;
1149
- };
1150
- }, "defaultMount");
1151
- const mount = storyAnnotations.mount ?? componentAnnotations.mount ?? projectAnnotations.mount ?? defaultMount;
1152
- const testingLibraryRender = projectAnnotations.testingLibraryRender;
1153
- return {
1154
- storyGlobals: {},
1155
- ...partialAnnotations,
1156
- moduleExport,
1157
- id,
1158
- name,
1159
- story: name,
1160
- originalStoryFn: render,
1161
- undecoratedStoryFn,
1162
- unboundStoryFn,
1163
- applyLoaders,
1164
- applyBeforeEach,
1165
- applyAfterEach,
1166
- playFunction,
1167
- runStep,
1168
- mount,
1169
- testingLibraryRender,
1170
- renderToCanvas: projectAnnotations.renderToCanvas,
1171
- usesMount
1172
- };
1173
- }
1174
- __name(prepareStory, "prepareStory");
1175
- function prepareMeta(componentAnnotations, projectAnnotations, moduleExport) {
1176
- return {
1177
- ...preparePartialAnnotations(void 0, componentAnnotations, projectAnnotations),
1178
- moduleExport
1179
- };
1180
- }
1181
- __name(prepareMeta, "prepareMeta");
1182
- function preparePartialAnnotations(storyAnnotations, componentAnnotations, projectAnnotations) {
1183
- const defaultTags = ["dev", "test"];
1184
- const extraTags = globalThis2.DOCS_OPTIONS?.autodocs === true ? ["autodocs"] : [];
1185
- const overrideTags = storyAnnotations?.tags?.includes("test-fn") ? ["!autodocs"] : [];
1186
- const tags = combineTags(
1187
- ...defaultTags,
1188
- ...extraTags,
1189
- ...projectAnnotations.tags ?? [],
1190
- ...componentAnnotations.tags ?? [],
1191
- ...overrideTags,
1192
- ...storyAnnotations?.tags ?? []
1193
- );
1194
- const parameters = combineParameters(
1195
- projectAnnotations.parameters,
1196
- componentAnnotations.parameters,
1197
- storyAnnotations?.parameters
1198
- );
1199
- const { argTypesEnhancers = [], argsEnhancers = [] } = projectAnnotations;
1200
- const passedArgTypes = combineParameters(
1201
- projectAnnotations.argTypes,
1202
- componentAnnotations.argTypes,
1203
- storyAnnotations?.argTypes
1204
- );
1205
- if (storyAnnotations) {
1206
- const render = storyAnnotations?.userStoryFn || storyAnnotations?.render || componentAnnotations.render || projectAnnotations.render;
1207
- parameters.__isArgsStory = render && render.length > 0;
1208
- }
1209
- const passedArgs = {
1210
- ...projectAnnotations.args,
1211
- ...componentAnnotations.args,
1212
- ...storyAnnotations?.args
1213
- };
1214
- const storyGlobals = {
1215
- ...componentAnnotations.globals,
1216
- ...storyAnnotations?.globals
1217
- };
1218
- const contextForEnhancers = {
1219
- componentId: componentAnnotations.id,
1220
- title: componentAnnotations.title,
1221
- kind: componentAnnotations.title,
1222
- // Back compat
1223
- id: storyAnnotations?.id || componentAnnotations.id,
1224
- // if there's no story name, we create a fake one since enhancers expect a name
1225
- name: storyAnnotations?.name || "__meta",
1226
- story: storyAnnotations?.name || "__meta",
1227
- // Back compat
1228
- component: componentAnnotations.component,
1229
- subcomponents: componentAnnotations.subcomponents,
1230
- tags,
1231
- parameters,
1232
- initialArgs: passedArgs,
1233
- argTypes: passedArgTypes,
1234
- storyGlobals
1235
- };
1236
- contextForEnhancers.argTypes = argTypesEnhancers.reduce(
1237
- (accumulatedArgTypes, enhancer) => enhancer({ ...contextForEnhancers, argTypes: accumulatedArgTypes }),
1238
- contextForEnhancers.argTypes
1239
- );
1240
- const initialArgsBeforeEnhancers = { ...passedArgs };
1241
- contextForEnhancers.initialArgs = [...argsEnhancers].reduce(
1242
- (accumulatedArgs, enhancer) => ({
1243
- ...accumulatedArgs,
1244
- ...enhancer({
1245
- ...contextForEnhancers,
1246
- initialArgs: accumulatedArgs
1247
- })
1248
- }),
1249
- initialArgsBeforeEnhancers
1250
- );
1251
- const { name, story, ...withoutStoryIdentifiers } = contextForEnhancers;
1252
- return withoutStoryIdentifiers;
1253
- }
1254
- __name(preparePartialAnnotations, "preparePartialAnnotations");
1255
- function prepareContext(context) {
1256
- const { args: unmappedArgs } = context;
1257
- let targetedContext = {
1258
- ...context,
1259
- allArgs: void 0,
1260
- argsByTarget: void 0
1261
- };
1262
- if (global3.FEATURES?.argTypeTargetsV7) {
1263
- const argsByTarget = groupArgsByTarget(context);
1264
- targetedContext = {
1265
- ...context,
1266
- allArgs: context.args,
1267
- argsByTarget,
1268
- args: argsByTarget[UNTARGETED] || {}
1269
- };
1270
- }
1271
- const mappedArgs = Object.entries(targetedContext.args).reduce((acc, [key, val]) => {
1272
- if (!targetedContext.argTypes[key]?.mapping) {
1273
- acc[key] = val;
1274
- return acc;
1275
- }
1276
- const mappingFn = /* @__PURE__ */ __name((originalValue) => {
1277
- const mapping = targetedContext.argTypes[key].mapping;
1278
- return mapping && originalValue in mapping ? mapping[originalValue] : originalValue;
1279
- }, "mappingFn");
1280
- acc[key] = Array.isArray(val) ? val.map(mappingFn) : mappingFn(val);
1281
- return acc;
1282
- }, {});
1283
- const includedArgs = Object.entries(mappedArgs).reduce((acc, [key, val]) => {
1284
- const argType = targetedContext.argTypes[key] || {};
1285
- if (includeConditionalArg(argType, mappedArgs, targetedContext.globals)) {
1286
- acc[key] = val;
1287
- }
1288
- return acc;
1289
- }, {});
1290
- return { ...targetedContext, unmappedArgs, args: includedArgs };
1291
- }
1292
- __name(prepareContext, "prepareContext");
1293
-
1294
- // src/preview-api/modules/store/inferArgTypes.ts
1295
- import { logger as logger5 } from "storybook/internal/client-logger";
1296
- var inferType = /* @__PURE__ */ __name((value, name, visited) => {
1297
- const type = typeof value;
1298
- switch (type) {
1299
- case "boolean":
1300
- case "string":
1301
- case "number":
1302
- case "function":
1303
- case "symbol":
1304
- return { name: type };
1305
- default:
1306
- break;
1307
- }
1308
- if (value) {
1309
- if (visited.has(value)) {
1310
- logger5.warn(dedent`
1311
- We've detected a cycle in arg '${name}'. Args should be JSON-serializable.
1312
-
1313
- Consider using the mapping feature or fully custom args:
1314
- - Mapping: https://storybook.js.org/docs/writing-stories/args#mapping-to-complex-arg-values
1315
- - Custom args: https://storybook.js.org/docs/essentials/controls#fully-custom-args
1316
- `);
1317
- return { name: "other", value: "cyclic object" };
1318
- }
1319
- visited.add(value);
1320
- if (Array.isArray(value)) {
1321
- const childType = value.length > 0 ? inferType(value[0], name, new Set(visited)) : { name: "other", value: "unknown" };
1322
- return { name: "array", value: childType };
1323
- }
1324
- const fieldTypes = mapValues(value, (field) => inferType(field, name, new Set(visited)));
1325
- return { name: "object", value: fieldTypes };
1326
- }
1327
- return { name: "object", value: {} };
1328
- }, "inferType");
1329
- var inferArgTypes = /* @__PURE__ */ __name((context) => {
1330
- const { id, argTypes: userArgTypes = {}, initialArgs = {} } = context;
1331
- const argTypes = mapValues(initialArgs, (arg, key) => ({
1332
- name: key,
1333
- type: inferType(arg, `${id}.${key}`, /* @__PURE__ */ new Set())
1334
- }));
1335
- const userArgTypesNames = mapValues(userArgTypes, (argType, key) => ({
1336
- name: key
1337
- }));
1338
- return combineParameters(argTypes, userArgTypesNames, userArgTypes);
1339
- }, "inferArgTypes");
1340
- inferArgTypes.secondPass = true;
1341
-
1342
- // src/preview-api/modules/store/inferControls.ts
1343
- import { logger as logger6 } from "storybook/internal/client-logger";
1344
-
1345
- // src/preview-api/modules/store/filterArgTypes.ts
1346
- var matches = /* @__PURE__ */ __name((name, descriptor) => Array.isArray(descriptor) ? descriptor.includes(name) : name.match(descriptor), "matches");
1347
- var filterArgTypes = /* @__PURE__ */ __name((argTypes, include, exclude) => {
1348
- if (!include && !exclude) {
1349
- return argTypes;
1350
- }
1351
- return argTypes && pickBy(argTypes, (argType, key) => {
1352
- const name = argType.name || key.toString();
1353
- return !!(!include || matches(name, include)) && (!exclude || !matches(name, exclude));
1354
- });
1355
- }, "filterArgTypes");
1356
-
1357
- // src/preview-api/modules/store/inferControls.ts
1358
- var inferControl = /* @__PURE__ */ __name((argType, name, matchers) => {
1359
- const { type, options } = argType;
1360
- if (!type) {
1361
- return void 0;
1362
- }
1363
- if (matchers.color && matchers.color.test(name)) {
1364
- const controlType = type.name;
1365
- if (controlType === "string") {
1366
- return { control: { type: "color" } };
1367
- }
1368
- if (controlType !== "enum") {
1369
- logger6.warn(
1370
- `Addon controls: Control of type color only supports string, received "${controlType}" instead`
1371
- );
1372
- }
1373
- }
1374
- if (matchers.date && matchers.date.test(name)) {
1375
- return { control: { type: "date" } };
1376
- }
1377
- switch (type.name) {
1378
- case "array":
1379
- return { control: { type: "object" } };
1380
- case "boolean":
1381
- return { control: { type: "boolean" } };
1382
- case "string":
1383
- return { control: { type: "text" } };
1384
- case "number":
1385
- return { control: { type: "number" } };
1386
- case "enum": {
1387
- const { value } = type;
1388
- return { control: { type: value?.length <= 5 ? "radio" : "select" }, options: value };
1389
- }
1390
- case "function":
1391
- case "symbol":
1392
- return null;
1393
- default:
1394
- return { control: { type: options ? "select" : "object" } };
1395
- }
1396
- }, "inferControl");
1397
- var inferControls = /* @__PURE__ */ __name((context) => {
1398
- const {
1399
- argTypes,
1400
- parameters: { __isArgsStory, controls: { include = null, exclude = null, matchers = {} } = {} }
1401
- } = context;
1402
- if (!__isArgsStory) {
1403
- return argTypes;
1404
- }
1405
- const filteredArgTypes = filterArgTypes(argTypes, include, exclude);
1406
- const withControls = mapValues(filteredArgTypes, (argType, name) => {
1407
- return argType?.type && inferControl(argType, name.toString(), matchers);
1408
- });
1409
- return combineParameters(withControls, filteredArgTypes);
1410
- }, "inferControls");
1411
- inferControls.secondPass = true;
1412
-
1413
- // src/preview-api/modules/store/csf/normalizeProjectAnnotations.ts
1414
- function normalizeProjectAnnotations({
1415
- argTypes,
1416
- globalTypes,
1417
- argTypesEnhancers,
1418
- decorators,
1419
- loaders,
1420
- beforeEach,
1421
- afterEach,
1422
- initialGlobals,
1423
- ...annotations
1424
- }) {
1425
- return {
1426
- ...argTypes && { argTypes: normalizeInputTypes(argTypes) },
1427
- ...globalTypes && { globalTypes: normalizeInputTypes(globalTypes) },
1428
- decorators: normalizeArrays(decorators),
1429
- loaders: normalizeArrays(loaders),
1430
- beforeEach: normalizeArrays(beforeEach),
1431
- afterEach: normalizeArrays(afterEach),
1432
- argTypesEnhancers: [
1433
- ...argTypesEnhancers || [],
1434
- inferArgTypes,
1435
- // There's an architectural decision to be made regarding embedded addons in core:
1436
- //
1437
- // Option 1: Keep embedded addons but ensure consistency by moving addon-specific code
1438
- // (like inferControls) to live alongside the addon code itself. This maintains the
1439
- // concept of core addons while improving code organization.
1440
- //
1441
- // Option 2: Fully integrate these addons into core, potentially moving UI components
1442
- // into the manager and treating them as core features rather than addons. This is a
1443
- // bigger architectural change requiring careful consideration.
1444
- //
1445
- // For now, we're keeping inferControls here as we need time to properly evaluate
1446
- // these options and their implications. Some features (like Angular's cleanArgsDecorator)
1447
- // currently rely on this behavior.
1448
- //
1449
- // TODO: Make an architectural decision on the handling of core addons
1450
- inferControls
1451
- ],
1452
- initialGlobals,
1453
- ...annotations
1454
- };
1455
- }
1456
- __name(normalizeProjectAnnotations, "normalizeProjectAnnotations");
1457
-
1458
- // src/preview-api/modules/store/csf/composeConfigs.ts
1459
- import { global as global4 } from "@storybook/global";
1460
-
1461
- // src/preview-api/modules/store/csf/beforeAll.ts
1462
- var composeBeforeAllHooks = /* @__PURE__ */ __name((hooks) => {
1463
- return async () => {
1464
- const cleanups2 = [];
1465
- for (const hook of hooks) {
1466
- const cleanup = await hook();
1467
- if (cleanup) {
1468
- cleanups2.unshift(cleanup);
1469
- }
1470
- }
1471
- return async () => {
1472
- for (const cleanup of cleanups2) {
1473
- await cleanup();
1474
- }
1475
- };
1476
- };
1477
- }, "composeBeforeAllHooks");
1478
-
1479
- // src/preview-api/modules/store/csf/stepRunners.ts
1480
- function composeStepRunners(stepRunners) {
1481
- return async (label, play, playContext) => {
1482
- const composedPlay = stepRunners.reduceRight(
1483
- (innerPlay, stepRunner) => async () => stepRunner(label, innerPlay, playContext),
1484
- async () => play(playContext)
1485
- );
1486
- await composedPlay();
1487
- };
1488
- }
1489
- __name(composeStepRunners, "composeStepRunners");
1490
-
1491
- // src/preview-api/modules/store/csf/composeConfigs.ts
1492
- function getField(moduleExportList, field) {
1493
- return moduleExportList.map((xs) => xs.default?.[field] ?? xs[field]).filter(Boolean);
1494
- }
1495
- __name(getField, "getField");
1496
- function getArrayField(moduleExportList, field, options = {}) {
1497
- return getField(moduleExportList, field).reduce((prev, cur) => {
1498
- const normalized = normalizeArrays(cur);
1499
- return options.reverseFileOrder ? [...normalized, ...prev] : [...prev, ...normalized];
1500
- }, []);
1501
- }
1502
- __name(getArrayField, "getArrayField");
1503
- function getObjectField(moduleExportList, field) {
1504
- return Object.assign({}, ...getField(moduleExportList, field));
1505
- }
1506
- __name(getObjectField, "getObjectField");
1507
- function getSingletonField(moduleExportList, field) {
1508
- return getField(moduleExportList, field).pop();
1509
- }
1510
- __name(getSingletonField, "getSingletonField");
1511
- function composeConfigs(moduleExportList) {
1512
- const allArgTypeEnhancers = getArrayField(moduleExportList, "argTypesEnhancers");
1513
- const stepRunners = getField(moduleExportList, "runStep");
1514
- const beforeAllHooks = getArrayField(moduleExportList, "beforeAll");
1515
- return {
1516
- parameters: combineParameters(...getField(moduleExportList, "parameters")),
1517
- decorators: getArrayField(moduleExportList, "decorators", {
1518
- reverseFileOrder: !(global4.FEATURES?.legacyDecoratorFileOrder ?? false)
1519
- }),
1520
- args: getObjectField(moduleExportList, "args"),
1521
- argsEnhancers: getArrayField(moduleExportList, "argsEnhancers"),
1522
- argTypes: getObjectField(moduleExportList, "argTypes"),
1523
- argTypesEnhancers: [
1524
- ...allArgTypeEnhancers.filter((e) => !e.secondPass),
1525
- ...allArgTypeEnhancers.filter((e) => e.secondPass)
1526
- ],
1527
- initialGlobals: getObjectField(moduleExportList, "initialGlobals"),
1528
- globalTypes: getObjectField(moduleExportList, "globalTypes"),
1529
- loaders: getArrayField(moduleExportList, "loaders"),
1530
- beforeAll: composeBeforeAllHooks(beforeAllHooks),
1531
- beforeEach: getArrayField(moduleExportList, "beforeEach"),
1532
- afterEach: getArrayField(moduleExportList, "afterEach"),
1533
- render: getSingletonField(moduleExportList, "render"),
1534
- renderToCanvas: getSingletonField(moduleExportList, "renderToCanvas"),
1535
- applyDecorators: getSingletonField(moduleExportList, "applyDecorators"),
1536
- runStep: composeStepRunners(stepRunners),
1537
- tags: getArrayField(moduleExportList, "tags"),
1538
- mount: getSingletonField(moduleExportList, "mount"),
1539
- testingLibraryRender: getSingletonField(moduleExportList, "testingLibraryRender")
1540
- };
1541
- }
1542
- __name(composeConfigs, "composeConfigs");
1543
-
1544
- // src/preview-api/modules/store/csf/portable-stories.ts
1545
- import { isExportStory as isExportStory2 } from "storybook/internal/csf";
1546
- import { getCoreAnnotations } from "storybook/internal/csf";
1547
- import { MountMustBeDestructuredError } from "storybook/internal/preview-errors";
1548
-
1549
- // src/preview-api/modules/store/reporter-api.ts
1550
- var _ReporterAPI = class _ReporterAPI {
1551
- constructor() {
1552
- this.reports = [];
1553
- }
1554
- async addReport(report) {
1555
- this.reports.push(report);
1556
- }
1557
- };
1558
- __name(_ReporterAPI, "ReporterAPI");
1559
- var ReporterAPI = _ReporterAPI;
1560
-
1561
- // src/preview-api/modules/store/csf/csf-factory-utils.ts
1562
- import { isMeta, isStory as isStory2 } from "storybook/internal/csf";
1563
- function getCsfFactoryAnnotations(story, meta, projectAnnotations) {
1564
- return isStory2(story) ? {
1565
- story: story.input,
1566
- meta: story.meta.input,
1567
- preview: story.meta.preview.composed
1568
- } : { story, meta: isMeta(meta) ? meta.input : meta, preview: projectAnnotations };
1569
- }
1570
- __name(getCsfFactoryAnnotations, "getCsfFactoryAnnotations");
1571
-
1572
- // src/preview-api/modules/store/csf/portable-stories.ts
1573
- function setDefaultProjectAnnotations(_defaultProjectAnnotations) {
1574
- globalThis.defaultProjectAnnotations = _defaultProjectAnnotations;
1575
- }
1576
- __name(setDefaultProjectAnnotations, "setDefaultProjectAnnotations");
1577
- var DEFAULT_STORY_TITLE = "ComposedStory";
1578
- var DEFAULT_STORY_NAME = "Unnamed Story";
1579
- function extractAnnotation(annotation) {
1580
- if (!annotation) {
1581
- return {};
1582
- }
1583
- return composeConfigs([annotation]);
1584
- }
1585
- __name(extractAnnotation, "extractAnnotation");
1586
- function setProjectAnnotations(projectAnnotations) {
1587
- const annotations = Array.isArray(projectAnnotations) ? projectAnnotations : [projectAnnotations];
1588
- globalThis.globalProjectAnnotations = composeConfigs([
1589
- ...getCoreAnnotations(),
1590
- globalThis.defaultProjectAnnotations ?? {},
1591
- composeConfigs(annotations.map(extractAnnotation))
1592
- ]);
1593
- return globalThis.globalProjectAnnotations ?? {};
1594
- }
1595
- __name(setProjectAnnotations, "setProjectAnnotations");
1596
- var cleanups = [];
1597
- function composeStory(storyAnnotations, componentAnnotations, projectAnnotations, defaultConfig, exportsName) {
1598
- if (storyAnnotations === void 0) {
1599
- throw new Error("Expected a story but received undefined.");
1600
- }
1601
- componentAnnotations.title = componentAnnotations.title ?? DEFAULT_STORY_TITLE;
1602
- const normalizedComponentAnnotations = normalizeComponentAnnotations(componentAnnotations);
1603
- const storyName = exportsName || storyAnnotations.storyName || storyAnnotations.story?.name || storyAnnotations.name || DEFAULT_STORY_NAME;
1604
- const normalizedStory = normalizeStory(
1605
- storyName,
1606
- storyAnnotations,
1607
- normalizedComponentAnnotations
1608
- );
1609
- const normalizedProjectAnnotations = normalizeProjectAnnotations(
1610
- composeConfigs([
1611
- defaultConfig ?? globalThis.globalProjectAnnotations ?? {},
1612
- projectAnnotations ?? {}
1613
- ])
1614
- );
1615
- const story = prepareStory(
1616
- normalizedStory,
1617
- normalizedComponentAnnotations,
1618
- normalizedProjectAnnotations
1619
- );
1620
- const globalsFromGlobalTypes = getValuesFromArgTypes(normalizedProjectAnnotations.globalTypes);
1621
- const globals = {
1622
- ...globalsFromGlobalTypes,
1623
- ...normalizedProjectAnnotations.initialGlobals,
1624
- ...story.storyGlobals
1625
- };
1626
- const reporting = new ReporterAPI();
1627
- const initializeContext = /* @__PURE__ */ __name(() => {
1628
- const context = prepareContext({
1629
- hooks: new HooksContext(),
1630
- globals,
1631
- args: { ...story.initialArgs },
1632
- viewMode: "story",
1633
- reporting,
1634
- loaded: {},
1635
- abortSignal: new AbortController().signal,
1636
- step: /* @__PURE__ */ __name((label, play2) => story.runStep(label, play2, context), "step"),
1637
- canvasElement: null,
1638
- canvas: {},
1639
- userEvent: {},
1640
- globalTypes: normalizedProjectAnnotations.globalTypes,
1641
- ...story,
1642
- context: null,
1643
- mount: null
1644
- });
1645
- context.parameters.__isPortableStory = true;
1646
- context.context = context;
1647
- if (story.renderToCanvas) {
1648
- context.renderToCanvas = async () => {
1649
- const unmount = await story.renderToCanvas?.(
1650
- {
1651
- componentId: story.componentId,
1652
- title: story.title,
1653
- id: story.id,
1654
- name: story.name,
1655
- tags: story.tags,
1656
- showMain: /* @__PURE__ */ __name(() => {
1657
- }, "showMain"),
1658
- showError: /* @__PURE__ */ __name((error) => {
1659
- throw new Error(`${error.title}
1660
- ${error.description}`);
1661
- }, "showError"),
1662
- showException: /* @__PURE__ */ __name((error) => {
1663
- throw error;
1664
- }, "showException"),
1665
- forceRemount: true,
1666
- storyContext: context,
1667
- storyFn: /* @__PURE__ */ __name(() => story.unboundStoryFn(context), "storyFn"),
1668
- unboundStoryFn: story.unboundStoryFn
1669
- },
1670
- context.canvasElement
1671
- );
1672
- if (unmount) {
1673
- cleanups.push(unmount);
1674
- }
1675
- };
1676
- }
1677
- context.mount = story.mount(context);
1678
- return context;
1679
- }, "initializeContext");
1680
- let loadedContext;
1681
- const play = /* @__PURE__ */ __name(async (extraContext) => {
1682
- const context = initializeContext();
1683
- context.canvasElement ??= globalThis?.document?.body;
1684
- if (loadedContext) {
1685
- context.loaded = loadedContext.loaded;
1686
- }
1687
- Object.assign(context, extraContext);
1688
- return story.playFunction(context);
1689
- }, "play");
1690
- const run = /* @__PURE__ */ __name((extraContext) => {
1691
- const context = initializeContext();
1692
- Object.assign(context, extraContext);
1693
- return runStory(story, context);
1694
- }, "run");
1695
- const playFunction = story.playFunction ? play : void 0;
1696
- const composedStory = Object.assign(
1697
- /* @__PURE__ */ __name(function storyFn(extraArgs) {
1698
- const context = initializeContext();
1699
- if (loadedContext) {
1700
- context.loaded = loadedContext.loaded;
1701
- }
1702
- context.args = {
1703
- ...context.initialArgs,
1704
- ...extraArgs
1705
- };
1706
- return story.unboundStoryFn(context);
1707
- }, "storyFn"),
1708
- {
1709
- id: story.id,
1710
- storyName,
1711
- load: /* @__PURE__ */ __name(async () => {
1712
- for (const callback of [...cleanups].reverse()) {
1713
- await callback();
1714
- }
1715
- cleanups.length = 0;
1716
- const context = initializeContext();
1717
- context.loaded = await story.applyLoaders(context);
1718
- cleanups.push(...(await story.applyBeforeEach(context)).filter(Boolean));
1719
- loadedContext = context;
1720
- }, "load"),
1721
- globals,
1722
- args: story.initialArgs,
1723
- parameters: story.parameters,
1724
- argTypes: story.argTypes,
1725
- play: playFunction,
1726
- run,
1727
- reporting,
1728
- tags: story.tags
1729
- }
1730
- );
1731
- return composedStory;
1732
- }
1733
- __name(composeStory, "composeStory");
1734
- var defaultComposeStory = /* @__PURE__ */ __name((story, component, project, exportsName) => composeStory(story, component, project, {}, exportsName), "defaultComposeStory");
1735
- function composeStories(storiesImport, globalConfig, composeStoryFn = defaultComposeStory) {
1736
- const { default: metaExport, __esModule, __namedExportsOrder, ...stories } = storiesImport;
1737
- let meta = metaExport;
1738
- const composedStories = Object.entries(stories).reduce(
1739
- (storiesMap, [exportsName, story]) => {
1740
- const { story: storyAnnotations, meta: componentAnnotations } = getCsfFactoryAnnotations(story);
1741
- if (!meta && componentAnnotations) {
1742
- meta = componentAnnotations;
1743
- }
1744
- if (!isExportStory2(exportsName, meta)) {
1745
- return storiesMap;
1746
- }
1747
- const result = Object.assign(storiesMap, {
1748
- [exportsName]: composeStoryFn(storyAnnotations, meta, globalConfig, exportsName)
1749
- });
1750
- return result;
1751
- },
1752
- {}
1753
- );
1754
- return composedStories;
1755
- }
1756
- __name(composeStories, "composeStories");
1757
- function createPlaywrightTest(baseTest) {
1758
- return baseTest.extend({
1759
- mount: /* @__PURE__ */ __name(async ({ mount, page }, use) => {
1760
- await use(async (storyRef, ...restArgs) => {
1761
- if (!("__pw_type" in storyRef) || "__pw_type" in storyRef && storyRef.__pw_type !== "jsx") {
1762
- throw new Error(dedent`
1763
- Portable stories in Playwright CT only work when referencing JSX elements.
1764
- Please use JSX format for your components such as:
1765
-
1766
- instead of:
1767
- await mount(MyComponent, { props: { foo: 'bar' } })
1768
-
1769
- do:
1770
- await mount(<MyComponent foo="bar"/>)
1771
-
1772
- More info: https://storybook.js.org/docs/api/portable-stories/portable-stories-playwright?ref=error
1773
- `);
1774
- }
1775
- const { props, ...storyRefWithoutProps } = storyRef;
1776
- await page.evaluate(async (wrappedStoryRef) => {
1777
- const unwrappedStoryRef = await globalThis.__pwUnwrapObject?.(wrappedStoryRef);
1778
- const story = "__pw_type" in unwrappedStoryRef ? unwrappedStoryRef.type : unwrappedStoryRef;
1779
- return story?.load?.();
1780
- }, storyRefWithoutProps);
1781
- const mountResult = await mount(storyRef, ...restArgs);
1782
- await page.evaluate(async (wrappedStoryRef) => {
1783
- const unwrappedStoryRef = await globalThis.__pwUnwrapObject?.(wrappedStoryRef);
1784
- const story = "__pw_type" in unwrappedStoryRef ? unwrappedStoryRef.type : unwrappedStoryRef;
1785
- const canvasElement = document.querySelector("#root");
1786
- return story?.play?.({ canvasElement });
1787
- }, storyRefWithoutProps);
1788
- return mountResult;
1789
- });
1790
- }, "mount")
1791
- });
1792
- }
1793
- __name(createPlaywrightTest, "createPlaywrightTest");
1794
- async function runStory(story, context) {
1795
- for (const callback of [...cleanups].reverse()) {
1796
- await callback();
1797
- }
1798
- cleanups.length = 0;
1799
- if (!context.canvasElement) {
1800
- const container = document.createElement("div");
1801
- globalThis?.document?.body?.appendChild(container);
1802
- context.canvasElement = container;
1803
- cleanups.push(() => {
1804
- if (globalThis?.document?.body?.contains(container)) {
1805
- globalThis?.document?.body?.removeChild(container);
1806
- }
1807
- });
1808
- }
1809
- context.loaded = await story.applyLoaders(context);
1810
- if (context.abortSignal.aborted) {
1811
- return;
1812
- }
1813
- cleanups.push(...(await story.applyBeforeEach(context)).filter(Boolean));
1814
- const playFunction = story.playFunction;
1815
- const isMountDestructured = story.usesMount;
1816
- if (!isMountDestructured) {
1817
- await context.mount();
1818
- }
1819
- if (context.abortSignal.aborted) {
1820
- return;
1821
- }
1822
- if (playFunction) {
1823
- if (!isMountDestructured) {
1824
- context.mount = async () => {
1825
- throw new MountMustBeDestructuredError({ playFunction: playFunction.toString() });
1826
- };
1827
- }
1828
- await playFunction(context);
1829
- }
1830
- let cleanUp;
1831
- if (isTestEnvironment()) {
1832
- cleanUp = pauseAnimations();
1833
- } else {
1834
- await waitForAnimations(context.abortSignal);
1835
- }
1836
- await story.applyAfterEach(context);
1837
- await cleanUp?.();
1838
- }
1839
- __name(runStory, "runStory");
1840
-
1841
- // src/preview-api/modules/store/StoryStore.ts
1842
- var CSF_CACHE_SIZE = 1e3;
1843
- var STORY_CACHE_SIZE = 1e4;
1844
- var _StoryStore = class _StoryStore {
1845
- constructor(storyIndex, importFn, projectAnnotations) {
1846
- this.importFn = importFn;
1847
- this.storyIndex = new StoryIndexStore(storyIndex);
1848
- this.projectAnnotations = normalizeProjectAnnotations(
1849
- composeConfigs([...getCoreAnnotations2(), projectAnnotations])
1850
- );
1851
- const { initialGlobals, globalTypes } = this.projectAnnotations;
1852
- this.args = new ArgsStore();
1853
- this.userGlobals = new GlobalsStore({ globals: initialGlobals, globalTypes });
1854
- this.hooks = {};
1855
- this.cleanupCallbacks = {};
1856
- this.processCSFFileWithCache = (0, import_memoizerific2.default)(CSF_CACHE_SIZE)(processCSFFile);
1857
- this.prepareMetaWithCache = (0, import_memoizerific2.default)(CSF_CACHE_SIZE)(prepareMeta);
1858
- this.prepareStoryWithCache = (0, import_memoizerific2.default)(STORY_CACHE_SIZE)(prepareStory);
1859
- }
1860
- setProjectAnnotations(projectAnnotations) {
1861
- this.projectAnnotations = normalizeProjectAnnotations(projectAnnotations);
1862
- const { initialGlobals, globalTypes } = projectAnnotations;
1863
- this.userGlobals.set({ globals: initialGlobals, globalTypes });
1864
- }
1865
- // This means that one of the CSF files has changed.
1866
- // If the `importFn` has changed, we will invalidate both caches.
1867
- // If the `storyIndex` data has changed, we may or may not invalidate the caches, depending
1868
- // on whether we've loaded the relevant files yet.
1869
- async onStoriesChanged({
1870
- importFn,
1871
- storyIndex
1872
- }) {
1873
- if (importFn) {
1874
- this.importFn = importFn;
1875
- }
1876
- if (storyIndex) {
1877
- this.storyIndex.entries = storyIndex.entries;
1878
- }
1879
- if (this.cachedCSFFiles) {
1880
- await this.cacheAllCSFFiles();
1881
- }
1882
- }
1883
- // Get an entry from the index, waiting on initialization if necessary
1884
- async storyIdToEntry(storyId) {
1885
- return this.storyIndex.storyIdToEntry(storyId);
1886
- }
1887
- // To load a single CSF file to service a story we need to look up the importPath in the index
1888
- async loadCSFFileByStoryId(storyId) {
1889
- const { importPath, title } = this.storyIndex.storyIdToEntry(storyId);
1890
- const moduleExports = await this.importFn(importPath);
1891
- return this.processCSFFileWithCache(moduleExports, importPath, title);
1892
- }
1893
- async loadAllCSFFiles() {
1894
- const importPaths = {};
1895
- Object.entries(this.storyIndex.entries).forEach(([storyId, { importPath }]) => {
1896
- importPaths[importPath] = storyId;
1897
- });
1898
- const list = await Promise.all(
1899
- Object.entries(importPaths).map(async ([importPath, storyId]) => ({
1900
- importPath,
1901
- csfFile: await this.loadCSFFileByStoryId(storyId)
1902
- }))
1903
- );
1904
- return list.reduce(
1905
- (acc, { importPath, csfFile }) => {
1906
- acc[importPath] = csfFile;
1907
- return acc;
1908
- },
1909
- {}
1910
- );
1911
- }
1912
- async cacheAllCSFFiles() {
1913
- this.cachedCSFFiles = await this.loadAllCSFFiles();
1914
- }
1915
- preparedMetaFromCSFFile({ csfFile }) {
1916
- const componentAnnotations = csfFile.meta;
1917
- return this.prepareMetaWithCache(
1918
- componentAnnotations,
1919
- this.projectAnnotations,
1920
- csfFile.moduleExports.default
1921
- );
1922
- }
1923
- // Load the CSF file for a story and prepare the story from it and the project annotations.
1924
- async loadStory({ storyId }) {
1925
- const csfFile = await this.loadCSFFileByStoryId(storyId);
1926
- return this.storyFromCSFFile({ storyId, csfFile });
1927
- }
1928
- // This function is synchronous for convenience -- often times if you have a CSF file already
1929
- // it is easier not to have to await `loadStory`.
1930
- storyFromCSFFile({
1931
- storyId,
1932
- csfFile
1933
- }) {
1934
- const storyAnnotations = csfFile.stories[storyId];
1935
- if (!storyAnnotations) {
1936
- throw new MissingStoryFromCsfFileError({ storyId });
1937
- }
1938
- const componentAnnotations = csfFile.meta;
1939
- const story = this.prepareStoryWithCache(
1940
- storyAnnotations,
1941
- componentAnnotations,
1942
- csfFile.projectAnnotations ?? this.projectAnnotations
1943
- );
1944
- this.args.setInitial(story);
1945
- this.hooks[story.id] = this.hooks[story.id] || new HooksContext();
1946
- return story;
1947
- }
1948
- // If we have a CSF file we can get all the stories from it synchronously
1949
- componentStoriesFromCSFFile({
1950
- csfFile
1951
- }) {
1952
- return Object.keys(this.storyIndex.entries).filter((storyId) => !!csfFile.stories[storyId]).map((storyId) => this.storyFromCSFFile({ storyId, csfFile }));
1953
- }
1954
- async loadEntry(id) {
1955
- const entry = await this.storyIdToEntry(id);
1956
- const storyImports = entry.type === "docs" ? entry.storiesImports : [];
1957
- const [entryExports, ...csfFiles] = await Promise.all([
1958
- this.importFn(entry.importPath),
1959
- ...storyImports.map((storyImportPath) => {
1960
- const firstStoryEntry = this.storyIndex.importPathToEntry(storyImportPath);
1961
- return this.loadCSFFileByStoryId(firstStoryEntry.id);
1962
- })
1963
- ]);
1964
- return { entryExports, csfFiles };
1965
- }
1966
- // A prepared story does not include args, globals or hooks. These are stored in the story store
1967
- // and updated separately to the (immutable) story.
1968
- getStoryContext(story, { forceInitialArgs = false } = {}) {
1969
- const userGlobals = this.userGlobals.get();
1970
- const { initialGlobals } = this.userGlobals;
1971
- const reporting = new ReporterAPI();
1972
- return prepareContext({
1973
- ...story,
1974
- args: forceInitialArgs ? story.initialArgs : this.args.get(story.id),
1975
- initialGlobals,
1976
- globalTypes: this.projectAnnotations.globalTypes,
1977
- userGlobals,
1978
- reporting,
1979
- globals: {
1980
- ...userGlobals,
1981
- ...story.storyGlobals
1982
- },
1983
- hooks: this.hooks[story.id]
1984
- });
1985
- }
1986
- addCleanupCallbacks(story, ...callbacks) {
1987
- this.cleanupCallbacks[story.id] = (this.cleanupCallbacks[story.id] || []).concat(callbacks);
1988
- }
1989
- async cleanupStory(story) {
1990
- this.hooks[story.id].clean();
1991
- const callbacks = this.cleanupCallbacks[story.id];
1992
- if (callbacks) {
1993
- for (const callback of [...callbacks].reverse()) {
1994
- await callback();
1995
- }
1996
- }
1997
- delete this.cleanupCallbacks[story.id];
1998
- }
1999
- extract(options = { includeDocsOnly: false }) {
2000
- const { cachedCSFFiles } = this;
2001
- console.log("extract: extracting stories", cachedCSFFiles);
2002
- if (!cachedCSFFiles) {
2003
- throw new CalledExtractOnStoreError();
2004
- }
2005
- const stories = Object.entries(this.storyIndex.entries).reduce(
2006
- (acc, [storyId, entry]) => {
2007
- if (entry.type === "docs") {
2008
- return acc;
2009
- }
2010
- const csfFile = cachedCSFFiles[entry.importPath];
2011
- const story = this.storyFromCSFFile({ storyId, csfFile });
2012
- if (!options.includeDocsOnly && story.parameters.docsOnly) {
2013
- return acc;
2014
- }
2015
- acc[storyId] = Object.entries(story).reduce(
2016
- (storyAcc, [key, value]) => {
2017
- if (key === "story" && entry.subtype === "test") {
2018
- return { ...storyAcc, story: entry.parentName };
2019
- }
2020
- if (key === "moduleExport") {
2021
- return storyAcc;
2022
- }
2023
- if (typeof value === "function") {
2024
- return storyAcc;
2025
- }
2026
- if (Array.isArray(value)) {
2027
- return Object.assign(storyAcc, { [key]: value.slice().sort() });
2028
- }
2029
- return Object.assign(storyAcc, { [key]: value });
2030
- },
2031
- {
2032
- args: story.initialArgs,
2033
- globals: {
2034
- ...this.userGlobals.initialGlobals,
2035
- ...this.userGlobals.globals,
2036
- ...story.storyGlobals
2037
- },
2038
- storyId: entry.parent ? entry.parent : storyId
2039
- }
2040
- );
2041
- return acc;
2042
- },
2043
- {}
2044
- );
2045
- console.log("extract: stories", stories);
2046
- return stories;
2047
- }
2048
- };
2049
- __name(_StoryStore, "StoryStore");
2050
- var StoryStore = _StoryStore;
2051
-
2052
- // src/preview-api/modules/store/autoTitle.ts
2053
- import { once as once2 } from "storybook/internal/client-logger";
2054
-
2055
- // ../node_modules/slash/index.js
2056
- function slash(path) {
2057
- const isExtendedLengthPath = path.startsWith("\\\\?\\");
2058
- if (isExtendedLengthPath) {
2059
- return path;
2060
- }
2061
- return path.replace(/\\/g, "/");
2062
- }
2063
- __name(slash, "slash");
2064
-
2065
- // src/preview-api/modules/store/autoTitle.ts
2066
- var sanitize2 = /* @__PURE__ */ __name((parts) => {
2067
- if (parts.length === 0) {
2068
- return parts;
2069
- }
2070
- const last = parts[parts.length - 1];
2071
- const lastStripped = last?.replace(/(?:[.](?:story|stories))?([.][^.]+)$/i, "");
2072
- if (parts.length === 1) {
2073
- return [lastStripped];
2074
- }
2075
- const nextToLast = parts[parts.length - 2];
2076
- if (lastStripped && nextToLast && lastStripped.toLowerCase() === nextToLast.toLowerCase()) {
2077
- return [...parts.slice(0, -2), lastStripped];
2078
- }
2079
- return lastStripped && (/^(story|stories)([.][^.]+)$/i.test(last) || /^index$/i.test(lastStripped)) ? parts.slice(0, -1) : [...parts.slice(0, -1), lastStripped];
2080
- }, "sanitize");
2081
- function pathJoin(paths) {
2082
- return paths.flatMap((p) => p.split("/")).filter(Boolean).join("/");
2083
- }
2084
- __name(pathJoin, "pathJoin");
2085
- var userOrAutoTitleFromSpecifier = /* @__PURE__ */ __name((fileName, entry, userTitle) => {
2086
- const { directory, importPathMatcher, titlePrefix = "" } = entry || {};
2087
- if (typeof fileName === "number") {
2088
- once2.warn(dedent`
2089
- CSF Auto-title received a numeric fileName. This typically happens when
2090
- webpack is mis-configured in production mode. To force webpack to produce
2091
- filenames, set optimization.moduleIds = "named" in your webpack config.
2092
- `);
2093
- }
2094
- const normalizedFileName = slash(String(fileName));
2095
- if (importPathMatcher.exec(normalizedFileName)) {
2096
- if (!userTitle) {
2097
- const suffix = normalizedFileName.replace(directory, "");
2098
- let parts = pathJoin([titlePrefix, suffix]).split("/");
2099
- parts = sanitize2(parts);
2100
- return parts.join("/");
2101
- }
2102
- if (!titlePrefix) {
2103
- return userTitle;
2104
- }
2105
- return pathJoin([titlePrefix, userTitle]);
2106
- }
2107
- return void 0;
2108
- }, "userOrAutoTitleFromSpecifier");
2109
- var userOrAutoTitle = /* @__PURE__ */ __name((fileName, storiesEntries, userTitle) => {
2110
- for (let i = 0; i < storiesEntries.length; i += 1) {
2111
- const title = userOrAutoTitleFromSpecifier(fileName, storiesEntries[i], userTitle);
2112
- if (title) {
2113
- return title;
2114
- }
2115
- }
2116
- return userTitle || void 0;
2117
- }, "userOrAutoTitle");
2118
-
2119
- // src/preview-api/modules/store/storySort.ts
2120
- var STORY_KIND_PATH_SEPARATOR = /\s*\/\s*/;
2121
- var storySort = /* @__PURE__ */ __name((options = {}) => (a, b) => {
2122
- if (a.title === b.title && !options.includeNames) {
2123
- return 0;
2124
- }
2125
- const method = options.method || "configure";
2126
- let order = options.order || [];
2127
- const storyTitleA = a.title.trim().split(STORY_KIND_PATH_SEPARATOR);
2128
- const storyTitleB = b.title.trim().split(STORY_KIND_PATH_SEPARATOR);
2129
- if (options.includeNames) {
2130
- storyTitleA.push(a.name);
2131
- storyTitleB.push(b.name);
2132
- }
2133
- let depth = 0;
2134
- while (storyTitleA[depth] || storyTitleB[depth]) {
2135
- if (!storyTitleA[depth]) {
2136
- return -1;
2137
- }
2138
- if (!storyTitleB[depth]) {
2139
- return 1;
2140
- }
2141
- const nameA = storyTitleA[depth];
2142
- const nameB = storyTitleB[depth];
2143
- if (nameA !== nameB) {
2144
- let indexA = order.indexOf(nameA);
2145
- let indexB = order.indexOf(nameB);
2146
- const indexWildcard = order.indexOf("*");
2147
- if (indexA !== -1 || indexB !== -1) {
2148
- if (indexA === -1) {
2149
- if (indexWildcard !== -1) {
2150
- indexA = indexWildcard;
2151
- } else {
2152
- indexA = order.length;
2153
- }
2154
- }
2155
- if (indexB === -1) {
2156
- if (indexWildcard !== -1) {
2157
- indexB = indexWildcard;
2158
- } else {
2159
- indexB = order.length;
2160
- }
2161
- }
2162
- return indexA - indexB;
2163
- }
2164
- if (method === "configure") {
2165
- return 0;
2166
- }
2167
- return nameA.localeCompare(nameB, options.locales ? options.locales : void 0, {
2168
- numeric: true,
2169
- sensitivity: "accent"
2170
- });
2171
- }
2172
- let index = order.indexOf(nameA);
2173
- if (index === -1) {
2174
- index = order.indexOf("*");
2175
- }
2176
- order = index !== -1 && Array.isArray(order[index + 1]) ? order[index + 1] : [];
2177
- depth += 1;
2178
- }
2179
- return 0;
2180
- }, "storySort");
2181
-
2182
- // src/preview-api/modules/store/sortStories.ts
2183
- var sortStoriesCommon = /* @__PURE__ */ __name((stories, storySortParameter, fileNameOrder) => {
2184
- if (storySortParameter) {
2185
- let sortFn;
2186
- if (typeof storySortParameter === "function") {
2187
- sortFn = storySortParameter;
2188
- } else {
2189
- sortFn = storySort(storySortParameter);
2190
- }
2191
- stories.sort(sortFn);
2192
- } else {
2193
- stories.sort(
2194
- (s1, s2) => fileNameOrder.indexOf(s1.importPath) - fileNameOrder.indexOf(s2.importPath)
2195
- );
2196
- }
2197
- return stories;
2198
- }, "sortStoriesCommon");
2199
- var sortStoriesV7 = /* @__PURE__ */ __name((stories, storySortParameter, fileNameOrder) => {
2200
- try {
2201
- return sortStoriesCommon(stories, storySortParameter, fileNameOrder);
2202
- } catch (err) {
2203
- throw new Error(dedent`
2204
- Error sorting stories with sort parameter ${storySortParameter}:
2205
-
2206
- > ${err.message}
2207
-
2208
- Are you using a V6-style sort function in V7 mode?
2209
-
2210
- More info: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#v7-style-story-sort
2211
- `);
2212
- }
2213
- }, "sortStoriesV7");
2214
-
2215
- // src/preview-api/modules/preview-web/Preview.tsx
2216
- import { deprecate as deprecate2, logger as logger7 } from "storybook/internal/client-logger";
2217
- import {
2218
- ARGTYPES_INFO_REQUEST,
2219
- ARGTYPES_INFO_RESPONSE,
2220
- CONFIG_ERROR,
2221
- FORCE_REMOUNT,
2222
- FORCE_RE_RENDER as FORCE_RE_RENDER2,
2223
- GLOBALS_UPDATED,
2224
- PREVIEW_INITIALIZED,
2225
- RESET_STORY_ARGS as RESET_STORY_ARGS2,
2226
- SET_GLOBALS,
2227
- STORY_ARGS_UPDATED,
2228
- STORY_HOT_UPDATED,
2229
- STORY_INDEX_INVALIDATED,
2230
- UPDATE_GLOBALS as UPDATE_GLOBALS2,
2231
- UPDATE_STORY_ARGS as UPDATE_STORY_ARGS2
2232
- } from "storybook/internal/core-events";
2233
- import {
2234
- CalledPreviewMethodBeforeInitializationError,
2235
- MissingRenderToCanvasError,
2236
- StoryIndexFetchError,
2237
- StoryStoreAccessedBeforeInitializationError
2238
- } from "storybook/internal/preview-errors";
2239
- import { global as global5 } from "@storybook/global";
2240
-
2241
- // src/preview-api/modules/preview-web/render/StoryRender.ts
2242
- import {
2243
- PLAY_FUNCTION_THREW_EXCEPTION,
2244
- STORY_FINISHED,
2245
- STORY_RENDERED as STORY_RENDERED2,
2246
- STORY_RENDER_PHASE_CHANGED,
2247
- UNHANDLED_ERRORS_WHILE_PLAYING
2248
- } from "storybook/internal/core-events";
2249
- import {
2250
- MountMustBeDestructuredError as MountMustBeDestructuredError2,
2251
- NoStoryMountedError
2252
- } from "storybook/internal/preview-errors";
2253
-
2254
- // src/preview-api/modules/preview-web/render/Render.ts
2255
- var PREPARE_ABORTED = new Error("prepareAborted");
2256
-
2257
- // src/preview-api/modules/preview-web/render/StoryRender.ts
2258
- var { AbortController: AbortController2 } = globalThis;
2259
- function serializeError(error) {
2260
- try {
2261
- const { name = "Error", message = String(error), stack } = error;
2262
- return { name, message, stack };
2263
- } catch (e) {
2264
- return { name: "Error", message: String(error) };
2265
- }
2266
- }
2267
- __name(serializeError, "serializeError");
2268
- var _StoryRender = class _StoryRender {
2269
- constructor(channel, store, renderToScreen, callbacks, id, viewMode, renderOptions = { autoplay: true, forceInitialArgs: false }, story) {
2270
- this.channel = channel;
2271
- this.store = store;
2272
- this.renderToScreen = renderToScreen;
2273
- this.callbacks = callbacks;
2274
- this.id = id;
2275
- this.viewMode = viewMode;
2276
- this.renderOptions = renderOptions;
2277
- this.type = "story";
2278
- this.notYetRendered = true;
2279
- this.rerenderEnqueued = false;
2280
- this.disableKeyListeners = false;
2281
- this.teardownRender = /* @__PURE__ */ __name(() => {
2282
- }, "teardownRender");
2283
- this.torndown = false;
2284
- this.abortController = new AbortController2();
2285
- this.renderId = Date.now();
2286
- if (story) {
2287
- this.story = story;
2288
- this.phase = "preparing";
2289
- }
2290
- }
2291
- async runPhase(signal, phase, phaseFn) {
2292
- this.phase = phase;
2293
- this.channel.emit(STORY_RENDER_PHASE_CHANGED, {
2294
- newPhase: this.phase,
2295
- renderId: this.renderId,
2296
- storyId: this.id
2297
- });
2298
- if (phaseFn) {
2299
- await phaseFn();
2300
- this.checkIfAborted(signal);
2301
- }
2302
- }
2303
- checkIfAborted(signal) {
2304
- if (signal.aborted && !["finished", "aborted", "errored"].includes(this.phase)) {
2305
- this.phase = "aborted";
2306
- this.channel.emit(STORY_RENDER_PHASE_CHANGED, {
2307
- newPhase: this.phase,
2308
- renderId: this.renderId,
2309
- storyId: this.id
2310
- });
2311
- }
2312
- return signal.aborted;
2313
- }
2314
- async prepare() {
2315
- await this.runPhase(this.abortController.signal, "preparing", async () => {
2316
- this.story = await this.store.loadStory({ storyId: this.id });
2317
- });
2318
- if (this.abortController.signal.aborted) {
2319
- await this.store.cleanupStory(this.story);
2320
- throw PREPARE_ABORTED;
2321
- }
2322
- }
2323
- // The two story "renders" are equal and have both loaded the same story
2324
- isEqual(other) {
2325
- return !!(this.id === other.id && this.story && this.story === other.story);
2326
- }
2327
- isPreparing() {
2328
- return ["preparing"].includes(this.phase);
2329
- }
2330
- isPending() {
2331
- return ["loading", "beforeEach", "rendering", "playing", "afterEach"].includes(
2332
- this.phase
2333
- );
2334
- }
2335
- async renderToElement(canvasElement) {
2336
- this.canvasElement = canvasElement;
2337
- return this.render({ initial: true, forceRemount: true });
2338
- }
2339
- storyContext() {
2340
- if (!this.story) {
2341
- throw new Error(`Cannot call storyContext before preparing`);
2342
- }
2343
- const { forceInitialArgs } = this.renderOptions;
2344
- return this.store.getStoryContext(this.story, { forceInitialArgs });
2345
- }
2346
- async render({
2347
- initial = false,
2348
- forceRemount = false
2349
- } = {}) {
2350
- const { canvasElement } = this;
2351
- if (!this.story) {
2352
- throw new Error("cannot render when not prepared");
2353
- }
2354
- const story = this.story;
2355
- if (!canvasElement) {
2356
- throw new Error("cannot render when canvasElement is unset");
2357
- }
2358
- const {
2359
- id,
2360
- componentId,
2361
- title,
2362
- name,
2363
- tags,
2364
- applyLoaders,
2365
- applyBeforeEach,
2366
- applyAfterEach,
2367
- unboundStoryFn,
2368
- playFunction,
2369
- runStep
2370
- } = story;
2371
- if (forceRemount && !initial) {
2372
- this.cancelRender();
2373
- this.abortController = new AbortController2();
2374
- }
2375
- const abortSignal = this.abortController.signal;
2376
- let mounted = false;
2377
- const isMountDestructured = story.usesMount;
2378
- try {
2379
- const context = {
2380
- ...this.storyContext(),
2381
- viewMode: this.viewMode,
2382
- abortSignal,
2383
- canvasElement,
2384
- loaded: {},
2385
- step: /* @__PURE__ */ __name((label, play) => runStep(label, play, context), "step"),
2386
- context: null,
2387
- canvas: {},
2388
- userEvent: {},
2389
- renderToCanvas: /* @__PURE__ */ __name(async () => {
2390
- const teardown = await this.renderToScreen(renderContext, canvasElement);
2391
- this.teardownRender = teardown || (() => {
2392
- });
2393
- mounted = true;
2394
- }, "renderToCanvas"),
2395
- // The story provides (set in a renderer) a mount function that is a higher order function
2396
- // (context) => (...args) => Canvas
2397
- //
2398
- // Before assigning it to the context, we resolve the context dependency,
2399
- // so that a user can just call it as await mount(...args) in their play function.
2400
- mount: /* @__PURE__ */ __name(async (...args) => {
2401
- this.callbacks.showStoryDuringRender?.();
2402
- let mountReturn = null;
2403
- await this.runPhase(abortSignal, "rendering", async () => {
2404
- mountReturn = await story.mount(context)(...args);
2405
- });
2406
- if (isMountDestructured) {
2407
- await this.runPhase(abortSignal, "playing");
2408
- }
2409
- return mountReturn;
2410
- }, "mount")
2411
- };
2412
- context.context = context;
2413
- const renderContext = {
2414
- componentId,
2415
- title,
2416
- kind: title,
2417
- id,
2418
- name,
2419
- story: name,
2420
- tags,
2421
- ...this.callbacks,
2422
- showError: /* @__PURE__ */ __name((error) => {
2423
- this.phase = "errored";
2424
- return this.callbacks.showError(error);
2425
- }, "showError"),
2426
- showException: /* @__PURE__ */ __name((error) => {
2427
- this.phase = "errored";
2428
- return this.callbacks.showException(error);
2429
- }, "showException"),
2430
- forceRemount: forceRemount || this.notYetRendered,
2431
- storyContext: context,
2432
- storyFn: /* @__PURE__ */ __name(() => unboundStoryFn(context), "storyFn"),
2433
- unboundStoryFn
2434
- };
2435
- await this.runPhase(abortSignal, "loading", async () => {
2436
- context.loaded = await applyLoaders(context);
2437
- });
2438
- if (abortSignal.aborted) {
2439
- return;
2440
- }
2441
- const cleanupCallbacks = await applyBeforeEach(context);
2442
- this.store.addCleanupCallbacks(story, ...cleanupCallbacks);
2443
- if (this.checkIfAborted(abortSignal)) {
2444
- return;
2445
- }
2446
- if (!mounted && !isMountDestructured) {
2447
- await context.mount();
2448
- }
2449
- this.notYetRendered = false;
2450
- if (abortSignal.aborted) {
2451
- return;
2452
- }
2453
- const ignoreUnhandledErrors = this.story.parameters?.test?.dangerouslyIgnoreUnhandledErrors === true;
2454
- const unhandledErrors = /* @__PURE__ */ new Set();
2455
- const onError = /* @__PURE__ */ __name((event) => {
2456
- if (event.error) {
2457
- unhandledErrors.add(event.error);
2458
- }
2459
- }, "onError");
2460
- const onUnhandledRejection = /* @__PURE__ */ __name((event) => {
2461
- if (event.reason) {
2462
- unhandledErrors.add(event.reason);
2463
- }
2464
- }, "onUnhandledRejection");
2465
- if (this.renderOptions.autoplay && forceRemount && playFunction && this.phase !== "errored") {
2466
- window?.addEventListener?.("error", onError);
2467
- window?.addEventListener?.("unhandledrejection", onUnhandledRejection);
2468
- this.disableKeyListeners = true;
2469
- try {
2470
- if (!isMountDestructured) {
2471
- context.mount = async () => {
2472
- throw new MountMustBeDestructuredError2({ playFunction: playFunction.toString() });
2473
- };
2474
- await this.runPhase(abortSignal, "playing", async () => playFunction(context));
2475
- } else {
2476
- await playFunction(context);
2477
- }
2478
- if (!mounted) {
2479
- throw new NoStoryMountedError();
2480
- }
2481
- this.checkIfAborted(abortSignal);
2482
- if (!ignoreUnhandledErrors && unhandledErrors.size > 0) {
2483
- await this.runPhase(abortSignal, "errored");
2484
- } else {
2485
- await this.runPhase(abortSignal, "played");
2486
- }
2487
- } catch (error) {
2488
- this.callbacks.showStoryDuringRender?.();
2489
- await this.runPhase(abortSignal, "errored", async () => {
2490
- this.channel.emit(PLAY_FUNCTION_THREW_EXCEPTION, serializeError(error));
2491
- });
2492
- if (this.story.parameters.throwPlayFunctionExceptions !== false) {
2493
- throw error;
2494
- }
2495
- console.error(error);
2496
- }
2497
- if (!ignoreUnhandledErrors && unhandledErrors.size > 0) {
2498
- this.channel.emit(
2499
- UNHANDLED_ERRORS_WHILE_PLAYING,
2500
- Array.from(unhandledErrors).map(serializeError)
2501
- );
2502
- }
2503
- this.disableKeyListeners = false;
2504
- window?.removeEventListener?.("unhandledrejection", onUnhandledRejection);
2505
- window?.removeEventListener?.("error", onError);
2506
- if (abortSignal.aborted) {
2507
- return;
2508
- }
2509
- }
2510
- await this.runPhase(abortSignal, "completing", async () => {
2511
- if (isTestEnvironment()) {
2512
- this.store.addCleanupCallbacks(story, pauseAnimations());
2513
- } else {
2514
- await waitForAnimations(abortSignal);
2515
- }
2516
- });
2517
- await this.runPhase(abortSignal, "completed", async () => {
2518
- this.channel.emit(STORY_RENDERED2, id);
2519
- });
2520
- if (this.phase !== "errored") {
2521
- await this.runPhase(abortSignal, "afterEach", async () => {
2522
- await applyAfterEach(context);
2523
- });
2524
- }
2525
- const hasUnhandledErrors = !ignoreUnhandledErrors && unhandledErrors.size > 0;
2526
- const hasSomeReportsFailed = context.reporting.reports.some(
2527
- (report) => report.status === "failed"
2528
- );
2529
- const hasStoryErrored = hasUnhandledErrors || hasSomeReportsFailed;
2530
- await this.runPhase(
2531
- abortSignal,
2532
- "finished",
2533
- async () => this.channel.emit(STORY_FINISHED, {
2534
- storyId: id,
2535
- status: hasStoryErrored ? "error" : "success",
2536
- reporters: context.reporting.reports
2537
- })
2538
- );
2539
- } catch (err) {
2540
- this.phase = "errored";
2541
- this.callbacks.showException(err);
2542
- await this.runPhase(
2543
- abortSignal,
2544
- "finished",
2545
- async () => this.channel.emit(STORY_FINISHED, {
2546
- storyId: id,
2547
- status: "error",
2548
- reporters: []
2549
- })
2550
- );
2551
- }
2552
- if (this.rerenderEnqueued) {
2553
- this.rerenderEnqueued = false;
2554
- this.render();
2555
- }
2556
- }
2557
- /**
2558
- * Rerender the story. If the story is currently pending (loading/rendering), the rerender will be
2559
- * enqueued, and will be executed after the current render is completed. Rerendering while playing
2560
- * will not be enqueued, and will be executed immediately, to support rendering args changes while
2561
- * playing.
2562
- */
2563
- async rerender() {
2564
- if (this.isPending() && this.phase !== "playing") {
2565
- this.rerenderEnqueued = true;
2566
- } else {
2567
- return this.render();
2568
- }
2569
- }
2570
- async remount() {
2571
- await this.teardown();
2572
- return this.render({ forceRemount: true });
2573
- }
2574
- // If the story is torn down (either a new story is rendered or the docs page removes it)
2575
- // we need to consider the fact that the initial render may not be finished
2576
- // (possibly the loaders or the play function are still running). We use the controller
2577
- // as a method to abort them, ASAP, but this is not foolproof as we cannot control what
2578
- // happens inside the user's code.
2579
- cancelRender() {
2580
- this.abortController.abort();
2581
- }
2582
- cancelPlayFunction() {
2583
- if (this.phase === "playing") {
2584
- this.abortController.abort();
2585
- this.runPhase(this.abortController.signal, "aborted");
2586
- }
2587
- }
2588
- async teardown() {
2589
- this.torndown = true;
2590
- this.cancelRender();
2591
- if (this.story) {
2592
- await this.store.cleanupStory(this.story);
2593
- }
2594
- for (let i = 0; i < 3; i += 1) {
2595
- if (!this.isPending()) {
2596
- await this.teardownRender();
2597
- return;
2598
- }
2599
- await new Promise((resolve) => setTimeout(resolve, 0));
2600
- }
2601
- window?.location?.reload?.();
2602
- await new Promise(() => {
2603
- });
2604
- }
2605
- };
2606
- __name(_StoryRender, "StoryRender");
2607
- var StoryRender = _StoryRender;
2608
-
2609
- // src/preview-api/modules/preview-web/Preview.tsx
2610
- var { fetch } = global5;
2611
- var STORY_INDEX_PATH = "./index.json";
2612
- var _Preview = class _Preview {
2613
- constructor(importFn, getProjectAnnotations, channel = addons.getChannel(), shouldInitialize = true) {
2614
- this.importFn = importFn;
2615
- this.getProjectAnnotations = getProjectAnnotations;
2616
- this.channel = channel;
2617
- this.storyRenders = [];
2618
- this.storeInitializationPromise = new Promise((resolve, reject) => {
2619
- this.resolveStoreInitializationPromise = resolve;
2620
- this.rejectStoreInitializationPromise = reject;
2621
- });
2622
- if (shouldInitialize) {
2623
- this.initialize();
2624
- }
2625
- }
2626
- // Create a proxy object for `__STORYBOOK_STORY_STORE__` and `__STORYBOOK_PREVIEW__.storyStore`
2627
- // That proxies through to the store once ready, and errors beforehand. This means we can set
2628
- // `__STORYBOOK_STORY_STORE__ = __STORYBOOK_PREVIEW__.storyStore` without having to wait, and
2629
- // similarly integrators can access the `storyStore` on the preview at any time, although
2630
- // it is considered deprecated and we will no longer allow access in 9.0
2631
- get storyStore() {
2632
- return new Proxy(
2633
- {},
2634
- {
2635
- get: /* @__PURE__ */ __name((_, method) => {
2636
- if (this.storyStoreValue) {
2637
- deprecate2("Accessing the Story Store is deprecated and will be removed in 9.0");
2638
- return this.storyStoreValue[method];
2639
- }
2640
- throw new StoryStoreAccessedBeforeInitializationError();
2641
- }, "get")
2642
- }
2643
- );
2644
- }
2645
- // INITIALIZATION
2646
- async initialize() {
2647
- this.setupListeners();
2648
- try {
2649
- const projectAnnotations = await this.getProjectAnnotationsOrRenderError();
2650
- await this.runBeforeAllHook(projectAnnotations);
2651
- await this.initializeWithProjectAnnotations(projectAnnotations);
2652
- const userAgent = globalThis?.navigator?.userAgent;
2653
- await this.channel.emit(PREVIEW_INITIALIZED, { userAgent });
2654
- } catch (err) {
2655
- this.rejectStoreInitializationPromise(err);
2656
- }
2657
- }
2658
- ready() {
2659
- return this.storeInitializationPromise;
2660
- }
2661
- setupListeners() {
2662
- this.channel.on(STORY_INDEX_INVALIDATED, this.onStoryIndexChanged.bind(this));
2663
- this.channel.on(UPDATE_GLOBALS2, this.onUpdateGlobals.bind(this));
2664
- this.channel.on(UPDATE_STORY_ARGS2, this.onUpdateArgs.bind(this));
2665
- this.channel.on(ARGTYPES_INFO_REQUEST, this.onRequestArgTypesInfo.bind(this));
2666
- this.channel.on(RESET_STORY_ARGS2, this.onResetArgs.bind(this));
2667
- this.channel.on(FORCE_RE_RENDER2, this.onForceReRender.bind(this));
2668
- this.channel.on(FORCE_REMOUNT, this.onForceRemount.bind(this));
2669
- this.channel.on(STORY_HOT_UPDATED, this.onStoryHotUpdated.bind(this));
2670
- }
2671
- async getProjectAnnotationsOrRenderError() {
2672
- try {
2673
- const projectAnnotations = await this.getProjectAnnotations();
2674
- this.renderToCanvas = projectAnnotations.renderToCanvas;
2675
- if (!this.renderToCanvas) {
2676
- throw new MissingRenderToCanvasError();
2677
- }
2678
- return projectAnnotations;
2679
- } catch (err) {
2680
- this.renderPreviewEntryError("Error reading preview.js:", err);
2681
- throw err;
2682
- }
2683
- }
2684
- // If initialization gets as far as project annotations, this function runs.
2685
- async initializeWithProjectAnnotations(projectAnnotations) {
2686
- this.projectAnnotationsBeforeInitialization = projectAnnotations;
2687
- try {
2688
- const storyIndex = await this.getStoryIndexFromServer();
2689
- return this.initializeWithStoryIndex(storyIndex);
2690
- } catch (err) {
2691
- this.renderPreviewEntryError("Error loading story index:", err);
2692
- throw err;
2693
- }
2694
- }
2695
- async runBeforeAllHook(projectAnnotations) {
2696
- try {
2697
- await this.beforeAllCleanup?.();
2698
- this.beforeAllCleanup = await projectAnnotations.beforeAll?.();
2699
- } catch (err) {
2700
- this.renderPreviewEntryError("Error in beforeAll hook:", err);
2701
- throw err;
2702
- }
2703
- }
2704
- async getStoryIndexFromServer() {
2705
- const result = await fetch(STORY_INDEX_PATH);
2706
- if (result.status === 200) {
2707
- return result.json();
2708
- }
2709
- throw new StoryIndexFetchError({ text: await result.text() });
2710
- }
2711
- // If initialization gets as far as the story index, this function runs.
2712
- initializeWithStoryIndex(storyIndex) {
2713
- if (!this.projectAnnotationsBeforeInitialization) {
2714
- throw new Error("Cannot call initializeWithStoryIndex until project annotations resolve");
2715
- }
2716
- this.storyStoreValue = new StoryStore(
2717
- storyIndex,
2718
- this.importFn,
2719
- this.projectAnnotationsBeforeInitialization
2720
- );
2721
- delete this.projectAnnotationsBeforeInitialization;
2722
- this.setInitialGlobals();
2723
- this.resolveStoreInitializationPromise();
2724
- }
2725
- async setInitialGlobals() {
2726
- this.emitGlobals();
2727
- }
2728
- emitGlobals() {
2729
- if (!this.storyStoreValue) {
2730
- throw new CalledPreviewMethodBeforeInitializationError({ methodName: "emitGlobals" });
2731
- }
2732
- const payload = {
2733
- globals: this.storyStoreValue.userGlobals.get() || {},
2734
- globalTypes: this.storyStoreValue.projectAnnotations.globalTypes || {}
2735
- };
2736
- this.channel.emit(SET_GLOBALS, payload);
2737
- }
2738
- // EVENT HANDLERS
2739
- // This happens when a config file gets reloaded
2740
- async onGetProjectAnnotationsChanged({
2741
- getProjectAnnotations
2742
- }) {
2743
- delete this.previewEntryError;
2744
- this.getProjectAnnotations = getProjectAnnotations;
2745
- const projectAnnotations = await this.getProjectAnnotationsOrRenderError();
2746
- await this.runBeforeAllHook(projectAnnotations);
2747
- if (!this.storyStoreValue) {
2748
- await this.initializeWithProjectAnnotations(projectAnnotations);
2749
- return;
2750
- }
2751
- this.storyStoreValue.setProjectAnnotations(projectAnnotations);
2752
- this.emitGlobals();
2753
- }
2754
- async onStoryIndexChanged() {
2755
- delete this.previewEntryError;
2756
- if (!this.storyStoreValue && !this.projectAnnotationsBeforeInitialization) {
2757
- return;
2758
- }
2759
- try {
2760
- const storyIndex = await this.getStoryIndexFromServer();
2761
- if (this.projectAnnotationsBeforeInitialization) {
2762
- this.initializeWithStoryIndex(storyIndex);
2763
- return;
2764
- }
2765
- await this.onStoriesChanged({ storyIndex });
2766
- } catch (err) {
2767
- this.renderPreviewEntryError("Error loading story index:", err);
2768
- throw err;
2769
- }
2770
- }
2771
- // This happens when a glob gets HMR-ed
2772
- async onStoriesChanged({
2773
- importFn,
2774
- storyIndex
2775
- }) {
2776
- if (!this.storyStoreValue) {
2777
- throw new CalledPreviewMethodBeforeInitializationError({ methodName: "onStoriesChanged" });
2778
- }
2779
- await this.storyStoreValue.onStoriesChanged({ importFn, storyIndex });
2780
- }
2781
- async onUpdateGlobals({
2782
- globals: updatedGlobals,
2783
- currentStory
2784
- }) {
2785
- if (!this.storyStoreValue) {
2786
- await this.storeInitializationPromise;
2787
- }
2788
- if (!this.storyStoreValue) {
2789
- throw new CalledPreviewMethodBeforeInitializationError({ methodName: "onUpdateGlobals" });
2790
- }
2791
- this.storyStoreValue.userGlobals.update(updatedGlobals);
2792
- if (currentStory) {
2793
- const { initialGlobals, storyGlobals, userGlobals, globals } = this.storyStoreValue.getStoryContext(currentStory);
2794
- this.channel.emit(GLOBALS_UPDATED, {
2795
- initialGlobals,
2796
- userGlobals,
2797
- storyGlobals,
2798
- globals
2799
- });
2800
- } else {
2801
- const { initialGlobals, globals } = this.storyStoreValue.userGlobals;
2802
- this.channel.emit(GLOBALS_UPDATED, {
2803
- initialGlobals,
2804
- userGlobals: globals,
2805
- storyGlobals: {},
2806
- globals
2807
- });
2808
- }
2809
- await Promise.all(this.storyRenders.map((r) => r.rerender()));
2810
- }
2811
- async onUpdateArgs({ storyId, updatedArgs }) {
2812
- if (!this.storyStoreValue) {
2813
- throw new CalledPreviewMethodBeforeInitializationError({ methodName: "onUpdateArgs" });
2814
- }
2815
- this.storyStoreValue.args.update(storyId, updatedArgs);
2816
- await Promise.all(
2817
- this.storyRenders.filter((r) => r.id === storyId && !r.renderOptions.forceInitialArgs).map(
2818
- (r) => (
2819
- // We only run the play function, with in a force remount.
2820
- // But when mount is destructured, the rendering happens inside of the play function.
2821
- r.story && r.story.usesMount ? r.remount() : r.rerender()
2822
- )
2823
- )
2824
- );
2825
- this.channel.emit(STORY_ARGS_UPDATED, {
2826
- storyId,
2827
- args: this.storyStoreValue.args.get(storyId)
2828
- });
2829
- }
2830
- async onRequestArgTypesInfo({ id, payload }) {
2831
- try {
2832
- await this.storeInitializationPromise;
2833
- const story = await this.storyStoreValue?.loadStory(payload);
2834
- this.channel.emit(ARGTYPES_INFO_RESPONSE, {
2835
- id,
2836
- success: true,
2837
- payload: { argTypes: story?.argTypes || {} },
2838
- error: null
2839
- });
2840
- } catch (e) {
2841
- this.channel.emit(ARGTYPES_INFO_RESPONSE, {
2842
- id,
2843
- success: false,
2844
- error: e?.message
2845
- });
2846
- }
2847
- }
2848
- async onResetArgs({ storyId, argNames }) {
2849
- if (!this.storyStoreValue) {
2850
- throw new CalledPreviewMethodBeforeInitializationError({ methodName: "onResetArgs" });
2851
- }
2852
- const render = this.storyRenders.find((r) => r.id === storyId);
2853
- const story = render?.story || await this.storyStoreValue.loadStory({ storyId });
2854
- const argNamesToReset = argNames || [
2855
- .../* @__PURE__ */ new Set([
2856
- ...Object.keys(story.initialArgs),
2857
- ...Object.keys(this.storyStoreValue.args.get(storyId))
2858
- ])
2859
- ];
2860
- const updatedArgs = argNamesToReset.reduce((acc, argName) => {
2861
- acc[argName] = story.initialArgs[argName];
2862
- return acc;
2863
- }, {});
2864
- await this.onUpdateArgs({ storyId, updatedArgs });
2865
- }
2866
- // ForceReRender does not include a story id, so we simply must
2867
- // re-render all stories in case they are relevant
2868
- async onForceReRender() {
2869
- await Promise.all(this.storyRenders.map((r) => r.rerender()));
2870
- }
2871
- async onForceRemount({ storyId }) {
2872
- await Promise.all(this.storyRenders.filter((r) => r.id === storyId).map((r) => r.remount()));
2873
- }
2874
- async onStoryHotUpdated() {
2875
- await Promise.all(this.storyRenders.map((r) => r.cancelPlayFunction()));
2876
- }
2877
- // Used by docs to render a story to a given element
2878
- // Note this short-circuits the `prepare()` phase of the StoryRender,
2879
- // main to be consistent with the previous behaviour. In the future,
2880
- // we will change it to go ahead and load the story, which will end up being
2881
- // "instant", although async.
2882
- renderStoryToElement(story, element, callbacks, options) {
2883
- if (!this.renderToCanvas || !this.storyStoreValue) {
2884
- throw new CalledPreviewMethodBeforeInitializationError({
2885
- methodName: "renderStoryToElement"
2886
- });
2887
- }
2888
- const render = new StoryRender(
2889
- this.channel,
2890
- this.storyStoreValue,
2891
- this.renderToCanvas,
2892
- callbacks,
2893
- story.id,
2894
- "docs",
2895
- options,
2896
- story
2897
- );
2898
- render.renderToElement(element);
2899
- this.storyRenders.push(render);
2900
- return async () => {
2901
- await this.teardownRender(render);
2902
- };
2903
- }
2904
- async teardownRender(render, { viewModeChanged } = {}) {
2905
- this.storyRenders = this.storyRenders.filter((r) => r !== render);
2906
- await render?.teardown?.({ viewModeChanged });
2907
- }
2908
- // API
2909
- async loadStory({ storyId }) {
2910
- if (!this.storyStoreValue) {
2911
- throw new CalledPreviewMethodBeforeInitializationError({ methodName: "loadStory" });
2912
- }
2913
- return this.storyStoreValue.loadStory({ storyId });
2914
- }
2915
- getStoryContext(story, { forceInitialArgs = false } = {}) {
2916
- if (!this.storyStoreValue) {
2917
- throw new CalledPreviewMethodBeforeInitializationError({ methodName: "getStoryContext" });
2918
- }
2919
- return this.storyStoreValue.getStoryContext(story, { forceInitialArgs });
2920
- }
2921
- async extract(options) {
2922
- if (!this.storyStoreValue) {
2923
- throw new CalledPreviewMethodBeforeInitializationError({ methodName: "extract" });
2924
- }
2925
- if (this.previewEntryError) {
2926
- throw this.previewEntryError;
2927
- }
2928
- await this.storyStoreValue.cacheAllCSFFiles();
2929
- return this.storyStoreValue.extract(options);
2930
- }
2931
- // UTILITIES
2932
- renderPreviewEntryError(reason, err) {
2933
- this.previewEntryError = err;
2934
- logger7.error(reason);
2935
- logger7.error(err);
2936
- this.channel.emit(CONFIG_ERROR, err);
2937
- }
2938
- };
2939
- __name(_Preview, "Preview");
2940
- var Preview = _Preview;
2941
-
2942
- // src/preview-api/modules/preview-web/PreviewWeb.tsx
2943
- import { global as global8 } from "@storybook/global";
2944
-
2945
- // src/preview-api/modules/preview-web/PreviewWithSelection.tsx
2946
- import { logger as logger8 } from "storybook/internal/client-logger";
2947
- import {
2948
- CURRENT_STORY_WAS_SET,
2949
- DOCS_PREPARED,
2950
- GLOBALS_UPDATED as GLOBALS_UPDATED2,
2951
- PRELOAD_ENTRIES,
2952
- PREVIEW_KEYDOWN,
2953
- SET_CURRENT_STORY,
2954
- STORY_CHANGED,
2955
- STORY_ERRORED,
2956
- STORY_MISSING,
2957
- STORY_PREPARED,
2958
- STORY_RENDER_PHASE_CHANGED as STORY_RENDER_PHASE_CHANGED2,
2959
- STORY_SPECIFIED,
2960
- STORY_THREW_EXCEPTION,
2961
- STORY_UNCHANGED,
2962
- UPDATE_QUERY_PARAMS
2963
- } from "storybook/internal/core-events";
2964
- import {
2965
- CalledPreviewMethodBeforeInitializationError as CalledPreviewMethodBeforeInitializationError2,
2966
- EmptyIndexError,
2967
- MdxFileWithNoCsfReferencesError,
2968
- NoStoryMatchError
2969
- } from "storybook/internal/preview-errors";
2970
-
2971
- // src/preview-api/modules/preview-web/render/CsfDocsRender.ts
2972
- import { DOCS_RENDERED } from "storybook/internal/core-events";
2973
-
2974
- // src/preview-api/modules/preview-web/docs-context/DocsContext.ts
2975
- import { isStory as isStory3 } from "storybook/internal/csf";
2976
- var _DocsContext = class _DocsContext {
2977
- constructor(channel, store, renderStoryToElement, csfFiles) {
2978
- this.channel = channel;
2979
- this.store = store;
2980
- this.renderStoryToElement = renderStoryToElement;
2981
- this.storyIdByName = /* @__PURE__ */ __name((storyName) => {
2982
- const storyId = this.nameToStoryId.get(storyName);
2983
- if (storyId) {
2984
- return storyId;
2985
- }
2986
- throw new Error(`No story found with that name: ${storyName}`);
2987
- }, "storyIdByName");
2988
- this.componentStories = /* @__PURE__ */ __name(() => {
2989
- return this.componentStoriesValue;
2990
- }, "componentStories");
2991
- this.componentStoriesFromCSFFile = /* @__PURE__ */ __name((csfFile) => {
2992
- return this.store.componentStoriesFromCSFFile({ csfFile });
2993
- }, "componentStoriesFromCSFFile");
2994
- this.storyById = /* @__PURE__ */ __name((storyId) => {
2995
- if (!storyId) {
2996
- if (!this.primaryStory) {
2997
- throw new Error(
2998
- `No primary story defined for docs entry. Did you forget to use \`<Meta>\`?`
2999
- );
3000
- }
3001
- return this.primaryStory;
3002
- }
3003
- const csfFile = this.storyIdToCSFFile.get(storyId);
3004
- if (!csfFile) {
3005
- throw new Error(`Called \`storyById\` for story that was never loaded: ${storyId}`);
3006
- }
3007
- return this.store.storyFromCSFFile({ storyId, csfFile });
3008
- }, "storyById");
3009
- this.getStoryContext = /* @__PURE__ */ __name((story) => {
3010
- return {
3011
- ...this.store.getStoryContext(story),
3012
- loaded: {},
3013
- viewMode: "docs"
3014
- };
3015
- }, "getStoryContext");
3016
- this.loadStory = /* @__PURE__ */ __name((id) => {
3017
- return this.store.loadStory({ storyId: id });
3018
- }, "loadStory");
3019
- this.componentStoriesValue = [];
3020
- this.storyIdToCSFFile = /* @__PURE__ */ new Map();
3021
- this.exportToStory = /* @__PURE__ */ new Map();
3022
- this.exportsToCSFFile = /* @__PURE__ */ new Map();
3023
- this.nameToStoryId = /* @__PURE__ */ new Map();
3024
- this.attachedCSFFiles = /* @__PURE__ */ new Set();
3025
- csfFiles.forEach((csfFile, index) => {
3026
- this.referenceCSFFile(csfFile);
3027
- });
3028
- }
3029
- // This docs entry references this CSF file and can synchronously load the stories, as well
3030
- // as reference them by module export. If the CSF is part of the "component" stories, they
3031
- // can also be referenced by name and are in the componentStories list.
3032
- referenceCSFFile(csfFile) {
3033
- this.exportsToCSFFile.set(csfFile.moduleExports, csfFile);
3034
- this.exportsToCSFFile.set(csfFile.moduleExports.default, csfFile);
3035
- const stories = this.store.componentStoriesFromCSFFile({ csfFile });
3036
- stories.forEach((story) => {
3037
- const annotation = csfFile.stories[story.id];
3038
- this.storyIdToCSFFile.set(annotation.id, csfFile);
3039
- this.exportToStory.set(annotation.moduleExport, story);
3040
- });
3041
- }
3042
- attachCSFFile(csfFile) {
3043
- if (!this.exportsToCSFFile.has(csfFile.moduleExports)) {
3044
- throw new Error("Cannot attach a CSF file that has not been referenced");
3045
- }
3046
- if (this.attachedCSFFiles.has(csfFile)) {
3047
- return;
3048
- }
3049
- this.attachedCSFFiles.add(csfFile);
3050
- const stories = this.store.componentStoriesFromCSFFile({ csfFile });
3051
- stories.forEach((story) => {
3052
- this.nameToStoryId.set(story.name, story.id);
3053
- this.componentStoriesValue.push(story);
3054
- if (!this.primaryStory) {
3055
- this.primaryStory = story;
3056
- }
3057
- });
3058
- }
3059
- referenceMeta(metaExports, attach) {
3060
- const resolved = this.resolveModuleExport(metaExports);
3061
- if (resolved.type !== "meta") {
3062
- throw new Error(
3063
- "<Meta of={} /> must reference a CSF file module export or meta export. Did you mistakenly reference your component instead of your CSF file?"
3064
- );
3065
- }
3066
- if (attach) {
3067
- this.attachCSFFile(resolved.csfFile);
3068
- }
3069
- }
3070
- get projectAnnotations() {
3071
- const { projectAnnotations } = this.store;
3072
- if (!projectAnnotations) {
3073
- throw new Error("Can't get projectAnnotations from DocsContext before they are initialized");
3074
- }
3075
- return projectAnnotations;
3076
- }
3077
- resolveAttachedModuleExportType(moduleExportType) {
3078
- if (moduleExportType === "story") {
3079
- if (!this.primaryStory) {
3080
- throw new Error(
3081
- `No primary story attached to this docs file, did you forget to use <Meta of={} />?`
3082
- );
3083
- }
3084
- return { type: "story", story: this.primaryStory };
3085
- }
3086
- if (this.attachedCSFFiles.size === 0) {
3087
- throw new Error(
3088
- `No CSF file attached to this docs file, did you forget to use <Meta of={} />?`
3089
- );
3090
- }
3091
- const firstAttachedCSFFile = Array.from(this.attachedCSFFiles)[0];
3092
- if (moduleExportType === "meta") {
3093
- return { type: "meta", csfFile: firstAttachedCSFFile };
3094
- }
3095
- const { component } = firstAttachedCSFFile.meta;
3096
- if (!component) {
3097
- throw new Error(
3098
- `Attached CSF file does not defined a component, did you forget to export one?`
3099
- );
3100
- }
3101
- return { type: "component", component };
3102
- }
3103
- resolveModuleExport(moduleExportOrType) {
3104
- const csfFile = this.exportsToCSFFile.get(moduleExportOrType);
3105
- if (csfFile) {
3106
- return { type: "meta", csfFile };
3107
- }
3108
- const story = this.exportToStory.get(
3109
- isStory3(moduleExportOrType) ? moduleExportOrType.input : moduleExportOrType
3110
- );
3111
- if (story) {
3112
- return { type: "story", story };
3113
- }
3114
- return { type: "component", component: moduleExportOrType };
3115
- }
3116
- resolveOf(moduleExportOrType, validTypes = []) {
3117
- let resolved;
3118
- if (["component", "meta", "story"].includes(moduleExportOrType)) {
3119
- const type = moduleExportOrType;
3120
- resolved = this.resolveAttachedModuleExportType(type);
3121
- } else {
3122
- resolved = this.resolveModuleExport(moduleExportOrType);
3123
- }
3124
- if (validTypes.length && !validTypes.includes(resolved.type)) {
3125
- const prettyType = resolved.type === "component" ? "component or unknown" : resolved.type;
3126
- throw new Error(dedent`Invalid value passed to the 'of' prop. The value was resolved to a '${prettyType}' type but the only types for this block are: ${validTypes.join(
3127
- ", "
3128
- )}.
3129
- - Did you pass a component to the 'of' prop when the block only supports a story or a meta?
3130
- - ... or vice versa?
3131
- - Did you pass a story, CSF file or meta to the 'of' prop that is not indexed, ie. is not targeted by the 'stories' globs in the main configuration?`);
3132
- }
3133
- switch (resolved.type) {
3134
- case "component": {
3135
- return {
3136
- ...resolved,
3137
- projectAnnotations: this.projectAnnotations
3138
- };
3139
- }
3140
- case "meta": {
3141
- return {
3142
- ...resolved,
3143
- preparedMeta: this.store.preparedMetaFromCSFFile({ csfFile: resolved.csfFile })
3144
- };
3145
- }
3146
- case "story":
3147
- default: {
3148
- return resolved;
3149
- }
3150
- }
3151
- }
3152
- };
3153
- __name(_DocsContext, "DocsContext");
3154
- var DocsContext = _DocsContext;
3155
-
3156
- // src/preview-api/modules/preview-web/render/CsfDocsRender.ts
3157
- var _CsfDocsRender = class _CsfDocsRender {
3158
- constructor(channel, store, entry, callbacks) {
3159
- this.channel = channel;
3160
- this.store = store;
3161
- this.entry = entry;
3162
- this.callbacks = callbacks;
3163
- this.type = "docs";
3164
- this.subtype = "csf";
3165
- this.torndown = false;
3166
- this.disableKeyListeners = false;
3167
- this.preparing = false;
3168
- this.id = entry.id;
3169
- this.renderId = Date.now();
3170
- }
3171
- isPreparing() {
3172
- return this.preparing;
3173
- }
3174
- async prepare() {
3175
- this.preparing = true;
3176
- const { entryExports, csfFiles = [] } = await this.store.loadEntry(this.id);
3177
- if (this.torndown) {
3178
- throw PREPARE_ABORTED;
3179
- }
3180
- const { importPath, title } = this.entry;
3181
- const primaryCsfFile = this.store.processCSFFileWithCache(
3182
- entryExports,
3183
- importPath,
3184
- title
3185
- );
3186
- const primaryStoryId = Object.keys(primaryCsfFile.stories)[0];
3187
- this.story = this.store.storyFromCSFFile({ storyId: primaryStoryId, csfFile: primaryCsfFile });
3188
- this.csfFiles = [primaryCsfFile, ...csfFiles];
3189
- this.preparing = false;
3190
- }
3191
- isEqual(other) {
3192
- return !!(this.id === other.id && this.story && this.story === other.story);
3193
- }
3194
- docsContext(renderStoryToElement) {
3195
- if (!this.csfFiles) {
3196
- throw new Error("Cannot render docs before preparing");
3197
- }
3198
- const docsContext = new DocsContext(
3199
- this.channel,
3200
- this.store,
3201
- renderStoryToElement,
3202
- this.csfFiles
3203
- );
3204
- this.csfFiles.forEach((csfFile) => docsContext.attachCSFFile(csfFile));
3205
- return docsContext;
3206
- }
3207
- async renderToElement(canvasElement, renderStoryToElement) {
3208
- if (!this.story || !this.csfFiles) {
3209
- throw new Error("Cannot render docs before preparing");
3210
- }
3211
- const docsContext = this.docsContext(renderStoryToElement);
3212
- const { docs: docsParameter } = this.story.parameters || {};
3213
- if (!docsParameter) {
3214
- throw new Error(
3215
- `Cannot render a story in viewMode=docs if \`@storybook/addon-docs\` is not installed`
3216
- );
3217
- }
3218
- const renderer = await docsParameter.renderer();
3219
- const { render } = renderer;
3220
- const renderDocs = /* @__PURE__ */ __name(async () => {
3221
- try {
3222
- await render(docsContext, docsParameter, canvasElement);
3223
- this.channel.emit(DOCS_RENDERED, this.id);
3224
- } catch (err) {
3225
- this.callbacks.showException(err);
3226
- }
3227
- }, "renderDocs");
3228
- this.rerender = async () => renderDocs();
3229
- this.teardownRender = async ({ viewModeChanged }) => {
3230
- if (!viewModeChanged || !canvasElement) {
3231
- return;
3232
- }
3233
- renderer.unmount(canvasElement);
3234
- };
3235
- return renderDocs();
3236
- }
3237
- async teardown({ viewModeChanged } = {}) {
3238
- this.teardownRender?.({ viewModeChanged });
3239
- this.torndown = true;
3240
- }
3241
- };
3242
- __name(_CsfDocsRender, "CsfDocsRender");
3243
- var CsfDocsRender = _CsfDocsRender;
3244
-
3245
- // src/preview-api/modules/preview-web/render/MdxDocsRender.ts
3246
- import { DOCS_RENDERED as DOCS_RENDERED2 } from "storybook/internal/core-events";
3247
- var _MdxDocsRender = class _MdxDocsRender {
3248
- constructor(channel, store, entry, callbacks) {
3249
- this.channel = channel;
3250
- this.store = store;
3251
- this.entry = entry;
3252
- this.callbacks = callbacks;
3253
- this.type = "docs";
3254
- this.subtype = "mdx";
3255
- this.torndown = false;
3256
- this.disableKeyListeners = false;
3257
- this.preparing = false;
3258
- this.id = entry.id;
3259
- this.renderId = Date.now();
3260
- }
3261
- isPreparing() {
3262
- return this.preparing;
3263
- }
3264
- async prepare() {
3265
- this.preparing = true;
3266
- const { entryExports, csfFiles = [] } = await this.store.loadEntry(this.id);
3267
- if (this.torndown) {
3268
- throw PREPARE_ABORTED;
3269
- }
3270
- this.csfFiles = csfFiles;
3271
- this.exports = entryExports;
3272
- this.preparing = false;
3273
- }
3274
- isEqual(other) {
3275
- return !!(this.id === other.id && this.exports && this.exports === other.exports);
3276
- }
3277
- docsContext(renderStoryToElement) {
3278
- if (!this.csfFiles) {
3279
- throw new Error("Cannot render docs before preparing");
3280
- }
3281
- return new DocsContext(
3282
- this.channel,
3283
- this.store,
3284
- renderStoryToElement,
3285
- this.csfFiles
3286
- );
3287
- }
3288
- async renderToElement(canvasElement, renderStoryToElement) {
3289
- if (!this.exports || !this.csfFiles || !this.store.projectAnnotations) {
3290
- throw new Error("Cannot render docs before preparing");
3291
- }
3292
- const docsContext = this.docsContext(renderStoryToElement);
3293
- const { docs } = this.store.projectAnnotations.parameters ?? {};
3294
- if (!docs) {
3295
- throw new Error(
3296
- `Cannot render a story in viewMode=docs if \`@storybook/addon-docs\` is not installed`
3297
- );
3298
- }
3299
- const docsParameter = { ...docs, page: this.exports.default };
3300
- const renderer = await docs.renderer();
3301
- const { render } = renderer;
3302
- const renderDocs = /* @__PURE__ */ __name(async () => {
3303
- try {
3304
- await render(docsContext, docsParameter, canvasElement);
3305
- this.channel.emit(DOCS_RENDERED2, this.id);
3306
- } catch (err) {
3307
- this.callbacks.showException(err);
3308
- }
3309
- }, "renderDocs");
3310
- this.rerender = async () => renderDocs();
3311
- this.teardownRender = async ({ viewModeChanged } = {}) => {
3312
- if (!viewModeChanged || !canvasElement) {
3313
- return;
3314
- }
3315
- renderer.unmount(canvasElement);
3316
- this.torndown = true;
3317
- };
3318
- return renderDocs();
3319
- }
3320
- async teardown({ viewModeChanged } = {}) {
3321
- this.teardownRender?.({ viewModeChanged });
3322
- this.torndown = true;
3323
- }
3324
- };
3325
- __name(_MdxDocsRender, "MdxDocsRender");
3326
- var MdxDocsRender = _MdxDocsRender;
3327
-
3328
- // src/preview-api/modules/preview-web/PreviewWithSelection.tsx
3329
- var globalWindow = globalThis;
3330
- function focusInInput(event) {
3331
- const target = event.composedPath && event.composedPath()[0] || event.target;
3332
- return /input|textarea/i.test(target.tagName) || target.getAttribute("contenteditable") !== null;
3333
- }
3334
- __name(focusInInput, "focusInInput");
3335
- var ATTACHED_MDX_TAG = "attached-mdx";
3336
- var UNATTACHED_MDX_TAG = "unattached-mdx";
3337
- function isMdxEntry({ tags }) {
3338
- return tags?.includes(UNATTACHED_MDX_TAG) || tags?.includes(ATTACHED_MDX_TAG);
3339
- }
3340
- __name(isMdxEntry, "isMdxEntry");
3341
- function isStoryRender(r) {
3342
- return r.type === "story";
3343
- }
3344
- __name(isStoryRender, "isStoryRender");
3345
- function isDocsRender(r) {
3346
- return r.type === "docs";
3347
- }
3348
- __name(isDocsRender, "isDocsRender");
3349
- function isCsfDocsRender(r) {
3350
- return isDocsRender(r) && r.subtype === "csf";
3351
- }
3352
- __name(isCsfDocsRender, "isCsfDocsRender");
3353
- var _PreviewWithSelection = class _PreviewWithSelection extends Preview {
3354
- constructor(importFn, getProjectAnnotations, selectionStore, view) {
3355
- super(importFn, getProjectAnnotations, void 0, false);
3356
- this.importFn = importFn;
3357
- this.getProjectAnnotations = getProjectAnnotations;
3358
- this.selectionStore = selectionStore;
3359
- this.view = view;
3360
- this.initialize();
3361
- }
3362
- setupListeners() {
3363
- super.setupListeners();
3364
- globalWindow.onkeydown = this.onKeydown.bind(this);
3365
- this.channel.on(SET_CURRENT_STORY, this.onSetCurrentStory.bind(this));
3366
- this.channel.on(UPDATE_QUERY_PARAMS, this.onUpdateQueryParams.bind(this));
3367
- this.channel.on(PRELOAD_ENTRIES, this.onPreloadStories.bind(this));
3368
- }
3369
- async setInitialGlobals() {
3370
- if (!this.storyStoreValue) {
3371
- throw new CalledPreviewMethodBeforeInitializationError2({ methodName: "setInitialGlobals" });
3372
- }
3373
- const { globals } = this.selectionStore.selectionSpecifier || {};
3374
- if (globals) {
3375
- this.storyStoreValue.userGlobals.updateFromPersisted(globals);
3376
- }
3377
- this.emitGlobals();
3378
- }
3379
- // If initialization gets as far as the story index, this function runs.
3380
- async initializeWithStoryIndex(storyIndex) {
3381
- await super.initializeWithStoryIndex(storyIndex);
3382
- return this.selectSpecifiedStory();
3383
- }
3384
- // Use the selection specifier to choose a story, then render it
3385
- async selectSpecifiedStory() {
3386
- if (!this.storyStoreValue) {
3387
- throw new CalledPreviewMethodBeforeInitializationError2({
3388
- methodName: "selectSpecifiedStory"
3389
- });
3390
- }
3391
- if (this.selectionStore.selection) {
3392
- await this.renderSelection();
3393
- return;
3394
- }
3395
- if (!this.selectionStore.selectionSpecifier) {
3396
- this.renderMissingStory();
3397
- return;
3398
- }
3399
- const { storySpecifier, args } = this.selectionStore.selectionSpecifier;
3400
- const entry = this.storyStoreValue.storyIndex.entryFromSpecifier(storySpecifier);
3401
- if (!entry) {
3402
- if (storySpecifier === "*") {
3403
- this.renderStoryLoadingException(storySpecifier, new EmptyIndexError());
3404
- } else {
3405
- this.renderStoryLoadingException(
3406
- storySpecifier,
3407
- new NoStoryMatchError({ storySpecifier: storySpecifier.toString() })
3408
- );
3409
- }
3410
- return;
3411
- }
3412
- const { id: storyId, type: viewMode } = entry;
3413
- this.selectionStore.setSelection({ storyId, viewMode });
3414
- this.channel.emit(STORY_SPECIFIED, this.selectionStore.selection);
3415
- this.channel.emit(CURRENT_STORY_WAS_SET, this.selectionStore.selection);
3416
- await this.renderSelection({ persistedArgs: args });
3417
- }
3418
- // EVENT HANDLERS
3419
- // This happens when a config file gets reloaded
3420
- async onGetProjectAnnotationsChanged({
3421
- getProjectAnnotations
3422
- }) {
3423
- await super.onGetProjectAnnotationsChanged({ getProjectAnnotations });
3424
- if (this.selectionStore.selection) {
3425
- this.renderSelection();
3426
- }
3427
- }
3428
- // This happens when a glob gets HMR-ed
3429
- async onStoriesChanged({
3430
- importFn,
3431
- storyIndex
3432
- }) {
3433
- await super.onStoriesChanged({ importFn, storyIndex });
3434
- if (this.selectionStore.selection) {
3435
- await this.renderSelection();
3436
- } else {
3437
- await this.selectSpecifiedStory();
3438
- }
3439
- }
3440
- onKeydown(event) {
3441
- if (!this.storyRenders.find((r) => r.disableKeyListeners) && !focusInInput(event)) {
3442
- const { altKey, ctrlKey, metaKey, shiftKey, key, code, keyCode } = event;
3443
- this.channel.emit(PREVIEW_KEYDOWN, {
3444
- event: { altKey, ctrlKey, metaKey, shiftKey, key, code, keyCode }
3445
- });
3446
- }
3447
- }
3448
- async onSetCurrentStory(selection) {
3449
- this.selectionStore.setSelection({ viewMode: "story", ...selection });
3450
- await this.storeInitializationPromise;
3451
- this.channel.emit(CURRENT_STORY_WAS_SET, this.selectionStore.selection);
3452
- this.renderSelection();
3453
- }
3454
- onUpdateQueryParams(queryParams) {
3455
- this.selectionStore.setQueryParams(queryParams);
3456
- }
3457
- async onUpdateGlobals({ globals }) {
3458
- const currentStory = this.currentRender instanceof StoryRender && this.currentRender.story || void 0;
3459
- super.onUpdateGlobals({ globals, currentStory });
3460
- if (this.currentRender instanceof MdxDocsRender || this.currentRender instanceof CsfDocsRender) {
3461
- await this.currentRender.rerender?.();
3462
- }
3463
- }
3464
- async onUpdateArgs({ storyId, updatedArgs }) {
3465
- super.onUpdateArgs({ storyId, updatedArgs });
3466
- }
3467
- async onPreloadStories({ ids }) {
3468
- await this.storeInitializationPromise;
3469
- if (this.storyStoreValue) {
3470
- await Promise.allSettled(ids.map((id) => this.storyStoreValue?.loadEntry(id)));
3471
- }
3472
- }
3473
- // RENDERING
3474
- // We can either have:
3475
- // - a story selected in "story" viewMode,
3476
- // in which case we render it to the root element, OR
3477
- // - a story selected in "docs" viewMode,
3478
- // in which case we render the docsPage for that story
3479
- async renderSelection({ persistedArgs } = {}) {
3480
- const { renderToCanvas } = this;
3481
- if (!this.storyStoreValue || !renderToCanvas) {
3482
- throw new CalledPreviewMethodBeforeInitializationError2({ methodName: "renderSelection" });
3483
- }
3484
- const { selection } = this.selectionStore;
3485
- if (!selection) {
3486
- throw new Error("Cannot call renderSelection as no selection was made");
3487
- }
3488
- const { storyId } = selection;
3489
- let entry;
3490
- try {
3491
- entry = await this.storyStoreValue.storyIdToEntry(storyId);
3492
- } catch (err) {
3493
- if (this.currentRender) {
3494
- await this.teardownRender(this.currentRender);
3495
- }
3496
- this.renderStoryLoadingException(storyId, err);
3497
- return;
3498
- }
3499
- const storyIdChanged = this.currentSelection?.storyId !== storyId;
3500
- const viewModeChanged = this.currentRender?.type !== entry.type;
3501
- if (entry.type === "story") {
3502
- this.view.showPreparingStory({ immediate: viewModeChanged });
3503
- } else {
3504
- this.view.showPreparingDocs({ immediate: viewModeChanged });
3505
- }
3506
- if (this.currentRender?.isPreparing()) {
3507
- await this.teardownRender(this.currentRender);
3508
- }
3509
- let render;
3510
- if (entry.type === "story") {
3511
- render = new StoryRender(
3512
- this.channel,
3513
- this.storyStoreValue,
3514
- renderToCanvas,
3515
- this.mainStoryCallbacks(storyId),
3516
- storyId,
3517
- "story"
3518
- );
3519
- } else if (isMdxEntry(entry)) {
3520
- render = new MdxDocsRender(
3521
- this.channel,
3522
- this.storyStoreValue,
3523
- entry,
3524
- this.mainStoryCallbacks(storyId)
3525
- );
3526
- } else {
3527
- render = new CsfDocsRender(
3528
- this.channel,
3529
- this.storyStoreValue,
3530
- entry,
3531
- this.mainStoryCallbacks(storyId)
3532
- );
3533
- }
3534
- const lastSelection = this.currentSelection;
3535
- this.currentSelection = selection;
3536
- const lastRender = this.currentRender;
3537
- this.currentRender = render;
3538
- try {
3539
- await render.prepare();
3540
- } catch (err) {
3541
- if (lastRender) {
3542
- await this.teardownRender(lastRender);
3543
- }
3544
- if (err !== PREPARE_ABORTED) {
3545
- this.renderStoryLoadingException(storyId, err);
3546
- }
3547
- return;
3548
- }
3549
- const implementationChanged = !storyIdChanged && lastRender && !render.isEqual(lastRender);
3550
- if (persistedArgs && isStoryRender(render)) {
3551
- invariant(!!render.story);
3552
- this.storyStoreValue.args.updateFromPersisted(render.story, persistedArgs);
3553
- }
3554
- if (lastRender && !lastRender.torndown && !storyIdChanged && !implementationChanged && !viewModeChanged) {
3555
- this.currentRender = lastRender;
3556
- this.channel.emit(STORY_UNCHANGED, storyId);
3557
- this.view.showMain();
3558
- return;
3559
- }
3560
- if (lastRender) {
3561
- await this.teardownRender(lastRender, { viewModeChanged });
3562
- }
3563
- if (lastSelection && (storyIdChanged || viewModeChanged)) {
3564
- this.channel.emit(STORY_CHANGED, storyId);
3565
- }
3566
- if (isStoryRender(render)) {
3567
- invariant(!!render.story);
3568
- const {
3569
- parameters,
3570
- initialArgs,
3571
- argTypes,
3572
- unmappedArgs,
3573
- initialGlobals,
3574
- userGlobals,
3575
- storyGlobals,
3576
- globals
3577
- } = this.storyStoreValue.getStoryContext(render.story);
3578
- this.channel.emit(STORY_PREPARED, {
3579
- id: storyId,
3580
- parameters,
3581
- initialArgs,
3582
- argTypes,
3583
- args: unmappedArgs
3584
- });
3585
- this.channel.emit(GLOBALS_UPDATED2, { userGlobals, storyGlobals, globals, initialGlobals });
3586
- } else {
3587
- let { parameters } = this.storyStoreValue.projectAnnotations;
3588
- const { initialGlobals, globals } = this.storyStoreValue.userGlobals;
3589
- this.channel.emit(GLOBALS_UPDATED2, {
3590
- globals,
3591
- initialGlobals,
3592
- storyGlobals: {},
3593
- userGlobals: globals
3594
- });
3595
- if (isCsfDocsRender(render) || render.entry.tags?.includes(ATTACHED_MDX_TAG)) {
3596
- if (!render.csfFiles) {
3597
- throw new MdxFileWithNoCsfReferencesError({ storyId });
3598
- }
3599
- ({ parameters } = this.storyStoreValue.preparedMetaFromCSFFile({
3600
- csfFile: render.csfFiles[0]
3601
- }));
3602
- }
3603
- this.channel.emit(DOCS_PREPARED, {
3604
- id: storyId,
3605
- parameters
3606
- });
3607
- }
3608
- if (isStoryRender(render)) {
3609
- invariant(!!render.story);
3610
- this.storyRenders.push(render);
3611
- this.currentRender.renderToElement(
3612
- this.view.prepareForStory(render.story)
3613
- );
3614
- } else {
3615
- this.currentRender.renderToElement(
3616
- this.view.prepareForDocs(),
3617
- // This argument is used for docs, which is currently only compatible with HTMLElements
3618
- this.renderStoryToElement.bind(this)
3619
- );
3620
- }
3621
- }
3622
- async teardownRender(render, { viewModeChanged = false } = {}) {
3623
- this.storyRenders = this.storyRenders.filter((r) => r !== render);
3624
- await render?.teardown?.({ viewModeChanged });
3625
- }
3626
- // UTILITIES
3627
- mainStoryCallbacks(storyId) {
3628
- return {
3629
- showStoryDuringRender: /* @__PURE__ */ __name(() => this.view.showStoryDuringRender(), "showStoryDuringRender"),
3630
- showMain: /* @__PURE__ */ __name(() => this.view.showMain(), "showMain"),
3631
- showError: /* @__PURE__ */ __name((err) => this.renderError(storyId, err), "showError"),
3632
- showException: /* @__PURE__ */ __name((err) => this.renderException(storyId, err), "showException")
3633
- };
3634
- }
3635
- renderPreviewEntryError(reason, err) {
3636
- super.renderPreviewEntryError(reason, err);
3637
- this.view.showErrorDisplay(err);
3638
- }
3639
- renderMissingStory() {
3640
- this.view.showNoPreview();
3641
- this.channel.emit(STORY_MISSING);
3642
- }
3643
- renderStoryLoadingException(storySpecifier, err) {
3644
- logger8.error(err);
3645
- this.view.showErrorDisplay(err);
3646
- this.channel.emit(STORY_MISSING, storySpecifier);
3647
- }
3648
- // renderException is used if we fail to render the story and it is uncaught by the app layer
3649
- renderException(storyId, error) {
3650
- const { name = "Error", message = String(error), stack } = error;
3651
- const renderId = this.currentRender?.renderId;
3652
- this.channel.emit(STORY_THREW_EXCEPTION, { name, message, stack });
3653
- this.channel.emit(STORY_RENDER_PHASE_CHANGED2, { newPhase: "errored", renderId, storyId });
3654
- this.view.showErrorDisplay(error);
3655
- logger8.error(`Error rendering story '${storyId}':`);
3656
- logger8.error(error);
3657
- }
3658
- // renderError is used by the various app layers to inform the user they have done something
3659
- // wrong -- for instance returned the wrong thing from a story
3660
- renderError(storyId, { title, description }) {
3661
- const renderId = this.currentRender?.renderId;
3662
- this.channel.emit(STORY_ERRORED, { title, description });
3663
- this.channel.emit(STORY_RENDER_PHASE_CHANGED2, { newPhase: "errored", renderId, storyId });
3664
- this.view.showErrorDisplay({ message: title, stack: description });
3665
- logger8.error(`Error rendering story ${title}: ${description}`);
3666
- }
3667
- };
3668
- __name(_PreviewWithSelection, "PreviewWithSelection");
3669
- var PreviewWithSelection = _PreviewWithSelection;
3670
-
3671
- // src/preview-api/modules/preview-web/UrlStore.ts
3672
- var import_picoquery2 = __toESM(require_main(), 1);
3673
- import { global as global6 } from "@storybook/global";
3674
-
3675
- // src/preview-api/modules/preview-web/parseArgsParam.ts
3676
- import { once as once3 } from "storybook/internal/client-logger";
3677
- var import_picoquery = __toESM(require_main(), 1);
3678
- var VALIDATION_REGEXP = /^[a-zA-Z0-9 _-]*$/;
3679
- var NUMBER_REGEXP = /^-?[0-9]+(\.[0-9]+)?$/;
3680
- var HEX_REGEXP = /^#([a-f0-9]{3,4}|[a-f0-9]{6}|[a-f0-9]{8})$/i;
3681
- var COLOR_REGEXP = /^(rgba?|hsla?)\(([0-9]{1,3}),\s?([0-9]{1,3})%?,\s?([0-9]{1,3})%?,?\s?([0-9](\.[0-9]{1,2})?)?\)$/i;
3682
- var validateArgs = /* @__PURE__ */ __name((key = "", value) => {
3683
- if (key === null) {
3684
- return false;
3685
- }
3686
- if (key === "" || !VALIDATION_REGEXP.test(key)) {
3687
- return false;
3688
- }
3689
- if (value === null || value === void 0) {
3690
- return true;
3691
- }
3692
- if (value instanceof Date) {
3693
- return true;
3694
- }
3695
- if (typeof value === "number" || typeof value === "boolean") {
3696
- return true;
3697
- }
3698
- if (typeof value === "string") {
3699
- return VALIDATION_REGEXP.test(value) || NUMBER_REGEXP.test(value) || HEX_REGEXP.test(value) || COLOR_REGEXP.test(value);
3700
- }
3701
- if (Array.isArray(value)) {
3702
- return value.every((v) => validateArgs(key, v));
3703
- }
3704
- if (isPlainObject(value)) {
3705
- return Object.entries(value).every(([k, v]) => validateArgs(k, v));
3706
- }
3707
- return false;
3708
- }, "validateArgs");
3709
- var QUERY_OPTIONS = {
3710
- delimiter: ";",
3711
- // we're parsing a single query param
3712
- nesting: true,
3713
- arrayRepeat: true,
3714
- arrayRepeatSyntax: "bracket",
3715
- nestingSyntax: "js",
3716
- // objects are encoded using dot notation
3717
- valueDeserializer(str) {
3718
- if (str.startsWith("!")) {
3719
- if (str === "!undefined") {
3720
- return void 0;
3721
- }
3722
- if (str === "!null") {
3723
- return null;
3724
- }
3725
- if (str === "!true") {
3726
- return true;
3727
- }
3728
- if (str === "!false") {
3729
- return false;
3730
- }
3731
- if (str.startsWith("!date(") && str.endsWith(")")) {
3732
- return new Date(str.replaceAll(" ", "+").slice(6, -1));
3733
- }
3734
- if (str.startsWith("!hex(") && str.endsWith(")")) {
3735
- return `#${str.slice(5, -1)}`;
3736
- }
3737
- const color = str.slice(1).match(COLOR_REGEXP);
3738
- if (color) {
3739
- if (str.startsWith("!rgba") || str.startsWith("!RGBA")) {
3740
- return `${color[1]}(${color[2]}, ${color[3]}, ${color[4]}, ${color[5]})`;
3741
- }
3742
- if (str.startsWith("!hsla") || str.startsWith("!HSLA")) {
3743
- return `${color[1]}(${color[2]}, ${color[3]}%, ${color[4]}%, ${color[5]})`;
3744
- }
3745
- return str.startsWith("!rgb") || str.startsWith("!RGB") ? `${color[1]}(${color[2]}, ${color[3]}, ${color[4]})` : `${color[1]}(${color[2]}, ${color[3]}%, ${color[4]}%)`;
3746
- }
3747
- }
3748
- if (NUMBER_REGEXP.test(str)) {
3749
- return Number(str);
3750
- }
3751
- return str;
3752
- }
3753
- };
3754
- var parseArgsParam = /* @__PURE__ */ __name((argsString) => {
3755
- const parts = argsString.split(";").map((part) => part.replace("=", "~").replace(":", "="));
3756
- return Object.entries((0, import_picoquery.parse)(parts.join(";"), QUERY_OPTIONS)).reduce((acc, [key, value]) => {
3757
- if (validateArgs(key, value)) {
3758
- return Object.assign(acc, { [key]: value });
3759
- }
3760
- once3.warn(dedent`
3761
- Omitted potentially unsafe URL args.
3762
-
3763
- More info: https://storybook.js.org/docs/writing-stories/args#setting-args-through-the-url?ref=error
3764
- `);
3765
- return acc;
3766
- }, {});
3767
- }, "parseArgsParam");
3768
-
3769
- // src/preview-api/modules/preview-web/UrlStore.ts
3770
- var { history, document: document2 } = global6;
3771
- function pathToId(path) {
3772
- const match = (path || "").match(/^\/story\/(.+)/);
3773
- if (!match) {
3774
- throw new Error(`Invalid path '${path}', must start with '/story/'`);
3775
- }
3776
- return match[1];
3777
- }
3778
- __name(pathToId, "pathToId");
3779
- var getQueryString = /* @__PURE__ */ __name(({
3780
- selection,
3781
- extraParams
3782
- }) => {
3783
- const search = document2?.location.search.slice(1);
3784
- const { path, selectedKind, selectedStory, ...rest } = (0, import_picoquery2.parse)(search);
3785
- const queryStr = (0, import_picoquery2.stringify)({
3786
- ...rest,
3787
- ...extraParams,
3788
- ...selection && { id: selection.storyId, viewMode: selection.viewMode }
3789
- });
3790
- return `?${queryStr}`;
3791
- }, "getQueryString");
3792
- var setPath = /* @__PURE__ */ __name((selection) => {
3793
- if (!selection) {
3794
- return;
3795
- }
3796
- const query = getQueryString({ selection });
3797
- const { hash = "" } = document2.location;
3798
- document2.title = selection.storyId;
3799
- history.replaceState({}, "", `${document2.location.pathname}${query}${hash}`);
3800
- }, "setPath");
3801
- var isObject = /* @__PURE__ */ __name((val) => val != null && typeof val === "object" && Array.isArray(val) === false, "isObject");
3802
- var getFirstString = /* @__PURE__ */ __name((v) => {
3803
- if (v === void 0) {
3804
- return void 0;
3805
- }
3806
- if (typeof v === "string") {
3807
- return v;
3808
- }
3809
- if (Array.isArray(v)) {
3810
- return getFirstString(v[0]);
3811
- }
3812
- if (isObject(v)) {
3813
- return getFirstString(
3814
- Object.values(v).filter(Boolean)
3815
- );
3816
- }
3817
- return void 0;
3818
- }, "getFirstString");
3819
- var getSelectionSpecifierFromPath = /* @__PURE__ */ __name(() => {
3820
- if (typeof document2 !== "undefined") {
3821
- const queryStr = document2.location.search.slice(1);
3822
- const query = (0, import_picoquery2.parse)(queryStr);
3823
- const args = typeof query.args === "string" ? parseArgsParam(query.args) : void 0;
3824
- const globals = typeof query.globals === "string" ? parseArgsParam(query.globals) : void 0;
3825
- let viewMode = getFirstString(query.viewMode);
3826
- if (typeof viewMode !== "string" || !viewMode.match(/docs|story/)) {
3827
- viewMode = "story";
3828
- }
3829
- const path = getFirstString(query.path);
3830
- const storyId = path ? pathToId(path) : getFirstString(query.id);
3831
- if (storyId) {
3832
- return { storySpecifier: storyId, args, globals, viewMode };
3833
- }
3834
- }
3835
- return null;
3836
- }, "getSelectionSpecifierFromPath");
3837
- var _UrlStore = class _UrlStore {
3838
- constructor() {
3839
- this.selectionSpecifier = getSelectionSpecifierFromPath();
3840
- }
3841
- setSelection(selection) {
3842
- this.selection = selection;
3843
- setPath(this.selection);
3844
- }
3845
- setQueryParams(queryParams) {
3846
- const query = getQueryString({ extraParams: queryParams });
3847
- const { hash = "" } = document2.location;
3848
- history.replaceState({}, "", `${document2.location.pathname}${query}${hash}`);
3849
- }
3850
- };
3851
- __name(_UrlStore, "UrlStore");
3852
- var UrlStore = _UrlStore;
3853
-
3854
- // src/preview-api/modules/preview-web/WebView.ts
3855
- var import_ansi_to_html = __toESM(require_ansi_to_html(), 1);
3856
- var import_picoquery3 = __toESM(require_main(), 1);
3857
- import { logger as logger9 } from "storybook/internal/client-logger";
3858
- import { global as global7 } from "@storybook/global";
3859
- var { document: document3 } = global7;
3860
- var PREPARING_DELAY = 100;
3861
- var Mode = /* @__PURE__ */ ((Mode2) => {
3862
- Mode2["MAIN"] = "MAIN";
3863
- Mode2["NOPREVIEW"] = "NOPREVIEW";
3864
- Mode2["PREPARING_STORY"] = "PREPARING_STORY";
3865
- Mode2["PREPARING_DOCS"] = "PREPARING_DOCS";
3866
- Mode2["ERROR"] = "ERROR";
3867
- return Mode2;
3868
- })(Mode || {});
3869
- var classes = {
3870
- PREPARING_STORY: "sb-show-preparing-story",
3871
- PREPARING_DOCS: "sb-show-preparing-docs",
3872
- MAIN: "sb-show-main",
3873
- NOPREVIEW: "sb-show-nopreview",
3874
- ERROR: "sb-show-errordisplay"
3875
- };
3876
- var layoutClassMap = {
3877
- centered: "sb-main-centered",
3878
- fullscreen: "sb-main-fullscreen",
3879
- padded: "sb-main-padded"
3880
- };
3881
- var ansiConverter = new import_ansi_to_html.default({
3882
- escapeXML: true
3883
- });
3884
- var _WebView = class _WebView {
3885
- constructor() {
3886
- this.testing = false;
3887
- if (typeof document3 !== "undefined") {
3888
- const { __SPECIAL_TEST_PARAMETER__ } = (0, import_picoquery3.parse)(document3.location.search.slice(1));
3889
- switch (__SPECIAL_TEST_PARAMETER__) {
3890
- case "preparing-story": {
3891
- this.showPreparingStory();
3892
- this.testing = true;
3893
- break;
3894
- }
3895
- case "preparing-docs": {
3896
- this.showPreparingDocs();
3897
- this.testing = true;
3898
- break;
3899
- }
3900
- default:
3901
- }
3902
- }
3903
- }
3904
- // Get ready to render a story, returning the element to render to
3905
- prepareForStory(story) {
3906
- this.showStory();
3907
- this.applyLayout(story.parameters.layout);
3908
- document3.documentElement.scrollTop = 0;
3909
- document3.documentElement.scrollLeft = 0;
3910
- return this.storyRoot();
3911
- }
3912
- storyRoot() {
3913
- return document3.getElementById("storybook-root");
3914
- }
3915
- prepareForDocs() {
3916
- this.showMain();
3917
- this.showDocs();
3918
- this.applyLayout("fullscreen");
3919
- document3.documentElement.scrollTop = 0;
3920
- document3.documentElement.scrollLeft = 0;
3921
- return this.docsRoot();
3922
- }
3923
- docsRoot() {
3924
- return document3.getElementById("storybook-docs");
3925
- }
3926
- applyLayout(layout = "padded") {
3927
- if (layout === "none") {
3928
- document3.body.classList.remove(this.currentLayoutClass);
3929
- this.currentLayoutClass = null;
3930
- return;
3931
- }
3932
- this.checkIfLayoutExists(layout);
3933
- const layoutClass = layoutClassMap[layout];
3934
- document3.body.classList.remove(this.currentLayoutClass);
3935
- document3.body.classList.add(layoutClass);
3936
- this.currentLayoutClass = layoutClass;
3937
- }
3938
- checkIfLayoutExists(layout) {
3939
- if (!layoutClassMap[layout]) {
3940
- logger9.warn(
3941
- dedent`
3942
- The desired layout: ${layout} is not a valid option.
3943
- The possible options are: ${Object.keys(layoutClassMap).join(", ")}, none.
3944
- `
3945
- );
3946
- }
3947
- }
3948
- showMode(mode) {
3949
- clearTimeout(this.preparingTimeout);
3950
- Object.keys(Mode).forEach((otherMode) => {
3951
- if (otherMode === mode) {
3952
- document3.body.classList.add(classes[otherMode]);
3953
- } else {
3954
- document3.body.classList.remove(classes[otherMode]);
3955
- }
3956
- });
3957
- }
3958
- showErrorDisplay({ message = "", stack = "" }) {
3959
- let header = message;
3960
- let detail = stack;
3961
- const parts = message.split("\n");
3962
- if (parts.length > 1) {
3963
- [header] = parts;
3964
- detail = parts.slice(1).join("\n").replace(/^\n/, "");
3965
- }
3966
- document3.getElementById("error-message").innerHTML = ansiConverter.toHtml(header);
3967
- document3.getElementById("error-stack").innerHTML = ansiConverter.toHtml(detail);
3968
- this.showMode("ERROR" /* ERROR */);
3969
- }
3970
- showNoPreview() {
3971
- if (this.testing) {
3972
- return;
3973
- }
3974
- this.showMode("NOPREVIEW" /* NOPREVIEW */);
3975
- this.storyRoot()?.setAttribute("hidden", "true");
3976
- this.docsRoot()?.setAttribute("hidden", "true");
3977
- }
3978
- showPreparingStory({ immediate = false } = {}) {
3979
- clearTimeout(this.preparingTimeout);
3980
- if (immediate) {
3981
- this.showMode("PREPARING_STORY" /* PREPARING_STORY */);
3982
- } else {
3983
- this.preparingTimeout = setTimeout(
3984
- () => this.showMode("PREPARING_STORY" /* PREPARING_STORY */),
3985
- PREPARING_DELAY
3986
- );
3987
- }
3988
- }
3989
- showPreparingDocs({ immediate = false } = {}) {
3990
- clearTimeout(this.preparingTimeout);
3991
- if (immediate) {
3992
- this.showMode("PREPARING_DOCS" /* PREPARING_DOCS */);
3993
- } else {
3994
- this.preparingTimeout = setTimeout(() => this.showMode("PREPARING_DOCS" /* PREPARING_DOCS */), PREPARING_DELAY);
3995
- }
3996
- }
3997
- showMain() {
3998
- this.showMode("MAIN" /* MAIN */);
3999
- }
4000
- showDocs() {
4001
- this.storyRoot().setAttribute("hidden", "true");
4002
- this.docsRoot().removeAttribute("hidden");
4003
- }
4004
- showStory() {
4005
- this.docsRoot().setAttribute("hidden", "true");
4006
- this.storyRoot().removeAttribute("hidden");
4007
- }
4008
- showStoryDuringRender() {
4009
- document3.body.classList.add(classes.MAIN);
4010
- }
4011
- };
4012
- __name(_WebView, "WebView");
4013
- var WebView = _WebView;
4014
-
4015
- // src/preview-api/modules/preview-web/PreviewWeb.tsx
4016
- var _PreviewWeb = class _PreviewWeb extends PreviewWithSelection {
4017
- constructor(importFn, getProjectAnnotations) {
4018
- super(importFn, getProjectAnnotations, new UrlStore(), new WebView());
4019
- this.importFn = importFn;
4020
- this.getProjectAnnotations = getProjectAnnotations;
4021
- global8.__STORYBOOK_PREVIEW__ = this;
4022
- }
4023
- };
4024
- __name(_PreviewWeb, "PreviewWeb");
4025
- var PreviewWeb = _PreviewWeb;
4026
-
4027
- // src/preview-api/modules/preview-web/simulate-pageload.ts
4028
- import { global as global9 } from "@storybook/global";
4029
- var { document: document4 } = global9;
4030
- var runScriptTypes = [
4031
- "application/javascript",
4032
- "application/ecmascript",
4033
- "application/x-ecmascript",
4034
- "application/x-javascript",
4035
- "text/ecmascript",
4036
- "text/javascript",
4037
- "text/javascript1.0",
4038
- "text/javascript1.1",
4039
- "text/javascript1.2",
4040
- "text/javascript1.3",
4041
- "text/javascript1.4",
4042
- "text/javascript1.5",
4043
- "text/jscript",
4044
- "text/livescript",
4045
- "text/x-ecmascript",
4046
- "text/x-javascript",
4047
- // Support modern javascript
4048
- "module"
4049
- ];
4050
- var SCRIPT = "script";
4051
- var SCRIPTS_ROOT_ID = "scripts-root";
4052
- function simulateDOMContentLoaded() {
4053
- const DOMContentLoadedEvent = document4.createEvent("Event");
4054
- DOMContentLoadedEvent.initEvent("DOMContentLoaded", true, true);
4055
- document4.dispatchEvent(DOMContentLoadedEvent);
4056
- }
4057
- __name(simulateDOMContentLoaded, "simulateDOMContentLoaded");
4058
- function insertScript($script, callback, $scriptRoot) {
4059
- const scriptEl = document4.createElement("script");
4060
- scriptEl.type = $script.type === "module" ? "module" : "text/javascript";
4061
- if ($script.src) {
4062
- scriptEl.onload = callback;
4063
- scriptEl.onerror = callback;
4064
- scriptEl.src = $script.src;
4065
- } else {
4066
- scriptEl.textContent = $script.innerText;
4067
- }
4068
- if ($scriptRoot) {
4069
- $scriptRoot.appendChild(scriptEl);
4070
- } else {
4071
- document4.head.appendChild(scriptEl);
4072
- }
4073
- $script.parentNode.removeChild($script);
4074
- if (!$script.src) {
4075
- callback();
4076
- }
4077
- }
4078
- __name(insertScript, "insertScript");
4079
- function insertScriptsSequentially(scriptsToExecute, callback, index = 0) {
4080
- scriptsToExecute[index](() => {
4081
- index++;
4082
- if (index === scriptsToExecute.length) {
4083
- callback();
4084
- } else {
4085
- insertScriptsSequentially(scriptsToExecute, callback, index);
4086
- }
4087
- });
4088
- }
4089
- __name(insertScriptsSequentially, "insertScriptsSequentially");
4090
- function simulatePageLoad($container) {
4091
- let $scriptsRoot = document4.getElementById(SCRIPTS_ROOT_ID);
4092
- if (!$scriptsRoot) {
4093
- $scriptsRoot = document4.createElement("div");
4094
- $scriptsRoot.id = SCRIPTS_ROOT_ID;
4095
- document4.body.appendChild($scriptsRoot);
4096
- } else {
4097
- $scriptsRoot.innerHTML = "";
4098
- }
4099
- const $scripts = Array.from($container.querySelectorAll(SCRIPT));
4100
- if ($scripts.length) {
4101
- const scriptsToExecute = [];
4102
- $scripts.forEach(($script) => {
4103
- const typeAttr = $script.getAttribute("type");
4104
- if (!typeAttr || runScriptTypes.includes(typeAttr)) {
4105
- scriptsToExecute.push((callback) => insertScript($script, callback, $scriptsRoot));
4106
- }
4107
- });
4108
- if (scriptsToExecute.length) {
4109
- insertScriptsSequentially(scriptsToExecute, simulateDOMContentLoaded, void 0);
4110
- }
4111
- } else {
4112
- simulateDOMContentLoaded();
4113
- }
4114
- }
4115
- __name(simulatePageLoad, "simulatePageLoad");
4116
-
4117
- // src/preview-api/modules/preview-web/emitTransformCode.ts
4118
- async function emitTransformCode(source, context) {
4119
- const transform = context.parameters?.docs?.source?.transform;
4120
- const { id, unmappedArgs } = context;
4121
- const transformed = transform && source ? transform?.(source, context) : source;
4122
- const result = transformed ? await transformed : void 0;
4123
- addons.getChannel().emit(SNIPPET_RENDERED, {
4124
- id,
4125
- source: result,
4126
- args: unmappedArgs
4127
- });
4128
- }
4129
- __name(emitTransformCode, "emitTransformCode");
4130
-
4131
- export {
4132
- mockChannel,
4133
- addons,
4134
- HooksContext,
4135
- applyHooks,
4136
- useMemo,
4137
- useCallback,
4138
- useRef,
4139
- useState,
4140
- useReducer,
4141
- useEffect,
4142
- useChannel,
4143
- useStoryContext,
4144
- useParameter,
4145
- useArgs,
4146
- useGlobals,
4147
- makeDecorator,
4148
- combineArgs,
4149
- normalizeArrays,
4150
- normalizeStory,
4151
- mountDestructured,
4152
- decorateStory,
4153
- sanitizeStoryContextUpdate,
4154
- defaultDecorateStory,
4155
- prepareStory,
4156
- prepareMeta,
4157
- filterArgTypes,
4158
- inferControls,
4159
- normalizeProjectAnnotations,
4160
- composeStepRunners,
4161
- composeConfigs,
4162
- ReporterAPI,
4163
- getCsfFactoryAnnotations,
4164
- setDefaultProjectAnnotations,
4165
- setProjectAnnotations,
4166
- composeStory,
4167
- composeStories,
4168
- createPlaywrightTest,
4169
- StoryStore,
4170
- userOrAutoTitleFromSpecifier,
4171
- userOrAutoTitle,
4172
- sortStoriesV7,
4173
- Preview,
4174
- DocsContext,
4175
- PreviewWithSelection,
4176
- UrlStore,
4177
- WebView,
4178
- PreviewWeb,
4179
- simulateDOMContentLoaded,
4180
- simulatePageLoad,
4181
- emitTransformCode
4182
- };