`
${resolve(props.title, data)}
`;
const $content = html``;
const $footer = html``;
const $background = html``;
const $page = html`${$background}
${$title}${$content}${$footer}
`;
$page.classList.toggle('page-centered', template === 'title');
$content.classList.toggle('page-full', template === 'full');
const $RenderSimplePage = Object.assign($page, {
$title,
$content,
$footer,
render() {
const $el = resolve(props.content, data, $content);
const $bg = resolve(props.background, data, $background);
if ($el) $content.append($el);
if ($bg) $background.append($bg);
$RenderSimplePage.render = () => {};
},
});
return $RenderSimplePage;
}
export type PageState = PageObject | ((data?: D) => PageObject);
export function Presentation({
lazy = 2,
Template = SimplePage,
}: {
lazy?: number;
Template?: (props: PageObject, data?: any) => PageElement;
} = {}) {
const cache = new Map, PageElement>();
const history = new Map, number>();
let steps = 0;
const $container = html``;
return Object.assign($container, {
load(newState: PageState, data?: T) {
// console.log('load', cache.has(newState), data);
let currentPage;
if (cache.has(newState)) {
// checks in cache
currentPage = cache.get(newState)!;
} else {
const props = typeof newState === 'object' ? newState : newState(data);
currentPage = Template(props, data);
cache.set(newState, currentPage);
}
if (history.size > 0)
// replace
$container.insertBefore(currentPage, $container.firstChild);
else $container.append(currentPage); // append
currentPage.render();
// add to history
steps++;
history.set(newState, steps);
history.forEach((v, props) => {
// delete expired
if (v < steps - lazy) {
$container.removeChild(cache.get(props)!);
history.delete(props);
cache.delete(props);
}
});
},
preload(newState: PageState, data?: T) {
if (!cache.has(newState)) {
// checks in cache
const props = typeof newState === 'object' ? newState : newState(data);
const page = Template(props, data);
cache.set(newState, page);
$container.append(page);
page.render();
}
history.set(newState, steps); // update ranking in history
},
});
}
export function resolve(
res: any,
...rest: [T, ...any]
): null | string | Node {
if (!res) return null;
if (typeof res === 'string') return res;
if (res instanceof Text) return res;
if (res instanceof DocumentFragment) return res;
if (res instanceof Element) return res;
if (res.node && typeof res.node === 'function') return res.node();
return resolve(res(...rest), ...rest);
}