@storybook/cli 10.4.0-alpha.15 → 10.4.0-alpha.17

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 (25) hide show
  1. package/dist/_node-chunks/{block-dependencies-versions-3JQG5RZL.js → block-dependencies-versions-2FTSXOV4.js} +11 -11
  2. package/dist/_node-chunks/{block-experimental-addon-test-DYNRVKQS.js → block-experimental-addon-test-MBAWHIVX.js} +9 -9
  3. package/dist/_node-chunks/{block-major-version-WUJ2IYKH.js → block-major-version-GLL4GDWB.js} +9 -9
  4. package/dist/_node-chunks/{block-node-version-ML6OV5FZ.js → block-node-version-RVJJJ4XR.js} +9 -9
  5. package/dist/_node-chunks/{block-webpack5-frameworks-IY3NOB6J.js → block-webpack5-frameworks-XEU7EO2R.js} +11 -11
  6. package/dist/_node-chunks/{chunk-522W525H.js → chunk-34WT6WHN.js} +6 -6
  7. package/dist/_node-chunks/{chunk-MNTUL4IJ.js → chunk-3FXXXDDK.js} +7 -7
  8. package/dist/_node-chunks/chunk-6HOHNSVJ.js +810 -0
  9. package/dist/_node-chunks/{chunk-TQZC6S4H.js → chunk-C2UHYVPK.js} +7 -7
  10. package/dist/_node-chunks/{chunk-KMODVRZU.js → chunk-CXC2V53L.js} +15 -15
  11. package/dist/_node-chunks/chunk-INX3KICK.js +20 -0
  12. package/dist/_node-chunks/chunk-JNFHA3R2.js +23 -0
  13. package/dist/_node-chunks/chunk-RXAW6T4J.js +527 -0
  14. package/dist/_node-chunks/chunk-SIZ5DHPZ.js +11 -0
  15. package/dist/_node-chunks/{globby-PFUJPJPH.js → globby-N46UCCVS.js} +8 -8
  16. package/dist/_node-chunks/monorepo-TVSJOSCW.js +111 -0
  17. package/dist/_node-chunks/optimized-tests-V6WOQ2XH.js +107 -0
  18. package/dist/_node-chunks/{p-limit-FVG52ILT.js → p-limit-BGPAPMNJ.js} +7 -7
  19. package/dist/_node-chunks/pattern-copy-play-6YIEGMCW.js +20 -0
  20. package/dist/_node-chunks/relaxed-limits-YQA6Y4DQ.js +107 -0
  21. package/dist/_node-chunks/{run-KUMQEGOH.js → run-IPZ5VOW3.js} +357 -1042
  22. package/dist/_node-chunks/{setup-VZ6IVNC4.js → setup-HAYJDL6K.js} +10 -10
  23. package/dist/bin/index.js +7 -7
  24. package/package.json +4 -4
  25. package/dist/_node-chunks/chunk-WSXOTENG.js +0 -11
@@ -1,10 +1,10 @@
1
- import CJS_COMPAT_NODE_URL_mvql93cv2wm from 'node:url';
2
- import CJS_COMPAT_NODE_PATH_mvql93cv2wm from 'node:path';
3
- import CJS_COMPAT_NODE_MODULE_mvql93cv2wm from "node:module";
1
+ import CJS_COMPAT_NODE_URL_cy5uq3ou7e from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_cy5uq3ou7e from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_cy5uq3ou7e from "node:module";
4
4
 
5
- var __filename = CJS_COMPAT_NODE_URL_mvql93cv2wm.fileURLToPath(import.meta.url);
6
- var __dirname = CJS_COMPAT_NODE_PATH_mvql93cv2wm.dirname(__filename);
7
- var require = CJS_COMPAT_NODE_MODULE_mvql93cv2wm.createRequire(import.meta.url);
5
+ var __filename = CJS_COMPAT_NODE_URL_cy5uq3ou7e.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_cy5uq3ou7e.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_cy5uq3ou7e.createRequire(import.meta.url);
8
8
 
9
9
  // ------------------------------------------------------------
10
10
  // end of CJS compatibility banner, injected by Storybook's esbuild configuration
@@ -13,7 +13,7 @@ import {
13
13
  __commonJS,
14
14
  __require,
15
15
  __toESM
16
- } from "./chunk-522W525H.js";
16
+ } from "./chunk-34WT6WHN.js";
17
17
 
18
18
  // ../../../node_modules/fast-glob/out/utils/array.js
19
19
  var require_array = __commonJS({
@@ -1,10 +1,10 @@
1
- import CJS_COMPAT_NODE_URL_mvql93cv2wm from 'node:url';
2
- import CJS_COMPAT_NODE_PATH_mvql93cv2wm from 'node:path';
3
- import CJS_COMPAT_NODE_MODULE_mvql93cv2wm from "node:module";
1
+ import CJS_COMPAT_NODE_URL_cy5uq3ou7e from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_cy5uq3ou7e from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_cy5uq3ou7e from "node:module";
4
4
 
5
- var __filename = CJS_COMPAT_NODE_URL_mvql93cv2wm.fileURLToPath(import.meta.url);
6
- var __dirname = CJS_COMPAT_NODE_PATH_mvql93cv2wm.dirname(__filename);
7
- var require = CJS_COMPAT_NODE_MODULE_mvql93cv2wm.createRequire(import.meta.url);
5
+ var __filename = CJS_COMPAT_NODE_URL_cy5uq3ou7e.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_cy5uq3ou7e.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_cy5uq3ou7e.createRequire(import.meta.url);
8
8
 
9
9
  // ------------------------------------------------------------
10
10
  // end of CJS compatibility banner, injected by Storybook's esbuild configuration
@@ -12,14 +12,14 @@ var require = CJS_COMPAT_NODE_MODULE_mvql93cv2wm.createRequire(import.meta.url);
12
12
  import {
13
13
  globby,
14
14
  globbySync
15
- } from "./chunk-TQZC6S4H.js";
15
+ } from "./chunk-C2UHYVPK.js";
16
16
  import {
17
17
  require_semver
18
- } from "./chunk-MNTUL4IJ.js";
18
+ } from "./chunk-3FXXXDDK.js";
19
19
  import {
20
20
  __commonJS,
21
21
  __toESM
22
- } from "./chunk-522W525H.js";
22
+ } from "./chunk-34WT6WHN.js";
23
23
 
24
24
  // ../../../node_modules/picocolors/picocolors.js
25
25
  var require_picocolors = __commonJS({
@@ -123,11 +123,11 @@ var import_picocolors2 = __toESM(require_picocolors(), 1), import_semver = __toE
123
123
  // src/autoblock/index.ts
124
124
  var blockers = () => [
125
125
  // add/remove blockers here
126
- import("./block-dependencies-versions-3JQG5RZL.js"),
127
- import("./block-node-version-ML6OV5FZ.js"),
128
- import("./block-webpack5-frameworks-IY3NOB6J.js"),
129
- import("./block-major-version-WUJ2IYKH.js"),
130
- import("./block-experimental-addon-test-DYNRVKQS.js")
126
+ import("./block-dependencies-versions-2FTSXOV4.js"),
127
+ import("./block-node-version-RVJJJ4XR.js"),
128
+ import("./block-webpack5-frameworks-XEU7EO2R.js"),
129
+ import("./block-major-version-GLL4GDWB.js"),
130
+ import("./block-experimental-addon-test-MBAWHIVX.js")
131
131
  ], autoblock = async (options, list = blockers()) => list.length === 0 ? null : await Promise.all(
132
132
  list.map(async (i) => {
133
133
  let blocker = (await i).blocker;
@@ -351,7 +351,7 @@ var processProject = async ({
351
351
  };
352
352
  }
353
353
  }, collectProjects = async (options, configDirs, onProjectScanStart) => {
354
- let { default: pLimit } = await import("./p-limit-FVG52ILT.js"), currentCLIVersion = versions.storybook, limit = pLimit(5), projectPromises = configDirs.map(
354
+ let { default: pLimit } = await import("./p-limit-BGPAPMNJ.js"), currentCLIVersion = versions.storybook, limit = pLimit(5), projectPromises = configDirs.map(
355
355
  (configDir) => limit(
356
356
  () => processProject({
357
357
  configDir,
@@ -0,0 +1,20 @@
1
+ import CJS_COMPAT_NODE_URL_cy5uq3ou7e from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_cy5uq3ou7e from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_cy5uq3ou7e from "node:module";
4
+
5
+ var __filename = CJS_COMPAT_NODE_URL_cy5uq3ou7e.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_cy5uq3ou7e.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_cy5uq3ou7e.createRequire(import.meta.url);
8
+
9
+ // ------------------------------------------------------------
10
+ // end of CJS compatibility banner, injected by Storybook's esbuild configuration
11
+ // ------------------------------------------------------------
12
+
13
+ // src/ai/utils/type-import-source.ts
14
+ function getTypeImportSource(projectInfo) {
15
+ return projectInfo.framework || projectInfo.rendererPackage || "@storybook/react";
16
+ }
17
+
18
+ export {
19
+ getTypeImportSource
20
+ };
@@ -0,0 +1,23 @@
1
+ import CJS_COMPAT_NODE_URL_cy5uq3ou7e from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_cy5uq3ou7e from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_cy5uq3ou7e from "node:module";
4
+
5
+ var __filename = CJS_COMPAT_NODE_URL_cy5uq3ou7e.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_cy5uq3ou7e.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_cy5uq3ou7e.createRequire(import.meta.url);
8
+
9
+ // ------------------------------------------------------------
10
+ // end of CJS compatibility banner, injected by Storybook's esbuild configuration
11
+ // ------------------------------------------------------------
12
+
13
+ // src/ai/utils/docs-markdown-url.ts
14
+ function getDocsMarkdownUrl(path, projectInfo) {
15
+ let { majorVersion, renderer = "react", language = "ts" } = projectInfo ?? {}, versionSegment = majorVersion ? `/${majorVersion}` : "", params = new URLSearchParams();
16
+ renderer && params.set("renderer", renderer), params.set("language", language);
17
+ let query = params.toString();
18
+ return `https://storybook.js.org/docs${versionSegment}/${path}.md${query ? `?${query}` : ""}`;
19
+ }
20
+
21
+ export {
22
+ getDocsMarkdownUrl
23
+ };
@@ -0,0 +1,527 @@
1
+ import CJS_COMPAT_NODE_URL_cy5uq3ou7e from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_cy5uq3ou7e from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_cy5uq3ou7e from "node:module";
4
+
5
+ var __filename = CJS_COMPAT_NODE_URL_cy5uq3ou7e.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_cy5uq3ou7e.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_cy5uq3ou7e.createRequire(import.meta.url);
8
+
9
+ // ------------------------------------------------------------
10
+ // end of CJS compatibility banner, injected by Storybook's esbuild configuration
11
+ // ------------------------------------------------------------
12
+
13
+ // src/ai/utils/ext.ts
14
+ function ext(language, jsx) {
15
+ return language === "ts" ? jsx ? "tsx" : "ts" : jsx ? "jsx" : "js";
16
+ }
17
+
18
+ // src/ai/utils/markdown.ts
19
+ import { dedent } from "ts-dedent";
20
+ function listRules(rules) {
21
+ return dedent`
22
+ ${rules.filter(Boolean).map((s, i) => `${i + 1}. ${s}`).join(`
23
+ `)}
24
+ `;
25
+ }
26
+ function listSteps(steps, options) {
27
+ let level = options?.level ?? 2, prefix = "#".repeat(level);
28
+ return dedent`
29
+ ${steps.filter(Boolean).map((step, i) => `${prefix} Step ${i + 1} \u2014 ${step.title}
30
+
31
+ ${step.body}`).join(`
32
+
33
+ `)}
34
+ `;
35
+ }
36
+
37
+ // src/ai/setup-prompts/partials/steps.ts
38
+ import { dedent as dedent3 } from "ts-dedent";
39
+
40
+ // src/ai/setup-prompts/partials/examples.ts
41
+ import { dedent as dedent2 } from "ts-dedent";
42
+ function getPreviewExample(projectInfo) {
43
+ let { configDir, language, framework, rendererPackage } = projectInfo, tsx = ext(language, !0), typeImport = framework || rendererPackage || "@storybook/react-vite";
44
+ return language === "js" ? dedent2`
45
+ \`\`\`${tsx}
46
+ // ${configDir}/preview.${tsx}
47
+ import '../src/index.css';
48
+ import MockDate from 'mockdate';
49
+ import { initialize, mswLoader } from 'msw-storybook-addon';
50
+ import { SessionProvider } from '../src/contexts/SessionContext';
51
+ import { mswHandlers } from './msw-handlers';
52
+
53
+ initialize({ onUnhandledRequest: 'bypass' });
54
+
55
+ const preview = {
56
+ decorators: [
57
+ (Story) => (
58
+ <SessionProvider>
59
+ <Story />
60
+ </SessionProvider>
61
+ ),
62
+ ],
63
+ loaders: [mswLoader],
64
+ parameters: { msw: { handlers: mswHandlers } },
65
+ async beforeEach() {
66
+ localStorage.setItem('theme', 'dark');
67
+ MockDate.set('2024-04-01T12:00:00Z');
68
+ },
69
+ };
70
+
71
+ export default preview;
72
+ \`\`\`
73
+ ` : dedent2`
74
+ \`\`\`${tsx}
75
+ // ${configDir}/preview.${tsx}
76
+ import type { Preview } from '${typeImport}';
77
+ import '../src/index.css';
78
+ import MockDate from 'mockdate';
79
+ import { initialize, mswLoader } from 'msw-storybook-addon';
80
+ import { SessionProvider } from '../src/contexts/SessionContext';
81
+ import { mswHandlers } from './msw-handlers';
82
+
83
+ initialize({ onUnhandledRequest: 'bypass' });
84
+
85
+ const preview: Preview = {
86
+ decorators: [
87
+ (Story) => (
88
+ <SessionProvider>
89
+ <Story />
90
+ </SessionProvider>
91
+ ),
92
+ ],
93
+ loaders: [mswLoader],
94
+ parameters: { msw: { handlers: mswHandlers } },
95
+ async beforeEach() {
96
+ localStorage.setItem('theme', 'dark');
97
+ MockDate.set('2024-04-01T12:00:00Z');
98
+ },
99
+ };
100
+
101
+ export default preview;
102
+ \`\`\`
103
+ `;
104
+ }
105
+ function getPortalDecoratorExample(projectInfo) {
106
+ let { language } = projectInfo, tsx = ext(language, !0);
107
+ return dedent2`
108
+ \`\`\`${tsx}
109
+ // Add this entry to the \`decorators\` array of your preview config:
110
+ (Story) => {
111
+ for (const id of ['modal-root', 'drawer-root', 'toast-root']) {
112
+ if (!document.getElementById(id)) {
113
+ const el = document.createElement('div');
114
+ el.id = id;
115
+ document.body.appendChild(el);
116
+ }
117
+ }
118
+ return <Story />;
119
+ }
120
+ \`\`\`
121
+ `;
122
+ }
123
+ function getMainConfigExample(projectInfo) {
124
+ let { configDir, framework, rendererPackage, language } = projectInfo, ts = ext(language, !1), typeImport = framework || rendererPackage || "@storybook/react";
125
+ return language === "js" ? dedent2`
126
+ \`\`\`js
127
+ // ${configDir}/main.js
128
+ const config = { staticDirs: ['../public'] };
129
+ export default config;
130
+ \`\`\`
131
+ ` : dedent2`
132
+ \`\`\`${ts}
133
+ // ${configDir}/main.${ts}
134
+ import type { StorybookConfig } from '${typeImport}';
135
+
136
+ const config: StorybookConfig = { staticDirs: ['../public'] };
137
+ export default config;
138
+ \`\`\`
139
+ `;
140
+ }
141
+ function getStoryExample(projectInfo) {
142
+ let { language, framework, rendererPackage } = projectInfo, tsx = ext(language, !0), typeImport = framework || rendererPackage || "@storybook/react-vite";
143
+ return language === "js" ? dedent2`
144
+ \`\`\`${tsx}
145
+ import { expect } from 'storybook/test';
146
+ import { Button } from './Button';
147
+
148
+ const meta = {
149
+ component: Button,
150
+ tags: ['ai-generated', 'needs-work'], // strip 'needs-work' once vitest passes
151
+ };
152
+
153
+ export default meta;
154
+
155
+ // Smoke check — one is enough per file
156
+ export const Primary = {
157
+ args: { children: 'Order now' },
158
+ play: async ({ canvas }) => {
159
+ await expect(canvas.getByRole('button', { name: /order now/i })).toBeVisible();
160
+ },
161
+ };
162
+
163
+ // Variant-only stories: no play needed
164
+ export const Clear = { args: { children: 'Cancel', clear: true } };
165
+ export const Large = { args: { children: 'Checkout', large: true } };
166
+ export const WithIcon = { args: { icon: 'cart', 'aria-label': 'food cart' } };
167
+ \`\`\`
168
+ ` : dedent2`
169
+ \`\`\`${tsx}
170
+ import type { Meta, StoryObj } from '${typeImport}';
171
+ import { expect } from 'storybook/test';
172
+ import { Button } from './Button';
173
+
174
+ const meta = {
175
+ component: Button,
176
+ tags: ['ai-generated', 'needs-work'], // strip 'needs-work' once vitest passes
177
+ } satisfies Meta<typeof Button>;
178
+
179
+ export default meta;
180
+ type Story = StoryObj<typeof meta>;
181
+
182
+ // Smoke check — one is enough per file
183
+ export const Primary: Story = {
184
+ args: { children: 'Order now' },
185
+ play: async ({ canvas }) => {
186
+ await expect(canvas.getByRole('button', { name: /order now/i })).toBeVisible();
187
+ },
188
+ };
189
+
190
+ // Variant-only stories: no play needed
191
+ export const Clear: Story = { args: { children: 'Cancel', clear: true } };
192
+ export const Large: Story = { args: { children: 'Checkout', large: true } };
193
+ export const WithIcon: Story = { args: { icon: 'cart', 'aria-label': 'food cart' } };
194
+ \`\`\`
195
+ `;
196
+ }
197
+ function getInteractionPlayExample(projectInfo) {
198
+ let { language } = projectInfo, tsx = ext(language, !0);
199
+ return dedent2`
200
+ \`\`\`${tsx}
201
+ export const FilledForm${language === "ts" ? ": Story" : ""} = {
202
+ play: async ({ canvas, userEvent }) => {
203
+ await userEvent.type(canvas.getByLabelText('email'), 'a@b.com', { delay: 50 });
204
+ await userEvent.click(canvas.getByRole('button', { name: /submit/i }));
205
+ await expect(await canvas.findByText(/welcome/i)).toBeVisible();
206
+ },
207
+ };
208
+ \`\`\`
209
+ `;
210
+ }
211
+
212
+ // src/ai/setup-prompts/partials/steps.ts
213
+ function discoveryStepStrict(projectInfo, { tsx }) {
214
+ return {
215
+ title: "Discover the runtime (\u226412 reads)",
216
+ body: dedent3`
217
+ Identify, in this order, using Glob/Grep first then targeted Reads:
218
+
219
+ - \`index.html\` — \`<link rel="stylesheet">\` tags, inline \`<style>\` blocks, fonts, and any \`<div id="...">\` mount or portal roots that aren't created by JS
220
+ - entry file (\`main.${tsx}\` / \`index.${tsx}\`) — providers wrapping \`<App />\`, root CSS imports
221
+ - \`App.${tsx}\` — top-level layout, router usage, providers it consumes
222
+ - providers / context files — what they expose
223
+ - root CSS — global styles, CSS variables, theme tokens (both JS-imported CSS **and** anything linked from \`index.html\`)
224
+ - data hooks — \`fetch(...)\`, \`useQuery\`, \`axios\`, etc. (capture base URL + endpoints actually called during render)
225
+ - browser state actually read at render — \`localStorage\`/\`sessionStorage\`/cookie keys
226
+ - portal targets — \`createPortal(...)\` and the DOM ids it mounts to (e.g. \`#modal-root\`)
227
+ - 1–2 real page or feature components (your story source-of-truth for JSX patterns)
228
+
229
+ Stop reading once you can answer: *"What providers, CSS, browser state, and network calls must the preview supply for a typical page to render?"*
230
+ `
231
+ };
232
+ }
233
+ function discoveryStepRelaxed(projectInfo, { tsx }) {
234
+ return {
235
+ title: "Discover the runtime (\u226440 reads)",
236
+ body: dedent3`
237
+ Identify, in this order, using Glob/Grep first then targeted Reads:
238
+
239
+ - \`index.html\` — \`<link rel="stylesheet">\` tags, inline \`<style>\` blocks, fonts, and any \`<div id="...">\` mount or portal roots that aren't created by JS
240
+ - entry file (\`main.${tsx}\` / \`index.${tsx}\`) — providers wrapping \`<App />\`, root CSS imports
241
+ - \`App.${tsx}\` — top-level layout, router usage, providers it consumes
242
+ - providers / context files — what they expose
243
+ - root CSS — global styles, CSS variables, theme tokens (both JS-imported CSS **and** anything linked from \`index.html\`)
244
+ - data hooks — \`fetch(...)\`, \`useQuery\`, \`axios\`, etc. (capture base URL + endpoints actually called during render)
245
+ - browser state actually read at render — \`localStorage\`/\`sessionStorage\`/cookie keys
246
+ - portal targets — \`createPortal(...)\` and the DOM ids it mounts to (e.g. \`#modal-root\`)
247
+ - 1–20 real page or feature components (your story source-of-truth for JSX patterns)
248
+
249
+ Stop reading once you can answer: *"What providers, CSS, browser state, and network calls must the preview supply for a typical page to render? What surrounding context do components need to render?"*
250
+ `
251
+ };
252
+ }
253
+ function verifyStep(projectInfo, { packageManager, tsx }) {
254
+ return {
255
+ title: "Verify in one batch, then iterate only on failures",
256
+ body: dedent3`**Read this rule once before running anything:** the first vitest invocation must run **all** the new stories together. No single-file runs before the batch.
257
+
258
+ \`\`\`bash
259
+ npx vitest --project storybook run
260
+ \`\`\`
261
+
262
+ Then run the project's TypeScript check (use the script from \`package.json\` — typically \`tsc --noEmit\` or \`${packageManager.getRunCommand("typecheck")}\`). Read the raw output once; don't pipe it through repeated \`grep\`/\`head\` invocations to slice it.
263
+
264
+ For each failure:
265
+
266
+ 1. Read the error.
267
+ 2. If multiple stories share the failure, fix the shared preview setup, not the stories.
268
+ 3. Re-run vitest **only for the affected file(s)**: \`npx vitest --project storybook run path/to/Foo.stories.${tsx}\`.
269
+ 4. Repeat until the file passes, then move on. Cap retries at ~5 per file — if it still fails, leave \`'needs-work'\` tag to inform the user.
270
+ 5. When you keep failing on a story, play function, etc., do not substitute it for easier content that contributes less to codebase understanding.
271
+
272
+ **After a file passes**, edit its meta and remove \`'needs-work'\` so its tags become \`['ai-generated']\`. Files you couldn't fix keep \`['ai-generated', 'needs-work']\` — move on, don't loop forever.`
273
+ };
274
+ }
275
+ function cleanupStep({ needsUserOnboarding }, ctx) {
276
+ return {
277
+ title: "Clean up",
278
+ body: `Before finishing, remove debug code, broad mocks added during diagnosis, unused deps, and eval artifacts. ${needsUserOnboarding ? "You must preserve the components, CSS, stories and MDX docs initially created by Storybook, as they are required for user onboarding in the UI." : "Delete the components, CSS, stories and MDX docs initially created by Storybook only if you managed to write successful stories."}`
279
+ };
280
+ }
281
+ function monorepoStep(projectInfo, ctx) {
282
+ return {
283
+ title: "Monorepo preparation",
284
+ body: dedent3`Build any local monorepo dependencies identified during discovery, and keep track of existing errors in the codebase unrelated to the package changes you'll make.`
285
+ };
286
+ }
287
+ function buildSharedPreviewStep(projectInfo, { configDir, tsx }) {
288
+ return {
289
+ title: "Build the shared preview",
290
+ body: dedent3` Set up Storybook **once** so most stories work without per-story setup. **Edit the existing \`${configDir}/preview.${tsx}\`** (created by \`storybook init\`) — add to its existing config object, don't replace it.
291
+
292
+ The complete shape should look like this (merge the new pieces into what's already there):
293
+
294
+ ${getPreviewExample(projectInfo)}
295
+
296
+ Rules for the preview:
297
+
298
+ - Use the **real** provider tree and the **real** root CSS import. Don't invent providers.
299
+ - If the app's CSS is loaded via \`<link>\` in \`index.html\` (rather than imported in JS), import the same file from preview so stories render with the same styles.
300
+ - Seed only the specific browser-state keys the app actually reads. Do **not** clear all of \`localStorage\`/\`sessionStorage\`/cookies, and do not reset Storybook's own state.
301
+ - Use \`mockdate\` only when render output depends on the date.
302
+ - Do not mock \`window\`, \`document\`, \`navigator\`, observers, or \`fetch\` directly.
303
+ `
304
+ };
305
+ }
306
+ function buildPortalStep(projectInfo, { configDir, tsx }) {
307
+ return {
308
+ title: "Portals (in a decorator, not `preview-body.html`)",
309
+ body: dedent3`If you found \`createPortal(..., document.getElementById('foo'))\` in discovery, **add a decorator in \`${configDir}/preview.${tsx}\` that creates the portal root** before the story renders. Do not use \`preview-body.html\`.
310
+
311
+ ${getPortalDecoratorExample(projectInfo)}
312
+
313
+ Add this decorator to the \`decorators\` array of your preview config. Skip this step entirely if portals only target \`document.body\`.`
314
+ };
315
+ }
316
+ function mswStep(projectInfo, { configDir, mswInstall, ts }) {
317
+ return {
318
+ title: "MSW handlers (only what stories will hit)",
319
+ body: `Use \`msw-storybook-addon\`. Install with:
320
+
321
+ \`\`\`bash
322
+ ${mswInstall}
323
+ npx msw init ./public --save
324
+ \`\`\`
325
+
326
+ Make sure \`${configDir}/main.${ts}\` serves \`./public\`:
327
+
328
+ ${getMainConfigExample(projectInfo)}
329
+
330
+ Put handlers in \`${configDir}/msw-handlers.${ts}\`. Cover only the endpoints your stories will exercise \u2014 no catch-alls.
331
+
332
+ \`\`\`${ts}
333
+ // ${configDir}/msw-handlers.${ts}
334
+ import { http, HttpResponse } from 'msw';
335
+
336
+ export const mswHandlers = {
337
+ products: [
338
+ http.get('https://api.example.com/products', () =>
339
+ HttpResponse.json({ items: [{ id: 'p1', name: 'Example', price: 42 }] })
340
+ ),
341
+ ],
342
+ };
343
+ \`\`\`
344
+ `
345
+ };
346
+ }
347
+ function writeStoriesStep(projectInfo, { tsx }) {
348
+ return {
349
+ title: "Write up to 10 story files (in one batch)",
350
+ body: dedent3`
351
+
352
+ This step has **two required deliverables**:
353
+
354
+ a. Up to 10 colocated \`*.stories.${tsx}\` files for meaningful targets in the codebase.
355
+ b. **Exactly one \`CssCheck\` story** added to one of those files (spec below). This step is not complete without it.
356
+
357
+ **Substep a — pick targets and write the files.** Pick ~10 meaningful targets from the real codebase (low-level reusable → page components). Skip subcomponents, hooks, contexts, helpers, and \`App\` itself when real page components exist.
358
+
359
+ Each story file: ~3 exports for typical components, up to ~10 when warranted by real usage. Copy JSX patterns from real pages/routes/tests.
360
+
361
+ **Tag every new story file with \`['ai-generated', 'needs-work']\` from the start.** You will remove \`'needs-work'\` only after vitest confirms the file passes. This way, anything not yet verified — including stories you ran out of time to fix — stays correctly marked.
362
+
363
+ ${getStoryExample(projectInfo)}
364
+
365
+ Story rules:
366
+
367
+ - Start every meta with \`tags: ['ai-generated', 'needs-work']\`.
368
+ - Show all imports explicitly.
369
+ - Don't add a custom \`title\`.
370
+ - Don't build large story-specific harnesses — fix preview instead.
371
+ - Don't create new app components.
372
+
373
+ **Substep b — add the single \`CssCheck\` story.** Before you finish this step, pick **one** visually distinctive component from the files you just wrote and add a \`CssCheck\` export to that file. Exactly **one** \`CssCheck\` across the whole project — not one per file. This step is not complete until the story exists.
374
+
375
+ Why it's mandatory: \`toBeVisible\` passes on an unstyled component. A concrete \`getComputedStyle\` value is the only proof that the shared preview actually loaded the app's CSS — without it, you have no idea whether your stories are rendering correctly.
376
+
377
+ How: read a real styling value from the component's source (e.g. a hex color in styled-components, a Tailwind class like \`bg-blue-600\`, a CSS variable from the theme), and assert the resolved \`getComputedStyle\` value:
378
+
379
+ \`\`\`${tsx}
380
+ export const CssCheck: Story = {
381
+ args: { children: 'Submit' },
382
+ play: async ({ canvas }) => {
383
+ const button = canvas.getByRole('button', { name: /submit/i });
384
+ // PrimaryButton uses bg-blue-600 — fails if Tailwind / global CSS did not load.
385
+ await expect(getComputedStyle(button).backgroundColor).toBe('rgb(37, 99, 235)');
386
+ },
387
+ };
388
+ \`\`\`
389
+ `
390
+ };
391
+ }
392
+ function interactionPlayStep(projectInfo, { tsx }) {
393
+ return {
394
+ title: "Add `play` functions only where they prove something non-trivial",
395
+ body: dedent3`
396
+ **Do not put a \`play\` on every story.** A \`play\` is worth writing only when it asserts something the rendered output alone doesn't already prove. Prefer one good \`play\` per file over five redundant ones.
397
+
398
+ Write a \`play\` when it can verify:
399
+
400
+ - an **interaction** (form fill + submit, click → menu opens, tab change reveals panel)
401
+ - **async data** actually arrived from MSW (waiting for mocked content to replace a spinner)
402
+ - a **portal** rendered into the right root (query via \`canvasElement.ownerDocument\`)
403
+ - a **CSS-driven state** that matters semantically (e.g. theme color, disabled styling, layout that confirms the global stylesheet loaded)
404
+ - **accessibility** that the component is responsible for (correct role/label exposure)
405
+
406
+ **Skip \`play\` entirely** when a story is just a static variant of the same component (different \`args\`, no new behavior). Repeating \`getByRole(...).toBeVisible()\` across \`Clear\`, \`Large\`, \`WithIcon\` etc. is redundant — the render itself already fails the test if the component throws or doesn't mount.
407
+
408
+ **Smoke plays must prove something the render alone doesn't.** A play that does only \`await expect(canvas.getByRole('button')).toBeVisible()\` adds nothing — the render already failed if the button didn't mount. Acceptable smoke plays assert one of:
409
+
410
+ - an **aria attribute reflecting state** (\`aria-expanded\`, \`aria-disabled\`, \`aria-checked\`, \`aria-current\`)
411
+ - a **prop value rendered as text or attribute** (e.g. \`args.label\` appears in the DOM, \`href\` matches \`args.to\`)
412
+ - **async content arriving** (\`findBy*\`, \`waitFor\` — proves the loader/MSW handler actually resolved)
413
+ - a **portal mounting in the right root** (queried via \`canvasElement.ownerDocument.body\`)
414
+
415
+ If none of those apply, skip the \`play\` and rely on the render itself.
416
+
417
+ Concretely, in a \`Button.stories.${tsx}\` with \`Primary\`, \`Clear\`, \`Large\`, \`WithIcon\`:
418
+
419
+ - \`Primary\` — keep one smoke \`play\` (one is enough for the file).
420
+ - \`Clear\`, \`Large\`, \`WithIcon\` — **no \`play\`**. They're variant-only stories.
421
+
422
+ (The single \`CssCheck\` story for the whole project was added in Step 5 — don't add another one here.)
423
+
424
+ Imports & play context — get this right or vitest will fail in subtle ways:
425
+
426
+ - \`expect\` and \`waitFor\` come from \`'storybook/test'\` — import those.
427
+ - \`canvas\`, \`userEvent\`, and \`canvasElement\` come from the **play arguments**: \`async ({ canvas, userEvent, canvasElement }) => { ... }\`. **Do not** \`import { userEvent } from 'storybook/test'\` and **do not** write \`const canvas = within(canvasElement)\` — both are already provided.
428
+ - For **portal queries only**, query via \`canvasElement.ownerDocument.body\`. You may import \`within\` from \`'storybook/test'\` for that case (e.g. \`within(canvasElement.ownerDocument.body).findByTestId(...)\`). Don't use \`within\` for anything else.
429
+
430
+ ${getInteractionPlayExample(projectInfo)}`
431
+ };
432
+ }
433
+
434
+ // src/ai/setup-prompts/partials/rules.ts
435
+ import { dedent as dedent4 } from "ts-dedent";
436
+
437
+ // ../../core/src/shared/utils/get-monorepo-type.ts
438
+ import { existsSync, readFileSync } from "node:fs";
439
+ import { join } from "node:path";
440
+ import { getProjectRoot } from "storybook/internal/common";
441
+ var monorepoConfigs = {
442
+ Nx: "nx.json",
443
+ Turborepo: "turbo.json",
444
+ Lerna: "lerna.json",
445
+ Rush: "rush.json",
446
+ Lage: "lage.config.json"
447
+ }, getMonorepoType = () => {
448
+ let monorepoType = Object.keys(monorepoConfigs).find((monorepo) => {
449
+ let configFile = join(getProjectRoot(), monorepoConfigs[monorepo]);
450
+ return existsSync(configFile);
451
+ });
452
+ if (monorepoType)
453
+ return monorepoType;
454
+ if (!existsSync(join(getProjectRoot(), "package.json")))
455
+ return;
456
+ if (JSON.parse(
457
+ readFileSync(join(getProjectRoot(), "package.json"), { encoding: "utf8" })
458
+ )?.workspaces)
459
+ return "Workspaces";
460
+ };
461
+
462
+ // src/ai/setup-prompts/partials/rules.ts
463
+ function toolsVsShellRule(ctx) {
464
+ return dedent4`**Discover with Glob/Grep/Read, not shell.** Never use \`ls\`, \`find\`, \`cat\`, \`head\`, \`tail\`, shell \`grep\`, \`sed\`, or \`node -e\` for discovery or for editing files in bulk — these are slower per call and violate caching. Substitute bash commands for the specific tool names listed below, or available tools with the closest semantics:
465
+ - List a directory → \`Glob('src/components/*')\` (alt names: \`search_files\`, \`file_search\`), not \`ls src/components\`.
466
+ - Search a string → \`Grep('pattern', { path: 'src' })\` (alt names: \`grep_search\`, \`search_files\`), not \`grep -rn ...\` or \`find ... | xargs grep\`.
467
+ - Read a file → \`Read('path/to/file')\` (alt names: \`read_file\`), not \`cat\`/\`head\`/\`tail\`.
468
+ - Bulk-edit many files → multiple \`Edit\` calls (alt names: \`apply_patch\`, \`replace_in_file\`, \`replace\`), or one \`Edit\` with \`replace_all\` (alt names: \`replace\` with \`allow_multiple\`), not \`sed -i\`.`;
469
+ }
470
+ function nodeModuleReadsRule(ctx) {
471
+ return dedent4`**Never read or grep inside \`node_modules\`.** The imports shown in this prompt are correct — don't verify them by introspecting installed packages. If something seems off, re-read this prompt, not \`node_modules\`.`;
472
+ }
473
+ function monorepoRule(ctx) {
474
+ let monorepoType = getMonorepoType();
475
+ if (monorepoType)
476
+ return `**${monorepoType} monorepo.** Don't initially look for config or existing Storybook content in other packages. Start exploring from config and tooling local to the package where you are asked to set up Storybook. If it uses local monorepo dependencies, build all dependencies found during discovery before writing stories or running tests.`;
477
+ }
478
+ function packageManagerRule({ packageManagerName }) {
479
+ return packageManagerName ? dedent4`**Use \`${packageManagerName}\` for every install** (detected from this project's lockfile).` : "**Detect the package manager once** from the lockfile (`pnpm-lock.yaml` \u2192 pnpm, `yarn.lock` \u2192 yarn, `bun.lockb` \u2192 bun, otherwise npm) and use it for every install in this trial.";
480
+ }
481
+ function editOverWriteRule({ configDir, tsx }) {
482
+ return dedent4`**Edit > Write.** For any file you've Read, use \`Edit\`. Use \`Write\` only for new files. The project already has a \`${configDir}/preview.${tsx}\` from \`storybook init\` — **Edit** it, do not overwrite.`;
483
+ }
484
+ function batchTestsRule(ctx) {
485
+ return dedent4`**Batch the test loop.** Write **all** stories first, then run vitest **once** across everything. No per-file vitest runs until after that first batch run reveals failures.`;
486
+ }
487
+ function readBudgetRule(ctx) {
488
+ return dedent4`**Read budget: ~12 files for discovery.** Before writing any code you may Read at most ~12 files (\`index.html\`, entry, App, providers, routing, root CSS, 2–3 representative pages/components, 1–2 hooks, 1 test). If you need more, summarize and move on.`;
489
+ }
490
+ function readBudgetRuleRelaxed(ctx) {
491
+ return dedent4`**Read budget: ~40 files for discovery.** Before writing any code you may Read at most ~40 files: \`index.html\`, entry, App, providers, routing, root CSS, 1–2 hooks, 1 test, and spend the rest on components. You may read direct component dependencies essential to their understanding only after having read 20 components (or all components if fewer in the codebase).`;
492
+ }
493
+ function preferSharedFixesRule({
494
+ configDir,
495
+ tsx
496
+ }) {
497
+ return dedent4`**Prefer fixing the shared \`${configDir}/preview.${tsx}\`** over story-local workarounds when multiple stories fail the same way.`;
498
+ }
499
+ function noPolishRule(ctx) {
500
+ return dedent4`**Stop when the success criteria are met** — don't keep polishing.`;
501
+ }
502
+
503
+ export {
504
+ ext,
505
+ listRules,
506
+ listSteps,
507
+ discoveryStepStrict,
508
+ discoveryStepRelaxed,
509
+ verifyStep,
510
+ cleanupStep,
511
+ monorepoStep,
512
+ buildSharedPreviewStep,
513
+ buildPortalStep,
514
+ mswStep,
515
+ writeStoriesStep,
516
+ interactionPlayStep,
517
+ toolsVsShellRule,
518
+ nodeModuleReadsRule,
519
+ monorepoRule,
520
+ packageManagerRule,
521
+ editOverWriteRule,
522
+ batchTestsRule,
523
+ readBudgetRule,
524
+ readBudgetRuleRelaxed,
525
+ preferSharedFixesRule,
526
+ noPolishRule
527
+ };
@@ -0,0 +1,11 @@
1
+ import CJS_COMPAT_NODE_URL_cy5uq3ou7e from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_cy5uq3ou7e from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_cy5uq3ou7e from "node:module";
4
+
5
+ var __filename = CJS_COMPAT_NODE_URL_cy5uq3ou7e.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_cy5uq3ou7e.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_cy5uq3ou7e.createRequire(import.meta.url);
8
+
9
+ // ------------------------------------------------------------
10
+ // end of CJS compatibility banner, injected by Storybook's esbuild configuration
11
+ // ------------------------------------------------------------