2022-02-18 16:34:33 +01:00
|
|
|
|
import React, { useRef, useEffect } from 'react';
|
|
|
|
|
|
|
|
|
|
import { renderPattern, simulateLoading } from 'storybook-django';
|
|
|
|
|
|
2022-02-18 17:07:09 +01:00
|
|
|
|
const getTemplateName = (template?: string, filename?: string): string =>
|
2022-02-18 16:34:33 +01:00
|
|
|
|
template ||
|
2022-02-18 17:07:09 +01:00
|
|
|
|
filename?.replace(/.+\/templates\//, '').replace(/\.stories\..+$/, '.html') ||
|
|
|
|
|
'template-not-found';
|
|
|
|
|
|
|
|
|
|
type ContextMapping = { [key: string]: any };
|
|
|
|
|
type TagsMapping = { [key: string]: any };
|
2022-02-18 16:34:33 +01:00
|
|
|
|
|
|
|
|
|
interface TemplatePatternProps {
|
|
|
|
|
element?: 'div' | 'span';
|
2022-02-18 17:07:09 +01:00
|
|
|
|
// Path to the template file.
|
2022-02-18 16:34:33 +01:00
|
|
|
|
template?: string;
|
2022-02-18 17:07:09 +01:00
|
|
|
|
// Path to a Storybook `stories` file, which should be placed next to and named the same as the HTML template.
|
2022-02-18 16:34:33 +01:00
|
|
|
|
filename?: string;
|
2022-02-18 17:07:09 +01:00
|
|
|
|
context?: ContextMapping;
|
|
|
|
|
tags?: TagsMapping;
|
2022-02-18 16:34:33 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-18 17:07:09 +01:00
|
|
|
|
const PATTERN_LIBRARY_RENDER_URL = '/pattern-library/api/v1/render-pattern';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Retrieves a template pattern’s 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.
|
|
|
|
|
*/
|
2022-02-18 16:34:33 +01:00
|
|
|
|
const TemplatePattern = ({
|
|
|
|
|
element = 'div',
|
|
|
|
|
template,
|
|
|
|
|
filename,
|
|
|
|
|
context = {},
|
|
|
|
|
tags = {},
|
|
|
|
|
}: TemplatePatternProps) => {
|
|
|
|
|
const ref = useRef(null);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
2022-02-18 17:07:09 +01:00
|
|
|
|
const templateName = getTemplateName(template, filename);
|
|
|
|
|
getTemplatePattern(templateName, context, tags, (html) =>
|
|
|
|
|
simulateLoading(ref.current, html),
|
|
|
|
|
);
|
|
|
|
|
});
|
2022-02-18 16:34:33 +01:00
|
|
|
|
|
|
|
|
|
return React.createElement(element, { ref });
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default TemplatePattern;
|