Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue3 ( fix ) implement reactive args + fix many vue app creation issue #20712

Merged
merged 23 commits into from
Jan 23, 2023
Merged
Changes from 6 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
482808b
fix the multipe creation of vue App and implemente reactive args
chakAs3 Jan 19, 2023
e7c7462
Merge branch 'next' into vue3-reactivemode
chakAs3 Jan 19, 2023
48859c6
trying to fix issue after merging 2 stories created with same id
chakAs3 Jan 20, 2023
b6dc9ea
Merge branch 'next' 7.0.0-beta.31 into vue3-reactivemode
chakAs3 Jan 20, 2023
a79d42a
vue render use return function instead to unmount vue story app
chakAs3 Jan 20, 2023
57c7065
refactory and optimisation .
chakAs3 Jan 20, 2023
332f617
vue3 use canvasElement as map key
chakAs3 Jan 20, 2023
df020a7
vue3 add Story to cli template to demo reactive args
chakAs3 Jan 20, 2023
e179c14
Merge branch 'next' into vue3-reactivemode
chakAs3 Jan 20, 2023
d4b8b9a
fixing test issues
chakAs3 Jan 21, 2023
5898ba5
fix issue with testing args.stories
chakAs3 Jan 21, 2023
8b069c2
remove reactive button from cli test
chakAs3 Jan 22, 2023
e447524
add test story to stories to test reactive args
chakAs3 Jan 22, 2023
3777314
fix import ref from vue
chakAs3 Jan 22, 2023
96fcaa5
fix add await to expect
chakAs3 Jan 22, 2023
cbc1942
add click event to the button
chakAs3 Jan 22, 2023
b761da7
fix play function test by awaiting for Args Update
chakAs3 Jan 22, 2023
5c296f3
change story name to reactive test
chakAs3 Jan 22, 2023
9670e97
refactory and cleanup
chakAs3 Jan 22, 2023
806c43e
minor refactory
chakAs3 Jan 22, 2023
bd367b1
cleanup some issue to fix testing
chakAs3 Jan 22, 2023
85e4d60
fix args reset from controls
chakAs3 Jan 22, 2023
682f8c1
cleanup and check the forceReRender api not firing
chakAs3 Jan 23, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 59 additions & 19 deletions code/renderers/vue3/src/render.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { dedent } from 'ts-dedent';
import { createApp, h } from 'vue';
import type { App } from 'vue';
import { createApp, h, reactive } from 'vue';
import type { RenderContext, ArgsStoryFn } from '@storybook/types';

import type { Args, StoryContext } from '@storybook/csf';
Expand All @@ -21,26 +22,24 @@ export const setup = (fn: (app: any) => void) => {
setupFunction = fn;
};

const map = new Map<VueRenderer['canvasElement'], ReturnType<typeof createApp>>();
const map = new Map<string, { vueApp: ReturnType<typeof createApp>; reactiveArgs: any }>();

export function renderToCanvas(
{ title, name, storyFn, showMain, showError, showException }: RenderContext<VueRenderer>,
{
storyFn,
name,
showMain,
showError,
showException,
id,
title,
forceRemount,
storyContext,
}: RenderContext<VueRenderer>,
canvasElement: VueRenderer['canvasElement']
) {
// TODO: explain cyclical nature of these app => story => mount
let element: StoryFnVueReturnType;
const storybookApp = createApp({
unmounted() {
map.delete(canvasElement);
},
render() {
map.set(canvasElement, storybookApp);
setupFunction(storybookApp);
return h(element);
},
});
storybookApp.config.errorHandler = (e: unknown) => showException(e as Error);
element = storyFn();
const element: StoryFnVueReturnType = storyFn();

if (!element) {
showError({
Expand All @@ -50,15 +49,39 @@ export function renderToCanvas(
Use "() => ({ template: '<my-comp></my-comp>' })" or "() => ({ components: MyComp, template: '<my-comp></my-comp>' })" when defining the story.
`,
});
return;
return () => {};
}
const { args: storyArgs, viewMode } = storyContext;

showMain();
const storyID = `${id}--${viewMode}`;
const existingApp = map.get(storyID);
chakAs3 marked this conversation as resolved.
Show resolved Hide resolved

if (existingApp && !forceRemount) {
updateArgs(existingApp.reactiveArgs, storyArgs);
return () => {
teardown(existingApp.vueApp, storyID);
};
}

map.get(canvasElement)?.unmount();
const reactiveArgs = storyArgs ? reactive(storyArgs) : storyArgs;

const storybookApp = createApp({
render() {
map.set(storyID, { vueApp: storybookApp, reactiveArgs });
return h(element, reactiveArgs);
},
});

storybookApp.config.errorHandler = (e: unknown) => showException(e as Error);
setupFunction(storybookApp);
storybookApp.mount(canvasElement);

showMain();
return () => {
teardown(storybookApp, storyID);
};
}

/**
* get the slots as functions to be rendered
* @param props
Expand All @@ -73,3 +96,20 @@ function getSlots(props: Args, context: StoryContext<VueRenderer, Args>) {

return Object.fromEntries(slots);
}

/**
* update the reactive args
* @param reactiveArgs
* @param nextArgs
* @returns
*/
function updateArgs(reactiveArgs: Args, nextArgs: Args) {
if (!nextArgs) return;
// use spread operator to merge new args with the existing args
Object.assign(reactiveArgs, nextArgs);
}

function teardown(storybookApp: App<Element>, storyID: string) {
storybookApp?.unmount();
if (map.has(storyID)) map.delete(storyID);
}