styled-components 6.4.0-prerelease.5 → 6.4.0-prerelease.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/constructors/createGlobalStyle.d.ts +10 -0
- package/dist/constructors/css.d.ts +12 -0
- package/dist/constructors/keyframes.d.ts +11 -0
- package/dist/constructors/styled.d.ts +8 -0
- package/dist/hoc/withTheme.d.ts +1 -0
- package/dist/models/ComponentStyle.d.ts +1 -2
- package/dist/models/InlineStyle.d.ts +11 -0
- package/dist/models/ServerStyleSheet.d.ts +10 -0
- package/dist/models/StyleSheetManager.d.ts +1 -0
- package/dist/native/index.d.ts +18 -2
- package/dist/styled-components.browser.cjs.js +3 -3
- package/dist/styled-components.browser.cjs.js.map +1 -1
- package/dist/styled-components.browser.esm.js +2 -2
- package/dist/styled-components.browser.esm.js.map +1 -1
- package/dist/styled-components.cjs.js +3 -3
- package/dist/styled-components.cjs.js.map +1 -1
- package/dist/styled-components.esm.js +3 -3
- package/dist/styled-components.esm.js.map +1 -1
- package/dist/styled-components.js +183 -90
- package/dist/styled-components.js.map +1 -1
- package/dist/styled-components.min.js +3 -3
- package/dist/styled-components.min.js.map +1 -1
- package/dist/utils/escape.d.ts +0 -4
- package/dist/utils/hash.d.ts +1 -0
- package/dist/utils/isStyledComponent.d.ts +1 -0
- package/native/dist/constructors/createGlobalStyle.d.ts +10 -0
- package/native/dist/constructors/css.d.ts +12 -0
- package/native/dist/constructors/keyframes.d.ts +11 -0
- package/native/dist/constructors/styled.d.ts +8 -0
- package/native/dist/dist/constructors/createGlobalStyle.d.ts +10 -0
- package/native/dist/dist/constructors/css.d.ts +12 -0
- package/native/dist/dist/constructors/keyframes.d.ts +11 -0
- package/native/dist/dist/constructors/styled.d.ts +8 -0
- package/native/dist/dist/hoc/withTheme.d.ts +1 -0
- package/native/dist/dist/models/ComponentStyle.d.ts +1 -2
- package/native/dist/dist/models/InlineStyle.d.ts +11 -0
- package/native/dist/dist/models/ServerStyleSheet.d.ts +10 -0
- package/native/dist/dist/models/StyleSheetManager.d.ts +1 -0
- package/native/dist/dist/native/index.d.ts +18 -2
- package/native/dist/dist/utils/escape.d.ts +0 -4
- package/native/dist/dist/utils/hash.d.ts +1 -0
- package/native/dist/dist/utils/isStyledComponent.d.ts +1 -0
- package/native/dist/hoc/withTheme.d.ts +1 -0
- package/native/dist/models/ComponentStyle.d.ts +1 -2
- package/native/dist/models/InlineStyle.d.ts +11 -0
- package/native/dist/models/ServerStyleSheet.d.ts +10 -0
- package/native/dist/models/StyleSheetManager.d.ts +1 -0
- package/native/dist/native/index.d.ts +18 -2
- package/native/dist/styled-components.native.cjs.js +1 -1
- package/native/dist/styled-components.native.cjs.js.map +1 -1
- package/native/dist/styled-components.native.esm.js +1 -1
- package/native/dist/styled-components.native.esm.js.map +1 -1
- package/native/dist/utils/escape.d.ts +0 -4
- package/native/dist/utils/hash.d.ts +1 -0
- package/native/dist/utils/isStyledComponent.d.ts +1 -0
- package/native/package.json +7 -2
- package/package.json +5 -5
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
'data-styled';
|
|
12
12
|
const SC_ATTR_ACTIVE = 'active';
|
|
13
13
|
const SC_ATTR_VERSION = 'data-styled-version';
|
|
14
|
-
const SC_VERSION = "6.4.0-prerelease.
|
|
14
|
+
const SC_VERSION = "6.4.0-prerelease.8";
|
|
15
15
|
const SPLITTER = '/*!sc*/\n';
|
|
16
16
|
const IS_BROWSER = typeof window !== 'undefined' && typeof document !== 'undefined';
|
|
17
17
|
function readSpeedyFlag(name) {
|
|
@@ -273,11 +273,11 @@
|
|
|
273
273
|
continue;
|
|
274
274
|
const selector = SC_ATTR + '.g' + group + '[id="' + id + '"]';
|
|
275
275
|
let content = '';
|
|
276
|
-
|
|
276
|
+
for (const name of names) {
|
|
277
277
|
if (name.length > 0) {
|
|
278
278
|
content += name + ',';
|
|
279
279
|
}
|
|
280
|
-
}
|
|
280
|
+
}
|
|
281
281
|
// NOTE: It's easier to collect rules and have the marker
|
|
282
282
|
// after the actual rules to simplify the rehydration
|
|
283
283
|
css += rules + selector + '{content:"' + content + '"}' + SPLITTER;
|
|
@@ -658,7 +658,7 @@
|
|
|
658
658
|
return '';
|
|
659
659
|
}
|
|
660
660
|
if (typeof value === 'number' && value !== 0 && !(name in unitless) && !name.startsWith('--')) {
|
|
661
|
-
return
|
|
661
|
+
return value + 'px'; // Presumes implicit 'px' suffix for unitless numbers except for CSS variables
|
|
662
662
|
}
|
|
663
663
|
return String(value).trim();
|
|
664
664
|
}
|
|
@@ -723,6 +723,7 @@
|
|
|
723
723
|
return isFunction(test) && !(test.prototype && test.prototype.isReactComponent);
|
|
724
724
|
}
|
|
725
725
|
|
|
726
|
+
/** Type guard that returns true if the target is a styled component. */
|
|
726
727
|
function isStyledComponent(target) {
|
|
727
728
|
return typeof target === 'object' && 'styledComponentId' in target;
|
|
728
729
|
}
|
|
@@ -739,13 +740,13 @@
|
|
|
739
740
|
continue;
|
|
740
741
|
// @ts-expect-error Property 'isCss' does not exist on type 'any[]'
|
|
741
742
|
if ((Array.isArray(val) && val.isCss) || isFunction(val)) {
|
|
742
|
-
rules.push(
|
|
743
|
+
rules.push(hyphenateStyleName(key) + ':', val, ';');
|
|
743
744
|
}
|
|
744
745
|
else if (isPlainObject(val)) {
|
|
745
|
-
rules.push(
|
|
746
|
+
rules.push(key + ' {', ...objToCssArray(val), '}');
|
|
746
747
|
}
|
|
747
748
|
else {
|
|
748
|
-
rules.push(
|
|
749
|
+
rules.push(hyphenateStyleName(key) + ': ' + addUnitIfNeeded(key, val) + ';');
|
|
749
750
|
}
|
|
750
751
|
}
|
|
751
752
|
return rules;
|
|
@@ -825,7 +826,7 @@
|
|
|
825
826
|
* Convenience function for joining strings to form className chains
|
|
826
827
|
*/
|
|
827
828
|
function joinStrings(a, b) {
|
|
828
|
-
return a && b ?
|
|
829
|
+
return a && b ? a + ' ' + b : a || b || '';
|
|
829
830
|
}
|
|
830
831
|
function joinStringArray(arr, sep) {
|
|
831
832
|
return arr.join(sep || '');
|
|
@@ -898,9 +899,9 @@
|
|
|
898
899
|
rebuildGroup(styleSheet) {
|
|
899
900
|
const id = this.componentId;
|
|
900
901
|
styleSheet.clearRules(id);
|
|
901
|
-
this.instanceRules.
|
|
902
|
+
for (const entry of this.instanceRules.values()) {
|
|
902
903
|
styleSheet.insertRules(id, entry.name, entry.rules);
|
|
903
|
-
}
|
|
904
|
+
}
|
|
904
905
|
}
|
|
905
906
|
}
|
|
906
907
|
|
|
@@ -1167,22 +1168,26 @@
|
|
|
1167
1168
|
* Takes an element and recurses through it's rules added the namespace to the start of each selector.
|
|
1168
1169
|
* Takes into account media queries by recursing through child rules if they are present.
|
|
1169
1170
|
*/
|
|
1170
|
-
function
|
|
1171
|
-
|
|
1171
|
+
function recursivelySetNamespace(compiled, namespace) {
|
|
1172
|
+
for (let i = 0; i < compiled.length; i++) {
|
|
1173
|
+
const rule = compiled[i];
|
|
1172
1174
|
if (rule.type === 'rule') {
|
|
1173
1175
|
// add the namespace to the start
|
|
1174
|
-
rule.value =
|
|
1176
|
+
rule.value = namespace + ' ' + rule.value;
|
|
1175
1177
|
// add the namespace after each comma for subsequent selectors.
|
|
1176
|
-
rule.value = rule.value.replaceAll(',',
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1178
|
+
rule.value = rule.value.replaceAll(',', ',' + namespace + ' ');
|
|
1179
|
+
const props = rule.props;
|
|
1180
|
+
const newProps = [];
|
|
1181
|
+
for (let j = 0; j < props.length; j++) {
|
|
1182
|
+
newProps[j] = namespace + ' ' + props[j];
|
|
1183
|
+
}
|
|
1184
|
+
rule.props = newProps;
|
|
1180
1185
|
}
|
|
1181
1186
|
if (Array.isArray(rule.children) && rule.type !== '@keyframes') {
|
|
1182
|
-
rule.children =
|
|
1187
|
+
rule.children = recursivelySetNamespace(rule.children, namespace);
|
|
1183
1188
|
}
|
|
1184
|
-
|
|
1185
|
-
|
|
1189
|
+
}
|
|
1190
|
+
return compiled;
|
|
1186
1191
|
}
|
|
1187
1192
|
function createStylisInstance({ options = EMPTY_OBJECT, plugins = EMPTY_ARRAY, } = EMPTY_OBJECT) {
|
|
1188
1193
|
let _componentId;
|
|
@@ -1251,9 +1256,9 @@
|
|
|
1251
1256
|
_selector = selector;
|
|
1252
1257
|
_selectorRegexp = undefined; // Reset for lazy creation per call
|
|
1253
1258
|
const flatCSS = sanitizeCSS(stripLineComments(css));
|
|
1254
|
-
let compiled = ue(prefix || selector ?
|
|
1259
|
+
let compiled = ue(prefix || selector ? prefix + ' ' + selector + ' { ' + flatCSS + ' }' : flatCSS);
|
|
1255
1260
|
if (options.namespace) {
|
|
1256
|
-
compiled =
|
|
1261
|
+
compiled = recursivelySetNamespace(compiled, options.namespace);
|
|
1257
1262
|
}
|
|
1258
1263
|
_stack = [];
|
|
1259
1264
|
ve(compiled, _middleware);
|
|
@@ -1286,9 +1291,9 @@
|
|
|
1286
1291
|
const StylisContext = React.createContext(undefined)
|
|
1287
1292
|
;
|
|
1288
1293
|
function useStyleSheetContext() {
|
|
1289
|
-
|
|
1290
|
-
return React.useContext(StyleSheetContext) ;
|
|
1294
|
+
return React.useContext(StyleSheetContext);
|
|
1291
1295
|
}
|
|
1296
|
+
/** Configure style injection for descendant styled components (target element, stylis plugins, prop forwarding). */
|
|
1292
1297
|
function StyleSheetManager(props) {
|
|
1293
1298
|
// In RSC environments without context support, StyleSheetManager becomes a no-op
|
|
1294
1299
|
if (!React.useMemo) {
|
|
@@ -1479,6 +1484,16 @@
|
|
|
1479
1484
|
return addTag(flatten(interleave(styleStringArray, interpolations)));
|
|
1480
1485
|
}
|
|
1481
1486
|
|
|
1487
|
+
/**
|
|
1488
|
+
* Create a component that injects global CSS when mounted. Supports theming and dynamic props.
|
|
1489
|
+
*
|
|
1490
|
+
* ```tsx
|
|
1491
|
+
* const GlobalStyle = createGlobalStyle`
|
|
1492
|
+
* body { margin: 0; font-family: system-ui; }
|
|
1493
|
+
* `;
|
|
1494
|
+
* // Render <GlobalStyle /> at the root of your app
|
|
1495
|
+
* ```
|
|
1496
|
+
*/
|
|
1482
1497
|
function createGlobalStyle(strings, ...interpolations) {
|
|
1483
1498
|
const rules = css(strings, ...interpolations);
|
|
1484
1499
|
const styledComponentId = `sc-global-${generateComponentId(JSON.stringify(rules))}`;
|
|
@@ -1710,6 +1725,17 @@
|
|
|
1710
1725
|
}
|
|
1711
1726
|
_a = KEYFRAMES_SYMBOL;
|
|
1712
1727
|
|
|
1728
|
+
/**
|
|
1729
|
+
* Define a CSS `@keyframes` animation with an automatically scoped name.
|
|
1730
|
+
*
|
|
1731
|
+
* ```tsx
|
|
1732
|
+
* const rotate = keyframes`
|
|
1733
|
+
* from { transform: rotate(0deg); }
|
|
1734
|
+
* to { transform: rotate(360deg); }
|
|
1735
|
+
* `;
|
|
1736
|
+
* const Spinner = styled.div`animation: ${rotate} 1s linear infinite;`;
|
|
1737
|
+
* ```
|
|
1738
|
+
*/
|
|
1713
1739
|
function keyframes(strings, ...interpolations) {
|
|
1714
1740
|
/* Warning if you've used keyframes on React Native */
|
|
1715
1741
|
if (typeof navigator !== 'undefined' &&
|
|
@@ -1815,6 +1841,7 @@
|
|
|
1815
1841
|
return targetComponent;
|
|
1816
1842
|
}
|
|
1817
1843
|
|
|
1844
|
+
/** Higher-order component that injects the current theme as a prop. Prefer `useTheme` in function components. */
|
|
1818
1845
|
function withTheme(Component) {
|
|
1819
1846
|
const WithTheme = React.forwardRef((props, ref) => {
|
|
1820
1847
|
const theme = React.useContext(ThemeContext) ;
|
|
@@ -1828,6 +1855,16 @@
|
|
|
1828
1855
|
return hoistNonReactStatics(WithTheme, Component);
|
|
1829
1856
|
}
|
|
1830
1857
|
|
|
1858
|
+
/**
|
|
1859
|
+
* Collect styled-components CSS during server-side rendering.
|
|
1860
|
+
*
|
|
1861
|
+
* ```tsx
|
|
1862
|
+
* const sheet = new ServerStyleSheet();
|
|
1863
|
+
* const html = renderToString(sheet.collectStyles(<App />));
|
|
1864
|
+
* const styleTags = sheet.getStyleTags();
|
|
1865
|
+
* sheet.seal();
|
|
1866
|
+
* ```
|
|
1867
|
+
*/
|
|
1831
1868
|
class ServerStyleSheet {
|
|
1832
1869
|
constructor({ nonce } = {}) {
|
|
1833
1870
|
this._emitSheetCSS = () => {
|
|
@@ -1990,10 +2027,6 @@
|
|
|
1990
2027
|
// Control characters and non-letter first symbols are not supported
|
|
1991
2028
|
const escapeRegex = /[!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~-]+/g;
|
|
1992
2029
|
const dashesAtEnds = /(^-|-$)/g;
|
|
1993
|
-
/**
|
|
1994
|
-
* TODO: Explore using CSS.escape when it becomes more available
|
|
1995
|
-
* in evergreen browsers.
|
|
1996
|
-
*/
|
|
1997
2030
|
function escape(str) {
|
|
1998
2031
|
return str // Replace all possible CSS selectors
|
|
1999
2032
|
.replace(escapeRegex, '-') // Remove extraneous hyphens at the start and end
|
|
@@ -2047,9 +2080,6 @@
|
|
|
2047
2080
|
class ComponentStyle {
|
|
2048
2081
|
constructor(rules, componentId, baseStyle) {
|
|
2049
2082
|
this.rules = rules;
|
|
2050
|
-
this.staticRulesId = '';
|
|
2051
|
-
this.isStatic =
|
|
2052
|
-
"development" === 'production' ;
|
|
2053
2083
|
this.componentId = componentId;
|
|
2054
2084
|
this.baseHash = phash(SEED, componentId);
|
|
2055
2085
|
this.baseStyle = baseStyle;
|
|
@@ -2061,42 +2091,48 @@
|
|
|
2061
2091
|
let names = this.baseStyle
|
|
2062
2092
|
? this.baseStyle.generateAndInjectStyles(executionContext, styleSheet, stylis)
|
|
2063
2093
|
: '';
|
|
2064
|
-
|
|
2065
|
-
if (this.isStatic && !stylis.hash) {
|
|
2066
|
-
if (this.staticRulesId && styleSheet.hasNameForId(this.componentId, this.staticRulesId)) {
|
|
2067
|
-
names = joinStrings(names, this.staticRulesId);
|
|
2068
|
-
}
|
|
2069
|
-
else {
|
|
2070
|
-
const cssStatic = joinStringArray(flatten(this.rules, executionContext, styleSheet, stylis));
|
|
2071
|
-
const name = generateAlphabeticName(phash(this.baseHash, cssStatic) >>> 0);
|
|
2072
|
-
if (!styleSheet.hasNameForId(this.componentId, name)) {
|
|
2073
|
-
const cssStaticFormatted = stylis(cssStatic, '.' + name, undefined, this.componentId);
|
|
2074
|
-
styleSheet.insertRules(this.componentId, name, cssStaticFormatted);
|
|
2075
|
-
}
|
|
2076
|
-
names = joinStrings(names, name);
|
|
2077
|
-
this.staticRulesId = name;
|
|
2078
|
-
}
|
|
2079
|
-
}
|
|
2080
|
-
else {
|
|
2081
|
-
let dynamicHash = phash(this.baseHash, stylis.hash);
|
|
2094
|
+
{
|
|
2082
2095
|
let css = '';
|
|
2083
2096
|
for (let i = 0; i < this.rules.length; i++) {
|
|
2084
2097
|
const partRule = this.rules[i];
|
|
2085
2098
|
if (typeof partRule === 'string') {
|
|
2086
2099
|
css += partRule;
|
|
2087
|
-
dynamicHash = phash(dynamicHash, partRule);
|
|
2088
2100
|
}
|
|
2089
2101
|
else if (partRule) {
|
|
2090
|
-
|
|
2091
|
-
//
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2102
|
+
// Fast path: inline function call for the common case (interpolation
|
|
2103
|
+
// returning a string). Avoids flatten's type dispatch and array alloc.
|
|
2104
|
+
if (isStatelessFunction(partRule)) {
|
|
2105
|
+
const fnResult = partRule(executionContext);
|
|
2106
|
+
if (typeof fnResult === 'string') {
|
|
2107
|
+
css += fnResult;
|
|
2108
|
+
}
|
|
2109
|
+
else if (fnResult !== undefined && fnResult !== null && fnResult !== false) {
|
|
2110
|
+
if (typeof fnResult === 'object' &&
|
|
2111
|
+
!Array.isArray(fnResult) &&
|
|
2112
|
+
!isKeyframes(fnResult) &&
|
|
2113
|
+
!isPlainObject(fnResult)) {
|
|
2114
|
+
console.error(`${getComponentName(partRule)} is not a styled component and cannot be referred to via component selector. See https://www.styled-components.com/docs/advanced#referring-to-other-components for more details.`);
|
|
2115
|
+
}
|
|
2116
|
+
css += joinStringArray(flatten(fnResult, executionContext, styleSheet, stylis));
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
else {
|
|
2120
|
+
css += joinStringArray(flatten(partRule, executionContext, styleSheet, stylis));
|
|
2121
|
+
}
|
|
2096
2122
|
}
|
|
2097
2123
|
}
|
|
2098
2124
|
if (css) {
|
|
2099
|
-
|
|
2125
|
+
// Cache css->name to skip phash+generateName for repeat CSS strings.
|
|
2126
|
+
// The CSS string fully determines the class name for a given component,
|
|
2127
|
+
// so a Map lookup replaces O(cssLen) hashing on cache hit.
|
|
2128
|
+
if (!this.dynamicNameCache)
|
|
2129
|
+
this.dynamicNameCache = new Map();
|
|
2130
|
+
const cacheKey = stylis.hash ? stylis.hash + css : css;
|
|
2131
|
+
let name = this.dynamicNameCache.get(cacheKey);
|
|
2132
|
+
if (!name) {
|
|
2133
|
+
name = generateAlphabeticName(phash(phash(this.baseHash, stylis.hash), css) >>> 0);
|
|
2134
|
+
this.dynamicNameCache.set(cacheKey, name);
|
|
2135
|
+
}
|
|
2100
2136
|
if (!styleSheet.hasNameForId(this.componentId, name)) {
|
|
2101
2137
|
const cssFormatted = stylis(css, '.' + name, undefined, this.componentId);
|
|
2102
2138
|
styleSheet.insertRules(this.componentId, name, cssFormatted);
|
|
@@ -2108,17 +2144,37 @@
|
|
|
2108
2144
|
}
|
|
2109
2145
|
}
|
|
2110
2146
|
|
|
2147
|
+
const hasOwn = Object.prototype.hasOwnProperty;
|
|
2111
2148
|
const identifiers = {};
|
|
2112
2149
|
/* We depend on components having unique IDs */
|
|
2113
2150
|
function generateId(displayName, parentComponentId) {
|
|
2114
2151
|
const name = typeof displayName !== 'string' ? 'sc' : escape(displayName);
|
|
2115
2152
|
// Ensure that no displayName can lead to duplicate componentIds
|
|
2116
2153
|
identifiers[name] = (identifiers[name] || 0) + 1;
|
|
2117
|
-
const componentId =
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2154
|
+
const componentId = name +
|
|
2155
|
+
'-' +
|
|
2156
|
+
generateComponentId(
|
|
2157
|
+
// SC_VERSION gives us isolation between multiple runtimes on the page at once
|
|
2158
|
+
// this is improved further with use of the babel plugin "namespace" feature
|
|
2159
|
+
SC_VERSION + name + identifiers[name]);
|
|
2160
|
+
return parentComponentId ? parentComponentId + '-' + componentId : componentId;
|
|
2161
|
+
}
|
|
2162
|
+
/**
|
|
2163
|
+
* Shallow-compare two context objects using a stored key count to avoid
|
|
2164
|
+
* a second iteration pass. Returns true if all own-property values match.
|
|
2165
|
+
*/
|
|
2166
|
+
function shallowEqualContext(prev, next, prevKeyCount) {
|
|
2167
|
+
const a = prev;
|
|
2168
|
+
const b = next;
|
|
2169
|
+
let nextKeyCount = 0;
|
|
2170
|
+
for (const key in b) {
|
|
2171
|
+
if (hasOwn.call(b, key)) {
|
|
2172
|
+
nextKeyCount++;
|
|
2173
|
+
if (a[key] !== b[key])
|
|
2174
|
+
return false;
|
|
2175
|
+
}
|
|
2176
|
+
}
|
|
2177
|
+
return nextKeyCount === prevKeyCount;
|
|
2122
2178
|
}
|
|
2123
2179
|
function useInjectedStyle(componentStyle, resolvedAttrs, styleSheet, stylis) {
|
|
2124
2180
|
const className = componentStyle.generateAndInjectStyles(resolvedAttrs, styleSheet, stylis);
|
|
@@ -2131,9 +2187,8 @@
|
|
|
2131
2187
|
const context = Object.assign(Object.assign({}, props), {
|
|
2132
2188
|
// unset, add `props.className` back at the end so props always "wins"
|
|
2133
2189
|
className: undefined, theme });
|
|
2134
|
-
let
|
|
2135
|
-
|
|
2136
|
-
attrDef = attrs[i];
|
|
2190
|
+
for (let i = 0; i < attrs.length; i++) {
|
|
2191
|
+
const attrDef = attrs[i];
|
|
2137
2192
|
// Pass a shallow copy to function attrs so the callback's captured
|
|
2138
2193
|
// reference isn't mutated by subsequent attrs processing (#3336).
|
|
2139
2194
|
const resolvedAttrDef = isFunction(attrDef) ? attrDef(Object.assign({}, context)) : attrDef;
|
|
@@ -2158,46 +2213,81 @@
|
|
|
2158
2213
|
return context;
|
|
2159
2214
|
}
|
|
2160
2215
|
let seenUnknownProps = new Set();
|
|
2161
|
-
function
|
|
2162
|
-
const { attrs: componentAttrs, componentStyle, defaultProps, foldedComponentIds, styledComponentId, target, } = forwardedComponent;
|
|
2163
|
-
const contextTheme = React.useContext(ThemeContext) ;
|
|
2164
|
-
const ssc = useStyleSheetContext();
|
|
2165
|
-
const shouldForwardProp = forwardedComponent.shouldForwardProp || ssc.shouldForwardProp;
|
|
2166
|
-
if (React.useDebugValue) {
|
|
2167
|
-
React.useDebugValue(styledComponentId);
|
|
2168
|
-
}
|
|
2169
|
-
// NOTE: the non-hooks version only subscribes to this when !componentStyle.isStatic,
|
|
2170
|
-
// but that'd be against the rules-of-hooks. We could be naughty and do it anyway as it
|
|
2171
|
-
// should be an immutable value, but behave for now.
|
|
2172
|
-
const theme = determineTheme(props, contextTheme, defaultProps) || (EMPTY_OBJECT);
|
|
2173
|
-
const context = resolveContext(componentAttrs, props, theme);
|
|
2174
|
-
const elementToBeCreated = context.as || target;
|
|
2216
|
+
function buildPropsForElement(context, elementToBeCreated, theme, shouldForwardProp) {
|
|
2175
2217
|
const propsForElement = {};
|
|
2176
2218
|
for (const key in context) {
|
|
2177
|
-
// @ts-expect-error context may have arbitrary properties from attrs
|
|
2178
2219
|
if (context[key] === undefined) ;
|
|
2179
2220
|
else if (key[0] === '$' || key === 'as' || (key === 'theme' && context.theme === theme)) ;
|
|
2180
2221
|
else if (key === 'forwardedAs') {
|
|
2181
2222
|
propsForElement.as = context.forwardedAs;
|
|
2182
2223
|
}
|
|
2183
2224
|
else if (!shouldForwardProp || shouldForwardProp(key, elementToBeCreated)) {
|
|
2184
|
-
// @ts-expect-error context may have arbitrary properties from attrs
|
|
2185
2225
|
propsForElement[key] = context[key];
|
|
2186
2226
|
if (!shouldForwardProp &&
|
|
2187
2227
|
"development" === 'development' &&
|
|
2188
2228
|
!isPropValid(key) &&
|
|
2189
2229
|
!seenUnknownProps.has(key) &&
|
|
2190
|
-
// Only warn on DOM Element.
|
|
2191
2230
|
domElements.has(elementToBeCreated)) {
|
|
2192
2231
|
seenUnknownProps.add(key);
|
|
2193
2232
|
console.warn(`styled-components: it looks like an unknown prop "${key}" is being sent through to the DOM, which will likely trigger a React console error. If you would like automatic filtering of unknown props, you can opt-into that behavior via \`<StyleSheetManager shouldForwardProp={...}>\` (connect an API like \`@emotion/is-prop-valid\`) or consider using transient props (\`$\` prefix for automatic filtering.)`);
|
|
2194
2233
|
}
|
|
2195
2234
|
}
|
|
2196
2235
|
}
|
|
2197
|
-
|
|
2236
|
+
return propsForElement;
|
|
2237
|
+
}
|
|
2238
|
+
function useStyledComponentImpl(forwardedComponent, props, forwardedRef) {
|
|
2239
|
+
const { attrs: componentAttrs, componentStyle, defaultProps, foldedComponentIds, styledComponentId, target, } = forwardedComponent;
|
|
2240
|
+
const contextTheme = React.useContext(ThemeContext) ;
|
|
2241
|
+
const ssc = useStyleSheetContext();
|
|
2242
|
+
const shouldForwardProp = forwardedComponent.shouldForwardProp || ssc.shouldForwardProp;
|
|
2243
|
+
if (React.useDebugValue) {
|
|
2244
|
+
React.useDebugValue(styledComponentId);
|
|
2245
|
+
}
|
|
2246
|
+
// NOTE: the non-hooks version only subscribes to this when !componentStyle.isStatic,
|
|
2247
|
+
// but that'd be against the rules-of-hooks. We could be naughty and do it anyway as it
|
|
2248
|
+
// should be an immutable value, but behave for now.
|
|
2249
|
+
const theme = determineTheme(props, contextTheme, defaultProps) || (EMPTY_OBJECT);
|
|
2250
|
+
let context;
|
|
2251
|
+
let generatedClassName;
|
|
2252
|
+
// Client-only render cache: skip resolveContext and generateAndInjectStyles
|
|
2253
|
+
// when props+theme haven't changed. propsForElement is always rebuilt since
|
|
2254
|
+
// it's mutated with className/ref after construction.
|
|
2255
|
+
// false and IS_RSC are build/module-level constants for dead-code elimination.
|
|
2256
|
+
{
|
|
2257
|
+
const renderCacheRef = React.useRef(null);
|
|
2258
|
+
const prev = renderCacheRef.current;
|
|
2259
|
+
if (prev !== null &&
|
|
2260
|
+
prev[1] === theme &&
|
|
2261
|
+
prev[2] === ssc.styleSheet &&
|
|
2262
|
+
prev[3] === ssc.stylis &&
|
|
2263
|
+
shallowEqualContext(prev[0], props, prev[4])) {
|
|
2264
|
+
context = prev[5];
|
|
2265
|
+
generatedClassName = prev[6];
|
|
2266
|
+
}
|
|
2267
|
+
else {
|
|
2268
|
+
context = resolveContext(componentAttrs, props, theme);
|
|
2269
|
+
generatedClassName = useInjectedStyle(componentStyle, context, ssc.styleSheet, ssc.stylis);
|
|
2270
|
+
let propsKeyCount = 0;
|
|
2271
|
+
for (const key in props) {
|
|
2272
|
+
if (hasOwn.call(props, key))
|
|
2273
|
+
propsKeyCount++;
|
|
2274
|
+
}
|
|
2275
|
+
renderCacheRef.current = [
|
|
2276
|
+
props,
|
|
2277
|
+
theme,
|
|
2278
|
+
ssc.styleSheet,
|
|
2279
|
+
ssc.stylis,
|
|
2280
|
+
propsKeyCount,
|
|
2281
|
+
context,
|
|
2282
|
+
generatedClassName,
|
|
2283
|
+
];
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2198
2286
|
if (forwardedComponent.warnTooManyClasses) {
|
|
2199
2287
|
forwardedComponent.warnTooManyClasses(generatedClassName);
|
|
2200
2288
|
}
|
|
2289
|
+
const elementToBeCreated = context.as || target;
|
|
2290
|
+
const propsForElement = buildPropsForElement(context, elementToBeCreated, theme, shouldForwardProp);
|
|
2201
2291
|
let classString = joinStrings(foldedComponentIds, styledComponentId);
|
|
2202
2292
|
if (generatedClassName) {
|
|
2203
2293
|
classString += ' ' + generatedClassName;
|
|
@@ -2205,15 +2295,10 @@
|
|
|
2205
2295
|
if (context.className) {
|
|
2206
2296
|
classString += ' ' + context.className;
|
|
2207
2297
|
}
|
|
2208
|
-
propsForElement[
|
|
2209
|
-
// handle custom elements which React doesn't properly alias
|
|
2210
|
-
isTag(elementToBeCreated) &&
|
|
2298
|
+
propsForElement[isTag(elementToBeCreated) &&
|
|
2211
2299
|
!domElements.has(elementToBeCreated)
|
|
2212
2300
|
? 'class'
|
|
2213
2301
|
: 'className'] = classString;
|
|
2214
|
-
// forwardedRef is coming from React.forwardRef.
|
|
2215
|
-
// But it might not exist. Since React 19 handles `ref` like a prop, it only define it if there is a value.
|
|
2216
|
-
// We don't want to inject an empty ref.
|
|
2217
2302
|
if (forwardedRef) {
|
|
2218
2303
|
propsForElement.ref = forwardedRef;
|
|
2219
2304
|
}
|
|
@@ -2226,7 +2311,7 @@
|
|
|
2226
2311
|
const isCompositeComponent = !isTag(target);
|
|
2227
2312
|
const { attrs = EMPTY_ARRAY, componentId = generateId(options.displayName, options.parentComponentId), displayName = generateDisplayName(target), } = options;
|
|
2228
2313
|
const styledComponentId = options.displayName && options.componentId
|
|
2229
|
-
?
|
|
2314
|
+
? escape(options.displayName) + '-' + options.componentId
|
|
2230
2315
|
: options.componentId || componentId;
|
|
2231
2316
|
// fold the underlying StyledComponent attrs up (implicit extend)
|
|
2232
2317
|
const finalAttrs = isTargetStyledComp && styledComponentTarget.attrs
|
|
@@ -2326,6 +2411,14 @@
|
|
|
2326
2411
|
return templateFunction;
|
|
2327
2412
|
}
|
|
2328
2413
|
|
|
2414
|
+
/**
|
|
2415
|
+
* Create a styled component from an HTML element or React component.
|
|
2416
|
+
*
|
|
2417
|
+
* ```tsx
|
|
2418
|
+
* const Button = styled.button`color: red;`;
|
|
2419
|
+
* const Link = styled(RouterLink)`text-decoration: none;`;
|
|
2420
|
+
* ```
|
|
2421
|
+
*/
|
|
2329
2422
|
const baseStyled = (tag) => constructWithOptions(createStyledComponent, tag);
|
|
2330
2423
|
const styled = baseStyled;
|
|
2331
2424
|
// Shorthands for all valid HTML Elements
|