From de856ce8f15ea2fa5bf0f74ff3b8f50142056158 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Thu, 25 May 2023 10:06:15 +0200 Subject: [PATCH] Merge pull request #22717 from storybookjs/kasper/update-args-reactively Vue3: Fix reactive args updates in decorators --- code/addons/controls/template/stories/basics.stories.ts | 3 ++- .../controls/template/stories/conditional.stories.ts | 3 ++- code/addons/controls/template/stories/disable.stories.ts | 3 ++- code/addons/controls/template/stories/filters.stories.ts | 3 ++- code/addons/controls/template/stories/issues.stories.ts | 3 ++- code/addons/controls/template/stories/matchers.stories.ts | 3 ++- code/addons/controls/template/stories/sorting.stories.ts | 3 ++- code/lib/store/template/stories/argMapping.stories.ts | 2 +- code/lib/store/template/stories/argTypes.stories.ts | 2 +- code/lib/store/template/stories/args.stories.ts | 3 ++- code/renderers/vue3/src/decorateStory.ts | 8 ++++---- code/renderers/vue3/src/docs/sourceDecorator.ts | 3 ++- 12 files changed, 24 insertions(+), 15 deletions(-) diff --git a/code/addons/controls/template/stories/basics.stories.ts b/code/addons/controls/template/stories/basics.stories.ts index 51acda9c1f21..aabbda0e4d4c 100644 --- a/code/addons/controls/template/stories/basics.stories.ts +++ b/code/addons/controls/template/stories/basics.stories.ts @@ -4,7 +4,8 @@ import type { PartialStoryFn, StoryContext } from '@storybook/types'; export default { component: globalThis.Components.Pre, decorators: [ - (storyFn: PartialStoryFn, context: StoryContext) => storyFn({ args: { object: context.args } }), + (storyFn: PartialStoryFn, context: StoryContext) => + storyFn({ args: { object: { ...context.args } } }), ], argTypes: { boolean: { control: 'boolean' }, diff --git a/code/addons/controls/template/stories/conditional.stories.ts b/code/addons/controls/template/stories/conditional.stories.ts index 8d8677f33e60..eba90f541a0d 100644 --- a/code/addons/controls/template/stories/conditional.stories.ts +++ b/code/addons/controls/template/stories/conditional.stories.ts @@ -4,7 +4,8 @@ import type { PartialStoryFn, StoryContext } from '@storybook/types'; export default { component: globalThis.Components.Pre, decorators: [ - (storyFn: PartialStoryFn, context: StoryContext) => storyFn({ args: { object: context.args } }), + (storyFn: PartialStoryFn, context: StoryContext) => + storyFn({ args: { object: { ...context.args } } }), ], }; diff --git a/code/addons/controls/template/stories/disable.stories.ts b/code/addons/controls/template/stories/disable.stories.ts index bcc53c876124..7b8be89df32f 100644 --- a/code/addons/controls/template/stories/disable.stories.ts +++ b/code/addons/controls/template/stories/disable.stories.ts @@ -4,7 +4,8 @@ import type { PartialStoryFn, StoryContext } from '@storybook/types'; export default { component: globalThis.Components.Pre, decorators: [ - (storyFn: PartialStoryFn, context: StoryContext) => storyFn({ args: { object: context.args } }), + (storyFn: PartialStoryFn, context: StoryContext) => + storyFn({ args: { object: { ...context.args } } }), ], }; diff --git a/code/addons/controls/template/stories/filters.stories.ts b/code/addons/controls/template/stories/filters.stories.ts index 8aa860e77b82..5b84f32e110a 100644 --- a/code/addons/controls/template/stories/filters.stories.ts +++ b/code/addons/controls/template/stories/filters.stories.ts @@ -4,7 +4,8 @@ import type { PartialStoryFn, StoryContext } from '@storybook/types'; export default { component: globalThis.Components.Pre, decorators: [ - (storyFn: PartialStoryFn, context: StoryContext) => storyFn({ args: { object: context.args } }), + (storyFn: PartialStoryFn, context: StoryContext) => + storyFn({ args: { object: { ...context.args } } }), ], args: { helloWorld: 1, diff --git a/code/addons/controls/template/stories/issues.stories.ts b/code/addons/controls/template/stories/issues.stories.ts index d3827f766d6b..00c5c71b21e0 100644 --- a/code/addons/controls/template/stories/issues.stories.ts +++ b/code/addons/controls/template/stories/issues.stories.ts @@ -4,7 +4,8 @@ import type { PartialStoryFn, StoryContext } from '@storybook/types'; export default { component: globalThis.Components.Pre, decorators: [ - (storyFn: PartialStoryFn, context: StoryContext) => storyFn({ args: { object: context.args } }), + (storyFn: PartialStoryFn, context: StoryContext) => + storyFn({ args: { object: { ...context.args } } }), ], }; diff --git a/code/addons/controls/template/stories/matchers.stories.ts b/code/addons/controls/template/stories/matchers.stories.ts index 0582447362a9..174d59f085c1 100644 --- a/code/addons/controls/template/stories/matchers.stories.ts +++ b/code/addons/controls/template/stories/matchers.stories.ts @@ -4,7 +4,8 @@ import type { PartialStoryFn, StoryContext } from '@storybook/types'; export default { component: globalThis.Components.Pre, decorators: [ - (storyFn: PartialStoryFn, context: StoryContext) => storyFn({ args: { object: context.args } }), + (storyFn: PartialStoryFn, context: StoryContext) => + storyFn({ args: { object: { ...context.args } } }), ], }; diff --git a/code/addons/controls/template/stories/sorting.stories.ts b/code/addons/controls/template/stories/sorting.stories.ts index 573f11a2bb3d..12353382b436 100644 --- a/code/addons/controls/template/stories/sorting.stories.ts +++ b/code/addons/controls/template/stories/sorting.stories.ts @@ -4,7 +4,8 @@ import type { PartialStoryFn, StoryContext } from '@storybook/types'; export default { component: globalThis.Components.Pre, decorators: [ - (storyFn: PartialStoryFn, context: StoryContext) => storyFn({ args: { object: context.args } }), + (storyFn: PartialStoryFn, context: StoryContext) => + storyFn({ args: { object: { ...context.args } } }), ], argTypes: { x: { type: { required: true } }, diff --git a/code/lib/store/template/stories/argMapping.stories.ts b/code/lib/store/template/stories/argMapping.stories.ts index 655647660c9d..d5fa145700a7 100644 --- a/code/lib/store/template/stories/argMapping.stories.ts +++ b/code/lib/store/template/stories/argMapping.stories.ts @@ -22,7 +22,7 @@ export default { decorators: [ (storyFn: PartialStoryFn, context: StoryContext) => { return storyFn({ - args: { object: context.args }, + args: { object: { ...context.args } }, }); }, ], diff --git a/code/lib/store/template/stories/argTypes.stories.ts b/code/lib/store/template/stories/argTypes.stories.ts index 93b9540ebb40..e0d2115d10ae 100644 --- a/code/lib/store/template/stories/argTypes.stories.ts +++ b/code/lib/store/template/stories/argTypes.stories.ts @@ -8,7 +8,7 @@ export default { // Compose all the argTypes into `object`, so the pre component only needs a single prop decorators: [ (storyFn: PartialStoryFn, context: StoryContext) => - storyFn({ args: { object: context.argTypes } }), + storyFn({ args: { object: { ...context.argTypes } } }), ], argTypes: { componentArg: { type: 'string' }, diff --git a/code/lib/store/template/stories/args.stories.ts b/code/lib/store/template/stories/args.stories.ts index e1e6eb7104f4..ac2c412de870 100644 --- a/code/lib/store/template/stories/args.stories.ts +++ b/code/lib/store/template/stories/args.stories.ts @@ -20,7 +20,8 @@ export default { decorators: [ (storyFn: PartialStoryFn, context: StoryContext) => { const { argNames } = context.parameters; - const object = argNames ? pick(context.args, argNames) : context.args; + const args = { ...context.args }; + const object = argNames ? pick(args, argNames) : args; return storyFn({ args: { object } }); }, ], diff --git a/code/renderers/vue3/src/decorateStory.ts b/code/renderers/vue3/src/decorateStory.ts index f63fdfb6ec82..1d8ef7e766cd 100644 --- a/code/renderers/vue3/src/decorateStory.ts +++ b/code/renderers/vue3/src/decorateStory.ts @@ -49,10 +49,10 @@ export function decorateStory( let story: VueRenderer['storyResult'] | undefined; const decoratedStory: VueRenderer['storyResult'] = decorator((update) => { - story = decorated({ - ...context, - ...sanitizeStoryContextUpdate(update), - }); + const sanitizedUpdate = sanitizeStoryContextUpdate(update); + // update the args in a reactive way + if (update) sanitizedUpdate.args = Object.assign(context.args, sanitizedUpdate.args); + story = decorated({ ...context, ...sanitizedUpdate }); return story; }, context); diff --git a/code/renderers/vue3/src/docs/sourceDecorator.ts b/code/renderers/vue3/src/docs/sourceDecorator.ts index 4331324b796a..59ac746ae027 100644 --- a/code/renderers/vue3/src/docs/sourceDecorator.ts +++ b/code/renderers/vue3/src/docs/sourceDecorator.ts @@ -9,6 +9,7 @@ import parserHTML from 'prettier/parser-html'; // eslint-disable-next-line import/no-extraneous-dependencies import { isArray } from '@vue/shared'; +import { toRaw } from 'vue'; type ArgEntries = [string, any][]; type Attribute = { @@ -60,7 +61,7 @@ function getComponentNameAndChildren(component: any): { */ function generateAttributesSource(_args: Args, argTypes: ArgTypes, byRef?: boolean): string { // create a copy of the args object to avoid modifying the original - const args = { ..._args }; + const args = { ...toRaw(_args) }; // filter out keys that are children or slots, and convert event keys to the proper format const argsKeys = Object.keys(args) .filter(