1 | import { h, createContext } from "preact";
|
2 | import { useContext } from "preact/hooks";
|
3 | const isServer = typeof window === "undefined";
|
4 | export const HydrateContext = createContext(false);
|
5 | export function withHydrate(Component, hydrationProps = {}) {
|
6 | const name = hydrationProps.displayName || Component.displayName || Component.name;
|
7 | const { method, fallback: Fallback } = hydrationProps;
|
8 | const Wrapped = (props, ref) => {
|
9 | const hydrateParent = useContext(HydrateContext);
|
10 | if (hydrateParent)
|
11 | throw new Error(`withHydrate() should only be called at the top-level of a Component tree. <${name} /> should not be nested within <${hydrateParent} />`);
|
12 | if (props.children && !["string", "number"].includes(typeof props.children))
|
13 | throw new Error(`withHydrate() is unable to serialize complex \`children\`. Please inline these children into <${name} />.`);
|
14 | const p = isServer ? `p=${JSON.stringify(props)}` : '';
|
15 | const m = isServer && method ? `m=${method}` : '';
|
16 | const f = isServer && typeof Fallback !== 'undefined' ? 'f=1' : '';
|
17 | const Marker = 'hydrate-marker';
|
18 | const Placeholder = 'hydrate-placeholder';
|
19 | return (h(HydrateContext.Provider, { value: name },
|
20 | isServer && (h(Marker, { dangerouslySetInnerHTML: { __html: `?h c=${name} ?` } })),
|
21 | typeof Fallback !== 'undefined' ? (Fallback || h(Placeholder, null)) : h(Component, Object.assign({}, Object.assign(Object.assign({}, props), { ref }))),
|
22 | isServer && (h(Marker, { dangerouslySetInnerHTML: { __html: `?h ${[p, m, f].filter(v => v).join(' ')} ?` } }))));
|
23 | };
|
24 | Object.defineProperty(Wrapped, "name", { value: name, configurable: true });
|
25 | return Wrapped;
|
26 | }
|