styled-components 6.4.0-prerelease.1 → 6.4.0-prerelease.3

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.
Files changed (34) hide show
  1. package/dist/base.d.ts +2 -1
  2. package/dist/constants.d.ts +1 -0
  3. package/dist/constructors/createTheme.d.ts +89 -0
  4. package/dist/models/ComponentStyle.d.ts +1 -4
  5. package/dist/models/GlobalStyle.d.ts +13 -1
  6. package/dist/sheet/Sheet.d.ts +2 -0
  7. package/dist/styled-components.browser.cjs.js +1 -1
  8. package/dist/styled-components.browser.cjs.js.map +1 -1
  9. package/dist/styled-components.browser.esm.js +1 -1
  10. package/dist/styled-components.browser.esm.js.map +1 -1
  11. package/dist/styled-components.cjs.js +1 -1
  12. package/dist/styled-components.cjs.js.map +1 -1
  13. package/dist/styled-components.esm.js +1 -1
  14. package/dist/styled-components.esm.js.map +1 -1
  15. package/dist/styled-components.js +227 -46
  16. package/dist/styled-components.js.map +1 -1
  17. package/dist/styled-components.min.js +1 -1
  18. package/dist/styled-components.min.js.map +1 -1
  19. package/native/dist/base.d.ts +2 -1
  20. package/native/dist/constants.d.ts +1 -0
  21. package/native/dist/constructors/createTheme.d.ts +89 -0
  22. package/native/dist/dist/base.d.ts +2 -1
  23. package/native/dist/dist/constants.d.ts +1 -0
  24. package/native/dist/dist/constructors/createTheme.d.ts +89 -0
  25. package/native/dist/dist/models/ComponentStyle.d.ts +1 -4
  26. package/native/dist/dist/models/GlobalStyle.d.ts +13 -1
  27. package/native/dist/dist/sheet/Sheet.d.ts +2 -0
  28. package/native/dist/models/ComponentStyle.d.ts +1 -4
  29. package/native/dist/models/GlobalStyle.d.ts +13 -1
  30. package/native/dist/sheet/Sheet.d.ts +2 -0
  31. package/native/dist/sheet/Tag.d.ts +4 -4
  32. package/native/dist/styled-components.native.cjs.js.map +1 -1
  33. package/native/dist/styled-components.native.esm.js.map +1 -1
  34. package/package.json +4 -3
@@ -10,7 +10,7 @@
10
10
  'data-styled';
11
11
  var SC_ATTR_ACTIVE = 'active';
12
12
  var SC_ATTR_VERSION = 'data-styled-version';
13
- var SC_VERSION = "6.4.0-prerelease.1";
13
+ var SC_VERSION = "6.4.0-prerelease.3";
14
14
  var SPLITTER = '/*!sc*/\n';
15
15
  var IS_BROWSER = typeof window !== 'undefined' && typeof document !== 'undefined';
16
16
  var DISABLE_SPEEDY = Boolean(typeof SC_DISABLE_SPEEDY === 'boolean'
@@ -30,6 +30,7 @@
30
30
  ? false
31
31
  : process.env.SC_DISABLE_SPEEDY
32
32
  : "development" !== 'production');
33
+ var KEYFRAMES_ID_PREFIX = 'sc-keyframes-';
33
34
  // Shared empty execution context when generating static styles
34
35
  var STATIC_EXECUTION_CONTEXT = {};
35
36
 
@@ -71,6 +72,10 @@
71
72
  return to.concat(ar || Array.prototype.slice.call(from));
72
73
  }
73
74
 
75
+ function __makeTemplateObject(cooked, raw) {
76
+ if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
77
+ return cooked;
78
+ }
74
79
  typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
75
80
  var e = new Error(message);
76
81
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
@@ -585,6 +590,7 @@
585
590
  var _this = this;
586
591
  this.options = __assign(__assign({}, defaultOptions), options);
587
592
  this.gs = globalStyles;
593
+ this.keyframeIds = new Set();
588
594
  this.names = new Map(names);
589
595
  this.server = !!options.isServer;
590
596
  // We rehydrate only once and use the sheet that is created first
@@ -606,6 +612,7 @@
606
612
  StyleSheet.prototype.reconstructWithOptions = function (options, withNames) {
607
613
  if (withNames === void 0) { withNames = true; }
608
614
  var newSheet = new StyleSheet(__assign(__assign({}, this.options), options), this.gs, (withNames && this.names) || undefined);
615
+ newSheet.keyframeIds = new Set(this.keyframeIds);
609
616
  // If we're reconstructing with a new target on the client, check if the container changed
610
617
  // This handles the case where StyleSheetManager's target prop changes (e.g., from undefined to shadowRoot)
611
618
  // We only rehydrate if the container (Document or ShadowRoot) actually changes
@@ -633,6 +640,9 @@
633
640
  /** Mark a group's name as known for caching */
634
641
  StyleSheet.prototype.registerName = function (id, name) {
635
642
  getGroupForId(id);
643
+ if (id.startsWith(KEYFRAMES_ID_PREFIX)) {
644
+ this.keyframeIds.add(id);
645
+ }
636
646
  var existing = this.names.get(id);
637
647
  if (existing) {
638
648
  existing.add(name);
@@ -902,40 +912,74 @@
902
912
 
903
913
  var GlobalStyle = /** @class */ (function () {
904
914
  function GlobalStyle(rules, componentId) {
915
+ /** @internal Per-instance rule cache for shared-group rebuild. */
916
+ this.instanceRules = new Map();
905
917
  this.rules = rules;
906
918
  this.componentId = componentId;
907
919
  this.isStatic = isStaticRules(rules);
908
- // pre-register the first instance to ensure global styles
909
- // load before component ones
910
- StyleSheet.registerId(this.componentId + 1);
920
+ // Pre-register the shared group so global styles defined before
921
+ // components always appear before them in the stylesheet.
922
+ StyleSheet.registerId(this.componentId);
911
923
  }
912
- GlobalStyle.prototype.createStyles = function (instance, executionContext, styleSheet, stylis) {
913
- var flatCSS = joinStringArray(flatten(this.rules, executionContext, styleSheet, stylis));
914
- var css = stylis(flatCSS, '');
915
- var id = this.componentId + instance;
916
- // NOTE: We use the id as a name as well, since these rules never change
917
- styleSheet.insertRules(id, id, css);
918
- };
919
924
  GlobalStyle.prototype.removeStyles = function (instance, styleSheet) {
920
- styleSheet.clearRules(this.componentId + instance);
925
+ this.instanceRules.delete(instance);
926
+ this.rebuildGroup(styleSheet);
921
927
  };
922
928
  GlobalStyle.prototype.renderStyles = function (instance, executionContext, styleSheet, stylis) {
923
- if (instance > 2)
924
- StyleSheet.registerId(this.componentId + instance);
925
- var id = this.componentId + instance;
926
- // For static styles that don't change based on props,
927
- // only inject once and don't remove/re-add on every render.
928
- // This prevents issues with React StrictMode where the effect cleanup
929
- // from the simulated unmount runs after the re-render.
929
+ var id = this.componentId;
930
930
  if (this.isStatic) {
931
- if (!styleSheet.hasNameForId(id, id)) {
932
- this.createStyles(instance, executionContext, styleSheet, stylis);
931
+ if (!styleSheet.hasNameForId(id, id + instance)) {
932
+ var entry = this.computeRules(instance, executionContext, styleSheet, stylis);
933
+ styleSheet.insertRules(id, entry.name, entry.rules);
934
+ }
935
+ else if (!this.instanceRules.has(instance)) {
936
+ // Rehydrated style: populate cache so rebuildGroup can restore
937
+ // survivors if another instance unmounts.
938
+ this.computeRules(instance, executionContext, styleSheet, stylis);
933
939
  }
934
940
  return;
935
941
  }
936
- // NOTE: Remove old styles, then inject the new ones
937
- this.removeStyles(instance, styleSheet);
938
- this.createStyles(instance, executionContext, styleSheet, stylis);
942
+ // Compute new rules; skip CSSOM rebuild if CSS is unchanged.
943
+ // The fast-path is only safe on the client where the tag persists between renders.
944
+ // During SSR, clearTag() destroys the tag between requests, so we must always rebuild.
945
+ var prev = this.instanceRules.get(instance);
946
+ this.computeRules(instance, executionContext, styleSheet, stylis);
947
+ if (!styleSheet.server && prev) {
948
+ var a = prev.rules;
949
+ var b = this.instanceRules.get(instance).rules;
950
+ if (a.length === b.length) {
951
+ var same = true;
952
+ for (var i = 0; i < a.length; i++) {
953
+ if (a[i] !== b[i]) {
954
+ same = false;
955
+ break;
956
+ }
957
+ }
958
+ if (same)
959
+ return;
960
+ }
961
+ }
962
+ this.rebuildGroup(styleSheet);
963
+ };
964
+ GlobalStyle.prototype.computeRules = function (instance, executionContext, styleSheet, stylis) {
965
+ var flatCSS = joinStringArray(flatten(this.rules, executionContext, styleSheet, stylis));
966
+ var entry = {
967
+ name: this.componentId + instance,
968
+ rules: stylis(flatCSS, ''),
969
+ };
970
+ this.instanceRules.set(instance, entry);
971
+ return entry;
972
+ };
973
+ /**
974
+ * Clear all CSS rules in the shared group and re-insert from surviving instances.
975
+ * Must run synchronously — no yielding between clear and re-insert.
976
+ */
977
+ GlobalStyle.prototype.rebuildGroup = function (styleSheet) {
978
+ var id = this.componentId;
979
+ styleSheet.clearRules(id);
980
+ this.instanceRules.forEach(function (entry) {
981
+ styleSheet.insertRules(id, entry.name, entry.rules);
982
+ });
939
983
  };
940
984
  return GlobalStyle;
941
985
  }());
@@ -1542,16 +1586,21 @@
1542
1586
  {
1543
1587
  checkDynamicCreation(styledComponentId);
1544
1588
  }
1545
- // Use a WeakMap to maintain stable instances per stylesheet
1546
- var instanceMap = new WeakMap();
1547
1589
  var GlobalStyleComponent = function (props) {
1548
1590
  var ssc = useStyleSheetContext();
1549
1591
  var theme = React.useContext(ThemeContext) ;
1550
- // Get or create instance ID for this stylesheet
1551
- var instance = instanceMap.get(ssc.styleSheet);
1552
- if (instance === undefined) {
1553
- instance = ssc.styleSheet.allocateGSInstance(styledComponentId);
1554
- instanceMap.set(ssc.styleSheet, instance);
1592
+ // Each mount needs a unique instance ID for the shared-group instanceRules cache.
1593
+ // false is a build-time constant: the dead branch is entirely eliminated,
1594
+ // so React never sees a conditional hook call.
1595
+ // Server bundle: direct allocation (one-shot renders, no stability needed).
1596
+ // Browser bundle: useRef for stable ID across re-renders + useLayoutEffect cleanup.
1597
+ var instance;
1598
+ {
1599
+ var instanceRef = React.useRef(null);
1600
+ if (instanceRef.current === null) {
1601
+ instanceRef.current = ssc.styleSheet.allocateGSInstance(styledComponentId);
1602
+ }
1603
+ instance = instanceRef.current;
1555
1604
  }
1556
1605
  if (// @ts-expect-error invariant check
1557
1606
  React.Children.count(props.children)) {
@@ -1560,6 +1609,13 @@
1560
1609
  if (rules.some(function (rule) { return typeof rule === 'string' && rule.indexOf('@import') !== -1; })) {
1561
1610
  console.warn("Please do not use @import CSS syntax in createGlobalStyle at this time, as the CSSOM APIs we use in production do not handle it well. Instead, we recommend using a library such as react-helmet to inject a typical <link> meta tag to the stylesheet, or simply embedding it manually in your index.html <head> section for a simpler app.");
1562
1611
  }
1612
+ // Render styles during component execution for server environments.
1613
+ // Uses false (build-time constant) OR styleSheet.server (runtime flag set by
1614
+ // ServerStyleSheet) because some bundlers (Turbopack) resolve the browser entry
1615
+ // for SSR of client components, making false false on the server.
1616
+ if (ssc.styleSheet.server) {
1617
+ renderStyles(instance, props, ssc.styleSheet, theme, ssc.stylis);
1618
+ }
1563
1619
  // Client-side lifecycle: render styles in effect and clean up on unmount.
1564
1620
  // false and IS_RSC are build/module-level constants, so this doesn't violate rules of hooks.
1565
1621
  {
@@ -1580,6 +1636,11 @@
1580
1636
  };
1581
1637
  }, effectDeps);
1582
1638
  }
1639
+ // Clean up server instance cache — no useLayoutEffect cleanup runs on the
1640
+ // server, so instanceRules would grow unboundedly across SSR requests.
1641
+ if (ssc.styleSheet.server) {
1642
+ globalStyle.instanceRules.delete(instance);
1643
+ }
1583
1644
  return null;
1584
1645
  };
1585
1646
  function renderStyles(instance, props, styleSheet, theme, stylis) {
@@ -1594,6 +1655,125 @@
1594
1655
  return React.memo(GlobalStyleComponent);
1595
1656
  }
1596
1657
 
1658
+ /** Shared recursive traversal — calls `leafFn` for each leaf, recurses for objects. */
1659
+ function walkTheme(obj, varPrefix, result, leafFn, path) {
1660
+ for (var key in obj) {
1661
+ var val = obj[key];
1662
+ var fullPath = path ? path + '-' + key : key;
1663
+ if (typeof val === 'object' && val !== null) {
1664
+ var nested = {};
1665
+ walkTheme(val, varPrefix, nested, leafFn, fullPath);
1666
+ result[key] = nested;
1667
+ }
1668
+ else {
1669
+ result[key] = leafFn(fullPath, val, key);
1670
+ }
1671
+ }
1672
+ }
1673
+ /** Build `var(--prefix-a-b, fallback)` accessor object */
1674
+ function buildVars(obj, varPrefix) {
1675
+ var result = {};
1676
+ walkTheme(obj, varPrefix, result, function (fullPath, val) {
1677
+ {
1678
+ var str = String(val);
1679
+ var depth = 0;
1680
+ for (var i = 0; i < str.length; i++) {
1681
+ if (str.charCodeAt(i) === 40)
1682
+ depth++;
1683
+ else if (str.charCodeAt(i) === 41)
1684
+ depth--;
1685
+ if (depth < 0)
1686
+ break;
1687
+ }
1688
+ if (depth !== 0) {
1689
+ console.warn("createTheme: value \"".concat(str, "\" at \"").concat(fullPath, "\" contains unbalanced parentheses and may break the var() fallback"));
1690
+ }
1691
+ }
1692
+ return 'var(--' + varPrefix + fullPath + ', ' + val + ')';
1693
+ });
1694
+ return result;
1695
+ }
1696
+ /** Read computed CSS variable values from the DOM */
1697
+ function resolveVars(obj, varPrefix, styles) {
1698
+ var result = {};
1699
+ walkTheme(obj, varPrefix, result, function (fullPath, val) {
1700
+ var resolved = styles.getPropertyValue('--' + varPrefix + fullPath).trim();
1701
+ return resolved || val;
1702
+ });
1703
+ return result;
1704
+ }
1705
+ /**
1706
+ * Emit CSS var declarations by walking `shape` for structure and reading
1707
+ * values from `theme`. This avoids hardcoded skip lists — only keys
1708
+ * present in the original theme shape are traversed.
1709
+ */
1710
+ function emitVarDeclarations(shape, theme, varPrefix, path) {
1711
+ var css = '';
1712
+ for (var key in shape) {
1713
+ var shapeVal = shape[key];
1714
+ var themeVal = theme[key];
1715
+ var fullPath = path ? path + '-' + key : key;
1716
+ if (typeof shapeVal === 'object' && shapeVal !== null) {
1717
+ if (typeof themeVal === 'object' && themeVal !== null) {
1718
+ css += emitVarDeclarations(shapeVal, themeVal, varPrefix, fullPath);
1719
+ }
1720
+ }
1721
+ else if (themeVal !== undefined && typeof themeVal !== 'function') {
1722
+ css += '--' + varPrefix + fullPath + ':' + themeVal + ';';
1723
+ }
1724
+ }
1725
+ return css;
1726
+ }
1727
+ /**
1728
+ * Create a theme contract that bridges `ThemeProvider` and CSS custom properties.
1729
+ *
1730
+ * Returns an object with the same shape as the input theme, but every leaf value
1731
+ * is a `var(--prefix-*, fallback)` CSS string. Use these in styled component
1732
+ * templates — they work in both client and RSC contexts.
1733
+ *
1734
+ * Mount the returned `GlobalStyle` component inside your `ThemeProvider` to emit
1735
+ * the CSS variables. When the theme changes (e.g. light → dark), the variables
1736
+ * update automatically.
1737
+ *
1738
+ * @example
1739
+ * ```tsx
1740
+ * const theme = createTheme({
1741
+ * colors: { primary: '#0070f3', text: '#111' },
1742
+ * });
1743
+ *
1744
+ * // Root layout (client):
1745
+ * <ThemeProvider theme={themes[preset]}>
1746
+ * <theme.GlobalStyle />
1747
+ * {children}
1748
+ * </ThemeProvider>
1749
+ *
1750
+ * // Any RSC file:
1751
+ * const Card = styled.div`
1752
+ * color: ${theme.colors.primary};
1753
+ * // → "var(--sc-colors-primary, #0070f3)"
1754
+ * `;
1755
+ * ```
1756
+ */
1757
+ function createTheme(defaultTheme, options) {
1758
+ var _a, _b;
1759
+ var pfx = ((_a = options === null || options === void 0 ? void 0 : options.prefix) !== null && _a !== void 0 ? _a : 'sc') + '-';
1760
+ var sel = (_b = options === null || options === void 0 ? void 0 : options.selector) !== null && _b !== void 0 ? _b : ':root';
1761
+ var vars = buildVars(defaultTheme, pfx);
1762
+ var GlobalStyle = createGlobalStyle(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n ", " {\n ", "\n }\n "], ["\n ", " {\n ", "\n }\n "])), sel, function (p) { return emitVarDeclarations(defaultTheme, p.theme, pfx); });
1763
+ return Object.assign(vars, {
1764
+ GlobalStyle: GlobalStyle,
1765
+ raw: defaultTheme,
1766
+ resolve: function (el) {
1767
+ if (!IS_BROWSER) {
1768
+ throw new Error('createTheme.resolve() is client-only');
1769
+ }
1770
+ var target = el !== null && el !== void 0 ? el : document.documentElement;
1771
+ return resolveVars(defaultTheme, pfx, getComputedStyle(target));
1772
+ },
1773
+ });
1774
+ }
1775
+ var templateObject_1;
1776
+
1597
1777
  var _a$1;
1598
1778
  var Keyframes = /** @class */ (function () {
1599
1779
  function Keyframes(name, rules) {
@@ -1607,8 +1787,13 @@
1607
1787
  }
1608
1788
  };
1609
1789
  this.name = name;
1610
- this.id = "sc-keyframes-".concat(name);
1790
+ this.id = KEYFRAMES_ID_PREFIX + name;
1611
1791
  this.rules = rules;
1792
+ // Eagerly register the group so keyframes defined before components
1793
+ // get a lower group ID and appear before them in the stylesheet.
1794
+ // Uses getGroupForId directly (not StyleSheet.registerId) because
1795
+ // GroupIDAllocator is pure JS — safe for native builds.
1796
+ getGroupForId(this.id);
1612
1797
  setToString(this, function () {
1613
1798
  throw throwStyledComponentsError(12, String(_this.name));
1614
1799
  });
@@ -1854,6 +2039,7 @@
1854
2039
  ThemeProvider: ThemeProvider,
1855
2040
  __PRIVATE__: __PRIVATE__,
1856
2041
  createGlobalStyle: createGlobalStyle,
2042
+ createTheme: createTheme,
1857
2043
  css: css,
1858
2044
  isStyledComponent: isStyledComponent,
1859
2045
  keyframes: keyframes,
@@ -2145,7 +2331,7 @@
2145
2331
  }
2146
2332
  ComponentStyle.prototype.generateAndInjectStyles = function (executionContext, styleSheet, stylis) {
2147
2333
  var names = this.baseStyle
2148
- ? this.baseStyle.generateAndInjectStyles(executionContext, styleSheet, stylis).className
2334
+ ? this.baseStyle.generateAndInjectStyles(executionContext, styleSheet, stylis)
2149
2335
  : '';
2150
2336
  // force dynamic classnames if user-supplied stylis plugins are in use
2151
2337
  if (this.isStatic && !stylis.hash) {
@@ -2156,7 +2342,7 @@
2156
2342
  var cssStatic = joinStringArray(flatten(this.rules, executionContext, styleSheet, stylis));
2157
2343
  var name_1 = generateAlphabeticName(phash(this.baseHash, cssStatic) >>> 0);
2158
2344
  if (!styleSheet.hasNameForId(this.componentId, name_1)) {
2159
- var cssStaticFormatted = stylis(cssStatic, ".".concat(name_1), undefined, this.componentId);
2345
+ var cssStaticFormatted = stylis(cssStatic, '.' + name_1, undefined, this.componentId);
2160
2346
  styleSheet.insertRules(this.componentId, name_1, cssStaticFormatted);
2161
2347
  }
2162
2348
  names = joinStrings(names, name_1);
@@ -2184,17 +2370,13 @@
2184
2370
  if (css) {
2185
2371
  var name_2 = generateAlphabeticName(dynamicHash >>> 0);
2186
2372
  if (!styleSheet.hasNameForId(this.componentId, name_2)) {
2187
- var cssFormatted = stylis(css, ".".concat(name_2), undefined, this.componentId);
2373
+ var cssFormatted = stylis(css, '.' + name_2, undefined, this.componentId);
2188
2374
  styleSheet.insertRules(this.componentId, name_2, cssFormatted);
2189
2375
  }
2190
2376
  names = joinStrings(names, name_2);
2191
2377
  }
2192
2378
  }
2193
- // Retrieve CSS from Tag for RSC rendering
2194
- var generatedCSS = typeof window === 'undefined'
2195
- ? styleSheet.getTag().getGroup(getGroupForId(this.componentId))
2196
- : '';
2197
- return { className: names, css: generatedCSS };
2379
+ return names;
2198
2380
  };
2199
2381
  return ComponentStyle;
2200
2382
  }());
@@ -2211,13 +2393,12 @@
2211
2393
  SC_VERSION + name + identifiers[name]));
2212
2394
  return parentComponentId ? "".concat(parentComponentId, "-").concat(componentId) : componentId;
2213
2395
  }
2214
- function useInjectedStyle(componentStyle, resolvedAttrs) {
2215
- var ssc = useStyleSheetContext();
2216
- var result = componentStyle.generateAndInjectStyles(resolvedAttrs, ssc.styleSheet, ssc.stylis);
2396
+ function useInjectedStyle(componentStyle, resolvedAttrs, styleSheet, stylis) {
2397
+ var className = componentStyle.generateAndInjectStyles(resolvedAttrs, styleSheet, stylis);
2217
2398
  if (React.useDebugValue) {
2218
- React.useDebugValue(result.className);
2399
+ React.useDebugValue(className);
2219
2400
  }
2220
- return result;
2401
+ return className;
2221
2402
  }
2222
2403
  function resolveContext(attrs, props, theme) {
2223
2404
  var context = __assign(__assign({}, props), {
@@ -2286,7 +2467,7 @@
2286
2467
  }
2287
2468
  }
2288
2469
  }
2289
- var _a = useInjectedStyle(componentStyle, context), generatedClassName = _a.className;
2470
+ var generatedClassName = useInjectedStyle(componentStyle, context, ssc.styleSheet, ssc.stylis);
2290
2471
  if (forwardedComponent.warnTooManyClasses) {
2291
2472
  forwardedComponent.warnTooManyClasses(generatedClassName);
2292
2473
  }