-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
/
render.ts
69 lines (61 loc) · 2.07 KB
/
render.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/* eslint-disable no-param-reassign */
import { global } from '@storybook/global';
import { dedent } from 'ts-dedent';
import { simulatePageLoad, simulateDOMContentLoaded } from '@storybook/preview-api';
import type { RenderContext, ArgsStoryFn } from '@storybook/types';
import type { HtmlRenderer } from './types';
const { Node } = global;
export const render: ArgsStoryFn<HtmlRenderer> = (args, context) => {
const { id, component: Component } = context;
if (typeof Component === 'string') {
let output = Component;
Object.keys(args).forEach((key) => {
output = output.replace(`{{${key}}}`, args[key]);
});
return output;
}
if (Component instanceof HTMLElement) {
const output = Component.cloneNode(true) as HTMLElement;
Object.keys(args).forEach((key) => {
output.setAttribute(
key,
typeof args[key] === 'string' ? args[key] : JSON.stringify(args[key])
);
});
return output;
}
if (typeof Component === 'function') {
return Component(args, context);
}
console.warn(dedent`
Storybook's HTML renderer only supports rendering DOM elements and strings.
Received: ${Component}
`);
throw new Error(`Unable to render story ${id}`);
};
export function renderToCanvas(
{ storyFn, kind, name, showMain, showError, forceRemount }: RenderContext<HtmlRenderer>,
canvasElement: HtmlRenderer['canvasElement']
) {
const element = storyFn();
showMain();
if (typeof element === 'string') {
canvasElement.innerHTML = element;
simulatePageLoad(canvasElement);
} else if (element instanceof Node) {
if (canvasElement.firstChild === element && forceRemount === false) {
return;
}
canvasElement.innerHTML = '';
canvasElement.appendChild(element);
simulateDOMContentLoaded();
} else {
showError({
title: `Expecting an HTML snippet or DOM node from the story: "${name}" of "${kind}".`,
description: dedent`
Did you forget to return the HTML snippet from the story?
Use "() => <your snippet or node>" or when defining the story.
`,
});
}
}