mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-08 07:52:07 +08:00
feat(angular): componentWrapperDecorator accept props
Note : compatible with StoryContext (args, globals, ...)
This commit is contained in:
parent
3ba763afc2
commit
3d11436e8f
@ -2,6 +2,7 @@ import { Component, EventEmitter, Input, NgModule, Output, Type } from '@angular
|
|||||||
|
|
||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed } from '@angular/core/testing';
|
||||||
import { BehaviorSubject } from 'rxjs';
|
import { BehaviorSubject } from 'rxjs';
|
||||||
|
import { ICollection } from '../types';
|
||||||
import { getStorybookModuleMetadata } from './StorybookModule';
|
import { getStorybookModuleMetadata } from './StorybookModule';
|
||||||
|
|
||||||
describe('StorybookModule', () => {
|
describe('StorybookModule', () => {
|
||||||
@ -132,7 +133,7 @@ describe('StorybookModule', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not override outputs if storyProps$ Subject emit', async () => {
|
it('should override outputs if storyProps$ Subject emit', async () => {
|
||||||
let expectedOutputValue;
|
let expectedOutputValue;
|
||||||
let expectedOutputBindingValue;
|
let expectedOutputBindingValue;
|
||||||
const initialProps = {
|
const initialProps = {
|
||||||
@ -155,10 +156,10 @@ describe('StorybookModule', () => {
|
|||||||
const newProps = {
|
const newProps = {
|
||||||
input: 'new input',
|
input: 'new input',
|
||||||
output: () => {
|
output: () => {
|
||||||
expectedOutputValue = 'should not be called';
|
expectedOutputValue = 'should be called';
|
||||||
},
|
},
|
||||||
outputBindingPropertyName: () => {
|
outputBindingPropertyName: () => {
|
||||||
expectedOutputBindingValue = 'should not be called';
|
expectedOutputBindingValue = 'should be called';
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
storyProps$.next(newProps);
|
storyProps$.next(newProps);
|
||||||
@ -168,8 +169,43 @@ describe('StorybookModule', () => {
|
|||||||
fixture.nativeElement.querySelector('p#outputBindingPropertyName').click();
|
fixture.nativeElement.querySelector('p#outputBindingPropertyName').click();
|
||||||
|
|
||||||
expect(fixture.nativeElement.querySelector('p#input').innerHTML).toEqual(newProps.input);
|
expect(fixture.nativeElement.querySelector('p#input').innerHTML).toEqual(newProps.input);
|
||||||
expect(expectedOutputValue).toEqual('outputEmitted');
|
expect(expectedOutputValue).toEqual('should be called');
|
||||||
expect(expectedOutputBindingValue).toEqual('outputEmitted');
|
expect(expectedOutputBindingValue).toEqual('should be called');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should change template inputs if storyProps$ Subject emit', async () => {
|
||||||
|
const initialProps = {
|
||||||
|
color: 'red',
|
||||||
|
input: 'input',
|
||||||
|
};
|
||||||
|
const storyProps$ = new BehaviorSubject<ICollection>(initialProps);
|
||||||
|
|
||||||
|
const ngModule = getStorybookModuleMetadata(
|
||||||
|
{
|
||||||
|
storyFnAngular: {
|
||||||
|
props: initialProps,
|
||||||
|
template: '<p [style.color]="color"><foo [input]="input"></foo></p>',
|
||||||
|
},
|
||||||
|
parameters: { component: FooComponent },
|
||||||
|
},
|
||||||
|
storyProps$
|
||||||
|
);
|
||||||
|
const { fixture } = await configureTestingModule(ngModule);
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(fixture.nativeElement.querySelector('p').style.color).toEqual('red');
|
||||||
|
expect(fixture.nativeElement.querySelector('p#input').innerHTML).toEqual(
|
||||||
|
initialProps.input
|
||||||
|
);
|
||||||
|
|
||||||
|
const newProps = {
|
||||||
|
color: 'black',
|
||||||
|
input: 'new input',
|
||||||
|
};
|
||||||
|
storyProps$.next(newProps);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(fixture.nativeElement.querySelector('p').style.color).toEqual('black');
|
||||||
|
expect(fixture.nativeElement.querySelector('p#input').innerHTML).toEqual(newProps.input);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -48,19 +48,30 @@ export const createStorybookWrapperComponent = (
|
|||||||
styles,
|
styles,
|
||||||
})
|
})
|
||||||
class StorybookWrapperComponent implements AfterViewInit, OnDestroy {
|
class StorybookWrapperComponent implements AfterViewInit, OnDestroy {
|
||||||
private storyPropsSubscription: Subscription;
|
private storyComponentPropsSubscription: Subscription;
|
||||||
|
|
||||||
|
private storyWrapperPropsSubscription: Subscription;
|
||||||
|
|
||||||
@ViewChild(storyComponent ?? '', { static: true }) storyComponentElementRef: ElementRef;
|
@ViewChild(storyComponent ?? '', { static: true }) storyComponentElementRef: ElementRef;
|
||||||
|
|
||||||
@ViewChild(storyComponent ?? '', { read: ViewContainerRef, static: true })
|
@ViewChild(storyComponent ?? '', { read: ViewContainerRef, static: true })
|
||||||
storyComponentViewContainerRef: ViewContainerRef;
|
storyComponentViewContainerRef: ViewContainerRef;
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-useless-constructor
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(STORY_PROPS) private storyProps$: Subject<ICollection | undefined>,
|
@Inject(STORY_PROPS) private storyProps$: Subject<ICollection | undefined>,
|
||||||
private changeDetectorRef: ChangeDetectorRef
|
private changeDetectorRef: ChangeDetectorRef
|
||||||
) {
|
) {}
|
||||||
// Initializes Inputs/Outputs values
|
|
||||||
Object.assign(this, initialProps);
|
ngOnInit(): void {
|
||||||
|
// Subscribes to the observable storyProps$ to keep these properties up to date
|
||||||
|
this.storyWrapperPropsSubscription = this.storyProps$.subscribe((storyProps = {}) => {
|
||||||
|
// All props are added as component properties
|
||||||
|
Object.assign(this, storyProps);
|
||||||
|
|
||||||
|
this.changeDetectorRef.detectChanges();
|
||||||
|
this.changeDetectorRef.markForCheck();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit(): void {
|
ngAfterViewInit(): void {
|
||||||
@ -81,7 +92,7 @@ export const createStorybookWrapperComponent = (
|
|||||||
this.changeDetectorRef.detectChanges();
|
this.changeDetectorRef.detectChanges();
|
||||||
|
|
||||||
// Once target component has been initialized, the storyProps$ observable keeps target component inputs up to date
|
// Once target component has been initialized, the storyProps$ observable keeps target component inputs up to date
|
||||||
this.storyPropsSubscription = this.storyProps$
|
this.storyComponentPropsSubscription = this.storyProps$
|
||||||
.pipe(
|
.pipe(
|
||||||
skip(1),
|
skip(1),
|
||||||
map((props) => {
|
map((props) => {
|
||||||
@ -128,8 +139,11 @@ export const createStorybookWrapperComponent = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
if (this.storyPropsSubscription != null) {
|
if (this.storyComponentPropsSubscription != null) {
|
||||||
this.storyPropsSubscription.unsubscribe();
|
this.storyComponentPropsSubscription.unsubscribe();
|
||||||
|
}
|
||||||
|
if (this.storyWrapperPropsSubscription != null) {
|
||||||
|
this.storyWrapperPropsSubscription.unsubscribe();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
/* eslint-disable no-param-reassign */
|
/* eslint-disable no-param-reassign */
|
||||||
import { Type } from '@angular/core';
|
import { Type } from '@angular/core';
|
||||||
import { DecoratorFunction } from '@storybook/addons';
|
import { DecoratorFunction, StoryContext } from '@storybook/addons';
|
||||||
import { computesTemplateFromComponent } from '../angular-beta/ComputesTemplateFromComponent';
|
import { computesTemplateFromComponent } from '../angular-beta/ComputesTemplateFromComponent';
|
||||||
import { isComponent } from '../angular-beta/utils/NgComponentAnalyzer';
|
import { isComponent } from '../angular-beta/utils/NgComponentAnalyzer';
|
||||||
import { NgModuleMetadata, StoryFnAngularReturnType } from '../types';
|
import { ICollection, NgModuleMetadata, StoryFnAngularReturnType } from '../types';
|
||||||
|
|
||||||
export const moduleMetadata = (metadata: Partial<NgModuleMetadata>) => (storyFn: () => any) => {
|
export const moduleMetadata = (metadata: Partial<NgModuleMetadata>) => (storyFn: () => any) => {
|
||||||
const story = storyFn();
|
const story = storyFn();
|
||||||
@ -26,13 +26,26 @@ export const moduleMetadata = (metadata: Partial<NgModuleMetadata>) => (storyFn:
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const componentWrapperDecorator = (
|
export const componentWrapperDecorator = (
|
||||||
element: Type<unknown> | ((story: string) => string)
|
element: Type<unknown> | ((story: string) => string),
|
||||||
): DecoratorFunction<StoryFnAngularReturnType> => (storyFn) => {
|
props?: ICollection | ((storyContext: StoryContext) => ICollection)
|
||||||
|
): DecoratorFunction<StoryFnAngularReturnType> => (storyFn, storyContext) => {
|
||||||
const story = storyFn();
|
const story = storyFn();
|
||||||
|
const currentProps = typeof props === 'function' ? (props(storyContext) as ICollection) : props;
|
||||||
|
|
||||||
const template = isComponent(element)
|
const template = isComponent(element)
|
||||||
? computesTemplateFromComponent(element, {}, story.template)
|
? computesTemplateFromComponent(element, currentProps ?? {}, story.template)
|
||||||
: element(story.template);
|
: element(story.template);
|
||||||
|
|
||||||
return { ...story, template };
|
return {
|
||||||
|
...story,
|
||||||
|
template,
|
||||||
|
...(currentProps || story.props
|
||||||
|
? {
|
||||||
|
props: {
|
||||||
|
...currentProps,
|
||||||
|
...story.props,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component, Input, Output } from '@angular/core';
|
||||||
import { DecoratorFunction, StoryContext } from '@storybook/addons';
|
import { DecoratorFunction, StoryContext } from '@storybook/addons';
|
||||||
import { componentWrapperDecorator } from './angular/decorators';
|
import { componentWrapperDecorator } from './angular/decorators';
|
||||||
|
|
||||||
@ -7,6 +7,77 @@ import { StoryFnAngularReturnType } from './types';
|
|||||||
|
|
||||||
describe('decorateStory', () => {
|
describe('decorateStory', () => {
|
||||||
describe('angular behavior', () => {
|
describe('angular behavior', () => {
|
||||||
|
it('should use componentWrapperDecorator with args', () => {
|
||||||
|
const decorators: DecoratorFunction<StoryFnAngularReturnType>[] = [
|
||||||
|
componentWrapperDecorator(ParentComponent, ({ args }) => args),
|
||||||
|
componentWrapperDecorator(
|
||||||
|
(story) => `<grandparent [grandparentInput]="grandparentInput">${story}</grandparent>`,
|
||||||
|
({ args }) => args
|
||||||
|
),
|
||||||
|
componentWrapperDecorator((story) => `<great-grandparent>${story}</great-grandparent>`),
|
||||||
|
];
|
||||||
|
const decorated = decorateStory(() => ({ template: '</child>' }), decorators);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
decorated(
|
||||||
|
makeContext({
|
||||||
|
parameters: { component: FooComponent },
|
||||||
|
args: {
|
||||||
|
parentInput: 'Parent input',
|
||||||
|
grandparentInput: 'grandparent input',
|
||||||
|
parentOutput: () => {},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
).toEqual({
|
||||||
|
props: {
|
||||||
|
parentInput: 'Parent input',
|
||||||
|
grandparentInput: 'grandparent input',
|
||||||
|
parentOutput: expect.any(Function),
|
||||||
|
},
|
||||||
|
template:
|
||||||
|
'<great-grandparent><grandparent [grandparentInput]="grandparentInput"><parent [parentInput]="parentInput" (parentOutput)="parentOutput($event)"></child></parent></grandparent></great-grandparent>',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use componentWrapperDecorator with input / output', () => {
|
||||||
|
const decorators: DecoratorFunction<StoryFnAngularReturnType>[] = [
|
||||||
|
componentWrapperDecorator(ParentComponent, {
|
||||||
|
parentInput: 'Parent input',
|
||||||
|
parentOutput: () => {},
|
||||||
|
}),
|
||||||
|
componentWrapperDecorator(
|
||||||
|
(story) => `<grandparent [grandparentInput]="grandparentInput">${story}</grandparent>`,
|
||||||
|
{
|
||||||
|
grandparentInput: 'Grandparent input',
|
||||||
|
sameInput: 'Should be override by story props',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
componentWrapperDecorator((story) => `<great-grandparent>${story}</great-grandparent>`),
|
||||||
|
];
|
||||||
|
const decorated = decorateStory(
|
||||||
|
() => ({ template: '</child>', props: { sameInput: 'Story input' } }),
|
||||||
|
decorators
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
decorated(
|
||||||
|
makeContext({
|
||||||
|
parameters: { component: FooComponent },
|
||||||
|
})
|
||||||
|
)
|
||||||
|
).toEqual({
|
||||||
|
props: {
|
||||||
|
parentInput: 'Parent input',
|
||||||
|
parentOutput: expect.any(Function),
|
||||||
|
grandparentInput: 'Grandparent input',
|
||||||
|
sameInput: 'Story input',
|
||||||
|
},
|
||||||
|
template:
|
||||||
|
'<great-grandparent><grandparent [grandparentInput]="grandparentInput"><parent [parentInput]="parentInput" (parentOutput)="parentOutput($event)"></child></parent></grandparent></great-grandparent>',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should use componentWrapperDecorator', () => {
|
it('should use componentWrapperDecorator', () => {
|
||||||
const decorators: DecoratorFunction<StoryFnAngularReturnType>[] = [
|
const decorators: DecoratorFunction<StoryFnAngularReturnType>[] = [
|
||||||
componentWrapperDecorator(ParentComponent),
|
componentWrapperDecorator(ParentComponent),
|
||||||
@ -249,4 +320,10 @@ class FooComponent {}
|
|||||||
selector: 'parent',
|
selector: 'parent',
|
||||||
template: `<ng-content></ng-content>`,
|
template: `<ng-content></ng-content>`,
|
||||||
})
|
})
|
||||||
class ParentComponent {}
|
class ParentComponent {
|
||||||
|
@Input()
|
||||||
|
parentInput: string;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
parentOutput: any;
|
||||||
|
}
|
||||||
|
@ -39,6 +39,86 @@ exports[`Storyshots Core / Decorators With Component 1`] = `
|
|||||||
</storybook-wrapper>
|
</storybook-wrapper>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`Storyshots Core / Decorators With Component Decorator And Args 1`] = `
|
||||||
|
<storybook-wrapper>
|
||||||
|
Grandparent<br /><div
|
||||||
|
style="margin: 3em; border:solid;"
|
||||||
|
>
|
||||||
|
<parent-component>
|
||||||
|
Parent
|
||||||
|
<br />
|
||||||
|
Input text:
|
||||||
|
<br />
|
||||||
|
Output :
|
||||||
|
<button>
|
||||||
|
Click here !
|
||||||
|
</button>
|
||||||
|
<br />
|
||||||
|
<div
|
||||||
|
style="margin: 3em; border:solid;"
|
||||||
|
>
|
||||||
|
<child-component
|
||||||
|
ng-reflect-child-text="Child text"
|
||||||
|
>
|
||||||
|
Child
|
||||||
|
<br />
|
||||||
|
Input text: Child text
|
||||||
|
<br />
|
||||||
|
Output :
|
||||||
|
<button>
|
||||||
|
Click here !
|
||||||
|
</button>
|
||||||
|
<br />
|
||||||
|
Private text: Child private text
|
||||||
|
<br />
|
||||||
|
</child-component>
|
||||||
|
</div>
|
||||||
|
</parent-component>
|
||||||
|
</div>
|
||||||
|
</storybook-wrapper>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Storyshots Core / Decorators With Component Decorator And Props 1`] = `
|
||||||
|
<storybook-wrapper>
|
||||||
|
Grandparent<br /><div
|
||||||
|
style="margin: 3em; border:solid;"
|
||||||
|
>
|
||||||
|
<parent-component
|
||||||
|
ng-reflect-parent-text="Parent text"
|
||||||
|
>
|
||||||
|
Parent
|
||||||
|
<br />
|
||||||
|
Input text: Parent text
|
||||||
|
<br />
|
||||||
|
Output :
|
||||||
|
<button>
|
||||||
|
Click here !
|
||||||
|
</button>
|
||||||
|
<br />
|
||||||
|
<div
|
||||||
|
style="margin: 3em; border:solid;"
|
||||||
|
>
|
||||||
|
<child-component
|
||||||
|
ng-reflect-child-text="Child text"
|
||||||
|
>
|
||||||
|
Child
|
||||||
|
<br />
|
||||||
|
Input text: Child text
|
||||||
|
<br />
|
||||||
|
Output :
|
||||||
|
<button>
|
||||||
|
Click here !
|
||||||
|
</button>
|
||||||
|
<br />
|
||||||
|
Private text: Child private text
|
||||||
|
<br />
|
||||||
|
</child-component>
|
||||||
|
</div>
|
||||||
|
</parent-component>
|
||||||
|
</div>
|
||||||
|
</storybook-wrapper>
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`Storyshots Core / Decorators With Component Wrapper Decorator 1`] = `
|
exports[`Storyshots Core / Decorators With Component Wrapper Decorator 1`] = `
|
||||||
<storybook-wrapper>
|
<storybook-wrapper>
|
||||||
Grandparent<br /><div
|
Grandparent<br /><div
|
||||||
@ -78,6 +158,86 @@ exports[`Storyshots Core / Decorators With Component Wrapper Decorator 1`] = `
|
|||||||
</storybook-wrapper>
|
</storybook-wrapper>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`Storyshots Core / Decorators With Component Wrapper Decorator And Args 1`] = `
|
||||||
|
<storybook-wrapper>
|
||||||
|
Grandparent<br /><div
|
||||||
|
style="margin: 3em; border:solid;"
|
||||||
|
>
|
||||||
|
<parent-component>
|
||||||
|
Parent
|
||||||
|
<br />
|
||||||
|
Input text:
|
||||||
|
<br />
|
||||||
|
Output :
|
||||||
|
<button>
|
||||||
|
Click here !
|
||||||
|
</button>
|
||||||
|
<br />
|
||||||
|
<div
|
||||||
|
style="margin: 3em; border:solid;"
|
||||||
|
>
|
||||||
|
<child-component
|
||||||
|
ng-reflect-child-text="Child text"
|
||||||
|
>
|
||||||
|
Child
|
||||||
|
<br />
|
||||||
|
Input text: Child text
|
||||||
|
<br />
|
||||||
|
Output :
|
||||||
|
<button>
|
||||||
|
Click here !
|
||||||
|
</button>
|
||||||
|
<br />
|
||||||
|
Private text: Child private text
|
||||||
|
<br />
|
||||||
|
</child-component>
|
||||||
|
</div>
|
||||||
|
</parent-component>
|
||||||
|
</div>
|
||||||
|
</storybook-wrapper>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Storyshots Core / Decorators With Component Wrapper Decorator And Props 1`] = `
|
||||||
|
<storybook-wrapper>
|
||||||
|
Grandparent<br /><div
|
||||||
|
style="margin: 3em; border:solid;"
|
||||||
|
>
|
||||||
|
<parent-component
|
||||||
|
ng-reflect-parent-text="Parent text"
|
||||||
|
>
|
||||||
|
Parent
|
||||||
|
<br />
|
||||||
|
Input text: Parent text
|
||||||
|
<br />
|
||||||
|
Output :
|
||||||
|
<button>
|
||||||
|
Click here !
|
||||||
|
</button>
|
||||||
|
<br />
|
||||||
|
<div
|
||||||
|
style="margin: 3em; border:solid;"
|
||||||
|
>
|
||||||
|
<child-component
|
||||||
|
ng-reflect-child-text="Child text"
|
||||||
|
>
|
||||||
|
Child
|
||||||
|
<br />
|
||||||
|
Input text: Child text
|
||||||
|
<br />
|
||||||
|
Output :
|
||||||
|
<button>
|
||||||
|
Click here !
|
||||||
|
</button>
|
||||||
|
<br />
|
||||||
|
Private text: Child private text
|
||||||
|
<br />
|
||||||
|
</child-component>
|
||||||
|
</div>
|
||||||
|
</parent-component>
|
||||||
|
</div>
|
||||||
|
</storybook-wrapper>
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`Storyshots Core / Decorators With Custom Decorator 1`] = `
|
exports[`Storyshots Core / Decorators With Custom Decorator 1`] = `
|
||||||
<storybook-wrapper>
|
<storybook-wrapper>
|
||||||
Grandparent<br /><div
|
Grandparent<br /><div
|
||||||
|
@ -13,6 +13,7 @@ export default {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
args: { childText: 'Child text', childPrivateText: 'Child private text' },
|
args: { childText: 'Child text', childPrivateText: 'Child private text' },
|
||||||
|
argTypes: { onClickChild: { action: 'onClickChild' } },
|
||||||
} as Meta;
|
} as Meta;
|
||||||
|
|
||||||
export const WithTemplate = (args) => ({
|
export const WithTemplate = (args) => ({
|
||||||
@ -46,6 +47,40 @@ WithComponentWrapperDecorator.decorators = [
|
|||||||
componentWrapperDecorator(ParentComponent),
|
componentWrapperDecorator(ParentComponent),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const WithComponentWrapperDecoratorAndProps = (args) => ({
|
||||||
|
component: ChildComponent,
|
||||||
|
props: {
|
||||||
|
...args,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
WithComponentWrapperDecoratorAndProps.decorators = [
|
||||||
|
moduleMetadata({ declarations: [ParentComponent] }),
|
||||||
|
componentWrapperDecorator(ParentComponent, {
|
||||||
|
parentText: 'Parent text',
|
||||||
|
onClickParent: () => {
|
||||||
|
console.log('onClickParent');
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
export const WithComponentWrapperDecoratorAndArgs = (args) => ({
|
||||||
|
component: ChildComponent,
|
||||||
|
props: {
|
||||||
|
...args,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
WithComponentWrapperDecoratorAndArgs.argTypes = {
|
||||||
|
parentText: { control: { type: 'text' } },
|
||||||
|
onClickParent: { action: 'onClickParent' },
|
||||||
|
};
|
||||||
|
WithComponentWrapperDecoratorAndArgs.decorators = [
|
||||||
|
moduleMetadata({ declarations: [ParentComponent] }),
|
||||||
|
componentWrapperDecorator(ParentComponent, ({ args }) => ({
|
||||||
|
parentText: args.parentText,
|
||||||
|
onClickParent: args.onClickParent,
|
||||||
|
})),
|
||||||
|
];
|
||||||
|
|
||||||
export const WithCustomDecorator = (args) => ({
|
export const WithCustomDecorator = (args) => ({
|
||||||
template: `Child Template`,
|
template: `Child Template`,
|
||||||
props: {
|
props: {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user