StyledEngineProvider.js
5.14 KB
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
"use strict";
'use client';
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.TEST_INTERNALS_DO_NOT_USE = void 0;
exports.default = StyledEngineProvider;
var React = _interopRequireWildcard(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _react2 = require("@emotion/react");
var _cache = _interopRequireDefault(require("@emotion/cache"));
var _sheet = require("@emotion/sheet");
var _jsxRuntime = require("react/jsx-runtime");
// To fix [Jest performance](https://github.com/mui/material-ui/issues/45638).
const cacheMap = new Map();
// Need to add a private variable to test the generated CSS from Emotion, this is the simplest way to do it.
// We can't test the CSS from `style` tag easily because the `speedy: true` (produce empty text content) is enabled by Emotion.
// Even if we disable it, JSDOM needs extra configuration to be able to parse `@layer` CSS.
const TEST_INTERNALS_DO_NOT_USE = exports.TEST_INTERNALS_DO_NOT_USE = {
/**
* to intercept the generated CSS before inserting to the style tag, so that we can check the generated CSS.
*
* let rule;
* TEST_INTERNALS_DO_NOT_USE.insert = (...args) => {
* rule = args[0];
* };
*
* expect(rule).to.equal(...);
*/
insert: undefined
};
// We might be able to remove this when this issue is fixed:
// https://github.com/emotion-js/emotion/issues/2790
const createEmotionCache = (options, CustomSheet) => {
const cache = (0, _cache.default)(options);
// Do the same as https://github.com/emotion-js/emotion/blob/main/packages/cache/src/index.js#L238-L245
cache.sheet = new CustomSheet({
key: cache.key,
nonce: cache.sheet.nonce,
container: cache.sheet.container,
speedy: cache.sheet.isSpeedy,
prepend: cache.sheet.prepend,
insertionPoint: cache.sheet.insertionPoint
});
return cache;
};
let insertionPoint;
if (typeof document === 'object') {
// Use `insertionPoint` over `prepend`(deprecated) because it can be controlled for GlobalStyles injection order
// For more information, see https://github.com/mui/material-ui/issues/44597
insertionPoint = document.querySelector('[name="emotion-insertion-point"]');
if (!insertionPoint) {
insertionPoint = document.createElement('meta');
insertionPoint.setAttribute('name', 'emotion-insertion-point');
insertionPoint.setAttribute('content', '');
const head = document.querySelector('head');
if (head) {
head.prepend(insertionPoint);
}
}
}
function getCache(injectFirst, enableCssLayer) {
if (injectFirst || enableCssLayer) {
/**
* This is for client-side apps only.
* A custom sheet is required to make the GlobalStyles API injected above the insertion point.
* This is because the [sheet](https://github.com/emotion-js/emotion/blob/main/packages/react/src/global.js#L94-L99) does not consume the options.
*/
class MyStyleSheet extends _sheet.StyleSheet {
insert(rule, options) {
if (TEST_INTERNALS_DO_NOT_USE.insert) {
return TEST_INTERNALS_DO_NOT_USE.insert(rule, options);
}
if (this.key && this.key.endsWith('global')) {
this.before = insertionPoint;
}
return super.insert(rule, options);
}
}
const emotionCache = createEmotionCache({
key: 'css',
insertionPoint: injectFirst ? insertionPoint : undefined
}, MyStyleSheet);
if (enableCssLayer) {
const prevInsert = emotionCache.insert;
emotionCache.insert = (...args) => {
if (!args[1].styles.match(/^@layer\s+[^{]*$/)) {
// avoid nested @layer
args[1].styles = `@layer mui {${args[1].styles}}`;
}
return prevInsert(...args);
};
}
return emotionCache;
}
return undefined;
}
function StyledEngineProvider(props) {
const {
injectFirst,
enableCssLayer,
children
} = props;
const cache = React.useMemo(() => {
const cacheKey = `${injectFirst}-${enableCssLayer}`;
if (typeof document === 'object' && cacheMap.has(cacheKey)) {
return cacheMap.get(cacheKey);
}
const fresh = getCache(injectFirst, enableCssLayer);
cacheMap.set(cacheKey, fresh);
return fresh;
}, [injectFirst, enableCssLayer]);
return cache ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_react2.CacheProvider, {
value: cache,
children: children
}) : children;
}
process.env.NODE_ENV !== "production" ? StyledEngineProvider.propTypes = {
/**
* Your component tree.
*/
children: _propTypes.default.node,
/**
* If `true`, the styles are wrapped in `@layer mui`.
* Learn more about [Cascade layers](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/Cascade_layers).
*/
enableCssLayer: _propTypes.default.bool,
/**
* By default, the styles are injected last in the <head> element of the page.
* As a result, they gain more specificity than any other style sheet.
* If you want to override MUI's styles, set this prop.
*/
injectFirst: _propTypes.default.bool
} : void 0;