astro/packages/integrations/preact/src/client.ts

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

50 lines
1.5 KiB
TypeScript
Raw Normal View History

2023-02-13 19:50:21 +00:00
import { h, render, type JSX } from 'preact';
import StaticHtml from './static-html.js';
import type { SignalLike } from './types';
const sharedSignalMap: Map<string, SignalLike> = new Map();
export default (element: HTMLElement) =>
async (
Component: any,
props: Record<string, any>,
{ default: children, ...slotted }: Record<string, any>
) => {
if (!element.hasAttribute('ssr')) return;
for (const [key, value] of Object.entries(slotted)) {
props[key] = h(StaticHtml, { value, name: key });
}
let signalsRaw = element.dataset.preactSignals;
if (signalsRaw) {
const { signal } = await import('@preact/signals');
let signals: Record<string, string> = JSON.parse(element.dataset.preactSignals as string);
for (const [propName, signalId] of Object.entries(signals)) {
if (!sharedSignalMap.has(signalId)) {
const signalValue = signal(props[propName]);
sharedSignalMap.set(signalId, signalValue);
}
props[propName] = sharedSignalMap.get(signalId);
}
}
// eslint-disable-next-line @typescript-eslint/no-shadow
2023-02-13 19:50:21 +00:00
function Wrapper({ children }: { children: JSX.Element }) {
let attrs = Object.fromEntries(
Array.from(element.attributes).map((attr) => [attr.name, attr.value])
);
return h(element.localName, attrs, children);
}
2023-02-13 19:50:21 +00:00
let parent = element.parentNode as Element;
render(
2023-02-13 19:50:21 +00:00
h(
Wrapper,
null,
h(Component, props, children != null ? h(StaticHtml, { value: children }) : children)
),
parent,
element
);
};