From 721406b8b58b11954ba5235a566c56159d03e30a Mon Sep 17 00:00:00 2001 From: Michael Shilman Date: Wed, 10 Jun 2020 21:53:26 +0800 Subject: [PATCH] Vue: Add first-class args support --- app/vue/src/client/preview/index.ts | 9 +++++++-- app/vue/src/client/preview/render.ts | 6 ++++-- app/vue/src/client/preview/util.ts | 9 +++++++++ .../src/stories/components/button.stories.js | 8 ++++---- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/app/vue/src/client/preview/index.ts b/app/vue/src/client/preview/index.ts index eeb0edf3464..51fb5f2972e 100644 --- a/app/vue/src/client/preview/index.ts +++ b/app/vue/src/client/preview/index.ts @@ -2,6 +2,7 @@ import Vue, { VueConstructor, ComponentOptions } from 'vue'; import { start } from '@storybook/core/client'; import { + Args, ClientStoryApi, StoryFn, DecoratorFunction, @@ -13,7 +14,7 @@ import './globals'; import { IStorybookSection, StoryFnVueReturnType } from './types'; import render, { VALUES } from './render'; -import { extractProps } from './util'; +import { extractProps, propsFromArgs } from './util'; export const WRAPS = 'STORYBOOK_WRAPS'; @@ -26,7 +27,11 @@ function prepare( if (typeof rawStory === 'string') { story = { template: rawStory }; } else if (rawStory != null) { - story = rawStory as ComponentOptions; + const { args, props } = rawStory as ComponentOptions & { args: Args }; + story = { + ...rawStory, + props: { ...propsFromArgs(args), ...props }, + } as ComponentOptions; } else { return null; } diff --git a/app/vue/src/client/preview/render.ts b/app/vue/src/client/preview/render.ts index 3500a087494..df40c67bea5 100644 --- a/app/vue/src/client/preview/render.ts +++ b/app/vue/src/client/preview/render.ts @@ -44,8 +44,10 @@ export default function render({ showMain(); - // always refresh the component - root[COMPONENT] = element; + // at component creation || refresh by HMR // always refresh the component + if (!root[COMPONENT] || !forceRender) { + root[COMPONENT] = element; + } // @ts-ignore https://github.com/storybookjs/storybook/pull/7578#discussion_r307986139 root[VALUES] = element.options[VALUES]; diff --git a/app/vue/src/client/preview/util.ts b/app/vue/src/client/preview/util.ts index b44667add41..3028d1412af 100644 --- a/app/vue/src/client/preview/util.ts +++ b/app/vue/src/client/preview/util.ts @@ -1,4 +1,5 @@ import { VueConstructor } from 'vue'; +import { Args } from '@storybook/addons'; function getType(fn: Function) { const match = fn && fn.toString().match(/^\s*function (\w+)/); @@ -21,3 +22,11 @@ export function extractProps(component: VueConstructor) { .map(([name, prop]) => ({ [name]: resolveDefault(prop) })) .reduce((wrap, prop) => ({ ...wrap, ...prop }), {}); } + +export const propsFromArgs = (args: Args) => { + if (!args) return {}; + return Object.entries(args).reduce((acc, [key, val]) => { + acc[key] = { default: val }; + return acc; + }, {} as any); +}; diff --git a/examples/vue-kitchen-sink/src/stories/components/button.stories.js b/examples/vue-kitchen-sink/src/stories/components/button.stories.js index 79832e339a7..e0749b3cd6c 100644 --- a/examples/vue-kitchen-sink/src/stories/components/button.stories.js +++ b/examples/vue-kitchen-sink/src/stories/components/button.stories.js @@ -1,3 +1,4 @@ +import { propsFromArgs } from '@storybook/vue'; import MyButton from '../Button.vue'; export default { @@ -6,11 +7,10 @@ export default { }; export const Rounded = (args) => ({ + args, components: { MyButton }, - template: 'A Button with rounded edges', - data() { - return args; - }, + template: + 'A Button with rounded edges', }); Rounded.argTypes = { rounded: { defaultValue: true },