diff --git a/.circleci/config.yml b/.circleci/config.yml index 70b387f58cb5..bd2d13b2af33 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -390,7 +390,7 @@ jobs: parallelism: type: integer executor: - class: medium + class: large name: sb_playwright parallelism: << parameters.parallelism >> steps: diff --git a/CHANGELOG.md b/CHANGELOG.md index 5143f97018fe..444fe7ae0bea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,23 @@ +## 8.2.6 + +- CPC: Fix missing exports for addon-kit - [#28691](https://github.com/storybookjs/storybook/pull/28691), thanks @ndelangen! + +## 8.2.5 + +- CPC: Add the globals export for manager - [#28650](https://github.com/storybookjs/storybook/pull/28650), thanks @ndelangen! +- CPC: Correct path to the `@storybook/theming/create` alias - [#28643](https://github.com/storybookjs/storybook/pull/28643), thanks @Averethel! +- Components: Remove external overrides - [#28632](https://github.com/storybookjs/storybook/pull/28632), thanks @kasperpeulen! +- Core: Fix header for MountMustBeDestructuredError message - [#28590](https://github.com/storybookjs/storybook/pull/28590), thanks @0916dhkim! +- Onboarding: Fix code snippet when story name differs from export name - [#28649](https://github.com/storybookjs/storybook/pull/28649), thanks @ghengeveld! +- Telemetry: Add mount, beforeEach, moduleMock stats - [#28624](https://github.com/storybookjs/storybook/pull/28624), thanks @shilman! +- Telemetry: CSF feature usage - [#28622](https://github.com/storybookjs/storybook/pull/28622), thanks @shilman! + +## 8.2.4 + +- CLI: Add diagnostic when the `storybook` package is missing - [#28604](https://github.com/storybookjs/storybook/pull/28604), thanks @kasperpeulen! +- CLI: Make a few automigrations run on all version upgrades - [#28601](https://github.com/storybookjs/storybook/pull/28601), thanks @yannbf! +- CPC: Direct dependencies on shim packages in renderers - [#28599](https://github.com/storybookjs/storybook/pull/28599), thanks @ndelangen! + ## 8.2.3 - Bug: Fix invalid docs links in Configure.mdx template page - [#28560](https://github.com/storybookjs/storybook/pull/28560), thanks @kylegach! diff --git a/CHANGELOG.prerelease.md b/CHANGELOG.prerelease.md index 1fa61452d5e9..c77cec1c61b7 100644 --- a/CHANGELOG.prerelease.md +++ b/CHANGELOG.prerelease.md @@ -1,3 +1,31 @@ +## 8.3.0-alpha.2 + +- Addon-Interactions: Fix status in panel tab - [#28580](https://github.com/storybookjs/storybook/pull/28580), thanks @yannbf! +- Build: Remove external overrides, use package.json as source of truth - [#28632](https://github.com/storybookjs/storybook/pull/28632), thanks @kasperpeulen! +- CLI: Add conditional logging for manager and preview start - [#28603](https://github.com/storybookjs/storybook/pull/28603), thanks @tobiasdiez! +- CPC: Add the globals export for manager - [#28650](https://github.com/storybookjs/storybook/pull/28650), thanks @ndelangen! +- CPC: Correct path to the `@storybook/theming/create` alias - [#28643](https://github.com/storybookjs/storybook/pull/28643), thanks @Averethel! +- Core: Fix manager-builder `tsconfig` to emit `react-jsx` - [#28541](https://github.com/storybookjs/storybook/pull/28541), thanks @williamhelmrath! +- Fix: Add header for MountMustBeDestructuredError message - [#28590](https://github.com/storybookjs/storybook/pull/28590), thanks @0916dhkim! +- Fix: Prevent iframe from capturing mouse events in composed Storybooks - [#28568](https://github.com/storybookjs/storybook/pull/28568), thanks @Vincentdevreede! +- Onboarding: Fix code snippet when story name differs from export name - [#28649](https://github.com/storybookjs/storybook/pull/28649), thanks @ghengeveld! +- Vue: Fix out of memory error when using vue-component-meta - [#28589](https://github.com/storybookjs/storybook/pull/28589), thanks @larsrickert! + +## 8.3.0-alpha.1 + +- Bug: Fix invalid docs links in Configure.mdx template page - [#28560](https://github.com/storybookjs/storybook/pull/28560), thanks @kylegach! +- CLI: Add "missing-storybook-dependencies" automigration - [#28579](https://github.com/storybookjs/storybook/pull/28579), thanks @yannbf! +- CLI: Add diagnostic when the `storybook` package is missing - [#28604](https://github.com/storybookjs/storybook/pull/28604), thanks @kasperpeulen! +- CLI: Make a few automigrations run on all version upgrades - [#28601](https://github.com/storybookjs/storybook/pull/28601), thanks @yannbf! +- CPC: Add `theming/create` aliases in docs preset - [#28570](https://github.com/storybookjs/storybook/pull/28570), thanks @ndelangen! +- CPC: Direct dependencies on shim packages in renderers - [#28599](https://github.com/storybookjs/storybook/pull/28599), thanks @ndelangen! +- CPC: Fix Vite builder had wrong conditions - [#28581](https://github.com/storybookjs/storybook/pull/28581), thanks @ndelangen! +- CPC: Fix incorrect re-export in `core-events` - [#28573](https://github.com/storybookjs/storybook/pull/28573), thanks @ndelangen! +- CSF: Fix small typing issue - [#28587](https://github.com/storybookjs/storybook/pull/28587), thanks @valentinpalkovic! +- Core: Upgrade docs-mdx for smaller install - [#28552](https://github.com/storybookjs/storybook/pull/28552), thanks @shilman! +- Portable stories: Remove unused types - [#28548](https://github.com/storybookjs/storybook/pull/28548), thanks @kasperpeulen! +- Webpack: Fix sourceMap generation in csf-tools - [#28585](https://github.com/storybookjs/storybook/pull/28585), thanks @valentinpalkovic! + ## 8.3.0-alpha.0 diff --git a/code/.storybook/main.ts b/code/.storybook/main.ts index 962bef2124da..7c4f74c8c2ef 100644 --- a/code/.storybook/main.ts +++ b/code/.storybook/main.ts @@ -8,34 +8,78 @@ const managerApiPath = path.join(__dirname, '../core/src/manager-api'); const config: StorybookConfig = { stories: [ + { + directory: '../core/template/stories', + titlePrefix: 'core', + }, { directory: '../core/src/manager', - titlePrefix: '@manager', + titlePrefix: 'manager', }, { directory: '../core/src/preview-api', - titlePrefix: '@preview', + titlePrefix: 'preview', + }, + { + directory: '../core/src/components/brand', + titlePrefix: 'brand', }, { - directory: '../core/src/components', - titlePrefix: '@components', + directory: '../core/src/components/components', + titlePrefix: 'components', }, { directory: '../lib/blocks/src', - titlePrefix: '@blocks', + titlePrefix: 'blocks', + }, + { + directory: '../addons/a11y/template/stories', + titlePrefix: 'addons/a11y', + }, + { + directory: '../addons/actions/template/stories', + titlePrefix: 'addons/actions', + }, + { + directory: '../addons/backgrounds/template/stories', + titlePrefix: 'addons/backgrounds', }, { directory: '../addons/controls/src', - titlePrefix: '@addons/controls', + titlePrefix: 'addons/controls', + }, + { + directory: '../addons/controls/template/stories', + titlePrefix: 'addons/controls', + }, + { + directory: '../addons/docs/template/stories', + titlePrefix: 'addons/docs', + }, + { + directory: '../addons/links/template/stories', + titlePrefix: 'addons/links', + }, + { + directory: '../addons/viewport/template/stories', + titlePrefix: 'addons/viewport', + }, + { + directory: '../addons/toolbars/template/stories', + titlePrefix: 'addons/toolbars', }, { directory: '../addons/onboarding/src', - titlePrefix: '@addons/onboarding', + titlePrefix: 'addons/onboarding', }, { directory: '../addons/interactions/src', - titlePrefix: '@addons/interactions', + titlePrefix: 'addons/interactions', }, + // { + // directory: '../addons/interactions/template/stories', + // titlePrefix: 'addons/interactions', + // }, ], addons: [ '@storybook/addon-links', @@ -46,6 +90,11 @@ const config: StorybookConfig = { '@storybook/addon-a11y', '@chromatic-com/storybook', ], + previewAnnotations: [ + './core/template/stories/preview.ts', + './addons/toolbars/template/stories/preview.ts', + './renderers/react/template/components/index.js', + ], build: { test: { // we have stories for the blocks here, we can't exclude them @@ -58,9 +107,21 @@ const config: StorybookConfig = { name: '@storybook/react-vite', options: {}, }, + refs: { + icons: { + title: 'Icons', + url: 'https://main--64b56e737c0aeefed9d5e675.chromatic.com', + expanded: false, + }, + }, core: { disableTelemetry: true, }, + features: { + viewportStoryGlobals: true, + themesStoryGlobals: true, + backgroundsStoryGlobals: true, + }, viteFinal: (viteConfig, { configType }) => mergeConfig(viteConfig, { resolve: { @@ -81,7 +142,7 @@ const config: StorybookConfig = { sourcemap: process.env.CI !== 'true', }, }), - logLevel: 'debug', + // logLevel: 'debug', }; export default config; diff --git a/code/.storybook/preview.tsx b/code/.storybook/preview.tsx index e1c81fe960e7..c80bdcea2937 100644 --- a/code/.storybook/preview.tsx +++ b/code/.storybook/preview.tsx @@ -296,20 +296,3 @@ export const parameters = { ], }, }; - -export const globalTypes = { - theme: { - name: 'Theme', - description: 'Global theme for components', - toolbar: { - icon: 'circlehollow', - title: 'Theme', - items: [ - { value: 'light', icon: 'circlehollow', title: 'light' }, - { value: 'dark', icon: 'circle', title: 'dark' }, - { value: 'side-by-side', icon: 'sidebar', title: 'side by side' }, - { value: 'stacked', icon: 'bottombar', title: 'stacked' }, - ], - }, - }, -}; diff --git a/code/addons/a11y/package.json b/code/addons/a11y/package.json index ebaea076514c..5d164861a0fa 100644 --- a/code/addons/a11y/package.json +++ b/code/addons/a11y/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-a11y", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Test component compliance with web accessibility standards", "keywords": [ "a11y", diff --git a/code/addons/actions/package.json b/code/addons/actions/package.json index dc1cc04c3558..1cd9bbe9ee2a 100644 --- a/code/addons/actions/package.json +++ b/code/addons/actions/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-actions", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Get UI feedback when an action is performed on an interactive element", "keywords": [ "storybook", diff --git a/code/addons/backgrounds/package.json b/code/addons/backgrounds/package.json index 7199d6d903cb..4b1a210dab04 100644 --- a/code/addons/backgrounds/package.json +++ b/code/addons/backgrounds/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-backgrounds", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Switch backgrounds to view components in different settings", "keywords": [ "addon", diff --git a/code/addons/controls/package.json b/code/addons/controls/package.json index 8d2460f22c6b..8f4ad3d9b6c8 100644 --- a/code/addons/controls/package.json +++ b/code/addons/controls/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-controls", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Interact with component inputs dynamically in the Storybook UI", "keywords": [ "addon", diff --git a/code/addons/docs/docs/recipes.md b/code/addons/docs/docs/recipes.md index e98c89145b78..0a982974f390 100644 --- a/code/addons/docs/docs/recipes.md +++ b/code/addons/docs/docs/recipes.md @@ -184,7 +184,7 @@ The Storybook UI is a workshop for developing components in isolation. Storybook To address this, we’ve added a CLI flag to only export the docs. This flag is also available in dev mode: ```sh -yarn build-storybook --docs +yarn storybook build --docs ``` ## Disabling docs stories diff --git a/code/addons/docs/package.json b/code/addons/docs/package.json index 8edc0d1a8063..a8d85a3f125f 100644 --- a/code/addons/docs/package.json +++ b/code/addons/docs/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-docs", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Document component usage and properties in Markdown", "keywords": [ "addon", @@ -118,7 +118,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "typescript": "^5.3.2", - "vite": "^4.0.4" + "vite": "^5.0.13" }, "peerDependencies": { "storybook": "workspace:^" diff --git a/code/addons/docs/src/preset.ts b/code/addons/docs/src/preset.ts index 0ad19b34bd58..8d359204c227 100644 --- a/code/addons/docs/src/preset.ts +++ b/code/addons/docs/src/preset.ts @@ -68,11 +68,11 @@ async function webpack( * * In the future the `@storybook/theming` and `@storybook/components` can be removed, as they should be singletons in the future due to the peerDependency on `storybook` package. */ - const cliPath = require.resolve('storybook/package.json'); - const themingPath = join(cliPath, '..', 'core', 'theming', 'index.js'); + const cliPath = dirname(require.resolve('storybook/package.json')); + const themingPath = join(cliPath, 'core', 'theming', 'index.js'); const themingCreatePath = join(cliPath, 'core', 'theming', 'create.js'); - const componentsPath = join(cliPath, '..', 'core', 'components', 'index.js'); + const componentsPath = join(cliPath, 'core', 'components', 'index.js'); const blocksPath = dirname(require.resolve('@storybook/blocks/package.json')); if (Array.isArray(webpackConfig.resolve?.alias)) { alias = [...webpackConfig.resolve?.alias]; diff --git a/code/addons/essentials/package.json b/code/addons/essentials/package.json index d4ddbcff684d..2e19ea8b4a10 100644 --- a/code/addons/essentials/package.json +++ b/code/addons/essentials/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-essentials", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Curated addons to bring out the best of Storybook", "keywords": [ "addon", diff --git a/code/addons/gfm/package.json b/code/addons/gfm/package.json index dd4ff4c3d8ee..47912ea8064e 100644 --- a/code/addons/gfm/package.json +++ b/code/addons/gfm/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-mdx-gfm", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "GitHub Flavored Markdown in Storybook", "keywords": [ "addon", diff --git a/code/addons/highlight/package.json b/code/addons/highlight/package.json index 39c938c555c1..c6bd762fa164 100644 --- a/code/addons/highlight/package.json +++ b/code/addons/highlight/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-highlight", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Highlight DOM nodes within your stories", "keywords": [ "storybook-addons", diff --git a/code/addons/interactions/package.json b/code/addons/interactions/package.json index 380f82dae2f8..70c63b2d806e 100644 --- a/code/addons/interactions/package.json +++ b/code/addons/interactions/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-interactions", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Automate, test and debug user interactions", "keywords": [ "storybook-addons", diff --git a/code/addons/interactions/src/Panel.tsx b/code/addons/interactions/src/Panel.tsx index 490d1df1564c..f6e1b06b8619 100644 --- a/code/addons/interactions/src/Panel.tsx +++ b/code/addons/interactions/src/Panel.tsx @@ -180,13 +180,13 @@ export const Panel = memo<{ storyId: string }>(function PanelMemoized({ storyId }); }, [STORY_THREW_EXCEPTION]: () => { - set((s) => ({ ...s, isErrored: true })); + set((s) => ({ ...s, isErrored: true, hasException: true })); }, [PLAY_FUNCTION_THREW_EXCEPTION]: (e) => { - set((s) => ({ ...s, caughtException: e })); + set((s) => ({ ...s, caughtException: e, hasException: true })); }, [UNHANDLED_ERRORS_WHILE_PLAYING]: (e) => { - set((s) => ({ ...s, unhandledErrors: e })); + set((s) => ({ ...s, unhandledErrors: e, hasException: true })); }, }, [collapsed] diff --git a/code/addons/interactions/src/components/TabStatus.tsx b/code/addons/interactions/src/components/TabStatus.tsx deleted file mode 100644 index fc2390b5c823..000000000000 --- a/code/addons/interactions/src/components/TabStatus.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { styled } from 'storybook/internal/theming'; - -import { StatusIcon } from './StatusIcon'; - -export const TabIcon = styled(StatusIcon)({ - marginLeft: 5, -}); diff --git a/code/addons/interactions/src/manager.tsx b/code/addons/interactions/src/manager.tsx index 88b20d1d8bb1..2de5d48d8fa6 100644 --- a/code/addons/interactions/src/manager.tsx +++ b/code/addons/interactions/src/manager.tsx @@ -2,10 +2,8 @@ import React, { useCallback } from 'react'; import type { Combo } from 'storybook/internal/manager-api'; import { addons, Consumer, types, useAddonState } from 'storybook/internal/manager-api'; import { AddonPanel, Badge, Spaced } from 'storybook/internal/components'; -import { CallStates } from '@storybook/instrumenter'; import { ADDON_ID, PANEL_ID } from './constants'; import { Panel } from './Panel'; -import { TabIcon } from './components/TabStatus'; function Title() { const [addonState = {}] = useAddonState(ADDON_ID); @@ -18,7 +16,7 @@ function Title() { {interactionsCount && !hasException ? ( {interactionsCount} ) : null} - {hasException ? : null} + {hasException ? {interactionsCount} : null} ); diff --git a/code/addons/interactions/template/stories/unhandled-errors.stories.ts b/code/addons/interactions/template/stories/unhandled-errors.stories.ts index 336c44b72f3a..dad3ce89ce8d 100644 --- a/code/addons/interactions/template/stories/unhandled-errors.stories.ts +++ b/code/addons/interactions/template/stories/unhandled-errors.stories.ts @@ -13,6 +13,7 @@ export default { actions: { argTypesRegex: '^on[A-Z].*' }, chromatic: { disable: true }, }, + tags: ['test-skip'], }; export const Default = { diff --git a/code/addons/jest/package.json b/code/addons/jest/package.json index ee2c153f25cc..119c37ef97f5 100644 --- a/code/addons/jest/package.json +++ b/code/addons/jest/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-jest", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "React storybook addon that show component jest report", "keywords": [ "addon", diff --git a/code/addons/links/package.json b/code/addons/links/package.json index ffdc2edc3b0b..d38a54820858 100644 --- a/code/addons/links/package.json +++ b/code/addons/links/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-links", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Link stories together to build demos and prototypes with your UI components", "keywords": [ "addon", @@ -67,7 +67,7 @@ "prep": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/addon-bundle.ts" }, "dependencies": { - "@storybook/csf": "0.1.11", + "@storybook/csf": "^0.1.11", "@storybook/global": "^5.0.0", "ts-dedent": "^2.0.0" }, diff --git a/code/addons/measure/package.json b/code/addons/measure/package.json index b31b31e8b2ee..a9106dffc019 100644 --- a/code/addons/measure/package.json +++ b/code/addons/measure/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-measure", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Inspect layouts by visualizing the box model", "keywords": [ "storybook-addons", diff --git a/code/addons/onboarding/package.json b/code/addons/onboarding/package.json index bb22179dbc1a..0c995838e4d6 100644 --- a/code/addons/onboarding/package.json +++ b/code/addons/onboarding/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-onboarding", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook Addon Onboarding - Introduces a new onboarding experience", "keywords": [ "storybook-addons", diff --git a/code/addons/onboarding/src/Onboarding.tsx b/code/addons/onboarding/src/Onboarding.tsx index e387659cf7ce..fde1526aa483 100644 --- a/code/addons/onboarding/src/Onboarding.tsx +++ b/code/addons/onboarding/src/Onboarding.tsx @@ -75,6 +75,7 @@ export default function Onboarding({ api }: { api: API }) { const [createNewStoryForm, setCreateNewStoryForm] = useState(); const [createdStory, setCreatedStory] = useState<{ newStoryName: string; + newStoryExportName: string; sourceFileContent: string; sourceFileName: string; } | null>(); @@ -158,8 +159,8 @@ export default function Onboarding({ api }: { api: API }) { } const source = createdStory?.sourceFileContent; - const startIndex = source?.lastIndexOf(`export const ${createdStory?.newStoryName}`); - const snippet = source?.slice(startIndex); + const startIndex = source?.lastIndexOf(`export const ${createdStory?.newStoryExportName}`); + const snippet = source?.slice(startIndex).trim(); const startingLineNumber = source?.slice(0, startIndex).split('\n').length; const steps: StepDefinition[] = [ diff --git a/code/addons/outline/package.json b/code/addons/outline/package.json index c5d87b4333c5..5dcbc6667e7c 100644 --- a/code/addons/outline/package.json +++ b/code/addons/outline/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-outline", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Outline all elements with CSS to help with layout placement and alignment", "keywords": [ "storybook-addons", diff --git a/code/addons/storysource/package.json b/code/addons/storysource/package.json index a5ad958fa003..d1d510da7807 100644 --- a/code/addons/storysource/package.json +++ b/code/addons/storysource/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-storysource", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "View a story’s source code to see how it works and paste into your app", "keywords": [ "addon", diff --git a/code/addons/themes/package.json b/code/addons/themes/package.json index 20776833b488..acec0b81da19 100644 --- a/code/addons/themes/package.json +++ b/code/addons/themes/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-themes", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Switch between multiple themes for you components in Storybook", "keywords": [ "css", diff --git a/code/addons/toolbars/package.json b/code/addons/toolbars/package.json index 614745a5f46d..9be689cf7b20 100644 --- a/code/addons/toolbars/package.json +++ b/code/addons/toolbars/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-toolbars", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Create your own toolbar items that control story rendering", "keywords": [ "addon", diff --git a/code/addons/viewport/package.json b/code/addons/viewport/package.json index 32b29f79e6a1..d108727bce1f 100644 --- a/code/addons/viewport/package.json +++ b/code/addons/viewport/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/addon-viewport", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Build responsive components by adjusting Storybook’s viewport size and orientation", "keywords": [ "addon", diff --git a/code/builders/builder-vite/package.json b/code/builders/builder-vite/package.json index 9db90a1648ae..4f3cb71218e7 100644 --- a/code/builders/builder-vite/package.json +++ b/code/builders/builder-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/builder-vite", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "A plugin to run and build Storybooks with Vite", "homepage": "https://github.com/storybookjs/storybook/tree/next/code/builders/builder-vite/#readme", "bugs": { @@ -59,7 +59,7 @@ "glob": "^10.0.0", "slash": "^5.0.0", "typescript": "^5.3.2", - "vite": "^4.0.4" + "vite": "^5.0.13" }, "peerDependencies": { "@preact/preset-vite": "*", diff --git a/code/builders/builder-webpack5/package.json b/code/builders/builder-webpack5/package.json index f6c854d55ed4..8911b233da19 100644 --- a/code/builders/builder-webpack5/package.json +++ b/code/builders/builder-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/builder-webpack5", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" @@ -87,7 +87,7 @@ "util": "^0.12.4", "util-deprecate": "^1.0.2", "webpack": "5", - "webpack-dev-middleware": "^6.1.2", + "webpack-dev-middleware": "^7.3.0", "webpack-hot-middleware": "^2.25.1", "webpack-virtual-modules": "^0.6.0" }, diff --git a/code/core/assets/server/addon.tsconfig.json b/code/core/assets/server/addon.tsconfig.json index 38452bcdfa20..9161d5ff8254 100644 --- a/code/core/assets/server/addon.tsconfig.json +++ b/code/core/assets/server/addon.tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "jsx": "react", + "jsx": "react-jsx", "jsxImportSource": "react" } } diff --git a/code/core/package.json b/code/core/package.json index 326b6d18f517..ba93bd1579e3 100644 --- a/code/core/package.json +++ b/code/core/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" @@ -142,6 +142,11 @@ "import": "./dist/manager/globals-module-info.js", "require": "./dist/manager/globals-module-info.cjs" }, + "./manager/globals": { + "types": "./dist/manager/globals.d.ts", + "import": "./dist/manager/globals.js", + "require": "./dist/manager/globals.cjs" + }, "./preview/globals": { "types": "./dist/preview/globals.d.ts", "import": "./dist/preview/globals.js", @@ -229,6 +234,9 @@ "manager/globals-module-info": [ "./dist/manager/globals-module-info.d.ts" ], + "manager/globals": [ + "./dist/manager/globals.d.ts" + ], "preview/globals": [ "./dist/preview/globals.d.ts" ] @@ -245,7 +253,7 @@ "prep": "bun ./scripts/prep.ts" }, "dependencies": { - "@storybook/csf": "0.1.11", + "@storybook/csf": "^0.1.11", "@types/express": "^4.17.21", "@types/node": "^18.0.0", "browser-assert": "^1.2.1", @@ -255,7 +263,7 @@ "process": "^0.11.10", "recast": "^0.23.5", "util": "^0.12.4", - "ws": "^8.2.3" + "ws": "^8.17.1" }, "devDependencies": { "@aw-web-design/x-default-browser": "1.4.126", @@ -277,7 +285,7 @@ "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-scroll-area": "^1.0.5", "@radix-ui/react-slot": "^1.0.2", - "@storybook/docs-mdx": "4.0.0-next.0", + "@storybook/docs-mdx": "4.0.0-next.1", "@storybook/global": "^5.0.0", "@storybook/icons": "^1.2.5", "@tanstack/react-virtual": "^3.3.0", diff --git a/code/core/scripts/entries.ts b/code/core/scripts/entries.ts index 85297c1b0c56..a618dac3b623 100644 --- a/code/core/scripts/entries.ts +++ b/code/core/scripts/entries.ts @@ -28,17 +28,13 @@ export const getEntries = (cwd: string) => { define('src/preview-api/index.ts', ['browser', 'node'], true), define('src/manager-api/index.ts', ['browser', 'node'], true, ['react']), define('src/router/index.ts', ['browser', 'node'], true, ['react']), - define('src/components/index.ts', ['browser', 'node'], true, [ - 'react', - 'react-dom', - '@storybook/csf', - '@storybook/global', - ]), + define('src/components/index.ts', ['browser', 'node'], true, ['react', 'react-dom']), define('src/theming/index.ts', ['browser', 'node'], true, ['react']), define('src/theming/create.ts', ['browser', 'node'], true, ['react']), define('src/docs-tools/index.ts', ['browser', 'node'], true), define('src/manager/globals-module-info.ts', ['node'], true), + define('src/manager/globals.ts', ['node'], true), define('src/preview/globals.ts', ['node'], true), ]; }; diff --git a/code/core/src/builder-manager/index.ts b/code/core/src/builder-manager/index.ts index c6b5840fb3ff..01755fbdef2c 100644 --- a/code/core/src/builder-manager/index.ts +++ b/code/core/src/builder-manager/index.ts @@ -126,7 +126,9 @@ const starter: StarterFunction = async function* starterGeneratorFn({ options, router, }) { - logger.info('=> Starting manager..'); + if (!options.quiet) { + logger.info('=> Starting manager..'); + } const { config, diff --git a/code/core/src/common/js-package-manager/JsPackageManager.ts b/code/core/src/common/js-package-manager/JsPackageManager.ts index 1000cc7bf174..5a18b572f248 100644 --- a/code/core/src/common/js-package-manager/JsPackageManager.ts +++ b/code/core/src/common/js-package-manager/JsPackageManager.ts @@ -64,22 +64,6 @@ export abstract class JsPackageManager { return packageJSON ? packageJSON.version ?? null : null; } - // NOTE: for some reason yarn prefers the npm registry in - // local development, so always use npm - async setRegistryURL(url: string) { - if (url) { - await this.executeCommand({ command: 'npm', args: ['config', 'set', 'registry', url] }); - } else { - await this.executeCommand({ command: 'npm', args: ['config', 'delete', 'registry'] }); - } - } - - async getRegistryURL() { - const res = await this.executeCommand({ command: 'npm', args: ['config', 'get', 'registry'] }); - const url = res.trim(); - return url === 'undefined' ? undefined : url; - } - constructor(options?: JsPackageManagerOptions) { this.cwd = options?.cwd || process.cwd(); } @@ -487,6 +471,8 @@ export abstract class JsPackageManager { ): // Use generic and conditional type to force `string[]` if fetchAllVersions is true and `string` if false Promise; + public abstract getRegistryURL(): Promise; + public abstract runPackageCommand( command: string, args: string[], diff --git a/code/core/src/common/js-package-manager/NPMProxy.test.ts b/code/core/src/common/js-package-manager/NPMProxy.test.ts index d1bb289112f1..9c88ea60af45 100644 --- a/code/core/src/common/js-package-manager/NPMProxy.test.ts +++ b/code/core/src/common/js-package-manager/NPMProxy.test.ts @@ -34,21 +34,6 @@ describe('NPM Proxy', () => { }); }); - describe('setRegistryUrl', () => { - it('should run `npm config set registry https://foo.bar`', async () => { - const executeCommandSpy = vi.spyOn(npmProxy, 'executeCommand').mockResolvedValueOnce(''); - - await npmProxy.setRegistryURL('https://foo.bar'); - - expect(executeCommandSpy).toHaveBeenCalledWith( - expect.objectContaining({ - command: 'npm', - args: ['config', 'set', 'registry', 'https://foo.bar'], - }) - ); - }); - }); - describe('installDependencies', () => { describe('npm6', () => { it('should run `npm install`', async () => { diff --git a/code/core/src/common/js-package-manager/NPMProxy.ts b/code/core/src/common/js-package-manager/NPMProxy.ts index ff77aedfa95a..d4d711915925 100644 --- a/code/core/src/common/js-package-manager/NPMProxy.ts +++ b/code/core/src/common/js-package-manager/NPMProxy.ts @@ -181,6 +181,17 @@ export class NPMProxy extends JsPackageManager { }); } + public async getRegistryURL() { + const res = await this.executeCommand({ + command: 'npm', + // "npm config" commands are not allowed in workspaces per default + // https://github.com/npm/cli/issues/6099#issuecomment-1847584792 + args: ['config', 'get', 'registry', '-ws=false', '-iwr'], + }); + const url = res.trim(); + return url === 'undefined' ? undefined : url; + } + protected async runAddDeps(dependencies: string[], installAsDevDependencies: boolean) { const { logStream, readLogFile, moveLogFile, removeLogFile } = await createLogStream(); let args = [...dependencies]; diff --git a/code/core/src/common/js-package-manager/PNPMProxy.test.ts b/code/core/src/common/js-package-manager/PNPMProxy.test.ts index 2430221cc2e8..cca2ca4ea364 100644 --- a/code/core/src/common/js-package-manager/PNPMProxy.test.ts +++ b/code/core/src/common/js-package-manager/PNPMProxy.test.ts @@ -24,21 +24,6 @@ describe('PNPM Proxy', () => { }); }); - describe('setRegistryUrl', () => { - it('should run `npm config set registry https://foo.bar`', async () => { - const executeCommandSpy = vi.spyOn(pnpmProxy, 'executeCommand').mockResolvedValueOnce(''); - - await pnpmProxy.setRegistryURL('https://foo.bar'); - - expect(executeCommandSpy).toHaveBeenCalledWith( - expect.objectContaining({ - command: 'npm', - args: ['config', 'set', 'registry', 'https://foo.bar'], - }) - ); - }); - }); - describe('installDependencies', () => { it('should run `pnpm install`', async () => { const executeCommandSpy = vi diff --git a/code/core/src/common/js-package-manager/PNPMProxy.ts b/code/core/src/common/js-package-manager/PNPMProxy.ts index 41c2858763c8..6d3f434c87c9 100644 --- a/code/core/src/common/js-package-manager/PNPMProxy.ts +++ b/code/core/src/common/js-package-manager/PNPMProxy.ts @@ -90,6 +90,15 @@ export class PNPMProxy extends JsPackageManager { }); } + public async getRegistryURL() { + const res = await this.executeCommand({ + command: 'pnpm', + args: ['config', 'get', 'registry'], + }); + const url = res.trim(); + return url === 'undefined' ? undefined : url; + } + async runPackageCommand(command: string, args: string[], cwd?: string): Promise { return this.executeCommand({ command: 'pnpm', diff --git a/code/core/src/common/js-package-manager/Yarn1Proxy.test.ts b/code/core/src/common/js-package-manager/Yarn1Proxy.test.ts index a26ce81efeb9..c20f496fed80 100644 --- a/code/core/src/common/js-package-manager/Yarn1Proxy.test.ts +++ b/code/core/src/common/js-package-manager/Yarn1Proxy.test.ts @@ -25,21 +25,6 @@ describe('Yarn 1 Proxy', () => { }); }); - describe('setRegistryUrl', () => { - it('should run `yarn config set npmRegistryServer https://foo.bar`', async () => { - const executeCommandSpy = vi.spyOn(yarn1Proxy, 'executeCommand').mockResolvedValueOnce(''); - - await yarn1Proxy.setRegistryURL('https://foo.bar'); - - expect(executeCommandSpy).toHaveBeenCalledWith( - expect.objectContaining({ - command: 'npm', - args: ['config', 'set', 'registry', 'https://foo.bar'], - }) - ); - }); - }); - describe('installDependencies', () => { it('should run `yarn`', async () => { const executeCommandSpy = vi.spyOn(yarn1Proxy, 'executeCommand').mockResolvedValueOnce(''); diff --git a/code/core/src/common/js-package-manager/Yarn1Proxy.ts b/code/core/src/common/js-package-manager/Yarn1Proxy.ts index b193d4db4f15..44a8f0ca3d45 100644 --- a/code/core/src/common/js-package-manager/Yarn1Proxy.ts +++ b/code/core/src/common/js-package-manager/Yarn1Proxy.ts @@ -83,6 +83,15 @@ export class Yarn1Proxy extends JsPackageManager { return JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as Record; } + public async getRegistryURL() { + const res = await this.executeCommand({ + command: 'yarn', + args: ['config', 'get', 'registry'], + }); + const url = res.trim(); + return url === 'undefined' ? undefined : url; + } + public async findInstallations(pattern: string[], { depth = 99 }: { depth?: number } = {}) { const yarnArgs = ['list', '--pattern', pattern.map((p) => `"${p}"`).join(' '), '--json']; diff --git a/code/core/src/common/js-package-manager/Yarn2Proxy.test.ts b/code/core/src/common/js-package-manager/Yarn2Proxy.test.ts index 21656ff1ccd2..4e4441aedb4d 100644 --- a/code/core/src/common/js-package-manager/Yarn2Proxy.test.ts +++ b/code/core/src/common/js-package-manager/Yarn2Proxy.test.ts @@ -53,21 +53,6 @@ describe('Yarn 2 Proxy', () => { }); }); - describe('setRegistryUrl', () => { - it('should run `yarn config set npmRegistryServer https://foo.bar`', async () => { - const executeCommandSpy = vi.spyOn(yarn2Proxy, 'executeCommand').mockResolvedValueOnce(''); - - await yarn2Proxy.setRegistryURL('https://foo.bar'); - - expect(executeCommandSpy).toHaveBeenCalledWith( - expect.objectContaining({ - command: 'npm', - args: ['config', 'set', 'registry', 'https://foo.bar'], - }) - ); - }); - }); - describe('addDependencies', () => { it('with devDep it should run `yarn install -D @storybook/core`', async () => { const executeCommandSpy = vi.spyOn(yarn2Proxy, 'executeCommand').mockResolvedValueOnce(''); diff --git a/code/core/src/common/js-package-manager/Yarn2Proxy.ts b/code/core/src/common/js-package-manager/Yarn2Proxy.ts index 7917bc7e1ebd..317a56b40090 100644 --- a/code/core/src/common/js-package-manager/Yarn2Proxy.ts +++ b/code/core/src/common/js-package-manager/Yarn2Proxy.ts @@ -239,6 +239,15 @@ export class Yarn2Proxy extends JsPackageManager { await removeLogFile(); } + public async getRegistryURL() { + const res = await this.executeCommand({ + command: 'yarn', + args: ['config', 'get', 'npmRegistryServer'], + }); + const url = res.trim(); + return url === 'undefined' ? undefined : url; + } + protected async runRemoveDeps(dependencies: string[]) { const args = [...dependencies]; diff --git a/code/core/src/common/versions.ts b/code/core/src/common/versions.ts index 44bb49ad6e5c..b20658d06bf6 100644 --- a/code/core/src/common/versions.ts +++ b/code/core/src/common/versions.ts @@ -1,84 +1,84 @@ // auto generated file, do not edit export default { - '@storybook/addon-a11y': '8.3.0-alpha.0', - '@storybook/addon-actions': '8.3.0-alpha.0', - '@storybook/addon-backgrounds': '8.3.0-alpha.0', - '@storybook/addon-controls': '8.3.0-alpha.0', - '@storybook/addon-docs': '8.3.0-alpha.0', - '@storybook/addon-essentials': '8.3.0-alpha.0', - '@storybook/addon-mdx-gfm': '8.3.0-alpha.0', - '@storybook/addon-highlight': '8.3.0-alpha.0', - '@storybook/addon-interactions': '8.3.0-alpha.0', - '@storybook/addon-jest': '8.3.0-alpha.0', - '@storybook/addon-links': '8.3.0-alpha.0', - '@storybook/addon-measure': '8.3.0-alpha.0', - '@storybook/addon-onboarding': '8.3.0-alpha.0', - '@storybook/addon-outline': '8.3.0-alpha.0', - '@storybook/addon-storysource': '8.3.0-alpha.0', - '@storybook/addon-themes': '8.3.0-alpha.0', - '@storybook/addon-toolbars': '8.3.0-alpha.0', - '@storybook/addon-viewport': '8.3.0-alpha.0', - '@storybook/builder-vite': '8.3.0-alpha.0', - '@storybook/builder-webpack5': '8.3.0-alpha.0', - '@storybook/core': '8.3.0-alpha.0', - '@storybook/builder-manager': '8.3.0-alpha.0', - '@storybook/channels': '8.3.0-alpha.0', - '@storybook/client-logger': '8.3.0-alpha.0', - '@storybook/components': '8.3.0-alpha.0', - '@storybook/core-common': '8.3.0-alpha.0', - '@storybook/core-events': '8.3.0-alpha.0', - '@storybook/core-server': '8.3.0-alpha.0', - '@storybook/csf-tools': '8.3.0-alpha.0', - '@storybook/docs-tools': '8.3.0-alpha.0', - '@storybook/manager': '8.3.0-alpha.0', - '@storybook/manager-api': '8.3.0-alpha.0', - '@storybook/node-logger': '8.3.0-alpha.0', - '@storybook/preview': '8.3.0-alpha.0', - '@storybook/preview-api': '8.3.0-alpha.0', - '@storybook/router': '8.3.0-alpha.0', - '@storybook/telemetry': '8.3.0-alpha.0', - '@storybook/theming': '8.3.0-alpha.0', - '@storybook/types': '8.3.0-alpha.0', - '@storybook/angular': '8.3.0-alpha.0', - '@storybook/ember': '8.3.0-alpha.0', - '@storybook/html-vite': '8.3.0-alpha.0', - '@storybook/html-webpack5': '8.3.0-alpha.0', - '@storybook/nextjs': '8.3.0-alpha.0', - '@storybook/preact-vite': '8.3.0-alpha.0', - '@storybook/preact-webpack5': '8.3.0-alpha.0', - '@storybook/react-vite': '8.3.0-alpha.0', - '@storybook/react-webpack5': '8.3.0-alpha.0', - '@storybook/server-webpack5': '8.3.0-alpha.0', - '@storybook/svelte-vite': '8.3.0-alpha.0', - '@storybook/svelte-webpack5': '8.3.0-alpha.0', - '@storybook/sveltekit': '8.3.0-alpha.0', - '@storybook/vue3-vite': '8.3.0-alpha.0', - '@storybook/vue3-webpack5': '8.3.0-alpha.0', - '@storybook/web-components-vite': '8.3.0-alpha.0', - '@storybook/web-components-webpack5': '8.3.0-alpha.0', - '@storybook/blocks': '8.3.0-alpha.0', - storybook: '8.3.0-alpha.0', - sb: '8.3.0-alpha.0', - '@storybook/cli': '8.3.0-alpha.0', - '@storybook/codemod': '8.3.0-alpha.0', - '@storybook/core-webpack': '8.3.0-alpha.0', - '@storybook/csf-plugin': '8.3.0-alpha.0', - '@storybook/instrumenter': '8.3.0-alpha.0', - '@storybook/react-dom-shim': '8.3.0-alpha.0', - '@storybook/source-loader': '8.3.0-alpha.0', - '@storybook/test': '8.3.0-alpha.0', - '@storybook/preset-create-react-app': '8.3.0-alpha.0', - '@storybook/preset-html-webpack': '8.3.0-alpha.0', - '@storybook/preset-preact-webpack': '8.3.0-alpha.0', - '@storybook/preset-react-webpack': '8.3.0-alpha.0', - '@storybook/preset-server-webpack': '8.3.0-alpha.0', - '@storybook/preset-svelte-webpack': '8.3.0-alpha.0', - '@storybook/preset-vue3-webpack': '8.3.0-alpha.0', - '@storybook/html': '8.3.0-alpha.0', - '@storybook/preact': '8.3.0-alpha.0', - '@storybook/react': '8.3.0-alpha.0', - '@storybook/server': '8.3.0-alpha.0', - '@storybook/svelte': '8.3.0-alpha.0', - '@storybook/vue3': '8.3.0-alpha.0', - '@storybook/web-components': '8.3.0-alpha.0', + '@storybook/addon-a11y': '8.3.0-alpha.2', + '@storybook/addon-actions': '8.3.0-alpha.2', + '@storybook/addon-backgrounds': '8.3.0-alpha.2', + '@storybook/addon-controls': '8.3.0-alpha.2', + '@storybook/addon-docs': '8.3.0-alpha.2', + '@storybook/addon-essentials': '8.3.0-alpha.2', + '@storybook/addon-mdx-gfm': '8.3.0-alpha.2', + '@storybook/addon-highlight': '8.3.0-alpha.2', + '@storybook/addon-interactions': '8.3.0-alpha.2', + '@storybook/addon-jest': '8.3.0-alpha.2', + '@storybook/addon-links': '8.3.0-alpha.2', + '@storybook/addon-measure': '8.3.0-alpha.2', + '@storybook/addon-onboarding': '8.3.0-alpha.2', + '@storybook/addon-outline': '8.3.0-alpha.2', + '@storybook/addon-storysource': '8.3.0-alpha.2', + '@storybook/addon-themes': '8.3.0-alpha.2', + '@storybook/addon-toolbars': '8.3.0-alpha.2', + '@storybook/addon-viewport': '8.3.0-alpha.2', + '@storybook/builder-vite': '8.3.0-alpha.2', + '@storybook/builder-webpack5': '8.3.0-alpha.2', + '@storybook/core': '8.3.0-alpha.2', + '@storybook/builder-manager': '8.3.0-alpha.2', + '@storybook/channels': '8.3.0-alpha.2', + '@storybook/client-logger': '8.3.0-alpha.2', + '@storybook/components': '8.3.0-alpha.2', + '@storybook/core-common': '8.3.0-alpha.2', + '@storybook/core-events': '8.3.0-alpha.2', + '@storybook/core-server': '8.3.0-alpha.2', + '@storybook/csf-tools': '8.3.0-alpha.2', + '@storybook/docs-tools': '8.3.0-alpha.2', + '@storybook/manager': '8.3.0-alpha.2', + '@storybook/manager-api': '8.3.0-alpha.2', + '@storybook/node-logger': '8.3.0-alpha.2', + '@storybook/preview': '8.3.0-alpha.2', + '@storybook/preview-api': '8.3.0-alpha.2', + '@storybook/router': '8.3.0-alpha.2', + '@storybook/telemetry': '8.3.0-alpha.2', + '@storybook/theming': '8.3.0-alpha.2', + '@storybook/types': '8.3.0-alpha.2', + '@storybook/angular': '8.3.0-alpha.2', + '@storybook/ember': '8.3.0-alpha.2', + '@storybook/html-vite': '8.3.0-alpha.2', + '@storybook/html-webpack5': '8.3.0-alpha.2', + '@storybook/nextjs': '8.3.0-alpha.2', + '@storybook/preact-vite': '8.3.0-alpha.2', + '@storybook/preact-webpack5': '8.3.0-alpha.2', + '@storybook/react-vite': '8.3.0-alpha.2', + '@storybook/react-webpack5': '8.3.0-alpha.2', + '@storybook/server-webpack5': '8.3.0-alpha.2', + '@storybook/svelte-vite': '8.3.0-alpha.2', + '@storybook/svelte-webpack5': '8.3.0-alpha.2', + '@storybook/sveltekit': '8.3.0-alpha.2', + '@storybook/vue3-vite': '8.3.0-alpha.2', + '@storybook/vue3-webpack5': '8.3.0-alpha.2', + '@storybook/web-components-vite': '8.3.0-alpha.2', + '@storybook/web-components-webpack5': '8.3.0-alpha.2', + '@storybook/blocks': '8.3.0-alpha.2', + storybook: '8.3.0-alpha.2', + sb: '8.3.0-alpha.2', + '@storybook/cli': '8.3.0-alpha.2', + '@storybook/codemod': '8.3.0-alpha.2', + '@storybook/core-webpack': '8.3.0-alpha.2', + '@storybook/csf-plugin': '8.3.0-alpha.2', + '@storybook/instrumenter': '8.3.0-alpha.2', + '@storybook/react-dom-shim': '8.3.0-alpha.2', + '@storybook/source-loader': '8.3.0-alpha.2', + '@storybook/test': '8.3.0-alpha.2', + '@storybook/preset-create-react-app': '8.3.0-alpha.2', + '@storybook/preset-html-webpack': '8.3.0-alpha.2', + '@storybook/preset-preact-webpack': '8.3.0-alpha.2', + '@storybook/preset-react-webpack': '8.3.0-alpha.2', + '@storybook/preset-server-webpack': '8.3.0-alpha.2', + '@storybook/preset-svelte-webpack': '8.3.0-alpha.2', + '@storybook/preset-vue3-webpack': '8.3.0-alpha.2', + '@storybook/html': '8.3.0-alpha.2', + '@storybook/preact': '8.3.0-alpha.2', + '@storybook/react': '8.3.0-alpha.2', + '@storybook/server': '8.3.0-alpha.2', + '@storybook/svelte': '8.3.0-alpha.2', + '@storybook/vue3': '8.3.0-alpha.2', + '@storybook/web-components': '8.3.0-alpha.2', }; diff --git a/code/core/src/core-events/data/save-story.ts b/code/core/src/core-events/data/save-story.ts index 8bb4091e513e..0162ecdb0819 100644 --- a/code/core/src/core-events/data/save-story.ts +++ b/code/core/src/core-events/data/save-story.ts @@ -9,7 +9,9 @@ export interface SaveStoryResponsePayload { csfId: string; newStoryId?: string; newStoryName?: string; + newStoryExportName?: string; sourceFileContent?: string; sourceFileName?: string; sourceStoryName?: string; + sourceStoryExportName?: string; } diff --git a/code/core/src/core-server/README.md b/code/core/src/core-server/README.md index 4af52cb89409..3dcc1dfcbac2 100644 --- a/code/core/src/core-server/README.md +++ b/code/core/src/core-server/README.md @@ -6,8 +6,8 @@ It contains: - CLI arg parsing - Storybook UI "manager" webpack configuration -- `start-storybook` dev server -- `build-storybook` static builder +- `storybook dev` dev server +- `storybook build` static builder - presets handling The "preview" (aka iframe) side is implemented in pluggable builders: diff --git a/code/core/src/core-server/dev-server.ts b/code/core/src/core-server/dev-server.ts index 1a8935d19a3a..1639e754fe04 100644 --- a/code/core/src/core-server/dev-server.ts +++ b/code/core/src/core-server/dev-server.ts @@ -95,7 +95,9 @@ export async function storybookDevServer(options: Options) { let previewStarted: Promise = Promise.resolve(); if (!options.ignorePreview) { - logger.info('=> Starting preview..'); + if (!options.quiet) { + logger.info('=> Starting preview..'); + } previewStarted = previewBuilder .start({ startTime: process.hrtime(), diff --git a/code/core/src/core-server/utils/StoryIndexGenerator.test.ts b/code/core/src/core-server/utils/StoryIndexGenerator.test.ts index 2d2b8d2b19c4..e07b46ba83af 100644 --- a/code/core/src/core-server/utils/StoryIndexGenerator.test.ts +++ b/code/core/src/core-server/utils/StoryIndexGenerator.test.ts @@ -68,7 +68,8 @@ describe('StoryIndexGenerator', () => { const generator = new StoryIndexGenerator([specifier], options); await generator.initialize(); - expect(await generator.getIndex()).toMatchInlineSnapshot(` + const { storyIndex, stats } = await generator.getIndexAndStats(); + expect(storyIndex).toMatchInlineSnapshot(` { "entries": { "a--story-one": { @@ -89,6 +90,18 @@ describe('StoryIndexGenerator', () => { "v": 5, } `); + + expect(stats).toMatchInlineSnapshot(` + { + "beforeEach": 0, + "loaders": 0, + "moduleMock": 0, + "mount": 0, + "play": 0, + "render": 0, + "storyFn": 0, + } + `); }); }); describe('single file .story specifier', () => { @@ -101,7 +114,8 @@ describe('StoryIndexGenerator', () => { const generator = new StoryIndexGenerator([specifier], options); await generator.initialize(); - expect(await generator.getIndex()).toMatchInlineSnapshot(` + const { storyIndex } = await generator.getIndexAndStats(); + expect(storyIndex).toMatchInlineSnapshot(` { "entries": { "f--story-one": { @@ -133,7 +147,8 @@ describe('StoryIndexGenerator', () => { const generator = new StoryIndexGenerator([specifier], options); await generator.initialize(); - expect(await generator.getIndex()).toMatchInlineSnapshot(` + const { storyIndex } = await generator.getIndexAndStats(); + expect(storyIndex).toMatchInlineSnapshot(` { "entries": { "stories--story-one": { @@ -165,7 +180,8 @@ describe('StoryIndexGenerator', () => { const generator = new StoryIndexGenerator([specifier], options); await generator.initialize(); - expect(await generator.getIndex()).toMatchInlineSnapshot(` + const { storyIndex } = await generator.getIndexAndStats(); + expect(storyIndex).toMatchInlineSnapshot(` { "entries": { "componentpath-extension--story-one": { @@ -245,7 +261,8 @@ describe('StoryIndexGenerator', () => { const generator = new StoryIndexGenerator([specifier], options); await generator.initialize(); - expect(await generator.getIndex()).toMatchInlineSnapshot(` + const { storyIndex, stats } = await generator.getIndexAndStats(); + expect(storyIndex).toMatchInlineSnapshot(` { "entries": { "a--story-one": { @@ -336,6 +353,68 @@ describe('StoryIndexGenerator', () => { "title": "first-nested/deeply/F", "type": "story", }, + "first-nested-deeply-features--with-csf-1": { + "componentPath": undefined, + "id": "first-nested-deeply-features--with-csf-1", + "importPath": "./src/first-nested/deeply/Features.stories.jsx", + "name": "With CSF 1", + "tags": [ + "dev", + "test", + ], + "title": "first-nested/deeply/Features", + "type": "story", + }, + "first-nested-deeply-features--with-play": { + "componentPath": undefined, + "id": "first-nested-deeply-features--with-play", + "importPath": "./src/first-nested/deeply/Features.stories.jsx", + "name": "With Play", + "tags": [ + "dev", + "test", + "play-fn", + ], + "title": "first-nested/deeply/Features", + "type": "story", + }, + "first-nested-deeply-features--with-render": { + "componentPath": undefined, + "id": "first-nested-deeply-features--with-render", + "importPath": "./src/first-nested/deeply/Features.stories.jsx", + "name": "With Render", + "tags": [ + "dev", + "test", + ], + "title": "first-nested/deeply/Features", + "type": "story", + }, + "first-nested-deeply-features--with-story-fn": { + "componentPath": undefined, + "id": "first-nested-deeply-features--with-story-fn", + "importPath": "./src/first-nested/deeply/Features.stories.jsx", + "name": "With Story Fn", + "tags": [ + "dev", + "test", + ], + "title": "first-nested/deeply/Features", + "type": "story", + }, + "first-nested-deeply-features--with-test": { + "componentPath": undefined, + "id": "first-nested-deeply-features--with-test", + "importPath": "./src/first-nested/deeply/Features.stories.jsx", + "name": "With Test", + "tags": [ + "dev", + "test", + "play-fn", + ], + "title": "first-nested/deeply/Features", + "type": "story", + }, "h--story-one": { "componentPath": undefined, "id": "h--story-one", @@ -378,6 +457,18 @@ describe('StoryIndexGenerator', () => { "v": 5, } `); + + expect(stats).toMatchInlineSnapshot(` + { + "beforeEach": 1, + "loaders": 1, + "moduleMock": 0, + "mount": 1, + "play": 2, + "render": 1, + "storyFn": 1, + } + `); }); }); @@ -395,7 +486,8 @@ describe('StoryIndexGenerator', () => { const generator = new StoryIndexGenerator([specifier], autodocsOptions); await generator.initialize(); - expect(await generator.getIndex()).toMatchInlineSnapshot(` + const { storyIndex, stats } = await generator.getIndexAndStats(); + expect(storyIndex).toMatchInlineSnapshot(` { "entries": { "a--story-one": { @@ -512,6 +604,68 @@ describe('StoryIndexGenerator', () => { "title": "first-nested/deeply/F", "type": "story", }, + "first-nested-deeply-features--with-csf-1": { + "componentPath": undefined, + "id": "first-nested-deeply-features--with-csf-1", + "importPath": "./src/first-nested/deeply/Features.stories.jsx", + "name": "With CSF 1", + "tags": [ + "dev", + "test", + ], + "title": "first-nested/deeply/Features", + "type": "story", + }, + "first-nested-deeply-features--with-play": { + "componentPath": undefined, + "id": "first-nested-deeply-features--with-play", + "importPath": "./src/first-nested/deeply/Features.stories.jsx", + "name": "With Play", + "tags": [ + "dev", + "test", + "play-fn", + ], + "title": "first-nested/deeply/Features", + "type": "story", + }, + "first-nested-deeply-features--with-render": { + "componentPath": undefined, + "id": "first-nested-deeply-features--with-render", + "importPath": "./src/first-nested/deeply/Features.stories.jsx", + "name": "With Render", + "tags": [ + "dev", + "test", + ], + "title": "first-nested/deeply/Features", + "type": "story", + }, + "first-nested-deeply-features--with-story-fn": { + "componentPath": undefined, + "id": "first-nested-deeply-features--with-story-fn", + "importPath": "./src/first-nested/deeply/Features.stories.jsx", + "name": "With Story Fn", + "tags": [ + "dev", + "test", + ], + "title": "first-nested/deeply/Features", + "type": "story", + }, + "first-nested-deeply-features--with-test": { + "componentPath": undefined, + "id": "first-nested-deeply-features--with-test", + "importPath": "./src/first-nested/deeply/Features.stories.jsx", + "name": "With Test", + "tags": [ + "dev", + "test", + "play-fn", + ], + "title": "first-nested/deeply/Features", + "type": "story", + }, "h--docs": { "id": "h--docs", "importPath": "./src/H.stories.mjs", @@ -567,6 +721,18 @@ describe('StoryIndexGenerator', () => { "v": 5, } `); + + expect(stats).toMatchInlineSnapshot(` + { + "beforeEach": 1, + "loaders": 1, + "moduleMock": 0, + "mount": 1, + "play": 2, + "render": 1, + "storyFn": 1, + } + `); }); const autodocsTrueOptions = { @@ -603,6 +769,12 @@ describe('StoryIndexGenerator', () => { "componentpath-package--story-one", "first-nested-deeply-f--docs", "first-nested-deeply-f--story-one", + "first-nested-deeply-features--docs", + "first-nested-deeply-features--with-play", + "first-nested-deeply-features--with-story-fn", + "first-nested-deeply-features--with-render", + "first-nested-deeply-features--with-test", + "first-nested-deeply-features--with-csf-1", "nested-button--docs", "nested-button--story-one", "second-nested-g--docs", @@ -639,6 +811,12 @@ describe('StoryIndexGenerator', () => { "componentpath-package--story-one", "first-nested-deeply-f--docs", "first-nested-deeply-f--story-one", + "first-nested-deeply-features--docs", + "first-nested-deeply-features--with-play", + "first-nested-deeply-features--with-story-fn", + "first-nested-deeply-features--with-render", + "first-nested-deeply-features--with-test", + "first-nested-deeply-features--with-csf-1", "nested-button--docs", "nested-button--story-one", "second-nested-g--docs", @@ -730,7 +908,8 @@ describe('StoryIndexGenerator', () => { const generator = new StoryIndexGenerator([csfSpecifier, docsSpecifier], autodocsOptions); await generator.initialize(); - expect(await generator.getIndex()).toMatchInlineSnapshot(` + const { storyIndex } = await generator.getIndexAndStats(); + expect(storyIndex).toMatchInlineSnapshot(` { "entries": { "b--docs": { @@ -794,7 +973,8 @@ describe('StoryIndexGenerator', () => { const generator = new StoryIndexGenerator([csfSpecifier, docsSpecifier], autodocsOptions); await generator.initialize(); - expect(await generator.getIndex()).toMatchInlineSnapshot(` + const { storyIndex } = await generator.getIndexAndStats(); + expect(storyIndex).toMatchInlineSnapshot(` { "entries": { "b--docs": { @@ -862,7 +1042,8 @@ describe('StoryIndexGenerator', () => { ); await generator.initialize(); - expect(await generator.getIndex()).toMatchInlineSnapshot(` + const { storyIndex } = await generator.getIndexAndStats(); + expect(storyIndex).toMatchInlineSnapshot(` { "entries": { "a--docs": { @@ -919,7 +1100,8 @@ describe('StoryIndexGenerator', () => { generator.getProjectTags = () => ['dev', 'test', 'autodocs']; await generator.initialize(); - expect(await generator.getIndex()).toMatchInlineSnapshot(` + const { storyIndex } = await generator.getIndexAndStats(); + expect(storyIndex).toMatchInlineSnapshot(` { "entries": { "a--docs": { @@ -970,7 +1152,8 @@ describe('StoryIndexGenerator', () => { const generator = new StoryIndexGenerator([specifier], autodocsOptions); await generator.initialize(); - expect(await generator.getIndex()).toMatchInlineSnapshot(` + const { storyIndex } = await generator.getIndexAndStats(); + expect(storyIndex).toMatchInlineSnapshot(` { "entries": { "duplicate-a--docs": { @@ -1030,7 +1213,8 @@ describe('StoryIndexGenerator', () => { const generator = new StoryIndexGenerator([csfSpecifier], autodocsOptions); await generator.initialize(); - expect(await generator.getIndex()).toMatchInlineSnapshot(` + const { storyIndex } = await generator.getIndexAndStats(); + expect(storyIndex).toMatchInlineSnapshot(` { "entries": {}, "v": 5, @@ -1047,7 +1231,8 @@ describe('StoryIndexGenerator', () => { const generator = new StoryIndexGenerator([csfSpecifier], autodocsOptions); await generator.initialize(); - expect(await generator.getIndex()).toMatchInlineSnapshot(` + const { storyIndex } = await generator.getIndexAndStats(); + expect(storyIndex).toMatchInlineSnapshot(` { "entries": { "my-component-a--docs": { @@ -1088,7 +1273,8 @@ describe('StoryIndexGenerator', () => { const generator = new StoryIndexGenerator([storiesSpecifier, docsSpecifier], options); await generator.initialize(); - expect(await generator.getIndex()).toMatchInlineSnapshot(` + const { storyIndex } = await generator.getIndexAndStats(); + expect(storyIndex).toMatchInlineSnapshot(` { "entries": { "a--metaof": { @@ -1222,7 +1408,8 @@ describe('StoryIndexGenerator', () => { }); await generator.initialize(); - expect(await generator.getIndex()).toMatchInlineSnapshot(` + const { storyIndex } = await generator.getIndexAndStats(); + expect(storyIndex).toMatchInlineSnapshot(` { "entries": { "a--metaof": { @@ -1328,7 +1515,8 @@ describe('StoryIndexGenerator', () => { options ); await generator.initialize(); - expect(await generator.getIndex()).toMatchInlineSnapshot(` + const { storyIndex } = await generator.getIndexAndStats(); + expect(storyIndex).toMatchInlineSnapshot(` { "entries": { "a--story-one": { @@ -1395,7 +1583,8 @@ describe('StoryIndexGenerator', () => { const generator = new StoryIndexGenerator([csfSpecifier, docsSpecifier], options); await generator.initialize(); - expect(await generator.getIndex()).toMatchInlineSnapshot(` + const { storyIndex } = await generator.getIndexAndStats(); + expect(storyIndex).toMatchInlineSnapshot(` { "entries": { "my-component-b--docs": { @@ -1603,6 +1792,11 @@ describe('StoryIndexGenerator', () => { "componentpath-noextension--story-one", "componentpath-package--story-one", "first-nested-deeply-f--story-one", + "first-nested-deeply-features--with-play", + "first-nested-deeply-features--with-story-fn", + "first-nested-deeply-features--with-render", + "first-nested-deeply-features--with-test", + "first-nested-deeply-features--with-csf-1", ] `); }); @@ -1621,7 +1815,7 @@ describe('StoryIndexGenerator', () => { const generator = new StoryIndexGenerator([specifier], options); await generator.initialize(); await generator.getIndex(); - expect(readCsfMock).toHaveBeenCalledTimes(10); + expect(readCsfMock).toHaveBeenCalledTimes(11); readCsfMock.mockClear(); await generator.getIndex(); @@ -1679,7 +1873,7 @@ describe('StoryIndexGenerator', () => { const generator = new StoryIndexGenerator([specifier], options); await generator.initialize(); await generator.getIndex(); - expect(readCsfMock).toHaveBeenCalledTimes(10); + expect(readCsfMock).toHaveBeenCalledTimes(11); generator.invalidate(specifier, './src/B.stories.ts', false); @@ -1764,7 +1958,7 @@ describe('StoryIndexGenerator', () => { const generator = new StoryIndexGenerator([specifier], options); await generator.initialize(); await generator.getIndex(); - expect(readCsfMock).toHaveBeenCalledTimes(10); + expect(readCsfMock).toHaveBeenCalledTimes(11); generator.invalidate(specifier, './src/B.stories.ts', true); @@ -1803,7 +1997,7 @@ describe('StoryIndexGenerator', () => { const generator = new StoryIndexGenerator([specifier], options); await generator.initialize(); await generator.getIndex(); - expect(readCsfMock).toHaveBeenCalledTimes(10); + expect(readCsfMock).toHaveBeenCalledTimes(11); generator.invalidate(specifier, './src/B.stories.ts', true); diff --git a/code/core/src/core-server/utils/StoryIndexGenerator.ts b/code/core/src/core-server/utils/StoryIndexGenerator.ts index dfcf2d4a5f51..64aa9744e00e 100644 --- a/code/core/src/core-server/utils/StoryIndexGenerator.ts +++ b/code/core/src/core-server/utils/StoryIndexGenerator.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-underscore-dangle */ import path from 'node:path'; import chalk from 'chalk'; import fs from 'fs-extra'; @@ -17,6 +18,7 @@ import type { StoryIndex, Indexer, StorybookConfigRaw, + IndexInputStats, } from '@storybook/core/types'; import { userOrAutoTitleFromSpecifier, sortStoriesV7 } from '@storybook/core/preview-api'; import { commonGlobOptions, normalizeStoryPath } from '@storybook/core/common'; @@ -26,14 +28,17 @@ import { storyNameFromExport, toId, combineTags } from '@storybook/csf'; import { dedent } from 'ts-dedent'; import { autoName } from './autoName'; import { IndexingError, MultipleIndexingError } from './IndexingError'; +import { addStats, type IndexStatsSummary } from './summarizeStats'; // Extended type to keep track of the csf meta id so we know the component id when referencing docs in `extractDocs` -type StoryIndexEntryWithMetaId = StoryIndexEntry & { metaId?: string }; +type StoryIndexEntryWithExtra = StoryIndexEntry & { + extra: { metaId?: string; stats: IndexInputStats }; +}; /** A .mdx file will produce a docs entry */ type DocsCacheEntry = DocsIndexEntry; /** A *.stories.* file will produce a list of stories and possibly a docs entry */ type StoriesCacheEntry = { - entries: (StoryIndexEntryWithMetaId | DocsIndexEntry)[]; + entries: (StoryIndexEntryWithExtra | DocsIndexEntry)[]; dependents: Path[]; type: 'stories'; }; @@ -103,6 +108,9 @@ export class StoryIndexGenerator { // - the preview changes [not yet implemented] private lastIndex?: StoryIndex | null; + // Cache the last value stats calculation, mirroring lastIndex + private lastStats?: IndexStatsSummary; + // Same as the above but for the error case private lastError?: Error | null; @@ -221,7 +229,7 @@ export class StoryIndexGenerator { projectTags, }: { projectTags?: Tag[]; - }): Promise<(IndexEntry | ErrorEntry)[]> { + }): Promise<{ entries: (IndexEntry | ErrorEntry)[]; stats: IndexStatsSummary }> { // First process all the story files. Then, in a second pass, // process the docs files. The reason for this is that the docs // files may use the `` syntax, which requires @@ -236,7 +244,8 @@ export class StoryIndexGenerator { this.extractDocs(specifier, absolutePath, projectTags) ); - return this.specifiers.flatMap((specifier) => { + const statsSummary = {} as IndexStatsSummary; + const entries = this.specifiers.flatMap((specifier) => { const cache = this.specifierToCache.get(specifier); invariant( cache, @@ -251,12 +260,17 @@ export class StoryIndexGenerator { return entry.entries.map((item) => { if (item.type === 'docs') return item; - // Drop the meta id as it isn't part of the index, we just used it for record keeping in `extractDocs` - const { metaId, ...existing } = item; + + addStats(item.extra.stats, statsSummary); + + // Drop extra data used for internal bookkeeping + const { extra, ...existing } = item; return existing; }); }); }); + + return { entries, stats: statsSummary }; } findDependencies(absoluteImports: Path[]) { @@ -340,7 +354,7 @@ export class StoryIndexGenerator { ]); } - const entries: ((StoryIndexEntryWithMetaId | DocsCacheEntry) & { tags: Tag[] })[] = + const entries: ((StoryIndexEntryWithExtra | DocsCacheEntry) & { tags: Tag[] })[] = indexInputs.map((input) => { const name = input.name ?? storyNameFromExport(input.exportName); const componentPath = @@ -348,14 +362,16 @@ export class StoryIndexGenerator { this.resolveComponentPath(input.rawComponentPath, absolutePath, matchPath); const title = input.title ?? defaultMakeTitle(); - // eslint-disable-next-line no-underscore-dangle const id = input.__id ?? toId(input.metaId ?? title, storyNameFromExport(input.exportName)); const tags = combineTags(...projectTags, ...(input.tags ?? [])); return { type: 'story', id, - metaId: input.metaId, + extra: { + metaId: input.metaId, + stats: input.__stats ?? {}, + }, name, title, importPath, @@ -428,12 +444,12 @@ export class StoryIndexGenerator { // Also, if `result.of` is set, it means that we're using the `` syntax, // so find the `title` defined the file that `meta` points to. - let csfEntry: StoryIndexEntryWithMetaId | undefined; + let csfEntry: StoryIndexEntryWithExtra | undefined; if (result.of) { const absoluteOf = makeAbsolute(result.of, normalizedPath, this.options.workingDir); dependencies.forEach((dep) => { if (dep.entries.length > 0) { - const first = dep.entries.find((e) => e.type !== 'docs') as StoryIndexEntryWithMetaId; + const first = dep.entries.find((e) => e.type !== 'docs') as StoryIndexEntryWithExtra; if ( path @@ -475,7 +491,7 @@ export class StoryIndexGenerator { result.name || (csfEntry ? autoName(importPath, csfEntry.importPath, defaultName) : defaultName); - const id = toId(csfEntry?.metaId || title, name); + const id = toId(csfEntry?.extra.metaId || title, name); const tags = combineTags( ...projectTags, @@ -598,7 +614,12 @@ export class StoryIndexGenerator { } async getIndex() { - if (this.lastIndex) return this.lastIndex; + return (await this.getIndexAndStats()).storyIndex; + } + + async getIndexAndStats(): Promise<{ storyIndex: StoryIndex; stats: IndexStatsSummary }> { + if (this.lastIndex && this.lastStats) + return { storyIndex: this.lastIndex, stats: this.lastStats }; if (this.lastError) throw this.lastError; const previewCode = await this.getPreviewCode(); @@ -606,7 +627,7 @@ export class StoryIndexGenerator { // Extract any entries that are currently missing // Pull out each file's stories into a list of stories, to be composed and sorted - const storiesList = await this.ensureExtracted({ projectTags }); + const { entries: storiesList, stats } = await this.ensureExtracted({ projectTags }); try { const errorEntries = storiesList.filter((entry) => entry.type === 'error'); @@ -635,12 +656,13 @@ export class StoryIndexGenerator { previewCode && getStorySortParameter(previewCode) ); + this.lastStats = stats; this.lastIndex = { v: 5, entries: sorted, }; - return this.lastIndex; + return { storyIndex: this.lastIndex, stats: this.lastStats }; } catch (err) { this.lastError = err == null || err instanceof Error ? err : undefined; invariant(this.lastError); diff --git a/code/core/src/core-server/utils/__mockdata__/src/first-nested/deeply/Features.stories.jsx b/code/core/src/core-server/utils/__mockdata__/src/first-nested/deeply/Features.stories.jsx new file mode 100644 index 000000000000..90d96b590b6a --- /dev/null +++ b/code/core/src/core-server/utils/__mockdata__/src/first-nested/deeply/Features.stories.jsx @@ -0,0 +1,27 @@ +const component = {}; +export default { + component, +}; + +export const WithPlay = { + play: async () => {}, +}; + +export const WithStoryFn = () => {}; + +export const WithRender = { + render: () => {}, +}; + +export const WithTest = { + beforeEach: async () => {}, + play: async ({ mount }) => { + await mount(); + }, +}; + +export const WithCSF1 = { + parameters: {}, + decorators: [], + loaders: [], +}; diff --git a/code/core/src/core-server/utils/__tests__/index-extraction.test.ts b/code/core/src/core-server/utils/__tests__/index-extraction.test.ts index 01a880479b99..6fbbdeb41c6c 100644 --- a/code/core/src/core-server/utils/__tests__/index-extraction.test.ts +++ b/code/core/src/core-server/utils/__tests__/index-extraction.test.ts @@ -62,9 +62,12 @@ describe('story extraction', () => { "entries": [ { "componentPath": undefined, + "extra": { + "metaId": "a", + "stats": {}, + }, "id": "a--story-one", "importPath": "./src/A.stories.js", - "metaId": "a", "name": "Story One", "tags": [ "story-tag-from-indexer", @@ -74,9 +77,12 @@ describe('story extraction', () => { }, { "componentPath": undefined, + "extra": { + "metaId": "custom-id", + "stats": {}, + }, "id": "some-fully-custom-id", "importPath": "./src/A.stories.js", - "metaId": "custom-id", "name": "Another Story Name", "tags": [ "story-tag-from-indexer", @@ -118,9 +124,12 @@ describe('story extraction', () => { "entries": [ { "componentPath": undefined, + "extra": { + "metaId": undefined, + "stats": {}, + }, "id": "f--story-one", "importPath": "./src/first-nested/deeply/F.stories.js", - "metaId": undefined, "name": "Story One", "tags": [], "title": "F", @@ -164,9 +173,12 @@ describe('story extraction', () => { "entries": [ { "componentPath": undefined, + "extra": { + "metaId": "a", + "stats": {}, + }, "id": "a--story-one", "importPath": "./src/first-nested/deeply/F.stories.js", - "metaId": "a", "name": "Story One", "tags": [ "story-tag-from-indexer", @@ -212,9 +224,12 @@ describe('story extraction', () => { "entries": [ { "componentPath": undefined, + "extra": { + "metaId": "a", + "stats": {}, + }, "id": "a--story-one", "importPath": "./src/A.stories.js", - "metaId": "a", "name": "Story One", "tags": [ "story-tag-from-indexer", @@ -278,9 +293,12 @@ describe('story extraction', () => { "entries": [ { "componentPath": undefined, + "extra": { + "metaId": undefined, + "stats": {}, + }, "id": "a--story-one", "importPath": "./src/A.stories.js", - "metaId": undefined, "name": "Story One", "tags": [ "story-tag-from-indexer", @@ -290,9 +308,12 @@ describe('story extraction', () => { }, { "componentPath": undefined, + "extra": { + "metaId": undefined, + "stats": {}, + }, "id": "custom-title--story-two", "importPath": "./src/A.stories.js", - "metaId": undefined, "name": "Custom Name For Second Story", "tags": [ "story-tag-from-indexer", @@ -302,9 +323,12 @@ describe('story extraction', () => { }, { "componentPath": undefined, + "extra": { + "metaId": "custom-meta-id", + "stats": {}, + }, "id": "custom-meta-id--story-three", "importPath": "./src/A.stories.js", - "metaId": "custom-meta-id", "name": "Story Three", "tags": [ "story-tag-from-indexer", @@ -347,9 +371,12 @@ describe('story extraction', () => { "entries": [ { "componentPath": undefined, + "extra": { + "metaId": undefined, + "stats": {}, + }, "id": "a--story-one", "importPath": "./src/A.stories.js", - "metaId": undefined, "name": "Story One", "tags": [ "story-tag-from-indexer", @@ -397,9 +424,12 @@ describe('docs entries from story extraction', () => { "entries": [ { "componentPath": undefined, + "extra": { + "metaId": undefined, + "stats": {}, + }, "id": "a--story-one", "importPath": "./src/A.stories.js", - "metaId": undefined, "name": "Story One", "tags": [ "story-tag-from-indexer", @@ -457,9 +487,12 @@ describe('docs entries from story extraction', () => { }, { "componentPath": undefined, + "extra": { + "metaId": undefined, + "stats": {}, + }, "id": "a--story-one", "importPath": "./src/A.stories.js", - "metaId": undefined, "name": "Story One", "tags": [ "autodocs", @@ -506,9 +539,12 @@ describe('docs entries from story extraction', () => { "entries": [ { "componentPath": undefined, + "extra": { + "metaId": undefined, + "stats": {}, + }, "id": "a--story-one", "importPath": "./src/A.stories.js", - "metaId": undefined, "name": "Story One", "tags": [ "autodocs", diff --git a/code/core/src/core-server/utils/doTelemetry.ts b/code/core/src/core-server/utils/doTelemetry.ts index b7d039119c3b..be9479cf3348 100644 --- a/code/core/src/core-server/utils/doTelemetry.ts +++ b/code/core/src/core-server/utils/doTelemetry.ts @@ -15,9 +15,9 @@ export async function doTelemetry( ) { if (!core?.disableTelemetry) { initializedStoryIndexGenerator.then(async (generator) => { - let storyIndex: StoryIndex | undefined; + let indexAndStats; try { - storyIndex = await generator?.getIndex(); + indexAndStats = await generator?.getIndexAndStats(); } catch (err) { // If we fail to get the index, treat it as a recoverable error, but send it up to telemetry // as if we crashed. In the future we will revisit this to send a distinct error @@ -36,10 +36,11 @@ export async function doTelemetry( const payload = { precedingUpgrade: await getPrecedingUpgrade(), }; - if (storyIndex) { + if (indexAndStats) { Object.assign(payload, { versionStatus: versionUpdates && versionCheck ? versionStatus(versionCheck) : 'disabled', - storyIndex: summarizeIndex(storyIndex), + storyIndex: summarizeIndex(indexAndStats.storyIndex), + storyStats: indexAndStats.stats, }); } telemetry('dev', payload, { configDir: options.configDir }); diff --git a/code/core/src/core-server/utils/save-story/save-story.ts b/code/core/src/core-server/utils/save-story/save-story.ts index 8ad7ef738ff3..5369d99a4cba 100644 --- a/code/core/src/core-server/utils/save-story/save-story.ts +++ b/code/core/src/core-server/utils/save-story/save-story.ts @@ -111,9 +111,11 @@ export function initializeSaveStory(channel: Channel, options: Options, coreConf csfId, newStoryId, newStoryName, + newStoryExportName: name, sourceFileContent: code, sourceFileName, sourceStoryName, + sourceStoryExportName: storyName, }, error: null, } satisfies ResponseData); diff --git a/code/core/src/core-server/utils/stories-json.test.ts b/code/core/src/core-server/utils/stories-json.test.ts index 84b201ab62f1..a4ad0fa780b7 100644 --- a/code/core/src/core-server/utils/stories-json.test.ts +++ b/code/core/src/core-server/utils/stories-json.test.ts @@ -263,6 +263,63 @@ describe('useStoriesJson', () => { "title": "first-nested/deeply/F", "type": "story", }, + "first-nested-deeply-features--with-csf-1": { + "id": "first-nested-deeply-features--with-csf-1", + "importPath": "./src/first-nested/deeply/Features.stories.jsx", + "name": "With CSF 1", + "tags": [ + "dev", + "test", + ], + "title": "first-nested/deeply/Features", + "type": "story", + }, + "first-nested-deeply-features--with-play": { + "id": "first-nested-deeply-features--with-play", + "importPath": "./src/first-nested/deeply/Features.stories.jsx", + "name": "With Play", + "tags": [ + "dev", + "test", + "play-fn", + ], + "title": "first-nested/deeply/Features", + "type": "story", + }, + "first-nested-deeply-features--with-render": { + "id": "first-nested-deeply-features--with-render", + "importPath": "./src/first-nested/deeply/Features.stories.jsx", + "name": "With Render", + "tags": [ + "dev", + "test", + ], + "title": "first-nested/deeply/Features", + "type": "story", + }, + "first-nested-deeply-features--with-story-fn": { + "id": "first-nested-deeply-features--with-story-fn", + "importPath": "./src/first-nested/deeply/Features.stories.jsx", + "name": "With Story Fn", + "tags": [ + "dev", + "test", + ], + "title": "first-nested/deeply/Features", + "type": "story", + }, + "first-nested-deeply-features--with-test": { + "id": "first-nested-deeply-features--with-test", + "importPath": "./src/first-nested/deeply/Features.stories.jsx", + "name": "With Test", + "tags": [ + "dev", + "test", + "play-fn", + ], + "title": "first-nested/deeply/Features", + "type": "story", + }, "h--story-one": { "id": "h--story-one", "importPath": "./src/H.stories.mjs", diff --git a/code/core/src/core-server/utils/summarizeStats.test.ts b/code/core/src/core-server/utils/summarizeStats.test.ts new file mode 100644 index 000000000000..e1e342e94260 --- /dev/null +++ b/code/core/src/core-server/utils/summarizeStats.test.ts @@ -0,0 +1,18 @@ +import { it, expect } from 'vitest'; +import { summarizeStats } from './summarizeStats'; + +it('should summarize stats', () => { + const stats = [ + { play: true, render: true, storyFn: false }, + { play: true, render: false, storyFn: false }, + { play: false, render: false, storyFn: false }, + ]; + const result = summarizeStats(stats); + expect(result).toMatchInlineSnapshot(` + { + "play": 2, + "render": 1, + "storyFn": 0, + } + `); +}); diff --git a/code/core/src/core-server/utils/summarizeStats.ts b/code/core/src/core-server/utils/summarizeStats.ts new file mode 100644 index 000000000000..bdd0ef026ce5 --- /dev/null +++ b/code/core/src/core-server/utils/summarizeStats.ts @@ -0,0 +1,18 @@ +import type { IndexInputStats } from '@storybook/core/types'; + +export type IndexStatsSummary = Record; + +export const addStats = (stat: IndexInputStats, acc: IndexStatsSummary) => { + Object.entries(stat).forEach(([key, value]) => { + const statsKey = key as keyof IndexInputStats; + if (!acc[statsKey]) acc[statsKey] = 0; + acc[statsKey] += value ? 1 : 0; + }); +}; + +export const summarizeStats = (stats: IndexInputStats[]): IndexStatsSummary => { + return stats.reduce((acc, stat) => { + addStats(stat, acc); + return acc; + }, {} as IndexStatsSummary); +}; diff --git a/code/core/src/csf-tools/CsfFile.test.ts b/code/core/src/csf-tools/CsfFile.test.ts index 4c87576d2474..0988e938a51b 100644 --- a/code/core/src/csf-tools/CsfFile.test.ts +++ b/code/core/src/csf-tools/CsfFile.test.ts @@ -2,7 +2,7 @@ import { dedent } from 'ts-dedent'; import { describe, it, expect, vi } from 'vitest'; import yaml from 'js-yaml'; -import { loadCsf } from './CsfFile'; +import { loadCsf, isModuleMock } from './CsfFile'; expect.addSnapshotSerializer({ print: (val: any) => yaml.dump(val).trimEnd(), @@ -42,11 +42,27 @@ describe('CsfFile', () => { parameters: __isArgsStory: false __id: foo-bar--a + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false - id: foo-bar--b name: B parameters: __isArgsStory: true __id: foo-bar--b + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false `); }); @@ -69,10 +85,26 @@ describe('CsfFile', () => { name: A parameters: __id: foo-bar--a + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false - id: foo-bar--b name: B parameters: __id: foo-bar--b + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false `); }); @@ -94,6 +126,14 @@ describe('CsfFile', () => { parameters: __isArgsStory: false __id: foo-bar--basic + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false `); }); @@ -116,6 +156,14 @@ describe('CsfFile', () => { stories: - id: foo-bar--a name: A + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false `); }); @@ -136,6 +184,14 @@ describe('CsfFile', () => { stories: - id: foo-bar--include-a name: Include A + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false `); }); @@ -154,6 +210,14 @@ describe('CsfFile', () => { stories: - id: foo-bar--a name: Some story + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false `); }); @@ -173,8 +237,24 @@ describe('CsfFile', () => { stories: - id: default-title--a name: A + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false - id: default-title--b name: B + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false `); }); @@ -194,8 +274,24 @@ describe('CsfFile', () => { stories: - id: custom-id--a name: A + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false - id: custom-id--b name: B + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false `); }); @@ -215,8 +311,24 @@ describe('CsfFile', () => { stories: - id: custom-meta-id--just-custom-meta-id name: Just Custom Meta Id + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false - id: custom-id name: Custom Paremeters Id + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false `); }); @@ -237,8 +349,24 @@ describe('CsfFile', () => { stories: - id: foo-bar-baz--a name: A + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false - id: foo-bar-baz--b name: B + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false `); }); @@ -263,11 +391,27 @@ describe('CsfFile', () => { parameters: __isArgsStory: true __id: foo-bar--a + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false - id: foo-bar--b name: B parameters: __isArgsStory: true __id: foo-bar--b + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false `); }); @@ -292,11 +436,27 @@ describe('CsfFile', () => { parameters: __isArgsStory: true __id: foo-bar--a + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false - id: foo-bar--b name: B parameters: __isArgsStory: true __id: foo-bar--b + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false `); }); @@ -318,8 +478,24 @@ describe('CsfFile', () => { stories: - id: foo-bar-baz--a name: A + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false - id: foo-bar-baz--b name: B + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false `); }); @@ -341,8 +517,24 @@ describe('CsfFile', () => { stories: - id: foo-bar-baz--a name: A + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false - id: foo-bar-baz--b name: B + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false `); }); @@ -362,8 +554,24 @@ describe('CsfFile', () => { stories: - id: default-title--a name: A + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false - id: default-title--b name: B + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false `); }); @@ -387,6 +595,14 @@ describe('CsfFile', () => { parameters: __isArgsStory: true __id: foo-bar--a + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false `); }); @@ -409,6 +625,14 @@ describe('CsfFile', () => { parameters: __isArgsStory: false __id: foo-bar--a + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false `); }); @@ -432,6 +656,14 @@ describe('CsfFile', () => { __isArgsStory: false __id: foo-bar--page docsOnly: true + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false `); }); @@ -460,6 +692,14 @@ describe('CsfFile', () => { __isArgsStory: false __id: foo-bar--page docsOnly: true + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false `); }); @@ -483,11 +723,27 @@ describe('CsfFile', () => { parameters: __isArgsStory: false __id: foo-bar--a + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false - id: foo-bar--b name: B parameters: __isArgsStory: true __id: foo-bar--b + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false `); }); @@ -506,8 +762,24 @@ describe('CsfFile', () => { stories: - id: foo-bar--a name: A + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false - id: foo-bar--b name: B + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false `); }); @@ -531,11 +803,27 @@ describe('CsfFile', () => { parameters: __isArgsStory: true __id: foo-bar--b + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false - id: foo-bar--a name: A parameters: __isArgsStory: false __id: foo-bar--a + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false `); }); @@ -560,6 +848,14 @@ describe('CsfFile', () => { name: A parameters: __id: foo-bar--a + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false `); }); @@ -631,8 +927,24 @@ describe('CsfFile', () => { stories: - id: default-title--a name: A + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false - id: default-title--b name: B + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false `); }); @@ -677,8 +989,24 @@ describe('CsfFile', () => { stories: - id: foo-bar--a name: A + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false - id: foo-bar--b name: B + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false `); }); }); @@ -747,6 +1075,14 @@ describe('CsfFile', () => { parameters: __isArgsStory: false __id: foo-bar--a + __stats: + play: false + render: true + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false `); }); @@ -770,6 +1106,14 @@ describe('CsfFile', () => { parameters: __isArgsStory: true __id: foo-bar--a + __stats: + play: false + render: true + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false `); }); @@ -791,6 +1135,14 @@ describe('CsfFile', () => { parameters: __isArgsStory: true __id: foo-bar--a + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false `); }); @@ -814,6 +1166,14 @@ describe('CsfFile', () => { parameters: __isArgsStory: true __id: foo-bar--a + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false `); }); @@ -886,6 +1246,14 @@ describe('CsfFile', () => { stories: - id: foo-bar--a name: A + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false tags: - 'Y' `); @@ -910,6 +1278,14 @@ describe('CsfFile', () => { stories: - id: foo-bar--a name: A + __stats: + play: false + render: true + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false tags: - 'Y' `); @@ -936,6 +1312,14 @@ describe('CsfFile', () => { stories: - id: foo-bar--a name: A + __stats: + play: false + render: true + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false tags: - 'Y' `); @@ -987,6 +1371,14 @@ describe('CsfFile', () => { stories: - id: foo-bar--a name: A + __stats: + play: true + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false tags: - 'Y' - play-fn @@ -1013,12 +1405,108 @@ describe('CsfFile', () => { stories: - id: foo-bar--a name: A + __stats: + play: true + render: true + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false tags: - 'Y' - play-fn `); }); + it('mount', () => { + expect( + parse( + dedent` + export default { title: 'foo/bar' }; + export const A = { + play: ({ mount }) => {}, + }; + ` + ) + ).toMatchInlineSnapshot(` + meta: + title: foo/bar + stories: + - id: foo-bar--a + name: A + __stats: + play: true + render: false + loaders: false + beforeEach: false + storyFn: false + mount: true + moduleMock: false + tags: + - play-fn + `); + }); + + it('mount renamed', () => { + expect( + parse( + dedent` + export default { title: 'foo/bar' }; + export const A = { + play: ({ mount: mountRenamed, context }) => {}, + }; + ` + ) + ).toMatchInlineSnapshot(` + meta: + title: foo/bar + stories: + - id: foo-bar--a + name: A + __stats: + play: true + render: false + loaders: false + beforeEach: false + storyFn: false + mount: true + moduleMock: false + tags: + - play-fn + `); + }); + + it('mount meta', () => { + expect( + parse( + dedent` + export default { + title: 'foo/bar', + play: ({ context, mount: mountRenamed }) => {}, + }; + export const A = {}; + ` + ) + ).toMatchInlineSnapshot(` + meta: + title: foo/bar + tags: + - play-fn + stories: + - id: foo-bar--a + name: A + __stats: + play: true + render: false + loaders: false + beforeEach: false + storyFn: false + mount: true + moduleMock: false + `); + }); + it('meta csf2', () => { expect( parse( @@ -1026,6 +1514,7 @@ describe('CsfFile', () => { export default { title: 'foo/bar', play: () => {}, tags: ['X'] }; export const A = { render: () => {}, + loaders: [], tags: ['Y'], }; ` @@ -1039,6 +1528,14 @@ describe('CsfFile', () => { stories: - id: foo-bar--a name: A + __stats: + play: true + render: true + loaders: true + beforeEach: false + storyFn: false + mount: false + moduleMock: false tags: - 'Y' `); @@ -1062,6 +1559,14 @@ describe('CsfFile', () => { stories: - id: foo-bar--a name: A + __stats: + play: true + render: false + loaders: false + beforeEach: false + storyFn: true + mount: false + moduleMock: false tags: - 'Y' `); @@ -1103,6 +1608,14 @@ describe('CsfFile', () => { - story-tag - play-fn __id: component-id--a + __stats: + play: true + render: false + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false - type: story importPath: foo/bar.stories.js exportName: B @@ -1114,6 +1627,14 @@ describe('CsfFile', () => { - story-tag - play-fn __id: component-id--b + __stats: + play: true + render: false + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false `); }); @@ -1143,6 +1664,14 @@ describe('CsfFile', () => { tags: - component-tag __id: custom-story-id + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false `); }); @@ -1177,6 +1706,14 @@ describe('CsfFile', () => { - story-tag-dup - inherit-tag-dup __id: custom-foo-title--a + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false `); }); @@ -1226,6 +1763,14 @@ describe('CsfFile', () => { title: custom foo title tags: [] __id: custom-foo-title--a + __stats: + play: false + render: true + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false `); }); @@ -1254,6 +1799,14 @@ describe('CsfFile', () => { title: custom foo title tags: [] __id: custom-foo-title--a + __stats: + play: false + render: true + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false `); }); @@ -1282,6 +1835,14 @@ describe('CsfFile', () => { title: custom foo title tags: [] __id: custom-foo-title--a + __stats: + play: false + render: true + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false `); }); @@ -1310,7 +1871,117 @@ describe('CsfFile', () => { title: custom foo title tags: [] __id: custom-foo-title--a + __stats: + play: false + render: true + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: false + `); + }); + }); + + describe('beforeEach', () => { + it('basic', () => { + expect( + parse( + dedent` + export default { title: 'foo/bar' }; + export const A = { + beforeEach: async () => {}, + }; + ` + ) + ).toMatchInlineSnapshot(` + meta: + title: foo/bar + stories: + - id: foo-bar--a + name: A + __stats: + play: false + render: false + loaders: false + beforeEach: true + storyFn: false + mount: false + moduleMock: false `); }); }); + + describe('module mocks', () => { + it('alias', () => { + expect( + parse( + dedent` + import foo from '#bar.mock'; + export default { title: 'foo/bar' }; + export const A = {}; + ` + ) + ).toMatchInlineSnapshot(` + meta: + title: foo/bar + stories: + - id: foo-bar--a + name: A + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: true + `); + }); + it('relative', () => { + expect( + parse( + dedent` + import foo from './bar.mock'; + export default { title: 'foo/bar' }; + export const A = {}; + ` + ) + ).toMatchInlineSnapshot(` + meta: + title: foo/bar + stories: + - id: foo-bar--a + name: A + __stats: + play: false + render: false + loaders: false + beforeEach: false + storyFn: false + mount: false + moduleMock: true + `); + }); + }); +}); + +describe('isModuleMock', () => { + it('prefix', () => { + expect(isModuleMock('#foo.mock')).toBe(true); + expect(isModuleMock('./foo.mock')).toBe(true); + expect(isModuleMock('../foo.mock')).toBe(true); + expect(isModuleMock('/foo.mock')).toBe(true); + + expect(isModuleMock('foo.mock')).toBe(false); + expect(isModuleMock('@/foo.mock')).toBe(false); + }); + it('sufixes', () => { + expect(isModuleMock('#foo.mock.js')).toBe(true); + expect(isModuleMock('#foo.mock.mjs')).toBe(true); + expect(isModuleMock('#foo.mock.vue')).toBe(true); + + expect(isModuleMock('#foo.mocktail')).toBe(false); + expect(isModuleMock('#foo.mock.test.ts')).toBe(false); + }); }); diff --git a/code/core/src/csf-tools/CsfFile.ts b/code/core/src/csf-tools/CsfFile.ts index 2ab3bfa27408..149a182bcf7d 100644 --- a/code/core/src/csf-tools/CsfFile.ts +++ b/code/core/src/csf-tools/CsfFile.ts @@ -9,12 +9,18 @@ import bt from '@babel/traverse'; import * as recast from 'recast'; import { toId, isExportStory, storyNameFromExport } from '@storybook/csf'; -import type { ComponentAnnotations, StoryAnnotations, Tag } from '@storybook/core/types'; +import type { + Tag, + StoryAnnotations, + ComponentAnnotations, + IndexedCSFFile, + IndexInput, + IndexInputStats, +} from '@storybook/core/types'; import type { Options } from 'recast'; import { babelParse } from './babelParse'; import { findVarInitialization } from './findVarInitialization'; import type { PrintResultType } from './PrintResultType'; -import type { IndexInput, IndexedCSFFile } from '@storybook/core/types'; // @ts-expect-error (needed due to it's use of `exports.default`) const traverse = (bt.default || bt) as typeof bt; @@ -54,6 +60,8 @@ const formatLocation = (node: t.Node, fileName?: string) => { return `${fileName || ''} (line ${line}, col ${column})`.trim(); }; +export const isModuleMock = (importPath: string) => MODULE_MOCK_REGEX.test(importPath); + const isArgsStory = (init: t.Node, parent: t.Node, csf: CsfFile) => { let storyFn: t.Node = init; // export const Foo = Bar.bind({}) @@ -110,6 +118,25 @@ const sortExports = (exportByName: Record, order: string[]) => { ); }; +const hasMount = (play: t.Node | undefined) => { + if (t.isArrowFunctionExpression(play) || t.isFunctionDeclaration(play)) { + const params = play.params; + if (params.length >= 1) { + const [arg] = params; + if (t.isObjectPattern(arg)) { + return !!arg.properties.find((prop) => { + if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) { + return prop.key.name === 'mount'; + } + }); + } + } + } + return false; +}; + +const MODULE_MOCK_REGEX = /^[.\/#].*\.mock($|\.[^.]*$)/i; + export interface CsfOptions { fileName?: string; makeTitle: (userTitle: string) => string; @@ -136,6 +163,7 @@ export interface StaticMeta export interface StaticStory extends Pick { id: string; + __stats: IndexInputStats; } export class CsfFile { @@ -392,6 +420,7 @@ export class CsfFile { id: 'FIXME', name, parameters, + __stats: {}, }; } }); @@ -422,7 +451,12 @@ export class CsfFile { } } else { self._storyAnnotations[exportName] = {}; - self._stories[exportName] = { id: 'FIXME', name: exportName, parameters: {} }; + self._stories[exportName] = { + id: 'FIXME', + name: exportName, + parameters: {}, + __stats: {}, + }; } } }); @@ -520,7 +554,8 @@ export class CsfFile { parameters.docsOnly = true; } acc[key] = { ...story, id, parameters }; - const { tags, play } = self._storyAnnotations[key]; + const storyAnnotations = self._storyAnnotations[key]; + const { tags, play } = storyAnnotations; if (tags) { const node = t.isIdentifier(tags) ? findVarInitialization(tags.name, this._ast.program) @@ -530,6 +565,18 @@ export class CsfFile { if (play) { acc[key].tags = [...(acc[key].tags || []), 'play-fn']; } + const stats = acc[key].__stats; + ['play', 'render', 'loaders', 'beforeEach'].forEach((annotation) => { + stats[annotation as keyof IndexInputStats] = + !!storyAnnotations[annotation] || !!self._metaAnnotations[annotation]; + }); + const storyExport = self.getStoryExport(key); + stats.storyFn = !!( + t.isArrowFunctionExpression(storyExport) || t.isFunctionDeclaration(storyExport) + ); + stats.mount = hasMount(storyAnnotations.play ?? self._metaAnnotations.play); + stats.moduleMock = !!self.imports.find((fname) => isModuleMock(fname)); + return acc; }, {} as Record @@ -589,6 +636,7 @@ export class CsfFile { metaId: this.meta?.id, tags, __id: story.id, + __stats: story.__stats, }; }); } diff --git a/code/core/src/manager-api/version.ts b/code/core/src/manager-api/version.ts index 2010c80e09ee..1b9549d41f0e 100644 --- a/code/core/src/manager-api/version.ts +++ b/code/core/src/manager-api/version.ts @@ -1 +1 @@ -export const version = '8.3.0-alpha.0'; +export const version = '8.3.0-alpha.2'; diff --git a/code/core/src/manager/components/layout/useDragging.ts b/code/core/src/manager/components/layout/useDragging.ts index 4711354153b3..1c00f516c234 100644 --- a/code/core/src/manager/components/layout/useDragging.ts +++ b/code/core/src/manager/components/layout/useDragging.ts @@ -37,7 +37,7 @@ export function useDragging({ useEffect(() => { const panelResizer = panelResizerRef.current; const sidebarResizer = sidebarResizerRef.current; - const previewIframe = document.querySelector('#storybook-preview-iframe') as HTMLIFrameElement; + const previewIframe = document.querySelector('#storybook-preview-wrapper') as HTMLIFrameElement; let draggedElement: typeof panelResizer | typeof sidebarResizer | null = null; const onDragStart = (e: MouseEvent) => { diff --git a/code/core/src/preview-errors.ts b/code/core/src/preview-errors.ts index 31341bb6132c..c1d070f7c10a 100644 --- a/code/core/src/preview-errors.ts +++ b/code/core/src/preview-errors.ts @@ -214,6 +214,7 @@ export class MountMustBeDestructuredError extends StorybookError { category: Category.PREVIEW_API, code: 12, message: dedent` + Incorrect use of mount in the play function. To use mount in the play function, you must satisfy the following two requirements: diff --git a/code/core/src/types/modules/indexer.ts b/code/core/src/types/modules/indexer.ts index ceb3bf915e51..4e92b647a489 100644 --- a/code/core/src/types/modules/indexer.ts +++ b/code/core/src/types/modules/indexer.ts @@ -87,6 +87,16 @@ export type DocsIndexEntry = BaseIndexEntry & { export type IndexEntry = StoryIndexEntry | DocsIndexEntry; +export interface IndexInputStats { + loaders?: boolean; + play?: boolean; + render?: boolean; + storyFn?: boolean; + mount?: boolean; + beforeEach?: boolean; + moduleMock?: boolean; +} + /** * The base input for indexing a story or docs entry. */ @@ -115,6 +125,10 @@ export type BaseIndexInput = { * Only use this if you need to override the auto-generated id. */ __id?: StoryId; + /** + * Stats about language feature usage that the indexer can optionally report + */ + __stats?: IndexInputStats; }; /** diff --git a/code/core/src/types/modules/story.ts b/code/core/src/types/modules/story.ts index 69d10027bbe9..afe3edf6c6b0 100644 --- a/code/core/src/types/modules/story.ts +++ b/code/core/src/types/modules/story.ts @@ -6,6 +6,7 @@ import type { CleanupCallback, StepRunner, Canvas, + BeforeAll, } from '@storybook/csf'; import type { @@ -57,13 +58,14 @@ export type NamedOrDefaultProjectAnnotations = Omit< ProjectAnnotations, - 'decorators' | 'loaders' | 'runStep' + 'decorators' | 'loaders' | 'runStep' | 'beforeAll' > & { argTypes?: StrictArgTypes; globalTypes?: StrictGlobalTypes; decorators?: DecoratorFunction[]; loaders?: LoaderFunction[]; runStep: StepRunner; + beforeAll: BeforeAll; }; export type NormalizedComponentAnnotations = Omit< diff --git a/code/deprecated/builder-manager/package.json b/code/deprecated/builder-manager/package.json index c23a94632c3d..c9397d3d1d82 100644 --- a/code/deprecated/builder-manager/package.json +++ b/code/deprecated/builder-manager/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/builder-manager", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook manager builder", "keywords": [ "storybook" diff --git a/code/deprecated/channels/package.json b/code/deprecated/channels/package.json index 5e355be150c0..c48b9f977958 100644 --- a/code/deprecated/channels/package.json +++ b/code/deprecated/channels/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/channels", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "", "keywords": [ "storybook" diff --git a/code/deprecated/client-logger/package.json b/code/deprecated/client-logger/package.json index 3ee33658fc74..f2e398ce9913 100644 --- a/code/deprecated/client-logger/package.json +++ b/code/deprecated/client-logger/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/client-logger", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "", "keywords": [ "storybook" diff --git a/code/deprecated/components/package.json b/code/deprecated/components/package.json index b072d5bd9955..8b6606409990 100644 --- a/code/deprecated/components/package.json +++ b/code/deprecated/components/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/components", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Core Storybook Components", "keywords": [ "storybook" diff --git a/code/deprecated/core-common/package.json b/code/deprecated/core-common/package.json index 5da58e0d0c0d..eae9ea7095a0 100644 --- a/code/deprecated/core-common/package.json +++ b/code/deprecated/core-common/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-common", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/deprecated/core-events/package.json b/code/deprecated/core-events/package.json index b99a130b55d5..3449105670ae 100644 --- a/code/deprecated/core-events/package.json +++ b/code/deprecated/core-events/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-events", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Event names used in storybook core", "keywords": [ "storybook" diff --git a/code/deprecated/core-server/package.json b/code/deprecated/core-server/package.json index 5837d5034869..10c97e82cdd0 100644 --- a/code/deprecated/core-server/package.json +++ b/code/deprecated/core-server/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-server", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/deprecated/csf-tools/package.json b/code/deprecated/csf-tools/package.json index 29bfaee4b142..e0c6e3dc6564 100644 --- a/code/deprecated/csf-tools/package.json +++ b/code/deprecated/csf-tools/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/csf-tools", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Parse and manipulate CSF and Storybook config files", "keywords": [ "storybook" diff --git a/code/deprecated/docs-tools/package.json b/code/deprecated/docs-tools/package.json index 289105b22848..372d0166e4ac 100644 --- a/code/deprecated/docs-tools/package.json +++ b/code/deprecated/docs-tools/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/docs-tools", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Shared utility functions for frameworks to implement docs", "keywords": [ "storybook" diff --git a/code/deprecated/manager-api/package.json b/code/deprecated/manager-api/package.json index 028caf13d0b6..a443513b9d3b 100644 --- a/code/deprecated/manager-api/package.json +++ b/code/deprecated/manager-api/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/manager-api", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Core Storybook Manager API & Context", "keywords": [ "storybook" diff --git a/code/deprecated/manager/globals.cjs b/code/deprecated/manager/globals.cjs new file mode 100644 index 000000000000..d6ee8ec2d144 --- /dev/null +++ b/code/deprecated/manager/globals.cjs @@ -0,0 +1 @@ +module.exports = require('storybook/internal/manager/globals'); diff --git a/code/deprecated/manager/globals.d.ts b/code/deprecated/manager/globals.d.ts new file mode 100644 index 000000000000..a2b581c8ca04 --- /dev/null +++ b/code/deprecated/manager/globals.d.ts @@ -0,0 +1,2 @@ +export * from 'storybook/internal/manager/globals'; +export type * from 'storybook/internal/manager/globals'; diff --git a/code/deprecated/manager/globals.js b/code/deprecated/manager/globals.js new file mode 100644 index 000000000000..0dab1b6906f8 --- /dev/null +++ b/code/deprecated/manager/globals.js @@ -0,0 +1 @@ +export * from 'storybook/internal/manager/globals'; diff --git a/code/deprecated/manager/package.json b/code/deprecated/manager/package.json index a52d06df9842..779cd2f09ba3 100644 --- a/code/deprecated/manager/package.json +++ b/code/deprecated/manager/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/manager", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Core Storybook UI", "keywords": [ "storybook" @@ -20,6 +20,14 @@ }, "license": "MIT", "sideEffects": false, + "type": "module", + "exports": { + "./globals": { + "type": "./globals.d.ts", + "import": "./globals.js", + "require": "./globals.cjs" + } + }, "files": [ "README.md", "*.js", diff --git a/code/deprecated/node-logger/package.json b/code/deprecated/node-logger/package.json index 1daca1180932..5b46f14f9236 100644 --- a/code/deprecated/node-logger/package.json +++ b/code/deprecated/node-logger/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/node-logger", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "", "keywords": [ "storybook" diff --git a/code/deprecated/preview-api/package.json b/code/deprecated/preview-api/package.json index f2744ff9215d..1a7e653b56d6 100644 --- a/code/deprecated/preview-api/package.json +++ b/code/deprecated/preview-api/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preview-api", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "", "keywords": [ "storybook" diff --git a/code/deprecated/preview/globals.cjs b/code/deprecated/preview/globals.cjs new file mode 100644 index 000000000000..91340ce6505b --- /dev/null +++ b/code/deprecated/preview/globals.cjs @@ -0,0 +1 @@ +module.exports = require('storybook/internal/preview/globals'); diff --git a/code/deprecated/preview/globals.d.ts b/code/deprecated/preview/globals.d.ts new file mode 100644 index 000000000000..165a3a44a8fb --- /dev/null +++ b/code/deprecated/preview/globals.d.ts @@ -0,0 +1,2 @@ +export * from 'storybook/internal/preview/globals'; +export type * from 'storybook/internal/preview/globals'; diff --git a/code/deprecated/preview/globals.js b/code/deprecated/preview/globals.js new file mode 100644 index 000000000000..c04bc1063044 --- /dev/null +++ b/code/deprecated/preview/globals.js @@ -0,0 +1 @@ +export * from 'storybook/internal/preview/globals'; diff --git a/code/deprecated/preview/package.json b/code/deprecated/preview/package.json index b19e7fd1a362..c634a85c29b6 100644 --- a/code/deprecated/preview/package.json +++ b/code/deprecated/preview/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preview", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "", "keywords": [ "storybook" @@ -20,6 +20,14 @@ }, "license": "MIT", "sideEffects": false, + "type": "module", + "exports": { + "./globals": { + "type": "./globals.d.ts", + "import": "./globals.js", + "require": "./globals.cjs" + } + }, "files": [ "README.md", "*.js", diff --git a/code/deprecated/router/package.json b/code/deprecated/router/package.json index c5569f52f46e..8e6620bd87c7 100644 --- a/code/deprecated/router/package.json +++ b/code/deprecated/router/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/router", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Core Storybook Router", "keywords": [ "storybook" diff --git a/code/deprecated/telemetry/package.json b/code/deprecated/telemetry/package.json index b8552ca62b66..dc445122bd1a 100644 --- a/code/deprecated/telemetry/package.json +++ b/code/deprecated/telemetry/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/telemetry", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Telemetry logging for crash reports and usage statistics", "keywords": [ "storybook" diff --git a/code/deprecated/theming/package.json b/code/deprecated/theming/package.json index 3d79a749fb7e..046d19cf0157 100644 --- a/code/deprecated/theming/package.json +++ b/code/deprecated/theming/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/theming", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Core Storybook Components", "keywords": [ "storybook" diff --git a/code/deprecated/types/package.json b/code/deprecated/types/package.json index 52b9096ee28b..1d5ade53e9fc 100644 --- a/code/deprecated/types/package.json +++ b/code/deprecated/types/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/types", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Core Storybook TS Types", "keywords": [ "storybook" diff --git a/code/frameworks/angular/package.json b/code/frameworks/angular/package.json index a16fc8150a80..646235ae7f3f 100644 --- a/code/frameworks/angular/package.json +++ b/code/frameworks/angular/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/angular", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for Angular: Develop Angular components in isolation with hot reloading.", "keywords": [ "storybook", diff --git a/code/frameworks/angular/src/client/angular-beta/ComputesTemplateFromComponent.test.ts b/code/frameworks/angular/src/client/angular-beta/ComputesTemplateFromComponent.test.ts index fca3ee9e37b4..cc12902b5c05 100644 --- a/code/frameworks/angular/src/client/angular-beta/ComputesTemplateFromComponent.test.ts +++ b/code/frameworks/angular/src/client/angular-beta/ComputesTemplateFromComponent.test.ts @@ -1,11 +1,314 @@ import { Component } from '@angular/core'; import { ArgTypes } from 'storybook/internal/types'; import { describe, it, expect } from 'vitest'; -import { computesTemplateSourceFromComponent } from './ComputesTemplateFromComponent'; +import { + computesTemplateFromComponent, + computesTemplateSourceFromComponent, +} from './ComputesTemplateFromComponent'; import { ISomeInterface, ButtonAccent, InputComponent } from './__testfixtures__/input.component'; +describe('angular template decorator', () => { + it('with props should generate tag with properties', () => { + const component = InputComponent; + const props = { + isDisabled: true, + label: 'Hello world', + accent: ButtonAccent.High, + counter: 4, + 'aria-label': 'Hello world', + }; + const source = computesTemplateFromComponent(component, props); + expect(source).toEqual( + `` + ); + }); + + it('with props should generate tag with outputs', () => { + const component = InputComponent; + const props = { + isDisabled: true, + label: 'Hello world', + onClick: ($event: any) => {}, + 'dash-out': ($event: any) => {}, + }; + const source = computesTemplateFromComponent(component, props); + expect(source).toEqual( + `` + ); + }); + + it('with no props should generate simple tag', () => { + const component = InputComponent; + const props = {}; + const source = computesTemplateFromComponent(component, props); + expect(source).toEqual(''); + }); + + describe('with component without selector', () => { + @Component({ + template: `The content`, + }) + class WithoutSelectorComponent {} + + it('should add component ng-container', async () => { + const component = WithoutSelectorComponent; + const props = {}; + const source = computesTemplateFromComponent(component, props); + expect(source).toEqual(``); + }); + }); + + describe('with component with attribute selector', () => { + @Component({ + selector: 'doc-button[foo]', + template: '', + }) + class WithAttributeComponent {} + + it('should add attribute to template', async () => { + const component = WithAttributeComponent; + const props = {}; + const source = computesTemplateFromComponent(component, props); + expect(source).toEqual(``); + }); + }); + + describe('with component with attribute and value selector', () => { + @Component({ + selector: 'doc-button[foo="bar"]', + template: '', + }) + class WithAttributeValueComponent {} + + it('should add attribute to template', async () => { + const component = WithAttributeValueComponent; + const props = {}; + const source = computesTemplateFromComponent(component, props); + expect(source).toEqual(``); + }); + }); + + describe('with component with attribute only selector', () => { + @Component({ + selector: '[foo]', + template: '', + }) + class WithAttributeOnlyComponent {} + + it('should create a div and add attribute to template', async () => { + const component = WithAttributeOnlyComponent; + const props = {}; + const source = computesTemplateFromComponent(component, props); + expect(source).toEqual(`
`); + }); + }); + + describe('with component with void element and attribute selector', () => { + @Component({ + selector: 'input[foo]', + template: '', + }) + class VoidElementWithAttributeComponent {} + + it('should create without separate closing tag', async () => { + const component = VoidElementWithAttributeComponent; + const props = {}; + const source = computesTemplateFromComponent(component, props); + expect(source).toEqual(``); + }); + }); + + describe('with component with attribute and value only selector', () => { + @Component({ + selector: '[foo="bar"]', + template: '', + }) + class WithAttributeOnlyComponent {} + + it('should create a div and add attribute to template', async () => { + const component = WithAttributeOnlyComponent; + const props = {}; + const source = computesTemplateFromComponent(component, props); + expect(source).toEqual(`
`); + }); + }); + + describe('with component with void element, attribute and value only selector', () => { + @Component({ + selector: 'input[foo="bar"]', + template: '', + }) + class VoidElementWithAttributeComponent {} + + it('should create and add attribute to template without separate closing tag', async () => { + const component = VoidElementWithAttributeComponent; + const props = {}; + const source = computesTemplateFromComponent(component, props); + expect(source).toEqual(``); + }); + }); + + describe('with component with class selector', () => { + @Component({ + selector: 'doc-button.foo', + template: '', + }) + class WithClassComponent {} + + it('should add class to template', async () => { + const component = WithClassComponent; + const props = {}; + const source = computesTemplateFromComponent(component, props); + expect(source).toEqual(``); + }); + }); + + describe('with component with class only selector', () => { + @Component({ + selector: '.foo', + template: '', + }) + class WithClassComponent {} + + it('should create a div and add attribute to template', async () => { + const component = WithClassComponent; + const props = {}; + const source = computesTemplateFromComponent(component, props); + expect(source).toEqual(`
`); + }); + }); + + describe('with component with multiple selectors', () => { + @Component({ + selector: 'doc-button, doc-button2', + template: '', + }) + class WithMultipleSelectorsComponent {} + + it('should use the first selector', async () => { + const component = WithMultipleSelectorsComponent; + const props = {}; + const source = computesTemplateFromComponent(component, props); + expect(source).toEqual(``); + }); + }); + + describe('with component with multiple selectors starting with attribute', () => { + @Component({ + selector: 'doc-button[foo], doc-button2', + template: '', + }) + class WithMultipleSelectorsComponent {} + + it('should use the first selector', async () => { + const component = WithMultipleSelectorsComponent; + const props = {}; + const source = computesTemplateFromComponent(component, props); + expect(source).toEqual(``); + }); + }); + + describe('with component with multiple selectors starting with attribute and value', () => { + @Component({ + selector: 'doc-button[foo="bar"], doc-button2', + template: '', + }) + class WithMultipleSelectorsComponent {} + + it('should use the first selector', async () => { + const component = WithMultipleSelectorsComponent; + const props = {}; + const source = computesTemplateFromComponent(component, props); + expect(source).toEqual(``); + }); + }); + + describe('with component with multiple selectors including 2 attributes and a class', () => { + @Component({ + selector: 'doc-button, button[foo], .button[foo], button[baz]', + template: '', + }) + class WithMultipleSelectorsComponent {} + + it('should use the first selector', async () => { + const component = WithMultipleSelectorsComponent; + const props = {}; + const source = computesTemplateFromComponent(component, props); + expect(source).toEqual(``); + }); + }); + + describe('with component with multiple selectors with line breaks', () => { + @Component({ + selector: `doc-button, + doc-button2`, + template: '', + }) + class WithMultipleSelectorsComponent {} + + it('should use the first selector', async () => { + const component = WithMultipleSelectorsComponent; + const props = {}; + const source = computesTemplateFromComponent(component, props); + expect(source).toEqual(``); + }); + }); + + describe('with component with multiple selectors starting with attribute only with line breaks', () => { + @Component({ + selector: `[foo], + doc-button2`, + template: '', + }) + class WithMultipleSelectorsComponent {} + + it('should use the first selector', async () => { + const component = WithMultipleSelectorsComponent; + const props = {}; + const source = computesTemplateFromComponent(component, props); + expect(source).toEqual(`
`); + }); + }); + + it('with props should generate tag with properties', () => { + const component = InputComponent; + const props = { + isDisabled: true, + label: 'Hello world', + accent: ButtonAccent.High, + counter: 4, + }; + const source = computesTemplateFromComponent(component, props); + expect(source).toEqual( + `` + ); + }); + + it('with props should generate tag with outputs', () => { + const component = InputComponent; + const props = { + isDisabled: true, + label: 'Hello world', + onClick: ($event: any) => {}, + }; + const source = computesTemplateFromComponent(component, props); + expect(source).toEqual( + `` + ); + }); + + it('should generate correct property for overridden name for Input', () => { + const component = InputComponent; + const props = { + color: '#ffffff', + }; + const source = computesTemplateFromComponent(component, props); + expect(source).toEqual(``); + }); +}); + describe('angular source decorator', () => { - it('With no props should generate simple tag', () => { + it('with no props should generate simple tag', () => { const component = InputComponent; const props = {}; const argTypes: ArgTypes = {}; @@ -264,32 +567,34 @@ describe('angular source decorator', () => { const source = computesTemplateSourceFromComponent(component, props, argTypes); expect(source).toEqual(``); }); - it('With props should generate tag with properties', () => { + it('with props should generate tag with properties', () => { const component = InputComponent; const props = { isDisabled: true, label: 'Hello world', accent: ButtonAccent.High, counter: 4, + 'aria-label': 'Hello world', }; const argTypes: ArgTypes = {}; const source = computesTemplateSourceFromComponent(component, props, argTypes); expect(source).toEqual( - `` + `` ); }); - it('With props should generate tag with outputs', () => { + it('with props should generate tag with outputs', () => { const component = InputComponent; const props = { isDisabled: true, label: 'Hello world', onClick: ($event: any) => {}, + 'dash-out': ($event: any) => {}, }; const argTypes: ArgTypes = {}; const source = computesTemplateSourceFromComponent(component, props, argTypes); expect(source).toEqual( - `` + `` ); }); @@ -305,7 +610,7 @@ describe('angular source decorator', () => { }); describe('with argTypes (from compodoc)', () => { - it('Should handle enum as strongly typed enum', () => { + it('should handle enum as strongly typed enum', () => { const component = InputComponent; const props = { isDisabled: false, @@ -335,7 +640,7 @@ describe('angular source decorator', () => { ); }); - it('Should handle enum without values as string', () => { + it('should handle enum without values as string', () => { const component = InputComponent; const props = { isDisabled: false, @@ -365,7 +670,7 @@ describe('angular source decorator', () => { ); }); - it('Should handle objects correctly', () => { + it('should handle simple object as stringified', () => { const component = InputComponent; const someDataObject: ISomeInterface = { @@ -400,5 +705,42 @@ describe('angular source decorator', () => { `` ); }); + + it('should handle circular object as stringified', () => { + const component = InputComponent; + + const someDataObject: ISomeInterface = { + one: 'Hello world', + two: true, + three: [ + `a string literal with "double quotes"`, + `a string literal with 'single quotes'`, + 'a single quoted string with "double quotes"', + "a double quoted string with 'single quotes'", + // eslint-disable-next-line prettier/prettier + 'a single quoted string with escaped \'single quotes\'', + // eslint-disable-next-line prettier/prettier + "a double quoted string with escaped \"double quotes\"", + + `a string literal with \'escaped single quotes\'`, + + `a string literal with \"escaped double quotes\"`, + ], + }; + someDataObject.ref = someDataObject; + + const props = { + isDisabled: false, + label: 'Hello world', + someDataObject, + }; + + const source = computesTemplateSourceFromComponent(component, props, null); + // Ideally we should stringify the object, but that could cause the story to break because of unescaped values in the JSON object. + // This will have to do for now + expect(source).toEqual( + `` + ); + }); }); }); diff --git a/code/frameworks/angular/src/client/angular-beta/ComputesTemplateFromComponent.ts b/code/frameworks/angular/src/client/angular-beta/ComputesTemplateFromComponent.ts index 7c585b8ff489..9e0d38f17986 100644 --- a/code/frameworks/angular/src/client/angular-beta/ComputesTemplateFromComponent.ts +++ b/code/frameworks/angular/src/client/angular-beta/ComputesTemplateFromComponent.ts @@ -7,6 +7,20 @@ import { getComponentInputsOutputs, } from './utils/NgComponentAnalyzer'; +/** + * Check if the name matches the criteria for a valid identifier. + * A valid identifier can only contain letters, digits, underscores, or dollar signs. + * It cannot start with a digit. + */ +const isValidIdentifier = (name: string): boolean => /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name); + +/** + * Returns the property name, if it can be accessed with dot notation. If not, + * it returns `this['propertyName']`. + */ +export const formatPropInTemplate = (propertyName: string) => + isValidIdentifier(propertyName) ? propertyName : `this['${propertyName}']`; + const separateInputsOutputsAttributes = ( ngComponentInputsOutputs: ComponentInputsOutputs, props: ICollection = {} @@ -50,10 +64,12 @@ export const computesTemplateFromComponent = ( ); const templateInputs = - initialInputs.length > 0 ? ` ${initialInputs.map((i) => `[${i}]="${i}"`).join(' ')}` : ''; + initialInputs.length > 0 + ? ` ${initialInputs.map((i) => `[${i}]="${formatPropInTemplate(i)}"`).join(' ')}` + : ''; const templateOutputs = initialOutputs.length > 0 - ? ` ${initialOutputs.map((i) => `(${i})="${i}($event)"`).join(' ')}` + ? ` ${initialOutputs.map((i) => `(${i})="${formatPropInTemplate(i)}($event)"`).join(' ')}` : ''; return buildTemplate( @@ -64,6 +80,22 @@ export const computesTemplateFromComponent = ( ); }; +/** + * Stringify an object with a placholder in the circular references. + */ +function stringifyCircular(obj: any) { + const seen = new Set(); + return JSON.stringify(obj, (key, value) => { + if (typeof value === 'object' && value !== null) { + if (seen.has(value)) { + return '[Circular]'; + } + seen.add(value); + } + return value; + }); +} + const createAngularInputProperty = ({ propertyName, value, @@ -79,7 +111,7 @@ const createAngularInputProperty = ({ templateValue = `'${value}'`; break; case 'object': - templateValue = JSON.stringify(value) + templateValue = stringifyCircular(value) .replace(/'/g, '\u2019') .replace(/\\"/g, '\u201D') .replace(/"([^-"]+)":/g, '$1: ') @@ -137,7 +169,7 @@ export const computesTemplateSourceFromComponent = ( : ''; const templateOutputs = initialOutputs.length > 0 - ? ` ${initialOutputs.map((i) => `(${i})="${i}($event)"`).join(' ')}` + ? ` ${initialOutputs.map((i) => `(${i})="${formatPropInTemplate(i)}($event)"`).join(' ')}` : ''; return buildTemplate(ngComponentMetadata.selector, '', templateInputs, templateOutputs); diff --git a/code/frameworks/angular/src/client/angular-beta/__testfixtures__/input.component.ts b/code/frameworks/angular/src/client/angular-beta/__testfixtures__/input.component.ts index abf4205eeaf5..b0ae93c94b99 100644 --- a/code/frameworks/angular/src/client/angular-beta/__testfixtures__/input.component.ts +++ b/code/frameworks/angular/src/client/angular-beta/__testfixtures__/input.component.ts @@ -11,6 +11,7 @@ export interface ISomeInterface { one: string; two: boolean; three: any[]; + ref?: ISomeInterface; } @Component({ @@ -39,9 +40,13 @@ export class InputComponent { @Input() public label: string; + @Input('aria-label') public ariaLabel: string; + /** Specifies some arbitrary object */ @Input() public someDataObject: ISomeInterface; @Output() public onClick = new EventEmitter(); + + @Output('dash-out') public dashOut = new EventEmitter(); } diff --git a/code/frameworks/angular/src/client/argsToTemplate.test.ts b/code/frameworks/angular/src/client/argsToTemplate.test.ts index b7405aba645a..29a51acb1b9d 100644 --- a/code/frameworks/angular/src/client/argsToTemplate.test.ts +++ b/code/frameworks/angular/src/client/argsToTemplate.test.ts @@ -100,4 +100,10 @@ describe('argsToTemplate', () => { const result = argsToTemplate(args, {}); expect(result).toEqual('[input]="input" (event1)="event1($event)"'); }); + + it('should format for non dot notation', () => { + const args = { 'non-dot': 'Value1', 'dash-out': () => {} }; + const result = argsToTemplate(args, {}); + expect(result).toEqual('[non-dot]="this[\'non-dot\']" (dash-out)="this[\'dash-out\']($event)"'); + }); }); diff --git a/code/frameworks/angular/src/client/argsToTemplate.ts b/code/frameworks/angular/src/client/argsToTemplate.ts index 0072aa84743d..5b29b627029f 100644 --- a/code/frameworks/angular/src/client/argsToTemplate.ts +++ b/code/frameworks/angular/src/client/argsToTemplate.ts @@ -1,3 +1,5 @@ +import { formatPropInTemplate } from './angular-beta/ComputesTemplateFromComponent'; + /** * Options for controlling the behavior of the argsToTemplate function. * @@ -68,7 +70,9 @@ export function argsToTemplate>( return true; }) .map(([key, value]) => - typeof value === 'function' ? `(${key})="${key}($event)"` : `[${key}]="${key}"` + typeof value === 'function' + ? `(${key})="${formatPropInTemplate(key)}($event)"` + : `[${key}]="${formatPropInTemplate(key)}"` ) .join(' '); } diff --git a/code/frameworks/ember/package.json b/code/frameworks/ember/package.json index dde834c496d5..9f7431d3c6f8 100644 --- a/code/frameworks/ember/package.json +++ b/code/frameworks/ember/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/ember", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for Ember: Develop Ember Component in isolation with Hot Reloading.", "homepage": "https://github.com/storybookjs/storybook/tree/next/code/frameworks/ember", "bugs": { diff --git a/code/frameworks/html-vite/package.json b/code/frameworks/html-vite/package.json index bbfe01fb992e..1dd2d044dc68 100644 --- a/code/frameworks/html-vite/package.json +++ b/code/frameworks/html-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/html-vite", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for HTML and Vite: Develop HTML in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/html-webpack5/package.json b/code/frameworks/html-webpack5/package.json index 19433e8b8f07..3aa2520dae63 100644 --- a/code/frameworks/html-webpack5/package.json +++ b/code/frameworks/html-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/html-webpack5", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for HTML: View HTML snippets in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/nextjs/package.json b/code/frameworks/nextjs/package.json index 0818278761e1..b4dcee345a34 100644 --- a/code/frameworks/nextjs/package.json +++ b/code/frameworks/nextjs/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/nextjs", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for Next.js", "keywords": [ "storybook", @@ -153,7 +153,7 @@ "loader-utils": "^3.2.1", "node-polyfill-webpack-plugin": "^2.0.1", "pnp-webpack-plugin": "^1.7.0", - "postcss": "^8.4.38", + "postcss": "^8.4.40", "postcss-loader": "^8.1.1", "react-refresh": "^0.14.0", "resolve-url-loader": "^5.0.0", @@ -172,9 +172,9 @@ "@types/babel__preset-env": "^7", "@types/loader-utils": "^2.0.5", "@types/react-refresh": "^0", - "next": "^14.1.0", + "next": "^14.1.1", "typescript": "^5.3.2", - "webpack": "^5.65.0" + "webpack": "^5.93.0" }, "peerDependencies": { "next": "^13.5.0 || ^14.0.0", diff --git a/code/frameworks/nextjs/template/stories_nextjs-default-ts/ServerActions.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-default-ts/ServerActions.stories.tsx index cb3f5bbdb2dd..21a911a08ac1 100644 --- a/code/frameworks/nextjs/template/stories_nextjs-default-ts/ServerActions.stories.tsx +++ b/code/frameworks/nextjs/template/stories_nextjs-default-ts/ServerActions.stories.tsx @@ -31,6 +31,7 @@ function Component() { export default { component: Component, + tags: ['test-skip'], parameters: { nextjs: { appDirectory: true, diff --git a/code/frameworks/preact-vite/package.json b/code/frameworks/preact-vite/package.json index d7344558a421..65cc6877d9d7 100644 --- a/code/frameworks/preact-vite/package.json +++ b/code/frameworks/preact-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact-vite", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for Preact and Vite: Develop Preact components in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -53,7 +53,7 @@ "devDependencies": { "@types/node": "^18.0.0", "typescript": "^5.3.2", - "vite": "^4.0.0" + "vite": "^5.0.13" }, "peerDependencies": { "preact": ">=10", diff --git a/code/frameworks/preact-webpack5/package.json b/code/frameworks/preact-webpack5/package.json index 413179dc6fd1..d2f127c025e5 100644 --- a/code/frameworks/preact-webpack5/package.json +++ b/code/frameworks/preact-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact-webpack5", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for Preact: Develop Preact Component in isolation.", "keywords": [ "storybook" diff --git a/code/frameworks/react-vite/package.json b/code/frameworks/react-vite/package.json index 320b99cb3005..9f04168fcf86 100644 --- a/code/frameworks/react-vite/package.json +++ b/code/frameworks/react-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-vite", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for React and Vite: Develop React components in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -60,7 +60,7 @@ "devDependencies": { "@types/node": "^18.0.0", "typescript": "^5.3.2", - "vite": "^4.0.0" + "vite": "^5.0.13" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", diff --git a/code/frameworks/react-webpack5/package.json b/code/frameworks/react-webpack5/package.json index 9be13bf40f80..c7dc0cb0a66e 100644 --- a/code/frameworks/react-webpack5/package.json +++ b/code/frameworks/react-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-webpack5", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for React: Develop React Component in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/server-webpack5/package.json b/code/frameworks/server-webpack5/package.json index 20c7176ad11c..c1ba5f6496ae 100644 --- a/code/frameworks/server-webpack5/package.json +++ b/code/frameworks/server-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/server-webpack5", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for Server: View HTML snippets from a server in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/svelte-vite/package.json b/code/frameworks/svelte-vite/package.json index 276a2c3a6404..a6e35d726de5 100644 --- a/code/frameworks/svelte-vite/package.json +++ b/code/frameworks/svelte-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/svelte-vite", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for Svelte and Vite: Develop Svelte components in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -60,7 +60,7 @@ "@sveltejs/vite-plugin-svelte": "^3.0.1", "@types/node": "^18.0.0", "svelte": "^5.0.0-next.65", - "vite": "^4.0.0" + "vite": "^5.0.13" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^2.0.0 || ^3.0.0", diff --git a/code/frameworks/svelte-vite/src/plugins/generateDocgen.ts b/code/frameworks/svelte-vite/src/plugins/generateDocgen.ts index a27584586176..35d828a58d6b 100644 --- a/code/frameworks/svelte-vite/src/plugins/generateDocgen.ts +++ b/code/frameworks/svelte-vite/src/plugins/generateDocgen.ts @@ -278,10 +278,11 @@ export function generateDocgen(targetFileName: string, sourceFileCache: SourceFi return sourceFileCache.hashToSourceFiles[digest]; } + const isTsFile = /]*?lang=('|")(ts|typescript)('|")/.test(content); + const tsx = svelte2tsx.svelte2tsx(content, { version: VERSION, - isTsFile: true, - emitOnTemplateError: true, + isTsFile: isTsFile, mode: 'dts', }); @@ -290,7 +291,7 @@ export function generateDocgen(targetFileName: string, sourceFileCache: SourceFi tsx.code, languageVersion, true, - ts.ScriptKind.JS // Set to 'JS' to enable TypeScript to parse JSDoc. + isTsFile ? ts.ScriptKind.TS : ts.ScriptKind.JS // Set to 'JS' to enable TypeScript to parse JSDoc. ); sourceFileCache.hashToSourceFiles[digest] = sourceFile; @@ -363,6 +364,7 @@ export function generateDocgen(targetFileName: string, sourceFileCache: SourceFi if (signature && signature.declaration) { // Get props type from ReturnType const type = checker.getReturnTypeOfSignature(signature); + type.getProperties().forEach((retObjProp) => { if (retObjProp.name === 'props') { const decl = signature.getDeclaration(); @@ -409,13 +411,18 @@ export function generateDocgen(targetFileName: string, sourceFileCache: SourceFi if (ts.isVariableStatement(node)) { node.declarationList.declarations.forEach((declaration) => { // Extract default values from: - // let { = , ... }: = ... - if ( - propsType && - declaration.type && - propsType === checker.getTypeFromTypeNode(declaration.type) && - ts.isObjectBindingPattern(declaration.name) - ) { + // let { = , ... }: = $props(); + + const isPropsRune = + declaration.initializer && + ts.isCallExpression(declaration.initializer) && + ts.isIdentifier(declaration.initializer.expression) && + declaration.initializer.expression.text === '$props'; + + const isPropsType = + declaration.type && propsType === checker.getTypeFromTypeNode(declaration.type); + + if (ts.isObjectBindingPattern(declaration.name) && (isPropsRune || isPropsType)) { propsRuneUsed = true; declaration.name.elements.forEach((element) => { const name = element.name.getText(); @@ -438,6 +445,7 @@ export function generateDocgen(targetFileName: string, sourceFileCache: SourceFi ) { const prop = propMap.get(declaration.name.text); if (prop && declaration.initializer) { + prop.optional = true; const defaultValue = initializerToDefaultValue(declaration.initializer, checker); if (defaultValue) { prop.defaultValue = defaultValue; diff --git a/code/frameworks/svelte-webpack5/package.json b/code/frameworks/svelte-webpack5/package.json index a26b09f0e119..88893b9de002 100644 --- a/code/frameworks/svelte-webpack5/package.json +++ b/code/frameworks/svelte-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/svelte-webpack5", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for Svelte: Develop Svelte Component in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/sveltekit/package.json b/code/frameworks/sveltekit/package.json index 07428f493a0d..70462a88bcf9 100644 --- a/code/frameworks/sveltekit/package.json +++ b/code/frameworks/sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/sveltekit", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for SvelteKit", "keywords": [ "storybook", @@ -61,7 +61,7 @@ "devDependencies": { "@types/node": "^18.0.0", "typescript": "^5.3.2", - "vite": "^4.0.0" + "vite": "^5.0.13" }, "peerDependencies": { "storybook": "workspace:^", diff --git a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/DocsJSDocRunes.svelte b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/DocsJSDocRunes.svelte index f399324da533..f57732f0b5b7 100644 --- a/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/DocsJSDocRunes.svelte +++ b/code/frameworks/sveltekit/template/stories_svelte-kit-prerelease-ts/DocsJSDocRunes.svelte @@ -24,7 +24,7 @@ * @property {Date=} date Date * @property {number | string =} unionTypes Union of types * @property {{ a: number } & { b: string } =} intersection Intersection of types - * @property {import("svelte").Snippet=} children Snippet contents + * @property {import("svelte").Snippet} children Snippet contents * @property {(event: MouseEvent) => number =} func Event callback function */ @@ -52,4 +52,4 @@ } = $props(); -
Docs: JSDoc + Runes (svelte2tsx@0.7.13 does not support this yet.)
+
Docs: JSDoc + Runes
diff --git a/code/frameworks/vue3-vite/package.json b/code/frameworks/vue3-vite/package.json index f9361e7b775b..1670841d4aa0 100644 --- a/code/frameworks/vue3-vite/package.json +++ b/code/frameworks/vue3-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/vue3-vite", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for Vue3 and Vite: Develop Vue3 components in isolation with Hot Reloading.", "keywords": [ "storybook" @@ -59,7 +59,7 @@ "@types/find-package-json": "^1.2.6", "@types/node": "^18.0.0", "typescript": "^5.3.2", - "vite": "^4.0.0" + "vite": "^5.0.13" }, "peerDependencies": { "storybook": "workspace:^", diff --git a/code/frameworks/vue3-vite/src/plugins/vue-component-meta.ts b/code/frameworks/vue3-vite/src/plugins/vue-component-meta.ts index 54ac30cbb9dd..c7218e328fc6 100644 --- a/code/frameworks/vue3-vite/src/plugins/vue-component-meta.ts +++ b/code/frameworks/vue3-vite/src/plugins/vue-component-meta.ts @@ -9,6 +9,7 @@ import { createCheckerByJson, type ComponentMeta, type MetaCheckerOptions, + type PropertyMetaSchema, } from 'vue-component-meta'; import { parseMulti } from 'vue-docgen-api'; @@ -50,6 +51,19 @@ export async function vueComponentMeta(tsconfigPath = 'tsconfig.json'): Promise< const exportName = exportNames[index]; + // we remove nested object schemas here since they are not used inside Storybook (we don't generate controls for object properties) + // and they can cause "out of memory" issues for large/complex schemas (e.g. HTMLElement) + // it also reduced the bundle size when running "storybook build" when such schemas are used + (['props', 'events', 'slots', 'exposed'] as const).forEach((key) => { + meta[key].forEach((value) => { + if (Array.isArray(value.schema)) { + value.schema.forEach((eventSchema) => removeNestedSchemas(eventSchema)); + } else { + removeNestedSchemas(value.schema); + } + }); + }); + const exposed = // the meta also includes duplicated entries in the "exposed" array with "on" // prefix (e.g. onClick instead of click), so we need to filter them out here @@ -250,3 +264,12 @@ async function getTsConfigReferences(tsConfigPath: string) { return []; } } + +/** + * Removes any nested schemas from the given main schema (e.g. from a prop, event, slot or exposed). + * Useful to drastically reduce build size and prevent out of memory issues when large schemas (e.g. HTMLElement, MouseEvent) are used. + */ +function removeNestedSchemas(schema: PropertyMetaSchema) { + if (typeof schema !== 'object') return; + delete schema.schema; +} diff --git a/code/frameworks/vue3-webpack5/package.json b/code/frameworks/vue3-webpack5/package.json index 41e17adba7a3..c0ac55025f03 100644 --- a/code/frameworks/vue3-webpack5/package.json +++ b/code/frameworks/vue3-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/vue3-webpack5", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for Vue 3: Develop Vue 3 Components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/web-components-vite/package.json b/code/frameworks/web-components-vite/package.json index a18fc4d66d45..664176f27d74 100644 --- a/code/frameworks/web-components-vite/package.json +++ b/code/frameworks/web-components-vite/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/web-components-vite", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for web-components and Vite: Develop Web Components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/frameworks/web-components-webpack5/package.json b/code/frameworks/web-components-webpack5/package.json index 7a3d01a09011..01d3521b5727 100644 --- a/code/frameworks/web-components-webpack5/package.json +++ b/code/frameworks/web-components-webpack5/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/web-components-webpack5", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for web-components: View web components snippets in isolation with Hot Reloading.", "keywords": [ "lit", diff --git a/code/lib/blocks/package.json b/code/lib/blocks/package.json index f6a998875bec..0acb8450e13b 100644 --- a/code/lib/blocks/package.json +++ b/code/lib/blocks/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/blocks", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook Doc Blocks", "keywords": [ "storybook" @@ -44,7 +44,7 @@ "prep": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/bundle.ts" }, "dependencies": { - "@storybook/csf": "0.1.11", + "@storybook/csf": "^0.1.11", "@storybook/global": "^5.0.0", "@storybook/icons": "^1.2.5", "@types/lodash": "^4.14.167", diff --git a/code/lib/cli-sb/package.json b/code/lib/cli-sb/package.json index 1f8b0cda1a5f..a602280cbee9 100644 --- a/code/lib/cli-sb/package.json +++ b/code/lib/cli-sb/package.json @@ -1,6 +1,6 @@ { "name": "sb", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook CLI", "keywords": [ "storybook" diff --git a/code/lib/cli-storybook/package.json b/code/lib/cli-storybook/package.json index 4f28285772e4..ad7b210137e5 100644 --- a/code/lib/cli-storybook/package.json +++ b/code/lib/cli-storybook/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/cli", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook CLI", "keywords": [ "storybook" diff --git a/code/lib/cli/core/manager/globals.cjs b/code/lib/cli/core/manager/globals.cjs new file mode 100644 index 000000000000..3dc797bf4cd7 --- /dev/null +++ b/code/lib/cli/core/manager/globals.cjs @@ -0,0 +1 @@ +module.exports = require('@storybook/core/manager/globals'); diff --git a/code/lib/cli/core/manager/globals.d.ts b/code/lib/cli/core/manager/globals.d.ts new file mode 100644 index 000000000000..47746a38ada4 --- /dev/null +++ b/code/lib/cli/core/manager/globals.d.ts @@ -0,0 +1,2 @@ +export * from '@storybook/core/manager/globals'; +export type * from '@storybook/core/manager/globals'; diff --git a/code/lib/cli/core/manager/globals.js b/code/lib/cli/core/manager/globals.js new file mode 100644 index 000000000000..779828900cda --- /dev/null +++ b/code/lib/cli/core/manager/globals.js @@ -0,0 +1 @@ +export * from '@storybook/core/manager/globals'; diff --git a/code/lib/cli/package.json b/code/lib/cli/package.json index 3b7f10bf0838..da7b06aca726 100644 --- a/code/lib/cli/package.json +++ b/code/lib/cli/package.json @@ -1,6 +1,6 @@ { "name": "storybook", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook's CLI - install, dev, build, upgrade, and more", "keywords": [ "cli", @@ -167,6 +167,11 @@ "types": "./core/preview/globals.d.ts", "import": "./core/preview/globals.js", "require": "./core/preview/globals.cjs" + }, + "./internal/manager/globals": { + "types": "./core/manager/globals.d.ts", + "import": "./core/manager/globals.js", + "require": "./core/manager/globals.cjs" } }, "main": "dist/index.cjs", @@ -219,6 +224,9 @@ "internal/manager-errors": [ "./core/manager-errors.d.ts" ], + "internal/manager/globals": [ + "./core/manager/globals.d.ts" + ], "internal/manager/globals-module-info": [ "./core/manager/globals-module-info.d.ts" ], diff --git a/code/lib/codemod/package.json b/code/lib/codemod/package.json index 6e55584c100d..5c14d632cd36 100644 --- a/code/lib/codemod/package.json +++ b/code/lib/codemod/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/codemod", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "A collection of codemod scripts written with JSCodeshift", "keywords": [ "storybook" @@ -58,7 +58,7 @@ "@babel/preset-env": "^7.24.4", "@babel/types": "^7.24.0", "@storybook/core": "workspace:*", - "@storybook/csf": "0.1.11", + "@storybook/csf": "^0.1.11", "@types/cross-spawn": "^6.0.2", "cross-spawn": "^7.0.3", "globby": "^14.0.1", diff --git a/code/lib/core-webpack/package.json b/code/lib/core-webpack/package.json index 1e95304dbf0f..15964d58d5f3 100644 --- a/code/lib/core-webpack/package.json +++ b/code/lib/core-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/core-webpack", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook framework-agnostic API", "keywords": [ "storybook" diff --git a/code/lib/csf-plugin/package.json b/code/lib/csf-plugin/package.json index 447d677386e5..8ed99087ecff 100644 --- a/code/lib/csf-plugin/package.json +++ b/code/lib/csf-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/csf-plugin", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Enrich CSF files via static analysis", "keywords": [ "storybook" diff --git a/code/lib/instrumenter/package.json b/code/lib/instrumenter/package.json index ba29f5151f1c..fc1928dea288 100644 --- a/code/lib/instrumenter/package.json +++ b/code/lib/instrumenter/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/instrumenter", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "", "keywords": [ "storybook" diff --git a/code/lib/react-dom-shim/package.json b/code/lib/react-dom-shim/package.json index 29af1e282b9a..90fe2180d93d 100644 --- a/code/lib/react-dom-shim/package.json +++ b/code/lib/react-dom-shim/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react-dom-shim", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "", "keywords": [ "storybook" diff --git a/code/lib/source-loader/package.json b/code/lib/source-loader/package.json index 3e052e22090b..5c2963555975 100644 --- a/code/lib/source-loader/package.json +++ b/code/lib/source-loader/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/source-loader", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Source loader", "keywords": [ "lib", @@ -45,7 +45,7 @@ "prep": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/bundle.ts" }, "dependencies": { - "@storybook/csf": "0.1.11", + "@storybook/csf": "^0.1.11", "estraverse": "^5.2.0", "lodash": "^4.17.21", "prettier": "^3.1.1" diff --git a/code/lib/test/package.json b/code/lib/test/package.json index ec3ed55f79cd..8fbcf1ba574f 100644 --- a/code/lib/test/package.json +++ b/code/lib/test/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/test", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "", "keywords": [ "storybook" @@ -44,7 +44,7 @@ "prep": "node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/bundle.ts" }, "dependencies": { - "@storybook/csf": "0.1.11", + "@storybook/csf": "^0.1.11", "@storybook/instrumenter": "workspace:*", "@testing-library/dom": "10.1.0", "@testing-library/jest-dom": "6.4.5", diff --git a/code/lib/test/template/stories/loader-enhancements.stories.ts b/code/lib/test/template/stories/loader-enhancements.stories.ts index 997b40e12644..b759a73b56c1 100644 --- a/code/lib/test/template/stories/loader-enhancements.stories.ts +++ b/code/lib/test/template/stories/loader-enhancements.stories.ts @@ -12,7 +12,7 @@ export default meta; export const canvas_is_equal_to_within_canvas_element = { async play({ canvas, canvasElement }) { const oldCanvas = within(canvasElement); - await expect(canvas satisfies typeof oldCanvas).toEqual(oldCanvas); + await expect(Object.keys(canvas)).toEqual(Object.keys(oldCanvas)); }, }; diff --git a/code/package.json b/code/package.json index e7d38085b51d..8f933a17f10c 100644 --- a/code/package.json +++ b/code/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/root", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "private": true, "description": "Storybook root", "homepage": "https://storybook.js.org/", @@ -118,7 +118,7 @@ "@storybook/codemod": "workspace:*", "@storybook/core": "workspace:*", "@storybook/core-webpack": "workspace:*", - "@storybook/csf": "0.1.11", + "@storybook/csf": "^0.1.11", "@storybook/csf-plugin": "workspace:*", "@storybook/ember": "workspace:*", "@storybook/eslint-config-storybook": "^4.0.0", @@ -205,8 +205,8 @@ "ts-dedent": "^2.0.0", "typescript": "^5.4.3", "util": "^0.12.4", - "vite": "^4.0.0", - "vitest": "^1.2.2", + "vite": "^5.0.13", + "vitest": "^1.6.0", "wait-on": "^7.0.1" }, "dependenciesMeta": { diff --git a/code/presets/create-react-app/package.json b/code/presets/create-react-app/package.json index 2241500c2450..146b84c7da5e 100644 --- a/code/presets/create-react-app/package.json +++ b/code/presets/create-react-app/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-create-react-app", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for Create React App preset", "keywords": [ "storybook" diff --git a/code/presets/html-webpack/package.json b/code/presets/html-webpack/package.json index 704f6d59d308..833b7805a33b 100644 --- a/code/presets/html-webpack/package.json +++ b/code/presets/html-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-html-webpack", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for HTML: View HTML snippets in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/presets/preact-webpack/package.json b/code/presets/preact-webpack/package.json index 6a1e0a280a15..16a87a9e1ce6 100644 --- a/code/presets/preact-webpack/package.json +++ b/code/presets/preact-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-preact-webpack", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for Preact: Develop Preact Component in isolation.", "keywords": [ "storybook" diff --git a/code/presets/react-webpack/package.json b/code/presets/react-webpack/package.json index 771b67e795c7..767f9649217f 100644 --- a/code/presets/react-webpack/package.json +++ b/code/presets/react-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-react-webpack", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for React: Develop React Component in isolation with Hot Reloading", "keywords": [ "storybook" diff --git a/code/presets/server-webpack/package.json b/code/presets/server-webpack/package.json index b516d0b928bf..e7039d11266f 100644 --- a/code/presets/server-webpack/package.json +++ b/code/presets/server-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-server-webpack", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for Server: View HTML snippets from a server in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/presets/svelte-webpack/package.json b/code/presets/svelte-webpack/package.json index a2e60dd2a774..2811f227da26 100644 --- a/code/presets/svelte-webpack/package.json +++ b/code/presets/svelte-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-svelte-webpack", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for Svelte: Develop Svelte Component in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/presets/vue3-webpack/package.json b/code/presets/vue3-webpack/package.json index b122128b6ee6..fa0001cfeb06 100644 --- a/code/presets/vue3-webpack/package.json +++ b/code/presets/vue3-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preset-vue3-webpack", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook for Vue 3: Develop Vue 3 Components in isolation with Hot Reloading.", "keywords": [ "storybook" diff --git a/code/renderers/html/package.json b/code/renderers/html/package.json index 66dc2ae7b0b2..dbc450b61fe0 100644 --- a/code/renderers/html/package.json +++ b/code/renderers/html/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/html", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook HTML renderer", "keywords": [ "storybook" diff --git a/code/renderers/preact/package.json b/code/renderers/preact/package.json index 37a3f71ca970..aef4175f0009 100644 --- a/code/renderers/preact/package.json +++ b/code/renderers/preact/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/preact", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook Preact renderer", "keywords": [ "storybook" diff --git a/code/renderers/react/package.json b/code/renderers/react/package.json index 19ade57fedf1..49a11b714bd1 100644 --- a/code/renderers/react/package.json +++ b/code/renderers/react/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/react", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook React renderer", "keywords": [ "storybook" diff --git a/code/renderers/react/template/stories/csf1.stories.tsx b/code/renderers/react/template/stories/csf1.stories.tsx new file mode 100644 index 000000000000..63a53672b396 --- /dev/null +++ b/code/renderers/react/template/stories/csf1.stories.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +export default { + component: {}, + parameters: { + chromatic: { disable: true }, + }, +}; + +export const Hello1 = () =>
Hello1
; +export const Hello2 = () =>
Hello2
; diff --git a/code/renderers/react/template/stories/csf2.stories.tsx b/code/renderers/react/template/stories/csf2.stories.tsx new file mode 100644 index 000000000000..6b78e54e36e2 --- /dev/null +++ b/code/renderers/react/template/stories/csf2.stories.tsx @@ -0,0 +1,17 @@ +import React from 'react'; + +export default { + component: {}, + parameters: { + chromatic: { disable: true }, + }, +}; + +const Template = ({ label }: { label: string }) =>
{label}
; +Template.args = { label: 'Hello' }; + +export const Hello1 = Template.bind({}); + +export const Hello2 = Template.bind({}); + +export const Hello3 = Template.bind({}); diff --git a/code/renderers/server/package.json b/code/renderers/server/package.json index 01ce95136d61..3646540c0d07 100644 --- a/code/renderers/server/package.json +++ b/code/renderers/server/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/server", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook Server renderer", "keywords": [ "storybook" @@ -47,7 +47,7 @@ }, "dependencies": { "@storybook/components": "workspace:^", - "@storybook/csf": "0.1.11", + "@storybook/csf": "^0.1.11", "@storybook/global": "^5.0.0", "@storybook/manager-api": "workspace:^", "@storybook/preview-api": "workspace:^", diff --git a/code/renderers/svelte/package.json b/code/renderers/svelte/package.json index a5076f7b8972..ea51d463e853 100644 --- a/code/renderers/svelte/package.json +++ b/code/renderers/svelte/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/svelte", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook Svelte renderer", "keywords": [ "storybook" diff --git a/code/renderers/vue3/package.json b/code/renderers/vue3/package.json index ff2881aadbe2..8eda47f81277 100644 --- a/code/renderers/vue3/package.json +++ b/code/renderers/vue3/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/vue3", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook Vue 3 renderer", "keywords": [ "storybook" diff --git a/code/renderers/vue3/src/docs/__snapshots__/extractArgTypes.test.ts.snap b/code/renderers/vue3/src/docs/__snapshots__/extractArgTypes.test.ts.snap index cbe74a47b7d6..39e2654bcff4 100644 --- a/code/renderers/vue3/src/docs/__snapshots__/extractArgTypes.test.ts.snap +++ b/code/renderers/vue3/src/docs/__snapshots__/extractArgTypes.test.ts.snap @@ -157,12 +157,7 @@ exports[`extractArgTypes (vue-docgen-api) > should extract props for component 1 "value": { "name": "object", "required": false, - "value": { - "nestedProp": { - "name": "string", - "required": true, - }, - }, + "value": {}, }, }, }, @@ -183,12 +178,7 @@ exports[`extractArgTypes (vue-docgen-api) > should extract props for component 1 "value": { "name": "object", "required": false, - "value": { - "nestedProp": { - "name": "string", - "required": true, - }, - }, + "value": {}, }, }, }, @@ -279,12 +269,7 @@ exports[`extractArgTypes (vue-docgen-api) > should extract props for component 1 "type": { "name": "object", "required": true, - "value": { - "foo": { - "name": "string", - "required": true, - }, - }, + "value": {}, }, }, "literalFromContext": { @@ -325,12 +310,7 @@ exports[`extractArgTypes (vue-docgen-api) > should extract props for component 1 "type": { "name": "object", "required": true, - "value": { - "nestedProp": { - "name": "string", - "required": true, - }, - }, + "value": {}, }, }, "nestedIntersection": { @@ -347,16 +327,7 @@ exports[`extractArgTypes (vue-docgen-api) > should extract props for component 1 "type": { "name": "object", "required": true, - "value": { - "additionalProp": { - "name": "string", - "required": true, - }, - "nestedProp": { - "name": "string", - "required": true, - }, - }, + "value": {}, }, }, "nestedOptional": { @@ -377,22 +348,12 @@ exports[`extractArgTypes (vue-docgen-api) > should extract props for component 1 { "name": "object", "required": false, - "value": { - "nestedProp": { - "name": "string", - "required": true, - }, - }, + "value": {}, }, { "name": "object", "required": false, - "value": { - "nestedProp": { - "name": "string", - "required": true, - }, - }, + "value": {}, }, ], }, @@ -411,13 +372,7 @@ exports[`extractArgTypes (vue-docgen-api) > should extract props for component 1 "type": { "name": "object", "required": false, - "value": { - "recursive": { - "name": "other", - "required": true, - "value": "MyNestedRecursiveProps", - }, - }, + "value": {}, }, }, "stringArray": { diff --git a/code/renderers/vue3/src/docs/extractArgTypes.ts b/code/renderers/vue3/src/docs/extractArgTypes.ts index 76c52cc755a7..31f4d19dc163 100644 --- a/code/renderers/vue3/src/docs/extractArgTypes.ts +++ b/code/renderers/vue3/src/docs/extractArgTypes.ts @@ -1,3 +1,4 @@ +import type { VueDocgenInfo, VueDocgenInfoEntry, VueDocgenPlugin } from '@storybook/vue3-vite'; import type { ExtractedProp } from 'storybook/internal/docs-tools'; import { convert, @@ -6,7 +7,6 @@ import { type ArgTypesExtractor, } from 'storybook/internal/docs-tools'; import type { SBType, StrictArgTypes, StrictInputType } from 'storybook/internal/types'; -import type { VueDocgenInfo, VueDocgenInfoEntry, VueDocgenPlugin } from '@storybook/vue3-vite'; type PropertyMetaSchema = VueDocgenInfoEntry<'vue-component-meta', 'props'>['schema']; @@ -283,17 +283,12 @@ export const convertVueComponentMetaProp = ( }; } - // recursively/deeply convert all properties of the object case 'object': return { name: 'object', - value: Object.entries(schema.schema ?? {}).reduce>( - (obj, [propName, propSchema]) => { - obj[propName] = convertVueComponentMetaProp(propSchema); - return obj; - }, - {} - ), + // while Storybook generates simple JSON object controls, nested schemas don't have specialized controls + // so we don't need to recursively map the object schema here + value: {}, required, }; diff --git a/code/renderers/vue3/src/docs/sourceDecorator.test.ts b/code/renderers/vue3/src/docs/sourceDecorator.test.ts index d695d7979c37..4f92bcd9cb27 100644 --- a/code/renderers/vue3/src/docs/sourceDecorator.test.ts +++ b/code/renderers/vue3/src/docs/sourceDecorator.test.ts @@ -1,304 +1,250 @@ -import { describe, expect, it } from 'vitest'; - +import { expect, test } from 'vitest'; +import { h } from 'vue'; +import type { SourceCodeGeneratorContext } from './sourceDecorator'; import { - mapAttributesAndDirectives, - generateAttributesSource, - attributeSource, - htmlEventAttributeToVueEventAttribute as htmlEventToVueEvent, + generatePropsSourceCode, + generateSlotSourceCode, + generateSourceCode, + getFunctionParamNames, + parseDocgenInfo, } from './sourceDecorator'; -expect.addSnapshotSerializer({ - print: (val: any) => val, - test: (val: unknown) => typeof val === 'string', -}); +test('should generate source code for props', () => { + const ctx: SourceCodeGeneratorContext = { + scriptVariables: {}, + imports: {}, + }; -describe('Vue3: sourceDecorator->mapAttributesAndDirective()', () => { - it('camelCase boolean Arg', () => { - expect(mapAttributesAndDirectives({ camelCaseBooleanArg: true })).toMatchInlineSnapshot(` - [ - { - arg: { - content: camel-case-boolean-arg, - loc: { - source: camel-case-boolean-arg, - }, - }, - exp: { - isStatic: false, - loc: { - source: true, - }, - }, - loc: { - source: :camel-case-boolean-arg="true", - }, - modifiers: [ - , - ], - name: bind, - type: 6, - }, - ] - `); - }); - it('camelCase string Arg', () => { - expect(mapAttributesAndDirectives({ camelCaseStringArg: 'foo' })).toMatchInlineSnapshot(` - [ - { - arg: { - content: camel-case-string-arg, - loc: { - source: camel-case-string-arg, - }, - }, - exp: { - isStatic: false, - loc: { - source: foo, - }, - }, - loc: { - source: camel-case-string-arg="foo", - }, - modifiers: [ - , - ], - name: bind, - type: 6, - }, - ] - `); - }); - it('boolean arg', () => { - expect(mapAttributesAndDirectives({ booleanarg: true })).toMatchInlineSnapshot(` - [ - { - arg: { - content: booleanarg, - loc: { - source: booleanarg, - }, - }, - exp: { - isStatic: false, - loc: { - source: true, - }, - }, - loc: { - source: :booleanarg="true", - }, - modifiers: [ - , - ], - name: bind, - type: 6, - }, - ] - `); - }); - it('string arg', () => { - expect(mapAttributesAndDirectives({ stringarg: 'bar' })).toMatchInlineSnapshot(` - [ - { - arg: { - content: stringarg, - loc: { - source: stringarg, - }, - }, - exp: { - isStatic: false, - loc: { - source: bar, - }, - }, - loc: { - source: stringarg="bar", - }, - modifiers: [ - , - ], - name: bind, - type: 6, - }, - ] - `); - }); - it('number arg', () => { - expect(mapAttributesAndDirectives({ numberarg: 2023 })).toMatchInlineSnapshot(` - [ - { - arg: { - content: numberarg, - loc: { - source: numberarg, - }, - }, - exp: { - isStatic: false, - loc: { - source: 2023, - }, - }, - loc: { - source: :numberarg="2023", - }, - modifiers: [ - , - ], - name: bind, - type: 6, - }, - ] - `); - }); - it('camelCase boolean, string, and number Args', () => { - expect( - mapAttributesAndDirectives({ - camelCaseBooleanArg: true, - camelCaseStringArg: 'foo', - cameCaseNumberArg: 2023, - }) - ).toMatchInlineSnapshot(` - [ - { - arg: { - content: camel-case-boolean-arg, - loc: { - source: camel-case-boolean-arg, - }, - }, - exp: { - isStatic: false, - loc: { - source: true, - }, - }, - loc: { - source: :camel-case-boolean-arg="true", - }, - modifiers: [ - , - ], - name: bind, - type: 6, - }, - { - arg: { - content: camel-case-string-arg, - loc: { - source: camel-case-string-arg, - }, - }, - exp: { - isStatic: false, - loc: { - source: foo, - }, - }, - loc: { - source: camel-case-string-arg="foo", - }, - modifiers: [ - , - ], - name: bind, - type: 6, - }, - { - arg: { - content: came-case-number-arg, - loc: { - source: came-case-number-arg, - }, - }, - exp: { - isStatic: false, - loc: { - source: 2023, - }, - }, - loc: { - source: :came-case-number-arg="2023", - }, - modifiers: [ - , - ], - name: bind, - type: 6, - }, - ] - `); + const code = generatePropsSourceCode( + { + a: 'foo', + b: '"I am double quoted"', + c: 42, + d: true, + e: false, + f: [1, 2, 3], + g: { + g1: 'foo', + g2: 42, + }, + h: undefined, + i: null, + j: '', + k: BigInt(9007199254740991), + l: Symbol(), + m: Symbol('foo'), + modelValue: 'test-v-model', + otherModelValue: 42, + default: 'default slot', + testSlot: 'test slot', + }, + ['default', 'testSlot'], + ['update:modelValue', 'update:otherModelValue'], + ctx + ); + + expect(code).toBe( + `a="foo" b='"I am double quoted"' :c="42" d :e="false" :f="f" :g="g" :k="BigInt(9007199254740991)" :l="Symbol()" :m="Symbol('foo')" v-model="modelValue" v-model:otherModelValue="otherModelValue"` + ); + + expect(ctx.scriptVariables).toStrictEqual({ + f: `[1,2,3]`, + g: `{"g1":"foo","g2":42}`, + modelValue: 'ref("test-v-model")', + otherModelValue: 'ref(42)', }); + + expect(Array.from(ctx.imports.vue.values())).toStrictEqual(['ref']); }); -describe('Vue3: sourceDecorator->generateAttributesSource()', () => { - it('camelCase boolean Arg', () => { - expect( - generateAttributesSource( - mapAttributesAndDirectives({ camelCaseBooleanArg: true }), - { camelCaseBooleanArg: true }, - [{ camelCaseBooleanArg: { type: 'boolean' } }] as any - ) - ).toMatchInlineSnapshot(`:camel-case-boolean-arg="true"`); - }); - it('camelCase string Arg', () => { - expect( - generateAttributesSource( - mapAttributesAndDirectives({ camelCaseStringArg: 'foo' }), - { camelCaseStringArg: 'foo' }, - [{ camelCaseStringArg: { type: 'string' } }] as any - ) - ).toMatchInlineSnapshot(`camel-case-string-arg="foo"`); +test('should generate source code for slots', () => { + // slot code generator should support primitive values (string, number etc.) + // but also VNodes (e.g. created using h()) so custom Vue components can also be used + // inside slots with proper generated code + + const slots = { + default: 'default content', + a: 'a content', + b: 42, + c: true, + // single VNode without props + d: h('div', 'd content'), + // VNode with props and single child + e: h('div', { style: 'color:red' }, 'e content'), + // VNode with props and single child returned as getter + f: h('div', { style: 'color:red' }, () => 'f content'), + // VNode with multiple children + g: h('div', { style: 'color:red' }, [ + 'child 1', + h('span', { style: 'color:green' }, 'child 2'), + ]), + // VNode multiple children but returned as getter + h: h('div', { style: 'color:red' }, () => [ + 'child 1', + h('span', { style: 'color:green' }, 'child 2'), + ]), + // VNode with multiple and nested children + i: h('div', { style: 'color:red' }, [ + 'child 1', + h('span', { style: 'color:green' }, ['nested child 1', h('p', 'nested child 2')]), + ]), + j: ['child 1', 'child 2'], + k: null, + l: { foo: 'bar' }, + m: BigInt(9007199254740991), + }; + + const expectedCode = `default content + + + + + + + + + + + + + + + + + + + + + + + +`; + + let actualCode = generateSlotSourceCode(slots, Object.keys(slots), { + scriptVariables: {}, + imports: {}, }); + expect(actualCode).toBe(expectedCode); + + // should generate the same code if getters/functions are used to return the slot content + const slotsWithGetters = Object.entries(slots).reduce< + Record (typeof slots)[keyof typeof slots]> + >((obj, [slotName, value]) => { + obj[slotName] = () => value; + return obj; + }, {}); - it('camelCase boolean, string, and number Args', () => { - expect( - generateAttributesSource( - mapAttributesAndDirectives({ - camelCaseBooleanArg: true, - camelCaseStringArg: 'foo', - cameCaseNumberArg: 2023, - }), - { - camelCaseBooleanArg: true, - camelCaseStringArg: 'foo', - cameCaseNumberArg: 2023, - }, - [] as any - ) - ).toMatchInlineSnapshot( - `:camel-case-boolean-arg="true" camel-case-string-arg="foo" :came-case-number-arg="2023"` - ); + actualCode = generateSlotSourceCode(slotsWithGetters, Object.keys(slotsWithGetters), { + scriptVariables: {}, + imports: {}, }); + expect(actualCode).toBe(expectedCode); }); -describe('Vue3: sourceDecorator->attributeSoure()', () => { - it('camelCase boolean Arg', () => { - expect(attributeSource('stringArg', 'foo')).toMatchInlineSnapshot(`stringArg="foo"`); - }); +test('should generate source code for slots with bindings', () => { + type TestBindings = { + foo: string; + bar?: number; + }; - it('html event attribute should convert to vue event directive', () => { - expect(attributeSource('onClick', () => {})).toMatchInlineSnapshot(`v-on:click='()=>({})'`); - expect(attributeSource('onclick', () => {})).toMatchInlineSnapshot(`v-on:click='()=>({})'`); - }); - it('normal html attribute should not convert to vue event directive', () => { - expect(attributeSource('on-click', () => {})).toMatchInlineSnapshot(`on-click='()=>({})'`); - }); - it('The value undefined or empty string must not be returned.', () => { - expect(attributeSource('icon', undefined)).toMatchInlineSnapshot(`icon=""`); - expect(attributeSource('icon', '')).toMatchInlineSnapshot(`icon=""`); + const slots = { + a: ({ foo, bar }: TestBindings) => `Slot with bindings ${foo} and ${bar}`, + b: ({ foo }: TestBindings) => h('a', { href: foo, target: foo }, `Test link: ${foo}`), + }; + + const expectedCode = ` + +`; + + const actualCode = generateSlotSourceCode(slots, Object.keys(slots), { + imports: {}, + scriptVariables: {}, }); - it('htmlEventAttributeToVueEventAttribute onEv => v-on:', () => { - const htmlEventAttributeToVueEventAttribute = (attribute: string) => { - return htmlEventToVueEvent(attribute); - }; - expect(/^on[A-Za-z]/.test('onClick')).toBeTruthy(); - expect(htmlEventAttributeToVueEventAttribute('onclick')).toMatchInlineSnapshot(`v-on:click`); - expect(htmlEventAttributeToVueEventAttribute('onClick')).toMatchInlineSnapshot(`v-on:click`); - expect(htmlEventAttributeToVueEventAttribute('onChange')).toMatchInlineSnapshot(`v-on:change`); - expect(htmlEventAttributeToVueEventAttribute('onFocus')).toMatchInlineSnapshot(`v-on:focus`); - expect(htmlEventAttributeToVueEventAttribute('on-focus')).toMatchInlineSnapshot(`on-focus`); + expect(actualCode).toBe(expectedCode); +}); + +test('should generate source code with + +`); +}); + +test.each([ + { __docgenInfo: 'invalid-value', slotNames: [] }, + { __docgenInfo: {}, slotNames: [] }, + { __docgenInfo: { slots: 'invalid-value' }, slotNames: [] }, + { __docgenInfo: { slots: ['invalid-value'] }, slotNames: [] }, + { + __docgenInfo: { slots: [{ name: 'slot-1' }, { name: 'slot-2' }, { notName: 'slot-3' }] }, + slotNames: ['slot-1', 'slot-2'], + }, +])('should parse slots names from __docgenInfo', ({ __docgenInfo, slotNames }) => { + const docgenInfo = parseDocgenInfo({ __docgenInfo }); + expect(docgenInfo.slotNames).toStrictEqual(slotNames); +}); + +test.each([ + { __docgenInfo: 'invalid-value', eventNames: [] }, + { __docgenInfo: {}, eventNames: [] }, + { __docgenInfo: { events: 'invalid-value' }, eventNames: [] }, + { __docgenInfo: { events: ['invalid-value'] }, eventNames: [] }, + { + __docgenInfo: { events: [{ name: 'event-1' }, { name: 'event-2' }, { notName: 'event-3' }] }, + eventNames: ['event-1', 'event-2'], + }, +])('should parse event names from __docgenInfo', ({ __docgenInfo, eventNames }) => { + const docgenInfo = parseDocgenInfo({ __docgenInfo }); + expect(docgenInfo.eventNames).toStrictEqual(eventNames); +}); + +test.each<{ fn: (...args: any[]) => unknown; expectedNames: string[] }>([ + { fn: () => ({}), expectedNames: [] }, + { fn: (a) => ({}), expectedNames: ['a'] }, + { fn: (a, b) => ({}), expectedNames: ['a', 'b'] }, + { fn: (a, b, { c }) => ({}), expectedNames: ['a', 'b', '{', 'c', '}'] }, + { fn: ({ a, b }) => ({}), expectedNames: ['{', 'a', 'b', '}'] }, + { + fn: { + // simulate minified function after running "storybook build" + toString: () => '({a:foo,b:bar})=>({})', + } as (...args: any[]) => unknown, + expectedNames: ['{', 'a', 'b', '}'], + }, +])('should extract function parameter names', ({ fn, expectedNames }) => { + const paramNames = getFunctionParamNames(fn); + expect(paramNames).toStrictEqual(expectedNames); }); diff --git a/code/renderers/vue3/src/docs/sourceDecorator.ts b/code/renderers/vue3/src/docs/sourceDecorator.ts index 28277a23b95b..764aacf91fe7 100644 --- a/code/renderers/vue3/src/docs/sourceDecorator.ts +++ b/code/renderers/vue3/src/docs/sourceDecorator.ts @@ -1,46 +1,119 @@ /* eslint-disable no-underscore-dangle */ +import { SNIPPET_RENDERED, SourceType } from 'storybook/internal/docs-tools'; import { addons } from 'storybook/internal/preview-api'; -import type { ArgTypes, Args, StoryContext } from 'storybook/internal/types'; - -import { SourceType, SNIPPET_RENDERED } from 'storybook/internal/docs-tools'; - -import type { - ElementNode, - AttributeNode, - DirectiveNode, - TextNode, - InterpolationNode, - TemplateChildNode, -} from '@vue/compiler-core'; -import { baseParse } from '@vue/compiler-core'; -import type { ConcreteComponent, FunctionalComponent, VNode } from 'vue'; -import { h, isVNode, watch } from 'vue'; -import kebabCase from 'lodash/kebabCase'; -import { - attributeSource, - htmlEventAttributeToVueEventAttribute, - omitEvent, - evalExp, - replaceValueWithRef, - generateExpression, -} from './utils'; -import type { VueRenderer } from '../types'; +import type { VNode } from 'vue'; +import { isVNode, watch } from 'vue'; +import type { Args, Decorator, StoryContext } from '../public-types'; /** - * Check if the sourcecode should be generated. - * - * @param context StoryContext + * Context that is passed down to nested components/slots when generating the source code for a single story. */ -const skipSourceRender = (context: StoryContext) => { - const sourceParams = context?.parameters.docs?.source; - const isArgsStory = context?.parameters.__isArgsStory; - const isDocsViewMode = context?.viewMode === 'docs'; +export type SourceCodeGeneratorContext = { + /** + * Properties/variables that should be placed inside a ` + +${template}`; +}; + +/** + * Checks if the source code generation should be skipped for the given Story context. + * Will be true if one of the following is true: + * - view mode is not "docs" + * - story is no arg story + * - story has set custom source code via parameters.docs.source.code + * - story has set source type to "code" via parameters.docs.source.type + */ +export const shouldSkipSourceCodeGeneration = (context: StoryContext): boolean => { + const sourceParams = context?.parameters.docs?.source; if (sourceParams?.type === SourceType.DYNAMIC) { + // always render if the user forces it return false; } + const isArgsStory = context?.parameters.__isArgsStory; + const isDocsViewMode = context?.viewMode === 'docs'; + // never render if the user is forcing the block to render code, or // if the user provides code, or if it's not an args story. return ( @@ -49,271 +122,441 @@ const skipSourceRender = (context: StoryContext) => { }; /** - * - * @param _args - * @param argTypes - * @param byRef - */ -export function generateAttributesSource( - tempArgs: (AttributeNode | DirectiveNode)[], - args: Args, - argTypes: ArgTypes, - byRef?: boolean -): string { - return Object.keys(tempArgs) - .map((key: any) => { - const source = tempArgs[key].loc.source.replace(/\$props/g, 'args'); - const argKey = (tempArgs[key] as DirectiveNode).arg?.loc.source; - return byRef && argKey - ? replaceValueWithRef(source, args, argKey) - : evalExp(source, omitEvent(args)); - }) - .join(' '); -} -/** - * map attributes and directives - * @param props + * Parses the __docgenInfo of the given component. + * Requires Storybook docs addon to be enabled. + * Default slot will always be sorted first, remaining slots are sorted alphabetically. */ -function mapAttributesAndDirectives(props: Args) { - const tranformKey = (key: string) => (key.startsWith('on') ? key : kebabCase(key)); - return Object.keys(props).map( - (key) => - ({ - name: 'bind', - type: ['v-', '@', 'v-on'].includes(key) ? 7 : 6, // 6 is attribute, 7 is directive - arg: { content: tranformKey(key), loc: { source: tranformKey(key) } }, // attribute name or directive name (v-bind, v-on, v-model) - loc: { source: attributeSource(tranformKey(key), props[key]) }, // attribute value or directive value - exp: { isStatic: false, loc: { source: props[key] } }, // directive expression - modifiers: [''], - }) as unknown as AttributeNode - ); -} +export const parseDocgenInfo = ( + component?: StoryContext['component'] & { __docgenInfo?: unknown } +) => { + // type check __docgenInfo to prevent errors + if ( + !component || + !('__docgenInfo' in component) || + !component.__docgenInfo || + typeof component.__docgenInfo !== 'object' + ) { + return { + displayName: component?.__name, + eventNames: [], + slotNames: [], + }; + } + + const docgenInfo = component.__docgenInfo as Record; + + const displayName = + 'displayName' in docgenInfo && typeof docgenInfo.displayName === 'string' + ? docgenInfo.displayName + : undefined; + + const parseNames = (key: 'slots' | 'events') => { + if (!(key in docgenInfo) || !Array.isArray(docgenInfo[key])) return []; + + const values = docgenInfo[key] as unknown[]; + + return values + .map((i) => (i && typeof i === 'object' && 'name' in i ? i.name : undefined)) + .filter((i): i is string => typeof i === 'string'); + }; + + return { + displayName: displayName || component.__name, + slotNames: parseNames('slots').sort((a, b) => { + if (a === 'default') return -1; + if (b === 'default') return 1; + return a.localeCompare(b); + }), + eventNames: parseNames('events'), + }; +}; + /** - * map slots - * @param slotsArgs + * Generates the source code for the given Vue component properties. + * Props with complex values (objects and arrays) and v-models will be added to the ctx.scriptVariables because they should be + * generated in a ``; -} /** - * get template components one or more - * @param renderFn + * Generates the source code for the given slot children (the code inside ). */ -function getTemplateComponents( - renderFn: any, - context?: StoryContext -): (TemplateChildNode | VNode)[] { - try { - const originalStoryFn = renderFn; - - const storyFn = originalStoryFn ? originalStoryFn(context?.args, context) : context?.component; - const story = typeof storyFn === 'function' ? storyFn() : storyFn; - - const { template } = story; - - if (!template) return [h(story, context?.args)]; - return getComponents(template); - } catch (e) { - return []; - } -} +const generateSlotChildrenSourceCode = ( + children: unknown[], + ctx: SourceCodeGeneratorContext +): string => { + const slotChildrenSourceCodes: string[] = []; + + /** + * Recursively generates the source code for a single slot child and all its children. + * @returns Source code for child and all nested children or empty string if child is of a non-supported type. + */ + const generateSingleChildSourceCode = (child: unknown): string => { + if (isVNode(child)) { + return generateVNodeSourceCode(child, ctx); + } + + switch (typeof child) { + case 'string': + case 'number': + case 'boolean': + return child.toString(); + + case 'object': + if (child === null) return ''; + if (Array.isArray(child)) { + // if child also has children, we generate them recursively + return child + .map(generateSingleChildSourceCode) + .filter((code) => code !== '') + .join('\n'); + } + return JSON.stringify(child); + + case 'function': { + const paramNames = getFunctionParamNames(child).filter( + (param) => !['{', '}'].includes(param) + ); + + const parameters = paramNames.reduce>((obj, param) => { + obj[param] = `{{ ${param} }}`; + return obj; + }, {}); + + const returnValue = child(parameters); + let slotSourceCode = generateSlotChildrenSourceCode([returnValue], ctx); -function getComponents(template: string): (TemplateChildNode | VNode)[] { - const ast = baseParse(template, { - isNativeTag: () => true, - decodeEntities: (rawtext, asAttr) => rawtext, + // if slot bindings are used for properties of other components, our {{ paramName }} is incorrect because + // it would generate e.g. my-prop="{{ paramName }}", therefore, we replace it here to e.g. :my-prop="paramName" + paramNames.forEach((param) => { + slotSourceCode = slotSourceCode.replaceAll( + new RegExp(` (\\S+)="{{ ${param} }}"`, 'g'), + ` :$1="${param}"` + ); + }); + + return slotSourceCode; + } + + case 'bigint': + return `{{ BigInt(${child.toString()}) }}`; + + // the only missing case here is "symbol" + // because rendering a symbol as slot / HTML does not make sense and is not supported by Vue + default: + return ''; + } + }; + + children.forEach((child) => { + const sourceCode = generateSingleChildSourceCode(child); + if (sourceCode !== '') slotChildrenSourceCodes.push(sourceCode); }); - const components = ast?.children; - if (!components) return []; - return components; -} + + return slotChildrenSourceCodes.join('\n'); +}; /** - * Generate a vue3 template. + * Generates source code for the given VNode and all its children (e.g. created using `h(MyComponent)` or `h("div")`). + */ +const generateVNodeSourceCode = (vnode: VNode, ctx: SourceCodeGeneratorContext): string => { + const componentName = getVNodeName(vnode); + let childrenCode = ''; + + if (typeof vnode.children === 'string') { + childrenCode = vnode.children; + } else if (Array.isArray(vnode.children)) { + childrenCode = generateSlotChildrenSourceCode(vnode.children, ctx); + } else if (vnode.children) { + // children are an object, just like if regular Story args where used + // so we can generate the source code with the regular "generateSlotSourceCode()". + childrenCode = generateSlotSourceCode( + vnode.children, + // $stable is a default property in vnode.children so we need to filter it out + // to not generate source code for it + Object.keys(vnode.children).filter((i) => i !== '$stable'), + ctx + ); + } + + const props = vnode.props ? generatePropsSourceCode(vnode.props, [], [], ctx) : ''; + + // prefer self closing tag if no children exist + if (childrenCode) { + return `<${componentName}${props ? ` ${props}` : ''}>${childrenCode}`; + } + return `<${componentName}${props ? ` ${props}` : ''} />`; +}; + +/** + * Gets the name for the given VNode. + * Will return "component" if name could not be extracted. * - * @param component Component - * @param args Args - * @param argTypes ArgTypes - * @param slotProp Prop used to simulate a slot + * @example "div" for `h("div")` or "MyComponent" for `h(MyComponent)` */ +const getVNodeName = (vnode: VNode) => { + // this is e.g. the case when rendering native HTML elements like, h("div") + if (typeof vnode.type === 'string') return vnode.type; -export function generateTemplateSource( - componentOrNodes: (ConcreteComponent | TemplateChildNode)[] | TemplateChildNode | VNode, - { args, argTypes }: { args: Args; argTypes: ArgTypes }, - byRef = false -) { - const isElementNode = (node: any) => node && node.type === 1; - const isInterpolationNode = (node: any) => node && node.type === 5; - const isTextNode = (node: any) => node && node.type === 2; - - const generateComponentSource = ( - componentOrNode: ConcreteComponent | TemplateChildNode | VNode - ) => { - if (isElementNode(componentOrNode)) { - const { tag: name, props: attributes, children } = componentOrNode as ElementNode; - const childSources: string = - typeof children === 'string' - ? children - : children.map((child: TemplateChildNode) => generateComponentSource(child)).join(''); - const props = generateAttributesSource(attributes, args, argTypes, byRef); - - return childSources === '' - ? `<${name} ${props} />` - : `<${name} ${props}>${childSources}`; + if (typeof vnode.type === 'object') { + // this is the case when using custom Vue components like h(MyComponent) + if ('name' in vnode.type && vnode.type.name) { + // prefer custom component name set by the developer + return vnode.type.name; + } else if ('__name' in vnode.type && vnode.type.__name) { + // otherwise use name inferred by Vue from the file name + return vnode.type.__name; } + } - if (isTextNode(componentOrNode)) { - const { content } = componentOrNode as TextNode; - return content; - } - if (isInterpolationNode(componentOrNode)) { - const { content } = componentOrNode as InterpolationNode; - const expValue = evalExp(content.loc.source, args); - if (expValue === content.loc.source) return `{{${expValue}}}`; - return eval(expValue); - } - if (isVNode(componentOrNode)) { - const vnode = componentOrNode as VNode; - const { props, type, children } = vnode; - const slotsProps = typeof children === 'string' ? undefined : (children as Args); - const componentSlots = (type as any)?.__docgenInfo?.slots; - - const attrsProps = slotsProps - ? Object.fromEntries( - Object.entries(props ?? {}) - .filter(([key, value]) => !slotsProps[key] && !['class', 'style'].includes(key)) - .map(([key, value]) => [key, value]) - ) - : props; - const attributes = mapAttributesAndDirectives(attrsProps ?? {}); - const slotArgs = Object.fromEntries( - Object.entries(props ?? {}).filter(([key, value]) => slotsProps?.[key]) - ); + return 'component'; +}; - const childSources: string = children - ? typeof children === 'string' - ? children - : mapSlots(slotArgs as Args, generateComponentSource, componentSlots ?? []) - .map((child) => child.content) - .join('') - : ''; - const name = - typeof type === 'string' - ? type - : (type as FunctionalComponent).name || - (type as ConcreteComponent).__name || - (type as any).__docgenInfo?.displayName; - const propsSource = generateAttributesSource(attributes, args, argTypes, byRef); - return childSources.trim() === '' - ? `<${name} ${propsSource}/>` - : `<${name} ${propsSource}>${childSources}`; - } +/** + * Gets a list of parameters for the given function since func.arguments can not be used since + * it throws a TypeError. + * + * If the arguments are destructured (e.g. "func({ foo, bar })"), the returned array will also + * include "{" and "}". + * + * @see Based on https://stackoverflow.com/a/9924463 + */ +// eslint-disable-next-line @typescript-eslint/ban-types +export const getFunctionParamNames = (func: Function): string[] => { + const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm; + const ARGUMENT_NAMES = /([^\s,]+)/g; - return null; - }; + const fnStr = func.toString().replace(STRIP_COMMENTS, ''); + const result = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')).match(ARGUMENT_NAMES); + if (!result) return []; - const componentsOrNodes = Array.isArray(componentOrNodes) ? componentOrNodes : [componentOrNodes]; - const source = componentsOrNodes - .map((componentOrNode) => generateComponentSource(componentOrNode)) - .join(' '); - return source || null; -} + // when running "storybook build", the function will be minified, so result for e.g. + // `({ foo, bar }) => { // function body }` will be `["{foo:e", "bar:a}"]` + // therefore we need to remove the :e and :a mappings and extract the "{" and "}"" from the destructured object + // so the final result becomes `["{", "foo", "bar", "}"]` + return result.flatMap((param) => { + if (['{', '}'].includes(param)) return param; + const nonMinifiedName = param.split(':')[0].trim(); + if (nonMinifiedName.startsWith('{')) { + return ['{', nonMinifiedName.substring(1)]; + } + if (param.endsWith('}') && !nonMinifiedName.endsWith('}')) { + return [nonMinifiedName, '}']; + } + return nonMinifiedName; + }); +}; /** - * source decorator. - * @param storyFn Fn - * @param context StoryContext + * Converts the given slot bindings/parameters to a string. + * + * @example + * If no params: '#slotName' + * If params: '#slotName="{ foo, bar }"' */ -export const sourceDecorator = (storyFn: any, context: StoryContext) => { - const skip = skipSourceRender(context); - const story = storyFn(); +const slotBindingsToString = ( + slotName: string, + params: string[] +): `#${string}` | `#${string}="${string}"` => { + if (!params.length) return `#${slotName}`; + if (params.length === 1) return `#${slotName}="${params[0]}"`; - watch( - () => context.args, - () => { - if (!skip) { - generateSource(context); - } - }, - { immediate: true, deep: true } - ); - return story; + // parameters might be destructured so remove duplicated brackets here + return `#${slotName}="{ ${params.filter((i) => !['{', '}'].includes(i)).join(', ')} }"`; }; -export function generateSource(context: StoryContext) { - const channel = addons.getChannel(); - const { args = {}, argTypes = {}, id } = context || {}; - const storyComponents = getTemplateComponents(context?.originalStoryFn, context); +/** + * Formats the given object as string. + * Will format in single line if it only contains non-object values. + * Otherwise will format multiline. + */ +export const formatObject = (obj: object): string => { + const isPrimitive = Object.values(obj).every( + (value) => value == null || typeof value !== 'object' + ); - const withScript = context?.parameters?.docs?.source?.withScriptSetup || false; - const generatedScript = withScript ? generateScriptSetup(args, argTypes, storyComponents) : ''; - const generatedTemplate = generateTemplateSource(storyComponents, context, withScript); + // if object/array only contains non-object values, we format all values in one line + if (isPrimitive) return JSON.stringify(obj); - if (generatedTemplate) { - const source = `${generatedScript}\n `; - channel.emit(SNIPPET_RENDERED, { id, args, source, format: 'vue' }); - return source; - } - return null; -} -// export local function for testing purpose -export { - generateScriptSetup, - getTemplateComponents as getComponentsFromRenderFn, - getComponents as getComponentsFromTemplate, - mapAttributesAndDirectives, - attributeSource, - htmlEventAttributeToVueEventAttribute, + // otherwise, we use a "pretty" formatting with newlines and spaces + return JSON.stringify(obj, null, 2); }; diff --git a/code/renderers/vue3/src/entry-preview-docs.ts b/code/renderers/vue3/src/entry-preview-docs.ts index 66e848f2bc12..16c9338a164b 100644 --- a/code/renderers/vue3/src/entry-preview-docs.ts +++ b/code/renderers/vue3/src/entry-preview-docs.ts @@ -1,6 +1,9 @@ -import type { ArgTypesEnhancer, DecoratorFunction } from 'storybook/internal/types'; -import type { ArgTypesExtractor } from 'storybook/internal/docs-tools'; -import { extractComponentDescription, enhanceArgTypes } from 'storybook/internal/docs-tools'; +import { + enhanceArgTypes, + extractComponentDescription, + type ArgTypesExtractor, +} from 'storybook/internal/docs-tools'; +import type { ArgTypesEnhancer } from 'storybook/internal/types'; import { extractArgTypes } from './docs/extractArgTypes'; import { sourceDecorator } from './docs/sourceDecorator'; import type { VueRenderer } from './types'; @@ -21,6 +24,6 @@ export const parameters: { }, }; -export const decorators: DecoratorFunction[] = [sourceDecorator]; +export const decorators = [sourceDecorator]; export const argTypesEnhancers: ArgTypesEnhancer[] = [enhanceArgTypes]; diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/SourceCode.stories.ts b/code/renderers/vue3/template/stories_vue3-vite-default-ts/SourceCode.stories.ts new file mode 100644 index 000000000000..c9500c509a48 --- /dev/null +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/SourceCode.stories.ts @@ -0,0 +1,29 @@ +import type { Meta, StoryObj } from '@storybook/vue3'; +import { h } from 'vue'; +import SourceCode from './SourceCode.vue'; + +const meta: Meta = { + component: SourceCode, + tags: ['autodocs'], +}; + +export default meta; +type Story = StoryObj; + +export const Default = { + args: { + foo: 'Example string', + bar: 42, + array: ['A', 'B', 'C'], + object: { + a: 'Test A', + b: 42, + }, + modelValue: 'Model value', + default: 'Default slot content', + namedSlot: ({ foo }) => [ + 'Plain text', + h('div', { style: 'color:red' }, ['Div child', h('span', foo)]), + ], + }, +} satisfies Story; diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/SourceCode.vue b/code/renderers/vue3/template/stories_vue3-vite-default-ts/SourceCode.vue new file mode 100644 index 000000000000..6fae0e0ec5d8 --- /dev/null +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/SourceCode.vue @@ -0,0 +1,27 @@ + + + diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/DefineSlots.stories.ts b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/DefineSlots.stories.ts index 1a06ce6bb504..da11664027c9 100644 --- a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/DefineSlots.stories.ts +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/DefineSlots.stories.ts @@ -11,8 +11,8 @@ export default meta; export const Default: Story = { args: { - default: ({ num }) => `Default slot { num=${num} }`, - named: ({ str }) => `Named slot { str=${str} }`, - vbind: ({ num, str }) => `Named v-bind slot { num=${num}, str=${str} }`, + default: ({ num }) => `Default slot: num=${num}`, + named: ({ str }) => `Named slot: str=${str}`, + vbind: ({ num, str }) => `Named v-bind slot: num=${num}, str=${str}`, }, }; diff --git a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/TemplateSlots.stories.ts b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/TemplateSlots.stories.ts index 817bdcba42df..7ae73f819caf 100644 --- a/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/TemplateSlots.stories.ts +++ b/code/renderers/vue3/template/stories_vue3-vite-default-ts/component-meta/TemplateSlots.stories.ts @@ -11,8 +11,8 @@ export default meta; export const Default: Story = { args: { - default: ({ num }) => `Default slot { num=${num} }`, - named: ({ str }) => `Named slot { str=${str} }`, - vbind: ({ num, str }) => `Named v-bind slot { num=${num}, str=${str} }`, + default: ({ num }) => `Default slot: num=${num}`, + named: ({ str }) => `Named slot: str=${str}`, + vbind: ({ num, str }) => `Named v-bind slot: num=${num}, str=${str}`, }, }; diff --git a/code/renderers/web-components/package.json b/code/renderers/web-components/package.json index 4287094def3b..85b6eebc4fde 100644 --- a/code/renderers/web-components/package.json +++ b/code/renderers/web-components/package.json @@ -1,6 +1,6 @@ { "name": "@storybook/web-components", - "version": "8.3.0-alpha.0", + "version": "8.3.0-alpha.2", "description": "Storybook web-components renderer", "keywords": [ "lit", diff --git a/code/yarn.lock b/code/yarn.lock index 83c9e7cd3c6b..0befd6419789 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -13,9 +13,9 @@ __metadata: linkType: hard "@adobe/css-tools@npm:^4.3.2": - version: 4.3.3 - resolution: "@adobe/css-tools@npm:4.3.3" - checksum: 10c0/e76e712df713964b87cdf2aca1f0477f19bebd845484d5fcba726d3ec7782366e2f26ec8cb2dcfaf47081a5c891987d8a9f5c3f30d11e1eb3c1848adc27fcb24 + version: 4.4.0 + resolution: "@adobe/css-tools@npm:4.4.0" + checksum: 10c0/d65ddc719389bf469097df80fb16a8af48a973dea4b57565789d70ac8e7ab4987e6dc0095da3ed5dc16c1b6f8960214a7590312eeda8abd543d91fd0f59e6c94 languageName: node linkType: hard @@ -3668,6 +3668,38 @@ __metadata: languageName: node linkType: hard +"@jsonjoy.com/base64@npm:^1.1.1": + version: 1.1.2 + resolution: "@jsonjoy.com/base64@npm:1.1.2" + peerDependencies: + tslib: 2 + checksum: 10c0/88717945f66dc89bf58ce75624c99fe6a5c9a0c8614e26d03e406447b28abff80c69fb37dabe5aafef1862cf315071ae66e5c85f6018b437d95f8d13d235e6eb + languageName: node + linkType: hard + +"@jsonjoy.com/json-pack@npm:^1.0.3": + version: 1.0.4 + resolution: "@jsonjoy.com/json-pack@npm:1.0.4" + dependencies: + "@jsonjoy.com/base64": "npm:^1.1.1" + "@jsonjoy.com/util": "npm:^1.1.2" + hyperdyperid: "npm:^1.2.0" + thingies: "npm:^1.20.0" + peerDependencies: + tslib: 2 + checksum: 10c0/c06e57c33d3c18ab31af163e04f77cb759f68386c41375d1e1bd6c28beb1a3cc82217cc3b26f4c94b7385ed28a61e59b01498cf4cec562fd9e464b17eab0cf16 + languageName: node + linkType: hard + +"@jsonjoy.com/util@npm:^1.1.2, @jsonjoy.com/util@npm:^1.3.0": + version: 1.3.0 + resolution: "@jsonjoy.com/util@npm:1.3.0" + peerDependencies: + tslib: 2 + checksum: 10c0/892bbe2073bb20bf392dd4dfed77881c6f7ae6a0cc5802e537fe3cbeeadde7738de5369f2d4529156efc5e98d9d43b15c85906ddb79140e322f1b26eaaf854df + languageName: node + linkType: hard + "@juggle/resize-observer@npm:^3.3.1": version: 3.4.0 resolution: "@juggle/resize-observer@npm:3.4.0" @@ -3781,72 +3813,72 @@ __metadata: languageName: node linkType: hard -"@next/env@npm:14.1.0": - version: 14.1.0 - resolution: "@next/env@npm:14.1.0" - checksum: 10c0/f45ce1e3dad87cdbddc58b06bd411f44a6d21dfc2c344d02a5e1b07f56fbc9a39e192c0b0917df9f2e9e4e2156306a8c78f173ca4b53932c2793e67797462a23 +"@next/env@npm:14.2.5": + version: 14.2.5 + resolution: "@next/env@npm:14.2.5" + checksum: 10c0/63d8b88ac450b3c37940a9e2119a63a1074aca89908574ade6157a8aa295275dcb3ac5f69e00883fc55d0f12963b73b74e87ba32a5768a489f9609c6be57b699 languageName: node linkType: hard -"@next/swc-darwin-arm64@npm:14.1.0": - version: 14.1.0 - resolution: "@next/swc-darwin-arm64@npm:14.1.0" +"@next/swc-darwin-arm64@npm:14.2.5": + version: 14.2.5 + resolution: "@next/swc-darwin-arm64@npm:14.2.5" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@next/swc-darwin-x64@npm:14.1.0": - version: 14.1.0 - resolution: "@next/swc-darwin-x64@npm:14.1.0" +"@next/swc-darwin-x64@npm:14.2.5": + version: 14.2.5 + resolution: "@next/swc-darwin-x64@npm:14.2.5" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@next/swc-linux-arm64-gnu@npm:14.1.0": - version: 14.1.0 - resolution: "@next/swc-linux-arm64-gnu@npm:14.1.0" +"@next/swc-linux-arm64-gnu@npm:14.2.5": + version: 14.2.5 + resolution: "@next/swc-linux-arm64-gnu@npm:14.2.5" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-arm64-musl@npm:14.1.0": - version: 14.1.0 - resolution: "@next/swc-linux-arm64-musl@npm:14.1.0" +"@next/swc-linux-arm64-musl@npm:14.2.5": + version: 14.2.5 + resolution: "@next/swc-linux-arm64-musl@npm:14.2.5" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@next/swc-linux-x64-gnu@npm:14.1.0": - version: 14.1.0 - resolution: "@next/swc-linux-x64-gnu@npm:14.1.0" +"@next/swc-linux-x64-gnu@npm:14.2.5": + version: 14.2.5 + resolution: "@next/swc-linux-x64-gnu@npm:14.2.5" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-x64-musl@npm:14.1.0": - version: 14.1.0 - resolution: "@next/swc-linux-x64-musl@npm:14.1.0" +"@next/swc-linux-x64-musl@npm:14.2.5": + version: 14.2.5 + resolution: "@next/swc-linux-x64-musl@npm:14.2.5" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@next/swc-win32-arm64-msvc@npm:14.1.0": - version: 14.1.0 - resolution: "@next/swc-win32-arm64-msvc@npm:14.1.0" +"@next/swc-win32-arm64-msvc@npm:14.2.5": + version: 14.2.5 + resolution: "@next/swc-win32-arm64-msvc@npm:14.2.5" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@next/swc-win32-ia32-msvc@npm:14.1.0": - version: 14.1.0 - resolution: "@next/swc-win32-ia32-msvc@npm:14.1.0" +"@next/swc-win32-ia32-msvc@npm:14.2.5": + version: 14.2.5 + resolution: "@next/swc-win32-ia32-msvc@npm:14.2.5" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@next/swc-win32-x64-msvc@npm:14.1.0": - version: 14.1.0 - resolution: "@next/swc-win32-x64-msvc@npm:14.1.0" +"@next/swc-win32-x64-msvc@npm:14.2.5": + version: 14.2.5 + resolution: "@next/swc-win32-x64-msvc@npm:14.2.5" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -4896,6 +4928,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-android-arm-eabi@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.19.1" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@rollup/rollup-android-arm-eabi@npm:4.9.1": version: 4.9.1 resolution: "@rollup/rollup-android-arm-eabi@npm:4.9.1" @@ -4903,6 +4942,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-android-arm64@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-android-arm64@npm:4.19.1" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-android-arm64@npm:4.9.1": version: 4.9.1 resolution: "@rollup/rollup-android-arm64@npm:4.9.1" @@ -4910,6 +4956,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-darwin-arm64@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-darwin-arm64@npm:4.19.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-darwin-arm64@npm:4.9.1": version: 4.9.1 resolution: "@rollup/rollup-darwin-arm64@npm:4.9.1" @@ -4917,6 +4970,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-darwin-x64@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-darwin-x64@npm:4.19.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@rollup/rollup-darwin-x64@npm:4.9.1": version: 4.9.1 resolution: "@rollup/rollup-darwin-x64@npm:4.9.1" @@ -4924,6 +4984,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm-gnueabihf@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.19.1" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-arm-gnueabihf@npm:4.9.1": version: 4.9.1 resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.9.1" @@ -4931,6 +4998,20 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm-musleabihf@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.19.1" + conditions: os=linux & cpu=arm & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-gnu@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.19.1" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-arm64-gnu@npm:4.9.1": version: 4.9.1 resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.9.1" @@ -4938,6 +5019,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm64-musl@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.19.1" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-arm64-musl@npm:4.9.1": version: 4.9.1 resolution: "@rollup/rollup-linux-arm64-musl@npm:4.9.1" @@ -4945,6 +5033,20 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-powerpc64le-gnu@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.19.1" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-riscv64-gnu@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.19.1" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-riscv64-gnu@npm:4.9.1": version: 4.9.1 resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.9.1" @@ -4952,6 +5054,20 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-s390x-gnu@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.19.1" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-gnu@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.19.1" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-x64-gnu@npm:4.9.1": version: 4.9.1 resolution: "@rollup/rollup-linux-x64-gnu@npm:4.9.1" @@ -4959,6 +5075,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-x64-musl@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.19.1" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-x64-musl@npm:4.9.1": version: 4.9.1 resolution: "@rollup/rollup-linux-x64-musl@npm:4.9.1" @@ -4966,6 +5089,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-arm64-msvc@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.19.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-win32-arm64-msvc@npm:4.9.1": version: 4.9.1 resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.9.1" @@ -4973,6 +5103,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-ia32-msvc@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.19.1" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@rollup/rollup-win32-ia32-msvc@npm:4.9.1": version: 4.9.1 resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.9.1" @@ -4980,6 +5117,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-x64-msvc@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.19.1" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@rollup/rollup-win32-x64-msvc@npm:4.9.1": version: 4.9.1 resolution: "@rollup/rollup-win32-x64-msvc@npm:4.9.1" @@ -5206,7 +5350,7 @@ __metadata: rehype-slug: "npm:^6.0.0" ts-dedent: "npm:^2.0.0" typescript: "npm:^5.3.2" - vite: "npm:^4.0.4" + vite: "npm:^5.0.13" peerDependencies: storybook: "workspace:^" languageName: unknown @@ -5287,7 +5431,7 @@ __metadata: version: 0.0.0-use.local resolution: "@storybook/addon-links@workspace:addons/links" dependencies: - "@storybook/csf": "npm:0.1.11" + "@storybook/csf": "npm:^0.1.11" "@storybook/global": "npm:^5.0.0" fs-extra: "npm:^11.1.0" ts-dedent: "npm:^2.0.0" @@ -5514,7 +5658,7 @@ __metadata: resolution: "@storybook/blocks@workspace:lib/blocks" dependencies: "@storybook/addon-actions": "workspace:*" - "@storybook/csf": "npm:0.1.11" + "@storybook/csf": "npm:^0.1.11" "@storybook/global": "npm:^5.0.0" "@storybook/icons": "npm:^1.2.5" "@storybook/react": "workspace:*" @@ -5570,7 +5714,7 @@ __metadata: slash: "npm:^5.0.0" ts-dedent: "npm:^2.0.0" typescript: "npm:^5.3.2" - vite: "npm:^4.0.4" + vite: "npm:^5.0.13" peerDependencies: "@preact/preset-vite": "*" storybook: "workspace:^" @@ -5621,7 +5765,7 @@ __metadata: util: "npm:^0.12.4" util-deprecate: "npm:^1.0.2" webpack: "npm:5" - webpack-dev-middleware: "npm:^6.1.2" + webpack-dev-middleware: "npm:^7.1.0" webpack-hot-middleware: "npm:^2.25.1" webpack-virtual-modules: "npm:^0.6.0" peerDependencies: @@ -5667,7 +5811,7 @@ __metadata: "@babel/preset-env": "npm:^7.24.4" "@babel/types": "npm:^7.24.0" "@storybook/core": "workspace:*" - "@storybook/csf": "npm:0.1.11" + "@storybook/csf": "npm:^0.1.11" "@types/cross-spawn": "npm:^6.0.2" "@types/jscodeshift": "npm:^0.11.10" ansi-regex: "npm:^6.0.1" @@ -5761,8 +5905,8 @@ __metadata: "@radix-ui/react-dialog": "npm:^1.0.5" "@radix-ui/react-scroll-area": "npm:^1.0.5" "@radix-ui/react-slot": "npm:^1.0.2" - "@storybook/csf": "npm:0.1.11" - "@storybook/docs-mdx": "npm:4.0.0-next.0" + "@storybook/csf": "npm:^0.1.11" + "@storybook/docs-mdx": "npm:4.0.0-next.1" "@storybook/global": "npm:^5.0.0" "@storybook/icons": "npm:^1.2.5" "@tanstack/react-virtual": "npm:^3.3.0" @@ -5874,7 +6018,7 @@ __metadata: use-resize-observer: "npm:^9.1.0" util: "npm:^0.12.4" watchpack: "npm:^2.2.0" - ws: "npm:^8.2.3" + ws: "npm:^8.17.1" languageName: unknown linkType: soft @@ -5897,15 +6041,6 @@ __metadata: languageName: unknown linkType: soft -"@storybook/csf@npm:0.1.11": - version: 0.1.11 - resolution: "@storybook/csf@npm:0.1.11" - dependencies: - type-fest: "npm:^2.19.0" - checksum: 10c0/c5329fc13e7d762049b5c91df1bc1c0e510a1a898c401b72b68f1ff64139a85ab64a92f8e681d2fcb226c0a4a55d0f23b569b2bdb517e0f067bd05ea46228356 - languageName: node - linkType: hard - "@storybook/csf@npm:^0.0.1": version: 0.0.1 resolution: "@storybook/csf@npm:0.0.1" @@ -5915,12 +6050,21 @@ __metadata: languageName: node linkType: hard -"@storybook/docs-mdx@npm:4.0.0-next.0": - version: 4.0.0-next.0 - resolution: "@storybook/docs-mdx@npm:4.0.0-next.0" +"@storybook/csf@npm:^0.1.11": + version: 0.1.11 + resolution: "@storybook/csf@npm:0.1.11" + dependencies: + type-fest: "npm:^2.19.0" + checksum: 10c0/c5329fc13e7d762049b5c91df1bc1c0e510a1a898c401b72b68f1ff64139a85ab64a92f8e681d2fcb226c0a4a55d0f23b569b2bdb517e0f067bd05ea46228356 + languageName: node + linkType: hard + +"@storybook/docs-mdx@npm:4.0.0-next.1": + version: 4.0.0-next.1 + resolution: "@storybook/docs-mdx@npm:4.0.0-next.1" dependencies: acorn: "npm:^8.12.1" - checksum: 10c0/6253361e4e3c6c716c4f4c8cc30c082bcdab66b35b30183f6574d94720d875e28927916be8bda0bff4987090c3e50d348ca898160b1812a90c5afa845400414e + checksum: 10c0/8779279014a0a48c00d5884d310b3ca7828a49057c7403371e4eaf0fd053d8c93a412084cbbd6e5ea65e509e27f96752e8de7dadacdfa89198158b8b10deabdc languageName: node linkType: hard @@ -6118,10 +6262,10 @@ __metadata: fs-extra: "npm:^11.1.0" image-size: "npm:^1.0.0" loader-utils: "npm:^3.2.1" - next: "npm:^14.1.0" + next: "npm:^14.1.1" node-polyfill-webpack-plugin: "npm:^2.0.1" pnp-webpack-plugin: "npm:^1.7.0" - postcss: "npm:^8.4.38" + postcss: "npm:^8.4.40" postcss-loader: "npm:^8.1.1" react-refresh: "npm:^0.14.0" resolve-url-loader: "npm:^5.0.0" @@ -6134,7 +6278,7 @@ __metadata: tsconfig-paths: "npm:^4.0.0" tsconfig-paths-webpack-plugin: "npm:^4.0.1" typescript: "npm:^5.3.2" - webpack: "npm:^5.65.0" + webpack: "npm:^5.93.0" peerDependencies: next: ^13.5.0 || ^14.0.0 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta @@ -6168,7 +6312,7 @@ __metadata: "@storybook/preact": "workspace:*" "@types/node": "npm:^18.0.0" typescript: "npm:^5.3.2" - vite: "npm:^4.0.0" + vite: "npm:^5.0.13" peerDependencies: preact: ">=10" storybook: "workspace:^" @@ -6400,7 +6544,7 @@ __metadata: resolve: "npm:^1.22.8" tsconfig-paths: "npm:^4.2.0" typescript: "npm:^5.3.2" - vite: "npm:^4.0.0" + vite: "npm:^5.0.13" peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta @@ -6507,7 +6651,7 @@ __metadata: "@storybook/codemod": "workspace:*" "@storybook/core": "workspace:*" "@storybook/core-webpack": "workspace:*" - "@storybook/csf": "npm:0.1.11" + "@storybook/csf": "npm:^0.1.11" "@storybook/csf-plugin": "workspace:*" "@storybook/ember": "workspace:*" "@storybook/eslint-config-storybook": "npm:^4.0.0" @@ -6594,8 +6738,8 @@ __metadata: ts-dedent: "npm:^2.0.0" typescript: "npm:^5.4.3" util: "npm:^0.12.4" - vite: "npm:^4.0.0" - vitest: "npm:^1.2.2" + vite: "npm:^5.0.13" + vitest: "npm:^1.6.0" wait-on: "npm:^7.0.1" dependenciesMeta: ejs: @@ -6643,7 +6787,7 @@ __metadata: resolution: "@storybook/server@workspace:renderers/server" dependencies: "@storybook/components": "workspace:^" - "@storybook/csf": "npm:0.1.11" + "@storybook/csf": "npm:^0.1.11" "@storybook/global": "npm:^5.0.0" "@storybook/manager-api": "workspace:^" "@storybook/preview-api": "workspace:^" @@ -6662,7 +6806,7 @@ __metadata: version: 0.0.0-use.local resolution: "@storybook/source-loader@workspace:lib/source-loader" dependencies: - "@storybook/csf": "npm:0.1.11" + "@storybook/csf": "npm:^0.1.11" estraverse: "npm:^5.2.0" lodash: "npm:^4.17.21" prettier: "npm:^3.1.1" @@ -6687,7 +6831,7 @@ __metadata: sveltedoc-parser: "npm:^4.2.1" ts-dedent: "npm:^2.2.0" typescript: "npm:^4.9.4 || ^5.0.0" - vite: "npm:^4.0.0" + vite: "npm:^5.0.13" peerDependencies: "@sveltejs/vite-plugin-svelte": ^2.0.0 || ^3.0.0 storybook: "workspace:^" @@ -6749,7 +6893,7 @@ __metadata: "@storybook/svelte-vite": "workspace:*" "@types/node": "npm:^18.0.0" typescript: "npm:^5.3.2" - vite: "npm:^4.0.0" + vite: "npm:^5.0.13" peerDependencies: storybook: "workspace:^" svelte: ^4.0.0 || ^5.0.0-next.65 @@ -6769,7 +6913,7 @@ __metadata: version: 0.0.0-use.local resolution: "@storybook/test@workspace:lib/test" dependencies: - "@storybook/csf": "npm:0.1.11" + "@storybook/csf": "npm:^0.1.11" "@storybook/instrumenter": "workspace:*" "@testing-library/dom": "npm:10.1.0" "@testing-library/jest-dom": "npm:6.4.5" @@ -6825,7 +6969,7 @@ __metadata: find-package-json: "npm:^1.2.0" magic-string: "npm:^0.30.0" typescript: "npm:^5.3.2" - vite: "npm:^4.0.0" + vite: "npm:^5.0.13" vue-component-meta: "npm:^2.0.0" vue-docgen-api: "npm:^4.75.1" peerDependencies: @@ -6962,12 +7106,20 @@ __metadata: languageName: node linkType: hard -"@swc/helpers@npm:0.5.2": - version: 0.5.2 - resolution: "@swc/helpers@npm:0.5.2" +"@swc/counter@npm:^0.1.3": + version: 0.1.3 + resolution: "@swc/counter@npm:0.1.3" + checksum: 10c0/8424f60f6bf8694cfd2a9bca45845bce29f26105cda8cf19cdb9fd3e78dc6338699e4db77a89ae449260bafa1cc6bec307e81e7fb96dbf7dcfce0eea55151356 + languageName: node + linkType: hard + +"@swc/helpers@npm:0.5.5": + version: 0.5.5 + resolution: "@swc/helpers@npm:0.5.5" dependencies: + "@swc/counter": "npm:^0.1.3" tslib: "npm:^2.4.0" - checksum: 10c0/b6fa49bcf6c00571d0eb7837b163f8609960d4d77538160585e27ed167361e9776bd6e5eb9646ffac2fb4d43c58df9ca50dab9d96ab097e6591bc82a75fd1164 + checksum: 10c0/21a9b9cfe7e00865f9c9f3eb4c1cc5b397143464f7abee76a2c5366e591e06b0155b5aac93fe8269ef8d548df253f6fd931e9ddfc0fd12efd405f90f45506e7d languageName: node linkType: hard @@ -7437,7 +7589,7 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:*, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.1, @types/estree@npm:^1.0.5": +"@types/estree@npm:*, @types/estree@npm:1.0.5, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.1, @types/estree@npm:^1.0.5": version: 1.0.5 resolution: "@types/estree@npm:1.0.5" checksum: 10c0/b3b0e334288ddb407c7b3357ca67dbee75ee22db242ca7c56fe27db4e1a31989cb8af48a84dd401deb787fe10cc6b2ab1ee82dc4783be87ededbe3d53c79c70d @@ -8488,34 +8640,25 @@ __metadata: languageName: node linkType: hard -"@vitest/runner@npm:1.2.2": - version: 1.2.2 - resolution: "@vitest/runner@npm:1.2.2" +"@vitest/runner@npm:1.6.0": + version: 1.6.0 + resolution: "@vitest/runner@npm:1.6.0" dependencies: - "@vitest/utils": "npm:1.2.2" + "@vitest/utils": "npm:1.6.0" p-limit: "npm:^5.0.0" pathe: "npm:^1.1.1" - checksum: 10c0/25a9c03cca5b40738fe606757b14ee9d60d25193115b4674e3cc402c2b2c3844d234902d48bfa7646cb205455ea27891fef96733e033a570b85fe74ed29ff81c + checksum: 10c0/27d67fa51f40effe0e41ee5f26563c12c0ef9a96161f806036f02ea5eb9980c5cdf305a70673942e7a1e3d472d4d7feb40093ae93024ef1ccc40637fc65b1d2f languageName: node linkType: hard -"@vitest/snapshot@npm:1.2.2": - version: 1.2.2 - resolution: "@vitest/snapshot@npm:1.2.2" +"@vitest/snapshot@npm:1.6.0": + version: 1.6.0 + resolution: "@vitest/snapshot@npm:1.6.0" dependencies: magic-string: "npm:^0.30.5" pathe: "npm:^1.1.1" pretty-format: "npm:^29.7.0" - checksum: 10c0/0f8a69a289aa6466c7dd56f8327190d56a0bc7ad10412127de001c94784f6dba5e5bccb757def21f565f4efa3e00c307b92e8b6c302f11fc57889b743ba18a95 - languageName: node - linkType: hard - -"@vitest/spy@npm:1.2.2": - version: 1.2.2 - resolution: "@vitest/spy@npm:1.2.2" - dependencies: - tinyspy: "npm:^2.2.0" - checksum: 10c0/5480048d26c0d82b524317552fbdcc05fed6ea626d887620647826453a344798a360f2a75af477512a1569b1b6c918eae62338e8b35575f875fc2d7ef51419f3 + checksum: 10c0/be027fd268d524589ff50c5fad7b4faa1ac5742b59ac6c1dc6f5a3930aad553560e6d8775e90ac4dfae4be746fc732a6f134ba95606a1519707ce70db3a772a5 languageName: node linkType: hard @@ -8528,18 +8671,6 @@ __metadata: languageName: node linkType: hard -"@vitest/utils@npm:1.2.2": - version: 1.2.2 - resolution: "@vitest/utils@npm:1.2.2" - dependencies: - diff-sequences: "npm:^29.6.3" - estree-walker: "npm:^3.0.3" - loupe: "npm:^2.3.7" - pretty-format: "npm:^29.7.0" - checksum: 10c0/32449cb7eca8ecea56e0fce280c9770f65fa6b60bbba73be06ca2891096818899b4b3220bd3c815df8beb4266034db394fcf235e4de8959cce686b8b360948d1 - languageName: node - linkType: hard - "@vitest/utils@npm:1.6.0, @vitest/utils@npm:^1.3.1": version: 1.6.0 resolution: "@vitest/utils@npm:1.6.0" @@ -8979,6 +9110,16 @@ __metadata: languageName: node linkType: hard +"@webassemblyjs/ast@npm:1.12.1, @webassemblyjs/ast@npm:^1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/ast@npm:1.12.1" + dependencies: + "@webassemblyjs/helper-numbers": "npm:1.11.6" + "@webassemblyjs/helper-wasm-bytecode": "npm:1.11.6" + checksum: 10c0/ba7f2b96c6e67e249df6156d02c69eb5f1bd18d5005303cdc42accb053bebbbde673826e54db0437c9748e97abd218366a1d13fa46859b23cde611b6b409998c + languageName: node + linkType: hard + "@webassemblyjs/floating-point-hex-parser@npm:1.11.6": version: 1.11.6 resolution: "@webassemblyjs/floating-point-hex-parser@npm:1.11.6" @@ -9000,6 +9141,13 @@ __metadata: languageName: node linkType: hard +"@webassemblyjs/helper-buffer@npm:1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/helper-buffer@npm:1.12.1" + checksum: 10c0/0270724afb4601237410f7fd845ab58ccda1d5456a8783aadfb16eaaf3f2c9610c28e4a5bcb6ad880cde5183c82f7f116d5ccfc2310502439d33f14b6888b48a + languageName: node + linkType: hard + "@webassemblyjs/helper-numbers@npm:1.11.6": version: 1.11.6 resolution: "@webassemblyjs/helper-numbers@npm:1.11.6" @@ -9030,6 +9178,18 @@ __metadata: languageName: node linkType: hard +"@webassemblyjs/helper-wasm-section@npm:1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/helper-wasm-section@npm:1.12.1" + dependencies: + "@webassemblyjs/ast": "npm:1.12.1" + "@webassemblyjs/helper-buffer": "npm:1.12.1" + "@webassemblyjs/helper-wasm-bytecode": "npm:1.11.6" + "@webassemblyjs/wasm-gen": "npm:1.12.1" + checksum: 10c0/0546350724d285ae3c26e6fc444be4c3b5fb824f3be0ec8ceb474179dc3f4430336dd2e36a44b3e3a1a6815960e5eec98cd9b3a8ec66dc53d86daedd3296a6a2 + languageName: node + linkType: hard + "@webassemblyjs/ieee754@npm:1.11.6": version: 1.11.6 resolution: "@webassemblyjs/ieee754@npm:1.11.6" @@ -9071,6 +9231,22 @@ __metadata: languageName: node linkType: hard +"@webassemblyjs/wasm-edit@npm:^1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/wasm-edit@npm:1.12.1" + dependencies: + "@webassemblyjs/ast": "npm:1.12.1" + "@webassemblyjs/helper-buffer": "npm:1.12.1" + "@webassemblyjs/helper-wasm-bytecode": "npm:1.11.6" + "@webassemblyjs/helper-wasm-section": "npm:1.12.1" + "@webassemblyjs/wasm-gen": "npm:1.12.1" + "@webassemblyjs/wasm-opt": "npm:1.12.1" + "@webassemblyjs/wasm-parser": "npm:1.12.1" + "@webassemblyjs/wast-printer": "npm:1.12.1" + checksum: 10c0/972f5e6c522890743999e0ed45260aae728098801c6128856b310dd21f1ee63435fc7b518e30e0ba1cdafd0d1e38275829c1e4451c3536a1d9e726e07a5bba0b + languageName: node + linkType: hard + "@webassemblyjs/wasm-gen@npm:1.11.6": version: 1.11.6 resolution: "@webassemblyjs/wasm-gen@npm:1.11.6" @@ -9084,6 +9260,19 @@ __metadata: languageName: node linkType: hard +"@webassemblyjs/wasm-gen@npm:1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/wasm-gen@npm:1.12.1" + dependencies: + "@webassemblyjs/ast": "npm:1.12.1" + "@webassemblyjs/helper-wasm-bytecode": "npm:1.11.6" + "@webassemblyjs/ieee754": "npm:1.11.6" + "@webassemblyjs/leb128": "npm:1.11.6" + "@webassemblyjs/utf8": "npm:1.11.6" + checksum: 10c0/1e257288177af9fa34c69cab94f4d9036ebed611f77f3897c988874e75182eeeec759c79b89a7a49dd24624fc2d3d48d5580b62b67c4a1c9bfbdcd266b281c16 + languageName: node + linkType: hard + "@webassemblyjs/wasm-opt@npm:1.11.6": version: 1.11.6 resolution: "@webassemblyjs/wasm-opt@npm:1.11.6" @@ -9096,6 +9285,18 @@ __metadata: languageName: node linkType: hard +"@webassemblyjs/wasm-opt@npm:1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/wasm-opt@npm:1.12.1" + dependencies: + "@webassemblyjs/ast": "npm:1.12.1" + "@webassemblyjs/helper-buffer": "npm:1.12.1" + "@webassemblyjs/wasm-gen": "npm:1.12.1" + "@webassemblyjs/wasm-parser": "npm:1.12.1" + checksum: 10c0/992a45e1f1871033c36987459436ab4e6430642ca49328e6e32a13de9106fe69ae6c0ac27d7050efd76851e502d11cd1ac0e06b55655dfa889ad82f11a2712fb + languageName: node + linkType: hard + "@webassemblyjs/wasm-parser@npm:1.11.6, @webassemblyjs/wasm-parser@npm:^1.11.5": version: 1.11.6 resolution: "@webassemblyjs/wasm-parser@npm:1.11.6" @@ -9110,6 +9311,20 @@ __metadata: languageName: node linkType: hard +"@webassemblyjs/wasm-parser@npm:1.12.1, @webassemblyjs/wasm-parser@npm:^1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/wasm-parser@npm:1.12.1" + dependencies: + "@webassemblyjs/ast": "npm:1.12.1" + "@webassemblyjs/helper-api-error": "npm:1.11.6" + "@webassemblyjs/helper-wasm-bytecode": "npm:1.11.6" + "@webassemblyjs/ieee754": "npm:1.11.6" + "@webassemblyjs/leb128": "npm:1.11.6" + "@webassemblyjs/utf8": "npm:1.11.6" + checksum: 10c0/e85cec1acad07e5eb65b92d37c8e6ca09c6ca50d7ca58803a1532b452c7321050a0328c49810c337cc2dfd100c5326a54d5ebd1aa5c339ebe6ef10c250323a0e + languageName: node + linkType: hard + "@webassemblyjs/wast-printer@npm:1.11.6": version: 1.11.6 resolution: "@webassemblyjs/wast-printer@npm:1.11.6" @@ -9120,6 +9335,16 @@ __metadata: languageName: node linkType: hard +"@webassemblyjs/wast-printer@npm:1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/wast-printer@npm:1.12.1" + dependencies: + "@webassemblyjs/ast": "npm:1.12.1" + "@xtuc/long": "npm:4.2.2" + checksum: 10c0/39bf746eb7a79aa69953f194943bbc43bebae98bd7cadd4d8bc8c0df470ca6bf9d2b789effaa180e900fab4e2691983c1f7d41571458bd2a26267f2f0c73705a + languageName: node + linkType: hard + "@xtuc/ieee754@npm:^1.2.0": version: 1.2.0 resolution: "@xtuc/ieee754@npm:1.2.0" @@ -9235,6 +9460,15 @@ __metadata: languageName: node linkType: hard +"acorn-import-attributes@npm:^1.9.5": + version: 1.9.5 + resolution: "acorn-import-attributes@npm:1.9.5" + peerDependencies: + acorn: ^8 + checksum: 10c0/5926eaaead2326d5a86f322ff1b617b0f698aa61dc719a5baa0e9d955c9885cc71febac3fb5bacff71bbf2c4f9c12db2056883c68c53eb962c048b952e1e013d + languageName: node + linkType: hard + "acorn-jsx@npm:^5.0.0, acorn-jsx@npm:^5.3.1, acorn-jsx@npm:^5.3.2": version: 5.3.2 resolution: "acorn-jsx@npm:5.3.2" @@ -13346,6 +13580,16 @@ __metadata: languageName: node linkType: hard +"enhanced-resolve@npm:^5.17.0": + version: 5.17.1 + resolution: "enhanced-resolve@npm:5.17.1" + dependencies: + graceful-fs: "npm:^4.2.4" + tapable: "npm:^2.2.0" + checksum: 10c0/81a0515675eca17efdba2cf5bad87abc91a528fc1191aad50e275e74f045b41506167d420099022da7181c8d787170ea41e4a11a0b10b7a16f6237daecb15370 + languageName: node + linkType: hard + "enquirer@npm:^2.3.5": version: 2.4.1 resolution: "enquirer@npm:2.4.1" @@ -15077,12 +15321,12 @@ __metadata: linkType: hard "follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.15.4": - version: 1.15.5 - resolution: "follow-redirects@npm:1.15.5" + version: 1.15.6 + resolution: "follow-redirects@npm:1.15.6" peerDependenciesMeta: debug: optional: true - checksum: 10c0/418d71688ceaf109dfd6f85f747a0c75de30afe43a294caa211def77f02ef19865b547dfb73fde82b751e1cc507c06c754120b848fe5a7400b0a669766df7615 + checksum: 10c0/9ff767f0d7be6aa6870c82ac79cf0368cd73e01bbc00e9eb1c2a16fbb198ec105e3c9b6628bb98e9f3ac66fe29a957b9645bcb9a490bb7aa0d35f908b6b85071 languageName: node linkType: hard @@ -16687,6 +16931,13 @@ __metadata: languageName: node linkType: hard +"hyperdyperid@npm:^1.2.0": + version: 1.2.0 + resolution: "hyperdyperid@npm:1.2.0" + checksum: 10c0/885ba3177c7181d315a856ee9c0005ff8eb5dcb1ce9e9d61be70987895d934d84686c37c981cceeb53216d4c9c15c1cc25f1804e84cc6a74a16993c5d7fd0893 + languageName: node + linkType: hard + "hyperlinker@npm:^1.0.0": version: 1.0.0 resolution: "hyperlinker@npm:1.0.0" @@ -17843,6 +18094,13 @@ __metadata: languageName: node linkType: hard +"js-tokens@npm:^9.0.0": + version: 9.0.0 + resolution: "js-tokens@npm:9.0.0" + checksum: 10c0/4ad1c12f47b8c8b2a3a99e29ef338c1385c7b7442198a425f3463f3537384dab6032012791bfc2f056ea5ecdb06b1ed4f70e11a3ab3f388d3dcebfe16a52b27d + languageName: node + linkType: hard + "js-yaml@npm:4.1.0, js-yaml@npm:^4.1.0": version: 4.1.0 resolution: "js-yaml@npm:4.1.0" @@ -19425,6 +19683,18 @@ __metadata: languageName: node linkType: hard +"memfs@npm:^4.6.0": + version: 4.11.0 + resolution: "memfs@npm:4.11.0" + dependencies: + "@jsonjoy.com/json-pack": "npm:^1.0.3" + "@jsonjoy.com/util": "npm:^1.3.0" + tree-dump: "npm:^1.0.1" + tslib: "npm:^2.0.0" + checksum: 10c0/2424dfe2bcd40e6935b46a22e90256a0ca3c5c64546aa4e9fdac318be87010625a512d24ee32a4f910c3f0a077d1637d2dcf25e1670c4e49474160c5f988a1e9 + languageName: node + linkType: hard + "memoizerific@npm:^1.11.3": version: 1.11.3 resolution: "memoizerific@npm:1.11.3" @@ -20661,21 +20931,21 @@ __metadata: languageName: node linkType: hard -"next@npm:^14.1.0": - version: 14.1.0 - resolution: "next@npm:14.1.0" +"next@npm:^14.1.1": + version: 14.2.5 + resolution: "next@npm:14.2.5" dependencies: - "@next/env": "npm:14.1.0" - "@next/swc-darwin-arm64": "npm:14.1.0" - "@next/swc-darwin-x64": "npm:14.1.0" - "@next/swc-linux-arm64-gnu": "npm:14.1.0" - "@next/swc-linux-arm64-musl": "npm:14.1.0" - "@next/swc-linux-x64-gnu": "npm:14.1.0" - "@next/swc-linux-x64-musl": "npm:14.1.0" - "@next/swc-win32-arm64-msvc": "npm:14.1.0" - "@next/swc-win32-ia32-msvc": "npm:14.1.0" - "@next/swc-win32-x64-msvc": "npm:14.1.0" - "@swc/helpers": "npm:0.5.2" + "@next/env": "npm:14.2.5" + "@next/swc-darwin-arm64": "npm:14.2.5" + "@next/swc-darwin-x64": "npm:14.2.5" + "@next/swc-linux-arm64-gnu": "npm:14.2.5" + "@next/swc-linux-arm64-musl": "npm:14.2.5" + "@next/swc-linux-x64-gnu": "npm:14.2.5" + "@next/swc-linux-x64-musl": "npm:14.2.5" + "@next/swc-win32-arm64-msvc": "npm:14.2.5" + "@next/swc-win32-ia32-msvc": "npm:14.2.5" + "@next/swc-win32-x64-msvc": "npm:14.2.5" + "@swc/helpers": "npm:0.5.5" busboy: "npm:1.6.0" caniuse-lite: "npm:^1.0.30001579" graceful-fs: "npm:^4.2.11" @@ -20683,6 +20953,7 @@ __metadata: styled-jsx: "npm:5.1.1" peerDependencies: "@opentelemetry/api": ^1.1.0 + "@playwright/test": ^1.41.2 react: ^18.2.0 react-dom: ^18.2.0 sass: ^1.3.0 @@ -20708,11 +20979,13 @@ __metadata: peerDependenciesMeta: "@opentelemetry/api": optional: true + "@playwright/test": + optional: true sass: optional: true bin: next: dist/bin/next - checksum: 10c0/dbb1ef8d22eec29a9127d28ed46eb34f14e3f7f7b4e4b91dc96027feb4d9ead554a804275484d9a54026e6e55d632d3997561e598c1fb8e8956e77614f39765f + checksum: 10c0/8df7d8ccc1a5bab03fa50dd6656c8a6f3750e81ef0b087dc329fea9346847c3094a933a890a8e87151dc32f0bc55020b8f6386d4565856d83bcc10895d29ec08 languageName: node linkType: hard @@ -21350,7 +21623,7 @@ __metadata: languageName: node linkType: hard -"on-finished@npm:2.4.1": +"on-finished@npm:2.4.1, on-finished@npm:^2.4.1": version: 2.4.1 resolution: "on-finished@npm:2.4.1" dependencies: @@ -22443,7 +22716,7 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.2.14, postcss@npm:^8.4.23, postcss@npm:^8.4.27, postcss@npm:^8.4.32, postcss@npm:^8.4.33, postcss@npm:^8.4.35, postcss@npm:^8.4.38": +"postcss@npm:^8.2.14, postcss@npm:^8.4.23, postcss@npm:^8.4.32, postcss@npm:^8.4.33, postcss@npm:^8.4.35": version: 8.4.39 resolution: "postcss@npm:8.4.39" dependencies: @@ -22454,6 +22727,17 @@ __metadata: languageName: node linkType: hard +"postcss@npm:^8.4.39, postcss@npm:^8.4.40": + version: 8.4.40 + resolution: "postcss@npm:8.4.40" + dependencies: + nanoid: "npm:^3.3.7" + picocolors: "npm:^1.0.1" + source-map-js: "npm:^1.2.0" + checksum: 10c0/65ed67573e5443beaeb582282ff27a6be7c7fe3b4d9fa15761157616f2b97510cb1c335023c26220b005909f007337026d6e3ff092f25010b484ad484e80ea7f + languageName: node + linkType: hard + "preact@npm:^10.5.13": version: 10.19.3 resolution: "preact@npm:10.19.3" @@ -22740,19 +23024,19 @@ __metadata: languageName: node linkType: hard -"pug-code-gen@npm:^3.0.2": - version: 3.0.2 - resolution: "pug-code-gen@npm:3.0.2" +"pug-code-gen@npm:^3.0.3": + version: 3.0.3 + resolution: "pug-code-gen@npm:3.0.3" dependencies: constantinople: "npm:^4.0.1" doctypes: "npm:^1.1.0" js-stringify: "npm:^1.0.2" pug-attrs: "npm:^3.0.0" - pug-error: "npm:^2.0.0" - pug-runtime: "npm:^3.0.0" + pug-error: "npm:^2.1.0" + pug-runtime: "npm:^3.0.1" void-elements: "npm:^3.1.0" with: "npm:^7.0.0" - checksum: 10c0/a9b7f7fe1cadd16682f46b5de087f22cce1be3b48cbb7137da046b4912434143f1ffdb0e7a07e03fa961f3342f944d3eefbc1a50751f7561ae431720c29448fe + checksum: 10c0/517a93930dbc80bc7fa5f60ff324229a07cc5ab70ed9d344ce105e2fe24de68db5121c8457a9ba99cdc8d48dd18779dd34956ebfcab009b3c1c6843a3cade109 languageName: node linkType: hard @@ -22763,6 +23047,13 @@ __metadata: languageName: node linkType: hard +"pug-error@npm:^2.1.0": + version: 2.1.0 + resolution: "pug-error@npm:2.1.0" + checksum: 10c0/bbce339b17fab9890de84975c0cd8723a847bf65f35653d3ebcf77018e8ad91529d56e978ab80f4c64c9f4f07ef9e56e7a9fda3be44249c344a93ba11fccff79 + languageName: node + linkType: hard + "pug-filters@npm:^4.0.0": version: 4.0.0 resolution: "pug-filters@npm:4.0.0" @@ -22841,10 +23132,10 @@ __metadata: linkType: hard "pug@npm:^3.0.2": - version: 3.0.2 - resolution: "pug@npm:3.0.2" + version: 3.0.3 + resolution: "pug@npm:3.0.3" dependencies: - pug-code-gen: "npm:^3.0.2" + pug-code-gen: "npm:^3.0.3" pug-filters: "npm:^4.0.0" pug-lexer: "npm:^5.0.1" pug-linker: "npm:^4.0.0" @@ -22852,7 +23143,7 @@ __metadata: pug-parser: "npm:^6.0.0" pug-runtime: "npm:^3.0.1" pug-strip-comments: "npm:^2.0.0" - checksum: 10c0/1d4d33e577a59f2df50bbb75aadebe67896c93046627a7435005bda693c34cf6023d814bd424d9b06b7842b03587da5ec66baedf7c49320a697696574302120b + checksum: 10c0/bda53d3a6deea1d348cd5ab17427c77f3d74165510ad16f4fd182cc63618ad09388ecda317d17122ee890c8a68f9a54b96221fce7f44a332e463fdbb10a9d1e2 languageName: node linkType: hard @@ -24380,17 +24671,66 @@ __metadata: languageName: node linkType: hard -"rollup@npm:^3.27.1": - version: 3.29.4 - resolution: "rollup@npm:3.29.4" - dependencies: +"rollup@npm:^4.13.0": + version: 4.19.1 + resolution: "rollup@npm:4.19.1" + dependencies: + "@rollup/rollup-android-arm-eabi": "npm:4.19.1" + "@rollup/rollup-android-arm64": "npm:4.19.1" + "@rollup/rollup-darwin-arm64": "npm:4.19.1" + "@rollup/rollup-darwin-x64": "npm:4.19.1" + "@rollup/rollup-linux-arm-gnueabihf": "npm:4.19.1" + "@rollup/rollup-linux-arm-musleabihf": "npm:4.19.1" + "@rollup/rollup-linux-arm64-gnu": "npm:4.19.1" + "@rollup/rollup-linux-arm64-musl": "npm:4.19.1" + "@rollup/rollup-linux-powerpc64le-gnu": "npm:4.19.1" + "@rollup/rollup-linux-riscv64-gnu": "npm:4.19.1" + "@rollup/rollup-linux-s390x-gnu": "npm:4.19.1" + "@rollup/rollup-linux-x64-gnu": "npm:4.19.1" + "@rollup/rollup-linux-x64-musl": "npm:4.19.1" + "@rollup/rollup-win32-arm64-msvc": "npm:4.19.1" + "@rollup/rollup-win32-ia32-msvc": "npm:4.19.1" + "@rollup/rollup-win32-x64-msvc": "npm:4.19.1" + "@types/estree": "npm:1.0.5" fsevents: "npm:~2.3.2" dependenciesMeta: + "@rollup/rollup-android-arm-eabi": + optional: true + "@rollup/rollup-android-arm64": + optional: true + "@rollup/rollup-darwin-arm64": + optional: true + "@rollup/rollup-darwin-x64": + optional: true + "@rollup/rollup-linux-arm-gnueabihf": + optional: true + "@rollup/rollup-linux-arm-musleabihf": + optional: true + "@rollup/rollup-linux-arm64-gnu": + optional: true + "@rollup/rollup-linux-arm64-musl": + optional: true + "@rollup/rollup-linux-powerpc64le-gnu": + optional: true + "@rollup/rollup-linux-riscv64-gnu": + optional: true + "@rollup/rollup-linux-s390x-gnu": + optional: true + "@rollup/rollup-linux-x64-gnu": + optional: true + "@rollup/rollup-linux-x64-musl": + optional: true + "@rollup/rollup-win32-arm64-msvc": + optional: true + "@rollup/rollup-win32-ia32-msvc": + optional: true + "@rollup/rollup-win32-x64-msvc": + optional: true fsevents: optional: true bin: rollup: dist/bin/rollup - checksum: 10c0/65eddf84bf389ea8e4d4c1614b1c6a298d08f8ae785c0c087e723a879190c8aaddbab4aa3b8a0524551b9036750c9f8bfea27b377798accfd2ba5084ceff5aaa + checksum: 10c0/2e526c38b4bcb22a058cf95e40c8c105a86f27d582c677c47df9315a17b18e75c772edc0773ca4d12d58ceca254bb5d63d4172041f6fd9f01e1a613d8bba6d09 languageName: node linkType: hard @@ -25849,12 +26189,12 @@ __metadata: languageName: node linkType: hard -"strip-literal@npm:^1.3.0": - version: 1.3.0 - resolution: "strip-literal@npm:1.3.0" +"strip-literal@npm:^2.0.0": + version: 2.1.0 + resolution: "strip-literal@npm:2.1.0" dependencies: - acorn: "npm:^8.10.0" - checksum: 10c0/3c0c9ee41eb346e827eede61ef288457f53df30e3e6ff8b94fa81b636933b0c13ca4ea5c97d00a10d72d04be326da99ac819f8769f0c6407ba8177c98344a916 + js-tokens: "npm:^9.0.0" + checksum: 10c0/bc8b8c8346125ae3c20fcdaf12e10a498ff85baf6f69597b4ab2b5fbf2e58cfd2827f1a44f83606b852da99a5f6c8279770046ddea974c510c17c98934c9cc24 languageName: node linkType: hard @@ -26219,8 +26559,8 @@ __metadata: linkType: hard "tar@npm:^6.1.11, tar@npm:^6.1.2, tar@npm:^6.2.0": - version: 6.2.0 - resolution: "tar@npm:6.2.0" + version: 6.2.1 + resolution: "tar@npm:6.2.1" dependencies: chownr: "npm:^2.0.0" fs-minipass: "npm:^2.0.0" @@ -26228,7 +26568,7 @@ __metadata: minizlib: "npm:^2.1.1" mkdirp: "npm:^1.0.3" yallist: "npm:^4.0.0" - checksum: 10c0/02ca064a1a6b4521fef88c07d389ac0936730091f8c02d30ea60d472e0378768e870769ab9e986d87807bfee5654359cf29ff4372746cc65e30cbddc352660d8 + checksum: 10c0/a5eca3eb50bc11552d453488344e6507156b9193efd7635e98e867fab275d527af53d8866e2370cd09dfe74378a18111622ace35af6a608e5223a7d27fe99537 languageName: node linkType: hard @@ -26343,6 +26683,15 @@ __metadata: languageName: node linkType: hard +"thingies@npm:^1.20.0": + version: 1.21.0 + resolution: "thingies@npm:1.21.0" + peerDependencies: + tslib: ^2 + checksum: 10c0/7570ee855aecb73185a672ecf3eb1c287a6512bf5476449388433b2d4debcf78100bc8bfd439b0edd38d2bc3bfb8341de5ce85b8557dec66d0f27b962c9a8bc1 + languageName: node + linkType: hard + "through2@npm:^2.0.3": version: 2.0.5 resolution: "through2@npm:2.0.5" @@ -26397,10 +26746,10 @@ __metadata: languageName: node linkType: hard -"tinypool@npm:^0.8.2": - version: 0.8.2 - resolution: "tinypool@npm:0.8.2" - checksum: 10c0/8998626614172fc37c394e9a14e701dc437727fc6525488a4d4fd42044a4b2b59d6f076d750cbf5c699f79c58dd4e40599ab09e2f1ae0df4b23516b98c9c3055 +"tinypool@npm:^0.8.3": + version: 0.8.4 + resolution: "tinypool@npm:0.8.4" + checksum: 10c0/779c790adcb0316a45359652f4b025958c1dff5a82460fe49f553c864309b12ad732c8288be52f852973bc76317f5e7b3598878aee0beb8a33322c0e72c4a66c languageName: node linkType: hard @@ -26540,6 +26889,15 @@ __metadata: languageName: node linkType: hard +"tree-dump@npm:^1.0.1": + version: 1.0.2 + resolution: "tree-dump@npm:1.0.2" + peerDependencies: + tslib: 2 + checksum: 10c0/d1d180764e9c691b28332dbd74226c6b6af361dfb1e134bb11e60e17cb11c215894adee50ffc578da5dcf546006693947be8b6665eb1269b56e2f534926f1c1f + languageName: node + linkType: hard + "tree-kill@npm:1.2.2": version: 1.2.2 resolution: "tree-kill@npm:1.2.2" @@ -27797,9 +28155,9 @@ __metadata: languageName: node linkType: hard -"vite-node@npm:1.2.2": - version: 1.2.2 - resolution: "vite-node@npm:1.2.2" +"vite-node@npm:1.6.0": + version: 1.6.0 + resolution: "vite-node@npm:1.6.0" dependencies: cac: "npm:^6.7.14" debug: "npm:^4.3.4" @@ -27808,7 +28166,7 @@ __metadata: vite: "npm:^5.0.0" bin: vite-node: vite-node.mjs - checksum: 10c0/39a5b9d9c806a012aab208eee0f59e4e12446ec19a4cf149a6459e7ff86491c289e189fda4f55a63b7e37d713f5edbda0e9efed95af4f7ebefa6d39eee093c0b + checksum: 10c0/0807e6501ac7763e0efa2b4bd484ce99fb207e92c98624c9f8999d1f6727ac026e457994260fa7fdb7060d87546d197081e46a705d05b0136a38b6f03715cbc2 languageName: node linkType: hard @@ -27852,16 +28210,16 @@ __metadata: languageName: node linkType: hard -"vite@npm:^4.0.0, vite@npm:^4.0.4": - version: 4.5.3 - resolution: "vite@npm:4.5.3" +"vite@npm:^5.0.13": + version: 5.3.5 + resolution: "vite@npm:5.3.5" dependencies: - esbuild: "npm:^0.18.10" - fsevents: "npm:~2.3.2" - postcss: "npm:^8.4.27" - rollup: "npm:^3.27.1" + esbuild: "npm:^0.21.3" + fsevents: "npm:~2.3.3" + postcss: "npm:^8.4.39" + rollup: "npm:^4.13.0" peerDependencies: - "@types/node": ">= 14" + "@types/node": ^18.0.0 || >=20.0.0 less: "*" lightningcss: ^1.21.0 sass: "*" @@ -27888,7 +28246,7 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 10c0/caeb1eecc0a8e0865782899e2f83d2993a9816562badc1c8291316d80d49b82f12038abd8cb8b8c627b6f369f58dfb25972ef4517d5e6e1b6e1bf7ee5b63a8a6 + checksum: 10c0/795c7e0dbc94b96c4a0aff0d5d4b349dd28ad8b7b70979c1010f96b4d83f7d6c1700ebd6fed91de2e021b0a3689b9abc2d8017f6dfa8c9a6ca5c7af637d6afc6 languageName: node linkType: hard @@ -27904,17 +28262,16 @@ __metadata: languageName: node linkType: hard -"vitest@npm:^1.2.2": - version: 1.2.2 - resolution: "vitest@npm:1.2.2" +"vitest@npm:^1.6.0": + version: 1.6.0 + resolution: "vitest@npm:1.6.0" dependencies: - "@vitest/expect": "npm:1.2.2" - "@vitest/runner": "npm:1.2.2" - "@vitest/snapshot": "npm:1.2.2" - "@vitest/spy": "npm:1.2.2" - "@vitest/utils": "npm:1.2.2" + "@vitest/expect": "npm:1.6.0" + "@vitest/runner": "npm:1.6.0" + "@vitest/snapshot": "npm:1.6.0" + "@vitest/spy": "npm:1.6.0" + "@vitest/utils": "npm:1.6.0" acorn-walk: "npm:^8.3.2" - cac: "npm:^6.7.14" chai: "npm:^4.3.10" debug: "npm:^4.3.4" execa: "npm:^8.0.1" @@ -27923,17 +28280,17 @@ __metadata: pathe: "npm:^1.1.1" picocolors: "npm:^1.0.0" std-env: "npm:^3.5.0" - strip-literal: "npm:^1.3.0" + strip-literal: "npm:^2.0.0" tinybench: "npm:^2.5.1" - tinypool: "npm:^0.8.2" + tinypool: "npm:^0.8.3" vite: "npm:^5.0.0" - vite-node: "npm:1.2.2" + vite-node: "npm:1.6.0" why-is-node-running: "npm:^2.2.2" peerDependencies: "@edge-runtime/vm": "*" "@types/node": ^18.0.0 || >=20.0.0 - "@vitest/browser": ^1.0.0 - "@vitest/ui": ^1.0.0 + "@vitest/browser": 1.6.0 + "@vitest/ui": 1.6.0 happy-dom: "*" jsdom: "*" peerDependenciesMeta: @@ -27951,7 +28308,7 @@ __metadata: optional: true bin: vitest: vitest.mjs - checksum: 10c0/085cb62146191b32dc98fac1a5b0de6d1c63c44cc1e7946a7d38309dd4135539432ec27b4bfad38ce79736688a0ce20d9b93f58de4ce4a41677cb3c5ca6ad980 + checksum: 10c0/065da5b8ead51eb174d93dac0cd50042ca9539856dc25e340ea905d668c41961f7e00df3e388e6c76125b2c22091db2e8465f993d0f6944daf9598d549e562e7 languageName: node linkType: hard @@ -28235,6 +28592,16 @@ __metadata: languageName: node linkType: hard +"watchpack@npm:^2.4.1": + version: 2.4.1 + resolution: "watchpack@npm:2.4.1" + dependencies: + glob-to-regexp: "npm:^0.4.1" + graceful-fs: "npm:^4.1.2" + checksum: 10c0/c694de0a61004e587a8a0fdc9cfec20ee692c52032d9ab2c2e99969a37fdab9e6e1bd3164ed506f9a13f7c83e65563d563e0d6b87358470cdb7309b83db78683 + languageName: node + linkType: hard + "wbuf@npm:^1.1.0, wbuf@npm:^1.7.3": version: 1.7.3 resolution: "wbuf@npm:1.7.3" @@ -28315,13 +28682,14 @@ __metadata: languageName: node linkType: hard -"webpack-dev-middleware@npm:^6.1.2": - version: 6.1.3 - resolution: "webpack-dev-middleware@npm:6.1.3" +"webpack-dev-middleware@npm:^7.1.0": + version: 7.3.0 + resolution: "webpack-dev-middleware@npm:7.3.0" dependencies: colorette: "npm:^2.0.10" - memfs: "npm:^3.4.12" + memfs: "npm:^4.6.0" mime-types: "npm:^2.1.31" + on-finished: "npm:^2.4.1" range-parser: "npm:^1.2.1" schema-utils: "npm:^4.0.0" peerDependencies: @@ -28329,7 +28697,7 @@ __metadata: peerDependenciesMeta: webpack: optional: true - checksum: 10c0/0f31670835f3c0f588392235a6183facf314c0dca312467254a56458142be6fee746f7f6b304f281c740364fd36f256c597ab37d87e5971633cee2f70a8cd5e7 + checksum: 10c0/03d34e1c7af3af8c98efe754ce6cfb9fe84a1f02d312bc37a77f55b8ae9525bc3ac913fc92c0143ab93a3a6377781661f07336031fcd5e6bbddccc11df9345db languageName: node linkType: hard @@ -28441,7 +28809,7 @@ __metadata: languageName: node linkType: hard -"webpack@npm:5, webpack@npm:5.90.3, webpack@npm:^5, webpack@npm:^5.65.0": +"webpack@npm:5, webpack@npm:5.90.3, webpack@npm:^5": version: 5.90.3 resolution: "webpack@npm:5.90.3" dependencies: @@ -28478,6 +28846,43 @@ __metadata: languageName: node linkType: hard +"webpack@npm:^5.93.0": + version: 5.93.0 + resolution: "webpack@npm:5.93.0" + dependencies: + "@types/eslint-scope": "npm:^3.7.3" + "@types/estree": "npm:^1.0.5" + "@webassemblyjs/ast": "npm:^1.12.1" + "@webassemblyjs/wasm-edit": "npm:^1.12.1" + "@webassemblyjs/wasm-parser": "npm:^1.12.1" + acorn: "npm:^8.7.1" + acorn-import-attributes: "npm:^1.9.5" + browserslist: "npm:^4.21.10" + chrome-trace-event: "npm:^1.0.2" + enhanced-resolve: "npm:^5.17.0" + es-module-lexer: "npm:^1.2.1" + eslint-scope: "npm:5.1.1" + events: "npm:^3.2.0" + glob-to-regexp: "npm:^0.4.1" + graceful-fs: "npm:^4.2.11" + json-parse-even-better-errors: "npm:^2.3.1" + loader-runner: "npm:^4.2.0" + mime-types: "npm:^2.1.27" + neo-async: "npm:^2.6.2" + schema-utils: "npm:^3.2.0" + tapable: "npm:^2.1.1" + terser-webpack-plugin: "npm:^5.3.10" + watchpack: "npm:^2.4.1" + webpack-sources: "npm:^3.2.3" + peerDependenciesMeta: + webpack-cli: + optional: true + bin: + webpack: bin/webpack.js + checksum: 10c0/f0c72f1325ff57a4cc461bb978e6e1296f2a7d45c9765965271aa686ccdd448512956f4d7fdcf8c164d073af046c5a0aba17ce85ea98e33e5e2bfbfe13aa5808 + languageName: node + linkType: hard + "websocket-driver@npm:>=0.5.1, websocket-driver@npm:^0.7.4": version: 0.7.4 resolution: "websocket-driver@npm:0.7.4" @@ -28754,7 +29159,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.13.0, ws@npm:^8.2.3": +"ws@npm:^8.13.0": version: 8.16.0 resolution: "ws@npm:8.16.0" peerDependencies: @@ -28769,6 +29174,21 @@ __metadata: languageName: node linkType: hard +"ws@npm:^8.17.1": + version: 8.18.0 + resolution: "ws@npm:8.18.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 10c0/25eb33aff17edcb90721ed6b0eb250976328533ad3cd1a28a274bd263682e7296a6591ff1436d6cbc50fa67463158b062f9d1122013b361cec99a05f84680e06 + languageName: node + linkType: hard + "xcase@npm:^2.0.1": version: 2.0.1 resolution: "xcase@npm:2.0.1" diff --git a/docs/_snippets/storybook-theme-example-variables.md b/docs/_snippets/storybook-theme-example-variables.md index 8fb75f792aba..0f045dc6c52e 100644 --- a/docs/_snippets/storybook-theme-example-variables.md +++ b/docs/_snippets/storybook-theme-example-variables.md @@ -1,5 +1,5 @@ ```js filename=".storybook/YourTheme.js" renderer="common" language="js" -import { create } from '@storybook/theming/create'; +import { create } from '@storybook/theming'; export default create({ base: 'light', diff --git a/docs/addons/addon-knowledge-base.mdx b/docs/addons/addon-knowledge-base.mdx index 11ebc0eec556..c2dbdb497d30 100644 --- a/docs/addons/addon-knowledge-base.mdx +++ b/docs/addons/addon-knowledge-base.mdx @@ -44,33 +44,35 @@ Addon authors can develop their UIs using any React library. But we recommend us Use the components listed below with your next addon. -| Component | Source | Story | -| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | -| Action Bar | [See component implementation](https://github.com/storybookjs/storybook/blob/main/code/ui/components/src/ActionBar/ActionBar.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-actionbar--single-item) | -| Addon Panel | [See component implementation](https://github.com/storybookjs/storybook/blob/main/code/ui/components/src/addon-panel/addon-panel.tsx) | N/A | -| Badge | [See component implementation](https://github.com/storybookjs/storybook/blob/main/code/ui/components/src/Badge/Badge.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-badge--all-badges) | -| Button | [See component implementation](https://github.com/storybookjs/storybook/blob/main/code/ui/components/src/Button/Button.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-button--all-buttons) | -| Form | [See component implementation](https://github.com/storybookjs/storybook/blob/main/code/ui/components/src/form/index.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-form-button--sizes) | -| Loader | [See component implementation](https://github.com/storybookjs/storybook/blob/main/code/ui/components/src/Loader/Loader.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-loader--progress-bar) | -| PlaceHolder | [See component implementation](https://github.com/storybookjs/storybook/blob/main/code/ui/components/src/placeholder/placeholder.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-placeholder--single-child) | -| Scroll Area | [See component implementation](https://github.com/storybookjs/storybook/blob/main/code/ui/components/src/ScrollArea/ScrollArea.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-scrollarea--vertical) | -| Space | [See component implementation](https://github.com/storybookjs/storybook/blob/main/code/ui/components/src/spaced/Spaced.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-spaced--row) | -| Syntax Highlighter | [See component implementation](https://github.com/storybookjs/storybook/blob/main/code/ui/components/src/syntaxhighlighter/syntaxhighlighter.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-syntaxhighlighter--bash) | -| Tabs | [See component implementation](https://github.com/storybookjs/storybook/blob/main/code/ui/components/src/tabs/tabs.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-tabs--stateful-static) | -| ToolBar | [See component implementation](https://github.com/storybookjs/storybook/blob/main/code/ui/components/src/bar/bar.tsx) | N/A | -| ToolTip | [See component implementation](https://github.com/storybookjs/storybook/blob/main/code/ui/components/src/tooltip/Tooltip.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-tooltip-tooltip--basic-default) | -| Zoom | [See component implementation](https://github.com/storybookjs/storybook/blob/main/code/ui/components/src/Zoom/Zoom.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-zoom--element-actual-size) | +| Component | Source | Story | +| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | +| Action Bar | [See component implementation](https://github.com/storybookjs/storybook/blob/next/code/core/src/components/components/ActionBar/ActionBar.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-actionbar--single-item) | +| Addon Panel | [See component implementation](https://github.com/storybookjs/storybook/blob/next/code/core/src/components/components/addon-panel/addon-panel.tsx) | N/A | +| Badge | [See component implementation](https://github.com/storybookjs/storybook/blob/next/code/core/src/components/components/Badge/Badge.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-badge--all-badges) | +| Button | [See component implementation](https://github.com/storybookjs/storybook/blob/next/code/core/src/components/components/Button/Button.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-button--all-buttons) | +| Form | [See component implementation](https://github.com/storybookjs/storybook/blob/next/code/core/src/components/components/form/index.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-form-button--sizes) | +| Loader | [See component implementation](https://github.com/storybookjs/storybook/blob/next/code/core/src/components/components/Loader/Loader.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-loader--progress-bar) | +| PlaceHolder | [See component implementation](https://github.com/storybookjs/storybook/blob/next/code/core/src/components/components/placeholder/placeholder.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-placeholder--single-child) | +| Scroll Area | [See component implementation](https://github.com/storybookjs/storybook/blob/next/code/core/src/components/components/ScrollArea/ScrollArea.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-scrollarea--vertical) | +| Space | [See component implementation](https://github.com/storybookjs/storybook/blob/next/code/core/src/components/components/spaced/Spaced.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-spaced--row) | +| Syntax Highlighter | [See component implementation](https://github.com/storybookjs/storybook/blob/next/code/core/src/components/components/syntaxhighlighter/syntaxhighlighter.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-syntaxhighlighter--bash) | +| Tabs | [See component implementation](https://github.com/storybookjs/storybook/blob/next/code/core/src/components/components/tabs/tabs.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-tabs--stateful-static) | +| ToolBar | [See component implementation](https://github.com/storybookjs/storybook/blob/next/code/core/src/components/components/bar/bar.tsx) | N/A | +| ToolTip | [See component implementation](https://github.com/storybookjs/storybook/blob/next/code/core/src/components/components/tooltip/Tooltip.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-tooltip-tooltip--basic-default) | +| Zoom | [See component implementation](https://github.com/storybookjs/storybook/blob/next/code/core/src/components/components/Zoom/Zoom.tsx) | [See component story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-zoom--element-actual-size) | Complementing the components, also included is a set of UI primitives. Use the content listed below as a reference for styling your addon. -| Component | Source | Story | -| ------------------------------ | -------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | -| Color Palette (see note below) | [See implementation](https://github.com/storybookjs/storybook/tree/master/code/ui/components/src/Colors) | [See story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-colorpalette--page) | -| Icon | [See implementation](https://github.com/storybookjs/storybook/blob/main/code/ui/components/src/icon/icons.tsx) | [See story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-icon--labels) | -| Typography | [See implementation](https://github.com/storybookjs/storybook/tree/master/code/ui/components/src/typography) | [See story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-typography--all) | +| Component | Source | Story | +| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | +| Color Palette (see note below) | [See implementation](https://github.com/storybookjs/storybook/tree/next/code/core/src/components/components/Colors) | [See story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-colorpalette--page) | +| Icon | [See implementation](https://github.com/storybookjs/storybook/blob/next/code/core/src/components/components/icon/icon.tsx)| [See story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-icon--labels) | +| Typography | [See implementation](https://github.com/storybookjs/storybook/tree/next/code/core/src/components/components/typography) | [See story](https://main--5a375b97f4b14f0020b0cda3.chromatic.com/?path=/story/basics-typography--all) | + The color palette implemented by `@storybook/components` is a high-level abstraction of the [`@storybook/theming`](https://github.com/storybookjs/storybook/tree/next/code/lib/theming/src) package. + ### Build system diff --git a/docs/api/main-config/main-config-build.mdx b/docs/api/main-config/main-config-build.mdx index 73d56d975273..d488fd06b0aa 100644 --- a/docs/api/main-config/main-config-build.mdx +++ b/docs/api/main-config/main-config-build.mdx @@ -31,7 +31,9 @@ Type: `TestBuildFlags` Configures Storybook's production builds for performance testing purposes by disabling certain features from the build. When running `build-storybook`, this feature is enabled by setting the `--test` [flag](../cli-options.mdx#build). - The options documented on this page are automatically enabled when the `--test` flag is provided to the `build-storybook` command. We encourage you to override these options only if you need to disable a specific feature for your project or if you are debugging a build issue. + + The options documented on this page are automatically enabled when the `--test` flag is provided to the [`storybook build`](../cli-options.mdx#build) command. We encourage you to override these options only if you need to disable a specific feature for your project or if you are debugging a build issue. + ### `test.disableBlocks` diff --git a/docs/versions/next.json b/docs/versions/next.json index 5ca4ed6ffcb7..f2daa3fb9b6b 100644 --- a/docs/versions/next.json +++ b/docs/versions/next.json @@ -1 +1 @@ -{"version":"8.3.0-alpha.0","info":{"plain":""}} +{"version":"8.3.0-alpha.2","info":{"plain":"- Addon-Interactions: Fix status in panel tab - [#28580](https://github.com/storybookjs/storybook/pull/28580), thanks @yannbf!\n- Build: Remove external overrides, use package.json as source of truth - [#28632](https://github.com/storybookjs/storybook/pull/28632), thanks @kasperpeulen!\n- CLI: Add conditional logging for manager and preview start - [#28603](https://github.com/storybookjs/storybook/pull/28603), thanks @tobiasdiez!\n- CPC: Add the globals export for manager - [#28650](https://github.com/storybookjs/storybook/pull/28650), thanks @ndelangen!\n- CPC: Correct path to the `@storybook/theming/create` alias - [#28643](https://github.com/storybookjs/storybook/pull/28643), thanks @Averethel!\n- Core: Fix manager-builder `tsconfig` to emit `react-jsx` - [#28541](https://github.com/storybookjs/storybook/pull/28541), thanks @williamhelmrath!\n- Fix: Add header for MountMustBeDestructuredError message - [#28590](https://github.com/storybookjs/storybook/pull/28590), thanks @0916dhkim!\n- Fix: Prevent iframe from capturing mouse events in composed Storybooks - [#28568](https://github.com/storybookjs/storybook/pull/28568), thanks @Vincentdevreede!\n- Onboarding: Fix code snippet when story name differs from export name - [#28649](https://github.com/storybookjs/storybook/pull/28649), thanks @ghengeveld!\n- Vue: Fix out of memory error when using vue-component-meta - [#28589](https://github.com/storybookjs/storybook/pull/28589), thanks @larsrickert!"}} diff --git a/docs/writing-docs/build-documentation.mdx b/docs/writing-docs/build-documentation.mdx index b32752fce3eb..19f052996a4d 100644 --- a/docs/writing-docs/build-documentation.mdx +++ b/docs/writing-docs/build-documentation.mdx @@ -33,7 +33,7 @@ There's some caveats to this build mode, as to the normal Storybook build: ## Publish Storybook's documentation -You can also publish your documentation, the same you would [publish](../sharing/publish-storybook.mdx) your Storybook. You can use the `--docs` flag with `build-storybook` command. We recommend as well including it as a script in your `package.json` file: +You can also publish your documentation the same you would [publish](../sharing/publish-storybook.mdx) your Storybook. You can use the `--docs` flag with the [`storybook build`](../api/cli-options.mdx#build) command. We recommend as well including it as a script in your `package.json` file: ```json { diff --git a/scripts/sandbox/generate.ts b/scripts/sandbox/generate.ts index 22c50716cc81..88871e6eec4d 100755 --- a/scripts/sandbox/generate.ts +++ b/scripts/sandbox/generate.ts @@ -45,18 +45,34 @@ const sbInit = async ( await runCommand(`${sbCliBinaryPath} init ${fullFlags.join(' ')}`, { cwd, env }, debug); }; -const withLocalRegistry = async (packageManager: JsPackageManager, action: () => Promise) => { +type LocalRegistryProps = { + packageManager: JsPackageManager; + action: () => Promise; + cwd: string; + env: Record; + debug: boolean; +}; + +const withLocalRegistry = async ({ + packageManager, + action, + cwd, + env, + debug, +}: LocalRegistryProps) => { const prevUrl = await packageManager.getRegistryURL(); let error; try { console.log(`📦 Configuring local registry: ${LOCAL_REGISTRY_URL}`); - packageManager.setRegistryURL(LOCAL_REGISTRY_URL); + // NOTE: for some reason yarn prefers the npm registry in + // local development, so always use npm + await runCommand(`npm config set registry ${LOCAL_REGISTRY_URL}`, { cwd, env }, debug); await action(); } catch (e) { error = e; } finally { console.log(`📦 Restoring registry: ${prevUrl}`); - await packageManager.setRegistryURL(prevUrl); + await runCommand(`npm config set registry ${prevUrl}`, { cwd, env }, debug); if (error) { throw error; @@ -88,14 +104,20 @@ const addStorybook = async ({ const packageManager = JsPackageManagerFactory.getPackageManager({ force: 'yarn1' }, tmpDir); if (localRegistry) { - await withLocalRegistry(packageManager, async () => { - await packageManager.addPackageResolutions({ - ...storybookVersions, - // Yarn1 Issue: https://github.com/storybookjs/storybook/issues/22431 - jackspeak: '2.1.1', - }); - - await sbInit(tmpDir, env, [...flags, '--package-manager=yarn1'], debug); + await withLocalRegistry({ + packageManager, + action: async () => { + await packageManager.addPackageResolutions({ + ...storybookVersions, + // Yarn1 Issue: https://github.com/storybookjs/storybook/issues/22431 + jackspeak: '2.1.1', + }); + + await sbInit(tmpDir, env, [...flags, '--package-manager=yarn1'], debug); + }, + cwd: tmpDir, + env, + debug, }); } else { await sbInit(tmpDir, env, [...flags, '--package-manager=yarn1'], debug); @@ -159,7 +181,7 @@ const runGenerators = async ( const baseDir = join(REPROS_DIRECTORY, dirName); const beforeDir = join(baseDir, BEFORE_DIR_NAME); try { - let flags: string[] = []; + let flags: string[] = ['--no-dev']; if (expected.renderer === '@storybook/html') flags = ['--type html']; else if (expected.renderer === '@storybook/server') flags = ['--type server']; diff --git a/scripts/tasks/test-runner-build.ts b/scripts/tasks/test-runner-build.ts index 9cecf1672120..b8249a091a49 100644 --- a/scripts/tasks/test-runner-build.ts +++ b/scripts/tasks/test-runner-build.ts @@ -18,6 +18,7 @@ export const testRunnerBuild: Task & { port: number } = { '--maxWorkers=2', '--failOnConsole', '--skipTags="test-skip"', + '--index-json', ]; await exec( diff --git a/scripts/yarn.lock b/scripts/yarn.lock index b99cb1a3a3c0..6f7e9e418ef9 100644 --- a/scripts/yarn.lock +++ b/scripts/yarn.lock @@ -33,9 +33,9 @@ __metadata: linkType: hard "@adobe/css-tools@npm:^4.0.1": - version: 4.3.1 - resolution: "@adobe/css-tools@npm:4.3.1" - checksum: 10c0/05672719b544cc0c21ae3ed0eb6349bf458e9d09457578eeeb07cf0f696469ac6417e9c9be1b129e5d6a18098a061c1db55b2275591760ef30a79822436fcbfa + version: 4.4.0 + resolution: "@adobe/css-tools@npm:4.4.0" + checksum: 10c0/d65ddc719389bf469097df80fb16a8af48a973dea4b57565789d70ac8e7ab4987e6dc0095da3ed5dc16c1b6f8960214a7590312eeda8abd543d91fd0f59e6c94 languageName: node linkType: hard @@ -1192,6 +1192,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-android-arm-eabi@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.19.1" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@rollup/rollup-android-arm64@npm:4.18.1": version: 4.18.1 resolution: "@rollup/rollup-android-arm64@npm:4.18.1" @@ -1199,6 +1206,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-android-arm64@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-android-arm64@npm:4.19.1" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-darwin-arm64@npm:4.18.1": version: 4.18.1 resolution: "@rollup/rollup-darwin-arm64@npm:4.18.1" @@ -1206,6 +1220,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-darwin-arm64@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-darwin-arm64@npm:4.19.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-darwin-x64@npm:4.18.1": version: 4.18.1 resolution: "@rollup/rollup-darwin-x64@npm:4.18.1" @@ -1213,6 +1234,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-darwin-x64@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-darwin-x64@npm:4.19.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@rollup/rollup-linux-arm-gnueabihf@npm:4.18.1": version: 4.18.1 resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.18.1" @@ -1220,6 +1248,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm-gnueabihf@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.19.1" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-arm-musleabihf@npm:4.18.1": version: 4.18.1 resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.18.1" @@ -1227,6 +1262,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm-musleabihf@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.19.1" + conditions: os=linux & cpu=arm & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-arm64-gnu@npm:4.18.1": version: 4.18.1 resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.18.1" @@ -1234,6 +1276,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm64-gnu@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.19.1" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-arm64-musl@npm:4.18.1": version: 4.18.1 resolution: "@rollup/rollup-linux-arm64-musl@npm:4.18.1" @@ -1241,6 +1290,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm64-musl@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.19.1" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-powerpc64le-gnu@npm:4.18.1": version: 4.18.1 resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.18.1" @@ -1248,6 +1304,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-powerpc64le-gnu@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.19.1" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-riscv64-gnu@npm:4.18.1": version: 4.18.1 resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.18.1" @@ -1255,6 +1318,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-riscv64-gnu@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.19.1" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-s390x-gnu@npm:4.18.1": version: 4.18.1 resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.18.1" @@ -1262,6 +1332,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-s390x-gnu@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.19.1" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-x64-gnu@npm:4.18.1": version: 4.18.1 resolution: "@rollup/rollup-linux-x64-gnu@npm:4.18.1" @@ -1269,6 +1346,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-x64-gnu@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.19.1" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-x64-musl@npm:4.18.1": version: 4.18.1 resolution: "@rollup/rollup-linux-x64-musl@npm:4.18.1" @@ -1276,6 +1360,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-x64-musl@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.19.1" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-win32-arm64-msvc@npm:4.18.1": version: 4.18.1 resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.18.1" @@ -1283,6 +1374,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-arm64-msvc@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.19.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-win32-ia32-msvc@npm:4.18.1": version: 4.18.1 resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.18.1" @@ -1290,6 +1388,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-ia32-msvc@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.19.1" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@rollup/rollup-win32-x64-msvc@npm:4.18.1": version: 4.18.1 resolution: "@rollup/rollup-win32-x64-msvc@npm:4.18.1" @@ -1297,6 +1402,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-x64-msvc@npm:4.19.1": + version: 4.19.1 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.19.1" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@sideway/address@npm:^4.1.3": version: 4.1.4 resolution: "@sideway/address@npm:4.1.4" @@ -10623,6 +10735,13 @@ __metadata: languageName: node linkType: hard +"picocolors@npm:^1.0.1": + version: 1.0.1 + resolution: "picocolors@npm:1.0.1" + checksum: 10c0/c63cdad2bf812ef0d66c8db29583802355d4ca67b9285d846f390cc15c2f6ccb94e8cb7eb6a6e97fc5990a6d3ad4ae42d86c84d3146e667c739a4234ed50d400 + languageName: node + linkType: hard + "picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.2.3, picomatch@npm:^2.3.1": version: 2.3.1 resolution: "picomatch@npm:2.3.1" @@ -10858,14 +10977,14 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.4.35": - version: 8.4.35 - resolution: "postcss@npm:8.4.35" +"postcss@npm:^8.4.39": + version: 8.4.40 + resolution: "postcss@npm:8.4.40" dependencies: nanoid: "npm:^3.3.7" - picocolors: "npm:^1.0.0" - source-map-js: "npm:^1.0.2" - checksum: 10c0/e8dd04e48001eb5857abc9475365bf08f4e508ddf9bc0b8525449a95d190f10d025acebc5b56ac2e94b3c7146790e4ae78989bb9633cb7ee20d1cc9b7dc909b2 + picocolors: "npm:^1.0.1" + source-map-js: "npm:^1.2.0" + checksum: 10c0/65ed67573e5443beaeb582282ff27a6be7c7fe3b4d9fa15761157616f2b97510cb1c335023c26220b005909f007337026d6e3ff092f25010b484ad484e80ea7f languageName: node linkType: hard @@ -11924,7 +12043,70 @@ __metadata: languageName: node linkType: hard -"rollup@npm:^4.18.1, rollup@npm:^4.2.0": +"rollup@npm:^4.13.0": + version: 4.19.1 + resolution: "rollup@npm:4.19.1" + dependencies: + "@rollup/rollup-android-arm-eabi": "npm:4.19.1" + "@rollup/rollup-android-arm64": "npm:4.19.1" + "@rollup/rollup-darwin-arm64": "npm:4.19.1" + "@rollup/rollup-darwin-x64": "npm:4.19.1" + "@rollup/rollup-linux-arm-gnueabihf": "npm:4.19.1" + "@rollup/rollup-linux-arm-musleabihf": "npm:4.19.1" + "@rollup/rollup-linux-arm64-gnu": "npm:4.19.1" + "@rollup/rollup-linux-arm64-musl": "npm:4.19.1" + "@rollup/rollup-linux-powerpc64le-gnu": "npm:4.19.1" + "@rollup/rollup-linux-riscv64-gnu": "npm:4.19.1" + "@rollup/rollup-linux-s390x-gnu": "npm:4.19.1" + "@rollup/rollup-linux-x64-gnu": "npm:4.19.1" + "@rollup/rollup-linux-x64-musl": "npm:4.19.1" + "@rollup/rollup-win32-arm64-msvc": "npm:4.19.1" + "@rollup/rollup-win32-ia32-msvc": "npm:4.19.1" + "@rollup/rollup-win32-x64-msvc": "npm:4.19.1" + "@types/estree": "npm:1.0.5" + fsevents: "npm:~2.3.2" + dependenciesMeta: + "@rollup/rollup-android-arm-eabi": + optional: true + "@rollup/rollup-android-arm64": + optional: true + "@rollup/rollup-darwin-arm64": + optional: true + "@rollup/rollup-darwin-x64": + optional: true + "@rollup/rollup-linux-arm-gnueabihf": + optional: true + "@rollup/rollup-linux-arm-musleabihf": + optional: true + "@rollup/rollup-linux-arm64-gnu": + optional: true + "@rollup/rollup-linux-arm64-musl": + optional: true + "@rollup/rollup-linux-powerpc64le-gnu": + optional: true + "@rollup/rollup-linux-riscv64-gnu": + optional: true + "@rollup/rollup-linux-s390x-gnu": + optional: true + "@rollup/rollup-linux-x64-gnu": + optional: true + "@rollup/rollup-linux-x64-musl": + optional: true + "@rollup/rollup-win32-arm64-msvc": + optional: true + "@rollup/rollup-win32-ia32-msvc": + optional: true + "@rollup/rollup-win32-x64-msvc": + optional: true + fsevents: + optional: true + bin: + rollup: dist/bin/rollup + checksum: 10c0/2e526c38b4bcb22a058cf95e40c8c105a86f27d582c677c47df9315a17b18e75c772edc0773ca4d12d58ceca254bb5d63d4172041f6fd9f01e1a613d8bba6d09 + languageName: node + linkType: hard + +"rollup@npm:^4.18.1": version: 4.18.1 resolution: "rollup@npm:4.18.1" dependencies: @@ -12463,6 +12645,13 @@ __metadata: languageName: node linkType: hard +"source-map-js@npm:^1.2.0": + version: 1.2.0 + resolution: "source-map-js@npm:1.2.0" + checksum: 10c0/7e5f896ac10a3a50fe2898e5009c58ff0dc102dcb056ed27a354623a0ece8954d4b2649e1a1b2b52ef2e161d26f8859c7710350930751640e71e374fe2d321a4 + languageName: node + linkType: hard + "source-map@npm:0.8.0-beta.0": version: 0.8.0-beta.0 resolution: "source-map@npm:0.8.0-beta.0" @@ -12987,8 +13176,8 @@ __metadata: linkType: hard "tar@npm:^6.1.11, tar@npm:^6.1.2": - version: 6.2.0 - resolution: "tar@npm:6.2.0" + version: 6.2.1 + resolution: "tar@npm:6.2.1" dependencies: chownr: "npm:^2.0.0" fs-minipass: "npm:^2.0.0" @@ -12996,7 +13185,7 @@ __metadata: minizlib: "npm:^2.1.1" mkdirp: "npm:^1.0.3" yallist: "npm:^4.0.0" - checksum: 10c0/02ca064a1a6b4521fef88c07d389ac0936730091f8c02d30ea60d472e0378768e870769ab9e986d87807bfee5654359cf29ff4372746cc65e30cbddc352660d8 + checksum: 10c0/a5eca3eb50bc11552d453488344e6507156b9193efd7635e98e867fab275d527af53d8866e2370cd09dfe74378a18111622ace35af6a608e5223a7d27fe99537 languageName: node linkType: hard @@ -13561,11 +13750,11 @@ __metadata: linkType: hard "undici@npm:^5.25.4": - version: 5.27.2 - resolution: "undici@npm:5.27.2" + version: 5.28.4 + resolution: "undici@npm:5.28.4" dependencies: "@fastify/busboy": "npm:^2.0.0" - checksum: 10c0/0cb62c57edc938f242c116e41fb2a74f81ed20e7e2e554cf1ceae548520df0592385b53d444f8cf59e1e10e6b27acd153198d8a2353b3040d0a778a099aac92c + checksum: 10c0/08d0f2596553aa0a54ca6e8e9c7f45aef7d042c60918564e3a142d449eda165a80196f6ef19ea2ef2e6446959e293095d8e40af1236f0d67223b06afac5ecad7 languageName: node linkType: hard @@ -14227,13 +14416,13 @@ __metadata: linkType: hard "vite@npm:^5.0.0": - version: 5.1.0 - resolution: "vite@npm:5.1.0" + version: 5.3.5 + resolution: "vite@npm:5.3.5" dependencies: - esbuild: "npm:^0.19.3" + esbuild: "npm:^0.21.3" fsevents: "npm:~2.3.3" - postcss: "npm:^8.4.35" - rollup: "npm:^4.2.0" + postcss: "npm:^8.4.39" + rollup: "npm:^4.13.0" peerDependencies: "@types/node": ^18.0.0 || >=20.0.0 less: "*" @@ -14262,7 +14451,7 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 10c0/62aa632b6f30cfca39db534b5b461b1e73dc4f4a3093088c1140a1e1b0c4c8f4eacc0e472a0d96d765ad6976b00e202da20a647865886df692240a2b06b62c6f + checksum: 10c0/795c7e0dbc94b96c4a0aff0d5d4b349dd28ad8b7b70979c1010f96b4d83f7d6c1700ebd6fed91de2e021b0a3689b9abc2d8017f6dfa8c9a6ca5c7af637d6afc6 languageName: node linkType: hard diff --git a/test-storybooks/portable-stories-kitchen-sink/svelte/package.json b/test-storybooks/portable-stories-kitchen-sink/svelte/package.json index fecb60d35bfc..dd8841800a3f 100644 --- a/test-storybooks/portable-stories-kitchen-sink/svelte/package.json +++ b/test-storybooks/portable-stories-kitchen-sink/svelte/package.json @@ -99,6 +99,6 @@ "tslib": "^2.6.2", "typescript": "^5.2.2", "vite": "^5.1.4", - "vitest": "^1.3.1" + "vitest": "^1.6.0" } } \ No newline at end of file