mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-09 00:19:13 +08:00
Merge branch 'next' into norbert/merge-core-cli
This commit is contained in:
commit
ed82b3b7f5
@ -635,6 +635,7 @@ jobs:
|
|||||||
command: |
|
command: |
|
||||||
cd code
|
cd code
|
||||||
yarn local-registry --open &
|
yarn local-registry --open &
|
||||||
|
yarn wait-on tcp:127.0.0.1:6001
|
||||||
cd ../../
|
cd ../../
|
||||||
mkdir features-1
|
mkdir features-1
|
||||||
cd features-1
|
cd features-1
|
||||||
|
@ -1,3 +1,29 @@
|
|||||||
|
## 8.6.0-beta.8
|
||||||
|
|
||||||
|
- Addon-Test: Fix console error in build mode - [#30625](https://github.com/storybookjs/storybook/pull/30625), thanks @JReinhold!
|
||||||
|
- Manager: Fix panel reactivity - [#30638](https://github.com/storybookjs/storybook/pull/30638), thanks @valentinpalkovic!
|
||||||
|
|
||||||
|
## 8.6.0-beta.7
|
||||||
|
|
||||||
|
- Angular: Fix @angular/platform-browser/animations never available - [#30618](https://github.com/storybookjs/storybook/pull/30618), thanks @valentinpalkovic!
|
||||||
|
- Angular: Fix @angular/platform-browser/animations never available - [#30619](https://github.com/storybookjs/storybook/pull/30619), thanks @valentinpalkovic!
|
||||||
|
- CLI: Fix peer dep issues for npm users during upgrade - [#30616](https://github.com/storybookjs/storybook/pull/30616), thanks @valentinpalkovic!
|
||||||
|
|
||||||
|
## 8.6.0-beta.6
|
||||||
|
|
||||||
|
- CLI: Fix printing of selected features - [#30605](https://github.com/storybookjs/storybook/pull/30605), thanks @ghengeveld!
|
||||||
|
- CLI: Remove Storybook dependencies before adding re-adding them - [#30600](https://github.com/storybookjs/storybook/pull/30600), thanks @valentinpalkovic!
|
||||||
|
|
||||||
|
## 8.6.0-beta.5
|
||||||
|
|
||||||
|
- Addon-Test: Make sure that only one global portable story config is ever loaded - [#30582](https://github.com/storybookjs/storybook/pull/30582), thanks @kasperpeulen!
|
||||||
|
- Angular: Support v19.2 when @angular/animations is not installed - [#30611](https://github.com/storybookjs/storybook/pull/30611), thanks @valentinpalkovic!
|
||||||
|
- Builder-Vite: Fix runtime and iframe 404 on first load - [#30567](https://github.com/storybookjs/storybook/pull/30567), thanks @valentinpalkovic!
|
||||||
|
- CLI: Don't initially select Documentation and Testing features - [#30599](https://github.com/storybookjs/storybook/pull/30599), thanks @ghengeveld!
|
||||||
|
- CLI: Make telemetry data an object - [#30581](https://github.com/storybookjs/storybook/pull/30581), thanks @ndelangen!
|
||||||
|
- Core: Support `esbuild@^0.25` - [#30574](https://github.com/storybookjs/storybook/pull/30574), thanks @JReinhold!
|
||||||
|
- Test addon: Only update `vitest.config.ts` with workspaces, otherwise create `vitest.workspace.ts` - [#30583](https://github.com/storybookjs/storybook/pull/30583), thanks @ghengeveld!
|
||||||
|
|
||||||
## 8.6.0-beta.4
|
## 8.6.0-beta.4
|
||||||
|
|
||||||
- Addon-Test: Add telemetry data for Focused Tests - [#30568](https://github.com/storybookjs/storybook/pull/30568), thanks @JReinhold!
|
- Addon-Test: Add telemetry data for Focused Tests - [#30568](https://github.com/storybookjs/storybook/pull/30568), thanks @JReinhold!
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-a11y",
|
"name": "@storybook/addon-a11y",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Test component compliance with web accessibility standards",
|
"description": "Test component compliance with web accessibility standards",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"a11y",
|
"a11y",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-actions",
|
"name": "@storybook/addon-actions",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Get UI feedback when an action is performed on an interactive element",
|
"description": "Get UI feedback when an action is performed on an interactive element",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook",
|
"storybook",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-backgrounds",
|
"name": "@storybook/addon-backgrounds",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Switch backgrounds to view components in different settings",
|
"description": "Switch backgrounds to view components in different settings",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"addon",
|
"addon",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-controls",
|
"name": "@storybook/addon-controls",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Interact with component inputs dynamically in the Storybook UI",
|
"description": "Interact with component inputs dynamically in the Storybook UI",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"addon",
|
"addon",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-docs",
|
"name": "@storybook/addon-docs",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Document component usage and properties in Markdown",
|
"description": "Document component usage and properties in Markdown",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"addon",
|
"addon",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-essentials",
|
"name": "@storybook/addon-essentials",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Curated addons to bring out the best of Storybook",
|
"description": "Curated addons to bring out the best of Storybook",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"addon",
|
"addon",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-mdx-gfm",
|
"name": "@storybook/addon-mdx-gfm",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "GitHub Flavored Markdown in Storybook",
|
"description": "GitHub Flavored Markdown in Storybook",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"addon",
|
"addon",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-highlight",
|
"name": "@storybook/addon-highlight",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Highlight DOM nodes within your stories",
|
"description": "Highlight DOM nodes within your stories",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook-addons",
|
"storybook-addons",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-interactions",
|
"name": "@storybook/addon-interactions",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Automate, test and debug user interactions",
|
"description": "Automate, test and debug user interactions",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook-addons",
|
"storybook-addons",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-jest",
|
"name": "@storybook/addon-jest",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "React storybook addon that show component jest report",
|
"description": "React storybook addon that show component jest report",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"addon",
|
"addon",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-links",
|
"name": "@storybook/addon-links",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Link stories together to build demos and prototypes with your UI components",
|
"description": "Link stories together to build demos and prototypes with your UI components",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook-addons",
|
"storybook-addons",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-measure",
|
"name": "@storybook/addon-measure",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Inspect layouts by visualizing the box model",
|
"description": "Inspect layouts by visualizing the box model",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook-addons",
|
"storybook-addons",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-onboarding",
|
"name": "@storybook/addon-onboarding",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook Addon Onboarding - Introduces a new onboarding experience",
|
"description": "Storybook Addon Onboarding - Introduces a new onboarding experience",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook-addons",
|
"storybook-addons",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-outline",
|
"name": "@storybook/addon-outline",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Outline all elements with CSS to help with layout placement and alignment",
|
"description": "Outline all elements with CSS to help with layout placement and alignment",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook-addons",
|
"storybook-addons",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-storysource",
|
"name": "@storybook/addon-storysource",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "View a story’s source code to see how it works and paste into your app",
|
"description": "View a story’s source code to see how it works and paste into your app",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"addon",
|
"addon",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/experimental-addon-test",
|
"name": "@storybook/experimental-addon-test",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Integrate Vitest with Storybook",
|
"description": "Integrate Vitest with Storybook",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook-addons",
|
"storybook-addons",
|
||||||
|
@ -2,4 +2,7 @@ import { experimental_UniversalStore } from 'storybook/internal/manager-api';
|
|||||||
|
|
||||||
import { type StoreState, storeOptions } from './constants';
|
import { type StoreState, storeOptions } from './constants';
|
||||||
|
|
||||||
export const store = experimental_UniversalStore.create<StoreState>(storeOptions);
|
export const store = experimental_UniversalStore.create<StoreState>({
|
||||||
|
...storeOptions,
|
||||||
|
leader: (globalThis as any).CONFIG_TYPE === 'PRODUCTION',
|
||||||
|
});
|
||||||
|
@ -405,9 +405,9 @@ export default async function postInstall(options: PostinstallOptions) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there's an existing workspace file, we update that file to include the Storybook test plugin.
|
||||||
|
// We assume the existing workspaces include the Vite(st) config, so we won't add it.
|
||||||
if (vitestWorkspaceFile) {
|
if (vitestWorkspaceFile) {
|
||||||
// If there's an existing workspace file, we update that file to include the Storybook test plugin.
|
|
||||||
// We assume the existing workspaces include the Vite(st) config, so we won't add it.
|
|
||||||
const workspaceTemplate = await loadTemplate('vitest.workspace.template.ts', {
|
const workspaceTemplate = await loadTemplate('vitest.workspace.template.ts', {
|
||||||
EXTENDS_WORKSPACE: viteConfigFile
|
EXTENDS_WORKSPACE: viteConfigFile
|
||||||
? relative(dirname(vitestWorkspaceFile), viteConfigFile)
|
? relative(dirname(vitestWorkspaceFile), viteConfigFile)
|
||||||
@ -445,21 +445,26 @@ export default async function postInstall(options: PostinstallOptions) {
|
|||||||
logger.line(1);
|
logger.line(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (rootConfig) {
|
}
|
||||||
// If there's an existing Vite/Vitest config, we update it to include the Storybook test plugin.
|
// If there's an existing Vite/Vitest config with workspaces, we update it to include the Storybook test plugin.
|
||||||
|
else if (rootConfig) {
|
||||||
let target, updated;
|
let target, updated;
|
||||||
// For Vitest 3+, we extend the config file, otherwise we fall back to creating a workspace file.
|
const configFile = await fs.readFile(rootConfig, 'utf8');
|
||||||
if (isVitest3OrLater) {
|
const hasWorkspaceConfig = configFile.includes('workspace:');
|
||||||
|
|
||||||
|
// For Vitest 3+ with an existing workspace option in the config file, we extend the workspace array,
|
||||||
|
// otherwise we fall back to creating a workspace file.
|
||||||
|
if (isVitest3OrLater && hasWorkspaceConfig) {
|
||||||
const configTemplate = await loadTemplate('vitest.config.template.ts', {
|
const configTemplate = await loadTemplate('vitest.config.template.ts', {
|
||||||
CONFIG_DIR: options.configDir,
|
CONFIG_DIR: options.configDir,
|
||||||
BROWSER_CONFIG: browserConfig,
|
BROWSER_CONFIG: browserConfig,
|
||||||
SETUP_FILE: relative(dirname(rootConfig), vitestSetupFile),
|
SETUP_FILE: relative(dirname(rootConfig), vitestSetupFile),
|
||||||
});
|
});
|
||||||
const configFile = await fs.readFile(rootConfig, 'utf8');
|
|
||||||
const source = babelParse(configTemplate);
|
const source = babelParse(configTemplate);
|
||||||
target = babelParse(configFile);
|
target = babelParse(configFile);
|
||||||
updated = updateConfigFile(source, target);
|
updated = updateConfigFile(source, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target && updated) {
|
if (target && updated) {
|
||||||
logger.line(1);
|
logger.line(1);
|
||||||
logger.plain(`${step} Updating your ${vitestConfigFile ? 'Vitest' : 'Vite'} config file:`);
|
logger.plain(`${step} Updating your ${vitestConfigFile ? 'Vitest' : 'Vite'} config file:`);
|
||||||
@ -502,8 +507,9 @@ export default async function postInstall(options: PostinstallOptions) {
|
|||||||
const formattedContent = await formatFileContent(newWorkspaceFile, workspaceTemplate);
|
const formattedContent = await formatFileContent(newWorkspaceFile, workspaceTemplate);
|
||||||
await writeFile(newWorkspaceFile, formattedContent);
|
await writeFile(newWorkspaceFile, formattedContent);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
// If there's no existing Vitest/Vite config, we create a new Vitest config file.
|
// If there's no existing Vitest/Vite config, we create a new Vitest config file.
|
||||||
|
else {
|
||||||
const newConfigFile = resolve(`vitest.config.${fileExtension}`);
|
const newConfigFile = resolve(`vitest.config.${fileExtension}`);
|
||||||
const configTemplate = await loadTemplate('vitest.config.template.ts', {
|
const configTemplate = await loadTemplate('vitest.config.template.ts', {
|
||||||
CONFIG_DIR: options.configDir,
|
CONFIG_DIR: options.configDir,
|
||||||
|
@ -35,4 +35,11 @@ export const modifyErrorMessage = ({ task }: { task: Task }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Enable this in 9.0
|
||||||
|
// beforeAll(() => {
|
||||||
|
// if (globalThis.globalProjectAnnotations) {
|
||||||
|
// return globalThis.globalProjectAnnotations.beforeAll();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
afterEach(modifyErrorMessage);
|
afterEach(modifyErrorMessage);
|
||||||
|
@ -5,6 +5,7 @@ import { type RunnerTask, type TaskMeta, type TestContext } from 'vitest';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
type Report,
|
type Report,
|
||||||
|
composeConfigs,
|
||||||
composeStory,
|
composeStory,
|
||||||
getCsfFactoryAnnotations,
|
getCsfFactoryAnnotations,
|
||||||
} from 'storybook/internal/preview-api';
|
} from 'storybook/internal/preview-api';
|
||||||
@ -34,7 +35,7 @@ export const testStory = (
|
|||||||
annotations.story,
|
annotations.story,
|
||||||
annotations.meta!,
|
annotations.meta!,
|
||||||
{ initialGlobals: (await getInitialGlobals?.()) ?? {} },
|
{ initialGlobals: (await getInitialGlobals?.()) ?? {} },
|
||||||
annotations.preview,
|
annotations.preview ?? globalThis.globalProjectAnnotations,
|
||||||
exportName
|
exportName
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-themes",
|
"name": "@storybook/addon-themes",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Switch between multiple themes for you components in Storybook",
|
"description": "Switch between multiple themes for you components in Storybook",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"css",
|
"css",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-toolbars",
|
"name": "@storybook/addon-toolbars",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Create your own toolbar items that control story rendering",
|
"description": "Create your own toolbar items that control story rendering",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"addon",
|
"addon",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-viewport",
|
"name": "@storybook/addon-viewport",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Build responsive components by adjusting Storybook’s viewport size and orientation",
|
"description": "Build responsive components by adjusting Storybook’s viewport size and orientation",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"addon",
|
"addon",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/builder-vite",
|
"name": "@storybook/builder-vite",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "A plugin to run and build Storybooks with Vite",
|
"description": "A plugin to run and build Storybooks with Vite",
|
||||||
"homepage": "https://github.com/storybookjs/storybook/tree/next/code/builders/builder-vite/#readme",
|
"homepage": "https://github.com/storybookjs/storybook/tree/next/code/builders/builder-vite/#readme",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
@ -4,7 +4,7 @@ import type { Options, PreviewAnnotation } from 'storybook/internal/types';
|
|||||||
import { dedent } from 'ts-dedent';
|
import { dedent } from 'ts-dedent';
|
||||||
|
|
||||||
import { processPreviewAnnotation } from './utils/process-preview-annotation';
|
import { processPreviewAnnotation } from './utils/process-preview-annotation';
|
||||||
import { SB_VIRTUAL_FILES, getResolvedVirtualModuleId } from './virtual-file-names';
|
import { SB_VIRTUAL_FILES } from './virtual-file-names';
|
||||||
|
|
||||||
export async function generateModernIframeScriptCode(options: Options, projectRoot: string) {
|
export async function generateModernIframeScriptCode(options: Options, projectRoot: string) {
|
||||||
const { presets, configDir } = options;
|
const { presets, configDir } = options;
|
||||||
|
@ -7,7 +7,6 @@ import type { Middleware, Options } from 'storybook/internal/types';
|
|||||||
import type { ViteDevServer } from 'vite';
|
import type { ViteDevServer } from 'vite';
|
||||||
|
|
||||||
import { build as viteBuild } from './build';
|
import { build as viteBuild } from './build';
|
||||||
import { transformIframeHtml } from './transform-iframe-html';
|
|
||||||
import type { ViteBuilder } from './types';
|
import type { ViteBuilder } from './types';
|
||||||
import { createViteServer } from './vite-server';
|
import { createViteServer } from './vite-server';
|
||||||
|
|
||||||
@ -16,22 +15,8 @@ export { hasVitePlugins } from './utils/has-vite-plugins';
|
|||||||
|
|
||||||
export * from './types';
|
export * from './types';
|
||||||
|
|
||||||
function iframeMiddleware(options: Options, server: ViteDevServer): Middleware {
|
function iframeHandler(options: Options, server: ViteDevServer): Middleware {
|
||||||
return async (req, res, next) => {
|
return async (req, res) => {
|
||||||
if (!req.url || !req.url.match(/^\/iframe\.html($|\?)/)) {
|
|
||||||
next();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// the base isn't used for anything, but it's required by the URL constructor
|
|
||||||
const url = new URL(req.url, 'http://localhost:6006');
|
|
||||||
|
|
||||||
// We need to handle `html-proxy` params for style tag HMR https://github.com/storybookjs/builder-vite/issues/266#issuecomment-1055677865
|
|
||||||
// e.g. /iframe.html?html-proxy&index=0.css
|
|
||||||
if (url.searchParams.has('html-proxy')) {
|
|
||||||
next();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const indexHtml = await readFile(require.resolve('@storybook/builder-vite/input/iframe.html'), {
|
const indexHtml = await readFile(require.resolve('@storybook/builder-vite/input/iframe.html'), {
|
||||||
encoding: 'utf8',
|
encoding: 'utf8',
|
||||||
});
|
});
|
||||||
@ -57,7 +42,7 @@ export const start: ViteBuilder['start'] = async ({
|
|||||||
}) => {
|
}) => {
|
||||||
server = await createViteServer(options as Options, devServer);
|
server = await createViteServer(options as Options, devServer);
|
||||||
|
|
||||||
router.use(iframeMiddleware(options as Options, server));
|
router.get('/iframe.html', iframeHandler(options as Options, server));
|
||||||
router.use(server.middlewares);
|
router.use(server.middlewares);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -27,6 +27,7 @@ const INCLUDE_CANDIDATES = [
|
|||||||
'@storybook/addon-essentials/outline/preview',
|
'@storybook/addon-essentials/outline/preview',
|
||||||
'@storybook/addon-essentials/viewport/preview',
|
'@storybook/addon-essentials/viewport/preview',
|
||||||
'@storybook/addon-highlight/preview',
|
'@storybook/addon-highlight/preview',
|
||||||
|
'@storybook/addon-interactions/preview',
|
||||||
'@storybook/addon-links/preview',
|
'@storybook/addon-links/preview',
|
||||||
'@storybook/addon-measure/preview',
|
'@storybook/addon-measure/preview',
|
||||||
'@storybook/addon-outline/preview',
|
'@storybook/addon-outline/preview',
|
||||||
@ -132,6 +133,7 @@ const INCLUDE_CANDIDATES = [
|
|||||||
'react-textarea-autosize',
|
'react-textarea-autosize',
|
||||||
'react',
|
'react',
|
||||||
'react/jsx-runtime',
|
'react/jsx-runtime',
|
||||||
|
'react/jsx-dev-runtime',
|
||||||
'refractor/core',
|
'refractor/core',
|
||||||
'refractor/lang/bash.js',
|
'refractor/lang/bash.js',
|
||||||
'refractor/lang/css.js',
|
'refractor/lang/css.js',
|
||||||
@ -150,6 +152,7 @@ const INCLUDE_CANDIDATES = [
|
|||||||
'slash',
|
'slash',
|
||||||
'store2',
|
'store2',
|
||||||
'storybook/internal/preview/runtime',
|
'storybook/internal/preview/runtime',
|
||||||
|
'storybook/internal/csf',
|
||||||
'synchronous-promise',
|
'synchronous-promise',
|
||||||
'telejson',
|
'telejson',
|
||||||
'ts-dedent',
|
'ts-dedent',
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/builder-webpack5",
|
"name": "@storybook/builder-webpack5",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook framework-agnostic API",
|
"description": "Storybook framework-agnostic API",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -15,7 +15,7 @@ import { checkWebpackVersion } from '@storybook/core-webpack';
|
|||||||
import prettyTime from 'pretty-hrtime';
|
import prettyTime from 'pretty-hrtime';
|
||||||
import sirv from 'sirv';
|
import sirv from 'sirv';
|
||||||
import type { Configuration, Stats, StatsOptions } from 'webpack';
|
import type { Configuration, Stats, StatsOptions } from 'webpack';
|
||||||
import webpackDep, { DefinePlugin, ProgressPlugin } from 'webpack';
|
import webpackDep, { DefinePlugin, IgnorePlugin, ProgressPlugin } from 'webpack';
|
||||||
import webpackDevMiddleware from 'webpack-dev-middleware';
|
import webpackDevMiddleware from 'webpack-dev-middleware';
|
||||||
import webpackHotMiddleware from 'webpack-hot-middleware';
|
import webpackHotMiddleware from 'webpack-hot-middleware';
|
||||||
|
|
||||||
@ -23,6 +23,7 @@ export * from './types';
|
|||||||
export * from './preview/virtual-module-mapping';
|
export * from './preview/virtual-module-mapping';
|
||||||
|
|
||||||
export const WebpackDefinePlugin = DefinePlugin;
|
export const WebpackDefinePlugin = DefinePlugin;
|
||||||
|
export const WebpackIgnorePlugin = IgnorePlugin;
|
||||||
|
|
||||||
export const printDuration = (startTime: [number, number]) =>
|
export const printDuration = (startTime: [number, number]) =>
|
||||||
prettyTime(process.hrtime(startTime))
|
prettyTime(process.hrtime(startTime))
|
||||||
|
@ -83,9 +83,5 @@
|
|||||||
|
|
||||||
import './sb-manager/runtime.js';
|
import './sb-manager/runtime.js';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<% if (!ignorePreview) { %>
|
|
||||||
<link href="./sb-preview/runtime.js" rel="prefetch" as="script" />
|
|
||||||
<% } %>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "storybook",
|
"name": "storybook",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook framework-agnostic API",
|
"description": "Storybook framework-agnostic API",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -34,7 +34,7 @@ export async function getAddonAnnotations(addon: string) {
|
|||||||
|
|
||||||
// for backwards compatibility, if it's not a core addon we use /preview entrypoint
|
// for backwards compatibility, if it's not a core addon we use /preview entrypoint
|
||||||
if (!data.isCoreAddon) {
|
if (!data.isCoreAddon) {
|
||||||
data.importPath = `@storybook/${addon}/preview`;
|
data.importPath = `${addon}/preview`;
|
||||||
}
|
}
|
||||||
|
|
||||||
require.resolve(path.join(addon, 'preview'));
|
require.resolve(path.join(addon, 'preview'));
|
||||||
|
@ -13,7 +13,7 @@ import findCacheDirectory from 'find-cache-dir';
|
|||||||
*/
|
*/
|
||||||
export function resolvePathInStorybookCache(fileOrDirectoryName: string, sub = 'default'): string {
|
export function resolvePathInStorybookCache(fileOrDirectoryName: string, sub = 'default'): string {
|
||||||
let cacheDirectory = findCacheDirectory({ name: 'storybook' });
|
let cacheDirectory = findCacheDirectory({ name: 'storybook' });
|
||||||
cacheDirectory ||= join(process.cwd(), '.cache', 'storybook');
|
cacheDirectory ||= join(process.cwd(), 'node_modules', '.cache', 'storybook');
|
||||||
|
|
||||||
return join(cacheDirectory, sub, fileOrDirectoryName);
|
return join(cacheDirectory, sub, fileOrDirectoryName);
|
||||||
}
|
}
|
||||||
|
@ -1,87 +1,87 @@
|
|||||||
// auto generated file, do not edit
|
// auto generated file, do not edit
|
||||||
export default {
|
export default {
|
||||||
'@storybook/addon-a11y': '8.6.0-beta.4',
|
'@storybook/addon-a11y': '8.6.0-beta.8',
|
||||||
'@storybook/addon-actions': '8.6.0-beta.4',
|
'@storybook/addon-actions': '8.6.0-beta.8',
|
||||||
'@storybook/addon-backgrounds': '8.6.0-beta.4',
|
'@storybook/addon-backgrounds': '8.6.0-beta.8',
|
||||||
'@storybook/addon-controls': '8.6.0-beta.4',
|
'@storybook/addon-controls': '8.6.0-beta.8',
|
||||||
'@storybook/addon-docs': '8.6.0-beta.4',
|
'@storybook/addon-docs': '8.6.0-beta.8',
|
||||||
'@storybook/addon-essentials': '8.6.0-beta.4',
|
'@storybook/addon-essentials': '8.6.0-beta.8',
|
||||||
'@storybook/addon-mdx-gfm': '8.6.0-beta.4',
|
'@storybook/addon-mdx-gfm': '8.6.0-beta.8',
|
||||||
'@storybook/addon-highlight': '8.6.0-beta.4',
|
'@storybook/addon-highlight': '8.6.0-beta.8',
|
||||||
'@storybook/addon-interactions': '8.6.0-beta.4',
|
'@storybook/addon-interactions': '8.6.0-beta.8',
|
||||||
'@storybook/addon-jest': '8.6.0-beta.4',
|
'@storybook/addon-jest': '8.6.0-beta.8',
|
||||||
'@storybook/addon-links': '8.6.0-beta.4',
|
'@storybook/addon-links': '8.6.0-beta.8',
|
||||||
'@storybook/addon-measure': '8.6.0-beta.4',
|
'@storybook/addon-measure': '8.6.0-beta.8',
|
||||||
'@storybook/addon-onboarding': '8.6.0-beta.4',
|
'@storybook/addon-onboarding': '8.6.0-beta.8',
|
||||||
'@storybook/addon-outline': '8.6.0-beta.4',
|
'@storybook/addon-outline': '8.6.0-beta.8',
|
||||||
'@storybook/addon-storysource': '8.6.0-beta.4',
|
'@storybook/addon-storysource': '8.6.0-beta.8',
|
||||||
'@storybook/experimental-addon-test': '8.6.0-beta.4',
|
'@storybook/experimental-addon-test': '8.6.0-beta.8',
|
||||||
'@storybook/addon-themes': '8.6.0-beta.4',
|
'@storybook/addon-themes': '8.6.0-beta.8',
|
||||||
'@storybook/addon-toolbars': '8.6.0-beta.4',
|
'@storybook/addon-toolbars': '8.6.0-beta.8',
|
||||||
'@storybook/addon-viewport': '8.6.0-beta.4',
|
'@storybook/addon-viewport': '8.6.0-beta.8',
|
||||||
'@storybook/builder-vite': '8.6.0-beta.4',
|
'@storybook/builder-vite': '8.6.0-beta.8',
|
||||||
'@storybook/builder-webpack5': '8.6.0-beta.4',
|
'@storybook/builder-webpack5': '8.6.0-beta.8',
|
||||||
storybook: '8.6.0-beta.4',
|
storybook: '8.6.0-beta.8',
|
||||||
'@storybook/builder-manager': '8.6.0-beta.4',
|
'@storybook/builder-manager': '8.6.0-beta.8',
|
||||||
'@storybook/channels': '8.6.0-beta.4',
|
'@storybook/channels': '8.6.0-beta.8',
|
||||||
'@storybook/client-logger': '8.6.0-beta.4',
|
'@storybook/client-logger': '8.6.0-beta.8',
|
||||||
'@storybook/components': '8.6.0-beta.4',
|
'@storybook/components': '8.6.0-beta.8',
|
||||||
'@storybook/core-common': '8.6.0-beta.4',
|
'@storybook/core-common': '8.6.0-beta.8',
|
||||||
'@storybook/core-events': '8.6.0-beta.4',
|
'@storybook/core-events': '8.6.0-beta.8',
|
||||||
'@storybook/core-server': '8.6.0-beta.4',
|
'@storybook/core-server': '8.6.0-beta.8',
|
||||||
'@storybook/csf-tools': '8.6.0-beta.4',
|
'@storybook/csf-tools': '8.6.0-beta.8',
|
||||||
'@storybook/docs-tools': '8.6.0-beta.4',
|
'@storybook/docs-tools': '8.6.0-beta.8',
|
||||||
'@storybook/manager': '8.6.0-beta.4',
|
'@storybook/manager': '8.6.0-beta.8',
|
||||||
'@storybook/manager-api': '8.6.0-beta.4',
|
'@storybook/manager-api': '8.6.0-beta.8',
|
||||||
'@storybook/node-logger': '8.6.0-beta.4',
|
'@storybook/node-logger': '8.6.0-beta.8',
|
||||||
'@storybook/preview': '8.6.0-beta.4',
|
'@storybook/preview': '8.6.0-beta.8',
|
||||||
'@storybook/preview-api': '8.6.0-beta.4',
|
'@storybook/preview-api': '8.6.0-beta.8',
|
||||||
'@storybook/router': '8.6.0-beta.4',
|
'@storybook/router': '8.6.0-beta.8',
|
||||||
'@storybook/telemetry': '8.6.0-beta.4',
|
'@storybook/telemetry': '8.6.0-beta.8',
|
||||||
'@storybook/theming': '8.6.0-beta.4',
|
'@storybook/theming': '8.6.0-beta.8',
|
||||||
'@storybook/types': '8.6.0-beta.4',
|
'@storybook/types': '8.6.0-beta.8',
|
||||||
'@storybook/angular': '8.6.0-beta.4',
|
'@storybook/angular': '8.6.0-beta.8',
|
||||||
'@storybook/ember': '8.6.0-beta.4',
|
'@storybook/ember': '8.6.0-beta.8',
|
||||||
'@storybook/experimental-nextjs-vite': '8.6.0-beta.4',
|
'@storybook/experimental-nextjs-vite': '8.6.0-beta.8',
|
||||||
'@storybook/html-vite': '8.6.0-beta.4',
|
'@storybook/html-vite': '8.6.0-beta.8',
|
||||||
'@storybook/html-webpack5': '8.6.0-beta.4',
|
'@storybook/html-webpack5': '8.6.0-beta.8',
|
||||||
'@storybook/nextjs': '8.6.0-beta.4',
|
'@storybook/nextjs': '8.6.0-beta.8',
|
||||||
'@storybook/preact-vite': '8.6.0-beta.4',
|
'@storybook/preact-vite': '8.6.0-beta.8',
|
||||||
'@storybook/preact-webpack5': '8.6.0-beta.4',
|
'@storybook/preact-webpack5': '8.6.0-beta.8',
|
||||||
'@storybook/react-native-web-vite': '8.6.0-beta.4',
|
'@storybook/react-native-web-vite': '8.6.0-beta.8',
|
||||||
'@storybook/react-vite': '8.6.0-beta.4',
|
'@storybook/react-vite': '8.6.0-beta.8',
|
||||||
'@storybook/react-webpack5': '8.6.0-beta.4',
|
'@storybook/react-webpack5': '8.6.0-beta.8',
|
||||||
'@storybook/server-webpack5': '8.6.0-beta.4',
|
'@storybook/server-webpack5': '8.6.0-beta.8',
|
||||||
'@storybook/svelte-vite': '8.6.0-beta.4',
|
'@storybook/svelte-vite': '8.6.0-beta.8',
|
||||||
'@storybook/svelte-webpack5': '8.6.0-beta.4',
|
'@storybook/svelte-webpack5': '8.6.0-beta.8',
|
||||||
'@storybook/sveltekit': '8.6.0-beta.4',
|
'@storybook/sveltekit': '8.6.0-beta.8',
|
||||||
'@storybook/vue3-vite': '8.6.0-beta.4',
|
'@storybook/vue3-vite': '8.6.0-beta.8',
|
||||||
'@storybook/vue3-webpack5': '8.6.0-beta.4',
|
'@storybook/vue3-webpack5': '8.6.0-beta.8',
|
||||||
'@storybook/web-components-vite': '8.6.0-beta.4',
|
'@storybook/web-components-vite': '8.6.0-beta.8',
|
||||||
'@storybook/web-components-webpack5': '8.6.0-beta.4',
|
'@storybook/web-components-webpack5': '8.6.0-beta.8',
|
||||||
'@storybook/blocks': '8.6.0-beta.4',
|
'@storybook/blocks': '8.6.0-beta.8',
|
||||||
sb: '8.6.0-beta.4',
|
sb: '8.6.0-beta.8',
|
||||||
'@storybook/cli': '8.6.0-beta.4',
|
'@storybook/cli': '8.6.0-beta.8',
|
||||||
'@storybook/codemod': '8.6.0-beta.4',
|
'@storybook/codemod': '8.6.0-beta.8',
|
||||||
'@storybook/core-webpack': '8.6.0-beta.4',
|
'@storybook/core-webpack': '8.6.0-beta.8',
|
||||||
'create-storybook': '8.6.0-beta.4',
|
'create-storybook': '8.6.0-beta.8',
|
||||||
'@storybook/csf-plugin': '8.6.0-beta.4',
|
'@storybook/csf-plugin': '8.6.0-beta.8',
|
||||||
'@storybook/instrumenter': '8.6.0-beta.4',
|
'@storybook/instrumenter': '8.6.0-beta.8',
|
||||||
'@storybook/react-dom-shim': '8.6.0-beta.4',
|
'@storybook/react-dom-shim': '8.6.0-beta.8',
|
||||||
'@storybook/source-loader': '8.6.0-beta.4',
|
'@storybook/source-loader': '8.6.0-beta.8',
|
||||||
'@storybook/test': '8.6.0-beta.4',
|
'@storybook/test': '8.6.0-beta.8',
|
||||||
'@storybook/preset-create-react-app': '8.6.0-beta.4',
|
'@storybook/preset-create-react-app': '8.6.0-beta.8',
|
||||||
'@storybook/preset-html-webpack': '8.6.0-beta.4',
|
'@storybook/preset-html-webpack': '8.6.0-beta.8',
|
||||||
'@storybook/preset-preact-webpack': '8.6.0-beta.4',
|
'@storybook/preset-preact-webpack': '8.6.0-beta.8',
|
||||||
'@storybook/preset-react-webpack': '8.6.0-beta.4',
|
'@storybook/preset-react-webpack': '8.6.0-beta.8',
|
||||||
'@storybook/preset-server-webpack': '8.6.0-beta.4',
|
'@storybook/preset-server-webpack': '8.6.0-beta.8',
|
||||||
'@storybook/preset-svelte-webpack': '8.6.0-beta.4',
|
'@storybook/preset-svelte-webpack': '8.6.0-beta.8',
|
||||||
'@storybook/preset-vue3-webpack': '8.6.0-beta.4',
|
'@storybook/preset-vue3-webpack': '8.6.0-beta.8',
|
||||||
'@storybook/html': '8.6.0-beta.4',
|
'@storybook/html': '8.6.0-beta.8',
|
||||||
'@storybook/preact': '8.6.0-beta.4',
|
'@storybook/preact': '8.6.0-beta.8',
|
||||||
'@storybook/react': '8.6.0-beta.4',
|
'@storybook/react': '8.6.0-beta.8',
|
||||||
'@storybook/server': '8.6.0-beta.4',
|
'@storybook/server': '8.6.0-beta.8',
|
||||||
'@storybook/svelte': '8.6.0-beta.4',
|
'@storybook/svelte': '8.6.0-beta.8',
|
||||||
'@storybook/vue3': '8.6.0-beta.4',
|
'@storybook/vue3': '8.6.0-beta.8',
|
||||||
'@storybook/web-components': '8.6.0-beta.4',
|
'@storybook/web-components': '8.6.0-beta.8',
|
||||||
};
|
};
|
||||||
|
@ -77,13 +77,14 @@ export async function storybookDevServer(options: Options) {
|
|||||||
channel: serverChannel,
|
channel: serverChannel,
|
||||||
});
|
});
|
||||||
|
|
||||||
let previewStarted: Promise<any> = Promise.resolve();
|
let previewResult: Awaited<ReturnType<(typeof previewBuilder)['start']>> =
|
||||||
|
await Promise.resolve();
|
||||||
|
|
||||||
if (!options.ignorePreview) {
|
if (!options.ignorePreview) {
|
||||||
if (!options.quiet) {
|
if (!options.quiet) {
|
||||||
logger.info('=> Starting preview..');
|
logger.info('=> Starting preview..');
|
||||||
}
|
}
|
||||||
previewStarted = previewBuilder
|
previewResult = await previewBuilder
|
||||||
.start({
|
.start({
|
||||||
startTime: process.hrtime(),
|
startTime: process.hrtime(),
|
||||||
options,
|
options,
|
||||||
@ -107,14 +108,6 @@ export async function storybookDevServer(options: Options) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is a preview route, the builder has to be started before we can serve it
|
|
||||||
// this handler keeps request to that route pending until the builder is ready to serve it, preventing a 404
|
|
||||||
app.use('/iframe.html', (req, res, next) => {
|
|
||||||
// We need to catch here or node will treat any errors thrown by `previewStarted` as
|
|
||||||
// unhandled and exit (even though they are very much handled below)
|
|
||||||
previewStarted.catch(() => {}).then(() => next());
|
|
||||||
});
|
|
||||||
|
|
||||||
const listening = new Promise<void>((resolve, reject) => {
|
const listening = new Promise<void>((resolve, reject) => {
|
||||||
server.once('error', reject);
|
server.once('error', reject);
|
||||||
app.listen({ port, host }, resolve);
|
app.listen({ port, host }, resolve);
|
||||||
@ -131,8 +124,6 @@ export async function storybookDevServer(options: Options) {
|
|||||||
throw indexError;
|
throw indexError;
|
||||||
}
|
}
|
||||||
|
|
||||||
const previewResult = await previewStarted;
|
|
||||||
|
|
||||||
// Now the preview has successfully started, we can count this as a 'dev' event.
|
// Now the preview has successfully started, we can count this as a 'dev' event.
|
||||||
doTelemetry(app, core, initializedStoryIndexGenerator, options);
|
doTelemetry(app, core, initializedStoryIndexGenerator, options);
|
||||||
|
|
||||||
|
@ -20,19 +20,26 @@ export interface Preview<TRenderer extends Renderer = Renderer> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function definePreview<TRenderer extends Renderer>(
|
export function definePreview<TRenderer extends Renderer>(
|
||||||
preview: Preview<TRenderer>['input']
|
input: Preview<TRenderer>['input']
|
||||||
): Preview<TRenderer> {
|
): Preview<TRenderer> {
|
||||||
return {
|
let composed: NormalizedProjectAnnotations<TRenderer>;
|
||||||
|
const preview: Preview<TRenderer> = {
|
||||||
_tag: 'Preview',
|
_tag: 'Preview',
|
||||||
input: preview,
|
input,
|
||||||
get composed() {
|
get composed() {
|
||||||
const { addons, ...rest } = preview;
|
if (composed) {
|
||||||
return normalizeProjectAnnotations<TRenderer>(composeConfigs([...(addons ?? []), rest]));
|
return composed;
|
||||||
|
}
|
||||||
|
const { addons, ...rest } = input;
|
||||||
|
composed = normalizeProjectAnnotations<TRenderer>(composeConfigs([...(addons ?? []), rest]));
|
||||||
|
return composed;
|
||||||
},
|
},
|
||||||
meta(meta: ComponentAnnotations<TRenderer>) {
|
meta(meta: ComponentAnnotations<TRenderer>) {
|
||||||
return defineMeta(meta, this);
|
return defineMeta(meta, this);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
globalThis.globalProjectAnnotations = preview.composed;
|
||||||
|
return preview;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isPreview(input: unknown): input is Preview<Renderer> {
|
export function isPreview(input: unknown): input is Preview<Renderer> {
|
||||||
|
@ -1 +1 @@
|
|||||||
export const version = '8.6.0-beta.4';
|
export const version = '8.6.0-beta.8';
|
||||||
|
@ -1,57 +1,69 @@
|
|||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import React from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { Consumer } from 'storybook/internal/manager-api';
|
import { useChannel, useStorybookApi, useStorybookState } from 'storybook/internal/manager-api';
|
||||||
import type { API, Combo } from 'storybook/internal/manager-api';
|
import { Addon_TypesEnum } from 'storybook/internal/types';
|
||||||
import { type API_LeafEntry, Addon_TypesEnum } from 'storybook/internal/types';
|
|
||||||
|
|
||||||
import memoize from 'memoizerific';
|
|
||||||
|
|
||||||
|
import { STORY_PREPARED } from '../../core-events';
|
||||||
import { AddonPanel } from '../components/panel/Panel';
|
import { AddonPanel } from '../components/panel/Panel';
|
||||||
|
|
||||||
const createPanelActions = memoize(1)((api) => ({
|
const Panel: FC<any> = (props) => {
|
||||||
onSelect: (panel: string) => api.setSelectedPanel(panel),
|
const api = useStorybookApi();
|
||||||
toggleVisibility: () => api.togglePanel(),
|
const state = useStorybookState();
|
||||||
togglePosition: () => api.togglePanelPosition(),
|
const [story, setStory] = useState(api.getCurrentStoryData());
|
||||||
}));
|
|
||||||
|
|
||||||
const getPanels = memoize(1)((api: API, story: API_LeafEntry) => {
|
useChannel(
|
||||||
const allPanels = api.getElements(Addon_TypesEnum.PANEL);
|
{
|
||||||
|
[STORY_PREPARED]: () => {
|
||||||
|
setStory(api.getCurrentStoryData());
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
if (!allPanels || !story || story.type !== 'story') {
|
const { parameters, type } = story ?? {};
|
||||||
return allPanels;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { parameters } = story;
|
const panelActions = useMemo(
|
||||||
|
() => ({
|
||||||
|
onSelect: (panel: string) => api.setSelectedPanel(panel),
|
||||||
|
toggleVisibility: () => api.togglePanel(),
|
||||||
|
togglePosition: () => api.togglePanelPosition(),
|
||||||
|
}),
|
||||||
|
[api]
|
||||||
|
);
|
||||||
|
|
||||||
const filteredPanels: typeof allPanels = {};
|
const panels = useMemo(() => {
|
||||||
Object.entries(allPanels).forEach(([id, panel]) => {
|
const allPanels = api.getElements(Addon_TypesEnum.PANEL);
|
||||||
const { paramKey }: any = panel;
|
|
||||||
if (paramKey && parameters && parameters[paramKey] && parameters[paramKey].disable) {
|
if (!allPanels || type !== 'story') {
|
||||||
return;
|
return allPanels;
|
||||||
}
|
}
|
||||||
if (
|
|
||||||
panel.disabled === true ||
|
|
||||||
(typeof panel.disabled === 'function' && panel.disabled(parameters))
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
filteredPanels[id] = panel;
|
|
||||||
});
|
|
||||||
|
|
||||||
return filteredPanels;
|
const filteredPanels: typeof allPanels = {};
|
||||||
});
|
Object.entries(allPanels).forEach(([id, p]) => {
|
||||||
|
const { paramKey }: any = p;
|
||||||
|
if (paramKey && parameters && parameters[paramKey] && parameters[paramKey].disable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (p.disabled === true || (typeof p.disabled === 'function' && p.disabled(parameters))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
filteredPanels[id] = p;
|
||||||
|
});
|
||||||
|
|
||||||
const mapper = ({ state, api }: Combo) => ({
|
return filteredPanels;
|
||||||
panels: getPanels(api, api.getCurrentStoryData()),
|
}, [api, type, parameters]);
|
||||||
selectedPanel: api.getSelectedPanel(),
|
|
||||||
panelPosition: state.layout.panelPosition,
|
|
||||||
actions: createPanelActions(api),
|
|
||||||
shortcuts: api.getShortcutKeys(),
|
|
||||||
});
|
|
||||||
|
|
||||||
const Panel: FC<any> = (props) => (
|
return (
|
||||||
<Consumer filter={mapper}>{(customProps) => <AddonPanel {...props} {...customProps} />}</Consumer>
|
<AddonPanel
|
||||||
);
|
panels={panels}
|
||||||
|
selectedPanel={api.getSelectedPanel()}
|
||||||
|
panelPosition={state.layout.panelPosition}
|
||||||
|
actions={panelActions}
|
||||||
|
shortcuts={api.getShortcutKeys()}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default Panel;
|
export default Panel;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* eslint-disable no-underscore-dangle */
|
/* eslint-disable no-underscore-dangle */
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
import { type CleanupCallback, isExportStory } from 'storybook/internal/csf';
|
import { type CleanupCallback, type Preview, isExportStory } from 'storybook/internal/csf';
|
||||||
import { MountMustBeDestructuredError } from 'storybook/internal/preview-errors';
|
import { MountMustBeDestructuredError } from 'storybook/internal/preview-errors';
|
||||||
import type {
|
import type {
|
||||||
Args,
|
Args,
|
||||||
@ -72,7 +72,10 @@ export function setProjectAnnotations<TRenderer extends Renderer = Renderer>(
|
|||||||
| NamedOrDefaultProjectAnnotations<TRenderer>[]
|
| NamedOrDefaultProjectAnnotations<TRenderer>[]
|
||||||
): NormalizedProjectAnnotations<TRenderer> {
|
): NormalizedProjectAnnotations<TRenderer> {
|
||||||
const annotations = Array.isArray(projectAnnotations) ? projectAnnotations : [projectAnnotations];
|
const annotations = Array.isArray(projectAnnotations) ? projectAnnotations : [projectAnnotations];
|
||||||
globalThis.globalProjectAnnotations = composeConfigs(annotations.map(extractAnnotation));
|
globalThis.globalProjectAnnotations = composeConfigs([
|
||||||
|
globalThis.defaultProjectAnnotations ?? {},
|
||||||
|
composeConfigs(annotations.map(extractAnnotation)),
|
||||||
|
]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We must return the composition of default and global annotations here
|
We must return the composition of default and global annotations here
|
||||||
@ -81,10 +84,7 @@ export function setProjectAnnotations<TRenderer extends Renderer = Renderer>(
|
|||||||
const projectAnnotations = setProjectAnnotations(...);
|
const projectAnnotations = setProjectAnnotations(...);
|
||||||
beforeAll(projectAnnotations.beforeAll)
|
beforeAll(projectAnnotations.beforeAll)
|
||||||
*/
|
*/
|
||||||
return composeConfigs([
|
return globalThis.globalProjectAnnotations ?? {};
|
||||||
globalThis.defaultProjectAnnotations ?? {},
|
|
||||||
globalThis.globalProjectAnnotations ?? {},
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const cleanups: CleanupCallback[] = [];
|
const cleanups: CleanupCallback[] = [];
|
||||||
@ -122,10 +122,7 @@ export function composeStory<TRenderer extends Renderer = Renderer, TArgs extend
|
|||||||
|
|
||||||
const normalizedProjectAnnotations = normalizeProjectAnnotations<TRenderer>(
|
const normalizedProjectAnnotations = normalizeProjectAnnotations<TRenderer>(
|
||||||
composeConfigs([
|
composeConfigs([
|
||||||
defaultConfig && Object.keys(defaultConfig).length > 0
|
defaultConfig ?? globalThis.globalProjectAnnotations ?? {},
|
||||||
? defaultConfig
|
|
||||||
: (globalThis.defaultProjectAnnotations ?? {}),
|
|
||||||
globalThis.globalProjectAnnotations ?? {},
|
|
||||||
projectAnnotations ?? {},
|
projectAnnotations ?? {},
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
@ -164,6 +161,8 @@ export function composeStory<TRenderer extends Renderer = Renderer, TArgs extend
|
|||||||
mount: null!,
|
mount: null!,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
context.parameters.__isPortableStory = true;
|
||||||
|
|
||||||
context.context = context;
|
context.context = context;
|
||||||
|
|
||||||
if (story.renderToCanvas) {
|
if (story.renderToCanvas) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/builder-manager",
|
"name": "@storybook/builder-manager",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook manager builder",
|
"description": "Storybook manager builder",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/channels",
|
"name": "@storybook/channels",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "",
|
"description": "",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/client-logger",
|
"name": "@storybook/client-logger",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "",
|
"description": "",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/components",
|
"name": "@storybook/components",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Core Storybook Components",
|
"description": "Core Storybook Components",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/core-common",
|
"name": "@storybook/core-common",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook framework-agnostic API",
|
"description": "Storybook framework-agnostic API",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/core-events",
|
"name": "@storybook/core-events",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Event names used in storybook core",
|
"description": "Event names used in storybook core",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/core-server",
|
"name": "@storybook/core-server",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook framework-agnostic API",
|
"description": "Storybook framework-agnostic API",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/csf-tools",
|
"name": "@storybook/csf-tools",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Parse and manipulate CSF and Storybook config files",
|
"description": "Parse and manipulate CSF and Storybook config files",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/docs-tools",
|
"name": "@storybook/docs-tools",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Shared utility functions for frameworks to implement docs",
|
"description": "Shared utility functions for frameworks to implement docs",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/manager-api",
|
"name": "@storybook/manager-api",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Core Storybook Manager API & Context",
|
"description": "Core Storybook Manager API & Context",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/manager",
|
"name": "@storybook/manager",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Core Storybook UI",
|
"description": "Core Storybook UI",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/node-logger",
|
"name": "@storybook/node-logger",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "",
|
"description": "",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/preview-api",
|
"name": "@storybook/preview-api",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "",
|
"description": "",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/preview",
|
"name": "@storybook/preview",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "",
|
"description": "",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/router",
|
"name": "@storybook/router",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Core Storybook Router",
|
"description": "Core Storybook Router",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/telemetry",
|
"name": "@storybook/telemetry",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Telemetry logging for crash reports and usage statistics",
|
"description": "Telemetry logging for crash reports and usage statistics",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/theming",
|
"name": "@storybook/theming",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Core Storybook Components",
|
"description": "Core Storybook Components",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/types",
|
"name": "@storybook/types",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Core Storybook TS Types",
|
"description": "Core Storybook TS Types",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/angular",
|
"name": "@storybook/angular",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook for Angular: Develop Angular components in isolation with hot reloading.",
|
"description": "Storybook for Angular: Develop Angular components in isolation with hot reloading.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook",
|
"storybook",
|
||||||
@ -101,6 +101,7 @@
|
|||||||
"@angular-devkit/architect": ">=0.1500.0 < 0.2000.0",
|
"@angular-devkit/architect": ">=0.1500.0 < 0.2000.0",
|
||||||
"@angular-devkit/build-angular": ">=15.0.0 < 20.0.0",
|
"@angular-devkit/build-angular": ">=15.0.0 < 20.0.0",
|
||||||
"@angular-devkit/core": ">=15.0.0 < 20.0.0",
|
"@angular-devkit/core": ">=15.0.0 < 20.0.0",
|
||||||
|
"@angular/animations": ">=15.0.0 < 20.0.0",
|
||||||
"@angular/cli": ">=15.0.0 < 20.0.0",
|
"@angular/cli": ">=15.0.0 < 20.0.0",
|
||||||
"@angular/common": ">=15.0.0 < 20.0.0",
|
"@angular/common": ">=15.0.0 < 20.0.0",
|
||||||
"@angular/compiler": ">=15.0.0 < 20.0.0",
|
"@angular/compiler": ">=15.0.0 < 20.0.0",
|
||||||
@ -115,6 +116,9 @@
|
|||||||
"zone.js": ">= 0.11.1 < 1.0.0"
|
"zone.js": ">= 0.11.1 < 1.0.0"
|
||||||
},
|
},
|
||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
|
"@angular/animations": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"@angular/cli": {
|
"@angular/cli": {
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
@ -101,6 +101,7 @@ export abstract class AbstractRenderer {
|
|||||||
this.initAngularRootElement(targetDOMNode, targetSelector);
|
this.initAngularRootElement(targetDOMNode, targetSelector);
|
||||||
|
|
||||||
const analyzedMetadata = new PropertyExtractor(storyFnAngular.moduleMetadata, component);
|
const analyzedMetadata = new PropertyExtractor(storyFnAngular.moduleMetadata, component);
|
||||||
|
await analyzedMetadata.init();
|
||||||
|
|
||||||
const storyUid = this.generateStoryUIdFromRawStoryUid(
|
const storyUid = this.generateStoryUIdFromRawStoryUid(
|
||||||
targetDOMNode.getAttribute(STORY_UID_ATTRIBUTE)
|
targetDOMNode.getAttribute(STORY_UID_ATTRIBUTE)
|
||||||
|
@ -59,6 +59,7 @@ describe('StorybookModule', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const analyzedMetadata = new PropertyExtractor({}, FooComponent);
|
const analyzedMetadata = new PropertyExtractor({}, FooComponent);
|
||||||
|
await analyzedMetadata.init();
|
||||||
|
|
||||||
const application = getApplication({
|
const application = getApplication({
|
||||||
storyFnAngular: { props },
|
storyFnAngular: { props },
|
||||||
@ -98,6 +99,7 @@ describe('StorybookModule', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const analyzedMetadata = new PropertyExtractor({}, FooComponent);
|
const analyzedMetadata = new PropertyExtractor({}, FooComponent);
|
||||||
|
await analyzedMetadata.init();
|
||||||
|
|
||||||
const application = getApplication({
|
const application = getApplication({
|
||||||
storyFnAngular: { props },
|
storyFnAngular: { props },
|
||||||
@ -127,6 +129,7 @@ describe('StorybookModule', () => {
|
|||||||
const storyProps$ = new BehaviorSubject<ICollection>(initialProps);
|
const storyProps$ = new BehaviorSubject<ICollection>(initialProps);
|
||||||
|
|
||||||
const analyzedMetadata = new PropertyExtractor({}, FooComponent);
|
const analyzedMetadata = new PropertyExtractor({}, FooComponent);
|
||||||
|
await analyzedMetadata.init();
|
||||||
|
|
||||||
const application = getApplication({
|
const application = getApplication({
|
||||||
storyFnAngular: { props: initialProps },
|
storyFnAngular: { props: initialProps },
|
||||||
@ -183,6 +186,7 @@ describe('StorybookModule', () => {
|
|||||||
const storyProps$ = new BehaviorSubject<ICollection>(initialProps);
|
const storyProps$ = new BehaviorSubject<ICollection>(initialProps);
|
||||||
|
|
||||||
const analyzedMetadata = new PropertyExtractor({}, FooComponent);
|
const analyzedMetadata = new PropertyExtractor({}, FooComponent);
|
||||||
|
await analyzedMetadata.init();
|
||||||
|
|
||||||
const application = getApplication({
|
const application = getApplication({
|
||||||
storyFnAngular: { props: initialProps },
|
storyFnAngular: { props: initialProps },
|
||||||
@ -224,6 +228,7 @@ describe('StorybookModule', () => {
|
|||||||
const storyProps$ = new BehaviorSubject<ICollection>(initialProps);
|
const storyProps$ = new BehaviorSubject<ICollection>(initialProps);
|
||||||
|
|
||||||
const analyzedMetadata = new PropertyExtractor({}, FooComponent);
|
const analyzedMetadata = new PropertyExtractor({}, FooComponent);
|
||||||
|
await analyzedMetadata.init();
|
||||||
|
|
||||||
const application = getApplication({
|
const application = getApplication({
|
||||||
storyFnAngular: {
|
storyFnAngular: {
|
||||||
@ -262,6 +267,7 @@ describe('StorybookModule', () => {
|
|||||||
const storyProps$ = new BehaviorSubject<ICollection>(initialProps);
|
const storyProps$ = new BehaviorSubject<ICollection>(initialProps);
|
||||||
|
|
||||||
const analyzedMetadata = new PropertyExtractor({}, FooComponent);
|
const analyzedMetadata = new PropertyExtractor({}, FooComponent);
|
||||||
|
await analyzedMetadata.init();
|
||||||
|
|
||||||
const application = getApplication({
|
const application = getApplication({
|
||||||
storyFnAngular: { props: initialProps },
|
storyFnAngular: { props: initialProps },
|
||||||
@ -302,6 +308,8 @@ describe('StorybookModule', () => {
|
|||||||
WithoutSelectorComponent
|
WithoutSelectorComponent
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await analyzedMetadata.init();
|
||||||
|
|
||||||
const application = getApplication({
|
const application = getApplication({
|
||||||
storyFnAngular: {
|
storyFnAngular: {
|
||||||
props,
|
props,
|
||||||
@ -330,6 +338,7 @@ describe('StorybookModule', () => {
|
|||||||
class FooComponent {}
|
class FooComponent {}
|
||||||
|
|
||||||
const analyzedMetadata = new PropertyExtractor({}, FooComponent);
|
const analyzedMetadata = new PropertyExtractor({}, FooComponent);
|
||||||
|
await analyzedMetadata.init();
|
||||||
|
|
||||||
const application = getApplication({
|
const application = getApplication({
|
||||||
storyFnAngular: { template: '' },
|
storyFnAngular: { template: '' },
|
||||||
|
@ -29,75 +29,81 @@ const TestModuleWithImportsAndProviders = NgModule({
|
|||||||
providers: [TestTokenProvider],
|
providers: [TestTokenProvider],
|
||||||
})(class {});
|
})(class {});
|
||||||
|
|
||||||
const analyzeMetadata = (metadata: NgModuleMetadata, component?: any) => {
|
const analyzeMetadata = async (metadata: NgModuleMetadata, component?: any) => {
|
||||||
return new PropertyExtractor(metadata, component);
|
const propertyExtractor = new PropertyExtractor(metadata, component);
|
||||||
|
await propertyExtractor.init();
|
||||||
|
return propertyExtractor;
|
||||||
};
|
};
|
||||||
const extractImports = (metadata: NgModuleMetadata, component?: any) => {
|
const extractImports = async (metadata: NgModuleMetadata, component?: any) => {
|
||||||
const { imports } = new PropertyExtractor(metadata, component);
|
const propertyExtractor = new PropertyExtractor(metadata, component);
|
||||||
return imports;
|
await propertyExtractor.init();
|
||||||
|
return propertyExtractor.imports;
|
||||||
};
|
};
|
||||||
const extractDeclarations = (metadata: NgModuleMetadata, component?: any) => {
|
const extractDeclarations = async (metadata: NgModuleMetadata, component?: any) => {
|
||||||
const { declarations } = new PropertyExtractor(metadata, component);
|
const propertyExtractor = new PropertyExtractor(metadata, component);
|
||||||
return declarations;
|
await propertyExtractor.init();
|
||||||
|
return propertyExtractor.declarations;
|
||||||
};
|
};
|
||||||
const extractProviders = (metadata: NgModuleMetadata, component?: any) => {
|
const extractProviders = async (metadata: NgModuleMetadata, component?: any) => {
|
||||||
const { providers } = new PropertyExtractor(metadata, component);
|
const propertyExtractor = new PropertyExtractor(metadata, component);
|
||||||
return providers;
|
await propertyExtractor.init();
|
||||||
|
return propertyExtractor.providers;
|
||||||
};
|
};
|
||||||
const extractApplicationProviders = (metadata: NgModuleMetadata, component?: any) => {
|
const extractApplicationProviders = async (metadata: NgModuleMetadata, component?: any) => {
|
||||||
const { applicationProviders } = new PropertyExtractor(metadata, component);
|
const propertyExtractor = new PropertyExtractor(metadata, component);
|
||||||
return applicationProviders;
|
await propertyExtractor.init();
|
||||||
|
return propertyExtractor.applicationProviders;
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('PropertyExtractor', () => {
|
describe('PropertyExtractor', () => {
|
||||||
vi.spyOn(console, 'warn').mockImplementation(() => {});
|
vi.spyOn(console, 'warn').mockImplementation(() => {});
|
||||||
|
|
||||||
describe('analyzeMetadata', () => {
|
describe('analyzeMetadata', () => {
|
||||||
it('should remove BrowserModule', () => {
|
it('should remove BrowserModule', async () => {
|
||||||
const metadata = {
|
const metadata = {
|
||||||
imports: [BrowserModule],
|
imports: [BrowserModule],
|
||||||
};
|
};
|
||||||
const { imports, providers, applicationProviders } = analyzeMetadata(metadata);
|
const { imports, providers, applicationProviders } = await analyzeMetadata(metadata);
|
||||||
expect(imports.flat(Number.MAX_VALUE)).toEqual([CommonModule]);
|
expect(imports.flat(Number.MAX_VALUE)).toEqual([CommonModule]);
|
||||||
expect(providers.flat(Number.MAX_VALUE)).toEqual([]);
|
expect(providers.flat(Number.MAX_VALUE)).toEqual([]);
|
||||||
expect(applicationProviders.flat(Number.MAX_VALUE)).toEqual([]);
|
expect(applicationProviders.flat(Number.MAX_VALUE)).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should remove BrowserAnimationsModule and use its providers instead', () => {
|
it('should remove BrowserAnimationsModule and use its providers instead', async () => {
|
||||||
const metadata = {
|
const metadata = {
|
||||||
imports: [BrowserAnimationsModule],
|
imports: [BrowserAnimationsModule],
|
||||||
};
|
};
|
||||||
const { imports, providers, applicationProviders } = analyzeMetadata(metadata);
|
const { imports, providers, applicationProviders } = await analyzeMetadata(metadata);
|
||||||
expect(imports.flat(Number.MAX_VALUE)).toEqual([CommonModule]);
|
expect(imports.flat(Number.MAX_VALUE)).toEqual([CommonModule]);
|
||||||
expect(providers.flat(Number.MAX_VALUE)).toEqual([]);
|
expect(providers.flat(Number.MAX_VALUE)).toEqual([]);
|
||||||
expect(applicationProviders.flat(Number.MAX_VALUE)).toEqual(provideAnimations());
|
expect(applicationProviders.flat(Number.MAX_VALUE)).toEqual(provideAnimations());
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should remove NoopAnimationsModule and use its providers instead', () => {
|
it('should remove NoopAnimationsModule and use its providers instead', async () => {
|
||||||
const metadata = {
|
const metadata = {
|
||||||
imports: [NoopAnimationsModule],
|
imports: [NoopAnimationsModule],
|
||||||
};
|
};
|
||||||
const { imports, providers, applicationProviders } = analyzeMetadata(metadata);
|
const { imports, providers, applicationProviders } = await analyzeMetadata(metadata);
|
||||||
expect(imports.flat(Number.MAX_VALUE)).toEqual([CommonModule]);
|
expect(imports.flat(Number.MAX_VALUE)).toEqual([CommonModule]);
|
||||||
expect(providers.flat(Number.MAX_VALUE)).toEqual([]);
|
expect(providers.flat(Number.MAX_VALUE)).toEqual([]);
|
||||||
expect(applicationProviders.flat(Number.MAX_VALUE)).toEqual(provideNoopAnimations());
|
expect(applicationProviders.flat(Number.MAX_VALUE)).toEqual(provideNoopAnimations());
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should remove Browser/Animations modules recursively', () => {
|
it('should remove Browser/Animations modules recursively', async () => {
|
||||||
const metadata = {
|
const metadata = {
|
||||||
imports: [BrowserAnimationsModule, BrowserModule],
|
imports: [BrowserAnimationsModule, BrowserModule],
|
||||||
};
|
};
|
||||||
const { imports, providers, applicationProviders } = analyzeMetadata(metadata);
|
const { imports, providers, applicationProviders } = await analyzeMetadata(metadata);
|
||||||
expect(imports.flat(Number.MAX_VALUE)).toEqual([CommonModule]);
|
expect(imports.flat(Number.MAX_VALUE)).toEqual([CommonModule]);
|
||||||
expect(providers.flat(Number.MAX_VALUE)).toEqual([]);
|
expect(providers.flat(Number.MAX_VALUE)).toEqual([]);
|
||||||
expect(applicationProviders.flat(Number.MAX_VALUE)).toEqual(provideAnimations());
|
expect(applicationProviders.flat(Number.MAX_VALUE)).toEqual(provideAnimations());
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not destructure Angular official module', () => {
|
it('should not destructure Angular official module', async () => {
|
||||||
const metadata = {
|
const metadata = {
|
||||||
imports: [WithOfficialModule],
|
imports: [WithOfficialModule],
|
||||||
};
|
};
|
||||||
const { imports, providers, applicationProviders } = analyzeMetadata(metadata);
|
const { imports, providers, applicationProviders } = await analyzeMetadata(metadata);
|
||||||
expect(imports.flat(Number.MAX_VALUE)).toEqual([CommonModule, WithOfficialModule]);
|
expect(imports.flat(Number.MAX_VALUE)).toEqual([CommonModule, WithOfficialModule]);
|
||||||
expect(providers.flat(Number.MAX_VALUE)).toEqual([]);
|
expect(providers.flat(Number.MAX_VALUE)).toEqual([]);
|
||||||
expect(applicationProviders.flat(Number.MAX_VALUE)).toEqual([]);
|
expect(applicationProviders.flat(Number.MAX_VALUE)).toEqual([]);
|
||||||
@ -105,13 +111,13 @@ describe('PropertyExtractor', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('extractImports', () => {
|
describe('extractImports', () => {
|
||||||
it('should return Angular official modules', () => {
|
it('should return Angular official modules', async () => {
|
||||||
const imports = extractImports({ imports: [TestModuleWithImportsAndProviders] });
|
const imports = await extractImports({ imports: [TestModuleWithImportsAndProviders] });
|
||||||
expect(imports).toEqual([CommonModule, TestModuleWithImportsAndProviders]);
|
expect(imports).toEqual([CommonModule, TestModuleWithImportsAndProviders]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return standalone components', () => {
|
it('should return standalone components', async () => {
|
||||||
const imports = extractImports(
|
const imports = await extractImports(
|
||||||
{
|
{
|
||||||
imports: [TestModuleWithImportsAndProviders],
|
imports: [TestModuleWithImportsAndProviders],
|
||||||
},
|
},
|
||||||
@ -124,8 +130,8 @@ describe('PropertyExtractor', () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return standalone directives', () => {
|
it('should return standalone directives', async () => {
|
||||||
const imports = extractImports(
|
const imports = await extractImports(
|
||||||
{
|
{
|
||||||
imports: [TestModuleWithImportsAndProviders],
|
imports: [TestModuleWithImportsAndProviders],
|
||||||
},
|
},
|
||||||
@ -140,8 +146,11 @@ describe('PropertyExtractor', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('extractDeclarations', () => {
|
describe('extractDeclarations', () => {
|
||||||
it('should return an array of declarations that contains `storyComponent`', () => {
|
it('should return an array of declarations that contains `storyComponent`', async () => {
|
||||||
const declarations = extractDeclarations({ declarations: [TestComponent1] }, TestComponent2);
|
const declarations = await extractDeclarations(
|
||||||
|
{ declarations: [TestComponent1] },
|
||||||
|
TestComponent2
|
||||||
|
);
|
||||||
expect(declarations).toEqual([TestComponent1, TestComponent2]);
|
expect(declarations).toEqual([TestComponent1, TestComponent2]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -174,15 +183,15 @@ describe('PropertyExtractor', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('extractProviders', () => {
|
describe('extractProviders', () => {
|
||||||
it('should return an array of providers', () => {
|
it('should return an array of providers', async () => {
|
||||||
const providers = extractProviders({
|
const providers = await extractProviders({
|
||||||
providers: [TestService],
|
providers: [TestService],
|
||||||
});
|
});
|
||||||
expect(providers).toEqual([TestService]);
|
expect(providers).toEqual([TestService]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return an array of singletons extracted', () => {
|
it('should return an array of singletons extracted', async () => {
|
||||||
const singeltons = extractApplicationProviders({
|
const singeltons = await extractApplicationProviders({
|
||||||
imports: [BrowserAnimationsModule],
|
imports: [BrowserAnimationsModule],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -14,12 +14,6 @@ import {
|
|||||||
VERSION,
|
VERSION,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import {
|
|
||||||
BrowserAnimationsModule,
|
|
||||||
NoopAnimationsModule,
|
|
||||||
provideAnimations,
|
|
||||||
provideNoopAnimations,
|
|
||||||
} from '@angular/platform-browser/animations';
|
|
||||||
import { dedent } from 'ts-dedent';
|
import { dedent } from 'ts-dedent';
|
||||||
|
|
||||||
import { NgModuleMetadata } from '../../types';
|
import { NgModuleMetadata } from '../../types';
|
||||||
@ -45,9 +39,7 @@ export class PropertyExtractor implements NgModuleMetadata {
|
|||||||
constructor(
|
constructor(
|
||||||
private metadata: NgModuleMetadata,
|
private metadata: NgModuleMetadata,
|
||||||
private component?: any
|
private component?: any
|
||||||
) {
|
) {}
|
||||||
this.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
// With the new way of mounting standalone components to the DOM via bootstrapApplication API,
|
// With the new way of mounting standalone components to the DOM via bootstrapApplication API,
|
||||||
// we should now pass ModuleWithProviders to the providers array of the bootstrapApplication function.
|
// we should now pass ModuleWithProviders to the providers array of the bootstrapApplication function.
|
||||||
@ -71,8 +63,8 @@ export class PropertyExtractor implements NgModuleMetadata {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private init() {
|
public async init() {
|
||||||
const analyzed = this.analyzeMetadata(this.metadata);
|
const analyzed = await this.analyzeMetadata(this.metadata);
|
||||||
this.imports = uniqueArray([CommonModule, analyzed.imports]);
|
this.imports = uniqueArray([CommonModule, analyzed.imports]);
|
||||||
this.providers = uniqueArray(analyzed.providers);
|
this.providers = uniqueArray(analyzed.providers);
|
||||||
this.applicationProviders = uniqueArray(analyzed.applicationProviders);
|
this.applicationProviders = uniqueArray(analyzed.applicationProviders);
|
||||||
@ -101,28 +93,28 @@ export class PropertyExtractor implements NgModuleMetadata {
|
|||||||
* - Extracts providers from ModuleWithProviders
|
* - Extracts providers from ModuleWithProviders
|
||||||
* - Returns a new NgModuleMetadata object
|
* - Returns a new NgModuleMetadata object
|
||||||
*/
|
*/
|
||||||
private analyzeMetadata = (metadata: NgModuleMetadata) => {
|
private analyzeMetadata = async (metadata: NgModuleMetadata) => {
|
||||||
const declarations = [...(metadata?.declarations || [])];
|
const declarations = [...(metadata?.declarations || [])];
|
||||||
const providers = [...(metadata?.providers || [])];
|
const providers = [...(metadata?.providers || [])];
|
||||||
const applicationProviders: Provider[] = [];
|
const applicationProviders: Provider[] = [];
|
||||||
const imports = [...(metadata?.imports || [])].reduce((acc, imported) => {
|
const imports = await Promise.all(
|
||||||
// remove ngModule and use only its providers if it is restricted
|
[...(metadata?.imports || [])].map(async (imported) => {
|
||||||
// (e.g. BrowserModule, BrowserAnimationsModule, NoopAnimationsModule, ...etc)
|
const [isRestricted, restrictedProviders] =
|
||||||
const [isRestricted, restrictedProviders] = PropertyExtractor.analyzeRestricted(imported);
|
await PropertyExtractor.analyzeRestricted(imported);
|
||||||
if (isRestricted) {
|
if (isRestricted) {
|
||||||
applicationProviders.unshift(restrictedProviders || []);
|
applicationProviders.unshift(restrictedProviders || []);
|
||||||
return acc;
|
return null;
|
||||||
}
|
}
|
||||||
|
return imported;
|
||||||
acc.push(imported);
|
})
|
||||||
|
).then((results) => results.filter(Boolean));
|
||||||
return acc;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return { ...metadata, imports, providers, applicationProviders, declarations };
|
return { ...metadata, imports, providers, applicationProviders, declarations };
|
||||||
};
|
};
|
||||||
|
|
||||||
static analyzeRestricted = (ngModule: NgModule): [boolean] | [boolean, Provider] => {
|
static analyzeRestricted = async (
|
||||||
|
ngModule: NgModule
|
||||||
|
): Promise<[boolean] | [boolean, Provider]> => {
|
||||||
if (ngModule === BrowserModule) {
|
if (ngModule === BrowserModule) {
|
||||||
console.warn(
|
console.warn(
|
||||||
dedent`
|
dedent`
|
||||||
@ -136,32 +128,38 @@ export class PropertyExtractor implements NgModuleMetadata {
|
|||||||
return [true];
|
return [true];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ngModule === BrowserAnimationsModule) {
|
try {
|
||||||
console.warn(
|
const animations = await import('@angular/platform-browser/animations');
|
||||||
dedent`
|
|
||||||
Storybook Warning:
|
|
||||||
You have added the "BrowserAnimationsModule" to the list of "imports" in your moduleMetadata definition of your Story.
|
|
||||||
In Storybook 7.0 we use Angular's new 'bootstrapApplication' API to mount the component to the DOM, which accepts a list of providers to set up application-wide providers.
|
|
||||||
Use the 'applicationConfig' decorator from '@storybook/angular' and add the "provideAnimations" function to the list of "providers".
|
|
||||||
If your Angular version does not support "provide-like" functions, use the helper function importProvidersFrom instead to set up animations. For this case, please add "importProvidersFrom(BrowserAnimationsModule)" to the list of providers of your applicationConfig definition.
|
|
||||||
Please visit https://angular.io/guide/standalone-components#configuring-dependency-injection for more information.
|
|
||||||
`
|
|
||||||
);
|
|
||||||
return [true, provideAnimations()];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ngModule === NoopAnimationsModule) {
|
if (ngModule === animations.BrowserAnimationsModule) {
|
||||||
console.warn(
|
console.warn(
|
||||||
dedent`
|
dedent`
|
||||||
Storybook Warning:
|
Storybook Warning:
|
||||||
You have added the "NoopAnimationsModule" to the list of "imports" in your moduleMetadata definition of your Story.
|
You have added the "BrowserAnimationsModule" to the list of "imports" in your moduleMetadata definition of your Story.
|
||||||
In Storybook v7.0 we are using Angular's new bootstrapApplication API to mount an Angular application to the DOM, which accepts a list of providers to set up application-wide providers.
|
In Storybook 7.0 we use Angular's new 'bootstrapApplication' API to mount the component to the DOM, which accepts a list of providers to set up application-wide providers.
|
||||||
Use the 'applicationConfig' decorator from '@storybook/angular' and add the "provideNoopAnimations" function to the list of "providers".
|
Use the 'applicationConfig' decorator from '@storybook/angular' and add the "provideAnimations" function to the list of "providers".
|
||||||
If your Angular version does not support "provide-like" functions, use the helper function importProvidersFrom instead to set up noop animations and to extract all necessary providers from NoopAnimationsModule. For this case, please add "importProvidersFrom(NoopAnimationsModule)" to the list of providers of your applicationConfig definition.
|
If your Angular version does not support "provide-like" functions, use the helper function importProvidersFrom instead to set up animations. For this case, please add "importProvidersFrom(BrowserAnimationsModule)" to the list of providers of your applicationConfig definition.
|
||||||
Please visit https://angular.io/guide/standalone-components#configuring-dependency-injection for more information.
|
Please visit https://angular.io/guide/standalone-components#configuring-dependency-injection for more information.
|
||||||
`
|
`
|
||||||
);
|
);
|
||||||
return [true, provideNoopAnimations()];
|
return [true, animations.provideAnimations()];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngModule === animations.NoopAnimationsModule) {
|
||||||
|
console.warn(
|
||||||
|
dedent`
|
||||||
|
Storybook Warning:
|
||||||
|
You have added the "NoopAnimationsModule" to the list of "imports" in your moduleMetadata definition of your Story.
|
||||||
|
In Storybook v7.0 we are using Angular's new bootstrapApplication API to mount an Angular application to the DOM, which accepts a list of providers to set up application-wide providers.
|
||||||
|
Use the 'applicationConfig' decorator from '@storybook/angular' and add the "provideNoopAnimations" function to the list of "providers".
|
||||||
|
If your Angular version does not support "provide-like" functions, use the helper function importProvidersFrom instead to set up noop animations and to extract all necessary providers from NoopAnimationsModule. For this case, please add "importProvidersFrom(NoopAnimationsModule)" to the list of providers of your applicationConfig definition.
|
||||||
|
Please visit https://angular.io/guide/standalone-components#configuring-dependency-injection for more information.
|
||||||
|
`
|
||||||
|
);
|
||||||
|
return [true, animations.provideNoopAnimations()];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
return [false];
|
||||||
}
|
}
|
||||||
|
|
||||||
return [false];
|
return [false];
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { logger } from 'storybook/internal/node-logger';
|
import { logger } from 'storybook/internal/node-logger';
|
||||||
import { AngularLegacyBuildOptionsError } from 'storybook/internal/server-errors';
|
import { AngularLegacyBuildOptionsError } from 'storybook/internal/server-errors';
|
||||||
import { WebpackDefinePlugin } from '@storybook/builder-webpack5';
|
import { WebpackDefinePlugin, WebpackIgnorePlugin } from '@storybook/builder-webpack5';
|
||||||
|
|
||||||
import { BuilderContext, targetFromTargetString } from '@angular-devkit/architect';
|
import { BuilderContext, targetFromTargetString } from '@angular-devkit/architect';
|
||||||
import { JsonObject, logging } from '@angular-devkit/core';
|
import { JsonObject, logging } from '@angular-devkit/core';
|
||||||
@ -40,6 +40,16 @@ export async function webpackFinal(baseConfig: webpack.Configuration, options: P
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
require.resolve('@angular/animations');
|
||||||
|
} catch (e) {
|
||||||
|
webpackConfig.plugins.push(
|
||||||
|
new WebpackIgnorePlugin({
|
||||||
|
resourceRegExp: /@angular\/platform-browser\/animations$/,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return webpackConfig;
|
return webpackConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
import { Meta, StoryObj, applicationConfig } from '@storybook/angular';
|
|
||||||
import { expect, userEvent, within } from '@storybook/test';
|
|
||||||
|
|
||||||
import { importProvidersFrom } from '@angular/core';
|
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
|
||||||
|
|
||||||
import { OpenCloseComponent } from '../moduleMetadata/angular-src/open-close-component/open-close.component';
|
|
||||||
|
|
||||||
const meta: Meta = {
|
|
||||||
component: OpenCloseComponent,
|
|
||||||
decorators: [
|
|
||||||
applicationConfig({
|
|
||||||
providers: [importProvidersFrom(BrowserAnimationsModule)],
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
parameters: {
|
|
||||||
chromatic: { delay: 100 },
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default meta;
|
|
||||||
|
|
||||||
type Story = StoryObj<typeof OpenCloseComponent>;
|
|
||||||
|
|
||||||
export const WithBrowserAnimations: Story = {
|
|
||||||
render: () => ({
|
|
||||||
template: `<app-open-close></app-open-close>`,
|
|
||||||
moduleMetadata: {
|
|
||||||
declarations: [OpenCloseComponent],
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
play: async ({ canvasElement }) => {
|
|
||||||
const canvas = within(canvasElement);
|
|
||||||
const opened = canvas.getByText('The box is now Open!');
|
|
||||||
expect(opened).toBeDefined();
|
|
||||||
const submitButton = canvas.getByRole('button');
|
|
||||||
await userEvent.click(submitButton);
|
|
||||||
const closed = canvas.getByText('The box is now Closed!');
|
|
||||||
expect(closed).toBeDefined();
|
|
||||||
},
|
|
||||||
};
|
|
@ -1,36 +0,0 @@
|
|||||||
import { Meta, StoryObj } from '@storybook/angular';
|
|
||||||
import { expect, userEvent, within } from '@storybook/test';
|
|
||||||
|
|
||||||
import { importProvidersFrom } from '@angular/core';
|
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
|
||||||
|
|
||||||
import { OpenCloseComponent } from '../moduleMetadata/angular-src/open-close-component/open-close.component';
|
|
||||||
|
|
||||||
const meta: Meta = {
|
|
||||||
component: OpenCloseComponent,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default meta;
|
|
||||||
|
|
||||||
type Story = StoryObj<typeof OpenCloseComponent>;
|
|
||||||
|
|
||||||
export const WithNoopBrowserAnimations: Story = {
|
|
||||||
render: () => ({
|
|
||||||
template: `<app-open-close></app-open-close>`,
|
|
||||||
applicationConfig: {
|
|
||||||
providers: [importProvidersFrom(NoopAnimationsModule)],
|
|
||||||
},
|
|
||||||
moduleMetadata: {
|
|
||||||
declarations: [OpenCloseComponent],
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
play: async ({ canvasElement }) => {
|
|
||||||
const canvas = within(canvasElement);
|
|
||||||
const opened = canvas.getByText('The box is now Open!');
|
|
||||||
expect(opened).toBeDefined();
|
|
||||||
const submitButton = canvas.getByRole('button');
|
|
||||||
await userEvent.click(submitButton);
|
|
||||||
const closed = canvas.getByText('The box is now Closed!');
|
|
||||||
expect(closed).toBeDefined();
|
|
||||||
},
|
|
||||||
};
|
|
@ -1,13 +0,0 @@
|
|||||||
:host {
|
|
||||||
display: block;
|
|
||||||
margin-top: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.open-close-container {
|
|
||||||
margin-top: 1em;
|
|
||||||
border: 1px solid #dddddd;
|
|
||||||
padding: 20px 20px 0px 20px;
|
|
||||||
color: #000000;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 20px;
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
<nav>
|
|
||||||
<button type="button" (click)="toggle()">Toggle Open/Close</button>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<div [@openClose]="isOpen ? 'open' : 'closed'" class="open-close-container">
|
|
||||||
<p>The box is now {{ isOpen ? 'Open' : 'Closed' }}!</p>
|
|
||||||
</div>
|
|
@ -1,39 +0,0 @@
|
|||||||
import { Component } from '@angular/core';
|
|
||||||
import { trigger, state, style, transition, animate } from '@angular/animations';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
standalone: false,
|
|
||||||
selector: 'app-open-close',
|
|
||||||
animations: [
|
|
||||||
trigger('openClose', [
|
|
||||||
// ...
|
|
||||||
state(
|
|
||||||
'open',
|
|
||||||
style({
|
|
||||||
height: '200px',
|
|
||||||
opacity: 1,
|
|
||||||
backgroundColor: 'yellow',
|
|
||||||
})
|
|
||||||
),
|
|
||||||
state(
|
|
||||||
'closed',
|
|
||||||
style({
|
|
||||||
height: '100px',
|
|
||||||
opacity: 0.8,
|
|
||||||
backgroundColor: 'blue',
|
|
||||||
})
|
|
||||||
),
|
|
||||||
transition('open => closed', [animate('0.1s')]),
|
|
||||||
transition('closed => open', [animate('0.1s')]),
|
|
||||||
]),
|
|
||||||
],
|
|
||||||
templateUrl: 'open-close.component.html',
|
|
||||||
styleUrls: ['open-close.component.css'],
|
|
||||||
})
|
|
||||||
export class OpenCloseComponent {
|
|
||||||
isOpen = true;
|
|
||||||
|
|
||||||
toggle() {
|
|
||||||
this.isOpen = !this.isOpen;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/ember",
|
"name": "@storybook/ember",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook for Ember: Develop Ember Component in isolation with Hot Reloading.",
|
"description": "Storybook for Ember: Develop Ember Component in isolation with Hot Reloading.",
|
||||||
"homepage": "https://github.com/storybookjs/storybook/tree/next/code/frameworks/ember",
|
"homepage": "https://github.com/storybookjs/storybook/tree/next/code/frameworks/ember",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/experimental-nextjs-vite",
|
"name": "@storybook/experimental-nextjs-vite",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook for Next.js and Vite",
|
"description": "Storybook for Next.js and Vite",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook",
|
"storybook",
|
||||||
|
@ -96,7 +96,7 @@ export function composeStory<TArgs extends Args = Args>(
|
|||||||
story as StoryAnnotationsOrFn<ReactRenderer, Args>,
|
story as StoryAnnotationsOrFn<ReactRenderer, Args>,
|
||||||
componentAnnotations,
|
componentAnnotations,
|
||||||
projectAnnotations,
|
projectAnnotations,
|
||||||
INTERNAL_DEFAULT_PROJECT_ANNOTATIONS,
|
globalThis.globalProjectAnnotations ?? INTERNAL_DEFAULT_PROJECT_ANNOTATIONS,
|
||||||
exportsName
|
exportsName
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/html-vite",
|
"name": "@storybook/html-vite",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook for HTML and Vite: Develop HTML in isolation with Hot Reloading.",
|
"description": "Storybook for HTML and Vite: Develop HTML in isolation with Hot Reloading.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/html-webpack5",
|
"name": "@storybook/html-webpack5",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook for HTML: View HTML snippets in isolation with Hot Reloading.",
|
"description": "Storybook for HTML: View HTML snippets in isolation with Hot Reloading.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/nextjs",
|
"name": "@storybook/nextjs",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook for Next.js",
|
"description": "Storybook for Next.js",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook",
|
"storybook",
|
||||||
|
@ -96,7 +96,7 @@ export function composeStory<TArgs extends Args = Args>(
|
|||||||
story as StoryAnnotationsOrFn<ReactRenderer, Args>,
|
story as StoryAnnotationsOrFn<ReactRenderer, Args>,
|
||||||
componentAnnotations,
|
componentAnnotations,
|
||||||
projectAnnotations,
|
projectAnnotations,
|
||||||
INTERNAL_DEFAULT_PROJECT_ANNOTATIONS,
|
globalThis.globalProjectAnnotations ?? INTERNAL_DEFAULT_PROJECT_ANNOTATIONS,
|
||||||
exportsName
|
exportsName
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/preact-vite",
|
"name": "@storybook/preact-vite",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook for Preact and Vite: Develop Preact components in isolation with Hot Reloading.",
|
"description": "Storybook for Preact and Vite: Develop Preact components in isolation with Hot Reloading.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/preact-webpack5",
|
"name": "@storybook/preact-webpack5",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook for Preact: Develop Preact Component in isolation.",
|
"description": "Storybook for Preact: Develop Preact Component in isolation.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/react-native-web-vite",
|
"name": "@storybook/react-native-web-vite",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Develop react-native components an isolated web environment with hot reloading.",
|
"description": "Develop react-native components an isolated web environment with hot reloading.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/react-vite",
|
"name": "@storybook/react-vite",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook for React and Vite: Develop React components in isolation with Hot Reloading.",
|
"description": "Storybook for React and Vite: Develop React components in isolation with Hot Reloading.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/react-webpack5",
|
"name": "@storybook/react-webpack5",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook for React: Develop React Component in isolation with Hot Reloading.",
|
"description": "Storybook for React: Develop React Component in isolation with Hot Reloading.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/server-webpack5",
|
"name": "@storybook/server-webpack5",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook for Server: View HTML snippets from a server in isolation with Hot Reloading.",
|
"description": "Storybook for Server: View HTML snippets from a server in isolation with Hot Reloading.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/svelte-vite",
|
"name": "@storybook/svelte-vite",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook for Svelte and Vite: Develop Svelte components in isolation with Hot Reloading.",
|
"description": "Storybook for Svelte and Vite: Develop Svelte components in isolation with Hot Reloading.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/svelte-webpack5",
|
"name": "@storybook/svelte-webpack5",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook for Svelte: Develop Svelte Component in isolation with Hot Reloading.",
|
"description": "Storybook for Svelte: Develop Svelte Component in isolation with Hot Reloading.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/sveltekit",
|
"name": "@storybook/sveltekit",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook for SvelteKit",
|
"description": "Storybook for SvelteKit",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook",
|
"storybook",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/vue3-vite",
|
"name": "@storybook/vue3-vite",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook for Vue3 and Vite: Develop Vue3 components in isolation with Hot Reloading.",
|
"description": "Storybook for Vue3 and Vite: Develop Vue3 components in isolation with Hot Reloading.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/vue3-webpack5",
|
"name": "@storybook/vue3-webpack5",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook for Vue 3: Develop Vue 3 Components in isolation with Hot Reloading.",
|
"description": "Storybook for Vue 3: Develop Vue 3 Components in isolation with Hot Reloading.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/web-components-vite",
|
"name": "@storybook/web-components-vite",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook for web-components and Vite: Develop Web Components in isolation with Hot Reloading.",
|
"description": "Storybook for web-components and Vite: Develop Web Components in isolation with Hot Reloading.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/web-components-webpack5",
|
"name": "@storybook/web-components-webpack5",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook for web-components: View web components snippets in isolation with Hot Reloading.",
|
"description": "Storybook for web-components: View web components snippets in isolation with Hot Reloading.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"lit",
|
"lit",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/blocks",
|
"name": "@storybook/blocks",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook Doc Blocks",
|
"description": "Storybook Doc Blocks",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sb",
|
"name": "sb",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook CLI",
|
"description": "Storybook CLI",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/cli",
|
"name": "@storybook/cli",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook CLI",
|
"description": "Storybook CLI",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -47,7 +47,7 @@ export async function runCodemod(
|
|||||||
// glob only supports forward slashes
|
// glob only supports forward slashes
|
||||||
const files = await globby(slash(globPattern), {
|
const files = await globby(slash(globPattern), {
|
||||||
followSymbolicLinks: true,
|
followSymbolicLinks: true,
|
||||||
ignore: ['node_modules/**', 'dist/**', 'storybook-static/**', 'build/**'],
|
ignore: ['**/node_modules/**', '**/dist/**', '**/storybook-static/**', '**/build/**'],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!files.length) {
|
if (!files.length) {
|
||||||
@ -64,11 +64,20 @@ export async function runCodemod(
|
|||||||
const limit = pLimit(maxConcurrentTasks);
|
const limit = pLimit(maxConcurrentTasks);
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
files.map((file) =>
|
files.map((file: string) =>
|
||||||
limit(async () => {
|
limit(async () => {
|
||||||
try {
|
try {
|
||||||
const source = await fs.readFile(file, 'utf-8');
|
let filePath = file;
|
||||||
const fileInfo: FileInfo = { path: file, source };
|
try {
|
||||||
|
if ((await fs.lstat(file)).isSymbolicLink()) {
|
||||||
|
filePath = await fs.realpath(file);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// if anything goes wrong when resolving the file, fallback to original path as is set above
|
||||||
|
}
|
||||||
|
|
||||||
|
const source = await fs.readFile(filePath, 'utf-8');
|
||||||
|
const fileInfo: FileInfo = { path: filePath, source };
|
||||||
const transformedSource = await transform(fileInfo);
|
const transformedSource = await transform(fileInfo);
|
||||||
|
|
||||||
if (transformedSource !== source) {
|
if (transformedSource !== source) {
|
||||||
|
@ -39,7 +39,7 @@ async function runStoriesCodemod(options: {
|
|||||||
).glob;
|
).glob;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.log('\n🛠️ Applying codemod on your stories, this might take some time...');
|
logger.log('\n🛠️ Applying codemod on your stories, this might take some time...');
|
||||||
|
|
||||||
// TODO: Move the csf-2-to-3 codemod into automigrations
|
// TODO: Move the csf-2-to-3 codemod into automigrations
|
||||||
await packageManager.executeCommand({
|
await packageManager.executeCommand({
|
||||||
@ -125,14 +125,14 @@ export const csfFactories: CommandFix = {
|
|||||||
previewConfigPath: previewConfigPath!,
|
previewConfigPath: previewConfigPath!,
|
||||||
});
|
});
|
||||||
|
|
||||||
logger.log('\n🛠️ Applying codemod on your main config...');
|
logger.log('\n🛠️ Applying codemod on your main config...');
|
||||||
const frameworkPackage =
|
const frameworkPackage =
|
||||||
getFrameworkPackageName(mainConfig) || '@storybook/your-framework-here';
|
getFrameworkPackageName(mainConfig) || '@storybook/your-framework-here';
|
||||||
await runCodemod(mainConfigPath, (fileInfo) =>
|
await runCodemod(mainConfigPath, (fileInfo) =>
|
||||||
configToCsfFactory(fileInfo, { configType: 'main', frameworkPackage }, { dryRun })
|
configToCsfFactory(fileInfo, { configType: 'main', frameworkPackage }, { dryRun })
|
||||||
);
|
);
|
||||||
|
|
||||||
logger.log('\n🛠️ Applying codemod on your preview config...');
|
logger.log('\n🛠️ Applying codemod on your preview config...');
|
||||||
await runCodemod(previewConfigPath, (fileInfo) =>
|
await runCodemod(previewConfigPath, (fileInfo) =>
|
||||||
configToCsfFactory(fileInfo, { configType: 'preview', frameworkPackage }, { dryRun })
|
configToCsfFactory(fileInfo, { configType: 'preview', frameworkPackage }, { dryRun })
|
||||||
);
|
);
|
||||||
|
@ -49,7 +49,7 @@ describe('stories codemod', () => {
|
|||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should rename meta object to meta if it has a different name', async () => {
|
it('should keep the original meta variable name', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
transform(dedent`
|
transform(dedent`
|
||||||
const componentMeta = { title: 'Component' };
|
const componentMeta = { title: 'Component' };
|
||||||
@ -58,7 +58,7 @@ describe('stories codemod', () => {
|
|||||||
).resolves.toMatchInlineSnapshot(`
|
).resolves.toMatchInlineSnapshot(`
|
||||||
import preview from '#.storybook/preview';
|
import preview from '#.storybook/preview';
|
||||||
|
|
||||||
const meta = preview.meta({ title: 'Component' });
|
const componentMeta = preview.meta({ title: 'Component' });
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -75,8 +75,8 @@ describe('stories codemod', () => {
|
|||||||
).resolves.toMatchInlineSnapshot(`
|
).resolves.toMatchInlineSnapshot(`
|
||||||
import preview from '#.storybook/preview';
|
import preview from '#.storybook/preview';
|
||||||
|
|
||||||
const meta = preview.meta({ title: 'Component' });
|
const componentMeta = preview.meta({ title: 'Component' });
|
||||||
export const A = meta.story({
|
export const A = componentMeta.story({
|
||||||
args: { primary: true },
|
args: { primary: true },
|
||||||
render: (args) => <Component {...args} />,
|
render: (args) => <Component {...args} />,
|
||||||
});
|
});
|
||||||
@ -97,8 +97,8 @@ describe('stories codemod', () => {
|
|||||||
).resolves.toMatchInlineSnapshot(`
|
).resolves.toMatchInlineSnapshot(`
|
||||||
import preview, { decorators } from '#.storybook/preview';
|
import preview, { decorators } from '#.storybook/preview';
|
||||||
|
|
||||||
const meta = preview.meta({ title: 'Component' });
|
const componentMeta = preview.meta({ title: 'Component' });
|
||||||
export const A = meta.story({
|
export const A = componentMeta.story({
|
||||||
args: { primary: true },
|
args: { primary: true },
|
||||||
render: (args) => <Component {...args} />,
|
render: (args) => <Component {...args} />,
|
||||||
});
|
});
|
||||||
@ -119,8 +119,8 @@ describe('stories codemod', () => {
|
|||||||
).resolves.toMatchInlineSnapshot(`
|
).resolves.toMatchInlineSnapshot(`
|
||||||
import previewConfig from '#.storybook/preview';
|
import previewConfig from '#.storybook/preview';
|
||||||
|
|
||||||
const meta = previewConfig.meta({ title: 'Component' });
|
const componentMeta = previewConfig.meta({ title: 'Component' });
|
||||||
export const A = meta.story({
|
export const A = componentMeta.story({
|
||||||
args: { primary: true },
|
args: { primary: true },
|
||||||
render: (args) => <Component {...args} />,
|
render: (args) => <Component {...args} />,
|
||||||
});
|
});
|
||||||
@ -141,9 +141,9 @@ describe('stories codemod', () => {
|
|||||||
).resolves.toMatchInlineSnapshot(`
|
).resolves.toMatchInlineSnapshot(`
|
||||||
import storybookPreview from '#.storybook/preview';
|
import storybookPreview from '#.storybook/preview';
|
||||||
|
|
||||||
const meta = storybookPreview.meta({ title: 'Component' });
|
const componentMeta = storybookPreview.meta({ title: 'Component' });
|
||||||
const preview = {};
|
const preview = {};
|
||||||
export const A = meta.story({
|
export const A = componentMeta.story({
|
||||||
args: { primary: true },
|
args: { primary: true },
|
||||||
render: (args) => <Component {...args} />,
|
render: (args) => <Component {...args} />,
|
||||||
});
|
});
|
||||||
@ -203,6 +203,63 @@ describe('stories codemod', () => {
|
|||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('migrate reused properties of meta from `meta.xyz` to `meta.input.xyz`', async () => {
|
||||||
|
await expect(
|
||||||
|
transform(dedent`
|
||||||
|
const myMeta = { title: 'Component', args: {} };
|
||||||
|
export default myMeta;
|
||||||
|
|
||||||
|
const metaProperties = {
|
||||||
|
...myMeta,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const A = {
|
||||||
|
args: myMeta.args,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const B = {
|
||||||
|
args: {
|
||||||
|
...myMeta.args,
|
||||||
|
...metaProperties.args,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export const C = {
|
||||||
|
render: async () => {
|
||||||
|
return JSON.stringify({
|
||||||
|
...myMeta.argTypes,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
`)
|
||||||
|
).resolves.toMatchInlineSnapshot(`
|
||||||
|
import preview from '#.storybook/preview';
|
||||||
|
|
||||||
|
const myMeta = preview.meta({ title: 'Component', args: {} });
|
||||||
|
|
||||||
|
const metaProperties = {
|
||||||
|
...myMeta.input,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const A = myMeta.story({
|
||||||
|
args: myMeta.input.args,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const B = myMeta.story({
|
||||||
|
args: {
|
||||||
|
...myMeta.input.args,
|
||||||
|
...metaProperties.args,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
export const C = myMeta.story({
|
||||||
|
render: async () => {
|
||||||
|
return JSON.stringify({
|
||||||
|
...myMeta.input.argTypes,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
it('does not migrate reused properties from disallowed list', async () => {
|
it('does not migrate reused properties from disallowed list', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
transform(dedent`
|
transform(dedent`
|
||||||
@ -398,6 +455,31 @@ describe('stories codemod', () => {
|
|||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const metaTypeDef = dedent`
|
||||||
|
import { Meta, StoryObj as CSF3 } from '@storybook/react';
|
||||||
|
import { ComponentProps } from './Component';
|
||||||
|
|
||||||
|
const meta: Meta<ComponentProps> = { title: 'Component', component: Component }
|
||||||
|
export default meta;
|
||||||
|
|
||||||
|
export const A: CSF3<ComponentProps> = {
|
||||||
|
args: { primary: true }
|
||||||
|
};
|
||||||
|
`;
|
||||||
|
it('meta type syntax', async () => {
|
||||||
|
await expect(transform(metaTypeDef)).resolves.toMatchInlineSnapshot(`
|
||||||
|
import preview from '#.storybook/preview';
|
||||||
|
|
||||||
|
import { ComponentProps } from './Component';
|
||||||
|
|
||||||
|
const meta = preview.meta({ title: 'Component', component: Component });
|
||||||
|
|
||||||
|
export const A = meta.story({
|
||||||
|
args: { primary: true },
|
||||||
|
});
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
const metaAs = dedent`
|
const metaAs = dedent`
|
||||||
import { Meta, StoryObj as CSF3 } from '@storybook/react';
|
import { Meta, StoryObj as CSF3 } from '@storybook/react';
|
||||||
import { ComponentProps } from './Component';
|
import { ComponentProps } from './Component';
|
||||||
|
@ -9,7 +9,7 @@ import { logger } from '../csf-factories';
|
|||||||
import { cleanupTypeImports } from './csf-factories-utils';
|
import { cleanupTypeImports } from './csf-factories-utils';
|
||||||
|
|
||||||
// Name of properties that should not be renamed to `Story.input.xyz`
|
// Name of properties that should not be renamed to `Story.input.xyz`
|
||||||
const reuseDisallowList = ['play', 'run', 'extends'];
|
const reuseDisallowList = ['play', 'run', 'extends', 'story'];
|
||||||
|
|
||||||
// Name of types that should be removed from the import list
|
// Name of types that should be removed from the import list
|
||||||
const typesDisallowList = [
|
const typesDisallowList = [
|
||||||
@ -36,7 +36,7 @@ export async function storyToCsfFactory(
|
|||||||
return info.source;
|
return info.source;
|
||||||
}
|
}
|
||||||
|
|
||||||
const metaVariableName = 'meta';
|
const metaVariableName = csf._metaVariableName ?? 'meta';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the preview import if it doesn't exist yet:
|
* Add the preview import if it doesn't exist yet:
|
||||||
@ -143,12 +143,17 @@ export async function storyToCsfFactory(
|
|||||||
|
|
||||||
// For each story, replace any reference of story reuse e.g.
|
// For each story, replace any reference of story reuse e.g.
|
||||||
// Story.args -> Story.input.args
|
// Story.args -> Story.input.args
|
||||||
|
// meta.args -> meta.input.args
|
||||||
traverse(csf._ast, {
|
traverse(csf._ast, {
|
||||||
Identifier(nodePath) {
|
Identifier(nodePath) {
|
||||||
const binding = nodePath.scope.getBinding(nodePath.node.name);
|
const identifierName = nodePath.node.name;
|
||||||
|
const binding = nodePath.scope.getBinding(identifierName);
|
||||||
|
|
||||||
// Check if the identifier corresponds to a story export
|
// Check if the identifier corresponds to a story export or the meta variable
|
||||||
if (binding && storyExportDecls.has(binding.identifier.name)) {
|
const isStoryExport = binding && storyExportDecls.has(binding.identifier.name);
|
||||||
|
const isMetaVariable = identifierName === metaVariableName;
|
||||||
|
|
||||||
|
if (isStoryExport || isMetaVariable) {
|
||||||
const parent = nodePath.parent;
|
const parent = nodePath.parent;
|
||||||
|
|
||||||
// Skip declarations (e.g., `const Story = {};`)
|
// Skip declarations (e.g., `const Story = {};`)
|
||||||
@ -162,14 +167,15 @@ export async function storyToCsfFactory(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Skip export statements e.g.`export const Story` or `export { Story }`
|
// Skip export statements e.g.`export const Story` or `export { Story }`
|
||||||
if (t.isExportSpecifier(parent)) {
|
if (t.isExportSpecifier(parent) || t.isExportDefaultDeclaration(parent)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip if it's already `Story.input`
|
// Skip if it's already `Story.input` or `meta.input`
|
||||||
if (t.isMemberExpression(parent) && t.isIdentifier(parent.property, { name: 'input' })) {
|
if (t.isMemberExpression(parent) && t.isIdentifier(parent.property, { name: 'input' })) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the property name is in the disallow list
|
// Check if the property name is in the disallow list
|
||||||
if (
|
if (
|
||||||
t.isMemberExpression(parent) &&
|
t.isMemberExpression(parent) &&
|
||||||
@ -180,9 +186,9 @@ export async function storyToCsfFactory(
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Replace the identifier with `Story.input`
|
// Replace the identifier with `Story.input` or `meta.input`
|
||||||
nodePath.replaceWith(
|
nodePath.replaceWith(
|
||||||
t.memberExpression(t.identifier(nodePath.node.name), t.identifier('input'))
|
t.memberExpression(t.identifier(identifierName), t.identifier('input'))
|
||||||
);
|
);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
// This is a tough one to support, we just skip for now.
|
// This is a tough one to support, we just skip for now.
|
||||||
|
@ -250,19 +250,51 @@ export const doUpgrade = async ({
|
|||||||
const upgradedDependencies = toUpgradedDependencies(packageJson.dependencies);
|
const upgradedDependencies = toUpgradedDependencies(packageJson.dependencies);
|
||||||
const upgradedDevDependencies = toUpgradedDependencies(packageJson.devDependencies);
|
const upgradedDevDependencies = toUpgradedDependencies(packageJson.devDependencies);
|
||||||
|
|
||||||
|
// Users struggle to upgrade Storybook with npm because of conflicting peer-dependencies
|
||||||
|
// GitHub Issue: https://github.com/storybookjs/storybook/issues/30306
|
||||||
|
// Solution: Remove all Storybook packages (except 'storybook') from the package.json and install them again
|
||||||
|
if (packageManager.type === 'npm') {
|
||||||
|
const getPackageName = (dep: string) => {
|
||||||
|
const lastAtIndex = dep.lastIndexOf('@');
|
||||||
|
return lastAtIndex > 0 ? dep.slice(0, lastAtIndex) : dep;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Remove all Storybook packages except 'storybook'
|
||||||
|
await packageManager.removeDependencies(
|
||||||
|
{ skipInstall: false },
|
||||||
|
[...upgradedDependencies, ...upgradedDevDependencies]
|
||||||
|
.map(getPackageName)
|
||||||
|
.filter((dep) => dep !== 'storybook')
|
||||||
|
);
|
||||||
|
|
||||||
|
// Handle 'storybook' package separately to maintain peer dependencies
|
||||||
|
const findStorybookPackage = (deps: string[]) =>
|
||||||
|
deps.find((dep) => getPackageName(dep) === 'storybook');
|
||||||
|
|
||||||
|
const storybookDep = findStorybookPackage(upgradedDependencies);
|
||||||
|
const storybookDevDep = findStorybookPackage(upgradedDevDependencies);
|
||||||
|
|
||||||
|
if (storybookDep) {
|
||||||
|
await packageManager.addDependencies({ installAsDevDependencies: false }, [storybookDep]);
|
||||||
|
}
|
||||||
|
if (storybookDevDep) {
|
||||||
|
await packageManager.addDependencies({ installAsDevDependencies: true }, [storybookDevDep]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update all dependencies
|
||||||
logger.info(`Updating dependencies in ${picocolors.cyan('package.json')}..`);
|
logger.info(`Updating dependencies in ${picocolors.cyan('package.json')}..`);
|
||||||
if (upgradedDependencies.length > 0) {
|
const addDeps = async (deps: string[], isDev: boolean) => {
|
||||||
await packageManager.addDependencies(
|
if (deps.length > 0) {
|
||||||
{ installAsDevDependencies: false, skipInstall: true, packageJson },
|
await packageManager.addDependencies(
|
||||||
upgradedDependencies
|
{ installAsDevDependencies: isDev, skipInstall: true, packageJson },
|
||||||
);
|
deps
|
||||||
}
|
);
|
||||||
if (upgradedDevDependencies.length > 0) {
|
}
|
||||||
await packageManager.addDependencies(
|
};
|
||||||
{ installAsDevDependencies: true, skipInstall: true, packageJson },
|
|
||||||
upgradedDevDependencies
|
await addDeps(upgradedDependencies, false);
|
||||||
);
|
await addDeps(upgradedDevDependencies, true);
|
||||||
}
|
|
||||||
await packageManager.installDependencies();
|
await packageManager.installDependencies();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/codemod",
|
"name": "@storybook/codemod",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "A collection of codemod scripts written with JSCodeshift",
|
"description": "A collection of codemod scripts written with JSCodeshift",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/core-webpack",
|
"name": "@storybook/core-webpack",
|
||||||
"version": "8.6.0-beta.4",
|
"version": "8.6.0-beta.8",
|
||||||
"description": "Storybook framework-agnostic API",
|
"description": "Storybook framework-agnostic API",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user