styled-components 6.4.0-prerelease.2 → 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.
@@ -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.2";
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);
@@ -1609,6 +1619,14 @@
1609
1619
  // Client-side lifecycle: render styles in effect and clean up on unmount.
1610
1620
  // false and IS_RSC are build/module-level constants, so this doesn't violate rules of hooks.
1611
1621
  {
1622
+ // For static global styles, renderStyles exits early after the first injection
1623
+ // (via hasNameForId check in GlobalStyle.renderStyles). We still need the effect
1624
+ // for initial injection and unmount cleanup, but we use a narrow deps array
1625
+ // to avoid unnecessary effect re-runs on every render.
1626
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1627
+ var effectDeps = globalStyle.isStatic
1628
+ ? [instance, ssc.styleSheet]
1629
+ : [instance, props, ssc.styleSheet, theme, ssc.stylis];
1612
1630
  React.useLayoutEffect(function () {
1613
1631
  if (!ssc.styleSheet.server) {
1614
1632
  renderStyles(instance, props, ssc.styleSheet, theme, ssc.stylis);
@@ -1616,7 +1634,7 @@
1616
1634
  return function () {
1617
1635
  globalStyle.removeStyles(instance, ssc.styleSheet);
1618
1636
  };
1619
- }, [instance, props, ssc.styleSheet, theme, ssc.stylis]);
1637
+ }, effectDeps);
1620
1638
  }
1621
1639
  // Clean up server instance cache — no useLayoutEffect cleanup runs on the
1622
1640
  // server, so instanceRules would grow unboundedly across SSR requests.
@@ -1637,6 +1655,125 @@
1637
1655
  return React.memo(GlobalStyleComponent);
1638
1656
  }
1639
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
+
1640
1777
  var _a$1;
1641
1778
  var Keyframes = /** @class */ (function () {
1642
1779
  function Keyframes(name, rules) {
@@ -1650,7 +1787,7 @@
1650
1787
  }
1651
1788
  };
1652
1789
  this.name = name;
1653
- this.id = "sc-keyframes-".concat(name);
1790
+ this.id = KEYFRAMES_ID_PREFIX + name;
1654
1791
  this.rules = rules;
1655
1792
  // Eagerly register the group so keyframes defined before components
1656
1793
  // get a lower group ID and appear before them in the stylesheet.
@@ -1902,6 +2039,7 @@
1902
2039
  ThemeProvider: ThemeProvider,
1903
2040
  __PRIVATE__: __PRIVATE__,
1904
2041
  createGlobalStyle: createGlobalStyle,
2042
+ createTheme: createTheme,
1905
2043
  css: css,
1906
2044
  isStyledComponent: isStyledComponent,
1907
2045
  keyframes: keyframes,
@@ -2193,7 +2331,7 @@
2193
2331
  }
2194
2332
  ComponentStyle.prototype.generateAndInjectStyles = function (executionContext, styleSheet, stylis) {
2195
2333
  var names = this.baseStyle
2196
- ? this.baseStyle.generateAndInjectStyles(executionContext, styleSheet, stylis).className
2334
+ ? this.baseStyle.generateAndInjectStyles(executionContext, styleSheet, stylis)
2197
2335
  : '';
2198
2336
  // force dynamic classnames if user-supplied stylis plugins are in use
2199
2337
  if (this.isStatic && !stylis.hash) {
@@ -2204,7 +2342,7 @@
2204
2342
  var cssStatic = joinStringArray(flatten(this.rules, executionContext, styleSheet, stylis));
2205
2343
  var name_1 = generateAlphabeticName(phash(this.baseHash, cssStatic) >>> 0);
2206
2344
  if (!styleSheet.hasNameForId(this.componentId, name_1)) {
2207
- var cssStaticFormatted = stylis(cssStatic, ".".concat(name_1), undefined, this.componentId);
2345
+ var cssStaticFormatted = stylis(cssStatic, '.' + name_1, undefined, this.componentId);
2208
2346
  styleSheet.insertRules(this.componentId, name_1, cssStaticFormatted);
2209
2347
  }
2210
2348
  names = joinStrings(names, name_1);
@@ -2232,17 +2370,13 @@
2232
2370
  if (css) {
2233
2371
  var name_2 = generateAlphabeticName(dynamicHash >>> 0);
2234
2372
  if (!styleSheet.hasNameForId(this.componentId, name_2)) {
2235
- var cssFormatted = stylis(css, ".".concat(name_2), undefined, this.componentId);
2373
+ var cssFormatted = stylis(css, '.' + name_2, undefined, this.componentId);
2236
2374
  styleSheet.insertRules(this.componentId, name_2, cssFormatted);
2237
2375
  }
2238
2376
  names = joinStrings(names, name_2);
2239
2377
  }
2240
2378
  }
2241
- // Retrieve CSS from Tag for RSC rendering
2242
- var generatedCSS = typeof window === 'undefined'
2243
- ? styleSheet.getTag().getGroup(getGroupForId(this.componentId))
2244
- : '';
2245
- return { className: names, css: generatedCSS };
2379
+ return names;
2246
2380
  };
2247
2381
  return ComponentStyle;
2248
2382
  }());
@@ -2259,13 +2393,12 @@
2259
2393
  SC_VERSION + name + identifiers[name]));
2260
2394
  return parentComponentId ? "".concat(parentComponentId, "-").concat(componentId) : componentId;
2261
2395
  }
2262
- function useInjectedStyle(componentStyle, resolvedAttrs) {
2263
- var ssc = useStyleSheetContext();
2264
- var result = componentStyle.generateAndInjectStyles(resolvedAttrs, ssc.styleSheet, ssc.stylis);
2396
+ function useInjectedStyle(componentStyle, resolvedAttrs, styleSheet, stylis) {
2397
+ var className = componentStyle.generateAndInjectStyles(resolvedAttrs, styleSheet, stylis);
2265
2398
  if (React.useDebugValue) {
2266
- React.useDebugValue(result.className);
2399
+ React.useDebugValue(className);
2267
2400
  }
2268
- return result;
2401
+ return className;
2269
2402
  }
2270
2403
  function resolveContext(attrs, props, theme) {
2271
2404
  var context = __assign(__assign({}, props), {
@@ -2334,7 +2467,7 @@
2334
2467
  }
2335
2468
  }
2336
2469
  }
2337
- var _a = useInjectedStyle(componentStyle, context), generatedClassName = _a.className;
2470
+ var generatedClassName = useInjectedStyle(componentStyle, context, ssc.styleSheet, ssc.stylis);
2338
2471
  if (forwardedComponent.warnTooManyClasses) {
2339
2472
  forwardedComponent.warnTooManyClasses(generatedClassName);
2340
2473
  }