mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-08 11:11:53 +08:00
Merge remote-tracking branch 'origin/next' into valentin/introduce-instances-vitest-3
This commit is contained in:
commit
678fb8fb5d
37
MIGRATION.md
37
MIGRATION.md
@ -1,7 +1,7 @@
|
|||||||
<h1>Migration</h1>
|
<h1>Migration</h1>
|
||||||
|
|
||||||
- [From version 8.4.x to 8.5.x](#from-version-84x-to-85x)
|
- [From version 8.5.x to 8.6.x](#from-version-85x-to-86x)
|
||||||
- [Introducing features.developmentModeForBuild](#introducing-featuresdevelopmentmodeforbuild)
|
- [Angular: Support experimental zoneless support](#angular-support-experimental-zoneless-support)
|
||||||
- [Added source code panel to docs](#added-source-code-panel-to-docs)
|
- [Added source code panel to docs](#added-source-code-panel-to-docs)
|
||||||
- [Addon-a11y: Component test integration](#addon-a11y-component-test-integration)
|
- [Addon-a11y: Component test integration](#addon-a11y-component-test-integration)
|
||||||
- [Addon-a11y: Changing the default element selector](#addon-a11y-changing-the-default-element-selector)
|
- [Addon-a11y: Changing the default element selector](#addon-a11y-changing-the-default-element-selector)
|
||||||
@ -427,6 +427,37 @@
|
|||||||
- [Packages renaming](#packages-renaming)
|
- [Packages renaming](#packages-renaming)
|
||||||
- [Deprecated embedded addons](#deprecated-embedded-addons)
|
- [Deprecated embedded addons](#deprecated-embedded-addons)
|
||||||
|
|
||||||
|
## From version 8.5.x to 8.6.x
|
||||||
|
|
||||||
|
### Angular: Support experimental zoneless support
|
||||||
|
|
||||||
|
Storybook now supports [Angular's experimental zoneless mode](https://angular.dev/guide/experimental/zoneless). This mode is intended to improve performance by removing Angular's zone.js dependency. To enable zoneless mode in your Angular Storybook, set the `experimentalZoneless` config in your `angular.json` file:
|
||||||
|
|
||||||
|
````diff
|
||||||
|
{
|
||||||
|
"projects": {
|
||||||
|
"your-project": {
|
||||||
|
"architect": {
|
||||||
|
"storybook": {
|
||||||
|
...
|
||||||
|
"options": {
|
||||||
|
...
|
||||||
|
+ "experimentalZoneless": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"build-storybook": {
|
||||||
|
...
|
||||||
|
"options": {
|
||||||
|
...
|
||||||
|
+ "experimentalZoneless": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## From version 8.4.x to 8.5.x
|
## From version 8.4.x to 8.5.x
|
||||||
|
|
||||||
### Introducing features.developmentModeForBuild
|
### Introducing features.developmentModeForBuild
|
||||||
@ -442,7 +473,7 @@ export default {
|
|||||||
developmentModeForBuild: true,
|
developmentModeForBuild: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
```
|
````
|
||||||
|
|
||||||
### Added source code panel to docs
|
### Added source code panel to docs
|
||||||
|
|
||||||
|
@ -58,27 +58,28 @@
|
|||||||
"webpack": "5"
|
"webpack": "5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@analogjs/vite-plugin-angular": "^0.2.24",
|
"@analogjs/vite-plugin-angular": "^1.12.1",
|
||||||
"@angular-devkit/architect": "^0.1703.0",
|
"@angular-devkit/architect": "^0.1901.1",
|
||||||
"@angular-devkit/build-angular": "^17.3.0",
|
"@angular-devkit/build-angular": "^19.1.1",
|
||||||
"@angular-devkit/core": "^17.3.0",
|
"@angular-devkit/core": "^19.1.1",
|
||||||
"@angular/animations": "^17.3.0",
|
"@angular/animations": "^19.1.1",
|
||||||
"@angular/cli": "^17.3.0",
|
"@angular/cli": "^19.1.1",
|
||||||
"@angular/common": "^17.3.0",
|
"@angular/common": "^19.1.1",
|
||||||
"@angular/compiler": "^17.3.0",
|
"@angular/compiler": "^19.1.1",
|
||||||
"@angular/compiler-cli": "^17.3.0",
|
"@angular/compiler-cli": "^19.1.1",
|
||||||
"@angular/core": "^17.3.0",
|
"@angular/core": "^19.1.1",
|
||||||
"@angular/forms": "^17.3.0",
|
"@angular/forms": "^19.1.1",
|
||||||
"@angular/platform-browser": "^17.3.0",
|
"@angular/platform-browser": "^19.1.1",
|
||||||
"@angular/platform-browser-dynamic": "^17.3.0",
|
"@angular/platform-browser-dynamic": "^19.1.1",
|
||||||
"@types/cross-spawn": "^6.0.2",
|
"@types/cross-spawn": "^6.0.2",
|
||||||
"@types/node": "^22.0.0",
|
"@types/node": "^22.0.0",
|
||||||
"@types/tmp": "^0.2.3",
|
"@types/tmp": "^0.2.3",
|
||||||
"cross-spawn": "^7.0.3",
|
"cross-spawn": "^7.0.3",
|
||||||
|
"rimraf": "^6.0.1",
|
||||||
"tmp": "^0.2.1",
|
"tmp": "^0.2.1",
|
||||||
"typescript": "^5.3.2",
|
"typescript": "^5.3.2",
|
||||||
"webpack": "5",
|
"webpack": "5",
|
||||||
"zone.js": "^0.14.2"
|
"zone.js": "^0.15.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@angular-devkit/architect": ">=0.1500.0 < 0.2000.0",
|
"@angular-devkit/architect": ">=0.1500.0 < 0.2000.0",
|
||||||
@ -100,6 +101,9 @@
|
|||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
"@angular/cli": {
|
"@angular/cli": {
|
||||||
"optional": true
|
"optional": true
|
||||||
|
},
|
||||||
|
"zone.js": {
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -43,6 +43,7 @@ export type StorybookBuilderOptions = JsonObject & {
|
|||||||
preserveSymlinks?: boolean;
|
preserveSymlinks?: boolean;
|
||||||
assets?: AssetPattern[];
|
assets?: AssetPattern[];
|
||||||
sourceMap?: SourceMapUnion;
|
sourceMap?: SourceMapUnion;
|
||||||
|
experimentalZoneless?: boolean;
|
||||||
} & Pick<
|
} & Pick<
|
||||||
// makes sure the option exists
|
// makes sure the option exists
|
||||||
CLIOptions,
|
CLIOptions,
|
||||||
@ -104,6 +105,7 @@ const commandBuilder: BuilderHandlerFn<StorybookBuilderOptions> = (
|
|||||||
previewUrl,
|
previewUrl,
|
||||||
sourceMap = false,
|
sourceMap = false,
|
||||||
preserveSymlinks = false,
|
preserveSymlinks = false,
|
||||||
|
experimentalZoneless = false,
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
const standaloneOptions: StandaloneBuildOptions = {
|
const standaloneOptions: StandaloneBuildOptions = {
|
||||||
@ -124,6 +126,7 @@ const commandBuilder: BuilderHandlerFn<StorybookBuilderOptions> = (
|
|||||||
...(assets ? { assets } : {}),
|
...(assets ? { assets } : {}),
|
||||||
sourceMap,
|
sourceMap,
|
||||||
preserveSymlinks,
|
preserveSymlinks,
|
||||||
|
experimentalZoneless,
|
||||||
},
|
},
|
||||||
tsConfig,
|
tsConfig,
|
||||||
webpackStatsJson,
|
webpackStatsJson,
|
||||||
|
@ -121,6 +121,11 @@
|
|||||||
"type": ["boolean", "object"],
|
"type": ["boolean", "object"],
|
||||||
"description": "Configure sourcemaps. See: https://angular.io/guide/workspace-config#source-map-configuration",
|
"description": "Configure sourcemaps. See: https://angular.io/guide/workspace-config#source-map-configuration",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"experimentalZoneless": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Experimental: Use zoneless change detection.",
|
||||||
|
"default": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
@ -40,6 +40,7 @@ export type StorybookBuilderOptions = JsonObject & {
|
|||||||
assets?: AssetPattern[];
|
assets?: AssetPattern[];
|
||||||
preserveSymlinks?: boolean;
|
preserveSymlinks?: boolean;
|
||||||
sourceMap?: SourceMapUnion;
|
sourceMap?: SourceMapUnion;
|
||||||
|
experimentalZoneless?: boolean;
|
||||||
} & Pick<
|
} & Pick<
|
||||||
// makes sure the option exists
|
// makes sure the option exists
|
||||||
CLIOptions,
|
CLIOptions,
|
||||||
@ -121,6 +122,7 @@ const commandBuilder: BuilderHandlerFn<StorybookBuilderOptions> = (options, cont
|
|||||||
previewUrl,
|
previewUrl,
|
||||||
sourceMap = false,
|
sourceMap = false,
|
||||||
preserveSymlinks = false,
|
preserveSymlinks = false,
|
||||||
|
experimentalZoneless = false,
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
const standaloneOptions: StandaloneOptions = {
|
const standaloneOptions: StandaloneOptions = {
|
||||||
@ -146,6 +148,7 @@ const commandBuilder: BuilderHandlerFn<StorybookBuilderOptions> = (options, cont
|
|||||||
...(assets ? { assets } : {}),
|
...(assets ? { assets } : {}),
|
||||||
preserveSymlinks,
|
preserveSymlinks,
|
||||||
sourceMap,
|
sourceMap,
|
||||||
|
experimentalZoneless,
|
||||||
},
|
},
|
||||||
tsConfig,
|
tsConfig,
|
||||||
initialPath,
|
initialPath,
|
||||||
|
@ -157,6 +157,11 @@
|
|||||||
"type": ["boolean", "object"],
|
"type": ["boolean", "object"],
|
||||||
"description": "Configure sourcemaps. See: https://angular.io/guide/workspace-config#source-map-configuration",
|
"description": "Configure sourcemaps. See: https://angular.io/guide/workspace-config#source-map-configuration",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"experimentalZoneless": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Experimental: Use zoneless change detection.",
|
||||||
|
"default": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
@ -20,6 +20,7 @@ export type StandaloneOptions = CLIOptions &
|
|||||||
assets?: AssetPattern[];
|
assets?: AssetPattern[];
|
||||||
sourceMap?: SourceMapUnion;
|
sourceMap?: SourceMapUnion;
|
||||||
preserveSymlinks?: boolean;
|
preserveSymlinks?: boolean;
|
||||||
|
experimentalZoneless?: boolean;
|
||||||
};
|
};
|
||||||
angularBuilderContext?: BuilderContext | null;
|
angularBuilderContext?: BuilderContext | null;
|
||||||
tsConfig?: string;
|
tsConfig?: string;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ApplicationRef, NgModule, enableProdMode } from '@angular/core';
|
import { ApplicationRef, NgModule } from '@angular/core';
|
||||||
import { bootstrapApplication } from '@angular/platform-browser';
|
import { bootstrapApplication } from '@angular/platform-browser';
|
||||||
import { BehaviorSubject, Subject } from 'rxjs';
|
import { BehaviorSubject, Subject } from 'rxjs';
|
||||||
import { stringify } from 'telejson';
|
import { stringify } from 'telejson';
|
||||||
@ -14,6 +14,12 @@ type StoryRenderInfo = {
|
|||||||
moduleMetadataSnapshot: string;
|
moduleMetadataSnapshot: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
const STORYBOOK_ANGULAR_OPTIONS: {
|
||||||
|
experimentalZoneless: boolean;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const applicationRefs = new Map<HTMLElement, ApplicationRef>();
|
const applicationRefs = new Map<HTMLElement, ApplicationRef>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -112,14 +118,25 @@ export abstract class AbstractRenderer {
|
|||||||
analyzedMetadata,
|
analyzedMetadata,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const providers = [
|
||||||
|
storyPropsProvider(newStoryProps$),
|
||||||
|
...analyzedMetadata.applicationProviders,
|
||||||
|
...(storyFnAngular.applicationConfig?.providers ?? []),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (STORYBOOK_ANGULAR_OPTIONS?.experimentalZoneless) {
|
||||||
|
const { provideExperimentalZonelessChangeDetection } = await import('@angular/core');
|
||||||
|
if (!provideExperimentalZonelessChangeDetection) {
|
||||||
|
throw new Error('Experimental zoneless change detection requires Angular 18 or higher');
|
||||||
|
} else {
|
||||||
|
providers.unshift(provideExperimentalZonelessChangeDetection());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const applicationRef = await queueBootstrapping(() => {
|
const applicationRef = await queueBootstrapping(() => {
|
||||||
return bootstrapApplication(application, {
|
return bootstrapApplication(application, {
|
||||||
...storyFnAngular.applicationConfig,
|
...storyFnAngular.applicationConfig,
|
||||||
providers: [
|
providers,
|
||||||
storyPropsProvider(newStoryProps$),
|
|
||||||
...analyzedMetadata.applicationProviders,
|
|
||||||
...(storyFnAngular.applicationConfig?.providers ?? []),
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@ describe('RendererFactory', () => {
|
|||||||
rootDocstargetDOMNode = global.document.getElementById('root-docs');
|
rootDocstargetDOMNode = global.document.getElementById('root-docs');
|
||||||
(platformBrowserDynamic as any).mockImplementation(platformBrowserDynamicTesting);
|
(platformBrowserDynamic as any).mockImplementation(platformBrowserDynamicTesting);
|
||||||
vi.spyOn(console, 'log').mockImplementation(() => {});
|
vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||||
|
// @ts-expect-error Ignore
|
||||||
|
globalThis.STORYBOOK_ANGULAR_OPTIONS = { experimentalZoneless: false };
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
@ -11,6 +11,8 @@ import {
|
|||||||
Input,
|
Input,
|
||||||
Output,
|
Output,
|
||||||
Pipe,
|
Pipe,
|
||||||
|
input,
|
||||||
|
output,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed } from '@angular/core/testing';
|
||||||
import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing';
|
import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing';
|
||||||
@ -26,7 +28,9 @@ import {
|
|||||||
|
|
||||||
describe('getComponentInputsOutputs', () => {
|
describe('getComponentInputsOutputs', () => {
|
||||||
it('should return empty if no I/O found', () => {
|
it('should return empty if no I/O found', () => {
|
||||||
@Component({})
|
@Component({
|
||||||
|
standalone: false,
|
||||||
|
})
|
||||||
class FooComponent {}
|
class FooComponent {}
|
||||||
|
|
||||||
expect(getComponentInputsOutputs(FooComponent)).toEqual({
|
expect(getComponentInputsOutputs(FooComponent)).toEqual({
|
||||||
@ -47,11 +51,18 @@ describe('getComponentInputsOutputs', () => {
|
|||||||
template: '',
|
template: '',
|
||||||
inputs: ['inputInComponentMetadata'],
|
inputs: ['inputInComponentMetadata'],
|
||||||
outputs: ['outputInComponentMetadata'],
|
outputs: ['outputInComponentMetadata'],
|
||||||
|
standalone: false,
|
||||||
})
|
})
|
||||||
class FooComponent {
|
class FooComponent {
|
||||||
@Input()
|
@Input()
|
||||||
public input: string;
|
public input: string;
|
||||||
|
|
||||||
|
public signalInput = input<string>();
|
||||||
|
|
||||||
|
public signalInputAliased = input<string>('signalInputAliased', {
|
||||||
|
alias: 'signalInputAliasedAlias',
|
||||||
|
});
|
||||||
|
|
||||||
@Input('inputPropertyName')
|
@Input('inputPropertyName')
|
||||||
public inputWithBindingPropertyName: string;
|
public inputWithBindingPropertyName: string;
|
||||||
|
|
||||||
@ -60,6 +71,8 @@ describe('getComponentInputsOutputs', () => {
|
|||||||
|
|
||||||
@Output('outputPropertyName')
|
@Output('outputPropertyName')
|
||||||
public outputWithBindingPropertyName = new EventEmitter<Event>();
|
public outputWithBindingPropertyName = new EventEmitter<Event>();
|
||||||
|
|
||||||
|
public signalOutput = output<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
const fooComponentFactory = resolveComponentFactory(FooComponent);
|
const fooComponentFactory = resolveComponentFactory(FooComponent);
|
||||||
@ -79,7 +92,9 @@ describe('getComponentInputsOutputs', () => {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(sortByPropName(inputs)).toEqual(sortByPropName(fooComponentFactory.inputs));
|
expect(sortByPropName(inputs)).toEqual(
|
||||||
|
sortByPropName(fooComponentFactory.inputs.map(({ isSignal, ...rest }) => rest))
|
||||||
|
);
|
||||||
expect(sortByPropName(outputs)).toEqual(sortByPropName(fooComponentFactory.outputs));
|
expect(sortByPropName(outputs)).toEqual(sortByPropName(fooComponentFactory.outputs));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -88,6 +103,7 @@ describe('getComponentInputsOutputs', () => {
|
|||||||
template: '',
|
template: '',
|
||||||
inputs: ['input', 'inputWithBindingPropertyName'],
|
inputs: ['input', 'inputWithBindingPropertyName'],
|
||||||
outputs: ['outputWithBindingPropertyName'],
|
outputs: ['outputWithBindingPropertyName'],
|
||||||
|
standalone: false,
|
||||||
})
|
})
|
||||||
class FooComponent {
|
class FooComponent {
|
||||||
@Input()
|
@Input()
|
||||||
@ -107,13 +123,16 @@ describe('getComponentInputsOutputs', () => {
|
|||||||
|
|
||||||
const { inputs, outputs } = getComponentInputsOutputs(FooComponent);
|
const { inputs, outputs } = getComponentInputsOutputs(FooComponent);
|
||||||
|
|
||||||
expect(sortByPropName(inputs)).toEqual(sortByPropName(fooComponentFactory.inputs));
|
expect(sortByPropName(inputs)).toEqual(
|
||||||
|
sortByPropName(fooComponentFactory.inputs.map(({ isSignal, ...rest }) => rest))
|
||||||
|
);
|
||||||
expect(sortByPropName(outputs)).toEqual(sortByPropName(fooComponentFactory.outputs));
|
expect(sortByPropName(outputs)).toEqual(sortByPropName(fooComponentFactory.outputs));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return I/O in the presence of multiple decorators', () => {
|
it('should return I/O in the presence of multiple decorators', () => {
|
||||||
@Component({
|
@Component({
|
||||||
template: '',
|
template: '',
|
||||||
|
standalone: false,
|
||||||
})
|
})
|
||||||
class FooComponent {
|
class FooComponent {
|
||||||
@Input()
|
@Input()
|
||||||
@ -137,13 +156,16 @@ describe('getComponentInputsOutputs', () => {
|
|||||||
outputs: [],
|
outputs: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(sortByPropName(inputs)).toEqual(sortByPropName(fooComponentFactory.inputs));
|
expect(sortByPropName(inputs)).toEqual(
|
||||||
|
sortByPropName(fooComponentFactory.inputs.map(({ isSignal, ...rest }) => rest))
|
||||||
|
);
|
||||||
expect(sortByPropName(outputs)).toEqual(sortByPropName(fooComponentFactory.outputs));
|
expect(sortByPropName(outputs)).toEqual(sortByPropName(fooComponentFactory.outputs));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return I/O with extending classes', () => {
|
it('should return I/O with extending classes', () => {
|
||||||
@Component({
|
@Component({
|
||||||
template: '',
|
template: '',
|
||||||
|
standalone: false,
|
||||||
})
|
})
|
||||||
class BarComponent {
|
class BarComponent {
|
||||||
@Input()
|
@Input()
|
||||||
@ -155,6 +177,7 @@ describe('getComponentInputsOutputs', () => {
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: '',
|
template: '',
|
||||||
|
standalone: false,
|
||||||
})
|
})
|
||||||
class FooComponent extends BarComponent {
|
class FooComponent extends BarComponent {
|
||||||
@Input()
|
@Input()
|
||||||
@ -177,7 +200,9 @@ describe('getComponentInputsOutputs', () => {
|
|||||||
outputs: [],
|
outputs: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(sortByPropName(inputs)).toEqual(sortByPropName(fooComponentFactory.inputs));
|
expect(sortByPropName(inputs)).toEqual(
|
||||||
|
sortByPropName(fooComponentFactory.inputs.map(({ isSignal, ...rest }) => rest))
|
||||||
|
);
|
||||||
expect(sortByPropName(outputs)).toEqual(sortByPropName(fooComponentFactory.outputs));
|
expect(sortByPropName(outputs)).toEqual(sortByPropName(fooComponentFactory.outputs));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -16,15 +16,13 @@ import { PropertyExtractor } from './PropertyExtractor';
|
|||||||
const TEST_TOKEN = new InjectionToken('testToken');
|
const TEST_TOKEN = new InjectionToken('testToken');
|
||||||
const TestTokenProvider = { provide: TEST_TOKEN, useValue: 123 };
|
const TestTokenProvider = { provide: TEST_TOKEN, useValue: 123 };
|
||||||
const TestService = Injectable()(class {});
|
const TestService = Injectable()(class {});
|
||||||
const TestComponent1 = Component({})(class {});
|
const TestComponent1 = Component({ standalone: false })(class {});
|
||||||
const TestComponent2 = Component({})(class {});
|
const TestComponent2 = Component({ standalone: false })(class {});
|
||||||
const StandaloneTestComponent = Component({ standalone: true })(class {});
|
const StandaloneTestComponent = Component({})(class {});
|
||||||
const StandaloneTestDirective = Directive({ standalone: true })(class {});
|
const StandaloneTestDirective = Directive({})(class {});
|
||||||
const MixedTestComponent1 = Component({ standalone: true })(
|
const MixedTestComponent1 = Component({})(class extends StandaloneTestComponent {});
|
||||||
class extends StandaloneTestComponent {}
|
const MixedTestComponent2 = Component({ standalone: false })(class extends MixedTestComponent1 {});
|
||||||
);
|
const MixedTestComponent3 = Component({})(class extends MixedTestComponent2 {});
|
||||||
const MixedTestComponent2 = Component({})(class extends MixedTestComponent1 {});
|
|
||||||
const MixedTestComponent3 = Component({ standalone: true })(class extends MixedTestComponent2 {});
|
|
||||||
const TestModuleWithDeclarations = NgModule({ declarations: [TestComponent1] })(class {});
|
const TestModuleWithDeclarations = NgModule({ declarations: [TestComponent1] })(class {});
|
||||||
const TestModuleWithImportsAndProviders = NgModule({
|
const TestModuleWithImportsAndProviders = NgModule({
|
||||||
imports: [TestModuleWithDeclarations],
|
imports: [TestModuleWithDeclarations],
|
||||||
|
@ -22,9 +22,6 @@ import { global } from '@storybook/global';
|
|||||||
*/
|
*/
|
||||||
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
||||||
|
|
||||||
/** Zone JS is required by Angular itself. */
|
|
||||||
import 'zone.js';
|
|
||||||
|
|
||||||
// Included with Angular CLI.
|
// Included with Angular CLI.
|
||||||
|
|
||||||
/** APPLICATION IMPORTS */
|
/** APPLICATION IMPORTS */
|
||||||
|
@ -3,7 +3,6 @@ import { PresetProperty } from 'storybook/internal/types';
|
|||||||
import { dirname, join } from 'node:path';
|
import { dirname, join } from 'node:path';
|
||||||
|
|
||||||
import { StandaloneOptions } from './builders/utils/standalone-options';
|
import { StandaloneOptions } from './builders/utils/standalone-options';
|
||||||
import { StorybookConfig } from './types';
|
|
||||||
|
|
||||||
const getAbsolutePath = <I extends string>(input: I): I =>
|
const getAbsolutePath = <I extends string>(input: I): I =>
|
||||||
dirname(require.resolve(join(input, 'package.json'))) as any;
|
dirname(require.resolve(join(input, 'package.json'))) as any;
|
||||||
|
@ -1,5 +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 { 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';
|
||||||
@ -21,13 +22,25 @@ export async function webpackFinal(baseConfig: webpack.Configuration, options: P
|
|||||||
const builderContext = getBuilderContext(options);
|
const builderContext = getBuilderContext(options);
|
||||||
const builderOptions = await getBuilderOptions(options, builderContext);
|
const builderOptions = await getBuilderOptions(options, builderContext);
|
||||||
|
|
||||||
return getCustomWebpackConfig(baseConfig, {
|
const webpackConfig = await getCustomWebpackConfig(baseConfig, {
|
||||||
builderOptions: {
|
builderOptions: {
|
||||||
watch: options.configType === 'DEVELOPMENT',
|
watch: options.configType === 'DEVELOPMENT',
|
||||||
...builderOptions,
|
...builderOptions,
|
||||||
},
|
} as any,
|
||||||
builderContext,
|
builderContext,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
webpackConfig.plugins = webpackConfig.plugins ?? [];
|
||||||
|
|
||||||
|
webpackConfig.plugins.push(
|
||||||
|
new WebpackDefinePlugin({
|
||||||
|
STORYBOOK_ANGULAR_OPTIONS: JSON.stringify({
|
||||||
|
experimentalZoneless: builderOptions.experimentalZoneless,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return webpackConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get Builder Context If storybook is not start by angular builder create dumb BuilderContext */
|
/** Get Builder Context If storybook is not start by angular builder create dumb BuilderContext */
|
||||||
@ -45,10 +58,7 @@ function getBuilderContext(options: PresetOptions): BuilderContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Get builder options Merge target options from browser target and from storybook options */
|
/** Get builder options Merge target options from browser target and from storybook options */
|
||||||
async function getBuilderOptions(
|
async function getBuilderOptions(options: PresetOptions, builderContext: BuilderContext) {
|
||||||
options: PresetOptions,
|
|
||||||
builderContext: BuilderContext
|
|
||||||
): Promise<JsonObject> {
|
|
||||||
/** Get Browser Target options */
|
/** Get Browser Target options */
|
||||||
let browserTargetOptions: JsonObject = {};
|
let browserTargetOptions: JsonObject = {};
|
||||||
if (options.angularBrowserTarget) {
|
if (options.angularBrowserTarget) {
|
||||||
@ -65,7 +75,7 @@ async function getBuilderOptions(
|
|||||||
/** Merge target options from browser target options and from storybook options */
|
/** Merge target options from browser target options and from storybook options */
|
||||||
const builderOptions = {
|
const builderOptions = {
|
||||||
...browserTargetOptions,
|
...browserTargetOptions,
|
||||||
...(options.angularBuilderOptions as JsonObject),
|
...options.angularBuilderOptions,
|
||||||
tsConfig:
|
tsConfig:
|
||||||
options.tsConfig ??
|
options.tsConfig ??
|
||||||
findUpSync('tsconfig.json', { cwd: options.configDir }) ??
|
findUpSync('tsconfig.json', { cwd: options.configDir }) ??
|
||||||
|
@ -1,17 +1,13 @@
|
|||||||
import { Options as CoreOptions } from 'storybook/internal/types';
|
import { Options as CoreOptions } from 'storybook/internal/types';
|
||||||
|
|
||||||
import { BuilderContext } from '@angular-devkit/architect';
|
import { BuilderContext } from '@angular-devkit/architect';
|
||||||
import { StylePreprocessorOptions } from '@angular-devkit/build-angular';
|
import { StandaloneOptions } from '../builders/utils/standalone-options';
|
||||||
import { StyleElement } from '@angular-devkit/build-angular/src/builders/browser/schema';
|
|
||||||
|
|
||||||
export type PresetOptions = CoreOptions & {
|
export type PresetOptions = CoreOptions & {
|
||||||
/* Allow to get the options of a targeted "browser builder" */
|
/* Allow to get the options of a targeted "browser builder" */
|
||||||
angularBrowserTarget?: string | null;
|
angularBrowserTarget?: string | null;
|
||||||
/* Defined set of options. These will take over priority from angularBrowserTarget options */
|
/* Defined set of options. These will take over priority from angularBrowserTarget options */
|
||||||
angularBuilderOptions?: {
|
angularBuilderOptions?: StandaloneOptions['angularBuilderOptions'];
|
||||||
styles?: StyleElement[];
|
|
||||||
stylePreprocessorOptions?: StylePreprocessorOptions;
|
|
||||||
};
|
|
||||||
/* Angular context from builder */
|
/* Angular context from builder */
|
||||||
angularBuilderContext?: BuilderContext | null;
|
angularBuilderContext?: BuilderContext | null;
|
||||||
tsConfig?: string;
|
tsConfig?: string;
|
||||||
|
@ -212,6 +212,7 @@
|
|||||||
"process": "^0.11.10",
|
"process": "^0.11.10",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
"rimraf": "^6.0.1",
|
||||||
"semver": "^7.3.7",
|
"semver": "^7.3.7",
|
||||||
"serve-static": "^1.14.1",
|
"serve-static": "^1.14.1",
|
||||||
"slash": "^5.0.0",
|
"slash": "^5.0.0",
|
||||||
|
5189
code/yarn.lock
5189
code/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user