hydro-js-integrations
Version:
Integrations for Vite and Astro and more TBC
55 lines (47 loc) • 1.64 kB
text/typescript
import { html, render, h, setReuseElements } from "hydro-js";
setReuseElements(false);
let elementMap = new WeakMap<HTMLElement, ReturnType<typeof h>>();
export default (element: HTMLElement) =>
async (
Component: any,
props: Record<string, any>,
{ default: children, ...slotted }: Record<string, any>
) => {
if (!element.hasAttribute("ssr")) return;
const slots: HTMLSlotElement[] = [];
for (const [key, value] of Object.entries(slotted)) {
let elem;
if (key === "default") {
elem = html`<astro-slot>${value}</astro-slot>`;
} else {
elem = html`<astro-slot name="${key}">${value}</astro-slot>`;
}
slots.push(elem as HTMLSlotElement);
}
const place = elementMap.get(element);
const node =
typeof Component === "function"
? Component({
...props,
...(children ? { children: html`${String(children)}` } : {}),
})
: html`<${Component} ${props}>${
children ? String(children) : ""
}</${Component}>`;
node.append(...slots);
let unmount: ReturnType<typeof render>;
if (place) {
unmount = render(node, place);
} else {
const span = document.createElement("span");
span.style.display = "contents";
const children = Array.from(element.childNodes);
element.appendChild(span);
span.append(...children);
unmount = render(node, span);
}
elementMap.set(element, node);
element.addEventListener("astro:unmount", () => unmount(), {
once: true,
});
};