mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-08 11:11:53 +08:00
61 lines
1.8 KiB
TypeScript
61 lines
1.8 KiB
TypeScript
import { dedent } from 'ts-dedent';
|
|
import { createApp, h } from 'vue';
|
|
import type { Store_RenderContext, ArgsStoryFn } from '@storybook/types';
|
|
|
|
import type { StoryFnVueReturnType, VueFramework } from './types';
|
|
|
|
export const render: ArgsStoryFn<VueFramework> = (props, context) => {
|
|
const { id, component: Component } = context;
|
|
if (!Component) {
|
|
throw new Error(
|
|
`Unable to render story ${id} as the component annotation is missing from the default export`
|
|
);
|
|
}
|
|
|
|
return h(Component, props);
|
|
};
|
|
|
|
let setupFunction = (app: any) => {};
|
|
export const setup = (fn: (app: any) => void) => {
|
|
setupFunction = fn;
|
|
};
|
|
|
|
const map = new Map<VueFramework['canvasElement'], ReturnType<typeof createApp>>();
|
|
|
|
export function renderToCanvas(
|
|
{ title, name, storyFn, showMain, showError, showException }: Store_RenderContext<VueFramework>,
|
|
canvasElement: VueFramework['canvasElement']
|
|
) {
|
|
// TODO: explain cyclical nature of these app => story => mount
|
|
let element: StoryFnVueReturnType;
|
|
const storybookApp = createApp({
|
|
unmounted() {
|
|
map.delete(domElement);
|
|
},
|
|
render() {
|
|
map.set(domElement, storybookApp);
|
|
setupFunction(storybookApp);
|
|
return h(element);
|
|
},
|
|
});
|
|
storybookApp.config.errorHandler = (e: unknown) => showException(e as Error);
|
|
element = storyFn();
|
|
|
|
if (!element) {
|
|
showError({
|
|
title: `Expecting a Vue component from the story: "${name}" of "${title}".`,
|
|
description: dedent`
|
|
Did you forget to return the Vue component from the story?
|
|
Use "() => ({ template: '<my-comp></my-comp>' })" or "() => ({ components: MyComp, template: '<my-comp></my-comp>' })" when defining the story.
|
|
`,
|
|
});
|
|
return;
|
|
}
|
|
|
|
showMain();
|
|
|
|
map.get(domElement)?.unmount();
|
|
|
|
storybookApp.mount(domElement);
|
|
}
|