tss-react
Version:
Type safe CSS-in-JS API heavily inspired by react-jss
63 lines (62 loc) • 2.56 kB
JavaScript
"use client";
import React from "react";
import createCache from "@emotion/cache";
import { useServerInsertedHTML } from "next/navigation";
import { useState } from "react";
import { CacheProvider as DefaultCacheProvider } from "@emotion/react";
export function NextAppDirEmotionCacheProvider(props) {
const { options: optionsWithPrepend, CacheProvider = DefaultCacheProvider, children } = props;
const { prepend = false, ...options } = optionsWithPrepend;
const [{ cache, flush }] = useState(() => {
const cache = createCache(options);
cache.compat = true;
const prevInsert = cache.insert;
let inserted = [];
cache.insert = (...args) => {
const [selector, serialized] = args;
if (cache.inserted[serialized.name] === undefined) {
inserted.push({
"name": serialized.name,
"isGlobal": selector === ""
});
}
return prevInsert(...args);
};
const flush = () => {
const prevInserted = inserted;
inserted = [];
return prevInserted;
};
return { cache, flush };
});
useServerInsertedHTML(() => {
const inserted = flush();
if (inserted.length === 0) {
return null;
}
let styles = "";
let dataEmotionAttribute = cache.key;
const globals = [];
for (const { name, isGlobal } of inserted) {
const style = cache.inserted[name];
if (typeof style === "boolean") {
continue;
}
if (isGlobal) {
globals.push({ name, style });
}
else {
styles += style;
dataEmotionAttribute += ` ${name}`;
}
}
const get__Html = (style) => prepend ? `@layer emotion {${style}}` : style;
return (React.createElement(React.Fragment, null,
globals.map(({ name, style }) => (React.createElement("style", { nonce: options.nonce, key: name, "data-emotion": `${cache.key}-global ${name}`, dangerouslySetInnerHTML: { "__html": get__Html(style) } }))),
styles !== "" && (React.createElement("style", { nonce: options.nonce, "data-emotion": dataEmotionAttribute, dangerouslySetInnerHTML: {
"__html": get__Html(styles)
} }))));
});
return React.createElement(CacheProvider, { value: cache }, children);
}
export default NextAppDirEmotionCacheProvider;