@muban/storybook
Version:
Storybook for Muban: View and Test Muban components.
59 lines (58 loc) • 3.02 kB
JavaScript
import { html } from '@muban/template';
import { getClientTemplateArgs as getClientTemplateArguments } from './getTemplateArgs.js';
import { parseServerConfig } from './parseServerConfig.js';
// eslint-disable-next-line @typescript-eslint/naming-convention
export const DECORATOR_PLACEHOLDER_FOR_SERVER_INJECTION = '__PLACEHOLDER__';
/**
* Helper function for component decorators that:
* - allows you to pass only a component or template, where this function will fill in the other part
* - already apply the template props and pass the rendered child template
*/
export function createDecoratorComponent(createDecoratorFunction) {
return (story, context) => {
var _a, _b, _c, _d, _e;
const storyComponent = story();
const { renderMode } = parseServerConfig(context.globals);
const data = ((_a = storyComponent.data) !== null && _a !== void 0 ? _a : context.args) || {};
const sanitizedStoryArguments = getClientTemplateArguments(data, context.argTypes);
let storyTemplateResult = storyComponent.template(sanitizedStoryArguments);
// If we are currently rendering on the server, we inject a __PLACEHOLDER__ when our story is empty.
// This allows us to identify where to inject our server-rendered story inside the decorators.
if (renderMode === 'server') {
storyTemplateResult || (storyTemplateResult = DECORATOR_PLACEHOLDER_FOR_SERVER_INJECTION);
}
const decoratorComponent = createDecoratorFunction({
story,
context,
// TODO: document that not all stories have components
component: storyComponent.component,
template: storyTemplateResult,
});
// merge appComponents to pass "up", so story renderer can access it
const appComponents = [
...((_b = decoratorComponent.appComponents) !== null && _b !== void 0 ? _b : []),
...((_c = storyComponent.appComponents) !== null && _c !== void 0 ? _c : []),
];
if (!decoratorComponent.component && !decoratorComponent.template) {
return Object.assign(Object.assign({}, storyComponent), { appComponents });
}
const component = (_d = decoratorComponent.component) !== null && _d !== void 0 ? _d : storyComponent.component;
let template = (_e = decoratorComponent.template) !== null && _e !== void 0 ? _e : storyComponent.template;
// create dummy template attaching to the decoratorComponent, so it gets initialized
if (!decoratorComponent.template && decoratorComponent.component) {
template = () => {
var _a;
return html `
<div data-component=${(_a = decoratorComponent.component) === null || _a === void 0 ? void 0 : _a.displayName}>
${storyTemplateResult}
</div>
`;
};
}
return {
appComponents,
component: component,
template,
};
};
}