mirror of
https://github.com/withastro/astro.git
synced 2025-01-06 22:10:10 -05:00
37021044dd
* Render async SolidJS components * Add renderer-specific hydration script to allow for proper SolidJS hydration * Add support for Solid.js 1.8.x * Address documentation feedback * Rebuild pnpm lock file based on main branch * Address PR feedback from ematipico --------- Co-authored-by: Johannes Spohr <johannes.spohr@futurice.com> Co-authored-by: Florian Lefebvre <contact@florian-lefebvre.dev>
62 lines
1.8 KiB
TypeScript
62 lines
1.8 KiB
TypeScript
import { Suspense } from 'solid-js';
|
|
import { createComponent, hydrate, render } from 'solid-js/web';
|
|
|
|
export default (element: HTMLElement) =>
|
|
(Component: any, props: any, slotted: any, { client }: { client: string }) => {
|
|
if (!element.hasAttribute('ssr')) return;
|
|
|
|
const isHydrate = client !== 'only';
|
|
const bootstrap = isHydrate ? hydrate : render;
|
|
|
|
let slot: HTMLElement | null;
|
|
let _slots: Record<string, any> = {};
|
|
if (Object.keys(slotted).length > 0) {
|
|
// hydratable
|
|
if (client !== 'only') {
|
|
const iterator = document.createTreeWalker(element, NodeFilter.SHOW_ELEMENT, (node) => {
|
|
if (node === element) return NodeFilter.FILTER_SKIP;
|
|
if (node.nodeName === 'ASTRO-SLOT') return NodeFilter.FILTER_ACCEPT;
|
|
if (node.nodeName === 'ASTRO-ISLAND') return NodeFilter.FILTER_REJECT;
|
|
return NodeFilter.FILTER_SKIP;
|
|
});
|
|
while ((slot = iterator.nextNode() as HTMLElement | null))
|
|
_slots[slot.getAttribute('name') || 'default'] = slot;
|
|
}
|
|
for (const [key, value] of Object.entries(slotted)) {
|
|
if (_slots[key]) continue;
|
|
_slots[key] = document.createElement('astro-slot');
|
|
if (key !== 'default') _slots[key].setAttribute('name', key);
|
|
_slots[key].innerHTML = value;
|
|
}
|
|
}
|
|
|
|
const { default: children, ...slots } = _slots;
|
|
const renderId = element.dataset.solidRenderId;
|
|
|
|
const dispose = bootstrap(
|
|
() => {
|
|
const inner = () =>
|
|
createComponent(Component, {
|
|
...props,
|
|
...slots,
|
|
children,
|
|
});
|
|
|
|
if (isHydrate) {
|
|
return createComponent(Suspense, {
|
|
get children() {
|
|
return inner();
|
|
},
|
|
});
|
|
} else {
|
|
return inner();
|
|
}
|
|
},
|
|
element,
|
|
{
|
|
renderId,
|
|
}
|
|
);
|
|
|
|
element.addEventListener('astro:unmount', () => dispose(), { once: true });
|
|
};
|