mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-01 05:05:25 +08:00
Export decorateStory
from frameworks that have it.
And no longer emit warnings for exported `decorateStory` or `renderToDOM`
This commit is contained in:
parent
f521a74479
commit
d9483a05a8
@ -1,3 +1,4 @@
|
||||
export { render, renderToDOM } from './render';
|
||||
export { decorateStory } from './decorateStory';
|
||||
|
||||
export const parameters = { framework: 'angular' };
|
||||
|
@ -27,6 +27,8 @@ export default function decorateStory(
|
||||
return returnDecorators;
|
||||
}
|
||||
|
||||
export { decorateStory };
|
||||
|
||||
const prepareMain = (
|
||||
story: AngularFramework['storyResult'],
|
||||
context: StoryContext<AngularFramework>
|
||||
|
@ -1,3 +1,4 @@
|
||||
export { renderToDOM } from './render';
|
||||
export { decorateStory } from './decorators';
|
||||
|
||||
export const parameters = { framework: 'svelte' };
|
||||
|
@ -1,3 +1,4 @@
|
||||
export { renderToDOM } from './render';
|
||||
export { decorateStory } from './decorateStory';
|
||||
|
||||
export const parameters = { framework: 'vue' };
|
||||
|
85
app/vue/src/client/preview/decorateStory.ts
Normal file
85
app/vue/src/client/preview/decorateStory.ts
Normal file
@ -0,0 +1,85 @@
|
||||
import Vue, { VueConstructor, ComponentOptions } from 'vue';
|
||||
import { DecoratorFunction, StoryContext, LegacyStoryFn } from '@storybook/csf';
|
||||
import { sanitizeStoryContextUpdate } from '@storybook/store';
|
||||
|
||||
import { StoryFnVueReturnType } from './types';
|
||||
import { VueFramework } from './types-6-0';
|
||||
import { extractProps } from './util';
|
||||
import { VALUES } from './render';
|
||||
|
||||
export const WRAPS = 'STORYBOOK_WRAPS';
|
||||
|
||||
function prepare(
|
||||
rawStory: StoryFnVueReturnType,
|
||||
innerStory?: VueConstructor
|
||||
): VueConstructor | null {
|
||||
let story: ComponentOptions<Vue> | VueConstructor;
|
||||
|
||||
if (typeof rawStory === 'string') {
|
||||
story = { template: rawStory };
|
||||
} else if (rawStory != null) {
|
||||
story = rawStory as ComponentOptions<Vue>;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
if (!story._isVue) {
|
||||
if (innerStory) {
|
||||
story.components = { ...(story.components || {}), story: innerStory };
|
||||
}
|
||||
story = Vue.extend(story);
|
||||
// @ts-ignore // https://github.com/storybookjs/storybook/pull/7578#discussion_r307984824
|
||||
} else if (story.options[WRAPS]) {
|
||||
return story as VueConstructor;
|
||||
}
|
||||
|
||||
return Vue.extend({
|
||||
// @ts-ignore // https://github.com/storybookjs/storybook/pull/7578#discussion_r307985279
|
||||
[WRAPS]: story,
|
||||
// @ts-ignore // https://github.com/storybookjs/storybook/pull/7578#discussion_r307984824
|
||||
[VALUES]: { ...(innerStory ? innerStory.options[VALUES] : {}), ...extractProps(story) },
|
||||
functional: true,
|
||||
render(h, { data, parent, children }) {
|
||||
return h(
|
||||
story,
|
||||
{
|
||||
...data,
|
||||
// @ts-ignore // https://github.com/storybookjs/storybook/pull/7578#discussion_r307986196
|
||||
props: { ...(data.props || {}), ...parent.$root[VALUES] },
|
||||
},
|
||||
children
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function decorateStory(
|
||||
storyFn: LegacyStoryFn<VueFramework>,
|
||||
decorators: DecoratorFunction<VueFramework>[]
|
||||
): LegacyStoryFn<VueFramework> {
|
||||
return decorators.reduce(
|
||||
(decorated: LegacyStoryFn<VueFramework>, decorator) => (
|
||||
context: StoryContext<VueFramework>
|
||||
) => {
|
||||
let story;
|
||||
|
||||
const decoratedStory = decorator((update) => {
|
||||
story = decorated({ ...context, ...sanitizeStoryContextUpdate(update) });
|
||||
return story;
|
||||
}, context);
|
||||
|
||||
if (!story) {
|
||||
story = decorated(context);
|
||||
}
|
||||
|
||||
if (decoratedStory === story) {
|
||||
return story;
|
||||
}
|
||||
|
||||
return prepare(decoratedStory, story as any);
|
||||
},
|
||||
(context) => prepare(storyFn(context))
|
||||
);
|
||||
}
|
@ -1,93 +1,13 @@
|
||||
/* eslint-disable prefer-destructuring */
|
||||
import Vue, { VueConstructor, ComponentOptions } from 'vue';
|
||||
import { start } from '@storybook/core/client';
|
||||
import { DecoratorFunction, StoryContext, LegacyStoryFn } from '@storybook/csf';
|
||||
import { ClientStoryApi, Loadable } from '@storybook/addons';
|
||||
import { sanitizeStoryContextUpdate } from '@storybook/store';
|
||||
|
||||
import './globals';
|
||||
import { IStorybookSection, StoryFnVueReturnType } from './types';
|
||||
import { IStorybookSection } from './types';
|
||||
import { VueFramework } from './types-6-0';
|
||||
import { renderToDOM } from './render';
|
||||
import { decorateStory } from './decorateStory';
|
||||
|
||||
import { renderToDOM, VALUES } from './render';
|
||||
import { extractProps } from './util';
|
||||
|
||||
export const WRAPS = 'STORYBOOK_WRAPS';
|
||||
|
||||
function prepare(
|
||||
rawStory: StoryFnVueReturnType,
|
||||
innerStory?: VueConstructor
|
||||
): VueConstructor | null {
|
||||
let story: ComponentOptions<Vue> | VueConstructor;
|
||||
|
||||
if (typeof rawStory === 'string') {
|
||||
story = { template: rawStory };
|
||||
} else if (rawStory != null) {
|
||||
story = rawStory as ComponentOptions<Vue>;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
if (!story._isVue) {
|
||||
if (innerStory) {
|
||||
story.components = { ...(story.components || {}), story: innerStory };
|
||||
}
|
||||
story = Vue.extend(story);
|
||||
// @ts-ignore // https://github.com/storybookjs/storybook/pull/7578#discussion_r307984824
|
||||
} else if (story.options[WRAPS]) {
|
||||
return story as VueConstructor;
|
||||
}
|
||||
|
||||
return Vue.extend({
|
||||
// @ts-ignore // https://github.com/storybookjs/storybook/pull/7578#discussion_r307985279
|
||||
[WRAPS]: story,
|
||||
// @ts-ignore // https://github.com/storybookjs/storybook/pull/7578#discussion_r307984824
|
||||
[VALUES]: { ...(innerStory ? innerStory.options[VALUES] : {}), ...extractProps(story) },
|
||||
functional: true,
|
||||
render(h, { data, parent, children }) {
|
||||
return h(
|
||||
story,
|
||||
{
|
||||
...data,
|
||||
// @ts-ignore // https://github.com/storybookjs/storybook/pull/7578#discussion_r307986196
|
||||
props: { ...(data.props || {}), ...parent.$root[VALUES] },
|
||||
},
|
||||
children
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function decorateStory(
|
||||
storyFn: LegacyStoryFn<VueFramework>,
|
||||
decorators: DecoratorFunction<VueFramework>[]
|
||||
): LegacyStoryFn<VueFramework> {
|
||||
return decorators.reduce(
|
||||
(decorated: LegacyStoryFn<VueFramework>, decorator) => (
|
||||
context: StoryContext<VueFramework>
|
||||
) => {
|
||||
let story;
|
||||
|
||||
const decoratedStory = decorator((update) => {
|
||||
story = decorated({ ...context, ...sanitizeStoryContextUpdate(update) });
|
||||
return story;
|
||||
}, context);
|
||||
|
||||
if (!story) {
|
||||
story = decorated(context);
|
||||
}
|
||||
|
||||
if (decoratedStory === story) {
|
||||
return story;
|
||||
}
|
||||
|
||||
return prepare(decoratedStory, story as any);
|
||||
},
|
||||
(context) => prepare(storyFn(context))
|
||||
);
|
||||
}
|
||||
const framework = 'vue';
|
||||
|
||||
interface ClientApi extends ClientStoryApi<VueFramework['storyResult']> {
|
||||
|
@ -1,3 +1,4 @@
|
||||
export { renderToDOM } from './render';
|
||||
export { decorateStory } from './decorateStory';
|
||||
|
||||
export const parameters = { framework: 'vue3' };
|
||||
|
70
app/vue3/src/client/preview/decorateStory.ts
Normal file
70
app/vue3/src/client/preview/decorateStory.ts
Normal file
@ -0,0 +1,70 @@
|
||||
import type { ConcreteComponent, Component, ComponentOptions } from 'vue';
|
||||
import { h } from 'vue';
|
||||
import { DecoratorFunction, StoryContext, LegacyStoryFn } from '@storybook/csf';
|
||||
import { sanitizeStoryContextUpdate } from '@storybook/store';
|
||||
|
||||
import { VueFramework } from './types-6-0';
|
||||
|
||||
/*
|
||||
This normalizes a functional component into a render method in ComponentOptions.
|
||||
|
||||
The concept is taken from Vue 3's `defineComponent` but changed from creating a `setup`
|
||||
method on the ComponentOptions so end-users don't need to specify a "thunk" as a decorator.
|
||||
*/
|
||||
function normalizeFunctionalComponent(options: ConcreteComponent): ComponentOptions {
|
||||
return typeof options === 'function' ? { render: options, name: options.name } : options;
|
||||
}
|
||||
|
||||
function prepare(
|
||||
rawStory: VueFramework['storyResult'],
|
||||
innerStory?: ConcreteComponent
|
||||
): Component | null {
|
||||
const story = rawStory as ComponentOptions;
|
||||
|
||||
if (story == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (innerStory) {
|
||||
return {
|
||||
// Normalize so we can always spread an object
|
||||
...normalizeFunctionalComponent(story),
|
||||
components: { ...(story.components || {}), story: innerStory },
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
render() {
|
||||
return h(story);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function decorateStory(
|
||||
storyFn: LegacyStoryFn<VueFramework>,
|
||||
decorators: DecoratorFunction<VueFramework>[]
|
||||
): LegacyStoryFn<VueFramework> {
|
||||
return decorators.reduce(
|
||||
(decorated: LegacyStoryFn<VueFramework>, decorator) => (
|
||||
context: StoryContext<VueFramework>
|
||||
) => {
|
||||
let story: VueFramework['storyResult'];
|
||||
|
||||
const decoratedStory: VueFramework['storyResult'] = decorator((update) => {
|
||||
story = decorated({ ...context, ...sanitizeStoryContextUpdate(update) });
|
||||
return story;
|
||||
}, context);
|
||||
|
||||
if (!story) {
|
||||
story = decorated(context);
|
||||
}
|
||||
|
||||
if (decoratedStory === story) {
|
||||
return story;
|
||||
}
|
||||
|
||||
return prepare(decoratedStory, story) as VueFramework['storyResult'];
|
||||
},
|
||||
(context) => prepare(storyFn(context)) as LegacyStoryFn<VueFramework>
|
||||
);
|
||||
}
|
@ -1,79 +1,14 @@
|
||||
import type { ConcreteComponent, Component, ComponentOptions, App } from 'vue';
|
||||
import { h } from 'vue';
|
||||
import type { App } from 'vue';
|
||||
import { start } from '@storybook/core/client';
|
||||
import { DecoratorFunction, StoryContext, LegacyStoryFn } from '@storybook/csf';
|
||||
import { ClientStoryApi, Loadable } from '@storybook/addons';
|
||||
import { sanitizeStoryContextUpdate } from '@storybook/store';
|
||||
|
||||
import './globals';
|
||||
import { IStorybookSection } from './types';
|
||||
import { VueFramework } from './types-6-0';
|
||||
import { decorateStory } from './decorateStory';
|
||||
|
||||
import { renderToDOM, storybookApp } from './render';
|
||||
|
||||
/*
|
||||
This normalizes a functional component into a render method in ComponentOptions.
|
||||
|
||||
The concept is taken from Vue 3's `defineComponent` but changed from creating a `setup`
|
||||
method on the ComponentOptions so end-users don't need to specify a "thunk" as a decorator.
|
||||
*/
|
||||
function normalizeFunctionalComponent(options: ConcreteComponent): ComponentOptions {
|
||||
return typeof options === 'function' ? { render: options, name: options.name } : options;
|
||||
}
|
||||
|
||||
function prepare(
|
||||
rawStory: VueFramework['storyResult'],
|
||||
innerStory?: ConcreteComponent
|
||||
): Component | null {
|
||||
const story = rawStory as ComponentOptions;
|
||||
|
||||
if (story == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (innerStory) {
|
||||
return {
|
||||
// Normalize so we can always spread an object
|
||||
...normalizeFunctionalComponent(story),
|
||||
components: { ...(story.components || {}), story: innerStory },
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
render() {
|
||||
return h(story);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function decorateStory(
|
||||
storyFn: LegacyStoryFn<VueFramework>,
|
||||
decorators: DecoratorFunction<VueFramework>[]
|
||||
): LegacyStoryFn<VueFramework> {
|
||||
return decorators.reduce(
|
||||
(decorated: LegacyStoryFn<VueFramework>, decorator) => (
|
||||
context: StoryContext<VueFramework>
|
||||
) => {
|
||||
let story: VueFramework['storyResult'];
|
||||
|
||||
const decoratedStory: VueFramework['storyResult'] = decorator((update) => {
|
||||
story = decorated({ ...context, ...sanitizeStoryContextUpdate(update) });
|
||||
return story;
|
||||
}, context);
|
||||
|
||||
if (!story) {
|
||||
story = decorated(context);
|
||||
}
|
||||
|
||||
if (decoratedStory === story) {
|
||||
return story;
|
||||
}
|
||||
|
||||
return prepare(decoratedStory, story) as VueFramework['storyResult'];
|
||||
},
|
||||
(context) => prepare(storyFn(context)) as LegacyStoryFn<VueFramework>
|
||||
);
|
||||
}
|
||||
const framework = 'vue3';
|
||||
|
||||
interface ClientApi extends ClientStoryApi<VueFramework['storyResult']> {
|
||||
|
@ -41,6 +41,10 @@ Object.keys(config).forEach((key) => {
|
||||
v[key] = value;
|
||||
return addParameters(v, false);
|
||||
}
|
||||
case 'decorateStory':
|
||||
case 'renderToDOM': {
|
||||
return null; // This key is not handled directly in v6 mode.
|
||||
}
|
||||
default: {
|
||||
// eslint-disable-next-line prefer-template
|
||||
return console.log(key + ' was not supported :( !');
|
||||
|
@ -41,6 +41,10 @@ Object.keys(config).forEach((key) => {
|
||||
v[key] = value;
|
||||
return addParameters(v, false);
|
||||
}
|
||||
case 'decorateStory':
|
||||
case 'renderToDOM': {
|
||||
return null; // This key is not handled directly in v6 mode.
|
||||
}
|
||||
default: {
|
||||
// eslint-disable-next-line prefer-template
|
||||
return console.log(key + ' was not supported :( !');
|
||||
|
Loading…
x
Reference in New Issue
Block a user