vira
Version:
A simple and highly versatile design system using element-vir.
62 lines (61 loc) • 2.27 kB
JavaScript
import { asyncProp } from 'element-vir';
/**
* Create a dynamic element loader. This should go in your element state. This makes deferring
* element importing convenient and allows parts of your app to be placed in separate bundles. Make
* sure to also use {@link renderDynamicElement} to use the output of this loader.
*
* @category Util
* @see {@link renderDynamicElement}
* @see [example usage](https://github.com/electrovir/vira/blob/dev/packages/vira-book/src/element-book/entries/dynamic-elements.book.ts)
*/
export function createDynamicElementLoader(loaders) {
return asyncProp({
async updateCallback(elementKey, previousResolvedValue) {
if (previousResolvedValue && elementKey in previousResolvedValue.cache) {
return {
cache: previousResolvedValue.cache,
element: previousResolvedValue.cache[elementKey],
key: elementKey,
};
}
const imported = await loaders[elementKey]();
return {
cache: {
...previousResolvedValue?.cache,
[elementKey]: imported,
},
element: imported,
key: elementKey,
};
},
});
}
/**
* Renders the current state of a dynamic element loader. This should go in your render function.
* Make sure to also use {@link createDynamicElementLoader} to create a dynamic loader in your
* element's state.
*
* @category Util
* @see {@link createDynamicElementLoader}
* @see [example usage](https://github.com/electrovir/vira/blob/dev/packages/vira-book/src/element-book/entries/dynamic-elements.book.ts)
*/
export function renderDynamicElement(asyncProp, { ready, loading, error, key, }) {
if (key) {
asyncProp.update(key);
}
if (asyncProp.value instanceof Error) {
return error(asyncProp.value);
}
else if (asyncProp.value instanceof Promise) {
return loading(asyncProp.value.then((value) => {
return {
[value.key]: value.element,
};
}));
}
else {
return ready({
[asyncProp.value.key]: asyncProp.value.element,
});
}
}