UNPKG

@astrojs/react

Version:
101 lines (100 loc) 3.21 kB
import { createElement, startTransition } from "react"; import { createRoot, hydrateRoot } from "react-dom/client"; import StaticHtml from "./static-html.js"; function isAlreadyHydrated(element) { for (const key in element) { if (key.startsWith("__reactContainer")) { return key; } } } function createReactElementFromDOMElement(element) { let attrs = {}; for (const attr of element.attributes) { attrs[attr.name] = attr.value; } if (element.firstChild === null) { return createElement(element.localName, attrs); } return createElement( element.localName, attrs, Array.from(element.childNodes).map((c) => { if (c.nodeType === Node.TEXT_NODE) { return c.data; } else if (c.nodeType === Node.ELEMENT_NODE) { return createReactElementFromDOMElement(c); } else { return void 0; } }).filter((a) => !!a) ); } function getChildren(childString, experimentalReactChildren) { if (experimentalReactChildren && childString) { let children = []; let template = document.createElement("template"); template.innerHTML = childString; for (let child of template.content.children) { children.push(createReactElementFromDOMElement(child)); } return children; } else if (childString) { return createElement(StaticHtml, { value: childString }); } else { return void 0; } } let rootMap = /* @__PURE__ */ new WeakMap(); const getOrCreateRoot = (element, creator) => { let root = rootMap.get(element); if (!root) { root = creator(); rootMap.set(element, root); } return root; }; var client_default = (element) => (Component, props, { default: children, ...slotted }, { client }) => { if (!element.hasAttribute("ssr")) return; const actionKey = element.getAttribute("data-action-key"); const actionName = element.getAttribute("data-action-name"); const stringifiedActionResult = element.getAttribute("data-action-result"); const formState = actionKey && actionName && stringifiedActionResult ? [JSON.parse(stringifiedActionResult), actionKey, actionName] : void 0; const renderOptions = { identifierPrefix: element.getAttribute("prefix"), formState }; for (const [key, value] of Object.entries(slotted)) { props[key] = createElement(StaticHtml, { value, name: key }); } const componentEl = createElement( Component, props, getChildren(children, element.hasAttribute("data-react-children")) ); const rootKey = isAlreadyHydrated(element); if (rootKey) { delete element[rootKey]; } if (client === "only") { return startTransition(() => { const root = getOrCreateRoot(element, () => { const r = createRoot(element); element.addEventListener("astro:unmount", () => r.unmount(), { once: true }); return r; }); root.render(componentEl); }); } startTransition(() => { const root = getOrCreateRoot(element, () => { const r = hydrateRoot(element, componentEl, renderOptions); element.addEventListener("astro:unmount", () => r.unmount(), { once: true }); return r; }); root.render(componentEl); }); }; export { client_default as default };