aquameta-widget
Version:
Widget rendering framework built on top of Aquameta
75 lines (70 loc) • 1.98 kB
JavaScript
import html from '/db/widget/core/html.js';
import React from '/db/widget/dep/react.js';
import styled from '/db/widget/dep/styled-components.js';
import Markdown from '/db/widget/component/markdown.js';
import Centered from '/db/widget/component/centered.js';
const SlideWrapper = styled.div`
background-color: ${({theme}) => theme.colors.opaque.light};
border: 2px solid ${({theme}) => theme.colors.dark};
border-radius: 2px;
color: ${({theme}) => theme.colors.dark};
display: inline-block;
height: auto;
height: ${({theme}) => theme.height};
overflow: auto;
padding: 0 30px;
width: 100%;
`;
function LazyLoader({importPath}) {
const LazyComp = React.useMemo(() => {
return React.lazy(async () => {
let component;
try {
component = await import(importPath);
} catch (e) {
component = {
default: () => html`<${Centered}>Component not found<//>`
};
}
return component;
});
}, [importPath]);
return html`
<${React.Suspense} fallback=${html`<${Loading} />`}>
<${LazyComp}/>
<//>
`;
}
function Loading() {
return html`<${Centered}>Loading...<//>`
}
const shortcodeRegex = /SHORTCODE'(.*?)'END/g;
export default function Slide(props) {
let content = props.slide.markdown;
const children = [];
while (true) {
const match = shortcodeRegex.exec(content);
if (!match) {
break;
}
const markdown = content.slice(0, match.index);
const [shortcode, importPath] = match;
content = content.slice(match.index + shortcode.length);
const l = children.length;
children.push(
html`<${Markdown} key=${l+'md'} markdown=${markdown} />`,
html`<${LazyLoader} key=${l+'comp'} importPath=${importPath} />`,
);
}
if (content) {
const l = children.length;
children.push(
html`<${Markdown} key=${l+'md'} markdown=${content} />`
);
}
return html`
<${SlideWrapper}>
${children}
<//>
`;
}