diff --git a/.circleci/config.yml b/.circleci/config.yml index b2567e7d37f..6a99d5190b6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -878,10 +878,11 @@ workflows: parallelism: 4 requires: - create-sandboxes - - bench-sandboxes: - parallelism: 5 - requires: - - create-sandboxes +# TODO: don't forget to reenable this +# - bench-sandboxes: +# parallelism: 5 +# requires: +# - create-sandboxes - test-ui-testing-module: requires: - build @@ -965,10 +966,11 @@ workflows: - test-init-features: requires: - build - - bench-sandboxes: - parallelism: 5 - requires: - - create-sandboxes +# TODO: don't forget to reenable this +# - bench-sandboxes: +# parallelism: 5 +# requires: +# - create-sandboxes # TODO: reenable once we find out the source of flakyness # - test-runner-dev: # parallelism: 4 @@ -1059,10 +1061,11 @@ workflows: # --smoke-test is not supported for the angular builder right now # - "angular-cli" - "lit-vite-ts" - - bench-sandboxes: - parallelism: 5 - requires: - - create-sandboxes +# TODO: don't forget to reenable this +# - bench-sandboxes: +# parallelism: 5 +# requires: +# - create-sandboxes # TODO: reenable once we find out the source of flakyness # - test-runner-dev: diff --git a/CHANGELOG.md b/CHANGELOG.md index b9a6fe3bcef..7cb041def8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 8.6.4 + +- Manager: Add Content-Type to fix Cloud IDEs - [#30606](https://github.com/storybookjs/storybook/pull/30606), thanks @GCHQDeveloper548! +- Vite: Include `node_modules` in stats file - [#30711](https://github.com/storybookjs/storybook/pull/30711), thanks @JReinhold! + ## 8.6.3 - CSF Factories: Align addon-essentials import with other addons - [#30716](https://github.com/storybookjs/storybook/pull/30716), thanks @kasperpeulen! @@ -37,7 +42,6 @@ Here’s what’s new: - Addon-Test: Add telemetry data for Focused Tests - [#30568](https://github.com/storybookjs/storybook/pull/30568), thanks @JReinhold! - Addon-Test: Fix config and watch mode inconsistencies - [#30491](https://github.com/storybookjs/storybook/pull/30491), thanks @JReinhold! - Addon-Test: Fix console error in build mode - [#30625](https://github.com/storybookjs/storybook/pull/30625), thanks @JReinhold! -- Addon Test: Fix printing Date object in MethodCall for test/interactions log - [#30507](https://github.com/storybookjs/storybook/pull/30507), thanks @ghengeveld! - Addon-Test: Make sure that only one global portable story config is ever loaded - [#30582](https://github.com/storybookjs/storybook/pull/30582), thanks @kasperpeulen! - Angular: Fix accent character issue - [#30276](https://github.com/storybookjs/storybook/pull/30276), thanks @valentinpalkovic! - Angular: Support experimental zoneless mode - [#28657](https://github.com/storybookjs/storybook/pull/28657), thanks @anedomansky! @@ -46,7 +50,6 @@ Here’s what’s new: - Builder-Vite: Fix runtime and iframe 404 on first load - [#30567](https://github.com/storybookjs/storybook/pull/30567), thanks @valentinpalkovic! - Bun: Add support for text lock file - [#30160](https://github.com/storybookjs/storybook/pull/30160), thanks @Arctomachine! - Cleanup: Remove unused constants in viewport addon - [#30479](https://github.com/storybookjs/storybook/pull/30479), thanks @Guria! -- CLI: Add "features" question & auto-install test addon & improve test-addon compatibility - [#30202](https://github.com/storybookjs/storybook/pull/30202), thanks @ndelangen! - CLI: Don't initially select Documentation and Testing features - [#30599](https://github.com/storybookjs/storybook/pull/30599), thanks @ghengeveld! - CLI: Fix peer dep issues for npm users during upgrade - [#30616](https://github.com/storybookjs/storybook/pull/30616), thanks @valentinpalkovic! - CLI: Fix printing of selected features - [#30605](https://github.com/storybookjs/storybook/pull/30605), thanks @ghengeveld! diff --git a/CHANGELOG.prerelease.md b/CHANGELOG.prerelease.md index 7f9725f547a..cf388a310b1 100644 --- a/CHANGELOG.prerelease.md +++ b/CHANGELOG.prerelease.md @@ -1,3 +1,46 @@ +## 9.0.0-alpha.3 + +- Addon A11y: Promote @storybook/global to full dependency - [#30723](https://github.com/storybookjs/storybook/pull/30723), thanks @mrginglymus! +- Addon Test: Improve unhandled error messages - [#30755](https://github.com/storybookjs/storybook/pull/30755), thanks @yannbf! +- Angular: Add @angular-devkit/build-angular to default installed pacakages in angular - [#30790](https://github.com/storybookjs/storybook/pull/30790), thanks @kasperpeulen! +- Automigrate: Disable `missingStorybookDependencies` for 9.0 - [#30769](https://github.com/storybookjs/storybook/pull/30769), thanks @ndelangen! +- CLI: Fix test install in RNW projects - [#30786](https://github.com/storybookjs/storybook/pull/30786), thanks @shilman! +- Core: Re-Export renderers from frameworks - [#30771](https://github.com/storybookjs/storybook/pull/30771), thanks @ndelangen! +- Core: Replace 'min' instead of 'm' in printDuration - [#30668](https://github.com/storybookjs/storybook/pull/30668), thanks @wlewis-formative! +- Migration: Add auto-automigration for merged packages - [#30753](https://github.com/storybookjs/storybook/pull/30753), thanks @ndelangen! +- Next.js: Upgrade image-size to 2.0 - [#30741](https://github.com/storybookjs/storybook/pull/30741), thanks @valentinpalkovic! +- Next.js: Use latest version when init in empty directory - [#30659](https://github.com/storybookjs/storybook/pull/30659), thanks @valentinpalkovic! +- Svelte: Fix Vite crashing on virtual module imports - [#26838](https://github.com/storybookjs/storybook/pull/26838), thanks @rChaoz! +- Svelte: Fix automatic argTypes inference coming up empty with `svelte2tsx@0.7.35` - [#30784](https://github.com/storybookjs/storybook/pull/30784), thanks @JReinhold! +- Svelte: Pin svelte2tsx to solve argType regression - [#30783](https://github.com/storybookjs/storybook/pull/30783), thanks @kasperpeulen! +- Test: Move `@storybook/test` into `storybook/test` - [#30742](https://github.com/storybookjs/storybook/pull/30742), thanks @valentinpalkovic! +- Universal Store: Don't use `crypto.randomUUID` - [#30781](https://github.com/storybookjs/storybook/pull/30781), thanks @JReinhold! + +## 9.0.0-alpha.2 + +- AutoBlocker: Add major version upgrade blocker - [#30714](https://github.com/storybookjs/storybook/pull/30714), thanks @ndelangen! +- CLI: Add index command / API - [#30071](https://github.com/storybookjs/storybook/pull/30071), thanks @shilman! +- CSF Factories: Align addon-essentials import with other addons - [#30716](https://github.com/storybookjs/storybook/pull/30716), thanks @kasperpeulen! +- Core: Move @storybook/instrumenter into core - [#30740](https://github.com/storybookjs/storybook/pull/30740), thanks @valentinpalkovic! +- Core: Support TS3.8+ again - [#30700](https://github.com/storybookjs/storybook/pull/30700), thanks @kasperpeulen! +- Maintenance: Merge `@storybook/core` with `storybook` - [#30168](https://github.com/storybookjs/storybook/pull/30168), thanks @ndelangen! +- Maintenance: Remove deprecated packages - [#30690](https://github.com/storybookjs/storybook/pull/30690), thanks @ndelangen! +- Manager: Add Content-Type to prevent reliance on content type sniffing, fixing Cloud IDEs - [#30606](https://github.com/storybookjs/storybook/pull/30606), thanks @GCHQDeveloper548! +- Next: Support Next 15.2 - [#30702](https://github.com/storybookjs/storybook/pull/30702), thanks @kasperpeulen! +- React: Export returntype of ReactMeta#story - [#30580](https://github.com/storybookjs/storybook/pull/30580), thanks @mrginglymus! +- Revert "CLI: Don't initially select Documentation and Testing features" - [#30694](https://github.com/storybookjs/storybook/pull/30694), thanks @shilman! +- Test Addon: Stabilize and remove experimental status - [#30727](https://github.com/storybookjs/storybook/pull/30727), thanks @valentinpalkovic! +- Typescript: Drop Typescript < 4.9 support - [#30736](https://github.com/storybookjs/storybook/pull/30736), thanks @valentinpalkovic! +- Vite: Improve handling of preview annotations - [#28798](https://github.com/storybookjs/storybook/pull/28798), thanks @tobiasdiez! +- Vite: Include `node_modules` in stats file - [#30711](https://github.com/storybookjs/storybook/pull/30711), thanks @JReinhold! + +## 9.0.0-alpha.1 + +- CLI: Install prereleases of `@chromatic-com/storybook` - [#30662](https://github.com/storybookjs/storybook/pull/30662), thanks @JReinhold! +- CSF: Only export definePreview from the framework - [#30676](https://github.com/storybookjs/storybook/pull/30676), thanks @kasperpeulen! +- Codemod: Only remove types when they are unused - [#30644](https://github.com/storybookjs/storybook/pull/30644), thanks @yannbf! +- Dependencies: Upgrades - [#30515](https://github.com/storybookjs/storybook/pull/30515), thanks @ndelangen! + ## 9.0.0-alpha.0 ## 8.6.0-beta.10 diff --git a/MIGRATION.md b/MIGRATION.md index 3b063eff396..8bde2228682 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -1,6 +1,7 @@

Migration

- [From version 8.x to 9.0.0](#from-version-8x-to-900) + - [Dropped support for legacy packages](#dropped-support-for-legacy-packages) - [Dropped support for TypeScript \< 4.9](#dropped-support-for-typescript--49) - [Test addon renamed from experimental to stable](#test-addon-renamed-from-experimental-to-stable) - [From version 8.5.x to 8.6.x](#from-version-85x-to-86x) @@ -436,6 +437,45 @@ ## From version 8.x to 9.0.0 +### Dropped support for legacy packages + +The following packages are no longer published as part of `9.0.0`: +The following packages have been consolidated into the main `storybook` package: + +| Old Package | New Path | +| ---------------------- | ------------------------------ | +| @storybook/manager-api | storybook/manager-api | +| @storybook/preview-api | storybook/preview-api | +| @storybook/theming | storybook/theming | +| @storybook/test | storybook/test | + +Please un-install these packages, and ensure you have the `storybook` package installed. + +Replace any imports with the path listed in the second column. + +Additionally the following packages were also consolidated and placed under a `/internal` sub-path, to indicate they are for internal usage only. +If you're depending on these packages, they will continue to work for `9.0`, but they will likely be removed in `10.0`. + +| Old Package | New Path | +| -------------------------- | ---------------------------------- | +| @storybook/channels | storybook/internal/channels | +| @storybook/client-logger | storybook/internal/client-logger | +| @storybook/core-common | storybook/internal/common | +| @storybook/core-events | storybook/internal/core-events | +| @storybook/csf-tools | storybook/internal/csf-tools | +| @storybook/docs-tools | storybook/internal/docs-tools | +| @storybook/node-logger | storybook/internal/node-logger | +| @storybook/router | storybook/internal/router | +| @storybook/telemetry | storybook/internal/telemetry | +| @storybook/types | storybook/internal/types | +| @storybook/manager | storybook/internal/manager | +| @storybook/preview | storybook/internal/preview | +| @storybook/core-server | storybook/internal/core-server | +| @storybook/builder-manager | storybook/internal/builder-manager | +| @storybook/components | storybook/internal/components | + +Addon authors may continue to use the internal packages, there is currently not yet any replacement. + ### Dropped support for TypeScript < 4.9 Storybook now requires TypeScript 4.9 or later. If you're using an older version of TypeScript, you'll need to upgrade to continue using Storybook. diff --git a/code/.storybook/bench.stories.tsx b/code/.storybook/bench.stories.tsx index 3b9055905aa..98578869b48 100644 --- a/code/.storybook/bench.stories.tsx +++ b/code/.storybook/bench.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import type { Meta } from '@storybook/react'; +import type { Meta } from '@storybook/react-vite'; // @ts-expect-error - TS doesn't know about import.meta.glob from Vite const allMetafiles = import.meta.glob([ diff --git a/code/.storybook/preview.tsx b/code/.storybook/preview.tsx index 2a3d237ce61..24924feaf9f 100644 --- a/code/.storybook/preview.tsx +++ b/code/.storybook/preview.tsx @@ -16,8 +16,8 @@ import { import { DocsContext } from '@storybook/blocks'; import { global } from '@storybook/global'; -import type { Decorator, Loader, ReactRenderer } from '@storybook/react'; +import type { Decorator, Loader, ReactRenderer } from '@storybook/react-vite'; // TODO add empty preview // import * as storysource from '@storybook/addon-storysource'; // import * as designs from '@storybook/addon-designs/preview'; diff --git a/code/.storybook/storybook.setup.ts b/code/.storybook/storybook.setup.ts index 80160218a31..833e21c50ac 100644 --- a/code/.storybook/storybook.setup.ts +++ b/code/.storybook/storybook.setup.ts @@ -1,7 +1,8 @@ import { beforeAll, vi, expect as vitestExpect } from 'vitest'; import { setProjectAnnotations } from '@storybook/react'; -import { userEvent as storybookEvent, expect as storybookExpect } from '@storybook/test'; + +import { userEvent as storybookEvent, expect as storybookExpect } from 'storybook/test'; import preview from './preview'; diff --git a/code/.storybook/vitest.config.ts b/code/.storybook/vitest.config.ts index 22f3d5f620c..e3d04ba0d37 100644 --- a/code/.storybook/vitest.config.ts +++ b/code/.storybook/vitest.config.ts @@ -1,5 +1,7 @@ import { defaultExclude, defineProject, mergeConfig } from 'vitest/config'; +import { storybookTest } from '@storybook/addon-test/vitest-plugin'; + import Inspect from 'vite-plugin-inspect'; import { vitestCommonConfig } from '../vitest.workspace'; @@ -22,14 +24,12 @@ export default mergeConfig( // @ts-expect-error added this because of testNamePattern below defineProject({ plugins: [ - import('@storybook/addon-test/vitest-plugin').then(({ storybookTest }) => - storybookTest({ - configDir: __dirname, - tags: { - include: ['vitest'], - }, - }) - ), + storybookTest({ + configDir: __dirname, + tags: { + include: ['vitest'], + }, + }), ...extraPlugins, ], test: { @@ -40,7 +40,7 @@ export default mergeConfig( '**/__mockdata__/**', '../**/__mockdata__/**', '**/Zoom.stories.tsx', // expected to fail in Vitest because of fetching /iframe.html to cause ECONNREFUSED - '**/lib/blocks/src/**', // won't work because of https://github.com/storybookjs/storybook/issues/29783 + '../lib/blocks/src/**', // won't work because of https://github.com/storybookjs/storybook/issues/29783 ], // TODO: bring this back once portable stories support storybook/internal/preview-api hooks // @ts-expect-error this type does not exist but the property does! diff --git a/code/addons/a11y/package.json b/code/addons/a11y/package.json index 2e2367f60fd..0a284bc98d8 100644 --- a/code/addons/a11y/package.json +++ b/code/addons/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-a11y", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Test component compliance with web accessibility standards", "keywords": [ "a11y", @@ -67,11 +67,10 @@ }, "dependencies": { "@storybook/addon-highlight": "workspace:*", - "@storybook/test": "workspace:*", + "@storybook/global": "^5.0.0", "axe-core": "^4.2.0" }, "devDependencies": { - "@storybook/global": "^5.0.0", "@storybook/icons": "^1.4.0", "@testing-library/react": "^14.0.0", "execa": "^9.5.2", diff --git a/code/addons/a11y/src/components/A11YPanel.stories.tsx b/code/addons/a11y/src/components/A11YPanel.stories.tsx index 701b5a50933..accbca14f3f 100644 --- a/code/addons/a11y/src/components/A11YPanel.stories.tsx +++ b/code/addons/a11y/src/components/A11YPanel.stories.tsx @@ -3,10 +3,10 @@ import React from 'react'; import { ManagerContext } from 'storybook/internal/manager-api'; import { ThemeProvider, convert, themes } from 'storybook/internal/theming'; -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import type axe from 'axe-core'; +import { fn } from 'storybook/test'; import { A11YPanel } from './A11YPanel'; import { A11yContext } from './A11yContext'; diff --git a/code/addons/a11y/src/components/TestDiscrepancyMessage.stories.tsx b/code/addons/a11y/src/components/TestDiscrepancyMessage.stories.tsx index 578c2bbac79..352edf11ca7 100644 --- a/code/addons/a11y/src/components/TestDiscrepancyMessage.stories.tsx +++ b/code/addons/a11y/src/components/TestDiscrepancyMessage.stories.tsx @@ -2,8 +2,9 @@ import React from 'react'; import { ManagerContext } from 'storybook/internal/manager-api'; -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { fn } from 'storybook/test'; import { TestDiscrepancyMessage } from './TestDiscrepancyMessage'; diff --git a/code/addons/a11y/src/preview.tsx b/code/addons/a11y/src/preview.tsx index 9b8a7598d6d..4a0704ed3eb 100644 --- a/code/addons/a11y/src/preview.tsx +++ b/code/addons/a11y/src/preview.tsx @@ -1,6 +1,6 @@ import type { AfterEach } from 'storybook/internal/types'; -import { expect } from '@storybook/test'; +import { expect } from 'storybook/test'; import { run } from './a11yRunner'; import type { A11yParameters } from './params'; @@ -64,7 +64,7 @@ export const experimental_afterEach: AfterEach = async ({ vitestMatchersExtended = true; } - // @ts-expect-error - todo - fix type extension of expect from @storybook/test + // @ts-expect-error - todo - fix type extension of expect from storybook/test expect(result).toHaveNoViolations(); } } diff --git a/code/addons/actions/package.json b/code/addons/actions/package.json index 1b8ac337fd6..6ffd0dfbf7d 100644 --- a/code/addons/actions/package.json +++ b/code/addons/actions/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-actions", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Get UI feedback when an action is performed on an interactive element", "keywords": [ "storybook", @@ -74,7 +74,6 @@ "uuid": "^9.0.0" }, "devDependencies": { - "@storybook/test": "workspace:*", "react": "^18.2.0", "react-dom": "^18.2.0", "react-inspector": "^6.0.0", diff --git a/code/addons/actions/src/loaders.ts b/code/addons/actions/src/loaders.ts index 118d5c0b1b7..60202ec3692 100644 --- a/code/addons/actions/src/loaders.ts +++ b/code/addons/actions/src/loaders.ts @@ -2,7 +2,8 @@ import type { LoaderFunction } from 'storybook/internal/types'; import { global } from '@storybook/global'; -import type { onMockCall as onMockCallType } from '@storybook/test'; + +import type { onMockCall as onMockCallType } from 'storybook/test'; import { action } from './runtime'; diff --git a/code/addons/actions/template/stories/spies.stories.ts b/code/addons/actions/template/stories/spies.stories.ts index 9d84cae3d36..d3f0ed19108 100644 --- a/code/addons/actions/template/stories/spies.stories.ts +++ b/code/addons/actions/template/stories/spies.stories.ts @@ -1,5 +1,6 @@ import { global as globalThis } from '@storybook/global'; -import { spyOn } from '@storybook/test'; + +import { spyOn } from 'storybook/test'; const meta = { component: globalThis.Components.Button, diff --git a/code/addons/backgrounds/package.json b/code/addons/backgrounds/package.json index e96d14bf6ba..026d62a4689 100644 --- a/code/addons/backgrounds/package.json +++ b/code/addons/backgrounds/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-backgrounds", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Switch backgrounds to view components in different settings", "keywords": [ "addon", diff --git a/code/addons/controls/package.json b/code/addons/controls/package.json index bda67f569cf..98a50016e8d 100644 --- a/code/addons/controls/package.json +++ b/code/addons/controls/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-controls", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Interact with component inputs dynamically in the Storybook UI", "keywords": [ "addon", diff --git a/code/addons/controls/src/SaveStory.stories.tsx b/code/addons/controls/src/SaveStory.stories.tsx index 9c39f6746e0..99d64fc7e28 100644 --- a/code/addons/controls/src/SaveStory.stories.tsx +++ b/code/addons/controls/src/SaveStory.stories.tsx @@ -1,10 +1,11 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, fireEvent, fn, userEvent, within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { action } from '@storybook/addon-actions'; +import { expect, fireEvent, fn, userEvent, within } from 'storybook/test'; + import { SaveStory } from './SaveStory'; const meta = { diff --git a/code/addons/docs/package.json b/code/addons/docs/package.json index 7b3950e5e91..31dbb391b2c 100644 --- a/code/addons/docs/package.json +++ b/code/addons/docs/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-docs", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Document component usage and properties in Markdown", "keywords": [ "addon", diff --git a/code/addons/docs/template/stories/docs2/resolved-react.stories.ts b/code/addons/docs/template/stories/docs2/resolved-react.stories.ts index 75e3d480ca9..43564cf4638 100644 --- a/code/addons/docs/template/stories/docs2/resolved-react.stories.ts +++ b/code/addons/docs/template/stories/docs2/resolved-react.stories.ts @@ -2,7 +2,7 @@ import * as ReactExport from 'react'; import * as ReactDom from 'react-dom'; import * as ReactDomServer from 'react-dom/server'; -import { expect, within } from '@storybook/test'; +import { expect, within } from 'storybook/test'; /** * This component is used to display the resolved version of React and its related packages. As long diff --git a/code/addons/docs/template/stories/docspage/autoplay.stories.ts b/code/addons/docs/template/stories/docspage/autoplay.stories.ts index 03d1388f2fb..e96aeeaf417 100644 --- a/code/addons/docs/template/stories/docspage/autoplay.stories.ts +++ b/code/addons/docs/template/stories/docspage/autoplay.stories.ts @@ -1,4 +1,4 @@ -import { expect, within } from '@storybook/test'; +import { expect, within } from 'storybook/test'; export default { component: globalThis.Components.Pre, diff --git a/code/addons/docs/template/stories/docspage/basic.stories.ts b/code/addons/docs/template/stories/docspage/basic.stories.ts index a9ea37650fc..a21d7ab3675 100644 --- a/code/addons/docs/template/stories/docspage/basic.stories.ts +++ b/code/addons/docs/template/stories/docspage/basic.stories.ts @@ -1,4 +1,4 @@ -import { fn } from '@storybook/test'; +import { fn } from 'storybook/test'; export default { component: globalThis.Components.Button, diff --git a/code/addons/essentials/package.json b/code/addons/essentials/package.json index 1255974604d..353f9bf69c6 100644 --- a/code/addons/essentials/package.json +++ b/code/addons/essentials/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-essentials", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Curated addons to bring out the best of Storybook", "keywords": [ "addon", diff --git a/code/addons/gfm/package.json b/code/addons/gfm/package.json index e291f215310..1875c5e01cc 100644 --- a/code/addons/gfm/package.json +++ b/code/addons/gfm/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-mdx-gfm", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "GitHub Flavored Markdown in Storybook", "keywords": [ "addon", diff --git a/code/addons/highlight/package.json b/code/addons/highlight/package.json index 425058b43b9..2f8d7f750ea 100644 --- a/code/addons/highlight/package.json +++ b/code/addons/highlight/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-highlight", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Highlight DOM nodes within your stories", "keywords": [ "storybook-addons", diff --git a/code/addons/interactions/README.md b/code/addons/interactions/README.md index 8e97267a65d..bd6895851cc 100644 --- a/code/addons/interactions/README.md +++ b/code/addons/interactions/README.md @@ -9,7 +9,7 @@ Storybook Addon Interactions enables visual debugging of interactions and tests Install this addon by adding the `@storybook/addon-interactions` dependency: ```sh -yarn add -D @storybook/addon-interactions @storybook/test +yarn add -D @storybook/addon-interactions ``` within `.storybook/main.js`: @@ -24,10 +24,10 @@ Note that `@storybook/addon-interactions` must be listed **after** `@storybook/a ## Usage -Interactions relies on "instrumented" versions of Vitest and Testing Library, that you import from `@storybook/test` instead of their original package. You can then use these libraries in your `play` function. +Interactions relies on "instrumented" versions of Vitest and Testing Library, that you import from `storybook/test` instead of their original package. You can then use these libraries in your `play` function. ```js -import { expect, fn, userEvent, within } from '@storybook/test'; +import { expect, fn, userEvent, within } from 'storybook/test'; import { Button } from './Button'; export default { diff --git a/code/addons/interactions/package.json b/code/addons/interactions/package.json index 6e7338c0564..cae9ba846e9 100644 --- a/code/addons/interactions/package.json +++ b/code/addons/interactions/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-interactions", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Automate, test and debug user interactions", "keywords": [ "storybook-addons", @@ -63,7 +63,6 @@ }, "dependencies": { "@storybook/global": "^5.0.0", - "@storybook/test": "workspace:*", "polished": "^4.2.2", "ts-dedent": "^2.2.0" }, diff --git a/code/addons/interactions/src/components/Interaction.stories.tsx b/code/addons/interactions/src/components/Interaction.stories.tsx index 64f43a8cef7..4526cdcebab 100644 --- a/code/addons/interactions/src/components/Interaction.stories.tsx +++ b/code/addons/interactions/src/components/Interaction.stories.tsx @@ -1,7 +1,8 @@ import { CallStates } from 'storybook/internal/instrumenter'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, userEvent, within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { expect, userEvent, within } from 'storybook/test'; import { getCalls } from '../mocks'; import { Interaction } from './Interaction'; diff --git a/code/addons/interactions/src/components/InteractionsPanel.stories.tsx b/code/addons/interactions/src/components/InteractionsPanel.stories.tsx index 8d6d7cd9f3f..20128d9f834 100644 --- a/code/addons/interactions/src/components/InteractionsPanel.stories.tsx +++ b/code/addons/interactions/src/components/InteractionsPanel.stories.tsx @@ -3,8 +3,9 @@ import React from 'react'; import { CallStates } from 'storybook/internal/instrumenter'; import { styled } from 'storybook/internal/theming'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, userEvent, waitFor, within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { expect, userEvent, waitFor, within } from 'storybook/test'; import { isChromatic } from '../../../../.storybook/isChromatic'; import { getCalls, getInteractions } from '../mocks'; diff --git a/code/addons/interactions/src/preview.ts b/code/addons/interactions/src/preview.ts index 635e50ccedb..227fef876d0 100644 --- a/code/addons/interactions/src/preview.ts +++ b/code/addons/interactions/src/preview.ts @@ -3,7 +3,7 @@ import type { PlayFunction, StepLabel, StepRunner, StoryContext } from 'storyboo // This makes sure that storybook test loaders are always loaded when addon-interactions is used // For 9.0 we want to merge storybook/test and addon-interactions into one addon. -import '@storybook/test'; +import 'storybook/test'; import type { InteractionsParameters } from './types'; diff --git a/code/addons/interactions/template/stories/basics.stories.ts b/code/addons/interactions/template/stories/basics.stories.ts index 2db5f0e016f..a1cb4ce7d41 100644 --- a/code/addons/interactions/template/stories/basics.stories.ts +++ b/code/addons/interactions/template/stories/basics.stories.ts @@ -1,4 +1,5 @@ import { global as globalThis } from '@storybook/global'; + import { expect, fireEvent, @@ -7,7 +8,7 @@ import { waitFor, waitForElementToBeRemoved, within, -} from '@storybook/test'; +} from 'storybook/test'; export default { component: globalThis.Components.Form, diff --git a/code/addons/interactions/template/stories/unhandled-errors.stories.ts b/code/addons/interactions/template/stories/unhandled-errors.stories.ts index b9be0df743e..d5c396b7168 100644 --- a/code/addons/interactions/template/stories/unhandled-errors.stories.ts +++ b/code/addons/interactions/template/stories/unhandled-errors.stories.ts @@ -1,5 +1,6 @@ import { global as globalThis } from '@storybook/global'; -import { userEvent, within } from '@storybook/test'; + +import { userEvent, within } from 'storybook/test'; export default { component: globalThis.Components.Button, diff --git a/code/addons/jest/package.json b/code/addons/jest/package.json index 7e6c7173be0..4deba14bb9b 100644 --- a/code/addons/jest/package.json +++ b/code/addons/jest/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-jest", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "React storybook addon that show component jest report", "keywords": [ "addon", diff --git a/code/addons/links/package.json b/code/addons/links/package.json index 08f1980beab..db9002b43d5 100644 --- a/code/addons/links/package.json +++ b/code/addons/links/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-links", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Link stories together to build demos and prototypes with your UI components", "keywords": [ "storybook-addons", diff --git a/code/addons/measure/package.json b/code/addons/measure/package.json index a389608f986..7eb7cae9554 100644 --- a/code/addons/measure/package.json +++ b/code/addons/measure/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-measure", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Inspect layouts by visualizing the box model", "keywords": [ "storybook-addons", diff --git a/code/addons/onboarding/package.json b/code/addons/onboarding/package.json index 04654eddbd1..f0ac20e8673 100644 --- a/code/addons/onboarding/package.json +++ b/code/addons/onboarding/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-onboarding", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook Addon Onboarding - Introduces a new onboarding experience", "keywords": [ "storybook-addons", @@ -48,7 +48,6 @@ "@neoconfetti/react": "^1.0.0", "@radix-ui/react-dialog": "^1.0.5", "@storybook/icons": "^1.4.0", - "@storybook/react": "workspace:*", "framer-motion": "^11.0.3", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/code/addons/onboarding/src/components/Button/Button.stories.tsx b/code/addons/onboarding/src/components/Button/Button.stories.tsx index 1d4396a29c6..0c9e0c9cbb2 100644 --- a/code/addons/onboarding/src/components/Button/Button.stories.tsx +++ b/code/addons/onboarding/src/components/Button/Button.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { Button } from './Button'; diff --git a/code/addons/onboarding/src/components/Confetti/Confetti.stories.tsx b/code/addons/onboarding/src/components/Confetti/Confetti.stories.tsx index 3540aadc2a8..8de0444a738 100644 --- a/code/addons/onboarding/src/components/Confetti/Confetti.stories.tsx +++ b/code/addons/onboarding/src/components/Confetti/Confetti.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { Confetti } from './Confetti'; diff --git a/code/addons/onboarding/src/components/HighlightElement/HighlightElement.stories.tsx b/code/addons/onboarding/src/components/HighlightElement/HighlightElement.stories.tsx index 7cb0c52b011..02f8cf3dc20 100644 --- a/code/addons/onboarding/src/components/HighlightElement/HighlightElement.stories.tsx +++ b/code/addons/onboarding/src/components/HighlightElement/HighlightElement.stories.tsx @@ -1,7 +1,8 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, waitFor, within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { expect, waitFor, within } from 'storybook/test'; import { HighlightElement } from './HighlightElement'; diff --git a/code/addons/onboarding/src/components/List/List.stories.tsx b/code/addons/onboarding/src/components/List/List.stories.tsx index 8e7667d8a12..1065ec1ae97 100644 --- a/code/addons/onboarding/src/components/List/List.stories.tsx +++ b/code/addons/onboarding/src/components/List/List.stories.tsx @@ -1,7 +1,8 @@ import React, { useState } from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, userEvent, waitFor, within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { expect, userEvent, waitFor, within } from 'storybook/test'; import { List } from './List'; import { ListItem } from './ListItem/ListItem'; diff --git a/code/addons/onboarding/src/features/GuidedTour/GuidedTour.stories.tsx b/code/addons/onboarding/src/features/GuidedTour/GuidedTour.stories.tsx index c35a02830a5..3ddb9409652 100644 --- a/code/addons/onboarding/src/features/GuidedTour/GuidedTour.stories.tsx +++ b/code/addons/onboarding/src/features/GuidedTour/GuidedTour.stories.tsx @@ -1,5 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { fn } from 'storybook/test'; import { GuidedTour } from './GuidedTour'; diff --git a/code/addons/onboarding/src/features/SplashScreen/SplashScreen.stories.tsx b/code/addons/onboarding/src/features/SplashScreen/SplashScreen.stories.tsx index 7e83cd3e655..a7184e39158 100644 --- a/code/addons/onboarding/src/features/SplashScreen/SplashScreen.stories.tsx +++ b/code/addons/onboarding/src/features/SplashScreen/SplashScreen.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { SplashScreen } from './SplashScreen'; diff --git a/code/addons/outline/package.json b/code/addons/outline/package.json index f0cc490fd90..41b1c71975f 100644 --- a/code/addons/outline/package.json +++ b/code/addons/outline/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-outline", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Outline all elements with CSS to help with layout placement and alignment", "keywords": [ "storybook-addons", diff --git a/code/addons/storysource/package.json b/code/addons/storysource/package.json index 2f4118da26f..54094511e67 100644 --- a/code/addons/storysource/package.json +++ b/code/addons/storysource/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-storysource", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "View a story’s source code to see how it works and paste into your app", "keywords": [ "addon", diff --git a/code/addons/test/package.json b/code/addons/test/package.json index d62f71e9fdd..87d3be518ef 100644 --- a/code/addons/test/package.json +++ b/code/addons/test/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-test", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook addon for testing components", "keywords": [ "storybook-addons", @@ -100,7 +100,6 @@ "dependencies": { "@storybook/global": "^5.0.0", "@storybook/icons": "^1.4.0", - "@storybook/test": "workspace:*", "polished": "^4.2.2", "prompts": "^2.4.0", "ts-dedent": "^2.2.0" @@ -110,8 +109,8 @@ "@types/istanbul-lib-report": "^3.0.3", "@types/node": "^22.0.0", "@types/semver": "^7", - "@vitest/browser": "^3.0.2", - "@vitest/runner": "^3.0.2", + "@vitest/browser": "^3.0.8", + "@vitest/runner": "^3.0.8", "ansi-to-html": "^0.7.2", "boxen": "^8.0.1", "es-toolkit": "^1.22.0", @@ -131,7 +130,7 @@ "tree-kill": "^1.2.2", "ts-dedent": "^2.2.0", "typescript": "^5.7.3", - "vitest": "^3.0.2" + "vitest": "^3.0.8" }, "peerDependencies": { "@vitest/browser": "^2.1.1 || ^3.0.0", diff --git a/code/addons/test/src/components/GlobalErrorModal.stories.tsx b/code/addons/test/src/components/GlobalErrorModal.stories.tsx index 773ff178f17..8d10b8d7d9a 100644 --- a/code/addons/test/src/components/GlobalErrorModal.stories.tsx +++ b/code/addons/test/src/components/GlobalErrorModal.stories.tsx @@ -2,9 +2,9 @@ import React, { useState } from 'react'; import { ManagerContext } from 'storybook/internal/manager-api'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, fn, userEvent, within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; +import { expect, fn, userEvent, within } from 'storybook/test'; import dedent from 'ts-dedent'; import { GlobalErrorContext, GlobalErrorModal } from './GlobalErrorModal'; diff --git a/code/addons/test/src/components/Interaction.stories.tsx b/code/addons/test/src/components/Interaction.stories.tsx index 64f43a8cef7..4526cdcebab 100644 --- a/code/addons/test/src/components/Interaction.stories.tsx +++ b/code/addons/test/src/components/Interaction.stories.tsx @@ -1,7 +1,8 @@ import { CallStates } from 'storybook/internal/instrumenter'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, userEvent, within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { expect, userEvent, within } from 'storybook/test'; import { getCalls } from '../mocks'; import { Interaction } from './Interaction'; diff --git a/code/addons/test/src/components/InteractionsPanel.stories.tsx b/code/addons/test/src/components/InteractionsPanel.stories.tsx index 2efaa5d96c5..a4509f49f8e 100644 --- a/code/addons/test/src/components/InteractionsPanel.stories.tsx +++ b/code/addons/test/src/components/InteractionsPanel.stories.tsx @@ -4,8 +4,9 @@ import { CallStates } from 'storybook/internal/instrumenter'; import { ManagerContext } from 'storybook/internal/manager-api'; import { styled } from 'storybook/internal/theming'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, fn, userEvent, waitFor, within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { expect, fn, userEvent, waitFor, within } from 'storybook/test'; import { isChromatic } from '../../../../.storybook/isChromatic'; import { getCalls, getInteractions } from '../mocks'; diff --git a/code/addons/test/src/components/RelativeTime.stories.tsx b/code/addons/test/src/components/RelativeTime.stories.tsx index 4d3c6af0f6d..aecc461c8b7 100644 --- a/code/addons/test/src/components/RelativeTime.stories.tsx +++ b/code/addons/test/src/components/RelativeTime.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { RelativeTime } from './RelativeTime'; diff --git a/code/addons/test/src/components/TestDiscrepancyMessage.stories.tsx b/code/addons/test/src/components/TestDiscrepancyMessage.stories.tsx index d6ca6aa8320..ab535bb80f1 100644 --- a/code/addons/test/src/components/TestDiscrepancyMessage.stories.tsx +++ b/code/addons/test/src/components/TestDiscrepancyMessage.stories.tsx @@ -3,8 +3,9 @@ import React from 'react'; import { CallStates } from 'storybook/internal/instrumenter'; import { ManagerContext } from 'storybook/internal/manager-api'; -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { fn } from 'storybook/test'; import { TestDiscrepancyMessage } from './TestDiscrepancyMessage'; diff --git a/code/addons/test/src/components/TestProviderRender.stories.tsx b/code/addons/test/src/components/TestProviderRender.stories.tsx index f300fbccbfc..8e693e9b852 100644 --- a/code/addons/test/src/components/TestProviderRender.stories.tsx +++ b/code/addons/test/src/components/TestProviderRender.stories.tsx @@ -5,8 +5,9 @@ import { ManagerContext, addons } from 'storybook/internal/manager-api'; import { styled } from 'storybook/internal/theming'; import { Addon_TypesEnum } from 'storybook/internal/types'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, fn, userEvent } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { expect, fn, userEvent } from 'storybook/test'; import { ADDON_ID as A11Y_ADDON_ID } from '../../../a11y/src/constants'; import { type Details, storeOptions } from '../constants'; diff --git a/code/addons/test/src/components/TestStatusIcon.stories.tsx b/code/addons/test/src/components/TestStatusIcon.stories.tsx index e46d22e015d..6d6bdd037f1 100644 --- a/code/addons/test/src/components/TestStatusIcon.stories.tsx +++ b/code/addons/test/src/components/TestStatusIcon.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { TestStatusIcon } from './TestStatusIcon'; diff --git a/code/addons/test/src/index.ts b/code/addons/test/src/index.ts index 0fcea514a60..296f896ee66 100644 --- a/code/addons/test/src/index.ts +++ b/code/addons/test/src/index.ts @@ -1,16 +1,7 @@ import { definePreview } from 'storybook/internal/preview-api'; import * as addonAnnotations from './preview'; -import type { storybookTest as storybookTestImport } from './vitest-plugin'; export default () => definePreview(addonAnnotations); export type { TestParameters } from './types'; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore-error - this is a hack to make the module's sub-path augmentable -declare module '@storybook/addon-test/vitest-plugin' { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore-error - this is a hack to make the module's sub-path augmentable - export const storybookTest: typeof storybookTestImport; -} diff --git a/code/addons/test/src/manager-store.mock.ts b/code/addons/test/src/manager-store.mock.ts index 9b64e314b03..cc4d18ef510 100644 --- a/code/addons/test/src/manager-store.mock.ts +++ b/code/addons/test/src/manager-store.mock.ts @@ -1,6 +1,6 @@ import { experimental_MockUniversalStore } from 'storybook/internal/manager-api'; -import * as testUtils from '@storybook/test'; +import * as testUtils from 'storybook/test'; import { storeOptions } from './constants'; diff --git a/code/addons/test/src/node/reporter.ts b/code/addons/test/src/node/reporter.ts index eb0c31a3847..93e6d25d50b 100644 --- a/code/addons/test/src/node/reporter.ts +++ b/code/addons/test/src/node/reporter.ts @@ -13,6 +13,7 @@ import type { API_StatusUpdate } from 'storybook/internal/types'; import type { Suite } from '@vitest/runner'; import { throttle } from 'es-toolkit'; import { satisfies } from 'semver'; +import { dedent } from 'ts-dedent'; import { TEST_PROVIDER_ID } from '../constants'; import type { TestManager } from './test-manager'; @@ -60,6 +61,36 @@ const isVitest3OrLater = vitestVersion ? satisfies(vitestVersion, '>=3.0.0-beta.3', { includePrerelease: true }) : false; +interface VitestError extends Error { + VITEST_TEST_PATH?: string; + VITEST_TEST_NAME?: string; +} + +const getErrorOrigin = (error: VitestError): string => { + const parts: string[] = []; + + if (error.VITEST_TEST_PATH) { + parts.push( + dedent` + \nThis error originated in "${error.VITEST_TEST_PATH}". It doesn't mean the error was thrown inside the file itself, but while it was running. + ` + ); + } + + if (error.VITEST_TEST_NAME) { + parts.push( + dedent` + The latest test that might've caused the error is "${error.VITEST_TEST_NAME}". + It might mean one of the following: + - The error was thrown, while Vitest was running this test. + - If the error occurred after the test had been completed, this was the last documented test before it was thrown. + ` + ); + } + + return parts.join('\n'); +}; + export class StorybookReporter implements Reporter { testStatusData: API_StatusUpdate = {}; @@ -219,6 +250,14 @@ export class StorybookReporter implements Reporter { async onFinished() { const unhandledErrors = this.ctx.state.getUnhandledErrors(); + unhandledErrors.forEach((e: unknown) => { + const error = e as VitestError; + const origin = getErrorOrigin(error); + if (origin) { + error.message = `${error.message}\n${origin}`; + error.stack = `${error.stack}\n${origin}`; + } + }); const isCancelled = isVitest3OrLater ? this.testManager.vitestManager.isCancelling @@ -256,7 +295,7 @@ export class StorybookReporter implements Reporter { name: `${unhandledErrors.length} unhandled error${unhandledErrors?.length > 1 ? 's' : ''}`, message: unhandledErrors .map((e, index) => `[${index}]: ${(e as any).stack || (e as any).message}`) - .join('\n----------\n'), + .join('\n\n----------\n\n'), }; this.sendReport({ diff --git a/code/addons/test/src/preview.ts b/code/addons/test/src/preview.ts index 2a78c0fde79..ac1b5893488 100644 --- a/code/addons/test/src/preview.ts +++ b/code/addons/test/src/preview.ts @@ -3,7 +3,7 @@ import type { PlayFunction, StepLabel, StoryContext } from 'storybook/internal/t // This makes sure that storybook test loaders are always loaded when addon-interactions is used // For 9.0 we want to merge storybook/test and addon-interactions into one addon. -import '@storybook/test'; +import 'storybook/test'; export const { step: runStep } = instrument( { diff --git a/code/addons/test/template/stories/basics.stories.ts b/code/addons/test/template/stories/basics.stories.ts index 2db5f0e016f..a1cb4ce7d41 100644 --- a/code/addons/test/template/stories/basics.stories.ts +++ b/code/addons/test/template/stories/basics.stories.ts @@ -1,4 +1,5 @@ import { global as globalThis } from '@storybook/global'; + import { expect, fireEvent, @@ -7,7 +8,7 @@ import { waitFor, waitForElementToBeRemoved, within, -} from '@storybook/test'; +} from 'storybook/test'; export default { component: globalThis.Components.Form, diff --git a/code/addons/test/template/stories/unhandled-errors.stories.ts b/code/addons/test/template/stories/unhandled-errors.stories.ts index b9be0df743e..d5c396b7168 100644 --- a/code/addons/test/template/stories/unhandled-errors.stories.ts +++ b/code/addons/test/template/stories/unhandled-errors.stories.ts @@ -1,5 +1,6 @@ import { global as globalThis } from '@storybook/global'; -import { userEvent, within } from '@storybook/test'; + +import { userEvent, within } from 'storybook/test'; export default { component: globalThis.Components.Button, diff --git a/code/addons/themes/package.json b/code/addons/themes/package.json index 867bb307dbe..8923aebed75 100644 --- a/code/addons/themes/package.json +++ b/code/addons/themes/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-themes", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Switch between multiple themes for you components in Storybook", "keywords": [ "css", diff --git a/code/addons/toolbars/package.json b/code/addons/toolbars/package.json index a0e5c3cd5fe..46291a827b8 100644 --- a/code/addons/toolbars/package.json +++ b/code/addons/toolbars/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-toolbars", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Create your own toolbar items that control story rendering", "keywords": [ "addon", diff --git a/code/addons/viewport/package.json b/code/addons/viewport/package.json index 92a45e41e25..faf662537f6 100644 --- a/code/addons/viewport/package.json +++ b/code/addons/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-viewport", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Build responsive components by adjusting Storybook’s viewport size and orientation", "keywords": [ "addon", diff --git a/code/addons/viewport/template/stories/parameters.stories.ts b/code/addons/viewport/template/stories/parameters.stories.ts index 697f675c214..4ee419895ae 100644 --- a/code/addons/viewport/template/stories/parameters.stories.ts +++ b/code/addons/viewport/template/stories/parameters.stories.ts @@ -1,8 +1,9 @@ import { global as globalThis } from '@storybook/global'; -import { expect } from '@storybook/test'; import { MINIMAL_VIEWPORTS } from '@storybook/addon-viewport'; +import { expect } from 'storybook/test'; + // these stories only work with `viewportStoryGlobals` set to false // because the `default` prop is dropped and because, `values` changed to `options` and is now an object diff --git a/code/builders/builder-vite/package.json b/code/builders/builder-vite/package.json index 363b4df8cbe..c6565756621 100644 --- a/code/builders/builder-vite/package.json +++ b/code/builders/builder-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/builder-vite", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "A plugin to run and build Storybooks with Vite", "homepage": "https://github.com/storybookjs/storybook/tree/next/code/builders/builder-vite/#readme", "bugs": { diff --git a/code/builders/builder-vite/src/optimizeDeps.ts b/code/builders/builder-vite/src/optimizeDeps.ts index 5caa431d378..9f982da5a36 100644 --- a/code/builders/builder-vite/src/optimizeDeps.ts +++ b/code/builders/builder-vite/src/optimizeDeps.ts @@ -9,10 +9,12 @@ import { listStories } from './list-stories'; // It ensures that vite converts cjs deps into esm without vite having to find them during startup and then having to log a message about them and restart // TODO: Many of the deps might be prebundled now though, so probably worth trying to remove and see what happens const INCLUDE_CANDIDATES = [ + '@ampproject/remapping', '@base2/pretty-print-object', '@emotion/core', '@emotion/is-prop-valid', '@emotion/styled', + '@jridgewell/sourcemap-codec', '@storybook/addon-a11y/preview', '@storybook/addon-backgrounds/preview', '@storybook/addon-designs/blocks', @@ -62,7 +64,9 @@ const INCLUDE_CANDIDATES = [ 'acorn', 'airbnb-js-shims', 'ansi-to-html', + 'aria-query', 'axe-core', + 'axobject-query', 'chromatic/isChromatic', 'color-convert', 'deep-object-diff', diff --git a/code/builders/builder-webpack5/package.json b/code/builders/builder-webpack5/package.json index 7a0941d9995..80cd42b0fdb 100644 --- a/code/builders/builder-webpack5/package.json +++ b/code/builders/builder-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/builder-webpack5", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/builders/builder-webpack5/src/index.ts b/code/builders/builder-webpack5/src/index.ts index b820f9e3c27..34dd4f1a6f5 100644 --- a/code/builders/builder-webpack5/src/index.ts +++ b/code/builders/builder-webpack5/src/index.ts @@ -29,7 +29,7 @@ export const printDuration = (startTime: [number, number]) => prettyTime(process.hrtime(startTime)) .replace(' ms', ' milliseconds') .replace(' s', ' seconds') - .replace(' m', ' minutes'); + .replace(' min', ' minutes'); const corePath = dirname(require.resolve('storybook/package.json')); diff --git a/code/core/package.json b/code/core/package.json index 6f8d504d2b5..8877d70973f 100644 --- a/code/core/package.json +++ b/code/core/package.json @@ -1,6 +1,6 @@ { "name": "storybook", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" @@ -21,6 +21,12 @@ "license": "MIT", "sideEffects": false, "type": "module", + "imports": { + "#utils": { + "storybook": "./template/stories/utils.mock.ts", + "default": "./template/stories/utils.ts" + } + }, "exports": { ".": { "types": "./dist/index.d.ts", @@ -181,6 +187,11 @@ "import": "./dist/instrumenter/index.js", "require": "./dist/instrumenter/index.cjs" }, + "./test": { + "types": "./dist/test/index.d.ts", + "import": "./dist/test/index.js", + "require": "./dist/test/index.cjs" + }, "./internal/preview/runtime": { "import": "./dist/preview/runtime.js" }, @@ -280,6 +291,9 @@ ], "internal/instrumenter": [ "./dist/instrumenter/index.d.ts" + ], + "test": [ + "./dist/test/index.d.ts" ] } }, @@ -295,6 +309,11 @@ "prep": "jiti ./scripts/prep.ts" }, "dependencies": { + "@testing-library/dom": "10.4.0", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/user-event": "14.5.2", + "@vitest/expect": "2.0.5", + "@vitest/spy": "2.0.5", "better-opn": "^3.0.2", "browser-assert": "^1.2.1", "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0", @@ -358,7 +377,9 @@ "babel-plugin-react-docgen": "4.2.1", "boxen": "^7.1.1", "browser-dtector": "^3.4.0", + "bundle-require": "^5.1.0", "camelcase": "^8.0.0", + "chai": "^5.1.1", "cli-table3": "^0.6.1", "commander": "^12.1.0", "comment-parser": "^1.4.1", @@ -423,7 +444,7 @@ "strip-json-comments": "^5.0.1", "telejson": "^7.2.0", "tiny-invariant": "^1.3.1", - "tinyspy": "^2.2.0", + "tinyspy": "^3.0.2", "ts-dedent": "^2.0.0", "tsconfig-paths": "^4.2.0", "type-fest": "^4.18.1", diff --git a/code/core/scripts/entries.ts b/code/core/scripts/entries.ts index 40396913186..00357cf4601 100644 --- a/code/core/scripts/entries.ts +++ b/code/core/scripts/entries.ts @@ -50,6 +50,23 @@ export const getEntries = (cwd: string) => { define('src/bin/index.ts', ['node'], false), define('src/instrumenter/index.ts', ['browser', 'node'], true), + define( + 'src/test/index.ts', + ['browser', 'node'], + true, + ['util'], + [], + [ + '@testing-library/dom', + '@testing-library/jest-dom', + '@testing-library/user-event', + 'chai', + '@vitest/expect', + '@vitest/spy', + '@vitest/utils', + ], + true + ), ]; }; diff --git a/code/core/scripts/helpers/generatePackageJsonFile.ts b/code/core/scripts/helpers/generatePackageJsonFile.ts index 020724b8113..c5a0632e5a2 100644 --- a/code/core/scripts/helpers/generatePackageJsonFile.ts +++ b/code/core/scripts/helpers/generatePackageJsonFile.ts @@ -40,7 +40,7 @@ export async function generatePackageJsonFile(entries: ReturnType { function removeDefault(input: string) { diff --git a/code/core/scripts/no-externals-plugin.ts b/code/core/scripts/no-externals-plugin.ts new file mode 100644 index 00000000000..f2cb2abf9bb --- /dev/null +++ b/code/core/scripts/no-externals-plugin.ts @@ -0,0 +1,21 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +import { match } from 'bundle-require'; +import type { Plugin } from 'esbuild'; + +// Must not start with "/" or "./" or "../" or "C:\" or be the exact strings ".." or "." +const NON_NODE_MODULE_RE = /^[A-Z]:[/\\]|^\.{0,2}\/|^\.{1,2}$/; + +export const externalPlugin = ({ noExternal }: { noExternal?: (string | RegExp)[] }): Plugin => { + return { + name: `external`, + + setup(build) { + build.onResolve({ filter: /.*/ }, (args) => { + // Respect explicit external/noExternal conditions + if (match(args.path, noExternal)) { + return undefined; + } + }); + }, + }; +}; diff --git a/code/core/scripts/prep.ts b/code/core/scripts/prep.ts index 2e431c57ceb..16d18c1c7c7 100644 --- a/code/core/scripts/prep.ts +++ b/code/core/scripts/prep.ts @@ -25,6 +25,7 @@ import { generateTypesMapperFiles } from './helpers/generateTypesMapperFiles'; import { isBrowser, isNode, noExternals } from './helpers/isEntryType'; import { modifyThemeTypes } from './helpers/modifyThemeTypes'; import { generateSourceFiles } from './helpers/sourcefiles'; +import { externalPlugin } from './no-externals-plugin'; async function run() { const flags = process.argv.slice(2); @@ -253,9 +254,14 @@ async function run() { entryPoints: [entry.file], external: [ ...nodeInternals, - ...esbuildDefaultOptions.external, + ...esbuildDefaultOptions.external.filter((e) => !entry.noExternal.includes(e)), ...entry.externals, ].filter((e) => !entry.internals.includes(e)), + plugins: [ + externalPlugin({ + noExternal: entry.noExternal, + }), + ], format: 'cjs', outdir: dirname(entry.file).replace('src', 'dist'), outExtension: { @@ -272,10 +278,15 @@ async function run() { entryPoints: [entry.file], external: [ ...nodeInternals, - ...esbuildDefaultOptions.external, + ...esbuildDefaultOptions.external.filter((e) => !entry.noExternal.includes(e)), ...entry.externals, ].filter((e) => !entry.internals.includes(e)), outdir: dirname(entry.file).replace('src', 'dist'), + plugins: [ + externalPlugin({ + noExternal: entry.noExternal, + }), + ], outExtension: { '.js': '.js', }, @@ -289,9 +300,14 @@ async function run() { entryPoints: [entry.file], external: [ ...nodeInternals, - ...esbuildDefaultOptions.external, + ...esbuildDefaultOptions.external.filter((e) => !entry.noExternal.includes(e)), ...entry.externals, ].filter((e) => !entry.internals.includes(e)), + plugins: [ + externalPlugin({ + noExternal: entry.noExternal, + }), + ], format: 'esm', outdir: dirname(entry.file).replace('src', 'dist'), outExtension: { diff --git a/code/core/src/cli/helpers.test.ts b/code/core/src/cli/helpers.test.ts index a82dfc911a7..f161f4469ca 100644 --- a/code/core/src/cli/helpers.test.ts +++ b/code/core/src/cli/helpers.test.ts @@ -158,7 +158,7 @@ describe('Helpers', () => { filePath === normalizePath('@storybook/react/template/cli') ); await helpers.copyTemplateFiles({ - renderer: 'react', + templateLocation: 'react', language, packageManager: packageManagerMock, commonAssetsDir: normalizePath('create-storybook/rendererAssets/common'), @@ -182,7 +182,7 @@ describe('Helpers', () => { return filePath === normalizePath('@storybook/react/template/cli') || filePath === './src'; }); await helpers.copyTemplateFiles({ - renderer: 'react', + templateLocation: 'react', language: SupportedLanguage.JAVASCRIPT, packageManager: packageManagerMock, features: ['dev', 'docs', 'test'], @@ -195,7 +195,7 @@ describe('Helpers', () => { return filePath === normalizePath('@storybook/react/template/cli'); }); await helpers.copyTemplateFiles({ - renderer: 'react', + templateLocation: 'react', language: SupportedLanguage.JAVASCRIPT, packageManager: packageManagerMock, features: ['dev', 'docs', 'test'], @@ -208,7 +208,7 @@ describe('Helpers', () => { const expectedMessage = `Unsupported renderer: ${renderer}`; await expect( helpers.copyTemplateFiles({ - renderer, + templateLocation: renderer, language: SupportedLanguage.JAVASCRIPT, packageManager: packageManagerMock, features: ['dev', 'docs', 'test'], diff --git a/code/core/src/cli/helpers.ts b/code/core/src/cli/helpers.ts index faee828be65..9bab59fdd85 100644 --- a/code/core/src/cli/helpers.ts +++ b/code/core/src/cli/helpers.ts @@ -135,7 +135,7 @@ export function copyTemplate(templateRoot: string, destination = '.') { type CopyTemplateFilesOptions = { packageManager: JsPackageManager; - renderer: SupportedFrameworks | SupportedRenderers; + templateLocation: SupportedFrameworks | SupportedRenderers; language: SupportedLanguage; commonAssetsDir?: string; destination?: string; @@ -205,7 +205,7 @@ export const cliStoriesTargetPath = async () => { export async function copyTemplateFiles({ packageManager, - renderer, + templateLocation, language, destination, commonAssetsDir, @@ -218,7 +218,7 @@ export async function copyTemplateFiles({ [SupportedLanguage.TYPESCRIPT_4_9]: 'ts-4-9', }; // FIXME: remove after 9.0 - if (renderer === 'svelte') { + if (templateLocation === 'svelte') { const svelteVersion = await getVersionSafe(packageManager, 'svelte'); if (svelteVersion && major(svelteVersion) >= 5) { languageFolderMapping = { @@ -230,7 +230,7 @@ export async function copyTemplateFiles({ } } const templatePath = async () => { - const baseDir = await getRendererDir(packageManager, renderer); + const baseDir = await getRendererDir(packageManager, templateLocation); const assetsDir = join(baseDir, 'template', 'cli'); const assetsLanguage = join(assetsDir, languageFolderMapping[language]); @@ -253,7 +253,7 @@ export async function copyTemplateFiles({ if (existsSync(assetsDir)) { return assetsDir; } - throw new Error(`Unsupported renderer: ${renderer} (${baseDir})`); + throw new Error(`Unsupported renderer: ${templateLocation} (${baseDir})`); }; const destinationPath = destination ?? (await cliStoriesTargetPath()); @@ -264,7 +264,7 @@ export async function copyTemplateFiles({ await cp(await templatePath(), destinationPath, { recursive: true, filter }); if (commonAssetsDir && features.includes('docs')) { - let rendererType = frameworkToRenderer[renderer] || 'react'; + let rendererType = frameworkToRenderer[templateLocation] || 'react'; // This is only used for docs links and the docs site uses `vue` for both `vue` & `vue3` renderers if (rendererType === 'vue3') { diff --git a/code/core/src/common/index.ts b/code/core/src/common/index.ts index 6700cdf14fa..8f73b0d4dea 100644 --- a/code/core/src/common/index.ts +++ b/code/core/src/common/index.ts @@ -47,4 +47,4 @@ export * from './js-package-manager'; export { versions }; -export { createFileSystemCache } from './utils/file-cache'; +export { createFileSystemCache, FileSystemCache } from './utils/file-cache'; diff --git a/code/core/src/common/js-package-manager/JsPackageManager.test.ts b/code/core/src/common/js-package-manager/JsPackageManager.test.ts index 153edd0be59..3ccdd59b084 100644 --- a/code/core/src/common/js-package-manager/JsPackageManager.test.ts +++ b/code/core/src/common/js-package-manager/JsPackageManager.test.ts @@ -43,12 +43,12 @@ describe('JsPackageManager', () => { expect(result).toEqual(['@storybook/react@8.3.0']); }); - it('should return the latest stable release version when there is no current version', async () => { + it('should get the requested version when the package is not in the monorepo', async () => { mockLatestVersion.mockResolvedValue('2.0.0'); - const result = await jsPackageManager.getVersionedPackages(['@storybook/new-addon@^8.3.0']); + const result = await jsPackageManager.getVersionedPackages(['@storybook/new-addon@^next']); - expect(result).toEqual(['@storybook/new-addon@^2.0.0']); + expect(result).toEqual(['@storybook/new-addon@^next']); }); }); }); diff --git a/code/core/src/common/js-package-manager/JsPackageManager.ts b/code/core/src/common/js-package-manager/JsPackageManager.ts index 3d3ecfacfa2..a63a8efcc55 100644 --- a/code/core/src/common/js-package-manager/JsPackageManager.ts +++ b/code/core/src/common/js-package-manager/JsPackageManager.ts @@ -333,6 +333,13 @@ export abstract class JsPackageManager { return Promise.all( packages.map(async (pkg) => { const [packageName, packageVersion] = getPackageDetails(pkg); + + // If the packageVersion is specified and we are not dealing with a storybook package, + // just return the requested version. + if (packageVersion && !(packageName in storybookPackagesVersions)) { + return pkg; + } + const latestInRange = await this.latestVersion(packageName, packageVersion); const k = packageName as keyof typeof storybookPackagesVersions; diff --git a/code/core/src/common/utils/print-duration.ts b/code/core/src/common/utils/print-duration.ts index b7bcad0c629..5a1f70f0151 100644 --- a/code/core/src/common/utils/print-duration.ts +++ b/code/core/src/common/utils/print-duration.ts @@ -4,4 +4,4 @@ export const printDuration = (startTime: [number, number]) => prettyTime(process.hrtime(startTime)) .replace(' ms', ' milliseconds') .replace(' s', ' seconds') - .replace(' m', ' minutes'); + .replace(' min', ' minutes'); diff --git a/code/core/src/common/versions.ts b/code/core/src/common/versions.ts index 0cabdc9c53d..a288c5f3efb 100644 --- a/code/core/src/common/versions.ts +++ b/code/core/src/common/versions.ts @@ -1,68 +1,67 @@ // auto generated file, do not edit export default { - '@storybook/addon-a11y': '9.0.0-alpha.0', - '@storybook/addon-actions': '9.0.0-alpha.0', - '@storybook/addon-backgrounds': '9.0.0-alpha.0', - '@storybook/addon-controls': '9.0.0-alpha.0', - '@storybook/addon-docs': '9.0.0-alpha.0', - '@storybook/addon-essentials': '9.0.0-alpha.0', - '@storybook/addon-mdx-gfm': '9.0.0-alpha.0', - '@storybook/addon-highlight': '9.0.0-alpha.0', - '@storybook/addon-interactions': '9.0.0-alpha.0', - '@storybook/addon-jest': '9.0.0-alpha.0', - '@storybook/addon-links': '9.0.0-alpha.0', - '@storybook/addon-measure': '9.0.0-alpha.0', - '@storybook/addon-onboarding': '9.0.0-alpha.0', - '@storybook/addon-outline': '9.0.0-alpha.0', - '@storybook/addon-storysource': '9.0.0-alpha.0', - '@storybook/addon-test': '9.0.0-alpha.0', - '@storybook/addon-themes': '9.0.0-alpha.0', - '@storybook/addon-toolbars': '9.0.0-alpha.0', - '@storybook/addon-viewport': '9.0.0-alpha.0', - '@storybook/builder-vite': '9.0.0-alpha.0', - '@storybook/builder-webpack5': '9.0.0-alpha.0', - storybook: '9.0.0-alpha.0', - '@storybook/angular': '9.0.0-alpha.0', - '@storybook/ember': '9.0.0-alpha.0', - '@storybook/experimental-nextjs-vite': '9.0.0-alpha.0', - '@storybook/html-vite': '9.0.0-alpha.0', - '@storybook/html-webpack5': '9.0.0-alpha.0', - '@storybook/nextjs': '9.0.0-alpha.0', - '@storybook/preact-vite': '9.0.0-alpha.0', - '@storybook/preact-webpack5': '9.0.0-alpha.0', - '@storybook/react-native-web-vite': '9.0.0-alpha.0', - '@storybook/react-vite': '9.0.0-alpha.0', - '@storybook/react-webpack5': '9.0.0-alpha.0', - '@storybook/server-webpack5': '9.0.0-alpha.0', - '@storybook/svelte-vite': '9.0.0-alpha.0', - '@storybook/svelte-webpack5': '9.0.0-alpha.0', - '@storybook/sveltekit': '9.0.0-alpha.0', - '@storybook/vue3-vite': '9.0.0-alpha.0', - '@storybook/vue3-webpack5': '9.0.0-alpha.0', - '@storybook/web-components-vite': '9.0.0-alpha.0', - '@storybook/web-components-webpack5': '9.0.0-alpha.0', - '@storybook/blocks': '9.0.0-alpha.0', - sb: '9.0.0-alpha.0', - '@storybook/cli': '9.0.0-alpha.0', - '@storybook/codemod': '9.0.0-alpha.0', - '@storybook/core-webpack': '9.0.0-alpha.0', - 'create-storybook': '9.0.0-alpha.0', - '@storybook/csf-plugin': '9.0.0-alpha.0', - '@storybook/react-dom-shim': '9.0.0-alpha.0', - '@storybook/source-loader': '9.0.0-alpha.0', - '@storybook/test': '9.0.0-alpha.0', - '@storybook/preset-create-react-app': '9.0.0-alpha.0', - '@storybook/preset-html-webpack': '9.0.0-alpha.0', - '@storybook/preset-preact-webpack': '9.0.0-alpha.0', - '@storybook/preset-react-webpack': '9.0.0-alpha.0', - '@storybook/preset-server-webpack': '9.0.0-alpha.0', - '@storybook/preset-svelte-webpack': '9.0.0-alpha.0', - '@storybook/preset-vue3-webpack': '9.0.0-alpha.0', - '@storybook/html': '9.0.0-alpha.0', - '@storybook/preact': '9.0.0-alpha.0', - '@storybook/react': '9.0.0-alpha.0', - '@storybook/server': '9.0.0-alpha.0', - '@storybook/svelte': '9.0.0-alpha.0', - '@storybook/vue3': '9.0.0-alpha.0', - '@storybook/web-components': '9.0.0-alpha.0', + '@storybook/addon-a11y': '9.0.0-alpha.3', + '@storybook/addon-actions': '9.0.0-alpha.3', + '@storybook/addon-backgrounds': '9.0.0-alpha.3', + '@storybook/addon-controls': '9.0.0-alpha.3', + '@storybook/addon-docs': '9.0.0-alpha.3', + '@storybook/addon-essentials': '9.0.0-alpha.3', + '@storybook/addon-mdx-gfm': '9.0.0-alpha.3', + '@storybook/addon-highlight': '9.0.0-alpha.3', + '@storybook/addon-interactions': '9.0.0-alpha.3', + '@storybook/addon-jest': '9.0.0-alpha.3', + '@storybook/addon-links': '9.0.0-alpha.3', + '@storybook/addon-measure': '9.0.0-alpha.3', + '@storybook/addon-onboarding': '9.0.0-alpha.3', + '@storybook/addon-outline': '9.0.0-alpha.3', + '@storybook/addon-storysource': '9.0.0-alpha.3', + '@storybook/addon-test': '9.0.0-alpha.3', + '@storybook/addon-themes': '9.0.0-alpha.3', + '@storybook/addon-toolbars': '9.0.0-alpha.3', + '@storybook/addon-viewport': '9.0.0-alpha.3', + '@storybook/builder-vite': '9.0.0-alpha.3', + '@storybook/builder-webpack5': '9.0.0-alpha.3', + storybook: '9.0.0-alpha.3', + '@storybook/angular': '9.0.0-alpha.3', + '@storybook/ember': '9.0.0-alpha.3', + '@storybook/experimental-nextjs-vite': '9.0.0-alpha.3', + '@storybook/html-vite': '9.0.0-alpha.3', + '@storybook/html-webpack5': '9.0.0-alpha.3', + '@storybook/nextjs': '9.0.0-alpha.3', + '@storybook/preact-vite': '9.0.0-alpha.3', + '@storybook/preact-webpack5': '9.0.0-alpha.3', + '@storybook/react-native-web-vite': '9.0.0-alpha.3', + '@storybook/react-vite': '9.0.0-alpha.3', + '@storybook/react-webpack5': '9.0.0-alpha.3', + '@storybook/server-webpack5': '9.0.0-alpha.3', + '@storybook/svelte-vite': '9.0.0-alpha.3', + '@storybook/svelte-webpack5': '9.0.0-alpha.3', + '@storybook/sveltekit': '9.0.0-alpha.3', + '@storybook/vue3-vite': '9.0.0-alpha.3', + '@storybook/vue3-webpack5': '9.0.0-alpha.3', + '@storybook/web-components-vite': '9.0.0-alpha.3', + '@storybook/web-components-webpack5': '9.0.0-alpha.3', + '@storybook/blocks': '9.0.0-alpha.3', + sb: '9.0.0-alpha.3', + '@storybook/cli': '9.0.0-alpha.3', + '@storybook/codemod': '9.0.0-alpha.3', + '@storybook/core-webpack': '9.0.0-alpha.3', + 'create-storybook': '9.0.0-alpha.3', + '@storybook/csf-plugin': '9.0.0-alpha.3', + '@storybook/react-dom-shim': '9.0.0-alpha.3', + '@storybook/source-loader': '9.0.0-alpha.3', + '@storybook/preset-create-react-app': '9.0.0-alpha.3', + '@storybook/preset-html-webpack': '9.0.0-alpha.3', + '@storybook/preset-preact-webpack': '9.0.0-alpha.3', + '@storybook/preset-react-webpack': '9.0.0-alpha.3', + '@storybook/preset-server-webpack': '9.0.0-alpha.3', + '@storybook/preset-svelte-webpack': '9.0.0-alpha.3', + '@storybook/preset-vue3-webpack': '9.0.0-alpha.3', + '@storybook/html': '9.0.0-alpha.3', + '@storybook/preact': '9.0.0-alpha.3', + '@storybook/react': '9.0.0-alpha.3', + '@storybook/server': '9.0.0-alpha.3', + '@storybook/svelte': '9.0.0-alpha.3', + '@storybook/vue3': '9.0.0-alpha.3', + '@storybook/web-components': '9.0.0-alpha.3', }; diff --git a/code/core/src/components/components/Badge/Badge.stories.tsx b/code/core/src/components/components/Badge/Badge.stories.tsx index 4f51422c0f0..189f98bcebe 100644 --- a/code/core/src/components/components/Badge/Badge.stories.tsx +++ b/code/core/src/components/components/Badge/Badge.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { Badge } from './Badge'; diff --git a/code/core/src/components/components/Button/Button.deprecated.stories.tsx b/code/core/src/components/components/Button/Button.deprecated.stories.tsx index ee10af77e39..fe7ebd265cc 100644 --- a/code/core/src/components/components/Button/Button.deprecated.stories.tsx +++ b/code/core/src/components/components/Button/Button.deprecated.stories.tsx @@ -1,7 +1,8 @@ import React from 'react'; import { LinkIcon } from '@storybook/icons'; -import type { Meta, StoryObj } from '@storybook/react'; + +import type { Meta, StoryObj } from '@storybook/react-vite'; import { Form } from '../form'; import { Button } from './Button'; diff --git a/code/core/src/components/components/ErrorFormatter/ErrorFormatter.stories.tsx b/code/core/src/components/components/ErrorFormatter/ErrorFormatter.stories.tsx index 3ffc4e68381..e0f97d77c8c 100644 --- a/code/core/src/components/components/ErrorFormatter/ErrorFormatter.stories.tsx +++ b/code/core/src/components/components/ErrorFormatter/ErrorFormatter.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { dedent } from 'ts-dedent'; diff --git a/code/core/src/components/components/IconButton/IconButton.stories.tsx b/code/core/src/components/components/IconButton/IconButton.stories.tsx index b7c8584cc15..b30009355b1 100644 --- a/code/core/src/components/components/IconButton/IconButton.stories.tsx +++ b/code/core/src/components/components/IconButton/IconButton.stories.tsx @@ -1,7 +1,8 @@ import React from 'react'; import { FaceHappyIcon } from '@storybook/icons'; -import type { Meta, StoryObj } from '@storybook/react'; + +import type { Meta, StoryObj } from '@storybook/react-vite'; import { IconButton } from './IconButton'; diff --git a/code/core/src/components/components/Modal/Modal.stories.tsx b/code/core/src/components/components/Modal/Modal.stories.tsx index 998e033d312..71008f98287 100644 --- a/code/core/src/components/components/Modal/Modal.stories.tsx +++ b/code/core/src/components/components/Modal/Modal.stories.tsx @@ -1,7 +1,8 @@ import React, { useState } from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, userEvent, within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { expect, userEvent, within } from 'storybook/test'; import { Button } from '../Button/Button'; import { Modal } from './Modal'; diff --git a/code/core/src/components/components/ProgressSpinner/ProgressSpinner.stories.tsx b/code/core/src/components/components/ProgressSpinner/ProgressSpinner.stories.tsx index b0f03752bed..95724e3aa6d 100644 --- a/code/core/src/components/components/ProgressSpinner/ProgressSpinner.stories.tsx +++ b/code/core/src/components/components/ProgressSpinner/ProgressSpinner.stories.tsx @@ -1,7 +1,8 @@ import React from 'react'; import { StopAltIcon } from '@storybook/icons'; -import type { Meta, StoryObj } from '@storybook/react'; + +import type { Meta, StoryObj } from '@storybook/react-vite'; import { ProgressSpinner } from './ProgressSpinner'; diff --git a/code/core/src/components/components/syntaxhighlighter/syntaxhighlighter.stories.tsx b/code/core/src/components/components/syntaxhighlighter/syntaxhighlighter.stories.tsx index 25367395b9c..0996291bf5c 100644 --- a/code/core/src/components/components/syntaxhighlighter/syntaxhighlighter.stories.tsx +++ b/code/core/src/components/components/syntaxhighlighter/syntaxhighlighter.stories.tsx @@ -180,7 +180,7 @@ export const UnsupportedDark = { export const Story = { args: { language: 'jsx', - children: `import type { Meta, StoryObj } from '@storybook/react'; + children: `import type { Meta, StoryObj } from '@storybook/react-vite'; import { Header } from './Header'; diff --git a/code/core/src/components/components/tabs/EmptyTabContent.stories.tsx b/code/core/src/components/components/tabs/EmptyTabContent.stories.tsx index fa4b90e709c..313607e8e6b 100644 --- a/code/core/src/components/components/tabs/EmptyTabContent.stories.tsx +++ b/code/core/src/components/components/tabs/EmptyTabContent.stories.tsx @@ -3,7 +3,8 @@ import React from 'react'; import { Link } from 'storybook/internal/components'; import { DocumentIcon } from '@storybook/icons'; -import type { Meta, StoryObj } from '@storybook/react'; + +import type { Meta, StoryObj } from '@storybook/react-vite'; import { EmptyTabContent } from './EmptyTabContent'; diff --git a/code/core/src/components/components/tabs/tabs.stories.tsx b/code/core/src/components/components/tabs/tabs.stories.tsx index f70565a2102..e9e9fb72c68 100644 --- a/code/core/src/components/components/tabs/tabs.stories.tsx +++ b/code/core/src/components/components/tabs/tabs.stories.tsx @@ -1,12 +1,14 @@ import React from 'react'; import { BottomBarIcon, CloseIcon } from '@storybook/icons'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect } from '@storybook/test'; -import { findByText, fireEvent, screen, userEvent, waitFor, within } from '@storybook/test'; + +import type { Meta, StoryObj } from '@storybook/react-vite'; import { action } from '@storybook/addon-actions'; +import { expect } from 'storybook/test'; +import { findByText, fireEvent, screen, userEvent, waitFor, within } from 'storybook/test'; + import { IconButton } from '../IconButton/IconButton'; import { TabWrapper, Tabs, TabsState } from './tabs'; import type { ChildrenList } from './tabs.helpers'; diff --git a/code/core/src/components/components/tooltip/TooltipLinkList.stories.tsx b/code/core/src/components/components/tooltip/TooltipLinkList.stories.tsx index 07e5ed7fc8d..3ada8459610 100644 --- a/code/core/src/components/components/tooltip/TooltipLinkList.stories.tsx +++ b/code/core/src/components/components/tooltip/TooltipLinkList.stories.tsx @@ -1,7 +1,8 @@ import React from 'react'; import { LinkIcon, LinuxIcon } from '@storybook/icons'; -import type { Meta, StoryObj } from '@storybook/react'; + +import type { Meta, StoryObj } from '@storybook/react-vite'; import { action } from '@storybook/addon-actions'; diff --git a/code/core/src/components/components/tooltip/TooltipMessage.stories.tsx b/code/core/src/components/components/tooltip/TooltipMessage.stories.tsx index c84eb4dcc40..d55d5247d9c 100644 --- a/code/core/src/components/components/tooltip/TooltipMessage.stories.tsx +++ b/code/core/src/components/components/tooltip/TooltipMessage.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import type { Meta } from '@storybook/react'; +import type { Meta } from '@storybook/react-vite'; import { TooltipMessage } from './TooltipMessage'; import { WithTooltip } from './WithTooltip'; diff --git a/code/core/src/components/components/tooltip/WithTooltip.stories.tsx b/code/core/src/components/components/tooltip/WithTooltip.stories.tsx index 952dceeaf51..dc959ca07f1 100644 --- a/code/core/src/components/components/tooltip/WithTooltip.stories.tsx +++ b/code/core/src/components/components/tooltip/WithTooltip.stories.tsx @@ -3,8 +3,9 @@ import React from 'react'; import { styled } from 'storybook/internal/theming'; -import type { StoryObj } from '@storybook/react'; -import { expect, screen } from '@storybook/test'; +import type { StoryObj } from '@storybook/react-vite'; + +import { expect, screen } from 'storybook/test'; import { TooltipMessage } from './TooltipMessage'; import { WithToolTipState as WithTooltip } from './WithTooltip'; diff --git a/code/core/src/core-server/utils/save-story/mocks/csf-variances.stories.tsx b/code/core/src/core-server/utils/save-story/mocks/csf-variances.stories.tsx index 674605e2ac4..bc388c16647 100644 --- a/code/core/src/core-server/utils/save-story/mocks/csf-variances.stories.tsx +++ b/code/core/src/core-server/utils/save-story/mocks/csf-variances.stories.tsx @@ -1,7 +1,7 @@ import React from 'react'; import type { FC } from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; export default { title: 'MyComponent', diff --git a/code/core/src/core-server/utils/save-story/mocks/data-variances.stories.tsx b/code/core/src/core-server/utils/save-story/mocks/data-variances.stories.tsx index e049efd5339..f75b6675ddf 100644 --- a/code/core/src/core-server/utils/save-story/mocks/data-variances.stories.tsx +++ b/code/core/src/core-server/utils/save-story/mocks/data-variances.stories.tsx @@ -1,7 +1,7 @@ import React from 'react'; import type { FC } from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; export default { title: 'MyComponent', diff --git a/code/core/src/core-server/utils/save-story/mocks/export-variances.stories.tsx b/code/core/src/core-server/utils/save-story/mocks/export-variances.stories.tsx index 3fc94bcceaa..b0f0c86b611 100644 --- a/code/core/src/core-server/utils/save-story/mocks/export-variances.stories.tsx +++ b/code/core/src/core-server/utils/save-story/mocks/export-variances.stories.tsx @@ -1,7 +1,7 @@ import React from 'react'; import type { FC } from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; export default { title: 'MyComponent', diff --git a/code/core/src/core-server/utils/save-story/mocks/typescript-constructs.stories.tsx b/code/core/src/core-server/utils/save-story/mocks/typescript-constructs.stories.tsx index 0d4aa951ad8..8e99617dcbb 100644 --- a/code/core/src/core-server/utils/save-story/mocks/typescript-constructs.stories.tsx +++ b/code/core/src/core-server/utils/save-story/mocks/typescript-constructs.stories.tsx @@ -1,7 +1,7 @@ import React from 'react'; import type { FC } from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; export default { title: 'MyComponent', diff --git a/code/core/src/core-server/utils/save-story/mocks/unsupported-csf-variances.stories.tsx b/code/core/src/core-server/utils/save-story/mocks/unsupported-csf-variances.stories.tsx index 7a300959e0a..05b0b8fd900 100644 --- a/code/core/src/core-server/utils/save-story/mocks/unsupported-csf-variances.stories.tsx +++ b/code/core/src/core-server/utils/save-story/mocks/unsupported-csf-variances.stories.tsx @@ -1,7 +1,7 @@ import React from 'react'; import type { FC } from 'react'; -import type { Meta } from '@storybook/react'; +import type { Meta } from '@storybook/react-vite'; export default { title: 'MyComponent', diff --git a/code/core/src/core-server/utils/warnWhenUsingArgTypesRegex.ts b/code/core/src/core-server/utils/warnWhenUsingArgTypesRegex.ts index 87d5d601dcd..740720e49d9 100644 --- a/code/core/src/core-server/utils/warnWhenUsingArgTypesRegex.ts +++ b/code/core/src/core-server/utils/warnWhenUsingArgTypesRegex.ts @@ -43,7 +43,7 @@ export async function warnWhenUsingArgTypesRegex( 'argTypesRegex' )} and assigning explicit action with the ${picocolors.cyan( 'fn' - )} function from ${picocolors.cyan('@storybook/test')} instead: + )} function from ${picocolors.cyan('storybook/test')} instead: https://storybook.js.org/docs/essentials/actions#via-storybooktest-fn-spy-function The build used by the addon for snapshot testing doesn't take the regex into account, which can cause hard to debug problems when a snapshot depends on the presence of action props. diff --git a/code/core/src/instrumenter/README.md b/code/core/src/instrumenter/README.md index 9f0227e0c91..058fe0e944b 100644 --- a/code/core/src/instrumenter/README.md +++ b/code/core/src/instrumenter/README.md @@ -31,7 +31,7 @@ Depending on the library and functions to be instrumented, you may want to confi `intercept` can take either a boolean (default `false`) or a function which returns a boolean. This enables you to only make specific library functions interceptable. This function receives a `method` and `path`, referring to the name of the function and the path to that function in the object tree. Some functions may return an object which is then instrumented as well, in which case the `path` will contain a "call ref", which is a plain object containing a `__callId__` property referencing the originating call. -Here's an example `intercept` function (from `@storybook/test`): +Here's an example `intercept` function (from `storybook/test`): ```js (method, path) => path[0] === 'fireEvent' || method.startsWith('findBy') || method.startsWith('waitFor'), diff --git a/code/core/src/manager-api/version.ts b/code/core/src/manager-api/version.ts index 32dd6d3b57f..4c267c031d1 100644 --- a/code/core/src/manager-api/version.ts +++ b/code/core/src/manager-api/version.ts @@ -1 +1 @@ -export const version = '9.0.0-alpha.0'; +export const version = '9.0.0-alpha.3'; diff --git a/code/core/src/manager/components/layout/Layout.stories.tsx b/code/core/src/manager/components/layout/Layout.stories.tsx index e3f19df412d..df183c4ea0d 100644 --- a/code/core/src/manager/components/layout/Layout.stories.tsx +++ b/code/core/src/manager/components/layout/Layout.stories.tsx @@ -4,11 +4,12 @@ import React, { useState } from 'react'; import { LocationProvider } from 'storybook/internal/router'; import { styled } from 'storybook/internal/theming'; -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { action } from '@storybook/addon-actions'; +import { fn } from 'storybook/test'; + import MobileNavigationStoriesMeta from '../mobile/navigation/MobileNavigation.stories'; import { Layout } from './Layout'; import { LayoutProvider } from './LayoutProvider'; diff --git a/code/core/src/manager/components/mobile/about/MobileAbout.stories.tsx b/code/core/src/manager/components/mobile/about/MobileAbout.stories.tsx index 36759e03950..40ffe255580 100644 --- a/code/core/src/manager/components/mobile/about/MobileAbout.stories.tsx +++ b/code/core/src/manager/components/mobile/about/MobileAbout.stories.tsx @@ -2,8 +2,9 @@ import React, { useEffect } from 'react'; import { ManagerContext } from 'storybook/internal/manager-api'; -import type { Meta, StoryObj } from '@storybook/react'; -import { within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { within } from 'storybook/test'; import { LayoutProvider, useLayout } from '../../layout/LayoutProvider'; import { MobileAbout } from './MobileAbout'; diff --git a/code/core/src/manager/components/mobile/navigation/MobileNavigation.stories.tsx b/code/core/src/manager/components/mobile/navigation/MobileNavigation.stories.tsx index 3ee9be594fc..26913cee363 100644 --- a/code/core/src/manager/components/mobile/navigation/MobileNavigation.stories.tsx +++ b/code/core/src/manager/components/mobile/navigation/MobileNavigation.stories.tsx @@ -2,10 +2,10 @@ import React from 'react'; import { ManagerContext } from 'storybook/internal/manager-api'; -import type { Meta, StoryObj } from '@storybook/react'; -import { within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { startCase } from 'es-toolkit'; +import { within } from 'storybook/test'; import { LayoutProvider, useLayout } from '../../layout/LayoutProvider'; import { MobileNavigation } from './MobileNavigation'; diff --git a/code/core/src/manager/components/notifications/NotificationItem.stories.tsx b/code/core/src/manager/components/notifications/NotificationItem.stories.tsx index 3af2381d945..ee0c1fd0999 100644 --- a/code/core/src/manager/components/notifications/NotificationItem.stories.tsx +++ b/code/core/src/manager/components/notifications/NotificationItem.stories.tsx @@ -7,11 +7,13 @@ import { BookIcon as BookIconIcon, FaceHappyIcon, } from '@storybook/icons'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, fn, userEvent, waitFor, within } from '@storybook/test'; + +import type { Meta, StoryObj } from '@storybook/react-vite'; import { action } from '@storybook/addon-actions'; +import { expect, fn, userEvent, waitFor, within } from 'storybook/test'; + import NotificationItem from './NotificationItem'; const meta = { diff --git a/code/core/src/manager/components/notifications/NotificationList.stories.tsx b/code/core/src/manager/components/notifications/NotificationList.stories.tsx index d79faa6da1f..7eecc760ba1 100644 --- a/code/core/src/manager/components/notifications/NotificationList.stories.tsx +++ b/code/core/src/manager/components/notifications/NotificationList.stories.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { LocationProvider } from 'storybook/internal/router'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import * as itemStories from './NotificationItem.stories'; import { NotificationList } from './NotificationList'; diff --git a/code/core/src/manager/components/sidebar/FileSearchList.stories.tsx b/code/core/src/manager/components/sidebar/FileSearchList.stories.tsx index 7388bf3cb4a..e7c983aadef 100644 --- a/code/core/src/manager/components/sidebar/FileSearchList.stories.tsx +++ b/code/core/src/manager/components/sidebar/FileSearchList.stories.tsx @@ -1,5 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, findByText, fireEvent, fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { expect, findByText, fireEvent, fn } from 'storybook/test'; import { FileSearchList } from './FileSearchList'; diff --git a/code/core/src/manager/components/sidebar/FileSearchListSkeleton.stories.tsx b/code/core/src/manager/components/sidebar/FileSearchListSkeleton.stories.tsx index d8d38eeb688..f7e4e436e33 100644 --- a/code/core/src/manager/components/sidebar/FileSearchListSkeleton.stories.tsx +++ b/code/core/src/manager/components/sidebar/FileSearchListSkeleton.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { FileSearchListLoadingSkeleton } from './FileSearchListSkeleton'; diff --git a/code/core/src/manager/components/sidebar/FileSearchModal.stories.tsx b/code/core/src/manager/components/sidebar/FileSearchModal.stories.tsx index c9e1790ef11..ef6a8ecf978 100644 --- a/code/core/src/manager/components/sidebar/FileSearchModal.stories.tsx +++ b/code/core/src/manager/components/sidebar/FileSearchModal.stories.tsx @@ -1,7 +1,8 @@ import React, { useState } from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, findByText, fireEvent, fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { expect, findByText, fireEvent, fn } from 'storybook/test'; import { WithResults } from './FileSearchList.stories'; import { FileSearchModal } from './FileSearchModal'; diff --git a/code/core/src/manager/components/sidebar/FilterToggle.stories.ts b/code/core/src/manager/components/sidebar/FilterToggle.stories.ts index 075b8c94dc9..f7528c87afe 100644 --- a/code/core/src/manager/components/sidebar/FilterToggle.stories.ts +++ b/code/core/src/manager/components/sidebar/FilterToggle.stories.ts @@ -1,4 +1,4 @@ -import { fn } from '@storybook/test'; +import { fn } from 'storybook/test'; import { FilterToggle } from './FilterToggle'; diff --git a/code/core/src/manager/components/sidebar/Heading.stories.tsx b/code/core/src/manager/components/sidebar/Heading.stories.tsx index 8e12d3eb777..208a62e4469 100644 --- a/code/core/src/manager/components/sidebar/Heading.stories.tsx +++ b/code/core/src/manager/components/sidebar/Heading.stories.tsx @@ -4,11 +4,12 @@ import React from 'react'; import { ThemeProvider, useTheme } from 'storybook/internal/theming'; import type { Theme } from 'storybook/internal/theming'; -import type { Meta, StoryFn, StoryObj } from '@storybook/react'; -import { screen } from '@storybook/test'; +import type { Meta, StoryFn, StoryObj } from '@storybook/react-vite'; import { action } from '@storybook/addon-actions'; +import { screen } from 'storybook/test'; + import { Heading } from './Heading'; type Story = StoryFn; diff --git a/code/core/src/manager/components/sidebar/IconSymbols.stories.tsx b/code/core/src/manager/components/sidebar/IconSymbols.stories.tsx index 143c08932d3..39f05e6e005 100644 --- a/code/core/src/manager/components/sidebar/IconSymbols.stories.tsx +++ b/code/core/src/manager/components/sidebar/IconSymbols.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { IconSymbols } from './IconSymbols'; diff --git a/code/core/src/manager/components/sidebar/Menu.stories.tsx b/code/core/src/manager/components/sidebar/Menu.stories.tsx index 858a04a2be9..fb5f34170b4 100644 --- a/code/core/src/manager/components/sidebar/Menu.stories.tsx +++ b/code/core/src/manager/components/sidebar/Menu.stories.tsx @@ -5,8 +5,10 @@ import type { State } from 'storybook/internal/manager-api'; import { styled } from 'storybook/internal/theming'; import { LinkIcon } from '@storybook/icons'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, screen, userEvent, within } from '@storybook/test'; + +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { expect, screen, userEvent, within } from 'storybook/test'; import { useMenu } from '../../container/Menu'; import { LayoutProvider } from '../layout/LayoutProvider'; diff --git a/code/core/src/manager/components/sidebar/Refs.stories.tsx b/code/core/src/manager/components/sidebar/Refs.stories.tsx index c137c252e11..7dd746e4123 100644 --- a/code/core/src/manager/components/sidebar/Refs.stories.tsx +++ b/code/core/src/manager/components/sidebar/Refs.stories.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { ManagerContext } from 'storybook/internal/manager-api'; -import { fn } from '@storybook/test'; +import { fn } from 'storybook/test'; import { standardData as standardHeaderData } from './Heading.stories'; import { IconSymbols } from './IconSymbols'; diff --git a/code/core/src/manager/components/sidebar/Search.stories.tsx b/code/core/src/manager/components/sidebar/Search.stories.tsx index 09a34d80dc8..0d83f2f1ad6 100644 --- a/code/core/src/manager/components/sidebar/Search.stories.tsx +++ b/code/core/src/manager/components/sidebar/Search.stories.tsx @@ -3,7 +3,7 @@ import React from 'react'; import type { API } from 'storybook/internal/manager-api'; import { ManagerContext } from 'storybook/internal/manager-api'; -import type { Meta, StoryFn } from '@storybook/react'; +import type { Meta, StoryFn } from '@storybook/react-vite'; import { action } from '@storybook/addon-actions'; diff --git a/code/core/src/manager/components/sidebar/Sidebar.stories.tsx b/code/core/src/manager/components/sidebar/Sidebar.stories.tsx index 973419fccc7..505e011cfc0 100644 --- a/code/core/src/manager/components/sidebar/Sidebar.stories.tsx +++ b/code/core/src/manager/components/sidebar/Sidebar.stories.tsx @@ -4,8 +4,9 @@ import type { IndexHash, State } from 'storybook/internal/manager-api'; import { ManagerContext } from 'storybook/internal/manager-api'; import type { API_StatusState, Addon_SidebarTopType } from 'storybook/internal/types'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, fn, userEvent, within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { expect, fn, userEvent, within } from 'storybook/test'; import { LayoutProvider } from '../layout/LayoutProvider'; import { standardData as standardHeaderData } from './Heading.stories'; diff --git a/code/core/src/manager/components/sidebar/SidebarBottom.stories.tsx b/code/core/src/manager/components/sidebar/SidebarBottom.stories.tsx index 9d7fd7d8392..93805bbc4f3 100644 --- a/code/core/src/manager/components/sidebar/SidebarBottom.stories.tsx +++ b/code/core/src/manager/components/sidebar/SidebarBottom.stories.tsx @@ -3,8 +3,9 @@ import React, { type FC, useEffect, useState } from 'react'; import { type API, ManagerContext } from 'storybook/internal/manager-api'; import { Addon_TypesEnum } from 'storybook/internal/types'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, fireEvent, fn, waitFor, within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { expect, fireEvent, fn, waitFor, within } from 'storybook/test'; import { SidebarBottomBase } from './SidebarBottom'; diff --git a/code/core/src/manager/components/sidebar/TagsFilter.stories.tsx b/code/core/src/manager/components/sidebar/TagsFilter.stories.tsx index 89236acda68..d7be4feedc3 100644 --- a/code/core/src/manager/components/sidebar/TagsFilter.stories.tsx +++ b/code/core/src/manager/components/sidebar/TagsFilter.stories.tsx @@ -1,5 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { findByRole, fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { findByRole, fn } from 'storybook/test'; import { TagsFilter } from './TagsFilter'; diff --git a/code/core/src/manager/components/sidebar/TagsFilterPanel.stories.tsx b/code/core/src/manager/components/sidebar/TagsFilterPanel.stories.tsx index 0602d0ed7a4..7884b231d30 100644 --- a/code/core/src/manager/components/sidebar/TagsFilterPanel.stories.tsx +++ b/code/core/src/manager/components/sidebar/TagsFilterPanel.stories.tsx @@ -1,5 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { fn } from 'storybook/test'; import { TagsFilterPanel } from './TagsFilterPanel'; diff --git a/code/core/src/manager/components/sidebar/TestingModule.stories.tsx b/code/core/src/manager/components/sidebar/TestingModule.stories.tsx index 854ce9b2213..ec1837d148e 100644 --- a/code/core/src/manager/components/sidebar/TestingModule.stories.tsx +++ b/code/core/src/manager/components/sidebar/TestingModule.stories.tsx @@ -6,8 +6,9 @@ import { ManagerContext, mockChannel } from 'storybook/internal/manager-api'; import { styled } from 'storybook/internal/theming'; import { Addon_TypesEnum } from 'storybook/internal/types'; -import type { Meta, StoryObj } from '@storybook/react'; -import { fireEvent, fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { fireEvent, fn } from 'storybook/test'; import { TestingModule } from './TestingModule'; diff --git a/code/core/src/manager/components/sidebar/Tree.stories.tsx b/code/core/src/manager/components/sidebar/Tree.stories.tsx index fdc231ba94f..40ead720cdf 100644 --- a/code/core/src/manager/components/sidebar/Tree.stories.tsx +++ b/code/core/src/manager/components/sidebar/Tree.stories.tsx @@ -7,11 +7,12 @@ import { ManagerContext, } from 'storybook/internal/manager-api'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, fn, userEvent, within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { action } from '@storybook/addon-actions'; +import { expect, fn, userEvent, within } from 'storybook/test'; + import { DEFAULT_REF_ID } from './Sidebar'; import { Tree } from './Tree'; import { index } from './mockdata.large'; diff --git a/code/core/src/manager/components/upgrade/UpgradeBlock.stories.tsx b/code/core/src/manager/components/upgrade/UpgradeBlock.stories.tsx index e882a41bf18..b3c3fdae32d 100644 --- a/code/core/src/manager/components/upgrade/UpgradeBlock.stories.tsx +++ b/code/core/src/manager/components/upgrade/UpgradeBlock.stories.tsx @@ -2,8 +2,9 @@ import React from 'react'; import { ManagerContext } from 'storybook/internal/manager-api'; -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { fn } from 'storybook/test'; import { UpgradeBlock } from './UpgradeBlock'; diff --git a/code/core/src/manager/container/Menu.stories.tsx b/code/core/src/manager/container/Menu.stories.tsx index c2633bb73df..1ba78e1652e 100644 --- a/code/core/src/manager/container/Menu.stories.tsx +++ b/code/core/src/manager/container/Menu.stories.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { TooltipLinkList, WithTooltip } from 'storybook/internal/components'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { action } from '@storybook/addon-actions'; diff --git a/code/core/src/manager/settings/SettingsFooter.stories.tsx b/code/core/src/manager/settings/SettingsFooter.stories.tsx index fb138e96b68..12b4af50f42 100644 --- a/code/core/src/manager/settings/SettingsFooter.stories.tsx +++ b/code/core/src/manager/settings/SettingsFooter.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import type { Decorator } from '@storybook/react'; +import type { Decorator } from '@storybook/react-vite'; import SettingsFooter from './SettingsFooter'; diff --git a/code/core/src/manager/settings/about.stories.tsx b/code/core/src/manager/settings/about.stories.tsx index d63d246d447..a89d90078bd 100644 --- a/code/core/src/manager/settings/about.stories.tsx +++ b/code/core/src/manager/settings/about.stories.tsx @@ -1,7 +1,8 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { fn } from 'storybook/test'; import UpgradeBlockStoriesMeta from '../components/upgrade/UpgradeBlock.stories'; import { AboutScreen } from './About'; diff --git a/code/core/src/manager/settings/shortcuts.stories.tsx b/code/core/src/manager/settings/shortcuts.stories.tsx index 67f3b97a149..b58bc38e11e 100644 --- a/code/core/src/manager/settings/shortcuts.stories.tsx +++ b/code/core/src/manager/settings/shortcuts.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import type { Decorator } from '@storybook/react'; +import type { Decorator } from '@storybook/react-vite'; import { actions as makeActions } from '@storybook/addon-actions'; diff --git a/code/core/src/manager/settings/whats_new_footer.stories.tsx b/code/core/src/manager/settings/whats_new_footer.stories.tsx index 9e0a88c0456..440bdf19919 100644 --- a/code/core/src/manager/settings/whats_new_footer.stories.tsx +++ b/code/core/src/manager/settings/whats_new_footer.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { WhatsNewFooter } from './whats_new'; diff --git a/code/core/src/preview-errors.ts b/code/core/src/preview-errors.ts index eb083277daa..bed6db57243 100644 --- a/code/core/src/preview-errors.ts +++ b/code/core/src/preview-errors.ts @@ -60,7 +60,7 @@ export class ImplicitActionsDuringRendering extends StorybookError { We detected that you use an implicit action arg while ${data.phase} of your story. ${data.deprecated ? `\nThis is deprecated and won't work in Storybook 8 anymore.\n` : ``} Please provide an explicit spy to your args like this: - import { fn } from '@storybook/test'; + import { fn } from 'storybook/test'; ... args: { ${data.name}: fn() diff --git a/code/core/src/shared/universal-store/index.test.ts b/code/core/src/shared/universal-store/index.test.ts index ced89580978..c589a79539f 100644 --- a/code/core/src/shared/universal-store/index.test.ts +++ b/code/core/src/shared/universal-store/index.test.ts @@ -46,9 +46,12 @@ const mockChannel = { describe('UniversalStore', () => { beforeEach((context) => { vi.useFakeTimers(); - let randomUUIDCounter = 0; - vi.spyOn(globalThis.crypto, 'randomUUID').mockImplementation(() => { - return `mocked-random-uuid-v4-${randomUUIDCounter++}`; + + // Mock Date and Math.random to make the actorId deterministic + let randomNumberCounter = 1; + vi.setSystemTime(new Date('2025-02-14')); + vi.spyOn(Math, 'random').mockImplementation(() => { + return randomNumberCounter++ / 10; }); // Always prepare the store, unless the test is specifically for unprepared state @@ -57,7 +60,7 @@ describe('UniversalStore', () => { } return () => { - randomUUIDCounter = 0; + randomNumberCounter = 0; vi.clearAllTimers(); mockedInstances.clearAllEnvironments(); mockChannelListeners.clear(); @@ -78,7 +81,7 @@ describe('UniversalStore', () => { // Assert - the store should be created with the initial state and actor expect(store.getState()).toEqual({ count: 0 }); expect(store.actor.type).toBe('LEADER'); - expect(store.actor.id).toBe('mocked-random-uuid-v4-0'); + expect(store.actor.id).toBe('m7405c003lllllllllm'); }); it('should throw when trying to create an instance with the constructor directly', () => { @@ -195,7 +198,6 @@ You should reuse the existing instance instead of trying to create a new one.`); // Arrange - create an initial leader and follower vi.spyOn(console, 'error').mockImplementation(() => {}); - vi.spyOn(globalThis.crypto, 'randomUUID').mockReturnValueOnce('first-uuid-1-2-3-4'); const firstLeader = UniversalStore.create({ id: 'env1:test', leader: true, @@ -203,7 +205,6 @@ You should reuse the existing instance instead of trying to create a new one.`); }); // Act - create the second leader - vi.spyOn(globalThis.crypto, 'randomUUID').mockReturnValueOnce('second-uuid-1-2-3-4'); const secondLeader = UniversalStore.create({ id: 'env2:test', leader: true, @@ -250,12 +251,12 @@ You should reuse the existing instance instead of trying to create a new one.`); Only one leader can exists at a time, your stores are now in an invalid state. Leaders detected: this: { - "id": "second-uuid-1-2-3-4", + "id": "m7405c0077777777778", "type": "LEADER", "environment": "MANAGER" } other: { - "id": "first-uuid-1-2-3-4", + "id": "m7405c003lllllllllm", "type": "LEADER", "environment": "MANAGER" }` @@ -266,12 +267,12 @@ You should reuse the existing instance instead of trying to create a new one.`); Only one leader can exists at a time, your stores are now in an invalid state. Leaders detected: this: { - "id": "first-uuid-1-2-3-4", + "id": "m7405c003lllllllllm", "type": "LEADER", "environment": "MANAGER" } other: { - "id": "second-uuid-1-2-3-4", + "id": "m7405c0077777777778", "type": "LEADER", "environment": "MANAGER" }` @@ -290,7 +291,7 @@ You should reuse the existing instance instead of trying to create a new one.`); // Assert - the store should be created with the initial state and actor expect(store.getState()).toEqual(undefined); expect(store.actor.type).toBe('FOLLOWER'); - expect(store.actor.id).toBe('mocked-random-uuid-v4-0'); + expect(store.actor.id).toBe('m7405c003lllllllllm'); }); it('should get existing state when a follower is created without initialState', async () => { @@ -325,7 +326,7 @@ You should reuse the existing instance instead of trying to create a new one.`); "eventInfo": { "actor": { "environment": "MANAGER", - "id": "mocked-random-uuid-v4-0", + "id": "m7405c003lllllllllm", "type": "LEADER", }, }, @@ -340,7 +341,7 @@ You should reuse the existing instance instead of trying to create a new one.`); "eventInfo": { "actor": { "environment": "MANAGER", - "id": "mocked-random-uuid-v4-1", + "id": "m7405c0077777777778", "type": "FOLLOWER", }, }, @@ -355,7 +356,7 @@ You should reuse the existing instance instead of trying to create a new one.`); "eventInfo": { "actor": { "environment": "MANAGER", - "id": "mocked-random-uuid-v4-1", + "id": "m7405c0077777777778", "type": "FOLLOWER", }, }, @@ -370,12 +371,12 @@ You should reuse the existing instance instead of trying to create a new one.`); "eventInfo": { "actor": { "environment": "MANAGER", - "id": "mocked-random-uuid-v4-1", + "id": "m7405c0077777777778", "type": "FOLLOWER", }, "forwardingActor": { "environment": "MANAGER", - "id": "mocked-random-uuid-v4-0", + "id": "m7405c003lllllllllm", "type": "LEADER", }, }, @@ -393,7 +394,7 @@ You should reuse the existing instance instead of trying to create a new one.`); "eventInfo": { "actor": { "environment": "MANAGER", - "id": "mocked-random-uuid-v4-0", + "id": "m7405c003lllllllllm", "type": "LEADER", }, }, @@ -437,7 +438,7 @@ You should reuse the existing instance instead of trying to create a new one.`); "eventInfo": { "actor": { "environment": "MANAGER", - "id": "mocked-random-uuid-v4-0", + "id": "m7405c003lllllllllm", "type": "LEADER", }, }, @@ -452,7 +453,7 @@ You should reuse the existing instance instead of trying to create a new one.`); "eventInfo": { "actor": { "environment": "MANAGER", - "id": "mocked-random-uuid-v4-1", + "id": "m7405c0077777777778", "type": "FOLLOWER", }, }, @@ -467,7 +468,7 @@ You should reuse the existing instance instead of trying to create a new one.`); "eventInfo": { "actor": { "environment": "MANAGER", - "id": "mocked-random-uuid-v4-1", + "id": "m7405c0077777777778", "type": "FOLLOWER", }, }, @@ -482,12 +483,12 @@ You should reuse the existing instance instead of trying to create a new one.`); "eventInfo": { "actor": { "environment": "MANAGER", - "id": "mocked-random-uuid-v4-1", + "id": "m7405c0077777777778", "type": "FOLLOWER", }, "forwardingActor": { "environment": "MANAGER", - "id": "mocked-random-uuid-v4-0", + "id": "m7405c003lllllllllm", "type": "LEADER", }, }, @@ -505,7 +506,7 @@ You should reuse the existing instance instead of trying to create a new one.`); "eventInfo": { "actor": { "environment": "MANAGER", - "id": "mocked-random-uuid-v4-0", + "id": "m7405c003lllllllllm", "type": "LEADER", }, }, @@ -560,7 +561,7 @@ You should reuse the existing instance instead of trying to create a new one.`); "eventInfo": { "actor": { "environment": "MANAGER", - "id": "mocked-random-uuid-v4-0", + "id": "m7405c003lllllllllm", "type": "LEADER", }, }, @@ -575,7 +576,7 @@ You should reuse the existing instance instead of trying to create a new one.`); "eventInfo": { "actor": { "environment": "MANAGER", - "id": "mocked-random-uuid-v4-1", + "id": "m7405c0077777777778", "type": "FOLLOWER", }, }, @@ -590,7 +591,7 @@ You should reuse the existing instance instead of trying to create a new one.`); "eventInfo": { "actor": { "environment": "MANAGER", - "id": "mocked-random-uuid-v4-1", + "id": "m7405c0077777777778", "type": "FOLLOWER", }, }, @@ -605,12 +606,12 @@ You should reuse the existing instance instead of trying to create a new one.`); "eventInfo": { "actor": { "environment": "MANAGER", - "id": "mocked-random-uuid-v4-1", + "id": "m7405c0077777777778", "type": "FOLLOWER", }, "forwardingActor": { "environment": "MANAGER", - "id": "mocked-random-uuid-v4-0", + "id": "m7405c003lllllllllm", "type": "LEADER", }, }, @@ -628,7 +629,7 @@ You should reuse the existing instance instead of trying to create a new one.`); "eventInfo": { "actor": { "environment": "MANAGER", - "id": "mocked-random-uuid-v4-0", + "id": "m7405c003lllllllllm", "type": "LEADER", }, }, @@ -664,7 +665,7 @@ You should reuse the existing instance instead of trying to create a new one.`); "eventInfo": { "actor": { "environment": "MANAGER", - "id": "mocked-random-uuid-v4-0", + "id": "m7405c003lllllllllm", "type": "FOLLOWER", }, }, @@ -679,7 +680,7 @@ You should reuse the existing instance instead of trying to create a new one.`); "eventInfo": { "actor": { "environment": "MANAGER", - "id": "mocked-random-uuid-v4-0", + "id": "m7405c003lllllllllm", "type": "FOLLOWER", }, }, @@ -951,7 +952,7 @@ You should reuse the existing instance instead of trying to create a new one.`); }, "id": "env2:test", "actor": { - "id": "mocked-random-uuid-v4-1", + "id": "m7405c0077777777778", "type": "FOLLOWER", "environment": "MANAGER" }, @@ -1136,7 +1137,7 @@ You should reuse the existing instance instead of trying to create a new one.`); }, "id": "env2:test", "actor": { - "id": "mocked-random-uuid-v4-1", + "id": "m7405c0077777777778", "type": "FOLLOWER", "environment": "MANAGER" }, diff --git a/code/core/src/shared/universal-store/index.ts b/code/core/src/shared/universal-store/index.ts index 3e033c0c5e1..df94ca009c4 100644 --- a/code/core/src/shared/universal-store/index.ts +++ b/code/core/src/shared/universal-store/index.ts @@ -259,10 +259,7 @@ export class UniversalStore< UniversalStore.isInternalConstructing = false; this.id = options.id; - this.actorId = globalThis.crypto - ? globalThis.crypto.randomUUID() - : // TODO: remove this fallback in SB 9.0 when we no longer support Node 18 - Date.now().toString(36) + Math.random().toString(36).substring(2); + this.actorId = Date.now().toString(36) + Math.random().toString(36).substring(2); this.actorType = options.leader ? UniversalStore.ActorType.LEADER : UniversalStore.ActorType.FOLLOWER; diff --git a/code/core/src/shared/universal-store/mock.ts b/code/core/src/shared/universal-store/mock.ts index a5695f48464..fc7214300ce 100644 --- a/code/core/src/shared/universal-store/mock.ts +++ b/code/core/src/shared/universal-store/mock.ts @@ -21,7 +21,7 @@ import type { StoreOptions } from './types'; * @example * * ```ts - * import * as testUtils from '@storybook/test'; // in stories + * import * as testUtils from 'storybook/test'; // in stories * import { vi as testUtils } from 'vitest'; // ... or in Vitest tests * * const initialState = { ... }; diff --git a/code/lib/test/README.md b/code/core/src/test/README.md similarity index 67% rename from code/lib/test/README.md rename to code/core/src/test/README.md index 81efc0635b0..a823cad323c 100644 --- a/code/lib/test/README.md +++ b/code/core/src/test/README.md @@ -1,18 +1,6 @@ # Storybook Test -The `@storybook/test` package contains utilities for testing your stories inside `play` functions. - -## Installation - -Install the package by adding the `@storybook/test` dev dependency: - -```sh -npm install -D @storybook/test -pnpm add -D @storybook/test -yarn add -D @storybook/test -``` - -Note that this package is not an addon, so you don't have to add it to your `main.js/main.ts` file. +The `storybook/test` package contains utilities for testing your stories inside `play` functions. ## Usage @@ -21,7 +9,7 @@ The instrumentation makes sure you can debug those methods in the [addon-interac ```ts // Button.stories.ts -import { expect, fn, userEvent, within } from '@storybook/test'; +import { expect, fn, userEvent, within } from 'storybook/test'; import { Button } from './Button'; export default { diff --git a/code/lib/test/src/expect.ts b/code/core/src/test/expect.ts similarity index 100% rename from code/lib/test/src/expect.ts rename to code/core/src/test/expect.ts diff --git a/code/lib/test/src/index.test.ts b/code/core/src/test/index.test.ts similarity index 94% rename from code/lib/test/src/index.test.ts rename to code/core/src/test/index.test.ts index e87c485c991..fb9fe2cd5ae 100644 --- a/code/lib/test/src/index.test.ts +++ b/code/core/src/test/index.test.ts @@ -1,10 +1,10 @@ // @vitest-environment happy-dom import { describe, it, test } from 'vitest'; -import { expect, fn, isMockFunction, traverseArgs } from '@storybook/test'; - import { action } from '@storybook/addon-actions'; +import { expect, fn, isMockFunction, traverseArgs } from 'storybook/test'; + it('storybook expect and fn can be used in vitest test', () => { const spy = fn(); spy(1); diff --git a/code/lib/test/src/index.ts b/code/core/src/test/index.ts similarity index 97% rename from code/lib/test/src/index.ts rename to code/core/src/test/index.ts index 54cfc8dbfa2..6c5bba5c702 100644 --- a/code/lib/test/src/index.ts +++ b/code/core/src/test/index.ts @@ -5,7 +5,7 @@ import { instrument } from 'storybook/internal/instrumenter'; import { global } from '@storybook/global'; -import * as chai from 'chai'; +import { Assertion } from 'chai'; import { expect as rawExpect } from './expect'; import { @@ -35,7 +35,7 @@ export const { expect } = instrument( { getKeys: (obj: Record, depth) => { const privateApi = ['assert', '__methods', '__flags', '_obj']; - if (obj.constructor === chai.Assertion) { + if (obj.constructor === Assertion) { const keys = Object.keys(Object.getPrototypeOf(obj)).filter( (it) => !privateApi.includes(it) ); diff --git a/code/lib/test/src/spy.test.ts b/code/core/src/test/spy.test.ts similarity index 100% rename from code/lib/test/src/spy.test.ts rename to code/core/src/test/spy.test.ts diff --git a/code/lib/test/src/spy.ts b/code/core/src/test/spy.ts similarity index 100% rename from code/lib/test/src/spy.ts rename to code/core/src/test/spy.ts diff --git a/code/lib/test/src/testing-library.ts b/code/core/src/test/testing-library.ts similarity index 97% rename from code/lib/test/src/testing-library.ts rename to code/core/src/test/testing-library.ts index c3f395640a3..a193904f804 100644 --- a/code/lib/test/src/testing-library.ts +++ b/code/core/src/test/testing-library.ts @@ -116,6 +116,7 @@ type _UserEvent = typeof _userEvent; export interface UserEvent extends _UserEvent {} export const { userEvent }: { userEvent: UserEvent } = instrument( - { userEvent: _userEvent }, + // @ts-expect-error CJS workaround + { userEvent: _userEvent.default ?? _userEvent }, { intercept: true } ); diff --git a/code/lib/test/src/utils.ts b/code/core/src/test/utils.ts similarity index 100% rename from code/lib/test/src/utils.ts rename to code/core/src/test/utils.ts diff --git a/code/core/src/types/modules/core-common.ts b/code/core/src/types/modules/core-common.ts index 135fd1cb5d1..b13f868e760 100644 --- a/code/core/src/types/modules/core-common.ts +++ b/code/core/src/types/modules/core-common.ts @@ -1,11 +1,12 @@ /* eslint-disable @typescript-eslint/naming-convention */ // should be node:http, but that caused the ui/manager to fail to build, might be able to switch this back once ui/manager is in the core +import type { FileSystemCache } from 'storybook/internal/common'; + import type { Server as HttpServer, IncomingMessage, ServerResponse } from 'http'; import type { Server as NetServer } from 'net'; import type { Options as TelejsonOptions } from 'telejson'; import type { PackageJson as PackageJsonFromTypeFest } from 'type-fest'; -import type { FileSystemCache } from '../../common/utils/file-cache'; import type { Indexer, StoriesEntry } from './indexer'; /** ⚠️ This file contains internal WIP types they MUST NOT be exported outside this package for now! */ diff --git a/code/core/template/stories/argMapping.stories.ts b/code/core/template/stories/argMapping.stories.ts index f2813a95d26..5b829b31ffa 100644 --- a/code/core/template/stories/argMapping.stories.ts +++ b/code/core/template/stories/argMapping.stories.ts @@ -1,7 +1,8 @@ import type { PartialStoryFn, PlayFunctionContext, StoryContext } from 'storybook/internal/types'; import { global as globalThis } from '@storybook/global'; -import { expect, within } from '@storybook/test'; + +import { expect, within } from 'storybook/test'; const arrows = { ArrowUp: { name: 'ArrowUp' }, diff --git a/code/core/template/stories/argTypes.stories.ts b/code/core/template/stories/argTypes.stories.ts index d64316c63b8..c97a9ef289e 100644 --- a/code/core/template/stories/argTypes.stories.ts +++ b/code/core/template/stories/argTypes.stories.ts @@ -1,7 +1,8 @@ import type { PartialStoryFn, PlayFunctionContext, StoryContext } from 'storybook/internal/types'; import { global as globalThis } from '@storybook/global'; -import { expect, within } from '@storybook/test'; + +import { expect, within } from 'storybook/test'; export default { component: globalThis.Components.Pre, diff --git a/code/core/template/stories/args.stories.ts b/code/core/template/stories/args.stories.ts index 43eed8f5070..a3b7c389475 100644 --- a/code/core/template/stories/args.stories.ts +++ b/code/core/template/stories/args.stories.ts @@ -6,7 +6,8 @@ import { import type { PartialStoryFn, PlayFunctionContext, StoryContext } from 'storybook/internal/types'; import { global as globalThis } from '@storybook/global'; -import { expect, within } from '@storybook/test'; + +import { expect, within } from 'storybook/test'; function pick(obj, keys) { const result = {}; diff --git a/code/core/template/stories/autotitle.stories.ts b/code/core/template/stories/autotitle.stories.ts index 9399cf24121..dea8cf850ad 100644 --- a/code/core/template/stories/autotitle.stories.ts +++ b/code/core/template/stories/autotitle.stories.ts @@ -1,7 +1,8 @@ import type { PlayFunctionContext } from 'storybook/internal/types'; import { global as globalThis } from '@storybook/global'; -import { expect } from '@storybook/test'; + +import { expect } from 'storybook/test'; export default { component: globalThis.Components.Pre, diff --git a/code/lib/test/template/stories/before-each.stories.ts b/code/core/template/stories/before-each.stories.ts similarity index 96% rename from code/lib/test/template/stories/before-each.stories.ts rename to code/core/template/stories/before-each.stories.ts index 0d9a88cafa3..5d23e6c8b12 100644 --- a/code/lib/test/template/stories/before-each.stories.ts +++ b/code/core/template/stories/before-each.stories.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention,storybook/prefer-pascal-case */ -import { expect } from '@storybook/test'; +import { expect } from 'storybook/test'; const meta = { component: globalThis.Components.Button, diff --git a/code/core/template/stories/component-play.stories.ts b/code/core/template/stories/component-play.stories.ts index db93783ed16..e71102fe50f 100644 --- a/code/core/template/stories/component-play.stories.ts +++ b/code/core/template/stories/component-play.stories.ts @@ -1,7 +1,8 @@ import type { PartialStoryFn, PlayFunctionContext, StoryContext } from 'storybook/internal/types'; import { global as globalThis } from '@storybook/global'; -import { expect, within } from '@storybook/test'; + +import { expect, within } from 'storybook/test'; export default { component: globalThis.Components.Pre, diff --git a/code/core/template/stories/decorators.stories.ts b/code/core/template/stories/decorators.stories.ts index d0822c0ab8c..117bfdf8ce0 100644 --- a/code/core/template/stories/decorators.stories.ts +++ b/code/core/template/stories/decorators.stories.ts @@ -12,7 +12,8 @@ import type { } from 'storybook/internal/types'; import { global as globalThis } from '@storybook/global'; -import { expect, within } from '@storybook/test'; + +import { expect, within } from 'storybook/test'; export default { component: globalThis.Components.Pre, diff --git a/code/lib/test/template/stories/destructuring-not-transpiled.stories.ts b/code/core/template/stories/destructuring-not-transpiled.stories.ts similarity index 94% rename from code/lib/test/template/stories/destructuring-not-transpiled.stories.ts rename to code/core/template/stories/destructuring-not-transpiled.stories.ts index b1f2c98e220..be1b38051e8 100644 --- a/code/lib/test/template/stories/destructuring-not-transpiled.stories.ts +++ b/code/core/template/stories/destructuring-not-transpiled.stories.ts @@ -1,5 +1,6 @@ import { global as globalThis } from '@storybook/global'; -import { expect } from '@storybook/test'; + +import { expect } from 'storybook/test'; export default { component: globalThis.Components.Button, diff --git a/code/core/template/stories/globals.stories.ts b/code/core/template/stories/globals.stories.ts index cbede539ce7..cf6be5d0d1b 100644 --- a/code/core/template/stories/globals.stories.ts +++ b/code/core/template/stories/globals.stories.ts @@ -1,7 +1,8 @@ import type { PartialStoryFn, PlayFunctionContext, StoryContext } from 'storybook/internal/types'; import { global as globalThis } from '@storybook/global'; -import { expect, within } from '@storybook/test'; + +import { expect, within } from 'storybook/test'; export default { component: globalThis.Components.Pre, diff --git a/code/core/template/stories/hooks.stories.ts b/code/core/template/stories/hooks.stories.ts index b2d2cc01e73..17704662b1b 100644 --- a/code/core/template/stories/hooks.stories.ts +++ b/code/core/template/stories/hooks.stories.ts @@ -2,7 +2,8 @@ import { useEffect, useState } from 'storybook/internal/preview-api'; import type { PartialStoryFn, StoryContext } from 'storybook/internal/types'; import { global as globalThis } from '@storybook/global'; -import { userEvent, within } from '@storybook/test'; + +import { userEvent, within } from 'storybook/test'; export default { component: globalThis.Components.Button, diff --git a/code/core/template/stories/indexer.stories.ts b/code/core/template/stories/indexer.stories.ts index 684b195e5bf..1ec6ad17e5b 100644 --- a/code/core/template/stories/indexer.stories.ts +++ b/code/core/template/stories/indexer.stories.ts @@ -1,7 +1,8 @@ import type { PlayFunctionContext } from 'storybook/internal/types'; import { global as globalThis } from '@storybook/global'; -import { expect } from '@storybook/test'; + +import { expect } from 'storybook/test'; export default { component: globalThis.Components.Pre, diff --git a/code/lib/test/template/stories/loader-enhancements.stories.ts b/code/core/template/stories/loader-enhancements.stories.ts similarity index 90% rename from code/lib/test/template/stories/loader-enhancements.stories.ts rename to code/core/template/stories/loader-enhancements.stories.ts index fdd1a7c4e64..07ac2d783b6 100644 --- a/code/lib/test/template/stories/loader-enhancements.stories.ts +++ b/code/core/template/stories/loader-enhancements.stories.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention,storybook/prefer-pascal-case */ -import { expect, userEvent as globalUserEvent, within } from '@storybook/test'; +import { expect, userEvent as globalUserEvent, within } from 'storybook/test'; const meta = { component: globalThis.Components.Button, diff --git a/code/core/template/stories/loaders.stories.ts b/code/core/template/stories/loaders.stories.ts index b9a5d31eaf1..ec035ca03d4 100644 --- a/code/core/template/stories/loaders.stories.ts +++ b/code/core/template/stories/loaders.stories.ts @@ -1,7 +1,8 @@ import type { PartialStoryFn, StoryContext } from 'storybook/internal/types'; import { global as globalThis } from '@storybook/global'; -import { expect, within } from '@storybook/test'; + +import { expect, within } from 'storybook/test'; export default { component: globalThis.Components.Pre, diff --git a/code/lib/test/template/stories/module-mocking.stories.ts b/code/core/template/stories/module-mocking.stories.ts similarity index 90% rename from code/lib/test/template/stories/module-mocking.stories.ts rename to code/core/template/stories/module-mocking.stories.ts index f773f675ff5..4afd1d52663 100644 --- a/code/lib/test/template/stories/module-mocking.stories.ts +++ b/code/core/template/stories/module-mocking.stories.ts @@ -1,9 +1,9 @@ import { global as globalThis } from '@storybook/global'; -import { expect, fn, isMockFunction, mocked } from '@storybook/test'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore This alias is set in the sandbox. Using ts-ignore instead of ts-expect-error to avoid build errors in the sandbox. import { foo } from '#utils'; +import { expect, fn, isMockFunction, mocked } from 'storybook/test'; export default { component: globalThis.Components.Button, diff --git a/code/lib/test/template/stories/mount-in-play.stories.ts b/code/core/template/stories/mount-in-play.stories.ts similarity index 92% rename from code/lib/test/template/stories/mount-in-play.stories.ts rename to code/core/template/stories/mount-in-play.stories.ts index 22c92497783..795c0a2fd5a 100644 --- a/code/lib/test/template/stories/mount-in-play.stories.ts +++ b/code/core/template/stories/mount-in-play.stories.ts @@ -1,4 +1,4 @@ -import { expect, fn } from '@storybook/test'; +import { expect, fn } from 'storybook/test'; const meta = { component: globalThis.Components.Button }; diff --git a/code/core/template/stories/names.stories.ts b/code/core/template/stories/names.stories.ts index 9ad9320b4e5..14547843f34 100644 --- a/code/core/template/stories/names.stories.ts +++ b/code/core/template/stories/names.stories.ts @@ -1,7 +1,8 @@ import type { PlayFunctionContext } from 'storybook/internal/types'; import { global as globalThis } from '@storybook/global'; -import { expect } from '@storybook/test'; + +import { expect } from 'storybook/test'; export default { component: globalThis.Components.Pre, diff --git a/code/lib/test/template/stories/order-of-hooks.stories.ts b/code/core/template/stories/order-of-hooks.stories.ts similarity index 94% rename from code/lib/test/template/stories/order-of-hooks.stories.ts rename to code/core/template/stories/order-of-hooks.stories.ts index f3e965dee1b..8306457cf14 100644 --- a/code/lib/test/template/stories/order-of-hooks.stories.ts +++ b/code/core/template/stories/order-of-hooks.stories.ts @@ -1,4 +1,4 @@ -import { expect, fn, getByRole, mocked, spyOn, userEvent } from '@storybook/test'; +import { expect, getByRole, mocked, spyOn, userEvent } from 'storybook/test'; const meta = { component: globalThis.Components.Button, diff --git a/code/core/template/stories/parameters.stories.ts b/code/core/template/stories/parameters.stories.ts index 5d702019719..d1582af593a 100644 --- a/code/core/template/stories/parameters.stories.ts +++ b/code/core/template/stories/parameters.stories.ts @@ -1,7 +1,8 @@ import type { PartialStoryFn, PlayFunctionContext, StoryContext } from 'storybook/internal/types'; import { global as globalThis } from '@storybook/global'; -import { expect, within } from '@storybook/test'; + +import { expect, within } from 'storybook/test'; export default { component: globalThis.Components.Pre, diff --git a/code/core/template/stories/rendering.stories.ts b/code/core/template/stories/rendering.stories.ts index 31cb903d19b..4876376a957 100644 --- a/code/core/template/stories/rendering.stories.ts +++ b/code/core/template/stories/rendering.stories.ts @@ -7,7 +7,8 @@ import { import type { PlayFunctionContext } from 'storybook/internal/types'; import { global as globalThis } from '@storybook/global'; -import { expect, waitFor, within } from '@storybook/test'; + +import { expect, waitFor, within } from 'storybook/test'; export default { component: globalThis.Components.Button, diff --git a/code/core/template/stories/shortcuts.stories.ts b/code/core/template/stories/shortcuts.stories.ts index 998b417d3de..81bc3f5ae2a 100644 --- a/code/core/template/stories/shortcuts.stories.ts +++ b/code/core/template/stories/shortcuts.stories.ts @@ -2,7 +2,8 @@ import { PREVIEW_KEYDOWN } from 'storybook/internal/core-events'; import type { PlayFunctionContext } from 'storybook/internal/csf'; import { global as globalThis } from '@storybook/global'; -import { expect, fn, userEvent, within } from '@storybook/test'; + +import { expect, fn, userEvent, within } from 'storybook/test'; export default { component: globalThis.Components.Form, diff --git a/code/core/template/stories/tags-add.stories.ts b/code/core/template/stories/tags-add.stories.ts index a86addb4aea..078c4eb2bef 100644 --- a/code/core/template/stories/tags-add.stories.ts +++ b/code/core/template/stories/tags-add.stories.ts @@ -1,7 +1,8 @@ import type { PartialStoryFn, PlayFunctionContext, StoryContext } from 'storybook/internal/types'; import { global as globalThis } from '@storybook/global'; -import { expect, within } from '@storybook/test'; + +import { expect, within } from 'storybook/test'; export default { component: globalThis.Components.Pre, diff --git a/code/core/template/stories/tags-config.stories.ts b/code/core/template/stories/tags-config.stories.ts index 03c835832e5..04292ae8790 100644 --- a/code/core/template/stories/tags-config.stories.ts +++ b/code/core/template/stories/tags-config.stories.ts @@ -1,7 +1,8 @@ import type { PartialStoryFn, PlayFunctionContext, StoryContext } from 'storybook/internal/types'; import { global as globalThis } from '@storybook/global'; -import { expect, within } from '@storybook/test'; + +import { expect, within } from 'storybook/test'; export default { component: globalThis.Components.Pre, diff --git a/code/core/template/stories/tags-remove.stories.ts b/code/core/template/stories/tags-remove.stories.ts index 27c313381a7..133d836275c 100644 --- a/code/core/template/stories/tags-remove.stories.ts +++ b/code/core/template/stories/tags-remove.stories.ts @@ -1,7 +1,8 @@ import type { PartialStoryFn, PlayFunctionContext, StoryContext } from 'storybook/internal/types'; import { global as globalThis } from '@storybook/global'; -import { expect, within } from '@storybook/test'; + +import { expect, within } from 'storybook/test'; export default { component: globalThis.Components.Pre, diff --git a/code/core/template/stories/title.stories.ts b/code/core/template/stories/title.stories.ts index 0c0246a096f..e5fed6c34fa 100644 --- a/code/core/template/stories/title.stories.ts +++ b/code/core/template/stories/title.stories.ts @@ -1,7 +1,8 @@ import type { PlayFunctionContext } from 'storybook/internal/types'; import { global as globalThis } from '@storybook/global'; -import { expect } from '@storybook/test'; + +import { expect } from 'storybook/test'; export default { component: globalThis.Components.Pre, diff --git a/code/core/template/stories/utils.mock.ts b/code/core/template/stories/utils.mock.ts index 93a72d03a0e..430f08797ae 100644 --- a/code/core/template/stories/utils.mock.ts +++ b/code/core/template/stories/utils.mock.ts @@ -1,4 +1,4 @@ -import { fn } from '@storybook/test'; +import { fn } from 'storybook/test'; import * as utils from './utils.ts'; diff --git a/code/e2e-tests/module-mocking.spec.ts b/code/e2e-tests/module-mocking.spec.ts index 3341f644900..ae57661f1d8 100644 --- a/code/e2e-tests/module-mocking.spec.ts +++ b/code/e2e-tests/module-mocking.spec.ts @@ -15,7 +15,7 @@ test.describe('module-mocking', () => { test('should assert story lifecycle order', async ({ page }) => { const sbPage = new SbPage(page, expect); - await sbPage.navigateToStory('lib/test/order-of-hooks', 'order-of-hooks'); + await sbPage.navigateToStory('core/order-of-hooks', 'order-of-hooks'); await sbPage.viewAddonPanel('Actions'); const logItem = page.locator('#storybook-panel-root #panel-tab-content'); @@ -43,7 +43,7 @@ test.describe('module-mocking', () => { test('should assert that utils import is mocked', async ({ page }) => { const sbPage = new SbPage(page, expect); - await sbPage.navigateToStory('lib/test/module-mocking', 'basic'); + await sbPage.navigateToStory('core/module-mocking', 'basic'); await sbPage.viewAddonPanel('Actions'); const logItem = page.locator('#storybook-panel-root #panel-tab-content', { diff --git a/code/frameworks/angular/package.json b/code/frameworks/angular/package.json index 4279acdddea..37026f6bad7 100644 --- a/code/frameworks/angular/package.json +++ b/code/frameworks/angular/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/angular", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for Angular: Develop Angular components in isolation with hot reloading.", "keywords": [ "storybook", diff --git a/code/frameworks/angular/template/cli/button.stories.ts b/code/frameworks/angular/template/cli/button.stories.ts index dedeca1f2e9..5c12e314188 100644 --- a/code/frameworks/angular/template/cli/button.stories.ts +++ b/code/frameworks/angular/template/cli/button.stories.ts @@ -1,5 +1,5 @@ import type { Meta, StoryObj } from '@storybook/angular'; -import { fn } from '@storybook/test'; +import { fn } from 'storybook/test'; import { ButtonComponent } from './button.component'; diff --git a/code/frameworks/angular/template/cli/header.stories.ts b/code/frameworks/angular/template/cli/header.stories.ts index ea9b0894e4b..8a9f73b151c 100644 --- a/code/frameworks/angular/template/cli/header.stories.ts +++ b/code/frameworks/angular/template/cli/header.stories.ts @@ -1,5 +1,5 @@ import type { Meta, StoryObj } from '@storybook/angular'; -import { fn } from '@storybook/test'; +import { fn } from 'storybook/test'; import { HeaderComponent } from './header.component'; diff --git a/code/frameworks/angular/template/cli/page.stories.ts b/code/frameworks/angular/template/cli/page.stories.ts index 8237ee228b3..47c99b233f7 100644 --- a/code/frameworks/angular/template/cli/page.stories.ts +++ b/code/frameworks/angular/template/cli/page.stories.ts @@ -1,5 +1,5 @@ import type { Meta, StoryObj } from '@storybook/angular'; -import { expect, userEvent, within } from '@storybook/test'; +import { expect, userEvent, within } from 'storybook/test'; import { PageComponent } from './page.component'; diff --git a/code/frameworks/angular/template/stories_angular-cli-default-ts/signal/button.stories.ts b/code/frameworks/angular/template/stories_angular-cli-default-ts/signal/button.stories.ts index db1fa2125d5..6849fc9bb42 100644 --- a/code/frameworks/angular/template/stories_angular-cli-default-ts/signal/button.stories.ts +++ b/code/frameworks/angular/template/stories_angular-cli-default-ts/signal/button.stories.ts @@ -1,5 +1,5 @@ import { Meta, StoryObj } from '@storybook/angular'; -import { fn } from '@storybook/test'; +import { fn } from 'storybook/test'; import SignalButtonComponent from './button.component'; diff --git a/code/frameworks/angular/template/stories_angular-cli-prerelease/signal/button.stories.ts b/code/frameworks/angular/template/stories_angular-cli-prerelease/signal/button.stories.ts index db1fa2125d5..6849fc9bb42 100644 --- a/code/frameworks/angular/template/stories_angular-cli-prerelease/signal/button.stories.ts +++ b/code/frameworks/angular/template/stories_angular-cli-prerelease/signal/button.stories.ts @@ -1,5 +1,5 @@ import { Meta, StoryObj } from '@storybook/angular'; -import { fn } from '@storybook/test'; +import { fn } from 'storybook/test'; import SignalButtonComponent from './button.component'; diff --git a/code/frameworks/ember/package.json b/code/frameworks/ember/package.json index a002ee0f837..67718f63577 100644 --- a/code/frameworks/ember/package.json +++ b/code/frameworks/ember/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/ember", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for Ember: Develop Ember Component in isolation with Hot Reloading.", "homepage": "https://github.com/storybookjs/storybook/tree/next/code/frameworks/ember", "bugs": { diff --git a/code/frameworks/ember/template/cli/Button.stories.js b/code/frameworks/ember/template/cli/Button.stories.js index 35ba57166a7..93511eade46 100644 --- a/code/frameworks/ember/template/cli/Button.stories.js +++ b/code/frameworks/ember/template/cli/Button.stories.js @@ -1,9 +1,8 @@ -import { fn } from '@storybook/test'; - import { action } from '@storybook/addon-actions'; import { linkTo } from '@storybook/addon-links'; import { hbs } from 'ember-cli-htmlbars'; +import { fn } from 'storybook/test'; // More on how to set up stories at: https://storybook.js.org/docs/writing-stories export default { diff --git a/code/frameworks/experimental-nextjs-vite/package.json b/code/frameworks/experimental-nextjs-vite/package.json index 46dcf6bfd2e..b4251763c2c 100644 --- a/code/frameworks/experimental-nextjs-vite/package.json +++ b/code/frameworks/experimental-nextjs-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/experimental-nextjs-vite", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for Next.js and Vite", "keywords": [ "storybook", @@ -107,9 +107,8 @@ "@storybook/builder-vite": "workspace:*", "@storybook/react": "workspace:*", "@storybook/react-vite": "workspace:*", - "@storybook/test": "workspace:*", "styled-jsx": "5.1.6", - "vite-plugin-storybook-nextjs": "^1.1.0" + "vite-plugin-storybook-nextjs": "2.0.0--canary.33.a61ad85.0" }, "devDependencies": { "@types/node": "^22.0.0", @@ -117,7 +116,6 @@ "typescript": "^5.7.3" }, "peerDependencies": { - "@storybook/test": "workspace:*", "next": "^14.1.0 || ^15.0.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", @@ -129,9 +127,6 @@ "optional": true } }, - "optionalDependencies": { - "sharp": "^0.33.3" - }, "engines": { "node": ">=18.0.0" }, diff --git a/code/frameworks/experimental-nextjs-vite/src/export-mocks/cache/index.ts b/code/frameworks/experimental-nextjs-vite/src/export-mocks/cache/index.ts index 35b74b8cb02..d81ed0affc7 100644 --- a/code/frameworks/experimental-nextjs-vite/src/export-mocks/cache/index.ts +++ b/code/frameworks/experimental-nextjs-vite/src/export-mocks/cache/index.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { fn } from '@storybook/test'; +import { fn } from 'storybook/test'; // biome-ignore lint/suspicious/noExplicitAny: type Callback = (...args: any[]) => Promise; diff --git a/code/frameworks/experimental-nextjs-vite/src/export-mocks/headers/cookies.ts b/code/frameworks/experimental-nextjs-vite/src/export-mocks/headers/cookies.ts index b1eb6a692ef..4697a1afb97 100644 --- a/code/frameworks/experimental-nextjs-vite/src/export-mocks/headers/cookies.ts +++ b/code/frameworks/experimental-nextjs-vite/src/export-mocks/headers/cookies.ts @@ -1,13 +1,12 @@ // We need this import to be a singleton, and because it's used in multiple entrypoints // both in ESM and CJS, importing it via the package name instead of having a local import // is the only way to achieve it actually being a singleton -import { fn } from '@storybook/test'; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore we must ignore types here as during compilation they are not generated yet import { headers } from '@storybook/experimental-nextjs-vite/headers.mock'; import { RequestCookies } from 'next/dist/compiled/@edge-runtime/cookies'; +import { fn } from 'storybook/test'; class RequestCookiesMock extends RequestCookies { get = fn(super.get.bind(this)).mockName('next/headers::cookies().get'); diff --git a/code/frameworks/experimental-nextjs-vite/src/export-mocks/headers/headers.ts b/code/frameworks/experimental-nextjs-vite/src/export-mocks/headers/headers.ts index 1aceec57089..1d65c9285d9 100644 --- a/code/frameworks/experimental-nextjs-vite/src/export-mocks/headers/headers.ts +++ b/code/frameworks/experimental-nextjs-vite/src/export-mocks/headers/headers.ts @@ -1,6 +1,5 @@ -import { fn } from '@storybook/test'; - import { HeadersAdapter } from 'next/dist/server/web/spec-extension/adapters/headers'; +import { fn } from 'storybook/test'; class HeadersAdapterMock extends HeadersAdapter { constructor() { diff --git a/code/frameworks/experimental-nextjs-vite/src/export-mocks/headers/index.ts b/code/frameworks/experimental-nextjs-vite/src/export-mocks/headers/index.ts index 1c903963ba2..f1e27b49c64 100644 --- a/code/frameworks/experimental-nextjs-vite/src/export-mocks/headers/index.ts +++ b/code/frameworks/experimental-nextjs-vite/src/export-mocks/headers/index.ts @@ -1,7 +1,6 @@ -import { fn } from '@storybook/test'; - import { draftMode as originalDraftMode } from 'next/dist/server/request/draft-mode'; import * as headers from 'next/dist/server/request/headers'; +import { fn } from 'storybook/test'; // re-exports of the actual module export * from 'next/dist/server/request/headers'; diff --git a/code/frameworks/experimental-nextjs-vite/src/export-mocks/navigation/index.ts b/code/frameworks/experimental-nextjs-vite/src/export-mocks/navigation/index.ts index 8cec0b3266f..c2c63c3c78d 100644 --- a/code/frameworks/experimental-nextjs-vite/src/export-mocks/navigation/index.ts +++ b/code/frameworks/experimental-nextjs-vite/src/export-mocks/navigation/index.ts @@ -1,11 +1,10 @@ import { NextjsRouterMocksNotAvailable } from 'storybook/internal/preview-errors'; -import type { Mock } from '@storybook/test'; -import { fn } from '@storybook/test'; - import * as actual from 'next/dist/client/components/navigation'; import { getRedirectError } from 'next/dist/client/components/redirect'; import { RedirectStatusCode } from 'next/dist/client/components/redirect-status-code'; +import type { Mock } from 'storybook/test'; +import { fn } from 'storybook/test'; let navigationAPI: { push: Mock; diff --git a/code/frameworks/experimental-nextjs-vite/src/export-mocks/router/index.ts b/code/frameworks/experimental-nextjs-vite/src/export-mocks/router/index.ts index c6e93e804f0..26ee30342c7 100644 --- a/code/frameworks/experimental-nextjs-vite/src/export-mocks/router/index.ts +++ b/code/frameworks/experimental-nextjs-vite/src/export-mocks/router/index.ts @@ -1,10 +1,9 @@ import { NextjsRouterMocksNotAvailable } from 'storybook/internal/preview-errors'; -import type { Mock } from '@storybook/test'; -import { fn } from '@storybook/test'; - import singletonRouter, * as originalRouter from 'next/dist/client/router'; import type { NextRouter, SingletonRouter } from 'next/router'; +import type { Mock } from 'storybook/test'; +import { fn } from 'storybook/test'; const defaultRouterState = { route: '/', diff --git a/code/frameworks/experimental-nextjs-vite/src/index.ts b/code/frameworks/experimental-nextjs-vite/src/index.ts index a7ab6e7ede7..ed2829032a7 100644 --- a/code/frameworks/experimental-nextjs-vite/src/index.ts +++ b/code/frameworks/experimental-nextjs-vite/src/index.ts @@ -1,12 +1,17 @@ +import type { ProjectAnnotations } from 'storybook/internal/types'; + import type { ReactPreview } from '@storybook/react'; import { __definePreview } from '@storybook/react'; +import type { ReactRenderer } from '@storybook/react'; import type vitePluginStorybookNextJs from 'vite-plugin-storybook-nextjs'; import * as nextPreview from './preview'; -export * from './types'; +export * from '@storybook/react'; +// @ts-expect-error (double exports) export * from './portable-stories'; +export * from './types'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore @@ -17,7 +22,10 @@ declare module '@storybook/experimental-nextjs-vite/vite-plugin' { export function definePreview(preview: NextPreview['input']) { return __definePreview({ ...preview, - addons: [nextPreview, ...(preview.addons ?? [])], + addons: [ + nextPreview as unknown as ProjectAnnotations, + ...(preview.addons ?? []), + ], }) as NextPreview; } diff --git a/code/frameworks/experimental-nextjs-vite/src/preview.tsx b/code/frameworks/experimental-nextjs-vite/src/preview.tsx index 57804c4e13b..86d6629f385 100644 --- a/code/frameworks/experimental-nextjs-vite/src/preview.tsx +++ b/code/frameworks/experimental-nextjs-vite/src/preview.tsx @@ -1,4 +1,8 @@ -import type { Addon_DecoratorFunction, Addon_LoaderFunction } from 'storybook/internal/types'; +import type * as React from 'react'; + +import type { Addon_DecoratorFunction, LoaderFunction } from 'storybook/internal/types'; + +import type { ReactRenderer, StoryFn } from '@storybook/react'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore we must ignore types here as during compilation they are not generated yet @@ -50,21 +54,25 @@ globalThis.addEventListener('error', (ev: WindowEventMap['error']): void => { } }); -export const decorators: Addon_DecoratorFunction[] = [ - StyledJsxDecorator, - ImageDecorator, - RouterDecorator, - HeadManagerDecorator, +// Type assertion to handle the decorator type mismatch +const asDecorator = (decorator: (Story: React.FC, context?: any) => React.ReactNode) => + decorator as unknown as Addon_DecoratorFunction; + +export const decorators: Addon_DecoratorFunction[] = [ + asDecorator(StyledJsxDecorator), + asDecorator(ImageDecorator), + asDecorator(RouterDecorator), + asDecorator(HeadManagerDecorator), ]; -export const loaders: Addon_LoaderFunction = async ({ globals, parameters }) => { +export const loaders: LoaderFunction = async ({ globals, parameters }) => { const { router, appDirectory } = parameters.nextjs ?? {}; if (appDirectory) { createNavigation(router); } else { createRouter({ locale: globals.locale, - ...router, + ...(router as Record), }); } }; diff --git a/code/frameworks/experimental-nextjs-vite/template/cli/js/Button.stories.js b/code/frameworks/experimental-nextjs-vite/template/cli/js/Button.stories.js index 045d9c477ab..1b56021e71d 100644 --- a/code/frameworks/experimental-nextjs-vite/template/cli/js/Button.stories.js +++ b/code/frameworks/experimental-nextjs-vite/template/cli/js/Button.stories.js @@ -1,4 +1,4 @@ -import { fn } from '@storybook/test'; +import { fn } from 'storybook/test'; import { Button } from './Button'; diff --git a/code/frameworks/experimental-nextjs-vite/template/cli/js/Header.stories.js b/code/frameworks/experimental-nextjs-vite/template/cli/js/Header.stories.js index 699abab0794..9fe689e0ac8 100644 --- a/code/frameworks/experimental-nextjs-vite/template/cli/js/Header.stories.js +++ b/code/frameworks/experimental-nextjs-vite/template/cli/js/Header.stories.js @@ -1,4 +1,4 @@ -import { fn } from '@storybook/test'; +import { fn } from 'storybook/test'; import { Header } from './Header'; diff --git a/code/frameworks/experimental-nextjs-vite/template/cli/js/Page.stories.js b/code/frameworks/experimental-nextjs-vite/template/cli/js/Page.stories.js index 7b9906a7351..1ffea36cf37 100644 --- a/code/frameworks/experimental-nextjs-vite/template/cli/js/Page.stories.js +++ b/code/frameworks/experimental-nextjs-vite/template/cli/js/Page.stories.js @@ -1,4 +1,4 @@ -import { expect, userEvent, within } from '@storybook/test'; +import { expect, userEvent, within } from 'storybook/test'; import { Page } from './Page'; diff --git a/code/frameworks/experimental-nextjs-vite/template/cli/ts-4-9/Button.stories.ts b/code/frameworks/experimental-nextjs-vite/template/cli/ts-4-9/Button.stories.ts index 2a05e01b06f..6a6779580f9 100644 --- a/code/frameworks/experimental-nextjs-vite/template/cli/ts-4-9/Button.stories.ts +++ b/code/frameworks/experimental-nextjs-vite/template/cli/ts-4-9/Button.stories.ts @@ -1,5 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/experimental-nextjs-vite'; + +import { fn } from 'storybook/test'; import { Button } from './Button'; diff --git a/code/frameworks/experimental-nextjs-vite/template/cli/ts-4-9/Header.stories.ts b/code/frameworks/experimental-nextjs-vite/template/cli/ts-4-9/Header.stories.ts index 80c71d0f520..3e99df69003 100644 --- a/code/frameworks/experimental-nextjs-vite/template/cli/ts-4-9/Header.stories.ts +++ b/code/frameworks/experimental-nextjs-vite/template/cli/ts-4-9/Header.stories.ts @@ -1,5 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/experimental-nextjs-vite'; + +import { fn } from 'storybook/test'; import { Header } from './Header'; diff --git a/code/frameworks/experimental-nextjs-vite/template/cli/ts-4-9/Page.stories.ts b/code/frameworks/experimental-nextjs-vite/template/cli/ts-4-9/Page.stories.ts index 5d2c688a978..fcdcca74580 100644 --- a/code/frameworks/experimental-nextjs-vite/template/cli/ts-4-9/Page.stories.ts +++ b/code/frameworks/experimental-nextjs-vite/template/cli/ts-4-9/Page.stories.ts @@ -1,5 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, userEvent, within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/experimental-nextjs-vite'; + +import { expect, userEvent, within } from 'storybook/test'; import { Page } from './Page'; diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/DynamicImport.stories.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/DynamicImport.stories.tsx index f6b5e2c99f3..ecc6eddfbba 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/DynamicImport.stories.tsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/DynamicImport.stories.tsx @@ -1,6 +1,6 @@ import React, { Suspense } from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/experimental-nextjs-vite'; import dynamic from 'next/dynamic'; diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/Font.stories.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/Font.stories.tsx index 32db81dcb67..2287970d604 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/Font.stories.tsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/Font.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/experimental-nextjs-vite'; import Font from './Font'; diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/GetImageProps.stories.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/GetImageProps.stories.tsx index d4ad15ab240..f23e61872c4 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/GetImageProps.stories.tsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/GetImageProps.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/experimental-nextjs-vite'; import { type ImageProps, getImageProps } from 'next/image'; diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/Head.stories.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/Head.stories.tsx index 0d344078868..3ba0228887f 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/Head.stories.tsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/Head.stories.tsx @@ -1,10 +1,10 @@ import React from 'react'; -import type { Meta } from '@storybook/react'; -import type { StoryObj } from '@storybook/react'; -import { expect, waitFor } from '@storybook/test'; +import type { Meta } from '@storybook/experimental-nextjs-vite'; +import type { StoryObj } from '@storybook/experimental-nextjs-vite'; import Head from 'next/head'; +import { expect, waitFor } from 'storybook/test'; function Component() { return ( diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/Image.stories.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/Image.stories.tsx index d9efdacdae8..1c9e1235c14 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/Image.stories.tsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/Image.stories.tsx @@ -1,6 +1,6 @@ import React, { useRef, useState } from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/experimental-nextjs-vite'; import Image from 'next/image'; diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/ImageLegacy.stories.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/ImageLegacy.stories.tsx index 5e8852c2fb3..00752e97ced 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/ImageLegacy.stories.tsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/ImageLegacy.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/experimental-nextjs-vite'; import Image from 'next/legacy/image'; diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/Link.stories.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/Link.stories.tsx index d071539c57a..ae599692733 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/Link.stories.tsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/Link.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/experimental-nextjs-vite'; import Link from 'next/link'; diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/Navigation.stories.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/Navigation.stories.tsx index 4b9b49904de..92f07126ee0 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/Navigation.stories.tsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/Navigation.stories.tsx @@ -1,8 +1,6 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, userEvent, within } from '@storybook/test'; - +import type { Meta, StoryObj } from '@storybook/experimental-nextjs-vite'; import { getRouter } from '@storybook/experimental-nextjs-vite/navigation.mock'; import { @@ -13,6 +11,7 @@ import { useSelectedLayoutSegment, useSelectedLayoutSegments, } from 'next/navigation'; +import { expect, userEvent, within } from 'storybook/test'; function Component() { const router = useRouter(); diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/NextHeader.stories.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/NextHeader.stories.tsx index 1d31006f63e..d6b464df5c1 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/NextHeader.stories.tsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/NextHeader.stories.tsx @@ -1,9 +1,9 @@ -import type { Meta } from '@storybook/react'; -import type { StoryObj } from '@storybook/react'; -import { expect, userEvent, within } from '@storybook/test'; - +import type { Meta } from '@storybook/experimental-nextjs-vite'; +import type { StoryObj } from '@storybook/experimental-nextjs-vite'; import { cookies, headers } from '@storybook/experimental-nextjs-vite/headers.mock'; +import { expect, userEvent, within } from 'storybook/test'; + import NextHeader from './NextHeader'; export default { diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/RSC.stories.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/RSC.stories.tsx index 655a5f1a93e..1045bc8c604 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/RSC.stories.tsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/RSC.stories.tsx @@ -1,7 +1,7 @@ /* eslint-disable local-rules/no-uncategorized-errors */ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/experimental-nextjs-vite'; import { Nested, RSC } from './RSC'; diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/Redirect.stories.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/Redirect.stories.tsx index 47fd4c5228d..0bf00616405 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/Redirect.stories.tsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/Redirect.stories.tsx @@ -1,9 +1,9 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; -import { userEvent, within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/experimental-nextjs-vite'; import { redirect } from 'next/navigation'; +import { userEvent, within } from 'storybook/test'; let state = 'Bug! Not invalidated'; diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/Router.stories.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/Router.stories.tsx index 7b1d5b0ec0c..402c3c945de 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/Router.stories.tsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/Router.stories.tsx @@ -1,11 +1,10 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, userEvent, within } from '@storybook/test'; - +import type { Meta, StoryObj } from '@storybook/experimental-nextjs-vite'; import { getRouter } from '@storybook/experimental-nextjs-vite/router.mock'; import Router, { useRouter } from 'next/router'; +import { expect, userEvent, within } from 'storybook/test'; function Component() { const router = useRouter(); diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/ServerActions.stories.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/ServerActions.stories.tsx index 0844293c34f..c813aaa9f28 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/ServerActions.stories.tsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/ServerActions.stories.tsx @@ -1,12 +1,12 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, userEvent, waitFor, within } from '@storybook/test'; - +import type { Meta, StoryObj } from '@storybook/experimental-nextjs-vite'; import { revalidatePath } from '@storybook/experimental-nextjs-vite/cache.mock'; import { cookies } from '@storybook/experimental-nextjs-vite/headers.mock'; import { getRouter, redirect } from '@storybook/experimental-nextjs-vite/navigation.mock'; +import { expect, userEvent, waitFor, within } from 'storybook/test'; + import { accessRoute, login, logout } from './ServerActions'; function Component() { diff --git a/code/frameworks/experimental-nextjs-vite/template/stories/StyledJsx.stories.tsx b/code/frameworks/experimental-nextjs-vite/template/stories/StyledJsx.stories.tsx index 31adea42456..64c9f9b5b4f 100644 --- a/code/frameworks/experimental-nextjs-vite/template/stories/StyledJsx.stories.tsx +++ b/code/frameworks/experimental-nextjs-vite/template/stories/StyledJsx.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/experimental-nextjs-vite'; const Component = () => (
diff --git a/code/frameworks/html-vite/package.json b/code/frameworks/html-vite/package.json index e56e9ae88d0..36b44461387 100644 --- a/code/frameworks/html-vite/package.json +++ b/code/frameworks/html-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/html-vite", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for HTML and Vite: Develop HTML in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/html-vite/src/index.ts b/code/frameworks/html-vite/src/index.ts index fcb073fefcd..a5fd712c4ce 100644 --- a/code/frameworks/html-vite/src/index.ts +++ b/code/frameworks/html-vite/src/index.ts @@ -1 +1,2 @@ +export * from '@storybook/html'; export * from './types'; diff --git a/code/frameworks/html-webpack5/package.json b/code/frameworks/html-webpack5/package.json index 0bda6d6d553..65c856c27c1 100644 --- a/code/frameworks/html-webpack5/package.json +++ b/code/frameworks/html-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/html-webpack5", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for HTML: View HTML snippets in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/html-webpack5/src/index.ts b/code/frameworks/html-webpack5/src/index.ts index fcb073fefcd..a5fd712c4ce 100644 --- a/code/frameworks/html-webpack5/src/index.ts +++ b/code/frameworks/html-webpack5/src/index.ts @@ -1 +1,2 @@ +export * from '@storybook/html'; export * from './types'; diff --git a/code/frameworks/nextjs/package.json b/code/frameworks/nextjs/package.json index 1565a161415..0bc130dccd4 100644 --- a/code/frameworks/nextjs/package.json +++ b/code/frameworks/nextjs/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/nextjs", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for Next.js", "keywords": [ "storybook", @@ -156,12 +156,11 @@ "@storybook/builder-webpack5": "workspace:*", "@storybook/preset-react-webpack": "workspace:*", "@storybook/react": "workspace:*", - "@storybook/test": "workspace:*", "@types/semver": "^7.3.4", "babel-loader": "^9.1.3", "css-loader": "^6.7.3", "find-up": "^5.0.0", - "image-size": "^1.0.0", + "image-size": "^2.0.0", "loader-utils": "^3.2.1", "node-polyfill-webpack-plugin": "^2.0.1", "pnp-webpack-plugin": "^1.7.0", @@ -204,9 +203,6 @@ "optional": true } }, - "optionalDependencies": { - "sharp": "^0.33.3" - }, "engines": { "node": ">=18.0.0" }, diff --git a/code/frameworks/nextjs/src/export-mocks/cache/index.ts b/code/frameworks/nextjs/src/export-mocks/cache/index.ts index 0344304bc79..16ecd0b42e4 100644 --- a/code/frameworks/nextjs/src/export-mocks/cache/index.ts +++ b/code/frameworks/nextjs/src/export-mocks/cache/index.ts @@ -1,7 +1,6 @@ -import { fn } from '@storybook/test'; - import { unstable_cache } from 'next/dist/server/web/spec-extension/unstable-cache'; import { unstable_noStore } from 'next/dist/server/web/spec-extension/unstable-no-store'; +import { fn } from 'storybook/test'; // mock utilities/overrides (as of Next v14.2.0) const revalidatePath = fn().mockName('next/cache::revalidatePath'); diff --git a/code/frameworks/nextjs/src/export-mocks/headers/cookies.ts b/code/frameworks/nextjs/src/export-mocks/headers/cookies.ts index 02e335834b8..b8125b5fef1 100644 --- a/code/frameworks/nextjs/src/export-mocks/headers/cookies.ts +++ b/code/frameworks/nextjs/src/export-mocks/headers/cookies.ts @@ -4,9 +4,9 @@ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore we must ignore types here as during compilation they are not generated yet import { headers } from '@storybook/nextjs/headers.mock'; -import { fn } from '@storybook/test'; import { RequestCookies } from 'next/dist/compiled/@edge-runtime/cookies'; +import { fn } from 'storybook/test'; class RequestCookiesMock extends RequestCookies { get = fn(super.get.bind(this)).mockName('next/headers::cookies().get'); diff --git a/code/frameworks/nextjs/src/export-mocks/headers/headers.ts b/code/frameworks/nextjs/src/export-mocks/headers/headers.ts index 1aceec57089..1d65c9285d9 100644 --- a/code/frameworks/nextjs/src/export-mocks/headers/headers.ts +++ b/code/frameworks/nextjs/src/export-mocks/headers/headers.ts @@ -1,6 +1,5 @@ -import { fn } from '@storybook/test'; - import { HeadersAdapter } from 'next/dist/server/web/spec-extension/adapters/headers'; +import { fn } from 'storybook/test'; class HeadersAdapterMock extends HeadersAdapter { constructor() { diff --git a/code/frameworks/nextjs/src/export-mocks/headers/index.ts b/code/frameworks/nextjs/src/export-mocks/headers/index.ts index 1c903963ba2..f1e27b49c64 100644 --- a/code/frameworks/nextjs/src/export-mocks/headers/index.ts +++ b/code/frameworks/nextjs/src/export-mocks/headers/index.ts @@ -1,7 +1,6 @@ -import { fn } from '@storybook/test'; - import { draftMode as originalDraftMode } from 'next/dist/server/request/draft-mode'; import * as headers from 'next/dist/server/request/headers'; +import { fn } from 'storybook/test'; // re-exports of the actual module export * from 'next/dist/server/request/headers'; diff --git a/code/frameworks/nextjs/src/export-mocks/navigation/index.ts b/code/frameworks/nextjs/src/export-mocks/navigation/index.ts index 8cec0b3266f..c2c63c3c78d 100644 --- a/code/frameworks/nextjs/src/export-mocks/navigation/index.ts +++ b/code/frameworks/nextjs/src/export-mocks/navigation/index.ts @@ -1,11 +1,10 @@ import { NextjsRouterMocksNotAvailable } from 'storybook/internal/preview-errors'; -import type { Mock } from '@storybook/test'; -import { fn } from '@storybook/test'; - import * as actual from 'next/dist/client/components/navigation'; import { getRedirectError } from 'next/dist/client/components/redirect'; import { RedirectStatusCode } from 'next/dist/client/components/redirect-status-code'; +import type { Mock } from 'storybook/test'; +import { fn } from 'storybook/test'; let navigationAPI: { push: Mock; diff --git a/code/frameworks/nextjs/src/export-mocks/router/index.ts b/code/frameworks/nextjs/src/export-mocks/router/index.ts index c6e93e804f0..26ee30342c7 100644 --- a/code/frameworks/nextjs/src/export-mocks/router/index.ts +++ b/code/frameworks/nextjs/src/export-mocks/router/index.ts @@ -1,10 +1,9 @@ import { NextjsRouterMocksNotAvailable } from 'storybook/internal/preview-errors'; -import type { Mock } from '@storybook/test'; -import { fn } from '@storybook/test'; - import singletonRouter, * as originalRouter from 'next/dist/client/router'; import type { NextRouter, SingletonRouter } from 'next/router'; +import type { Mock } from 'storybook/test'; +import { fn } from 'storybook/test'; const defaultRouterState = { route: '/', diff --git a/code/frameworks/nextjs/src/index.ts b/code/frameworks/nextjs/src/index.ts index 92aebbe57d3..f91791742e5 100644 --- a/code/frameworks/nextjs/src/index.ts +++ b/code/frameworks/nextjs/src/index.ts @@ -3,7 +3,9 @@ import { __definePreview } from '@storybook/react'; import * as nextPreview from './preview'; +export * from '@storybook/react'; export * from './types'; +// @ts-expect-error (double exports) export * from './portable-stories'; export function definePreview(preview: NextPreview['input']) { diff --git a/code/frameworks/nextjs/src/next-image-loader-stub.ts b/code/frameworks/nextjs/src/next-image-loader-stub.ts index e85414c85d1..a562c276473 100644 --- a/code/frameworks/nextjs/src/next-image-loader-stub.ts +++ b/code/frameworks/nextjs/src/next-image-loader-stub.ts @@ -1,8 +1,4 @@ -import { cpus } from 'node:os'; - -import { NextJsSharpError } from 'storybook/internal/preview-errors'; - -import imageSizeOf from 'image-size'; +import { imageSize } from 'image-size'; import { interpolateName } from 'loader-utils'; import type { NextConfig } from 'next'; import type { RawLoaderDefinition } from 'webpack'; @@ -12,21 +8,6 @@ interface LoaderOptions { nextConfig: NextConfig; } -let sharp: typeof import('sharp') | undefined; - -try { - sharp = require('sharp'); - if (sharp && sharp.concurrency() > 1) { - // Reducing concurrency reduces the memory usage too. - const divisor = process.env.NODE_ENV === 'development' ? 4 : 2; - sharp.concurrency(Math.floor(Math.max(cpus().length / divisor, 1))); - } -} catch (e) { - console.warn( - 'You have to install sharp in order to use image optimization features in Next.js. AVIF support is also disabled.' - ); -} - const nextImageLoaderStub: RawLoaderDefinition = async function NextImageLoader( content ) { @@ -36,7 +17,6 @@ const nextImageLoaderStub: RawLoaderDefinition = async function N content, }; const outputPath = interpolateName(this, filename.replace('[ext]', '.[ext]'), opts); - const extension = interpolateName(this, '[ext]', opts); this.emitFile(outputPath, content); @@ -44,23 +24,7 @@ const nextImageLoaderStub: RawLoaderDefinition = async function N return `const src = '${outputPath}'; export default src;`; } - let width; - let height; - - if (extension === 'avif') { - if (sharp) { - const transformer = sharp(content); - const result = await transformer.metadata(); - width = result.width; - height = result.height; - } else { - throw new NextJsSharpError(); - } - } else { - const result = imageSizeOf(this.resourcePath); - width = result.width; - height = result.height; - } + const { width, height } = imageSize(content as Uint8Array); return `export default ${JSON.stringify({ src: outputPath, diff --git a/code/frameworks/nextjs/template/cli/js/Button.stories.js b/code/frameworks/nextjs/template/cli/js/Button.stories.js index 045d9c477ab..1b56021e71d 100644 --- a/code/frameworks/nextjs/template/cli/js/Button.stories.js +++ b/code/frameworks/nextjs/template/cli/js/Button.stories.js @@ -1,4 +1,4 @@ -import { fn } from '@storybook/test'; +import { fn } from 'storybook/test'; import { Button } from './Button'; diff --git a/code/frameworks/nextjs/template/cli/js/Header.stories.js b/code/frameworks/nextjs/template/cli/js/Header.stories.js index 699abab0794..9fe689e0ac8 100644 --- a/code/frameworks/nextjs/template/cli/js/Header.stories.js +++ b/code/frameworks/nextjs/template/cli/js/Header.stories.js @@ -1,4 +1,4 @@ -import { fn } from '@storybook/test'; +import { fn } from 'storybook/test'; import { Header } from './Header'; diff --git a/code/frameworks/nextjs/template/cli/js/Page.stories.js b/code/frameworks/nextjs/template/cli/js/Page.stories.js index 7b9906a7351..1ffea36cf37 100644 --- a/code/frameworks/nextjs/template/cli/js/Page.stories.js +++ b/code/frameworks/nextjs/template/cli/js/Page.stories.js @@ -1,4 +1,4 @@ -import { expect, userEvent, within } from '@storybook/test'; +import { expect, userEvent, within } from 'storybook/test'; import { Page } from './Page'; diff --git a/code/frameworks/nextjs/template/cli/ts-4-9/Button.stories.ts b/code/frameworks/nextjs/template/cli/ts-4-9/Button.stories.ts index 2a05e01b06f..747e7c8b3e6 100644 --- a/code/frameworks/nextjs/template/cli/ts-4-9/Button.stories.ts +++ b/code/frameworks/nextjs/template/cli/ts-4-9/Button.stories.ts @@ -1,5 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/nextjs'; + +import { fn } from 'storybook/test'; import { Button } from './Button'; diff --git a/code/frameworks/nextjs/template/cli/ts-4-9/Header.stories.ts b/code/frameworks/nextjs/template/cli/ts-4-9/Header.stories.ts index 80c71d0f520..56ed5e07cfd 100644 --- a/code/frameworks/nextjs/template/cli/ts-4-9/Header.stories.ts +++ b/code/frameworks/nextjs/template/cli/ts-4-9/Header.stories.ts @@ -1,5 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/nextjs'; + +import { fn } from 'storybook/test'; import { Header } from './Header'; diff --git a/code/frameworks/nextjs/template/cli/ts-4-9/Page.stories.ts b/code/frameworks/nextjs/template/cli/ts-4-9/Page.stories.ts index 5d2c688a978..97f11551f56 100644 --- a/code/frameworks/nextjs/template/cli/ts-4-9/Page.stories.ts +++ b/code/frameworks/nextjs/template/cli/ts-4-9/Page.stories.ts @@ -1,5 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, userEvent, within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/nextjs'; + +import { expect, userEvent, within } from 'storybook/test'; import { Page } from './Page'; diff --git a/code/frameworks/nextjs/template/stories/DynamicImport.stories.tsx b/code/frameworks/nextjs/template/stories/DynamicImport.stories.tsx index b71430f7254..b33f6bb449f 100644 --- a/code/frameworks/nextjs/template/stories/DynamicImport.stories.tsx +++ b/code/frameworks/nextjs/template/stories/DynamicImport.stories.tsx @@ -1,6 +1,6 @@ import React, { Suspense } from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/nextjs'; import dynamic from 'next/dynamic'; diff --git a/code/frameworks/nextjs/template/stories/Font.stories.tsx b/code/frameworks/nextjs/template/stories/Font.stories.tsx index 0e078409da0..c7b5eb69220 100644 --- a/code/frameworks/nextjs/template/stories/Font.stories.tsx +++ b/code/frameworks/nextjs/template/stories/Font.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/nextjs'; import Font from './Font'; diff --git a/code/frameworks/nextjs/template/stories/Head.stories.tsx b/code/frameworks/nextjs/template/stories/Head.stories.tsx index 540d0e04dc3..f5f9d4629bf 100644 --- a/code/frameworks/nextjs/template/stories/Head.stories.tsx +++ b/code/frameworks/nextjs/template/stories/Head.stories.tsx @@ -1,9 +1,9 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, waitFor } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/nextjs'; import Head from 'next/head'; +import { expect, waitFor } from 'storybook/test'; function Component() { return ( diff --git a/code/frameworks/nextjs/template/stories/Image.stories.tsx b/code/frameworks/nextjs/template/stories/Image.stories.tsx index ebceacaf130..61676d6896f 100644 --- a/code/frameworks/nextjs/template/stories/Image.stories.tsx +++ b/code/frameworks/nextjs/template/stories/Image.stories.tsx @@ -1,6 +1,6 @@ import React, { useState } from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/nextjs'; import Image from 'next/image'; diff --git a/code/frameworks/nextjs/template/stories/ImageLegacy.stories.tsx b/code/frameworks/nextjs/template/stories/ImageLegacy.stories.tsx index 954bc36a260..bea2df97b72 100644 --- a/code/frameworks/nextjs/template/stories/ImageLegacy.stories.tsx +++ b/code/frameworks/nextjs/template/stories/ImageLegacy.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/nextjs'; import Image from 'next/legacy/image'; diff --git a/code/frameworks/nextjs/template/stories/Link.stories.tsx b/code/frameworks/nextjs/template/stories/Link.stories.tsx index d071539c57a..f9e1fd044f8 100644 --- a/code/frameworks/nextjs/template/stories/Link.stories.tsx +++ b/code/frameworks/nextjs/template/stories/Link.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/nextjs'; import Link from 'next/link'; diff --git a/code/frameworks/nextjs/template/stories/Navigation.stories.tsx b/code/frameworks/nextjs/template/stories/Navigation.stories.tsx index 5c4872d1ac3..e0dfa4e0579 100644 --- a/code/frameworks/nextjs/template/stories/Navigation.stories.tsx +++ b/code/frameworks/nextjs/template/stories/Navigation.stories.tsx @@ -1,8 +1,7 @@ import React from 'react'; +import type { Meta, StoryObj } from '@storybook/nextjs'; import { getRouter } from '@storybook/nextjs/navigation.mock'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, userEvent, within } from '@storybook/test'; import { useParams, @@ -12,6 +11,7 @@ import { useSelectedLayoutSegment, useSelectedLayoutSegments, } from 'next/navigation'; +import { expect, userEvent, within } from 'storybook/test'; function Component() { const router = useRouter(); diff --git a/code/frameworks/nextjs/template/stories/RSC.stories.tsx b/code/frameworks/nextjs/template/stories/RSC.stories.tsx index 655a5f1a93e..f8ba1dc120a 100644 --- a/code/frameworks/nextjs/template/stories/RSC.stories.tsx +++ b/code/frameworks/nextjs/template/stories/RSC.stories.tsx @@ -1,7 +1,7 @@ /* eslint-disable local-rules/no-uncategorized-errors */ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/nextjs'; import { Nested, RSC } from './RSC'; diff --git a/code/frameworks/nextjs/template/stories/Router.stories.tsx b/code/frameworks/nextjs/template/stories/Router.stories.tsx index d6586364fd0..3ad0d29dd89 100644 --- a/code/frameworks/nextjs/template/stories/Router.stories.tsx +++ b/code/frameworks/nextjs/template/stories/Router.stories.tsx @@ -1,10 +1,10 @@ import React from 'react'; +import type { Meta, StoryObj } from '@storybook/nextjs'; import { getRouter } from '@storybook/nextjs/router.mock'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, userEvent, within } from '@storybook/test'; import Router, { useRouter } from 'next/router'; +import { expect, userEvent, within } from 'storybook/test'; function Component() { const router = useRouter(); diff --git a/code/frameworks/nextjs/template/stories/StyledJsx.stories.tsx b/code/frameworks/nextjs/template/stories/StyledJsx.stories.tsx index 31adea42456..a213c13928d 100644 --- a/code/frameworks/nextjs/template/stories/StyledJsx.stories.tsx +++ b/code/frameworks/nextjs/template/stories/StyledJsx.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/nextjs'; const Component = () => (
diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-ts/GetImageProps.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-default-ts/GetImageProps.stories.tsx index aefc27f54cf..abd21cab707 100644 --- a/code/frameworks/nextjs/template/stories_nextjs-default-ts/GetImageProps.stories.tsx +++ b/code/frameworks/nextjs/template/stories_nextjs-default-ts/GetImageProps.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/nextjs'; import { getImageProps } from 'next/image'; diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-ts/NextHeader.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-default-ts/NextHeader.stories.tsx index f5e83ef867f..5478d835d89 100644 --- a/code/frameworks/nextjs/template/stories_nextjs-default-ts/NextHeader.stories.tsx +++ b/code/frameworks/nextjs/template/stories_nextjs-default-ts/NextHeader.stories.tsx @@ -1,6 +1,7 @@ +import type { Meta, StoryObj } from '@storybook/nextjs'; import { cookies, headers } from '@storybook/nextjs/headers.mock'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, userEvent, within } from '@storybook/test'; + +import { expect, userEvent, within } from 'storybook/test'; import NextHeader from './NextHeader'; diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-ts/Redirect.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-default-ts/Redirect.stories.tsx index 3c5980b7975..6cf56ede2f1 100644 --- a/code/frameworks/nextjs/template/stories_nextjs-default-ts/Redirect.stories.tsx +++ b/code/frameworks/nextjs/template/stories_nextjs-default-ts/Redirect.stories.tsx @@ -1,9 +1,9 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; -import { userEvent, within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/nextjs'; import { redirect } from 'next/navigation'; +import { userEvent, within } from 'storybook/test'; let state = 'Bug! Not invalidated'; diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-ts/ServerActions.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-default-ts/ServerActions.stories.tsx index f1a9ad762ee..4da326d7d98 100644 --- a/code/frameworks/nextjs/template/stories_nextjs-default-ts/ServerActions.stories.tsx +++ b/code/frameworks/nextjs/template/stories_nextjs-default-ts/ServerActions.stories.tsx @@ -1,10 +1,11 @@ import React from 'react'; +import type { Meta, StoryObj } from '@storybook/nextjs'; import { revalidatePath } from '@storybook/nextjs/cache.mock'; import { cookies } from '@storybook/nextjs/headers.mock'; import { getRouter, redirect } from '@storybook/nextjs/navigation.mock'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, userEvent, waitFor, within } from '@storybook/test'; + +import { expect, userEvent, waitFor, within } from 'storybook/test'; import { accessRoute, login, logout } from './server-actions'; diff --git a/code/frameworks/nextjs/template/stories_nextjs-prerelease/GetImageProps.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-prerelease/GetImageProps.stories.tsx index aefc27f54cf..abd21cab707 100644 --- a/code/frameworks/nextjs/template/stories_nextjs-prerelease/GetImageProps.stories.tsx +++ b/code/frameworks/nextjs/template/stories_nextjs-prerelease/GetImageProps.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/nextjs'; import { getImageProps } from 'next/image'; diff --git a/code/frameworks/nextjs/template/stories_nextjs-prerelease/NextHeader.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-prerelease/NextHeader.stories.tsx index f5e83ef867f..5478d835d89 100644 --- a/code/frameworks/nextjs/template/stories_nextjs-prerelease/NextHeader.stories.tsx +++ b/code/frameworks/nextjs/template/stories_nextjs-prerelease/NextHeader.stories.tsx @@ -1,6 +1,7 @@ +import type { Meta, StoryObj } from '@storybook/nextjs'; import { cookies, headers } from '@storybook/nextjs/headers.mock'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, userEvent, within } from '@storybook/test'; + +import { expect, userEvent, within } from 'storybook/test'; import NextHeader from './NextHeader'; diff --git a/code/frameworks/nextjs/template/stories_nextjs-prerelease/Redirect.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-prerelease/Redirect.stories.tsx index 3c5980b7975..6cf56ede2f1 100644 --- a/code/frameworks/nextjs/template/stories_nextjs-prerelease/Redirect.stories.tsx +++ b/code/frameworks/nextjs/template/stories_nextjs-prerelease/Redirect.stories.tsx @@ -1,9 +1,9 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; -import { userEvent, within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/nextjs'; import { redirect } from 'next/navigation'; +import { userEvent, within } from 'storybook/test'; let state = 'Bug! Not invalidated'; diff --git a/code/frameworks/nextjs/template/stories_nextjs-prerelease/ServerActions.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-prerelease/ServerActions.stories.tsx index f1a9ad762ee..4da326d7d98 100644 --- a/code/frameworks/nextjs/template/stories_nextjs-prerelease/ServerActions.stories.tsx +++ b/code/frameworks/nextjs/template/stories_nextjs-prerelease/ServerActions.stories.tsx @@ -1,10 +1,11 @@ import React from 'react'; +import type { Meta, StoryObj } from '@storybook/nextjs'; import { revalidatePath } from '@storybook/nextjs/cache.mock'; import { cookies } from '@storybook/nextjs/headers.mock'; import { getRouter, redirect } from '@storybook/nextjs/navigation.mock'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, userEvent, waitFor, within } from '@storybook/test'; + +import { expect, userEvent, waitFor, within } from 'storybook/test'; import { accessRoute, login, logout } from './server-actions'; diff --git a/code/frameworks/preact-vite/package.json b/code/frameworks/preact-vite/package.json index 93571b87a80..2253f224daf 100644 --- a/code/frameworks/preact-vite/package.json +++ b/code/frameworks/preact-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact-vite", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for Preact and Vite: Develop Preact components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/preact-vite/src/index.ts b/code/frameworks/preact-vite/src/index.ts index fcb073fefcd..6a07f64e683 100644 --- a/code/frameworks/preact-vite/src/index.ts +++ b/code/frameworks/preact-vite/src/index.ts @@ -1 +1,2 @@ +export * from '@storybook/preact'; export * from './types'; diff --git a/code/frameworks/preact-webpack5/package.json b/code/frameworks/preact-webpack5/package.json index 90269b7e4dd..77e02cd99ba 100644 --- a/code/frameworks/preact-webpack5/package.json +++ b/code/frameworks/preact-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact-webpack5", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for Preact: Develop Preact Component in isolation.", "keywords": [ "storybook" diff --git a/code/frameworks/preact-webpack5/src/index.ts b/code/frameworks/preact-webpack5/src/index.ts index fcb073fefcd..6a07f64e683 100644 --- a/code/frameworks/preact-webpack5/src/index.ts +++ b/code/frameworks/preact-webpack5/src/index.ts @@ -1 +1,2 @@ +export * from '@storybook/preact'; export * from './types'; diff --git a/code/frameworks/react-native-web-vite/package.json b/code/frameworks/react-native-web-vite/package.json index 56818e7da76..95b1794c2b5 100644 --- a/code/frameworks/react-native-web-vite/package.json +++ b/code/frameworks/react-native-web-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-native-web-vite", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Develop react-native components an isolated web environment with hot reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/react-native-web-vite/src/index.ts b/code/frameworks/react-native-web-vite/src/index.ts index baac63e5f10..274fe088be3 100644 --- a/code/frameworks/react-native-web-vite/src/index.ts +++ b/code/frameworks/react-native-web-vite/src/index.ts @@ -1,3 +1,4 @@ export type { FrameworkOptions, StorybookConfig } from './types'; export { __definePreview as definePreview } from '@storybook/react'; +export * from '@storybook/react'; diff --git a/code/frameworks/react-native-web-vite/template/cli/js/Button.stories.jsx b/code/frameworks/react-native-web-vite/template/cli/js/Button.stories.jsx index b7136fd8ae6..3ea891e65ce 100644 --- a/code/frameworks/react-native-web-vite/template/cli/js/Button.stories.jsx +++ b/code/frameworks/react-native-web-vite/template/cli/js/Button.stories.jsx @@ -1,6 +1,5 @@ -import { fn } from '@storybook/test'; - import { View } from 'react-native'; +import { fn } from 'storybook/test'; import { Button } from './Button'; diff --git a/code/frameworks/react-native-web-vite/template/cli/js/Page.stories.jsx b/code/frameworks/react-native-web-vite/template/cli/js/Page.stories.jsx index 249647fce86..bbf8729b8a3 100644 --- a/code/frameworks/react-native-web-vite/template/cli/js/Page.stories.jsx +++ b/code/frameworks/react-native-web-vite/template/cli/js/Page.stories.jsx @@ -1,4 +1,4 @@ -import { expect, userEvent, within } from '@storybook/test'; +import { expect, userEvent, within } from 'storybook/test'; import { Page } from './Page'; diff --git a/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Button.stories.tsx b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Button.stories.tsx index 8e655fbfe26..3d532efa99b 100644 --- a/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Button.stories.tsx +++ b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Button.stories.tsx @@ -1,7 +1,7 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-native-web-vite'; import { View } from 'react-native'; +import { fn } from 'storybook/test'; import { Button } from './Button'; diff --git a/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Header.stories.tsx b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Header.stories.tsx index 029f040b039..b5a633e2e98 100644 --- a/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Header.stories.tsx +++ b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Header.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-native-web-vite'; import { Header } from './Header'; diff --git a/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Page.stories.tsx b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Page.stories.tsx index 5a5db7ff268..bb9b828da45 100644 --- a/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Page.stories.tsx +++ b/code/frameworks/react-native-web-vite/template/cli/ts-4-9/Page.stories.tsx @@ -1,5 +1,6 @@ -import type { Meta } from '@storybook/react'; -import { expect, userEvent, within } from '@storybook/test'; +import type { Meta } from '@storybook/react-native-web-vite'; + +import { expect, userEvent, within } from 'storybook/test'; import { Page } from './Page'; diff --git a/code/frameworks/react-vite/package.json b/code/frameworks/react-vite/package.json index 8dbd936945d..0bb64b76ba1 100644 --- a/code/frameworks/react-vite/package.json +++ b/code/frameworks/react-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-vite", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for React and Vite: Develop React components in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -56,6 +56,7 @@ }, "files": [ "dist/**/*", + "template/**/*", "README.md", "*.js", "*.d.ts", @@ -82,17 +83,11 @@ "vite": "^4.0.0" }, "peerDependencies": { - "@storybook/test": "workspace:*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "storybook": "workspace:^", "vite": "^4.0.0 || ^5.0.0 || ^6.0.0" }, - "peerDependenciesMeta": { - "@storybook/test": { - "optional": true - } - }, "engines": { "node": ">=18.0.0" }, diff --git a/code/frameworks/react-vite/src/index.ts b/code/frameworks/react-vite/src/index.ts index f71bd648bf9..cb9de933e71 100644 --- a/code/frameworks/react-vite/src/index.ts +++ b/code/frameworks/react-vite/src/index.ts @@ -1,3 +1,4 @@ +export * from '@storybook/react'; export { __definePreview as definePreview } from '@storybook/react'; export * from './types'; diff --git a/code/frameworks/react-vite/template/cli/.eslintrc.json b/code/frameworks/react-vite/template/cli/.eslintrc.json new file mode 100644 index 00000000000..40ece4a0aa1 --- /dev/null +++ b/code/frameworks/react-vite/template/cli/.eslintrc.json @@ -0,0 +1,5 @@ +{ + "rules": { + "import/extensions": "off" + } +} diff --git a/code/frameworks/react-vite/template/cli/js/Button.jsx b/code/frameworks/react-vite/template/cli/js/Button.jsx new file mode 100644 index 00000000000..dabe38e0e82 --- /dev/null +++ b/code/frameworks/react-vite/template/cli/js/Button.jsx @@ -0,0 +1,39 @@ +import React from 'react'; + +import PropTypes from 'prop-types'; + +import './button.css'; + +/** Primary UI component for user interaction */ +export const Button = ({ + primary = false, + backgroundColor = null, + size = 'medium', + label, + ...props +}) => { + const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary'; + return ( + + ); +}; + +Button.propTypes = { + /** Is this the principal call to action on the page? */ + primary: PropTypes.bool, + /** What background color to use */ + backgroundColor: PropTypes.string, + /** How large should the button be? */ + size: PropTypes.oneOf(['small', 'medium', 'large']), + /** Button contents */ + label: PropTypes.string.isRequired, + /** Optional click handler */ + onClick: PropTypes.func, +}; diff --git a/code/frameworks/react-vite/template/cli/js/Button.stories.js b/code/frameworks/react-vite/template/cli/js/Button.stories.js new file mode 100644 index 00000000000..1b56021e71d --- /dev/null +++ b/code/frameworks/react-vite/template/cli/js/Button.stories.js @@ -0,0 +1,49 @@ +import { fn } from 'storybook/test'; + +import { Button } from './Button'; + +// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export +export default { + title: 'Example/Button', + component: Button, + parameters: { + // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout + layout: 'centered', + }, + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], + // More on argTypes: https://storybook.js.org/docs/api/argtypes + argTypes: { + backgroundColor: { control: 'color' }, + }, + // Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args + args: { onClick: fn() }, +}; + +// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args +export const Primary = { + args: { + primary: true, + label: 'Button', + }, +}; + +export const Secondary = { + args: { + label: 'Button', + }, +}; + +export const Large = { + args: { + size: 'large', + label: 'Button', + }, +}; + +export const Small = { + args: { + size: 'small', + label: 'Button', + }, +}; diff --git a/code/frameworks/react-vite/template/cli/js/Header.jsx b/code/frameworks/react-vite/template/cli/js/Header.jsx new file mode 100644 index 00000000000..94a691e1dd7 --- /dev/null +++ b/code/frameworks/react-vite/template/cli/js/Header.jsx @@ -0,0 +1,56 @@ +import React from 'react'; + +import PropTypes from 'prop-types'; + +import { Button } from './Button'; +import './header.css'; + +export const Header = ({ user = null, onLogin, onLogout, onCreateAccount }) => ( +
+
+
+ + + + + + + +

Acme

+
+
+ {user ? ( + <> + + Welcome, {user.name}! + +
+
+
+); + +Header.propTypes = { + user: PropTypes.shape({ + name: PropTypes.string.isRequired, + }), + onLogin: PropTypes.func.isRequired, + onLogout: PropTypes.func.isRequired, + onCreateAccount: PropTypes.func.isRequired, +}; diff --git a/code/frameworks/react-vite/template/cli/js/Header.stories.js b/code/frameworks/react-vite/template/cli/js/Header.stories.js new file mode 100644 index 00000000000..6d88e100749 --- /dev/null +++ b/code/frameworks/react-vite/template/cli/js/Header.stories.js @@ -0,0 +1,29 @@ +import { fn } from 'storybook/test'; + +import { Header } from './Header'; + +export default { + title: 'Example/Header', + component: Header, + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + layout: 'fullscreen', + }, + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), + }, +}; + +export const LoggedIn = { + args: { + user: { + name: 'Jane Doe', + }, + }, +}; + +export const LoggedOut = {}; diff --git a/code/frameworks/react-vite/template/cli/js/Page.jsx b/code/frameworks/react-vite/template/cli/js/Page.jsx new file mode 100644 index 00000000000..c421401138e --- /dev/null +++ b/code/frameworks/react-vite/template/cli/js/Page.jsx @@ -0,0 +1,69 @@ +import React from 'react'; + +import { Header } from './Header'; +import './page.css'; + +export const Page = () => { + const [user, setUser] = React.useState(); + + return ( +
+
setUser({ name: 'Jane Doe' })} + onLogout={() => setUser(undefined)} + onCreateAccount={() => setUser({ name: 'Jane Doe' })} + /> + +
+

Pages in Storybook

+

+ We recommend building UIs with a{' '} + + component-driven + {' '} + process starting with atomic components and ending with pages. +

+

+ Render pages with mock data. This makes it easy to build and review page states without + needing to navigate to them in your app. Here are some handy patterns for managing page + data in Storybook: +

+
    +
  • + Use a higher-level connected component. Storybook helps you compose such data from the + "args" of child component stories +
  • +
  • + Assemble data in the page component from your services. You can mock these services out + using Storybook. +
  • +
+

+ Get a guided tutorial on component-driven development at{' '} + + Storybook tutorials + + . Read more in the{' '} + + docs + + . +

+
+ Tip Adjust the width of the canvas with the{' '} + + + + + + Viewports addon in the toolbar +
+
+
+ ); +}; diff --git a/code/frameworks/react-vite/template/cli/js/Page.stories.js b/code/frameworks/react-vite/template/cli/js/Page.stories.js new file mode 100644 index 00000000000..7b9906a7351 --- /dev/null +++ b/code/frameworks/react-vite/template/cli/js/Page.stories.js @@ -0,0 +1,28 @@ +import { expect, userEvent, within } from '@storybook/test'; + +import { Page } from './Page'; + +export default { + title: 'Example/Page', + component: Page, + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + layout: 'fullscreen', + }, +}; + +export const LoggedOut = {}; + +// More on component testing: https://storybook.js.org/docs/writing-tests/component-testing +export const LoggedIn = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const loginButton = canvas.getByRole('button', { name: /Log in/i }); + await expect(loginButton).toBeInTheDocument(); + await userEvent.click(loginButton); + await expect(loginButton).not.toBeInTheDocument(); + + const logoutButton = canvas.getByRole('button', { name: /Log out/i }); + await expect(logoutButton).toBeInTheDocument(); + }, +}; diff --git a/code/frameworks/react-vite/template/cli/ts-4-9/Button.stories.ts b/code/frameworks/react-vite/template/cli/ts-4-9/Button.stories.ts new file mode 100644 index 00000000000..0c3151f3089 --- /dev/null +++ b/code/frameworks/react-vite/template/cli/ts-4-9/Button.stories.ts @@ -0,0 +1,54 @@ +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { fn } from 'storybook/test'; + +import { Button } from './Button'; + +// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export +const meta = { + title: 'Example/Button', + component: Button, + parameters: { + // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout + layout: 'centered', + }, + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], + // More on argTypes: https://storybook.js.org/docs/api/argtypes + argTypes: { + backgroundColor: { control: 'color' }, + }, + // Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args + args: { onClick: fn() }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args +export const Primary: Story = { + args: { + primary: true, + label: 'Button', + }, +}; + +export const Secondary: Story = { + args: { + label: 'Button', + }, +}; + +export const Large: Story = { + args: { + size: 'large', + label: 'Button', + }, +}; + +export const Small: Story = { + args: { + size: 'small', + label: 'Button', + }, +}; diff --git a/code/frameworks/react-vite/template/cli/ts-4-9/Button.tsx b/code/frameworks/react-vite/template/cli/ts-4-9/Button.tsx new file mode 100644 index 00000000000..f35dafdcb42 --- /dev/null +++ b/code/frameworks/react-vite/template/cli/ts-4-9/Button.tsx @@ -0,0 +1,37 @@ +import React from 'react'; + +import './button.css'; + +export interface ButtonProps { + /** Is this the principal call to action on the page? */ + primary?: boolean; + /** What background color to use */ + backgroundColor?: string; + /** How large should the button be? */ + size?: 'small' | 'medium' | 'large'; + /** Button contents */ + label: string; + /** Optional click handler */ + onClick?: () => void; +} + +/** Primary UI component for user interaction */ +export const Button = ({ + primary = false, + size = 'medium', + backgroundColor, + label, + ...props +}: ButtonProps) => { + const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary'; + return ( + + ); +}; diff --git a/code/frameworks/react-vite/template/cli/ts-4-9/Header.stories.ts b/code/frameworks/react-vite/template/cli/ts-4-9/Header.stories.ts new file mode 100644 index 00000000000..36a3b8f9f2b --- /dev/null +++ b/code/frameworks/react-vite/template/cli/ts-4-9/Header.stories.ts @@ -0,0 +1,34 @@ +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { fn } from 'storybook/test'; + +import { Header } from './Header'; + +const meta = { + title: 'Example/Header', + component: Header, + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + layout: 'fullscreen', + }, + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const LoggedIn: Story = { + args: { + user: { + name: 'Jane Doe', + }, + }, +}; + +export const LoggedOut: Story = {}; diff --git a/code/frameworks/react-vite/template/cli/ts-4-9/Header.tsx b/code/frameworks/react-vite/template/cli/ts-4-9/Header.tsx new file mode 100644 index 00000000000..1bf981a4251 --- /dev/null +++ b/code/frameworks/react-vite/template/cli/ts-4-9/Header.tsx @@ -0,0 +1,56 @@ +import React from 'react'; + +import { Button } from './Button'; +import './header.css'; + +type User = { + name: string; +}; + +export interface HeaderProps { + user?: User; + onLogin?: () => void; + onLogout?: () => void; + onCreateAccount?: () => void; +} + +export const Header = ({ user, onLogin, onLogout, onCreateAccount }: HeaderProps) => ( +
+
+
+ + + + + + + +

Acme

+
+
+ {user ? ( + <> + + Welcome, {user.name}! + +
+
+
+); diff --git a/code/frameworks/react-vite/template/cli/ts-4-9/Page.stories.ts b/code/frameworks/react-vite/template/cli/ts-4-9/Page.stories.ts new file mode 100644 index 00000000000..9ca0d882bce --- /dev/null +++ b/code/frameworks/react-vite/template/cli/ts-4-9/Page.stories.ts @@ -0,0 +1,33 @@ +import { expect, userEvent, within } from '@storybook/test'; + +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { Page } from './Page'; + +const meta = { + title: 'Example/Page', + component: Page, + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + layout: 'fullscreen', + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const LoggedOut: Story = {}; + +// More on component testing: https://storybook.js.org/docs/writing-tests/component-testing +export const LoggedIn: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const loginButton = canvas.getByRole('button', { name: /Log in/i }); + await expect(loginButton).toBeInTheDocument(); + await userEvent.click(loginButton); + await expect(loginButton).not.toBeInTheDocument(); + + const logoutButton = canvas.getByRole('button', { name: /Log out/i }); + await expect(logoutButton).toBeInTheDocument(); + }, +}; diff --git a/code/frameworks/react-vite/template/cli/ts-4-9/Page.tsx b/code/frameworks/react-vite/template/cli/ts-4-9/Page.tsx new file mode 100644 index 00000000000..e1174830139 --- /dev/null +++ b/code/frameworks/react-vite/template/cli/ts-4-9/Page.tsx @@ -0,0 +1,73 @@ +import React from 'react'; + +import { Header } from './Header'; +import './page.css'; + +type User = { + name: string; +}; + +export const Page: React.FC = () => { + const [user, setUser] = React.useState(); + + return ( +
+
setUser({ name: 'Jane Doe' })} + onLogout={() => setUser(undefined)} + onCreateAccount={() => setUser({ name: 'Jane Doe' })} + /> + +
+

Pages in Storybook

+

+ We recommend building UIs with a{' '} + + component-driven + {' '} + process starting with atomic components and ending with pages. +

+

+ Render pages with mock data. This makes it easy to build and review page states without + needing to navigate to them in your app. Here are some handy patterns for managing page + data in Storybook: +

+
    +
  • + Use a higher-level connected component. Storybook helps you compose such data from the + "args" of child component stories +
  • +
  • + Assemble data in the page component from your services. You can mock these services out + using Storybook. +
  • +
+

+ Get a guided tutorial on component-driven development at{' '} + + Storybook tutorials + + . Read more in the{' '} + + docs + + . +

+
+ Tip Adjust the width of the canvas with the{' '} + + + + + + Viewports addon in the toolbar +
+
+
+ ); +}; diff --git a/code/frameworks/react-webpack5/package.json b/code/frameworks/react-webpack5/package.json index f70d68698d1..23acdcd85e5 100644 --- a/code/frameworks/react-webpack5/package.json +++ b/code/frameworks/react-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-webpack5", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for React: Develop React Component in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/react-webpack5/src/index.ts b/code/frameworks/react-webpack5/src/index.ts index 9dce8313193..cf6d4c05ce5 100644 --- a/code/frameworks/react-webpack5/src/index.ts +++ b/code/frameworks/react-webpack5/src/index.ts @@ -1,2 +1,3 @@ +export * from '@storybook/react'; export * from './types'; export { __definePreview as definePreview } from '@storybook/react'; diff --git a/code/frameworks/server-webpack5/package.json b/code/frameworks/server-webpack5/package.json index f6881942d57..2a0d367b32f 100644 --- a/code/frameworks/server-webpack5/package.json +++ b/code/frameworks/server-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/server-webpack5", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for Server: View HTML snippets from a server in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/server-webpack5/src/index.ts b/code/frameworks/server-webpack5/src/index.ts index fcb073fefcd..098058fdbc0 100644 --- a/code/frameworks/server-webpack5/src/index.ts +++ b/code/frameworks/server-webpack5/src/index.ts @@ -1 +1,2 @@ +export * from '@storybook/server'; export * from './types'; diff --git a/code/frameworks/svelte-vite/package.json b/code/frameworks/svelte-vite/package.json index 66098f2acaf..595f52fb7ed 100644 --- a/code/frameworks/svelte-vite/package.json +++ b/code/frameworks/svelte-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/svelte-vite", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for Svelte and Vite: Develop Svelte components in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -43,6 +43,7 @@ "types": "dist/index.d.ts", "files": [ "dist/**/*", + "template/**/*", "README.md", "*.js", "*.d.ts", @@ -57,7 +58,7 @@ "@storybook/svelte": "workspace:*", "magic-string": "^0.30.0", "svelte-preprocess": "^5.1.1", - "svelte2tsx": "^0.7.13", + "svelte2tsx": "^0.7.35", "sveltedoc-parser": "^4.2.1", "ts-dedent": "^2.2.0", "typescript": "^4.9.4 || ^5.0.0" diff --git a/code/frameworks/svelte-vite/src/index.ts b/code/frameworks/svelte-vite/src/index.ts index fcb073fefcd..07de4359ae1 100644 --- a/code/frameworks/svelte-vite/src/index.ts +++ b/code/frameworks/svelte-vite/src/index.ts @@ -1 +1,2 @@ +export * from '@storybook/svelte'; export * from './types'; diff --git a/code/frameworks/svelte-vite/src/plugins/generateDocgen.ts b/code/frameworks/svelte-vite/src/plugins/generateDocgen.ts index eff343fbfe0..01905776d96 100644 --- a/code/frameworks/svelte-vite/src/plugins/generateDocgen.ts +++ b/code/frameworks/svelte-vite/src/plugins/generateDocgen.ts @@ -1,6 +1,6 @@ import path from 'node:path'; -import svelte2tsx from 'svelte2tsx'; +import svelte2tsx, { internalHelpers } from 'svelte2tsx'; import { VERSION } from 'svelte/compiler'; import ts from 'typescript'; @@ -411,7 +411,9 @@ export function generateDocgen(targetFileName: string, cache: DocgenCache): Docg // Get render function generated by svelte2tsx const renderFunction = sourceFile.statements.find((statement) => { - return ts.isFunctionDeclaration(statement) && statement.name?.text === 'render'; + return ( + ts.isFunctionDeclaration(statement) && statement.name?.text === internalHelpers.renderName + ); }) as ts.FunctionDeclaration | undefined; if (renderFunction === undefined) { return { diff --git a/code/frameworks/svelte-vite/src/plugins/svelte-docgen.ts b/code/frameworks/svelte-vite/src/plugins/svelte-docgen.ts index c1647653933..062e7f68327 100644 --- a/code/frameworks/svelte-vite/src/plugins/svelte-docgen.ts +++ b/code/frameworks/svelte-vite/src/plugins/svelte-docgen.ts @@ -146,7 +146,7 @@ export async function svelteDocgen(svelteOptions: Record = {}): Pro return { name: 'storybook:svelte-docgen-plugin', async transform(src: string, id: string) { - if (!filter(id)) { + if (id.startsWith('\0') || !filter(id)) { return undefined; } @@ -189,7 +189,13 @@ export async function svelteDocgen(svelteOptions: Record = {}): Pro let docOptions; if (docPreprocessOptions) { - const rawSource = readFileSync(resource).toString(); + let rawSource; + try { + rawSource = readFileSync(resource).toString(); + } catch (_) { + // ignore/skip modules that can't be loaded, possibly virtual module + return undefined; + } const { code: fileContent } = await preprocess(rawSource, docPreprocessOptions, { filename: resource, }); diff --git a/code/frameworks/svelte-vite/template/cli/js/Button.stories.js b/code/frameworks/svelte-vite/template/cli/js/Button.stories.js new file mode 100644 index 00000000000..c5c88776d6b --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/js/Button.stories.js @@ -0,0 +1,43 @@ +import Button from './Button.svelte'; + +// More on how to set up stories at: https://storybook.js.org/docs/writing-stories +export default { + title: 'Example/Button', + component: Button, + tags: ['autodocs'], + argTypes: { + backgroundColor: { control: 'color' }, + size: { + control: { type: 'select' }, + options: ['small', 'medium', 'large'], + }, + }, +}; + +// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args +export const Primary = { + args: { + primary: true, + label: 'Button', + }, +}; + +export const Secondary = { + args: { + label: 'Button', + }, +}; + +export const Large = { + args: { + size: 'large', + label: 'Button', + }, +}; + +export const Small = { + args: { + size: 'small', + label: 'Button', + }, +}; diff --git a/code/frameworks/svelte-vite/template/cli/js/Button.svelte b/code/frameworks/svelte-vite/template/cli/js/Button.svelte new file mode 100644 index 00000000000..a2a78d9d0d6 --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/js/Button.svelte @@ -0,0 +1,36 @@ + + + diff --git a/code/frameworks/svelte-vite/template/cli/js/Header.stories.js b/code/frameworks/svelte-vite/template/cli/js/Header.stories.js new file mode 100644 index 00000000000..e2856c0e035 --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/js/Header.stories.js @@ -0,0 +1,22 @@ +import Header from './Header.svelte'; + +export default { + title: 'Example/Header', + component: Header, + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + layout: 'fullscreen', + }, +}; + +export const LoggedIn = { + args: { + user: { + name: 'Jane Doe', + }, + }, +}; + +export const LoggedOut = {}; diff --git a/code/frameworks/svelte-vite/template/cli/js/Header.svelte b/code/frameworks/svelte-vite/template/cli/js/Header.svelte new file mode 100644 index 00000000000..a9c08f75db7 --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/js/Header.svelte @@ -0,0 +1,52 @@ + + +
+
+
+ + + + + + + +

Acme

+
+
+ {#if user} + + Welcome, {user.name}! + +
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/js/Page.stories.js b/code/frameworks/svelte-vite/template/cli/js/Page.stories.js new file mode 100644 index 00000000000..5ce7b3dac56 --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/js/Page.stories.js @@ -0,0 +1,28 @@ +import { expect, userEvent, waitFor, within } from '@storybook/test'; + +import Page from './Page.svelte'; + +export default { + title: 'Example/Page', + component: Page, + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + layout: 'fullscreen', + }, +}; + +export const LoggedOut = {}; + +// More on component testing: https://storybook.js.org/docs/writing-tests/component-testing +export const LoggedIn = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const loginButton = canvas.getByRole('button', { name: /Log in/i }); + await expect(loginButton).toBeInTheDocument(); + await userEvent.click(loginButton); + await waitFor(() => expect(loginButton).not.toBeInTheDocument()); + + const logoutButton = canvas.getByRole('button', { name: /Log out/i }); + await expect(logoutButton).toBeInTheDocument(); + }, +}; diff --git a/code/frameworks/svelte-vite/template/cli/js/Page.svelte b/code/frameworks/svelte-vite/template/cli/js/Page.svelte new file mode 100644 index 00000000000..acc473c2518 --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/js/Page.svelte @@ -0,0 +1,70 @@ + + +
+
(user = { name: 'Jane Doe' })} + on:logout={() => (user = null)} + on:createAccount={() => (user = { name: 'Jane Doe' })} + /> + +
+

Pages in Storybook

+

+ We recommend building UIs with a + + component-driven + + process starting with atomic components and ending with pages. +

+

+ Render pages with mock data. This makes it easy to build and review page states without + needing to navigate to them in your app. Here are some handy patterns for managing page data + in Storybook: +

+
    +
  • + Use a higher-level connected component. Storybook helps you compose such data from the + "args" of child component stories +
  • +
  • + Assemble data in the page component from your services. You can mock these services out + using Storybook. +
  • +
+

+ Get a guided tutorial on component-driven development at + + Storybook tutorials + + . Read more in the + docs + . +

+
+ Tip + Adjust the width of the canvas with the + + + + + + Viewports addon in the toolbar +
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-js/Button.stories.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Button.stories.svelte new file mode 100644 index 00000000000..e6fb72dac17 --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Button.stories.svelte @@ -0,0 +1,31 @@ + + + + + + + + + + diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-js/Button.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Button.svelte new file mode 100644 index 00000000000..b2b820ea497 --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Button.svelte @@ -0,0 +1,26 @@ + + + diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-js/Header.stories.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Header.stories.svelte new file mode 100644 index 00000000000..23175a8203e --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Header.stories.svelte @@ -0,0 +1,26 @@ + + + + + diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-js/Header.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Header.svelte new file mode 100644 index 00000000000..dba3b7880f4 --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Header.svelte @@ -0,0 +1,47 @@ + + +
+
+
+ + + + + + + +

Acme

+
+
+ {#if user} + + Welcome, {user.name}! + +
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-js/Page.stories.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Page.stories.svelte new file mode 100644 index 00000000000..2f4fd9e890a --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Page.stories.svelte @@ -0,0 +1,30 @@ + + + { + const canvas = within(canvasElement); + const loginButton = canvas.getByRole('button', { name: /Log in/i }); + await expect(loginButton).toBeInTheDocument(); + await userEvent.click(loginButton); + await waitFor(() => expect(loginButton).not.toBeInTheDocument()); + + const logoutButton = canvas.getByRole('button', { name: /Log out/i }); + await expect(logoutButton).toBeInTheDocument(); + }} + /> + + diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-js/Page.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Page.svelte new file mode 100644 index 00000000000..92a95c00c5c --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/svelte-5-js/Page.svelte @@ -0,0 +1,70 @@ + + +
+
(user = { name: 'Jane Doe' })} + onLogout={() => (user = null)} + onCreateAccount={() => (user = { name: 'Jane Doe' })} + /> + +
+

Pages in Storybook

+

+ We recommend building UIs with a + + component-driven + + process starting with atomic components and ending with pages. +

+

+ Render pages with mock data. This makes it easy to build and review page states without + needing to navigate to them in your app. Here are some handy patterns for managing page data + in Storybook: +

+
    +
  • + Use a higher-level connected component. Storybook helps you compose such data from the + "args" of child component stories +
  • +
  • + Assemble data in the page component from your services. You can mock these services out + using Storybook. +
  • +
+

+ Get a guided tutorial on component-driven development at + + Storybook tutorials + + . Read more in the + docs + . +

+
+ Tip + Adjust the width of the canvas with the + + + + + + Viewports addon in the toolbar +
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Button.stories.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Button.stories.svelte new file mode 100644 index 00000000000..e6fb72dac17 --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Button.stories.svelte @@ -0,0 +1,31 @@ + + + + + + + + + + diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Button.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Button.svelte new file mode 100644 index 00000000000..b31f5bffe4a --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Button.svelte @@ -0,0 +1,29 @@ + + + diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Header.stories.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Header.stories.svelte new file mode 100644 index 00000000000..23175a8203e --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Header.stories.svelte @@ -0,0 +1,26 @@ + + + + + diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Header.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Header.svelte new file mode 100644 index 00000000000..14e890c79e9 --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Header.svelte @@ -0,0 +1,45 @@ + + +
+
+
+ + + + + + + +

Acme

+
+
+ {#if user} + + Welcome, {user.name}! + +
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Page.stories.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Page.stories.svelte new file mode 100644 index 00000000000..f782871a115 --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Page.stories.svelte @@ -0,0 +1,30 @@ + + + { + const canvas = within(canvasElement); + const loginButton = canvas.getByRole('button', { name: /Log in/i }); + await expect(loginButton).toBeInTheDocument(); + await userEvent.click(loginButton); + await waitFor(() => expect(loginButton).not.toBeInTheDocument()); + + const logoutButton = canvas.getByRole('button', { name: /Log out/i }); + await expect(logoutButton).toBeInTheDocument(); + }} +/> + + diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Page.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Page.svelte new file mode 100644 index 00000000000..c4c069a5a50 --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-3-8/Page.svelte @@ -0,0 +1,70 @@ + + +
+
(user = { name: 'Jane Doe' })} + onLogout={() => (user = undefined)} + onCreateAccount={() => (user = { name: 'Jane Doe' })} + /> + +
+

Pages in Storybook

+

+ We recommend building UIs with a + + component-driven + + process starting with atomic components and ending with pages. +

+

+ Render pages with mock data. This makes it easy to build and review page states without + needing to navigate to them in your app. Here are some handy patterns for managing page data + in Storybook: +

+
    +
  • + Use a higher-level connected component. Storybook helps you compose such data from the + "args" of child component stories +
  • +
  • + Assemble data in the page component from your services. You can mock these services out + using Storybook. +
  • +
+

+ Get a guided tutorial on component-driven development at + + Storybook tutorials + + . Read more in the + docs + . +

+
+ Tip + Adjust the width of the canvas with the + + + + + + Viewports addon in the toolbar +
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Button.stories.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Button.stories.svelte new file mode 100644 index 00000000000..e6fb72dac17 --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Button.stories.svelte @@ -0,0 +1,31 @@ + + + + + + + + + + diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Button.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Button.svelte new file mode 100644 index 00000000000..b31f5bffe4a --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Button.svelte @@ -0,0 +1,29 @@ + + + diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Header.stories.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Header.stories.svelte new file mode 100644 index 00000000000..23175a8203e --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Header.stories.svelte @@ -0,0 +1,26 @@ + + + + + diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Header.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Header.svelte new file mode 100644 index 00000000000..14e890c79e9 --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Header.svelte @@ -0,0 +1,45 @@ + + +
+
+
+ + + + + + + +

Acme

+
+
+ {#if user} + + Welcome, {user.name}! + +
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Page.stories.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Page.stories.svelte new file mode 100644 index 00000000000..f782871a115 --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Page.stories.svelte @@ -0,0 +1,30 @@ + + + { + const canvas = within(canvasElement); + const loginButton = canvas.getByRole('button', { name: /Log in/i }); + await expect(loginButton).toBeInTheDocument(); + await userEvent.click(loginButton); + await waitFor(() => expect(loginButton).not.toBeInTheDocument()); + + const logoutButton = canvas.getByRole('button', { name: /Log out/i }); + await expect(logoutButton).toBeInTheDocument(); + }} +/> + + diff --git a/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Page.svelte b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Page.svelte new file mode 100644 index 00000000000..c4c069a5a50 --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/svelte-5-ts-4-9/Page.svelte @@ -0,0 +1,70 @@ + + +
+
(user = { name: 'Jane Doe' })} + onLogout={() => (user = undefined)} + onCreateAccount={() => (user = { name: 'Jane Doe' })} + /> + +
+

Pages in Storybook

+

+ We recommend building UIs with a + + component-driven + + process starting with atomic components and ending with pages. +

+

+ Render pages with mock data. This makes it easy to build and review page states without + needing to navigate to them in your app. Here are some handy patterns for managing page data + in Storybook: +

+
    +
  • + Use a higher-level connected component. Storybook helps you compose such data from the + "args" of child component stories +
  • +
  • + Assemble data in the page component from your services. You can mock these services out + using Storybook. +
  • +
+

+ Get a guided tutorial on component-driven development at + + Storybook tutorials + + . Read more in the + docs + . +

+
+ Tip + Adjust the width of the canvas with the + + + + + + Viewports addon in the toolbar +
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/ts-4-9/Button.stories.ts b/code/frameworks/svelte-vite/template/cli/ts-4-9/Button.stories.ts new file mode 100644 index 00000000000..bcc54cde4d5 --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/ts-4-9/Button.stories.ts @@ -0,0 +1,48 @@ +import type { Meta, StoryObj } from '@storybook/svelte-vite'; + +import Button from './Button.svelte'; + +// More on how to set up stories at: https://storybook.js.org/docs/writing-stories +const meta = { + title: 'Example/Button', + component: Button, + tags: ['autodocs'], + argTypes: { + backgroundColor: { control: 'color' }, + size: { + control: { type: 'select' }, + options: ['small', 'medium', 'large'], + }, + }, +} satisfies Meta diff --git a/code/frameworks/svelte-vite/template/cli/ts-4-9/Header.stories.ts b/code/frameworks/svelte-vite/template/cli/ts-4-9/Header.stories.ts new file mode 100644 index 00000000000..22e301266db --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/ts-4-9/Header.stories.ts @@ -0,0 +1,27 @@ +import type { Meta, StoryObj } from '@storybook/svelte-vite'; + +import Header from './Header.svelte'; + +const meta = { + title: 'Example/Header', + component: Header, + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + layout: 'fullscreen', + }, +} satisfies Meta
; + +export default meta; +type Story = StoryObj; + +export const LoggedIn: Story = { + args: { + user: { + name: 'Jane Doe', + }, + }, +}; + +export const LoggedOut: Story = {}; diff --git a/code/frameworks/svelte-vite/template/cli/ts-4-9/Header.svelte b/code/frameworks/svelte-vite/template/cli/ts-4-9/Header.svelte new file mode 100644 index 00000000000..cb6f82d5e66 --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/ts-4-9/Header.svelte @@ -0,0 +1,52 @@ + + +
+
+
+ + + + + + + +

Acme

+
+
+ {#if user} + + Welcome, {user.name}! + +
+
+
diff --git a/code/frameworks/svelte-vite/template/cli/ts-4-9/Page.stories.ts b/code/frameworks/svelte-vite/template/cli/ts-4-9/Page.stories.ts new file mode 100644 index 00000000000..d6b261fb586 --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/ts-4-9/Page.stories.ts @@ -0,0 +1,33 @@ +import { expect, userEvent, waitFor, within } from '@storybook/test'; + +import type { Meta, StoryObj } from '@storybook/svelte-vite'; + +import Page from './Page.svelte'; + +const meta = { + title: 'Example/Page', + component: Page, + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + layout: 'fullscreen', + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const LoggedOut: Story = {}; + +// More on component testing: https://storybook.js.org/docs/writing-tests/component-testing +export const LoggedIn: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const loginButton = canvas.getByRole('button', { name: /Log in/i }); + await expect(loginButton).toBeInTheDocument(); + await userEvent.click(loginButton); + await waitFor(() => expect(loginButton).not.toBeInTheDocument()); + + const logoutButton = canvas.getByRole('button', { name: /Log out/i }); + await expect(logoutButton).toBeInTheDocument(); + }, +}; diff --git a/code/frameworks/svelte-vite/template/cli/ts-4-9/Page.svelte b/code/frameworks/svelte-vite/template/cli/ts-4-9/Page.svelte new file mode 100644 index 00000000000..94cdb07ecd3 --- /dev/null +++ b/code/frameworks/svelte-vite/template/cli/ts-4-9/Page.svelte @@ -0,0 +1,70 @@ + + +
+
(user = { name: 'Jane Doe' })} + on:logout={() => (user = null)} + on:createAccount={() => (user = { name: 'Jane Doe' })} + /> + +
+

Pages in Storybook

+

+ We recommend building UIs with a + + component-driven + + process starting with atomic components and ending with pages. +

+

+ Render pages with mock data. This makes it easy to build and review page states without + needing to navigate to them in your app. Here are some handy patterns for managing page data + in Storybook: +

+
    +
  • + Use a higher-level connected component. Storybook helps you compose such data from the + "args" of child component stories +
  • +
  • + Assemble data in the page component from your services. You can mock these services out + using Storybook. +
  • +
+

+ Get a guided tutorial on component-driven development at + + Storybook tutorials + + . Read more in the + docs + . +

+
+ Tip + Adjust the width of the canvas with the + + + + + + Viewports addon in the toolbar +
+
+
diff --git a/code/frameworks/svelte-webpack5/package.json b/code/frameworks/svelte-webpack5/package.json index cb2f03ab475..a42f5eb1507 100644 --- a/code/frameworks/svelte-webpack5/package.json +++ b/code/frameworks/svelte-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/svelte-webpack5", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for Svelte: Develop Svelte Component in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -43,6 +43,7 @@ "types": "dist/index.d.ts", "files": [ "dist/**/*", + "templates/**/*", "README.md", "*.js", "*.d.ts", diff --git a/code/frameworks/svelte-webpack5/src/index.ts b/code/frameworks/svelte-webpack5/src/index.ts index fcb073fefcd..07de4359ae1 100644 --- a/code/frameworks/svelte-webpack5/src/index.ts +++ b/code/frameworks/svelte-webpack5/src/index.ts @@ -1 +1,2 @@ +export * from '@storybook/svelte'; export * from './types'; diff --git a/code/frameworks/sveltekit/package.json b/code/frameworks/sveltekit/package.json index cc8a207e575..1c1ef886290 100644 --- a/code/frameworks/sveltekit/package.json +++ b/code/frameworks/sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/sveltekit", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for SvelteKit", "keywords": [ "storybook", @@ -54,6 +54,7 @@ "types": "dist/index.d.ts", "files": [ "dist/**/*", + "template/**/*", "README.md", "*.js", "*.d.ts", diff --git a/code/frameworks/sveltekit/src/index.ts b/code/frameworks/sveltekit/src/index.ts index a904f93ec89..ee64168c3b8 100644 --- a/code/frameworks/sveltekit/src/index.ts +++ b/code/frameworks/sveltekit/src/index.ts @@ -1,2 +1,4 @@ +export * from '@storybook/svelte'; export * from './types'; +// @ts-expect-error (double exports) export * from './portable-stories'; diff --git a/code/frameworks/sveltekit/template/cli/js/Button.stories.js b/code/frameworks/sveltekit/template/cli/js/Button.stories.js new file mode 100644 index 00000000000..c5c88776d6b --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/js/Button.stories.js @@ -0,0 +1,43 @@ +import Button from './Button.svelte'; + +// More on how to set up stories at: https://storybook.js.org/docs/writing-stories +export default { + title: 'Example/Button', + component: Button, + tags: ['autodocs'], + argTypes: { + backgroundColor: { control: 'color' }, + size: { + control: { type: 'select' }, + options: ['small', 'medium', 'large'], + }, + }, +}; + +// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args +export const Primary = { + args: { + primary: true, + label: 'Button', + }, +}; + +export const Secondary = { + args: { + label: 'Button', + }, +}; + +export const Large = { + args: { + size: 'large', + label: 'Button', + }, +}; + +export const Small = { + args: { + size: 'small', + label: 'Button', + }, +}; diff --git a/code/frameworks/sveltekit/template/cli/js/Button.svelte b/code/frameworks/sveltekit/template/cli/js/Button.svelte new file mode 100644 index 00000000000..a2a78d9d0d6 --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/js/Button.svelte @@ -0,0 +1,36 @@ + + + diff --git a/code/frameworks/sveltekit/template/cli/js/Header.stories.js b/code/frameworks/sveltekit/template/cli/js/Header.stories.js new file mode 100644 index 00000000000..e2856c0e035 --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/js/Header.stories.js @@ -0,0 +1,22 @@ +import Header from './Header.svelte'; + +export default { + title: 'Example/Header', + component: Header, + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + layout: 'fullscreen', + }, +}; + +export const LoggedIn = { + args: { + user: { + name: 'Jane Doe', + }, + }, +}; + +export const LoggedOut = {}; diff --git a/code/frameworks/sveltekit/template/cli/js/Header.svelte b/code/frameworks/sveltekit/template/cli/js/Header.svelte new file mode 100644 index 00000000000..a9c08f75db7 --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/js/Header.svelte @@ -0,0 +1,52 @@ + + +
+
+
+ + + + + + + +

Acme

+
+
+ {#if user} + + Welcome, {user.name}! + +
+
+
diff --git a/code/frameworks/sveltekit/template/cli/js/Page.stories.js b/code/frameworks/sveltekit/template/cli/js/Page.stories.js new file mode 100644 index 00000000000..5ce7b3dac56 --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/js/Page.stories.js @@ -0,0 +1,28 @@ +import { expect, userEvent, waitFor, within } from '@storybook/test'; + +import Page from './Page.svelte'; + +export default { + title: 'Example/Page', + component: Page, + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + layout: 'fullscreen', + }, +}; + +export const LoggedOut = {}; + +// More on component testing: https://storybook.js.org/docs/writing-tests/component-testing +export const LoggedIn = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const loginButton = canvas.getByRole('button', { name: /Log in/i }); + await expect(loginButton).toBeInTheDocument(); + await userEvent.click(loginButton); + await waitFor(() => expect(loginButton).not.toBeInTheDocument()); + + const logoutButton = canvas.getByRole('button', { name: /Log out/i }); + await expect(logoutButton).toBeInTheDocument(); + }, +}; diff --git a/code/frameworks/sveltekit/template/cli/js/Page.svelte b/code/frameworks/sveltekit/template/cli/js/Page.svelte new file mode 100644 index 00000000000..acc473c2518 --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/js/Page.svelte @@ -0,0 +1,70 @@ + + +
+
(user = { name: 'Jane Doe' })} + on:logout={() => (user = null)} + on:createAccount={() => (user = { name: 'Jane Doe' })} + /> + +
+

Pages in Storybook

+

+ We recommend building UIs with a + + component-driven + + process starting with atomic components and ending with pages. +

+

+ Render pages with mock data. This makes it easy to build and review page states without + needing to navigate to them in your app. Here are some handy patterns for managing page data + in Storybook: +

+
    +
  • + Use a higher-level connected component. Storybook helps you compose such data from the + "args" of child component stories +
  • +
  • + Assemble data in the page component from your services. You can mock these services out + using Storybook. +
  • +
+

+ Get a guided tutorial on component-driven development at + + Storybook tutorials + + . Read more in the + docs + . +

+
+ Tip + Adjust the width of the canvas with the + + + + + + Viewports addon in the toolbar +
+
+
diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-js/Button.stories.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-js/Button.stories.svelte new file mode 100644 index 00000000000..e6fb72dac17 --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/svelte-5-js/Button.stories.svelte @@ -0,0 +1,31 @@ + + + + + + + + + + diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-js/Button.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-js/Button.svelte new file mode 100644 index 00000000000..b2b820ea497 --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/svelte-5-js/Button.svelte @@ -0,0 +1,26 @@ + + + diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-js/Header.stories.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-js/Header.stories.svelte new file mode 100644 index 00000000000..23175a8203e --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/svelte-5-js/Header.stories.svelte @@ -0,0 +1,26 @@ + + + + + diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-js/Header.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-js/Header.svelte new file mode 100644 index 00000000000..dba3b7880f4 --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/svelte-5-js/Header.svelte @@ -0,0 +1,47 @@ + + +
+
+
+ + + + + + + +

Acme

+
+
+ {#if user} + + Welcome, {user.name}! + +
+
+
diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-js/Page.stories.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-js/Page.stories.svelte new file mode 100644 index 00000000000..2f4fd9e890a --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/svelte-5-js/Page.stories.svelte @@ -0,0 +1,30 @@ + + + { + const canvas = within(canvasElement); + const loginButton = canvas.getByRole('button', { name: /Log in/i }); + await expect(loginButton).toBeInTheDocument(); + await userEvent.click(loginButton); + await waitFor(() => expect(loginButton).not.toBeInTheDocument()); + + const logoutButton = canvas.getByRole('button', { name: /Log out/i }); + await expect(logoutButton).toBeInTheDocument(); + }} + /> + + diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-js/Page.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-js/Page.svelte new file mode 100644 index 00000000000..92a95c00c5c --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/svelte-5-js/Page.svelte @@ -0,0 +1,70 @@ + + +
+
(user = { name: 'Jane Doe' })} + onLogout={() => (user = null)} + onCreateAccount={() => (user = { name: 'Jane Doe' })} + /> + +
+

Pages in Storybook

+

+ We recommend building UIs with a + + component-driven + + process starting with atomic components and ending with pages. +

+

+ Render pages with mock data. This makes it easy to build and review page states without + needing to navigate to them in your app. Here are some handy patterns for managing page data + in Storybook: +

+
    +
  • + Use a higher-level connected component. Storybook helps you compose such data from the + "args" of child component stories +
  • +
  • + Assemble data in the page component from your services. You can mock these services out + using Storybook. +
  • +
+

+ Get a guided tutorial on component-driven development at + + Storybook tutorials + + . Read more in the + docs + . +

+
+ Tip + Adjust the width of the canvas with the + + + + + + Viewports addon in the toolbar +
+
+
diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Button.stories.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Button.stories.svelte new file mode 100644 index 00000000000..e6fb72dac17 --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Button.stories.svelte @@ -0,0 +1,31 @@ + + + + + + + + + + diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Button.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Button.svelte new file mode 100644 index 00000000000..b31f5bffe4a --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Button.svelte @@ -0,0 +1,29 @@ + + + diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Header.stories.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Header.stories.svelte new file mode 100644 index 00000000000..23175a8203e --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Header.stories.svelte @@ -0,0 +1,26 @@ + + + + + diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Header.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Header.svelte new file mode 100644 index 00000000000..14e890c79e9 --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Header.svelte @@ -0,0 +1,45 @@ + + +
+
+
+ + + + + + + +

Acme

+
+
+ {#if user} + + Welcome, {user.name}! + +
+
+
diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Page.stories.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Page.stories.svelte new file mode 100644 index 00000000000..f782871a115 --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Page.stories.svelte @@ -0,0 +1,30 @@ + + + { + const canvas = within(canvasElement); + const loginButton = canvas.getByRole('button', { name: /Log in/i }); + await expect(loginButton).toBeInTheDocument(); + await userEvent.click(loginButton); + await waitFor(() => expect(loginButton).not.toBeInTheDocument()); + + const logoutButton = canvas.getByRole('button', { name: /Log out/i }); + await expect(logoutButton).toBeInTheDocument(); + }} +/> + + diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Page.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Page.svelte new file mode 100644 index 00000000000..c4c069a5a50 --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-3-8/Page.svelte @@ -0,0 +1,70 @@ + + +
+
(user = { name: 'Jane Doe' })} + onLogout={() => (user = undefined)} + onCreateAccount={() => (user = { name: 'Jane Doe' })} + /> + +
+

Pages in Storybook

+

+ We recommend building UIs with a + + component-driven + + process starting with atomic components and ending with pages. +

+

+ Render pages with mock data. This makes it easy to build and review page states without + needing to navigate to them in your app. Here are some handy patterns for managing page data + in Storybook: +

+
    +
  • + Use a higher-level connected component. Storybook helps you compose such data from the + "args" of child component stories +
  • +
  • + Assemble data in the page component from your services. You can mock these services out + using Storybook. +
  • +
+

+ Get a guided tutorial on component-driven development at + + Storybook tutorials + + . Read more in the + docs + . +

+
+ Tip + Adjust the width of the canvas with the + + + + + + Viewports addon in the toolbar +
+
+
diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Button.stories.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Button.stories.svelte new file mode 100644 index 00000000000..e6fb72dac17 --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Button.stories.svelte @@ -0,0 +1,31 @@ + + + + + + + + + + diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Button.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Button.svelte new file mode 100644 index 00000000000..b31f5bffe4a --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Button.svelte @@ -0,0 +1,29 @@ + + + diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Header.stories.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Header.stories.svelte new file mode 100644 index 00000000000..23175a8203e --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Header.stories.svelte @@ -0,0 +1,26 @@ + + + + + diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Header.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Header.svelte new file mode 100644 index 00000000000..14e890c79e9 --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Header.svelte @@ -0,0 +1,45 @@ + + +
+
+
+ + + + + + + +

Acme

+
+
+ {#if user} + + Welcome, {user.name}! + +
+
+
diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Page.stories.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Page.stories.svelte new file mode 100644 index 00000000000..f782871a115 --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Page.stories.svelte @@ -0,0 +1,30 @@ + + + { + const canvas = within(canvasElement); + const loginButton = canvas.getByRole('button', { name: /Log in/i }); + await expect(loginButton).toBeInTheDocument(); + await userEvent.click(loginButton); + await waitFor(() => expect(loginButton).not.toBeInTheDocument()); + + const logoutButton = canvas.getByRole('button', { name: /Log out/i }); + await expect(logoutButton).toBeInTheDocument(); + }} +/> + + diff --git a/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Page.svelte b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Page.svelte new file mode 100644 index 00000000000..c4c069a5a50 --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/svelte-5-ts-4-9/Page.svelte @@ -0,0 +1,70 @@ + + +
+
(user = { name: 'Jane Doe' })} + onLogout={() => (user = undefined)} + onCreateAccount={() => (user = { name: 'Jane Doe' })} + /> + +
+

Pages in Storybook

+

+ We recommend building UIs with a + + component-driven + + process starting with atomic components and ending with pages. +

+

+ Render pages with mock data. This makes it easy to build and review page states without + needing to navigate to them in your app. Here are some handy patterns for managing page data + in Storybook: +

+
    +
  • + Use a higher-level connected component. Storybook helps you compose such data from the + "args" of child component stories +
  • +
  • + Assemble data in the page component from your services. You can mock these services out + using Storybook. +
  • +
+

+ Get a guided tutorial on component-driven development at + + Storybook tutorials + + . Read more in the + docs + . +

+
+ Tip + Adjust the width of the canvas with the + + + + + + Viewports addon in the toolbar +
+
+
diff --git a/code/frameworks/sveltekit/template/cli/ts-4-9/Button.stories.ts b/code/frameworks/sveltekit/template/cli/ts-4-9/Button.stories.ts new file mode 100644 index 00000000000..1b8ab10d8b7 --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/ts-4-9/Button.stories.ts @@ -0,0 +1,48 @@ +import type { Meta, StoryObj } from '@storybook/sveltekit'; + +import Button from './Button.svelte'; + +// More on how to set up stories at: https://storybook.js.org/docs/writing-stories +const meta = { + title: 'Example/Button', + component: Button, + tags: ['autodocs'], + argTypes: { + backgroundColor: { control: 'color' }, + size: { + control: { type: 'select' }, + options: ['small', 'medium', 'large'], + }, + }, +} satisfies Meta diff --git a/code/frameworks/sveltekit/template/cli/ts-4-9/Header.stories.ts b/code/frameworks/sveltekit/template/cli/ts-4-9/Header.stories.ts new file mode 100644 index 00000000000..8f3588a55c1 --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/ts-4-9/Header.stories.ts @@ -0,0 +1,27 @@ +import type { Meta, StoryObj } from '@storybook/sveltekit'; + +import Header from './Header.svelte'; + +const meta = { + title: 'Example/Header', + component: Header, + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + layout: 'fullscreen', + }, +} satisfies Meta
; + +export default meta; +type Story = StoryObj; + +export const LoggedIn: Story = { + args: { + user: { + name: 'Jane Doe', + }, + }, +}; + +export const LoggedOut: Story = {}; diff --git a/code/frameworks/sveltekit/template/cli/ts-4-9/Header.svelte b/code/frameworks/sveltekit/template/cli/ts-4-9/Header.svelte new file mode 100644 index 00000000000..cb6f82d5e66 --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/ts-4-9/Header.svelte @@ -0,0 +1,52 @@ + + +
+
+
+ + + + + + + +

Acme

+
+
+ {#if user} + + Welcome, {user.name}! + +
+
+
diff --git a/code/frameworks/sveltekit/template/cli/ts-4-9/Page.stories.ts b/code/frameworks/sveltekit/template/cli/ts-4-9/Page.stories.ts new file mode 100644 index 00000000000..0465cf53122 --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/ts-4-9/Page.stories.ts @@ -0,0 +1,32 @@ +import type { Meta, StoryObj } from '@storybook/sveltekit'; +import { expect, userEvent, waitFor, within } from '@storybook/test'; + +import Page from './Page.svelte'; + +const meta = { + title: 'Example/Page', + component: Page, + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + layout: 'fullscreen', + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const LoggedOut: Story = {}; + +// More on component testing: https://storybook.js.org/docs/writing-tests/component-testing +export const LoggedIn: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const loginButton = canvas.getByRole('button', { name: /Log in/i }); + await expect(loginButton).toBeInTheDocument(); + await userEvent.click(loginButton); + await waitFor(() => expect(loginButton).not.toBeInTheDocument()); + + const logoutButton = canvas.getByRole('button', { name: /Log out/i }); + await expect(logoutButton).toBeInTheDocument(); + }, +}; diff --git a/code/frameworks/sveltekit/template/cli/ts-4-9/Page.svelte b/code/frameworks/sveltekit/template/cli/ts-4-9/Page.svelte new file mode 100644 index 00000000000..94cdb07ecd3 --- /dev/null +++ b/code/frameworks/sveltekit/template/cli/ts-4-9/Page.svelte @@ -0,0 +1,70 @@ + + +
+
(user = { name: 'Jane Doe' })} + on:logout={() => (user = null)} + on:createAccount={() => (user = { name: 'Jane Doe' })} + /> + +
+

Pages in Storybook

+

+ We recommend building UIs with a + + component-driven + + process starting with atomic components and ending with pages. +

+

+ Render pages with mock data. This makes it easy to build and review page states without + needing to navigate to them in your app. Here are some handy patterns for managing page data + in Storybook: +

+
    +
  • + Use a higher-level connected component. Storybook helps you compose such data from the + "args" of child component stories +
  • +
  • + Assemble data in the page component from your services. You can mock these services out + using Storybook. +
  • +
+

+ Get a guided tutorial on component-driven development at + + Storybook tutorials + + . Read more in the + docs + . +

+
+ Tip + Adjust the width of the canvas with the + + + + + + Viewports addon in the toolbar +
+
+
diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/forms.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/forms.stories.js index baff059fa21..a60865e1d17 100644 --- a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/forms.stories.js +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/forms.stories.js @@ -1,4 +1,4 @@ -import { expect, fn, within } from '@storybook/test'; +import { expect, fn, within } from 'storybook/test'; import Forms from './Forms.svelte'; diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/hrefs.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/hrefs.stories.js index 9f7033e36a3..e5517ce62f8 100644 --- a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/hrefs.stories.js +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/hrefs.stories.js @@ -1,4 +1,4 @@ -import { expect, fn, within } from '@storybook/test'; +import { expect, fn, within } from 'storybook/test'; import Hrefs from './Hrefs.svelte'; diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/navigation.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/navigation.stories.js index e102fce9643..cde66fd4f5a 100644 --- a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/navigation.stories.js +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/navigation.stories.js @@ -1,4 +1,4 @@ -import { expect, fn, within } from '@storybook/test'; +import { expect, fn, within } from 'storybook/test'; import Navigation from './Navigation.svelte'; diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/environment.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/environment.stories.js index fb4c85d9926..47f2f3a4424 100644 --- a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/environment.stories.js +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/environment.stories.js @@ -1,4 +1,4 @@ -import { expect, fn, within } from '@storybook/test'; +import { expect, fn, within } from 'storybook/test'; import Environment from './Environment.svelte'; diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/forms.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/forms.stories.js index 7659291df4f..6a020c8e124 100644 --- a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/forms.stories.js +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/forms.stories.js @@ -1,4 +1,4 @@ -import { expect, fn, userEvent, within } from '@storybook/test'; +import { expect, fn, userEvent, within } from 'storybook/test'; import Forms from './Forms.svelte'; diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/hrefs.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/hrefs.stories.js index 9f7033e36a3..e5517ce62f8 100644 --- a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/hrefs.stories.js +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/hrefs.stories.js @@ -1,4 +1,4 @@ -import { expect, fn, within } from '@storybook/test'; +import { expect, fn, within } from 'storybook/test'; import Hrefs from './Hrefs.svelte'; diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/navigation.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/navigation.stories.js index e102fce9643..cde66fd4f5a 100644 --- a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/navigation.stories.js +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/navigation.stories.js @@ -1,4 +1,4 @@ -import { expect, fn, within } from '@storybook/test'; +import { expect, fn, within } from 'storybook/test'; import Navigation from './Navigation.svelte'; diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/paths.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/paths.stories.js index 4ef5ddbcb54..1c6d5f362c5 100644 --- a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/paths.stories.js +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-js/paths.stories.js @@ -1,4 +1,4 @@ -import { expect, fn, within } from '@storybook/test'; +import { expect, fn, within } from 'storybook/test'; import Paths from './Paths.svelte'; diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/environment.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/environment.stories.js index fb4c85d9926..47f2f3a4424 100644 --- a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/environment.stories.js +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/environment.stories.js @@ -1,4 +1,4 @@ -import { expect, fn, within } from '@storybook/test'; +import { expect, fn, within } from 'storybook/test'; import Environment from './Environment.svelte'; diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/forms.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/forms.stories.js index baff059fa21..a60865e1d17 100644 --- a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/forms.stories.js +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/forms.stories.js @@ -1,4 +1,4 @@ -import { expect, fn, within } from '@storybook/test'; +import { expect, fn, within } from 'storybook/test'; import Forms from './Forms.svelte'; diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/hrefs.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/hrefs.stories.js index 9f7033e36a3..e5517ce62f8 100644 --- a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/hrefs.stories.js +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/hrefs.stories.js @@ -1,4 +1,4 @@ -import { expect, fn, within } from '@storybook/test'; +import { expect, fn, within } from 'storybook/test'; import Hrefs from './Hrefs.svelte'; diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/navigation.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/navigation.stories.js index e102fce9643..cde66fd4f5a 100644 --- a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/navigation.stories.js +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/navigation.stories.js @@ -1,4 +1,4 @@ -import { expect, fn, within } from '@storybook/test'; +import { expect, fn, within } from 'storybook/test'; import Navigation from './Navigation.svelte'; diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/paths.stories.js b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/paths.stories.js index 4ef5ddbcb54..1c6d5f362c5 100644 --- a/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/paths.stories.js +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-skeleton-ts/paths.stories.js @@ -1,4 +1,4 @@ -import { expect, fn, within } from '@storybook/test'; +import { expect, fn, within } from 'storybook/test'; import Paths from './Paths.svelte'; diff --git a/code/frameworks/vue3-vite/package.json b/code/frameworks/vue3-vite/package.json index 98dcaa45223..022248c746a 100644 --- a/code/frameworks/vue3-vite/package.json +++ b/code/frameworks/vue3-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/vue3-vite", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for Vue3 and Vite: Develop Vue3 components in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -48,6 +48,7 @@ "types": "dist/index.d.ts", "files": [ "dist/**/*", + "template/**/*", "README.md", "*.js", "*.d.ts", diff --git a/code/frameworks/vue3-vite/src/index.ts b/code/frameworks/vue3-vite/src/index.ts index fcb073fefcd..034adb8b02a 100644 --- a/code/frameworks/vue3-vite/src/index.ts +++ b/code/frameworks/vue3-vite/src/index.ts @@ -1 +1,2 @@ +export * from '@storybook/vue3'; export * from './types'; diff --git a/code/frameworks/vue3-vite/template/cli/js/Button.stories.js b/code/frameworks/vue3-vite/template/cli/js/Button.stories.js new file mode 100644 index 00000000000..2bd009f3816 --- /dev/null +++ b/code/frameworks/vue3-vite/template/cli/js/Button.stories.js @@ -0,0 +1,44 @@ +import { fn } from 'storybook/test'; + +import MyButton from './Button.vue'; + +// More on how to set up stories at: https://storybook.js.org/docs/writing-stories +export default { + title: 'Example/Button', + component: MyButton, + tags: ['autodocs'], + argTypes: { + size: { control: { type: 'select' }, options: ['small', 'medium', 'large'] }, + backgroundColor: { control: 'color' }, + }, + // Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args + args: { onClick: fn() }, +}; + +// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args +export const Primary = { + args: { + primary: true, + label: 'Button', + }, +}; + +export const Secondary = { + args: { + label: 'Button', + }, +}; + +export const Large = { + args: { + size: 'large', + label: 'Button', + }, +}; + +export const Small = { + args: { + size: 'small', + label: 'Button', + }, +}; diff --git a/code/frameworks/vue3-vite/template/cli/js/Button.vue b/code/frameworks/vue3-vite/template/cli/js/Button.vue new file mode 100644 index 00000000000..a831ddf4991 --- /dev/null +++ b/code/frameworks/vue3-vite/template/cli/js/Button.vue @@ -0,0 +1,52 @@ + + + diff --git a/code/frameworks/vue3-vite/template/cli/js/Header.stories.js b/code/frameworks/vue3-vite/template/cli/js/Header.stories.js new file mode 100644 index 00000000000..ca1b5e65bf0 --- /dev/null +++ b/code/frameworks/vue3-vite/template/cli/js/Header.stories.js @@ -0,0 +1,48 @@ +import { fn } from 'storybook/test'; + +import MyHeader from './Header.vue'; + +export default { + title: 'Example/Header', + component: MyHeader, + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], + render: (args) => ({ + // Components used in your story `template` are defined in the `components` object + components: { + MyHeader, + }, + // The story's `args` need to be mapped into the template through the `setup()` method + setup() { + // Story args can be spread into the returned object + return { + ...args, + }; + }, + // Then, the spread values can be accessed directly in the template + template: '', + }), + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + layout: 'fullscreen', + }, + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), + }, +}; + +export const LoggedIn = { + args: { + user: { + name: 'Jane Doe', + }, + }, +}; + +export const LoggedOut = { + args: { + user: null, + }, +}; diff --git a/code/frameworks/vue3-vite/template/cli/js/Header.vue b/code/frameworks/vue3-vite/template/cli/js/Header.vue new file mode 100644 index 00000000000..16d7740d96c --- /dev/null +++ b/code/frameworks/vue3-vite/template/cli/js/Header.vue @@ -0,0 +1,59 @@ + + + diff --git a/code/frameworks/vue3-vite/template/cli/js/Page.stories.js b/code/frameworks/vue3-vite/template/cli/js/Page.stories.js new file mode 100644 index 00000000000..f03db3c7f07 --- /dev/null +++ b/code/frameworks/vue3-vite/template/cli/js/Page.stories.js @@ -0,0 +1,34 @@ +import { expect, userEvent, within } from '@storybook/test'; + +import MyPage from './Page.vue'; + +export default { + title: 'Example/Page', + component: MyPage, + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + layout: 'fullscreen', + }, +}; + +export const LoggedOut = {}; + +// More on component testing: https://storybook.js.org/docs/writing-tests/component-testing +export const LoggedIn = { + render: () => ({ + components: { + MyPage, + }, + template: '', + }), + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const loginButton = canvas.getByRole('button', { name: /Log in/i }); + await expect(loginButton).toBeInTheDocument(); + await userEvent.click(loginButton); + await expect(loginButton).not.toBeInTheDocument(); + + const logoutButton = canvas.getByRole('button', { name: /Log out/i }); + await expect(logoutButton).toBeInTheDocument(); + }, +}; diff --git a/code/frameworks/vue3-vite/template/cli/js/Page.vue b/code/frameworks/vue3-vite/template/cli/js/Page.vue new file mode 100644 index 00000000000..245401b72c4 --- /dev/null +++ b/code/frameworks/vue3-vite/template/cli/js/Page.vue @@ -0,0 +1,83 @@ + + + diff --git a/code/frameworks/vue3-vite/template/cli/ts-4-9/Button.stories.ts b/code/frameworks/vue3-vite/template/cli/ts-4-9/Button.stories.ts new file mode 100644 index 00000000000..c9cf6edbe7d --- /dev/null +++ b/code/frameworks/vue3-vite/template/cli/ts-4-9/Button.stories.ts @@ -0,0 +1,57 @@ +import type { Meta, StoryObj } from '@storybook/vue3-vite'; + +import { fn } from 'storybook/test'; + +import Button from './Button.vue'; + +// More on how to set up stories at: https://storybook.js.org/docs/writing-stories +const meta = { + title: 'Example/Button', + component: Button, + // This component will have an automatically generated docsPage entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], + argTypes: { + size: { control: 'select', options: ['small', 'medium', 'large'] }, + backgroundColor: { control: 'color' }, + }, + args: { + primary: false, + // Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args + onClick: fn(), + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; +/* + *👇 Render functions are a framework specific feature to allow you control on how the component renders. + * See https://storybook.js.org/docs/api/csf + * to learn how to use render functions. + */ +export const Primary: Story = { + args: { + primary: true, + label: 'Button', + }, +}; + +export const Secondary: Story = { + args: { + primary: false, + label: 'Button', + }, +}; + +export const Large: Story = { + args: { + label: 'Button', + size: 'large', + }, +}; + +export const Small: Story = { + args: { + label: 'Button', + size: 'small', + }, +}; diff --git a/code/frameworks/vue3-vite/template/cli/ts-4-9/Button.vue b/code/frameworks/vue3-vite/template/cli/ts-4-9/Button.vue new file mode 100644 index 00000000000..2e1ee0ee22f --- /dev/null +++ b/code/frameworks/vue3-vite/template/cli/ts-4-9/Button.vue @@ -0,0 +1,48 @@ + + + \ No newline at end of file diff --git a/code/frameworks/vue3-vite/template/cli/ts-4-9/Header.stories.ts b/code/frameworks/vue3-vite/template/cli/ts-4-9/Header.stories.ts new file mode 100644 index 00000000000..47caa29a09e --- /dev/null +++ b/code/frameworks/vue3-vite/template/cli/ts-4-9/Header.stories.ts @@ -0,0 +1,49 @@ +import type { Meta, StoryObj } from '@storybook/vue3-vite'; + +import { fn } from 'storybook/test'; + +import MyHeader from './Header.vue'; + +const meta = { + /* 👇 The title prop is optional. + * See https://storybook.js.org/docs/configure/#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'Example/Header', + component: MyHeader, + render: (args: any) => ({ + components: { MyHeader }, + setup() { + return { args }; + }, + template: '', + }), + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + layout: 'fullscreen', + }, + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), + }, + // This component will have an automatically generated docsPage entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const LoggedIn: Story = { + args: { + user: { + name: 'Jane Doe', + }, + }, +}; + +export const LoggedOut: Story = { + args: { + user: null, + }, +}; diff --git a/code/frameworks/vue3-vite/template/cli/ts-4-9/Header.vue b/code/frameworks/vue3-vite/template/cli/ts-4-9/Header.vue new file mode 100644 index 00000000000..b716db02b3f --- /dev/null +++ b/code/frameworks/vue3-vite/template/cli/ts-4-9/Header.vue @@ -0,0 +1,37 @@ + + + + diff --git a/code/frameworks/vue3-vite/template/cli/ts-4-9/Page.stories.ts b/code/frameworks/vue3-vite/template/cli/ts-4-9/Page.stories.ts new file mode 100644 index 00000000000..906f674fa3a --- /dev/null +++ b/code/frameworks/vue3-vite/template/cli/ts-4-9/Page.stories.ts @@ -0,0 +1,39 @@ +import { expect, userEvent, within } from '@storybook/test'; + +import type { Meta, StoryObj } from '@storybook/vue3-vite'; + +import MyPage from './Page.vue'; + +const meta = { + title: 'Example/Page', + component: MyPage, + render: () => ({ + components: { MyPage }, + template: '', + }), + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + layout: 'fullscreen', + }, + // This component will have an automatically generated docsPage entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +// More on component testing: https://storybook.js.org/docs/writing-tests/component-testing +export const LoggedIn: Story = { + play: async ({ canvasElement }: any) => { + const canvas = within(canvasElement); + const loginButton = canvas.getByRole('button', { name: /Log in/i }); + await expect(loginButton).toBeInTheDocument(); + await userEvent.click(loginButton); + await expect(loginButton).not.toBeInTheDocument(); + + const logoutButton = canvas.getByRole('button', { name: /Log out/i }); + await expect(logoutButton).toBeInTheDocument(); + }, +}; + +export const LoggedOut: Story = {}; diff --git a/code/frameworks/vue3-vite/template/cli/ts-4-9/Page.vue b/code/frameworks/vue3-vite/template/cli/ts-4-9/Page.vue new file mode 100644 index 00000000000..6a6e5eb1a4a --- /dev/null +++ b/code/frameworks/vue3-vite/template/cli/ts-4-9/Page.vue @@ -0,0 +1,73 @@ + + + diff --git a/code/frameworks/vue3-webpack5/package.json b/code/frameworks/vue3-webpack5/package.json index da3d69ad3a6..603b93809e5 100644 --- a/code/frameworks/vue3-webpack5/package.json +++ b/code/frameworks/vue3-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/vue3-webpack5", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for Vue 3: Develop Vue 3 Components in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -43,6 +43,7 @@ "types": "dist/index.d.ts", "files": [ "dist/**/*", + "template/**/*", "README.md", "*.js", "*.d.ts", diff --git a/code/frameworks/vue3-webpack5/src/index.ts b/code/frameworks/vue3-webpack5/src/index.ts index fcb073fefcd..034adb8b02a 100644 --- a/code/frameworks/vue3-webpack5/src/index.ts +++ b/code/frameworks/vue3-webpack5/src/index.ts @@ -1 +1,2 @@ +export * from '@storybook/vue3'; export * from './types'; diff --git a/code/frameworks/vue3-webpack5/template/cli/js/Button.stories.js b/code/frameworks/vue3-webpack5/template/cli/js/Button.stories.js new file mode 100644 index 00000000000..2bd009f3816 --- /dev/null +++ b/code/frameworks/vue3-webpack5/template/cli/js/Button.stories.js @@ -0,0 +1,44 @@ +import { fn } from 'storybook/test'; + +import MyButton from './Button.vue'; + +// More on how to set up stories at: https://storybook.js.org/docs/writing-stories +export default { + title: 'Example/Button', + component: MyButton, + tags: ['autodocs'], + argTypes: { + size: { control: { type: 'select' }, options: ['small', 'medium', 'large'] }, + backgroundColor: { control: 'color' }, + }, + // Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args + args: { onClick: fn() }, +}; + +// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args +export const Primary = { + args: { + primary: true, + label: 'Button', + }, +}; + +export const Secondary = { + args: { + label: 'Button', + }, +}; + +export const Large = { + args: { + size: 'large', + label: 'Button', + }, +}; + +export const Small = { + args: { + size: 'small', + label: 'Button', + }, +}; diff --git a/code/frameworks/vue3-webpack5/template/cli/js/Button.vue b/code/frameworks/vue3-webpack5/template/cli/js/Button.vue new file mode 100644 index 00000000000..a831ddf4991 --- /dev/null +++ b/code/frameworks/vue3-webpack5/template/cli/js/Button.vue @@ -0,0 +1,52 @@ + + + diff --git a/code/frameworks/vue3-webpack5/template/cli/js/Header.stories.js b/code/frameworks/vue3-webpack5/template/cli/js/Header.stories.js new file mode 100644 index 00000000000..ca1b5e65bf0 --- /dev/null +++ b/code/frameworks/vue3-webpack5/template/cli/js/Header.stories.js @@ -0,0 +1,48 @@ +import { fn } from 'storybook/test'; + +import MyHeader from './Header.vue'; + +export default { + title: 'Example/Header', + component: MyHeader, + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], + render: (args) => ({ + // Components used in your story `template` are defined in the `components` object + components: { + MyHeader, + }, + // The story's `args` need to be mapped into the template through the `setup()` method + setup() { + // Story args can be spread into the returned object + return { + ...args, + }; + }, + // Then, the spread values can be accessed directly in the template + template: '', + }), + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + layout: 'fullscreen', + }, + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), + }, +}; + +export const LoggedIn = { + args: { + user: { + name: 'Jane Doe', + }, + }, +}; + +export const LoggedOut = { + args: { + user: null, + }, +}; diff --git a/code/frameworks/vue3-webpack5/template/cli/js/Header.vue b/code/frameworks/vue3-webpack5/template/cli/js/Header.vue new file mode 100644 index 00000000000..16d7740d96c --- /dev/null +++ b/code/frameworks/vue3-webpack5/template/cli/js/Header.vue @@ -0,0 +1,59 @@ + + + diff --git a/code/frameworks/vue3-webpack5/template/cli/js/Page.stories.js b/code/frameworks/vue3-webpack5/template/cli/js/Page.stories.js new file mode 100644 index 00000000000..f03db3c7f07 --- /dev/null +++ b/code/frameworks/vue3-webpack5/template/cli/js/Page.stories.js @@ -0,0 +1,34 @@ +import { expect, userEvent, within } from '@storybook/test'; + +import MyPage from './Page.vue'; + +export default { + title: 'Example/Page', + component: MyPage, + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + layout: 'fullscreen', + }, +}; + +export const LoggedOut = {}; + +// More on component testing: https://storybook.js.org/docs/writing-tests/component-testing +export const LoggedIn = { + render: () => ({ + components: { + MyPage, + }, + template: '', + }), + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const loginButton = canvas.getByRole('button', { name: /Log in/i }); + await expect(loginButton).toBeInTheDocument(); + await userEvent.click(loginButton); + await expect(loginButton).not.toBeInTheDocument(); + + const logoutButton = canvas.getByRole('button', { name: /Log out/i }); + await expect(logoutButton).toBeInTheDocument(); + }, +}; diff --git a/code/frameworks/vue3-webpack5/template/cli/js/Page.vue b/code/frameworks/vue3-webpack5/template/cli/js/Page.vue new file mode 100644 index 00000000000..245401b72c4 --- /dev/null +++ b/code/frameworks/vue3-webpack5/template/cli/js/Page.vue @@ -0,0 +1,83 @@ + + + diff --git a/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Button.stories.ts b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Button.stories.ts new file mode 100644 index 00000000000..73deaf7ecc0 --- /dev/null +++ b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Button.stories.ts @@ -0,0 +1,57 @@ +import type { Meta, StoryObj } from '@storybook/vue3-webpack5'; + +import { fn } from 'storybook/test'; + +import Button from './Button.vue'; + +// More on how to set up stories at: https://storybook.js.org/docs/writing-stories +const meta = { + title: 'Example/Button', + component: Button, + // This component will have an automatically generated docsPage entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], + argTypes: { + size: { control: 'select', options: ['small', 'medium', 'large'] }, + backgroundColor: { control: 'color' }, + }, + args: { + primary: false, + // Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args + onClick: fn(), + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; +/* + *👇 Render functions are a framework specific feature to allow you control on how the component renders. + * See https://storybook.js.org/docs/api/csf + * to learn how to use render functions. + */ +export const Primary: Story = { + args: { + primary: true, + label: 'Button', + }, +}; + +export const Secondary: Story = { + args: { + primary: false, + label: 'Button', + }, +}; + +export const Large: Story = { + args: { + label: 'Button', + size: 'large', + }, +}; + +export const Small: Story = { + args: { + label: 'Button', + size: 'small', + }, +}; diff --git a/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Button.vue b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Button.vue new file mode 100644 index 00000000000..2e1ee0ee22f --- /dev/null +++ b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Button.vue @@ -0,0 +1,48 @@ + + + \ No newline at end of file diff --git a/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Header.stories.ts b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Header.stories.ts new file mode 100644 index 00000000000..5826d501c98 --- /dev/null +++ b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Header.stories.ts @@ -0,0 +1,49 @@ +import type { Meta, StoryObj } from '@storybook/vue3-webpack5'; + +import { fn } from 'storybook/test'; + +import MyHeader from './Header.vue'; + +const meta = { + /* 👇 The title prop is optional. + * See https://storybook.js.org/docs/configure/#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'Example/Header', + component: MyHeader, + render: (args: any) => ({ + components: { MyHeader }, + setup() { + return { args }; + }, + template: '', + }), + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + layout: 'fullscreen', + }, + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), + }, + // This component will have an automatically generated docsPage entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const LoggedIn: Story = { + args: { + user: { + name: 'Jane Doe', + }, + }, +}; + +export const LoggedOut: Story = { + args: { + user: null, + }, +}; diff --git a/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Header.vue b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Header.vue new file mode 100644 index 00000000000..b716db02b3f --- /dev/null +++ b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Header.vue @@ -0,0 +1,37 @@ + + + + diff --git a/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Page.stories.ts b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Page.stories.ts new file mode 100644 index 00000000000..dfc690f896c --- /dev/null +++ b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Page.stories.ts @@ -0,0 +1,39 @@ +import { expect, userEvent, within } from '@storybook/test'; + +import type { Meta, StoryObj } from '@storybook/vue3-webpack5'; + +import MyPage from './Page.vue'; + +const meta = { + title: 'Example/Page', + component: MyPage, + render: () => ({ + components: { MyPage }, + template: '', + }), + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + layout: 'fullscreen', + }, + // This component will have an automatically generated docsPage entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +// More on component testing: https://storybook.js.org/docs/writing-tests/component-testing +export const LoggedIn: Story = { + play: async ({ canvasElement }: any) => { + const canvas = within(canvasElement); + const loginButton = canvas.getByRole('button', { name: /Log in/i }); + await expect(loginButton).toBeInTheDocument(); + await userEvent.click(loginButton); + await expect(loginButton).not.toBeInTheDocument(); + + const logoutButton = canvas.getByRole('button', { name: /Log out/i }); + await expect(logoutButton).toBeInTheDocument(); + }, +}; + +export const LoggedOut: Story = {}; diff --git a/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Page.vue b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Page.vue new file mode 100644 index 00000000000..6a6e5eb1a4a --- /dev/null +++ b/code/frameworks/vue3-webpack5/template/cli/ts-4-9/Page.vue @@ -0,0 +1,73 @@ + + + diff --git a/code/frameworks/web-components-vite/package.json b/code/frameworks/web-components-vite/package.json index 07fc28902e9..f7c3b6b697a 100644 --- a/code/frameworks/web-components-vite/package.json +++ b/code/frameworks/web-components-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/web-components-vite", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for web-components and Vite: Develop Web Components in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -43,6 +43,7 @@ "types": "dist/index.d.ts", "files": [ "dist/**/*", + "template/**/*", "README.md", "*.js", "*.d.ts", diff --git a/code/frameworks/web-components-vite/src/index.ts b/code/frameworks/web-components-vite/src/index.ts index fcb073fefcd..538d3b3a6d6 100644 --- a/code/frameworks/web-components-vite/src/index.ts +++ b/code/frameworks/web-components-vite/src/index.ts @@ -1 +1,2 @@ +export * from '@storybook/web-components'; export * from './types'; diff --git a/code/frameworks/web-components-vite/template/cli/.eslintrc.json b/code/frameworks/web-components-vite/template/cli/.eslintrc.json new file mode 100644 index 00000000000..40ece4a0aa1 --- /dev/null +++ b/code/frameworks/web-components-vite/template/cli/.eslintrc.json @@ -0,0 +1,5 @@ +{ + "rules": { + "import/extensions": "off" + } +} diff --git a/code/frameworks/web-components-vite/template/cli/js/Button.js b/code/frameworks/web-components-vite/template/cli/js/Button.js new file mode 100644 index 00000000000..6cbe804eb1b --- /dev/null +++ b/code/frameworks/web-components-vite/template/cli/js/Button.js @@ -0,0 +1,20 @@ +import { html } from 'lit'; +import { styleMap } from 'lit/directives/style-map.js'; + +import './button.css'; + +/** Primary UI component for user interaction */ +export const Button = ({ primary, backgroundColor = null, size, label, onClick }) => { + const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary'; + + return html` + + `; +}; diff --git a/code/frameworks/web-components-vite/template/cli/js/Button.stories.js b/code/frameworks/web-components-vite/template/cli/js/Button.stories.js new file mode 100644 index 00000000000..9efdf07ece3 --- /dev/null +++ b/code/frameworks/web-components-vite/template/cli/js/Button.stories.js @@ -0,0 +1,46 @@ +import { fn } from 'storybook/test'; + +import { Button } from './Button'; + +// More on how to set up stories at: https://storybook.js.org/docs/writing-stories +export default { + title: 'Example/Button', + tags: ['autodocs'], + render: (args) => Button(args), + argTypes: { + backgroundColor: { control: 'color' }, + size: { + control: { type: 'select' }, + options: ['small', 'medium', 'large'], + }, + }, + args: { onClick: fn() }, +}; + +// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args +export const Primary = { + args: { + primary: true, + label: 'Button', + }, +}; + +export const Secondary = { + args: { + label: 'Button', + }, +}; + +export const Large = { + args: { + size: 'large', + label: 'Button', + }, +}; + +export const Small = { + args: { + size: 'small', + label: 'Button', + }, +}; diff --git a/code/frameworks/web-components-vite/template/cli/js/Header.js b/code/frameworks/web-components-vite/template/cli/js/Header.js new file mode 100644 index 00000000000..19fea63604a --- /dev/null +++ b/code/frameworks/web-components-vite/template/cli/js/Header.js @@ -0,0 +1,45 @@ +import { html } from 'lit'; + +import { Button } from './Button'; +import './header.css'; + +export const Header = ({ user, onLogin, onLogout, onCreateAccount }) => html` +
+
+
+ + + + + + + +

Acme

+
+
+ ${user + ? Button({ size: 'small', onClick: onLogout, label: 'Log out' }) + : html`${Button({ + size: 'small', + onClick: onLogin, + label: 'Log in', + })} + ${Button({ + primary: true, + size: 'small', + onClick: onCreateAccount, + label: 'Sign up', + })}`} +
+
+
+`; diff --git a/code/frameworks/web-components-vite/template/cli/js/Header.stories.js b/code/frameworks/web-components-vite/template/cli/js/Header.stories.js new file mode 100644 index 00000000000..b45ba68c5a8 --- /dev/null +++ b/code/frameworks/web-components-vite/template/cli/js/Header.stories.js @@ -0,0 +1,24 @@ +import { fn } from 'storybook/test'; + +import { Header } from './Header'; + +export default { + title: 'Example/Header', + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/web-components/vue/writing-docs/autodocs + tags: ['autodocs'], + render: (args) => Header(args), + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), + }, +}; +export const LoggedIn = { + args: { + user: { + name: 'Jane Doe', + }, + }, +}; + +export const LoggedOut = {}; diff --git a/code/frameworks/web-components-vite/template/cli/js/Page.js b/code/frameworks/web-components-vite/template/cli/js/Page.js new file mode 100644 index 00000000000..54919dabd48 --- /dev/null +++ b/code/frameworks/web-components-vite/template/cli/js/Page.js @@ -0,0 +1,62 @@ +import { html } from 'lit'; + +import { Header } from './Header'; +import './page.css'; + +export const Page = ({ user, onLogin, onLogout, onCreateAccount }) => html` +
+ ${Header({ + user, + onLogin, + onLogout, + onCreateAccount, + })} + +
+

Pages in Storybook

+

+ We recommend building UIs with a + + component-driven process starting with atomic components and ending with pages. +

+

+ Render pages with mock data. This makes it easy to build and review page states without + needing to navigate to them in your app. Here are some handy patterns for managing page data + in Storybook: +

+
    +
  • + Use a higher-level connected component. Storybook helps you compose such data from the + "args" of child component stories +
  • +
  • + Assemble data in the page component from your services. You can mock these services out + using Storybook. +
  • +
+

+ Get a guided tutorial on component-driven development at + + Storybook tutorials + + . Read more in the + docs + . +

+
+ Tip Adjust the width of the canvas with the + + + + + + Viewports addon in the toolbar +
+
+
+`; diff --git a/code/frameworks/web-components-vite/template/cli/js/Page.stories.js b/code/frameworks/web-components-vite/template/cli/js/Page.stories.js new file mode 100644 index 00000000000..7c28c5ad14b --- /dev/null +++ b/code/frameworks/web-components-vite/template/cli/js/Page.stories.js @@ -0,0 +1,20 @@ +import * as HeaderStories from './Header.stories'; +import { Page } from './Page'; + +export default { + title: 'Example/Page', + render: (args) => Page(args), +}; + +export const LoggedIn = { + args: { + // More on composing args: https://storybook.js.org/docs/writing-stories/args#args-composition + ...HeaderStories.LoggedIn.args, + }, +}; + +export const LoggedOut = { + args: { + ...HeaderStories.LoggedOut.args, + }, +}; diff --git a/code/frameworks/web-components-vite/template/cli/ts-4-9/Button.stories.ts b/code/frameworks/web-components-vite/template/cli/ts-4-9/Button.stories.ts new file mode 100644 index 00000000000..8b595baddc2 --- /dev/null +++ b/code/frameworks/web-components-vite/template/cli/ts-4-9/Button.stories.ts @@ -0,0 +1,52 @@ +import type { Meta, StoryObj } from '@storybook/web-components-vite'; + +import { fn } from 'storybook/test'; + +import type { ButtonProps } from './Button'; +import { Button } from './Button'; + +// More on how to set up stories at: https://storybook.js.org/docs/writing-stories +const meta = { + title: 'Example/Button', + tags: ['autodocs'], + render: (args) => Button(args), + argTypes: { + backgroundColor: { control: 'color' }, + size: { + control: { type: 'select' }, + options: ['small', 'medium', 'large'], + }, + }, + args: { onClick: fn() }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args +export const Primary: Story = { + args: { + primary: true, + label: 'Button', + }, +}; + +export const Secondary: Story = { + args: { + label: 'Button', + }, +}; + +export const Large: Story = { + args: { + size: 'large', + label: 'Button', + }, +}; + +export const Small: Story = { + args: { + size: 'small', + label: 'Button', + }, +}; diff --git a/code/frameworks/web-components-vite/template/cli/ts-4-9/Button.ts b/code/frameworks/web-components-vite/template/cli/ts-4-9/Button.ts new file mode 100644 index 00000000000..4ca7fe4a723 --- /dev/null +++ b/code/frameworks/web-components-vite/template/cli/ts-4-9/Button.ts @@ -0,0 +1,32 @@ +import { html } from 'lit'; +import { styleMap } from 'lit/directives/style-map.js'; + +import './button.css'; + +export interface ButtonProps { + /** Is this the principal call to action on the page? */ + primary?: boolean; + /** What background color to use */ + backgroundColor?: string; + /** How large should the button be? */ + size?: 'small' | 'medium' | 'large'; + /** Button contents */ + label: string; + /** Optional click handler */ + onClick?: () => void; +} +/** Primary UI component for user interaction */ +export const Button = ({ primary, backgroundColor, size, label, onClick }: ButtonProps) => { + const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary'; + + return html` + + `; +}; diff --git a/code/frameworks/web-components-vite/template/cli/ts-4-9/Header.stories.ts b/code/frameworks/web-components-vite/template/cli/ts-4-9/Header.stories.ts new file mode 100644 index 00000000000..b2f7d90ce37 --- /dev/null +++ b/code/frameworks/web-components-vite/template/cli/ts-4-9/Header.stories.ts @@ -0,0 +1,31 @@ +import type { Meta, StoryObj } from '@storybook/web-components-vite'; + +import { fn } from 'storybook/test'; + +import type { HeaderProps } from './Header'; +import { Header } from './Header'; + +const meta = { + title: 'Example/Header', + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], + render: (args: HeaderProps) => Header(args), + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const LoggedIn: Story = { + args: { + user: { + name: 'Jane Doe', + }, + }, +}; + +export const LoggedOut: Story = {}; diff --git a/code/frameworks/web-components-vite/template/cli/ts-4-9/Header.ts b/code/frameworks/web-components-vite/template/cli/ts-4-9/Header.ts new file mode 100644 index 00000000000..7c3c8b89375 --- /dev/null +++ b/code/frameworks/web-components-vite/template/cli/ts-4-9/Header.ts @@ -0,0 +1,56 @@ +import { html } from 'lit'; + +import { Button } from './Button'; +import './header.css'; + +type User = { + name: string; +}; + +export interface HeaderProps { + user?: User; + onLogin?: () => void; + onLogout?: () => void; + onCreateAccount?: () => void; +} + +export const Header = ({ user, onLogin, onLogout, onCreateAccount }: HeaderProps) => html` +
+
+
+ + + + + + + +

Acme

+
+
+ ${user + ? Button({ size: 'small', onClick: onLogout, label: 'Log out' }) + : html`${Button({ + size: 'small', + onClick: onLogin, + label: 'Log in', + })} + ${Button({ + primary: true, + size: 'small', + onClick: onCreateAccount, + label: 'Sign up', + })}`} +
+
+
+`; diff --git a/code/frameworks/web-components-vite/template/cli/ts-4-9/Page.stories.ts b/code/frameworks/web-components-vite/template/cli/ts-4-9/Page.stories.ts new file mode 100644 index 00000000000..57505c5f694 --- /dev/null +++ b/code/frameworks/web-components-vite/template/cli/ts-4-9/Page.stories.ts @@ -0,0 +1,26 @@ +import type { Meta, StoryObj } from '@storybook/web-components-vite'; + +import * as HeaderStories from './Header.stories'; +import type { PageProps } from './Page'; +import { Page } from './Page'; + +const meta = { + title: 'Example/Page', + render: (args: PageProps) => Page(args), +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const LoggedIn: Story = { + args: { + // More on composing args: https://storybook.js.org/docs/writing-stories/args#args-composition + ...HeaderStories.LoggedIn.args, + }, +}; + +export const LoggedOut: Story = { + args: { + ...HeaderStories.LoggedOut.args, + }, +}; diff --git a/code/frameworks/web-components-vite/template/cli/ts-4-9/Page.ts b/code/frameworks/web-components-vite/template/cli/ts-4-9/Page.ts new file mode 100644 index 00000000000..079c4f04cfb --- /dev/null +++ b/code/frameworks/web-components-vite/template/cli/ts-4-9/Page.ts @@ -0,0 +1,73 @@ +import { html } from 'lit'; + +import { Header } from './Header'; +import './page.css'; + +type User = { + name: string; +}; + +export interface PageProps { + user?: User; + onLogin?: () => void; + onLogout?: () => void; + onCreateAccount?: () => void; +} + +export const Page = ({ user, onLogin, onLogout, onCreateAccount }: PageProps) => html` +
+ ${Header({ + user, + onLogin, + onLogout, + onCreateAccount, + })} + +
+

Pages in Storybook

+

+ We recommend building UIs with a + + component-driven process starting with atomic components and ending with pages. +

+

+ Render pages with mock data. This makes it easy to build and review page states without + needing to navigate to them in your app. Here are some handy patterns for managing page data + in Storybook: +

+
    +
  • + Use a higher-level connected component. Storybook helps you compose such data from the + "args" of child component stories +
  • +
  • + Assemble data in the page component from your services. You can mock these services out + using Storybook. +
  • +
+

+ Get a guided tutorial on component-driven development at + + Storybook tutorials + + . Read more in the + docs + . +

+
+ Tip Adjust the width of the canvas with the + + + + + + Viewports addon in the toolbar +
+
+
+`; diff --git a/code/frameworks/web-components-webpack5/package.json b/code/frameworks/web-components-webpack5/package.json index 2e31f45b943..d78e57f1d5d 100644 --- a/code/frameworks/web-components-webpack5/package.json +++ b/code/frameworks/web-components-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/web-components-webpack5", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for web-components: View web components snippets in isolation with Hot Reloading.", "keywords": [ "lit", @@ -46,6 +46,7 @@ "types": "dist/index.d.ts", "files": [ "dist/**/*", + "template/**/*", "README.md", "*.js", "*.d.ts", diff --git a/code/frameworks/web-components-webpack5/src/index.ts b/code/frameworks/web-components-webpack5/src/index.ts index fcb073fefcd..538d3b3a6d6 100644 --- a/code/frameworks/web-components-webpack5/src/index.ts +++ b/code/frameworks/web-components-webpack5/src/index.ts @@ -1 +1,2 @@ +export * from '@storybook/web-components'; export * from './types'; diff --git a/code/frameworks/web-components-webpack5/template/cli/.eslintrc.json b/code/frameworks/web-components-webpack5/template/cli/.eslintrc.json new file mode 100644 index 00000000000..40ece4a0aa1 --- /dev/null +++ b/code/frameworks/web-components-webpack5/template/cli/.eslintrc.json @@ -0,0 +1,5 @@ +{ + "rules": { + "import/extensions": "off" + } +} diff --git a/code/frameworks/web-components-webpack5/template/cli/js/Button.js b/code/frameworks/web-components-webpack5/template/cli/js/Button.js new file mode 100644 index 00000000000..6cbe804eb1b --- /dev/null +++ b/code/frameworks/web-components-webpack5/template/cli/js/Button.js @@ -0,0 +1,20 @@ +import { html } from 'lit'; +import { styleMap } from 'lit/directives/style-map.js'; + +import './button.css'; + +/** Primary UI component for user interaction */ +export const Button = ({ primary, backgroundColor = null, size, label, onClick }) => { + const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary'; + + return html` + + `; +}; diff --git a/code/frameworks/web-components-webpack5/template/cli/js/Button.stories.js b/code/frameworks/web-components-webpack5/template/cli/js/Button.stories.js new file mode 100644 index 00000000000..9efdf07ece3 --- /dev/null +++ b/code/frameworks/web-components-webpack5/template/cli/js/Button.stories.js @@ -0,0 +1,46 @@ +import { fn } from 'storybook/test'; + +import { Button } from './Button'; + +// More on how to set up stories at: https://storybook.js.org/docs/writing-stories +export default { + title: 'Example/Button', + tags: ['autodocs'], + render: (args) => Button(args), + argTypes: { + backgroundColor: { control: 'color' }, + size: { + control: { type: 'select' }, + options: ['small', 'medium', 'large'], + }, + }, + args: { onClick: fn() }, +}; + +// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args +export const Primary = { + args: { + primary: true, + label: 'Button', + }, +}; + +export const Secondary = { + args: { + label: 'Button', + }, +}; + +export const Large = { + args: { + size: 'large', + label: 'Button', + }, +}; + +export const Small = { + args: { + size: 'small', + label: 'Button', + }, +}; diff --git a/code/frameworks/web-components-webpack5/template/cli/js/Header.js b/code/frameworks/web-components-webpack5/template/cli/js/Header.js new file mode 100644 index 00000000000..19fea63604a --- /dev/null +++ b/code/frameworks/web-components-webpack5/template/cli/js/Header.js @@ -0,0 +1,45 @@ +import { html } from 'lit'; + +import { Button } from './Button'; +import './header.css'; + +export const Header = ({ user, onLogin, onLogout, onCreateAccount }) => html` +
+
+
+ + + + + + + +

Acme

+
+
+ ${user + ? Button({ size: 'small', onClick: onLogout, label: 'Log out' }) + : html`${Button({ + size: 'small', + onClick: onLogin, + label: 'Log in', + })} + ${Button({ + primary: true, + size: 'small', + onClick: onCreateAccount, + label: 'Sign up', + })}`} +
+
+
+`; diff --git a/code/frameworks/web-components-webpack5/template/cli/js/Header.stories.js b/code/frameworks/web-components-webpack5/template/cli/js/Header.stories.js new file mode 100644 index 00000000000..b45ba68c5a8 --- /dev/null +++ b/code/frameworks/web-components-webpack5/template/cli/js/Header.stories.js @@ -0,0 +1,24 @@ +import { fn } from 'storybook/test'; + +import { Header } from './Header'; + +export default { + title: 'Example/Header', + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/web-components/vue/writing-docs/autodocs + tags: ['autodocs'], + render: (args) => Header(args), + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), + }, +}; +export const LoggedIn = { + args: { + user: { + name: 'Jane Doe', + }, + }, +}; + +export const LoggedOut = {}; diff --git a/code/frameworks/web-components-webpack5/template/cli/js/Page.js b/code/frameworks/web-components-webpack5/template/cli/js/Page.js new file mode 100644 index 00000000000..54919dabd48 --- /dev/null +++ b/code/frameworks/web-components-webpack5/template/cli/js/Page.js @@ -0,0 +1,62 @@ +import { html } from 'lit'; + +import { Header } from './Header'; +import './page.css'; + +export const Page = ({ user, onLogin, onLogout, onCreateAccount }) => html` +
+ ${Header({ + user, + onLogin, + onLogout, + onCreateAccount, + })} + +
+

Pages in Storybook

+

+ We recommend building UIs with a + + component-driven process starting with atomic components and ending with pages. +

+

+ Render pages with mock data. This makes it easy to build and review page states without + needing to navigate to them in your app. Here are some handy patterns for managing page data + in Storybook: +

+
    +
  • + Use a higher-level connected component. Storybook helps you compose such data from the + "args" of child component stories +
  • +
  • + Assemble data in the page component from your services. You can mock these services out + using Storybook. +
  • +
+

+ Get a guided tutorial on component-driven development at + + Storybook tutorials + + . Read more in the + docs + . +

+
+ Tip Adjust the width of the canvas with the + + + + + + Viewports addon in the toolbar +
+
+
+`; diff --git a/code/frameworks/web-components-webpack5/template/cli/js/Page.stories.js b/code/frameworks/web-components-webpack5/template/cli/js/Page.stories.js new file mode 100644 index 00000000000..7c28c5ad14b --- /dev/null +++ b/code/frameworks/web-components-webpack5/template/cli/js/Page.stories.js @@ -0,0 +1,20 @@ +import * as HeaderStories from './Header.stories'; +import { Page } from './Page'; + +export default { + title: 'Example/Page', + render: (args) => Page(args), +}; + +export const LoggedIn = { + args: { + // More on composing args: https://storybook.js.org/docs/writing-stories/args#args-composition + ...HeaderStories.LoggedIn.args, + }, +}; + +export const LoggedOut = { + args: { + ...HeaderStories.LoggedOut.args, + }, +}; diff --git a/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Button.stories.ts b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Button.stories.ts new file mode 100644 index 00000000000..e3085252e4b --- /dev/null +++ b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Button.stories.ts @@ -0,0 +1,52 @@ +import type { Meta, StoryObj } from '@storybook/web-components-webpack5'; + +import { fn } from 'storybook/test'; + +import type { ButtonProps } from './Button'; +import { Button } from './Button'; + +// More on how to set up stories at: https://storybook.js.org/docs/writing-stories +const meta = { + title: 'Example/Button', + tags: ['autodocs'], + render: (args) => Button(args), + argTypes: { + backgroundColor: { control: 'color' }, + size: { + control: { type: 'select' }, + options: ['small', 'medium', 'large'], + }, + }, + args: { onClick: fn() }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args +export const Primary: Story = { + args: { + primary: true, + label: 'Button', + }, +}; + +export const Secondary: Story = { + args: { + label: 'Button', + }, +}; + +export const Large: Story = { + args: { + size: 'large', + label: 'Button', + }, +}; + +export const Small: Story = { + args: { + size: 'small', + label: 'Button', + }, +}; diff --git a/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Button.ts b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Button.ts new file mode 100644 index 00000000000..4ca7fe4a723 --- /dev/null +++ b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Button.ts @@ -0,0 +1,32 @@ +import { html } from 'lit'; +import { styleMap } from 'lit/directives/style-map.js'; + +import './button.css'; + +export interface ButtonProps { + /** Is this the principal call to action on the page? */ + primary?: boolean; + /** What background color to use */ + backgroundColor?: string; + /** How large should the button be? */ + size?: 'small' | 'medium' | 'large'; + /** Button contents */ + label: string; + /** Optional click handler */ + onClick?: () => void; +} +/** Primary UI component for user interaction */ +export const Button = ({ primary, backgroundColor, size, label, onClick }: ButtonProps) => { + const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary'; + + return html` + + `; +}; diff --git a/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Header.stories.ts b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Header.stories.ts new file mode 100644 index 00000000000..9564aa90e73 --- /dev/null +++ b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Header.stories.ts @@ -0,0 +1,31 @@ +import type { Meta, StoryObj } from '@storybook/web-components-webpack5'; + +import { fn } from 'storybook/test'; + +import type { HeaderProps } from './Header'; +import { Header } from './Header'; + +const meta = { + title: 'Example/Header', + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], + render: (args: HeaderProps) => Header(args), + args: { + onLogin: fn(), + onLogout: fn(), + onCreateAccount: fn(), + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const LoggedIn: Story = { + args: { + user: { + name: 'Jane Doe', + }, + }, +}; + +export const LoggedOut: Story = {}; diff --git a/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Header.ts b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Header.ts new file mode 100644 index 00000000000..7c3c8b89375 --- /dev/null +++ b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Header.ts @@ -0,0 +1,56 @@ +import { html } from 'lit'; + +import { Button } from './Button'; +import './header.css'; + +type User = { + name: string; +}; + +export interface HeaderProps { + user?: User; + onLogin?: () => void; + onLogout?: () => void; + onCreateAccount?: () => void; +} + +export const Header = ({ user, onLogin, onLogout, onCreateAccount }: HeaderProps) => html` +
+
+
+ + + + + + + +

Acme

+
+
+ ${user + ? Button({ size: 'small', onClick: onLogout, label: 'Log out' }) + : html`${Button({ + size: 'small', + onClick: onLogin, + label: 'Log in', + })} + ${Button({ + primary: true, + size: 'small', + onClick: onCreateAccount, + label: 'Sign up', + })}`} +
+
+
+`; diff --git a/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Page.stories.ts b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Page.stories.ts new file mode 100644 index 00000000000..51ba30dfaae --- /dev/null +++ b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Page.stories.ts @@ -0,0 +1,26 @@ +import type { Meta, StoryObj } from '@storybook/web-components-webpack5'; + +import * as HeaderStories from './Header.stories'; +import type { PageProps } from './Page'; +import { Page } from './Page'; + +const meta = { + title: 'Example/Page', + render: (args: PageProps) => Page(args), +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const LoggedIn: Story = { + args: { + // More on composing args: https://storybook.js.org/docs/writing-stories/args#args-composition + ...HeaderStories.LoggedIn.args, + }, +}; + +export const LoggedOut: Story = { + args: { + ...HeaderStories.LoggedOut.args, + }, +}; diff --git a/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Page.ts b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Page.ts new file mode 100644 index 00000000000..079c4f04cfb --- /dev/null +++ b/code/frameworks/web-components-webpack5/template/cli/ts-4-9/Page.ts @@ -0,0 +1,73 @@ +import { html } from 'lit'; + +import { Header } from './Header'; +import './page.css'; + +type User = { + name: string; +}; + +export interface PageProps { + user?: User; + onLogin?: () => void; + onLogout?: () => void; + onCreateAccount?: () => void; +} + +export const Page = ({ user, onLogin, onLogout, onCreateAccount }: PageProps) => html` +
+ ${Header({ + user, + onLogin, + onLogout, + onCreateAccount, + })} + +
+

Pages in Storybook

+

+ We recommend building UIs with a + + component-driven process starting with atomic components and ending with pages. +

+

+ Render pages with mock data. This makes it easy to build and review page states without + needing to navigate to them in your app. Here are some handy patterns for managing page data + in Storybook: +

+
    +
  • + Use a higher-level connected component. Storybook helps you compose such data from the + "args" of child component stories +
  • +
  • + Assemble data in the page component from your services. You can mock these services out + using Storybook. +
  • +
+

+ Get a guided tutorial on component-driven development at + + Storybook tutorials + + . Read more in the + docs + . +

+
+ Tip Adjust the width of the canvas with the + + + + + + Viewports addon in the toolbar +
+
+
+`; diff --git a/code/lib/blocks/package.json b/code/lib/blocks/package.json index 239d9850ad2..0da3e3f5834 100644 --- a/code/lib/blocks/package.json +++ b/code/lib/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/blocks", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook Doc Blocks", "keywords": [ "storybook" @@ -49,7 +49,6 @@ "devDependencies": { "@storybook/addon-actions": "workspace:*", "@storybook/react": "workspace:*", - "@storybook/test": "workspace:*", "@types/color-convert": "^2.0.0", "color-convert": "^2.0.1", "es-toolkit": "^1.22.0", diff --git a/code/lib/blocks/src/blocks/Anchor.stories.tsx b/code/lib/blocks/src/blocks/Anchor.stories.tsx index 276c5aa2219..262af3d7703 100644 --- a/code/lib/blocks/src/blocks/Anchor.stories.tsx +++ b/code/lib/blocks/src/blocks/Anchor.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { Anchor } from './Anchor'; diff --git a/code/lib/blocks/src/blocks/ArgTypes.stories.tsx b/code/lib/blocks/src/blocks/ArgTypes.stories.tsx index 7738bde257e..4a17e355d87 100644 --- a/code/lib/blocks/src/blocks/ArgTypes.stories.tsx +++ b/code/lib/blocks/src/blocks/ArgTypes.stories.tsx @@ -2,8 +2,9 @@ import React from 'react'; import type { PlayFunctionContext } from 'storybook/internal/csf'; -import type { Meta, StoryObj } from '@storybook/react'; -import { within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { within } from 'storybook/test'; import * as ExampleStories from '../examples/ArgTypesParameters.stories'; import * as SubcomponentsExampleStories from '../examples/ArgTypesWithSubcomponentsParameters.stories'; diff --git a/code/lib/blocks/src/blocks/Canvas.stories.tsx b/code/lib/blocks/src/blocks/Canvas.stories.tsx index 987e28678a7..befddeebd0a 100644 --- a/code/lib/blocks/src/blocks/Canvas.stories.tsx +++ b/code/lib/blocks/src/blocks/Canvas.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { dedent } from 'ts-dedent'; diff --git a/code/lib/blocks/src/blocks/Controls.stories.tsx b/code/lib/blocks/src/blocks/Controls.stories.tsx index 624f03452b8..09e424484c5 100644 --- a/code/lib/blocks/src/blocks/Controls.stories.tsx +++ b/code/lib/blocks/src/blocks/Controls.stories.tsx @@ -2,8 +2,9 @@ import React from 'react'; import type { PlayFunctionContext } from 'storybook/internal/csf'; -import type { Meta, StoryObj } from '@storybook/react'; -import { within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { within } from 'storybook/test'; import * as ExampleStories from '../examples/ControlsParameters.stories'; import * as SubcomponentsExampleStories from '../examples/ControlsWithSubcomponentsParameters.stories'; diff --git a/code/lib/blocks/src/blocks/Description.stories.tsx b/code/lib/blocks/src/blocks/Description.stories.tsx index 9285fd9095f..31bbea23458 100644 --- a/code/lib/blocks/src/blocks/Description.stories.tsx +++ b/code/lib/blocks/src/blocks/Description.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { Button as ButtonComponent } from '../examples/Button'; import * as DefaultButtonStories from '../examples/Button.stories'; diff --git a/code/lib/blocks/src/blocks/DocsPage.stories.tsx b/code/lib/blocks/src/blocks/DocsPage.stories.tsx index 1ed85bfa3ac..31b433f6886 100644 --- a/code/lib/blocks/src/blocks/DocsPage.stories.tsx +++ b/code/lib/blocks/src/blocks/DocsPage.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { DocsPage } from './DocsPage'; diff --git a/code/lib/blocks/src/blocks/Primary.stories.tsx b/code/lib/blocks/src/blocks/Primary.stories.tsx index 6ea9025eac9..39b9123ea72 100644 --- a/code/lib/blocks/src/blocks/Primary.stories.tsx +++ b/code/lib/blocks/src/blocks/Primary.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import * as DefaultButtonStories from '../examples/Button.stories'; import * as StoriesParametersStories from '../examples/StoriesParameters.stories'; diff --git a/code/lib/blocks/src/blocks/Source.stories.tsx b/code/lib/blocks/src/blocks/Source.stories.tsx index 8981289a149..30915ce18af 100644 --- a/code/lib/blocks/src/blocks/Source.stories.tsx +++ b/code/lib/blocks/src/blocks/Source.stories.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { SourceType } from 'storybook/internal/docs-tools'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { dedent } from 'ts-dedent'; diff --git a/code/lib/blocks/src/blocks/Stories.stories.tsx b/code/lib/blocks/src/blocks/Stories.stories.tsx index 017da21c799..98576f0892b 100644 --- a/code/lib/blocks/src/blocks/Stories.stories.tsx +++ b/code/lib/blocks/src/blocks/Stories.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { Stories } from './Stories'; diff --git a/code/lib/blocks/src/blocks/Story.stories.tsx b/code/lib/blocks/src/blocks/Story.stories.tsx index 370262bf0f2..6616b489934 100644 --- a/code/lib/blocks/src/blocks/Story.stories.tsx +++ b/code/lib/blocks/src/blocks/Story.stories.tsx @@ -1,7 +1,8 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, waitFor } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { expect, waitFor } from 'storybook/test'; import * as StoryComponentStories from '../components/Story.stories'; import * as ButtonStories from '../examples/Button.stories'; diff --git a/code/lib/blocks/src/blocks/Subtitle.stories.tsx b/code/lib/blocks/src/blocks/Subtitle.stories.tsx index df1b8ff2fd7..e0e847cd918 100644 --- a/code/lib/blocks/src/blocks/Subtitle.stories.tsx +++ b/code/lib/blocks/src/blocks/Subtitle.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import * as DefaultButtonStories from '../examples/Button.stories'; import * as ButtonStoriesWithMetaSubtitleAsBoth from '../examples/ButtonWithMetaSubtitleAsBoth.stories'; diff --git a/code/lib/blocks/src/blocks/Title.stories.tsx b/code/lib/blocks/src/blocks/Title.stories.tsx index 00ec452971b..7eed0521a0a 100644 --- a/code/lib/blocks/src/blocks/Title.stories.tsx +++ b/code/lib/blocks/src/blocks/Title.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import * as DefaultButtonStories from '../examples/Button.stories'; import { Title } from './Title'; diff --git a/code/lib/blocks/src/components/ArgsTable/ArgsTable.stories.tsx b/code/lib/blocks/src/components/ArgsTable/ArgsTable.stories.tsx index ce83ae7e67e..3cbad6a0e32 100644 --- a/code/lib/blocks/src/components/ArgsTable/ArgsTable.stories.tsx +++ b/code/lib/blocks/src/components/ArgsTable/ArgsTable.stories.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { styled } from 'storybook/internal/theming'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { action } from '@storybook/addon-actions'; diff --git a/code/lib/blocks/src/components/Source.stories.tsx b/code/lib/blocks/src/components/Source.stories.tsx index d7028b920e0..cd2d7ae38bb 100644 --- a/code/lib/blocks/src/components/Source.stories.tsx +++ b/code/lib/blocks/src/components/Source.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { Source, SourceError } from './Source'; diff --git a/code/lib/blocks/src/components/Story.stories.tsx b/code/lib/blocks/src/components/Story.stories.tsx index 09e64a2dd1d..9d3ad8c7591 100644 --- a/code/lib/blocks/src/components/Story.stories.tsx +++ b/code/lib/blocks/src/components/Story.stories.tsx @@ -10,8 +10,9 @@ import type { PlayFunctionContext } from 'storybook/internal/csf'; import type { PreviewWeb } from 'storybook/internal/preview-api'; import type { ModuleExport, WebRenderer } from 'storybook/internal/types'; -import type { Meta, ReactRenderer, StoryObj } from '@storybook/react'; -import { within } from '@storybook/test'; +import type { Meta, ReactRenderer, StoryObj } from '@storybook/react-vite'; + +import { within } from 'storybook/test'; import type { DocsContextProps } from '../blocks'; import * as ButtonStories from '../examples/Button.stories'; diff --git a/code/lib/blocks/src/controls/Boolean.stories.tsx b/code/lib/blocks/src/controls/Boolean.stories.tsx index ad7365c0383..5276f71edb6 100644 --- a/code/lib/blocks/src/controls/Boolean.stories.tsx +++ b/code/lib/blocks/src/controls/Boolean.stories.tsx @@ -1,8 +1,9 @@ import { RESET_STORY_ARGS, STORY_ARGS_UPDATED } from 'storybook/internal/core-events'; import { addons } from 'storybook/internal/preview-api'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, fireEvent, fn, waitFor, within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { expect, fireEvent, fn, waitFor, within } from 'storybook/test'; import { BooleanControl } from './Boolean'; diff --git a/code/lib/blocks/src/controls/Color.stories.tsx b/code/lib/blocks/src/controls/Color.stories.tsx index 8b77cff62f0..867e0d0c5cb 100644 --- a/code/lib/blocks/src/controls/Color.stories.tsx +++ b/code/lib/blocks/src/controls/Color.stories.tsx @@ -1,5 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { fn } from 'storybook/test'; import { ColorControl } from './Color'; diff --git a/code/lib/blocks/src/controls/Date.stories.tsx b/code/lib/blocks/src/controls/Date.stories.tsx index c2fcb33e39b..f8f3200f312 100644 --- a/code/lib/blocks/src/controls/Date.stories.tsx +++ b/code/lib/blocks/src/controls/Date.stories.tsx @@ -1,5 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { fn } from 'storybook/test'; import { DateControl } from './Date'; diff --git a/code/lib/blocks/src/controls/Files.stories.tsx b/code/lib/blocks/src/controls/Files.stories.tsx index 640f954260c..82c8f61eed1 100644 --- a/code/lib/blocks/src/controls/Files.stories.tsx +++ b/code/lib/blocks/src/controls/Files.stories.tsx @@ -1,5 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { fn } from 'storybook/test'; import { FilesControl } from './Files'; diff --git a/code/lib/blocks/src/controls/Number.stories.tsx b/code/lib/blocks/src/controls/Number.stories.tsx index 80bde03aeef..ae5daf07be0 100644 --- a/code/lib/blocks/src/controls/Number.stories.tsx +++ b/code/lib/blocks/src/controls/Number.stories.tsx @@ -1,5 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { fn } from 'storybook/test'; import { NumberControl } from './Number'; diff --git a/code/lib/blocks/src/controls/Object.stories.tsx b/code/lib/blocks/src/controls/Object.stories.tsx index 0929234e3ad..de883570198 100644 --- a/code/lib/blocks/src/controls/Object.stories.tsx +++ b/code/lib/blocks/src/controls/Object.stories.tsx @@ -1,5 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { fn } from 'storybook/test'; import { ObjectControl } from './Object'; diff --git a/code/lib/blocks/src/controls/Range.stories.tsx b/code/lib/blocks/src/controls/Range.stories.tsx index cd8ca20c522..b8464d923c1 100644 --- a/code/lib/blocks/src/controls/Range.stories.tsx +++ b/code/lib/blocks/src/controls/Range.stories.tsx @@ -1,5 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { fn } from 'storybook/test'; import { RangeControl } from './Range'; diff --git a/code/lib/blocks/src/controls/Text.stories.tsx b/code/lib/blocks/src/controls/Text.stories.tsx index 71dee59dc19..e1ce009699f 100644 --- a/code/lib/blocks/src/controls/Text.stories.tsx +++ b/code/lib/blocks/src/controls/Text.stories.tsx @@ -1,5 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { fn } from 'storybook/test'; import { TextControl } from './Text'; diff --git a/code/lib/blocks/src/controls/options/CheckOptions.stories.tsx b/code/lib/blocks/src/controls/options/CheckOptions.stories.tsx index 8e98d88c080..e98ac3cc049 100644 --- a/code/lib/blocks/src/controls/options/CheckOptions.stories.tsx +++ b/code/lib/blocks/src/controls/options/CheckOptions.stories.tsx @@ -1,5 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { fn } from 'storybook/test'; import { OptionsControl } from './Options'; diff --git a/code/lib/blocks/src/controls/options/RadioOptions.stories.tsx b/code/lib/blocks/src/controls/options/RadioOptions.stories.tsx index e96f52b781c..e0a5bb706a4 100644 --- a/code/lib/blocks/src/controls/options/RadioOptions.stories.tsx +++ b/code/lib/blocks/src/controls/options/RadioOptions.stories.tsx @@ -1,5 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { fn } from 'storybook/test'; import { OptionsControl } from './Options'; diff --git a/code/lib/blocks/src/controls/options/SelectOptions.stories.tsx b/code/lib/blocks/src/controls/options/SelectOptions.stories.tsx index 81efc451c7f..71e28da394d 100644 --- a/code/lib/blocks/src/controls/options/SelectOptions.stories.tsx +++ b/code/lib/blocks/src/controls/options/SelectOptions.stories.tsx @@ -1,5 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { fn } from 'storybook/test'; import { OptionsControl } from './Options'; diff --git a/code/lib/blocks/src/examples/ArgTypesParameters.stories.tsx b/code/lib/blocks/src/examples/ArgTypesParameters.stories.tsx index 95fef9f585f..a5660dbfd96 100644 --- a/code/lib/blocks/src/examples/ArgTypesParameters.stories.tsx +++ b/code/lib/blocks/src/examples/ArgTypesParameters.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { ArgTypesParameters } from './ArgTypesParameters'; diff --git a/code/lib/blocks/src/examples/ArgTypesWithSubcomponentsParameters.stories.tsx b/code/lib/blocks/src/examples/ArgTypesWithSubcomponentsParameters.stories.tsx index b6c66a4ae53..24b00efc25d 100644 --- a/code/lib/blocks/src/examples/ArgTypesWithSubcomponentsParameters.stories.tsx +++ b/code/lib/blocks/src/examples/ArgTypesWithSubcomponentsParameters.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { ArgTypesParameters, SubcomponentA, SubcomponentB } from './ArgTypesParameters'; diff --git a/code/lib/blocks/src/examples/Button.stories.tsx b/code/lib/blocks/src/examples/Button.stories.tsx index c22d141f541..8aa24f8a8ed 100644 --- a/code/lib/blocks/src/examples/Button.stories.tsx +++ b/code/lib/blocks/src/examples/Button.stories.tsx @@ -1,8 +1,9 @@ /* eslint-disable local-rules/no-uncategorized-errors */ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; -import { expect, fireEvent, within } from '@storybook/test'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import { expect, fireEvent, within } from 'storybook/test'; import { Button } from './Button'; diff --git a/code/lib/blocks/src/examples/ButtonNoAutodocs.stories.tsx b/code/lib/blocks/src/examples/ButtonNoAutodocs.stories.tsx index 727ba4598ba..ac771a2c43d 100644 --- a/code/lib/blocks/src/examples/ButtonNoAutodocs.stories.tsx +++ b/code/lib/blocks/src/examples/ButtonNoAutodocs.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { Button } from './Button'; diff --git a/code/lib/blocks/src/examples/ButtonReadonly.stories.tsx b/code/lib/blocks/src/examples/ButtonReadonly.stories.tsx index 442f945490b..7fc7bffe26b 100644 --- a/code/lib/blocks/src/examples/ButtonReadonly.stories.tsx +++ b/code/lib/blocks/src/examples/ButtonReadonly.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { Button } from './Button'; diff --git a/code/lib/blocks/src/examples/ButtonSomeAutodocs.stories.tsx b/code/lib/blocks/src/examples/ButtonSomeAutodocs.stories.tsx index fbc06945b97..62e7c8c3721 100644 --- a/code/lib/blocks/src/examples/ButtonSomeAutodocs.stories.tsx +++ b/code/lib/blocks/src/examples/ButtonSomeAutodocs.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { Button } from './Button'; diff --git a/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsBoth.stories.tsx b/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsBoth.stories.tsx index a5515b3ee33..40543373c6e 100644 --- a/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsBoth.stories.tsx +++ b/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsBoth.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { Button } from './Button'; diff --git a/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsComment.stories.tsx b/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsComment.stories.tsx index 95464610b4a..31862be623d 100644 --- a/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsComment.stories.tsx +++ b/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsComment.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { Button } from './Button'; diff --git a/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsParameter.stories.tsx b/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsParameter.stories.tsx index fff71f67e62..bf044d45bac 100644 --- a/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsParameter.stories.tsx +++ b/code/lib/blocks/src/examples/ButtonWithMetaDescriptionAsParameter.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { Button } from './Button'; diff --git a/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsBoth.stories.tsx b/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsBoth.stories.tsx index 6ee3c6c1293..78f6218743b 100644 --- a/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsBoth.stories.tsx +++ b/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsBoth.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { Button } from './Button'; diff --git a/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsComponentSubtitle.stories.tsx b/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsComponentSubtitle.stories.tsx index 9a430f39e81..f67f7c5aeae 100644 --- a/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsComponentSubtitle.stories.tsx +++ b/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsComponentSubtitle.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { Button } from './Button'; diff --git a/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsDocsSubtitle.stories.tsx b/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsDocsSubtitle.stories.tsx index 0ec5ff64c6f..47794cda900 100644 --- a/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsDocsSubtitle.stories.tsx +++ b/code/lib/blocks/src/examples/ButtonWithMetaSubtitleAsDocsSubtitle.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { Button } from './Button'; diff --git a/code/lib/blocks/src/examples/CanvasParameters.stories.tsx b/code/lib/blocks/src/examples/CanvasParameters.stories.tsx index 4d443374749..c286e07e7bb 100644 --- a/code/lib/blocks/src/examples/CanvasParameters.stories.tsx +++ b/code/lib/blocks/src/examples/CanvasParameters.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { EmptyExample } from './EmptyExample'; diff --git a/code/lib/blocks/src/examples/ControlsParameters.stories.tsx b/code/lib/blocks/src/examples/ControlsParameters.stories.tsx index 7684d4f0e02..497c543d728 100644 --- a/code/lib/blocks/src/examples/ControlsParameters.stories.tsx +++ b/code/lib/blocks/src/examples/ControlsParameters.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { ControlsParameters } from './ControlsParameters'; diff --git a/code/lib/blocks/src/examples/ControlsWithSubcomponentsParameters.stories.tsx b/code/lib/blocks/src/examples/ControlsWithSubcomponentsParameters.stories.tsx index bf2e1e77d37..543c55be554 100644 --- a/code/lib/blocks/src/examples/ControlsWithSubcomponentsParameters.stories.tsx +++ b/code/lib/blocks/src/examples/ControlsWithSubcomponentsParameters.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { ControlsParameters, SubcomponentA, SubcomponentB } from './ControlsParameters'; diff --git a/code/lib/blocks/src/examples/DocsPageParameters.stories.tsx b/code/lib/blocks/src/examples/DocsPageParameters.stories.tsx index 91d5b3f3cad..2f52462c6e7 100644 --- a/code/lib/blocks/src/examples/DocsPageParameters.stories.tsx +++ b/code/lib/blocks/src/examples/DocsPageParameters.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { EmptyExample } from './EmptyExample'; diff --git a/code/lib/blocks/src/examples/EmptyArgTypes.stories.tsx b/code/lib/blocks/src/examples/EmptyArgTypes.stories.tsx index 9c596e5def6..ebe717ad91d 100644 --- a/code/lib/blocks/src/examples/EmptyArgTypes.stories.tsx +++ b/code/lib/blocks/src/examples/EmptyArgTypes.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import type { ControlsParameters } from './ControlsParameters'; diff --git a/code/lib/blocks/src/examples/SourceParameters.stories.tsx b/code/lib/blocks/src/examples/SourceParameters.stories.tsx index ee40704a051..cc104367822 100644 --- a/code/lib/blocks/src/examples/SourceParameters.stories.tsx +++ b/code/lib/blocks/src/examples/SourceParameters.stories.tsx @@ -1,7 +1,7 @@ import { SourceType } from 'storybook/internal/docs-tools'; import type { StoryContext } from 'storybook/internal/types'; -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { dedent } from 'ts-dedent'; diff --git a/code/lib/blocks/src/examples/StoriesParameters.stories.tsx b/code/lib/blocks/src/examples/StoriesParameters.stories.tsx index 731291ad75f..74b397ee4b6 100644 --- a/code/lib/blocks/src/examples/StoriesParameters.stories.tsx +++ b/code/lib/blocks/src/examples/StoriesParameters.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { EmptyExample } from './EmptyExample'; diff --git a/code/lib/blocks/src/examples/StoryParameters.stories.tsx b/code/lib/blocks/src/examples/StoryParameters.stories.tsx index 79c8dcb7bdc..2280656b0b4 100644 --- a/code/lib/blocks/src/examples/StoryParameters.stories.tsx +++ b/code/lib/blocks/src/examples/StoryParameters.stories.tsx @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryObj } from '@storybook/react-vite'; import { SimpleSizeTest } from './SimpleSizeTest'; diff --git a/code/lib/cli-sb/package.json b/code/lib/cli-sb/package.json index 42099db21c6..5f6252f09af 100644 --- a/code/lib/cli-sb/package.json +++ b/code/lib/cli-sb/package.json @@ -1,6 +1,6 @@ { "name": "sb", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook CLI", "keywords": [ "storybook" diff --git a/code/lib/cli-storybook/package.json b/code/lib/cli-storybook/package.json index fc51868416f..072811e46fa 100644 --- a/code/lib/cli-storybook/package.json +++ b/code/lib/cli-storybook/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/cli", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook CLI", "keywords": [ "storybook" diff --git a/code/lib/cli-storybook/src/autoblock/block-storystorev6.ts b/code/lib/cli-storybook/src/autoblock/block-storystorev6.ts index 9d28b8d15a0..83cff982ef9 100644 --- a/code/lib/cli-storybook/src/autoblock/block-storystorev6.ts +++ b/code/lib/cli-storybook/src/autoblock/block-storystorev6.ts @@ -28,7 +28,7 @@ export const blocker = createBlocker({ In your Storybook configuration we found storyStoreV7 feature defined. For instance: - export default = { + export default { features: { ${picocolors.cyan(`storyStoreV7: false`)}, <--- ${picocolors.bold('remove this line')} }, diff --git a/code/lib/cli-storybook/src/automigrate/fixes/addon-a11y-addon-test.ts b/code/lib/cli-storybook/src/automigrate/fixes/addon-a11y-addon-test.ts index 41d58bc46a7..d54bd76733a 100644 --- a/code/lib/cli-storybook/src/automigrate/fixes/addon-a11y-addon-test.ts +++ b/code/lib/cli-storybook/src/automigrate/fixes/addon-a11y-addon-test.ts @@ -8,7 +8,7 @@ import path from 'path'; import picocolors from 'picocolors'; import { dedent } from 'ts-dedent'; -// Relative path import to avoid dependency to @storybook/test +// Relative path import to avoid dependency to storybook/test import { SUPPORTED_FRAMEWORKS, SUPPORTED_RENDERERS, diff --git a/code/lib/cli-storybook/src/automigrate/fixes/consolidated-imports.test.ts b/code/lib/cli-storybook/src/automigrate/fixes/consolidated-imports.test.ts new file mode 100644 index 00000000000..a7f0c5cbee4 --- /dev/null +++ b/code/lib/cli-storybook/src/automigrate/fixes/consolidated-imports.test.ts @@ -0,0 +1,298 @@ +import { readFile, writeFile } from 'node:fs/promises'; +import { join } from 'node:path'; + +import { describe, expect, it, vi } from 'vitest'; + +import { dedent } from 'ts-dedent'; + +import { + consolidatedImports, + transformImportFiles, + transformPackageJsonFiles, +} from './consolidated-imports'; + +vi.mock('node:fs/promises'); +vi.mock('globby', () => ({ + globby: vi.fn(), +})); + +const mockPackageJson = { + dependencies: { + '@storybook/react': '^7.0.0', + '@storybook/core-common': '^7.0.0', + react: '^18.0.0', + }, + devDependencies: { + '@storybook/addon-essentials': '^7.0.0', + '@storybook/manager-api': '^7.0.0', + typescript: '^5.0.0', + }, +}; + +const mockRunOptions = { + packageManager: { + retrievePackageJson: async () => mockPackageJson, + } as any, + mainConfig: {} as any, + mainConfigPath: 'main.ts', + packageJson: mockPackageJson, +}; + +const setupGlobby = async (files: string[]) => { + // eslint-disable-next-line depend/ban-dependencies + const { globby } = await import('globby'); + vi.mocked(globby).mockResolvedValueOnce(files); +}; + +const setupCheck = async (packageJsonContents: string, packageJsonFiles: string[]) => { + vi.mocked(readFile).mockImplementation(async (path: any) => { + const filePath = path.toString(); + if (filePath.endsWith('package.json')) { + return packageJsonContents; + } + return ''; + }); + await setupGlobby(packageJsonFiles); + + return consolidatedImports.check({ + ...mockRunOptions, + storybookVersion: '8.0.0', + }); +}; + +describe('check', () => { + it('should call globby with correct patterns for package.json files', async () => { + const filePath = 'test/package.json'; + const contents = JSON.stringify(mockPackageJson); + + await setupCheck(contents, [filePath]); + + // eslint-disable-next-line depend/ban-dependencies + const { globby } = await import('globby'); + expect(globby).toHaveBeenCalledWith( + ['**/package.json'], + expect.objectContaining({ + ignore: ['**/node_modules/**'], + }) + ); + }); + + it('should detect consolidated packages in package.json', async () => { + const contents = JSON.stringify(mockPackageJson); + const filePath = 'test/package.json'; + + const result = await setupCheck(contents, [filePath]); + expect(result).toMatchObject({ + packageJsonFiles: [filePath], + }); + }); + + it('should not detect non-consolidated packages in package.json', async () => { + const packageJsonWithoutConsolidated = { + dependencies: { + react: '^18.0.0', + }, + devDependencies: { + typescript: '^5.0.0', + }, + }; + const contents = JSON.stringify(packageJsonWithoutConsolidated); + const filePath = 'test/package.json'; + + const result = await setupCheck(contents, [filePath]); + expect(result).toBeNull(); + }); +}); + +describe('transformPackageJsonFiles', () => { + it('should transform package.json files', async () => { + const contents = JSON.stringify(mockPackageJson); + const filePath = 'test/package.json'; + + vi.mocked(readFile).mockResolvedValueOnce(contents); + + const errors = await transformPackageJsonFiles([filePath], false); + + expect(errors).toHaveLength(0); + expect(writeFile).toHaveBeenCalledWith( + filePath, + expect.not.stringContaining('"@storybook/core-common": "^8.0.0"') + ); + }); + + it('should not write files in dry run mode', async () => { + const contents = JSON.stringify(mockPackageJson); + const filePath = 'test/package.json'; + + vi.mocked(readFile).mockResolvedValueOnce(contents); + + const errors = await transformPackageJsonFiles([filePath], true); + + expect(errors).toHaveLength(0); + expect(writeFile).not.toHaveBeenCalled(); + }); + + it('should handle file read errors', async () => { + const filePath = 'test/package.json'; + vi.mocked(readFile).mockRejectedValueOnce(new Error('Failed to read file')); + + const errors = await transformPackageJsonFiles([filePath], false); + + expect(errors).toHaveLength(1); + expect(errors[0]).toMatchObject({ + file: filePath, + error: expect.any(Error), + }); + }); + + it('should handle file write errors', async () => { + const contents = JSON.stringify(mockPackageJson); + const filePath = 'test/package.json'; + vi.mocked(readFile).mockResolvedValueOnce(contents); + vi.mocked(writeFile).mockRejectedValueOnce(new Error('Failed to write file')); + + const errors = await transformPackageJsonFiles([filePath], false); + + expect(errors).toHaveLength(1); + expect(errors[0]).toMatchObject({ + file: filePath, + error: expect.any(Error), + }); + }); +}); + +describe('transformImportFiles', () => { + it('should transform import declarations', async () => { + const sourceContents = dedent` + import { something } from '@storybook/components'; + import { other } from '@storybook/core-common'; + `; + const sourceFiles = [join('src', 'test.ts')]; + + vi.mocked(readFile).mockResolvedValueOnce(sourceContents); + + const errors = await transformImportFiles(sourceFiles, false); + + expect(errors).toHaveLength(0); + expect(writeFile).toHaveBeenCalledWith( + sourceFiles[0], + expect.stringContaining(`from 'storybook/internal/components'`) + ); + }); + + it('should transform import declarations with sub-paths', async () => { + const sourceContents = dedent` + import { other } from '@storybook/theming/create'; + `; + const sourceFiles = [join('src', 'test.ts')]; + + vi.mocked(readFile).mockResolvedValueOnce(sourceContents); + + const errors = await transformImportFiles(sourceFiles, false); + + expect(errors).toHaveLength(0); + expect(writeFile).toHaveBeenCalledWith( + sourceFiles[0], + expect.stringContaining(`from 'storybook/internal/theming/create'`) + ); + }); + + it('should transform require calls', async () => { + const sourceContents = dedent` + const something = require('@storybook/components'); + const other = require('@storybook/core-common'); + `; + const sourceFiles = [join('src', 'test.ts')]; + + vi.mocked(readFile).mockResolvedValueOnce(sourceContents); + + const errors = await transformImportFiles(sourceFiles, false); + + expect(errors).toHaveLength(0); + expect(writeFile).toHaveBeenCalledWith( + sourceFiles[0], + expect.stringContaining(`require('storybook/internal/components')`) + ); + }); + + it('should handle mixed import styles', async () => { + const sourceContents = dedent` + import { something } from '@storybook/components'; + const other = require('@storybook/core-common'); + `; + const sourceFiles = [join('src', 'test.ts')]; + + vi.mocked(readFile).mockResolvedValueOnce(sourceContents); + + const errors = await transformImportFiles(sourceFiles, false); + + expect(errors).toHaveLength(0); + expect(writeFile).toHaveBeenCalledWith( + sourceFiles[0], + expect.stringContaining(`from 'storybook/internal/components'`) + ); + expect(writeFile).toHaveBeenCalledWith( + sourceFiles[0], + expect.stringContaining(`require('storybook/internal/common')`) + ); + }); + + it('should not transform non-consolidated package imports', async () => { + const sourceContents = ` + import { something } from '@storybook/other-package'; + const other = require('some-other-package'); + `; + const sourceFiles = [join('src', 'test.ts')]; + + vi.mocked(readFile).mockResolvedValueOnce(sourceContents); + + const errors = await transformImportFiles(sourceFiles, false); + + expect(errors).toHaveLength(0); + expect(writeFile).not.toHaveBeenCalledWith(sourceFiles[0], expect.any(String)); + }); + + it('should not write files in dry run mode', async () => { + const sourceContents = dedent` + import { something } from '@storybook/components'; + `; + const sourceFiles = [join('src', 'test.ts')]; + + vi.mocked(readFile).mockResolvedValueOnce(sourceContents); + + const errors = await transformImportFiles(sourceFiles, true); + + expect(errors).toHaveLength(0); + expect(writeFile).not.toHaveBeenCalled(); + }); + + it('should handle file read errors', async () => { + const sourceFiles = [join('src', 'test.ts')]; + vi.mocked(readFile).mockRejectedValueOnce(new Error('Failed to read file')); + + const errors = await transformImportFiles(sourceFiles, false); + + expect(errors).toHaveLength(1); + expect(errors[0]).toMatchObject({ + file: sourceFiles[0], + error: expect.any(Error), + }); + }); + + it('should handle file write errors', async () => { + const sourceContents = dedent` + import { something } from '@storybook/components'; + `; + const sourceFiles = [join('src', 'test.ts')]; + vi.mocked(readFile).mockResolvedValueOnce(sourceContents); + vi.mocked(writeFile).mockRejectedValueOnce(new Error('Failed to write file')); + + const errors = await transformImportFiles(sourceFiles, false); + + expect(errors).toHaveLength(1); + expect(errors[0]).toMatchObject({ + file: sourceFiles[0], + error: expect.any(Error), + }); + }); +}); diff --git a/code/lib/cli-storybook/src/automigrate/fixes/consolidated-imports.ts b/code/lib/cli-storybook/src/automigrate/fixes/consolidated-imports.ts new file mode 100644 index 00000000000..103911b3996 --- /dev/null +++ b/code/lib/cli-storybook/src/automigrate/fixes/consolidated-imports.ts @@ -0,0 +1,203 @@ +import { readFile, writeFile } from 'node:fs/promises'; + +import { commonGlobOptions, getProjectRoot } from 'storybook/internal/common'; + +import prompts from 'prompts'; +import { dedent } from 'ts-dedent'; + +import { consolidatedPackages } from '../helpers/consolidated-packages'; +import type { Fix, RunOptions } from '../types'; + +export interface ConsolidatedOptions { + packageJsonFiles: string[]; +} + +function transformPackageJson(content: string): string | null { + const packageJson = JSON.parse(content); + let hasChanges = false; + + // Check dependencies + if (packageJson.dependencies) { + for (const [dep, version] of Object.entries(packageJson.dependencies)) { + if (dep in consolidatedPackages) { + delete packageJson.dependencies[dep]; + hasChanges = true; + } + } + } + + // Check devDependencies + if (packageJson.devDependencies) { + for (const [dep, version] of Object.entries(packageJson.devDependencies)) { + if (dep in consolidatedPackages) { + delete packageJson.devDependencies[dep]; + hasChanges = true; + } + } + } + + return hasChanges ? JSON.stringify(packageJson, null, 2) : null; +} + +function transformImports(source: string) { + let hasChanges = false; + let transformed = source; + + for (const [from, to] of Object.entries(consolidatedPackages)) { + // Match the package name when it's inside either single or double quotes + const regex = new RegExp(`(['"])${from}(.*)\\1`, 'g'); + if (regex.test(transformed)) { + transformed = transformed.replace(regex, `$1${to}$2$1`); + hasChanges = true; + } + } + + return hasChanges ? transformed : null; +} + +export const transformPackageJsonFiles = async (files: string[], dryRun: boolean) => { + const errors: Array<{ file: string; error: Error }> = []; + + const { default: pLimit } = await import('p-limit'); + + const limit = pLimit(10); + + await Promise.all( + files.map((file) => + limit(async () => { + try { + const contents = await readFile(file, 'utf-8'); + const transformed = transformPackageJson(contents); + if (!dryRun && transformed) { + await writeFile(file, transformed); + } + } catch (error) { + errors.push({ file, error: error as Error }); + } + }) + ) + ); + + return errors; +}; + +export const transformImportFiles = async (files: string[], dryRun: boolean) => { + const errors: Array<{ file: string; error: Error }> = []; + const { default: pLimit } = await import('p-limit'); + const limit = pLimit(10); + + await Promise.all( + files.map((file) => + limit(async () => { + try { + const contents = await readFile(file, 'utf-8'); + const transformed = transformImports(contents); + if (!dryRun && transformed) { + await writeFile(file, transformed); + } + } catch (error) { + errors.push({ file, error: error as Error }); + } + }) + ) + ); + + return errors; +}; + +export const consolidatedImports: Fix = { + id: 'consolidated-imports', + versionRange: ['^8.0.0', '^9.0.0-0'], + check: async () => { + const projectRoot = getProjectRoot(); + // eslint-disable-next-line depend/ban-dependencies + const globby = (await import('globby')).globby; + + const packageJsonFiles = await globby(['**/package.json'], { + ...commonGlobOptions(''), + ignore: ['**/node_modules/**'], + cwd: projectRoot, + gitignore: true, + }); + + // check if any of the package.json files have consolidated packages + const hasConsolidatedDependencies = await Promise.all( + packageJsonFiles.map(async (file) => { + const contents = await readFile(file, 'utf-8'); + const packageJson = JSON.parse(contents); + return ( + Object.keys(packageJson.dependencies || {}).some((dep) => dep in consolidatedPackages) || + Object.keys(packageJson.devDependencies || {}).some((dep) => dep in consolidatedPackages) + ); + }) + ).then((results) => results.some(Boolean)); + + if (!hasConsolidatedDependencies) { + return null; + } + return { + packageJsonFiles, + }; + }, + prompt: (result: ConsolidatedOptions) => { + return dedent` + Found package.json files that contain consolidated Storybook packages that need to be updated: + ${result.packageJsonFiles.map((file) => `- ${file}`).join('\n')} + + These packages have been consolidated into the main storybook package and should be removed. + The main storybook package will be added to devDependencies if not already present. + + Would you like to: + 1. Update these package.json files + 2. Scan your codebase and update any imports from these consolidated packages + + This will ensure your project is properly updated to use the new consolidated package structure. + `; + }, + run: async (options: RunOptions) => { + const { result, dryRun = false } = options; + const { packageJsonFiles } = result; + + const errors: Array<{ file: string; error: Error }> = []; + + const packageJsonErrors = await transformPackageJsonFiles(packageJsonFiles, dryRun); + errors.push(...packageJsonErrors); + + const projectRoot = getProjectRoot(); + + const defaultGlob = '**/*.{mjs,cjs,js,jsx,ts,tsx}'; + // Find all files matching the glob pattern + const { glob } = await prompts({ + type: 'text', + name: 'glob', + message: 'Enter a custom glob pattern to scan (or press enter to use default):', + initial: defaultGlob, + }); + + // eslint-disable-next-line depend/ban-dependencies + const globby = (await import('globby')).globby; + + const sourceFiles = await globby([glob], { + ...commonGlobOptions(''), + ignore: ['**/node_modules/**'], + dot: true, + cwd: projectRoot, + }); + + const importErrors = await transformImportFiles(sourceFiles, dryRun); + errors.push(...importErrors); + + if (errors.length > 0) { + // eslint-disable-next-line local-rules/no-uncategorized-errors + throw new Error( + `Failed to process ${errors.length} files:\n${errors + .map(({ file, error }) => `- ${file}: ${error.message}`) + .join('\n')}` + ); + } + + if (!dryRun && result.packageJsonFiles.length > 0) { + await options.packageManager.installDependencies(); + } + }, +}; diff --git a/code/lib/cli-storybook/src/automigrate/fixes/index.ts b/code/lib/cli-storybook/src/automigrate/fixes/index.ts index 60f009ee14b..87f11b33690 100644 --- a/code/lib/cli-storybook/src/automigrate/fixes/index.ts +++ b/code/lib/cli-storybook/src/automigrate/fixes/index.ts @@ -9,19 +9,18 @@ import { angularBuildersMultiproject } from './angular-builders-multiproject'; import { autodocsTags } from './autodocs-tags'; import { autodocsTrue } from './autodocs-true'; import { builderVite } from './builder-vite'; +import { consolidatedImports } from './consolidated-imports'; import { cra5 } from './cra5'; import { eslintPlugin } from './eslint-plugin'; import { initialGlobals } from './initial-globals'; import { mdx1to3 } from './mdx-1-to-3'; import { mdxgfm } from './mdx-gfm'; import { mdxToCSF } from './mdx-to-csf'; -import { missingStorybookDependencies } from './missing-storybook-dependencies'; import { newFrameworks } from './new-frameworks'; import { removeReactDependency } from './prompt-remove-react'; import { reactDocgen } from './react-docgen'; import { removeArgtypesRegex } from './remove-argtypes-regex'; import { removedGlobalClientAPIs } from './remove-global-client-apis'; -import { removeJestTestingLibrary } from './remove-jest-testing-library'; import { removeLegacyMDX1 } from './remove-legacymdx1'; import { sbBinary } from './sb-binary'; import { sbScripts } from './sb-scripts'; @@ -37,7 +36,6 @@ import { wrapRequire } from './wrap-require'; export * from '../types'; export const allFixes: Fix[] = [ - missingStorybookDependencies, addonsAPI, newFrameworks, cra5, @@ -49,7 +47,6 @@ export const allFixes: Fix[] = [ builderVite, sbBinary, sbScripts, - removeJestTestingLibrary, removeArgtypesRegex, removedGlobalClientAPIs, mdxgfm, @@ -69,6 +66,7 @@ export const allFixes: Fix[] = [ autodocsTags, initialGlobals, addonA11yAddonTest, + consolidatedImports, addonExperimentalTest, ]; diff --git a/code/lib/cli-storybook/src/automigrate/fixes/missing-storybook-dependencies.test.ts b/code/lib/cli-storybook/src/automigrate/fixes/missing-storybook-dependencies.test.ts deleted file mode 100644 index 3663cf3f0bd..00000000000 --- a/code/lib/cli-storybook/src/automigrate/fixes/missing-storybook-dependencies.test.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { describe, expect, it, vi } from 'vitest'; - -import type { JsPackageManager } from 'storybook/internal/common'; - -import stripAnsi from 'strip-ansi'; - -import { missingStorybookDependencies } from './missing-storybook-dependencies'; - -vi.mock('globby', () => ({ - __esModule: true, - globby: vi.fn().mockResolvedValue(['.storybook/manager.ts', 'path/to/file.stories.tsx']), -})); - -vi.mock('node:fs/promises', async (importOriginal) => { - const original = (await importOriginal()) as typeof import('node:fs/promises'); - return { - ...original, - readFile: vi.fn().mockResolvedValue(` - // these are NOT installed, will be reported - import { someFunction } from '@storybook/preview-api'; - import { anotherFunction } from '@storybook/manager-api'; - import { SomeError } from '@storybook/core-events/server-errors'; - // this IS installed, will not be reported - import { yetAnotherFunction } from '@storybook/theming'; - `), - }; -}); - -vi.mock('../../helpers', () => ({ - getStorybookVersionSpecifier: vi.fn().mockReturnValue('^8.1.10'), -})); - -const check = async ({ - packageManager, - storybookVersion = '8.1.10', -}: { - packageManager: JsPackageManager; - storybookVersion?: string; -}) => { - return missingStorybookDependencies.check({ - packageManager, - mainConfig: {} as any, - storybookVersion, - }); -}; - -describe('missingStorybookDependencies', () => { - const mockPackageManager = { - findInstallations: vi.fn().mockResolvedValue({ - dependencies: { - '@storybook/react': '8.1.0', - '@storybook/theming': '8.1.0', - }, - }), - retrievePackageJson: vi.fn().mockResolvedValue({ - dependencies: { - storybook: '8.1.0', - }, - }), - addDependencies: vi.fn().mockResolvedValue(undefined), - } as Partial; - - describe('check function', () => { - it('should identify missing dependencies', async () => { - const result = await check({ - packageManager: mockPackageManager as JsPackageManager, - }); - - expect(Object.keys(result!.packageUsage)).not.includes('@storybook/theming'); - expect(result).toEqual({ - packageUsage: { - '@storybook/preview-api': ['.storybook/manager.ts', 'path/to/file.stories.tsx'], - '@storybook/manager-api': ['.storybook/manager.ts', 'path/to/file.stories.tsx'], - '@storybook/core-events': ['.storybook/manager.ts', 'path/to/file.stories.tsx'], - }, - }); - }); - }); - - describe('prompt function', () => { - it('should provide a proper message with the missing dependencies', () => { - const packageUsage = { - '@storybook/preview-api': ['.storybook/manager.ts'], - '@storybook/manager-api': ['path/to/file.stories.tsx'], - }; - - const message = missingStorybookDependencies.prompt({ packageUsage }); - - expect(stripAnsi(message)).toMatchInlineSnapshot(` - "Found the following Storybook packages used in your project, but they are missing from your project dependencies: - - @storybook/manager-api: (1 file) - - @storybook/preview-api: (1 file) - - Referencing missing packages can cause your project to crash. We can automatically add them to your dependencies. - - More info: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#failed-to-resolve-import-storybookx-error" - `); - }); - }); - - describe('run function', () => { - it('should add missing dependencies', async () => { - const dryRun = false; - const packageUsage = { - '@storybook/preview-api': ['.storybook/manager.ts'], - '@storybook/manager-api': ['path/to/file.stories.tsx'], - }; - - await missingStorybookDependencies.run!({ - result: { packageUsage }, - dryRun, - packageJson: {}, - mainConfig: { stories: [] }, - packageManager: mockPackageManager as JsPackageManager, - mainConfigPath: 'path/to/main-config.js', - }); - - expect(mockPackageManager.addDependencies).toHaveBeenNthCalledWith( - 1, - { installAsDevDependencies: true }, - ['@storybook/preview-api@8.1.0', '@storybook/manager-api@8.1.0'] - ); - expect(mockPackageManager.addDependencies).toHaveBeenNthCalledWith( - 2, - { installAsDevDependencies: true, skipInstall: true, packageJson: expect.anything() }, - ['@storybook/preview-api@8.1.0', '@storybook/manager-api@8.1.0'] - ); - }); - }); -}); diff --git a/code/lib/cli-storybook/src/automigrate/fixes/missing-storybook-dependencies.ts b/code/lib/cli-storybook/src/automigrate/fixes/missing-storybook-dependencies.ts deleted file mode 100644 index 7e36f475028..00000000000 --- a/code/lib/cli-storybook/src/automigrate/fixes/missing-storybook-dependencies.ts +++ /dev/null @@ -1,157 +0,0 @@ -import { readFile } from 'node:fs/promises'; - -import { getStorybookVersionSpecifier } from 'storybook/internal/cli'; -import type { InstallationMetadata, JsPackageManager } from 'storybook/internal/common'; - -import picocolors from 'picocolors'; -import { dedent } from 'ts-dedent'; - -import type { Fix } from '../types'; - -const logger = console; - -type PackageUsage = Record; - -interface MissingStorybookDependenciesOptions { - packageUsage: PackageUsage; -} - -const consolidatedPackages = [ - '@storybook/channels', - '@storybook/client-logger', - '@storybook/core-common', - '@storybook/core-events', - '@storybook/csf-tools', - '@storybook/docs-tools', - '@storybook/node-logger', - '@storybook/preview-api', - '@storybook/router', - '@storybook/telemetry', - '@storybook/theming', - '@storybook/types', - '@storybook/manager-api', - '@storybook/manager', - '@storybook/preview', - '@storybook/core-server', - '@storybook/builder-manager', - '@storybook/components', -]; - -async function checkInstallations( - packageManager: JsPackageManager, - packages: string[] -): Promise { - let result: Record = {}; - - // go through each package and get installation info at depth 0 to make sure - // the dependency is directly installed, else they could come from other dependencies - const promises = packages.map((pkg) => packageManager.findInstallations([pkg], { depth: 0 })); - - const analyses = await Promise.all(promises); - - analyses.forEach((analysis) => { - if (analysis?.dependencies) { - result = { - ...result, - ...analysis.dependencies, - }; - } - }); - - return result; -} - -/** Find usage of Storybook packages in the project files which are not present in the dependencies. */ -export const missingStorybookDependencies: Fix = { - id: 'missingStorybookDependencies', - promptType: 'auto', - versionRange: ['<8.2', '>=8.2'], - - async check({ packageManager }) { - // Dynamically import globby because it is a pure ESM module - // eslint-disable-next-line depend/ban-dependencies - const { globby } = await import('globby'); - - const result = await checkInstallations(packageManager, consolidatedPackages); - if (!result) { - return null; - } - - const installedDependencies = Object.keys(result).sort(); - const dependenciesToCheck = consolidatedPackages.filter( - (pkg) => !installedDependencies.includes(pkg) - ); - - const patterns = ['**/.storybook/*', '**/*.stories.*', '**/*.story.*']; - - const files = await globby(patterns, { - ignore: ['**/node_modules/**'], - }); - const packageUsage: PackageUsage = {}; - - for (const file of files) { - const content = await readFile(file, 'utf-8'); - dependenciesToCheck.forEach((pkg) => { - // match imports like @storybook/theming or @storybook/theming/create - const regex = new RegExp(`['"]${pkg}(/[^'"]*)?['"]`); - if (regex.test(content)) { - if (!packageUsage[pkg]) { - packageUsage[pkg] = []; - } - packageUsage[pkg].push(file); - } - }); - } - - return Object.keys(packageUsage).length > 0 ? { packageUsage } : null; - }, - - prompt({ packageUsage }) { - return dedent` - Found the following Storybook packages used in your project, but they are missing from your project dependencies: - ${Object.entries(packageUsage) - .map( - ([pkg, files]) => - `- ${picocolors.cyan(pkg)}: (${files.length} ${files.length === 1 ? 'file' : 'files'})` - ) - .sort() - .join('\n')} - - Referencing missing packages can cause your project to crash. We can automatically add them to your dependencies. - - More info: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#failed-to-resolve-import-storybookx-error - `; - }, - - async run({ result: { packageUsage }, dryRun, packageManager }) { - logger.info( - `✅ Installing the following packages as devDependencies: ${Object.keys(packageUsage)}` - ); - if (!dryRun) { - console.log(packageManager.retrievePackageJson()); - const dependenciesToInstall = Object.keys(packageUsage); - const versionToInstall = getStorybookVersionSpecifier( - await packageManager.retrievePackageJson() - ); - - const versionToInstallWithoutModifiers = versionToInstall?.replace(/[\^~]/, ''); - - /** - * WORKAROUND: necessary for the following scenario: Storybook latest is currently at 8.2.2 - * User has all Storybook deps at ^8.2.1 We run e.g. npm install with the dependency@^8.2.1 - * The package.json will have ^8.2.1 but install 8.2.2 So we first install the exact version, - * then run code again to write to package.json to add the caret back, but without running - * install - */ - await packageManager.addDependencies( - { installAsDevDependencies: true }, - dependenciesToInstall.map((pkg) => `${pkg}@${versionToInstallWithoutModifiers}`) - ); - const packageJson = await packageManager.retrievePackageJson(); - await packageManager.addDependencies( - { installAsDevDependencies: true, skipInstall: true, packageJson }, - dependenciesToInstall.map((pkg) => `${pkg}@${versionToInstall}`) - ); - } - }, -}; diff --git a/code/lib/cli-storybook/src/automigrate/fixes/remove-jest-testing-library.test.ts b/code/lib/cli-storybook/src/automigrate/fixes/remove-jest-testing-library.test.ts deleted file mode 100644 index 80e5e4989ba..00000000000 --- a/code/lib/cli-storybook/src/automigrate/fixes/remove-jest-testing-library.test.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { expect, it } from 'vitest'; - -import type { JsPackageManager } from 'storybook/internal/common'; -import type { StorybookConfig } from 'storybook/internal/types'; - -import ansiRegex from 'ansi-regex'; - -import { removeJestTestingLibrary } from './remove-jest-testing-library'; - -const check = async ({ - packageManager, - main: mainConfig = {}, - storybookVersion = '8.0.0', -}: { - packageManager: Partial; - main?: Partial & Record; - storybookVersion?: string; -}) => { - return removeJestTestingLibrary.check({ - packageManager: packageManager as any, - configDir: '', - mainConfig: mainConfig as any, - storybookVersion, - }); -}; - -it('should prompt to install the test package and run the codemod', async () => { - const options = await check({ - packageManager: { - getAllDependencies: async () => ({ - '@storybook/jest': '1.0.0', - '@storybook/testing-library': '1.0.0', - }), - }, - main: { addons: ['@storybook/essentials', '@storybook/addon-info'] }, - }); - - expect(options).toMatchInlineSnapshot(` - { - "incompatiblePackages": [ - "@storybook/jest", - "@storybook/testing-library", - ], - } - `); - - expect.addSnapshotSerializer({ - serialize: (value) => { - const stringVal = typeof value === 'string' ? value : value.toString(); - return stringVal.replace(ansiRegex(), ''); - }, - test: () => true, - }); - - expect(await removeJestTestingLibrary.prompt(options!)).toMatchInlineSnapshot(` - Attention: We've detected that you're using the following packages which are known to be incompatible since Storybook 8: - - - @storybook/jest - - @storybook/testing-library - - We will uninstall them for you and install @storybook/test instead. - - Also, we can help you migrate your stories to use the new package. - `); -}); diff --git a/code/lib/cli-storybook/src/automigrate/fixes/remove-jest-testing-library.ts b/code/lib/cli-storybook/src/automigrate/fixes/remove-jest-testing-library.ts deleted file mode 100644 index b7de9df0afc..00000000000 --- a/code/lib/cli-storybook/src/automigrate/fixes/remove-jest-testing-library.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { getStorybookVersionSpecifier } from 'storybook/internal/cli'; - -import { runCodemod } from '@storybook/codemod'; - -import picocolors from 'picocolors'; -import prompts from 'prompts'; -import { dedent } from 'ts-dedent'; - -import type { Fix } from '../types'; - -const logger = console; - -export const removeJestTestingLibrary: Fix<{ incompatiblePackages: string[] }> = { - id: 'remove-jest-testing-library', - versionRange: ['<8.0.0-alpha.0', '>=8.0.0-alpha.0'], - promptType: 'auto', - async check({ packageManager }) { - const deps = await packageManager.getAllDependencies(); - - const incompatiblePackages = Object.keys(deps).filter( - (it) => it === '@storybook/jest' || it === '@storybook/testing-library' - ); - return incompatiblePackages.length ? { incompatiblePackages } : null; - }, - prompt({ incompatiblePackages }) { - return dedent` - ${picocolors.bold( - 'Attention' - )}: We've detected that you're using the following packages which are known to be incompatible since Storybook 8: - - ${incompatiblePackages.map((name) => `- ${picocolors.cyan(`${name}`)}`).join('\n')} - - We will uninstall them for you and install ${picocolors.cyan('@storybook/test')} instead. - - Also, we can help you migrate your stories to use the new package. - `; - }, - async run({ packageManager, dryRun }) { - if (!dryRun) { - const packageJson = await packageManager.retrievePackageJson(); - - await packageManager.removeDependencies({ skipInstall: true, packageJson }, [ - '@storybook/jest', - '@storybook/testing-library', - ]); - - const versionToInstall = getStorybookVersionSpecifier(packageJson); - - await packageManager.addDependencies({ installAsDevDependencies: true, packageJson }, [ - `@storybook/test@${versionToInstall}`, - ]); - - const { glob: globString } = await prompts({ - type: 'text', - name: 'glob', - message: 'Please enter the glob for your stories to migrate to @storybook/test', - initial: './src/**/*.stories.*', - }); - - if (globString) { - await runCodemod('migrate-to-test-package', { glob: globString, dryRun, logger }); - } - } - }, -}; diff --git a/code/lib/cli-storybook/src/automigrate/helpers/consolidated-packages.ts b/code/lib/cli-storybook/src/automigrate/helpers/consolidated-packages.ts new file mode 100644 index 00000000000..4880dad9498 --- /dev/null +++ b/code/lib/cli-storybook/src/automigrate/helpers/consolidated-packages.ts @@ -0,0 +1,27 @@ +/** + * Consolidated packages are packages that have been merged into the main storybook package. This + * object maps the old package name to the new package name. + */ +export const consolidatedPackages = { + '@storybook/channels': 'storybook/internal/channels', + '@storybook/client-logger': 'storybook/internal/client-logger', + '@storybook/core-common': 'storybook/internal/common', + '@storybook/core-events': 'storybook/internal/core-events', + '@storybook/csf-tools': 'storybook/internal/csf-tools', + '@storybook/docs-tools': 'storybook/internal/docs-tools', + '@storybook/node-logger': 'storybook/internal/node-logger', + '@storybook/preview-api': 'storybook/internal/preview-api', + '@storybook/router': 'storybook/internal/router', + '@storybook/telemetry': 'storybook/internal/telemetry', + '@storybook/theming': 'storybook/internal/theming', + '@storybook/types': 'storybook/internal/types', + '@storybook/manager-api': 'storybook/internal/manager-api', + '@storybook/manager': 'storybook/internal/manager', + '@storybook/preview': 'storybook/internal/preview', + '@storybook/core-server': 'storybook/internal/core-server', + '@storybook/builder-manager': 'storybook/internal/builder-manager', + '@storybook/components': 'storybook/internal/components', + '@storybook/test': 'storybook/test', +} as const; + +export type ConsolidatedPackage = keyof typeof consolidatedPackages; diff --git a/code/lib/cli-storybook/src/sandbox-templates.ts b/code/lib/cli-storybook/src/sandbox-templates.ts index d6000075ca0..3177a982082 100644 --- a/code/lib/cli-storybook/src/sandbox-templates.ts +++ b/code/lib/cli-storybook/src/sandbox-templates.ts @@ -499,6 +499,9 @@ export const baseTemplates = { renderer: '@storybook/angular', builder: '@storybook/builder-webpack5', }, + modifications: { + extraDependencies: ['@angular-devkit/build-angular@next'], + }, skipTasks: ['e2e-tests-dev', 'bench', 'vitest-integration'], }, 'angular-cli/default-ts': { diff --git a/code/lib/codemod/package.json b/code/lib/codemod/package.json index 2c74d027c33..35095ef63af 100644 --- a/code/lib/codemod/package.json +++ b/code/lib/codemod/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/codemod", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "A collection of codemod scripts written with JSCodeshift", "keywords": [ "storybook" @@ -32,7 +32,6 @@ "./dist/transforms/find-implicit-spies.js": "./dist/transforms/find-implicit-spies.js", "./dist/transforms/move-builtin-addons.js": "./dist/transforms/move-builtin-addons.js", "./dist/transforms/mdx-to-csf.js": "./dist/transforms/mdx-to-csf.js", - "./dist/transforms/migrate-to-test-package.js": "./dist/transforms/migrate-to-test-package.js", "./dist/transforms/storiesof-to-csf.js": "./dist/transforms/storiesof-to-csf.js", "./dist/transforms/update-addon-info.js": "./dist/transforms/update-addon-info.js", "./dist/transforms/update-organisation-name.js": "./dist/transforms/update-organisation-name.js", @@ -95,7 +94,6 @@ "./src/transforms/csf-hoist-story-annotations.js", "./src/transforms/find-implicit-spies.ts", "./src/transforms/add-component-parameters.js", - "./src/transforms/migrate-to-test-package.ts", "./src/transforms/move-builtin-addons.js", "./src/transforms/update-addon-info.js", "./src/transforms/update-organisation-name.js", diff --git a/code/lib/codemod/src/transforms/__tests__/migrate-to-test-package.test.ts b/code/lib/codemod/src/transforms/__tests__/migrate-to-test-package.test.ts deleted file mode 100644 index e3c2b2e517f..00000000000 --- a/code/lib/codemod/src/transforms/__tests__/migrate-to-test-package.test.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { expect, test } from 'vitest'; - -import { dedent } from 'ts-dedent'; - -import transform from '../migrate-to-test-package'; - -expect.addSnapshotSerializer({ - serialize: (val: any) => (typeof val === 'string' ? val : val.toString()), - test: () => true, -}); - -const tsTransform = async (source: string) => - (await transform({ source, path: 'Component.stories.tsx' })).trim(); - -test('replace jest and testing-library with the test package', async () => { - const input = dedent` - import { expect } from '@storybook/jest'; - import { within, userEvent } from '@storybook/testing-library'; - `; - - expect(await tsTransform(input)).toMatchInlineSnapshot(` - import { expect } from '@storybook/test'; - import { userEvent, within } from '@storybook/test'; - `); -}); - -test('Make jest imports namespace imports', async () => { - const input = dedent` - import { expect, jest } from '@storybook/jest'; - import { within, userEvent } from '@storybook/testing-library'; - - const onFocusMock = jest.fn(); - const onSearchMock = jest.fn(); - - jest.spyOn(window, 'Something'); - `; - - expect(await tsTransform(input)).toMatchInlineSnapshot(` - import { expect } from '@storybook/test'; - import * as test from '@storybook/test'; - import { userEvent, within } from '@storybook/test'; - - const onFocusMock = test.fn(); - const onSearchMock = test.fn(); - - test.spyOn(window, 'Something'); - `); -}); diff --git a/code/lib/codemod/src/transforms/migrate-to-test-package.ts b/code/lib/codemod/src/transforms/migrate-to-test-package.ts deleted file mode 100644 index 9fffa57f7ad..00000000000 --- a/code/lib/codemod/src/transforms/migrate-to-test-package.ts +++ /dev/null @@ -1,65 +0,0 @@ -/* eslint-disable no-underscore-dangle */ -import { type BabelFile, core as babel, types as t } from 'storybook/internal/babel'; -import { loadCsf, printCsf } from 'storybook/internal/csf-tools'; - -import type { FileInfo } from 'jscodeshift'; -import prettier from 'prettier'; - -export default async function transform(info: FileInfo) { - const csf = loadCsf(info.source, { makeTitle: (title) => title }); - const fileNode = csf._ast; - // @ts-expect-error File is not yet exposed, see https://github.com/babel/babel/issues/11350#issuecomment-644118606 - const file: BabelFile = new babel.File( - { filename: info.path }, - { code: info.source, ast: fileNode } - ); - - file.path.traverse({ - ImportDeclaration: (path) => { - if ( - path.node.source.value === '@storybook/jest' || - path.node.source.value === '@storybook/testing-library' - ) { - if (path.node.source.value === '@storybook/jest') { - path.get('specifiers').forEach((specifier) => { - if (specifier.isImportSpecifier()) { - const imported = specifier.get('imported'); - - if (!imported.isIdentifier()) { - return; - } - if (imported.node.name === 'jest') { - specifier.remove(); - path.insertAfter( - t.importDeclaration( - [t.importNamespaceSpecifier(t.identifier('test'))], - t.stringLiteral('@storybook/test') - ) - ); - } - } - }); - } - path.get('source').replaceWith(t.stringLiteral('@storybook/test')); - } - }, - Identifier: (path) => { - if (path.node.name === 'jest') { - path.replaceWith(t.identifier('test')); - } - }, - }); - - let output = printCsf(csf).code; - try { - output = await prettier.format(output, { - ...(await prettier.resolveConfig(info.path)), - filepath: info.path, - }); - } catch (e) { - console.warn(`Failed applying prettier to ${info.path}.`); - } - return output; -} - -export const parser = 'tsx'; diff --git a/code/lib/core-webpack/package.json b/code/lib/core-webpack/package.json index f5a26a80ee5..e4dadd31773 100644 --- a/code/lib/core-webpack/package.json +++ b/code/lib/core-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-webpack", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/lib/create-storybook/package.json b/code/lib/create-storybook/package.json index 4da42683a9a..e6ab8199284 100644 --- a/code/lib/create-storybook/package.json +++ b/code/lib/create-storybook/package.json @@ -1,6 +1,6 @@ { "name": "create-storybook", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Initialize Storybook into your project", "homepage": "https://github.com/storybookjs/storybook/tree/next/code/lib/create-storybook", "bugs": { diff --git a/code/lib/create-storybook/src/generators/ANGULAR/index.ts b/code/lib/create-storybook/src/generators/ANGULAR/index.ts index dfea1b03b31..1fa1bc2c53a 100644 --- a/code/lib/create-storybook/src/generators/ANGULAR/index.ts +++ b/code/lib/create-storybook/src/generators/ANGULAR/index.ts @@ -73,7 +73,10 @@ const generator: Generator<{ projectName: string }> = async ( 'angular', { extraAddons: [`@storybook/addon-onboarding`], - ...(useCompodoc && { extraPackages: ['@compodoc/compodoc', '@storybook/addon-docs'] }), + extraPackages: [ + '@angular-devkit/build-angular', + ...(useCompodoc ? ['@compodoc/compodoc', '@storybook/addon-docs'] : []), + ], addScripts: false, componentsDestinationPath: root ? `${root}/src/stories` : undefined, storybookConfigFolder: storybookFolder, diff --git a/code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts b/code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts index 13d50bfb347..bfe983ab551 100644 --- a/code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts +++ b/code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts @@ -56,7 +56,7 @@ const generator: Generator = async (packageManager, npmOptions, options) => { await copyTemplateFiles({ packageManager: packageManager as any, - renderer: 'react-native', + templateLocation: 'react-native', // this value for language is not used since we only ship the ts template. This means we just fallback to @storybook/react-native/template/cli. language: SupportedLanguage.TYPESCRIPT_4_9, destination: storybookConfigFolder, diff --git a/code/lib/create-storybook/src/generators/baseGenerator.ts b/code/lib/create-storybook/src/generators/baseGenerator.ts index 6f842d59e25..9d332674c68 100644 --- a/code/lib/create-storybook/src/generators/baseGenerator.ts +++ b/code/lib/create-storybook/src/generators/baseGenerator.ts @@ -224,6 +224,7 @@ export async function baseGenerator( ProjectType.SVELTE, ProjectType.SVELTEKIT, ProjectType.WEB_COMPONENTS, + ProjectType.REACT_NATIVE_WEB, ]; const supportsTestAddon = projectType === ProjectType.NEXTJS || @@ -296,7 +297,6 @@ export async function baseGenerator( const addonPackages = [ '@storybook/addon-essentials', '@storybook/blocks', - '@storybook/test', ...(compiler ? [`@storybook/addon-webpack5-compiler-${compiler}`] : []), ...extraAddonsToInstall, ].filter(Boolean); @@ -448,7 +448,7 @@ export async function baseGenerator( throw new Error(`Could not find template location for ${framework} or ${rendererId}`); } await copyTemplateFiles({ - renderer: templateLocation, + templateLocation, packageManager: packageManager as any, language, destination: componentsDestinationPath, diff --git a/code/lib/create-storybook/src/scaffold-new-project.ts b/code/lib/create-storybook/src/scaffold-new-project.ts index cfbf63c41fe..d86414b23aa 100644 --- a/code/lib/create-storybook/src/scaffold-new-project.ts +++ b/code/lib/create-storybook/src/scaffold-new-project.ts @@ -45,10 +45,10 @@ const SUPPORTED_PROJECTS: Record = { language: 'TS', }, createScript: { - npm: 'npm create next-app@^14 . -- --typescript --use-npm --eslint --tailwind --no-app --import-alias="@/*" --src-dir', + npm: 'npm create next-app . -- --turbopack --typescript --use-npm --eslint --tailwind --no-app --import-alias="@/*" --src-dir', // yarn doesn't support version ranges, so we have to use npx - yarn: 'npx create-next-app@^14 . --typescript --use-yarn --eslint --tailwind --no-app --import-alias="@/*" --src-dir', - pnpm: 'pnpm create next-app@^14 . --typescript --use-pnpm --eslint --tailwind --no-app --import-alias="@/*" --src-dir', + yarn: 'npx create-next-app . --turbopack --typescript --use-yarn --eslint --tailwind --no-app --import-alias="@/*" --src-dir', + pnpm: 'pnpm create next-app . --turbopack --typescript --use-pnpm --eslint --tailwind --no-app --import-alias="@/*" --src-dir', }, }, 'vue-vite-ts': { diff --git a/code/lib/csf-plugin/package.json b/code/lib/csf-plugin/package.json index ef8a12b15b3..ee741c1444d 100644 --- a/code/lib/csf-plugin/package.json +++ b/code/lib/csf-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/csf-plugin", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Enrich CSF files via static analysis", "keywords": [ "storybook" diff --git a/code/lib/react-dom-shim/package.json b/code/lib/react-dom-shim/package.json index a36e18ed2e8..a29c9993444 100644 --- a/code/lib/react-dom-shim/package.json +++ b/code/lib/react-dom-shim/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-dom-shim", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "", "keywords": [ "storybook" diff --git a/code/lib/source-loader/package.json b/code/lib/source-loader/package.json index 960e91abef9..87b0d2b6b7c 100644 --- a/code/lib/source-loader/package.json +++ b/code/lib/source-loader/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/source-loader", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Source loader", "keywords": [ "lib", diff --git a/code/lib/test/package.json b/code/lib/test/package.json deleted file mode 100644 index 8e627337a3b..00000000000 --- a/code/lib/test/package.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "name": "@storybook/test", - "version": "9.0.0-alpha.0", - "description": "", - "keywords": [ - "storybook" - ], - "homepage": "https://github.com/storybookjs/storybook/tree/next/code/lib/test", - "bugs": { - "url": "https://github.com/storybookjs/storybook/issues" - }, - "repository": { - "type": "git", - "url": "https://github.com/storybookjs/storybook.git", - "directory": "code/lib/test" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "license": "MIT", - "sideEffects": true, - "exports": { - ".": { - "types": "./dist/index.d.ts", - "node": "./dist/index.js", - "import": "./dist/index.mjs", - "require": "./dist/index.js" - }, - "./package.json": "./package.json" - }, - "main": "dist/index.js", - "module": "dist/index.mjs", - "types": "dist/index.d.ts", - "files": [ - "dist/**/*", - "README.md", - "*.js", - "*.d.ts" - ], - "scripts": { - "check": "jiti ../../../scripts/prepare/check.ts", - "prep": "jiti ../../../scripts/prepare/bundle.ts" - }, - "dependencies": { - "@storybook/global": "^5.0.0", - "@testing-library/dom": "10.4.0", - "@testing-library/jest-dom": "6.5.0", - "@testing-library/user-event": "14.5.2", - "@vitest/expect": "2.0.5", - "@vitest/spy": "2.0.5" - }, - "devDependencies": { - "chai": "^5.1.1", - "tinyspy": "^3.0.0", - "ts-dedent": "^2.2.0", - "type-fest": "~2.19", - "typescript": "^5.7.3" - }, - "peerDependencies": { - "storybook": "workspace:^" - }, - "publishConfig": { - "access": "public" - }, - "bundler": { - "entries": [ - "./src/index.ts" - ], - "noExternal": [ - "@testing-library/dom", - "@testing-library/jest-dom", - "@testing-library/user-event", - "chai", - "@vitest/expect", - "@vitest/spy", - "@vitest/utils" - ], - "externals": [ - "util" - ] - }, - "gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae16" -} diff --git a/code/lib/test/project.json b/code/lib/test/project.json deleted file mode 100644 index 1302a230f1e..00000000000 --- a/code/lib/test/project.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "test", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "targets": { - "build": {} - } -} diff --git a/code/lib/test/template/stories/utils.mock.ts b/code/lib/test/template/stories/utils.mock.ts deleted file mode 100644 index 93a72d03a0e..00000000000 --- a/code/lib/test/template/stories/utils.mock.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { fn } from '@storybook/test'; - -import * as utils from './utils.ts'; - -export const foo = fn(utils.foo).mockName('foo'); diff --git a/code/lib/test/template/stories/utils.ts b/code/lib/test/template/stories/utils.ts deleted file mode 100644 index 5a80b1903c1..00000000000 --- a/code/lib/test/template/stories/utils.ts +++ /dev/null @@ -1 +0,0 @@ -export const foo = () => 'not mocked'; diff --git a/code/lib/test/tsconfig.json b/code/lib/test/tsconfig.json deleted file mode 100644 index 73a65ef2ef6..00000000000 --- a/code/lib/test/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": {}, - "include": ["src/**/*"] -} diff --git a/code/lib/test/vitest.config.ts b/code/lib/test/vitest.config.ts deleted file mode 100644 index 7420176b2e4..00000000000 --- a/code/lib/test/vitest.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig, mergeConfig } from 'vitest/config'; - -import { vitestCommonConfig } from '../../vitest.workspace'; - -export default mergeConfig( - vitestCommonConfig, - defineConfig({ - // Add custom config here - }) -); diff --git a/code/package.json b/code/package.json index cca111cd7de..836b9f3c934 100644 --- a/code/package.json +++ b/code/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/root", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "private": true, "description": "Storybook root", "homepage": "https://storybook.js.org/", @@ -153,7 +153,6 @@ "@storybook/source-loader": "workspace:*", "@storybook/svelte": "workspace:*", "@storybook/svelte-webpack5": "workspace:*", - "@storybook/test": "workspace:*", "@storybook/testing-library": "next", "@storybook/vue3": "workspace:*", "@storybook/vue3-vite": "workspace:*", @@ -162,8 +161,8 @@ "@storybook/web-components-vite": "workspace:*", "@storybook/web-components-webpack5": "workspace:*", "@testing-library/dom": "^10.4.0", - "@testing-library/jest-dom": "^6.5.0", - "@testing-library/react": "^16.0.0", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/react": "^16.2.0", "@testing-library/user-event": "^14.5.2", "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@types/mock-require": "^2.0.3", @@ -176,9 +175,9 @@ "@typescript-eslint/parser": "7.18.0", "@vitejs/plugin-react": "^4.3.2", "@vitejs/plugin-vue": "^4.4.0", - "@vitest/browser": "^3.0.2", - "@vitest/coverage-istanbul": "^3.0.2", - "@vitest/coverage-v8": "^3.0.2", + "@vitest/browser": "^3.0.8", + "@vitest/coverage-istanbul": "^3.0.8", + "@vitest/coverage-v8": "^3.0.8", "create-storybook": "workspace:*", "cross-env": "^7.0.3", "danger": "^12.3.3", @@ -192,7 +191,7 @@ "eslint-plugin-import": "^2.29.1", "eslint-plugin-local-rules": "portal:../scripts/eslint-plugin-local-rules", "eslint-plugin-playwright": "^1.6.2", - "eslint-plugin-storybook": "0.11.3--canary.187.1af857a.0", + "eslint-plugin-storybook": "0.11.4", "github-release-from-changelog": "^2.1.1", "glob": "^10.0.0", "happy-dom": "^14.12.0", @@ -225,7 +224,7 @@ "util": "^0.12.4", "vite": "^4.0.0", "vite-plugin-inspect": "^0.8.5", - "vitest": "^3.0.2", + "vitest": "^3.0.8", "wait-on": "^7.0.1" }, "dependenciesMeta": { diff --git a/code/presets/create-react-app/package.json b/code/presets/create-react-app/package.json index 67039566e38..d52dbee17e7 100644 --- a/code/presets/create-react-app/package.json +++ b/code/presets/create-react-app/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-create-react-app", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for Create React App preset", "keywords": [ "storybook" diff --git a/code/presets/html-webpack/package.json b/code/presets/html-webpack/package.json index 60b93b6e7a8..e07a2ca6906 100644 --- a/code/presets/html-webpack/package.json +++ b/code/presets/html-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-html-webpack", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for HTML: View HTML snippets in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/presets/preact-webpack/package.json b/code/presets/preact-webpack/package.json index 23db593d9f2..c1fbb31e0ce 100644 --- a/code/presets/preact-webpack/package.json +++ b/code/presets/preact-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-preact-webpack", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for Preact: Develop Preact Component in isolation.", "keywords": [ "storybook" diff --git a/code/presets/react-webpack/package.json b/code/presets/react-webpack/package.json index da60324d2ee..0cad50b2b8c 100644 --- a/code/presets/react-webpack/package.json +++ b/code/presets/react-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-react-webpack", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for React: Develop React Component in isolation with Hot Reloading", "keywords": [ "storybook" diff --git a/code/presets/server-webpack/package.json b/code/presets/server-webpack/package.json index fbc2f723247..b6440e1064a 100644 --- a/code/presets/server-webpack/package.json +++ b/code/presets/server-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-server-webpack", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for Server: View HTML snippets from a server in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/presets/svelte-webpack/package.json b/code/presets/svelte-webpack/package.json index 6b3c0bcb917..24118cc4027 100644 --- a/code/presets/svelte-webpack/package.json +++ b/code/presets/svelte-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-svelte-webpack", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for Svelte: Develop Svelte Component in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/presets/vue3-webpack/package.json b/code/presets/vue3-webpack/package.json index 9426116d31f..f1eefa542b6 100644 --- a/code/presets/vue3-webpack/package.json +++ b/code/presets/vue3-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-vue3-webpack", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook for Vue 3: Develop Vue 3 Components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/renderers/html/package.json b/code/renderers/html/package.json index 4237334bac9..a5c24cbbde1 100644 --- a/code/renderers/html/package.json +++ b/code/renderers/html/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/html", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook HTML renderer", "keywords": [ "storybook" diff --git a/code/renderers/html/template/cli/js/Button.stories.js b/code/renderers/html/template/cli/js/Button.stories.js index 985eb1f26e1..36ffffe5f27 100644 --- a/code/renderers/html/template/cli/js/Button.stories.js +++ b/code/renderers/html/template/cli/js/Button.stories.js @@ -1,4 +1,4 @@ -import { fn } from '@storybook/test'; +import { fn } from 'storybook/test'; import { createButton } from './Button'; diff --git a/code/renderers/html/template/cli/js/Header.stories.js b/code/renderers/html/template/cli/js/Header.stories.js index 1168c39159c..5c9949fe83f 100644 --- a/code/renderers/html/template/cli/js/Header.stories.js +++ b/code/renderers/html/template/cli/js/Header.stories.js @@ -1,4 +1,4 @@ -import { fn } from '@storybook/test'; +import { fn } from 'storybook/test'; import { createHeader } from './Header'; diff --git a/code/renderers/html/template/cli/js/Page.stories.js b/code/renderers/html/template/cli/js/Page.stories.js index 4e98ad615cd..17002143e81 100644 --- a/code/renderers/html/template/cli/js/Page.stories.js +++ b/code/renderers/html/template/cli/js/Page.stories.js @@ -1,4 +1,4 @@ -import { expect, userEvent, within } from '@storybook/test'; +import { expect, userEvent, within } from 'storybook/test'; import { createPage } from './Page'; diff --git a/code/renderers/html/template/cli/ts-4-9/Button.stories.ts b/code/renderers/html/template/cli/ts-4-9/Button.stories.ts index e65f93d20f0..8e3e8fceb29 100644 --- a/code/renderers/html/template/cli/ts-4-9/Button.stories.ts +++ b/code/renderers/html/template/cli/ts-4-9/Button.stories.ts @@ -1,5 +1,6 @@ import type { Meta, StoryObj } from '@storybook/html'; -import { fn } from '@storybook/test'; + +import { fn } from 'storybook/test'; import type { ButtonProps } from './Button'; import { createButton } from './Button'; diff --git a/code/renderers/html/template/cli/ts-4-9/Header.stories.ts b/code/renderers/html/template/cli/ts-4-9/Header.stories.ts index 93bc0f66b4a..5a119106099 100644 --- a/code/renderers/html/template/cli/ts-4-9/Header.stories.ts +++ b/code/renderers/html/template/cli/ts-4-9/Header.stories.ts @@ -1,5 +1,6 @@ import type { Meta, StoryObj } from '@storybook/html'; -import { fn } from '@storybook/test'; + +import { fn } from 'storybook/test'; import type { HeaderProps } from './Header'; import { createHeader } from './Header'; diff --git a/code/renderers/html/template/cli/ts-4-9/Page.stories.ts b/code/renderers/html/template/cli/ts-4-9/Page.stories.ts index 5aa9e689913..b5b06055cac 100644 --- a/code/renderers/html/template/cli/ts-4-9/Page.stories.ts +++ b/code/renderers/html/template/cli/ts-4-9/Page.stories.ts @@ -1,5 +1,6 @@ import type { Meta, StoryObj } from '@storybook/html'; -import { expect, userEvent, within } from '@storybook/test'; + +import { expect, userEvent, within } from 'storybook/test'; import { createPage } from './Page'; diff --git a/code/renderers/preact/package.json b/code/renderers/preact/package.json index 97df8ee6c17..e10fd8e7472 100644 --- a/code/renderers/preact/package.json +++ b/code/renderers/preact/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook Preact renderer", "keywords": [ "storybook" diff --git a/code/renderers/preact/template/cli/Button.stories.jsx b/code/renderers/preact/template/cli/Button.stories.jsx index 94fd8d336e4..0cc0adf6def 100644 --- a/code/renderers/preact/template/cli/Button.stories.jsx +++ b/code/renderers/preact/template/cli/Button.stories.jsx @@ -1,4 +1,4 @@ -import { fn } from '@storybook/test'; +import { fn } from 'storybook/test'; import { Button } from './Button'; diff --git a/code/renderers/preact/template/cli/Header.stories.jsx b/code/renderers/preact/template/cli/Header.stories.jsx index 7cb7da7cd8c..6d88e100749 100644 --- a/code/renderers/preact/template/cli/Header.stories.jsx +++ b/code/renderers/preact/template/cli/Header.stories.jsx @@ -1,4 +1,4 @@ -import { fn } from '@storybook/test'; +import { fn } from 'storybook/test'; import { Header } from './Header'; diff --git a/code/renderers/preact/template/cli/Page.stories.jsx b/code/renderers/preact/template/cli/Page.stories.jsx index b7a417b634f..478ae05a870 100644 --- a/code/renderers/preact/template/cli/Page.stories.jsx +++ b/code/renderers/preact/template/cli/Page.stories.jsx @@ -1,4 +1,4 @@ -import { userEvent, within } from '@storybook/test'; +import { userEvent, within } from 'storybook/test'; import { Page } from './Page'; diff --git a/code/renderers/react/package.json b/code/renderers/react/package.json index 2e40bcd5df0..a8cb19dcc2a 100644 --- a/code/renderers/react/package.json +++ b/code/renderers/react/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook React renderer", "keywords": [ "storybook" @@ -74,7 +74,6 @@ "@storybook/react-dom-shim": "workspace:*" }, "devDependencies": { - "@storybook/test": "workspace:*", "@types/babel-plugin-react-docgen": "^4.2.3", "@types/escodegen": "^0.0.6", "@types/estree": "^0.0.51", @@ -96,16 +95,12 @@ "type-fest": "~2.19" }, "peerDependencies": { - "@storybook/test": "workspace:*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "storybook": "workspace:^", "typescript": ">= 4.9.x" }, "peerDependenciesMeta": { - "@storybook/test": { - "optional": true - }, "typescript": { "optional": true } diff --git a/code/renderers/react/src/__test__/Button.csf4.stories.tsx b/code/renderers/react/src/__test__/Button.csf4.stories.tsx index 71e8eafa02a..19b9c20460e 100644 --- a/code/renderers/react/src/__test__/Button.csf4.stories.tsx +++ b/code/renderers/react/src/__test__/Button.csf4.stories.tsx @@ -1,10 +1,10 @@ import React, { useEffect, useState } from 'react'; import { createPortal } from 'react-dom'; -import { expect, fn, mocked, userEvent, within } from '@storybook/test'; - import { action } from '@storybook/addon-actions'; +import { expect, fn, mocked, userEvent, within } from 'storybook/test'; + import { __definePreview } from '../preview'; import { Button } from './Button'; diff --git a/code/renderers/react/src/__test__/Button.stories.tsx b/code/renderers/react/src/__test__/Button.stories.tsx index 0e6e0d6e8c6..134748e8b34 100644 --- a/code/renderers/react/src/__test__/Button.stories.tsx +++ b/code/renderers/react/src/__test__/Button.stories.tsx @@ -1,11 +1,11 @@ import React, { useEffect, useState } from 'react'; import { createPortal } from 'react-dom'; -import { expect, fn, mocked, userEvent, within } from '@storybook/test'; - import type { HandlerFunction } from '@storybook/addon-actions'; import { action } from '@storybook/addon-actions'; +import { expect, fn, mocked, userEvent, within } from 'storybook/test'; + import type { StoryFn as CSF2Story, StoryObj as CSF3Story, Meta } from '..'; import type { ButtonProps } from './Button'; import { Button } from './Button'; diff --git a/code/renderers/react/src/csf-factories.test.tsx b/code/renderers/react/src/csf-factories.test.tsx index 3289e3394ec..7a9aa5093d7 100644 --- a/code/renderers/react/src/csf-factories.test.tsx +++ b/code/renderers/react/src/csf-factories.test.tsx @@ -9,10 +9,9 @@ import React from 'react'; import type { Canvas } from 'storybook/internal/csf'; import type { Args, StrictArgs } from 'storybook/internal/types'; -import type { Mock } from '@storybook/test'; -import { fn } from '@storybook/test'; - import { expectTypeOf } from 'expect-type'; +import { fn } from 'storybook/test'; +import type { Mock } from 'storybook/test'; import { __definePreview } from './preview'; import type { Decorator } from './public-types'; diff --git a/code/renderers/react/src/entry-preview.tsx b/code/renderers/react/src/entry-preview.tsx index b2e6c1de5b1..7c83cd3f45b 100644 --- a/code/renderers/react/src/entry-preview.tsx +++ b/code/renderers/react/src/entry-preview.tsx @@ -30,7 +30,7 @@ export const beforeAll = async () => { try { // copied from // https://github.com/testing-library/react-testing-library/blob/3dcd8a9649e25054c0e650d95fca2317b7008576/src/pure.js - const { configure } = await import('@storybook/test'); + const { configure } = await import('storybook/test'); configure({ unstable_advanceTimersWrapper: (cb) => { @@ -73,7 +73,7 @@ export const beforeAll = async () => { }); } catch (e) { // no-op - // @storybook/test might not be available + // storybook/test might not be available } }; diff --git a/code/renderers/react/src/preview.tsx b/code/renderers/react/src/preview.tsx index b8eea5532b9..507303dbbf9 100644 --- a/code/renderers/react/src/preview.tsx +++ b/code/renderers/react/src/preview.tsx @@ -79,4 +79,4 @@ interface ReactMeta< ): ReactStory; } -interface ReactStory extends Story {} +export interface ReactStory extends Story {} diff --git a/code/renderers/react/src/public-types.test.tsx b/code/renderers/react/src/public-types.test.tsx index 42544c6bb15..45a36ab1d01 100644 --- a/code/renderers/react/src/public-types.test.tsx +++ b/code/renderers/react/src/public-types.test.tsx @@ -9,10 +9,9 @@ import { satisfies } from 'storybook/internal/common'; import type { Canvas } from 'storybook/internal/csf'; import type { Args, StoryAnnotations, StrictArgs } from 'storybook/internal/types'; -import type { Mock } from '@storybook/test'; -import { fn } from '@storybook/test'; - import { expectTypeOf } from 'expect-type'; +import { fn } from 'storybook/test'; +import type { Mock } from 'storybook/test'; import type { SetOptional } from 'type-fest'; import type { Decorator, Meta, StoryObj } from './public-types'; diff --git a/code/renderers/react/template/cli/js/Button.stories.js b/code/renderers/react/template/cli/js/Button.stories.js index 045d9c477ab..1b56021e71d 100644 --- a/code/renderers/react/template/cli/js/Button.stories.js +++ b/code/renderers/react/template/cli/js/Button.stories.js @@ -1,4 +1,4 @@ -import { fn } from '@storybook/test'; +import { fn } from 'storybook/test'; import { Button } from './Button'; diff --git a/code/renderers/react/template/cli/js/Header.stories.js b/code/renderers/react/template/cli/js/Header.stories.js index 7cb7da7cd8c..6d88e100749 100644 --- a/code/renderers/react/template/cli/js/Header.stories.js +++ b/code/renderers/react/template/cli/js/Header.stories.js @@ -1,4 +1,4 @@ -import { fn } from '@storybook/test'; +import { fn } from 'storybook/test'; import { Header } from './Header'; diff --git a/code/renderers/react/template/cli/js/Page.stories.js b/code/renderers/react/template/cli/js/Page.stories.js index 7b9906a7351..1ffea36cf37 100644 --- a/code/renderers/react/template/cli/js/Page.stories.js +++ b/code/renderers/react/template/cli/js/Page.stories.js @@ -1,4 +1,4 @@ -import { expect, userEvent, within } from '@storybook/test'; +import { expect, userEvent, within } from 'storybook/test'; import { Page } from './Page'; diff --git a/code/renderers/react/template/cli/ts-4-9/Button.stories.ts b/code/renderers/react/template/cli/ts-4-9/Button.stories.ts index 2a05e01b06f..535e1b3fd96 100644 --- a/code/renderers/react/template/cli/ts-4-9/Button.stories.ts +++ b/code/renderers/react/template/cli/ts-4-9/Button.stories.ts @@ -1,5 +1,6 @@ import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; + +import { fn } from 'storybook/test'; import { Button } from './Button'; diff --git a/code/renderers/react/template/cli/ts-4-9/Header.stories.ts b/code/renderers/react/template/cli/ts-4-9/Header.stories.ts index 80c71d0f520..b233bcb4f4d 100644 --- a/code/renderers/react/template/cli/ts-4-9/Header.stories.ts +++ b/code/renderers/react/template/cli/ts-4-9/Header.stories.ts @@ -1,5 +1,6 @@ import type { Meta, StoryObj } from '@storybook/react'; -import { fn } from '@storybook/test'; + +import { fn } from 'storybook/test'; import { Header } from './Header'; diff --git a/code/renderers/react/template/cli/ts-4-9/Page.stories.ts b/code/renderers/react/template/cli/ts-4-9/Page.stories.ts index 5d2c688a978..6c39800e3e5 100644 --- a/code/renderers/react/template/cli/ts-4-9/Page.stories.ts +++ b/code/renderers/react/template/cli/ts-4-9/Page.stories.ts @@ -1,5 +1,6 @@ import type { Meta, StoryObj } from '@storybook/react'; -import { expect, userEvent, within } from '@storybook/test'; + +import { expect, userEvent, within } from 'storybook/test'; import { Page } from './Page'; diff --git a/code/renderers/server/package.json b/code/renderers/server/package.json index c757fa72fd6..9d1e1534dfb 100644 --- a/code/renderers/server/package.json +++ b/code/renderers/server/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/server", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook Server renderer", "keywords": [ "storybook" diff --git a/code/renderers/svelte/package.json b/code/renderers/svelte/package.json index e5ac46b5ae8..5411f409f4c 100644 --- a/code/renderers/svelte/package.json +++ b/code/renderers/svelte/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/svelte", - "version": "9.0.0-alpha.0", + "version": "9.0.0-alpha.3", "description": "Storybook Svelte renderer", "keywords": [ "storybook" diff --git a/code/renderers/svelte/src/__test__/composeStories/Button.stories.ts b/code/renderers/svelte/src/__test__/composeStories/Button.stories.ts index 92ade46f29a..9bc3ad429f8 100644 --- a/code/renderers/svelte/src/__test__/composeStories/Button.stories.ts +++ b/code/renderers/svelte/src/__test__/composeStories/Button.stories.ts @@ -1,4 +1,4 @@ -import { expect, fn, userEvent, within } from '@storybook/test'; +import { expect, fn, userEvent, within } from 'storybook/test'; import type { StoryFn as CSF2Story, Meta, StoryObj } from '../..'; import AddWrapperDecorator from './AddWrapperDecorator.svelte'; diff --git a/code/renderers/svelte/template/cli/js/Page.stories.js b/code/renderers/svelte/template/cli/js/Page.stories.js index 5ce7b3dac56..7355660af63 100644 --- a/code/renderers/svelte/template/cli/js/Page.stories.js +++ b/code/renderers/svelte/template/cli/js/Page.stories.js @@ -1,4 +1,4 @@ -import { expect, userEvent, waitFor, within } from '@storybook/test'; +import { expect, userEvent, waitFor, within } from 'storybook/test'; import Page from './Page.svelte'; diff --git a/code/renderers/svelte/template/cli/svelte-5-js/Button.stories.svelte b/code/renderers/svelte/template/cli/svelte-5-js/Button.stories.svelte index 4c8c7cce632..e6fb72dac17 100644 --- a/code/renderers/svelte/template/cli/svelte-5-js/Button.stories.svelte +++ b/code/renderers/svelte/template/cli/svelte-5-js/Button.stories.svelte @@ -1,7 +1,7 @@