0
0
mirror of https://github.com/wagtail/wagtail.git synced 2024-11-30 19:20:56 +01:00
wagtail/client/storybook/TemplatePattern.tsx

63 lines
1.7 KiB
TypeScript
Raw Normal View History

import React, { useRef, useEffect } from 'react';
import { renderPattern, simulateLoading } from 'storybook-django';
const getTemplateName = (template?: string, filename?: string): string =>
template ||
filename?.replace(/.+\/templates\//, '').replace(/\.stories\..+$/, '.html') ||
'template-not-found';
type ContextMapping = { [key: string]: any };
type TagsMapping = { [key: string]: any };
interface TemplatePatternProps {
element?: 'div' | 'span';
// Path to the template file.
template?: string;
// Path to a Storybook `stories` file, which should be placed next to and named the same as the HTML template.
filename?: string;
context?: ContextMapping;
tags?: TagsMapping;
}
const PATTERN_LIBRARY_RENDER_URL = '/pattern-library/api/v1/render-pattern';
/**
* Retrieves a template patterns HTML (or error response) from the server.
*/
export const getTemplatePattern = (
templateName: string,
context: ContextMapping,
tags: TagsMapping,
callback: (html: string) => void,
) =>
renderPattern(PATTERN_LIBRARY_RENDER_URL, templateName, context, tags)
.catch(callback)
.then((res) => res.text())
.then(callback);
/**
* Renders one of our Django templates as if it was a React component.
* All props are marked as optional, but either template or filename should be provided.
*/
const TemplatePattern = ({
element = 'div',
template,
filename,
context = {},
tags = {},
}: TemplatePatternProps) => {
const ref = useRef(null);
useEffect(() => {
const templateName = getTemplateName(template, filename);
getTemplatePattern(templateName, context, tags, (html) =>
simulateLoading(ref.current, html),
);
});
return React.createElement(element, { ref });
};
export default TemplatePattern;