1 | import { h, createContext } from "preact";
|
2 | import { useContext } from "preact/hooks";
|
3 | import { Buffer } from "buffer";
|
4 | import { __DocContext } from "./document";
|
5 | const isServer = typeof window === "undefined";
|
6 | const btoa = (str) => Buffer.from(str, "utf-8").toString("base64");
|
7 | const HydrateContext = createContext(false);
|
8 | export function withHydrate(Component, hydrationProps = {}) {
|
9 | const name = Component.displayName || Component.name;
|
10 | const { method = "idle" } = hydrationProps;
|
11 | const Wrapped = (props, ref) => {
|
12 | const { hydrate } = useContext(__DocContext);
|
13 | const hydrateParent = useContext(HydrateContext);
|
14 | if (hydrateParent)
|
15 | throw new Error(`withHydrate() should only be called at the top-level of a Component tree. <${name} /> should not be nested within <${hydrateParent} />`);
|
16 | if (isServer)
|
17 | hydrate.current.push({ name });
|
18 | if (props.children && !["string", "number"].includes(typeof props.children))
|
19 | throw new Error(`withHydrate() is unable to serialize complex \`children\`. Please inline these children into <${name} />.`);
|
20 | return (h(HydrateContext.Provider, { value: name },
|
21 | h("div", Object.assign({}, (isServer
|
22 | ? {
|
23 | "data-hydrate": name,
|
24 | "data-props": Object.keys(props).length > 0
|
25 | ? btoa(JSON.stringify(props))
|
26 | : null,
|
27 | "data-method": method,
|
28 | }
|
29 | : {})),
|
30 | h(Component, Object.assign({}, Object.assign(Object.assign({}, props), { ref }))))));
|
31 | };
|
32 | Object.defineProperty(Wrapped, "name", { value: name, configurable: true });
|
33 | return Wrapped;
|
34 | }
|