|
@@ -2,18 +2,44 @@ import React, { useRef, useEffect } from 'react';
|
|
|
|
|
|
import { renderPattern, simulateLoading } from 'storybook-django';
|
|
|
|
|
|
-const getTemplateName = (template?: string, filename?: string) =>
|
|
|
+const getTemplateName = (template?: string, filename?: string): string =>
|
|
|
template ||
|
|
|
- filename?.replace(/.+\/templates\//, '').replace(/\.stories\..+$/, '.html');
|
|
|
+ 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?: { [key: string]: any };
|
|
|
- tags?: { [key: string]: any };
|
|
|
+ context?: ContextMapping;
|
|
|
+ tags?: TagsMapping;
|
|
|
}
|
|
|
|
|
|
+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.
|
|
|
+ */
|
|
|
const TemplatePattern = ({
|
|
|
element = 'div',
|
|
|
template,
|
|
@@ -22,14 +48,13 @@ const TemplatePattern = ({
|
|
|
tags = {},
|
|
|
}: TemplatePatternProps) => {
|
|
|
const ref = useRef(null);
|
|
|
- const templateName = getTemplateName(template, filename);
|
|
|
|
|
|
useEffect(() => {
|
|
|
- renderPattern(window.PATTERN_LIBRARY_API, templateName, context, tags)
|
|
|
- .catch((err) => simulateLoading(ref.current, err))
|
|
|
- .then((res) => res.text())
|
|
|
- .then((html) => simulateLoading(ref.current, html));
|
|
|
- }, []);
|
|
|
+ const templateName = getTemplateName(template, filename);
|
|
|
+ getTemplatePattern(templateName, context, tags, (html) =>
|
|
|
+ simulateLoading(ref.current, html),
|
|
|
+ );
|
|
|
+ });
|
|
|
|
|
|
return React.createElement(element, { ref });
|
|
|
};
|