UNPKG

tss-react

Version:

Type safe CSS-in-JS API heavily inspired by react-jss

63 lines (62 loc) 2.56 kB
"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;