diff --git a/.circleci/config.yml b/.circleci/config.yml
index 04ef5634826e..6db12bf41959 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -560,27 +560,27 @@ workflows:
requires:
- unit-tests
- create-sandboxes:
- parallelism: 23
+ parallelism: 21
requires:
- build
- build-sandboxes:
- parallelism: 23
+ parallelism: 21
requires:
- create-sandboxes
- chromatic-sandboxes:
- parallelism: 20
+ parallelism: 18
requires:
- build-sandboxes
- e2e-production:
- parallelism: 18
+ parallelism: 16
requires:
- build-sandboxes
- e2e-dev:
- parallelism: 4
+ parallelism: 2
requires:
- create-sandboxes
- test-runner-production:
- parallelism: 18
+ parallelism: 16
requires:
- build-sandboxes
- bench:
@@ -614,30 +614,30 @@ workflows:
requires:
- build
- create-sandboxes:
- parallelism: 38
+ parallelism: 36
requires:
- build
# - smoke-test-sandboxes: # disabled for now
# requires:
# - create-sandboxes
- build-sandboxes:
- parallelism: 38
+ parallelism: 36
requires:
- create-sandboxes
- chromatic-sandboxes:
- parallelism: 35
+ parallelism: 33
requires:
- build-sandboxes
- e2e-production:
- parallelism: 33
+ parallelism: 31
requires:
- build-sandboxes
- e2e-dev:
- parallelism: 4
+ parallelism: 2
requires:
- create-sandboxes
- test-runner-production:
- parallelism: 33
+ parallelism: 31
requires:
- build-sandboxes
# TODO: reenable once we find out the source of flakyness
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index ba472744a8f1..954092e8d2e2 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -4,11 +4,10 @@ Closes #
-
## What I did
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 1737faa78f27..2eaa07fec3cd 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -16,7 +16,7 @@
"editor.formatOnSave": true
},
"editor.codeActionsOnSave": {
- "source.fixAll.eslint": true
+ "source.fixAll.eslint": "explicit"
},
"editor.tabSize": 2,
"editor.formatOnSave": true,
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e424acc666c1..28d18cedd4ca 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,108 @@
+## 7.6.0
+
+Storybook 7.6 is here with increased performance and much more!
+
+- 🔥 Improved SWC support
+- 🧪 New test utilities and fast build mode
+- 🔼 NextJS SWC + avif support & fixes
+- 🤡 SvelteKit page and navigation mocking
+- ⚛️ React-docgen upgrade
+- 🎨 Controls a11y, background theming, and viewports
+- 🩺 CLI: The doctor is in!
+- 🚫 Addons: Remove React as a peer dependency
+- 🪦 Storyshots and Vue2 deprecated
+
+
+
+ List of all updates
+
+
+ - Actions: Attach spies on actions across stories when defined in meta - [#24451](https://github.com/storybookjs/storybook/pull/24451), thanks [@kasperpeulen](https://github.com/kasperpeulen)!
+ - Actions: Fix `@storybook/core-events/preview-errors` dependency missing for Yarn PnP - [#24973](https://github.com/storybookjs/storybook/pull/24973), thanks [@JReinhold](https://github.com/JReinhold)!
+ - Actions: Fix missing crypto module crashing React Native - [#24546](https://github.com/storybookjs/storybook/pull/24546), thanks [@dannyhw](https://github.com/dannyhw)!
+ - Actions: Warn on implicit actions - [#24856](https://github.com/storybookjs/storybook/pull/24856), thanks [@kasperpeulen](https://github.com/kasperpeulen)!
+ - Addon A11y: Avoid CSP issue - [#24477](https://github.com/storybookjs/storybook/pull/24477), thanks [@Marklb](https://github.com/Marklb)!
+ - Addon: Move Visual Test addon to the code directory - [#24771](https://github.com/storybookjs/storybook/pull/24771), thanks [@cdedreuille](https://github.com/cdedreuille)!
+ - Addons, core: Make `react` and Storybook packages `devDependencies` where possible - [#24676](https://github.com/storybookjs/storybook/pull/24676), thanks [@JReinhold](https://github.com/JReinhold)!
+ - Addons, core: Make `react` and Storybook packages `devDependencies` where possible - ATTEMPT 2 - [#24834](https://github.com/storybookjs/storybook/pull/24834), thanks [@JReinhold](https://github.com/JReinhold)!
+ - Angular: Add source-map option to builder - [#24466](https://github.com/storybookjs/storybook/pull/24466), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - Angular: Handle nested module metadata - [#24798](https://github.com/storybookjs/storybook/pull/24798), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - Angular: Include object configured styles - [#24768](https://github.com/storybookjs/storybook/pull/24768), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - Babel: Update all @babel/* dependencies - [#24610](https://github.com/storybookjs/storybook/pull/24610), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - CLI: Add "doctor" command - [#22236](https://github.com/storybookjs/storybook/pull/22236), thanks [@yannbf](https://github.com/yannbf)!
+ - CLI: Add @storybook/addon-designs to non-core list - [#24507](https://github.com/storybookjs/storybook/pull/24507), thanks [@yannbf](https://github.com/yannbf)!
+ - CLI: Ensure errors with opening the browser are caught - [#24668](https://github.com/storybookjs/storybook/pull/24668), thanks [@xueyawei](https://github.com/xueyawei)!
+ - CLI: Ignore `addon-onboarding` when checking versions - [#24634](https://github.com/storybookjs/storybook/pull/24634), thanks [@JReinhold](https://github.com/JReinhold)!
+ - CLI: Use @storybook/test in template stories - [#24393](https://github.com/storybookjs/storybook/pull/24393), thanks [@yannbf](https://github.com/yannbf)!
+ - Controls: Improve accessibility of BooleanControl for screen readers - [#24418](https://github.com/storybookjs/storybook/pull/24418), thanks [@danielmarcano](https://github.com/danielmarcano)!
+ - Core-Server: Ignore all node_module folders for watchpack - [#24553](https://github.com/storybookjs/storybook/pull/24553), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - Core: Add deprecation notice for Vite + CommonJS - [#23950](https://github.com/storybookjs/storybook/pull/23950), thanks [@JReinhold](https://github.com/JReinhold)!
+ - Core: Detect no matching export error in storybook start and build - [#24877](https://github.com/storybookjs/storybook/pull/24877), thanks [@yannbf](https://github.com/yannbf)!
+ - Core: Fix `useStoryPrepared` hook failing with `undefined` data - [#22631](https://github.com/storybookjs/storybook/pull/22631), thanks [@SpookyJelly](https://github.com/SpookyJelly)!
+ - Core: Fix pnp support when cache dir is outside working dir - [#24572](https://github.com/storybookjs/storybook/pull/24572), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - Core: Fix post message channel location.search access for React Native - [#24545](https://github.com/storybookjs/storybook/pull/24545), thanks [@dannyhw](https://github.com/dannyhw)!
+ - Core: Gracefully handle error when parsing preview.js file - [#24858](https://github.com/storybookjs/storybook/pull/24858), thanks [@yannbf](https://github.com/yannbf)!
+ - Core: Make warnOnIncompatibleAddons fault-tolerant - [#24880](https://github.com/storybookjs/storybook/pull/24880), thanks [@taozhou-glean](https://github.com/taozhou-glean)!
+ - Dependencies: Fix Yarn 4 failing to install due to jscodeshift dependency issue - [#24914](https://github.com/storybookjs/storybook/pull/24914), thanks [@samvv](https://github.com/samvv)!
+ - Dependencies: Update @babel/traverse and @babel/core to fix vulnerability - [#24670](https://github.com/storybookjs/storybook/pull/24670), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - Dependencies: Update browserify-sign transitive dependency - [#24674](https://github.com/storybookjs/storybook/pull/24674), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - Dependencies: Update jscodeshift to v0.15.1 - [#24882](https://github.com/storybookjs/storybook/pull/24882), thanks [@epreston](https://github.com/epreston)!
+ - Dependencies: Update nx dependencies to v17 - [#24671](https://github.com/storybookjs/storybook/pull/24671), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - Doc Blocks: Add support for `of` prop to `Primary` block - [#23849](https://github.com/storybookjs/storybook/pull/23849), thanks [@Wilson2k](https://github.com/Wilson2k)!
+ - Doc Blocks: Remove `defaultProps` in `Stories` block - [#24506](https://github.com/storybookjs/storybook/pull/24506), thanks [@WouterK12](https://github.com/WouterK12)!
+ - Docs: Changes corresponding to docs design updates - [#24925](https://github.com/storybookjs/storybook/pull/24925), thanks [@kylegach](https://github.com/kylegach)!
+ - Maintenance: Split renderers preview entrypoints - [#24623](https://github.com/storybookjs/storybook/pull/24623), thanks [@ndelangen](https://github.com/ndelangen)!
+ - Manager: Update `store.settings.lastTrackedStoryId` - [#24115](https://github.com/storybookjs/storybook/pull/24115), thanks [@rashidshamloo](https://github.com/rashidshamloo)!
+ - ManagerAPI: Fix setting status without index, crashes storybook - [#24866](https://github.com/storybookjs/storybook/pull/24866), thanks [@ndelangen](https://github.com/ndelangen)!
+ - ManagerBuilder: Fix `"type": "commonjs"` compatibility - [#24534](https://github.com/storybookjs/storybook/pull/24534), thanks [@ndelangen](https://github.com/ndelangen)!
+ - Next.js: Add avif support - [#24611](https://github.com/storybookjs/storybook/pull/24611), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - Next.js: Add back image context CommonJS export - [#24885](https://github.com/storybookjs/storybook/pull/24885), thanks [@martinnabhan](https://github.com/martinnabhan)!
+ - Next.js: Add experimental SWC support - [#24852](https://github.com/storybookjs/storybook/pull/24852), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - Next.js: Fix Fast Refresh config for SWC mode - [#24991](https://github.com/storybookjs/storybook/pull/24991), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - Next.js: Fix forwarding ref for Image component - [#24648](https://github.com/storybookjs/storybook/pull/24648), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - Next.js: Fix import path in swc loader - [#24922](https://github.com/storybookjs/storybook/pull/24922), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - Next.js: Fix react-docgen usage with preset-env settings - [#24993](https://github.com/storybookjs/storybook/pull/24993), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - Next.js: Remove duplicate Fast Refresh plugin init - [#24963](https://github.com/storybookjs/storybook/pull/24963), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - React: Upgrade `react-docgen` to v7 - [#24530](https://github.com/storybookjs/storybook/pull/24530), thanks [@shilman](https://github.com/shilman)!
+ - ReactNative: Fix missing assert dep in docs-tools - [#24732](https://github.com/storybookjs/storybook/pull/24732), thanks [@dannyhw](https://github.com/dannyhw)!
+ - Svelte: Fix decorators always running twice - [#24921](https://github.com/storybookjs/storybook/pull/24921), thanks [@paoloricciuti](https://github.com/paoloricciuti)!
+ - Svelte: Fix source with decorators always showing the `SlotDecorator` component - [#24800](https://github.com/storybookjs/storybook/pull/24800), thanks [@JReinhold](https://github.com/JReinhold)!
+ - SvelteKit: Add experimental page and navigation mocking - [#24795](https://github.com/storybookjs/storybook/pull/24795), thanks [@paoloricciuti](https://github.com/paoloricciuti)!
+ - SvelteKit: Default to log an action for `goto`, `invalidate` and `invalidateAll` - [#24955](https://github.com/storybookjs/storybook/pull/24955), thanks [@paoloricciuti](https://github.com/paoloricciuti)!
+ - SWC: Add settings for react and preact - [#24805](https://github.com/storybookjs/storybook/pull/24805), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - Test Build: Add env-variable support to `--test` CLI-flag - [#24862](https://github.com/storybookjs/storybook/pull/24862), thanks [@ndelangen](https://github.com/ndelangen)!
+ - Test Build: Add tests and rename to camelCase - [#24911](https://github.com/storybookjs/storybook/pull/24911), thanks [@ndelangen](https://github.com/ndelangen)!
+ - Test Build: Disable composition when `--test` is `true` - [#24799](https://github.com/storybookjs/storybook/pull/24799), thanks [@ndelangen](https://github.com/ndelangen)!
+ - Test Build: Disable docs related stuff for test builds - [#24691](https://github.com/storybookjs/storybook/pull/24691), thanks [@ndelangen](https://github.com/ndelangen)!
+ - Test Build: Disable telemetry for test builds - [#24706](https://github.com/storybookjs/storybook/pull/24706), thanks [@kasperpeulen](https://github.com/kasperpeulen)!
+ - Test Build: Disable warnOnIncompatibleAddons - [#24797](https://github.com/storybookjs/storybook/pull/24797), thanks [@ndelangen](https://github.com/ndelangen)!
+ - Test Build: Filter out addon-docs from essentials in the test build - [#24994](https://github.com/storybookjs/storybook/pull/24994), thanks [@kasperpeulen](https://github.com/kasperpeulen)!
+ - Test Build: Fix disabledAddons filter - [#24924](https://github.com/storybookjs/storybook/pull/24924), thanks [@IanVS](https://github.com/IanVS)!
+ - Test Build: Fix indexer bug - [#24890](https://github.com/storybookjs/storybook/pull/24890), thanks [@ndelangen](https://github.com/ndelangen)!
+ - Test Build: Globalize `@storybook/blocks` if `build.test.emptyBlocks` is `true` - [#24650](https://github.com/storybookjs/storybook/pull/24650), thanks [@ndelangen](https://github.com/ndelangen)!
+ - Test Build: Implement builder options for test build - [#24826](https://github.com/storybookjs/storybook/pull/24826), thanks [@kasperpeulen](https://github.com/kasperpeulen)!
+ - Test Build: Improve config loading & naming - [#24837](https://github.com/storybookjs/storybook/pull/24837), thanks [@ndelangen](https://github.com/ndelangen)!
+ - Test Build: No sourcemaps for test builds - [#24804](https://github.com/storybookjs/storybook/pull/24804), thanks [@ndelangen](https://github.com/ndelangen)!
+ - Test Build: Revert defaulting to SWC in test build, but keep using esbuild for minification - [#24843](https://github.com/storybookjs/storybook/pull/24843), thanks [@kasperpeulen](https://github.com/kasperpeulen)!
+ - Test: Create @storybook/test package based on vitest - [#24392](https://github.com/storybookjs/storybook/pull/24392), thanks [@kasperpeulen](https://github.com/kasperpeulen)!
+ - Test: Don\'t attach action to function mock if action was added already - [#24966](https://github.com/storybookjs/storybook/pull/24966), thanks [@tmeasday](https://github.com/tmeasday)!
+ - Test: Model loaders as before each and restore mocks properly - [#24948](https://github.com/storybookjs/storybook/pull/24948), thanks [@kasperpeulen](https://github.com/kasperpeulen)!
+ - Theming: Add theme variable to set the preview background color - [#24575](https://github.com/storybookjs/storybook/pull/24575), thanks [@JReinhold](https://github.com/JReinhold)!
+ - Typescript: Add \'skipCompiler\' option to TypeScript presets - [#24847](https://github.com/storybookjs/storybook/pull/24847), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - UI: Fix horizontal scroll bar in Canvas hidden by styling - [#24408](https://github.com/storybookjs/storybook/pull/24408), thanks [@yoshi2no](https://github.com/yoshi2no)!
+ - UI: improve A11Y remove redundant styling rules, update icon color - [#24402](https://github.com/storybookjs/storybook/pull/24402), thanks [@tolkadot](https://github.com/tolkadot)!
+ - UI: Logo fixed value - [#24726](https://github.com/storybookjs/storybook/pull/24726), thanks [@black-arm](https://github.com/black-arm)!
+ - UI: Update zIndex on NotificationList to fix the notification not being clickable in certain cases - [#24602](https://github.com/storybookjs/storybook/pull/24602), thanks [@yoshi2no](https://github.com/yoshi2no)!
+ - Viewport: Add newer device viewports - [#24777](https://github.com/storybookjs/storybook/pull/24777), thanks [@Tomo5524](https://github.com/Tomo5524)!
+ - Vite: Prevent non-deterministic build output - [#24833](https://github.com/storybookjs/storybook/pull/24833), thanks [@henkerik](https://github.com/henkerik)!
+ - Webpack: Add export-order-loader and remove babel-plugin-named-exports-order - [#24749](https://github.com/storybookjs/storybook/pull/24749), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - Webpack: Add react-docgen loader and remove babel-plugin-react-docgen - [#24762](https://github.com/storybookjs/storybook/pull/24762), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - Webpack: Fix race condition for export-order loader - [#24817](https://github.com/storybookjs/storybook/pull/24817), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - Webpack: Hide critical dependency warning - [#24784](https://github.com/storybookjs/storybook/pull/24784), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - Webpack: Only load babel config when babel-loader is used - [#25002](https://github.com/storybookjs/storybook/pull/25002), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+ - Webpack: Resolve circular dependency and fix HMR - [#24974](https://github.com/storybookjs/storybook/pull/24974), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+
+
## 7.5.2
- Addon-themes: Fix globals not being set when using absolute path - [#24596](https://github.com/storybookjs/storybook/pull/24596), thanks [@JReinhold](https://github.com/JReinhold)!
diff --git a/CHANGELOG.prerelease.md b/CHANGELOG.prerelease.md
index d389bce1cfb6..5ef41fa93384 100644
--- a/CHANGELOG.prerelease.md
+++ b/CHANGELOG.prerelease.md
@@ -1,3 +1,33 @@
+## 8.0.0-alpha.0
+
+- Addon Viewport: Expose types for user parameter validation - [#24896](https://github.com/storybookjs/storybook/pull/24896), thanks [@piratetaco](https://github.com/piratetaco)!
+- Packages: Remove unused/deprecated packages - [#24528](https://github.com/storybookjs/storybook/pull/24528), thanks [@ndelangen](https://github.com/ndelangen)!
+- Vite: use user's `build.target` - [#23123](https://github.com/storybookjs/storybook/pull/23123), thanks [@Hoishin](https://github.com/Hoishin)!
+- CLI: Remove `sb extract` command - [#24653](https://github.com/storybookjs/storybook/pull/24653), thanks [@ndelangen](https://github.com/ndelangen)!
+- Core: Improve project root detection logic - [#20791](https://github.com/storybookjs/storybook/pull/20791), thanks [@dobesv](https://github.com/dobesv)!
+- Core: Prebundling globalize the core-event sub paths - [#24976](https://github.com/storybookjs/storybook/pull/24976), thanks [@ndelangen](https://github.com/ndelangen)!
+- Core: Remove `storiesOf`-API - [#24655](https://github.com/storybookjs/storybook/pull/24655), thanks [@ndelangen](https://github.com/ndelangen)!
+- Core: `StorybookConfig` `stories`-field support type async function - [#21555](https://github.com/storybookjs/storybook/pull/21555), thanks [@imccausl](https://github.com/imccausl)!
+- Dependencies: Update Typescript - [#24970](https://github.com/storybookjs/storybook/pull/24970), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
+- Dependencies: Upgrade monorepo to TS5 - [#24440](https://github.com/storybookjs/storybook/pull/24440), thanks [@ndelangen](https://github.com/ndelangen)!
+- TypeScript: Migrate `@storybook/preset-create-react-app` to strict TS - [#22395](https://github.com/storybookjs/storybook/pull/22395), thanks [@kuriacka](https://github.com/kuriacka)!
+- Manager: Enable refs filtered via `experimental_setFilter` - [#24211](https://github.com/storybookjs/storybook/pull/24211), thanks [@ndelangen](https://github.com/ndelangen)!
+- MDX: Theme `fontCode` not applied consistently when writing MDX - [#23110](https://github.com/storybookjs/storybook/pull/23110), thanks [@gitstart-storybook](https://github.com/gitstart-storybook)!
+- UI: Bring back role main - [#24411](https://github.com/storybookjs/storybook/pull/24411), thanks [@cdedreuille](https://github.com/cdedreuille)!
+- UI: Fix `IconButton` not being aligned correctly in blocks - [#24529](https://github.com/storybookjs/storybook/pull/24529), thanks [@cdedreuille](https://github.com/cdedreuille)!
+- UI: Fix button size on controls - [#24737](https://github.com/storybookjs/storybook/pull/24737), thanks [@cdedreuille](https://github.com/cdedreuille)!
+- UI: Fix layout height - [#24370](https://github.com/storybookjs/storybook/pull/24370), thanks [@cdedreuille](https://github.com/cdedreuille)!
+- UI: Fix notifications not appearing in new layout - [#24281](https://github.com/storybookjs/storybook/pull/24281), thanks [@jreinhold](https://github.com/jreinhold)!
+- UI: Fix theming not updating - [#24399](https://github.com/storybookjs/storybook/pull/24399), thanks [@cdedreuille](https://github.com/cdedreuille)!
+- UI: Improved `Button` and `IconButton` - [#24266](https://github.com/storybookjs/storybook/pull/24266), thanks [@cdedreuille](https://github.com/cdedreuille)!
+- UI: Keep mobile drawer open on component selection - [#24258](https://github.com/storybookjs/storybook/pull/24258), thanks [@cdedreuille](https://github.com/cdedreuille)!
+- UI: Mobile truncate story name - [#24372](https://github.com/storybookjs/storybook/pull/24372), thanks [@cdedreuille](https://github.com/cdedreuille)!
+- UI: New icon library - [#24433](https://github.com/storybookjs/storybook/pull/24433), thanks [@cdedreuille](https://github.com/cdedreuille)!
+- UI: Replace `Form.Button` with the new `Button` component - [#24360](https://github.com/storybookjs/storybook/pull/24360), thanks [@cdedreuille](https://github.com/cdedreuille)!
+- UI: Screen reader announcing changes for expand/collapse button - [#24984](https://github.com/storybookjs/storybook/pull/24984), thanks [@wjdtjdgns](https://github.com/wjdtjdgns)!
+- UI: Upgrade manager to React v18 - [#24514](https://github.com/storybookjs/storybook/pull/24514), thanks [@ndelangen](https://github.com/ndelangen)!
+- UI: sidebar UI updates - [#24707](https://github.com/storybookjs/storybook/pull/24707), thanks [@cdedreuille](https://github.com/cdedreuille)!
+
## 7.6.0-beta.2
- Actions: Fix `@storybook/core-events/preview-errors` dependency missing for Yarn PnP - [#24973](https://github.com/storybookjs/storybook/pull/24973), thanks [@JReinhold](https://github.com/JReinhold)!
diff --git a/CHANGELOG.v6.md b/CHANGELOG.v6.md
index 391f14fed6ed..8501b232d289 100644
--- a/CHANGELOG.v6.md
+++ b/CHANGELOG.v6.md
@@ -4942,7 +4942,7 @@ Storybook 6.0 is here!
- 🧬 [Args: Next-generation, dynamic story format](https://medium.com/storybookjs/introducing-storybook-args-2dadcdb777cc)
- 🎛 [Controls: Live edit component examples](https://medium.com/storybookjs/storybook-controls-ce82af93e430)
- 🌐 [Composition: Combine multiple Storybooks](https://medium.com/storybookjs/storybook-composition-af0da9084fba)
-- 📚 [Documentation: Complete project overhaul](https://storybook.js.org/docs/react/get-started/introduction)
+- 📚 [Documentation: Complete project overhaul](https://storybook.js.org/docs/react/get-started)
6.0 contains hundreds more fixes, features, and tweaks. Browse the changelogs matching `6.0.0-alpha.*`, `6.0.0-beta.*`, and `6.0.0-rc.*` for the full list of changes. See [MIGRATION.md](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md) to upgrade from `5.3` or earlier.
diff --git a/CODEOWNERS b/CODEOWNERS
index b0e8ad0575d4..2e23565e1f5a 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -26,8 +26,6 @@
/code/addons/links/ @yannbf @JReinhold
/code/addons/measure/ @yannbf @valentinpalkovic
/code/addons/outline/ @yannbf @valentinpalkovic
-/code/addons/storyshots-core/ @ndelangen
-/code/addons/storyshots-puppeteer/ @ndelangen
/code/addons/storysource/ @ndelangen
/code/addons/themes/ @JReinhold @Integrayshaun
/code/addons/toolbars/ @ndelangen @JReinhold
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 78993afd8386..d90fef7e5ee5 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -55,4 +55,4 @@ yarn task --task dev --template --start-from=publish
# Contributing to Storybook
-For further advice on how to contribute, please refer to our [NEW contributing guide on the Storybook website](https://storybook.js.org/docs/react/contribute/how-to-contribute).
+For further advice on how to contribute, please refer to our [NEW contributing guide on the Storybook website](https://storybook.js.org/docs/contribute).
diff --git a/MAINTAINERS.md b/MAINTAINERS.md
index 191dc42d5b90..e7640a31d10e 100644
--- a/MAINTAINERS.md
+++ b/MAINTAINERS.md
@@ -25,7 +25,7 @@ This document outlines some of the processes that the maintainers should adhere
| compatibility with other tools | Issue, bug, or pull request between Storybook and other tools (e.g., [Nuxt](https://nuxtjs.org/)) |
| components | Issue, bug, or pull request related to Storybook's internal components |
| composition | Issue, bug, or pull request related to Storybook [Composition](/docs/sharing/storybook-composition.md) |
-| configuration | Issue, bug, or pull request related to Storybook [configuration](/docs/configure/overview.md) |
+| configuration | Issue, bug, or pull request related to Storybook [configuration](/docs/configure/index.md) |
| core | Issue, bug, or pull request related to Storybook's Core |
| cra | Issue, bug, or pull request that affects Storybook's compatibility with Create React APP ([CRA](https://create-react-app.dev/docs/getting-started/)) |
| CSF | Issue, bug, or pull request related to Storybook's [Component Story Format (CSF)](/docs/api/csf.md) |
diff --git a/MIGRATION.md b/MIGRATION.md
index 4495d71096a8..d116de268ec3 100644
--- a/MIGRATION.md
+++ b/MIGRATION.md
@@ -1,5 +1,13 @@
Migration
+- [From version 7.x to 8.0.0](#from-version-7x-to-800)
+ - [Implicit actions can not be used during rendering (for example in the play function)](#implicit-actions-can-not-be-used-during-rendering-for-example-in-the-play-function)
+ - [Core changes](#core-changes)
+ - [React v18 in the manager UI (including addons)](#react-v18-in-the-manager-ui-including-addons)
+ - [Storyshots has been removed](#storyshots-has-been-removed)
+ - [UI layout state has changed shape](#ui-layout-state-has-changed-shape)
+ - [New UI and props for Button and IconButton components](#new-ui-and-props-for-button-and-iconbutton-components)
+ - [Icons is deprecated](#icons-is-deprecated)
- [From version 7.5.0 to 7.6.0](#from-version-750-to-760)
- [CommonJS with Vite is deprecated](#commonjs-with-vite-is-deprecated)
- [Using implicit actions during rendering is deprecated](#using-implicit-actions-during-rendering-is-deprecated)
@@ -41,6 +49,7 @@
- [7.0 feature flags removed](#70-feature-flags-removed)
- [Story context is prepared before for supporting fine grained updates](#story-context-is-prepared-before-for-supporting-fine-grained-updates)
- [Changed decorator order between preview.js and addons/frameworks](#changed-decorator-order-between-previewjs-and-addonsframeworks)
+ - [Dark mode detection](#dark-mode-detection)
- [7.0 core addons changes](#70-core-addons-changes)
- [Removed auto injection of @storybook/addon-actions decorator](#removed-auto-injection-of-storybookaddon-actions-decorator)
- [Addon-backgrounds: Removed deprecated grid parameter](#addon-backgrounds-removed-deprecated-grid-parameter)
@@ -311,6 +320,115 @@
- [Packages renaming](#packages-renaming)
- [Deprecated embedded addons](#deprecated-embedded-addons)
+## From version 7.x to 8.0.0
+
+### Implicit actions can not be used during rendering (for example in the play function)
+
+In Storybook 7, we inferred if the component accepts any action props,
+by checking if it starts with `onX` (for example `onClick`), or as configured by `actions.argTypesRegex`.
+If that was the case, we would fill in jest spies for those args automatically.
+
+```ts
+export default {
+ component: Button,
+};
+
+export const ButtonClick = {
+ play: async ({ args, canvasElement }) => {
+ await userEvent.click(within(canvasElement).getByRole('button'));
+ // args.onClick is a jest spy in 7.0
+ await expect(args.onClick).toHaveBeenCalled();
+ },
+};
+```
+
+In Storybook 8 this feature is removed, and spies have to added explicitly:
+
+```ts
+import { fn } from '@storybook/test';
+
+export default {
+ component: Button,
+ args: {
+ onClick: fn(),
+ },
+};
+
+export const ButtonClick = {
+ play: async ({ args, canvasElement }) => {
+ await userEvent.click(within(canvasElement).getByRole('button'));
+ await expect(args.onClick).toHaveBeenCalled();
+ },
+};
+```
+
+For more context, see this RFC:
+https://github.com/storybookjs/storybook/discussions/23649
+
+To summarize:
+
+- This makes CSF files less magical and more portable, so that CSF files will render the same in a test environment where docgen is not available.
+- This allows users and (test) integrators to run or build storybook without docgen, boosting the user performance and allows tools to give quicker feedback.
+- This will make sure that we can one day lazy load docgen, without changing how stories are rendered.
+
+### Core changes
+
+#### React v18 in the manager UI (including addons)
+
+Storybook 7 used React 16 in the manager. In Storybook 8 this is upgraded to react v18.
+Addons that inject UI into panels, tools, etc. are possibly affected by this.
+
+Addon authors are advised to upgrade to react v18.
+
+##### Storyshots has been removed
+
+Storyshots was an addon for storybook which allowed users to turn their stories into automated snapshot-tests.
+
+Every story would automatically be taken into account and created a snapshot-file for.
+
+Snapshot-testing has since fallen out of favor and is no longer recommended.
+
+In addition to it's limited use, and high chance of false-positives, storyshots ran code developed to run in the browser in NodeJS via JSDOM.
+JSDOM has limitations and is not a perfect emulation of the browser environment; therefore storyshots was always a pain to setup and maintain.
+
+The storybook team has build the test-runner as a direct replacement, which utilizes playwright to connect to an actual browser where storybook runs the code.
+
+In addition CSF has expanded to allow for play-function to be defined on stories, which allows for more complex testing scenarios, fully integrated within storybook itself (and supported by the test-runner, and not storyshots).
+
+Finally `storyStoreV7: true` (the default and only options in storybook 8), was not supported by storyshots.
+
+By removing storyshots, the storybook team was unblocked from moving (eventually) to an ESM-only storybook, which is a big step towards a more modern storybook.
+
+#### UI layout state has changed shape
+
+In Storybook 7 it was possible to use `addons.setConfig({...});` to configure Storybook UI features and behavior as documented [here (v7)](https://storybook.js.org/docs/7.3/react/configure/features-and-behavior), [(latest)](https://storybook.js.org/docs/react/configure/features-and-behavior). The state and API for the UI layout has changed:
+
+- `showNav: boolean` is now `navSize: number`, where the number represents the size of the sidebar in pixels.
+- `showPanel: boolean` is now split into `bottomPanelHeight: number` and `rightPanelWidth: number`, where the numbers represents the size of the panel in pixels.
+- `isFullscreen: boolean` is no longer supported, but can be achieved by setting a combination of the above.
+
+#### New UI and props for Button and IconButton components
+
+We used to have a lot of different buttons in `@storybook/components` that were not used anywhere. In Storybook 8.0 we are deprecating `Form.Button` and added a new `Button` component that can be used in all places. The `IconButton` component has also been updated to use the new `Button` component under the hood. Going forward addon creators and Storybook maintainers should use the new `Button` component instead of `Form.Button`.
+
+For the `Button` component, the following props are now deprecated:
+
+- `isLink` - Please use the `asChild` prop instead like this: `Link `
+- `primary` - Please use the `variant` prop instead.
+- `secondary` - Please use the `variant` prop instead.
+- `tertiary` - Please use the `variant` prop instead.
+- `gray` - Please use the `variant` prop instead.
+- `inForm` - Please use the `variant` prop instead.
+- `small` - Please use the `size` prop instead.
+- `outline` - Please use the `variant` prop instead.
+- `containsIcon`. Please add your icon as a child directly. No need for this prop anymore.
+
+The `IconButton` doesn't have any deprecated props but it now uses the new `Button` component under the hood so all props for `IconButton` will be the same as `Button`.
+
+#### Icons is deprecated
+
+In Storybook 8.0 we are introducing a new icon library available with `@storybook/icons`. We are deprecating the `Icons` component in `@storybook/components` and recommend that addon creators and Storybook maintainers use the new `@storybook/icons` component instead.
+
## From version 7.5.0 to 7.6.0
#### CommonJS with Vite is deprecated
@@ -988,7 +1106,7 @@ import ReadMe from './README.md?raw';
#### Stories field in .storybook/main.js is mandatory
In 6.x, the `stories` key field in `.storybook/main.js` was optional. In 7.0, it is mandatory.
-Please follow up the [Configure your Storybook project](https://storybook.js.org/docs/react/configure/overview#configure-your-storybook-project) section to configure your Storybook project.
+Please follow up the [Configure your Storybook project](https://storybook.js.org/docs/react/configure/#configure-your-storybook-project) section to configure your Storybook project.
#### Stricter global types
@@ -1089,6 +1207,14 @@ export default {
};
```
+#### Dark mode detection
+
+Storybook 7 uses `prefers-color-scheme` to detects your system's dark mode preference if a theme is not set.
+
+Earlier versions used the light theme by default, so if you don't set a theme and your system's settings are in dark mode, this could surprise you.
+
+To learn more about theming, read our [documentation](https://storybook.js.org/docs/react/configure/theming).
+
### 7.0 core addons changes
#### Removed auto injection of @storybook/addon-actions decorator
diff --git a/code/.eslintrc.js b/code/.eslintrc.js
index 953ccaf79d25..d298ea5a9f68 100644
--- a/code/.eslintrc.js
+++ b/code/.eslintrc.js
@@ -28,6 +28,7 @@ module.exports = {
'react-hooks/rules-of-hooks': 'off',
'import/extensions': 'off', // for mjs, we sometimes need extensions
'jest/no-done-callback': 'off',
+ 'jsx-a11y/control-has-associated-label': 'off',
'@typescript-eslint/dot-notation': [
'error',
{
@@ -140,13 +141,7 @@ module.exports = {
},
})),
{
- files: [
- '**/__tests__/**',
- '**/__testfixtures__/**',
- '**/*.test.*',
- '**/*.stories.*',
- '**/storyshots-*/**/stories/**',
- ],
+ files: ['**/__tests__/**', '**/__testfixtures__/**', '**/*.test.*', '**/*.stories.*'],
rules: {
'@typescript-eslint/no-empty-function': 'off',
'import/no-extraneous-dependencies': 'off',
diff --git a/code/.yarnrc.yml b/code/.yarnrc.yml
index 360474b5bcc8..2cee4e0d364c 100644
--- a/code/.yarnrc.yml
+++ b/code/.yarnrc.yml
@@ -7,8 +7,6 @@ logFilters:
level: discard
- code: YN0076
level: discard
- - level: discard
- pattern: '@workspace:addons/storyshots-*/'
nodeLinker: node-modules
@@ -27,3 +25,5 @@ unsafeHttpWhitelist:
yarnPath: ../.yarn/releases/yarn-4.0.0.cjs
installStatePath: '../.yarn/code-install-state.gz'
+# Sometimes you get a "The remote archive doesn't match the expected checksum" error, uncommenting this line will fix it
+# checksumBehavior: 'update'
diff --git a/code/addons/a11y/package.json b/code/addons/a11y/package.json
index 9b0cbad18636..8410e7675f90 100644
--- a/code/addons/a11y/package.json
+++ b/code/addons/a11y/package.json
@@ -60,17 +60,18 @@
"@storybook/client-logger": "workspace:*",
"@storybook/components": "workspace:*",
"@storybook/global": "^5.0.0",
+ "@storybook/icons": "^1.2.1",
"@storybook/manager-api": "workspace:*",
"@storybook/preview-api": "workspace:*",
"@storybook/theming": "workspace:*",
"@storybook/types": "workspace:*",
- "@testing-library/react": "^11.2.2",
+ "@testing-library/react": "^14.0.0",
"lodash": "^4.17.21",
- "react": "^16.8.0",
- "react-dom": "^16.8.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
"react-resize-detector": "^7.1.2",
"resize-observer-polyfill": "^1.5.1",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/addons/a11y/src/components/A11YPanel.tsx b/code/addons/a11y/src/components/A11YPanel.tsx
index 7855cd9396ac..9552b7951e9d 100644
--- a/code/addons/a11y/src/components/A11YPanel.tsx
+++ b/code/addons/a11y/src/components/A11YPanel.tsx
@@ -2,7 +2,8 @@ import React, { useCallback, useMemo, useState } from 'react';
import { styled } from '@storybook/theming';
-import { ActionBar, Icons, ScrollArea } from '@storybook/components';
+import { ActionBar, ScrollArea } from '@storybook/components';
+import { SyncIcon, CheckIcon } from '@storybook/icons';
import type { AxeResults } from 'axe-core';
import { useChannel, useParameter, useStorybookState } from '@storybook/manager-api';
@@ -21,9 +22,7 @@ export enum RuleType {
INCOMPLETION,
}
-const Icon = styled(Icons)({
- height: 12,
- width: 12,
+const Icon = styled(SyncIcon)({
marginRight: 4,
});
@@ -108,7 +107,7 @@ export const A11YPanel: React.FC = () => {
'Rerun tests'
) : (
<>
- Tests completed
+ Tests completed
>
),
onClick: handleManual,
@@ -164,7 +163,7 @@ export const A11YPanel: React.FC = () => {
)}
{status === 'running' && (
- Please wait while the accessibility scan is running ...
+ Please wait while the accessibility scan is running ...
)}
{(status === 'ready' || status === 'ran') && (
diff --git a/code/addons/a11y/src/components/A11yContext.tsx b/code/addons/a11y/src/components/A11yContext.tsx
index fcd2523164bd..8410a646ce65 100644
--- a/code/addons/a11y/src/components/A11yContext.tsx
+++ b/code/addons/a11y/src/components/A11yContext.tsx
@@ -52,7 +52,10 @@ const defaultResult = {
violations: [],
};
-export const A11yContextProvider: React.FC = ({ active, ...props }) => {
+export const A11yContextProvider: React.FC> = ({
+ active,
+ ...props
+}) => {
const [results, setResults] = useAddonState(ADDON_ID, defaultResult);
const [tab, setTab] = React.useState(0);
const [highlighted, setHighlighted] = React.useState([]);
diff --git a/code/addons/a11y/src/components/Tabs.tsx b/code/addons/a11y/src/components/Tabs.tsx
index ba4a1fb8689a..a3b85809b084 100644
--- a/code/addons/a11y/src/components/Tabs.tsx
+++ b/code/addons/a11y/src/components/Tabs.tsx
@@ -87,8 +87,8 @@ const List = styled.div(({ theme }) => ({
interface TabsProps {
tabs: {
- label: JSX.Element;
- panel: JSX.Element;
+ label: React.ReactElement;
+ panel: React.ReactElement;
items: Result[];
type: RuleType;
}[];
diff --git a/code/addons/a11y/src/components/VisionSimulator.tsx b/code/addons/a11y/src/components/VisionSimulator.tsx
index b66f8eef297d..f604bef57161 100644
--- a/code/addons/a11y/src/components/VisionSimulator.tsx
+++ b/code/addons/a11y/src/components/VisionSimulator.tsx
@@ -1,8 +1,9 @@
import type { ReactNode } from 'react';
import React, { useState } from 'react';
import { Global, styled } from '@storybook/theming';
-import { Icons, IconButton, WithTooltip, TooltipLinkList } from '@storybook/components';
+import { IconButton, WithTooltip, TooltipLinkList } from '@storybook/components';
+import { AccessibilityIcon } from '@storybook/icons';
import { Filters } from './ColorFilters';
const iframeId = 'storybook-preview-iframe';
@@ -144,7 +145,7 @@ export const VisionSimulator = () => {
onDoubleClick={() => setFilter(null)}
>
-
+
diff --git a/code/addons/actions/README.md b/code/addons/actions/README.md
index 71bf4a2f53d6..80d2bd5d746c 100644
--- a/code/addons/actions/README.md
+++ b/code/addons/actions/README.md
@@ -8,13 +8,13 @@ Storybook Addon Actions can be used to display data received by event handlers i
## Installation
-Actions is part of [essentials](https://storybook.js.org/docs/react/essentials/introduction) and so is installed in all new Storybooks by default. If you need to add it to your Storybook, you can run:
+Actions is part of [essentials](https://storybook.js.org/docs/react/essentials) and so is installed in all new Storybooks by default. If you need to add it to your Storybook, you can run:
```sh
npm i -D @storybook/addon-actions
```
-Then, add following content to [`.storybook/main.js`](https://storybook.js.org/docs/react/configure/overview#configure-your-storybook-project):
+Then, add following content to [`.storybook/main.js`](https://storybook.js.org/docs/react/configure/#configure-your-storybook-project):
```js
export default {
diff --git a/code/addons/actions/package.json b/code/addons/actions/package.json
index 059a6f210cc3..840c7481df18 100644
--- a/code/addons/actions/package.json
+++ b/code/addons/actions/package.json
@@ -77,11 +77,11 @@
"@storybook/preview-api": "workspace:*",
"@storybook/theming": "workspace:*",
"@storybook/types": "workspace:*",
- "react": "^16.8.0",
- "react-dom": "^16.8.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
"react-inspector": "^6.0.0",
"telejson": "^7.2.0",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/addons/actions/src/components/ActionLogger/index.tsx b/code/addons/actions/src/components/ActionLogger/index.tsx
index f4231a8474ff..a3e48337107f 100644
--- a/code/addons/actions/src/components/ActionLogger/index.tsx
+++ b/code/addons/actions/src/components/ActionLogger/index.tsx
@@ -1,4 +1,4 @@
-import type { FC } from 'react';
+import type { FC, PropsWithChildren } from 'react';
import React, { Fragment } from 'react';
import { styled, withTheme } from '@storybook/theming';
import type { Theme } from '@storybook/theming';
@@ -9,7 +9,10 @@ import { ActionBar, ScrollArea } from '@storybook/components';
import { Action, InspectorContainer, Counter } from './style';
import type { ActionDisplay } from '../../models';
-const UnstyledWrapped: FC<{ className?: string }> = ({ children, className }) => (
+const UnstyledWrapped: FC> = ({
+ children,
+ className,
+}) => (
{children}
diff --git a/code/addons/actions/src/typings.d.ts b/code/addons/actions/src/typings.d.ts
index fba51cec4ab6..4ae6735dbc30 100644
--- a/code/addons/actions/src/typings.d.ts
+++ b/code/addons/actions/src/typings.d.ts
@@ -1 +1 @@
-declare var FEATURES: import('@storybook/types').StorybookConfig['features'];
+declare var FEATURES: import('@storybook/types').StorybookConfigRaw['features'];
diff --git a/code/addons/backgrounds/README.md b/code/addons/backgrounds/README.md
index 62c88e19a7e7..481ba54bcd2f 100644
--- a/code/addons/backgrounds/README.md
+++ b/code/addons/backgrounds/README.md
@@ -8,7 +8,7 @@ Storybook Addon Backgrounds can be used to change background colors inside the p
## Installation
-Backgrounds is part of [essentials](https://storybook.js.org/docs/react/essentials/introduction) and so is installed in all new Storybooks by default. If you need to add it to your Storybook, you can run:
+Backgrounds is part of [essentials](https://storybook.js.org/docs/react/essentials) and so is installed in all new Storybooks by default. If you need to add it to your Storybook, you can run:
```sh
npm i -D @storybook/addon-backgrounds
@@ -16,7 +16,7 @@ npm i -D @storybook/addon-backgrounds
## Configuration
-Then, add following content to [`.storybook/main.js`](https://storybook.js.org/docs/react/configure/overview#configure-your-storybook-project):
+Then, add following content to [`.storybook/main.js`](https://storybook.js.org/docs/react/configure/#configure-your-storybook-project):
```js
export default {
diff --git a/code/addons/backgrounds/package.json b/code/addons/backgrounds/package.json
index 28fe642a9c23..88479d56d2bd 100644
--- a/code/addons/backgrounds/package.json
+++ b/code/addons/backgrounds/package.json
@@ -53,6 +53,7 @@
},
"dependencies": {
"@storybook/global": "^5.0.0",
+ "@storybook/icons": "^1.2.1",
"memoizerific": "^1.11.3",
"ts-dedent": "^2.0.0"
},
@@ -63,9 +64,9 @@
"@storybook/preview-api": "workspace:*",
"@storybook/theming": "workspace:*",
"@storybook/types": "workspace:*",
- "react": "^16.8.0",
- "react-dom": "^16.8.0",
- "typescript": "~4.9.3"
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/addons/backgrounds/src/containers/BackgroundSelector.tsx b/code/addons/backgrounds/src/containers/BackgroundSelector.tsx
index d941f178b788..87bf6e84f133 100644
--- a/code/addons/backgrounds/src/containers/BackgroundSelector.tsx
+++ b/code/addons/backgrounds/src/containers/BackgroundSelector.tsx
@@ -4,8 +4,9 @@ import memoize from 'memoizerific';
import { useParameter, useGlobals } from '@storybook/manager-api';
import { logger } from '@storybook/client-logger';
-import { Icons, IconButton, WithTooltip, TooltipLinkList } from '@storybook/components';
+import { IconButton, WithTooltip, TooltipLinkList } from '@storybook/components';
+import { PhotoIcon } from '@storybook/icons';
import { PARAM_KEY as BACKGROUNDS_PARAM_KEY } from '../constants';
import { ColorIcon } from '../components/ColorIcon';
import type {
@@ -140,7 +141,7 @@ export const BackgroundSelector: FC = memo(function BackgroundSelector() {
title="Change the background of the preview"
active={selectedBackgroundColor !== 'transparent' || isTooltipVisible}
>
-
+
diff --git a/code/addons/backgrounds/src/containers/GridSelector.tsx b/code/addons/backgrounds/src/containers/GridSelector.tsx
index 80d6477884b4..64ac3cf9c4aa 100644
--- a/code/addons/backgrounds/src/containers/GridSelector.tsx
+++ b/code/addons/backgrounds/src/containers/GridSelector.tsx
@@ -2,8 +2,9 @@ import type { FC } from 'react';
import React, { memo } from 'react';
import { useGlobals, useParameter } from '@storybook/manager-api';
-import { Icons, IconButton } from '@storybook/components';
+import { IconButton } from '@storybook/components';
+import { GridIcon } from '@storybook/icons';
import { PARAM_KEY as BACKGROUNDS_PARAM_KEY } from '../constants';
export const GridSelector: FC = memo(function GridSelector() {
@@ -30,7 +31,7 @@ export const GridSelector: FC = memo(function GridSelector() {
})
}
>
-
+
);
});
diff --git a/code/addons/controls/README.md b/code/addons/controls/README.md
index cb37957a0766..0622e23a302c 100644
--- a/code/addons/controls/README.md
+++ b/code/addons/controls/README.md
@@ -8,13 +8,13 @@
## Installation
-Controls is part of [essentials](https://storybook.js.org/docs/react/essentials/introduction) and so is installed in all new Storybooks by default. If you need to add it to your Storybook, you can run:
+Controls is part of [essentials](https://storybook.js.org/docs/react/essentials) and so is installed in all new Storybooks by default. If you need to add it to your Storybook, you can run:
```sh
npm i -D @storybook/addon-controls
```
-Then, add following content to [`.storybook/main.js`](https://storybook.js.org/docs/react/configure/overview#configure-your-storybook-project):
+Then, add following content to [`.storybook/main.js`](https://storybook.js.org/docs/react/configure/#configure-your-storybook-project):
```js
export default {
diff --git a/code/addons/controls/package.json b/code/addons/controls/package.json
index cdac72d747b6..90ea2642a762 100644
--- a/code/addons/controls/package.json
+++ b/code/addons/controls/package.json
@@ -64,8 +64,8 @@
"@storybook/preview-api": "workspace:*",
"@storybook/theming": "workspace:*",
"@storybook/types": "workspace:*",
- "react": "^16.8.0",
- "react-dom": "^16.8.0"
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
},
"publishConfig": {
"access": "public"
diff --git a/code/addons/controls/template/stories/basics.stories.ts b/code/addons/controls/template/stories/basics.stories.ts
index 812f66ebc0e3..b1d636d2a790 100644
--- a/code/addons/controls/template/stories/basics.stories.ts
+++ b/code/addons/controls/template/stories/basics.stories.ts
@@ -78,6 +78,5 @@ export const Defined = {
// parameters: {
// docs: { disable: true },
// chromatic: { disable: true },
-// storyshots: { disable: true },
// },
// };
diff --git a/code/addons/docs/package.json b/code/addons/docs/package.json
index 3dc510919b18..87122e127f54 100644
--- a/code/addons/docs/package.json
+++ b/code/addons/docs/package.json
@@ -120,9 +120,9 @@
},
"devDependencies": {
"@rollup/pluginutils": "^5.0.2",
- "react": "^16.14.0",
- "react-dom": "^16.8.0",
- "typescript": "~4.9.3",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "typescript": "^5.3.2",
"vite": "^4.0.4"
},
"peerDependencies": {
diff --git a/code/addons/docs/src/DocsRenderer.tsx b/code/addons/docs/src/DocsRenderer.tsx
index 42d8d279b749..f87aac472f68 100644
--- a/code/addons/docs/src/DocsRenderer.tsx
+++ b/code/addons/docs/src/DocsRenderer.tsx
@@ -1,3 +1,4 @@
+import type { PropsWithChildren } from 'react';
import React, { Component } from 'react';
import { renderElement, unmountElement } from '@storybook/react-dom-shim';
import type { Renderer, Parameters, DocsContextProps, DocsRenderFunction } from '@storybook/types';
@@ -10,9 +11,11 @@ export const defaultComponents: Record = {
...HeadersMdx,
};
-class ErrorBoundary extends Component<{
- showException: (err: Error) => void;
-}> {
+class ErrorBoundary extends Component<
+ PropsWithChildren<{
+ showException: (err: Error) => void;
+ }>
+> {
state = { hasError: false };
static getDerivedStateFromError() {
diff --git a/code/addons/docs/src/preset.ts b/code/addons/docs/src/preset.ts
index c716775bdfa9..2ead78d53ac6 100644
--- a/code/addons/docs/src/preset.ts
+++ b/code/addons/docs/src/preset.ts
@@ -4,7 +4,7 @@ import remarkSlug from 'remark-slug';
import remarkExternalLinks from 'remark-external-links';
import { dedent } from 'ts-dedent';
-import type { DocsOptions, Indexer, Options, StorybookConfig } from '@storybook/types';
+import type { DocsOptions, Indexer, Options, PresetProperty } from '@storybook/types';
import type { CsfPluginOptions } from '@storybook/csf-plugin';
import type { JSXOptions, CompileOptions } from '@storybook/mdx2-csf';
import { global } from '@storybook/global';
@@ -160,7 +160,7 @@ export const createStoriesMdxIndexer = (legacyMdx1?: boolean): Indexer => ({
},
});
-const indexers: StorybookConfig['experimental_indexers'] = (existingIndexers) =>
+const indexers: PresetProperty<'experimental_indexers'> = (existingIndexers) =>
[createStoriesMdxIndexer(global.FEATURES?.legacyMdx1)].concat(existingIndexers || []);
const docs = (docsOptions: DocsOptions) => {
@@ -171,7 +171,7 @@ const docs = (docsOptions: DocsOptions) => {
};
};
-export const addons: StorybookConfig['addons'] = [
+export const addons: PresetProperty<'addons'> = [
require.resolve('@storybook/react-dom-shim/dist/preset'),
];
diff --git a/code/addons/docs/src/typings.d.ts b/code/addons/docs/src/typings.d.ts
index 79397caba109..04846593c045 100644
--- a/code/addons/docs/src/typings.d.ts
+++ b/code/addons/docs/src/typings.d.ts
@@ -9,6 +9,6 @@ declare module 'sveltedoc-parser' {
export function parse(options: any): Promise;
}
-declare var FEATURES: import('@storybook/types').StorybookConfig['features'];
+declare var FEATURES: import('@storybook/types').StorybookConfigRaw['features'];
declare var LOGLEVEL: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent' | undefined;
diff --git a/code/addons/essentials/package.json b/code/addons/essentials/package.json
index f0430f0c75ad..3a47f5855578 100644
--- a/code/addons/essentials/package.json
+++ b/code/addons/essentials/package.json
@@ -77,7 +77,7 @@
},
"devDependencies": {
"@storybook/vue": "workspace:*",
- "typescript": "^4.9.3"
+ "typescript": "^5.3.2"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
diff --git a/code/addons/essentials/src/index.ts b/code/addons/essentials/src/index.ts
index 358cf796a579..b2d879c2d794 100644
--- a/code/addons/essentials/src/index.ts
+++ b/code/addons/essentials/src/index.ts
@@ -3,15 +3,55 @@ import { logger } from '@storybook/node-logger';
import { serverRequire } from '@storybook/core-common';
interface PresetOptions {
+ /**
+ * Allow to use @storybook/addon-actions
+ * @see https://storybook.js.org/addons/@storybook/addon-actions
+ * @default true
+ */
actions?: boolean;
+ /**
+ * Allow to use @storybook/addon-backgrounds
+ * @see https://storybook.js.org/addons/@storybook/addon-backgrounds
+ * @default true
+ */
backgrounds?: boolean;
configDir: string;
+ /**
+ * Allow to use @storybook/addon-controls
+ * @see https://storybook.js.org/addons/@storybook/addon-controls
+ * @default true
+ */
controls?: boolean;
+ /**
+ * Allow to use @storybook/addon-docs
+ * @see https://storybook.js.org/addons/@storybook/addon-docs
+ * @default true
+ */
docs?: boolean;
+ /**
+ * Allow to use @storybook/addon-measure
+ * @see https://storybook.js.org/addons/@storybook/addon-measure
+ * @default true
+ */
measure?: boolean;
+ /**
+ * Allow to use @storybook/addon-outline
+ * @see https://storybook.js.org/addons/@storybook/addon-outline
+ * @default true
+ */
outline?: boolean;
themes?: boolean;
+ /**
+ * Allow to use @storybook/addon-toolbars
+ * @see https://storybook.js.org/addons/@storybook/addon-toolbars
+ * @default true
+ */
toolbars?: boolean;
+ /**
+ * Allow to use @storybook/addon-viewport
+ * @see https://storybook.js.org/addons/@storybook/addon-viewport
+ * @default true
+ */
viewport?: boolean;
}
diff --git a/code/addons/gfm/package.json b/code/addons/gfm/package.json
index 1803127eab5f..f3eeb90b0501 100644
--- a/code/addons/gfm/package.json
+++ b/code/addons/gfm/package.json
@@ -49,7 +49,7 @@
"ts-dedent": "^2.0.0"
},
"devDependencies": {
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/addons/highlight/README.md b/code/addons/highlight/README.md
index e4b245acc5fd..5f7ffbe0c3a9 100644
--- a/code/addons/highlight/README.md
+++ b/code/addons/highlight/README.md
@@ -8,7 +8,7 @@ Use it to call attention to particular parts of the story. Or use it to enhance
## Usage
-This addon requires Storybook 6.5 or later. Highlight is part of [essentials](https://storybook.js.org/docs/react/essentials/introduction) and so is installed in all new Storybooks by default. If you need to add it to your Storybook, you can run the following command:
+This addon requires Storybook 6.5 or later. Highlight is part of [essentials](https://storybook.js.org/docs/react/essentials) and so is installed in all new Storybooks by default. If you need to add it to your Storybook, you can run the following command:
yarn:
diff --git a/code/addons/highlight/package.json b/code/addons/highlight/package.json
index 10fdafc7c9af..120613f19673 100644
--- a/code/addons/highlight/package.json
+++ b/code/addons/highlight/package.json
@@ -54,7 +54,7 @@
"@storybook/core-events": "workspace:*",
"@storybook/preview-api": "workspace:*",
"@types/webpack-env": "^1.16.0",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/addons/interactions/README.md b/code/addons/interactions/README.md
index 6167242008f9..815a83b1804d 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/jest @storybook/testing-library
+yarn add -D @storybook/addon-interactions @storybook/test
```
within `.storybook/main.js`:
@@ -24,19 +24,17 @@ Note that `@storybook/addon-interactions` must be listed **after** `@storybook/a
## Usage
-Interactions relies on "instrumented" versions of Jest and Testing Library, that you import from `@storybook/jest` and
-`@storybook/testing-library` 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 { Button } from './Button';
-import { expect } from '@storybook/jest';
-import { within, userEvent } from '@storybook/testing-library';
+import { within, userEvent, expect, fn } from '@storybook/test';
export default {
title: 'Button',
component: Button,
- argTypes: {
- onClick: { action: true },
+ args: {
+ onClick: fn(),
},
};
@@ -50,12 +48,10 @@ Demo.play = async ({ args, canvasElement }) => {
};
```
-In order to enable step-through debugging, calls to `userEvent.*`, `fireEvent`, `findBy*`, `waitFor*` and `expect` have to
+In order to enable step-through debugging in the addon panel, calls to `userEvent.*`, `fireEvent`, `findBy*`, `waitFor*` and `expect` have to
be `await`-ed. While debugging, these functions return a Promise that won't resolve until you continue to the next step.
While you can technically use `screen`, it's recommended to use `within(canvasElement)`. Besides giving you a better error
message when a DOM element can't be found, it will also ensure your play function is compatible with Storybook Docs.
-Any `args` that are marked as an `action` (typically via `argTypes` or `argTypesRegex`) will be automatically wrapped in
-a [Jest mock function](https://jestjs.io/docs/jest-object#jestfnimplementation) so you can assert invocations. See
-[addon-actions](https://storybook.js.org/docs/react/essentials/actions) for how to setup actions.
+Note that the `fn` function will assign a spy to your arg, so that you can assert invocations.
diff --git a/code/addons/interactions/package.json b/code/addons/interactions/package.json
index 4c69b33816f9..b5e9140bbdc4 100644
--- a/code/addons/interactions/package.json
+++ b/code/addons/interactions/package.json
@@ -49,6 +49,7 @@
},
"dependencies": {
"@storybook/global": "^5.0.0",
+ "@storybook/icons": "^1.2.1",
"@storybook/types": "workspace:*",
"jest-mock": "^27.0.6",
"polished": "^4.2.2",
@@ -68,9 +69,9 @@
"@storybook/theming": "workspace:*",
"@types/node": "^18.0.0",
"formik": "^2.2.9",
- "react": "^16.8.0",
- "react-dom": "^16.8.0",
- "typescript": "~4.9.3"
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/addons/interactions/src/Panel.tsx b/code/addons/interactions/src/Panel.tsx
index 0bf1111fca01..3d5733710d19 100644
--- a/code/addons/interactions/src/Panel.tsx
+++ b/code/addons/interactions/src/Panel.tsx
@@ -148,32 +148,33 @@ export const Panel = memo<{ storyId: string }>(function PanelMemoized({ storyId
},
[STORY_RENDER_PHASE_CHANGED]: (event) => {
if (event.newPhase === 'preparing') {
- set((s) => ({
+ set({
controlStates: INITIAL_CONTROL_STATES,
isErrored: false,
pausedAt: undefined,
interactions: [],
isPlaying: false,
- isRerunAnimating: false,
- scrollTarget,
- collapsed: new Set() as Set,
hasException: false,
caughtException: undefined,
interactionsCount: 0,
- }));
+ });
return;
}
- set((s) => ({
- ...s,
- isPlaying: event.newPhase === 'playing',
- pausedAt: undefined,
- ...(event.newPhase === 'rendering'
- ? {
- isErrored: false,
- caughtException: undefined,
- }
- : {}),
- }));
+ set((s) => {
+ const newState: typeof s = {
+ ...s,
+ isPlaying: event.newPhase === 'playing',
+ pausedAt: undefined,
+ ...(event.newPhase === 'rendering'
+ ? {
+ isErrored: false,
+ caughtException: undefined,
+ }
+ : {}),
+ };
+
+ return newState;
+ });
},
[STORY_THREW_EXCEPTION]: () => {
set((s) => ({ ...s, isErrored: true }));
diff --git a/code/addons/interactions/src/components/Interaction.tsx b/code/addons/interactions/src/components/Interaction.tsx
index af2bea6bd20b..5c817e71a0aa 100644
--- a/code/addons/interactions/src/components/Interaction.tsx
+++ b/code/addons/interactions/src/components/Interaction.tsx
@@ -1,9 +1,10 @@
import * as React from 'react';
-import { IconButton, Icons, TooltipNote, WithTooltip } from '@storybook/components';
+import { IconButton, TooltipNote, WithTooltip } from '@storybook/components';
import { type Call, CallStates, type ControlStates } from '@storybook/instrumenter';
import { styled, typography } from '@storybook/theming';
import { transparentize } from 'polished';
+import { ListUnorderedIcon } from '@storybook/icons';
import { Expected, MatcherResult, Received } from './MatcherResult';
import { MethodCall } from './MethodCall';
import { StatusIcon } from './StatusIcon';
@@ -197,7 +198,7 @@ export const Interaction = ({
tooltip={ }
>
-
+
)}
diff --git a/code/addons/interactions/src/components/MethodCall.tsx b/code/addons/interactions/src/components/MethodCall.tsx
index a12aaa4f1a29..d45efa646813 100644
--- a/code/addons/interactions/src/components/MethodCall.tsx
+++ b/code/addons/interactions/src/components/MethodCall.tsx
@@ -431,7 +431,7 @@ export const MethodCall = ({
callId ? (
) : (
- {elem}
+ {elem as any}
),
,
. ,
diff --git a/code/addons/interactions/src/components/Subnav.tsx b/code/addons/interactions/src/components/Subnav.tsx
index 3d2e5c41d1a3..4a9dda73a28a 100644
--- a/code/addons/interactions/src/components/Subnav.tsx
+++ b/code/addons/interactions/src/components/Subnav.tsx
@@ -3,7 +3,6 @@ import React from 'react';
import {
Button,
IconButton,
- Icons,
Separator,
P,
TooltipNote,
@@ -14,6 +13,13 @@ import type { Call, ControlStates } from '@storybook/instrumenter';
import { CallStates } from '@storybook/instrumenter';
import { styled } from '@storybook/theming';
+import {
+ FastForwardIcon,
+ PlayBackIcon,
+ PlayNextIcon,
+ RewindIcon,
+ SyncIcon,
+} from '@storybook/icons';
import { StatusBadge } from './StatusBadge';
import type { Controls } from './InteractionsPanel';
@@ -135,7 +141,7 @@ export const Subnav: React.FC = ({
onClick={controls.start}
disabled={!controlStates.start}
>
-
+
@@ -146,7 +152,7 @@ export const Subnav: React.FC = ({
onClick={controls.back}
disabled={!controlStates.back}
>
-
+
@@ -157,7 +163,7 @@ export const Subnav: React.FC = ({
onClick={controls.next}
disabled={!controlStates.next}
>
-
+
@@ -168,13 +174,13 @@ export const Subnav: React.FC = ({
onClick={controls.end}
disabled={!controlStates.end}
>
-
+
}>
-
+
diff --git a/code/addons/jest/README.md b/code/addons/jest/README.md
index 50678d636094..ec2cc8a34c6c 100644
--- a/code/addons/jest/README.md
+++ b/code/addons/jest/README.md
@@ -20,7 +20,7 @@ Or if you're using yarn as a package manager:
## Configuration
-Register the addon in your [`.storybook/main.js`](https://storybook.js.org/docs/react/configure/overview#configure-your-storybook-project):
+Register the addon in your [`.storybook/main.js`](https://storybook.js.org/docs/react/configure/#configure-your-storybook-project):
```js
export default {
@@ -133,7 +133,7 @@ Default.parameters = {
### Global level
To avoid importing the results of the tests in each story, you can update
-your [`.storybook/preview.js`](https://storybook.js.org/docs/react/configure/overview#configure-story-rendering) and include a decorator allowing you to display the results only for the stories that have the `jest` parameter defined:
+your [`.storybook/preview.js`](https://storybook.js.org/docs/react/configure/#configure-story-rendering) and include a decorator allowing you to display the results only for the stories that have the `jest` parameter defined:
```js
// .storybook/preview.js
diff --git a/code/addons/jest/package.json b/code/addons/jest/package.json
index 249bd810a2f8..9a32eabe1c98 100644
--- a/code/addons/jest/package.json
+++ b/code/addons/jest/package.json
@@ -65,10 +65,10 @@
"@storybook/manager-api": "workspace:*",
"@storybook/preview-api": "workspace:*",
"@storybook/theming": "workspace:*",
- "react": "^16.8.0",
- "react-dom": "^16.8.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
"react-resize-detector": "^7.1.2",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/addons/jest/src/components/Message.tsx b/code/addons/jest/src/components/Message.tsx
index 96aa5ed30262..9245e66bc0fb 100644
--- a/code/addons/jest/src/components/Message.tsx
+++ b/code/addons/jest/src/components/Message.tsx
@@ -1,4 +1,4 @@
-import type { FC } from 'react';
+import type { FC, ReactElement } from 'react';
import React, { Fragment } from 'react';
import { styled } from '@storybook/theming';
@@ -12,7 +12,7 @@ const passStartToken = '[32m';
const stackTraceStartToken = 'at';
const titleEndToken = ':';
-type MsgElement = string | JSX.Element;
+type MsgElement = string | ReactElement;
class TestDetail {
description!: MsgElement[];
diff --git a/code/addons/links/package.json b/code/addons/links/package.json
index 28c509559a72..565ef44f6f80 100644
--- a/code/addons/links/package.json
+++ b/code/addons/links/package.json
@@ -75,7 +75,7 @@
"@storybook/router": "workspace:*",
"@storybook/types": "workspace:*",
"fs-extra": "^11.1.0",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
diff --git a/code/addons/links/src/react/components/link.test.tsx b/code/addons/links/src/react/components/link.test.tsx
index dd19a2eab69f..43538b927aeb 100644
--- a/code/addons/links/src/react/components/link.test.tsx
+++ b/code/addons/links/src/react/components/link.test.tsx
@@ -61,11 +61,8 @@ describe('LinkTo', () => {
});
describe('events', () => {
- it('should select the kind and story on click', () => {
- const channel = {
- emit: jest.fn(),
- on: jest.fn(),
- } as any;
+ it('should select the kind and story on click', async () => {
+ const channel = mockChannel() as any;
mockAddons.getChannel.mockReturnValue(channel);
render(
@@ -74,7 +71,15 @@ describe('LinkTo', () => {
link
);
- userEvent.click(screen.getByText('link'));
+
+ await waitFor(() => {
+ expect(screen.getByText('link')).toHaveAttribute(
+ 'href',
+ 'originpathname?path=/story/foo--bar'
+ );
+ });
+
+ await userEvent.click(screen.getByText('link'));
expect(channel.emit).toHaveBeenLastCalledWith(
SELECT_STORY,
diff --git a/code/addons/measure/README.md b/code/addons/measure/README.md
index ca1387d474c8..8e280f150124 100644
--- a/code/addons/measure/README.md
+++ b/code/addons/measure/README.md
@@ -12,7 +12,7 @@ Storybook addon for inspecting layouts and visualizing the box model.
## Usage
-This addon requires Storybook 6.3 or later. Measure is part of [essentials](https://storybook.js.org/docs/react/essentials/introduction) and so is installed in all new Storybooks by default. If you need to add it to your Storybook, you can run:
+This addon requires Storybook 6.3 or later. Measure is part of [essentials](https://storybook.js.org/docs/react/essentials) and so is installed in all new Storybooks by default. If you need to add it to your Storybook, you can run:
```sh
npm i -D @storybook/addon-measure
diff --git a/code/addons/measure/package.json b/code/addons/measure/package.json
index cd563ea34ed3..e1e256d5863a 100644
--- a/code/addons/measure/package.json
+++ b/code/addons/measure/package.json
@@ -65,6 +65,7 @@
},
"dependencies": {
"@storybook/global": "^5.0.0",
+ "@storybook/icons": "^1.2.1",
"tiny-invariant": "^1.3.1"
},
"devDependencies": {
@@ -74,9 +75,9 @@
"@storybook/manager-api": "workspace:*",
"@storybook/preview-api": "workspace:*",
"@storybook/types": "workspace:*",
- "react": "^16.8.0",
- "react-dom": "^16.8.0",
- "typescript": "~4.9.3"
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/addons/measure/src/Tool.tsx b/code/addons/measure/src/Tool.tsx
index 2e68078aa06b..16af4de9af96 100644
--- a/code/addons/measure/src/Tool.tsx
+++ b/code/addons/measure/src/Tool.tsx
@@ -1,6 +1,7 @@
import React, { useCallback, useEffect } from 'react';
import { useGlobals, useStorybookApi } from '@storybook/manager-api';
-import { Icons, IconButton } from '@storybook/components';
+import { IconButton } from '@storybook/components';
+import { RulerIcon } from '@storybook/icons';
import { TOOL_ID, ADDON_ID } from './constants';
export const Tool = () => {
@@ -33,7 +34,7 @@ export const Tool = () => {
title="Enable measure"
onClick={toggleMeasure}
>
-
+
);
};
diff --git a/code/addons/outline/README.md b/code/addons/outline/README.md
index 301c140c3cff..e73da501a3f6 100644
--- a/code/addons/outline/README.md
+++ b/code/addons/outline/README.md
@@ -6,13 +6,13 @@ Storybook Addon Outline can be used for visually debugging CSS layout and alignm
## Usage
-Requires Storybook 6.1 or later. Outline is part of [essentials](https://storybook.js.org/docs/react/essentials/introduction) and so is installed in all new Storybooks by default. If you need to add it to your Storybook, you can run:
+Requires Storybook 6.1 or later. Outline is part of [essentials](https://storybook.js.org/docs/react/essentials) and so is installed in all new Storybooks by default. If you need to add it to your Storybook, you can run:
```sh
npm i -D @storybook/addon-outline
```
-Then, add following content to [`.storybook/main.js`](https://storybook.js.org/docs/react/configure/overview#configure-your-storybook-project):
+Then, add following content to [`.storybook/main.js`](https://storybook.js.org/docs/react/configure/#configure-your-storybook-project):
```js
export default {
diff --git a/code/addons/outline/package.json b/code/addons/outline/package.json
index 8f25fabfd51d..c3027f76585b 100644
--- a/code/addons/outline/package.json
+++ b/code/addons/outline/package.json
@@ -55,6 +55,7 @@
},
"dependencies": {
"@storybook/global": "^5.0.0",
+ "@storybook/icons": "^1.2.1",
"ts-dedent": "^2.0.0"
},
"devDependencies": {
@@ -64,9 +65,9 @@
"@storybook/manager-api": "workspace:*",
"@storybook/preview-api": "workspace:*",
"@storybook/types": "workspace:*",
- "react": "^16.8.0",
- "react-dom": "^16.8.0",
- "typescript": "~4.9.3"
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/addons/outline/src/OutlineSelector.tsx b/code/addons/outline/src/OutlineSelector.tsx
index 93bdf321df07..012477bae60c 100644
--- a/code/addons/outline/src/OutlineSelector.tsx
+++ b/code/addons/outline/src/OutlineSelector.tsx
@@ -1,6 +1,7 @@
import React, { memo, useCallback, useEffect } from 'react';
import { useGlobals, useStorybookApi } from '@storybook/manager-api';
-import { Icons, IconButton } from '@storybook/components';
+import { IconButton } from '@storybook/components';
+import { OutlineIcon } from '@storybook/icons';
import { ADDON_ID, PARAM_KEY } from './constants';
export const OutlineSelector = memo(function OutlineSelector() {
@@ -34,7 +35,7 @@ export const OutlineSelector = memo(function OutlineSelector() {
title="Apply outlines to the preview"
onClick={toggleOutline}
>
-
+
);
});
diff --git a/code/addons/storyshots-core/.eslintrc.js b/code/addons/storyshots-core/.eslintrc.js
deleted file mode 100644
index 79e820da0d30..000000000000
--- a/code/addons/storyshots-core/.eslintrc.js
+++ /dev/null
@@ -1,12 +0,0 @@
-module.exports = {
- settings: {
- 'import/core-modules': [
- '@storybook/angular',
- '@storybook/html',
- '@storybook/react',
- '@storybook/preact',
- '@storybook/vue',
- '@storybook/svelte',
- ],
- },
-};
diff --git a/code/addons/storyshots-core/README.md b/code/addons/storyshots-core/README.md
deleted file mode 100644
index 8a20edd2c7f3..000000000000
--- a/code/addons/storyshots-core/README.md
+++ /dev/null
@@ -1,795 +0,0 @@
-# StoryShots
-
-StoryShots adds automatic Jest Snapshot Testing for [Storybook](https://storybook.js.org/).
-
-[Framework Support](https://storybook.js.org/docs/react/api/frameworks-feature-support)
-
-![StoryShots In Action](https://raw.githubusercontent.com/storybookjs/storybook/next/code/addons/storyshots/storyshots-core/docs/storyshots-fail.png)
-
-To use StoryShots, you must use your existing Storybook stories as the input for Jest Snapshot Testing.
-
-## Getting Started
-
-Add the following module into your app.
-
-```sh
-yarn add @storybook/addon-storyshots --dev
-```
-
-## Configure Storyshots for HTML snapshots
-
-Create a new test file with the name `Storyshots.test.js`. (Or whatever the name you prefer, as long as it matches Jest's config [`testMatch`](http://facebook.github.io/jest/docs/en/configuration.html#testmatch-array-string)).
-Then add following content to it:
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-
-initStoryshots();
-```
-
-That's all.
-
-Now run your Jest test command. (Usually, `npm test`.) Then you can see all of your stories are converted as Jest snapshot tests.
-
-![Screenshot](https://raw.githubusercontent.com/storybookjs/storybook/next/code/addons/storyshots/storyshots-core/docs/storyshots.png)
-
-### Testing stories that rely on addon-added decorators
-
-If you have stories in your Storybook that can only render inside a decorator (for instance the [`apollo-storybook-decorator`](https://github.com/abhiaiyer91/apollo-storybook-decorator)), you'll need to ensure those decorators are applied in Storyshots.
-
-If you export those decorators from your `.storybook/preview.js` then Storyshots will apply those decorators for you in the same way that Storybook does. However if the addon _automatically_ adds the decorator for you (which is a new feature in Storybook 6.0), you will find the decorator does not get added in Storyshots. This is a limitation in Storyshots currently.
-
-To ensure such decorators get added, export them from `.storybook/preview.js`:
-
-```js
-import addonDecorator from 'some-addon';
-
-export const decorators = [addonDecorator];
-```
-
-## Configure your app for Jest
-
-In many cases, for example Create React App, it's already configured for Jest. You need to create a filename with the extension `.test.js`.
-
-If you still need to configure jest you can use the resources mentioned below:
-
-- [Getting Started - Jest Official Documentation](https://facebook.github.io/jest/docs/en/getting-started.html)
-- [Javascript Testing with Jest - Egghead](https://egghead.io/lessons/javascript-test-javascript-with-jest). **_paid content_**
-
-> Note: If you use React 16, you'll need to follow [these additional instructions](https://github.com/facebook/react/issues/9102#issuecomment-283873039).
->
-> Note: Make sure you have added the `json` extension to `moduleFileExtensions` in `jest.config.json`. If this is missing it leads to the [following error](https://github.com/storybookjs/storybook/issues/3728): `Cannot find module 'spdx-license-ids' from 'scan.js'`.
->
-> Note: Please make sure you are using `jsdom` as the testEnvironment on your jest config file.
-
-### Configure Jest to work with Webpack's [require.context()](https://webpack.js.org/guides/dependency-management/#require-context)
-
-**NOTE**: if you are using Storybook 5.3's `main.js` to list story files, this is no longer needed.
-
-Sometimes it's useful to configure Storybook with Webpack's require.context feature. You could be loading stories [one of two ways](https://github.com/storybookjs/storybook/blob/release/5.3/docs/src/pages/basics/writing-stories/index.md#loading-stories).
-
-1. If you're using the `storiesOf` API, you can integrate it this way:
-
-```js
-import { configure } from '@storybook/react';
-
-const req = require.context('../stories', true, /\.stories\.js$/); // <- import all the stories at once
-
-function loadStories() {
- req.keys().forEach((filename) => req(filename));
-}
-
-configure(loadStories, module);
-```
-
-2. If you're using Component Story Format (CSF), you'll integrate it like so:
-
-```js
-import { configure } from '@storybook/react';
-
-const req = require.context('../stories', true, /\.stories\.js$/); // <- import all the stories at once
-
-configure(req, module);
-```
-
-The problem here is that it will work only during the build with webpack,
-other tools may lack this feature. Since Storyshot is running under Jest,
-we need to polyfill this functionality to work with Jest. The easiest
-way is to integrate it to babel.
-
-You can do this with a Babel [plugin](https://github.com/smrq/babel-plugin-require-context-hook) or [macro](https://github.com/storybookjs/require-context.macro). If you're using `create-react-app` (v2 or above), use the macro.
-
-#### Option 1: Plugin
-
-First, install it:
-
-```sh
-yarn add babel-plugin-require-context-hook --dev
-```
-
-Next, it needs to be registered and loaded before each test. To register it, create a file with the following register function `.jest/register-context.js`:
-
-```js
-import registerRequireContextHook from 'babel-plugin-require-context-hook/register';
-registerRequireContextHook();
-```
-
-That file needs to be added as a setup file for Jest. To do that, add (or create) a property in Jest's config called [`setupFiles`](https://jestjs.io/docs/en/configuration.html#setupfiles-array). Add the file name and path to this array.
-
-```json
-setupFiles: ['/.jest/register-context.js']
-```
-
-Finally, add the plugin to `.babelrc`:
-
-```json
-{
- "presets": ["..."],
- "plugins": ["..."],
- "env": {
- "test": {
- "plugins": ["require-context-hook"]
- }
- }
-}
-```
-
-The plugin is only added to the test environment otherwise it could replace webpack's version of it.
-
-#### Option 2: Macro
-
-First, install it:
-
-```sh
-yarn add require-context.macro --dev
-```
-
-Now, inside of your Storybook config file, import the macro and run it in place of `require.context`, like so:
-
-```javascript
-import requireContext from 'require-context.macro';
-
-// const req = require.context('../stories', true, /\.stories\.js$/); <-- replaced
-const req = requireContext('../stories', true, /\.stories\.js$/);
-```
-
-### Configure Jest for React
-
-StoryShots addon for React is dependent on [react-test-renderer](https://github.com/facebook/react/tree/master/packages/react-test-renderer), but
-[doesn't](#deps-issue) install it, so you need to install it separately.
-
-```sh
-yarn add react-test-renderer --dev
-```
-
-### Configure Jest for Angular
-
-StoryShots addon for Angular is dependent on [jest-preset-angular](https://github.com/thymikee/jest-preset-angular), but
-[doesn't](#deps-issue) install it, so you need to install it separately.
-
-```sh
-yarn add jest-preset-angular
-```
-
-If you already use Jest for testing your angular app - probably you already have the needed jest configuration.
-Anyway you can add these lines to your jest config:
-
-```js
-module.exports = {
- globals: {
- __TRANSFORM_HTML__: true,
- },
- transform: {
- '^.+\\.jsx?$': 'babel-jest',
- '^.+\\.(ts|html)$': '/node_modules/jest-preset-angular/preprocessor.js',
- },
- moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node', '.html'],
-};
-```
-
-### Configure Jest for Vue
-
-StoryShots addon for Vue is dependent on [jest-vue-preprocessor](https://github.com/vire/jest-vue-preprocessor), but
-[doesn't](#deps-issue) install it, so you need to install it separately.
-
-```sh
-yarn add jest-vue-preprocessor
-```
-
-If you already use Jest for testing your vue app - probably you already have the needed jest configuration.
-Anyway you can add these lines to your jest config:
-
-```js
-module.exports = {
- transform: {
- '^.+\\.jsx?$': 'babel-jest',
- '.*\\.(vue)$': '/node_modules/jest-vue-preprocessor',
- },
- transformIgnorePatterns: ['/node_modules/(?!(@storybook/.*\\.vue$))'],
- moduleFileExtensions: ['vue', 'js', 'jsx', 'json', 'node'],
-};
-```
-
-### Configure Jest for Vue 3
-
-StoryShots addon for Vue is dependent on [vue-jest v5](https://www.npmjs.com/package/vue-jest/v/5.0.0-alpha.8), but
-[doesn't](#deps-issue) install it, so you need to install it separately.
-
-```sh
-yarn add vue-jest@5.0.0-alpha.8
-```
-
-If you already use Jest for testing your vue app - probably you already have the needed jest configuration.
-Anyway you can add these lines to your jest config:
-
-```js
-module.exports = {
- transform: {
- '^.+\\.jsx?$': 'babel-jest',
- '.*\\.(vue)$': '/node_modules/vue-jest',
- },
- transformIgnorePatterns: ['/node_modules/(?!(@storybook/.*\\.vue$))'],
- moduleFileExtensions: ['vue', 'js', 'jsx', 'json', 'node'],
-};
-```
-
-### Configure Jest for Preact
-
-StoryShots addon for Preact is dependent on [preact-render-to-string](https://github.com/preactjs/preact-render-to-string), but
-[doesn't](#deps-issue) install it, so you need to install it separately.
-
-```sh
-yarn add preact-render-to-string --dev
-```
-
-### Configure Jest for Web Components
-
-StoryShots addon for Web Components requires [jsdom](https://github.com/jsdom/jsdom) 16 or later to fully support the
-web component shadow dom. To use jsdom 16 or later you can set the Jest `testEnvironment` configuration key to
-`jest-environment-jsdom-sixteen`. This should work back to Jest 24 and is the default in Jest 26 and later.
-
-### Configure Jest for MDX Docs Add-On Stories
-
-If using the [Docs add-on](../../docs/README.md) with
-[MDX stories](../../docs/docs/mdx.md) you will need
-to configure Jest to transform MDX stories into something Storyshots can understand:
-
-Add the following to your Jest configuration:
-
-```json
-{
- "transform": {
- "^.+\\.[tj]sx?$": "babel-jest",
- "^.+\\.mdx?$": "@storybook/addon-docs/jest-transform-mdx"
- }
-}
-```
-
-### Why don't we install dependencies of each framework ?
-
-Storyshots addon is currently supporting React, Angular and Vue. Each framework needs its own packages to be integrated with Jest. We don't want people that use only React will need to bring other dependencies that do not make sense for them.
-
-`dependencies` - will installed an exact version of the particular dep - Storyshots can work with different versions of the same framework (let's say React v16 and React v15), that have to be compatible with a version of its plugin (react-test-renderer).
-
-`optionalDependencies` - behaves like a regular dependency, but do not fail the installation in case there is a problem to bring the dep.
-
-`peerDependencies` - listing all the deps in peer will trigger warnings during the installation - we don't want users to install unneeded deps by hand.
-
-`optionalPeerDependencies` - unfortunately there is nothing like this =(
-
-For more information read npm [docs](https://docs.npmjs.com/files/package.json#dependencies)
-
-### Using `createNodeMock` to mock refs
-
-`react-test-renderer` doesn't provide refs for rendered components. By
-default, it returns null when the refs are referenced. In order to mock
-out elements that rely on refs, you will have to use the
-`createNodeMock` option [added to React](https://reactjs.org/blog/2016/11/16/react-v15.4.0.html#mocking-refs-for-snapshot-testing) starting with version 15.4.0.
-
-Here is an example of how to specify the `createNodeMock` option in Storyshots:
-
-```js
-import initStoryshots, { snapshotWithOptions } from '@storybook/addon-storyshots';
-import TextareaThatUsesRefs from '../component/TextareaThatUsesRefs';
-
-initStoryshots({
- test: snapshotWithOptions({
- createNodeMock: (element) => {
- if (element.type === TextareaThatUsesRefs) {
- return document.createElement('textarea');
- }
- },
- }),
-});
-```
-
-Provide a function to have story-specific options:
-
-```js
-initStoryshots({
- test: snapshotWithOptions((story) => ({
- createNodeMock: (element) => {
- if (story.name == 'foobar') {
- return null;
- }
- return element;
- },
- })),
-});
-```
-
-### Using a custom renderer
-
-By design, [`react-test-renderer` doesn't use a browser environment or JSDOM](https://github.com/facebook/react/issues/20589). Because of this difference, some stories might render in your browser, but not in Storyshots. If you encounter this problem, you may want to switch for an higher level renderer such as `mount` from Enzyme or `render` from React Testing Library.
-
-#### Example with React Testing Library
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-import { render } from '@testing-library/react';
-
-const reactTestingLibrarySerializer = {
- print: (val, serialize, indent) => serialize(val.container.firstChild),
- test: (val) => val && val.hasOwnProperty('container'),
-};
-
-initStoryshots({
- renderer: render,
- snapshotSerializers: [reactTestingLibrarySerializer],
-});
-```
-
-#### Example with Enzyme
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-import { mount } from 'enzyme';
-
-initStoryshots({
- renderer: mount,
-});
-```
-
-If you are using enzyme, you need to make sure jest knows how to serialize rendered components.
-For that, you can pass an enzyme-compatible snapshotSerializer (like [enzyme-to-json](https://github.com/adriantoine/enzyme-to-json), [jest-serializer-enzyme](https://github.com/rogeliog/jest-serializer-enzyme) etc.) with the `snapshotSerializer` option (see below).
-
-### StoryShots for async rendered components
-
-You can make use of [Jest done callback](https://jestjs.io/docs/en/asynchronous) to test components that render asynchronously. This callback is passed as param to test method passed to `initStoryshots(...)` when the `asyncJest` option is given as true.
-
-#### Example
-
-The following example shows how we can use the **done callback** to take StoryShots of a [Relay](http://facebook.github.io/relay/) component. Each kind of story is written into its own snapshot file with the use of `getSnapshotFileName`.
-
-Add _stories of UserForm_ in the file: UserForm.story.jsx
-
-```jsx
-/* global module */
-import React from 'react';
-import { QueryRenderer } from 'react-relay';
-import { storiesOf } from '@storybook/react';
-
-// Use the same queries used in YOUR app routes
-import { newUserFormQuery, editUserFormQuery } from 'app/routes';
-import UserFormContainer from 'app/users/UserForm';
-
-// YOUR function to generate a Relay Environment mock.
-// See https://github.com/1stdibs/relay-mock-network-layer for more info
-import getEnvironment from 'test/support/relay-environment-mock';
-
-// User test data YOU generated for your tests
-import { user } from 'test/support/data/index';
-
-// Use this function to return a new Environment for each story
-const Environment = () =>
- getEnvironment({
- mocks: {
- Node: () => ({ __typename: 'User' }),
- User: () => user,
- },
- });
-
-/**
-
- NOTICE that the QueryRenderer render its children via its render props.
-
- If we don't take the StoryShot async then we will only see the QueryRenderer in the StoryShot.
-
- The following QueryRenderer returns null in the first render (it can be a loading indicator instead in real file) and then when it gets the data to respond to query, it renders again with props containing the data for the Component
- */
-const renderStory = (query, environment, variables = {}) => (
- {
- if (error) {
- console.error(error);
- } else if (props) {
- return ;
- }
- return null;
- }}
- />
-);
-
-storiesOf('users/UserForm', module)
- .add('New User', () => {
- const environment = new Environment();
- return renderStory(newUserFormQuery, environment);
- })
- .add('Editing User', () => {
- const environment = new Environment();
- return renderStory(editUserFormQuery, environment, { id: user.id });
- });
-```
-
-Then, init Storyshots for async component in the file: StoryShots.test.js
-
-```jsx
-import initStoryshots, { Stories2SnapsConverter } from '@storybook/addon-storyshots';
-import { mount } from 'enzyme';
-import toJson from 'enzyme-to-json';
-
-// Runner
-initStoryshots({
- asyncJest: true, // this is the option that activates the async behaviour
- test: ({
- story,
- context,
- done, // --> callback passed to test method when asyncJest option is true
- }) => {
- const converter = new Stories2SnapsConverter();
- const snapshotFilename = converter.getSnapshotFileName(context);
- const storyElement = story.render();
-
- // mount the story
- const tree = mount(storyElement);
-
- // wait until the mount is updated, in our app mostly by Relay
- // but maybe something else updating the state of the component
- // somewhere
- const waitTime = 1;
- setTimeout(() => {
- if (snapshotFilename) {
- expect(toJson(tree.update())).toMatchSpecificSnapshot(snapshotFilename);
- }
-
- done();
- }, waitTime);
- },
- // other options here
-});
-```
-
-NOTICE that When using the `asyncJest: true` option, you also must specify a `test` method that calls the `done()` callback.
-
-This is a really powerful technique to write stories of Relay components because it integrates data fetching with component rendering. So instead of passing data props manually, we can let Relay do the job for us as it does in our application.
-
-Whenever you change your data requirements by adding (and rendering) or (accidentally) deleting fields in your graphql query fragments, you'll get a different snapshot and thus an error in the StoryShot test.
-
-## Using a custom directory
-
-Depending on your project's needs, you can configure the `@storybook/addon-storyshots` to use a custom directory for the snapshots. You can read more about it in the [official docs](https://storybook.js.org/docs/react/writing-tests/snapshot-testing).
-
-## Options
-
-### `config`
-
-The `config` parameter must be a function that helps to configure storybook like the `preview.js` does.
-If it's not specified, storyshots will try to use [configPath](#configPath) parameter.
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-
-initStoryshots({
- config: ({ configure }) =>
- configure(() => {
- require('../stories/Button.story.js');
- }, module),
-});
-```
-
-### `configPath`
-
-By default, Storyshots assumes the config directory path for your project as below:
-
-- Storybook for React: `.storybook`
-- Storybook for React Native: `storybook`
-
-If you are using a different config directory path, you could change it like this:
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-
-initStoryshots({
- configPath: '.my-storybook-config-dir',
-});
-```
-
-Or, as a more complex example, if we have a package in our `lerna` project called `app` with the path `./packages/app/src/__tests__/storyshots.js` and the storybook config directory `./packages/app/.storybook`:
-
-```js
-import path from 'path';
-import initStoryshots from '@storybook/addon-storyshots';
-
-initStoryshots({ configPath: path.resolve(__dirname, '../../.storybook') });
-```
-
-`configPath` can also specify path to the `preview.js` itself. In this case, config directory will be
-a base directory of the `configPath`. It may be useful when the `preview.js` for test should differ from the
-original one. It also may be useful for separating tests to different test configs:
-
-```js
-initStoryshots({
- configPath: '.my-storybook-config-dir/testConfig1.js',
-});
-
-initStoryshots({
- configPath: '.my-storybook-config-dir/testConfig2.js',
-});
-```
-
-### `suite`
-
-By default, Storyshots groups stories inside a Jest test suite called "Storyshots". You could change it like this:
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-
-initStoryshots({
- suite: 'MyStoryshots',
-});
-```
-
-### `storyKindRegex`
-
-If you'd like to only run a subset of the stories for your snapshot tests based on the story's kind:
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-
-initStoryshots({
- storyKindRegex: /^MyComponent$/,
-});
-```
-
-This can be useful if you want to separate the snapshots in directories next to each component. See an example [here](https://github.com/storybookjs/storybook/issues/892).
-
-If you want to run all stories except stories of a specific kind, you can write an inverse regex which is true for all kinds except those with a specific word such as `DontTest`
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-
-initStoryshots({
- storyKindRegex: /^((?!.*?DontTest).)*$/,
-});
-```
-
-This can be useful while testing react components which make use of the findDomNode API since they always fail with snapshot testing
-while using react-test-renderer see [here](https://github.com/facebook/react/issues/8324)
-
-### `storyNameRegex`
-
-If you'd like to only run a subset of the stories for your snapshot tests based on the story's name:
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-
-initStoryshots({
- storyNameRegex: /buttons/,
-});
-```
-
-### `framework`
-
-If you are running tests from outside of your app's directory, storyshots' detection of which framework you are using may fail. Pass `"react"` or `"react-native"` to short-circuit this.
-
-For example:
-
-```js
-// storybook.test.js
-
-import path from 'path';
-import initStoryshots from '@storybook/addon-storyshots';
-
-initStoryshots({
- framework: 'react', // Manually specify the project's framework
- configPath: path.join(__dirname, '.storybook'),
- integrityOptions: { cwd: path.join(__dirname, 'src', 'stories') },
- // Other configurations
-});
-```
-
-Use this table as a reference for manually specifying the framework.
-
-| angular | html | preact |
-| ------- | ------------ | -------------- |
-| react | react-native | vue3 |
-| svelte | vue | web-components |
-
-### `test`
-
-Run a custom test function for each story, rather than the default (a vanilla snapshot test).
-Setting `test` will take precedence over the `renderer` option.
-You can still overwrite what renderer is used for the test function:
-
-```js
-import initStoryshots, { renderWithOptions } from '@storybook/addon-storyshots';
-import { mount } from 'enzyme';
-
-initStoryshots({
- test: renderWithOptions({
- renderer: mount,
- }),
-});
-```
-
-### `renderer`
-
-Pass a custom renderer (such as enzymes `mount`) to record snapshots.
-This may be necessary if you want to use React features that are not supported by the default test renderer,
-such as **ref** or **Portals**.
-Note that setting `test` overrides `renderer`.
-
-### `snapshotSerializers`
-
-Pass an array of snapshotSerializers to the jest runtime that serializes your story (such as enzyme-to-json).
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-import { createSerializer } from 'enzyme-to-json';
-
-initStoryshots({
- renderer: mount,
- snapshotSerializers: [createSerializer()],
-});
-```
-
-This option needs to be set if either:
-
-- the multiSnapshot function is used to create multiple snapshot files (i.e. one per story), since it ignores any serializers specified in your jest config.
-- serializers not specified in your jest config should be used when snapshotting stories.
-
-### `serializer` (deprecated)
-
-Pass a custom serializer (such as enzyme-to-json) to serialize components to snapshot-comparable data. The functionality of this option is completely covered by [snapshotSerializers](#snapshotserializers) which should be used instead.
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-import toJSON from 'enzyme-to-json';
-
-initStoryshots({
- renderer: mount,
- serializer: toJSON,
-});
-```
-
-This option only needs to be set if the default `snapshotSerializers` is not set in your jest config.
-
-### `stories2snapsConverter`
-
-This parameter should be an instance of the [`Stories2SnapsConverter`](src/Stories2SnapsConverter.js) (or a derived from it) Class that is used to convert story-file name to snapshot-file name and vice versa.
-
-By default, the instance of this class is created with these default options:
-
-```js
-{
- snapshotsDirName: '__snapshots__',
- snapshotExtension: '.storyshot',
- storiesExtensions: ['.js', '.jsx', '.ts', '.tsx'],
-}
-```
-
-This class might be overridden to extend the existing conversion functionality or instantiated to provide different options:
-
-```js
-import initStoryshots, { Stories2SnapsConverter } from '@storybook/addon-storyshots';
-
-initStoryshots({
- stories2snapsConverter: new Stories2SnapsConverter({
- snapshotExtension: '.storypuke',
- storiesExtensions: ['.foo'],
- }),
-});
-```
-
-## Exports
-
-Apart from the default export (`initStoryshots`), Storyshots also exports some named test functions (see the `test` option above):
-
-### `snapshot`
-
-The default, render the story as normal and take a Jest snapshot.
-
-### `renderOnly`
-
-Just render the story, don't check the output at all. This is useful as a low-effort way of smoke testing your
-components to ensure they do not error.
-
-### `snapshotWithOptions(options)`
-
-Like the default, but allows you to specify a set of options for the test renderer. [See for example here](https://github.com/storybookjs/storybook/blob/b915b5439786e0edb17d7f5ab404bba9f7919381/examples/test-cra/src/storyshots.test.js#L14-L16).
-
-### `renderWithOptions(options)`
-
-Like the default, but allows you to specify a set of options for the renderer, just like `snapshotWithOptions`.
-
-### `multiSnapshotWithOptions(options)`
-
-Like `snapshotWithOptions`, but generate a separate snapshot file for each stories file rather than a single monolithic file (as is the convention in Jest). This makes it dramatically easier to review changes. If you'd like the benefit of separate snapshot files, but don't have custom options to pass, you can pass an empty object.
-If you use [Component Story Format](https://storybook.js.org/docs/react/api/csf), you may also need to add an additional Jest transform to automate detecting story file names:
-
-```js
-// jest.config.js
-export default {
- transform: {
- '^.+\\.stories\\.jsx?$': '@storybook/addon-storyshots/injectFileName',
- '^.+\\.jsx?$': 'babel-jest',
- },
-};
-```
-
-#### integrityOptions
-
-This option is useful when running test with `multiSnapshotWithOptions(options)` in order to track snapshots are matching the stories. (disabled by default).
-The value is a [settings](https://github.com/isaacs/node-glob#options) to a `glob` object, that searches for the snapshot files.
-
-```js
-initStoryshots({
- integrityOptions: { cwd: __dirname }, // it will start searching from the current directory
- test: multiSnapshotWithOptions(),
-});
-```
-
-### `shallowSnapshot`
-
-Take a snapshot of a shallow-rendered version of the component. Note that this option will be overridden if you pass a `renderer` option.
-
-### `Stories2SnapsConverter`
-
-This is a class that generates snapshot's name based on the story (kind, story & filename) and vice versa.
-
-###### Example:
-
-Let's say we wanted to create a test function for shallow && multi-file snapshots:
-
-```js
-import initStoryshots, { Stories2SnapsConverter } from '@storybook/addon-storyshots';
-import { shallow } from 'enzyme';
-import toJson from 'enzyme-to-json';
-
-const converter = new Stories2SnapsConverter();
-
-initStoryshots({
- test: ({ story, context }) => {
- const snapshotFileName = converter.getSnapshotFileName(context);
- const storyElement = story.render();
- const shallowTree = shallow(storyElement);
-
- if (snapshotFileName) {
- expect(toJson(shallowTree)).toMatchSpecificSnapshot(snapshotFileName);
- }
- },
-});
-```
-
-### `asyncJest`
-
-Enables Jest `done()` callback in the StoryShots tests for async testing. See [StoryShots for async rendered components](#storyshots-for-async-rendered-components) for more info.
-
-## Story Parameters
-
-### `disable`
-
-Some stories are difficult or impossible to snapshot, such as those covering components that use external DOM-modifying libraries, and those that deliberately throw errors. It is possible to skip stories like these by giving them a parameter of `storyshots: {disable: true}`. There is also a shorthand for this, `storyshots: false`.
-
-```js
-export const Exception = () => {
- throw new Error('storyFn threw an error! WHOOPS');
-};
-Exception.storyName = 'story throws exception';
-Exception.parameters = {
- storyshots: { disable: true },
-};
-```
diff --git a/code/addons/storyshots-core/docs/storyshots-fail.png b/code/addons/storyshots-core/docs/storyshots-fail.png
deleted file mode 100644
index a85498d2ff2f..000000000000
Binary files a/code/addons/storyshots-core/docs/storyshots-fail.png and /dev/null differ
diff --git a/code/addons/storyshots-core/docs/storyshots.png b/code/addons/storyshots-core/docs/storyshots.png
deleted file mode 100644
index 991e6c0bc18c..000000000000
Binary files a/code/addons/storyshots-core/docs/storyshots.png and /dev/null differ
diff --git a/code/addons/storyshots-core/injectFileName.js b/code/addons/storyshots-core/injectFileName.js
deleted file mode 100644
index 991bce4fc5f3..000000000000
--- a/code/addons/storyshots-core/injectFileName.js
+++ /dev/null
@@ -1,23 +0,0 @@
-const { ScriptTransformer } = require('@jest/transform');
-
-const getNextTransformer = (fileName, config) => {
- const self = config.transform.find(([pattern]) => new RegExp(pattern).test(fileName));
- return new ScriptTransformer({
- ...config,
- transform: config.transform.filter((entry) => entry !== self),
- });
-};
-
-module.exports = {
- process(src, fileName, config, { instrument }) {
- const transformer = getNextTransformer(fileName, config);
- const { code } = transformer.transformSource(fileName, src, instrument);
-
- return `${code};
-if(exports.default != null) {
- exports.default.parameters = exports.default.parameters || {};
- exports.default.parameters.fileName = '${fileName.replace(/\\/g, '\\\\')}';
-}
-`;
- },
-};
diff --git a/code/addons/storyshots-core/jest.config.js b/code/addons/storyshots-core/jest.config.js
deleted file mode 100644
index 0115c67e5629..000000000000
--- a/code/addons/storyshots-core/jest.config.js
+++ /dev/null
@@ -1,12 +0,0 @@
-const path = require('path');
-const baseConfig = require('../../jest.config.browser');
-
-module.exports = {
- ...baseConfig,
- snapshotSerializers: [...baseConfig.snapshotSerializers, 'enzyme-to-json/serializer'],
- transform: {
- ...baseConfig.transform,
- '^.+\\.stories\\.[jt]sx?$': '@storybook/addon-storyshots/injectFileName',
- },
- displayName: __dirname.split(path.sep).slice(-2).join(path.posix.sep),
-};
diff --git a/code/addons/storyshots-core/package.json b/code/addons/storyshots-core/package.json
deleted file mode 100644
index ab7e10f31a92..000000000000
--- a/code/addons/storyshots-core/package.json
+++ /dev/null
@@ -1,153 +0,0 @@
-{
- "name": "@storybook/addon-storyshots",
- "version": "7.6.0-beta.2",
- "description": "Take a code snapshot of every story automatically with Jest",
- "keywords": [
- "addon",
- "storybook",
- "test"
- ],
- "homepage": "https://github.com/storybookjs/storybook/tree/next/code/addons/storyshots-core",
- "bugs": {
- "url": "https://github.com/storybookjs/storybook/issues"
- },
- "repository": {
- "type": "git",
- "url": "https://github.com/storybookjs/storybook.git",
- "directory": "code/addons/storyshots-core"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/storybook"
- },
- "license": "MIT",
- "main": "dist/index.js",
- "module": "dist/index.mjs",
- "types": "dist/index.d.ts",
- "files": [
- "dist/**/*",
- "README.md",
- "*.js",
- "*.mjs",
- "*.d.ts",
- "!src/**/*"
- ],
- "scripts": {
- "check": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/check.ts",
- "prep": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/tsc.ts"
- },
- "dependencies": {
- "@jest/transform": "^29.3.1",
- "@storybook/babel-plugin-require-context-hook": "1.0.1",
- "@storybook/client-api": "workspace:*",
- "@storybook/core-common": "workspace:*",
- "@storybook/core-webpack": "workspace:*",
- "@storybook/global": "^5.0.0",
- "@storybook/preview-api": "workspace:*",
- "@storybook/types": "workspace:*",
- "@types/jest-specific-snapshot": "^0.5.6",
- "glob": "^10.0.0",
- "jest-specific-snapshot": "^8.0.0",
- "preact-render-to-string": "^5.1.19",
- "pretty-format": "^29.0.0",
- "react-test-renderer": "^16.8.0 || ^17.0.0 || ^18.0.0",
- "read-pkg-up": "^7.0.1",
- "ts-dedent": "^2.0.0"
- },
- "devDependencies": {
- "@angular/core": "^16.0.0-rc.4",
- "@angular/platform-browser-dynamic": "^16.0.0-rc.4",
- "@emotion/jest": "^11.8.0",
- "@storybook/addon-docs": "workspace:*",
- "@storybook/angular": "workspace:*",
- "@storybook/react": "workspace:*",
- "@storybook/vue": "workspace:*",
- "@storybook/vue3": "workspace:*",
- "babel-loader": "^9.1.2",
- "enzyme": "^3.11.0",
- "enzyme-adapter-react-16": "^1.15.5",
- "enzyme-to-json": "^3.6.1",
- "jest-preset-angular": "^13.0.1",
- "jest-vue-preprocessor": "^1.7.1",
- "react-test-renderer": "^16",
- "rxjs": "^6.6.3",
- "vue-jest": "^5.0.0-alpha.8"
- },
- "peerDependencies": {
- "@angular/core": ">=13.0.0",
- "@angular/platform-browser-dynamic": ">=13.0.0",
- "@storybook/angular": "*",
- "@storybook/react": "*",
- "@storybook/vue": "*",
- "@storybook/vue3": "*",
- "jest": "*",
- "jest-preset-angular": " >= 12.2.3",
- "jest-vue-preprocessor": "*",
- "preact": "^10.5.13",
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
- "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
- "rxjs": "*",
- "svelte": "*",
- "vue": "*",
- "vue-jest": "*"
- },
- "peerDependenciesMeta": {
- "@angular/core": {
- "optional": true
- },
- "@angular/platform-browser-dynamic": {
- "optional": true
- },
- "@storybook/angular": {
- "optional": true
- },
- "@storybook/react": {
- "optional": true
- },
- "@storybook/vue": {
- "optional": true
- },
- "@storybook/vue3": {
- "optional": true
- },
- "jest-preset-angular": {
- "optional": true
- },
- "jest-vue-preprocessor": {
- "optional": true
- },
- "preact": {
- "optional": true
- },
- "react": {
- "optional": true
- },
- "react-dom": {
- "optional": true
- },
- "rxjs": {
- "optional": true
- },
- "svelte": {
- "optional": true
- },
- "vue": {
- "optional": true
- },
- "vue-jest": {
- "optional": true
- }
- },
- "publishConfig": {
- "access": "public"
- },
- "bundler": {},
- "gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae17",
- "storybook": {
- "displayName": "Storyshots",
- "icon": "https://user-images.githubusercontent.com/263385/101991676-48cdf300-3c7c-11eb-8aa1-944dab6ab29b.png",
- "unsupportedFrameworks": [
- "ember"
- ]
- }
-}
diff --git a/code/addons/storyshots-core/preset.js b/code/addons/storyshots-core/preset.js
deleted file mode 100644
index 501f6e0c1310..000000000000
--- a/code/addons/storyshots-core/preset.js
+++ /dev/null
@@ -1,4 +0,0 @@
-// storyshots is not a typical addon because it's just a command-line tool
-// nevertheless if you add it to .storybook/main.js it shouldn't complain
-// https://github.com/storybookjs/storybook/issues/7959
-module.exports = {};
diff --git a/code/addons/storyshots-core/project.json b/code/addons/storyshots-core/project.json
deleted file mode 100644
index d4369a8485c9..000000000000
--- a/code/addons/storyshots-core/project.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "@storybook/addon-storyshots",
- "$schema": "../../node_modules/nx/schemas/project-schema.json",
- "implicitDependencies": [],
- "type": "library"
-}
diff --git a/code/addons/storyshots-core/src/Stories2SnapsConverter.test.ts b/code/addons/storyshots-core/src/Stories2SnapsConverter.test.ts
deleted file mode 100644
index 916ee94eb34c..000000000000
--- a/code/addons/storyshots-core/src/Stories2SnapsConverter.test.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-import { Stories2SnapsConverter } from './Stories2SnapsConverter';
-
-const target = new Stories2SnapsConverter();
-
-describe('getSnapshotFileName', () => {
- it('fileName is provided - snapshot is stored in __snapshots__ dir', () => {
- const context = { fileName: 'foo.js', kind: 'kind' };
-
- const result = target.getSnapshotFileName(context);
- const platformAgnosticResult = result?.replace(/\\|\//g, '/');
-
- // This is an absolute path, so we need to use `toContain()`
- expect(platformAgnosticResult).toContain('__snapshots__/foo.storyshot');
- });
-
- it('fileName with multiple extensions is provided - only the last extension is replaced', () => {
- const context = { fileName: 'foo.web.stories.js', kind: 'kind' };
-
- const result = target.getSnapshotFileName(context);
- const platformAgnosticResult = result?.replace(/\\|\//g, '/');
-
- // This is an absolute path, so we need to use `toContain()`
- expect(platformAgnosticResult).toContain('__snapshots__/foo.web.stories.storyshot');
- });
-
- it('fileName with dir is provided - __snapshots__ dir is created inside another dir', () => {
- const context = { fileName: 'test/foo.js', kind: 'kind' };
-
- const result = target.getSnapshotFileName(context);
- const platformAgnosticResult = result?.replace(/\\|\//g, '/');
-
- // This is an absolute path, so we need to use `toContain()`
- expect(platformAgnosticResult).toContain('test/__snapshots__/foo.storyshot');
- });
-});
-
-describe('getPossibleStoriesFiles', () => {
- it('storyshots is provided and all the posible stories file names are returned', () => {
- const storyshots = 'test/__snapshots__/foo.web.stories.storyshot';
-
- const result = target.getPossibleStoriesFiles(storyshots);
- const platformAgnosticResult = result.map((path) => path.replace(/\\|\//g, '/'));
-
- expect(platformAgnosticResult).toEqual([
- 'test/foo.web.stories.js',
- 'test/foo.web.stories.jsx',
- 'test/foo.web.stories.ts',
- 'test/foo.web.stories.tsx',
- 'test/foo.web.stories.mdx',
- ]);
- });
-});
diff --git a/code/addons/storyshots-core/src/Stories2SnapsConverter.ts b/code/addons/storyshots-core/src/Stories2SnapsConverter.ts
deleted file mode 100644
index 4d6788e6b278..000000000000
--- a/code/addons/storyshots-core/src/Stories2SnapsConverter.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-import path from 'path';
-import { dedent } from 'ts-dedent';
-
-const defaultOptions: Stories2SnapsConverterOptions = {
- snapshotsDirName: '__snapshots__',
- snapshotExtension: '.storyshot',
- storiesExtensions: ['.js', '.jsx', '.ts', '.tsx', '.mdx'],
-};
-
-export interface Stories2SnapsConverterOptions {
- storiesExtensions: string[];
- snapshotExtension: string;
- snapshotsDirName: string;
-}
-
-export class Stories2SnapsConverter {
- options: Stories2SnapsConverterOptions;
-
- constructor(options: Partial = {}) {
- this.options = {
- ...defaultOptions,
- ...options,
- };
- }
-
- getSnapshotExtension = () => this.options.snapshotExtension;
-
- getStoryshotFile(fileName: string) {
- const { dir, name } = path.parse(fileName);
- const { snapshotsDirName, snapshotExtension } = this.options;
-
- // Convert to absolute path, in case jest is not running in CWD,
- // else it will create snapshots with the wrong path
- const absDir = path.isAbsolute(dir) ? dir : path.resolve(dir);
-
- return path.format({
- dir: path.join(absDir, snapshotsDirName),
- name,
- ext: snapshotExtension,
- });
- }
-
- getSnapshotFileName(context: { fileName?: string; kind: any }) {
- const { fileName, kind } = context;
-
- if (!fileName) {
- // eslint-disable-next-line no-console
- console.warn(
- dedent`
- Storybook was unable to detect filename for stories of kind "${kind}".
- To fix it, add following to your jest.config.js:
- transform: {
- // should be above any other js transform like babel-jest
- '^.+\\.stories\\.js$': '@storybook/addon-storyshots/injectFileName',
- }
- `
- );
- return undefined;
- }
-
- return this.getStoryshotFile(fileName);
- }
-
- getPossibleStoriesFiles(storyshotFile: string) {
- const { dir, name } = path.parse(storyshotFile);
- const { storiesExtensions } = this.options;
-
- return storiesExtensions.map((ext) =>
- path.format({
- dir: path.dirname(dir),
- name,
- ext,
- })
- );
- }
-}
diff --git a/code/addons/storyshots-core/src/api/StoryshotsOptions.ts b/code/addons/storyshots-core/src/api/StoryshotsOptions.ts
deleted file mode 100644
index cbc853717de3..000000000000
--- a/code/addons/storyshots-core/src/api/StoryshotsOptions.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import type { GlobOptionsWithFileTypesFalse } from 'glob';
-import type { Stories2SnapsConverter } from '../Stories2SnapsConverter';
-import type { SupportedFramework } from '../frameworks';
-import type { RenderTree } from '../frameworks/Loader';
-
-export interface TestMethodOptions {
- story: any;
- context: any;
- renderTree: RenderTree;
- renderShallowTree: RenderTree;
- stories2snapsConverter: Stories2SnapsConverter;
- snapshotFileName?: string;
- options: any;
- done?: () => void;
-}
-
-export interface StoryshotsTestMethod {
- (args: TestMethodOptions): any;
- beforeAll?: () => void | Promise;
- beforeEach?: () => void | Promise;
- afterAll?: () => void | Promise;
- afterEach?: () => void | Promise;
-}
-
-export interface StoryshotsOptions {
- asyncJest?: boolean;
- config?: (options: any) => void;
- integrityOptions?: GlobOptionsWithFileTypesFalse | false;
- configPath?: string;
- suite?: string;
- storyKindRegex?: RegExp | string;
- storyNameRegex?: RegExp | string;
- framework?: SupportedFramework;
- test?: StoryshotsTestMethod;
- renderer?: Function;
- snapshotSerializers?: jest.SnapshotSerializerPlugin[];
- /**
- * @Deprecated The functionality of this option is completely covered by snapshotSerializers which should be used instead.
- */
- serializer?: any;
- stories2snapsConverter?: Stories2SnapsConverter;
-}
diff --git a/code/addons/storyshots-core/src/api/ensureOptionsDefaults.ts b/code/addons/storyshots-core/src/api/ensureOptionsDefaults.ts
deleted file mode 100644
index 742c85173bb7..000000000000
--- a/code/addons/storyshots-core/src/api/ensureOptionsDefaults.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import { snapshotWithOptions } from '../test-bodies';
-import { Stories2SnapsConverter } from '../Stories2SnapsConverter';
-import type { StoryshotsOptions } from './StoryshotsOptions';
-
-const ignore = ['**/node_modules/**'];
-const defaultStories2SnapsConverter = new Stories2SnapsConverter();
-
-function getIntegrityOptions({ integrityOptions }: StoryshotsOptions) {
- if (integrityOptions === false) {
- return false;
- }
-
- if (typeof integrityOptions !== 'object') {
- return false;
- }
-
- const ignoreOption: string[] = Array.isArray(integrityOptions.ignore)
- ? integrityOptions.ignore
- : [];
-
- return {
- ...integrityOptions,
- ignore: [...ignore, ...ignoreOption],
- absolute: true,
- };
-}
-
-function ensureOptionsDefaults(options: StoryshotsOptions) {
- const {
- suite = 'Storyshots',
- asyncJest,
- storyNameRegex,
- storyKindRegex,
- renderer,
- serializer,
- snapshotSerializers,
- stories2snapsConverter = defaultStories2SnapsConverter,
- test: testMethod = snapshotWithOptions({ renderer, serializer }),
- } = options;
-
- const integrityOptions = getIntegrityOptions(options);
-
- return {
- asyncJest,
- suite,
- storyNameRegex,
- storyKindRegex,
- stories2snapsConverter,
- testMethod,
- snapshotSerializers,
- integrityOptions,
- } as any;
-}
-
-export default ensureOptionsDefaults;
diff --git a/code/addons/storyshots-core/src/api/index.ts b/code/addons/storyshots-core/src/api/index.ts
deleted file mode 100644
index 932d728a6345..000000000000
--- a/code/addons/storyshots-core/src/api/index.ts
+++ /dev/null
@@ -1,109 +0,0 @@
-import { global } from '@storybook/global';
-import { addons, mockChannel } from '@storybook/preview-api';
-import ensureOptionsDefaults from './ensureOptionsDefaults';
-import snapshotsTests from './snapshotsTestsTemplate';
-import integrityTest from './integrityTestTemplate';
-import loadFramework from '../frameworks/frameworkLoader';
-import type { StoryshotsOptions } from './StoryshotsOptions';
-
-const { describe, window: globalWindow } = global;
-
-type TestMethod = 'beforeAll' | 'beforeEach' | 'afterEach' | 'afterAll';
-const methods: TestMethod[] = ['beforeAll', 'beforeEach', 'afterEach', 'afterAll'];
-
-function callTestMethodGlobals(
- testMethod: { [key in TestMethod]?: Function & { timeout?: number } } & { [key in string]: any }
-) {
- methods.forEach((method) => {
- if (typeof testMethod[method] === 'function') {
- // @ts-expect-error (ignore)
- global[method](testMethod[method], testMethod[method].timeout);
- }
- });
-}
-
-const isDisabled = (parameter: any) =>
- parameter === false || (parameter && parameter.disable === true);
-function testStorySnapshots(options: StoryshotsOptions = {}) {
- if (typeof describe !== 'function') {
- throw new Error('testStorySnapshots is intended only to be used inside jest');
- }
-
- addons.setChannel(mockChannel());
-
- const { storybook, framework, renderTree, renderShallowTree } = loadFramework(options);
- const {
- asyncJest,
- suite,
- storyNameRegex,
- storyKindRegex,
- stories2snapsConverter,
- testMethod,
- integrityOptions,
- snapshotSerializers,
- } = ensureOptionsDefaults(options);
- const testMethodParams = {
- renderTree,
- renderShallowTree,
- stories2snapsConverter,
- };
-
- // NOTE: as the store + preview's initialization process entirely uses
- // `SychronousPromise`s in the v6 store case, the callback to the `then()` here
- // will run *immediately* (in the same tick), and thus the `snapshotsTests`, and
- // subsequent calls to `it()` etc will all happen within this tick, which is required
- // by Jest (cannot add tests asynchronously)
- globalWindow.__STORYBOOK_STORY_STORE__.initializationPromise.then(() => {
- const data = storybook.raw()?.reduce(
- (acc, item) => {
- if (storyNameRegex && !item.name.match(storyNameRegex)) {
- return acc;
- }
-
- if (storyKindRegex && !item.kind.match(storyKindRegex)) {
- return acc;
- }
-
- const { kind, storyFn: render, parameters } = item;
- const existing = acc.find((i: any) => i.kind === kind);
- const { fileName } = item.parameters;
-
- if (!isDisabled(parameters.storyshots)) {
- if (existing) {
- existing.children.push({ ...item, render, fileName });
- } else {
- acc.push({
- kind,
- children: [{ ...item, render, fileName }],
- });
- }
- }
- return acc;
- },
- [] as {
- kind: string;
- children: any[];
- }[]
- );
-
- if (data && data.length) {
- callTestMethodGlobals(testMethod);
-
- snapshotsTests({
- data,
- asyncJest,
- suite,
- framework,
- testMethod,
- testMethodParams,
- snapshotSerializers,
- });
-
- integrityTest(integrityOptions, stories2snapsConverter);
- } else {
- throw new Error('storyshots found 0 stories');
- }
- });
-}
-
-export default testStorySnapshots;
diff --git a/code/addons/storyshots-core/src/api/integrityTestTemplate.ts b/code/addons/storyshots-core/src/api/integrityTestTemplate.ts
deleted file mode 100644
index be6cd5bf79fe..000000000000
--- a/code/addons/storyshots-core/src/api/integrityTestTemplate.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-/* eslint-disable jest/no-export */
-import fs from 'fs';
-import { globSync } from 'glob';
-import { global } from '@storybook/global';
-import { dedent } from 'ts-dedent';
-
-const { describe, it } = global;
-
-expect.extend({
- notToBeAbandoned(storyshots, stories2snapsConverter) {
- const abandonedStoryshots = storyshots.filter((fileName: string) => {
- const possibleStoriesFiles = stories2snapsConverter.getPossibleStoriesFiles(fileName);
- return !possibleStoriesFiles.some(fs.existsSync);
- });
-
- if (abandonedStoryshots.length === 0) {
- return { pass: true, message: () => '' };
- }
-
- const formattedList = abandonedStoryshots.join('\n ');
-
- // See https://github.com/facebook/jest/issues/8732#issuecomment-516445064
- // eslint-disable-next-line no-underscore-dangle
- const isUpdate = expect.getState().snapshotState._updateSnapshot === 'all';
- if (isUpdate) {
- abandonedStoryshots.forEach((file: string) => fs.unlinkSync(file));
- // eslint-disable-next-line no-console
- console.log(dedent`
- Removed abandoned storyshots:
- ${formattedList}
- `);
- return { pass: true, message: () => '' };
- }
-
- return {
- pass: false,
- message: () => dedent`
- Found abandoned storyshots. Run jest with -u to remove them:
- ${formattedList}
- `,
- };
- },
-});
-
-function integrityTest(integrityOptions: any, stories2snapsConverter: any) {
- if (integrityOptions === false) {
- return;
- }
-
- describe('Storyshots Integrity', () => {
- it('Abandoned Storyshots', () => {
- const snapshotExtension = stories2snapsConverter.getSnapshotExtension();
- const storyshots = globSync(`**/*${snapshotExtension}`, integrityOptions);
-
- // @ts-expect-error (ts doesn't 'get' the extension happening on line 9)
- expect(storyshots).notToBeAbandoned(stories2snapsConverter);
- });
- });
-}
-
-export default integrityTest;
diff --git a/code/addons/storyshots-core/src/api/snapshotsTestsTemplate.ts b/code/addons/storyshots-core/src/api/snapshotsTestsTemplate.ts
deleted file mode 100644
index 1e2ee8cbf9f4..000000000000
--- a/code/addons/storyshots-core/src/api/snapshotsTestsTemplate.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-/* eslint-disable jest/no-export */
-/* eslint-disable jest/expect-expect */
-import { global } from '@storybook/global';
-import { addSerializer } from 'jest-specific-snapshot';
-
-const { describe, it } = global;
-
-function snapshotTest({ item, asyncJest, framework, testMethod, testMethodParams }: any) {
- const { name } = item;
- const context = { ...item, framework };
-
- if (asyncJest === true) {
- it(
- `${name}`,
- () =>
- new Promise((resolve, reject) =>
- testMethod({
- done: (error: any) => (error ? reject(error) : resolve()),
- story: item,
- context,
- ...testMethodParams,
- })
- ),
- testMethod.timeout
- );
- } else {
- it(
- `${name}`,
- () =>
- testMethod({
- story: item,
- context,
- ...testMethodParams,
- }),
- testMethod.timeout
- );
- }
-}
-
-function snapshotTestSuite({ item, suite, ...restParams }: any) {
- const { kind, children } = item;
- describe(`${suite}`, () => {
- describe(`${kind}`, () => {
- children.forEach((c: any) => {
- snapshotTest({ item: c, ...restParams });
- });
- });
- });
-}
-
-function snapshotsTests({ data, snapshotSerializers, ...restParams }: any) {
- if (snapshotSerializers) {
- snapshotSerializers.forEach((serializer: any) => {
- addSerializer(serializer);
- expect.addSnapshotSerializer(serializer);
- });
- }
-
- data.forEach((item: any) => {
- snapshotTestSuite({ item, ...restParams });
- });
-}
-
-export default snapshotsTests;
diff --git a/code/addons/storyshots-core/src/frameworks/Loader.ts b/code/addons/storyshots-core/src/frameworks/Loader.ts
deleted file mode 100644
index b7d93898aa1f..000000000000
--- a/code/addons/storyshots-core/src/frameworks/Loader.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import type { Renderer, Addon_Loadable } from '@storybook/types';
-import type { ClientApi as ClientApiClass } from '@storybook/preview-api';
-import type { StoryshotsOptions } from '../api/StoryshotsOptions';
-import type { SupportedFramework } from './SupportedFramework';
-
-export type RenderTree = (story: any, context?: any, options?: any) => any;
-
-export interface ClientApi extends ClientApiClass {
- configure(
- loader: Addon_Loadable,
- module: NodeModule | false,
- showDeprecationWarning?: boolean
- ): void;
- forceReRender(): void;
-}
-
-export interface Loader {
- load: (options: StoryshotsOptions) => {
- framework: SupportedFramework;
- renderTree: RenderTree;
- renderShallowTree: any;
- storybook: ClientApi;
- };
- test: (options: StoryshotsOptions) => boolean;
-}
diff --git a/code/addons/storyshots-core/src/frameworks/SupportedFramework.ts b/code/addons/storyshots-core/src/frameworks/SupportedFramework.ts
deleted file mode 100644
index dfc20d8163ce..000000000000
--- a/code/addons/storyshots-core/src/frameworks/SupportedFramework.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-export type SupportedFramework =
- | 'angular'
- | 'html'
- | 'preact'
- | 'react'
- | 'react-native'
- | 'svelte'
- | 'vue'
- | 'vue3'
- | 'web-components';
diff --git a/code/addons/storyshots-core/src/frameworks/angular/loader.ts b/code/addons/storyshots-core/src/frameworks/angular/loader.ts
deleted file mode 100644
index 48b367bb4d27..000000000000
--- a/code/addons/storyshots-core/src/frameworks/angular/loader.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import hasDependency from '../hasDependency';
-import configure from '../configure';
-import type { Loader } from '../Loader';
-import type { StoryshotsOptions } from '../../api/StoryshotsOptions';
-
-function setupAngularJestPreset() {
- // Angular + Jest + Storyshots = Crazy Shit:
- // We need to require 'jest-preset-angular/build/setupJest' before any storybook code
- // is running inside jest - one of the things that `jest-preset-angular/build/setupJest` does is
- // extending the `window.Reflect` with all the needed metadata functions, that are required
- // for emission of the TS decorations like 'design:paramtypes'
- jest.requireActual('jest-preset-angular/setup-jest');
-}
-
-function test(options: StoryshotsOptions): boolean {
- return (
- options.framework === 'angular' || (!options.framework && hasDependency('@storybook/angular'))
- );
-}
-
-function load(options: StoryshotsOptions) {
- setupAngularJestPreset();
-
- let mockStartedAPI: any;
-
- jest.mock('@storybook/preview-api', () => {
- const previewAPI = jest.requireActual('@storybook/preview-api');
-
- return {
- ...previewAPI,
- start: (...args: any[]) => {
- mockStartedAPI = previewAPI.start(...args);
- return mockStartedAPI;
- },
- };
- });
-
- jest.mock('@storybook/angular', () => {
- const renderAPI = jest.requireActual('@storybook/angular');
-
- renderAPI.addDecorator = mockStartedAPI.clientApi.addDecorator;
- renderAPI.addParameters = mockStartedAPI.clientApi.addParameters;
-
- return renderAPI;
- });
-
- // eslint-disable-next-line global-require
- const storybook = require('@storybook/angular');
-
- configure({
- ...options,
- storybook,
- });
-
- return {
- framework: 'angular' as const,
- renderTree: jest.requireActual('./renderTree').default,
- renderShallowTree: () => {
- throw new Error('Shallow renderer is not supported for angular');
- },
- storybook,
- };
-}
-
-const angularLoader: Loader = {
- load,
- test,
-};
-
-export default angularLoader;
diff --git a/code/addons/storyshots-core/src/frameworks/angular/renderTree.ts b/code/addons/storyshots-core/src/frameworks/angular/renderTree.ts
deleted file mode 100644
index 3c501c70dcc5..000000000000
--- a/code/addons/storyshots-core/src/frameworks/angular/renderTree.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import AngularSnapshotSerializer from 'jest-preset-angular/build/serializers/ng-snapshot';
-import HTMLCommentSerializer from 'jest-preset-angular/build/serializers/html-comment';
-import { TestBed } from '@angular/core/testing';
-import { addSerializer } from 'jest-specific-snapshot';
-import { getApplication, storyPropsProvider, PropertyExtractor } from '@storybook/angular/renderer';
-import { BehaviorSubject } from 'rxjs';
-
-addSerializer(HTMLCommentSerializer);
-addSerializer(AngularSnapshotSerializer);
-
-function getRenderedTree(story: any) {
- const currentStory = story.render();
-
- const analyzedMetadata = new PropertyExtractor(currentStory.moduleMetadata, story.component);
-
- const application = getApplication({
- storyFnAngular: currentStory,
- component: story.component,
- // TODO : To change with the story Id in v7. Currently keep with static id to avoid changes in snapshots
- targetSelector: 'storybook-wrapper',
- analyzedMetadata,
- });
-
- TestBed.configureTestingModule({
- imports: [application],
- providers: [storyPropsProvider(new BehaviorSubject(currentStory.props))],
- });
-
- return TestBed.compileComponents().then(() => {
- const tree = TestBed.createComponent(application);
- tree.detectChanges();
-
- // Empty componentInstance remove attributes of the internal main component () in snapshot
- return { ...tree, componentInstance: {} };
- });
-}
-
-export default getRenderedTree;
diff --git a/code/addons/storyshots-core/src/frameworks/angular/types.ts b/code/addons/storyshots-core/src/frameworks/angular/types.ts
deleted file mode 100644
index b97c5d24fdc9..000000000000
--- a/code/addons/storyshots-core/src/frameworks/angular/types.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-export interface NgModuleMetadata {
- declarations?: any[];
- entryComponents?: any[];
- imports?: any[];
- schemas?: any[];
- providers?: any[];
-}
-
-export interface ICollection {
- [p: string]: any;
-}
-
-export interface NgStory {
- props: ICollection;
- moduleMetadata?: NgModuleMetadata;
- template?: string;
-}
diff --git a/code/addons/storyshots-core/src/frameworks/configure.test.ts b/code/addons/storyshots-core/src/frameworks/configure.test.ts
deleted file mode 100644
index 0e4377e9dede..000000000000
--- a/code/addons/storyshots-core/src/frameworks/configure.test.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-import path from 'path';
-import { getPreviewFile, getMainFile } from './configure';
-
-// eslint-disable-next-line global-require, jest/no-mocks-import
-jest.mock('fs', () => require('../../../../__mocks__/fs'));
-const setupFiles = (files: Record) => {
- // eslint-disable-next-line no-underscore-dangle, global-require
- require('fs').__setMockFiles(files);
-};
-
-describe('preview files', () => {
- it.each`
- filepath
- ${'preview.ts'}
- ${'preview.tsx'}
- ${'preview.js'}
- ${'preview.jsx'}
- ${'config.ts'}
- ${'config.tsx'}
- ${'config.js'}
- ${'config.jsx'}
- `('resolves a valid preview file from $filepath', ({ filepath }) => {
- setupFiles({ [path.join('test', filepath)]: 'true' });
-
- expect(getPreviewFile('test/')).toEqual(`test${path.sep}${filepath}`);
- });
-
- it('returns false when none of the paths exist', () => {
- setupFiles(Object.create(null));
-
- expect(getPreviewFile('test/')).toEqual(false);
- });
-});
-
-describe('main files', () => {
- it.each`
- filepath
- ${'main.ts'}
- ${'main.tsx'}
- ${'main.js'}
- ${'main.jsx'}
- `('resolves a valid main file path from $filepath', ({ filepath }) => {
- setupFiles({ [path.join('test', filepath)]: 'true' });
-
- expect(getMainFile('test/')).toEqual(`test${path.sep}${filepath}`);
- });
-
- it('returns false when none of the paths exist', () => {
- setupFiles(Object.create(null));
-
- expect(getPreviewFile('test/')).toEqual(false);
- });
-});
diff --git a/code/addons/storyshots-core/src/frameworks/configure.ts b/code/addons/storyshots-core/src/frameworks/configure.ts
deleted file mode 100644
index 5532a2dfea8c..000000000000
--- a/code/addons/storyshots-core/src/frameworks/configure.ts
+++ /dev/null
@@ -1,157 +0,0 @@
-import fs from 'fs';
-import path from 'path';
-import type {
- Renderer,
- ArgsEnhancer,
- ArgTypesEnhancer,
- NormalizedStoriesSpecifier,
- StoriesEntry,
- DecoratorFunction,
-} from '@storybook/types';
-import { toRequireContext } from '@storybook/core-webpack';
-import { normalizeStoriesEntry } from '@storybook/core-common';
-import registerRequireContextHook from '@storybook/babel-plugin-require-context-hook/register';
-import { global } from '@storybook/global';
-
-import type { ClientApi } from './Loader';
-import type { StoryshotsOptions } from '../api/StoryshotsOptions';
-
-registerRequireContextHook();
-
-const isFile = (file: string): boolean => {
- try {
- return fs.lstatSync(file).isFile();
- } catch (e) {
- return false;
- }
-};
-
-interface Output {
- features?: Record;
- preview?: string;
- stories?: NormalizedStoriesSpecifier[];
- requireContexts?: string[];
-}
-
-const supportedExtensions = ['ts', 'tsx', 'js', 'jsx', 'cjs', 'mjs'];
-
-const resolveFile = (configDir: string, supportedFilenames: string[]) =>
- supportedFilenames
- .flatMap((filename) =>
- supportedExtensions.map((ext) => path.join(configDir, `${filename}.${ext}`))
- )
- .find(isFile) || false;
-
-export const getPreviewFile = (configDir: string): string | false =>
- resolveFile(configDir, ['preview', 'config']);
-
-export const getMainFile = (configDir: string): string | false => resolveFile(configDir, ['main']);
-
-function getConfigPathParts(input: string): Output {
- const configDir = path.resolve(input);
-
- if (fs.lstatSync(configDir).isDirectory()) {
- const output: Output = {};
-
- const preview = getPreviewFile(configDir);
- const main = getMainFile(configDir);
-
- if (preview) {
- output.preview = preview;
- }
- if (main) {
- const { default: defaultExport, ...rest } = jest.requireActual(main);
- const { stories = [], features = {} } = defaultExport || rest;
-
- output.features = features;
-
- const workingDir = process.cwd();
- output.stories = stories.map((entry: StoriesEntry) => {
- const specifier = normalizeStoriesEntry(entry, {
- configDir,
- workingDir,
- });
-
- return specifier;
- });
- output.requireContexts = output.stories?.map((specifier) => {
- const { path: basePath, recursive, match } = toRequireContext(specifier);
-
- // eslint-disable-next-line no-underscore-dangle
- return global.__requireContext(workingDir, basePath, recursive, match);
- });
- }
-
- return output;
- }
-
- return { preview: configDir };
-}
-
-function configure(
- options: {
- storybook: ClientApi;
- } & StoryshotsOptions
-): void {
- const { configPath = '.storybook', config, storybook } = options;
-
- if (config && typeof config === 'function') {
- config(storybook);
- return;
- }
-
- const {
- preview,
- features = {},
- stories = [],
- requireContexts = [],
- } = getConfigPathParts(configPath);
-
- global.FEATURES = features;
- global.CONFIG_TYPE = 'DEVELOPMENT';
- global.STORIES = stories.map((specifier) => ({
- ...specifier,
- importPathMatcher: specifier.importPathMatcher.source,
- }));
-
- if (preview) {
- // This is essentially the same code as builders/builder-webpack5/templates/virtualModuleEntry.template
- const {
- parameters,
- decorators,
- globals,
- globalTypes,
- argsEnhancers,
- argTypesEnhancers,
- runStep,
- } = jest.requireActual(preview);
-
- if (decorators) {
- decorators.forEach((decorator: DecoratorFunction) =>
- storybook.addDecorator(decorator)
- );
- }
- if (parameters || globals || globalTypes) {
- storybook.addParameters({ ...parameters, globals, globalTypes });
- }
- if (runStep) {
- storybook.addStepRunner(runStep);
- }
- if (argsEnhancers) {
- argsEnhancers.forEach((enhancer: ArgsEnhancer) =>
- storybook.addArgsEnhancer(enhancer as any)
- );
- }
- if (argTypesEnhancers) {
- argTypesEnhancers.forEach((enhancer: ArgTypesEnhancer) =>
- storybook.addArgTypesEnhancer(enhancer as any)
- );
- }
- }
-
- if (requireContexts && requireContexts.length) {
- storybook.configure(requireContexts, false, false);
- }
-}
-
-export default configure;
diff --git a/code/addons/storyshots-core/src/frameworks/frameworkLoader.ts b/code/addons/storyshots-core/src/frameworks/frameworkLoader.ts
deleted file mode 100644
index 40fbed19b2a3..000000000000
--- a/code/addons/storyshots-core/src/frameworks/frameworkLoader.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-/* eslint-disable global-require,import/no-dynamic-require */
-import fs from 'fs';
-import path from 'path';
-import type { Loader } from './Loader';
-import type { StoryshotsOptions } from '../api/StoryshotsOptions';
-
-const loaderScriptName = 'loader.js';
-
-const isDirectory = (source: string) => fs.lstatSync(source).isDirectory();
-
-function getLoaders(): Loader[] {
- return fs
- .readdirSync(__dirname)
- .map((name) => path.join(__dirname, name))
- .filter(isDirectory)
- .map((framework) => {
- const pa = path.join(framework, loaderScriptName);
- const pb = path.join(framework, 'loader.ts');
-
- if (fs.existsSync(pa)) {
- return pa;
- }
-
- if (fs.existsSync(pb)) {
- return pb;
- }
-
- return null;
- })
- .filter(Boolean)
- .map((loader) => loader && require(loader).default);
-}
-
-function loadFramework(options: StoryshotsOptions) {
- const loaders = getLoaders();
-
- const loader = loaders.find((frameworkLoader) => frameworkLoader.test(options));
-
- if (!loader) {
- throw new Error(
- "Couldn't find an appropriate framework loader -- do you need to set the `framework` option?"
- );
- }
-
- return loader.load(options);
-}
-
-export default loadFramework;
diff --git a/code/addons/storyshots-core/src/frameworks/hasDependency.ts b/code/addons/storyshots-core/src/frameworks/hasDependency.ts
deleted file mode 100644
index c88d5347b116..000000000000
--- a/code/addons/storyshots-core/src/frameworks/hasDependency.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import fs from 'fs';
-import path from 'path';
-import readPkgUp from 'read-pkg-up';
-
-const {
- packageJson: { dependencies, devDependencies } = {
- dependencies: undefined,
- devDependencies: undefined,
- },
-} = readPkgUp.sync() || {};
-
-export default function hasDependency(name: string): boolean {
- return Boolean(
- (devDependencies && devDependencies[name]) ||
- (dependencies && dependencies[name]) ||
- fs.existsSync(path.join('node_modules', name, 'package.json'))
- );
-}
diff --git a/code/addons/storyshots-core/src/frameworks/html/loader.ts b/code/addons/storyshots-core/src/frameworks/html/loader.ts
deleted file mode 100644
index df86afc1961e..000000000000
--- a/code/addons/storyshots-core/src/frameworks/html/loader.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import { global } from '@storybook/global';
-import configure from '../configure';
-import type { Loader } from '../Loader';
-import type { StoryshotsOptions } from '../../api/StoryshotsOptions';
-
-function test(options: StoryshotsOptions): boolean {
- return options.framework === 'html';
-}
-
-function load(options: StoryshotsOptions) {
- global.STORYBOOK_ENV = 'html';
-
- let mockStartedAPI: any;
-
- jest.mock('@storybook/preview-api', () => {
- const previewAPI = jest.requireActual('@storybook/preview-api');
-
- return {
- ...previewAPI,
- start: (...args: any[]) => {
- mockStartedAPI = previewAPI.start(...args);
- return mockStartedAPI;
- },
- };
- });
-
- jest.mock('@storybook/html', () => {
- const renderAPI = jest.requireActual('@storybook/html');
-
- renderAPI.addDecorator = mockStartedAPI.clientApi.addDecorator;
- renderAPI.addParameters = mockStartedAPI.clientApi.addParameters;
-
- return renderAPI;
- });
-
- // eslint-disable-next-line global-require
- const storybook = require('@storybook/html');
-
- configure({
- ...options,
- storybook,
- });
-
- return {
- framework: 'html' as const,
- renderTree: jest.requireActual('./renderTree').default,
- renderShallowTree: () => {
- throw new Error('Shallow renderer is not supported for HTML');
- },
- storybook,
- };
-}
-
-const htmLoader: Loader = {
- load,
- test,
-};
-
-export default htmLoader;
diff --git a/code/addons/storyshots-core/src/frameworks/html/renderTree.ts b/code/addons/storyshots-core/src/frameworks/html/renderTree.ts
deleted file mode 100644
index 2347acb15867..000000000000
--- a/code/addons/storyshots-core/src/frameworks/html/renderTree.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { global } from '@storybook/global';
-
-const { document, Node } = global;
-
-function getRenderedTree(story: { render: () => any }) {
- const component = story.render();
-
- if (component instanceof Node) {
- return component;
- }
-
- const section: HTMLElement = document.createElement('section');
- section.innerHTML = component;
-
- if (section.childElementCount > 1) {
- return section;
- }
-
- return section.firstChild;
-}
-
-export default getRenderedTree;
diff --git a/code/addons/storyshots-core/src/frameworks/index.ts b/code/addons/storyshots-core/src/frameworks/index.ts
deleted file mode 100644
index 3eb9b3a990b0..000000000000
--- a/code/addons/storyshots-core/src/frameworks/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './SupportedFramework';
diff --git a/code/addons/storyshots-core/src/frameworks/preact/loader.ts b/code/addons/storyshots-core/src/frameworks/preact/loader.ts
deleted file mode 100644
index b938dac3f928..000000000000
--- a/code/addons/storyshots-core/src/frameworks/preact/loader.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-/** @jsxRuntime classic */
-/** @jsx h */
-
-import { global } from '@storybook/global';
-import configure from '../configure';
-import hasDependency from '../hasDependency';
-import type { Loader } from '../Loader';
-import type { StoryshotsOptions } from '../../api/StoryshotsOptions';
-
-function test(options: StoryshotsOptions): boolean {
- return (
- options.framework === 'preact' || (!options.framework && hasDependency('@storybook/preact'))
- );
-}
-
-function load(options: StoryshotsOptions) {
- global.STORYBOOK_ENV = 'preact';
-
- let mockStartedAPI: any;
-
- jest.mock('@storybook/preview-api', () => {
- const previewAPI = jest.requireActual('@storybook/preview-api');
-
- return {
- ...previewAPI,
- start: (...args: any[]) => {
- mockStartedAPI = previewAPI.start(...args);
- return mockStartedAPI;
- },
- };
- });
-
- jest.mock('@storybook/preact', () => {
- const renderAPI = jest.requireActual('@storybook/preact');
-
- renderAPI.addDecorator = mockStartedAPI.clientApi.addDecorator;
- renderAPI.addParameters = mockStartedAPI.clientApi.addParameters;
-
- return renderAPI;
- });
-
- // eslint-disable-next-line global-require
- const storybook = require('@storybook/preact');
-
- configure({
- ...options,
- storybook,
- });
-
- return {
- framework: 'preact' as const,
- renderTree: jest.requireActual('./renderTree').default,
- renderShallowTree: () => {
- throw new Error('Shallow renderer is not supported for preact');
- },
- storybook,
- };
-}
-
-const preactLoader: Loader = {
- load,
- test,
-};
-
-export default preactLoader;
diff --git a/code/addons/storyshots-core/src/frameworks/preact/renderTree.ts b/code/addons/storyshots-core/src/frameworks/preact/renderTree.ts
deleted file mode 100644
index 5e95dbe95920..000000000000
--- a/code/addons/storyshots-core/src/frameworks/preact/renderTree.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-/** @jsx h */
-import { h } from 'preact';
-import preactRenderer from 'preact-render-to-string/jsx';
-
-const boundRenderer = (_storyElement: any, _rendererOptions: any) =>
- preactRenderer(_storyElement, null, { pretty: ' ' });
-
-function getRenderedTree(story: any, context: any, { renderer, ...rendererOptions }: any) {
- const currentRenderer = renderer || boundRenderer;
- const tree = currentRenderer(h(story.render, null), rendererOptions);
-
- return tree;
-}
-
-export default getRenderedTree;
diff --git a/code/addons/storyshots-core/src/frameworks/react-native/loader.ts b/code/addons/storyshots-core/src/frameworks/react-native/loader.ts
deleted file mode 100644
index 7c0e51d23f0f..000000000000
--- a/code/addons/storyshots-core/src/frameworks/react-native/loader.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-/* eslint-disable global-require */
-import path from 'path';
-import hasDependency from '../hasDependency';
-import type { Loader } from '../Loader';
-import type { StoryshotsOptions } from '../../api/StoryshotsOptions';
-
-function test(options: StoryshotsOptions): boolean {
- return (
- options.framework === 'react-native' ||
- (!options.framework && hasDependency('@storybook/react-native'))
- );
-}
-
-function configure(options: StoryshotsOptions, storybook: any) {
- const { configPath = 'storybook', config } = options;
-
- if (config && typeof config === 'function') {
- config(storybook);
- return;
- }
-
- const resolvedConfigPath = path.resolve(configPath);
- jest.requireActual(resolvedConfigPath);
-}
-
-function load(options: StoryshotsOptions) {
- const storybook = jest.requireActual('@storybook/react-native');
-
- configure(options, storybook);
-
- return {
- renderTree: require('../react/renderTree').default,
- renderShallowTree: require('../react/renderShallowTree').default,
- framework: 'react-native' as const,
- storybook,
- };
-}
-
-const reactNativeLoader: Loader = {
- load,
- test,
-};
-
-export default reactNativeLoader;
diff --git a/code/addons/storyshots-core/src/frameworks/react/loader.ts b/code/addons/storyshots-core/src/frameworks/react/loader.ts
deleted file mode 100644
index 35d62098d183..000000000000
--- a/code/addons/storyshots-core/src/frameworks/react/loader.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import configure from '../configure';
-import hasDependency from '../hasDependency';
-import type { Loader } from '../Loader';
-import type { StoryshotsOptions } from '../../api/StoryshotsOptions';
-
-function test(options: StoryshotsOptions): boolean {
- return options.framework === 'react' || (!options.framework && hasDependency('@storybook/react'));
-}
-
-function load(options: StoryshotsOptions) {
- let mockStartedAPI: any;
-
- jest.mock('@storybook/preview-api', () => {
- const previewAPI = jest.requireActual('@storybook/preview-api');
-
- return {
- ...previewAPI,
- start: (...args: any[]) => {
- mockStartedAPI = previewAPI.start(...args);
- return mockStartedAPI;
- },
- };
- });
-
- jest.mock('@storybook/react', () => {
- const renderAPI = jest.requireActual('@storybook/react');
-
- renderAPI.addDecorator = mockStartedAPI.clientApi.addDecorator;
- renderAPI.addParameters = mockStartedAPI.clientApi.addParameters;
-
- return renderAPI;
- });
-
- // eslint-disable-next-line global-require
- const storybook = require('@storybook/react');
-
- configure({
- ...options,
- storybook,
- });
-
- return {
- framework: 'react' as const,
- renderTree: jest.requireActual('./renderTree').default,
- renderShallowTree: jest.requireActual('./renderShallowTree').default,
- storybook,
- };
-}
-
-const reactLoader: Loader = {
- load,
- test,
-};
-
-export default reactLoader;
diff --git a/code/addons/storyshots-core/src/frameworks/react/renderShallowTree.ts b/code/addons/storyshots-core/src/frameworks/react/renderShallowTree.ts
deleted file mode 100644
index d8ac7b865b4e..000000000000
--- a/code/addons/storyshots-core/src/frameworks/react/renderShallowTree.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import shallow from 'react-test-renderer/shallow';
-
-function getRenderedTree(story: any, context: any, { renderer, serializer }: any) {
- const storyElement = story.render();
- const shallowRenderer = renderer || shallow.createRenderer();
- const tree = shallowRenderer.render(storyElement);
- return serializer ? serializer(tree) : tree;
-}
-
-export default getRenderedTree;
diff --git a/code/addons/storyshots-core/src/frameworks/react/renderTree.ts b/code/addons/storyshots-core/src/frameworks/react/renderTree.ts
deleted file mode 100644
index d92a55710ab1..000000000000
--- a/code/addons/storyshots-core/src/frameworks/react/renderTree.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import React from 'react';
-import reactTestRenderer from 'react-test-renderer';
-
-function getRenderedTree(story: any, context: any, { renderer, ...rendererOptions }: any) {
- const StoryFn = story.render;
- const storyElement = React.createElement(StoryFn);
- const currentRenderer = renderer || reactTestRenderer.create;
- const tree = currentRenderer(storyElement, rendererOptions);
-
- return tree;
-}
-
-export default getRenderedTree;
diff --git a/code/addons/storyshots-core/src/frameworks/svelte/loader.ts b/code/addons/storyshots-core/src/frameworks/svelte/loader.ts
deleted file mode 100644
index 5bd09594013c..000000000000
--- a/code/addons/storyshots-core/src/frameworks/svelte/loader.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import { global } from '@storybook/global';
-import hasDependency from '../hasDependency';
-import configure from '../configure';
-import type { Loader } from '../Loader';
-import type { StoryshotsOptions } from '../../api/StoryshotsOptions';
-
-function test(options: StoryshotsOptions): boolean {
- return (
- options.framework === 'svelte' || (!options.framework && hasDependency('@storybook/svelte'))
- );
-}
-
-function load(options: StoryshotsOptions) {
- global.STORYBOOK_ENV = 'svelte';
-
- let mockStartedAPI: any;
-
- jest.mock('@storybook/preview-api', () => {
- const previewAPI = jest.requireActual('@storybook/preview-api');
-
- return {
- ...previewAPI,
- start: (...args: any[]) => {
- mockStartedAPI = previewAPI.start(...args);
- return mockStartedAPI;
- },
- };
- });
-
- jest.mock('@storybook/svelte', () => {
- const renderAPI = jest.requireActual('@storybook/svelte');
-
- renderAPI.addDecorator = mockStartedAPI.clientApi.addDecorator;
- renderAPI.addParameters = mockStartedAPI.clientApi.addParameters;
-
- return renderAPI;
- });
-
- // eslint-disable-next-line global-require
- const storybook = require('@storybook/svelte');
-
- configure({
- ...options,
- storybook,
- });
- return {
- framework: 'svelte' as const,
- renderTree: jest.requireActual('./renderTree').default,
- renderShallowTree: () => {
- throw new Error('Shallow renderer is not supported for svelte');
- },
- storybook,
- };
-}
-
-const svelteLoader: Loader = {
- load,
- test,
-};
-
-export default svelteLoader;
diff --git a/code/addons/storyshots-core/src/frameworks/svelte/renderTree.ts b/code/addons/storyshots-core/src/frameworks/svelte/renderTree.ts
deleted file mode 100644
index d39cf95008e9..000000000000
--- a/code/addons/storyshots-core/src/frameworks/svelte/renderTree.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import { global } from '@storybook/global';
-// eslint-disable-next-line @typescript-eslint/ban-ts-comment
-// @ts-ignore - types are removed in Svelte 4 but it still works. ts-ignore is safer than ts-expect-error because it's not an error in Svelte 3
-// eslint-disable-next-line import/no-unresolved
-import { set_current_component } from 'svelte/internal';
-
-const { document } = global;
-
-/**
- * Provides functionality to convert your raw story to the resulting markup.
- *
- * Storybook snapshots need the rendered markup that svelte outputs,
- * but since we only have the story config data ({ Component, data }) in
- * the Svelte stories, we need to mount the component, and then return the
- * resulting HTML.
- *
- * If we don't render to HTML, we will get a snapshot of the raw story
- * i.e. ({ Component, data }).
- */
-function getRenderedTree(story: any) {
- // allow setContext to work
- set_current_component({ $$: { context: new Map() } });
-
- const { Component, props } = story.render();
-
- const DefaultCompatComponent = Component.default || Component;
-
- // We need to create a target to mount onto.
- const target = document.createElement('section');
-
- // eslint-disable-next-line no-new
- new DefaultCompatComponent({ target, props });
-
- // Classify the target so that it is clear where the markup
- // originates from, and that it is specific for snapshot tests.
- target.className = 'storybook-snapshot-container';
-
- return target;
-}
-
-export default getRenderedTree;
diff --git a/code/addons/storyshots-core/src/frameworks/vue/loader.ts b/code/addons/storyshots-core/src/frameworks/vue/loader.ts
deleted file mode 100644
index a29a88a2d98b..000000000000
--- a/code/addons/storyshots-core/src/frameworks/vue/loader.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-import { global } from '@storybook/global';
-import hasDependency from '../hasDependency';
-import configure from '../configure';
-import type { Loader } from '../Loader';
-import type { StoryshotsOptions } from '../../api/StoryshotsOptions';
-
-function mockVueToIncludeCompiler() {
- jest.mock('vue', () => jest.requireActual('vue/dist/vue.common.js'));
-}
-
-function test(options: StoryshotsOptions): boolean {
- return options.framework === 'vue' || (!options.framework && hasDependency('@storybook/vue'));
-}
-
-function load(options: StoryshotsOptions) {
- global.STORYBOOK_ENV = 'vue';
- mockVueToIncludeCompiler();
-
- let mockStartedAPI: any;
-
- jest.mock('@storybook/preview-api', () => {
- const previewAPI = jest.requireActual('@storybook/preview-api');
-
- return {
- ...previewAPI,
- start: (...args: any[]) => {
- mockStartedAPI = previewAPI.start(...args);
- return mockStartedAPI;
- },
- };
- });
-
- jest.mock('@storybook/vue', () => {
- const renderAPI = jest.requireActual('@storybook/vue');
-
- renderAPI.addDecorator = mockStartedAPI.clientApi.addDecorator;
- renderAPI.addParameters = mockStartedAPI.clientApi.addParameters;
-
- return renderAPI;
- });
-
- // eslint-disable-next-line global-require
- const storybook = require('@storybook/vue');
-
- configure({
- ...options,
- storybook,
- });
- return {
- framework: 'vue' as const,
- renderTree: jest.requireActual('./renderTree').default,
- renderShallowTree: () => {
- throw new Error('Shallow renderer is not supported for vue');
- },
- storybook,
- };
-}
-
-const vueLoader: Loader = {
- load,
- test,
-};
-
-export default vueLoader;
diff --git a/code/addons/storyshots-core/src/frameworks/vue/renderTree.ts b/code/addons/storyshots-core/src/frameworks/vue/renderTree.ts
deleted file mode 100644
index d37139e813ea..000000000000
--- a/code/addons/storyshots-core/src/frameworks/vue/renderTree.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-/* eslint-disable @typescript-eslint/ban-ts-comment */
-import Vue from 'vue';
-
-// this is defined in @storybook/vue but not exported,
-// and we need it to inject args into the story component's props
-const VALUES = 'STORYBOOK_VALUES';
-
-function getRenderedTree(story: any) {
- const component = story.render();
-
- // @ts-ignore FIXME storyshots type error
- const vm = new Vue({
- // @ts-ignore FIXME storyshots type error
- render(h) {
- return h(component);
- },
- });
-
- // @ts-ignore FIXME storyshots type error
- vm[VALUES] = story.initialArgs;
-
- return vm.$mount().$el;
-}
-
-export default getRenderedTree;
diff --git a/code/addons/storyshots-core/src/frameworks/vue3/loader.ts b/code/addons/storyshots-core/src/frameworks/vue3/loader.ts
deleted file mode 100644
index 3fed6869e1a2..000000000000
--- a/code/addons/storyshots-core/src/frameworks/vue3/loader.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-import { global } from '@storybook/global';
-import hasDependency from '../hasDependency';
-import configure from '../configure';
-import type { Loader } from '../Loader';
-import type { StoryshotsOptions } from '../../api/StoryshotsOptions';
-
-function test(options: StoryshotsOptions): boolean {
- return options.framework === 'vue3' || (!options.framework && hasDependency('@storybook/vue3'));
-}
-
-function load(options: StoryshotsOptions) {
- global.STORYBOOK_ENV = 'vue3';
-
- let mockStartedAPI: any;
-
- jest.mock('@storybook/preview-api', () => {
- const previewAPI = jest.requireActual('@storybook/preview-api');
-
- return {
- ...previewAPI,
- start: (...args: any[]) => {
- mockStartedAPI = previewAPI.start(...args);
- return mockStartedAPI;
- },
- };
- });
-
- jest.mock('@storybook/vue3', () => {
- const renderAPI = jest.requireActual('@storybook/vue3');
-
- renderAPI.addDecorator = mockStartedAPI.clientApi.addDecorator;
- renderAPI.addParameters = mockStartedAPI.clientApi.addParameters;
-
- return renderAPI;
- });
-
- // eslint-disable-next-line global-require
- const storybook = require('@storybook/vue3');
-
- configure({
- ...options,
- storybook,
- });
-
- return {
- framework: 'vue3' as const,
- renderTree: jest.requireActual('./renderTree').default,
- renderShallowTree: () => {
- throw new Error('Shallow renderer is not supported for Vue 3');
- },
- storybook,
- };
-}
-
-const vueLoader: Loader = {
- load,
- test,
-};
-
-export default vueLoader;
diff --git a/code/addons/storyshots-core/src/frameworks/vue3/renderTree.ts b/code/addons/storyshots-core/src/frameworks/vue3/renderTree.ts
deleted file mode 100644
index 854cb485b3c1..000000000000
--- a/code/addons/storyshots-core/src/frameworks/vue3/renderTree.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import * as Vue from 'vue';
-import { global } from '@storybook/global';
-
-const { document } = global;
-
-// This is cast as `any` to workaround type errors caused by Vue 2 types
-const { h, createApp } = Vue as any;
-
-function getRenderedTree(story: any) {
- const component = story.render();
-
- const app = createApp({
- render() {
- return h(component, story.args);
- },
- });
-
- const vm = app.mount(document.createElement('div'));
- vm.$forceUpdate();
- return vm.$el;
-}
-
-export default getRenderedTree;
diff --git a/code/addons/storyshots-core/src/frameworks/web-components/loader.ts b/code/addons/storyshots-core/src/frameworks/web-components/loader.ts
deleted file mode 100644
index e3536d85d99d..000000000000
--- a/code/addons/storyshots-core/src/frameworks/web-components/loader.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import { global } from '@storybook/global';
-import configure from '../configure';
-import type { Loader } from '../Loader';
-import type { StoryshotsOptions } from '../../api/StoryshotsOptions';
-
-function test(options: StoryshotsOptions): boolean {
- return options.framework === 'web-components';
-}
-
-function load(options: StoryshotsOptions) {
- global.STORYBOOK_ENV = 'web-components';
-
- let mockStartedAPI: any;
-
- jest.mock('@storybook/preview-api', () => {
- const previewAPI = jest.requireActual('@storybook/preview-api');
-
- return {
- ...previewAPI,
- start: (...args: any[]) => {
- mockStartedAPI = previewAPI.start(...args);
- return mockStartedAPI;
- },
- };
- });
-
- jest.mock('@storybook/html', () => {
- const renderAPI = jest.requireActual('@storybook/html');
-
- renderAPI.addDecorator = mockStartedAPI.clientApi.addDecorator;
- renderAPI.addParameters = mockStartedAPI.clientApi.addParameters;
-
- return renderAPI;
- });
-
- // eslint-disable-next-line global-require
- const storybook = require('@storybook/html');
-
- configure({
- ...options,
- storybook,
- });
-
- return {
- framework: 'web-components' as const,
- renderTree: jest.requireActual('./renderTree').default,
- renderShallowTree: () => {
- throw new Error('Shallow renderer is not supported for web-components');
- },
- storybook,
- };
-}
-
-const webComponentsLoader: Loader = {
- load,
- test,
-};
-
-export default webComponentsLoader;
diff --git a/code/addons/storyshots-core/src/frameworks/web-components/renderTree.ts b/code/addons/storyshots-core/src/frameworks/web-components/renderTree.ts
deleted file mode 100644
index 8c45ea52eaca..000000000000
--- a/code/addons/storyshots-core/src/frameworks/web-components/renderTree.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-function getRenderedTree(story: { render: () => any }) {
- const component = story.render();
- return component.getHTML ? component.getHTML() : component;
-}
-
-export default getRenderedTree;
diff --git a/code/addons/storyshots-core/src/index.ts b/code/addons/storyshots-core/src/index.ts
deleted file mode 100644
index 1ded51620241..000000000000
--- a/code/addons/storyshots-core/src/index.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import api from './api';
-import {
- snapshotWithOptions,
- multiSnapshotWithOptions,
- renderOnly,
- renderWithOptions,
- shallowSnapshot,
- snapshot,
-} from './test-bodies';
-
-export {
- snapshotWithOptions,
- multiSnapshotWithOptions,
- renderOnly,
- renderWithOptions,
- shallowSnapshot,
- snapshot,
-};
-
-export * from './Stories2SnapsConverter';
-export * from './frameworks';
-
-export default api;
diff --git a/code/addons/storyshots-core/src/test-bodies.ts b/code/addons/storyshots-core/src/test-bodies.ts
deleted file mode 100644
index 3dc307d6b847..000000000000
--- a/code/addons/storyshots-core/src/test-bodies.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-import 'jest-specific-snapshot';
-import type {
- StoryshotsTestMethod,
- TestMethodOptions,
- StoryshotsOptions,
-} from './api/StoryshotsOptions';
-
-const isFunction = (obj: any) => !!(obj && obj.constructor && obj.call && obj.apply);
-const optionsOrCallOptions = (opts: any, story: any) => (isFunction(opts) ? opts(story) : opts);
-
-type SnapshotsWithOptionsArgType = Pick | Function;
-
-type SnapshotsWithOptionsReturnType = (
- options: Pick
-) => any;
-
-export function snapshotWithOptions(
- options: SnapshotsWithOptionsArgType = {}
-): SnapshotsWithOptionsReturnType {
- return ({ story, context, renderTree, snapshotFileName }) => {
- const result = renderTree(story, context, optionsOrCallOptions(options, story));
-
- function match(tree: any) {
- let target = tree;
- const isReact = story.parameters.renderer === 'react';
-
- if (isReact && typeof tree.childAt === 'function') {
- target = tree.childAt(0);
- }
- if (isReact && Array.isArray(tree.children)) {
- [target] = tree.children;
- }
-
- if (snapshotFileName) {
- expect(target).toMatchSpecificSnapshot(snapshotFileName);
- } else {
- expect(target).toMatchSnapshot();
- }
-
- if (typeof tree.unmount === 'function') {
- tree.unmount();
- }
- }
-
- if (typeof result.then === 'function') {
- return result.then(match);
- }
-
- return match(result);
- };
-}
-
-export function multiSnapshotWithOptions(
- options: SnapshotsWithOptionsArgType = {}
-): StoryshotsTestMethod {
- return ({ story, context, renderTree, stories2snapsConverter }) => {
- const snapshotFileName = stories2snapsConverter.getSnapshotFileName(context);
- return snapshotWithOptions(options)({ story, context, renderTree, snapshotFileName });
- };
-}
-
-export const shallowSnapshot: StoryshotsTestMethod = ({
- story,
- context,
- renderShallowTree,
- options = {},
-}) => {
- const result = renderShallowTree(story, context, options);
- expect(result).toMatchSnapshot();
-};
-
-export function renderWithOptions(options = {}): StoryshotsTestMethod {
- return ({ story, context, renderTree }) => {
- const result = renderTree(story, context, options);
- if (typeof result.then === 'function') {
- return result;
- }
-
- return undefined;
- };
-}
-
-export const renderOnly = renderWithOptions();
-
-export const snapshot = snapshotWithOptions();
diff --git a/code/addons/storyshots-core/src/typings.d.ts b/code/addons/storyshots-core/src/typings.d.ts
deleted file mode 100644
index 2ae47a5617de..000000000000
--- a/code/addons/storyshots-core/src/typings.d.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-/* eslint-disable no-underscore-dangle */
-/* eslint-disable @typescript-eslint/naming-convention */
-declare module 'jest-preset-angular/*';
-declare module 'preact-render-to-string/jsx';
-declare module 'react-test-renderer*';
-
-declare module '@storybook/babel-plugin-require-context-hook/register';
-
-declare var STORYBOOK_ENV: any;
-declare var STORIES: any;
-
-declare var CONFIG_TYPE: 'DEVELOPMENT' | 'PRODUCTION';
-declare var FEATURES: import('@storybook/types').StorybookConfig['features'];
-
-declare var __STORYBOOK_STORY_STORE__: any;
-declare var __requireContext: any;
diff --git a/code/addons/storyshots-core/stories/__snapshots__/storyshot.defaultExport.test.js.snap b/code/addons/storyshots-core/stories/__snapshots__/storyshot.defaultExport.test.js.snap
deleted file mode 100644
index 42d99ae740ca..000000000000
--- a/code/addons/storyshots-core/stories/__snapshots__/storyshot.defaultExport.test.js.snap
+++ /dev/null
@@ -1,44 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Storyshots Another Button with some emoji 1`] = `
-
- prefix
-
-
-
- 😀 😎 👍 💯
-
-
-
- suffix
-
-`;
-
-exports[`Storyshots Another Button with text 1`] = `
-
- prefix
-
-
- Hello button
-
-
- suffix
-
-`;
-
-exports[`Storyshots Text Simple 1`] = `
-
- prefix
-
- contents
-
- suffix
-
-`;
diff --git a/code/addons/storyshots-core/stories/__snapshots__/storyshot.enzyme.test.js.snap b/code/addons/storyshots-core/stories/__snapshots__/storyshot.enzyme.test.js.snap
deleted file mode 100644
index 984165bef39c..000000000000
--- a/code/addons/storyshots-core/stories/__snapshots__/storyshot.enzyme.test.js.snap
+++ /dev/null
@@ -1,56 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Storyshots Another Button with some emoji 1`] = `
-
-
- prefix
-
-
-
-
- 😀 😎 👍 💯
-
-
-
-
- suffix
-
-
-`;
-
-exports[`Storyshots Another Button with text 1`] = `
-
-
- prefix
-
-
-
- Hello button
-
-
-
- suffix
-
-
-`;
-
-exports[`Storyshots Text Simple 1`] = `
-
-
- prefix
-
-
- contents
-
-
- suffix
-
-
-`;
diff --git a/code/addons/storyshots-core/stories/__snapshots__/storyshot.metadata.test.js.snap b/code/addons/storyshots-core/stories/__snapshots__/storyshot.metadata.test.js.snap
deleted file mode 100644
index 42d99ae740ca..000000000000
--- a/code/addons/storyshots-core/stories/__snapshots__/storyshot.metadata.test.js.snap
+++ /dev/null
@@ -1,44 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Storyshots Another Button with some emoji 1`] = `
-
- prefix
-
-
-
- 😀 😎 👍 💯
-
-
-
- suffix
-
-`;
-
-exports[`Storyshots Another Button with text 1`] = `
-
- prefix
-
-
- Hello button
-
-
- suffix
-
-`;
-
-exports[`Storyshots Text Simple 1`] = `
-
- prefix
-
- contents
-
- suffix
-
-`;
diff --git a/code/addons/storyshots-core/stories/__snapshots__/storyshot.shallow.test.js.snap b/code/addons/storyshots-core/stories/__snapshots__/storyshot.shallow.test.js.snap
deleted file mode 100644
index d7def107120a..000000000000
--- a/code/addons/storyshots-core/stories/__snapshots__/storyshot.shallow.test.js.snap
+++ /dev/null
@@ -1,31 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Storyshots Another Button with some emoji 1`] = `
-
- prefix
-
-
-
- suffix
-
-`;
-
-exports[`Storyshots Another Button with text 1`] = `
-
- prefix
-
-
-
- suffix
-
-`;
-
-exports[`Storyshots Text Simple 1`] = `
-
- prefix
-
-
-
- suffix
-
-`;
diff --git a/code/addons/storyshots-core/stories/__snapshots__/storyshot.shallowWithOptions.test.js.snap b/code/addons/storyshots-core/stories/__snapshots__/storyshot.shallowWithOptions.test.js.snap
deleted file mode 100644
index d7def107120a..000000000000
--- a/code/addons/storyshots-core/stories/__snapshots__/storyshot.shallowWithOptions.test.js.snap
+++ /dev/null
@@ -1,31 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Storyshots Another Button with some emoji 1`] = `
-
- prefix
-
-
-
- suffix
-
-`;
-
-exports[`Storyshots Another Button with text 1`] = `
-
- prefix
-
-
-
- suffix
-
-`;
-
-exports[`Storyshots Text Simple 1`] = `
-
- prefix
-
-
-
- suffix
-
-`;
diff --git a/code/addons/storyshots-core/stories/__snapshots__/storyshot.snapshotWithOptionsFunction.test.js.snap b/code/addons/storyshots-core/stories/__snapshots__/storyshot.snapshotWithOptionsFunction.test.js.snap
deleted file mode 100644
index 42d99ae740ca..000000000000
--- a/code/addons/storyshots-core/stories/__snapshots__/storyshot.snapshotWithOptionsFunction.test.js.snap
+++ /dev/null
@@ -1,44 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Storyshots Another Button with some emoji 1`] = `
-
- prefix
-
-
-
- 😀 😎 👍 💯
-
-
-
- suffix
-
-`;
-
-exports[`Storyshots Another Button with text 1`] = `
-
- prefix
-
-
- Hello button
-
-
- suffix
-
-`;
-
-exports[`Storyshots Text Simple 1`] = `
-
- prefix
-
- contents
-
- suffix
-
-`;
diff --git a/code/addons/storyshots-core/stories/default_export/Extra.stories.jsx b/code/addons/storyshots-core/stories/default_export/Extra.stories.jsx
deleted file mode 100644
index 4886a1c158f7..000000000000
--- a/code/addons/storyshots-core/stories/default_export/Extra.stories.jsx
+++ /dev/null
@@ -1,15 +0,0 @@
-/* eslint-disable react/button-has-type */
-import React from 'react';
-
-import { storiesOf } from '@storybook/react';
-import { action } from '@storybook/addon-actions';
-
-storiesOf('Another Button', module)
- .add('with text', () => Hello button )
- .add('with some emoji', () => (
-
-
- 😀 😎 👍 💯
-
-
- ));
diff --git a/code/addons/storyshots-core/stories/default_export/Text.stories.jsx b/code/addons/storyshots-core/stories/default_export/Text.stories.jsx
deleted file mode 100644
index e87143f2c786..000000000000
--- a/code/addons/storyshots-core/stories/default_export/Text.stories.jsx
+++ /dev/null
@@ -1,5 +0,0 @@
-export default {
- title: 'Text',
-};
-
-export const Simple = () => 'contents';
diff --git a/code/addons/storyshots-core/stories/default_export/__snapshots__/Extra.stories@Another-_-Button@with-_-some-_-emoji.boo b/code/addons/storyshots-core/stories/default_export/__snapshots__/Extra.stories@Another-_-Button@with-_-some-_-emoji.boo
deleted file mode 100644
index a1027859204f..000000000000
--- a/code/addons/storyshots-core/stories/default_export/__snapshots__/Extra.stories@Another-_-Button@with-_-some-_-emoji.boo
+++ /dev/null
@@ -1,14 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Storyshots Another Button with some emoji 1`] = `
-
-
- 😀 😎 👍 💯
-
-
-`;
diff --git a/code/addons/storyshots-core/stories/default_export/__snapshots__/Extra.stories@Another-_-Button@with-_-text.boo b/code/addons/storyshots-core/stories/default_export/__snapshots__/Extra.stories@Another-_-Button@with-_-text.boo
deleted file mode 100644
index e344c7924619..000000000000
--- a/code/addons/storyshots-core/stories/default_export/__snapshots__/Extra.stories@Another-_-Button@with-_-text.boo
+++ /dev/null
@@ -1,9 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Storyshots Another Button with text 1`] = `
-
- Hello button
-
-`;
diff --git a/code/addons/storyshots-core/stories/default_export/main.js b/code/addons/storyshots-core/stories/default_export/main.js
deleted file mode 100644
index 233070243d8a..000000000000
--- a/code/addons/storyshots-core/stories/default_export/main.js
+++ /dev/null
@@ -1,5 +0,0 @@
-const config = {
- stories: ['./Text.stories.jsx', './Extra.stories.jsx'],
-};
-
-export default config;
diff --git a/code/addons/storyshots-core/stories/default_export/preview.jsx b/code/addons/storyshots-core/stories/default_export/preview.jsx
deleted file mode 100644
index 54fec6401462..000000000000
--- a/code/addons/storyshots-core/stories/default_export/preview.jsx
+++ /dev/null
@@ -1,15 +0,0 @@
-/* eslint-disable react/prop-types */
-import React from 'react';
-
-const Container = ({ children }) => {children}
;
-
-export const decorators = [
- (StoryFn, { parameters, globals }) => (
-
- {parameters.prefix} {globals.suffix}
-
- ),
-];
-
-export const parameters = { prefix: 'prefix' };
-export const globals = { suffix: 'suffix' };
diff --git a/code/addons/storyshots-core/stories/exported_metadata/Async.stories.jsx b/code/addons/storyshots-core/stories/exported_metadata/Async.stories.jsx
deleted file mode 100644
index f469d8b2a638..000000000000
--- a/code/addons/storyshots-core/stories/exported_metadata/Async.stories.jsx
+++ /dev/null
@@ -1,34 +0,0 @@
-import React from 'react';
-
-export const EXPECTED_VALUE = 'THIS IS SO DONE';
-export const TIMEOUT = 5;
-
-class AsyncTestComponent extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- value: '',
- };
- }
-
- componentDidMount() {
- setTimeout(() => {
- this.setState({
- value: EXPECTED_VALUE,
- });
- }, TIMEOUT);
- }
-
- render() {
- const { value } = this.state;
- return {value} ;
- }
-}
-
-export default {
- title: 'Async',
- includeStories: ['WithTimeout'],
-};
-
-export const WithTimeout = () => ;
-WithTimeout.storyName = `with ${TIMEOUT}ms timeout simulating async operation`;
diff --git a/code/addons/storyshots-core/stories/exported_metadata/Extra.stories.jsx b/code/addons/storyshots-core/stories/exported_metadata/Extra.stories.jsx
deleted file mode 100644
index 4886a1c158f7..000000000000
--- a/code/addons/storyshots-core/stories/exported_metadata/Extra.stories.jsx
+++ /dev/null
@@ -1,15 +0,0 @@
-/* eslint-disable react/button-has-type */
-import React from 'react';
-
-import { storiesOf } from '@storybook/react';
-import { action } from '@storybook/addon-actions';
-
-storiesOf('Another Button', module)
- .add('with text', () => Hello button )
- .add('with some emoji', () => (
-
-
- 😀 😎 👍 💯
-
-
- ));
diff --git a/code/addons/storyshots-core/stories/exported_metadata/Text.stories.jsx b/code/addons/storyshots-core/stories/exported_metadata/Text.stories.jsx
deleted file mode 100644
index e87143f2c786..000000000000
--- a/code/addons/storyshots-core/stories/exported_metadata/Text.stories.jsx
+++ /dev/null
@@ -1,5 +0,0 @@
-export default {
- title: 'Text',
-};
-
-export const Simple = () => 'contents';
diff --git a/code/addons/storyshots-core/stories/exported_metadata/__snapshots__/Extra.stories.storyshot b/code/addons/storyshots-core/stories/exported_metadata/__snapshots__/Extra.stories.storyshot
deleted file mode 100644
index 841630b0fc01..000000000000
--- a/code/addons/storyshots-core/stories/exported_metadata/__snapshots__/Extra.stories.storyshot
+++ /dev/null
@@ -1,34 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Storyshots Another Button with some emoji 1`] = `
-
- prefix
-
-
-
- 😀 😎 👍 💯
-
-
-
- suffix
-
-`;
-
-exports[`Storyshots Another Button with text 1`] = `
-
- prefix
-
-
- Hello button
-
-
- suffix
-
-`;
diff --git a/code/addons/storyshots-core/stories/exported_metadata/__snapshots__/Extra.stories@Another-_-Button@with-_-some-_-emoji.boo b/code/addons/storyshots-core/stories/exported_metadata/__snapshots__/Extra.stories@Another-_-Button@with-_-some-_-emoji.boo
deleted file mode 100644
index a1027859204f..000000000000
--- a/code/addons/storyshots-core/stories/exported_metadata/__snapshots__/Extra.stories@Another-_-Button@with-_-some-_-emoji.boo
+++ /dev/null
@@ -1,14 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Storyshots Another Button with some emoji 1`] = `
-
-
- 😀 😎 👍 💯
-
-
-`;
diff --git a/code/addons/storyshots-core/stories/exported_metadata/__snapshots__/Extra.stories@Another-_-Button@with-_-text.boo b/code/addons/storyshots-core/stories/exported_metadata/__snapshots__/Extra.stories@Another-_-Button@with-_-text.boo
deleted file mode 100644
index e344c7924619..000000000000
--- a/code/addons/storyshots-core/stories/exported_metadata/__snapshots__/Extra.stories@Another-_-Button@with-_-text.boo
+++ /dev/null
@@ -1,9 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Storyshots Another Button with text 1`] = `
-
- Hello button
-
-`;
diff --git a/code/addons/storyshots-core/stories/exported_metadata/__snapshots__/Text.stories.storyshot b/code/addons/storyshots-core/stories/exported_metadata/__snapshots__/Text.stories.storyshot
deleted file mode 100644
index c9965e394a4c..000000000000
--- a/code/addons/storyshots-core/stories/exported_metadata/__snapshots__/Text.stories.storyshot
+++ /dev/null
@@ -1,11 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Storyshots Text Simple 1`] = `
-
- prefix
-
- contents
-
- suffix
-
-`;
diff --git a/code/addons/storyshots-core/stories/exported_metadata/main.js b/code/addons/storyshots-core/stories/exported_metadata/main.js
deleted file mode 100644
index fbb87ec1dfc5..000000000000
--- a/code/addons/storyshots-core/stories/exported_metadata/main.js
+++ /dev/null
@@ -1,3 +0,0 @@
-module.exports = {
- stories: ['./Text.stories.jsx', './Extra.stories.jsx'],
-};
diff --git a/code/addons/storyshots-core/stories/exported_metadata/preview.jsx b/code/addons/storyshots-core/stories/exported_metadata/preview.jsx
deleted file mode 100644
index 54fec6401462..000000000000
--- a/code/addons/storyshots-core/stories/exported_metadata/preview.jsx
+++ /dev/null
@@ -1,15 +0,0 @@
-/* eslint-disable react/prop-types */
-import React from 'react';
-
-const Container = ({ children }) => {children}
;
-
-export const decorators = [
- (StoryFn, { parameters, globals }) => (
-
- {parameters.prefix} {globals.suffix}
-
- ),
-];
-
-export const parameters = { prefix: 'prefix' };
-export const globals = { suffix: 'suffix' };
diff --git a/code/addons/storyshots-core/stories/storyshot.async.test.js b/code/addons/storyshots-core/stories/storyshot.async.test.js
deleted file mode 100644
index a4f13e34ddc6..000000000000
--- a/code/addons/storyshots-core/stories/storyshot.async.test.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import path from 'path';
-import { render, screen, waitFor } from '@testing-library/react';
-import initStoryshots, { Stories2SnapsConverter } from '../src';
-import { EXPECTED_VALUE } from './exported_metadata/Async.stories.jsx';
-
-initStoryshots({
- asyncJest: true,
- framework: 'react',
- integrityOptions: false,
- configPath: path.join(__dirname, 'exported_metadata'),
-
- // When async is true we need to provide a test method that
- // calls done() when at the end of the test method
- test: async ({ story, context, done }) => {
- expect(done).toBeDefined();
-
- // This is a storyOf Async (see ./required_with_context/Async.stories)
- if (context.kind === 'Async') {
- const converter = new Stories2SnapsConverter({ snapshotExtension: '.async.storyshot' });
- const snapshotFilename = converter.getSnapshotFileName(context);
- const storyElement = story.render();
-
- // Mount the component
- const { container } = render(storyElement);
-
- // The Async component should not contain the expected value
- expect(screen.queryByText(EXPECTED_VALUE)).toBeFalsy();
-
- await waitFor(() => {
- expect(screen.getByText(EXPECTED_VALUE)).toBeInTheDocument();
- expect(container.firstChild).toMatchSpecificSnapshot(snapshotFilename);
- });
-
- // finally mark test as done
- done();
- } else {
- // If not async, mark the test as done
- done();
- }
- },
-});
diff --git a/code/addons/storyshots-core/stories/storyshot.configFunc.test.js b/code/addons/storyshots-core/stories/storyshot.configFunc.test.js
deleted file mode 100644
index 346c581207b9..000000000000
--- a/code/addons/storyshots-core/stories/storyshot.configFunc.test.js
+++ /dev/null
@@ -1,50 +0,0 @@
-import path from 'path';
-import initStoryshots, { multiSnapshotWithOptions, Stories2SnapsConverter } from '../src';
-
-/* deprecated and will be removed in Storybook 8.0 */
-
-class AnotherStories2SnapsConverter extends Stories2SnapsConverter {
- getSnapshotFileName(context) {
- const { fileName, kind, name } = context;
- const { dir, name: filename } = path.parse(fileName);
- const uniqueName = `${filename}@${kind.replace(/ /g, '-_-')}@${name.replace(/ /g, '-_-')}`;
- const { snapshotsDirName, snapshotExtension } = this.options;
-
- return path.format({
- dir: path.join(dir, snapshotsDirName),
- name: uniqueName,
- ext: snapshotExtension,
- });
- }
-
- getPossibleStoriesFiles(storyshotFile) {
- const { dir, name } = path.parse(storyshotFile);
- const { storiesExtensions } = this.options;
-
- const [fileName] = name.split('@');
-
- return storiesExtensions.map((ext) =>
- path.format({
- dir: path.dirname(dir),
- name: fileName,
- ext,
- })
- );
- }
-}
-
-initStoryshots({
- framework: 'react',
- integrityOptions: { cwd: __dirname },
- stories2snapsConverter: new AnotherStories2SnapsConverter({ snapshotExtension: '.boo' }),
- config: ({ configure }) =>
- configure(
- () => {
- // eslint-disable-next-line global-require
- require('./exported_metadata/Extra.stories.jsx');
- },
- module,
- false
- ),
- test: multiSnapshotWithOptions(),
-});
diff --git a/code/addons/storyshots-core/stories/storyshot.defaultExport.test.js b/code/addons/storyshots-core/stories/storyshot.defaultExport.test.js
deleted file mode 100644
index 0d88bddea1ff..000000000000
--- a/code/addons/storyshots-core/stories/storyshot.defaultExport.test.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import path from 'path';
-import initStoryshots from '../src';
-
-initStoryshots({
- framework: 'react',
- configPath: path.join(__dirname, 'default_export'),
-});
diff --git a/code/addons/storyshots-core/stories/storyshot.enzyme.test.js b/code/addons/storyshots-core/stories/storyshot.enzyme.test.js
deleted file mode 100644
index afaaf9b3b537..000000000000
--- a/code/addons/storyshots-core/stories/storyshot.enzyme.test.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import path from 'path';
-import { mount, configure } from 'enzyme';
-// @ts-expect-error (Converted from ts-ignore)
-import Adapter from 'enzyme-adapter-react-16';
-import initStoryshots from '../src';
-
-configure({ adapter: new Adapter() });
-
-initStoryshots({
- framework: 'react',
- configPath: path.join(__dirname, 'exported_metadata'),
- renderer: mount,
-});
diff --git a/code/addons/storyshots-core/stories/storyshot.metadata.test.js b/code/addons/storyshots-core/stories/storyshot.metadata.test.js
deleted file mode 100644
index 971390d2b513..000000000000
--- a/code/addons/storyshots-core/stories/storyshot.metadata.test.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import path from 'path';
-import initStoryshots from '../src';
-
-// jest.mock('@storybook/node-logger');
-
-initStoryshots({
- framework: 'react',
- configPath: path.join(__dirname, 'exported_metadata'),
-});
diff --git a/code/addons/storyshots-core/stories/storyshot.renderOnly.test.js b/code/addons/storyshots-core/stories/storyshot.renderOnly.test.js
deleted file mode 100644
index e620fd15ed47..000000000000
--- a/code/addons/storyshots-core/stories/storyshot.renderOnly.test.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import path from 'path';
-import initStoryshots, { renderOnly } from '../src';
-
-initStoryshots({
- framework: 'react',
- configPath: path.join(__dirname, 'exported_metadata'),
- test: renderOnly,
-});
diff --git a/code/addons/storyshots-core/stories/storyshot.renderWithOptions.test.js b/code/addons/storyshots-core/stories/storyshot.renderWithOptions.test.js
deleted file mode 100644
index 4aac113cedd4..000000000000
--- a/code/addons/storyshots-core/stories/storyshot.renderWithOptions.test.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import path from 'path';
-import initStoryshots, { renderWithOptions } from '../src';
-
-initStoryshots({
- framework: 'react',
- configPath: path.join(__dirname, 'exported_metadata'),
- test: renderWithOptions({}),
-});
diff --git a/code/addons/storyshots-core/stories/storyshot.shallow.test.js b/code/addons/storyshots-core/stories/storyshot.shallow.test.js
deleted file mode 100644
index 62cf107e089a..000000000000
--- a/code/addons/storyshots-core/stories/storyshot.shallow.test.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import path from 'path';
-import initStoryshots, { shallowSnapshot } from '../src';
-
-initStoryshots({
- framework: 'react',
- configPath: path.join(__dirname, 'exported_metadata'),
- test: shallowSnapshot,
-});
diff --git a/code/addons/storyshots-core/stories/storyshot.shallowWithOptions.test.js b/code/addons/storyshots-core/stories/storyshot.shallowWithOptions.test.js
deleted file mode 100644
index 5a4c45b78257..000000000000
--- a/code/addons/storyshots-core/stories/storyshot.shallowWithOptions.test.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import path from 'path';
-import initStoryshots, { shallowSnapshot } from '../src';
-
-initStoryshots({
- framework: 'react',
- configPath: path.join(__dirname, 'exported_metadata'),
- test: (data) =>
- shallowSnapshot({
- ...data,
- }),
-});
diff --git a/code/addons/storyshots-core/stories/storyshot.snapshotWithOptionsFunction.test.js b/code/addons/storyshots-core/stories/storyshot.snapshotWithOptionsFunction.test.js
deleted file mode 100644
index f6fc73770aa9..000000000000
--- a/code/addons/storyshots-core/stories/storyshot.snapshotWithOptionsFunction.test.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import path from 'path';
-import initStoryshots, { snapshotWithOptions } from '../src';
-
-initStoryshots({
- framework: 'react',
- configPath: path.join(__dirname, 'exported_metadata'),
- test: snapshotWithOptions(() => ({})),
-});
diff --git a/code/addons/storyshots-core/stories/storyshot.test.js b/code/addons/storyshots-core/stories/storyshot.test.js
deleted file mode 100644
index 9a1dde49cb99..000000000000
--- a/code/addons/storyshots-core/stories/storyshot.test.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import path from 'path';
-import initStoryshots, { multiSnapshotWithOptions } from '../src';
-
-jest.mock('@storybook/node-logger');
-
-// with react-test-renderer
-initStoryshots({
- framework: 'react',
- // Ignore integrityOptions for async.storyshot because only run when asyncJest is true
- integrityOptions: { cwd: __dirname, ignore: ['**/**.async.storyshot'] },
- configPath: path.join(__dirname, 'exported_metadata'),
- test: multiSnapshotWithOptions(),
-});
diff --git a/code/addons/storyshots-core/tsconfig.build.json b/code/addons/storyshots-core/tsconfig.build.json
deleted file mode 100644
index dae6c1e39197..000000000000
--- a/code/addons/storyshots-core/tsconfig.build.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "extends": "./tsconfig.json",
- "compileOnSave": false,
- "compilerOptions": {
- "target": "ES2020",
- "module": "CommonJS",
- "lib": ["es2020", "dom"],
- "esModuleInterop": true,
- "experimentalDecorators": true,
- "emitDecoratorMetadata": true,
- "declaration": true,
- "outDir": "dist",
- "types": ["node"],
- "skipLibCheck": true,
- "resolveJsonModule": true,
- "allowJs": true,
- "pretty": true,
- "noErrorTruncation": true,
- "listEmittedFiles": false,
- "noUnusedLocals": false
- },
- "include": ["src/**/*", "src/**/*.json"]
-}
diff --git a/code/addons/storyshots-core/tsconfig.json b/code/addons/storyshots-core/tsconfig.json
deleted file mode 100644
index 6d43397802f1..000000000000
--- a/code/addons/storyshots-core/tsconfig.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "extends": "../../tsconfig.json",
- "compilerOptions": {
- "declaration": true,
- "jsx": "preserve",
- "skipLibCheck": true,
- "skipDefaultLibCheck": true,
- "strict": true
- },
- "include": ["src/**/*.ts"]
-}
diff --git a/code/addons/storyshots-puppeteer/.eslintrc.js b/code/addons/storyshots-puppeteer/.eslintrc.js
deleted file mode 100644
index cc34d2deab0f..000000000000
--- a/code/addons/storyshots-puppeteer/.eslintrc.js
+++ /dev/null
@@ -1,5 +0,0 @@
-module.exports = {
- settings: {
- 'import/core-modules': ['puppeteer'],
- },
-};
diff --git a/code/addons/storyshots-puppeteer/README.md b/code/addons/storyshots-puppeteer/README.md
deleted file mode 100644
index de7d4d801326..000000000000
--- a/code/addons/storyshots-puppeteer/README.md
+++ /dev/null
@@ -1,346 +0,0 @@
-# StoryShots + [Puppeteer](https://github.com/GoogleChrome/puppeteer)
-
-## Getting Started
-
-Add the following modules into your app.
-
-```sh
-npm install @storybook/addon-storyshots-puppeteer puppeteer --save-dev
-```
-
-⚠️ As of Storybook 5.3 `puppeteer` is no longer included in the addon dependencies and must be added to your project directly.
-
-## Configure Storyshots for Puppeteer tests
-
-⚠️ **React-native** is **not supported** by this test function.
-
-When running Puppeteer tests for your stories, you have two options:
-
-- Have a storybook running (ie. accessible via http(s), for instance using `npm run storybook`)
-- Have a static build of the storybook (for instance, using `npm run build-storybook`)
-
-Then you will need to reference the storybook URL (`http(s)://...`)
-
-## _puppeteerTest_
-
-Allows to define arbitrary Puppeteer tests as `story.parameters.puppeteerTest` function.
-
-You can either create a new Storyshots instance or edit the one you previously used:
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-import { puppeteerTest } from '@storybook/addon-storyshots-puppeteer';
-
-initStoryshots({ suite: 'Puppeteer storyshots', test: puppeteerTest() });
-```
-
-Then, in your stories:
-
-```js
-export const myExample = () => {
- ...
-};
-myExample.parameters = {
- async puppeteerTest(page) {
- const element = await page.$('');
- await element.click();
- expect(something).toBe(something);
- },
-};
-```
-
-This will assume you have a storybook running on at __.
-Internally here are the steps:
-
-- Launches a Chrome headless using [puppeteer](https://github.com/GoogleChrome/puppeteer)
-- Browses each stories (calling __ URL),
-- Runs the `parameters.puppeteerTest` function if it's defined.
-
-### Specifying the storybook URL
-
-If you want to set specific storybook URL, you can specify via the `storybookUrl` parameter, see below:
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-import { puppeteerTest } from '@storybook/addon-storyshots-puppeteer';
-
-initStoryshots({
- suite: 'Puppeteer storyshots',
- test: puppeteerTest({ storybookUrl: 'http://my-specific-domain.com:9010' }),
-});
-```
-
-The above config will use __ for tests. You can also use query parameters in your URL (e.g. for setting a different background for your storyshots, if you use `@storybook/addon-backgrounds`).
-
-### Specifying options to _goto()_ (Puppeteer API)
-
-You might use `getGotoOptions` to specify options when the storybook is navigating to a story (using the `goto` method). Will be passed to [Puppeteer .goto() fn](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagegotourl-options)
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-import { puppeteerTest } from '@storybook/addon-storyshots-puppeteer';
-
-const getGotoOptions = ({ context, url }) => {
- return {
- waitUntil: 'networkidle0',
- };
-};
-
-initStoryshots({
- suite: 'Puppeteer storyshots',
- test: puppeteerTest({ storybookUrl: 'http://localhost:6006', getGotoOptions }),
-});
-```
-
-### Customizing browser launch options (Puppeteer API)
-
-You might use the `browserLaunchOptions` to specify options for the default browser instance. Will be passed to [puppeteer.launch()](https://pptr.dev/api/puppeteer.puppeteernode.launch)
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-import { puppeteerTest } from '@storybook/addon-storyshots-puppeteer';
-
-initStoryshots({
- suite: 'Puppeteer storyshots',
- test: puppeteerTest({
- storybookUrl: 'https://some-local-ssl-url:7777',
- browserLaunchOptions: {
- // For ignoring self-signed certificates
- ignoreHTTPSErrors: true,
- },
- }),
-});
-```
-
-### Specifying custom Chrome executable path (Puppeteer API)
-
-You might use `chromeExecutablePath` to specify the path to a different version of Chrome, without downloading Chromium. Will be passed to [Runs a bundled version of Chromium](https://github.com/GoogleChrome/puppeteer#default-runtime-settings)
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-import { puppeteerTest } from '@storybook/addon-storyshots-puppeteer';
-
-const chromeExecutablePath = '/usr/local/bin/chrome';
-
-initStoryshots({
- suite: 'Puppeteer storyshots',
- test: puppeteerTest({ storybookUrl: 'http://localhost:6006', chromeExecutablePath }),
-});
-```
-
-Alternatively, you may set the `SB_CHROMIUM_PATH` environment variable. If both are set, then `chromeExecutablePath` will take precedence.
-
-### Specifying a custom Puppeteer `browser` instance
-
-You might use the async `getCustomBrowser` function to obtain a custom instance of a Puppeteer `browser` object. This will prevent `storyshots-puppeteer` from creating its own `browser`. It will create and close pages within the `browser`, and it is your responsibility to manage the lifecycle of the `browser` itself.
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-import { puppeteerTest } from '@storybook/addon-storyshots-puppeteer';
-import puppeteer from 'puppeteer';
-
-(async function () {
- initStoryshots({
- suite: 'Puppeteer storyshots',
- test: puppeteerTest({
- storybookUrl: 'http://localhost:6006',
- getCustomBrowser: () => puppeteer.connect({ browserWSEndpoint: 'ws://yourUrl' }),
- }),
- });
-})();
-```
-
-### Customizing a `page` instance
-
-Sometimes, there is a need to customize a page before it calls the `goto` api.
-
-An example of device emulation:
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-import { puppeteerTest } from '@storybook/addon-storyshots-puppeteer';
-const devices = require('puppeteer/DeviceDescriptors');
-
-const iPhone = devices['iPhone 6'];
-
-function customizePage(page) {
- return page.emulate(iPhone);
-}
-
-initStoryshots({
- suite: 'Puppeteer storyshots',
- test: puppeteerTest({
- storybookUrl: 'http://localhost:6006',
- customizePage,
- }),
-});
-```
-
-### Specifying setup and tests timeout
-
-By default, `@storybook/addon-storyshots-puppeteer` uses 15 second timeouts for browser setup and test functions.
-Those can be customized with `setupTimeout` and `testTimeout` parameters.
-
-### Integrate Puppeteer storyshots with regular app
-
-You may want to use another Jest project to run your Puppeteer storyshots as they require more resources: Chrome and Storybook built/served.
-
-### Integrate Puppeteer storyshots with [Create React App](https://github.com/facebookincubator/create-react-app)
-
-You have two options here, you can either:
-
-- Add the storyshots configuration inside any of your `test.js` file. You must ensure you have either a running storybook or a static build available.
-
-- Create a custom test file using Jest outside of the CRA scope:
-
- A more robust approach would be to separate existing test files ran by create-react-app (anything `(test|spec).js` suffixed files) from the test files to run Puppeteer storyshots.
- This use case can be achieved by using a custom name for the test file, ie something like `puppeteer-storyshots.runner.js`. This file will contain the `initStoryshots` call with Puppeteer storyshots configuration.
- Then you will create a separate script entry in your package.json, for instance
-
- ```json
- {
- "scripts": {
- "puppeteer-storyshots": "jest puppeteer-storyshots.runner.js --config path/to/custom/jest.config.json"
- }
- }
- ```
-
- Note that you will certainly need a custom config file for Jest as you run it outside of the CRA scope and thus you do not have the built-in config.
-
- Once that's setup, you can run `npm run puppeteer-storyshots`.
-
-### Reminder
-
-Puppeteer launches a web browser (Chrome) internally.
-
-The browser opens a page (either using the static build of storybook or a running instance of Storybook)
-
-If you run your test without either the static build or a running instance, this wont work.
-
-To make sure your tests run against the latest changes of your Storybook, you must keep your static build or running Storybook up-to-date.
-This can be achieved by adding a step before running the test ie: `npm run build-storybook && npm run image-snapshots`.
-If you run the Puppeteer storyshots against a running Storybook in dev mode, you don't have to worry about the stories being up-to-date because the dev-server is watching changes and rebuilds automatically.
-
-## _axeTest_
-
-Runs [Axe](https://www.deque.com/axe/) accessibility checks and verifies that they pass using [jest-puppeteer-axe](https://github.com/WordPress/gutenberg/tree/master/packages/jest-puppeteer-axe).
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-import { axeTest } from '@storybook/addon-storyshots-puppeteer';
-
-initStoryshots({ suite: 'A11y checks', test: axeTest() });
-```
-
-For configuration, it uses the same `story.parameters.a11y` parameter as [`@storybook/addon-a11y`](https://github.com/storybookjs/storybook/tree/next/code/addons/a11y#parameters)
-
-### Specifying options to `axeTest`
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-import { axeTest } from '@storybook/addon-storyshots-puppeteer';
-
-const beforeAxeTest = (page, { context: { kind, story }, url }) => {
- return new Promise((resolve) =>
- setTimeout(() => {
- resolve();
- }, 600)
- );
-};
-
-initStoryshots({ suite: 'A11y checks', test: axeTest({ beforeAxeTest }) });
-```
-
-`beforeAxeTest` receives the [Puppeteer page instance](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-page) and an object: `{ context: {kind, story}, url}`. _kind_ is the kind of the story and the _story_ its name. _url_ is the URL the browser will use to screenshot. `beforeAxeTest` is part of the promise chain and is called after the browser navigation is completed but before the screenshot is taken. It allows for triggering events on the page elements and delaying the axe test .
-
-## _imageSnapshots_
-
-Generates and compares screenshots of your stories using [jest-image-snapshot](https://github.com/americanexpress/jest-image-snapshot).
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-import { imageSnapshot } from '@storybook/addon-storyshots-puppeteer';
-
-initStoryshots({ suite: 'Image storyshots', test: imageSnapshot() });
-```
-
-It saves all images under \_\_image_snapshots\_\_ folder.
-
-### Specifying options to _jest-image-snapshots_
-
-If you wish to customize [jest-image-snapshot](https://github.com/americanexpress/jest-image-snapshot), then you can provide a `getMatchOptions` parameter that should return the options config object. Additionally, you can provide `beforeScreenshot` which is called before the screenshot is captured and a `afterScreenshot` handler which is called after the screenshot and receives the just created image.
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-import { imageSnapshot } from '@storybook/addon-storyshots-puppeteer';
-const getMatchOptions = ({ context: { kind, story }, url }) => {
- return {
- failureThreshold: 0.2,
- failureThresholdType: 'percent',
- };
-};
-const beforeScreenshot = (page, { context: { kind, story }, url }) => {
- return new Promise((resolve) =>
- setTimeout(() => {
- resolve();
- }, 600)
- );
-};
-const afterScreenshot = ({ image, context }) => {
- return new Promise((resolve) =>
- setTimeout(() => {
- resolve();
- }, 600)
- );
-};
-initStoryshots({
- suite: 'Image storyshots',
- test: imageSnapshot({
- storybookUrl: 'http://localhost:6006',
- getMatchOptions,
- beforeScreenshot,
- afterScreenshot,
- }),
-});
-```
-
-`getMatchOptions` receives an object: `{ context: {kind, story}, url}`. _kind_ is the kind of the story and the _story_ its name. _url_ is the URL the browser will use to screenshot.
-
-`beforeScreenshot` receives the [Puppeteer page instance](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-page) and an object: `{ context: {kind, story}, url}`. _kind_ is the kind of the story and the _story_ its name. _url_ is the URL the browser will use to screenshot. `beforeScreenshot` is part of the promise chain and is called after the browser navigation is completed but before the screenshot is taken. It allows for triggering events on the page elements and delaying the screenshot and can be used avoid regressions due to mounting animations.
-
-`afterScreenshot` receives the created image from puppeteer.
-
-### Specifying options to _screenshot()_ (Puppeteer API)
-
-You might use `getScreenshotOptions` to specify options for screenshot. Will be passed to [Puppeteer .screenshot() fn](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagescreenshotoptions)
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-import { imageSnapshot } from '@storybook/addon-storyshots-puppeteer';
-const getScreenshotOptions = ({ context, url }) => {
- return {
- encoding: 'base64', // encoding: 'base64' is a property required by puppeteer
- fullPage: false, // Do not take the full page screenshot. Default is 'true' in Storyshots.,
- };
-};
-initStoryshots({
- suite: 'Image storyshots',
- test: imageSnapshot({ storybookUrl: 'http://localhost:6006', getScreenshotOptions }),
-});
-```
-
-`getScreenshotOptions` receives an object `{ context: {kind, story}, url}`. _kind_ is the kind of the story and the _story_ its name. _url_ is the URL the browser will use to screenshot.
-
-To create a screenshot of just a single element (with its children), rather than the page or current viewport, an ElementHandle can be returned from `beforeScreenshot`:
-
-```js
-import initStoryshots from '@storybook/addon-storyshots';
-import { imageSnapshot } from '@storybook/addon-storyshots-puppeteer';
-
-const beforeScreenshot = (page) => page.$('#storybook-root > *');
-
-initStoryshots({
- suite: 'Image storyshots',
- test: imageSnapshot({ storybookUrl: 'http://localhost:6006', beforeScreenshot }),
-});
-```
diff --git a/code/addons/storyshots-puppeteer/jest.config.js b/code/addons/storyshots-puppeteer/jest.config.js
deleted file mode 100644
index 0115c67e5629..000000000000
--- a/code/addons/storyshots-puppeteer/jest.config.js
+++ /dev/null
@@ -1,12 +0,0 @@
-const path = require('path');
-const baseConfig = require('../../jest.config.browser');
-
-module.exports = {
- ...baseConfig,
- snapshotSerializers: [...baseConfig.snapshotSerializers, 'enzyme-to-json/serializer'],
- transform: {
- ...baseConfig.transform,
- '^.+\\.stories\\.[jt]sx?$': '@storybook/addon-storyshots/injectFileName',
- },
- displayName: __dirname.split(path.sep).slice(-2).join(path.posix.sep),
-};
diff --git a/code/addons/storyshots-puppeteer/package.json b/code/addons/storyshots-puppeteer/package.json
deleted file mode 100644
index 657369001f2a..000000000000
--- a/code/addons/storyshots-puppeteer/package.json
+++ /dev/null
@@ -1,66 +0,0 @@
-{
- "name": "@storybook/addon-storyshots-puppeteer",
- "version": "7.6.0-beta.2",
- "description": "Image snapshots addition to StoryShots based on puppeteer",
- "keywords": [
- "addon",
- "storybook"
- ],
- "homepage": "https://github.com/storybookjs/storybook/tree/next/code/addons/storyshots-puppeteer",
- "bugs": {
- "url": "https://github.com/storybookjs/storybook/issues"
- },
- "repository": {
- "type": "git",
- "url": "https://github.com/storybookjs/storybook.git",
- "directory": "code/addons/storyshots-puppeteer"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/storybook"
- },
- "license": "MIT",
- "main": "dist/index.js",
- "module": "dist/index.mjs",
- "types": "dist/index.d.ts",
- "files": [
- "dist/**/*",
- "README.md",
- "*.js",
- "*.mjs",
- "*.d.ts",
- "!src/**/*"
- ],
- "scripts": {
- "check": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/check.ts",
- "prep": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/tsc.ts"
- },
- "dependencies": {
- "@axe-core/puppeteer": "^4.2.0",
- "@storybook/csf": "^0.1.2",
- "@storybook/node-logger": "workspace:*",
- "@storybook/types": "workspace:*",
- "@types/jest-image-snapshot": "^6.0.0",
- "jest-image-snapshot": "^6.0.0"
- },
- "devDependencies": {
- "@types/puppeteer": "^5.4.0",
- "enzyme": "^3.11.0",
- "enzyme-to-json": "^3.6.1",
- "puppeteer": "^2.0.0 || ^3.0.0"
- },
- "peerDependencies": {
- "@storybook/addon-storyshots": "workspace:*",
- "puppeteer": ">=2.0.0"
- },
- "peerDependenciesMeta": {
- "puppeteer": {
- "optional": true
- }
- },
- "publishConfig": {
- "access": "public"
- },
- "bundler": {},
- "gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae17"
-}
diff --git a/code/addons/storyshots-puppeteer/preset.js b/code/addons/storyshots-puppeteer/preset.js
deleted file mode 100644
index 501f6e0c1310..000000000000
--- a/code/addons/storyshots-puppeteer/preset.js
+++ /dev/null
@@ -1,4 +0,0 @@
-// storyshots is not a typical addon because it's just a command-line tool
-// nevertheless if you add it to .storybook/main.js it shouldn't complain
-// https://github.com/storybookjs/storybook/issues/7959
-module.exports = {};
diff --git a/code/addons/storyshots-puppeteer/project.json b/code/addons/storyshots-puppeteer/project.json
deleted file mode 100644
index 7625e336cc8d..000000000000
--- a/code/addons/storyshots-puppeteer/project.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "@storybook/addon-storyshots-puppeteer",
- "$schema": "../../node_modules/nx/schemas/project-schema.json",
- "implicitDependencies": [],
- "type": "library"
-}
diff --git a/code/addons/storyshots-puppeteer/src/__tests__/url.test.ts b/code/addons/storyshots-puppeteer/src/__tests__/url.test.ts
deleted file mode 100644
index cf36929dee62..000000000000
--- a/code/addons/storyshots-puppeteer/src/__tests__/url.test.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import { toId } from '@storybook/csf';
-
-import { constructUrl } from '../url';
-
-jest.mock('@storybook/node-logger');
-
-const id = toId('someKind', 'someStory');
-
-describe('Construct URL for Storyshots', () => {
- it('can use a url without path and without query params', () => {
- expect(constructUrl('http://localhost:9001', id)).toEqual(
- 'http://localhost:9001/iframe.html?id=somekind--somestory'
- );
- });
-
- it('can use a url without path (but slash) and without query params', () => {
- expect(constructUrl('http://localhost:9001/', id)).toEqual(
- 'http://localhost:9001/iframe.html?id=somekind--somestory'
- );
- });
-
- it('can use a url without path and with query params', () => {
- expect(constructUrl('http://localhost:9001?hello=world', id)).toEqual(
- 'http://localhost:9001/iframe.html?hello=world&id=somekind--somestory'
- );
- });
-
- it('can use a url without path (buth slash) and with query params', () => {
- expect(constructUrl('http://localhost:9001/?hello=world', id)).toEqual(
- 'http://localhost:9001/iframe.html?hello=world&id=somekind--somestory'
- );
- });
-
- it('can use a url with some path and query params', () => {
- expect(constructUrl('http://localhost:9001/nice-path?hello=world', id)).toEqual(
- 'http://localhost:9001/nice-path/iframe.html?hello=world&id=somekind--somestory'
- );
- });
-
- it('can use a url with some path (slash) and query params', () => {
- expect(constructUrl('http://localhost:9001/nice-path/?hello=world', id)).toEqual(
- 'http://localhost:9001/nice-path/iframe.html?hello=world&id=somekind--somestory'
- );
- });
-
- it('can use a url with username and password and query params', () => {
- expect(
- constructUrl('http://username:password@localhost:9001/nice-path/?hello=world', id)
- ).toEqual(
- 'http://username:password@localhost:9001/nice-path/iframe.html?hello=world&id=somekind--somestory'
- );
- });
-
- it('can use a url with username and query params', () => {
- expect(constructUrl('http://username@localhost:9001/nice-path/?hello=world', id)).toEqual(
- 'http://username@localhost:9001/nice-path/iframe.html?hello=world&id=somekind--somestory'
- );
- });
-
- it('can use a url with file protocol', () => {
- expect(constructUrl('file://users/storybook', id)).toEqual(
- 'file://users/storybook/iframe.html?id=somekind--somestory'
- );
- });
-});
diff --git a/code/addons/storyshots-puppeteer/src/axeTest.ts b/code/addons/storyshots-puppeteer/src/axeTest.ts
deleted file mode 100644
index b2a7bdb603ff..000000000000
--- a/code/addons/storyshots-puppeteer/src/axeTest.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import AxePuppeteer from '@axe-core/puppeteer';
-import type { AxeConfig } from './config';
-import { defaultAxeConfig } from './config';
-import { puppeteerTest } from './puppeteerTest';
-
-export const axeTest = (customConfig: Partial = {}) => {
- const extendedConfig = { ...defaultAxeConfig, ...customConfig };
- const { beforeAxeTest } = extendedConfig;
-
- return puppeteerTest({
- ...extendedConfig,
- async testBody(page, testOptions) {
- const {
- element = '#storybook-root',
- exclude,
- disabledRules,
- options,
- config,
- } = testOptions.context.parameters.a11y || {};
- await beforeAxeTest(page, options);
- const axe = new AxePuppeteer(page);
- axe.include(element);
-
- if (exclude) {
- axe.exclude(exclude);
- }
-
- if (options) {
- axe.options(options);
- }
-
- if (disabledRules) {
- axe.disableRules(disabledRules);
- }
-
- if (config) {
- axe.configure(config);
- }
-
- const { violations } = await axe.analyze();
-
- expect(violations).toHaveLength(0);
- },
- });
-};
diff --git a/code/addons/storyshots-puppeteer/src/config.ts b/code/addons/storyshots-puppeteer/src/config.ts
deleted file mode 100644
index 25d6633540bc..000000000000
--- a/code/addons/storyshots-puppeteer/src/config.ts
+++ /dev/null
@@ -1,105 +0,0 @@
-import type { MatchImageSnapshotOptions } from 'jest-image-snapshot';
-import type { ScreenshotOptions, Browser, Page, ElementHandle, LaunchOptions } from 'puppeteer';
-
-type PuppeteerLifeCycleEvent = 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2';
-
-export interface Context {
- kind: string;
- story: string;
- parameters: {
- [key: string]: any;
- };
-}
-
-interface Options {
- context: Context;
- url: string;
-}
-
-interface Base64ScreenShotOptions extends ScreenshotOptions {
- encoding: 'base64';
-}
-
-interface DirectNavigationOptions {
- referer?: string;
- timeout?: number;
- waitUntil?: PuppeteerLifeCycleEvent | PuppeteerLifeCycleEvent[];
-}
-
-export interface CommonConfig {
- storybookUrl: string;
- chromeExecutablePath?: string;
- getGotoOptions: (options: Options) => DirectNavigationOptions | undefined;
- customizePage: (page: Page) => Promise;
- getCustomBrowser?: () => Promise;
- /**
- * Puppeteer browser launch options:
- * {@link https://pptr.dev/api/puppeteer.puppeteernode.launch/ puppeteer.launch()}
- */
- browserLaunchOptions: LaunchOptions;
- setupTimeout: number;
- testTimeout: number;
-}
-
-export interface PuppeteerTestConfig extends CommonConfig {
- testBody: ((page: Page, options: Options) => void | Promise) & {
- filter?: (options: Options) => boolean;
- };
-}
-
-export interface ImageSnapshotConfig extends CommonConfig {
- getMatchOptions: (options: Options) => MatchImageSnapshotOptions | undefined;
- getScreenshotOptions: (options: Options) => Base64ScreenShotOptions;
- beforeScreenshot: (page: Page, options: Options) => Promise;
- afterScreenshot: (options: { image: string | void | Buffer; context: Context }) => Promise;
-}
-
-export interface AxeConfig extends CommonConfig {
- beforeAxeTest: (page: Page, options: Options) => Promise;
-}
-
-const noop: () => undefined = () => undefined;
-const asyncNoop: () => Promise = async () => undefined;
-
-export const defaultCommonConfig: CommonConfig = {
- storybookUrl: 'http://localhost:6006',
- chromeExecutablePath: process.env.SB_CHROMIUM_PATH,
- getGotoOptions: noop,
- customizePage: asyncNoop,
- getCustomBrowser: undefined,
- browserLaunchOptions: {},
- setupTimeout: 15000,
- testTimeout: 15000,
-};
-
-const getTestBody = (options: Options) => options.context.parameters.puppeteerTest;
-
-function defaultTestBody(page: Page, options: Options) {
- const testBody = getTestBody(options);
- if (testBody != null) {
- return testBody(page, options);
- }
- return null;
-}
-
-defaultTestBody.filter = (options: Options) => getTestBody(options) != null;
-
-export const defaultPuppeteerTestConfig: PuppeteerTestConfig = {
- ...defaultCommonConfig,
- testBody: defaultTestBody,
-};
-
-// We consider taking the full page is a reasonable default.
-const defaultScreenshotOptions = () => ({ fullPage: true, encoding: 'base64' } as const);
-export const defaultImageSnapshotConfig: ImageSnapshotConfig = {
- ...defaultCommonConfig,
- getMatchOptions: noop,
- getScreenshotOptions: defaultScreenshotOptions,
- beforeScreenshot: asyncNoop,
- afterScreenshot: asyncNoop,
-};
-
-export const defaultAxeConfig: AxeConfig = {
- ...defaultCommonConfig,
- beforeAxeTest: asyncNoop,
-};
diff --git a/code/addons/storyshots-puppeteer/src/imageSnapshot.ts b/code/addons/storyshots-puppeteer/src/imageSnapshot.ts
deleted file mode 100644
index b61552be7787..000000000000
--- a/code/addons/storyshots-puppeteer/src/imageSnapshot.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { toMatchImageSnapshot } from 'jest-image-snapshot';
-import type { ImageSnapshotConfig } from './config';
-import { defaultImageSnapshotConfig } from './config';
-import { puppeteerTest } from './puppeteerTest';
-
-expect.extend({ toMatchImageSnapshot });
-
-export const imageSnapshot = (customConfig: Partial = {}) => {
- const config = { ...defaultImageSnapshotConfig, ...customConfig };
- const { getMatchOptions, getScreenshotOptions, beforeScreenshot, afterScreenshot } = config;
-
- return puppeteerTest({
- ...config,
- async testBody(page, options) {
- expect.hasAssertions();
- const element = await beforeScreenshot(page, options);
- const image = await (element || page).screenshot(getScreenshotOptions(options));
- await afterScreenshot({ image, context: options.context });
- expect(image).toMatchImageSnapshot(getMatchOptions(options));
- },
- });
-};
diff --git a/code/addons/storyshots-puppeteer/src/index.ts b/code/addons/storyshots-puppeteer/src/index.ts
deleted file mode 100644
index dd2e0b715fee..000000000000
--- a/code/addons/storyshots-puppeteer/src/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export * from './config';
-export * from './puppeteerTest';
-export * from './axeTest';
-export * from './imageSnapshot';
diff --git a/code/addons/storyshots-puppeteer/src/puppeteerTest.ts b/code/addons/storyshots-puppeteer/src/puppeteerTest.ts
deleted file mode 100644
index 03517979d31b..000000000000
--- a/code/addons/storyshots-puppeteer/src/puppeteerTest.ts
+++ /dev/null
@@ -1,100 +0,0 @@
-import type { Browser, Page } from 'puppeteer';
-import { logger } from '@storybook/node-logger';
-import { constructUrl } from './url';
-import type { PuppeteerTestConfig } from './config';
-import { defaultPuppeteerTestConfig } from './config';
-
-export const puppeteerTest = (customConfig: Partial = {}) => {
- const {
- storybookUrl,
- chromeExecutablePath,
- getGotoOptions,
- customizePage,
- getCustomBrowser,
- browserLaunchOptions,
- testBody,
- setupTimeout,
- testTimeout,
- } = { ...defaultPuppeteerTestConfig, ...customConfig };
-
- let browser: Browser; // holds ref to browser. (ie. Chrome)
- let page: Page; // Hold ref to the page to screenshot.
-
- const testFn = async ({ context }: any) => {
- const { kind, framework, name, id } = context;
- if (framework === 'react-native') {
- // Skip tests since RN is not a browser environment.
- logger.error(
- "It seems you are running puppeteer test on RN app and it's not supported. Skipping test."
- );
-
- return;
- }
-
- const url = constructUrl(storybookUrl, id);
- const options = { context, url };
- if (testBody.filter != null && !testBody.filter(options)) {
- return;
- }
-
- if (!browser || !page) {
- logger.error(
- `Error when running puppeteer test for ${kind} - ${name} : It seems the headless browser is not running.`
- );
-
- throw new Error('no-headless-browser-running');
- }
-
- try {
- await customizePage(page);
- await page.goto(url, getGotoOptions(options));
- } catch (e) {
- logger.error(
- `Error when connecting to ${url}, did you start or build the storybook first? A storybook instance should be running or a static version should be built when using puppeteer test feature.`
- );
- throw e;
- }
- await testBody(page, options);
- };
- testFn.timeout = testTimeout;
-
- const cleanup = async () => {
- if (getCustomBrowser && page) {
- await page.close();
- } else if (browser) {
- await browser.close();
- }
- };
-
- process.on('SIGINT', async () => {
- await cleanup();
- process.exit();
- });
- testFn.afterAll = cleanup;
-
- const beforeAll = async () => {
- if (getCustomBrowser) {
- browser = await getCustomBrowser();
- } else {
- // eslint-disable-next-line global-require
- const puppeteer = require('puppeteer');
- // add some options "no-sandbox" to make it work properly on some Linux systems as proposed here: https://github.com/Googlechrome/puppeteer/issues/290#issuecomment-322851507
- browser = await puppeteer.launch({
- ...browserLaunchOptions,
- args: [
- '--no-sandbox ',
- '--disable-setuid-sandbox',
- '--disable-dev-shm-usage',
- ...(browserLaunchOptions?.args || []),
- ],
- executablePath: chromeExecutablePath,
- });
- }
-
- page = await browser.newPage();
- };
- beforeAll.timeout = setupTimeout;
- testFn.beforeAll = beforeAll;
-
- return testFn;
-};
diff --git a/code/addons/storyshots-puppeteer/src/url.ts b/code/addons/storyshots-puppeteer/src/url.ts
deleted file mode 100644
index 036fc76200c6..000000000000
--- a/code/addons/storyshots-puppeteer/src/url.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { URL } from 'url';
-
-export const constructUrl = (storybookUrl: string, id: string) => {
- const url = new URL(storybookUrl);
- url.pathname = url.pathname.replace(/\/$/, '').concat('/iframe.html');
- url.searchParams.append('id', id);
- return url.toString();
-};
diff --git a/code/addons/storyshots-puppeteer/tsconfig.build.json b/code/addons/storyshots-puppeteer/tsconfig.build.json
deleted file mode 100644
index dae6c1e39197..000000000000
--- a/code/addons/storyshots-puppeteer/tsconfig.build.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "extends": "./tsconfig.json",
- "compileOnSave": false,
- "compilerOptions": {
- "target": "ES2020",
- "module": "CommonJS",
- "lib": ["es2020", "dom"],
- "esModuleInterop": true,
- "experimentalDecorators": true,
- "emitDecoratorMetadata": true,
- "declaration": true,
- "outDir": "dist",
- "types": ["node"],
- "skipLibCheck": true,
- "resolveJsonModule": true,
- "allowJs": true,
- "pretty": true,
- "noErrorTruncation": true,
- "listEmittedFiles": false,
- "noUnusedLocals": false
- },
- "include": ["src/**/*", "src/**/*.json"]
-}
diff --git a/code/addons/storyshots-puppeteer/tsconfig.json b/code/addons/storyshots-puppeteer/tsconfig.json
deleted file mode 100644
index b32dad6f525c..000000000000
--- a/code/addons/storyshots-puppeteer/tsconfig.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "extends": "../../tsconfig.json",
- "compilerOptions": {
- "skipLibCheck": true,
- "types": ["node"],
- "declaration": true,
- "strict": true
- },
- "include": ["src/**/*"]
-}
diff --git a/code/addons/storysource/package.json b/code/addons/storysource/package.json
index 333dc2b3ceda..1f564a9602de 100644
--- a/code/addons/storysource/package.json
+++ b/code/addons/storysource/package.json
@@ -58,12 +58,12 @@
"@storybook/router": "workspace:*",
"@storybook/source-loader": "workspace:*",
"@storybook/theming": "workspace:*",
- "@types/react": "^16.14.34",
+ "@types/react": "^18.0.37",
"@types/react-syntax-highlighter": "11.0.5",
- "react": "^16.8.0",
- "react-dom": "^16.8.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
"react-syntax-highlighter": "^15.5.0",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/addons/themes/README.md b/code/addons/themes/README.md
index 5ed36f2c4050..55bc748fd48f 100644
--- a/code/addons/themes/README.md
+++ b/code/addons/themes/README.md
@@ -12,7 +12,7 @@ Requires Storybook 7.0 or later. If you need to add it to your Storybook, you ca
npm i -D @storybook/addon-themes
```
-Then, add following content to [`.storybook/main.js`](https://storybook.js.org/docs/react/configure/overview#configure-your-storybook-project):
+Then, add following content to [`.storybook/main.js`](https://storybook.js.org/docs/react/configure/#configure-your-storybook-project):
```js
export default {
diff --git a/code/addons/themes/package.json b/code/addons/themes/package.json
index 511dcbc81b07..2edb9b7c2488 100644
--- a/code/addons/themes/package.json
+++ b/code/addons/themes/package.json
@@ -59,11 +59,12 @@
"@storybook/client-logger": "workspace:*",
"@storybook/components": "workspace:*",
"@storybook/core-events": "workspace:*",
+ "@storybook/icons": "^1.2.1",
"@storybook/manager-api": "workspace:*",
"@storybook/preview-api": "workspace:*",
"@storybook/theming": "workspace:*",
"@storybook/types": "workspace:*",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/addons/themes/src/theme-switcher.tsx b/code/addons/themes/src/theme-switcher.tsx
index 3658a3ef78cc..4fc7ffa89256 100644
--- a/code/addons/themes/src/theme-switcher.tsx
+++ b/code/addons/themes/src/theme-switcher.tsx
@@ -1,8 +1,9 @@
import React, { Fragment, useMemo } from 'react';
import { useAddonState, useChannel, useGlobals, useParameter } from '@storybook/manager-api';
import { styled } from '@storybook/theming';
-import { Icons, IconButton, WithTooltip, TooltipLinkList } from '@storybook/components';
+import { IconButton, WithTooltip, TooltipLinkList } from '@storybook/components';
+import { PaintBrushIcon } from '@storybook/icons';
import type { ThemeAddonState, ThemeParameters } from './constants';
import {
PARAM_KEY,
@@ -74,7 +75,7 @@ export const ThemeSwitcher = () => {
}}
>
-
+
{label && {label} }
diff --git a/code/addons/toolbars/README.md b/code/addons/toolbars/README.md
index b6cf730ab141..560966c094ce 100644
--- a/code/addons/toolbars/README.md
+++ b/code/addons/toolbars/README.md
@@ -12,13 +12,13 @@ The Toolbars addon controls global story rendering options from [Storybook's](ht
## Installation
-Toolbars is part of [essentials](https://storybook.js.org/docs/react/essentials/introduction) and so is installed in all new Storybooks by default. If you need to add it to your Storybook, you can run:
+Toolbars is part of [essentials](https://storybook.js.org/docs/react/essentials) and so is installed in all new Storybooks by default. If you need to add it to your Storybook, you can run:
```sh
npm i -D @storybook/addon-toolbars
```
-Then, add following content to [`.storybook/main.js`](https://storybook.js.org/docs/react/configure/overview#configure-your-storybook-project):
+Then, add following content to [`.storybook/main.js`](https://storybook.js.org/docs/react/configure/#configure-your-storybook-project):
```js
export default {
diff --git a/code/addons/toolbars/package.json b/code/addons/toolbars/package.json
index 6d79696b0154..80ba3891dedb 100644
--- a/code/addons/toolbars/package.json
+++ b/code/addons/toolbars/package.json
@@ -56,9 +56,9 @@
"@storybook/manager-api": "workspace:*",
"@storybook/preview-api": "workspace:*",
"@storybook/theming": "workspace:*",
- "react": "^16.8.0",
- "react-dom": "^16.8.0",
- "typescript": "~4.9.3"
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/addons/toolbars/src/components/ToolbarMenuListItem.tsx b/code/addons/toolbars/src/components/ToolbarMenuListItem.tsx
index 8c0ddea7ede7..29a2bfb236f6 100644
--- a/code/addons/toolbars/src/components/ToolbarMenuListItem.tsx
+++ b/code/addons/toolbars/src/components/ToolbarMenuListItem.tsx
@@ -9,7 +9,6 @@ export type ToolbarMenuListItemProps = {
} & ToolbarItem;
export const ToolbarMenuListItem = ({
- left,
right,
title,
value,
@@ -25,12 +24,12 @@ export const ToolbarMenuListItem = ({
active: currentValue === value,
right,
title,
- left,
+ icon,
onClick,
};
if (icon && !hideIcon) {
- Item.left = Icon;
+ Item.icon = Icon;
}
return Item;
diff --git a/code/addons/viewport/README.md b/code/addons/viewport/README.md
index 196c5e0b0aa5..3766d555f8b3 100644
--- a/code/addons/viewport/README.md
+++ b/code/addons/viewport/README.md
@@ -8,13 +8,13 @@ Storybook Viewport Addon allows your stories to be displayed in different sizes
## Installation
-Viewport is part of [essentials](https://storybook.js.org/docs/react/essentials/introduction) and so is installed in all new Storybooks by default. If you need to add it to your Storybook, you can run:
+Viewport is part of [essentials](https://storybook.js.org/docs/react/essentials) and so is installed in all new Storybooks by default. If you need to add it to your Storybook, you can run:
```sh
npm i -D @storybook/addon-viewport
```
-Then, add following content to [`.storybook/main.js`](https://storybook.js.org/docs/react/configure/overview#configure-your-storybook-project):
+Then, add following content to [`.storybook/main.js`](https://storybook.js.org/docs/react/configure/#configure-your-storybook-project):
```js
export default {
diff --git a/code/addons/viewport/package.json b/code/addons/viewport/package.json
index 7f57d1eba792..b47cf9aa903f 100644
--- a/code/addons/viewport/package.json
+++ b/code/addons/viewport/package.json
@@ -56,12 +56,13 @@
"@storybook/components": "workspace:*",
"@storybook/core-events": "workspace:*",
"@storybook/global": "^5.0.0",
+ "@storybook/icons": "^1.2.1",
"@storybook/manager-api": "workspace:*",
"@storybook/preview-api": "workspace:*",
"@storybook/theming": "workspace:*",
- "react": "^16.8.0",
- "react-dom": "^16.8.0",
- "typescript": "~4.9.3"
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/addons/viewport/src/Tool.tsx b/code/addons/viewport/src/Tool.tsx
index df65988e5097..093d16bb57ba 100644
--- a/code/addons/viewport/src/Tool.tsx
+++ b/code/addons/viewport/src/Tool.tsx
@@ -4,9 +4,10 @@ import memoize from 'memoizerific';
import { styled, Global, type Theme, withTheme } from '@storybook/theming';
-import { Icons, IconButton, WithTooltip, TooltipLinkList } from '@storybook/components';
+import { IconButton, WithTooltip, TooltipLinkList } from '@storybook/components';
import { useStorybookApi, useParameter, useAddonState } from '@storybook/manager-api';
+import { GrowIcon, TransferIcon } from '@storybook/icons';
import { registerShortcuts } from './shortcuts';
import { PARAM_KEY, ADDON_ID } from './constants';
import { MINIMAL_VIEWPORTS } from './defaults';
@@ -48,8 +49,6 @@ const toLinks = memoize(50)((list: ViewportItem[], active: LinkBase, set, state,
});
});
-const wrapperId = 'storybook-preview-wrapper';
-
interface LinkBase {
id: string;
title: string;
@@ -188,7 +187,7 @@ export const ViewportTool: FC = memo(
setState({ ...state, selected: responsiveViewport.id });
}}
>
-
+
{styles ? (
{isRotated ? `${item.title} (L)` : `${item.title} (P)`}
@@ -202,25 +201,10 @@ export const ViewportTool: FC = memo(
@@ -234,7 +218,7 @@ export const ViewportTool: FC = memo(
setState({ ...state, isRotated: !isRotated });
}}
>
-
+
{styles.height.replace('px', '')}
diff --git a/code/addons/viewport/src/index.ts b/code/addons/viewport/src/index.ts
index 341f696ad7b5..832595462640 100644
--- a/code/addons/viewport/src/index.ts
+++ b/code/addons/viewport/src/index.ts
@@ -1,3 +1,4 @@
export * from './constants';
export * from './defaults';
+export * from './models';
export * from './shortcuts';
diff --git a/code/builders/builder-manager/package.json b/code/builders/builder-manager/package.json
index 2fc14cd4251c..db8469fcc11e 100644
--- a/code/builders/builder-manager/package.json
+++ b/code/builders/builder-manager/package.json
@@ -63,7 +63,7 @@
},
"devDependencies": {
"slash": "^5.0.0",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/builders/builder-manager/src/utils/data.ts b/code/builders/builder-manager/src/utils/data.ts
index 5e315c92e9f8..eb6754e7635a 100644
--- a/code/builders/builder-manager/src/utils/data.ts
+++ b/code/builders/builder-manager/src/utils/data.ts
@@ -1,5 +1,5 @@
import { basename } from 'path';
-import type { DocsOptions, Options } from '@storybook/types';
+import type { Options } from '@storybook/types';
import { getRefs } from '@storybook/core-common';
import { readTemplate } from './template';
@@ -13,7 +13,7 @@ export const getData = async (options: Options) => {
const features = options.presets.apply>('features');
const logLevel = options.presets.apply('logLevel');
const title = options.presets.apply('title');
- const docsOptions = options.presets.apply('docs', {});
+ const docsOptions = options.presets.apply('docs', {});
const template = readTemplate('template.ejs');
const customHead = options.presets.apply('managerHead');
diff --git a/code/builders/builder-manager/templates/template.ejs b/code/builders/builder-manager/templates/template.ejs
index 462a83649e9c..7961f4ae4f7c 100644
--- a/code/builders/builder-manager/templates/template.ejs
+++ b/code/builders/builder-manager/templates/template.ejs
@@ -4,7 +4,7 @@
<%= typeof title !== 'undefined'? title : 'Storybook'%>
-
+
<% if (favicon.endsWith('.svg')) {%>
@@ -57,11 +57,13 @@
<% } %>
diff --git a/code/builders/builder-vite/package.json b/code/builders/builder-vite/package.json
index 9efe43c618b6..261857257f6b 100644
--- a/code/builders/builder-vite/package.json
+++ b/code/builders/builder-vite/package.json
@@ -66,7 +66,7 @@
"glob": "^10.0.0",
"rollup": "^3.20.1",
"slash": "^5.0.0",
- "typescript": "~4.9.3",
+ "typescript": "^5.3.2",
"vite": "^4.0.4"
},
"peerDependencies": {
diff --git a/code/builders/builder-vite/src/plugins/csf-plugin.ts b/code/builders/builder-vite/src/plugins/csf-plugin.ts
index 9f472f6552f8..94cea3344c1c 100644
--- a/code/builders/builder-vite/src/plugins/csf-plugin.ts
+++ b/code/builders/builder-vite/src/plugins/csf-plugin.ts
@@ -1,11 +1,11 @@
import type { Plugin } from 'vite';
import { vite } from '@storybook/csf-plugin';
-import type { StorybookConfig, Options } from '@storybook/types';
+import type { Options } from '@storybook/types';
export async function csfPlugin(config: Options): Promise {
const { presets } = config;
- const addons = await presets.apply('addons', []);
+ const addons = await presets.apply('addons', []);
const docsOptions =
// @ts-expect-error - not sure what type to use here
addons.find((a) => [a, a.name].includes('@storybook/addon-docs'))?.options ?? {};
diff --git a/code/builders/builder-vite/src/transform-iframe-html.ts b/code/builders/builder-vite/src/transform-iframe-html.ts
index 620cbed3da0a..8c0546125162 100644
--- a/code/builders/builder-vite/src/transform-iframe-html.ts
+++ b/code/builders/builder-vite/src/transform-iframe-html.ts
@@ -1,5 +1,5 @@
import { normalizeStories } from '@storybook/core-common';
-import type { CoreConfig, DocsOptions, Options } from '@storybook/types';
+import type { DocsOptions, Options } from '@storybook/types';
export type PreviewHtml = string | undefined;
@@ -12,7 +12,7 @@ export async function transformIframeHtml(html: string, options: Options) {
const logLevel = await presets.apply('logLevel', undefined);
const docsOptions = await presets.apply('docs');
- const coreOptions = await presets.apply('core');
+ const coreOptions = await presets.apply('core');
const stories = normalizeStories(await options.presets.apply('stories', [], options), {
configDir: options.configDir,
workingDir: process.cwd(),
diff --git a/code/builders/builder-vite/src/vite-config.ts b/code/builders/builder-vite/src/vite-config.ts
index def3e631cb65..b4d1744d3833 100644
--- a/code/builders/builder-vite/src/vite-config.ts
+++ b/code/builders/builder-vite/src/vite-config.ts
@@ -68,6 +68,10 @@ export async function commonConfig(
// If an envPrefix is specified in the vite config, add STORYBOOK_ to it,
// otherwise, add VITE_ and STORYBOOK_ so that vite doesn't lose its default.
envPrefix: userConfig.envPrefix ? ['STORYBOOK_'] : ['VITE_', 'STORYBOOK_'],
+ // Pass build.target option from user's vite config
+ build: {
+ target: buildProperty?.target,
+ },
};
const config: ViteConfig = mergeConfig(userConfig, sbConfig);
diff --git a/code/builders/builder-webpack5/package.json b/code/builders/builder-webpack5/package.json
index f99ef3bc3253..3c9f218fdd85 100644
--- a/code/builders/builder-webpack5/package.json
+++ b/code/builders/builder-webpack5/package.json
@@ -108,7 +108,7 @@
"@types/webpack-virtual-modules": "^0.1.1",
"pretty-hrtime": "^1.0.3",
"slash": "^5.0.0",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"peerDependenciesMeta": {
"typescript": {
diff --git a/code/builders/builder-webpack5/src/index.ts b/code/builders/builder-webpack5/src/index.ts
index 53c4fba32df5..b4725b4a1f4c 100644
--- a/code/builders/builder-webpack5/src/index.ts
+++ b/code/builders/builder-webpack5/src/index.ts
@@ -61,7 +61,6 @@ export const executor = {
export const getConfig: WebpackBuilder['getConfig'] = async (options) => {
const { presets } = options;
const typescriptOptions = await presets.apply('typescript', {}, options);
- const babelOptions = await presets.apply('babel', {}, { ...options, typescriptOptions });
const frameworkOptions = await presets.apply('frameworkOptions');
return presets.apply(
@@ -69,7 +68,6 @@ export const getConfig: WebpackBuilder['getConfig'] = async (options) => {
{},
{
...options,
- babelOptions,
typescriptOptions,
frameworkOptions,
}
diff --git a/code/builders/builder-webpack5/src/presets/custom-webpack-preset.ts b/code/builders/builder-webpack5/src/presets/custom-webpack-preset.ts
index d71a67322d3e..5d921943012c 100644
--- a/code/builders/builder-webpack5/src/presets/custom-webpack-preset.ts
+++ b/code/builders/builder-webpack5/src/presets/custom-webpack-preset.ts
@@ -1,6 +1,6 @@
import * as webpackReal from 'webpack';
import { logger } from '@storybook/node-logger';
-import type { Options, CoreConfig } from '@storybook/types';
+import type { Options } from '@storybook/types';
import type { Configuration } from 'webpack';
import deprecate from 'util-deprecate';
import { dedent } from 'ts-dedent';
@@ -11,7 +11,7 @@ export async function webpack(config: Configuration, options: Options) {
// @ts-expect-error (Converted from ts-ignore)
const { configDir, configType, presets, webpackConfig } = options;
- const coreOptions = await presets.apply('core');
+ const coreOptions = await presets.apply('core');
let defaultConfig = config;
if (!coreOptions?.disableWebpackDefaults) {
diff --git a/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts b/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts
index f1598a66e5da..ac573827715a 100644
--- a/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts
+++ b/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts
@@ -9,7 +9,7 @@ import VirtualModulePlugin from 'webpack-virtual-modules';
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
import type { TransformOptions as EsbuildOptions } from 'esbuild';
import type { JsMinifyOptions as SwcOptions } from '@swc/core';
-import type { Options, CoreConfig, DocsOptions } from '@storybook/types';
+import type { Options } from '@storybook/types';
import { globalsNameReferenceMap } from '@storybook/preview/globals';
import {
getBuilderOptions,
@@ -45,8 +45,6 @@ const themingPath = maybeGetAbsolutePath(`@storybook/theming`);
const storybookPaths: Record = {
...(managerAPIPath
? {
- // deprecated, remove in 8.0
- [`@storybook/api`]: managerAPIPath,
[`@storybook/manager-api`]: managerAPIPath,
}
: {}),
@@ -57,7 +55,7 @@ const storybookPaths: Record = {
};
export default async (
- options: Options & Record & { typescriptOptions: TypescriptOptions }
+ options: Options & { typescriptOptions: TypescriptOptions }
): Promise => {
const {
outputDir = join('.', 'public'),
@@ -66,7 +64,6 @@ export default async (
configType,
presets,
previewUrl,
- babelOptions,
typescriptOptions,
features,
} = options;
@@ -88,14 +85,14 @@ export default async (
modulesCount = 1000,
build,
] = await Promise.all([
- presets.apply('core'),
+ presets.apply('core'),
presets.apply('frameworkOptions'),
presets.apply>('env'),
presets.apply('logLevel', undefined),
presets.apply('previewHead'),
presets.apply('previewBody'),
presets.apply('previewMainTemplate'),
- presets.apply('docs'),
+ presets.apply('docs'),
presets.apply('entries', []),
presets.apply('stories', []),
options.cache?.get('modulesCount').catch(() => {}),
@@ -240,7 +237,7 @@ export default async (
},
builderOptions.useSWC
? await createSWCLoader(Object.keys(virtualModuleMapping), options)
- : createBabelLoader(babelOptions, typescriptOptions, Object.keys(virtualModuleMapping)),
+ : await createBabelLoader(options, typescriptOptions, Object.keys(virtualModuleMapping)),
{
test: /\.md$/,
type: 'asset/source',
diff --git a/code/builders/builder-webpack5/src/preview/loaders.ts b/code/builders/builder-webpack5/src/preview/loaders.ts
index f10bd93a5ebc..868d35ba394c 100644
--- a/code/builders/builder-webpack5/src/preview/loaders.ts
+++ b/code/builders/builder-webpack5/src/preview/loaders.ts
@@ -5,18 +5,19 @@ import { logger } from '@storybook/node-logger';
import type { Options } from '@storybook/types';
import type { TypescriptOptions } from '../types';
-export const createBabelLoader = (
- options: any,
+export const createBabelLoader = async (
+ options: Options & { typescriptOptions: TypescriptOptions },
typescriptOptions: TypescriptOptions,
excludes: string[] = []
) => {
logger.info(dedent`Using Babel compiler`);
+ const babelOptions = await options.presets.apply('babel', {}, options);
return {
test: typescriptOptions.skipBabel ? /\.(mjs|jsx?)$/ : /\.(mjs|tsx?|jsx?)$/,
use: [
{
loader: require.resolve('babel-loader'),
- options,
+ options: babelOptions,
},
],
include: [getProjectRoot()],
diff --git a/code/deprecated/addons/README.md b/code/deprecated/addons/README.md
deleted file mode 100644
index 41f81df8a95d..000000000000
--- a/code/deprecated/addons/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-The contents of this package have moved to `@storybook/preview-api` and `@storybook/manager-api`. Please update your import depending on where are using this API.
-
-This package will no longer be released as part of the 8.0 release of storybook.
diff --git a/code/deprecated/addons/package.json b/code/deprecated/addons/package.json
deleted file mode 100644
index eee2a170485b..000000000000
--- a/code/deprecated/addons/package.json
+++ /dev/null
@@ -1,60 +0,0 @@
-{
- "name": "@storybook/addons",
- "version": "7.6.0-beta.2",
- "description": "Storybook addons store",
- "keywords": [
- "storybook"
- ],
- "homepage": "https://github.com/storybookjs/storybook/tree/next/code/deprecated/addons",
- "bugs": {
- "url": "https://github.com/storybookjs/storybook/issues"
- },
- "repository": {
- "type": "git",
- "url": "https://github.com/storybookjs/storybook.git",
- "directory": "code/deprecated/addons"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/storybook"
- },
- "license": "MIT",
- "sideEffects": false,
- "exports": {
- ".": {
- "types": "./dist/index.d.ts",
- "node": "./dist/index.js",
- "require": "./dist/index.js",
- "import": "./dist/index.mjs"
- },
- "./package.json": "./package.json"
- },
- "main": "./dist/index.js",
- "module": "./dist/index.mjs",
- "types": "./dist/index.d.ts",
- "files": [
- "dist/**/*",
- "README.md",
- "*.js",
- "*.d.ts",
- "!src/**/*"
- ],
- "scripts": {
- "check": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/check.ts",
- "prep": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/bundle.ts"
- },
- "dependencies": {
- "@storybook/manager-api": "workspace:*",
- "@storybook/preview-api": "workspace:*",
- "@storybook/types": "workspace:*"
- },
- "publishConfig": {
- "access": "public"
- },
- "bundler": {
- "entries": [
- "./src/index.ts"
- ]
- },
- "gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae17"
-}
diff --git a/code/deprecated/addons/project.json b/code/deprecated/addons/project.json
deleted file mode 100644
index db49d29418b1..000000000000
--- a/code/deprecated/addons/project.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "@storybook/addons",
- "$schema": "../../node_modules/nx/schemas/project-schema.json",
- "implicitDependencies": [],
- "type": "library"
-}
diff --git a/code/deprecated/addons/src/index.ts b/code/deprecated/addons/src/index.ts
deleted file mode 100644
index 2dee3d2d2ea4..000000000000
--- a/code/deprecated/addons/src/index.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { type Addon_Type, Addon_TypesEnum } from '@storybook/types';
-
-export { type Addon_Type as Addon, Addon_TypesEnum as types };
-
-export { addons, type AddonStore, mockChannel } from '@storybook/manager-api';
-
-export {
- type EventMap,
- HooksContext,
- type Listener,
- type MakeDecoratorOptions,
- type MakeDecoratorResult,
- applyHooks,
- makeDecorator,
- useArgs,
- useCallback,
- useChannel,
- useEffect,
- useGlobals,
- useMemo,
- useParameter,
- useReducer,
- useRef,
- useState,
- useStoryContext,
-} from '@storybook/preview-api/dist/addons';
diff --git a/code/deprecated/addons/tsconfig.json b/code/deprecated/addons/tsconfig.json
deleted file mode 100644
index 4c6f20a1be4d..000000000000
--- a/code/deprecated/addons/tsconfig.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "extends": "../../tsconfig.json",
- "include": ["src/**/*"],
- "compilerOptions": {
- "strict": false
- }
-}
diff --git a/code/deprecated/channel-postmessage/README.md b/code/deprecated/channel-postmessage/README.md
deleted file mode 100644
index 8edc7163f9e2..000000000000
--- a/code/deprecated/channel-postmessage/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# Storybook PostMessage Channel
-
-Storybook PostMessage Channel is a channel for Storybook that can be used when the Storybook Renderer runs inside an iframe or a child window.
-A channel can be created using the `createChannel` function.
-
-```js
-import { createChannel } from '@storybook/channel-postmessage';
-
-const channel = createChannel({ key: 'postmsg-key' });
-```
-
----
-
-For more information visit: [storybook.js.org](https://storybook.js.org)
diff --git a/code/deprecated/channel-postmessage/jest.config.js b/code/deprecated/channel-postmessage/jest.config.js
deleted file mode 100644
index 4396fbc7010d..000000000000
--- a/code/deprecated/channel-postmessage/jest.config.js
+++ /dev/null
@@ -1,7 +0,0 @@
-const path = require('path');
-const baseConfig = require('../../jest.config.browser');
-
-module.exports = {
- ...baseConfig,
- displayName: __dirname.split(path.sep).slice(-2).join(path.posix.sep),
-};
diff --git a/code/deprecated/channel-postmessage/package.json b/code/deprecated/channel-postmessage/package.json
deleted file mode 100644
index 3e9669447029..000000000000
--- a/code/deprecated/channel-postmessage/package.json
+++ /dev/null
@@ -1,63 +0,0 @@
-{
- "name": "@storybook/channel-postmessage",
- "version": "7.6.0-beta.2",
- "description": "",
- "keywords": [
- "storybook"
- ],
- "homepage": "https://github.com/storybookjs/storybook/tree/next/code/lib/channel-postmessage",
- "bugs": {
- "url": "https://github.com/storybookjs/storybook/issues"
- },
- "repository": {
- "type": "git",
- "url": "https://github.com/storybookjs/storybook.git",
- "directory": "code/lib/channel-postmessage"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/storybook"
- },
- "license": "MIT",
- "sideEffects": false,
- "exports": {
- ".": {
- "types": "./dist/entry.d.ts",
- "node": "./dist/entry.js",
- "require": "./dist/entry.js",
- "import": "./dist/entry.mjs"
- },
- "./package.json": "./package.json"
- },
- "main": "dist/entry.js",
- "module": "dist/entry.mjs",
- "types": "dist/entry.d.ts",
- "files": [
- "dist/**/*",
- "README.md",
- "*.js",
- "*.d.ts",
- "!src/**/*"
- ],
- "scripts": {
- "check": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/check.ts",
- "prep": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/bundle.ts"
- },
- "dependencies": {
- "@storybook/channels": "workspace:*",
- "@storybook/client-logger": "workspace:*"
- },
- "devDependencies": {
- "typescript": "~4.9.3"
- },
- "publishConfig": {
- "access": "public"
- },
- "bundler": {
- "entries": [
- "./src/entry.ts"
- ],
- "shim": "@storybook/channels/dist/postmessage/index"
- },
- "gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae17"
-}
diff --git a/code/deprecated/channel-postmessage/project.json b/code/deprecated/channel-postmessage/project.json
deleted file mode 100644
index 8a56b8804d7f..000000000000
--- a/code/deprecated/channel-postmessage/project.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "@storybook/channel-postmessage",
- "$schema": "../../node_modules/nx/schemas/project-schema.json",
- "implicitDependencies": [],
- "type": "library"
-}
diff --git a/code/deprecated/channel-postmessage/src/entry.ts b/code/deprecated/channel-postmessage/src/entry.ts
deleted file mode 100644
index 2190b9f5382e..000000000000
--- a/code/deprecated/channel-postmessage/src/entry.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { deprecate } from '@storybook/client-logger';
-
-deprecate(
- 'importing from @storybook/channel-postmessage is deprecated and will be removed in 8.0, please import createPostmessageChannel from @storybook/channels'
-);
-
-export * from '@storybook/channels/dist/postmessage/index';
diff --git a/code/deprecated/channel-postmessage/tsconfig.json b/code/deprecated/channel-postmessage/tsconfig.json
deleted file mode 100644
index b5a2f9a70918..000000000000
--- a/code/deprecated/channel-postmessage/tsconfig.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "extends": "../../tsconfig.json",
- "include": ["src/**/*"],
- "compilerOptions": {
- "strict": true
- }
-}
diff --git a/code/deprecated/channel-websocket/README.md b/code/deprecated/channel-websocket/README.md
deleted file mode 100644
index 8f131ab21ae3..000000000000
--- a/code/deprecated/channel-websocket/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# Storybook Websocket Channel
-
-Storybook Websocket Channel is a channel for Storybook that can be used when the Storybook Renderer should communicate with the Storybook Manager over the network.
-A channel can be created using the `createChannel` function.
-
-```js
-import createChannel from '@storybook/channel-websocket';
-
-const channel = createChannel({ url: 'ws://localhost:9001' });
-```
-
----
-
-For more information visit: [storybook.js.org](https://storybook.js.org)
diff --git a/code/deprecated/channel-websocket/jest.config.js b/code/deprecated/channel-websocket/jest.config.js
deleted file mode 100644
index 4396fbc7010d..000000000000
--- a/code/deprecated/channel-websocket/jest.config.js
+++ /dev/null
@@ -1,7 +0,0 @@
-const path = require('path');
-const baseConfig = require('../../jest.config.browser');
-
-module.exports = {
- ...baseConfig,
- displayName: __dirname.split(path.sep).slice(-2).join(path.posix.sep),
-};
diff --git a/code/deprecated/channel-websocket/package.json b/code/deprecated/channel-websocket/package.json
deleted file mode 100644
index 812efc5fb460..000000000000
--- a/code/deprecated/channel-websocket/package.json
+++ /dev/null
@@ -1,63 +0,0 @@
-{
- "name": "@storybook/channel-websocket",
- "version": "7.6.0-beta.2",
- "description": "",
- "keywords": [
- "storybook"
- ],
- "homepage": "https://github.com/storybookjs/storybook/tree/next/code/lib/channel-websocket",
- "bugs": {
- "url": "https://github.com/storybookjs/storybook/issues"
- },
- "repository": {
- "type": "git",
- "url": "https://github.com/storybookjs/storybook.git",
- "directory": "code/lib/channel-websocket"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/storybook"
- },
- "license": "MIT",
- "sideEffects": false,
- "exports": {
- ".": {
- "types": "./dist/entry.d.ts",
- "node": "./dist/entry.js",
- "require": "./dist/entry.js",
- "import": "./dist/entry.mjs"
- },
- "./package.json": "./package.json"
- },
- "main": "dist/entry.js",
- "module": "dist/entry.mjs",
- "types": "dist/entry.d.ts",
- "files": [
- "dist/**/*",
- "README.md",
- "*.js",
- "*.d.ts",
- "!src/**/*"
- ],
- "scripts": {
- "check": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/check.ts",
- "prep": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/facade.ts"
- },
- "dependencies": {
- "@storybook/channels": "workspace:*",
- "@storybook/client-logger": "workspace:*"
- },
- "devDependencies": {
- "typescript": "~4.9.3"
- },
- "publishConfig": {
- "access": "public"
- },
- "bundler": {
- "entries": [
- "./src/entry.ts"
- ],
- "shim": "@storybook/channels/dist/websocket/index"
- },
- "gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae17"
-}
diff --git a/code/deprecated/channel-websocket/project.json b/code/deprecated/channel-websocket/project.json
deleted file mode 100644
index f778bc09228d..000000000000
--- a/code/deprecated/channel-websocket/project.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "@storybook/channel-websocket",
- "$schema": "../../node_modules/nx/schemas/project-schema.json",
- "implicitDependencies": [],
- "type": "library"
-}
diff --git a/code/deprecated/channel-websocket/src/entry.ts b/code/deprecated/channel-websocket/src/entry.ts
deleted file mode 100644
index e5b6602e6120..000000000000
--- a/code/deprecated/channel-websocket/src/entry.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { deprecate } from '@storybook/client-logger';
-
-deprecate(
- 'importing from @storybook/channel-websocket is deprecated and will be removed in 8.0, please import createWebsocketChannel from @storybook/channels'
-);
-
-export * from '@storybook/channels/dist/websocket/index';
diff --git a/code/deprecated/channel-websocket/tsconfig.json b/code/deprecated/channel-websocket/tsconfig.json
deleted file mode 100644
index b5a2f9a70918..000000000000
--- a/code/deprecated/channel-websocket/tsconfig.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "extends": "../../tsconfig.json",
- "include": ["src/**/*"],
- "compilerOptions": {
- "strict": true
- }
-}
diff --git a/code/deprecated/client-api/README.md b/code/deprecated/client-api/README.md
deleted file mode 100644
index 2220a03cb98b..000000000000
--- a/code/deprecated/client-api/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-The contents of this package have moved to `@storybook/preview-api`. Please update your import.
-
-This package will no longer be released as part of the 8.0 release of storybook.
diff --git a/code/deprecated/client-api/package.json b/code/deprecated/client-api/package.json
deleted file mode 100644
index ca91a85f270e..000000000000
--- a/code/deprecated/client-api/package.json
+++ /dev/null
@@ -1,59 +0,0 @@
-{
- "name": "@storybook/client-api",
- "version": "7.6.0-beta.2",
- "description": "Storybook Client API",
- "keywords": [
- "storybook"
- ],
- "homepage": "https://github.com/storybookjs/storybook/tree/next/code/deprecated/client-api",
- "bugs": {
- "url": "https://github.com/storybookjs/storybook/issues"
- },
- "repository": {
- "type": "git",
- "url": "https://github.com/storybookjs/storybook.git",
- "directory": "code/deprecated/client-api"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/storybook"
- },
- "license": "MIT",
- "sideEffects": false,
- "exports": {
- ".": {
- "types": "./dist/entry.d.ts",
- "require": "./dist/entry.js",
- "import": "./dist/entry.mjs"
- },
- "./package.json": "./package.json"
- },
- "main": "dist/entry.js",
- "module": "dist/entry.mjs",
- "types": "dist/entry.d.ts",
- "files": [
- "dist/**/*",
- "README.md",
- "*.js",
- "*.d.ts",
- "!src/**/*"
- ],
- "scripts": {
- "check": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/check.ts",
- "prep": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/facade.ts"
- },
- "dependencies": {
- "@storybook/client-logger": "workspace:*",
- "@storybook/preview-api": "workspace:*"
- },
- "publishConfig": {
- "access": "public"
- },
- "bundler": {
- "entries": [
- "./src/entry.ts"
- ],
- "shim": "@storybook/preview-api/dist/client-api"
- },
- "gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae17"
-}
diff --git a/code/deprecated/client-api/project.json b/code/deprecated/client-api/project.json
deleted file mode 100644
index 6ad043cf9a61..000000000000
--- a/code/deprecated/client-api/project.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "@storybook/client-api",
- "$schema": "../../node_modules/nx/schemas/project-schema.json",
- "implicitDependencies": [],
- "type": "library"
-}
diff --git a/code/deprecated/client-api/src/entry.ts b/code/deprecated/client-api/src/entry.ts
deleted file mode 100644
index c5528bee29db..000000000000
--- a/code/deprecated/client-api/src/entry.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { deprecate } from '@storybook/client-logger';
-
-deprecate(
- 'importing from @storybook/client-api is deprecated and will be removed in 8.0, please import canvas related modules from @storybook/preview-api'
-);
-
-export * from '@storybook/preview-api/dist/client-api';
diff --git a/code/deprecated/client-api/src/typings.d.ts b/code/deprecated/client-api/src/typings.d.ts
deleted file mode 100644
index bfd9e55123ff..000000000000
--- a/code/deprecated/client-api/src/typings.d.ts
+++ /dev/null
@@ -1 +0,0 @@
-declare var LOGLEVEL: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent' | undefined;
diff --git a/code/deprecated/client-api/tsconfig.json b/code/deprecated/client-api/tsconfig.json
deleted file mode 100644
index b5a2f9a70918..000000000000
--- a/code/deprecated/client-api/tsconfig.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "extends": "../../tsconfig.json",
- "include": ["src/**/*"],
- "compilerOptions": {
- "strict": true
- }
-}
diff --git a/code/deprecated/core-client/README.md b/code/deprecated/core-client/README.md
deleted file mode 100644
index 2220a03cb98b..000000000000
--- a/code/deprecated/core-client/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-The contents of this package have moved to `@storybook/preview-api`. Please update your import.
-
-This package will no longer be released as part of the 8.0 release of storybook.
diff --git a/code/deprecated/core-client/package.json b/code/deprecated/core-client/package.json
deleted file mode 100644
index 1894929ef3e8..000000000000
--- a/code/deprecated/core-client/package.json
+++ /dev/null
@@ -1,51 +0,0 @@
-{
- "name": "@storybook/core-client",
- "version": "7.6.0-beta.2",
- "description": "Storybook framework-agnostic API",
- "keywords": [
- "storybook"
- ],
- "homepage": "https://github.com/storybookjs/storybook/tree/next/code/deprecated/core-client",
- "bugs": {
- "url": "https://github.com/storybookjs/storybook/issues"
- },
- "repository": {
- "type": "git",
- "url": "https://github.com/storybookjs/storybook.git",
- "directory": "code/deprecated/core-client"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/storybook"
- },
- "license": "MIT",
- "exports": {
- ".": {
- "types": "./dist/entry.d.ts",
- "require": "./dist/entry.js",
- "import": "./dist/entry.mjs"
- },
- "./package.json": "./package.json"
- },
- "main": "dist/entry.js",
- "module": "dist/entry.mjs",
- "types": "dist/entry.d.ts",
- "scripts": {
- "check": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/check.ts",
- "prep": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/facade.ts"
- },
- "dependencies": {
- "@storybook/client-logger": "workspace:*",
- "@storybook/preview-api": "workspace:*"
- },
- "publishConfig": {
- "access": "public"
- },
- "bundler": {
- "entries": [
- "./src/entry.ts"
- ],
- "shim": "@storybook/preview-api/dist/core-client"
- },
- "gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae17"
-}
diff --git a/code/deprecated/core-client/project.json b/code/deprecated/core-client/project.json
deleted file mode 100644
index 9ae6f7635e71..000000000000
--- a/code/deprecated/core-client/project.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "@storybook/core-client",
- "$schema": "../../node_modules/nx/schemas/project-schema.json",
- "implicitDependencies": [],
- "type": "library"
-}
diff --git a/code/deprecated/core-client/src/entry.ts b/code/deprecated/core-client/src/entry.ts
deleted file mode 100644
index e838a6bd7930..000000000000
--- a/code/deprecated/core-client/src/entry.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { deprecate } from '@storybook/client-logger';
-
-deprecate(
- 'importing from @storybook/core-client is deprecated and will be removed in 8.0, please import canvas related modules from @storybook/preview-api'
-);
-
-export * from '@storybook/preview-api/dist/core-client';
diff --git a/code/deprecated/core-client/src/typings.d.ts b/code/deprecated/core-client/src/typings.d.ts
deleted file mode 100644
index bfd9e55123ff..000000000000
--- a/code/deprecated/core-client/src/typings.d.ts
+++ /dev/null
@@ -1 +0,0 @@
-declare var LOGLEVEL: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent' | undefined;
diff --git a/code/deprecated/core-client/tsconfig.json b/code/deprecated/core-client/tsconfig.json
deleted file mode 100644
index cb1c83813c18..000000000000
--- a/code/deprecated/core-client/tsconfig.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "extends": "../../tsconfig.json",
- "include": ["src/**/*", "typings.d.ts"],
- "compilerOptions": {
- "strict": true
- }
-}
diff --git a/code/deprecated/core-client/typings.d.ts b/code/deprecated/core-client/typings.d.ts
deleted file mode 100644
index 2a4bb7deb464..000000000000
--- a/code/deprecated/core-client/typings.d.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-declare class AnsiToHtml {
- constructor(options: { escapeHtml: boolean });
-
- toHtml: (ansi: string) => string;
-}
diff --git a/code/deprecated/manager-api-shim/README.md b/code/deprecated/manager-api-shim/README.md
deleted file mode 100644
index 21130d9a30f1..000000000000
--- a/code/deprecated/manager-api-shim/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-The contents of this package have moved to `@storybook/manager-api`. Please update your import.
-
-This package will no longer be released as part of the 8.0 release of storybook.
diff --git a/code/deprecated/manager-api-shim/package.json b/code/deprecated/manager-api-shim/package.json
deleted file mode 100644
index 32893c3fc69e..000000000000
--- a/code/deprecated/manager-api-shim/package.json
+++ /dev/null
@@ -1,59 +0,0 @@
-{
- "name": "@storybook/api",
- "version": "7.6.0-beta.2",
- "description": "Storybook Manager API (facade)",
- "keywords": [
- "storybook"
- ],
- "homepage": "https://github.com/storybookjs/storybook/tree/next/code/lib/api",
- "bugs": {
- "url": "https://github.com/storybookjs/storybook/issues"
- },
- "repository": {
- "type": "git",
- "url": "https://github.com/storybookjs/storybook.git",
- "directory": "code/deprecated/manager-api-shim"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/storybook"
- },
- "license": "MIT",
- "sideEffects": false,
- "exports": {
- ".": {
- "types": "./dist/entry.d.ts",
- "require": "./dist/entry.js",
- "import": "./dist/entry.mjs"
- },
- "./package.json": "./package.json"
- },
- "main": "dist/entry.js",
- "module": "dist/entry.mjs",
- "types": "dist/entry.d.ts",
- "files": [
- "dist/**/*",
- "README.md",
- "*.js",
- "*.d.ts",
- "!src/**/*"
- ],
- "scripts": {
- "check": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/check.ts",
- "prep": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/facade.ts"
- },
- "dependencies": {
- "@storybook/client-logger": "workspace:*",
- "@storybook/manager-api": "workspace:*"
- },
- "publishConfig": {
- "access": "public"
- },
- "bundler": {
- "entries": [
- "./src/entry.ts"
- ],
- "shim": "@storybook/manager-api"
- },
- "gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae17"
-}
diff --git a/code/deprecated/manager-api-shim/project.json b/code/deprecated/manager-api-shim/project.json
deleted file mode 100644
index fdba5d62b5b2..000000000000
--- a/code/deprecated/manager-api-shim/project.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "@storybook/api",
- "$schema": "../../node_modules/nx/schemas/project-schema.json",
- "implicitDependencies": [],
- "type": "library"
-}
diff --git a/code/deprecated/manager-api-shim/src/entry.ts b/code/deprecated/manager-api-shim/src/entry.ts
deleted file mode 100644
index c0174219dd33..000000000000
--- a/code/deprecated/manager-api-shim/src/entry.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { deprecate } from '@storybook/client-logger';
-
-deprecate(
- 'importing from @storybook/api is deprecated and will be removed in 8.0, please import manager related modules from @storybook/manager-api'
-);
-
-export * from '@storybook/manager-api';
diff --git a/code/deprecated/manager-api-shim/src/typings.d.ts b/code/deprecated/manager-api-shim/src/typings.d.ts
deleted file mode 100644
index bfd9e55123ff..000000000000
--- a/code/deprecated/manager-api-shim/src/typings.d.ts
+++ /dev/null
@@ -1 +0,0 @@
-declare var LOGLEVEL: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent' | undefined;
diff --git a/code/deprecated/manager-api-shim/tsconfig.json b/code/deprecated/manager-api-shim/tsconfig.json
deleted file mode 100644
index 4c6f20a1be4d..000000000000
--- a/code/deprecated/manager-api-shim/tsconfig.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "extends": "../../tsconfig.json",
- "include": ["src/**/*"],
- "compilerOptions": {
- "strict": false
- }
-}
diff --git a/code/deprecated/preview-web/README.md b/code/deprecated/preview-web/README.md
deleted file mode 100644
index 2220a03cb98b..000000000000
--- a/code/deprecated/preview-web/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-The contents of this package have moved to `@storybook/preview-api`. Please update your import.
-
-This package will no longer be released as part of the 8.0 release of storybook.
diff --git a/code/deprecated/preview-web/package.json b/code/deprecated/preview-web/package.json
deleted file mode 100644
index a528dd003460..000000000000
--- a/code/deprecated/preview-web/package.json
+++ /dev/null
@@ -1,59 +0,0 @@
-{
- "name": "@storybook/preview-web",
- "version": "7.6.0-beta.2",
- "description": "",
- "keywords": [
- "storybook"
- ],
- "homepage": "https://github.com/storybookjs/storybook/tree/next/code/deprecated/preview-web",
- "bugs": {
- "url": "https://github.com/storybookjs/storybook/issues"
- },
- "repository": {
- "type": "git",
- "url": "https://github.com/storybookjs/storybook.git",
- "directory": "code/deprecated/preview-web"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/storybook"
- },
- "license": "MIT",
- "sideEffects": false,
- "exports": {
- ".": {
- "types": "./dist/entry.d.ts",
- "require": "./dist/entry.js",
- "import": "./dist/entry.mjs"
- },
- "./package.json": "./package.json"
- },
- "main": "dist/entry.js",
- "module": "dist/entry.mjs",
- "types": "dist/entry.d.ts",
- "files": [
- "dist/**/*",
- "README.md",
- "*.js",
- "*.d.ts",
- "!src/**/*"
- ],
- "scripts": {
- "check": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/check.ts",
- "prep": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/facade.ts"
- },
- "dependencies": {
- "@storybook/client-logger": "workspace:*",
- "@storybook/preview-api": "workspace:*"
- },
- "publishConfig": {
- "access": "public"
- },
- "bundler": {
- "entries": [
- "./src/entry.ts"
- ],
- "shim": "@storybook/preview-api/dist/preview-web"
- },
- "gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae17"
-}
diff --git a/code/deprecated/preview-web/project.json b/code/deprecated/preview-web/project.json
deleted file mode 100644
index 461764d60368..000000000000
--- a/code/deprecated/preview-web/project.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "@storybook/preview-web",
- "$schema": "../../node_modules/nx/schemas/project-schema.json",
- "implicitDependencies": [],
- "type": "library"
-}
diff --git a/code/deprecated/preview-web/src/entry.ts b/code/deprecated/preview-web/src/entry.ts
deleted file mode 100644
index 0e2b07b5379e..000000000000
--- a/code/deprecated/preview-web/src/entry.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { deprecate } from '@storybook/client-logger';
-
-deprecate(
- 'importing from @storybook/preview is deprecated and will be removed in 8.0, please import canvas related modules from @storybook/preview-api'
-);
-
-export * from '@storybook/preview-api/dist/preview-web';
diff --git a/code/deprecated/preview-web/src/typings.d.ts b/code/deprecated/preview-web/src/typings.d.ts
deleted file mode 100644
index bfd9e55123ff..000000000000
--- a/code/deprecated/preview-web/src/typings.d.ts
+++ /dev/null
@@ -1 +0,0 @@
-declare var LOGLEVEL: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent' | undefined;
diff --git a/code/deprecated/preview-web/tsconfig.json b/code/deprecated/preview-web/tsconfig.json
deleted file mode 100644
index 5b3f3a56a68d..000000000000
--- a/code/deprecated/preview-web/tsconfig.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "extends": "../../tsconfig.json",
- "compilerOptions": {
- "strict": true,
- "skipLibCheck": true
- },
- "include": ["src/**/*"]
-}
diff --git a/code/deprecated/store/README.md b/code/deprecated/store/README.md
deleted file mode 100644
index 2220a03cb98b..000000000000
--- a/code/deprecated/store/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-The contents of this package have moved to `@storybook/preview-api`. Please update your import.
-
-This package will no longer be released as part of the 8.0 release of storybook.
diff --git a/code/deprecated/store/package.json b/code/deprecated/store/package.json
deleted file mode 100644
index dd37248555bf..000000000000
--- a/code/deprecated/store/package.json
+++ /dev/null
@@ -1,59 +0,0 @@
-{
- "name": "@storybook/store",
- "version": "7.6.0-beta.2",
- "description": "",
- "keywords": [
- "storybook"
- ],
- "homepage": "https://github.com/storybookjs/storybook/tree/next/code/deprecated/store",
- "bugs": {
- "url": "https://github.com/storybookjs/storybook/issues"
- },
- "repository": {
- "type": "git",
- "url": "https://github.com/storybookjs/storybook.git",
- "directory": "code/deprecated/store"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/storybook"
- },
- "license": "MIT",
- "sideEffects": false,
- "exports": {
- ".": {
- "types": "./dist/entry.d.ts",
- "require": "./dist/entry.js",
- "import": "./dist/entry.mjs"
- },
- "./package.json": "./package.json"
- },
- "main": "dist/entry.js",
- "module": "dist/entry.mjs",
- "types": "dist/entry.d.ts",
- "files": [
- "dist/**/*",
- "README.md",
- "*.js",
- "*.d.ts",
- "!src/**/*"
- ],
- "scripts": {
- "check": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/check.ts",
- "prep": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/facade.ts"
- },
- "dependencies": {
- "@storybook/client-logger": "workspace:*",
- "@storybook/preview-api": "workspace:*"
- },
- "publishConfig": {
- "access": "public"
- },
- "bundler": {
- "entries": [
- "./src/entry.ts"
- ],
- "platform": "node",
- "shim": "@storybook/preview-api/dist/store"
- }
-}
diff --git a/code/deprecated/store/project.json b/code/deprecated/store/project.json
deleted file mode 100644
index 7fc42733239c..000000000000
--- a/code/deprecated/store/project.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "@storybook/store",
- "$schema": "../../node_modules/nx/schemas/project-schema.json",
- "implicitDependencies": [],
- "type": "library"
-}
diff --git a/code/deprecated/store/src/entry.ts b/code/deprecated/store/src/entry.ts
deleted file mode 100644
index 5183f9456376..000000000000
--- a/code/deprecated/store/src/entry.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { deprecate } from '@storybook/client-logger';
-
-deprecate(
- 'importing from @storybook/store is deprecated and will be removed in 8.0, please import canvas related modules from @storybook/preview-api'
-);
-
-export * from '@storybook/preview-api/dist/store';
diff --git a/code/deprecated/store/src/typings.d.ts b/code/deprecated/store/src/typings.d.ts
deleted file mode 100644
index bfd9e55123ff..000000000000
--- a/code/deprecated/store/src/typings.d.ts
+++ /dev/null
@@ -1 +0,0 @@
-declare var LOGLEVEL: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent' | undefined;
diff --git a/code/deprecated/store/tsconfig.json b/code/deprecated/store/tsconfig.json
deleted file mode 100644
index 5b3f3a56a68d..000000000000
--- a/code/deprecated/store/tsconfig.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "extends": "../../tsconfig.json",
- "compilerOptions": {
- "strict": true,
- "skipLibCheck": true
- },
- "include": ["src/**/*"]
-}
diff --git a/code/e2e-tests/addon-actions.spec.ts b/code/e2e-tests/addon-actions.spec.ts
index a38b6b82d118..520c2b5dc41f 100644
--- a/code/e2e-tests/addon-actions.spec.ts
+++ b/code/e2e-tests/addon-actions.spec.ts
@@ -5,13 +5,10 @@ import { SbPage } from './util';
const storybookUrl = process.env.STORYBOOK_URL || 'http://localhost:8001';
test.describe('addon-actions', () => {
- test.beforeEach(async ({ page }) => {
- await page.goto(storybookUrl);
- await new SbPage(page).waitUntilLoaded();
- });
-
test('should trigger an action', async ({ page }) => {
+ await page.goto(storybookUrl);
const sbPage = new SbPage(page);
+ sbPage.waitUntilLoaded();
await sbPage.navigateToStory('example/button', 'primary');
const root = sbPage.previewRoot();
diff --git a/code/e2e-tests/manager.spec.ts b/code/e2e-tests/manager.spec.ts
index bd07a1adc30a..b54c6b0df8a2 100644
--- a/code/e2e-tests/manager.spec.ts
+++ b/code/e2e-tests/manager.spec.ts
@@ -3,92 +3,256 @@ import process from 'process';
import { SbPage } from './util';
const storybookUrl = process.env.STORYBOOK_URL || 'http://localhost:8001';
+const templateName = process.env.STORYBOOK_TEMPLATE_NAME;
-test.describe('manager', () => {
+test.describe('Manager UI', () => {
test.beforeEach(async ({ page }) => {
await page.goto(storybookUrl);
await new SbPage(page).waitUntilLoaded();
});
- test('shortcuts sidebar', async ({ page }) => {
- const sbPage = new SbPage(page);
+ test.describe('Desktop', () => {
+ // TODO: test dragging and resizing
- await expect(sbPage.page.locator('.sidebar-container')).toBeVisible();
+ test('Sidebar toggling', async ({ page }) => {
+ const sbPage = new SbPage(page);
- await sbPage.page.locator('html').press('s');
- await expect(sbPage.page.locator('.sidebar-container')).not.toBeVisible();
+ await expect(sbPage.page.locator('.sidebar-container')).toBeVisible();
- await sbPage.page.locator('[aria-label="Show sidebar"]').click();
- await expect(sbPage.page.locator('.sidebar-container')).toBeVisible();
+ // toggle with keyboard shortcut
+ await sbPage.page.locator('html').press('s');
+ await expect(sbPage.page.locator('.sidebar-container')).not.toBeVisible();
+ await sbPage.page.locator('html').press('s');
+ await expect(sbPage.page.locator('.sidebar-container')).toBeVisible();
- await sbPage.page.locator('[aria-label="Shortcuts"]').click();
- await sbPage.page.locator('#list-item-S').click();
+ // toggle with menu item
+ await sbPage.page.locator('[aria-label="Shortcuts"]').click();
+ await sbPage.page.locator('#list-item-S').click();
+ await expect(sbPage.page.locator('.sidebar-container')).not.toBeVisible();
- await expect(sbPage.page.locator('.sidebar-container')).not.toBeVisible();
+ // toggle with "show sidebar" button
+ await sbPage.page.locator('[aria-label="Show sidebar"]').click();
+ await expect(sbPage.page.locator('.sidebar-container')).toBeVisible();
+ });
- await sbPage.page.locator('html').press('s');
- await expect(sbPage.page.locator('.sidebar-container')).toBeVisible();
- });
+ test('Toolbar toggling', async ({ page }) => {
+ const sbPage = new SbPage(page);
+ const expectToolbarVisibility = async (visible: boolean) => {
+ expect(async () => {
+ const toolbar = await sbPage.page.locator(`[data-test-id="sb-preview-toolbar"]`);
+ const marginTop = await toolbar.evaluate(
+ (element) => window.getComputedStyle(element).marginTop
+ );
+ expect(marginTop).toBe(visible ? '0px' : '-40px');
+ }).toPass({ intervals: [400] });
+ };
+
+ await expectToolbarVisibility(true);
+
+ // toggle with keyboard shortcut
+ await sbPage.page.locator('html').press('t');
+ await expectToolbarVisibility(false);
+ await sbPage.page.locator('html').press('t');
+ await expectToolbarVisibility(true);
+
+ // toggle with menu item
+ await sbPage.page.locator('[aria-label="Shortcuts"]').click();
+ await sbPage.page.locator('#list-item-T').click();
+ await expectToolbarVisibility(false);
+ await sbPage.page.locator('[aria-label="Shortcuts"]').click();
+ await sbPage.page.locator('#list-item-T').click();
+ await expectToolbarVisibility(true);
+ });
+
+ test.describe('Panel', () => {
+ test('Hidden in docs view', async ({ page }) => {
+ const sbPage = new SbPage(page);
- test('shortcuts toolbar', async ({ page }) => {
- const sbPage = new SbPage(page);
- const isToolbarShown = async () => {
- const canvas = await sbPage.page.locator('div', {
- has: sbPage.page.locator('> #storybook-preview-wrapper'),
+ // navigate to docs to hide panel
+ await sbPage.navigateToStory('example/button', 'docs');
+
+ await expect(sbPage.page.locator('#storybook-panel-root')).not.toBeVisible();
+
+ // toggle with keyboard shortcut
+ await sbPage.page.locator('html').press('a');
+ await expect(sbPage.page.locator('#storybook-panel-root')).not.toBeVisible();
+ await sbPage.page.locator('html').press('a');
+ await expect(sbPage.page.locator('#storybook-panel-root')).not.toBeVisible();
});
- return (await canvas.getAttribute('offset')) === '40';
- };
+ test('Toggling', async ({ page }) => {
+ const sbPage = new SbPage(page);
- await expect(await isToolbarShown()).toBeTruthy();
+ // navigate to story to show panel
+ await sbPage.navigateToStory('example/button', 'primary');
- await sbPage.page.locator('html').press('t');
- await expect(await isToolbarShown()).toBeFalsy();
+ await expect(sbPage.page.locator('#storybook-panel-root')).toBeVisible();
- await sbPage.page.locator('[aria-label="Shortcuts"]').click();
- await sbPage.page.locator('#list-item-T').click();
- await expect(await isToolbarShown()).toBeTruthy();
- });
+ // toggle with keyboard shortcut
+ await sbPage.page.locator('html').press('a');
+ await expect(sbPage.page.locator('#storybook-panel-root')).not.toBeVisible();
+ await sbPage.page.locator('html').press('a');
+ await expect(sbPage.page.locator('#storybook-panel-root')).toBeVisible();
- test('shortcuts panel', async ({ page }) => {
- const sbPage = new SbPage(page);
- const isPanelsShown = async () => {
- const main = await sbPage.page.locator('div', {
- has: sbPage.page.locator('> * > #storybook-preview-wrapper'),
+ // toggle with menu item
+ await sbPage.page.locator('[aria-label="Shortcuts"]').click();
+ await sbPage.page.locator('#list-item-A').click();
+ await expect(sbPage.page.locator('#storybook-panel-root')).not.toBeVisible();
+
+ // toggle with "show addons" button
+ await sbPage.page.locator('[aria-label="Show addons"]').click();
+ await expect(sbPage.page.locator('#storybook-panel-root')).toBeVisible();
});
- const style = await main.getAttribute('style');
- return style;
- };
+ test('Positioning', async ({ page }) => {
+ const sbPage = new SbPage(page);
+
+ // navigate to story to show panel
+ await sbPage.navigateToStory('example/button', 'primary');
+
+ await expect(sbPage.page.locator('#storybook-panel-root')).toBeVisible();
+
+ // toggle position with keyboard shortcut
+ await sbPage.page.locator('html').press('d');
+ await expect(sbPage.page.locator('#storybook-panel-root')).toBeVisible();
+ // TODO: how to assert panel position?
+
+ // hide with keyboard shortcut
+ await sbPage.page.locator('html').press('a');
+ await expect(sbPage.page.locator('#storybook-panel-root')).not.toBeVisible();
+
+ // toggling position should also show the panel again
+ await sbPage.page.locator('html').press('d');
+ await expect(sbPage.page.locator('#storybook-panel-root')).toBeVisible();
+ });
+ });
+
+ test('Fullscreen toggling', async ({ page }) => {
+ const sbPage = new SbPage(page);
+
+ // navigate to story to show panel
+ await sbPage.navigateToStory('example/button', 'primary');
+
+ await expect(sbPage.page.locator('#storybook-panel-root')).toBeVisible();
+ await expect(sbPage.page.locator('.sidebar-container')).toBeVisible();
+
+ // toggle with keyboard shortcut
+ await sbPage.page.locator('html').press('f');
+ await expect(sbPage.page.locator('#storybook-panel-root')).not.toBeVisible();
+ await expect(sbPage.page.locator('.sidebar-container')).not.toBeVisible();
- await sbPage.navigateToStory('example/button', 'primary');
- await expect(await isPanelsShown()).toBeTruthy();
+ await sbPage.page.locator('html').press('f');
+ await expect(sbPage.page.locator('#storybook-panel-root')).toBeVisible();
+ await expect(sbPage.page.locator('.sidebar-container')).toBeVisible();
- await sbPage.page.locator('html').press('a');
- await expect(await isPanelsShown()).toBeFalsy();
+ // toggle with menu item
+ await sbPage.page.locator('[aria-label="Shortcuts"]').click();
+ await sbPage.page.locator('#list-item-F').click();
+ await expect(sbPage.page.locator('.sidebar-container')).not.toBeVisible();
+ await expect(sbPage.page.locator('#storybook-panel-root')).not.toBeVisible();
- await sbPage.page.locator('[aria-label="Shortcuts"]').click();
- await sbPage.page.locator('#list-item-A').click();
- await expect(await isPanelsShown()).toBeTruthy();
+ // toggle with "go/exit fullscreen" button
+ await sbPage.page.locator('[aria-label="Exit full screen"]').click();
+ await expect(sbPage.page.locator('#storybook-panel-root')).toBeVisible();
+ await expect(sbPage.page.locator('.sidebar-container')).toBeVisible();
- await sbPage.page.locator('html').press('a');
- await expect(await isPanelsShown()).toBeFalsy();
+ await sbPage.page.locator('[aria-label="Go full screen"]').click();
+ await expect(sbPage.page.locator('#storybook-panel-root')).not.toBeVisible();
+ await expect(sbPage.page.locator('.sidebar-container')).not.toBeVisible();
- await sbPage.page.locator('html').press('a');
- await sbPage.page.locator('[aria-label="Shortcuts"]').click();
- await sbPage.page.locator('#list-item-D').click();
- await expect(await isPanelsShown()).toBeTruthy();
+ // go fullscreen when sidebar is shown but panel is hidden
+ await sbPage.page.locator('[aria-label="Show sidebar"]').click();
+ await sbPage.page.locator('[aria-label="Go full screen"]').click();
+ await expect(sbPage.page.locator('#storybook-panel-root')).not.toBeVisible();
+ await expect(sbPage.page.locator('.sidebar-container')).not.toBeVisible();
+
+ // go fullscreen when panel is shown but sidebar is hidden
+ await sbPage.page.locator('[aria-label="Show addons"]').click();
+ await sbPage.page.locator('[aria-label="Go full screen"]').click();
+ await expect(sbPage.page.locator('#storybook-panel-root')).not.toBeVisible();
+ await expect(sbPage.page.locator('.sidebar-container')).not.toBeVisible();
+ });
+
+ test('Settings page', async ({ page }) => {
+ const sbPage = new SbPage(page);
+ await sbPage.page.locator('[aria-label="Shortcuts"]').click();
+ await sbPage.page.locator('#list-item-about').click();
+
+ await expect(sbPage.page.url()).toContain('/settings/about');
+
+ await expect(sbPage.page.locator('#storybook-panel-root')).not.toBeVisible();
+
+ await sbPage.page.locator('[title="Close settings page"]').click();
+ await expect(sbPage.page.url()).not.toContain('/settings/about');
+ });
});
- test('settings page', async ({ page }) => {
- const sbPage = new SbPage(page);
- await sbPage.page.locator('[aria-label="Shortcuts"]').click();
- await sbPage.page.locator('#list-item-about').click();
+ test.describe('Mobile', () => {
+ // TODO: remove this when SSV6 templates have been removed
+ // Some assertions in these tests are not compatible with SSV6
+ // GIven that SSV6 will be removed before the new mobile UI released, it doesn't make sense to fix them
+ // eslint-disable-next-line jest/no-disabled-tests
+ test.skip(
+ // eslint-disable-next-line jest/valid-title
+ templateName?.includes('ssv6') || false,
+ 'Skip mobile UI tests for SSV6'
+ );
+
+ // standard iPhone viewport size
+ test.use({ viewport: { width: 390, height: 844 } });
+
+ test('Navigate to story', async ({ page }) => {
+ const sbPage = new SbPage(page);
+
+ const mobileNavigationHeading = await sbPage.page.locator('[title="Open navigation menu"]');
+
+ // navigation menu is closed
+ await expect(mobileNavigationHeading).toHaveText('Configure your project/Docs');
+ await expect(sbPage.page.locator('#storybook-explorer-menu')).not.toBeVisible();
+
+ // open navigation menu
+ await mobileNavigationHeading.click();
+
+ await sbPage.openComponent('Example/Button');
+
+ // navigation menu is still open
+ await expect(sbPage.page.locator('#storybook-explorer-menu')).toBeVisible();
+ // story has not changed
+ await expect(sbPage.page.url()).toContain('configure-your-project');
+
+ await sbPage.navigateToStory('Example/Button', 'Secondary');
+
+ // navigation menu is closed
+ await expect(mobileNavigationHeading).toHaveText('Example/Button/Secondary');
+ await expect(sbPage.page.locator('#storybook-explorer-menu')).not.toBeVisible();
+ // story has changed
+ await expect(sbPage.page.url()).toContain('example-button--secondary');
+ });
+
+ test('Open and close addon panel', async ({ page }) => {
+ const sbPage = new SbPage(page);
+
+ const mobileNavigationHeading = await sbPage.page.locator('[title="Open navigation menu"]');
+ await mobileNavigationHeading.click();
+ await sbPage.navigateToStory('Example/Button', 'Secondary');
+
+ // panel is closed
+ await expect(mobileNavigationHeading).toHaveText('Example/Button/Secondary');
+ await expect(sbPage.page.locator('#tabbutton-addon-controls')).not.toBeVisible();
+
+ // open panel
+ await sbPage.page.locator('[title="Open addon panel"]').click();
+
+ // panel is open
+ await expect(sbPage.page.locator('#tabbutton-addon-controls')).toBeVisible();
- await expect(sbPage.page.url()).toContain('/settings/about');
+ // close panel
+ await sbPage.page.locator('[title="Close addon panel"]').click();
- await sbPage.page.locator('[title="Close settings page"]').click();
- await expect(sbPage.page.url()).not.toContain('/settings/about');
+ // panel is closed
+ await expect(mobileNavigationHeading).toHaveText('Example/Button/Secondary');
+ await expect(sbPage.page.locator('#tabbutton-addon-controls')).not.toBeVisible();
+ });
});
});
diff --git a/code/e2e-tests/util.ts b/code/e2e-tests/util.ts
index 5ca303d47ef6..e0c45c1ae336 100644
--- a/code/e2e-tests/util.ts
+++ b/code/e2e-tests/util.ts
@@ -57,6 +57,8 @@ export class SbPage {
const selected = await storyLink.getAttribute('data-selected');
await expect(selected).toBe('true');
+
+ await this.previewRoot();
}
async waitUntilLoaded() {
@@ -65,8 +67,9 @@ export class SbPage {
const storeState = {
layout: {
showToolbar: true,
- showNav: true,
- showPanel: true,
+ navSize: 300,
+ bottomPanelHeight: 300,
+ rightPanelWidth: 300,
},
};
window.sessionStorage.setItem('@storybook/manager/store', JSON.stringify(storeState));
diff --git a/code/frameworks/angular/package.json b/code/frameworks/angular/package.json
index 2498bcb774b1..05e03971ed78 100644
--- a/code/frameworks/angular/package.json
+++ b/code/frameworks/angular/package.json
@@ -51,8 +51,8 @@
"@storybook/telemetry": "workspace:*",
"@storybook/types": "workspace:*",
"@types/node": "^18.0.0",
- "@types/react": "^16.14.34",
- "@types/react-dom": "^16.9.14",
+ "@types/react": "^18.0.37",
+ "@types/react-dom": "^18.0.11",
"@types/semver": "^7.3.4",
"@types/webpack-env": "^1.18.0",
"find-up": "^5.0.0",
@@ -84,7 +84,7 @@
"jest-preset-angular": "^13.0.1",
"jest-specific-snapshot": "^8.0.0",
"tmp": "^0.2.1",
- "typescript": "^5.0.4",
+ "typescript": "^5.3.2",
"webpack": "5",
"zone.js": "^0.13.0"
},
diff --git a/code/frameworks/angular/src/client/public-api.ts b/code/frameworks/angular/src/client/public-api.ts
index 3f91276a044b..553c4c85907e 100644
--- a/code/frameworks/angular/src/client/public-api.ts
+++ b/code/frameworks/angular/src/client/public-api.ts
@@ -1,29 +1 @@
-/* eslint-disable prefer-destructuring */
-import { Addon_ClientStoryApi, Addon_Loadable } from '@storybook/types';
-import { start } from '@storybook/preview-api';
-import { renderToCanvas, render } from './render';
-import decorateStory from './decorateStory';
-import { AngularRenderer } from './types';
-
export * from './public-types';
-
-const RENDERER = 'angular';
-
-interface ClientApi extends Addon_ClientStoryApi {
- configure(loader: Addon_Loadable, module: NodeModule): void;
- forceReRender(): void;
- raw: () => any; // todo add type
- load: (...args: any[]) => void;
-}
-
-const api = start(renderToCanvas, { decorateStory, render });
-
-export const storiesOf: ClientApi['storiesOf'] = (kind, m) => {
- return (api.clientApi.storiesOf(kind, m) as ReturnType).addParameters({
- renderer: RENDERER,
- });
-};
-
-export const configure: ClientApi['configure'] = (...args) => api.configure(RENDERER, ...args);
-export const forceReRender: ClientApi['forceReRender'] = api.forceReRender;
-export const raw: ClientApi['raw'] = api.clientApi.raw;
diff --git a/code/frameworks/angular/src/preset.ts b/code/frameworks/angular/src/preset.ts
index f093cb6cc8b8..3d433ba2b841 100644
--- a/code/frameworks/angular/src/preset.ts
+++ b/code/frameworks/angular/src/preset.ts
@@ -6,16 +6,13 @@ import { StandaloneOptions } from './builders/utils/standalone-options';
const getAbsolutePath = (input: I): I =>
dirname(require.resolve(join(input, 'package.json'))) as any;
-export const addons: PresetProperty<'addons', StorybookConfig> = [
+export const addons: PresetProperty<'addons'> = [
require.resolve('./server/framework-preset-angular-cli'),
require.resolve('./server/framework-preset-angular-ivy'),
require.resolve('./server/framework-preset-angular-docs'),
];
-export const previewAnnotations: StorybookConfig['previewAnnotations'] = (
- entries = [],
- options
-) => {
+export const previewAnnotations: PresetProperty<'previewAnnotations'> = (entries = [], options) => {
const annotations = [...entries, require.resolve('./client/config')];
if ((options as any as StandaloneOptions).enableProdMode) {
@@ -26,7 +23,7 @@ export const previewAnnotations: StorybookConfig['previewAnnotations'] = (
};
export const core: PresetProperty<'core', StorybookConfig> = async (config, options) => {
- const framework = await options.presets.apply('framework');
+ const framework = await options.presets.apply('framework');
return {
...config,
diff --git a/code/frameworks/angular/src/server/framework-preset-angular-docs.ts b/code/frameworks/angular/src/server/framework-preset-angular-docs.ts
index a055b0c430d6..0b31ffe9c12e 100644
--- a/code/frameworks/angular/src/server/framework-preset-angular-docs.ts
+++ b/code/frameworks/angular/src/server/framework-preset-angular-docs.ts
@@ -1,7 +1,7 @@
-import { StorybookConfig } from '@storybook/types';
+import { PresetProperty } from '@storybook/types';
import { hasDocsOrControls } from '@storybook/docs-tools';
-export const previewAnnotations: StorybookConfig['previewAnnotations'] = (entry = [], options) => {
+export const previewAnnotations: PresetProperty<'previewAnnotations'> = (entry = [], options) => {
if (!hasDocsOrControls(options)) return entry;
return [...entry, require.resolve('../client/docs/config')];
};
diff --git a/code/frameworks/angular/src/typings.d.ts b/code/frameworks/angular/src/typings.d.ts
index a1bde958b56d..ca7bae4c5383 100644
--- a/code/frameworks/angular/src/typings.d.ts
+++ b/code/frameworks/angular/src/typings.d.ts
@@ -12,7 +12,7 @@ declare var __STORYBOOK_STORY_STORE__: any;
declare var CHANNEL_OPTIONS: any;
declare var DOCS_OPTIONS: any;
-declare var FEATURES: import('@storybook/types').StorybookConfig['features'];
+declare var FEATURES: import('@storybook/types').StorybookConfigRaw['features'];
declare var IS_STORYBOOK: any;
declare var LOGLEVEL: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent' | undefined;
diff --git a/code/frameworks/angular/template/cli/Button.stories.ts b/code/frameworks/angular/template/cli/Button.stories.ts
index 8f280fb0c763..3809c0e3dd19 100644
--- a/code/frameworks/angular/template/cli/Button.stories.ts
+++ b/code/frameworks/angular/template/cli/Button.stories.ts
@@ -1,7 +1,7 @@
import type { Meta, StoryObj } from '@storybook/angular';
import Button from './button.component';
-// More on how to set up stories at: https://storybook.js.org/docs/angular/writing-stories/introduction
+// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
const meta: Meta = {
title: 'Example/Button',
component: Button,
@@ -22,7 +22,7 @@ const meta: Meta = {
export default meta;
type Story = StoryObj;
-// More on writing stories with args: https://storybook.js.org/docs/angular/writing-stories/args
+// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
export const Primary: Story = {
args: {
primary: true,
diff --git a/code/frameworks/angular/template/cli/Header.stories.ts b/code/frameworks/angular/template/cli/Header.stories.ts
index b7dba18630af..e6b99c02a089 100644
--- a/code/frameworks/angular/template/cli/Header.stories.ts
+++ b/code/frameworks/angular/template/cli/Header.stories.ts
@@ -8,7 +8,7 @@ import Header from './header.component';
const meta: Meta = {
title: 'Example/Header',
component: Header,
- // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/angular/writing-docs/autodocs
+ // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
tags: ['autodocs'],
render: (args) => ({ props: args }),
decorators: [
@@ -18,7 +18,7 @@ const meta: Meta = {
}),
],
parameters: {
- // More on how to position stories at: https://storybook.js.org/docs/angular/configure/story-layout
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
layout: 'fullscreen',
},
};
diff --git a/code/frameworks/angular/template/cli/Page.stories.ts b/code/frameworks/angular/template/cli/Page.stories.ts
index a21cdf7d8304..35e69e7775ba 100644
--- a/code/frameworks/angular/template/cli/Page.stories.ts
+++ b/code/frameworks/angular/template/cli/Page.stories.ts
@@ -11,7 +11,7 @@ const meta: Meta = {
title: 'Example/Page',
component: Page,
parameters: {
- // More on how to position stories at: https://storybook.js.org/docs/angular/configure/story-layout
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
layout: 'fullscreen',
},
decorators: [
@@ -31,7 +31,7 @@ export const LoggedOut: Story = {
}),
};
-// More on interaction testing: https://storybook.js.org/docs/angular/writing-tests/interaction-testing
+// More on interaction testing: https://storybook.js.org/docs/writing-tests/interaction-testing
export const LoggedIn: Story = {
render: (args: Page) => ({
props: args,
diff --git a/code/frameworks/angular/template/stories/basics/component-with-ng-on-destroy/component-with-on-destroy.stories.ts b/code/frameworks/angular/template/stories/basics/component-with-ng-on-destroy/component-with-on-destroy.stories.ts
index 9ac53d2dde03..cc8b2662c1be 100644
--- a/code/frameworks/angular/template/stories/basics/component-with-ng-on-destroy/component-with-on-destroy.stories.ts
+++ b/code/frameworks/angular/template/stories/basics/component-with-ng-on-destroy/component-with-on-destroy.stories.ts
@@ -32,7 +32,6 @@ const meta: Meta = {
component: OnDestroyComponent,
parameters: {
// disabled due to new Date()
- storyshots: { disable: true },
chromatic: { disable: true },
},
} as Meta;
diff --git a/code/frameworks/ember/README.md b/code/frameworks/ember/README.md
index f1ed9be67304..774862f546e4 100644
--- a/code/frameworks/ember/README.md
+++ b/code/frameworks/ember/README.md
@@ -24,8 +24,8 @@ You can also build a [static version](https://storybook.js.org/docs/ember/sharin
## Docs
-- [Basics](https://storybook.js.org/docs/ember/get-started/introduction)
-- [Configurations](https://storybook.js.org/docs/ember/configure/overview)
+- [Basics](https://storybook.js.org/docs/ember/get-started)
+- [Configurations](https://storybook.js.org/docs/ember/configure)
- [Addons](https://storybook.js.org/docs/ember/configure/storybook-addons)
## Working with polyfills
diff --git a/code/frameworks/ember/package.json b/code/frameworks/ember/package.json
index 01998434388d..d7bd61f6d70b 100644
--- a/code/frameworks/ember/package.json
+++ b/code/frameworks/ember/package.json
@@ -42,7 +42,7 @@
},
"devDependencies": {
"ember-source": "~3.28.1",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"peerDependencies": {
"@babel/core": "*",
diff --git a/code/frameworks/ember/src/client/preview/index.ts b/code/frameworks/ember/src/client/preview/index.ts
index 7b77a8755219..53521e8aa728 100644
--- a/code/frameworks/ember/src/client/preview/index.ts
+++ b/code/frameworks/ember/src/client/preview/index.ts
@@ -1,16 +1 @@
-import { start } from '@storybook/preview-api';
-
import './globals';
-import type { EmberRenderer } from './types';
-import { renderToCanvas } from './render';
-
-const { configure: coreConfigure, clientApi, forceReRender } = start(renderToCanvas);
-
-export const { raw } = clientApi;
-
-const RENDERER = 'ember';
-export const storiesOf = (kind: string, m: any) =>
- clientApi.storiesOf(kind, m).addParameters({ renderer: RENDERER });
-export const configure = (...args: any[]) => coreConfigure(RENDERER, ...args);
-
-export { forceReRender };
diff --git a/code/frameworks/ember/src/index.ts b/code/frameworks/ember/src/index.ts
index 3d30d71982e6..fc8faa13668a 100644
--- a/code/frameworks/ember/src/index.ts
+++ b/code/frameworks/ember/src/index.ts
@@ -1,6 +1,6 @@
///
-export { storiesOf, configure, forceReRender, raw } from './client/preview';
+import './client/preview';
// optimization: stop HMR propagation in webpack
if (typeof module !== 'undefined') module?.hot?.decline();
diff --git a/code/frameworks/ember/src/preset.ts b/code/frameworks/ember/src/preset.ts
index 6524132780e5..998edbfa7405 100644
--- a/code/frameworks/ember/src/preset.ts
+++ b/code/frameworks/ember/src/preset.ts
@@ -5,13 +5,13 @@ import type { StorybookConfig } from './types';
const getAbsolutePath = (input: I): I =>
dirname(require.resolve(join(input, 'package.json'))) as any;
-export const addons: PresetProperty<'addons', StorybookConfig> = [
+export const addons: PresetProperty<'addons'> = [
require.resolve('./server/framework-preset-babel-ember'),
require.resolve('./server/framework-preset-ember-docs'),
];
export const core: PresetProperty<'core', StorybookConfig> = async (config, options) => {
- const framework = await options.presets.apply('framework');
+ const framework = await options.presets.apply('framework');
return {
...config,
diff --git a/code/frameworks/ember/src/server/framework-preset-babel-ember.ts b/code/frameworks/ember/src/server/framework-preset-babel-ember.ts
index f85328fb84ee..54f31c0fd739 100644
--- a/code/frameworks/ember/src/server/framework-preset-babel-ember.ts
+++ b/code/frameworks/ember/src/server/framework-preset-babel-ember.ts
@@ -1,7 +1,6 @@
-import type { TransformOptions } from '@babel/core';
import { precompile } from 'ember-source/dist/ember-template-compiler';
import { findDistEsm } from '@storybook/core-common';
-import type { StorybookConfig, Options } from '@storybook/types';
+import type { PresetProperty } from '@storybook/types';
let emberOptions: any;
@@ -14,7 +13,7 @@ function precompileWithPlugins(string: string, options: any) {
return precompile(string, precompileOptions);
}
-export function babel(config: TransformOptions, options: Options): TransformOptions {
+export const babel: PresetProperty<'babel'> = (config, options) => {
if (options && options.presetsList) {
options.presetsList.forEach((e: any, index: number) => {
if (e.preset && e.preset.emberOptions) {
@@ -27,7 +26,7 @@ export function babel(config: TransformOptions, options: Options): TransformOpti
});
}
- const babelConfigPlugins = config.plugins || [];
+ const babelConfigPlugins = config?.plugins || [];
const extraPlugins = [
[
@@ -48,8 +47,8 @@ export function babel(config: TransformOptions, options: Options): TransformOpti
...config,
plugins: [...babelConfigPlugins, ...extraPlugins],
};
-}
+};
-export const previewAnnotations: StorybookConfig['previewAnnotations'] = (entry = []) => {
+export const previewAnnotations: PresetProperty<'previewAnnotations'> = (entry = []) => {
return [...entry, findDistEsm(__dirname, 'client/preview/config')];
};
diff --git a/code/frameworks/ember/src/server/framework-preset-ember-docs.ts b/code/frameworks/ember/src/server/framework-preset-ember-docs.ts
index f6dd860c2f9f..24e1a97a1cc9 100644
--- a/code/frameworks/ember/src/server/framework-preset-ember-docs.ts
+++ b/code/frameworks/ember/src/server/framework-preset-ember-docs.ts
@@ -1,8 +1,8 @@
-import type { StorybookConfig } from '@storybook/types';
+import type { PresetProperty } from '@storybook/types';
import { findDistEsm } from '@storybook/core-common';
import { hasDocsOrControls } from '@storybook/docs-tools';
-export const previewAnnotations: StorybookConfig['previewAnnotations'] = (entry = [], options) => {
+export const previewAnnotations: PresetProperty<'previewAnnotations'> = (entry = [], options) => {
if (!hasDocsOrControls(options)) return entry;
return [...entry, findDistEsm(__dirname, 'client/docs/config')];
};
diff --git a/code/frameworks/ember/template/cli/Button.stories.js b/code/frameworks/ember/template/cli/Button.stories.js
index bfb6bd756b1f..c32f8a065659 100644
--- a/code/frameworks/ember/template/cli/Button.stories.js
+++ b/code/frameworks/ember/template/cli/Button.stories.js
@@ -2,7 +2,7 @@ import { hbs } from 'ember-cli-htmlbars';
import { action } from '@storybook/addon-actions';
import { linkTo } from '@storybook/addon-links';
-// More on how to set up stories at: https://storybook.js.org/docs/ember/writing-stories/introduction
+// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
export default {
title: 'Example/Button',
render: (args) => ({
@@ -12,11 +12,11 @@ export default {
argTypes: {
label: { control: 'text' },
},
- // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
+ // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
tags: ['autodocs'],
};
-// More on writing stories with args: https://storybook.js.org/docs/ember/writing-stories/args
+// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
export const Text = {
args: {
label: 'Button',
diff --git a/code/frameworks/html-vite/package.json b/code/frameworks/html-vite/package.json
index bdde39577ac6..e95384d4c21f 100644
--- a/code/frameworks/html-vite/package.json
+++ b/code/frameworks/html-vite/package.json
@@ -47,18 +47,15 @@
"prep": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/bundle.ts"
},
"dependencies": {
- "@storybook/addons": "workspace:*",
"@storybook/builder-vite": "workspace:*",
- "@storybook/client-api": "workspace:*",
"@storybook/core-server": "workspace:*",
"@storybook/html": "workspace:*",
"@storybook/node-logger": "workspace:*",
- "@storybook/preview-web": "workspace:*",
"magic-string": "^0.30.0"
},
"devDependencies": {
"@types/node": "^18.0.0",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"engines": {
"node": "^14.18 || >=16"
diff --git a/code/frameworks/html-webpack5/package.json b/code/frameworks/html-webpack5/package.json
index 7042fdd34780..7b95c59dceb1 100644
--- a/code/frameworks/html-webpack5/package.json
+++ b/code/frameworks/html-webpack5/package.json
@@ -55,7 +55,7 @@
"@types/node": "^18.0.0"
},
"devDependencies": {
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"peerDependencies": {
"@babel/core": "*"
diff --git a/code/frameworks/html-webpack5/src/preset.ts b/code/frameworks/html-webpack5/src/preset.ts
index 969bee1b1e63..b2f0058627e2 100644
--- a/code/frameworks/html-webpack5/src/preset.ts
+++ b/code/frameworks/html-webpack5/src/preset.ts
@@ -1,16 +1,13 @@
import { dirname, join } from 'path';
import type { PresetProperty } from '@storybook/types';
-import type { StorybookConfig } from './types';
const getAbsolutePath = (input: I): I =>
dirname(require.resolve(join(input, 'package.json'))) as any;
-export const addons: PresetProperty<'addons', StorybookConfig> = [
- getAbsolutePath('@storybook/preset-html-webpack'),
-];
+export const addons: PresetProperty<'addons'> = [getAbsolutePath('@storybook/preset-html-webpack')];
-export const core: PresetProperty<'core', StorybookConfig> = async (config, options) => {
- const framework = await options.presets.apply('framework');
+export const core: PresetProperty<'core'> = async (config, options) => {
+ const framework = await options.presets.apply('framework');
return {
...config,
diff --git a/code/frameworks/nextjs/README.md b/code/frameworks/nextjs/README.md
index 2a834fb7ee4a..252fb329167d 100644
--- a/code/frameworks/nextjs/README.md
+++ b/code/frameworks/nextjs/README.md
@@ -354,7 +354,7 @@ export const Example = {
#### Global Defaults
-Global defaults can be set in [preview.js](https://storybook.js.org/docs/react/configure/overview#configure-story-rendering) and will be shallowly merged with the default router.
+Global defaults can be set in [preview.js](https://storybook.js.org/docs/react/configure/#configure-story-rendering) and will be shallowly merged with the default router.
```js
// .storybook/preview.js
@@ -489,7 +489,7 @@ export const Example = {
},
```
-If your Next.js project uses the `app` directory for every page (in other words, it does not have a `pages` directory), you can set the parameter `nextjs.appDirectory` to `true` in the [preview.js](https://storybook.js.org/docs/react/configure/overview#configure-story-rendering) file to apply it to all stories.
+If your Next.js project uses the `app` directory for every page (in other words, it does not have a `pages` directory), you can set the parameter `nextjs.appDirectory` to `true` in the [preview.js](https://storybook.js.org/docs/react/configure/#configure-story-rendering) file to apply it to all stories.
```js
// .storybook/preview.js
@@ -534,7 +534,7 @@ export const Example = {
#### Global Defaults
-Global defaults can be set in [preview.js](https://storybook.js.org/docs/react/configure/overview#configure-story-rendering) and will be shallowly merged with the default router.
+Global defaults can be set in [preview.js](https://storybook.js.org/docs/react/configure/#configure-story-rendering) and will be shallowly merged with the default router.
```js
// .storybook/preview.js
@@ -694,7 +694,7 @@ export const parameters = {
### Sass/Scss
-[Global sass/scss stylesheets](https://nextjs.org/docs/basic-features/built-in-css-support#sass-support) are supported without any additional configuration as well. Just import them into [preview.js](https://storybook.js.org/docs/react/configure/overview#configure-story-rendering)
+[Global sass/scss stylesheets](https://nextjs.org/docs/basic-features/built-in-css-support#sass-support) are supported without any additional configuration as well. Just import them into [preview.js](https://storybook.js.org/docs/react/configure/#configure-story-rendering)
```js
import '../styles/globals.scss';
diff --git a/code/frameworks/nextjs/package.json b/code/frameworks/nextjs/package.json
index 7831dfa90280..a78675dceeaa 100644
--- a/code/frameworks/nextjs/package.json
+++ b/code/frameworks/nextjs/package.json
@@ -123,7 +123,7 @@
"@types/babel__preset-env": "^7",
"@types/loader-utils": "^2.0.5",
"next": "^14.0.2",
- "typescript": "^4.9.3",
+ "typescript": "^5.3.2",
"webpack": "^5.65.0"
},
"peerDependencies": {
diff --git a/code/frameworks/nextjs/src/head-manager/head-manager-provider.tsx b/code/frameworks/nextjs/src/head-manager/head-manager-provider.tsx
index 45c3a4ab4c33..ee62063351ea 100644
--- a/code/frameworks/nextjs/src/head-manager/head-manager-provider.tsx
+++ b/code/frameworks/nextjs/src/head-manager/head-manager-provider.tsx
@@ -1,3 +1,4 @@
+import type { PropsWithChildren } from 'react';
import React, { useMemo } from 'react';
import { HeadManagerContext } from 'next/dist/shared/lib/head-manager-context.shared-runtime';
import initHeadManager from 'next/dist/client/head-manager';
@@ -12,7 +13,7 @@ type HeadManagerValue = {
nonce?: string | undefined;
};
-const HeadManagerProvider: React.FC = ({ children }) => {
+const HeadManagerProvider: React.FC = ({ children }) => {
const headManager: HeadManagerValue = useMemo(initHeadManager, []);
headManager.getIsSsr = () => false;
diff --git a/code/frameworks/nextjs/src/preset.ts b/code/frameworks/nextjs/src/preset.ts
index e4fdd7936fb9..f29290209281 100644
--- a/code/frameworks/nextjs/src/preset.ts
+++ b/code/frameworks/nextjs/src/preset.ts
@@ -1,7 +1,7 @@
// https://storybook.js.org/docs/react/addons/writing-presets
import { dirname, join } from 'path';
-import type { Options, PresetProperty } from '@storybook/types';
-import type { ConfigItem, PluginItem, TransformOptions } from '@babel/core';
+import type { PresetProperty } from '@storybook/types';
+import type { ConfigItem, PluginItem } from '@babel/core';
import { loadPartialConfig } from '@babel/core';
import { getProjectRoot } from '@storybook/core-common';
import { configureConfig } from './config/webpack';
@@ -19,17 +19,14 @@ import { configureNodePolyfills } from './nodePolyfills/webpack';
import { configureAliasing } from './dependency-map';
import { configureSWCLoader } from './swc/loader';
-export const addons: PresetProperty<'addons', StorybookConfig> = [
+export const addons: PresetProperty<'addons'> = [
dirname(require.resolve(join('@storybook/preset-react-webpack', 'package.json'))),
];
const defaultFrameworkOptions: FrameworkOptions = {};
-export const frameworkOptions = async (
- _: never,
- options: Options
-): Promise => {
- const config = await options.presets.apply('framework');
+export const frameworkOptions: PresetProperty<'framework'> = async (_, options) => {
+ const config = await options.presets.apply('framework');
if (typeof config === 'string') {
return {
@@ -53,8 +50,8 @@ export const frameworkOptions = async (
};
};
-export const core: PresetProperty<'core', StorybookConfig> = async (config, options) => {
- const framework = await options.presets.apply('framework');
+export const core: PresetProperty<'core'> = async (config, options) => {
+ const framework = await options.presets.apply('framework');
return {
...config,
@@ -70,7 +67,7 @@ export const core: PresetProperty<'core', StorybookConfig> = async (config, opti
};
};
-export const previewAnnotations: StorybookConfig['previewAnnotations'] = (entry = []) => [
+export const previewAnnotations: PresetProperty<'previewAnnotations'> = (entry = []) => [
...entry,
join(dirname(require.resolve('@storybook/nextjs/package.json')), 'dist/preview.mjs'),
];
@@ -78,7 +75,7 @@ export const previewAnnotations: StorybookConfig['previewAnnotations'] = (entry
// Not even sb init - automigrate - running dev
// You're using a version of Nextjs prior to v10, which is unsupported by this framework.
-export const babel = async (baseConfig: TransformOptions): Promise => {
+export const babel: PresetProperty<'babel'> = async (baseConfig) => {
const configPartial = loadPartialConfig({
...baseConfig,
filename: `${getProjectRoot()}/__fake__.js`,
diff --git a/code/frameworks/nextjs/src/routing/app-router-provider.tsx b/code/frameworks/nextjs/src/routing/app-router-provider.tsx
index c8b1c96c80a3..478b8a59f9df 100644
--- a/code/frameworks/nextjs/src/routing/app-router-provider.tsx
+++ b/code/frameworks/nextjs/src/routing/app-router-provider.tsx
@@ -26,7 +26,7 @@ const getParallelRoutes = (segmentsList: Array): FlightRouterState => {
return [] as any;
};
-export const AppRouterProvider: React.FC = ({
+export const AppRouterProvider: React.FC> = ({
children,
action,
routeParams,
diff --git a/code/frameworks/nextjs/src/routing/page-router-provider.tsx b/code/frameworks/nextjs/src/routing/page-router-provider.tsx
index 466d8dd21b3b..066e7f32b3fd 100644
--- a/code/frameworks/nextjs/src/routing/page-router-provider.tsx
+++ b/code/frameworks/nextjs/src/routing/page-router-provider.tsx
@@ -1,5 +1,6 @@
import type { Globals } from '@storybook/csf';
import { RouterContext } from 'next/dist/shared/lib/router-context.shared-runtime';
+import type { PropsWithChildren } from 'react';
import React from 'react';
import type { RouteParams } from './types';
@@ -9,7 +10,7 @@ type PageRouterProviderProps = {
globals: Globals;
};
-export const PageRouterProvider: React.FC = ({
+export const PageRouterProvider: React.FC> = ({
children,
action,
routeParams,
diff --git a/code/frameworks/nextjs/src/styledJsx/decorator.tsx b/code/frameworks/nextjs/src/styledJsx/decorator.tsx
index 33040334055d..d358ecf55a15 100644
--- a/code/frameworks/nextjs/src/styledJsx/decorator.tsx
+++ b/code/frameworks/nextjs/src/styledJsx/decorator.tsx
@@ -1,6 +1,6 @@
import * as React from 'react';
-let StyleRegistry: React.FC;
+let StyleRegistry: React.FC;
try {
// next >= v12
diff --git a/code/frameworks/nextjs/src/swc/loader.ts b/code/frameworks/nextjs/src/swc/loader.ts
index 099914e1be85..352d3796d549 100644
--- a/code/frameworks/nextjs/src/swc/loader.ts
+++ b/code/frameworks/nextjs/src/swc/loader.ts
@@ -50,7 +50,7 @@ export const configureSWCLoader = async (
rootDir: dir,
pagesDir: `${dir}/pages`,
appDir: `${dir}/apps`,
- hasReactRefresh: applyFastRefresh(options),
+ hasReactRefresh: await applyFastRefresh(options),
nextConfig,
supportedBrowsers: require('next/dist/build/utils').getSupportedBrowsers(
dir,
diff --git a/code/frameworks/nextjs/template/cli/js/Button.stories.js b/code/frameworks/nextjs/template/cli/js/Button.stories.js
index e085f9ed312f..3a3f67ec8fb4 100644
--- a/code/frameworks/nextjs/template/cli/js/Button.stories.js
+++ b/code/frameworks/nextjs/template/cli/js/Button.stories.js
@@ -1,22 +1,22 @@
import { Button } from './Button';
-// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
+// 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/react/configure/story-layout
+ // 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/react/writing-docs/autodocs
+ // 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/react/api/argtypes
+ // More on argTypes: https://storybook.js.org/docs/api/argtypes
argTypes: {
backgroundColor: { control: 'color' },
},
};
-// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
+// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
export const Primary = {
args: {
primary: true,
diff --git a/code/frameworks/nextjs/template/cli/js/Configure.mdx b/code/frameworks/nextjs/template/cli/js/Configure.mdx
index e05f151edf74..055a3c564efc 100644
--- a/code/frameworks/nextjs/template/cli/js/Configure.mdx
+++ b/code/frameworks/nextjs/template/cli/js/Configure.mdx
@@ -52,7 +52,7 @@ export const RightArrow = () => Add styling and CSS
Like with web applications, there are many ways to include CSS within Storybook. Learn more about setting up styling within Storybook.
Learn more
@@ -67,7 +67,7 @@ export const RightArrow = () => Provide context and mocking
Often when a story doesn't render, it's because your component is expecting a specific environment or context (like a theme provider) to be available.
Learn more
@@ -85,7 +85,7 @@ export const RightArrow = () =>
Learn more
@@ -113,7 +113,7 @@ export const RightArrow = () => Auto-generate living,
interactive reference documentation from your components and stories.
Learn more
@@ -128,7 +128,7 @@ export const RightArrow = () => Publish to Chromatic
Publish your Storybook to review and collaborate with your entire team.
Learn more
@@ -144,7 +144,7 @@ export const RightArrow = () => Embed your stories into Figma to cross-reference the design and live
implementation in one place.
Learn more
@@ -160,7 +160,7 @@ export const RightArrow = () => Use stories to test a component in all its variations, no matter how
complex.
Learn more
@@ -175,7 +175,7 @@ export const RightArrow = () => Accessibility
Automatically test your components for a11y issues as you develop.
Learn more
@@ -190,7 +190,7 @@ export const RightArrow = () => Theming
Theme Storybook's UI to personalize it to your project.
Learn more
diff --git a/code/frameworks/nextjs/template/cli/js/Header.stories.js b/code/frameworks/nextjs/template/cli/js/Header.stories.js
index 704a8c699534..a1d32b3ad65e 100644
--- a/code/frameworks/nextjs/template/cli/js/Header.stories.js
+++ b/code/frameworks/nextjs/template/cli/js/Header.stories.js
@@ -3,10 +3,10 @@ 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/react/writing-docs/autodocs
+ // 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/react/configure/story-layout
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
layout: 'fullscreen',
},
};
diff --git a/code/frameworks/nextjs/template/cli/js/Page.stories.js b/code/frameworks/nextjs/template/cli/js/Page.stories.js
index f339fa246d39..53362f140e61 100644
--- a/code/frameworks/nextjs/template/cli/js/Page.stories.js
+++ b/code/frameworks/nextjs/template/cli/js/Page.stories.js
@@ -5,14 +5,14 @@ export default {
title: 'Example/Page',
component: Page,
parameters: {
- // More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
layout: 'fullscreen',
},
};
export const LoggedOut = {};
-// More on interaction testing: https://storybook.js.org/docs/react/writing-tests/interaction-testing
+// More on interaction testing: https://storybook.js.org/docs/writing-tests/interaction-testing
export const LoggedIn = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
diff --git a/code/frameworks/nextjs/template/cli/ts-3-8/Button.stories.ts b/code/frameworks/nextjs/template/cli/ts-3-8/Button.stories.ts
index 7d049116d13f..b65080126a44 100644
--- a/code/frameworks/nextjs/template/cli/ts-3-8/Button.stories.ts
+++ b/code/frameworks/nextjs/template/cli/ts-3-8/Button.stories.ts
@@ -2,17 +2,17 @@ import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
-// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
+// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
const meta: Meta = {
title: 'Example/Button',
component: Button,
parameters: {
- // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
+ // 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/react/writing-docs/autodocs
+ // 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/react/api/argtypes
+ // More on argTypes: https://storybook.js.org/docs/api/argtypes
argTypes: {
backgroundColor: { control: 'color' },
},
@@ -21,7 +21,7 @@ const meta: Meta = {
export default meta;
type Story = StoryObj;
-// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
+// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
export const Primary: Story = {
args: {
primary: true,
diff --git a/code/frameworks/nextjs/template/cli/ts-3-8/Configure.mdx b/code/frameworks/nextjs/template/cli/ts-3-8/Configure.mdx
index e05f151edf74..055a3c564efc 100644
--- a/code/frameworks/nextjs/template/cli/ts-3-8/Configure.mdx
+++ b/code/frameworks/nextjs/template/cli/ts-3-8/Configure.mdx
@@ -52,7 +52,7 @@ export const RightArrow = () => Add styling and CSS
Like with web applications, there are many ways to include CSS within Storybook. Learn more about setting up styling within Storybook.
Learn more
@@ -67,7 +67,7 @@ export const RightArrow = () => Provide context and mocking
Often when a story doesn't render, it's because your component is expecting a specific environment or context (like a theme provider) to be available.
Learn more
@@ -85,7 +85,7 @@ export const RightArrow = () =>
Learn more
@@ -113,7 +113,7 @@ export const RightArrow = () => Auto-generate living,
interactive reference documentation from your components and stories.
Learn more
@@ -128,7 +128,7 @@ export const RightArrow = () => Publish to Chromatic
Publish your Storybook to review and collaborate with your entire team.
Learn more
@@ -144,7 +144,7 @@ export const RightArrow = () => Embed your stories into Figma to cross-reference the design and live
implementation in one place.
Learn more
@@ -160,7 +160,7 @@ export const RightArrow = () => Use stories to test a component in all its variations, no matter how
complex.
Learn more
@@ -175,7 +175,7 @@ export const RightArrow = () => Accessibility
Automatically test your components for a11y issues as you develop.
Learn more
@@ -190,7 +190,7 @@ export const RightArrow = () => Theming
Theme Storybook's UI to personalize it to your project.
Learn more
diff --git a/code/frameworks/nextjs/template/cli/ts-3-8/Header.stories.ts b/code/frameworks/nextjs/template/cli/ts-3-8/Header.stories.ts
index 448685eab0eb..82a109720879 100644
--- a/code/frameworks/nextjs/template/cli/ts-3-8/Header.stories.ts
+++ b/code/frameworks/nextjs/template/cli/ts-3-8/Header.stories.ts
@@ -4,10 +4,10 @@ import { Header } from './Header';
const meta: Meta = {
title: 'Example/Header',
component: Header,
- // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
+ // 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/react/configure/story-layout
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
layout: 'fullscreen',
},
};
diff --git a/code/frameworks/nextjs/template/cli/ts-3-8/Page.stories.ts b/code/frameworks/nextjs/template/cli/ts-3-8/Page.stories.ts
index c072a1cc43ed..4bcf593cafa7 100644
--- a/code/frameworks/nextjs/template/cli/ts-3-8/Page.stories.ts
+++ b/code/frameworks/nextjs/template/cli/ts-3-8/Page.stories.ts
@@ -7,7 +7,7 @@ const meta: Meta = {
title: 'Example/Page',
component: Page,
parameters: {
- // More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
layout: 'fullscreen',
},
};
@@ -17,7 +17,7 @@ type Story = StoryObj;
export const LoggedOut: Story = {};
-// More on interaction testing: https://storybook.js.org/docs/react/writing-tests/interaction-testing
+// More on interaction testing: https://storybook.js.org/docs/writing-tests/interaction-testing
export const LoggedIn: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
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 7a68cbfec557..742c3aa7b029 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
@@ -2,17 +2,17 @@ import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
-// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
+// 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/react/configure/story-layout
+ // 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/react/writing-docs/autodocs
+ // 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/react/api/argtypes
+ // More on argTypes: https://storybook.js.org/docs/api/argtypes
argTypes: {
backgroundColor: { control: 'color' },
},
@@ -21,7 +21,7 @@ const meta = {
export default meta;
type Story = StoryObj;
-// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
+// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
export const Primary: Story = {
args: {
primary: true,
diff --git a/code/frameworks/nextjs/template/cli/ts-4-9/Configure.mdx b/code/frameworks/nextjs/template/cli/ts-4-9/Configure.mdx
index e05f151edf74..055a3c564efc 100644
--- a/code/frameworks/nextjs/template/cli/ts-4-9/Configure.mdx
+++ b/code/frameworks/nextjs/template/cli/ts-4-9/Configure.mdx
@@ -52,7 +52,7 @@ export const RightArrow = () => Add styling and CSS
Like with web applications, there are many ways to include CSS within Storybook. Learn more about setting up styling within Storybook.
Learn more
@@ -67,7 +67,7 @@ export const RightArrow = () => Provide context and mocking
Often when a story doesn't render, it's because your component is expecting a specific environment or context (like a theme provider) to be available.
Learn more
@@ -85,7 +85,7 @@ export const RightArrow = () =>
Learn more
@@ -113,7 +113,7 @@ export const RightArrow = () => Auto-generate living,
interactive reference documentation from your components and stories.
Learn more
@@ -128,7 +128,7 @@ export const RightArrow = () => Publish to Chromatic
Publish your Storybook to review and collaborate with your entire team.
Learn more
@@ -144,7 +144,7 @@ export const RightArrow = () => Embed your stories into Figma to cross-reference the design and live
implementation in one place.
Learn more
@@ -160,7 +160,7 @@ export const RightArrow = () => Use stories to test a component in all its variations, no matter how
complex.
Learn more
@@ -175,7 +175,7 @@ export const RightArrow = () => Accessibility
Automatically test your components for a11y issues as you develop.
Learn more
@@ -190,7 +190,7 @@ export const RightArrow = () => Theming
Theme Storybook's UI to personalize it to your project.
Learn more
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 b0766a5a4839..046982e62673 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
@@ -4,10 +4,10 @@ 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/react/writing-docs/autodocs
+ // 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/react/configure/story-layout
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
layout: 'fullscreen',
},
} satisfies Meta;
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 622858e72e7f..f7a06817f85a 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
@@ -7,7 +7,7 @@ const meta = {
title: 'Example/Page',
component: Page,
parameters: {
- // More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
layout: 'fullscreen',
},
} satisfies Meta;
@@ -17,7 +17,7 @@ type Story = StoryObj;
export const LoggedOut: Story = {};
-// More on interaction testing: https://storybook.js.org/docs/react/writing-tests/interaction-testing
+// More on interaction testing: https://storybook.js.org/docs/writing-tests/interaction-testing
export const LoggedIn: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-ts/Navigation.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-default-ts/Navigation.stories.tsx
index 39efad27c256..8bb209bd9d45 100644
--- a/code/frameworks/nextjs/template/stories_nextjs-default-ts/Navigation.stories.tsx
+++ b/code/frameworks/nextjs/template/stories_nextjs-default-ts/Navigation.stories.tsx
@@ -24,7 +24,6 @@ function Component() {
name: 'Prefetch',
},
{
- // @ts-expect-error (old-api)
cb: () => router.push('/push-html', { forceOptimisticNavigation: true }),
name: 'Push HTML',
},
@@ -33,7 +32,6 @@ function Component() {
name: 'Refresh',
},
{
- // @ts-expect-error (old-api)
cb: () => router.replace('/replaced-html', { forceOptimisticNavigation: true }),
name: 'Replace',
},
diff --git a/code/frameworks/preact-vite/package.json b/code/frameworks/preact-vite/package.json
index 2a1c37fa3a6c..75c50f4c5d5f 100644
--- a/code/frameworks/preact-vite/package.json
+++ b/code/frameworks/preact-vite/package.json
@@ -53,7 +53,7 @@
},
"devDependencies": {
"@types/node": "^18.0.0",
- "typescript": "~4.9.3",
+ "typescript": "^5.3.2",
"vite": "^4.0.0"
},
"peerDependencies": {
diff --git a/code/frameworks/preact-webpack5/README.md b/code/frameworks/preact-webpack5/README.md
index 0402d392c40b..eda406d5509e 100644
--- a/code/frameworks/preact-webpack5/README.md
+++ b/code/frameworks/preact-webpack5/README.md
@@ -24,6 +24,6 @@ You can also build a [static version](https://storybook.js.org/docs/preact/shari
## Docs
-- [Basics](https://storybook.js.org/docs/preact/get-started/introduction)
-- [Configurations](https://storybook.js.org/docs/preact/configure/overview)
+- [Basics](https://storybook.js.org/docs/preact/get-started)
+- [Configurations](https://storybook.js.org/docs/preact/configure)
- [Addons](https://storybook.js.org/docs/preact/configure/storybook-addons)
diff --git a/code/frameworks/preact-webpack5/package.json b/code/frameworks/preact-webpack5/package.json
index e85bf0ee863c..98b97e75a38e 100644
--- a/code/frameworks/preact-webpack5/package.json
+++ b/code/frameworks/preact-webpack5/package.json
@@ -55,7 +55,7 @@
},
"devDependencies": {
"preact": "^10.5.13",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"peerDependencies": {
"@babel/core": "*",
diff --git a/code/frameworks/preact-webpack5/src/preset.ts b/code/frameworks/preact-webpack5/src/preset.ts
index e815e7884248..0d90ce796e79 100644
--- a/code/frameworks/preact-webpack5/src/preset.ts
+++ b/code/frameworks/preact-webpack5/src/preset.ts
@@ -1,16 +1,15 @@
import { dirname, join } from 'path';
import type { PresetProperty } from '@storybook/types';
-import type { StorybookConfig } from './types';
const getAbsolutePath = (input: I): I =>
dirname(require.resolve(join(input, 'package.json'))) as any;
-export const addons: PresetProperty<'addons', StorybookConfig> = [
+export const addons: PresetProperty<'addons'> = [
getAbsolutePath('@storybook/preset-preact-webpack'),
];
-export const core: PresetProperty<'core', StorybookConfig> = async (config, options) => {
- const framework = await options.presets.apply('framework');
+export const core: PresetProperty<'core'> = async (config, options) => {
+ const framework = await options.presets.apply('framework');
return {
...config,
diff --git a/code/frameworks/react-vite/package.json b/code/frameworks/react-vite/package.json
index de7122e28e60..1fd368072636 100644
--- a/code/frameworks/react-vite/package.json
+++ b/code/frameworks/react-vite/package.json
@@ -57,7 +57,7 @@
},
"devDependencies": {
"@types/node": "^18.0.0",
- "typescript": "~4.9.3",
+ "typescript": "^5.3.2",
"vite": "^4.0.0"
},
"peerDependencies": {
diff --git a/code/frameworks/react-vite/src/typings.d.ts b/code/frameworks/react-vite/src/typings.d.ts
deleted file mode 100644
index 53aa2b04a775..000000000000
--- a/code/frameworks/react-vite/src/typings.d.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-// TODO: Replace, as soon as @types/react-dom 17.0.14 is used
-// Source: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/fb0f14b7a35cde26ffaa82e7536c062e593e9ae6/types/react-dom/client.d.ts
-declare module 'react-dom/client' {
- import React = require('react');
-
- export interface HydrationOptions {
- onHydrated?(suspenseInstance: Comment): void;
- onDeleted?(suspenseInstance: Comment): void;
- /**
- * Prefix for `useId`.
- */
- identifierPrefix?: string;
- onRecoverableError?: (error: unknown) => void;
- }
-
- export interface RootOptions {
- /**
- * Prefix for `useId`.
- */
- identifierPrefix?: string;
- onRecoverableError?: (error: unknown) => void;
- }
-
- export interface Root {
- render(children: React.ReactChild | Iterable): void;
- unmount(): void;
- }
-
- /**
- * Replaces `ReactDOM.render` when the `.render` method is called and enables Concurrent Mode.
- *
- * @see https://reactjs.org/docs/concurrent-mode-reference.html#createroot
- */
- export function createRoot(
- container: Element | Document | DocumentFragment | Comment,
- options?: RootOptions
- ): Root;
-
- export function hydrateRoot(
- container: Element | Document | DocumentFragment | Comment,
- initialChildren: React.ReactChild | Iterable,
- options?: HydrationOptions
- ): Root;
-}
diff --git a/code/frameworks/react-webpack5/README.md b/code/frameworks/react-webpack5/README.md
index 68e2ff7255c4..b3b1d877eaa2 100644
--- a/code/frameworks/react-webpack5/README.md
+++ b/code/frameworks/react-webpack5/README.md
@@ -42,6 +42,6 @@ But you probably also need to use types from `@types/node @types/react`.
## Docs
-- [Basics](https://storybook.js.org/docs/react/get-started/introduction)
-- [Configurations](https://storybook.js.org/docs/react/configure/overview)
+- [Basics](https://storybook.js.org/docs/react/get-started)
+- [Configurations](https://storybook.js.org/docs/react/configure)
- [Addons](https://storybook.js.org/docs/react/configure/storybook-addons)
diff --git a/code/frameworks/react-webpack5/src/preset.ts b/code/frameworks/react-webpack5/src/preset.ts
index 873d214c597c..997d070537f9 100644
--- a/code/frameworks/react-webpack5/src/preset.ts
+++ b/code/frameworks/react-webpack5/src/preset.ts
@@ -7,7 +7,7 @@ import type { FrameworkOptions, StorybookConfig } from './types';
const getAbsolutePath = (input: I): I =>
dirname(require.resolve(join(input, 'package.json'))) as any;
-export const addons: PresetProperty<'addons', StorybookConfig> = [
+export const addons: PresetProperty<'addons'> = [
getAbsolutePath('@storybook/preset-react-webpack'),
];
@@ -43,8 +43,8 @@ export const frameworkOptions = async (
};
};
-export const core: PresetProperty<'core', StorybookConfig> = async (config, options) => {
- const framework = await options.presets.apply('framework');
+export const core: PresetProperty<'core'> = async (config, options) => {
+ const framework = await options.presets.apply('framework');
return {
...config,
diff --git a/code/frameworks/react-webpack5/src/typings.d.ts b/code/frameworks/react-webpack5/src/typings.d.ts
deleted file mode 100644
index 53aa2b04a775..000000000000
--- a/code/frameworks/react-webpack5/src/typings.d.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-// TODO: Replace, as soon as @types/react-dom 17.0.14 is used
-// Source: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/fb0f14b7a35cde26ffaa82e7536c062e593e9ae6/types/react-dom/client.d.ts
-declare module 'react-dom/client' {
- import React = require('react');
-
- export interface HydrationOptions {
- onHydrated?(suspenseInstance: Comment): void;
- onDeleted?(suspenseInstance: Comment): void;
- /**
- * Prefix for `useId`.
- */
- identifierPrefix?: string;
- onRecoverableError?: (error: unknown) => void;
- }
-
- export interface RootOptions {
- /**
- * Prefix for `useId`.
- */
- identifierPrefix?: string;
- onRecoverableError?: (error: unknown) => void;
- }
-
- export interface Root {
- render(children: React.ReactChild | Iterable): void;
- unmount(): void;
- }
-
- /**
- * Replaces `ReactDOM.render` when the `.render` method is called and enables Concurrent Mode.
- *
- * @see https://reactjs.org/docs/concurrent-mode-reference.html#createroot
- */
- export function createRoot(
- container: Element | Document | DocumentFragment | Comment,
- options?: RootOptions
- ): Root;
-
- export function hydrateRoot(
- container: Element | Document | DocumentFragment | Comment,
- initialChildren: React.ReactChild | Iterable,
- options?: HydrationOptions
- ): Root;
-}
diff --git a/code/frameworks/server-webpack5/package.json b/code/frameworks/server-webpack5/package.json
index c3934c2feb9a..4401248d36fc 100644
--- a/code/frameworks/server-webpack5/package.json
+++ b/code/frameworks/server-webpack5/package.json
@@ -54,7 +54,7 @@
"@types/node": "^18.0.0"
},
"devDependencies": {
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"engines": {
"node": ">=16.0.0"
diff --git a/code/frameworks/server-webpack5/src/preset.ts b/code/frameworks/server-webpack5/src/preset.ts
index 0dd7d63814f0..5dc0b94b30ad 100644
--- a/code/frameworks/server-webpack5/src/preset.ts
+++ b/code/frameworks/server-webpack5/src/preset.ts
@@ -1,16 +1,15 @@
import { dirname, join } from 'path';
import type { PresetProperty } from '@storybook/types';
-import type { StorybookConfig } from './types';
const getAbsolutePath = (input: I): I =>
dirname(require.resolve(join(input, 'package.json'))) as any;
-export const addons: PresetProperty<'addons', StorybookConfig> = [
+export const addons: PresetProperty<'addons'> = [
getAbsolutePath('@storybook/preset-server-webpack'),
];
-export const core: PresetProperty<'core', StorybookConfig> = async (config, options) => {
- const framework = await options.presets.apply('framework');
+export const core: PresetProperty<'core'> = async (config, options) => {
+ const framework = await options.presets.apply('framework');
return {
...config,
diff --git a/code/frameworks/svelte-vite/package.json b/code/frameworks/svelte-vite/package.json
index 2da7f1a7ec88..073303400c10 100644
--- a/code/frameworks/svelte-vite/package.json
+++ b/code/frameworks/svelte-vite/package.json
@@ -59,7 +59,7 @@
"devDependencies": {
"@types/node": "^18.0.0",
"svelte": "^4.0.0",
- "typescript": "~4.9.3",
+ "typescript": "^5.3.2",
"vite": "^4.0.0"
},
"peerDependencies": {
diff --git a/code/frameworks/svelte-webpack5/package.json b/code/frameworks/svelte-webpack5/package.json
index 6ef4e7fe4e32..c5523964a755 100644
--- a/code/frameworks/svelte-webpack5/package.json
+++ b/code/frameworks/svelte-webpack5/package.json
@@ -55,7 +55,7 @@
"devDependencies": {
"svelte": "^4.0.0",
"svelte-loader": "^3.1.9",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"peerDependencies": {
"@babel/core": "*",
diff --git a/code/frameworks/svelte-webpack5/src/preset.ts b/code/frameworks/svelte-webpack5/src/preset.ts
index 176bce0c0bc5..8b4500023010 100644
--- a/code/frameworks/svelte-webpack5/src/preset.ts
+++ b/code/frameworks/svelte-webpack5/src/preset.ts
@@ -1,16 +1,15 @@
import { dirname, join } from 'path';
import type { PresetProperty } from '@storybook/types';
-import type { StorybookConfig } from './types';
const getAbsolutePath = (input: I): I =>
dirname(require.resolve(join(input, 'package.json'))) as any;
-export const addons: PresetProperty<'addons', StorybookConfig> = [
+export const addons: PresetProperty<'addons'> = [
getAbsolutePath('@storybook/preset-svelte-webpack'),
];
-export const core: PresetProperty<'core', StorybookConfig> = async (config, options) => {
- const framework = await options.presets.apply('framework');
+export const core: PresetProperty<'core'> = async (config, options) => {
+ const framework = await options.presets.apply('framework');
return {
...config,
diff --git a/code/frameworks/sveltekit/README.md b/code/frameworks/sveltekit/README.md
index 20248ce0d3f3..02f43b117710 100644
--- a/code/frameworks/sveltekit/README.md
+++ b/code/frameworks/sveltekit/README.md
@@ -40,7 +40,7 @@ However SvelteKit has some [Kit-specific modules](https://kit.svelte.dev/docs/mo
| [`$service-worker`](https://kit.svelte.dev/docs/modules#$service-worker) | ⛔ Not supported | They are only meant to be used in service workers |
| [`@sveltejs/kit/*`](https://kit.svelte.dev/docs/modules#sveltejs-kit) | ✅ Supported | |
-This is just the beginning. We're close to adding basic support for many of the SvelteKit features. Longer term we're planning on making it an even better experience to [build](https://storybook.js.org/docs/svelte/writing-stories/introduction), [test](https://storybook.js.org/docs/svelte/writing-tests/introduction) and [document](https://storybook.js.org/docs/svelte/writing-docs/introduction) all the SvelteKit goodies like [pages](https://kit.svelte.dev/docs/routing), [forms](https://kit.svelte.dev/docs/form-actions) and [layouts](https://kit.svelte.dev/docs/routing#layout) in Storybook, while still integrating with all the addons and workflows you know and love.
+This is just the beginning. We're close to adding basic support for many of the SvelteKit features. Longer term we're planning on making it an even better experience to [build](https://storybook.js.org/docs/svelte/writing-stories), [test](https://storybook.js.org/docs/svelte/writing-tests) and [document](https://storybook.js.org/docs/svelte/writing-docs) all the SvelteKit goodies like [pages](https://kit.svelte.dev/docs/routing), [forms](https://kit.svelte.dev/docs/form-actions) and [layouts](https://kit.svelte.dev/docs/routing#layout) in Storybook, while still integrating with all the addons and workflows you know and love.
## Requirements
diff --git a/code/frameworks/sveltekit/package.json b/code/frameworks/sveltekit/package.json
index 61eb49eeb405..d36fd1d00e54 100644
--- a/code/frameworks/sveltekit/package.json
+++ b/code/frameworks/sveltekit/package.json
@@ -60,7 +60,7 @@
},
"devDependencies": {
"@types/node": "^18.0.0",
- "typescript": "^4.9.3",
+ "typescript": "^5.3.2",
"vite": "^4.0.0"
},
"peerDependencies": {
diff --git a/code/frameworks/sveltekit/src/preset.ts b/code/frameworks/sveltekit/src/preset.ts
index 45cfe7d0a6dd..7af34f9e4206 100644
--- a/code/frameworks/sveltekit/src/preset.ts
+++ b/code/frameworks/sveltekit/src/preset.ts
@@ -10,11 +10,11 @@ import { type StorybookConfig } from './types';
const getAbsolutePath = (input: I): I =>
dirname(require.resolve(join(input, 'package.json'))) as any;
-export const core: PresetProperty<'core', StorybookConfig> = {
+export const core: PresetProperty<'core'> = {
builder: getAbsolutePath('@storybook/builder-vite'),
renderer: getAbsolutePath('@storybook/svelte'),
};
-export const previewAnnotations: StorybookConfig['previewAnnotations'] = (entry = []) => [
+export const previewAnnotations: PresetProperty<'previewAnnotations'> = (entry = []) => [
...entry,
join(dirname(require.resolve('@storybook/sveltekit/package.json')), 'dist/preview.mjs'),
];
diff --git a/code/frameworks/vue-vite/package.json b/code/frameworks/vue-vite/package.json
index c9410d017e2f..b663dc001ef5 100644
--- a/code/frameworks/vue-vite/package.json
+++ b/code/frameworks/vue-vite/package.json
@@ -55,7 +55,7 @@
"vue-docgen-api": "^4.40.0"
},
"devDependencies": {
- "typescript": "~4.9.3",
+ "typescript": "^5.3.2",
"vite": "^4.0.0",
"vue": "^2.7.10"
},
diff --git a/code/frameworks/vue-vite/src/preset.ts b/code/frameworks/vue-vite/src/preset.ts
index 3030587afaaa..aec3778a7525 100644
--- a/code/frameworks/vue-vite/src/preset.ts
+++ b/code/frameworks/vue-vite/src/preset.ts
@@ -7,8 +7,8 @@ import { vueDocgen } from './plugins/vue-docgen';
const getAbsolutePath = (input: I): I =>
dirname(require.resolve(join(input, 'package.json'))) as any;
-export const core: PresetProperty<'core', StorybookConfig> = async (config, options) => {
- const framework = await options.presets.apply('framework');
+export const core: PresetProperty<'core'> = async (config, options) => {
+ const framework = await options.presets.apply('framework');
return {
...config,
diff --git a/code/frameworks/vue-webpack5/package.json b/code/frameworks/vue-webpack5/package.json
index ad127e7e1ca7..2c483b4abe7e 100644
--- a/code/frameworks/vue-webpack5/package.json
+++ b/code/frameworks/vue-webpack5/package.json
@@ -54,7 +54,7 @@
"@types/node": "^18.0.0"
},
"devDependencies": {
- "typescript": "~4.9.3",
+ "typescript": "^5.3.2",
"vue": "^2.6.12",
"vue-loader": "^15.7.0",
"vue-template-compiler": "^2.6.14"
diff --git a/code/frameworks/vue-webpack5/src/preset.ts b/code/frameworks/vue-webpack5/src/preset.ts
index 1e493e9a7f99..690adc16b7c8 100644
--- a/code/frameworks/vue-webpack5/src/preset.ts
+++ b/code/frameworks/vue-webpack5/src/preset.ts
@@ -1,16 +1,13 @@
import { dirname, join } from 'path';
import type { PresetProperty } from '@storybook/types';
-import type { StorybookConfig } from './types';
const getAbsolutePath = (input: I): I =>
dirname(require.resolve(join(input, 'package.json'))) as any;
-export const addons: PresetProperty<'addons', StorybookConfig> = [
- getAbsolutePath('@storybook/preset-vue-webpack'),
-];
+export const addons: PresetProperty<'addons'> = [getAbsolutePath('@storybook/preset-vue-webpack')];
-export const core: PresetProperty<'core', StorybookConfig> = async (config, options) => {
- const framework = await options.presets.apply('framework');
+export const core: PresetProperty<'core'> = async (config, options) => {
+ const framework = await options.presets.apply('framework');
return {
...config,
@@ -22,7 +19,7 @@ export const core: PresetProperty<'core', StorybookConfig> = async (config, opti
};
};
-export const typescript: PresetProperty<'typescript', StorybookConfig> = async (config) => ({
+export const typescript: PresetProperty<'typescript'> = async (config) => ({
...config,
skipBabel: true,
skipCompiler: true,
diff --git a/code/frameworks/vue3-vite/package.json b/code/frameworks/vue3-vite/package.json
index 0ab72705651f..9ed7cfa8f117 100644
--- a/code/frameworks/vue3-vite/package.json
+++ b/code/frameworks/vue3-vite/package.json
@@ -56,7 +56,7 @@
},
"devDependencies": {
"@types/node": "^18.0.0",
- "typescript": "~4.9.3",
+ "typescript": "^5.3.2",
"vite": "^4.0.0"
},
"peerDependencies": {
diff --git a/code/frameworks/vue3-vite/src/preset.ts b/code/frameworks/vue3-vite/src/preset.ts
index b987f0381c0b..c0d97bd8da87 100644
--- a/code/frameworks/vue3-vite/src/preset.ts
+++ b/code/frameworks/vue3-vite/src/preset.ts
@@ -8,7 +8,7 @@ import { vueDocgen } from './plugins/vue-docgen';
const getAbsolutePath = (input: I): I =>
dirname(require.resolve(join(input, 'package.json'))) as any;
-export const core: PresetProperty<'core', StorybookConfig> = {
+export const core: PresetProperty<'core'> = {
builder: getAbsolutePath('@storybook/builder-vite'),
renderer: getAbsolutePath('@storybook/vue3'),
};
diff --git a/code/frameworks/vue3-webpack5/package.json b/code/frameworks/vue3-webpack5/package.json
index f88b0eac666a..34db85da79e9 100644
--- a/code/frameworks/vue3-webpack5/package.json
+++ b/code/frameworks/vue3-webpack5/package.json
@@ -55,7 +55,7 @@
},
"devDependencies": {
"@vue/compiler-sfc": "3.0.0",
- "typescript": "~4.9.3",
+ "typescript": "^5.3.2",
"vue": "3.0.0"
},
"peerDependencies": {
diff --git a/code/frameworks/vue3-webpack5/src/preset.ts b/code/frameworks/vue3-webpack5/src/preset.ts
index 1714cc16075e..b06e70968cdb 100644
--- a/code/frameworks/vue3-webpack5/src/preset.ts
+++ b/code/frameworks/vue3-webpack5/src/preset.ts
@@ -9,8 +9,8 @@ export const addons: PresetProperty<'addons', StorybookConfig> = [
getAbsolutePath('@storybook/preset-vue3-webpack'),
];
-export const core: PresetProperty<'core', StorybookConfig> = async (config, options) => {
- const framework = await options.presets.apply('framework');
+export const core: PresetProperty<'core'> = async (config, options) => {
+ const framework = await options.presets.apply('framework');
return {
...config,
@@ -22,7 +22,7 @@ export const core: PresetProperty<'core', StorybookConfig> = async (config, opti
};
};
-export const typescript: PresetProperty<'typescript', StorybookConfig> = async (config) => ({
+export const typescript: PresetProperty<'typescript'> = async (config) => ({
...config,
skipBabel: true,
skipCompiler: true,
diff --git a/code/frameworks/web-components-vite/package.json b/code/frameworks/web-components-vite/package.json
index 46d499d612d8..eac1425cddb6 100644
--- a/code/frameworks/web-components-vite/package.json
+++ b/code/frameworks/web-components-vite/package.json
@@ -55,7 +55,7 @@
},
"devDependencies": {
"@types/node": "^18.0.0",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"engines": {
"node": "^14.18 || >=16"
diff --git a/code/frameworks/web-components-webpack5/package.json b/code/frameworks/web-components-webpack5/package.json
index 3abed50fec8a..71cc8c58dac7 100644
--- a/code/frameworks/web-components-webpack5/package.json
+++ b/code/frameworks/web-components-webpack5/package.json
@@ -59,7 +59,7 @@
},
"devDependencies": {
"lit": "2.3.1",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"peerDependencies": {
"lit": "^2.0.0 || ^3.0.0"
diff --git a/code/frameworks/web-components-webpack5/src/preset.ts b/code/frameworks/web-components-webpack5/src/preset.ts
index 101539931f27..f746c12a788a 100644
--- a/code/frameworks/web-components-webpack5/src/preset.ts
+++ b/code/frameworks/web-components-webpack5/src/preset.ts
@@ -1,16 +1,15 @@
import { dirname, join } from 'path';
import type { PresetProperty } from '@storybook/types';
-import type { StorybookConfig } from './types';
const getAbsolutePath = (input: I): I =>
dirname(require.resolve(join(input, 'package.json'))) as any;
-export const addons: PresetProperty<'addons', StorybookConfig> = [
+export const addons: PresetProperty<'addons'> = [
getAbsolutePath('@storybook/preset-web-components-webpack'),
];
-export const core: PresetProperty<'core', StorybookConfig> = async (config, options) => {
- const framework = await options.presets.apply('framework');
+export const core: PresetProperty<'core'> = async (config, options) => {
+ const framework = await options.presets.apply('framework');
return {
...config,
diff --git a/code/jest.config.base.js b/code/jest.config.base.js
index 89ff7acf0b8b..40ac535cd60a 100644
--- a/code/jest.config.base.js
+++ b/code/jest.config.base.js
@@ -13,7 +13,6 @@ const swcrc = JSON.parse(fs.readFileSync('.swcrc', 'utf8'));
const skipOnWindows = [
'lib/core-server/src/utils/__tests__/server-statics.test.ts',
'lib/core-common/src/utils/__tests__/template.test.ts',
- 'addons/storyshots-core/src/frameworks/configure.test.ts',
'lib/core-common/src/utils/__tests__/interpret-files.test.ts',
'lib/cli/src/helpers.test.ts',
'lib/csf-tools/src/enrichCsf.test.ts',
diff --git a/code/jest.init.base.ts b/code/jest.init.base.ts
index 5641077f934c..641a21599d47 100644
--- a/code/jest.init.base.ts
+++ b/code/jest.init.base.ts
@@ -29,12 +29,9 @@ const ignoreList = [
(error: any) => error.message.includes('":nth-child" is potentially unsafe'),
(error: any) => error.message.includes('":first-child" is potentially unsafe'),
(error: any) => error.message.match(/Browserslist: .* is outdated. Please run:/),
- (error: any) => error.message.includes('Failed prop type') && error.stack.includes('storyshots'),
(error: any) =>
error.message.includes('react-async-component-lifecycle-hooks') &&
error.stack.includes('addons/knobs/src/components/__tests__/Options.js'),
- // Storyshots blows up if your project includes a (non stories.) mdx file.
- (error: any) => error.message.match(/Unexpected error while loading .*(? {
diff --git a/code/lib/channels/package.json b/code/lib/channels/package.json
index 251d12e19f96..2a26cb0ef200 100644
--- a/code/lib/channels/package.json
+++ b/code/lib/channels/package.json
@@ -27,36 +27,11 @@
"require": "./dist/index.js",
"import": "./dist/index.mjs"
},
- "./dist/postmessage/index": {
- "types": "./dist/postmessage/index.d.ts",
- "node": "./dist/postmessage/index.js",
- "require": "./dist/postmessage/index.js",
- "import": "./dist/postmessage/index.mjs"
- },
- "./dist/websocket/index": {
- "types": "./dist/websocket/index.d.ts",
- "node": "./dist/websocket/index.js",
- "require": "./dist/websocket/index.js",
- "import": "./dist/websocket/index.mjs"
- },
"./package.json": "./package.json"
},
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
- "typesVersions": {
- "*": {
- "*": [
- "dist/index.d.ts"
- ],
- "dist/postmessage/index": [
- "dist/postmessage/index.d.ts"
- ],
- "dist/websocket/index": [
- "dist/websocket/index.d.ts"
- ]
- }
- },
"files": [
"dist/**/*",
"README.md",
@@ -77,16 +52,14 @@
"tiny-invariant": "^1.3.1"
},
"devDependencies": {
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
},
"bundler": {
"entries": [
- "./src/index.ts",
- "./src/postmessage/index.ts",
- "./src/websocket/index.ts"
+ "./src/index.ts"
]
},
"gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae17"
diff --git a/code/lib/channels/src/index.ts b/code/lib/channels/src/index.ts
index fff392082cdd..a6c975752f13 100644
--- a/code/lib/channels/src/index.ts
+++ b/code/lib/channels/src/index.ts
@@ -23,7 +23,7 @@ type Options = Config & {
/**
* Creates a new browser channel instance.
* @param {Options} options - The options object.
- * @param {Page} options.page - The puppeteer page instance.
+ * @param {Page} options.page - page identifier.
* @param {ChannelTransport[]} [options.extraTransports=[]] - An optional array of extra channel transports.
* @returns {Channel} - The new channel instance.
*/
diff --git a/code/lib/cli/package.json b/code/lib/cli/package.json
index 098c8ca3162b..335bc8a6a618 100644
--- a/code/lib/cli/package.json
+++ b/code/lib/cli/package.json
@@ -88,7 +88,6 @@
"ora": "^5.4.1",
"prettier": "^2.8.0",
"prompts": "^2.4.0",
- "puppeteer-core": "^2.1.1",
"read-pkg-up": "^7.0.1",
"semver": "^7.3.7",
"simple-update-notifier": "^2.0.0",
@@ -98,21 +97,20 @@
"util-deprecate": "^1.0.2"
},
"devDependencies": {
- "@storybook/client-api": "workspace:*",
"@types/cross-spawn": "^6.0.2",
"@types/prompts": "^2.0.9",
- "@types/puppeteer-core": "^2.1.0",
"@types/semver": "^7.3.4",
"@types/util-deprecate": "^1.0.0",
"boxen": "^5.1.2",
"slash": "^5.0.0",
"strip-json-comments": "^3.1.1",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
},
"bundler": {
+ "pre": "./scripts/generate-sb-packages-versions.js",
"entries": [
"./src/generate.ts",
"./src/index.ts"
diff --git a/code/lib/cli/rendererAssets/common/Configure.mdx b/code/lib/cli/rendererAssets/common/Configure.mdx
index 40b04abb105a..a3d3c80985fb 100644
--- a/code/lib/cli/rendererAssets/common/Configure.mdx
+++ b/code/lib/cli/rendererAssets/common/Configure.mdx
@@ -123,7 +123,7 @@ export const RightArrow = () => Use stories to test a component in all its variations, no matter how
complex.
Learn more
diff --git a/code/lib/cli/scripts/generate-sb-packages-versions.js b/code/lib/cli/scripts/generate-sb-packages-versions.js
new file mode 100644
index 000000000000..72c97fcf7abc
--- /dev/null
+++ b/code/lib/cli/scripts/generate-sb-packages-versions.js
@@ -0,0 +1,72 @@
+#!/usr/bin/env node
+
+const { promisify } = require('util');
+const { readJson, writeFile } = require('fs-extra');
+const { exec } = require('child_process');
+const path = require('path');
+const semver = require('semver');
+const { default: dedent } = require('ts-dedent');
+
+const rootDirectory = path.join(__dirname, '..', '..', '..');
+
+const logger = console;
+
+const getMonorepoPackages = async () => {
+ const process = promisify(exec);
+ const contents = await process('yarn workspaces list --json --no-private', {
+ cwd: rootDirectory,
+ });
+
+ return JSON.parse(`[${contents.stdout.trim().split('\n').join(',')}]`).map((w) => w.location);
+};
+
+const run = async () => {
+ let updatedVersion = process.argv[process.argv.length - 1];
+
+ if (!semver.valid(updatedVersion)) {
+ updatedVersion = (await readJson(path.join(rootDirectory, 'package.json'))).version;
+ }
+
+ const storybookPackages = await getMonorepoPackages();
+
+ const packageToVersionMap = (
+ await Promise.all(
+ storybookPackages.map(async (location) => {
+ const { name, version } = await readJson(
+ path.join(rootDirectory, location, 'package.json')
+ );
+
+ return {
+ name,
+ version,
+ };
+ })
+ )
+ )
+ .filter(({ name }) => /^(@storybook|sb$|storybook$)/.test(name))
+ // As some previous steps are asynchronous order is not always the same so sort them to avoid that
+ .sort((package1, package2) => package1.name.localeCompare(package2.name))
+ .reduce((acc, { name }) => ({ ...acc, [name]: updatedVersion }), {});
+
+ const versionsPath = path.join(__dirname, '..', 'src', 'versions.ts');
+
+ await writeFile(
+ versionsPath,
+ dedent`
+ // auto generated file, do not edit
+ export default ${JSON.stringify(packageToVersionMap, null, 2)}
+ `
+ );
+
+ logger.log(`Updating versions and formatting results at: ${versionsPath}`);
+
+ const prettierBin = path.join(rootDirectory, '..', 'scripts', 'node_modules', '.bin', 'prettier');
+ exec(`${prettierBin} --write ${versionsPath}`, {
+ cwd: path.join(rootDirectory),
+ });
+};
+
+run().catch((e) => {
+ logger.error(e);
+ process.exit(1);
+});
diff --git a/code/lib/cli/src/automigrate/fixes/add-react.test.ts b/code/lib/cli/src/automigrate/fixes/add-react.test.ts
index 4602a30d3ecd..9b7103625de7 100644
--- a/code/lib/cli/src/automigrate/fixes/add-react.test.ts
+++ b/code/lib/cli/src/automigrate/fixes/add-react.test.ts
@@ -1,4 +1,4 @@
-import type { StorybookConfig } from '@storybook/types';
+import type { StorybookConfigRaw } from '@storybook/types';
import type { JsPackageManager, PackageJson } from '../../js-package-manager';
import { addReact } from './add-react';
@@ -9,7 +9,7 @@ const checkAddReact = async (packageJson: PackageJson) => {
return addReact.check({
packageManager,
- mainConfig: {} as StorybookConfig,
+ mainConfig: {} as StorybookConfigRaw,
storybookVersion: '7.0.0',
});
};
diff --git a/code/lib/cli/src/automigrate/fixes/autodocs-true.test.ts b/code/lib/cli/src/automigrate/fixes/autodocs-true.test.ts
index c21de1bd9727..af244a8ad073 100644
--- a/code/lib/cli/src/automigrate/fixes/autodocs-true.test.ts
+++ b/code/lib/cli/src/automigrate/fixes/autodocs-true.test.ts
@@ -1,4 +1,4 @@
-import type { StorybookConfig } from '@storybook/types';
+import type { StorybookConfigRaw } from '@storybook/types';
import type { PackageJson } from '../../js-package-manager';
import { makePackageManager } from '../helpers/testing-helpers';
import { autodocsTrue } from './autodocs-true';
@@ -8,11 +8,11 @@ const checkAutodocs = async ({
main: mainConfig,
}: {
packageJson?: PackageJson;
- main: Partial & Record;
+ main: Partial & Record;
}) => {
return autodocsTrue.check({
packageManager: makePackageManager(packageJson),
- mainConfig: mainConfig as StorybookConfig,
+ mainConfig: mainConfig as StorybookConfigRaw,
storybookVersion: '7.0.0',
});
};
diff --git a/code/lib/cli/src/automigrate/fixes/autodocs-true.ts b/code/lib/cli/src/automigrate/fixes/autodocs-true.ts
index 336bd111d39a..c3c2adc59f06 100644
--- a/code/lib/cli/src/automigrate/fixes/autodocs-true.ts
+++ b/code/lib/cli/src/automigrate/fixes/autodocs-true.ts
@@ -1,7 +1,7 @@
import chalk from 'chalk';
import { dedent } from 'ts-dedent';
-import type { StorybookConfig } from '@storybook/types';
+import type { StorybookConfigRaw } from '@storybook/types';
import type { Fix } from '../types';
import { updateMainConfig } from '../helpers/mainConfigFile';
@@ -9,7 +9,7 @@ import { updateMainConfig } from '../helpers/mainConfigFile';
const logger = console;
interface AutodocsTrueFrameworkRunOptions {
- value?: StorybookConfig['docs']['autodocs'];
+ value?: StorybookConfigRaw['docs']['autodocs'];
}
/**
diff --git a/code/lib/cli/src/automigrate/fixes/bare-mdx-stories-glob.test.ts b/code/lib/cli/src/automigrate/fixes/bare-mdx-stories-glob.test.ts
index 7354fca3c4a9..46ea29710724 100644
--- a/code/lib/cli/src/automigrate/fixes/bare-mdx-stories-glob.test.ts
+++ b/code/lib/cli/src/automigrate/fixes/bare-mdx-stories-glob.test.ts
@@ -1,6 +1,6 @@
/// ;
-import type { StorybookConfig } from '@storybook/types';
+import type { StorybookConfigRaw } from '@storybook/types';
import type { PackageJson } from '../../js-package-manager';
import { ansiRegex } from '../helpers/cleanLog';
import { makePackageManager } from '../helpers/testing-helpers';
@@ -13,11 +13,11 @@ const checkBareMdxStoriesGlob = async ({
storybookVersion = '7.0.0',
}: {
packageJson: PackageJson;
- main?: Partial & Record;
+ main?: Partial & Record;
storybookVersion?: string;
}) => {
return bareMdxStoriesGlob.check({
- mainConfig: mainConfig as StorybookConfig,
+ mainConfig: mainConfig as StorybookConfigRaw,
packageManager: makePackageManager(packageJson),
storybookVersion,
});
diff --git a/code/lib/cli/src/automigrate/fixes/builder-vite.test.ts b/code/lib/cli/src/automigrate/fixes/builder-vite.test.ts
index 20b8f935c0e7..4905a22c2d9b 100644
--- a/code/lib/cli/src/automigrate/fixes/builder-vite.test.ts
+++ b/code/lib/cli/src/automigrate/fixes/builder-vite.test.ts
@@ -1,4 +1,4 @@
-import type { StorybookConfig } from '@storybook/types';
+import type { StorybookConfigRaw } from '@storybook/types';
import { makePackageManager } from '../helpers/testing-helpers';
import type { PackageJson } from '../../js-package-manager';
import { builderVite } from './builder-vite';
@@ -8,10 +8,10 @@ const checkBuilderVite = async ({
main: mainConfig,
}: {
packageJson?: PackageJson;
- main: Partial & Record;
+ main: Partial & Record;
}) => {
return builderVite.check({
- mainConfig: mainConfig as StorybookConfig,
+ mainConfig: mainConfig as StorybookConfigRaw,
packageManager: makePackageManager(packageJson),
storybookVersion: '7.0.0',
});
diff --git a/code/lib/cli/src/automigrate/fixes/cra5.test.ts b/code/lib/cli/src/automigrate/fixes/cra5.test.ts
index 15ef6485851d..1eedffc0a12f 100644
--- a/code/lib/cli/src/automigrate/fixes/cra5.test.ts
+++ b/code/lib/cli/src/automigrate/fixes/cra5.test.ts
@@ -1,4 +1,4 @@
-import type { StorybookConfig } from '@storybook/types';
+import type { StorybookConfigRaw } from '@storybook/types';
import type { JsPackageManager } from '../../js-package-manager';
import { cra5 } from './cra5';
@@ -8,12 +8,12 @@ const checkCra5 = async ({
storybookVersion = '7.0.0',
}: {
packageManager: any;
- main?: Partial & Record;
+ main?: Partial & Record;
storybookVersion?: string;
}) => {
return cra5.check({
packageManager,
- mainConfig: mainConfig as StorybookConfig,
+ mainConfig: mainConfig as StorybookConfigRaw,
storybookVersion,
});
};
diff --git a/code/lib/cli/src/automigrate/helpers/checkWebpack5Builder.test.ts b/code/lib/cli/src/automigrate/helpers/checkWebpack5Builder.test.ts
index 51cb622baf42..89428a48fb2d 100644
--- a/code/lib/cli/src/automigrate/helpers/checkWebpack5Builder.test.ts
+++ b/code/lib/cli/src/automigrate/helpers/checkWebpack5Builder.test.ts
@@ -1,8 +1,8 @@
-import type { StorybookConfig } from '@storybook/types';
+import type { StorybookConfigRaw } from '@storybook/types';
import { checkWebpack5Builder } from './checkWebpack5Builder';
import { getBuilderPackageName } from './mainConfigFile';
-const mockMainConfig: StorybookConfig = {
+const mockMainConfig: StorybookConfigRaw = {
framework: 'react',
addons: [],
stories: [],
diff --git a/code/lib/cli/src/automigrate/helpers/checkWebpack5Builder.ts b/code/lib/cli/src/automigrate/helpers/checkWebpack5Builder.ts
index 8d59d62d0bcc..860b68fb0718 100644
--- a/code/lib/cli/src/automigrate/helpers/checkWebpack5Builder.ts
+++ b/code/lib/cli/src/automigrate/helpers/checkWebpack5Builder.ts
@@ -1,7 +1,7 @@
import chalk from 'chalk';
import semver from 'semver';
import dedent from 'ts-dedent';
-import type { StorybookConfig } from '@storybook/types';
+import type { StorybookConfigRaw } from '@storybook/types';
import { getBuilderPackageName } from './mainConfigFile';
const logger = console;
@@ -10,7 +10,7 @@ export const checkWebpack5Builder = async ({
mainConfig,
storybookVersion,
}: {
- mainConfig: StorybookConfig;
+ mainConfig: StorybookConfigRaw;
storybookVersion: string;
}) => {
if (semver.lt(storybookVersion, '6.3.0')) {
diff --git a/code/lib/cli/src/automigrate/helpers/getMigrationSummary.test.ts b/code/lib/cli/src/automigrate/helpers/getMigrationSummary.test.ts
index 8a28a6c4fe23..a435976da1ab 100644
--- a/code/lib/cli/src/automigrate/helpers/getMigrationSummary.test.ts
+++ b/code/lib/cli/src/automigrate/helpers/getMigrationSummary.test.ts
@@ -25,7 +25,6 @@ describe('getMigrationSummary', () => {
const installationMetadata: InstallationMetadata = {
duplicatedDependencies: {
- '@storybook/core-client': ['7.0.0', '7.1.0'],
'@storybook/instrumenter': ['6.0.0', '7.1.0'],
'@storybook/core-common': ['6.0.0', '7.1.0'],
'@storybook/addon-essentials': ['7.0.0', '7.1.0'],
diff --git a/code/lib/cli/src/automigrate/helpers/mainConfigFile.ts b/code/lib/cli/src/automigrate/helpers/mainConfigFile.ts
index b5325df31ac2..188e9bd9d99b 100644
--- a/code/lib/cli/src/automigrate/helpers/mainConfigFile.ts
+++ b/code/lib/cli/src/automigrate/helpers/mainConfigFile.ts
@@ -5,7 +5,7 @@ import {
frameworkPackages,
builderPackages,
} from '@storybook/core-common';
-import type { StorybookConfig } from '@storybook/types';
+import type { StorybookConfigRaw, StorybookConfig } from '@storybook/types';
import type { ConfigFile } from '@storybook/csf-tools';
import { readConfig, writeConfig as writeConfigFile } from '@storybook/csf-tools';
import chalk from 'chalk';
@@ -21,7 +21,7 @@ const logger = console;
* @param mainConfig - The main Storybook configuration object to lookup.
* @returns - The package name of the framework. If not found, returns null.
*/
-export const getFrameworkPackageName = (mainConfig?: StorybookConfig) => {
+export const getFrameworkPackageName = (mainConfig?: StorybookConfigRaw) => {
const packageNameOrPath =
typeof mainConfig?.framework === 'string' ? mainConfig.framework : mainConfig?.framework?.name;
@@ -41,7 +41,7 @@ export const getFrameworkPackageName = (mainConfig?: StorybookConfig) => {
* @param mainConfig - The main Storybook configuration object to lookup.
* @returns - The package name of the builder. If not found, returns null.
*/
-export const getBuilderPackageName = (mainConfig?: StorybookConfig) => {
+export const getBuilderPackageName = (mainConfig?: StorybookConfigRaw) => {
const packageNameOrPath =
typeof mainConfig?.core?.builder === 'string'
? mainConfig.core.builder
@@ -97,9 +97,9 @@ export const getStorybookData = async ({
const configDir = userDefinedConfigDir || configDirFromScript || '.storybook';
- let mainConfig: StorybookConfig;
+ let mainConfig: StorybookConfigRaw;
try {
- mainConfig = await loadMainConfig({ configDir, noCache: true });
+ mainConfig = (await loadMainConfig({ configDir, noCache: true })) as StorybookConfigRaw;
} catch (err) {
throw new Error(
dedent`Unable to find or evaluate ${chalk.blue(mainConfigPath)}: ${err.message}`
diff --git a/code/lib/cli/src/automigrate/helpers/new-frameworks-utils.ts b/code/lib/cli/src/automigrate/helpers/new-frameworks-utils.ts
index db84aaa3b245..3f7348e0c7a5 100644
--- a/code/lib/cli/src/automigrate/helpers/new-frameworks-utils.ts
+++ b/code/lib/cli/src/automigrate/helpers/new-frameworks-utils.ts
@@ -1,5 +1,5 @@
import { frameworkPackages } from '@storybook/core-common';
-import type { Preset, StorybookConfig } from '@storybook/types';
+import type { Preset, StorybookConfigRaw } from '@storybook/types';
import findUp from 'find-up';
import type { JsPackageManager } from '../../js-package-manager';
import { getBuilderPackageName, getFrameworkPackageName } from './mainConfigFile';
@@ -66,7 +66,7 @@ export const detectBuilderInfo = async ({
configDir,
packageManager,
}: {
- mainConfig: StorybookConfig & { builder?: string | Preset };
+ mainConfig: StorybookConfigRaw & { builder?: string | Preset };
configDir: string;
packageManager: JsPackageManager;
}): Promise<{ name: BuilderType; options: any }> => {
diff --git a/code/lib/cli/src/automigrate/types.ts b/code/lib/cli/src/automigrate/types.ts
index 740dfa3a0451..a2c124c09629 100644
--- a/code/lib/cli/src/automigrate/types.ts
+++ b/code/lib/cli/src/automigrate/types.ts
@@ -1,11 +1,11 @@
-import type { StorybookConfig } from '@storybook/types';
+import type { StorybookConfigRaw } from '@storybook/types';
import type { JsPackageManager, PackageManagerName } from '../js-package-manager';
export interface CheckOptions {
packageManager: JsPackageManager;
rendererPackage?: string;
configDir?: string;
- mainConfig: StorybookConfig;
+ mainConfig: StorybookConfigRaw;
storybookVersion: string;
previewConfigPath?: string;
mainConfigPath?: string;
diff --git a/code/lib/cli/src/extract.ts b/code/lib/cli/src/extract.ts
deleted file mode 100644
index e7e45d82d0fc..000000000000
--- a/code/lib/cli/src/extract.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-import path from 'path';
-import { writeFile, stat } from 'fs-extra';
-import puppeteerCore from 'puppeteer-core';
-import express from 'express';
-import getPort from 'get-port';
-import { logger } from '@storybook/node-logger';
-
-const read = async (url: string) => {
- const browser = await usePuppeteerBrowser();
- const page = await browser.newPage();
-
- await page.goto(url);
-
- // we don't know whether we are running against a new or old storybook
- // FIXME: add tests for both
- await page.waitForFunction(`
- (window.__STORYBOOK_PREVIEW__ && window.__STORYBOOK_PREVIEW__.extract && window.__STORYBOOK_PREVIEW__.extract()) ||
- (window.__STORYBOOK_STORY_STORE__ && window.__STORYBOOK_STORY_STORE__.extract && window.__STORYBOOK_STORY_STORE__.extract())
- `);
- const data = JSON.parse(
- await page.evaluate(async () => {
- return JSON.stringify(window.__STORYBOOK_STORY_STORE__.getStoriesJsonData(), null, 2);
- })
- );
-
- setImmediate(() => {
- browser.close();
- });
- return data;
-};
-
-const useLocation: (input: string) => Promise<[string, () => void]> = async (input: string) => {
- // check for input's existence
- await stat(path.resolve(input));
-
- if (input.match(/^http/)) {
- return [input, async () => {}];
- }
-
- const app = express();
-
- app.use(express.static(input));
-
- const port = await getPort();
-
- return new Promise((resolve) => {
- const server = app.listen(port, () => {
- const result = `http://localhost:${port}/iframe.html`;
-
- logger.info(`connecting to: ${result}`);
-
- resolve([result, server.close.bind(server)]);
- });
- });
-};
-
-const usePuppeteerBrowser: () => Promise = async () => {
- const args = ['--no-sandbox ', '--disable-setuid-sandbox'];
- try {
- return await puppeteerCore.launch({ args, executablePath: process.env.SB_CHROMIUM_PATH });
- } catch (e) {
- // it's not installed
- logger.info('installing puppeteer...');
- return new Promise((resolve, reject) => {
- // eslint-disable-next-line global-require
- require('child_process').exec(
- `node ${require.resolve(path.join('puppeteer-core', 'install.js'))}`,
- (error: any) => (error ? reject(error) : resolve(puppeteerCore.launch({ args })))
- );
- });
- }
-};
-
-export async function extract(input: string, targetPath: string) {
- if (input && targetPath) {
- const [location, exit] = await useLocation(input);
-
- const data = await read(location);
-
- await writeFile(targetPath, JSON.stringify(data, null, 2));
-
- await exit();
- } else {
- throw new Error(
- 'Extract: please specify a path where your built-storybook is (can be a public url) and a target directory'
- );
- }
-}
diff --git a/code/lib/cli/src/generate.ts b/code/lib/cli/src/generate.ts
index 8f37de772933..c1572af2c132 100644
--- a/code/lib/cli/src/generate.ts
+++ b/code/lib/cli/src/generate.ts
@@ -1,5 +1,4 @@
import program from 'commander';
-import path from 'path';
import chalk from 'chalk';
import envinfo from 'envinfo';
import leven from 'leven';
@@ -12,7 +11,6 @@ import type { CommandOptions } from './generators/types';
import { initiate } from './initiate';
import { add } from './add';
import { migrate } from './migrate';
-import { extract } from './extract';
import { upgrade, type UpgradeOptions } from './upgrade';
import { sandbox } from './sandbox';
import { link } from './link';
@@ -137,15 +135,6 @@ command('migrate [migration]')
});
});
-command('extract [location] [output]')
- .description('extract stories.json from a built version')
- .action((location = 'storybook-static', output = path.join(location, 'stories.json')) =>
- extract(location, output).catch((e) => {
- logger.error(e);
- process.exit(1);
- })
- );
-
command('sandbox [filterValue]')
.alias('repro') // for backwards compatibility
.description('Create a sandbox from a set of possible templates')
diff --git a/code/lib/cli/src/repro-generators/configs.ts b/code/lib/cli/src/repro-generators/configs.ts
index 7cf305e56ed0..b3cd46836fbf 100644
--- a/code/lib/cli/src/repro-generators/configs.ts
+++ b/code/lib/cli/src/repro-generators/configs.ts
@@ -283,5 +283,5 @@ export const svelteKit: Parameters = {
name: 'svelteKit',
version: 'latest',
generator:
- 'yarn create svelte-with-args --name={{appName}} --directory=. --template=skeleton --types=null --no-prettier --no-eslint --no-playwright',
+ 'yarn create svelte-with-args --name={{appName}} --directory=. --template=skeleton --types=null --no-prettier --no-eslint --no-playwright --no-vitest --no-svelte5',
};
diff --git a/code/lib/cli/src/sandbox-templates.ts b/code/lib/cli/src/sandbox-templates.ts
index 600a01044e56..86b28646fb10 100644
--- a/code/lib/cli/src/sandbox-templates.ts
+++ b/code/lib/cli/src/sandbox-templates.ts
@@ -1,4 +1,4 @@
-import type { StorybookConfig } from '@storybook/types';
+import type { StorybookConfigRaw } from '@storybook/types';
export type SkippableTask =
| 'smoke-test'
@@ -66,7 +66,7 @@ export type Template = {
*/
modifications?: {
skipTemplateStories?: boolean;
- mainConfig?: Partial;
+ mainConfig?: Partial;
testBuild?: boolean;
disableDocs?: boolean;
};
@@ -336,7 +336,7 @@ const baseTemplates = {
'svelte-kit/skeleton-js': {
name: 'SvelteKit Latest (Vite | JavaScript)',
script:
- 'yarn create svelte-with-args --name=svelte-kit/skeleton-js --directory={{beforeDir}} --template=skeleton --types=null --no-prettier --no-eslint --no-playwright --no-vitest',
+ 'yarn create svelte-with-args --name=svelte-kit/skeleton-js --directory={{beforeDir}} --template=skeleton --types=null --no-prettier --no-eslint --no-playwright --no-vitest --no-svelte5',
expected: {
framework: '@storybook/sveltekit',
renderer: '@storybook/svelte',
@@ -347,7 +347,7 @@ const baseTemplates = {
'svelte-kit/skeleton-ts': {
name: 'SvelteKit Latest (Vite | TypeScript)',
script:
- 'yarn create svelte-with-args --name=svelte-kit/skeleton-ts --directory={{beforeDir}} --template=skeleton --types=typescript --no-prettier --no-eslint --no-playwright --no-vitest',
+ 'yarn create svelte-with-args --name=svelte-kit/skeleton-ts --directory={{beforeDir}} --template=skeleton --types=typescript --no-prettier --no-eslint --no-playwright --no-vitest --no-svelte5',
expected: {
framework: '@storybook/sveltekit',
renderer: '@storybook/svelte',
@@ -466,34 +466,6 @@ const baseTemplates = {
* They will be hidden by default in the Storybook status page.
*/
const internalTemplates = {
- 'internal/ssv6-vite': {
- ...baseTemplates['react-vite/default-ts'],
- name: 'StoryStore v6 (react-vite/default-ts)',
- isInternal: true,
- modifications: {
- mainConfig: {
- features: {
- storyStoreV7: false,
- storyStoreV7MdxErrors: false,
- },
- },
- },
- skipTasks: ['bench'],
- },
- 'internal/ssv6-webpack': {
- ...baseTemplates['cra/default-ts'],
- name: 'StoryStore v6 (cra/default-ts)',
- isInternal: true,
- modifications: {
- mainConfig: {
- features: {
- storyStoreV7: false,
- storyStoreV7MdxErrors: false,
- },
- },
- },
- skipTasks: ['bench'],
- },
'internal/swc-webpack': {
...baseTemplates['react-webpack/18-ts'],
name: 'SWC (react-webpack/18-ts)',
@@ -615,8 +587,6 @@ export const merged: TemplateKey[] = [
'preact-vite/default-ts',
'html-webpack/default',
'html-vite/default-ts',
- 'internal/ssv6-vite',
- 'internal/ssv6-webpack',
];
export const daily: TemplateKey[] = [
...merged,
diff --git a/code/lib/cli/src/versions.ts b/code/lib/cli/src/versions.ts
index 88fc9806b29a..564316aa8797 100644
--- a/code/lib/cli/src/versions.ts
+++ b/code/lib/cli/src/versions.ts
@@ -13,28 +13,20 @@ export default {
'@storybook/addon-mdx-gfm': '7.6.0-beta.2',
'@storybook/addon-measure': '7.6.0-beta.2',
'@storybook/addon-outline': '7.6.0-beta.2',
- '@storybook/addon-themes': '7.6.0-beta.2',
- '@storybook/addon-storyshots': '7.6.0-beta.2',
- '@storybook/addon-storyshots-puppeteer': '7.6.0-beta.2',
'@storybook/addon-storysource': '7.6.0-beta.2',
+ '@storybook/addon-themes': '7.6.0-beta.2',
'@storybook/addon-toolbars': '7.6.0-beta.2',
'@storybook/addon-viewport': '7.6.0-beta.2',
- '@storybook/addons': '7.6.0-beta.2',
'@storybook/angular': '7.6.0-beta.2',
- '@storybook/api': '7.6.0-beta.2',
'@storybook/blocks': '7.6.0-beta.2',
'@storybook/builder-manager': '7.6.0-beta.2',
'@storybook/builder-vite': '7.6.0-beta.2',
'@storybook/builder-webpack5': '7.6.0-beta.2',
- '@storybook/channel-postmessage': '7.6.0-beta.2',
- '@storybook/channel-websocket': '7.6.0-beta.2',
'@storybook/channels': '7.6.0-beta.2',
'@storybook/cli': '7.6.0-beta.2',
- '@storybook/client-api': '7.6.0-beta.2',
'@storybook/client-logger': '7.6.0-beta.2',
'@storybook/codemod': '7.6.0-beta.2',
'@storybook/components': '7.6.0-beta.2',
- '@storybook/core-client': '7.6.0-beta.2',
'@storybook/core-common': '7.6.0-beta.2',
'@storybook/core-events': '7.6.0-beta.2',
'@storybook/core-server': '7.6.0-beta.2',
@@ -66,7 +58,6 @@ export default {
'@storybook/preset-web-components-webpack': '7.6.0-beta.2',
'@storybook/preview': '7.6.0-beta.2',
'@storybook/preview-api': '7.6.0-beta.2',
- '@storybook/preview-web': '7.6.0-beta.2',
'@storybook/react': '7.6.0-beta.2',
'@storybook/react-dom-shim': '7.6.0-beta.2',
'@storybook/react-vite': '7.6.0-beta.2',
@@ -75,12 +66,12 @@ export default {
'@storybook/server': '7.6.0-beta.2',
'@storybook/server-webpack5': '7.6.0-beta.2',
'@storybook/source-loader': '7.6.0-beta.2',
- '@storybook/store': '7.6.0-beta.2',
'@storybook/svelte': '7.6.0-beta.2',
'@storybook/svelte-vite': '7.6.0-beta.2',
'@storybook/svelte-webpack5': '7.6.0-beta.2',
'@storybook/sveltekit': '7.6.0-beta.2',
'@storybook/telemetry': '7.6.0-beta.2',
+ '@storybook/test': '7.6.0-beta.2',
'@storybook/theming': '7.6.0-beta.2',
'@storybook/types': '7.6.0-beta.2',
'@storybook/vue': '7.6.0-beta.2',
diff --git a/code/lib/client-logger/package.json b/code/lib/client-logger/package.json
index fb6ce245c092..6553c5f0ff20 100644
--- a/code/lib/client-logger/package.json
+++ b/code/lib/client-logger/package.json
@@ -47,7 +47,7 @@
"@storybook/global": "^5.0.0"
},
"devDependencies": {
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/lib/codemod/package.json b/code/lib/codemod/package.json
index fe880a95862b..44b58b17eb90 100644
--- a/code/lib/codemod/package.json
+++ b/code/lib/codemod/package.json
@@ -77,7 +77,7 @@
"remark": "^14.0.2",
"remark-mdx": "^2.3.0",
"ts-dedent": "^2.2.0",
- "typescript": "~4.9.3",
+ "typescript": "^5.3.2",
"unist-util-is": "^5.2.0",
"unist-util-select": "^4.0.3",
"unist-util-visit": "^4.1.2",
diff --git a/code/lib/core-common/package.json b/code/lib/core-common/package.json
index 8e8ebb05b6b0..a1955d133247 100644
--- a/code/lib/core-common/package.json
+++ b/code/lib/core-common/package.json
@@ -75,7 +75,7 @@
"mock-fs": "^5.2.0",
"slash": "^5.0.0",
"type-fest": "~2.19",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/lib/core-common/src/presets.ts b/code/lib/core-common/src/presets.ts
index 407ff1775d3c..7555a90b9eb4 100644
--- a/code/lib/core-common/src/presets.ts
+++ b/code/lib/core-common/src/presets.ts
@@ -9,7 +9,7 @@ import type {
LoadOptions,
PresetConfig,
Presets,
- StorybookConfig,
+ StorybookConfigRaw,
} from '@storybook/types';
import { join, parse } from 'path';
import { CriticalPresetLoadError } from '@storybook/core-events/server-errors';
@@ -21,7 +21,7 @@ import { stripAbsNodeModulesPath } from './utils/strip-abs-node-modules-path';
type InterPresetOptions = Omit<
CLIOptions &
LoadOptions &
- BuilderOptions & { isCritical?: boolean; build?: StorybookConfig['build'] },
+ BuilderOptions & { isCritical?: boolean; build?: StorybookConfigRaw['build'] },
'frameworkPresets'
>;
@@ -404,7 +404,7 @@ export async function loadAllPresets(
overridePresets: PresetConfig[];
/** Whether preset failures should be critical or not */
isCritical?: boolean;
- build?: StorybookConfig['build'];
+ build?: StorybookConfigRaw['build'];
}
) {
const { corePresets = [], overridePresets = [], ...restOptions } = options;
diff --git a/code/lib/core-common/src/utils/get-renderer-name.ts b/code/lib/core-common/src/utils/get-renderer-name.ts
index 35131f5e0090..ce4a14891086 100644
--- a/code/lib/core-common/src/utils/get-renderer-name.ts
+++ b/code/lib/core-common/src/utils/get-renderer-name.ts
@@ -5,13 +5,13 @@ import { getFrameworkName } from './get-framework-name';
* Render is set as a string on core. It must be set by the framework
*/
export async function getRendererName(options: Options) {
- const { renderer } = await options.presets.apply('core', {}, options);
+ const core = await options.presets.apply('core', {}, options);
- if (!renderer) {
+ if (!core || !core.renderer) {
// At the moment some frameworks (Angular/Ember) do not define a renderer, but themselves
// serve the purpose (in particular exporting the symbols needed by entrypoints)
return getFrameworkName(options);
}
- return renderer;
+ return core.renderer;
}
diff --git a/code/lib/core-common/src/utils/paths.ts b/code/lib/core-common/src/utils/paths.ts
index ad8f3f7124af..3895a69dd2b1 100644
--- a/code/lib/core-common/src/utils/paths.ts
+++ b/code/lib/core-common/src/utils/paths.ts
@@ -3,6 +3,11 @@ import findUp from 'find-up';
export const getProjectRoot = () => {
let result;
+ // Allow manual override in cases where auto-detect doesn't work
+ if (process.env.STORYBOOK_PROJECT_ROOT) {
+ return process.env.STORYBOOK_PROJECT_ROOT;
+ }
+
try {
const found = findUp.sync('.git', { type: 'directory' });
if (found) {
@@ -19,6 +24,14 @@ export const getProjectRoot = () => {
} catch (e) {
//
}
+ try {
+ const found = findUp.sync('.hg', { type: 'directory' });
+ if (found) {
+ result = result || path.join(found, '..');
+ }
+ } catch (e) {
+ //
+ }
try {
const found = findUp.sync('.yarn', { type: 'directory' });
if (found) {
diff --git a/code/lib/core-events/package.json b/code/lib/core-events/package.json
index 2b7192e57b8c..c74e13d26c26 100644
--- a/code/lib/core-events/package.json
+++ b/code/lib/core-events/package.json
@@ -81,7 +81,7 @@
"ts-dedent": "^2.0.0"
},
"devDependencies": {
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/lib/core-server/package.json b/code/lib/core-server/package.json
index ff4af21db038..8f4571e5a0d6 100644
--- a/code/lib/core-server/package.json
+++ b/code/lib/core-server/package.json
@@ -113,7 +113,7 @@
"jest-specific-snapshot": "^8.0.0",
"node-fetch": "^3.3.1",
"slash": "^5.0.0",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/lib/core-server/src/build-dev.ts b/code/lib/core-server/src/build-dev.ts
index 96bbc120fc7f..186a1a6fc47b 100644
--- a/code/lib/core-server/src/build-dev.ts
+++ b/code/lib/core-server/src/build-dev.ts
@@ -1,11 +1,4 @@
-import type {
- BuilderOptions,
- CLIOptions,
- CoreConfig,
- LoadOptions,
- Options,
- StorybookConfig,
-} from '@storybook/types';
+import type { BuilderOptions, CLIOptions, LoadOptions, Options } from '@storybook/types';
import {
loadAllPresets,
loadMainConfig,
@@ -97,7 +90,7 @@ export async function buildDevStandalone(
isCritical: true,
});
- const { renderer, builder, disableTelemetry } = await presets.apply('core', {});
+ const { renderer, builder, disableTelemetry } = await presets.apply('core', {});
if (!builder) {
throw new MissingBuilderError();
@@ -152,7 +145,7 @@ export async function buildDevStandalone(
...options,
});
- const features = await presets.apply('features');
+ const features = await presets.apply('features');
global.FEATURES = features;
const fullOptions: Options = {
diff --git a/code/lib/core-server/src/build-static.ts b/code/lib/core-server/src/build-static.ts
index cde136c47413..020b9060af6a 100644
--- a/code/lib/core-server/src/build-static.ts
+++ b/code/lib/core-server/src/build-static.ts
@@ -4,15 +4,7 @@ import { dirname, isAbsolute, join, resolve } from 'path';
import { global } from '@storybook/global';
import { deprecate, logger } from '@storybook/node-logger';
import { getPrecedingUpgrade, telemetry } from '@storybook/telemetry';
-import type {
- BuilderOptions,
- CLIOptions,
- CoreConfig,
- DocsOptions,
- LoadOptions,
- Options,
- StorybookConfig,
-} from '@storybook/types';
+import type { BuilderOptions, CLIOptions, LoadOptions, Options } from '@storybook/types';
import {
loadAllPresets,
loadMainConfig,
@@ -90,7 +82,7 @@ export async function buildStaticStandalone(options: BuildStaticStandaloneOption
...options,
});
- const { renderer } = await presets.apply('core', {});
+ const { renderer } = await presets.apply('core', {});
const build = await presets.apply('build', {});
const [previewBuilder, managerBuilder] = await getBuilders({ ...options, presets, build });
@@ -116,13 +108,13 @@ export async function buildStaticStandalone(options: BuildStaticStandaloneOption
const [features, core, staticDirs, indexers, deprecatedStoryIndexers, stories, docsOptions] =
await Promise.all([
- presets.apply('features'),
- presets.apply('core'),
- presets.apply('staticDirs'),
+ presets.apply('features'),
+ presets.apply('core'),
+ presets.apply('staticDirs'),
presets.apply('experimental_indexers', []),
presets.apply('storyIndexers', []),
presets.apply('stories'),
- presets.apply('docs', {}),
+ presets.apply('docs', {}),
]);
if (features?.storyStoreV7 === false) {
diff --git a/code/lib/core-server/src/dev-server.ts b/code/lib/core-server/src/dev-server.ts
index 1e8de546880e..682937e367b0 100644
--- a/code/lib/core-server/src/dev-server.ts
+++ b/code/lib/core-server/src/dev-server.ts
@@ -2,7 +2,7 @@ import express from 'express';
import compression from 'compression';
import invariant from 'tiny-invariant';
-import type { CoreConfig, Options, StorybookConfig } from '@storybook/types';
+import type { Options } from '@storybook/types';
import { logConfig } from '@storybook/core-common';
import { deprecate, logger } from '@storybook/node-logger';
@@ -29,8 +29,8 @@ export async function storybookDevServer(options: Options) {
const [server, features, core] = await Promise.all([
getServer(app, options),
- options.presets.apply('features'),
- options.presets.apply('core'),
+ options.presets.apply('features'),
+ options.presets.apply('core'),
]);
const serverChannel = await options.presets.apply(
diff --git a/code/lib/core-server/src/presets/common-override-preset.ts b/code/lib/core-server/src/presets/common-override-preset.ts
index 8cc740aea7d7..1680b5b146cd 100644
--- a/code/lib/core-server/src/presets/common-override-preset.ts
+++ b/code/lib/core-server/src/presets/common-override-preset.ts
@@ -1,7 +1,7 @@
-import type { Options, PresetProperty, StorybookConfig, TestBuildFlags } from '@storybook/types';
+import type { PresetProperty, TestBuildFlags } from '@storybook/types';
import { removeMDXEntries } from '../utils/remove-mdx-entries';
-export const framework: PresetProperty<'framework', StorybookConfig> = async (config) => {
+export const framework: PresetProperty<'framework'> = async (config) => {
// This will get called with the values from the user's main config, but before
// framework preset from framework packages e.g. react-webpack5 gets called.
// This means we can add default values to the framework config, before it's requested by other packages.
@@ -14,21 +14,21 @@ export const framework: PresetProperty<'framework', StorybookConfig> = async (co
};
};
-export const stories: PresetProperty<'stories', StorybookConfig> = async (entries, options) => {
+export const stories: PresetProperty<'stories'> = async (entries, options) => {
if (options?.build?.test?.disableMDXEntries) {
return removeMDXEntries(entries, options);
}
return entries;
};
-export const typescript: PresetProperty<'typescript', StorybookConfig> = async (input, options) => {
+export const typescript: PresetProperty<'typescript'> = async (input, options) => {
if (options?.build?.test?.disableDocgen) {
return { ...(input ?? {}), reactDocgen: false, check: false };
}
return input;
};
-export const docs: PresetProperty<'docs', StorybookConfig> = async (input, options) => {
+export const docs: PresetProperty<'docs'> = async (input, options) => {
if (options?.build?.test?.disableAutoDocs) {
return {};
}
@@ -37,7 +37,9 @@ export const docs: PresetProperty<'docs', StorybookConfig> = async (input, optio
const createTestBuildFeatures = (value: boolean): Required => ({
disableBlocks: value,
- disabledAddons: value ? ['@storybook/addon-docs', '@storybook/addon-coverage'] : [],
+ disabledAddons: value
+ ? ['@storybook/addon-docs', '@storybook/addon-essentials/docs', '@storybook/addon-coverage']
+ : [],
disableMDXEntries: value,
disableAutoDocs: value,
disableDocgen: value,
@@ -46,7 +48,7 @@ const createTestBuildFeatures = (value: boolean): Required => ({
esbuildMinify: value,
});
-export const build = async (value: StorybookConfig['build'], options: Options) => {
+export const build: PresetProperty<'build'> = async (value, options) => {
return {
...value,
test: {
diff --git a/code/lib/core-server/src/presets/common-preset.ts b/code/lib/core-server/src/presets/common-preset.ts
index 9512038cc3cb..3ea66c25743a 100644
--- a/code/lib/core-server/src/presets/common-preset.ts
+++ b/code/lib/core-server/src/presets/common-preset.ts
@@ -14,7 +14,7 @@ import type {
Indexer,
Options,
PresetPropertyFn,
- StorybookConfig,
+ PresetProperty,
} from '@storybook/types';
import { printConfig, readConfig, readCsf } from '@storybook/csf-tools';
import { join, isAbsolute } from 'path';
@@ -51,7 +51,7 @@ export const favicon = async (
if (value) {
return value;
}
- const staticDirsValue = await options.presets.apply('staticDirs');
+ const staticDirsValue = await options.presets.apply('staticDirs');
const statics = staticDirsValue
? staticDirsValue.map((dir) => (typeof dir === 'string' ? dir : `${dir.from}:${dir.to}`))
@@ -185,9 +185,7 @@ export const previewAnnotations = async (base: any, options: Options) => {
return [...config, ...base];
};
-export const features = async (
- existing: StorybookConfig['features']
-): Promise => ({
+export const features: PresetProperty<'features'> = async (existing) => ({
...existing,
warnOnLegacyHierarchySeparator: true,
buildStoriesJson: false,
@@ -203,14 +201,14 @@ export const csfIndexer: Indexer = {
};
// eslint-disable-next-line @typescript-eslint/naming-convention
-export const experimental_indexers: StorybookConfig['experimental_indexers'] = (existingIndexers) =>
+export const experimental_indexers: PresetProperty<'experimental_indexers'> = (existingIndexers) =>
[csfIndexer].concat(existingIndexers || []);
export const frameworkOptions = async (
_: never,
options: Options
): Promise | null> => {
- const config = await options.presets.apply('framework');
+ const config = await options.presets.apply('framework');
if (typeof config === 'string') {
return {};
@@ -223,10 +221,7 @@ export const frameworkOptions = async (
return config.options;
};
-export const docs = (
- docsOptions: StorybookConfig['docs'],
- { docs: docsMode }: CLIOptions
-): StorybookConfig['docs'] =>
+export const docs: PresetProperty<'docs'> = (docsOptions, { docs: docsMode }: CLIOptions) =>
docsOptions && docsMode !== undefined
? {
...docsOptions,
diff --git a/code/lib/core-server/src/typings.d.ts b/code/lib/core-server/src/typings.d.ts
index 7ebf6a02c0b4..597bae6cdc17 100644
--- a/code/lib/core-server/src/typings.d.ts
+++ b/code/lib/core-server/src/typings.d.ts
@@ -6,4 +6,4 @@ declare module '@aw-web-design/x-default-browser';
declare module '@discoveryjs/json-ext';
declare module 'watchpack';
-declare var FEATURES: import('@storybook/types').StorybookConfig['features'];
+declare var FEATURES: import('@storybook/types').StorybookConfigRaw['features'];
diff --git a/code/lib/core-server/src/utils/StoryIndexGenerator.ts b/code/lib/core-server/src/utils/StoryIndexGenerator.ts
index f77d11c8ef3c..fc0f38aa8833 100644
--- a/code/lib/core-server/src/utils/StoryIndexGenerator.ts
+++ b/code/lib/core-server/src/utils/StoryIndexGenerator.ts
@@ -22,7 +22,7 @@ import type {
Indexer,
IndexerOptions,
DeprecatedIndexer,
- StorybookConfig,
+ StorybookConfigRaw,
} from '@storybook/types';
import { userOrAutoTitleFromSpecifier, sortStoriesV7 } from '@storybook/preview-api';
import { commonGlobOptions, normalizeStoryPath } from '@storybook/core-common';
@@ -59,7 +59,7 @@ export type StoryIndexGeneratorOptions = {
storyIndexers: StoryIndexer[];
indexers: Indexer[];
docs: DocsOptions;
- build?: StorybookConfig['build'];
+ build?: StorybookConfigRaw['build'];
};
export const AUTODOCS_TAG = 'autodocs';
diff --git a/code/lib/core-server/src/utils/get-builders.ts b/code/lib/core-server/src/utils/get-builders.ts
index 542492a4c683..9d6535559deb 100644
--- a/code/lib/core-server/src/utils/get-builders.ts
+++ b/code/lib/core-server/src/utils/get-builders.ts
@@ -1,4 +1,4 @@
-import type { Builder, CoreConfig, Options } from '@storybook/types';
+import type { Builder, Options } from '@storybook/types';
import { MissingBuilderError } from '@storybook/core-events/server-errors';
import { pathToFileURL } from 'node:url';
@@ -19,7 +19,7 @@ export async function getPreviewBuilder(
}
export async function getBuilders({ presets, configDir }: Options): Promise[]> {
- const { builder } = await presets.apply('core', {});
+ const { builder } = await presets.apply('core', {});
if (!builder) {
throw new MissingBuilderError();
diff --git a/code/lib/core-server/src/utils/server-statics.ts b/code/lib/core-server/src/utils/server-statics.ts
index ca0f8c55e354..386db92d143e 100644
--- a/code/lib/core-server/src/utils/server-statics.ts
+++ b/code/lib/core-server/src/utils/server-statics.ts
@@ -1,5 +1,5 @@
import { logger } from '@storybook/node-logger';
-import type { Options, StorybookConfig } from '@storybook/types';
+import type { Options } from '@storybook/types';
import { getDirectoryFromWorkingDir } from '@storybook/core-common';
import { ConflictingStaticDirConfigError } from '@storybook/core-events/server-errors';
import chalk from 'chalk';
@@ -13,8 +13,7 @@ import { dedent } from 'ts-dedent';
import { defaultStaticDirs } from './constants';
export async function useStatics(router: Router, options: Options) {
- const staticDirs =
- (await options.presets.apply('staticDirs')) ?? [];
+ const staticDirs = (await options.presets.apply('staticDirs')) ?? [];
const faviconPath = await options.presets.apply('favicon');
if (options.staticDir && !isEqual(staticDirs, defaultStaticDirs)) {
diff --git a/code/lib/core-server/src/withTelemetry.ts b/code/lib/core-server/src/withTelemetry.ts
index 0d78d5caafb7..aca04a2c417b 100644
--- a/code/lib/core-server/src/withTelemetry.ts
+++ b/code/lib/core-server/src/withTelemetry.ts
@@ -1,5 +1,5 @@
import prompts from 'prompts';
-import type { CLIOptions, CoreConfig } from '@storybook/types';
+import type { CLIOptions } from '@storybook/types';
import { loadAllPresets, cache } from '@storybook/core-common';
import { telemetry, getPrecedingUpgrade, oneWayHash } from '@storybook/telemetry';
import type { EventType } from '@storybook/telemetry';
@@ -46,7 +46,7 @@ export async function getErrorLevel({
// If the user has chosen to enable/disable crash reports in main.js
// or disabled telemetry, we can return that
- const core = await presets.apply('core');
+ const core = await presets.apply('core');
if (core?.enableCrashReports !== undefined) return core.enableCrashReports ? 'full' : 'error';
if (core?.disableTelemetry) return 'none';
diff --git a/code/lib/core-webpack/package.json b/code/lib/core-webpack/package.json
index 726ac8af6324..5739b56538d8 100644
--- a/code/lib/core-webpack/package.json
+++ b/code/lib/core-webpack/package.json
@@ -51,7 +51,8 @@
"ts-dedent": "^2.0.0"
},
"devDependencies": {
- "typescript": "~4.9.3",
+ "slash": "^5.1.0",
+ "typescript": "^5.3.2",
"webpack": "5"
},
"publishConfig": {
diff --git a/code/lib/core-webpack/src/types.ts b/code/lib/core-webpack/src/types.ts
index 1028c08a0a4d..aecd1ccc62e3 100644
--- a/code/lib/core-webpack/src/types.ts
+++ b/code/lib/core-webpack/src/types.ts
@@ -1,4 +1,4 @@
-import type { Options, StorybookConfig as StorybookConfigBase } from '@storybook/types';
+import type { Options, StorybookConfigRaw as StorybookConfigBase } from '@storybook/types';
export type { Options, Preset, BuilderResult, TypescriptOptions } from '@storybook/types';
diff --git a/code/lib/csf-plugin/package.json b/code/lib/csf-plugin/package.json
index 90099743de5f..24ea12df2e5c 100644
--- a/code/lib/csf-plugin/package.json
+++ b/code/lib/csf-plugin/package.json
@@ -48,7 +48,7 @@
"unplugin": "^1.3.1"
},
"devDependencies": {
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/lib/csf-tools/package.json b/code/lib/csf-tools/package.json
index f6e533a3dadc..97ff8346f0c9 100644
--- a/code/lib/csf-tools/package.json
+++ b/code/lib/csf-tools/package.json
@@ -56,7 +56,7 @@
"@types/fs-extra": "^11.0.1",
"@types/js-yaml": "^4.0.5",
"js-yaml": "^4.1.0",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/lib/csf-tools/src/CsfFile.ts b/code/lib/csf-tools/src/CsfFile.ts
index 15ab39abdc45..897f6b2e0b0d 100644
--- a/code/lib/csf-tools/src/CsfFile.ts
+++ b/code/lib/csf-tools/src/CsfFile.ts
@@ -117,7 +117,7 @@ export class NoMetaError extends Error {
super(dedent`
CSF: ${message} ${formatLocation(ast, fileName)}
- More info: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
+ More info: https://storybook.js.org/docs/react/writing-stories#default-export
`);
this.name = this.constructor.name;
}
@@ -481,7 +481,7 @@ export class CsfFile {
throw new Error(dedent`
CSF: missing title/component ${formatLocation(self._ast, self._fileName)}
- More info: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
+ More info: https://storybook.js.org/docs/react/writing-stories#default-export
`);
}
diff --git a/code/lib/docs-tools/package.json b/code/lib/docs-tools/package.json
index 02e7168609d7..387cf68c90a3 100644
--- a/code/lib/docs-tools/package.json
+++ b/code/lib/docs-tools/package.json
@@ -57,7 +57,7 @@
"babel-plugin-react-docgen": "4.2.1",
"jest-specific-snapshot": "^8.0.0",
"require-from-string": "^2.0.2",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/lib/instrumenter/README.md b/code/lib/instrumenter/README.md
index 74fe933067d9..9f0227e0c913 100644
--- a/code/lib/instrumenter/README.md
+++ b/code/lib/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/testing-library`):
+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/lib/instrumenter/package.json b/code/lib/instrumenter/package.json
index f72a50e5531d..5b3d313951ef 100644
--- a/code/lib/instrumenter/package.json
+++ b/code/lib/instrumenter/package.json
@@ -53,7 +53,7 @@
"util": "^0.12.4"
},
"devDependencies": {
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/lib/instrumenter/src/typings.d.ts b/code/lib/instrumenter/src/typings.d.ts
index cde68861ee72..63361b8ef85b 100644
--- a/code/lib/instrumenter/src/typings.d.ts
+++ b/code/lib/instrumenter/src/typings.d.ts
@@ -1,6 +1,6 @@
/* eslint-disable no-underscore-dangle, @typescript-eslint/naming-convention */
-declare var FEATURES: import('@storybook/types').StorybookConfig['features'];
+declare var FEATURES: import('@storybook/types').StorybookConfigRaw['features'];
declare var __STORYBOOK_PREVIEW__: any;
declare var __STORYBOOK_ADDON_INTERACTIONS_INSTRUMENTER_STATE__: any;
diff --git a/code/lib/manager-api/package.json b/code/lib/manager-api/package.json
index 4332917c4866..e3138a8e3fdb 100644
--- a/code/lib/manager-api/package.json
+++ b/code/lib/manager-api/package.json
@@ -65,9 +65,9 @@
"@types/qs": "^6",
"flush-promises": "^1.0.2",
"qs": "^6.10.0",
- "react": "^16.8.0",
- "react-dom": "^16.8.0",
- "typescript": "~4.9.3"
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/lib/manager-api/src/index.tsx b/code/lib/manager-api/src/index.tsx
index d44b49002ca7..d110a8b1901e 100644
--- a/code/lib/manager-api/src/index.tsx
+++ b/code/lib/manager-api/src/index.tsx
@@ -135,7 +135,7 @@ export interface Combo {
export type ManagerProviderProps = RouterData &
API_ProviderData & {
- children: ReactNode | ((props: Combo) => ReactNode);
+ children: ReactNode | FC;
};
// This is duplicated from @storybook/preview-api for the reasons mentioned in lib-addons/types.js
@@ -169,7 +169,11 @@ class ManagerProvider extends Component {
const store = new Store({
getState: () => this.state,
- setState: (stateChange: Partial, callback) => this.setState(stateChange, callback),
+ setState: (stateChange: Partial, callback) => {
+ this.setState(stateChange, () => callback(this.state));
+
+ return this.state;
+ },
});
const routeData = { location, path, viewMode, singleStory, storyId, refId };
@@ -290,7 +294,7 @@ function ManagerConsumer({
filter = defaultFilter,
children,
}: ManagerConsumerProps
): ReactElement {
- const c = useContext(ManagerContext);
+ const managerContext = useContext(ManagerContext);
const renderer = useRef(children);
const filterer = useRef(filter);
@@ -298,17 +302,17 @@ function ManagerConsumer
({
return {renderer.current} ;
}
- const data = filterer.current(c);
+ const comboData = filterer.current(managerContext);
- const l = useMemo(() => {
- return [...Object.entries(data).reduce((acc, keyval) => acc.concat(keyval), [])];
- }, [c.state]);
+ const comboDataArray = useMemo(() => {
+ return [...Object.entries(comboData).reduce((acc, keyval) => acc.concat(keyval), [])];
+ }, [managerContext.state]);
return useMemo(() => {
const Child = renderer.current as FC
;
- return ;
- }, l);
+ return ;
+ }, comboDataArray);
}
export function useStorybookState(): State {
@@ -413,7 +417,9 @@ export function useSharedState(stateId: string, defaultState?: S) {
}, [quicksync]);
const setState = async (s: S | API_StateMerger, options?: Options) => {
- const result = await api.setAddonState(stateId, s, options);
+ await api.setAddonState(stateId, s, options);
+ const result = api.getAddonState(stateId);
+
STORYBOOK_ADDON_STATE[stateId] = result;
return result;
};
@@ -459,7 +465,8 @@ export function useSharedState(stateId: string, defaultState?: S) {
return [
state,
async (newStateOrMerger: S | API_StateMerger, options?: Options) => {
- const result = await setState(newStateOrMerger, options);
+ await setState(newStateOrMerger, options);
+ const result = api.getAddonState(stateId);
emit(`${SHARED_STATE_CHANGED}-manager-${stateId}`, result);
},
] as [S, (newStateOrMerger: S | API_StateMerger, options?: Options) => void];
diff --git a/code/lib/manager-api/src/lib/stories.ts b/code/lib/manager-api/src/lib/stories.ts
index b48cbd51b877..c3c40ce513ed 100644
--- a/code/lib/manager-api/src/lib/stories.ts
+++ b/code/lib/manager-api/src/lib/stories.ts
@@ -49,7 +49,7 @@ export const transformSetStoriesStoryDataToStoriesHash = (
) =>
transformStoryIndexToStoriesHash(transformSetStoriesStoryDataToPreparedStoryIndex(data), options);
-const transformSetStoriesStoryDataToPreparedStoryIndex = (
+export const transformSetStoriesStoryDataToPreparedStoryIndex = (
stories: SetStoriesStoryData
): API_PreparedStoryIndex => {
const entries: API_PreparedStoryIndex['entries'] = Object.entries(stories).reduce(
diff --git a/code/lib/manager-api/src/modules/addons.ts b/code/lib/manager-api/src/modules/addons.ts
index 4f618a23b7ff..15e265cb184c 100644
--- a/code/lib/manager-api/src/modules/addons.ts
+++ b/code/lib/manager-api/src/modules/addons.ts
@@ -133,16 +133,14 @@ export const init: ModuleFn = ({ provider, store, fullAPI }) =
newStateOrMerger: S | API_StateMerger,
options?: Options
): Promise {
- let nextState;
- const { addons: existing } = store.getState();
- if (typeof newStateOrMerger === 'function') {
- const merger = newStateOrMerger as API_StateMerger;
- nextState = merger(api.getAddonState(addonId));
- } else {
- nextState = newStateOrMerger;
- }
+ const merger = (
+ typeof newStateOrMerger === 'function' ? newStateOrMerger : () => newStateOrMerger
+ ) as API_StateMerger;
return store
- .setState({ addons: { ...existing, [addonId]: nextState } }, options)
+ .setState(
+ (s) => ({ ...s, addons: { ...s.addons, [addonId]: merger(s.addons[addonId]) } }),
+ options
+ )
.then(() => api.getAddonState(addonId));
},
getAddonState: (addonId) => {
diff --git a/code/lib/manager-api/src/modules/layout.ts b/code/lib/manager-api/src/modules/layout.ts
index f37e51e19942..a7d529868613 100644
--- a/code/lib/manager-api/src/modules/layout.ts
+++ b/code/lib/manager-api/src/modules/layout.ts
@@ -56,20 +56,43 @@ export interface SubAPI {
* @param options - An object containing the options to set.
*/
setOptions: (options: any) => void;
+ /**
+ * Sets the sizes of the resizable elements in the layout.
+ */
+ setSizes: (
+ options: Partial>
+ ) => void;
+ /**
+ * getIsFullscreen - Returns the current fullscreen mode of the Storybook UI.
+ */
+ getIsFullscreen: () => boolean;
+ /**
+ * getIsPanelShown - Returns the current visibility of the panel in the Storybook UI.
+ */
+ getIsPanelShown: () => boolean;
+ /**
+ * getIsNavShown - Returns the current visibility of the navigation bar in the Storybook UI.
+ */
+ getIsNavShown: () => boolean;
}
type PartialSubState = Partial;
-const defaultState: SubState = {
+export const defaultLayoutState: SubState = {
ui: {
enableShortcuts: true,
},
layout: {
initialActive: ActiveTabs.CANVAS,
showToolbar: true,
- isFullscreen: false,
- showPanel: true,
- showNav: true,
+ navSize: 300,
+ bottomPanelHeight: 300,
+ rightPanelWidth: 400,
+ recentVisibleSizes: {
+ navSize: 300,
+ bottomPanelHeight: 300,
+ rightPanelWidth: 400,
+ },
panelPosition: 'bottom',
showTabs: true,
},
@@ -83,88 +106,150 @@ export const focusableUIElements = {
storyPanelRoot: 'storybook-panel-root',
};
-export const init: ModuleFn = ({ store, provider, singleStory, fullAPI }) => {
+const getIsNavShown = (state: State) => {
+ return state.layout.navSize > 0;
+};
+const getIsPanelShown = (state: State) => {
+ const { bottomPanelHeight, rightPanelWidth, panelPosition } = state.layout;
+
+ return (
+ (panelPosition === 'bottom' && bottomPanelHeight > 0) ||
+ (panelPosition === 'right' && rightPanelWidth > 0)
+ );
+};
+const getIsFullscreen = (state: State) => {
+ return !getIsNavShown(state) && !getIsPanelShown(state);
+};
+
+const getRecentVisibleSizes = (layoutState: API_Layout) => {
+ return {
+ navSize: layoutState.navSize > 0 ? layoutState.navSize : layoutState.recentVisibleSizes.navSize,
+ bottomPanelHeight:
+ layoutState.bottomPanelHeight > 0
+ ? layoutState.bottomPanelHeight
+ : layoutState.recentVisibleSizes.bottomPanelHeight,
+ rightPanelWidth:
+ layoutState.rightPanelWidth > 0
+ ? layoutState.rightPanelWidth
+ : layoutState.recentVisibleSizes.rightPanelWidth,
+ };
+};
+
+export const init: ModuleFn = ({ store, provider, singleStory }) => {
const api = {
- toggleFullscreen(toggled?: boolean) {
+ toggleFullscreen(nextState?: boolean) {
return store.setState(
(state: State) => {
- const { showNav } = state.layout;
-
- const value = typeof toggled === 'boolean' ? toggled : !state.layout.isFullscreen;
- const shouldShowNav = showNav === false && value === false;
-
- return {
- layout: {
- ...state.layout,
- isFullscreen: value,
- showNav: !singleStory && shouldShowNav ? true : showNav,
- },
- };
+ const isFullscreen = getIsFullscreen(state);
+ const shouldFullscreen = typeof nextState === 'boolean' ? nextState : !isFullscreen;
+
+ if (shouldFullscreen === isFullscreen) {
+ return { layout: state.layout };
+ }
+
+ return shouldFullscreen
+ ? {
+ layout: {
+ ...state.layout,
+ navSize: 0,
+ bottomPanelHeight: 0,
+ rightPanelWidth: 0,
+ recentVisibleSizes: getRecentVisibleSizes(state.layout),
+ },
+ }
+ : {
+ layout: {
+ ...state.layout,
+ navSize: state.singleStory ? 0 : state.layout.recentVisibleSizes.navSize,
+ bottomPanelHeight: state.layout.recentVisibleSizes.bottomPanelHeight,
+ rightPanelWidth: state.layout.recentVisibleSizes.rightPanelWidth,
+ },
+ };
},
{ persistence: 'session' }
);
},
- togglePanel(toggled?: boolean) {
+ togglePanel(nextState?: boolean) {
return store.setState(
(state: State) => {
- const { showNav, isFullscreen } = state.layout;
-
- const value = typeof toggled !== 'undefined' ? toggled : !state.layout.showPanel;
- const shouldToggleFullScreen = showNav === false && value === false;
-
- return {
- layout: {
- ...state.layout,
- showPanel: value,
- isFullscreen: shouldToggleFullScreen ? true : isFullscreen,
- },
- };
+ const isPanelShown = getIsPanelShown(state);
+
+ const shouldShowPanel = typeof nextState === 'boolean' ? nextState : !isPanelShown;
+
+ if (shouldShowPanel === isPanelShown) {
+ return { layout: state.layout };
+ }
+
+ return shouldShowPanel
+ ? {
+ layout: {
+ ...state.layout,
+ bottomPanelHeight: state.layout.recentVisibleSizes.bottomPanelHeight,
+ rightPanelWidth: state.layout.recentVisibleSizes.rightPanelWidth,
+ },
+ }
+ : {
+ layout: {
+ ...state.layout,
+ bottomPanelHeight: 0,
+ rightPanelWidth: 0,
+ recentVisibleSizes: getRecentVisibleSizes(state.layout),
+ },
+ };
},
{ persistence: 'session' }
);
},
togglePanelPosition(position?: 'bottom' | 'right') {
- if (typeof position !== 'undefined') {
- return store.setState(
- (state: State) => ({
+ return store.setState(
+ (state: State) => {
+ const nextPosition =
+ position || (state.layout.panelPosition === 'right' ? 'bottom' : 'right');
+
+ return {
layout: {
...state.layout,
- panelPosition: position,
+ panelPosition: nextPosition,
+ bottomPanelHeight: state.layout.recentVisibleSizes.bottomPanelHeight,
+ rightPanelWidth: state.layout.recentVisibleSizes.rightPanelWidth,
},
- }),
- { persistence: 'permanent' }
- );
- }
-
- return store.setState(
- (state: State) => ({
- layout: {
- ...state.layout,
- panelPosition: state.layout.panelPosition === 'right' ? 'bottom' : 'right',
- },
- }),
+ };
+ },
{ persistence: 'permanent' }
);
},
- toggleNav(toggled?: boolean) {
+ toggleNav(nextState?: boolean) {
return store.setState(
(state: State) => {
- if (singleStory) return { layout: state.layout };
-
- const { showPanel, isFullscreen } = state.layout;
- const showNav = typeof toggled !== 'undefined' ? toggled : !state.layout.showNav;
- const shouldToggleFullScreen = showPanel === false && showNav === false;
-
- return {
- layout: {
- ...state.layout,
- showNav,
- isFullscreen: shouldToggleFullScreen ? true : !showNav && isFullscreen,
- },
- };
+ if (state.singleStory) {
+ return { layout: state.layout };
+ }
+
+ const isNavShown = getIsNavShown(state);
+
+ const shouldShowNav = typeof nextState === 'boolean' ? nextState : !isNavShown;
+
+ if (shouldShowNav === isNavShown) {
+ return { layout: state.layout };
+ }
+
+ return shouldShowNav
+ ? {
+ layout: {
+ ...state.layout,
+ navSize: state.layout.recentVisibleSizes.navSize,
+ },
+ }
+ : {
+ layout: {
+ ...state.layout,
+ navSize: 0,
+ recentVisibleSizes: getRecentVisibleSizes(state.layout),
+ },
+ };
},
{ persistence: 'session' }
);
@@ -186,15 +271,23 @@ export const init: ModuleFn = ({ store, provider, singleStory, fullAPI }) => {
);
},
- resetLayout() {
+ setSizes({
+ navSize,
+ bottomPanelHeight,
+ rightPanelWidth,
+ }: Partial>) {
return store.setState(
(state: State) => {
+ const nextLayoutState = {
+ ...state.layout,
+ navSize: navSize ?? state.layout.navSize,
+ bottomPanelHeight: bottomPanelHeight ?? state.layout.bottomPanelHeight,
+ rightPanelWidth: rightPanelWidth ?? state.layout.rightPanelWidth,
+ };
return {
layout: {
- ...state.layout,
- showNav: false,
- showPanel: false,
- isFullscreen: false,
+ ...nextLayoutState,
+ recentVisibleSizes: getRecentVisibleSizes(nextLayoutState),
},
};
},
@@ -219,75 +312,85 @@ export const init: ModuleFn = ({ store, provider, singleStory, fullAPI }) => {
const { theme, selectedPanel, ...options } = provider.getConfig();
return {
- ...defaultState,
+ ...defaultLayoutState,
layout: {
- ...defaultState.layout,
- ...pick(options, Object.keys(defaultState.layout)),
- ...(singleStory && { showNav: false }),
+ ...defaultLayoutState.layout,
+ ...pick(options, Object.keys(defaultLayoutState.layout)),
+ ...(singleStory && { navSize: 0 }),
},
ui: {
- ...defaultState.ui,
- ...pick(options, Object.keys(defaultState.ui)),
+ ...defaultLayoutState.ui,
+ ...pick(options, Object.keys(defaultLayoutState.ui)),
},
- selectedPanel: selectedPanel || defaultState.selectedPanel,
- theme: theme || defaultState.theme,
+ selectedPanel: selectedPanel || defaultLayoutState.selectedPanel,
+ theme: theme || defaultLayoutState.theme,
};
},
+ getIsFullscreen() {
+ return getIsFullscreen(store.getState());
+ },
+ getIsPanelShown() {
+ return getIsPanelShown(store.getState());
+ },
+ getIsNavShown() {
+ return getIsNavShown(store.getState());
+ },
+
setOptions: (options: any) => {
const { layout, ui, selectedPanel, theme } = store.getState();
- if (options) {
- const updatedLayout = {
- ...layout,
- ...options.layout,
- ...pick(options, Object.keys(layout)),
- ...(singleStory && { showNav: false }),
- };
-
- const updatedUi = {
- ...ui,
- ...options.ui,
- ...pick(options, Object.keys(ui)),
- };
-
- const updatedTheme = {
- ...theme,
- ...options.theme,
- };
-
- const modification: PartialSubState = {};
-
- if (!deepEqual(ui, updatedUi)) {
- modification.ui = updatedUi;
- }
- if (!deepEqual(layout, updatedLayout)) {
- modification.layout = updatedLayout;
- }
- if (options.selectedPanel && !deepEqual(selectedPanel, options.selectedPanel)) {
- modification.selectedPanel = options.selectedPanel;
- }
+ if (!options) {
+ return;
+ }
- if (Object.keys(modification).length) {
- store.setState(modification, { persistence: 'permanent' });
- }
- if (!deepEqual(theme, updatedTheme)) {
- store.setState({ theme: updatedTheme });
- }
+ const updatedLayout = {
+ ...layout,
+ ...options.layout,
+ ...pick(options, Object.keys(layout)),
+ ...(singleStory && { navSize: 0 }),
+ };
+
+ const updatedUi = {
+ ...ui,
+ ...options.ui,
+ ...pick(options, Object.keys(ui)),
+ };
+
+ const updatedTheme = {
+ ...theme,
+ ...options.theme,
+ };
+
+ const modification: PartialSubState = {};
+
+ if (!deepEqual(ui, updatedUi)) {
+ modification.ui = updatedUi;
+ }
+ if (!deepEqual(layout, updatedLayout)) {
+ modification.layout = updatedLayout;
+ }
+ if (options.selectedPanel && !deepEqual(selectedPanel, options.selectedPanel)) {
+ modification.selectedPanel = options.selectedPanel;
+ }
+
+ if (Object.keys(modification).length) {
+ store.setState(modification, { persistence: 'permanent' });
+ }
+ if (!deepEqual(theme, updatedTheme)) {
+ store.setState({ theme: updatedTheme });
}
},
};
const persisted = pick(store.getState(), 'layout', 'selectedPanel');
+ provider.channel.on(SET_CONFIG, () => {
+ api.setOptions(merge(api.getInitialOptions(), persisted));
+ });
+
return {
api,
state: merge(api.getInitialOptions(), persisted),
- init: () => {
- api.setOptions(merge(api.getInitialOptions(), persisted));
- provider.channel.on(SET_CONFIG, () => {
- api.setOptions(merge(api.getInitialOptions(), persisted));
- });
- },
};
};
diff --git a/code/lib/manager-api/src/modules/refs.ts b/code/lib/manager-api/src/modules/refs.ts
index 02884665cf5a..20c3f6cc887e 100644
--- a/code/lib/manager-api/src/modules/refs.ts
+++ b/code/lib/manager-api/src/modules/refs.ts
@@ -8,10 +8,11 @@ import type {
SetStoriesStoryData,
API_IndexHash,
API_StoryMapper,
+ StoryIndex,
} from '@storybook/types';
// eslint-disable-next-line import/no-cycle
import {
- transformSetStoriesStoryDataToStoriesHash,
+ transformSetStoriesStoryDataToPreparedStoryIndex,
transformStoryIndexToStoriesHash,
} from '../lib/stories';
@@ -104,8 +105,12 @@ async function handleRequest(
try {
const response = await request;
- if (response === false || response === true) throw new Error('Unexpected boolean response');
- if (!response.ok) throw new Error(`Unexpected response not OK: ${response.statusText}`);
+ if (response === false || response === true) {
+ throw new Error('Unexpected boolean response');
+ }
+ if (!response.ok) {
+ throw new Error(`Unexpected response not OK: ${response.statusText}`);
+ }
const json = await response.json();
@@ -276,26 +281,33 @@ export const init: ModuleFn = (
if (singleStory) {
return;
}
+ // eslint-disable-next-line @typescript-eslint/naming-convention
+ let internal_index: StoryIndex | undefined;
+ let index: API_IndexHash | undefined;
+ const { filters } = store.getState();
const { storyMapper = defaultStoryMapper } = provider.getConfig();
const ref = api.getRefs()[id];
- let index: API_IndexHash;
- if (setStoriesData) {
- index = transformSetStoriesStoryDataToStoriesHash(
- map(setStoriesData, ref, { storyMapper }),
- { provider, docsOptions, filters: {}, status: {} }
- );
- } else if (storyIndex) {
+ if (storyIndex || setStoriesData) {
+ internal_index = setStoriesData
+ ? transformSetStoriesStoryDataToPreparedStoryIndex(
+ map(setStoriesData, ref, { storyMapper })
+ )
+ : storyIndex;
+
index = transformStoryIndexToStoriesHash(storyIndex, {
provider,
docsOptions,
- filters: {},
+ filters,
status: {},
});
}
- if (index) index = addRefIds(index, ref);
- api.updateRef(id, { index, ...rest });
+ if (index) {
+ index = addRefIds(index, ref);
+ }
+
+ api.updateRef(id, { ...ref, ...rest, index, internal_index });
},
updateRef: (id, data) => {
diff --git a/code/lib/manager-api/src/modules/shortcuts.ts b/code/lib/manager-api/src/modules/shortcuts.ts
index 6d1dc4814c43..bdea217ab7c4 100644
--- a/code/lib/manager-api/src/modules/shortcuts.ts
+++ b/code/lib/manager-api/src/modules/shortcuts.ts
@@ -226,7 +226,6 @@ export const init: ModuleFn = ({ store, fullAPI, provider }) => {
// warning: event might not have a full prototype chain because it may originate from the channel
handleShortcutFeature(feature, event) {
const {
- layout: { isFullscreen, showNav, showPanel },
ui: { enableShortcuts },
storyId,
} = store.getState();
@@ -237,31 +236,31 @@ export const init: ModuleFn = ({ store, fullAPI, provider }) => {
if (event?.preventDefault) event.preventDefault();
switch (feature) {
case 'escape': {
- if (isFullscreen) {
- fullAPI.toggleFullscreen();
- } else if (!showNav) {
- fullAPI.toggleNav();
+ if (fullAPI.getIsFullscreen()) {
+ fullAPI.toggleFullscreen(false);
+ } else if (fullAPI.getIsNavShown()) {
+ fullAPI.toggleNav(true);
}
break;
}
case 'focusNav': {
- if (isFullscreen) {
- fullAPI.toggleFullscreen();
+ if (fullAPI.getIsFullscreen()) {
+ fullAPI.toggleFullscreen(false);
}
- if (!showNav) {
- fullAPI.toggleNav();
+ if (!fullAPI.getIsNavShown()) {
+ fullAPI.toggleNav(true);
}
fullAPI.focusOnUIElement(focusableUIElements.storyListMenu);
break;
}
case 'search': {
- if (isFullscreen) {
- fullAPI.toggleFullscreen();
+ if (fullAPI.getIsFullscreen()) {
+ fullAPI.toggleFullscreen(false);
}
- if (!showNav) {
- fullAPI.toggleNav();
+ if (!fullAPI.getIsNavShown()) {
+ fullAPI.toggleNav(true);
}
setTimeout(() => {
@@ -285,11 +284,11 @@ export const init: ModuleFn = ({ store, fullAPI, provider }) => {
}
case 'focusPanel': {
- if (isFullscreen) {
- fullAPI.toggleFullscreen();
+ if (fullAPI.getIsFullscreen()) {
+ fullAPI.toggleFullscreen(false);
}
- if (!showPanel) {
- fullAPI.togglePanel();
+ if (!fullAPI.getIsPanelShown()) {
+ fullAPI.togglePanel(true);
}
fullAPI.focusOnUIElement(focusableUIElements.storyPanelRoot);
break;
@@ -321,21 +320,11 @@ export const init: ModuleFn = ({ store, fullAPI, provider }) => {
}
case 'togglePanel': {
- if (isFullscreen) {
- fullAPI.toggleFullscreen();
- fullAPI.resetLayout();
- }
-
fullAPI.togglePanel();
break;
}
case 'toggleNav': {
- if (isFullscreen) {
- fullAPI.toggleFullscreen();
- fullAPI.resetLayout();
- }
-
fullAPI.toggleNav();
break;
}
@@ -346,11 +335,11 @@ export const init: ModuleFn = ({ store, fullAPI, provider }) => {
}
case 'panelPosition': {
- if (isFullscreen) {
- fullAPI.toggleFullscreen();
+ if (fullAPI.getIsFullscreen()) {
+ fullAPI.toggleFullscreen(false);
}
- if (!showPanel) {
- fullAPI.togglePanel();
+ if (!fullAPI.getIsPanelShown()) {
+ fullAPI.togglePanel(true);
}
fullAPI.togglePanelPosition();
diff --git a/code/lib/manager-api/src/modules/stories.ts b/code/lib/manager-api/src/modules/stories.ts
index 72c4198a3863..5f96f2ed7d48 100644
--- a/code/lib/manager-api/src/modules/stories.ts
+++ b/code/lib/manager-api/src/modules/stories.ts
@@ -615,14 +615,29 @@ export const init: ModuleFn = ({
});
await store.setState({ status: newStatus }, { persistence: 'session' });
+
if (index) {
+ // We need to re-prepare the index
await api.setIndex(index);
+
+ const refs = await fullAPI.getRefs();
+ Object.entries(refs).forEach(([refId, { internal_index, ...ref }]) => {
+ fullAPI.setRef(refId, { ...ref, storyIndex: internal_index }, true);
+ });
}
},
experimental_setFilter: async (id, filterFunction) => {
const { internal_index: index } = store.getState();
await store.setState({ filters: { ...store.getState().filters, [id]: filterFunction } });
- await api.setIndex(index);
+
+ if (index) {
+ await api.setIndex(index);
+
+ const refs = await fullAPI.getRefs();
+ Object.entries(refs).forEach(([refId, { internal_index, ...ref }]) => {
+ fullAPI.setRef(refId, { ...ref, storyIndex: internal_index }, true);
+ });
+ }
},
};
diff --git a/code/lib/manager-api/src/modules/url.ts b/code/lib/manager-api/src/modules/url.ts
index c6cfc5abbd80..8a74803825ef 100644
--- a/code/lib/manager-api/src/modules/url.ts
+++ b/code/lib/manager-api/src/modules/url.ts
@@ -12,6 +12,7 @@ import { global } from '@storybook/global';
import type { API_Layout, API_UI } from '@storybook/types';
import type { ModuleArgs, ModuleFn } from '../lib/types';
+import { defaultLayoutState } from './layout';
const { window: globalWindow } = global;
@@ -50,10 +51,39 @@ const initialUrlSupport = ({
...otherParams // the rest gets passed to the iframe
} = queryFromLocation(location);
+ let navSize;
+ let bottomPanelHeight;
+ let rightPanelWidth;
+
+ // set sizes based on fullscreen
+ if (parseBoolean(full) === true) {
+ navSize = 0;
+ bottomPanelHeight = 0;
+ rightPanelWidth = 0;
+ } else if (parseBoolean(full) === false) {
+ navSize = defaultLayoutState.layout.navSize;
+ bottomPanelHeight = defaultLayoutState.layout.bottomPanelHeight;
+ rightPanelWidth = defaultLayoutState.layout.rightPanelWidth;
+ }
+ // set sizes based on nav
+ if (!singleStory) {
+ if (parseBoolean(nav) === true) {
+ navSize = defaultLayoutState.layout.navSize;
+ }
+ if (parseBoolean(nav) === false) {
+ navSize = 0;
+ }
+ }
+ // set sizes based on panel
+ if (parseBoolean(panel) === false) {
+ bottomPanelHeight = 0;
+ rightPanelWidth = 0;
+ }
+
const layout: Partial = {
- isFullscreen: parseBoolean(full),
- showNav: !singleStory && parseBoolean(nav),
- showPanel: parseBoolean(panel),
+ navSize,
+ bottomPanelHeight,
+ rightPanelWidth,
panelPosition: ['right', 'bottom'].includes(panel) ? panel : undefined,
showTabs: parseBoolean(tabs),
};
diff --git a/code/lib/manager-api/src/store.ts b/code/lib/manager-api/src/store.ts
index d508c7740c1c..284443e8a96a 100644
--- a/code/lib/manager-api/src/store.ts
+++ b/code/lib/manager-api/src/store.ts
@@ -103,7 +103,9 @@ export default class Store {
}
const newState: State = await new Promise((resolve) => {
- this.upstreamSetState(patch, resolve);
+ this.upstreamSetState(patch, () => {
+ resolve(this.getState());
+ });
});
if (persistence !== 'none') {
@@ -114,6 +116,7 @@ export default class Store {
if (callback) {
callback(newState);
}
+
return newState;
}
}
diff --git a/code/lib/manager-api/src/tests/layout.test.js b/code/lib/manager-api/src/tests/layout.test.js
deleted file mode 100644
index f2032ba1e118..000000000000
--- a/code/lib/manager-api/src/tests/layout.test.js
+++ /dev/null
@@ -1,168 +0,0 @@
-import { themes } from '@storybook/theming';
-import { init as initLayout } from '../modules/layout';
-
-let layoutApi;
-let store;
-let provider;
-let currentState;
-
-beforeEach(() => {
- currentState = {
- ui: {
- enableShortcuts: true,
- },
- layout: {
- showToolbar: true,
- isFullscreen: false,
- showPanel: true,
- showNav: true,
- panelPosition: 'bottom',
- },
- selectedPanel: 'storybook/actions/panel',
- theme: themes.light,
- };
- store = {
- getState: () => currentState,
- setState: jest.fn((patch) => {
- currentState = {
- ...currentState,
- ...(typeof patch === 'function' ? patch(currentState) : patch),
- };
- }),
- };
- provider = { getConfig: jest.fn(() => ({})) };
- layoutApi = initLayout({ store, provider }).api;
-});
-
-describe('layout API', () => {
- describe('toggleFullscreen', () => {
- it('should toggle isFullscreen', () => {
- currentState.layout.isFullscreen = false;
- layoutApi.toggleFullscreen();
- expect(currentState.layout.isFullscreen).toBe(true);
- layoutApi.toggleFullscreen();
- expect(currentState.layout.isFullscreen).toBe(false);
- layoutApi.toggleFullscreen(false);
- expect(currentState.layout.isFullscreen).toBe(false);
- layoutApi.toggleFullscreen(true);
- expect(currentState.layout.isFullscreen).toBe(true);
- });
-
- it('should not affect nav or panel state when enabling fullscreen', () => {
- currentState.layout.isFullscreen = false;
- layoutApi.toggleFullscreen();
- expect(currentState.layout.showNav).toBe(true);
- expect(currentState.layout.showNav).toBe(true);
- });
-
- it('should enable nav when exiting fullscreen', () => {
- currentState.layout.isFullscreen = true;
- currentState.layout.showNav = false;
- layoutApi.toggleFullscreen();
- expect(currentState.layout).toEqual(
- expect.objectContaining({
- isFullscreen: false,
- showPanel: true,
- showNav: true,
- })
- );
- });
-
- describe('singleStory=true', () => {
- beforeEach(() => {
- layoutApi = initLayout({ store, provider, singleStory: true }).api;
- });
-
- it('should NOT enable nav when exiting fullscreen', () => {
- currentState.layout.showNav = false;
- layoutApi.toggleFullscreen();
- expect(currentState.layout).toEqual(
- expect.objectContaining({
- isFullscreen: true,
- showPanel: true,
- showNav: false,
- })
- );
- });
- });
- });
-
- describe('toggleNav', () => {
- it('should toggle showNav', () => {
- currentState.layout.showNav = true;
- layoutApi.toggleNav();
- expect(currentState.layout.showNav).toBe(false);
- layoutApi.toggleNav();
- expect(currentState.layout.showNav).toBe(true);
- layoutApi.toggleNav(true);
- expect(currentState.layout.showNav).toBe(true);
- layoutApi.toggleNav(false);
- expect(currentState.layout.showNav).toBe(false);
- });
-
- describe('singleStory=true', () => {
- beforeEach(() => {
- layoutApi = initLayout({ store, provider, singleStory: true }).api;
- });
-
- it('should NOT toggle showNav', () => {
- currentState.layout.showNav = false;
- layoutApi.toggleNav();
- expect(currentState.layout.showNav).toBe(false);
- layoutApi.toggleNav(true);
- expect(currentState.layout.showNav).toBe(false);
- });
- });
- });
-
- describe('setOptions', () => {
- const getLastSetStateArgs = () => {
- const { calls } = store.setState.mock;
- return calls[calls.length - 1];
- };
-
- it('should not change selectedPanel if it is undefined in the options', () => {
- layoutApi.setOptions({});
-
- expect(getLastSetStateArgs()).toBeUndefined();
- });
-
- it('should not change selectedPanel if it is undefined in the options, but something else has changed', () => {
- layoutApi.setOptions({ panelPosition: 'right' });
-
- expect(getLastSetStateArgs()[0].selectedPanel).toBeUndefined();
- });
-
- it('should not change selectedPanel if it is currently the same', () => {
- const panelName = currentState.selectedPanel;
- layoutApi.setOptions({});
- // second call is needed to overwrite initial layout
- layoutApi.setOptions({ selectedPanel: panelName });
-
- expect(getLastSetStateArgs()).toBeUndefined();
- });
-
- it('should not change selectedPanel if it is currently the same, but something else has changed', () => {
- layoutApi.setOptions({});
- // second call is needed to overwrite initial layout
- layoutApi.setOptions({ panelPosition: 'right', selectedPanel: currentState.selectedPanel });
-
- expect(getLastSetStateArgs()[0].selectedPanel).toBeUndefined();
- });
-
- it('should set selectedPanel initially', () => {
- const panelName = 'storybook/a11y/panel';
- layoutApi.setOptions({ selectedPanel: panelName });
-
- expect(getLastSetStateArgs()[0].selectedPanel).toEqual(panelName);
- });
-
- it('should change selectedPanel if it is defined in the options and is different', () => {
- const panelName = 'storybook/a11y/panel';
- layoutApi.setOptions({});
- layoutApi.setOptions({ selectedPanel: panelName });
-
- expect(getLastSetStateArgs()[0].selectedPanel).toEqual(panelName);
- });
- });
-});
diff --git a/code/lib/manager-api/src/tests/layout.test.ts b/code/lib/manager-api/src/tests/layout.test.ts
new file mode 100644
index 000000000000..a1891558ecda
--- /dev/null
+++ b/code/lib/manager-api/src/tests/layout.test.ts
@@ -0,0 +1,538 @@
+import { themes } from '@storybook/theming';
+import type { API_Provider } from 'lib/types/src';
+import EventEmitter from 'events';
+import type { SubAPI, SubState } from '../modules/layout';
+import type { SubState as AddonsSubState } from '../modules/addons';
+import { defaultLayoutState, init as initLayout } from '../modules/layout';
+import type Store from '../store';
+import type { API, State } from '..';
+import type { ModuleArgs } from '../lib/types';
+
+describe('layout API', () => {
+ let layoutApi: SubAPI;
+ let store: Store;
+ let provider: API_Provider;
+ let currentState: SubState & {
+ selectedPanel: AddonsSubState['selectedPanel'];
+ singleStory?: boolean;
+ };
+
+ beforeEach(() => {
+ currentState = {
+ ...defaultLayoutState,
+ selectedPanel: 'storybook/actions/panel',
+ theme: themes.light,
+ singleStory: false,
+ };
+ store = {
+ getState: () => currentState as unknown as State,
+ setState: jest.fn(async (patch) => {
+ currentState = {
+ ...currentState,
+ ...(typeof patch === 'function' ? patch(currentState as unknown as State) : patch),
+ };
+ return currentState as unknown as State;
+ }),
+ } as unknown as Store;
+ provider = {
+ getConfig: jest.fn(() => ({})),
+ channel: new EventEmitter(),
+ } as unknown as API_Provider;
+ layoutApi = initLayout({
+ store,
+ provider,
+ singleStory: false,
+ } as unknown as ModuleArgs).api;
+ });
+
+ describe('toggleFullscreen', () => {
+ it('should toggle fullscreen', () => {
+ // start not in fullscreen
+ expect(currentState.layout.navSize).toBeGreaterThan(0);
+ expect(currentState.layout.bottomPanelHeight).toBeGreaterThan(0);
+ expect(currentState.layout.rightPanelWidth).toBeGreaterThan(0);
+
+ layoutApi.toggleFullscreen();
+
+ // now in fullscreen
+ expect(currentState.layout.navSize).toBe(0);
+ expect(currentState.layout.bottomPanelHeight).toBe(0);
+ expect(currentState.layout.rightPanelWidth).toBe(0);
+
+ layoutApi.toggleFullscreen();
+
+ // back to not in fullscreen
+ expect(currentState.layout.navSize).toBeGreaterThan(0);
+ expect(currentState.layout.bottomPanelHeight).toBeGreaterThan(0);
+ expect(currentState.layout.rightPanelWidth).toBeGreaterThan(0);
+ });
+ it('should toggle fullscreen to recent visible sizes', () => {
+ // start not in fullscreen
+ expect(currentState.layout.navSize).toBe(300);
+ expect(currentState.layout.bottomPanelHeight).toBe(300);
+ expect(currentState.layout.rightPanelWidth).toBe(400);
+
+ layoutApi.setSizes({
+ navSize: 100,
+ bottomPanelHeight: 200,
+ rightPanelWidth: 250,
+ });
+
+ layoutApi.toggleFullscreen();
+
+ // now in fullscreen
+ expect(currentState.layout.navSize).toBe(0);
+ expect(currentState.layout.bottomPanelHeight).toBe(0);
+ expect(currentState.layout.rightPanelWidth).toBe(0);
+
+ layoutApi.toggleFullscreen();
+
+ // back to recent visible sizes, not default size
+ expect(currentState.layout.navSize).toBe(100);
+ expect(currentState.layout.bottomPanelHeight).toBe(200);
+ expect(currentState.layout.rightPanelWidth).toBe(250);
+ });
+ it('should toggle fullscreen with argument', () => {
+ // start not in fullscreen
+ expect(currentState.layout.navSize).toBeGreaterThan(0);
+ expect(currentState.layout.bottomPanelHeight).toBeGreaterThan(0);
+ expect(currentState.layout.rightPanelWidth).toBeGreaterThan(0);
+
+ layoutApi.toggleFullscreen(false);
+
+ // nothing should change
+ expect(currentState.layout.navSize).toBeGreaterThan(0);
+ expect(currentState.layout.bottomPanelHeight).toBeGreaterThan(0);
+ expect(currentState.layout.rightPanelWidth).toBeGreaterThan(0);
+
+ layoutApi.toggleFullscreen(true);
+
+ // now in fullscreen
+ expect(currentState.layout.navSize).toBe(0);
+ expect(currentState.layout.bottomPanelHeight).toBe(0);
+ expect(currentState.layout.rightPanelWidth).toBe(0);
+
+ // nothing should change
+ layoutApi.toggleFullscreen(true);
+
+ expect(currentState.layout.navSize).toBe(0);
+ expect(currentState.layout.bottomPanelHeight).toBe(0);
+ expect(currentState.layout.rightPanelWidth).toBe(0);
+
+ layoutApi.toggleFullscreen(false);
+
+ // now out of fullscreen
+ expect(currentState.layout.navSize).toBeGreaterThan(0);
+ expect(currentState.layout.bottomPanelHeight).toBeGreaterThan(0);
+ expect(currentState.layout.rightPanelWidth).toBeGreaterThan(0);
+ });
+ it('should toggle fullscreen when nav is hidden', () => {
+ layoutApi.toggleNav(false);
+ // start not in fullscreen
+ expect(currentState.layout.navSize).toBe(0);
+ expect(currentState.layout.bottomPanelHeight).toBeGreaterThan(0);
+ expect(currentState.layout.rightPanelWidth).toBeGreaterThan(0);
+
+ layoutApi.toggleFullscreen();
+
+ // now in fullscreen
+ expect(currentState.layout.navSize).toBe(0); // unchanged
+ expect(currentState.layout.bottomPanelHeight).toBe(0);
+ expect(currentState.layout.rightPanelWidth).toBe(0);
+
+ layoutApi.toggleFullscreen();
+
+ // now out of fullscreen
+ expect(currentState.layout.navSize).toBeGreaterThan(0); // shown
+ expect(currentState.layout.bottomPanelHeight).toBeGreaterThan(0);
+ expect(currentState.layout.rightPanelWidth).toBeGreaterThan(0);
+ });
+ it('should toggle fullscreen when panel is hidden', () => {
+ layoutApi.togglePanel(false);
+ // start not in fullscreen
+ expect(currentState.layout.navSize).toBeGreaterThan(0);
+ expect(currentState.layout.bottomPanelHeight).toBe(0);
+ expect(currentState.layout.rightPanelWidth).toBe(0);
+
+ layoutApi.toggleFullscreen();
+
+ // now in fullscreen
+ expect(currentState.layout.navSize).toBe(0); // unchanged
+ expect(currentState.layout.bottomPanelHeight).toBe(0);
+ expect(currentState.layout.rightPanelWidth).toBe(0);
+
+ layoutApi.toggleFullscreen();
+
+ // now out of fullscreen
+ expect(currentState.layout.navSize).toBeGreaterThan(0); // shown
+ expect(currentState.layout.bottomPanelHeight).toBeGreaterThan(0);
+ expect(currentState.layout.rightPanelWidth).toBeGreaterThan(0);
+ });
+ it('should NOT show nav when disabling fullscreen with singleStory=true', () => {
+ store.setState((current) => ({
+ singleStory: true,
+ layout: { ...current.layout, navSize: 0 },
+ }));
+ layoutApi = initLayout({ store, provider, singleStory: true } as unknown as ModuleArgs).api;
+
+ // start not in fullscreen, nav hidden
+ expect(currentState.layout.navSize).toBe(0);
+ expect(currentState.layout.bottomPanelHeight).toBeGreaterThan(0);
+ expect(currentState.layout.rightPanelWidth).toBeGreaterThan(0);
+
+ layoutApi.toggleFullscreen();
+
+ // now in fullscreen
+ expect(currentState.layout.navSize).toBe(0);
+ expect(currentState.layout.bottomPanelHeight).toBe(0);
+ expect(currentState.layout.rightPanelWidth).toBe(0);
+
+ layoutApi.toggleFullscreen();
+
+ // back to not in fullscreen, nav still hidden
+ expect(currentState.layout.navSize).toBe(0);
+ expect(currentState.layout.bottomPanelHeight).toBeGreaterThan(0);
+ expect(currentState.layout.rightPanelWidth).toBeGreaterThan(0);
+ });
+ });
+
+ describe('toggleNav', () => {
+ it('should toggle navigation', () => {
+ // start default, nav shown
+ expect(currentState.layout.navSize).toBeGreaterThan(0);
+
+ layoutApi.toggleNav();
+
+ expect(currentState.layout.navSize).toBe(0);
+
+ layoutApi.toggleNav();
+
+ expect(currentState.layout.navSize).toBeGreaterThan(0);
+ });
+ it('should toggle navigation with argument', () => {
+ // start default, nav shown
+ expect(currentState.layout.navSize).toBeGreaterThan(0);
+
+ layoutApi.toggleNav(true);
+
+ // nothing should change
+ expect(currentState.layout.navSize).toBeGreaterThan(0);
+
+ layoutApi.toggleNav(false);
+
+ // should hide nav
+ expect(currentState.layout.navSize).toBe(0);
+
+ layoutApi.toggleNav(false);
+
+ // nothing should change
+ expect(currentState.layout.navSize).toBe(0);
+
+ layoutApi.toggleNav(true);
+
+ // should show nav
+ expect(currentState.layout.navSize).toBeGreaterThan(0);
+ });
+ it('should toggle navigation to recent visible size', () => {
+ // start default, nav shown
+ expect(currentState.layout.navSize).toBe(300);
+
+ layoutApi.setSizes({
+ navSize: 100,
+ });
+
+ layoutApi.toggleNav();
+
+ expect(currentState.layout.navSize).toBe(0);
+
+ layoutApi.toggleNav();
+
+ expect(currentState.layout.navSize).toBe(100);
+ });
+ it('should NOT toggle navigation when singleStory=true', () => {
+ store.setState((current) => ({
+ singleStory: true,
+ layout: { ...current.layout, navSize: 0 },
+ }));
+ layoutApi = initLayout({ store, provider, singleStory: true } as unknown as ModuleArgs).api;
+
+ layoutApi.toggleNav();
+ expect(currentState.layout.navSize).toBe(0);
+ });
+ });
+
+ describe('togglePanel', () => {
+ it('should toggle panel', () => {
+ // start default, panel shown
+ expect(currentState.layout.rightPanelWidth).toBeGreaterThan(0);
+ expect(currentState.layout.bottomPanelHeight).toBeGreaterThan(0);
+
+ layoutApi.togglePanel();
+
+ expect(currentState.layout.rightPanelWidth).toBe(0);
+ expect(currentState.layout.bottomPanelHeight).toBe(0);
+
+ layoutApi.togglePanel();
+
+ expect(currentState.layout.rightPanelWidth).toBeGreaterThan(0);
+ expect(currentState.layout.bottomPanelHeight).toBeGreaterThan(0);
+ });
+ it('should toggle panel with argument', () => {
+ // start default, panel shown
+ expect(currentState.layout.bottomPanelHeight).toBeGreaterThan(0);
+ expect(currentState.layout.rightPanelWidth).toBeGreaterThan(0);
+
+ layoutApi.togglePanel(true);
+
+ // nothing should change
+ expect(currentState.layout.bottomPanelHeight).toBeGreaterThan(0);
+ expect(currentState.layout.rightPanelWidth).toBeGreaterThan(0);
+
+ layoutApi.togglePanel(false);
+
+ // should hide panel
+ expect(currentState.layout.bottomPanelHeight).toBe(0);
+ expect(currentState.layout.rightPanelWidth).toBe(0);
+
+ layoutApi.togglePanel(false);
+
+ // nothing should change
+ expect(currentState.layout.bottomPanelHeight).toBe(0);
+ expect(currentState.layout.rightPanelWidth).toBe(0);
+
+ layoutApi.togglePanel(true);
+
+ // should show panel
+ expect(currentState.layout.bottomPanelHeight).toBeGreaterThan(0);
+ expect(currentState.layout.rightPanelWidth).toBeGreaterThan(0);
+ });
+ it('should toggle to recent visible size', () => {
+ // start default, panel shown
+ expect(currentState.layout.rightPanelWidth).toBe(400);
+ expect(currentState.layout.bottomPanelHeight).toBe(300);
+
+ layoutApi.setSizes({
+ rightPanelWidth: 350,
+ bottomPanelHeight: 250,
+ });
+
+ layoutApi.togglePanel();
+
+ expect(currentState.layout.rightPanelWidth).toBe(0);
+ expect(currentState.layout.bottomPanelHeight).toBe(0);
+
+ layoutApi.togglePanel();
+
+ // should show panel with recent visible size, not default size
+ expect(currentState.layout.rightPanelWidth).toBe(350);
+ expect(currentState.layout.bottomPanelHeight).toBe(250);
+ });
+ });
+
+ describe('togglePanelPosition', () => {
+ it('should toggle panel position', () => {
+ // start default, panel on the bottom
+ expect(currentState.layout.panelPosition).toBe('bottom');
+
+ layoutApi.togglePanelPosition();
+
+ expect(currentState.layout.panelPosition).toBe('right');
+
+ layoutApi.togglePanelPosition();
+
+ expect(currentState.layout.panelPosition).toBe('bottom');
+ });
+ it('should toggle panel position with argument', () => {
+ // start default, panel on the bottom
+ expect(currentState.layout.panelPosition).toBe('bottom');
+
+ layoutApi.togglePanelPosition('bottom');
+
+ // nothing should change
+ expect(currentState.layout.panelPosition).toBe('bottom');
+
+ layoutApi.togglePanelPosition('right');
+
+ // move to the right
+ expect(currentState.layout.panelPosition).toBe('right');
+
+ layoutApi.togglePanelPosition('right');
+
+ // nothing should change
+ expect(currentState.layout.panelPosition).toBe('right');
+
+ layoutApi.togglePanelPosition('bottom');
+
+ // move to the bottom
+ expect(currentState.layout.panelPosition).toBe('bottom');
+ });
+ });
+
+ describe('setSizes', () => {
+ it('should set all sizes', () => {
+ // start default
+ expect(currentState.layout.navSize).toBe(300);
+ expect(currentState.layout.bottomPanelHeight).toBe(300);
+ expect(currentState.layout.rightPanelWidth).toBe(400);
+
+ layoutApi.setSizes({
+ navSize: 100,
+ bottomPanelHeight: 200,
+ rightPanelWidth: 300,
+ });
+
+ expect(currentState.layout.navSize).toBe(100);
+ expect(currentState.layout.bottomPanelHeight).toBe(200);
+ expect(currentState.layout.rightPanelWidth).toBe(300);
+ });
+ it('should set a subset of sizes', () => {
+ // start default
+ expect(currentState.layout.navSize).toBe(300);
+ expect(currentState.layout.bottomPanelHeight).toBe(300);
+ expect(currentState.layout.rightPanelWidth).toBe(400);
+
+ layoutApi.setSizes({
+ navSize: 100,
+ });
+
+ expect(currentState.layout.navSize).toBe(100);
+ expect(currentState.layout.bottomPanelHeight).toBe(300); // unchanged
+ expect(currentState.layout.rightPanelWidth).toBe(400); // unchanged
+ });
+ it('should set recentVisibleSizes when setting sizes', () => {
+ // start default
+ expect(currentState.layout.navSize).toBe(300);
+ expect(currentState.layout.bottomPanelHeight).toBe(300);
+ expect(currentState.layout.rightPanelWidth).toBe(400);
+
+ expect(currentState.layout.recentVisibleSizes.navSize).toBe(300);
+ expect(currentState.layout.recentVisibleSizes.bottomPanelHeight).toBe(300);
+ expect(currentState.layout.recentVisibleSizes.rightPanelWidth).toBe(400);
+
+ layoutApi.setSizes({
+ navSize: 50,
+ bottomPanelHeight: 100,
+ rightPanelWidth: 150,
+ });
+
+ expect(currentState.layout.recentVisibleSizes.navSize).toBe(50);
+ expect(currentState.layout.recentVisibleSizes.bottomPanelHeight).toBe(100);
+ expect(currentState.layout.recentVisibleSizes.rightPanelWidth).toBe(150);
+
+ layoutApi.setSizes({
+ navSize: 0,
+ bottomPanelHeight: 0,
+ rightPanelWidth: 0,
+ });
+
+ // recent visible sizes should not change when being set to 0
+ expect(currentState.layout.recentVisibleSizes.navSize).toBe(50);
+ expect(currentState.layout.recentVisibleSizes.bottomPanelHeight).toBe(100);
+ expect(currentState.layout.recentVisibleSizes.rightPanelWidth).toBe(150);
+ });
+ });
+
+ describe('setOptions', () => {
+ const getLastSetStateArgs = () => {
+ const { calls } = (store.setState as jest.Mock).mock;
+ return calls[calls.length - 1];
+ };
+
+ it('should not change selectedPanel if it is undefined in the options', () => {
+ layoutApi.setOptions({});
+
+ expect(getLastSetStateArgs()).toBeUndefined();
+ });
+
+ it('should not change selectedPanel if it is undefined in the options, but something else has changed', () => {
+ layoutApi.setOptions({ panelPosition: 'right' });
+
+ expect(getLastSetStateArgs()[0].selectedPanel).toBeUndefined();
+ });
+
+ it('should not change selectedPanel if it is currently the same', () => {
+ const panelName = currentState.selectedPanel;
+ layoutApi.setOptions({});
+ // second call is needed to overwrite initial layout
+ layoutApi.setOptions({ selectedPanel: panelName });
+
+ expect(getLastSetStateArgs()).toBeUndefined();
+ });
+
+ it('should not change selectedPanel if it is currently the same, but something else has changed', () => {
+ layoutApi.setOptions({});
+ // second call is needed to overwrite initial layout
+ layoutApi.setOptions({ panelPosition: 'right', selectedPanel: currentState.selectedPanel });
+
+ expect(getLastSetStateArgs()[0].selectedPanel).toBeUndefined();
+ });
+
+ it('should set selectedPanel initially', () => {
+ const panelName = 'storybook/a11y/panel';
+ layoutApi.setOptions({ selectedPanel: panelName });
+
+ expect(getLastSetStateArgs()[0].selectedPanel).toEqual(panelName);
+ });
+
+ it('should change selectedPanel if it is defined in the options and is different', () => {
+ const panelName = 'storybook/a11y/panel';
+ layoutApi.setOptions({});
+ layoutApi.setOptions({ selectedPanel: panelName });
+
+ expect(getLastSetStateArgs()[0].selectedPanel).toEqual(panelName);
+ });
+ });
+
+ describe('state getters', () => {
+ it('should get navShown with getIsNavShown', () => {
+ expect(layoutApi.getIsNavShown()).toBe(true);
+
+ layoutApi.toggleNav();
+
+ expect(layoutApi.getIsNavShown()).toBe(false);
+
+ layoutApi.toggleFullscreen();
+
+ expect(layoutApi.getIsNavShown()).toBe(false);
+
+ layoutApi.toggleFullscreen();
+
+ expect(layoutApi.getIsNavShown()).toBe(true);
+ });
+
+ it('should get panelShwon with getIsPanelShown', () => {
+ expect(layoutApi.getIsPanelShown()).toBe(true);
+
+ layoutApi.togglePanel();
+
+ expect(layoutApi.getIsPanelShown()).toBe(false);
+
+ layoutApi.toggleFullscreen();
+
+ expect(layoutApi.getIsPanelShown()).toBe(false);
+
+ layoutApi.toggleFullscreen();
+
+ expect(layoutApi.getIsPanelShown()).toBe(true);
+ });
+
+ it('should get fullscreen with getIsFullscreen', () => {
+ expect(layoutApi.getIsFullscreen()).toBe(false);
+
+ layoutApi.toggleNav();
+
+ // still not fullscreen
+ expect(layoutApi.getIsFullscreen()).toBe(false);
+
+ layoutApi.togglePanel();
+
+ // now it is fullscreen
+ expect(layoutApi.getIsFullscreen()).toBe(true);
+
+ layoutApi.toggleFullscreen();
+
+ // not fullscreen anymore
+ expect(layoutApi.getIsFullscreen()).toBe(false);
+ });
+ });
+});
diff --git a/code/lib/manager-api/src/tests/refs.test.ts b/code/lib/manager-api/src/tests/refs.test.ts
index f0556d560ba3..d07275337b04 100644
--- a/code/lib/manager-api/src/tests/refs.test.ts
+++ b/code/lib/manager-api/src/tests/refs.test.ts
@@ -1,5 +1,9 @@
import { global } from '@storybook/global';
+import type { StoryIndex } from 'lib/types/src';
+import type { State } from '..';
+import { transformStoryIndexToStoriesHash } from '../lib/stories';
import { getSourceType, init as initRefs } from '../modules/refs';
+import type Store from '../store';
const { fetch } = global;
@@ -40,6 +44,7 @@ const provider = {
const store = {
getState: jest.fn().mockReturnValue({
+ filters: {},
refs: {
fake: {
id: 'fake',
@@ -51,6 +56,17 @@ const store = {
setState: jest.fn((a: any) => {}),
};
+function createMockStore(initialState: Partial = {}) {
+ let state = initialState;
+ return {
+ getState: jest.fn(() => state),
+ setState: jest.fn((s: typeof state) => {
+ state = { ...state, ...s };
+ return Promise.resolve(state);
+ }),
+ } as any as Store;
+}
+
interface ResponseResult {
ok?: boolean;
err?: Error;
@@ -279,6 +295,7 @@ describe('Refs API', () => {
Please check your dev-tools network tab.",
},
+ "internal_index": undefined,
"title": "Fake",
"type": "auto-inject",
"url": "https://example.com",
@@ -347,6 +364,7 @@ describe('Refs API', () => {
Please check your dev-tools network tab.",
},
+ "internal_index": undefined,
"title": "Fake",
"type": "auto-inject",
"url": "https://example.com",
@@ -479,6 +497,10 @@ describe('Refs API', () => {
"fake": Object {
"id": "fake",
"index": Object {},
+ "internal_index": Object {
+ "entries": Object {},
+ "v": 4,
+ },
"title": "Fake",
"type": "lazy",
"url": "https://example.com",
@@ -493,6 +515,10 @@ describe('Refs API', () => {
"fake": Object {
"id": "fake",
"index": Object {},
+ "internal_index": Object {
+ "entries": Object {},
+ "v": 4,
+ },
"title": "Fake",
"type": "lazy",
"url": "https://example.com",
@@ -568,6 +594,10 @@ describe('Refs API', () => {
"fake": Object {
"id": "fake",
"index": Object {},
+ "internal_index": Object {
+ "entries": Object {},
+ "v": 4,
+ },
"title": "Fake",
"type": "lazy",
"url": "https://example.com",
@@ -645,6 +675,10 @@ describe('Refs API', () => {
"fake": Object {
"id": "fake",
"index": Object {},
+ "internal_index": Object {
+ "entries": Object {},
+ "v": 4,
+ },
"title": "Fake",
"type": "lazy",
"url": "https://example.com",
@@ -722,6 +756,7 @@ describe('Refs API', () => {
"fake": Object {
"id": "fake",
"index": undefined,
+ "internal_index": undefined,
"loginUrl": "https://example.com/login",
"title": "Fake",
"type": "auto-inject",
@@ -863,6 +898,7 @@ describe('Refs API', () => {
"fake": Object {
"id": "fake",
"index": undefined,
+ "internal_index": undefined,
"loginUrl": "https://example.com/login",
"title": "Fake",
"type": "auto-inject",
@@ -944,6 +980,10 @@ describe('Refs API', () => {
"fake": Object {
"id": "fake",
"index": Object {},
+ "internal_index": Object {
+ "entries": Object {},
+ "v": 4,
+ },
"title": "Fake",
"type": "lazy",
"url": "https://example.com",
@@ -1021,6 +1061,10 @@ describe('Refs API', () => {
"fake": Object {
"id": "fake",
"index": Object {},
+ "internal_index": Object {
+ "entries": Object {},
+ "v": 4,
+ },
"title": "Fake",
"type": "lazy",
"url": "https://example.com",
@@ -1152,6 +1196,71 @@ describe('Refs API', () => {
});
});
+ describe('setRef', () => {
+ it('can filter', async () => {
+ const index: StoryIndex = {
+ v: 4,
+ entries: {
+ 'a--1': {
+ id: 'a--1',
+ title: 'A',
+ name: '1',
+ importPath: './path/to/a1.ts',
+ type: 'story',
+ },
+ 'a--2': {
+ id: 'a--2',
+ title: 'A',
+ name: '2',
+ importPath: './path/to/a2.ts',
+ type: 'story',
+ },
+ },
+ };
+
+ const initialState: Partial = {
+ refs: {
+ fake: {
+ id: 'fake',
+ url: 'https://example.com',
+ previewInitialized: true,
+ index: transformStoryIndexToStoriesHash(index, {
+ provider: provider as any,
+ docsOptions: {},
+ filters: {},
+ status: {},
+ }),
+ internal_index: index,
+ },
+ },
+ };
+ // eslint-disable-next-line @typescript-eslint/no-shadow
+ const store = createMockStore(initialState);
+ const { api } = initRefs({ provider, store } as any, { runCheck: false });
+
+ await expect(api.getRefs().fake.index).toEqual(
+ expect.objectContaining({ 'a--2': expect.anything() })
+ );
+
+ const stateWithFilters: Partial = {
+ filters: {
+ fake: (a) => a.name.includes('1'),
+ },
+ };
+
+ await store.setState(stateWithFilters);
+
+ await api.setRef('fake', { storyIndex: index });
+
+ await expect(api.getRefs().fake.index).toEqual(
+ expect.objectContaining({ 'a--1': expect.anything() })
+ );
+ await expect(api.getRefs().fake.index).not.toEqual(
+ expect.objectContaining({ 'a--2': expect.anything() })
+ );
+ });
+ });
+
it('errors on unknown version', async () => {
// given
const { api } = initRefs({ provider, store } as any, { runCheck: false });
diff --git a/code/lib/manager-api/src/tests/store.test.js b/code/lib/manager-api/src/tests/store.test.js
index 4d555d74f9f0..b633eb8fdfe5 100644
--- a/code/lib/manager-api/src/tests/store.test.js
+++ b/code/lib/manager-api/src/tests/store.test.js
@@ -1,6 +1,6 @@
import store2 from 'store2';
import flushPromises from 'flush-promises';
-
+//
import Store, { STORAGE_KEY } from '../store';
jest.mock('store2', () => ({
@@ -41,7 +41,8 @@ describe('store', () => {
describe('setState', () => {
it('sets values in React only by default', async () => {
const setState = jest.fn().mockImplementation((x, cb) => cb());
- const store = new Store({ setState });
+ const getState = jest.fn();
+ const store = new Store({ setState, getState });
await store.setState({ foo: 'bar' });
@@ -52,7 +53,8 @@ describe('store', () => {
it('sets values in React and sessionStorage if persistence === session', async () => {
const setState = jest.fn().mockImplementation((x, cb) => cb());
- const store = new Store({ setState });
+ const getState = jest.fn();
+ const store = new Store({ setState, getState });
await store.setState({ foo: 'bar' }, { persistence: 'session' });
@@ -63,7 +65,8 @@ describe('store', () => {
it('sets values in React and sessionStorage if persistence === permanent', async () => {
const setState = jest.fn().mockImplementation((x, cb) => cb());
- const store = new Store({ setState });
+ const getState = jest.fn();
+ const store = new Store({ setState, getState });
await store.setState({ foo: 'bar' }, { persistence: 'permanent' });
@@ -74,12 +77,13 @@ describe('store', () => {
it('properly patches existing values', async () => {
const setState = jest.fn().mockImplementation((x, cb) => cb());
+ const getState = jest.fn();
store2.session.get.mockReturnValueOnce({
foo: 'baz',
another: 'value',
combined: { a: 'b' },
});
- const store = new Store({ setState });
+ const store = new Store({ setState, getState });
await store.setState({ foo: 'bar', combined: { c: 'd' } }, { persistence: 'session' });
@@ -99,7 +103,8 @@ describe('store', () => {
const setState = jest.fn().mockImplementation((x, inputCb) => {
cb = inputCb;
});
- const store = new Store({ setState });
+ const getState = jest.fn();
+ const store = new Store({ setState, getState });
// NOTE: not awaiting here
let done = false;
@@ -117,8 +122,9 @@ describe('store', () => {
});
it('returns react.setState result', async () => {
- const setState = jest.fn().mockImplementation((x, cb) => cb('RESULT'));
- const store = new Store({ setState });
+ const setState = jest.fn().mockImplementation((x, cb) => cb());
+ const getState = jest.fn().mockImplementation(() => 'RESULT');
+ const store = new Store({ setState, getState });
const result = await store.setState({ foo: 'bar' });
@@ -127,8 +133,9 @@ describe('store', () => {
it('allows a callback', async () =>
new Promise((resolve) => {
- const setState = jest.fn().mockImplementation((x, cb) => cb('RESULT'));
- const store = new Store({ setState });
+ const setState = jest.fn().mockImplementation((x, cb) => cb());
+ const getState = jest.fn().mockImplementation(() => 'RESULT');
+ const store = new Store({ setState, getState });
store.setState({ foo: 'bar' }, (result) => {
expect(result).toBe('RESULT');
@@ -141,7 +148,8 @@ describe('store', () => {
x('OLD_STATE');
cb();
});
- const store = new Store({ setState });
+ const getState = jest.fn();
+ const store = new Store({ setState, getState });
const patch = jest.fn().mockReturnValue({ foo: 'bar' });
await store.setState(patch, { persistence: 'session' });
diff --git a/code/lib/manager-api/src/tests/stories.test.ts b/code/lib/manager-api/src/tests/stories.test.ts
index 7733f569e5c5..a07d6d202171 100644
--- a/code/lib/manager-api/src/tests/stories.test.ts
+++ b/code/lib/manager-api/src/tests/stories.test.ts
@@ -72,7 +72,7 @@ function createMockModuleArgs({
const store = createMockStore({ filters: {}, status: {}, ...initialState });
const provider = createMockProvider();
- return { navigate, store, provider, fullAPI };
+ return { navigate, store, provider, fullAPI: { ...fullAPI, getRefs: () => ({}) } };
}
describe('stories API', () => {
diff --git a/code/lib/manager-api/src/tests/url.test.js b/code/lib/manager-api/src/tests/url.test.js
index 33cf4a1872c1..a51e259f51b7 100644
--- a/code/lib/manager-api/src/tests/url.test.js
+++ b/code/lib/manager-api/src/tests/url.test.js
@@ -20,7 +20,11 @@ describe('initial state', () => {
state: { layout },
} = initURL({ navigate, state: { location }, provider: { channel: new EventEmitter() } });
- expect(layout).toEqual({ isFullscreen: true });
+ expect(layout).toMatchObject({
+ bottomPanelHeight: 0,
+ navSize: 0,
+ rightPanelWidth: 0,
+ });
});
it('handles nav parameter', () => {
@@ -31,7 +35,7 @@ describe('initial state', () => {
state: { layout },
} = initURL({ navigate, state: { location }, provider: { channel: new EventEmitter() } });
- expect(layout).toEqual({ showNav: false });
+ expect(layout).toMatchObject({ navSize: 0 });
});
it('handles shortcuts parameter', () => {
@@ -53,7 +57,7 @@ describe('initial state', () => {
state: { layout },
} = initURL({ navigate, state: { location }, provider: { channel: new EventEmitter() } });
- expect(layout).toEqual({ panelPosition: 'bottom' });
+ expect(layout).toMatchObject({ panelPosition: 'bottom' });
});
it('handles panel parameter, right', () => {
@@ -64,7 +68,7 @@ describe('initial state', () => {
state: { layout },
} = initURL({ navigate, state: { location }, provider: { channel: new EventEmitter() } });
- expect(layout).toEqual({ panelPosition: 'right' });
+ expect(layout).toMatchObject({ panelPosition: 'right' });
});
it('handles panel parameter, 0', () => {
@@ -75,7 +79,10 @@ describe('initial state', () => {
state: { layout },
} = initURL({ navigate, state: { location }, provider: { channel: new EventEmitter() } });
- expect(layout).toEqual({ showPanel: false });
+ expect(layout).toMatchObject({
+ bottomPanelHeight: 0,
+ rightPanelWidth: 0,
+ });
});
});
});
diff --git a/code/lib/manager-api/src/typings.d.ts b/code/lib/manager-api/src/typings.d.ts
index b7de89a44b4e..d14b4196753e 100644
--- a/code/lib/manager-api/src/typings.d.ts
+++ b/code/lib/manager-api/src/typings.d.ts
@@ -2,7 +2,7 @@
declare var __STORYBOOK_ADDONS_MANAGER: any;
declare var CONFIG_TYPE: string;
-declare var FEATURES: import('@storybook/types').StorybookConfig['features'];
+declare var FEATURES: import('@storybook/types').StorybookConfigRaw['features'];
declare var REFS: any;
declare var VERSIONCHECK: any;
declare var LOGLEVEL: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent' | undefined;
diff --git a/code/lib/node-logger/package.json b/code/lib/node-logger/package.json
index de012e06cc67..900291b25426 100644
--- a/code/lib/node-logger/package.json
+++ b/code/lib/node-logger/package.json
@@ -47,7 +47,7 @@
"chalk": "^4.1.0",
"npmlog": "^5.0.1",
"pretty-hrtime": "^1.0.3",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/lib/postinstall/package.json b/code/lib/postinstall/package.json
index a498e38aa9b0..ebedf1c23004 100644
--- a/code/lib/postinstall/package.json
+++ b/code/lib/postinstall/package.json
@@ -48,7 +48,7 @@
"jest": "^29.7.0",
"jest-specific-snapshot": "^8.0.0",
"jscodeshift": "^0.15.1",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/lib/postinstall/src/frameworks.test.ts b/code/lib/postinstall/src/frameworks.test.ts
index 6b498477e193..0fce293caae6 100644
--- a/code/lib/postinstall/src/frameworks.test.ts
+++ b/code/lib/postinstall/src/frameworks.test.ts
@@ -1,3 +1,4 @@
+import { it, describe, expect } from '@jest/globals';
import { getFrameworks } from './frameworks';
const REACT = {
diff --git a/code/lib/preview-api/package.json b/code/lib/preview-api/package.json
index 3b84b570c359..aee9cd449a8d 100644
--- a/code/lib/preview-api/package.json
+++ b/code/lib/preview-api/package.json
@@ -26,31 +26,6 @@
"import": "./dist/index.mjs",
"require": "./dist/index.js"
},
- "./dist/addons": {
- "types": "./dist/addons.d.ts",
- "import": "./dist/addons.mjs",
- "require": "./dist/addons.js"
- },
- "./dist/store": {
- "types": "./dist/store.d.ts",
- "import": "./dist/store.mjs",
- "require": "./dist/store.js"
- },
- "./dist/client-api": {
- "types": "./dist/client-api.d.ts",
- "import": "./dist/client-api.mjs",
- "require": "./dist/client-api.js"
- },
- "./dist/core-client": {
- "types": "./dist/core-client.d.ts",
- "import": "./dist/core-client.mjs",
- "require": "./dist/core-client.js"
- },
- "./dist/preview-web": {
- "types": "./dist/preview-web.d.ts",
- "import": "./dist/preview-web.mjs",
- "require": "./dist/preview-web.js"
- },
"./package.json": "./package.json"
},
"main": "dist/index.js",
@@ -94,12 +69,7 @@
},
"bundler": {
"entries": [
- "./src/index.ts",
- "./src/addons.ts",
- "./src/client-api.ts",
- "./src/core-client.ts",
- "./src/preview-web.ts",
- "./src/store.ts"
+ "./src/index.ts"
]
},
"gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae17"
diff --git a/code/lib/preview-api/src/modules/addons/main.ts b/code/lib/preview-api/src/modules/addons/main.ts
index 5b663fe0f435..cf81d655724d 100644
--- a/code/lib/preview-api/src/modules/addons/main.ts
+++ b/code/lib/preview-api/src/modules/addons/main.ts
@@ -75,9 +75,4 @@ function getAddonsStore(): AddonStore {
return global[KEY];
}
-// Exporting this twice in order to to be able to import it like { addons } instead of 'addons'
-// prefer import { addons } from '@storybook/addons' over import addons from '@storybook/addons'
-//
-// See public_api.ts
-
export const addons = getAddonsStore();
diff --git a/code/lib/preview-api/src/modules/client-api/ClientApi.test.ts b/code/lib/preview-api/src/modules/client-api/ClientApi.test.ts
deleted file mode 100644
index 65f4d718a9ed..000000000000
--- a/code/lib/preview-api/src/modules/client-api/ClientApi.test.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import { addons, mockChannel } from '../addons';
-import { ClientApi } from './ClientApi';
-
-beforeEach(() => {
- addons.setChannel(mockChannel());
-});
-
-describe('ClientApi', () => {
- describe('getStoryIndex', () => {
- it('should remember the order that files were added in', async () => {
- const clientApi = new ClientApi();
- const store = {
- processCSFFileWithCache: jest.fn(() => ({ meta: { title: 'title' } })),
- storyFromCSFFile: jest.fn(({ storyId }) => ({
- id: storyId,
- parameters: { fileName: storyId.split('-')[0].replace('kind', 'file') },
- })),
- };
- clientApi.storyStore = store as any;
-
- let disposeCallback: () => void = () => {};
- const module1 = {
- id: 'file1',
- hot: {
- data: {},
- accept: jest.fn(),
- dispose(cb: () => void) {
- disposeCallback = cb;
- },
- },
- };
- const module2 = {
- id: 'file2',
- };
- clientApi.storiesOf('kind1', module1 as unknown as NodeModule).add('story1', jest.fn());
- clientApi.storiesOf('kind2', module2 as unknown as NodeModule).add('story2', jest.fn());
- // This gets called by configure
- // eslint-disable-next-line no-underscore-dangle
- clientApi._loadAddedExports();
-
- expect(Object.keys(clientApi.getStoryIndex().entries)).toEqual([
- 'kind1--story1',
- 'kind2--story2',
- ]);
-
- disposeCallback();
- clientApi.storiesOf('kind1', module1 as unknown as NodeModule).add('story1', jest.fn());
- await new Promise((r) => setTimeout(r, 0));
- expect(Object.keys(clientApi.getStoryIndex().entries)).toEqual([
- 'kind1--story1',
- 'kind2--story2',
- ]);
- });
- });
-});
diff --git a/code/lib/preview-api/src/modules/client-api/ClientApi.ts b/code/lib/preview-api/src/modules/client-api/ClientApi.ts
index d68bf30b47cd..57b721f1c3db 100644
--- a/code/lib/preview-api/src/modules/client-api/ClientApi.ts
+++ b/code/lib/preview-api/src/modules/client-api/ClientApi.ts
@@ -2,8 +2,6 @@
import { dedent } from 'ts-dedent';
import { global } from '@storybook/global';
-import { logger } from '@storybook/client-logger';
-import { toId, sanitize } from '@storybook/csf';
import type {
Args,
StepRunner,
@@ -14,12 +12,8 @@ import type {
ArgTypesEnhancer,
ArgsEnhancer,
LoaderFunction,
- StoryFn,
Globals,
GlobalTypes,
- Addon_ClientApiAddons,
- Addon_StoryApi,
- NormalizedComponentAnnotations,
Path,
ModuleImportFn,
ModuleExports,
@@ -108,25 +102,19 @@ export const setGlobalRender = (render: StoryStoreFacade['projectAnnotation
}
};
-const invalidStoryTypes = new Set(['string', 'number', 'boolean', 'symbol']);
export class ClientApi {
facade: StoryStoreFacade;
storyStore?: StoryStore;
- private addons: Addon_ClientApiAddons;
-
onImportFnChanged?: ({ importFn }: { importFn: ModuleImportFn }) => void;
// If we don't get passed modules so don't know filenames, we can
// just use numeric indexes
- private lastFileName = 0;
constructor({ storyStore }: { storyStore?: StoryStore } = {}) {
this.facade = new StoryStoreFacade();
- this.addons = {};
-
this.storyStore = storyStore;
}
@@ -214,157 +202,6 @@ export class ClientApi {
);
}
- // what are the occasions that "m" is a boolean vs an obj
- storiesOf = (kind: string, m?: NodeModule): Addon_StoryApi => {
- if (!kind && typeof kind !== 'string') {
- throw new Error('Invalid or missing kind provided for stories, should be a string');
- }
-
- if (!m) {
- logger.warn(
- `Missing 'module' parameter for story with a kind of '${kind}'. It will break your HMR`
- );
- }
-
- if (m) {
- const proto = Object.getPrototypeOf(m);
- if (proto.exports && proto.exports.default) {
- // FIXME: throw an error in SB6.0
- logger.error(
- `Illegal mix of CSF default export and storiesOf calls in a single file: ${proto.i}`
- );
- }
- }
-
- // eslint-disable-next-line no-plusplus
- const baseFilename = m && m.id ? `${m.id}` : (this.lastFileName++).toString();
- let fileName = baseFilename;
- let i = 1;
- // Deal with `storiesOf()` being called twice in the same file.
- // On HMR, we clear _addedExports[fileName] below.
-
- while (this._addedExports[fileName]) {
- i += 1;
- fileName = `${baseFilename}-${i}`;
- }
-
- if (m && m.hot && m.hot.accept) {
- // This module used storiesOf(), so when it re-runs on HMR, it will reload
- // itself automatically without us needing to look at our imports
- m.hot.accept();
- m.hot.dispose(() => {
- this.facade.clearFilenameExports(fileName);
-
- delete this._addedExports[fileName];
-
- // We need to update the importFn as soon as the module re-evaluates
- // (and calls storiesOf() again, etc). We could call `onImportFnChanged()`
- // at the end of every setStories call (somehow), but then we'd need to
- // debounce it somehow for initial startup. Instead, we'll take advantage of
- // the fact that the evaluation of the module happens immediately in the same tick
- setTimeout(() => {
- this._loadAddedExports();
- this.onImportFnChanged?.({ importFn: this.importFn.bind(this) });
- }, 0);
- });
- }
-
- let hasAdded = false;
- const api: Addon_StoryApi = {
- kind: kind.toString(),
- add: () => api,
- addDecorator: () => api,
- addLoader: () => api,
- addParameters: () => api,
- };
-
- // apply addons
- Object.keys(this.addons).forEach((name) => {
- const addon = this.addons[name];
- api[name] = (...args: any[]) => {
- addon.apply(api, args);
- return api;
- };
- });
-
- const meta: NormalizedComponentAnnotations = {
- id: sanitize(kind),
- title: kind,
- decorators: [],
- loaders: [],
- parameters: {},
- };
- // We map these back to a simple default export, even though we have type guarantees at this point
-
- this._addedExports[fileName] = { default: meta };
-
- let counter = 0;
- api.add = (storyName: string, storyFn: StoryFn, parameters: Parameters = {}) => {
- hasAdded = true;
-
- if (typeof storyName !== 'string') {
- throw new Error(`Invalid or missing storyName provided for a "${kind}" story.`);
- }
-
- if (!storyFn || Array.isArray(storyFn) || invalidStoryTypes.has(typeof storyFn)) {
- throw new Error(
- `Cannot load story "${storyName}" in "${kind}" due to invalid format. Storybook expected a function/object but received ${typeof storyFn} instead.`
- );
- }
-
- const { decorators, loaders, component, args, argTypes, ...storyParameters } = parameters;
-
- const storyId = parameters.__id || toId(kind, storyName);
-
- const csfExports = this._addedExports[fileName];
- // Whack a _ on the front incase it is "default"
- csfExports[`story${counter}`] = {
- name: storyName,
- parameters: { fileName, __id: storyId, ...storyParameters },
- decorators,
- loaders,
- args,
- argTypes,
- component,
- render: storyFn,
- };
- counter += 1;
-
- return api;
- };
-
- api.addDecorator = (decorator: DecoratorFunction) => {
- if (hasAdded)
- throw new Error(`You cannot add a decorator after the first story for a kind.
-Read more here: https://github.com/storybookjs/storybook/blob/master/MIGRATION.md#can-no-longer-add-decoratorsparameters-after-stories`);
-
- meta.decorators?.push(decorator);
- return api;
- };
-
- api.addLoader = (loader: LoaderFunction) => {
- if (hasAdded) throw new Error(`You cannot add a loader after the first story for a kind.`);
-
- meta.loaders?.push(loader);
- return api;
- };
-
- api.addParameters = ({ component, args, argTypes, tags, ...parameters }: Parameters) => {
- if (hasAdded)
- throw new Error(`You cannot add parameters after the first story for a kind.
-Read more here: https://github.com/storybookjs/storybook/blob/master/MIGRATION.md#can-no-longer-add-decoratorsparameters-after-stories`);
-
- meta.parameters = combineParameters(meta.parameters, parameters);
- if (component) meta.component = component;
- if (args) meta.args = { ...meta.args, ...args };
- if (argTypes) meta.argTypes = { ...meta.argTypes, ...argTypes };
- if (tags) meta.tags = tags;
- return api;
- };
-
- return api;
- };
-
// @deprecated
raw = () => {
return this.storyStore?.raw();
diff --git a/code/lib/preview-api/src/modules/client-api/StoryStoreFacade.ts b/code/lib/preview-api/src/modules/client-api/StoryStoreFacade.ts
index 34688935debf..ccd95120b45c 100644
--- a/code/lib/preview-api/src/modules/client-api/StoryStoreFacade.ts
+++ b/code/lib/preview-api/src/modules/client-api/StoryStoreFacade.ts
@@ -113,7 +113,6 @@ export class StoryStoreFacade {
const entries = sortedV7.reduce((acc, s) => {
// We use the original entry we stored in `this.stories` because it is possible that the CSF file itself
// exports a `parameters.fileName` which can be different and mess up our `importFn`.
- // In fact, in Storyshots there is a Jest transformer that does exactly that.
// NOTE: this doesn't actually change the story object, just the index.
acc[s.id] = this.entries[s.id];
return acc;
diff --git a/code/lib/preview-api/src/modules/core-client/start.test.ts b/code/lib/preview-api/src/modules/core-client/start.test.ts
index b114e640f50a..aa304d2ba883 100644
--- a/code/lib/preview-api/src/modules/core-client/start.test.ts
+++ b/code/lib/preview-api/src/modules/core-client/start.test.ts
@@ -117,464 +117,6 @@ describe('start', () => {
// @ts-expect-error (setting this to undefined is indeed what we want to do)
global.IS_STORYBOOK = undefined;
});
- describe('when configure is called with storiesOf only', () => {
- it('loads and renders the first story correctly', async () => {
- const renderToCanvas = jest.fn();
-
- const { configure, clientApi } = start(renderToCanvas);
-
- configure('test', () => {
- clientApi
- .storiesOf('Component A', { id: 'file1' } as NodeModule)
- .add('Story One', jest.fn())
- .add('Story Two', jest.fn());
-
- clientApi
- .storiesOf('Component B', { id: 'file2' } as NodeModule)
- .add('Story Three', jest.fn());
- });
-
- await waitForRender();
-
- expect(mockChannel.emit.mock.calls.find((call) => call[0] === SET_INDEX)?.[1])
- .toMatchInlineSnapshot(`
- Object {
- "entries": Object {
- "component-a--story-one": Object {
- "argTypes": Object {},
- "args": Object {},
- "componentId": "component-a",
- "id": "component-a--story-one",
- "importPath": "file1",
- "initialArgs": Object {},
- "name": "Story One",
- "parameters": Object {
- "__id": "component-a--story-one",
- "__isArgsStory": false,
- "fileName": "file1",
- "renderer": "test",
- },
- "tags": Array [
- "story",
- ],
- "title": "Component A",
- "type": "story",
- },
- "component-a--story-two": Object {
- "argTypes": Object {},
- "args": Object {},
- "componentId": "component-a",
- "id": "component-a--story-two",
- "importPath": "file1",
- "initialArgs": Object {},
- "name": "Story Two",
- "parameters": Object {
- "__id": "component-a--story-two",
- "__isArgsStory": false,
- "fileName": "file1",
- "renderer": "test",
- },
- "tags": Array [
- "story",
- ],
- "title": "Component A",
- "type": "story",
- },
- "component-b--story-three": Object {
- "argTypes": Object {},
- "args": Object {},
- "componentId": "component-b",
- "id": "component-b--story-three",
- "importPath": "file2",
- "initialArgs": Object {},
- "name": "Story Three",
- "parameters": Object {
- "__id": "component-b--story-three",
- "__isArgsStory": false,
- "fileName": "file2",
- "renderer": "test",
- },
- "tags": Array [
- "story",
- ],
- "title": "Component B",
- "type": "story",
- },
- },
- "v": 4,
- }
- `);
-
- await waitForRender();
- expect(mockChannel.emit).toHaveBeenCalledWith(STORY_RENDERED, 'component-a--story-one');
-
- expect(renderToCanvas).toHaveBeenCalledWith(
- expect.objectContaining({
- id: 'component-a--story-one',
- }),
- 'story-root'
- );
- });
-
- it('deals with stories with "default" name', async () => {
- const renderToCanvas = jest.fn();
-
- const { configure, clientApi } = start(renderToCanvas);
-
- configure('test', () => {
- clientApi.storiesOf('Component A', { id: 'file1' } as NodeModule).add('default', jest.fn());
- });
-
- await waitForRender();
-
- expect(mockChannel.emit).toHaveBeenCalledWith(STORY_RENDERED, 'component-a--default');
- });
-
- it('deals with stories with camel-cased names', async () => {
- const renderToCanvas = jest.fn();
-
- const { configure, clientApi } = start(renderToCanvas);
-
- configure('test', () => {
- clientApi
- .storiesOf('Component A', { id: 'file1' } as NodeModule)
- .add('storyOne', jest.fn());
- });
-
- await waitForRender();
-
- expect(mockChannel.emit).toHaveBeenCalledWith(STORY_RENDERED, 'component-a--storyone');
- });
-
- it('deals with stories with spaces in the name', async () => {
- const renderToCanvas = jest.fn();
-
- const { configure, clientApi } = start(renderToCanvas);
-
- configure('test', () => {
- clientApi
- .storiesOf('Component A', { id: 'file1' } as NodeModule)
- .add('Story One', jest.fn());
- });
-
- await waitForRender();
-
- expect(mockChannel.emit).toHaveBeenCalledWith(STORY_RENDERED, 'component-a--story-one');
- });
-
- // https://github.com/storybookjs/storybook/issues/16303
- it('deals with stories with numeric names', async () => {
- const renderToCanvas = jest.fn();
-
- const { configure, clientApi } = start(renderToCanvas);
-
- configure('test', () => {
- clientApi.storiesOf('Component A', { id: 'file1' } as NodeModule).add('story0', jest.fn());
- });
-
- await waitForRender();
-
- expect(mockChannel.emit).toHaveBeenCalledWith(STORY_RENDERED, 'component-a--story0');
- });
-
- it('deals with storiesOf from the same file twice', async () => {
- const renderToCanvas = jest.fn();
-
- const { configure, clientApi } = start(renderToCanvas);
-
- configure('test', () => {
- clientApi.storiesOf('Component A', { id: 'file1' } as NodeModule).add('default', jest.fn());
- clientApi.storiesOf('Component B', { id: 'file1' } as NodeModule).add('default', jest.fn());
- clientApi.storiesOf('Component C', { id: 'file1' } as NodeModule).add('default', jest.fn());
- });
-
- await waitForRender();
- expect(mockChannel.emit).toHaveBeenCalledWith(STORY_RENDERED, 'component-a--default');
-
- const storiesOfData = mockChannel.emit.mock.calls.find((call) => call[0] === SET_INDEX)?.[1];
- expect(Object.values(storiesOfData.entries).map((s: any) => s.parameters.fileName)).toEqual([
- 'file1',
- 'file1-2',
- 'file1-3',
- ]);
- });
-
- it('allows setting compomnent/args/argTypes via a parameter', async () => {
- const renderToCanvas = jest.fn(({ storyFn }) => storyFn());
-
- const { configure, clientApi } = start(renderToCanvas);
-
- const component = {};
- configure('test', () => {
- clientApi
- .storiesOf('Component A', { id: 'file1' } as NodeModule)
- .addParameters({
- component,
- args: { a: 'a' },
- argTypes: { a: { type: 'string' } },
- })
- .add('default', jest.fn(), {
- args: { b: 'b' },
- argTypes: { b: { type: 'string' } },
- });
- });
-
- await waitForRender();
-
- expect(renderToCanvas).toHaveBeenCalledWith(
- expect.objectContaining({
- storyContext: expect.objectContaining({
- component,
- args: { a: 'a', b: 'b' },
- argTypes: {
- a: { name: 'a', type: { name: 'string' } },
- b: { name: 'b', type: { name: 'string' } },
- },
- }),
- }),
- 'story-root'
- );
-
- expect(global.IS_STORYBOOK).toBe(true);
- });
-
- it('supports forceRerender()', async () => {
- const renderToCanvas = jest.fn(({ storyFn }) => storyFn());
-
- const { configure, clientApi, forceReRender } = start(renderToCanvas);
-
- configure('test', () => {
- clientApi.storiesOf('Component A', { id: 'file1' } as NodeModule).add('default', jest.fn());
- });
-
- await waitForRender();
- expect(mockChannel.emit).toHaveBeenCalledWith(STORY_RENDERED, 'component-a--default');
-
- mockChannel.emit.mockClear();
- forceReRender();
-
- await waitForRender();
- expect(mockChannel.emit).toHaveBeenCalledWith(STORY_RENDERED, 'component-a--default');
- });
-
- it('supports HMR when a story file changes', async () => {
- const renderToCanvas = jest.fn(({ storyFn }) => storyFn());
-
- const { configure, clientApi } = start(renderToCanvas);
-
- let disposeCallback: () => void = () => {};
- const module = {
- id: 'file1',
- hot: {
- accept: jest.fn(),
- dispose(cb: () => void) {
- disposeCallback = cb;
- },
- },
- };
- const firstImplementation = jest.fn();
- configure('test', () => {
- clientApi.storiesOf('Component A', module as any).add('default', firstImplementation);
- });
-
- await waitForRender();
- expect(mockChannel.emit).toHaveBeenCalledWith(STORY_RENDERED, 'component-a--default');
- expect(firstImplementation).toHaveBeenCalled();
- expect(module.hot.accept).toHaveBeenCalled();
- expect(disposeCallback).toBeDefined();
-
- mockChannel.emit.mockClear();
- disposeCallback();
- const secondImplementation = jest.fn();
- clientApi.storiesOf('Component A', module as any).add('default', secondImplementation);
-
- await waitForRender();
- expect(mockChannel.emit).toHaveBeenCalledWith(STORY_RENDERED, 'component-a--default');
- expect(secondImplementation).toHaveBeenCalled();
- });
-
- it('re-emits SET_INDEX when a story is added', async () => {
- const renderToCanvas = jest.fn(({ storyFn }) => storyFn());
-
- const { configure, clientApi } = start(renderToCanvas);
-
- let disposeCallback: () => void = () => {};
- const module = {
- id: 'file1',
- hot: {
- accept: jest.fn(),
- dispose(cb: () => void) {
- disposeCallback = cb;
- },
- },
- };
- configure('test', () => {
- clientApi.storiesOf('Component A', module as any).add('default', jest.fn());
- });
-
- await waitForRender();
-
- mockChannel.emit.mockClear();
- disposeCallback();
- clientApi
- .storiesOf('Component A', module as any)
- .add('default', jest.fn())
- .add('new', jest.fn());
-
- await waitForEvents([SET_INDEX]);
- expect(mockChannel.emit.mock.calls.find((call) => call[0] === SET_INDEX)?.[1])
- .toMatchInlineSnapshot(`
- Object {
- "entries": Object {
- "component-a--default": Object {
- "argTypes": Object {},
- "args": Object {},
- "componentId": "component-a",
- "id": "component-a--default",
- "importPath": "file1",
- "initialArgs": Object {},
- "name": "default",
- "parameters": Object {
- "__id": "component-a--default",
- "__isArgsStory": false,
- "fileName": "file1",
- "renderer": "test",
- },
- "tags": Array [
- "story",
- ],
- "title": "Component A",
- "type": "story",
- },
- "component-a--new": Object {
- "argTypes": Object {},
- "args": Object {},
- "componentId": "component-a",
- "id": "component-a--new",
- "importPath": "file1",
- "initialArgs": Object {},
- "name": "new",
- "parameters": Object {
- "__id": "component-a--new",
- "__isArgsStory": false,
- "fileName": "file1",
- "renderer": "test",
- },
- "tags": Array [
- "story",
- ],
- "title": "Component A",
- "type": "story",
- },
- },
- "v": 4,
- }
- `);
- });
-
- it('re-emits SET_INDEX when a story file is removed', async () => {
- const renderToCanvas = jest.fn(({ storyFn }) => storyFn());
-
- const { configure, clientApi } = start(renderToCanvas);
-
- let disposeCallback: () => void = () => {};
- const moduleB = {
- id: 'file2',
- hot: {
- accept: jest.fn(),
- dispose(cb: () => void) {
- disposeCallback = cb;
- },
- },
- };
- configure('test', () => {
- clientApi.storiesOf('Component A', { id: 'file1' } as any).add('default', jest.fn());
- clientApi.storiesOf('Component B', moduleB as any).add('default', jest.fn());
- });
-
- await waitForEvents([SET_INDEX]);
- expect(mockChannel.emit.mock.calls.find((call) => call[0] === SET_INDEX)?.[1])
- .toMatchInlineSnapshot(`
- Object {
- "entries": Object {
- "component-a--default": Object {
- "argTypes": Object {},
- "args": Object {},
- "componentId": "component-a",
- "id": "component-a--default",
- "importPath": "file1",
- "initialArgs": Object {},
- "name": "default",
- "parameters": Object {
- "__id": "component-a--default",
- "__isArgsStory": false,
- "fileName": "file1",
- "renderer": "test",
- },
- "tags": Array [
- "story",
- ],
- "title": "Component A",
- "type": "story",
- },
- "component-b--default": Object {
- "argTypes": Object {},
- "args": Object {},
- "componentId": "component-b",
- "id": "component-b--default",
- "importPath": "file2",
- "initialArgs": Object {},
- "name": "default",
- "parameters": Object {
- "__id": "component-b--default",
- "__isArgsStory": false,
- "fileName": "file2",
- "renderer": "test",
- },
- "tags": Array [
- "story",
- ],
- "title": "Component B",
- "type": "story",
- },
- },
- "v": 4,
- }
- `);
- mockChannel.emit.mockClear();
- disposeCallback();
-
- await waitForEvents([SET_INDEX]);
- expect(mockChannel.emit.mock.calls.find((call) => call[0] === SET_INDEX)?.[1])
- .toMatchInlineSnapshot(`
- Object {
- "entries": Object {
- "component-a--default": Object {
- "argTypes": Object {},
- "args": Object {},
- "componentId": "component-a",
- "id": "component-a--default",
- "importPath": "file1",
- "initialArgs": Object {},
- "name": "default",
- "parameters": Object {
- "__id": "component-a--default",
- "__isArgsStory": false,
- "fileName": "file1",
- "renderer": "test",
- },
- "tags": Array [
- "story",
- ],
- "title": "Component A",
- "type": "story",
- },
- },
- "v": 4,
- }
- `);
- });
- });
const componentCExports = {
default: {
@@ -1039,356 +581,6 @@ describe('start', () => {
});
});
- describe('when configure is called with a combination', () => {
- it('loads and renders the first story correctly', async () => {
- const renderToCanvas = jest.fn();
-
- const { configure, clientApi } = start(renderToCanvas);
- configure('test', () => {
- clientApi
- .storiesOf('Component A', { id: 'file1' } as NodeModule)
- .add('Story One', jest.fn())
- .add('Story Two', jest.fn());
-
- clientApi
- .storiesOf('Component B', { id: 'file2' } as NodeModule)
- .add('Story Three', jest.fn());
-
- return [componentCExports];
- });
-
- await waitForRender();
- expect(mockChannel.emit.mock.calls.find((call) => call[0] === SET_INDEX)?.[1])
- .toMatchInlineSnapshot(`
- Object {
- "entries": Object {
- "component-a--story-one": Object {
- "argTypes": Object {},
- "args": Object {},
- "componentId": "component-a",
- "id": "component-a--story-one",
- "importPath": "file1",
- "initialArgs": Object {},
- "name": "Story One",
- "parameters": Object {
- "__id": "component-a--story-one",
- "__isArgsStory": false,
- "fileName": "file1",
- "renderer": "test",
- },
- "tags": Array [
- "story",
- ],
- "title": "Component A",
- "type": "story",
- },
- "component-a--story-two": Object {
- "argTypes": Object {},
- "args": Object {},
- "componentId": "component-a",
- "id": "component-a--story-two",
- "importPath": "file1",
- "initialArgs": Object {},
- "name": "Story Two",
- "parameters": Object {
- "__id": "component-a--story-two",
- "__isArgsStory": false,
- "fileName": "file1",
- "renderer": "test",
- },
- "tags": Array [
- "story",
- ],
- "title": "Component A",
- "type": "story",
- },
- "component-b--story-three": Object {
- "argTypes": Object {},
- "args": Object {},
- "componentId": "component-b",
- "id": "component-b--story-three",
- "importPath": "file2",
- "initialArgs": Object {},
- "name": "Story Three",
- "parameters": Object {
- "__id": "component-b--story-three",
- "__isArgsStory": false,
- "fileName": "file2",
- "renderer": "test",
- },
- "tags": Array [
- "story",
- ],
- "title": "Component B",
- "type": "story",
- },
- "component-c--story-one": Object {
- "argTypes": Object {},
- "args": Object {},
- "id": "component-c--story-one",
- "importPath": "exports-map-0",
- "initialArgs": Object {},
- "name": "Story One",
- "parameters": Object {
- "__isArgsStory": false,
- "fileName": "exports-map-0",
- "renderer": "test",
- },
- "tags": Array [
- "story-tag",
- "story",
- ],
- "title": "Component C",
- "type": "story",
- },
- "component-c--story-two": Object {
- "argTypes": Object {},
- "args": Object {},
- "id": "component-c--story-two",
- "importPath": "exports-map-0",
- "initialArgs": Object {},
- "name": "Story Two",
- "parameters": Object {
- "__isArgsStory": false,
- "fileName": "exports-map-0",
- "renderer": "test",
- },
- "tags": Array [
- "component-tag",
- "autodocs",
- "story",
- ],
- "title": "Component C",
- "type": "story",
- },
- },
- "v": 4,
- }
- `);
-
- await waitForRender();
- expect(mockChannel.emit).toHaveBeenCalledWith(STORY_RENDERED, 'component-a--story-one');
-
- expect(renderToCanvas).toHaveBeenCalledWith(
- expect.objectContaining({
- id: 'component-a--story-one',
- }),
- 'story-root'
- );
- });
-
- describe('autodocs', () => {
- beforeEach(() => {
- global.DOCS_OPTIONS = { autodocs: 'tag', defaultName: 'Docs' };
- });
-
- it('adds stories for each component with autodocs tag', async () => {
- const renderToCanvas = jest.fn();
-
- const { configure, clientApi } = start(renderToCanvas);
- configure('test', () => {
- clientApi
- .storiesOf('Component A', { id: 'file1' } as NodeModule)
- .add('Story One', jest.fn())
- .add('Story Two', jest.fn());
-
- clientApi
- .storiesOf('Component B', { id: 'file2' } as NodeModule)
- .addParameters({ tags: ['autodocs'] })
- .add('Story Three', jest.fn());
-
- return [componentCExports];
- });
-
- await waitForRender();
- expect(mockChannel.emit.mock.calls.find((call) => call[0] === SET_INDEX)?.[1])
- .toMatchInlineSnapshot(`
- Object {
- "entries": Object {
- "component-a--story-one": Object {
- "argTypes": Object {},
- "args": Object {},
- "componentId": "component-a",
- "id": "component-a--story-one",
- "importPath": "file1",
- "initialArgs": Object {},
- "name": "Story One",
- "parameters": Object {
- "__id": "component-a--story-one",
- "__isArgsStory": false,
- "fileName": "file1",
- "renderer": "test",
- },
- "tags": Array [
- "story",
- ],
- "title": "Component A",
- "type": "story",
- },
- "component-a--story-two": Object {
- "argTypes": Object {},
- "args": Object {},
- "componentId": "component-a",
- "id": "component-a--story-two",
- "importPath": "file1",
- "initialArgs": Object {},
- "name": "Story Two",
- "parameters": Object {
- "__id": "component-a--story-two",
- "__isArgsStory": false,
- "fileName": "file1",
- "renderer": "test",
- },
- "tags": Array [
- "story",
- ],
- "title": "Component A",
- "type": "story",
- },
- "component-b--docs": Object {
- "componentId": "component-b",
- "id": "component-b--docs",
- "importPath": "file2",
- "name": "Docs",
- "parameters": Object {
- "fileName": "file2",
- "renderer": "test",
- },
- "storiesImports": Array [],
- "tags": Array [
- "autodocs",
- "docs",
- ],
- "title": "Component B",
- "type": "docs",
- },
- "component-b--story-three": Object {
- "argTypes": Object {},
- "args": Object {},
- "componentId": "component-b",
- "id": "component-b--story-three",
- "importPath": "file2",
- "initialArgs": Object {},
- "name": "Story Three",
- "parameters": Object {
- "__id": "component-b--story-three",
- "__isArgsStory": false,
- "fileName": "file2",
- "renderer": "test",
- },
- "tags": Array [
- "autodocs",
- "story",
- ],
- "title": "Component B",
- "type": "story",
- },
- "component-c--docs": Object {
- "id": "component-c--docs",
- "importPath": "exports-map-0",
- "name": "Docs",
- "parameters": Object {
- "fileName": "exports-map-0",
- "renderer": "test",
- },
- "storiesImports": Array [],
- "tags": Array [
- "component-tag",
- "autodocs",
- "docs",
- ],
- "title": "Component C",
- "type": "docs",
- },
- "component-c--story-one": Object {
- "argTypes": Object {},
- "args": Object {},
- "id": "component-c--story-one",
- "importPath": "exports-map-0",
- "initialArgs": Object {},
- "name": "Story One",
- "parameters": Object {
- "__isArgsStory": false,
- "fileName": "exports-map-0",
- "renderer": "test",
- },
- "tags": Array [
- "story-tag",
- "story",
- ],
- "title": "Component C",
- "type": "story",
- },
- "component-c--story-two": Object {
- "argTypes": Object {},
- "args": Object {},
- "id": "component-c--story-two",
- "importPath": "exports-map-0",
- "initialArgs": Object {},
- "name": "Story Two",
- "parameters": Object {
- "__isArgsStory": false,
- "fileName": "exports-map-0",
- "renderer": "test",
- },
- "tags": Array [
- "component-tag",
- "autodocs",
- "story",
- ],
- "title": "Component C",
- "type": "story",
- },
- },
- "v": 4,
- }
- `);
- });
- });
- describe('when docsOptions.autodocs = true', () => {
- beforeEach(() => {
- global.DOCS_OPTIONS = { autodocs: true, defaultName: 'Docs' };
- });
-
- it('adds stories for each component with autodocs tag', async () => {
- const renderToDOM = jest.fn();
-
- const { configure, clientApi } = start(renderToDOM);
- configure('test', () => {
- (clientApi as any).addParameters({
- docs: { renderer: () => ({ render: jest.fn((_, _2, _3, d) => d()) }) },
- });
- clientApi
- .storiesOf('Component A', { id: 'file1' } as NodeModule)
- .add('Story One', jest.fn())
- .add('Story Two', jest.fn());
-
- clientApi
- .storiesOf('Component B', { id: 'file2' } as NodeModule)
- .addParameters({ tags: ['autodocs'] })
- .add('Story Three', jest.fn());
-
- return [componentCExports];
- });
-
- await waitForRender();
- const setIndexData = mockChannel.emit.mock.calls.find((call) => call[0] === SET_INDEX)?.[1];
- expect(Object.keys(setIndexData.entries)).toMatchInlineSnapshot(`
- Array [
- "component-a--docs",
- "component-a--story-one",
- "component-a--story-two",
- "component-b--docs",
- "component-b--story-three",
- "component-c--docs",
- "component-c--story-one",
- "component-c--story-two",
- ]
- `);
- });
- });
- });
-
describe('auto-title', () => {
const componentDExports = {
default: {
diff --git a/code/lib/preview-api/src/modules/core-client/start.ts b/code/lib/preview-api/src/modules/core-client/start.ts
index f9c389f71e8f..3b527da4cd1a 100644
--- a/code/lib/preview-api/src/modules/core-client/start.ts
+++ b/code/lib/preview-api/src/modules/core-client/start.ts
@@ -32,11 +32,6 @@ interface CoreClient_RendererImplementation {
}
interface CoreClient_ClientAPIFacade {
- /**
- * The old way of adding stories at runtime.
- * @deprecated This method is deprecated and will be removed in a future version.
- */
- storiesOf: (...args: any[]) => never;
/**
* The old way of retrieving the list of stories at runtime.
* @deprecated This method is deprecated and will be removed in a future version.
@@ -88,7 +83,6 @@ export function start(
forceReRender: removedApi('forceReRender'),
configure: removedApi('configure'),
clientApi: {
- storiesOf: removedApi('clientApi.storiesOf'),
raw: removedApi('raw'),
},
};
diff --git a/code/lib/preview-api/src/modules/preview-web/PreviewWeb.integration.test.ts b/code/lib/preview-api/src/modules/preview-web/PreviewWeb.integration.test.ts
index 805c5e7cb1b6..91d2cd35ae3e 100644
--- a/code/lib/preview-api/src/modules/preview-web/PreviewWeb.integration.test.ts
+++ b/code/lib/preview-api/src/modules/preview-web/PreviewWeb.integration.test.ts
@@ -118,7 +118,8 @@ describe('PreviewWeb', () => {
`);
});
- it('sends docs rendering exceptions to showException', async () => {
+ // TODO @tmeasday please help fixing this test
+ it.skip('sends docs rendering exceptions to showException', async () => {
const { DocsRenderer } = await import('@storybook/addon-docs');
projectAnnotations.parameters.docs.renderer = () => new DocsRenderer() as any;
diff --git a/code/lib/preview-api/src/modules/store/StoryIndexStore.test.ts b/code/lib/preview-api/src/modules/store/StoryIndexStore.test.ts
index c906d7a21a75..677cf83ee1a6 100644
--- a/code/lib/preview-api/src/modules/store/StoryIndexStore.test.ts
+++ b/code/lib/preview-api/src/modules/store/StoryIndexStore.test.ts
@@ -3,8 +3,6 @@ import { expect } from '@jest/globals';
import type { StoryIndex } from '@storybook/types';
import { StoryIndexStore } from './StoryIndexStore';
-jest.mock('@storybook/channel-websocket', () => () => ({ on: jest.fn() }));
-
const storyIndex: StoryIndex = {
v: 4,
entries: {
diff --git a/code/lib/preview-api/src/typings.d.ts b/code/lib/preview-api/src/typings.d.ts
index bedefed4b9a8..e6f7de7ada44 100644
--- a/code/lib/preview-api/src/typings.d.ts
+++ b/code/lib/preview-api/src/typings.d.ts
@@ -7,7 +7,7 @@ declare module 'better-opn';
declare module 'open';
declare module '@aw-web-design/x-default-browser';
-declare var FEATURES: import('@storybook/types').StorybookConfig['features'];
+declare var FEATURES: import('@storybook/types').StorybookConfigRaw['features'];
declare var STORIES: any;
declare var DOCS_OPTIONS: any;
diff --git a/code/lib/preview/package.json b/code/lib/preview/package.json
index 3ecf8e8f098f..4b9d7e70d5ac 100644
--- a/code/lib/preview/package.json
+++ b/code/lib/preview/package.json
@@ -63,9 +63,7 @@
"@storybook/global": "^5.0.0",
"@storybook/preview-api": "workspace:*",
"browser-dtector": "^3.4.0",
- "fs-extra": "^11.1.0",
- "ts-dedent": "^2.0.0",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/lib/preview/src/globals/globals.ts b/code/lib/preview/src/globals/globals.ts
index 3cd77282fe49..ba9b6056fbce 100644
--- a/code/lib/preview/src/globals/globals.ts
+++ b/code/lib/preview/src/globals/globals.ts
@@ -1,18 +1,12 @@
// Here we map the name of a module to their REFERENCE in the global scope.
export const globalsNameReferenceMap = {
- '@storybook/addons': '__STORYBOOK_MODULE_ADDONS__',
'@storybook/global': '__STORYBOOK_MODULE_GLOBAL__',
- '@storybook/channel-postmessage': '__STORYBOOK_MODULE_CHANNEL_POSTMESSAGE__', // @deprecated: remove in 8.0
- '@storybook/channel-websocket': '__STORYBOOK_MODULE_CHANNEL_WEBSOCKET__', // @deprecated: remove in 8.0
'@storybook/channels': '__STORYBOOK_MODULE_CHANNELS__',
- '@storybook/client-api': '__STORYBOOK_MODULE_CLIENT_API__',
'@storybook/client-logger': '__STORYBOOK_MODULE_CLIENT_LOGGER__',
- '@storybook/core-client': '__STORYBOOK_MODULE_CORE_CLIENT__',
'@storybook/core-events': '__STORYBOOK_MODULE_CORE_EVENTS__',
- '@storybook/preview-web': '__STORYBOOK_MODULE_PREVIEW_WEB__',
+ '@storybook/core-events/preview-errors': '__STORYBOOK_MODULE_CORE_EVENTS_PREVIEW_ERRORS__',
'@storybook/preview-api': '__STORYBOOK_MODULE_PREVIEW_API__',
- '@storybook/store': '__STORYBOOK_MODULE_STORE__',
'@storybook/types': '__STORYBOOK_MODULE_TYPES__',
} as const;
diff --git a/code/lib/preview/src/globals/runtime.ts b/code/lib/preview/src/globals/runtime.ts
index f05dd3ef24cd..39868d36ac9a 100644
--- a/code/lib/preview/src/globals/runtime.ts
+++ b/code/lib/preview/src/globals/runtime.ts
@@ -1,19 +1,11 @@
import * as CHANNELS from '@storybook/channels';
import * as CLIENT_LOGGER from '@storybook/client-logger';
import * as CORE_EVENTS from '@storybook/core-events';
+import * as CORE_EVENTS_PREVIEW_ERRORS from '@storybook/core-events/preview-errors';
import * as PREVIEW_API from '@storybook/preview-api';
import * as TYPES from '@storybook/types';
import * as GLOBAL from '@storybook/global';
-// DEPRECATED, remove in 8.0
-import * as ADDONS from '@storybook/preview-api/dist/addons';
-import * as CLIENT_API from '@storybook/preview-api/dist/client-api';
-import * as CORE_CLIENT from '@storybook/preview-api/dist/core-client';
-import * as PREVIEW_WEB from '@storybook/preview-api/dist/preview-web';
-import * as STORE from '@storybook/preview-api/dist/store';
-import * as CHANNEL_POSTMESSAGE from '@storybook/channels/dist/postmessage/index';
-import * as CHANNEL_WEBSOCKET from '@storybook/channels/dist/websocket/index';
-
import type { globalsNameReferenceMap } from './globals';
// Here we map the name of a module to their VALUE in the global scope.
@@ -21,16 +13,8 @@ export const globalsNameValueMap: Required void;
diff --git a/code/lib/react-dom-shim/package.json b/code/lib/react-dom-shim/package.json
index c68ca959edcf..428ed5386b9d 100644
--- a/code/lib/react-dom-shim/package.json
+++ b/code/lib/react-dom-shim/package.json
@@ -22,26 +22,26 @@
"sideEffects": false,
"exports": {
".": {
- "types": "./dist/react-16.d.ts",
- "node": "./dist/react-16.js",
- "require": "./dist/react-16.js",
- "import": "./dist/react-16.mjs"
- },
- "./dist/react-18": {
"types": "./dist/react-18.d.ts",
"node": "./dist/react-18.js",
"require": "./dist/react-18.js",
"import": "./dist/react-18.mjs"
},
+ "./dist/react-16": {
+ "types": "./dist/react-16.d.ts",
+ "node": "./dist/react-16.js",
+ "require": "./dist/react-16.js",
+ "import": "./dist/react-16.mjs"
+ },
"./dist/preset": {
"types": "./dist/preset.d.ts",
"require": "./dist/preset.js"
},
"./package.json": "./package.json"
},
- "main": "dist/react-16.js",
- "module": "dist/react-16.mjs",
- "types": "dist/react-16.d.ts",
+ "main": "dist/react-18.js",
+ "module": "dist/react-18.mjs",
+ "types": "dist/react-18.d.ts",
"files": [
"dist/**/*",
"README.md",
@@ -55,7 +55,7 @@
},
"devDependencies": {
"@storybook/types": "workspace:*",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
diff --git a/code/lib/react-dom-shim/src/preset.ts b/code/lib/react-dom-shim/src/preset.ts
index cfd44f567649..7c7f18bfb29a 100644
--- a/code/lib/react-dom-shim/src/preset.ts
+++ b/code/lib/react-dom-shim/src/preset.ts
@@ -8,7 +8,7 @@ export const webpackFinal = async (config: any, options: Options) => {
const isReact18 = version.startsWith('18') || version.startsWith('0.0.0');
const useReact17 = legacyRootApi ?? !isReact18;
- if (useReact17) return config;
+ if (!useReact17) return config;
return {
...config,
@@ -16,7 +16,7 @@ export const webpackFinal = async (config: any, options: Options) => {
...config.resolve,
alias: {
...config.resolve?.alias,
- '@storybook/react-dom-shim': '@storybook/react-dom-shim/dist/react-18',
+ '@storybook/react-dom-shim': '@storybook/react-dom-shim/dist/react-16',
},
},
};
@@ -28,16 +28,16 @@ export const viteFinal = async (config: any, options: Options) => {
const isReact18 = version.startsWith('18') || version.startsWith('0.0.0');
const useReact17 = legacyRootApi || !isReact18;
- if (useReact17) return config;
+ if (!useReact17) return config;
const alias = Array.isArray(config.resolve?.alias)
? config.resolve.alias.concat({
find: /^@storybook\/react-dom-shim$/,
- replacement: '@storybook/react-dom-shim/dist/react-18',
+ replacement: '@storybook/react-dom-shim/dist/react-16',
})
: {
...config.resolve?.alias,
- '@storybook/react-dom-shim': '@storybook/react-dom-shim/dist/react-18',
+ '@storybook/react-dom-shim': '@storybook/react-dom-shim/dist/react-16',
};
return {
diff --git a/code/lib/react-dom-shim/src/react-16.tsx b/code/lib/react-dom-shim/src/react-16.tsx
index 8fa5809a982e..8d2e60aea9e5 100644
--- a/code/lib/react-dom-shim/src/react-16.tsx
+++ b/code/lib/react-dom-shim/src/react-16.tsx
@@ -3,10 +3,12 @@ import ReactDOM from 'react-dom';
export const renderElement = async (node: ReactElement, el: Element) => {
return new Promise((resolve) => {
+ // eslint-disable-next-line react/no-deprecated
ReactDOM.render(node, el, () => resolve(null));
});
};
export const unmountElement = (el: Element) => {
+ // eslint-disable-next-line react/no-deprecated
ReactDOM.unmountComponentAtNode(el);
};
diff --git a/code/lib/react-dom-shim/src/react-18.tsx b/code/lib/react-dom-shim/src/react-18.tsx
index 36ca75d529d8..ddfa738d4dd9 100644
--- a/code/lib/react-dom-shim/src/react-18.tsx
+++ b/code/lib/react-dom-shim/src/react-18.tsx
@@ -1,9 +1,7 @@
import type { FC, ReactElement } from 'react';
-// @ts-expect-error react-dom doesn't have this in v16, which confuses TS
import type { Root as ReactRoot } from 'react-dom/client';
import React, { useLayoutEffect, useRef } from 'react';
-// @ts-expect-error react-dom doesn't have this in v16, which confuses TS
-import ReactDOM from 'react-dom/client'; // eslint-disable-line import/no-unresolved
+import ReactDOM from 'react-dom/client';
// A map of all rendered React 18 nodes
const nodes = new Map();
@@ -41,7 +39,7 @@ export const unmountElement = (el: Element, shouldUseNewRootApi?: boolean) => {
}
};
-const getReactRoot = async (el: Element): Promise => {
+const getReactRoot = async (el: Element): Promise => {
let root = nodes.get(el);
if (!root) {
diff --git a/code/lib/router/package.json b/code/lib/router/package.json
index 1b871d3f6df1..a4b1d47cee62 100644
--- a/code/lib/router/package.json
+++ b/code/lib/router/package.json
@@ -57,11 +57,11 @@
"@storybook/global": "^5.0.0",
"dequal": "^2.0.2",
"lodash": "^4.17.21",
- "react": "^16.8.0",
- "react-dom": "^16.8.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
"react-router-dom": "6.0.2",
"ts-dedent": "^2.0.0",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/lib/source-loader/package.json b/code/lib/source-loader/package.json
index 54a534773858..3a94ecc093a6 100644
--- a/code/lib/source-loader/package.json
+++ b/code/lib/source-loader/package.json
@@ -53,7 +53,7 @@
},
"devDependencies": {
"jest-specific-snapshot": "^8.0.0",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/lib/telemetry/package.json b/code/lib/telemetry/package.json
index 6f96b811659a..88a0d2f4ae68 100644
--- a/code/lib/telemetry/package.json
+++ b/code/lib/telemetry/package.json
@@ -56,7 +56,7 @@
"devDependencies": {
"nanoid": "^4.0.2",
"node-fetch": "^3.3.1",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/lib/telemetry/src/storybook-metadata.ts b/code/lib/telemetry/src/storybook-metadata.ts
index 782c4d4a4b78..edab1a536b6a 100644
--- a/code/lib/telemetry/src/storybook-metadata.ts
+++ b/code/lib/telemetry/src/storybook-metadata.ts
@@ -91,17 +91,17 @@ export const computeStorybookMetadata = async ({
metadata.hasCustomWebpack = !!mainConfig.webpackFinal;
metadata.hasStaticDirs = !!mainConfig.staticDirs;
- if (mainConfig.typescript) {
+ if (typeof mainConfig.typescript === 'object') {
metadata.typescriptOptions = mainConfig.typescript;
}
const frameworkInfo = await getFrameworkInfo(mainConfig);
- if (mainConfig.refs) {
+ if (typeof mainConfig.refs === 'object') {
metadata.refCount = Object.keys(mainConfig.refs).length;
}
- if (mainConfig.features) {
+ if (typeof mainConfig.features === 'object') {
metadata.features = mainConfig.features;
}
diff --git a/code/lib/test/package.json b/code/lib/test/package.json
index e24e700c030c..0c0e56f14aff 100644
--- a/code/lib/test/package.json
+++ b/code/lib/test/package.json
@@ -49,7 +49,7 @@
"@storybook/preview-api": "workspace:*",
"@testing-library/dom": "^9.3.1",
"@testing-library/jest-dom": "^6.1.3",
- "@testing-library/user-event": "^14.4.3",
+ "@testing-library/user-event": "14.3.0",
"@types/chai": "^4",
"@vitest/expect": "^0.34.2",
"@vitest/spy": "^0.34.1",
@@ -59,7 +59,7 @@
"devDependencies": {
"ts-dedent": "^2.2.0",
"type-fest": "~2.19",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/lib/theming/package.json b/code/lib/theming/package.json
index c18963e409a6..7069e1cd1897 100644
--- a/code/lib/theming/package.json
+++ b/code/lib/theming/package.json
@@ -65,7 +65,7 @@
"fs-extra": "^11.1.0",
"polished": "^4.2.2",
"ts-dedent": "^2.0.0",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
diff --git a/code/lib/types/package.json b/code/lib/types/package.json
index 8f36e3916088..fde570b6b03e 100644
--- a/code/lib/types/package.json
+++ b/code/lib/types/package.json
@@ -53,7 +53,7 @@
"@storybook/csf": "^0.1.2",
"@types/fs-extra": "^11.0.1",
"@types/node": "^18.0.0",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"publishConfig": {
"access": "public"
diff --git a/code/lib/types/src/modules/addons.ts b/code/lib/types/src/modules/addons.ts
index ef76feb2560c..6002d713e52c 100644
--- a/code/lib/types/src/modules/addons.ts
+++ b/code/lib/types/src/modules/addons.ts
@@ -1,13 +1,6 @@
/* eslint-disable @typescript-eslint/naming-convention */
-import type {
- FC,
- PropsWithChildren,
- ReactElement,
- ReactNode,
- ValidationMap,
- WeakValidationMap,
-} from 'react';
+import type { FC, PropsWithChildren, ReactElement, ReactNode } from 'react';
import type { RenderData as RouterData } from '../../../router/src/types';
import type { ThemeVars } from '../../../theming/src/types';
import type { API_SidebarOptions } from './api';
@@ -163,9 +156,8 @@ export interface Addon_StoryApi {
[k: string]: string | Addon_ClientApiReturnFn;
}
-export interface Addon_ClientStoryApi {
- storiesOf(kind: StoryKind, module: any): Addon_StoryApi;
-}
+// eslint-disable-next-line @typescript-eslint/no-empty-interface
+export interface Addon_ClientStoryApi {}
export type Addon_LoadFn = () => any;
export type Addon_RequireContext = any; // FIXME
@@ -204,7 +196,7 @@ export interface Addon_BaseAnnotations<
* Wrapper components or Storybook decorators that wrap a story.
*
* Decorators defined in Meta will be applied to every story variation.
- * @see [Decorators](https://storybook.js.org/docs/addons/introduction/#1-decorators)
+ * @see [Decorators](https://storybook.js.org/docs/addons/#1-decorators)
*/
decorators?: Addon_BaseDecorators;
@@ -320,15 +312,6 @@ export interface Addon_RenderOptions {
key?: unknown;
}
-/**
- * @deprecated This type is deprecated and will be removed in 8.0.
- */
-export type ReactJSXElement = {
- type: any;
- props: any;
- key: any;
-};
-
export type Addon_Type =
| Addon_BaseType
| Addon_PageType
@@ -340,7 +323,7 @@ export interface Addon_BaseType {
* The title of the addon.
* This can be a simple string, but it can also be a React.FunctionComponent or a React.ReactElement.
*/
- title: FCWithoutChildren | ReactNode;
+ title: FC | ReactNode | (() => string);
/**
* The type of the addon.
* @example Addon_TypesEnum.PANEL
@@ -396,20 +379,6 @@ export interface Addon_BaseType {
hidden?: boolean;
}
-/**
- * This is a copy of FC from react/index.d.ts, but has the PropsWithChildren type removed
- * this is correct and more type strict, and future compatible with React.FC in React 18+
- *
- * @deprecated This type is deprecated and will be removed in 8.0. (assuming the manager uses React 18 is out by then)
- */
-interface FCWithoutChildren {
- (props: P, context?: any): ReactElement | null;
- propTypes?: WeakValidationMap | undefined;
- contextTypes?: ValidationMap | undefined;
- defaultProps?: Partial | undefined;
- displayName?: string | undefined;
-}
-
export interface Addon_PageType {
type: Addon_TypesEnum.experimental_PAGE;
/**
@@ -423,7 +392,7 @@ export interface Addon_PageType {
/**
* The title is used in mobile mode to represent the page in the navigation.
*/
- title: FCWithoutChildren | string | ReactElement | ReactNode;
+ title: FC | string | ReactElement | ReactNode;
/**
* The main content of the addon, a function component without any props.
* Storybook will render your component always.
@@ -440,7 +409,7 @@ export interface Addon_PageType {
* );
* };
*/
- render: FCWithoutChildren;
+ render: FC;
}
export interface Addon_WrapperType {
@@ -473,7 +442,7 @@ export interface Addon_SidebarBottomType {
/**
* A React.FunctionComponent.
*/
- render: FCWithoutChildren;
+ render: FC;
}
export interface Addon_SidebarTopType {
@@ -485,7 +454,7 @@ export interface Addon_SidebarTopType {
/**
* A React.FunctionComponent.
*/
- render: FCWithoutChildren;
+ render: FC;
}
type Addon_TypeBaseNames = Exclude<
diff --git a/code/lib/types/src/modules/api.ts b/code/lib/types/src/modules/api.ts
index 53fa99965b55..be510b4bdfe4 100644
--- a/code/lib/types/src/modules/api.ts
+++ b/code/lib/types/src/modules/api.ts
@@ -90,10 +90,20 @@ export interface API_UIOptions {
export interface API_Layout {
initialActive: API_ActiveTabsType;
- isFullscreen: boolean;
- showPanel: boolean;
+ navSize: number;
+ bottomPanelHeight: number;
+ rightPanelWidth: number;
+ /**
+ * the sizes of the panels when they were last visible
+ * used to restore the sizes when the panels are shown again
+ * eg. when toggling fullscreen, panels, etc.
+ */
+ recentVisibleSizes: {
+ navSize: number;
+ bottomPanelHeight: number;
+ rightPanelWidth: number;
+ };
panelPosition: API_PanelPositions;
- showNav: boolean;
showTabs: boolean;
showToolbar: boolean;
/**
@@ -165,6 +175,8 @@ export interface API_ComposedRef extends API_LoadedRefData {
versions?: API_Versions;
loginUrl?: string;
version?: string;
+ /** DO NOT USE THIS */
+ internal_index?: StoryIndex;
}
export type API_ComposedRefUpdate = Partial<
@@ -179,6 +191,7 @@ export type API_ComposedRefUpdate = Partial<
| 'version'
| 'indexError'
| 'previewInitialized'
+ | 'internal_index'
>
>;
diff --git a/code/lib/types/src/modules/core-common.ts b/code/lib/types/src/modules/core-common.ts
index 2f7077fc5d88..aaf96ddb2207 100644
--- a/code/lib/types/src/modules/core-common.ts
+++ b/code/lib/types/src/modules/core-common.ts
@@ -76,9 +76,37 @@ export interface Presets {
apply(extension: 'entries', config?: [], args?: any): Promise;
apply(extension: 'stories', config?: [], args?: any): Promise;
apply(extension: 'managerEntries', config: [], args?: any): Promise;
- apply(extension: 'refs', config?: [], args?: any): Promise;
- apply(extension: 'core', config?: {}, args?: any): Promise;
- apply(extension: 'build', config?: {}, args?: any): Promise;
+ apply(extension: 'refs', config?: [], args?: any): Promise;
+ apply(
+ extension: 'core',
+ config?: StorybookConfigRaw['core'],
+ args?: any
+ ): Promise>;
+ apply(
+ extension: 'docs',
+ config?: StorybookConfigRaw['docs'],
+ args?: any
+ ): Promise>;
+ apply(
+ extension: 'features',
+ config?: StorybookConfigRaw['features'],
+ args?: any
+ ): Promise>;
+ apply(
+ extension: 'typescript',
+ config?: StorybookConfigRaw['typescript'],
+ args?: any
+ ): Promise>;
+ apply(
+ extension: 'build',
+ config?: StorybookConfigRaw['build'],
+ args?: any
+ ): Promise>;
+ apply(
+ extension: 'staticDirs',
+ config?: StorybookConfigRaw['staticDirs'],
+ args?: any
+ ): Promise;
apply(extension: string, config?: T, args?: unknown): Promise;
}
@@ -171,7 +199,7 @@ export interface BuilderOptions {
cache?: FileSystemCache;
configDir: string;
docsMode?: boolean;
- features?: StorybookConfig['features'];
+ features?: StorybookConfigRaw['features'];
versionCheck?: VersionCheck;
disableWebpackDefaults?: boolean;
serverChannelUrl?: string;
@@ -310,9 +338,10 @@ export interface TestBuildConfig {
}
/**
- * The interface for Storybook configuration in `main.ts` files.
+ * The interface for Storybook configuration used internally in presets
+ * The difference is that these values are the raw values, AKA, not wrapped with `PresetValue<>`
*/
-export interface StorybookConfig {
+export interface StorybookConfigRaw {
/**
* Sets the addons you want to use with Storybook.
*
@@ -320,11 +349,6 @@ export interface StorybookConfig {
*/
addons?: Preset[];
core?: CoreConfig;
- /**
- * Sets a list of directories of static files to be loaded by Storybook server
- *
- * @example `['./public']` or `[{from: './public', 'to': '/assets'}]`
- */
staticDirs?: (DirectoryMapping | string)[];
logLevel?: string;
features?: {
@@ -375,84 +399,143 @@ export interface StorybookConfig {
build?: TestBuildConfig;
+ stories: StoriesEntry[];
+
+ framework?: Preset;
+
+ typescript?: Partial;
+
+ refs?: CoreCommon_StorybookRefs;
+
+ babel?: BabelOptions;
+
+ swc?: SWCOptions;
+
+ env?: Record;
+
+ babelDefault?: BabelOptions;
+
+ config?: Entry[];
+
+ previewAnnotations?: Entry[];
+
+ storyIndexers?: StoryIndexer[];
+
+ experimental_indexers?: Indexer[];
+
+ docs?: DocsOptions;
+
+ previewHead?: string;
+
+ previewBody?: string;
+
+ previewMainTemplate?: string;
+
+ managerHead?: string;
+}
+
+/**
+ * The interface for Storybook configuration in `main.ts` files.
+ * This interface is public
+ * All values should be wrapped with `PresetValue<>`, though there are a few exceptions: `addons`, `framework`
+ */
+export interface StorybookConfig {
+ /**
+ * Sets the addons you want to use with Storybook.
+ *
+ * @example `['@storybook/addon-essentials']` or `[{ name: '@storybook/addon-essentials', options: { backgrounds: false } }]`
+ */
+ addons?: StorybookConfigRaw['addons'];
+ core?: PresetValue;
+ /**
+ * Sets a list of directories of static files to be loaded by Storybook server
+ *
+ * @example `['./public']` or `[{from: './public', 'to': '/assets'}]`
+ */
+ staticDirs?: PresetValue;
+ logLevel?: PresetValue;
+ features?: PresetValue;
+
+ build?: PresetValue;
+
/**
* Tells Storybook where to find stories.
*
- * @example `['./src/*.stories.@(j|t)sx?']`
+ * @example `['./src/*.stories.@(j|t)sx?']` or `async () => [...(await myCustomStoriesEntryBuilderFunc())]`
*/
- stories: StoriesEntry[];
+ stories: PresetValue;
/**
* Framework, e.g. '@storybook/react-vite', required in v7
*/
- framework?: Preset;
+ framework?: StorybookConfigRaw['framework'];
/**
* Controls how Storybook handles TypeScript files.
*/
- typescript?: Partial;
+ typescript?: PresetValue;
/**
* References external Storybooks
*/
- refs?: PresetValue;
+ refs?: PresetValue;
/**
* Modify or return babel config.
*/
- babel?: (config: BabelOptions, options: Options) => BabelOptions | Promise;
+ babel?: PresetValue;
/**
* Modify or return swc config.
*/
- swc?: (config: SWCOptions, options: Options) => SWCOptions | Promise;
+ swc?: PresetValue;
/**
* Modify or return env config.
*/
- env?: PresetValue>;
+ env?: PresetValue;
/**
* Modify or return babel config.
*/
- babelDefault?: (config: BabelOptions, options: Options) => BabelOptions | Promise;
+ babelDefault?: PresetValue;
/**
* Add additional scripts to run in the preview a la `.storybook/preview.js`
*
* @deprecated use `previewAnnotations` or `/preview.js` file instead
*/
- config?: PresetValue;
+ config?: PresetValue;
/**
* Add additional scripts to run in the preview a la `.storybook/preview.js`
*/
- previewAnnotations?: PresetValue;
+ previewAnnotations?: PresetValue;
/**
* Process CSF files for the story index.
* @deprecated use {@link experimental_indexers} instead
*/
- storyIndexers?: PresetValue;
+ storyIndexers?: PresetValue;
/**
* Process CSF files for the story index.
*/
- experimental_indexers?: PresetValue;
+ experimental_indexers?: PresetValue;
/**
* Docs related features in index generation
*/
- docs?: DocsOptions;
+ docs?: PresetValue;
/**
* Programmatically modify the preview head/body HTML.
* The previewHead and previewBody functions accept a string,
* which is the existing head/body, and return a modified string.
*/
- previewHead?: PresetValue;
+ previewHead?: PresetValue;
- previewBody?: PresetValue;
+ previewBody?: PresetValue;
/**
* Programmatically override the preview's main page template.
@@ -461,23 +544,23 @@ export interface StorybookConfig {
*
* @example '.storybook/index.ejs'
*/
- previewMainTemplate?: string;
+ previewMainTemplate?: PresetValue;
/**
* Programmatically modify the preview head/body HTML.
* The managerHead function accept a string,
* which is the existing head content, and return a modified string.
*/
- managerHead?: PresetValue;
+ managerHead?: PresetValue;
}
export type PresetValue = T | ((config: T, options: Options) => T | Promise);
-export type PresetProperty =
+export type PresetProperty =
| TStorybookConfig[K extends keyof TStorybookConfig ? K : never]
| PresetPropertyFn;
-export type PresetPropertyFn = (
+export type PresetPropertyFn = (
config: TStorybookConfig[K extends keyof TStorybookConfig ? K : never],
options: Options & TOptions
) =>
diff --git a/code/package.json b/code/package.json
index 4dbcb9ebd4a9..52557059656c 100644
--- a/code/package.json
+++ b/code/package.json
@@ -113,29 +113,21 @@
"@storybook/addon-mdx-gfm": "workspace:*",
"@storybook/addon-measure": "workspace:*",
"@storybook/addon-outline": "workspace:*",
- "@storybook/addon-storyshots": "workspace:*",
- "@storybook/addon-storyshots-puppeteer": "workspace:*",
"@storybook/addon-storysource": "workspace:*",
"@storybook/addon-toolbars": "workspace:*",
"@storybook/addon-viewport": "workspace:*",
- "@storybook/addons": "workspace:*",
"@storybook/angular": "workspace:*",
- "@storybook/api": "workspace:*",
"@storybook/babel-plugin-require-context-hook": "1.0.1",
"@storybook/bench": "next",
"@storybook/blocks": "workspace:*",
"@storybook/builder-manager": "workspace:*",
"@storybook/builder-vite": "workspace:*",
"@storybook/builder-webpack5": "workspace:*",
- "@storybook/channel-postmessage": "workspace:*",
- "@storybook/channel-websocket": "workspace:*",
"@storybook/channels": "workspace:*",
"@storybook/cli": "workspace:*",
- "@storybook/client-api": "workspace:*",
"@storybook/client-logger": "workspace:*",
"@storybook/codemod": "workspace:*",
"@storybook/components": "workspace:*",
- "@storybook/core-client": "workspace:*",
"@storybook/core-common": "workspace:*",
"@storybook/core-events": "workspace:*",
"@storybook/core-server": "workspace:*",
@@ -172,7 +164,6 @@
"@storybook/preset-web-components-webpack": "workspace:*",
"@storybook/preview": "workspace:*",
"@storybook/preview-api": "workspace:*",
- "@storybook/preview-web": "workspace:*",
"@storybook/react": "workspace:*",
"@storybook/react-vite": "workspace:*",
"@storybook/react-webpack5": "workspace:*",
@@ -180,7 +171,6 @@
"@storybook/server": "workspace:*",
"@storybook/server-webpack5": "workspace:*",
"@storybook/source-loader": "workspace:*",
- "@storybook/store": "workspace:*",
"@storybook/svelte": "workspace:*",
"@storybook/svelte-webpack5": "workspace:*",
"@storybook/telemetry": "workspace:*",
@@ -199,14 +189,15 @@
"@swc/jest": "^0.2.26",
"@testing-library/dom": "^7.29.4",
"@testing-library/jest-dom": "^5.11.9",
- "@testing-library/react": "^11.2.2",
- "@testing-library/user-event": "^13.2.1",
+ "@testing-library/react": "^14.0.0",
+ "@testing-library/user-event": "^14.4.3",
"@types/express": "^4.17.11",
"@types/fs-extra": "^11.0.1",
+ "@types/jest-specific-snapshot": "^0.5.6",
"@types/lodash": "^4.14.167",
"@types/node": "^18.0.0",
- "@types/react": "^16.14.34",
- "@types/react-dom": "^16.9.14",
+ "@types/react": "^18.0.37",
+ "@types/react-dom": "^18.0.11",
"@types/semver": "^7.3.4",
"@types/serve-static": "^1.13.8",
"@typescript-eslint/eslint-plugin": "^5.45.0",
@@ -227,7 +218,7 @@
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-local-rules": "portal:../scripts/eslint-plugin-local-rules",
"eslint-plugin-react": "^7.31.10",
- "eslint-plugin-storybook": "^0.6.6",
+ "eslint-plugin-storybook": "^0.6.15",
"fs-extra": "^11.1.0",
"github-release-from-changelog": "^2.1.1",
"glob": "^10.0.0",
@@ -235,10 +226,10 @@
"husky": "^4.3.7",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.5.0",
- "jest-image-snapshot": "^6.0.0",
"jest-junit": "^16.0.0",
"jest-os-detection": "^1.3.1",
"jest-serializer-html": "^7.1.0",
+ "jest-specific-snapshot": "^8.0.0",
"jest-watch-typeahead": "^2.2.1",
"lint-staged": "^13.2.2",
"lodash": "^4.17.21",
@@ -247,13 +238,14 @@
"prettier": "2.8.0",
"process": "^0.11.10",
"raf": "^3.4.1",
- "react": "^16.14.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
"semver": "^7.3.7",
"serve-static": "^1.14.1",
"trash": "^7.0.0",
"ts-dedent": "^2.0.0",
"ts-node": "^10.9.1",
- "typescript": "~4.9.3",
+ "typescript": "^5.3.2",
"util": "^0.12.4",
"vite": "^4.0.0",
"vite-plugin-turbosnap": "^1.0.1",
@@ -328,5 +320,6 @@
"Dependency Upgrades"
]
]
- }
+ },
+ "deferredNextVersion": "8.0.0-alpha.0"
}
diff --git a/code/presets/create-react-app/package.json b/code/presets/create-react-app/package.json
index 572e6403ae72..8d71fdb45ac6 100644
--- a/code/presets/create-react-app/package.json
+++ b/code/presets/create-react-app/package.json
@@ -59,7 +59,7 @@
"devDependencies": {
"@storybook/node-logger": "workspace:*",
"@types/node": "^18.0.0",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"peerDependencies": {
"@babel/core": "*",
diff --git a/code/presets/create-react-app/src/helpers/checkPresets.ts b/code/presets/create-react-app/src/helpers/checkPresets.ts
index 38d11839343c..2827dab51f58 100644
--- a/code/presets/create-react-app/src/helpers/checkPresets.ts
+++ b/code/presets/create-react-app/src/helpers/checkPresets.ts
@@ -7,7 +7,7 @@ const incompatiblePresets = ['@storybook/preset-scss', '@storybook/preset-typesc
export const checkPresets = (options: PluginOptions): void => {
const { presetsList } = options;
- presetsList.forEach((preset: string | { name: string }) => {
+ presetsList?.forEach((preset: string | { name: string }) => {
const presetName = typeof preset === 'string' ? preset : preset.name;
if (incompatiblePresets.includes(presetName)) {
logger.warn(
diff --git a/code/presets/create-react-app/src/helpers/mergePlugins.ts b/code/presets/create-react-app/src/helpers/mergePlugins.ts
index 4c3ff84ead18..c5fc7888674e 100644
--- a/code/presets/create-react-app/src/helpers/mergePlugins.ts
+++ b/code/presets/create-react-app/src/helpers/mergePlugins.ts
@@ -1,18 +1,19 @@
-import type { Configuration } from 'webpack';
+import type { Configuration, WebpackPluginInstance } from 'webpack';
import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
-export const mergePlugins = (...args: Configuration['plugins']): Configuration['plugins'] =>
- args.reduce((plugins, plugin) => {
+export const mergePlugins = (...args: WebpackPluginInstance[]): Configuration['plugins'] =>
+ args?.reduce((plugins, plugin) => {
if (
- plugins.some(
- (includedPlugin) => includedPlugin.constructor.name === plugin.constructor.name
+ plugins?.some(
+ (includedPlugin: WebpackPluginInstance) =>
+ includedPlugin?.constructor.name === plugin?.constructor.name
) ||
- plugin.constructor.name === 'WebpackManifestPlugin'
+ plugin?.constructor.name === 'WebpackManifestPlugin'
) {
return plugins;
}
let updatedPlugin = plugin;
- if (plugin.constructor.name === 'ReactRefreshPlugin') {
+ if (plugin?.constructor.name === 'ReactRefreshPlugin') {
// Storybook uses webpack-hot-middleware
// https://github.com/storybookjs/presets/issues/177
@@ -22,5 +23,5 @@ export const mergePlugins = (...args: Configuration['plugins']): Configuration['
},
});
}
- return [...plugins, updatedPlugin];
- }, [] as Configuration['plugins']);
+ return [...(plugins ?? []), updatedPlugin];
+ }, [] as WebpackPluginInstance[]);
diff --git a/code/presets/create-react-app/src/helpers/processCraConfig.ts b/code/presets/create-react-app/src/helpers/processCraConfig.ts
index 25024ada0351..b0931784cf5a 100644
--- a/code/presets/create-react-app/src/helpers/processCraConfig.ts
+++ b/code/presets/create-react-app/src/helpers/processCraConfig.ts
@@ -19,10 +19,10 @@ const testMatch = (rule: RuleSetRule, string: string): boolean => {
: isRegExp(rule.test) && rule.test.test(string);
};
-export const processCraConfig = (
+export const processCraConfig = async (
craWebpackConfig: Configuration,
options: PluginOptions
-): RuleSetRule[] => {
+): Promise => {
const configDir = resolve(options.configDir);
/*
@@ -37,9 +37,11 @@ export const processCraConfig = (
*/
const storybookVersion = semver.coerce(options.packageJson.version) || '';
const isStorybook530 = semver.gte(storybookVersion, '5.3.0');
+ const babelOptions = await options.presets.apply('babel');
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- return craWebpackConfig.module!.rules.reduce((rules, rule): RuleSetRule[] => {
+ if (!craWebpackConfig?.module?.rules) return [];
+
+ return craWebpackConfig.module.rules.reduce((rules, rule): RuleSetRule[] => {
const { oneOf, include } = rule as RuleSetRule;
// Add our `configDir` to support JSX and TypeScript in that folder.
@@ -61,6 +63,7 @@ export const processCraConfig = (
return [
...rules,
{
+ // @ts-expect-error (not type correct)
oneOf: oneOf.map((oneOfRule: RuleSetRule): RuleSetRule => {
if (oneOfRule.type === 'asset/resource') {
if (isStorybook530) {
@@ -108,12 +111,7 @@ export const processCraConfig = (
overrides: TransformOptions[] | null;
};
- const {
- extends: _extends,
- plugins,
- presets,
- overrides,
- } = (options as any).babelOptions;
+ const { extends: _extends, plugins, presets, overrides } = babelOptions;
return {
...oneOfRule,
diff --git a/code/presets/create-react-app/src/index.ts b/code/presets/create-react-app/src/index.ts
index e480e438ef91..e47c824426ce 100644
--- a/code/presets/create-react-app/src/index.ts
+++ b/code/presets/create-react-app/src/index.ts
@@ -1,6 +1,6 @@
/* eslint-disable import/no-extraneous-dependencies */
import { join, relative, dirname } from 'path';
-import type { Configuration, RuleSetRule } from 'webpack';
+import type { Configuration, RuleSetRule, WebpackPluginInstance } from 'webpack';
import semver from 'semver';
import { logger } from '@storybook/node-logger';
import PnpWebpackPlugin from 'pnp-webpack-plugin';
@@ -10,7 +10,7 @@ import { getReactScriptsPath } from './helpers/getReactScriptsPath';
import { processCraConfig } from './helpers/processCraConfig';
import { checkPresets } from './helpers/checkPresets';
import { getModulePath } from './helpers/getModulePath';
-import type { PluginOptions, CoreConfig } from './types';
+import type { PluginOptions } from './types';
const CWD = process.cwd();
@@ -78,12 +78,13 @@ const webpack = async (
// Remove existing rules related to JavaScript and TypeScript.
logger.info(`=> Removing existing JavaScript and TypeScript rules.`);
- const filteredRules =
- webpackConfig.module &&
- webpackConfig.module.rules.filter(
- ({ test }: RuleSetRule) =>
- !(test instanceof RegExp && ((test && test.test('.js')) || test.test('.ts')))
- );
+ const filteredRules = (webpackConfig.module?.rules as RuleSetRule[])?.filter((rule) => {
+ if (typeof rule === 'string') {
+ return false;
+ }
+ const { test } = rule;
+ return !(test instanceof RegExp && (test?.test('.js') || test?.test('.ts')));
+ });
// Require the CRA config and set the appropriate mode.
const craWebpackConfigPath = join(scriptsPath, 'config', 'webpack.config');
@@ -92,7 +93,7 @@ const webpack = async (
// Select the relevant CRA rules and add the Storybook config directory.
logger.info(`=> Modifying Create React App rules.`);
- const craRules = processCraConfig(craWebpackConfig, options);
+ const craRules = await processCraConfig(craWebpackConfig, options);
// NOTE: These are set by default in Storybook 6.
const isStorybook6 = semver.gte(options.packageJson.version || '', '6.0.0');
@@ -113,8 +114,9 @@ const webpack = async (
// We need to figure out a better way to apply various layers of webpack config; perhaps
// these options need to be in a separate preset.
const isProd = webpackConfig.mode !== 'development';
- const coreOptions = await options.presets.apply('core');
- const builderOptions = coreOptions?.builder?.options;
+ const coreOptions = await options.presets.apply('core');
+ const builder = coreOptions?.builder;
+ const builderOptions = typeof builder === 'string' ? {} : builder?.options;
const cacheConfig = builderOptions?.fsCache ? { cache: { type: 'filesystem' } } : {};
const lazyCompilationConfig =
builderOptions?.lazyCompilation && !isProd
@@ -133,8 +135,8 @@ const webpack = async (
// NOTE: this prioritizes the storybook version of a plugin
// when there are duplicates between SB and CRA
plugins: mergePlugins(
- ...(webpackConfig.plugins || []),
- ...(craWebpackConfig.plugins ?? []),
+ ...((webpackConfig.plugins ?? []) as WebpackPluginInstance[]),
+ ...((craWebpackConfig.plugins ?? []) as WebpackPluginInstance[]),
...tsDocgenPlugin
),
resolve: {
diff --git a/code/presets/create-react-app/tsconfig.json b/code/presets/create-react-app/tsconfig.json
index a7d41e8a79b5..a4429176e35f 100644
--- a/code/presets/create-react-app/tsconfig.json
+++ b/code/presets/create-react-app/tsconfig.json
@@ -1,7 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
- "strict": false
+ "strict": true
},
"include": ["src/**/*"]
}
diff --git a/code/presets/html-webpack/README.md b/code/presets/html-webpack/README.md
index dd70fe593868..3fa497407563 100644
--- a/code/presets/html-webpack/README.md
+++ b/code/presets/html-webpack/README.md
@@ -3,4 +3,4 @@
This package is a [preset](https://storybook.js.org/docs/html/addons/writing-presets#presets-api) that configures Storybook's webpack settings for handling HTML.
It's an internal package that's not intended to be used directly by users.
-- More info on [Storybook for HTML](https://storybook.js.org/docs/html/get-started/introduction)
+- More info on [Storybook for HTML](https://storybook.js.org/docs/html/get-started)
diff --git a/code/presets/html-webpack/package.json b/code/presets/html-webpack/package.json
index c7f77e9f4036..8275ea254ce9 100644
--- a/code/presets/html-webpack/package.json
+++ b/code/presets/html-webpack/package.json
@@ -55,7 +55,7 @@
"webpack": "5"
},
"devDependencies": {
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"peerDependencies": {
"@babel/core": "*"
diff --git a/code/presets/preact-webpack/README.md b/code/presets/preact-webpack/README.md
index 3afe613128d0..5ac103fdd029 100644
--- a/code/presets/preact-webpack/README.md
+++ b/code/presets/preact-webpack/README.md
@@ -3,4 +3,4 @@
This package is a [preset](https://storybook.js.org/docs/preact/addons/writing-presets#presets-api) that configures Storybook's webpack settings for handling Preact.
It's an internal package that's not intended to be used directly by users.
-- More info on [Storybook for Preact](https://storybook.js.org/docs/preact/get-started/introduction)
+- More info on [Storybook for Preact](https://storybook.js.org/docs/preact/get-started)
diff --git a/code/presets/preact-webpack/package.json b/code/presets/preact-webpack/package.json
index c6ec5dcbb041..55a133f502aa 100644
--- a/code/presets/preact-webpack/package.json
+++ b/code/presets/preact-webpack/package.json
@@ -56,7 +56,7 @@
},
"devDependencies": {
"preact": "^10.5.13",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"peerDependencies": {
"@babel/core": "*",
diff --git a/code/presets/preact-webpack/src/index.ts b/code/presets/preact-webpack/src/index.ts
index e6cb9524dca3..807098909d49 100644
--- a/code/presets/preact-webpack/src/index.ts
+++ b/code/presets/preact-webpack/src/index.ts
@@ -1,4 +1,5 @@
import { dirname, join } from 'path';
+import type { PresetProperty } from '@storybook/types';
import type { StorybookConfig } from './types';
export * from './types';
@@ -6,7 +7,7 @@ export * from './types';
const getAbsolutePath = (input: I): I =>
dirname(require.resolve(join(input, 'package.json'))) as any;
-export const babel: StorybookConfig['babelDefault'] = (config) => {
+export const babel: PresetProperty<'babel'> = (config) => {
return {
...config,
plugins: [
@@ -14,7 +15,7 @@ export const babel: StorybookConfig['babelDefault'] = (config) => {
require.resolve('@babel/plugin-transform-react-jsx'),
{ importSource: 'preact', runtime: 'automatic' },
],
- ...(config.plugins || []).filter((p) => {
+ ...(config?.plugins || []).filter((p) => {
const name = Array.isArray(p) ? p[0] : p;
if (typeof name === 'string') {
return !name.includes('plugin-transform-react-jsx');
@@ -48,7 +49,7 @@ export const webpackFinal: StorybookConfig['webpackFinal'] = (config) => {
};
};
-export const swc: StorybookConfig['swc'] = (config) => {
+export const swc: PresetProperty<'swc'> = (config) => {
const isDevelopment = process.env.NODE_ENV !== 'production';
return {
diff --git a/code/presets/react-webpack/README.md b/code/presets/react-webpack/README.md
index 43fa9210cdee..74e2ad35024f 100644
--- a/code/presets/react-webpack/README.md
+++ b/code/presets/react-webpack/README.md
@@ -3,4 +3,4 @@
This package is a [preset](https://storybook.js.org/docs/react/addons/writing-presets#presets-api) that configures Storybook's webpack settings for handling React.
It's an internal package that's not intended to be used directly by users.
-- More info on [Storybook for React](https://storybook.js.org/docs/react/get-started/introduction)
+- More info on [Storybook for React](https://storybook.js.org/docs/react/get-started)
diff --git a/code/presets/react-webpack/package.json b/code/presets/react-webpack/package.json
index 395de20f8f17..0f3780b86551 100644
--- a/code/presets/react-webpack/package.json
+++ b/code/presets/react-webpack/package.json
@@ -88,7 +88,7 @@
"webpack": "5"
},
"devDependencies": {
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"peerDependencies": {
"@babel/core": "^7.22.0",
diff --git a/code/presets/react-webpack/src/framework-preset-react-docs.test.ts b/code/presets/react-webpack/src/framework-preset-react-docs.test.ts
index 9ec5fd3bd029..e3dac587cb54 100644
--- a/code/presets/react-webpack/src/framework-preset-react-docs.test.ts
+++ b/code/presets/react-webpack/src/framework-preset-react-docs.test.ts
@@ -18,11 +18,23 @@ describe('framework-preset-react-docgen', () => {
const config = await preset.webpackFinal?.(webpackConfig, {
presets: {
- apply: async () =>
- ({
- check: false,
- reactDocgen: 'react-docgen',
- } as Partial),
+ apply: async (name: string) => {
+ if (name === 'typescript') {
+ return {
+ check: false,
+ reactDocgen: 'react-docgen',
+ } as Partial;
+ }
+
+ if (name === 'babel') {
+ return {
+ plugins: [],
+ presets: [],
+ };
+ }
+
+ return undefined;
+ },
},
presetsList: presetsListWithDocs,
} as any);
@@ -33,6 +45,7 @@ describe('framework-preset-react-docgen', () => {
{
exclude: /node_modules\/.*/,
loader: '@storybook/preset-react-webpack/dist/loaders/react-docgen-loader',
+ options: { babelOptions: { plugins: [], presets: [] } },
test: /\.(cjs|mjs|tsx?|jsx?)$/,
},
],
@@ -50,11 +63,23 @@ describe('framework-preset-react-docgen', () => {
const config = await preset.webpackFinal?.(webpackConfig, {
presets: {
// @ts-expect-error (not strict)
- apply: async () =>
- ({
- check: false,
- reactDocgen: 'react-docgen-typescript',
- } as Partial),
+ apply: async (name: string) => {
+ if (name === 'typescript') {
+ return {
+ check: false,
+ reactDocgen: 'react-docgen-typescript',
+ } as Partial;
+ }
+
+ if (name === 'babel') {
+ return {
+ plugins: [],
+ presets: [],
+ };
+ }
+
+ return undefined;
+ },
},
presetsList: presetsListWithDocs,
});
@@ -65,6 +90,7 @@ describe('framework-preset-react-docgen', () => {
{
exclude: /node_modules\/.*/,
loader: '@storybook/preset-react-webpack/dist/loaders/react-docgen-loader',
+ options: { babelOptions: { plugins: [], presets: [] } },
test: /\.(cjs|mjs|jsx?)$/,
},
],
diff --git a/code/presets/react-webpack/src/framework-preset-react-docs.ts b/code/presets/react-webpack/src/framework-preset-react-docs.ts
index 3538c2c8dbad..1260d08eaf40 100644
--- a/code/presets/react-webpack/src/framework-preset-react-docs.ts
+++ b/code/presets/react-webpack/src/framework-preset-react-docs.ts
@@ -10,10 +10,7 @@ export const webpackFinal: StorybookConfig['webpackFinal'] = async (
): Promise => {
if (!hasDocsOrControls(options)) return config;
- const typescriptOptions = await options.presets.apply(
- 'typescript',
- {} as any
- );
+ const typescriptOptions = await options.presets.apply('typescript', {} as any);
const { reactDocgen, reactDocgenTypescriptOptions } = typescriptOptions || {};
@@ -22,6 +19,7 @@ export const webpackFinal: StorybookConfig['webpackFinal'] = async (
}
if (reactDocgen !== 'react-docgen-typescript') {
+ const babelOptions = await options.presets.apply('babel', {});
return {
...config,
module: {
@@ -34,6 +32,9 @@ export const webpackFinal: StorybookConfig['webpackFinal'] = async (
require.resolve,
'@storybook/preset-react-webpack/dist/loaders/react-docgen-loader'
),
+ options: {
+ babelOptions,
+ },
exclude: /node_modules\/.*/,
},
],
@@ -43,6 +44,8 @@ export const webpackFinal: StorybookConfig['webpackFinal'] = async (
const { ReactDocgenTypeScriptPlugin } = await import('@storybook/react-docgen-typescript-plugin');
+ const babelOptions = await options.presets.apply('babel', {});
+
return {
...config,
module: {
@@ -55,6 +58,9 @@ export const webpackFinal: StorybookConfig['webpackFinal'] = async (
require.resolve,
'@storybook/preset-react-webpack/dist/loaders/react-docgen-loader'
),
+ options: {
+ babelOptions,
+ },
exclude: /node_modules\/.*/,
},
],
diff --git a/code/presets/react-webpack/src/framework-preset-react.ts b/code/presets/react-webpack/src/framework-preset-react.ts
index 65da5b9825aa..a3a1d273189c 100644
--- a/code/presets/react-webpack/src/framework-preset-react.ts
+++ b/code/presets/react-webpack/src/framework-preset-react.ts
@@ -4,6 +4,7 @@ import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
import { logger } from '@storybook/node-logger';
import type { Options, Preset } from '@storybook/core-webpack';
+import type { PresetProperty, PresetPropertyFn } from 'lib/types/dist';
import type { StorybookConfig, ReactOptions } from './types';
const getAbsolutePath = (input: I): I =>
@@ -16,14 +17,14 @@ const applyFastRefresh = async (options: Options) => {
return isDevelopment && (reactOptions.fastRefresh || process.env.FAST_REFRESH === 'true');
};
-export const babel: StorybookConfig['babel'] = async (config, options) => {
+export const babel: PresetPropertyFn<'babel'> = async (config, options) => {
if (!(await applyFastRefresh(options))) return config;
return {
...config,
plugins: [
[require.resolve('react-refresh/babel'), {}, 'storybook-react-refresh'],
- ...(config.plugins || []),
+ ...(config?.plugins || []),
],
};
};
@@ -42,7 +43,7 @@ const hasJsxRuntime = () => {
}
};
-export const babelDefault: StorybookConfig['babelDefault'] = async (config) => {
+export const babelDefault: PresetPropertyFn<'babelDefault'> = async (config) => {
const presetReactOptions = hasJsxRuntime() ? { runtime: 'automatic' } : {};
return {
...config,
@@ -84,7 +85,7 @@ export const webpackFinal: StorybookConfig['webpackFinal'] = async (config, opti
};
};
-export const swc: StorybookConfig['swc'] = async (config, options) => {
+export const swc: PresetProperty<'swc'> = async (config, options) => {
const isDevelopment = options.configType !== 'PRODUCTION';
if (!(await applyFastRefresh(options))) {
diff --git a/code/presets/react-webpack/src/index.ts b/code/presets/react-webpack/src/index.ts
index f1a4332fbbd4..22ce14617df4 100644
--- a/code/presets/react-webpack/src/index.ts
+++ b/code/presets/react-webpack/src/index.ts
@@ -1,8 +1,8 @@
-import type { StorybookConfig } from './types';
+import type { PresetProperty } from '@storybook/types';
export * from './types';
-export const addons: StorybookConfig['addons'] = [
+export const addons: PresetProperty<'addons'> = [
require.resolve('@storybook/preset-react-webpack/dist/framework-preset-react'),
require.resolve('@storybook/preset-react-webpack/dist/framework-preset-cra'),
require.resolve('@storybook/preset-react-webpack/dist/framework-preset-react-docs'),
diff --git a/code/presets/react-webpack/src/loaders/react-docgen-loader.ts b/code/presets/react-webpack/src/loaders/react-docgen-loader.ts
index 279840739014..aa1724fd880f 100644
--- a/code/presets/react-webpack/src/loaders/react-docgen-loader.ts
+++ b/code/presets/react-webpack/src/loaders/react-docgen-loader.ts
@@ -58,6 +58,11 @@ const handlers = [...defaultHandlers, actualNameHandler];
export default async function reactDocgenLoader(this: LoaderContext, source: string) {
const callback = this.async();
+ // get options
+ const options = this.getOptions() || {};
+ const { babelOptions = {} } = options;
+
+ const { plugins, presets } = babelOptions;
try {
const docgenResults = parse(source, {
@@ -65,6 +70,12 @@ export default async function reactDocgenLoader(this: LoaderContext, source
resolver: defaultResolver,
handlers,
importer: defaultImporter,
+ babelOptions: {
+ babelrc: false,
+ configFile: false,
+ plugins,
+ presets,
+ },
}) as DocObj[];
const magicString = new MagicString(source);
diff --git a/code/presets/react-webpack/src/typings.d.ts b/code/presets/react-webpack/src/typings.d.ts
deleted file mode 100644
index 53aa2b04a775..000000000000
--- a/code/presets/react-webpack/src/typings.d.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-// TODO: Replace, as soon as @types/react-dom 17.0.14 is used
-// Source: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/fb0f14b7a35cde26ffaa82e7536c062e593e9ae6/types/react-dom/client.d.ts
-declare module 'react-dom/client' {
- import React = require('react');
-
- export interface HydrationOptions {
- onHydrated?(suspenseInstance: Comment): void;
- onDeleted?(suspenseInstance: Comment): void;
- /**
- * Prefix for `useId`.
- */
- identifierPrefix?: string;
- onRecoverableError?: (error: unknown) => void;
- }
-
- export interface RootOptions {
- /**
- * Prefix for `useId`.
- */
- identifierPrefix?: string;
- onRecoverableError?: (error: unknown) => void;
- }
-
- export interface Root {
- render(children: React.ReactChild | Iterable): void;
- unmount(): void;
- }
-
- /**
- * Replaces `ReactDOM.render` when the `.render` method is called and enables Concurrent Mode.
- *
- * @see https://reactjs.org/docs/concurrent-mode-reference.html#createroot
- */
- export function createRoot(
- container: Element | Document | DocumentFragment | Comment,
- options?: RootOptions
- ): Root;
-
- export function hydrateRoot(
- container: Element | Document | DocumentFragment | Comment,
- initialChildren: React.ReactChild | Iterable,
- options?: HydrationOptions
- ): Root;
-}
diff --git a/code/presets/server-webpack/package.json b/code/presets/server-webpack/package.json
index de79e80f712a..a85412312c48 100644
--- a/code/presets/server-webpack/package.json
+++ b/code/presets/server-webpack/package.json
@@ -66,7 +66,7 @@
"devDependencies": {
"fs-extra": "^11.1.0",
"jest-specific-snapshot": "^8.0.0",
- "typescript": "~4.9.3",
+ "typescript": "^5.3.2",
"yaml": "^2.3.1"
},
"engines": {
diff --git a/code/presets/svelte-webpack/README.md b/code/presets/svelte-webpack/README.md
index 2cf2606a3b91..b2d6cd5e9035 100644
--- a/code/presets/svelte-webpack/README.md
+++ b/code/presets/svelte-webpack/README.md
@@ -3,4 +3,4 @@
This package is a [preset](https://storybook.js.org/docs/svelte/addons/writing-presets#presets-api) that configures Storybook's webpack settings for handling Svelte.
It's an internal package that's not intended to be used directly by users.
-- More info on [Storybook for Svelte](https://storybook.js.org/docs/svelte/get-started/introduction)
+- More info on [Storybook for Svelte](https://storybook.js.org/docs/svelte/get-started)
diff --git a/code/presets/svelte-webpack/package.json b/code/presets/svelte-webpack/package.json
index 87475344aaf1..65794c0dde8d 100644
--- a/code/presets/svelte-webpack/package.json
+++ b/code/presets/svelte-webpack/package.json
@@ -72,7 +72,7 @@
"devDependencies": {
"svelte": "^4.0.0",
"svelte-loader": "^3.1.9",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"peerDependencies": {
"@babel/core": "*",
diff --git a/code/presets/svelte-webpack/src/framework-preset-svelte.ts b/code/presets/svelte-webpack/src/framework-preset-svelte.ts
index b82680721fff..89b2c24f81eb 100644
--- a/code/presets/svelte-webpack/src/framework-preset-svelte.ts
+++ b/code/presets/svelte-webpack/src/framework-preset-svelte.ts
@@ -1,4 +1,4 @@
-import type { Preset } from '@storybook/types';
+import type { Preset, PresetProperty } from '@storybook/types';
import type { StorybookConfig, SvelteOptions } from './types';
export const webpack: StorybookConfig['webpack'] = async (config, { presets }) => {
@@ -29,7 +29,7 @@ export const webpack: StorybookConfig['webpack'] = async (config, { presets }) =
};
};
-export const babelDefault: StorybookConfig['babelDefault'] = (config) => {
+export const babelDefault: PresetProperty<'babelDefault'> = (config) => {
return {
...config,
presets: [...(config?.presets || [])],
diff --git a/code/presets/svelte-webpack/src/index.ts b/code/presets/svelte-webpack/src/index.ts
index 1ff749f3285e..f6da040e368e 100644
--- a/code/presets/svelte-webpack/src/index.ts
+++ b/code/presets/svelte-webpack/src/index.ts
@@ -1,8 +1,8 @@
-import type { StorybookConfig } from './types';
+import type { PresetProperty } from '@storybook/types';
export * from './types';
-export const addons: StorybookConfig['addons'] = [
+export const addons: PresetProperty<'addons'> = [
require.resolve('@storybook/preset-svelte-webpack/dist/framework-preset-svelte'),
require.resolve('@storybook/preset-svelte-webpack/dist/framework-preset-svelte-docs'),
];
diff --git a/code/presets/vue-webpack/README.md b/code/presets/vue-webpack/README.md
index 17acb9801107..1e301b010570 100644
--- a/code/presets/vue-webpack/README.md
+++ b/code/presets/vue-webpack/README.md
@@ -3,4 +3,4 @@
This package is a [preset](https://storybook.js.org/docs/vue/addons/writing-presets#presets-api) that configures Storybook's webpack settings for handling Vue.
It's an internal package that's not intended to be used directly by users.
-- More info on [Storybook for Vue](https://storybook.js.org/docs/vue/get-started/introduction)
+- More info on [Storybook for Vue](https://storybook.js.org/docs/vue/get-started)
diff --git a/code/presets/vue-webpack/package.json b/code/presets/vue-webpack/package.json
index b2ae724e9057..09e7cad20284 100644
--- a/code/presets/vue-webpack/package.json
+++ b/code/presets/vue-webpack/package.json
@@ -68,7 +68,7 @@
"webpack": "5"
},
"devDependencies": {
- "typescript": "~4.9.3",
+ "typescript": "^5.3.2",
"vue": "^2.6.12",
"vue-loader": "^15.7.0",
"vue-template-compiler": "^2.6.14",
diff --git a/code/presets/vue-webpack/src/framework-preset-vue.ts b/code/presets/vue-webpack/src/framework-preset-vue.ts
index 4546bb359e43..6938d4ab5217 100644
--- a/code/presets/vue-webpack/src/framework-preset-vue.ts
+++ b/code/presets/vue-webpack/src/framework-preset-vue.ts
@@ -4,7 +4,7 @@ import { VueLoaderPlugin } from 'vue-loader';
import type { StorybookConfig } from '@storybook/core-webpack';
export const webpack: StorybookConfig['webpack'] = async (config, { presets }) => {
- const typescriptOptions = await presets.apply('typescript', {});
+ const typescriptOptions = await presets.apply('typescript', {});
config.plugins?.push(new VueLoaderPlugin());
config.module?.rules?.push({
diff --git a/code/presets/vue-webpack/src/index.ts b/code/presets/vue-webpack/src/index.ts
index 5e6768b64cf6..71b23495a8b2 100644
--- a/code/presets/vue-webpack/src/index.ts
+++ b/code/presets/vue-webpack/src/index.ts
@@ -1,8 +1,8 @@
-import type { StorybookConfig } from './types';
+import type { PresetProperty } from '@storybook/types';
export * from './types';
-export const addons: StorybookConfig['addons'] = [
+export const addons: PresetProperty<'addons'> = [
require.resolve('@storybook/preset-vue-webpack/dist/framework-preset-vue'),
require.resolve('@storybook/preset-vue-webpack/dist/framework-preset-vue-docs'),
];
diff --git a/code/presets/vue3-webpack/README.md b/code/presets/vue3-webpack/README.md
index aee6a93bb9fb..d600b0fa0eab 100644
--- a/code/presets/vue3-webpack/README.md
+++ b/code/presets/vue3-webpack/README.md
@@ -3,4 +3,4 @@
This package is a [preset](https://storybook.js.org/docs/vue/addons/writing-presets#presets-api) that configures Storybook's webpack settings for handling Vue3.
It's an internal package that's not intended to be used directly by users.
-- More info on [Storybook for Vue3](https://storybook.js.org/docs/vue/get-started/introduction)
+- More info on [Storybook for Vue3](https://storybook.js.org/docs/vue/get-started)
diff --git a/code/presets/vue3-webpack/package.json b/code/presets/vue3-webpack/package.json
index ad69ff5ec5cb..c1e5191b7421 100644
--- a/code/presets/vue3-webpack/package.json
+++ b/code/presets/vue3-webpack/package.json
@@ -70,7 +70,7 @@
},
"devDependencies": {
"@vue/compiler-sfc": "^3.2.33",
- "typescript": "~4.9.3",
+ "typescript": "^5.3.2",
"vue": "^3.2.33"
},
"peerDependencies": {
diff --git a/code/presets/vue3-webpack/src/index.ts b/code/presets/vue3-webpack/src/index.ts
index c628a37c635b..2990fc06db18 100644
--- a/code/presets/vue3-webpack/src/index.ts
+++ b/code/presets/vue3-webpack/src/index.ts
@@ -1,8 +1,8 @@
-import type { StorybookConfig } from './types';
+import type { PresetProperty } from '@storybook/types';
export * from './types';
-export const addons: StorybookConfig['addons'] = [
+export const addons: PresetProperty<'addons'> = [
require.resolve('@storybook/preset-vue3-webpack/dist/framework-preset-vue3'),
require.resolve('@storybook/preset-vue3-webpack/dist/framework-preset-vue3-docs'),
];
diff --git a/code/presets/web-components-webpack/README.md b/code/presets/web-components-webpack/README.md
index d2da44b36356..b3d65a886224 100644
--- a/code/presets/web-components-webpack/README.md
+++ b/code/presets/web-components-webpack/README.md
@@ -3,4 +3,4 @@
This package is a [preset](https://storybook.js.org/docs/web-components/addons/writing-presets#presets-api) that configures Storybook's webpack settings for handling Web components.
It's an internal package that's not intended to be used directly by users.
-- More info on [Storybook for Web components](https://storybook.js.org/docs/web-components/get-started/introduction)
+- More info on [Storybook for Web components](https://storybook.js.org/docs/web-components/get-started)
diff --git a/code/presets/web-components-webpack/package.json b/code/presets/web-components-webpack/package.json
index f0826256d3ae..5b0a123aa8a7 100644
--- a/code/presets/web-components-webpack/package.json
+++ b/code/presets/web-components-webpack/package.json
@@ -62,7 +62,7 @@
},
"devDependencies": {
"lit": "2.3.1",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"peerDependencies": {
"lit": "^2.0.0 || ^3.0.0"
diff --git a/code/renderers/html/package.json b/code/renderers/html/package.json
index cb4298dee141..f9c351e19088 100644
--- a/code/renderers/html/package.json
+++ b/code/renderers/html/package.json
@@ -47,7 +47,6 @@
"prep": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/bundle.ts"
},
"dependencies": {
- "@storybook/core-client": "workspace:*",
"@storybook/docs-tools": "workspace:*",
"@storybook/global": "^5.0.0",
"@storybook/preview-api": "workspace:*",
@@ -55,7 +54,7 @@
"ts-dedent": "^2.0.0"
},
"devDependencies": {
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"peerDependencies": {
"@babel/core": "*"
diff --git a/code/renderers/html/src/index.ts b/code/renderers/html/src/index.ts
index 0c37ede8d826..145fbf2612ea 100644
--- a/code/renderers/html/src/index.ts
+++ b/code/renderers/html/src/index.ts
@@ -2,7 +2,6 @@
import './globals';
-export * from './public-api';
export * from './public-types';
// optimization: stop HMR propagation in webpack
diff --git a/code/renderers/html/src/preset.ts b/code/renderers/html/src/preset.ts
index b60ba9208510..03b11e7e6097 100644
--- a/code/renderers/html/src/preset.ts
+++ b/code/renderers/html/src/preset.ts
@@ -1,7 +1,10 @@
-import type { StorybookConfig } from '@storybook/types';
+import type { PresetProperty } from '@storybook/types';
import { join } from 'path';
-export const previewAnnotations: StorybookConfig['previewAnnotations'] = async (input, options) => {
+export const previewAnnotations: PresetProperty<'previewAnnotations'> = async (
+ input = [],
+ options
+) => {
const docsEnabled = Object.keys(await options.presets.apply('docs', {}, options)).length > 0;
const result: string[] = [];
diff --git a/code/renderers/html/src/public-api.ts b/code/renderers/html/src/public-api.ts
deleted file mode 100644
index 542eb1ca7b65..000000000000
--- a/code/renderers/html/src/public-api.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-/* eslint-disable prefer-destructuring */
-import type { Addon_ClientStoryApi, Addon_Loadable } from '@storybook/types';
-import { start } from '@storybook/preview-api';
-import type { HtmlRenderer } from './types';
-
-import { renderToCanvas, render } from './render';
-
-const RENDERER = 'html';
-
-interface ClientApi extends Addon_ClientStoryApi {
- configure(loader: Addon_Loadable, module: NodeModule): void;
- forceReRender(): void;
- raw: () => any; // todo add type
-}
-
-const api = start(renderToCanvas, { render });
-
-export const storiesOf: ClientApi['storiesOf'] = (kind, m) => {
- return (api.clientApi.storiesOf(kind, m) as ReturnType).addParameters({
- renderer: RENDERER,
- });
-};
-
-export const configure: ClientApi['configure'] = (...args) => api.configure(RENDERER, ...args);
-export const forceReRender: ClientApi['forceReRender'] = api.forceReRender;
-export const raw: ClientApi['raw'] = api.clientApi.raw;
diff --git a/code/renderers/html/template/cli/js/Button.stories.js b/code/renderers/html/template/cli/js/Button.stories.js
index 62c96643b7ed..81d0ba1fb150 100644
--- a/code/renderers/html/template/cli/js/Button.stories.js
+++ b/code/renderers/html/template/cli/js/Button.stories.js
@@ -1,6 +1,6 @@
import { createButton } from './Button';
-// More on how to set up stories at: https://storybook.js.org/docs/html/writing-stories/introduction
+// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
export default {
title: 'Example/Button',
tags: ['autodocs'],
@@ -21,7 +21,7 @@ export default {
},
};
-// More on writing stories with args: https://storybook.js.org/docs/html/writing-stories/args
+// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
export const Primary = {
args: {
primary: true,
diff --git a/code/renderers/html/template/cli/js/Header.stories.js b/code/renderers/html/template/cli/js/Header.stories.js
index e593d18c3c90..44fa3cbbff46 100644
--- a/code/renderers/html/template/cli/js/Header.stories.js
+++ b/code/renderers/html/template/cli/js/Header.stories.js
@@ -2,14 +2,14 @@ import { createHeader } from './Header';
export default {
title: 'Example/Header',
- // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/html/writing-docs/autodocs
+ // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
tags: ['autodocs'],
render: (args) => createHeader(args),
parameters: {
- // More on how to position stories at: https://storybook.js.org/docs/html/configure/story-layout
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
layout: 'fullscreen',
},
- // More on argTypes: https://storybook.js.org/docs/html/api/argtypes
+ // More on argTypes: https://storybook.js.org/docs/api/argtypes
argTypes: {
onLogin: { action: 'onLogin' },
onLogout: { action: 'onLogout' },
diff --git a/code/renderers/html/template/cli/js/Page.stories.js b/code/renderers/html/template/cli/js/Page.stories.js
index fcab88181bee..38e8331ec791 100644
--- a/code/renderers/html/template/cli/js/Page.stories.js
+++ b/code/renderers/html/template/cli/js/Page.stories.js
@@ -5,14 +5,14 @@ export default {
title: 'Example/Page',
render: () => createPage(),
parameters: {
- // More on how to position stories at: https://storybook.js.org/docs/html/configure/story-layout
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
layout: 'fullscreen',
},
};
export const LoggedOut = {};
-// More on interaction testing: https://storybook.js.org/docs/html/writing-tests/interaction-testing
+// More on interaction testing: https://storybook.js.org/docs/writing-tests/interaction-testing
export const LoggedIn = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
diff --git a/code/renderers/html/template/cli/ts-3-8/Button.stories.ts b/code/renderers/html/template/cli/ts-3-8/Button.stories.ts
index cd13a8c0c50c..f91d91ae731e 100644
--- a/code/renderers/html/template/cli/ts-3-8/Button.stories.ts
+++ b/code/renderers/html/template/cli/ts-3-8/Button.stories.ts
@@ -2,7 +2,7 @@ import type { StoryObj, Meta } from '@storybook/html';
import type { ButtonProps } from './Button';
import { createButton } from './Button';
-// More on how to set up stories at: https://storybook.js.org/docs/html/writing-stories/introduction#default-export
+// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
const meta: Meta = {
title: 'Example/Button',
tags: ['autodocs'],
@@ -26,7 +26,7 @@ const meta: Meta = {
export default meta;
type Story = StoryObj;
-// More on writing stories with args: https://storybook.js.org/docs/html/writing-stories/args
+// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
export const Primary: Story = {
args: {
primary: true,
diff --git a/code/renderers/html/template/cli/ts-3-8/Header.stories.ts b/code/renderers/html/template/cli/ts-3-8/Header.stories.ts
index d5391bb4a2a9..0bc5d9ce3aba 100644
--- a/code/renderers/html/template/cli/ts-3-8/Header.stories.ts
+++ b/code/renderers/html/template/cli/ts-3-8/Header.stories.ts
@@ -4,14 +4,14 @@ import { createHeader } from './Header';
const meta: Meta = {
title: 'Example/Header',
- // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/html/writing-docs/autodocs
+ // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
tags: ['autodocs'],
render: (args) => createHeader(args),
parameters: {
- // More on how to position stories at: https://storybook.js.org/docs/html/configure/story-layout
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
layout: 'fullscreen',
},
- // More on argTypes: https://storybook.js.org/docs/html/api/argtypes
+ // More on argTypes: https://storybook.js.org/docs/api/argtypes
argTypes: {
onLogin: { action: 'onLogin' },
onLogout: { action: 'onLogout' },
diff --git a/code/renderers/html/template/cli/ts-3-8/Page.stories.ts b/code/renderers/html/template/cli/ts-3-8/Page.stories.ts
index 0c2e79e8e907..ae132d98862d 100644
--- a/code/renderers/html/template/cli/ts-3-8/Page.stories.ts
+++ b/code/renderers/html/template/cli/ts-3-8/Page.stories.ts
@@ -6,7 +6,7 @@ const meta: Meta = {
title: 'Example/Page',
render: () => createPage(),
parameters: {
- // More on how to position stories at: https://storybook.js.org/docs/html/configure/story-layout
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
layout: 'fullscreen',
},
};
@@ -15,7 +15,7 @@ export default meta;
export const LoggedOut: StoryObj = {};
-// More on interaction testing: https://storybook.js.org/docs/html/writing-tests/interaction-testing
+// More on interaction testing: https://storybook.js.org/docs/writing-tests/interaction-testing
export const LoggedIn: StoryObj = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
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 d9bb7c93b473..2a86ecbec3b0 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
@@ -2,7 +2,7 @@ import type { StoryObj, Meta } from '@storybook/html';
import type { ButtonProps } from './Button';
import { createButton } from './Button';
-// More on how to set up stories at: https://storybook.js.org/docs/html/writing-stories/introduction#default-export
+// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
const meta = {
title: 'Example/Button',
tags: ['autodocs'],
@@ -26,7 +26,7 @@ const meta = {
export default meta;
type Story = StoryObj;
-// More on writing stories with args: https://storybook.js.org/docs/html/writing-stories/args
+// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
export const Primary: Story = {
args: {
primary: true,
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 930fc0ea2e7c..7570a625a869 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
@@ -4,14 +4,14 @@ import { createHeader } from './Header';
const meta = {
title: 'Example/Header',
- // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/html/writing-docs/autodocs
+ // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
tags: ['autodocs'],
render: (args) => createHeader(args),
parameters: {
- // More on how to position stories at: https://storybook.js.org/docs/html/configure/story-layout
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
layout: 'fullscreen',
},
- // More on argTypes: https://storybook.js.org/docs/html/api/argtypes
+ // More on argTypes: https://storybook.js.org/docs/api/argtypes
argTypes: {
onLogin: { action: 'onLogin' },
onLogout: { action: 'onLogout' },
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 c64a88fbb84f..4108dbc0d9c5 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
@@ -6,7 +6,7 @@ const meta = {
title: 'Example/Page',
render: () => createPage(),
parameters: {
- // More on how to position stories at: https://storybook.js.org/docs/html/configure/story-layout
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
layout: 'fullscreen',
},
} satisfies Meta;
@@ -15,7 +15,7 @@ export default meta;
export const LoggedOut: StoryObj = {};
-// More on interaction testing: https://storybook.js.org/docs/html/writing-tests/interaction-testing
+// More on interaction testing: https://storybook.js.org/docs/writing-tests/interaction-testing
export const LoggedIn: StoryObj = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
diff --git a/code/renderers/preact/package.json b/code/renderers/preact/package.json
index 93ed5c97b833..dd9730449cb3 100644
--- a/code/renderers/preact/package.json
+++ b/code/renderers/preact/package.json
@@ -47,7 +47,6 @@
"prep": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/bundle.ts"
},
"dependencies": {
- "@storybook/core-client": "workspace:*",
"@storybook/global": "^5.0.0",
"@storybook/preview-api": "workspace:*",
"@storybook/types": "workspace:*",
@@ -55,7 +54,7 @@
},
"devDependencies": {
"preact": "^10.5.13",
- "typescript": "~4.9.3"
+ "typescript": "^5.3.2"
},
"peerDependencies": {
"preact": "^8.0.0||^10.0.0"
diff --git a/code/renderers/preact/src/index.ts b/code/renderers/preact/src/index.ts
index 0c37ede8d826..145fbf2612ea 100644
--- a/code/renderers/preact/src/index.ts
+++ b/code/renderers/preact/src/index.ts
@@ -2,7 +2,6 @@
import './globals';
-export * from './public-api';
export * from './public-types';
// optimization: stop HMR propagation in webpack
diff --git a/code/renderers/preact/src/preset.ts b/code/renderers/preact/src/preset.ts
index b60ba9208510..03b11e7e6097 100644
--- a/code/renderers/preact/src/preset.ts
+++ b/code/renderers/preact/src/preset.ts
@@ -1,7 +1,10 @@
-import type { StorybookConfig } from '@storybook/types';
+import type { PresetProperty } from '@storybook/types';
import { join } from 'path';
-export const previewAnnotations: StorybookConfig['previewAnnotations'] = async (input, options) => {
+export const previewAnnotations: PresetProperty<'previewAnnotations'> = async (
+ input = [],
+ options
+) => {
const docsEnabled = Object.keys(await options.presets.apply('docs', {}, options)).length > 0;
const result: string[] = [];
diff --git a/code/renderers/preact/src/public-api.ts b/code/renderers/preact/src/public-api.ts
deleted file mode 100644
index 7a5451bb9ae8..000000000000
--- a/code/renderers/preact/src/public-api.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-/* eslint-disable prefer-destructuring */
-import type { Addon_ClientStoryApi, Addon_Loadable } from '@storybook/types';
-import { start } from '@storybook/preview-api';
-
-import { renderToCanvas } from './render';
-import type { PreactRenderer } from './types';
-
-export interface ClientApi extends Addon_ClientStoryApi {
- configure(loader: Addon_Loadable, module: NodeModule): void;
- forceReRender(): void;
- raw: () => any; // todo add type
- load: (...args: any[]) => void;
-}
-
-const RENDERER = 'preact';
-const api = start(renderToCanvas);
-
-export const storiesOf: ClientApi['storiesOf'] = (kind, m) => {
- return (api.clientApi.storiesOf(kind, m) as ReturnType).addParameters({
- renderer: RENDERER,
- });
-};
-
-export const configure: ClientApi['configure'] = (...args) => api.configure(RENDERER, ...args);
-export const forceReRender: ClientApi['forceReRender'] = api.forceReRender;
-export const raw: ClientApi['raw'] = api.clientApi.raw;
diff --git a/code/renderers/preact/template/cli/Button.stories.jsx b/code/renderers/preact/template/cli/Button.stories.jsx
index f1e083a02030..53ce0d71dd44 100644
--- a/code/renderers/preact/template/cli/Button.stories.jsx
+++ b/code/renderers/preact/template/cli/Button.stories.jsx
@@ -1,6 +1,6 @@
import { Button } from './Button';
-// More on how to set up stories at: https://storybook.js.org/docs/preact/writing-stories/introduction
+// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
export default {
title: 'Example/Button',
component: Button,
@@ -11,7 +11,7 @@ export default {
},
};
-// More on writing stories with args: https://storybook.js.org/docs/preact/writing-stories/args
+// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
export const Primary = {
args: {
primary: true,
diff --git a/code/renderers/preact/template/cli/Header.stories.jsx b/code/renderers/preact/template/cli/Header.stories.jsx
index 0fb4c57ada40..58b353a57db2 100644
--- a/code/renderers/preact/template/cli/Header.stories.jsx
+++ b/code/renderers/preact/template/cli/Header.stories.jsx
@@ -3,10 +3,10 @@ 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/preact/writing-docs/autodocs
+ // 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/preact/configure/story-layout
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
layout: 'fullscreen',
},
argTypes: {
diff --git a/code/renderers/preact/template/cli/Page.stories.jsx b/code/renderers/preact/template/cli/Page.stories.jsx
index 46669ac1c89d..67e60e684395 100644
--- a/code/renderers/preact/template/cli/Page.stories.jsx
+++ b/code/renderers/preact/template/cli/Page.stories.jsx
@@ -6,14 +6,14 @@ export default {
title: 'Example/Page',
component: Page,
parameters: {
- // More on how to position stories at: https://storybook.js.org/docs/preact/configure/story-layout
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
layout: 'fullscreen',
},
};
export const LoggedOut = {};
-// More on interaction testing: https://storybook.js.org/docs/preact/writing-tests/interaction-testing
+// More on interaction testing: https://storybook.js.org/docs/writing-tests/interaction-testing
export const LoggedIn = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
diff --git a/code/renderers/react/package.json b/code/renderers/react/package.json
index 442979520b84..ea4291d60371 100644
--- a/code/renderers/react/package.json
+++ b/code/renderers/react/package.json
@@ -48,7 +48,6 @@
},
"dependencies": {
"@storybook/client-logger": "workspace:*",
- "@storybook/core-client": "workspace:*",
"@storybook/docs-tools": "workspace:*",
"@storybook/global": "^5.0.0",
"@storybook/preview-api": "workspace:*",
diff --git a/code/renderers/react/src/docs/jsxDecorator.test.tsx b/code/renderers/react/src/docs/jsxDecorator.test.tsx
index 63fe5fb217b5..a1206a028c06 100644
--- a/code/renderers/react/src/docs/jsxDecorator.test.tsx
+++ b/code/renderers/react/src/docs/jsxDecorator.test.tsx
@@ -111,7 +111,7 @@ describe('renderJsx', () => {
});
it('forwardRef component', () => {
- const MyExoticComponent = React.forwardRef>(function MyExoticComponent(
+ const MyExoticComponent = React.forwardRef(function MyExoticComponent(
props,
_ref
) {
@@ -127,7 +127,7 @@ describe('renderJsx', () => {
});
it('memo component', () => {
- const MyMemoComponent: FC = React.memo(function MyMemoComponent(props) {
+ const MyMemoComponent: FC = React.memo(function MyMemoComponent(props) {
return {props.children}
;
});
diff --git a/code/renderers/react/src/docs/jsxDecorator.tsx b/code/renderers/react/src/docs/jsxDecorator.tsx
index d2df67445a17..a3b56f73d6b1 100644
--- a/code/renderers/react/src/docs/jsxDecorator.tsx
+++ b/code/renderers/react/src/docs/jsxDecorator.tsx
@@ -24,6 +24,7 @@ function simplifyNodeForStringify(node: ReactNode): ReactNode {
return {
...node,
props,
+ // @ts-expect-error (this is an internal or removed api)
_owner: null,
};
}
diff --git a/code/renderers/react/src/index.ts b/code/renderers/react/src/index.ts
index ae032e4f06b8..07a118109716 100644
--- a/code/renderers/react/src/index.ts
+++ b/code/renderers/react/src/index.ts
@@ -2,7 +2,6 @@
import './globals';
-export * from './public-api';
export * from './public-types';
export * from './testing-api';
diff --git a/code/renderers/react/src/preset.ts b/code/renderers/react/src/preset.ts
index 6da62d30bbf2..ebf8a18201d8 100644
--- a/code/renderers/react/src/preset.ts
+++ b/code/renderers/react/src/preset.ts
@@ -1,12 +1,15 @@
-import type { StorybookConfig } from '@storybook/types';
+import type { PresetProperty } from '@storybook/types';
import { join } from 'path';
-export const addons: StorybookConfig['addons'] = [
+export const addons: PresetProperty<'addons'> = [
require.resolve('@storybook/react-dom-shim/dist/preset'),
];
-export const previewAnnotations: StorybookConfig['previewAnnotations'] = async (input, options) => {
+export const previewAnnotations: PresetProperty<'previewAnnotations'> = async (
+ input = [],
+ options
+) => {
const docsConfig = await options.presets.apply('docs', {}, options);
const docsEnabled = Object.keys(docsConfig).length > 0;
const result: string[] = [];
diff --git a/code/renderers/react/src/public-api.test.ts b/code/renderers/react/src/public-api.test.ts
deleted file mode 100644
index c27393afbce4..000000000000
--- a/code/renderers/react/src/public-api.test.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import * as api from '.';
-
-describe('preview', () => {
- afterEach(() => {
- jest.resetModules();
- });
-
- const isFunction = (value: unknown) => typeof value === 'function';
-
- it('should return the client api in a browser environment', () => {
- expect(Object.keys(api).length).toBeGreaterThan(0);
- expect(Object.values(api).every(isFunction)).toEqual(true);
- });
-
- it('should return the client api in a node.js environment', () => {
- expect(Object.keys(api).length).toBeGreaterThan(0);
- expect(Object.values(api).every(isFunction)).toEqual(true);
- });
-});
diff --git a/code/renderers/react/src/public-api.tsx b/code/renderers/react/src/public-api.tsx
deleted file mode 100644
index aaef6d65ddd2..000000000000
--- a/code/renderers/react/src/public-api.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-/* eslint-disable prefer-destructuring */
-import { start } from '@storybook/preview-api';
-import type { Addon_ClientStoryApi, Addon_Loadable } from '@storybook/types';
-
-import { render, renderToCanvas } from './render';
-import type { ReactRenderer } from './types';
-
-interface ClientApi extends Addon_ClientStoryApi {
- configure(loader: Addon_Loadable, module: NodeModule): void;
- forceReRender(): void;
- raw: () => any; // todo add type
-}
-const RENDERER = 'react';
-
-const api = start(renderToCanvas, { render });
-
-export const storiesOf: ClientApi['storiesOf'] = (kind, m) => {
- return (api.clientApi.storiesOf(kind, m) as ReturnType).addParameters({
- renderer: RENDERER,
- });
-};
-
-export const configure: ClientApi['configure'] = (...args) => api.configure(RENDERER, ...args);
-export const forceReRender: ClientApi['forceReRender'] = api.forceReRender;
-export const raw: ClientApi['raw'] = api.clientApi.raw;
diff --git a/code/renderers/react/src/public-types.test.tsx b/code/renderers/react/src/public-types.test.tsx
index ea4beb7810c0..270552dce5b7 100644
--- a/code/renderers/react/src/public-types.test.tsx
+++ b/code/renderers/react/src/public-types.test.tsx
@@ -1,9 +1,10 @@
+/* eslint-disable @typescript-eslint/ban-types */
import { describe, test } from '@jest/globals';
import { satisfies } from '@storybook/core-common';
import type { Args, StoryAnnotations, StrictArgs } from '@storybook/types';
import { expectTypeOf } from 'expect-type';
-import type { KeyboardEventHandler, ReactNode } from 'react';
+import type { KeyboardEventHandler, ReactElement, ReactNode } from 'react';
import React from 'react';
import type { SetOptional } from 'type-fest';
@@ -16,7 +17,7 @@ import type { ReactRenderer } from './types';
type ReactStory = StoryAnnotations;
type ButtonProps = { label: string; disabled: boolean };
-const Button: (props: ButtonProps) => JSX.Element = () => <>>;
+const Button: (props: ButtonProps) => ReactElement = () => <>>;
describe('Args can be provided in multiple ways', () => {
test('✅ All required args may be provided in meta', () => {
@@ -92,11 +93,11 @@ test('✅ All void functions are optional', () => {
disabled: boolean;
onClick(): void;
onKeyDown: KeyboardEventHandler;
- onLoading: (s: string) => JSX.Element;
+ onLoading: (s: string) => ReactElement;
submitAction(): void;
}
- const Cmp: (props: CmpProps) => JSX.Element = () => <>>;
+ const Cmp: (props: CmpProps) => ReactElement = () => <>>;
const meta = satisfies >()({
component: Cmp,
@@ -115,7 +116,7 @@ test('✅ All void functions are optional', () => {
});
type ThemeData = 'light' | 'dark';
-declare const Theme: (props: { theme: ThemeData; children?: ReactNode }) => JSX.Element;
+declare const Theme: (props: { theme: ThemeData; children?: ReactNode }) => ReactElement;
describe('Story args can be inferred', () => {
test('Correct args are inferred when type is widened for render function', () => {
@@ -205,25 +206,19 @@ describe('Story args can be inferred', () => {
test('StoryObj is allowed when meta is upcasted to Meta', () => {
expectTypeOf>>().toEqualTypeOf<
- ReactStory<
- ButtonProps & { children?: ReactNode },
- Partial
- >
+ ReactStory>
>();
});
test('StoryObj