generated from garronej/ts-ci
-
-
Notifications
You must be signed in to change notification settings - Fork 38
/
Copy pathappDir.tsx
113 lines (99 loc) · 3.51 KB
/
appDir.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
"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";
import type { Options as OptionsOfCreateCache } from "@emotion/cache";
import type { EmotionCache } from "@emotion/cache";
import type { ReactNode } from "react";
export type NextAppDirEmotionCacheProviderProps = {
/** This is the options passed to createCache() from 'import createCache from "@emotion/cache"' */
options: Omit<OptionsOfCreateCache, "insertionPoint"> & {
prepend?: boolean;
};
/** By default <CacheProvider /> from 'import { CacheProvider } from "@emotion/react"' */
CacheProvider?: React.Provider<EmotionCache>;
children: ReactNode;
};
export function NextAppDirEmotionCacheProvider(
props: NextAppDirEmotionCacheProviderProps
) {
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: { name: string; isGlobal: boolean }[] = [];
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: {
name: string;
style: string;
}[] = [];
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: string) =>
prepend ? `@layer emotion {${style}}` : style;
return (
<>
{globals.map(({ name, style }) => (
<style
nonce={options.nonce}
key={name}
data-emotion={`${cache.key}-global ${name}`}
dangerouslySetInnerHTML={{ "__html": get__Html(style) }}
/>
))}
{styles !== "" && (
<style
nonce={options.nonce}
data-emotion={dataEmotionAttribute}
dangerouslySetInnerHTML={{
"__html": get__Html(styles)
}}
/>
)}
</>
);
});
return <CacheProvider value={cache}>{children}</CacheProvider>;
}
export default NextAppDirEmotionCacheProvider;