89 lines
2.1 KiB
JavaScript
89 lines
2.1 KiB
JavaScript
|
|
'use client'
|
||
|
|
|
||
|
|
import * as React from 'react'
|
||
|
|
import PropTypes from 'prop-types'
|
||
|
|
import createCache from '@emotion/cache'
|
||
|
|
import {useServerInsertedHTML} from 'next/navigation'
|
||
|
|
import {CacheProvider as DefaultCacheProvider} from '@emotion/react'
|
||
|
|
|
||
|
|
export default function NextAppDirEmotionCacheProvider(props) {
|
||
|
|
const {options, CacheProvider = DefaultCacheProvider, children} = props
|
||
|
|
|
||
|
|
const [registry] = React.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 = registry.flush()
|
||
|
|
if (inserted.length === 0) {
|
||
|
|
return null
|
||
|
|
}
|
||
|
|
|
||
|
|
let styles = ''
|
||
|
|
let dataEmotionAttribute = registry.cache.key
|
||
|
|
|
||
|
|
const globals = []
|
||
|
|
|
||
|
|
for (const {name, isGlobal} of inserted) {
|
||
|
|
const style = registry.cache.inserted[name]
|
||
|
|
|
||
|
|
if (typeof style !== 'boolean') {
|
||
|
|
if (isGlobal) {
|
||
|
|
globals.push({name, style})
|
||
|
|
} else {
|
||
|
|
styles += style
|
||
|
|
dataEmotionAttribute += ` ${name}`
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return (
|
||
|
|
<>
|
||
|
|
{globals.map(({name, style}) => (
|
||
|
|
<style
|
||
|
|
key={name}
|
||
|
|
dangerouslySetInnerHTML={{__html: style}}
|
||
|
|
data-emotion={`${registry.cache.key}-global ${name}`}
|
||
|
|
/>
|
||
|
|
))}
|
||
|
|
{styles !== '' && (
|
||
|
|
<style
|
||
|
|
dangerouslySetInnerHTML={{__html: styles}}
|
||
|
|
data-emotion={dataEmotionAttribute}
|
||
|
|
/>
|
||
|
|
)}
|
||
|
|
</>
|
||
|
|
)
|
||
|
|
})
|
||
|
|
|
||
|
|
return <CacheProvider value={registry.cache}>{children}</CacheProvider>
|
||
|
|
}
|
||
|
|
|
||
|
|
NextAppDirEmotionCacheProvider.propTypes = {
|
||
|
|
options: PropTypes.object.isRequired,
|
||
|
|
CacheProvider: PropTypes.func,
|
||
|
|
children: PropTypes.node.isRequired
|
||
|
|
}
|