stoop 0.3.0 → 0.4.1

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 (65) hide show
  1. package/README.md +125 -0
  2. package/dist/api/core-api.d.ts +34 -0
  3. package/dist/api/styled.d.ts +0 -1
  4. package/dist/api/theme-provider.d.ts +41 -0
  5. package/dist/constants.d.ts +11 -1
  6. package/dist/core/compiler.d.ts +11 -0
  7. package/dist/core/theme-manager.d.ts +34 -3
  8. package/dist/create-stoop-internal.d.ts +30 -0
  9. package/dist/create-stoop-ssr.d.ts +10 -0
  10. package/dist/create-stoop-ssr.js +16 -0
  11. package/dist/create-stoop.d.ts +32 -1
  12. package/dist/create-stoop.js +16 -147
  13. package/dist/inject.d.ts +113 -0
  14. package/dist/types/index.d.ts +147 -12
  15. package/dist/types/react-polymorphic-types.d.ts +13 -2
  16. package/dist/utils/auto-preload.d.ts +45 -0
  17. package/dist/utils/helpers.d.ts +64 -0
  18. package/dist/utils/storage.d.ts +148 -0
  19. package/dist/utils/{string.d.ts → theme-utils.d.ts} +20 -3
  20. package/dist/utils/theme.d.ts +14 -2
  21. package/package.json +44 -17
  22. package/dist/api/create-theme.d.ts +0 -13
  23. package/dist/api/create-theme.js +0 -43
  24. package/dist/api/css.d.ts +0 -16
  25. package/dist/api/css.js +0 -20
  26. package/dist/api/global-css.js +0 -89
  27. package/dist/api/keyframes.d.ts +0 -16
  28. package/dist/api/keyframes.js +0 -95
  29. package/dist/api/provider.d.ts +0 -19
  30. package/dist/api/provider.js +0 -109
  31. package/dist/api/styled.js +0 -170
  32. package/dist/api/use-theme.d.ts +0 -13
  33. package/dist/api/use-theme.js +0 -21
  34. package/dist/constants.js +0 -144
  35. package/dist/core/cache.js +0 -68
  36. package/dist/core/compiler.js +0 -198
  37. package/dist/core/theme-manager.js +0 -97
  38. package/dist/core/variants.js +0 -32
  39. package/dist/create-stoop-server.d.ts +0 -33
  40. package/dist/create-stoop-server.js +0 -130
  41. package/dist/index.d.ts +0 -6
  42. package/dist/index.js +0 -5
  43. package/dist/inject/browser.d.ts +0 -58
  44. package/dist/inject/browser.js +0 -149
  45. package/dist/inject/dedup.d.ts +0 -29
  46. package/dist/inject/dedup.js +0 -38
  47. package/dist/inject/index.d.ts +0 -40
  48. package/dist/inject/index.js +0 -75
  49. package/dist/inject/ssr.d.ts +0 -27
  50. package/dist/inject/ssr.js +0 -46
  51. package/dist/ssr.d.ts +0 -21
  52. package/dist/ssr.js +0 -19
  53. package/dist/types/index.js +0 -5
  54. package/dist/utils/environment.d.ts +0 -6
  55. package/dist/utils/environment.js +0 -12
  56. package/dist/utils/string.js +0 -253
  57. package/dist/utils/theme-map.d.ts +0 -22
  58. package/dist/utils/theme-map.js +0 -97
  59. package/dist/utils/theme-validation.d.ts +0 -13
  60. package/dist/utils/theme-validation.js +0 -36
  61. package/dist/utils/theme.js +0 -279
  62. package/dist/utils/type-guards.d.ts +0 -26
  63. package/dist/utils/type-guards.js +0 -38
  64. package/dist/utils/utilities.d.ts +0 -14
  65. package/dist/utils/utilities.js +0 -43
@@ -1,147 +1,16 @@
1
- "use client";
2
- import { createTheme as createThemeFactory } from "./api/create-theme";
3
- import { createCSSFunction } from "./api/css";
4
- import { createGlobalCSSFunction } from "./api/global-css";
5
- import { createKeyframesFunction } from "./api/keyframes";
6
- import { createProvider } from "./api/provider";
7
- import { createStyledFunction } from "./api/styled";
8
- import { createUseThemeHook } from "./api/use-theme";
9
- import { DEFAULT_THEME_MAP } from "./constants";
10
- import { compileCSS } from "./core/compiler";
11
- import { registerDefaultTheme, updateThemeVariables } from "./core/theme-manager";
12
- import { getCssText as getCssTextBase, registerTheme } from "./inject";
13
- import { getRootRegex, sanitizePrefix } from "./utils/string";
14
- import { generateCSSVariables } from "./utils/theme";
15
- import { validateTheme } from "./utils/theme-validation";
16
- /**
17
- * Creates a Stoop instance with the provided configuration.
18
- * Includes all APIs: styled, Provider, useTheme, etc.
19
- *
20
- * @param config - Configuration object containing theme, media queries, utilities, and optional prefix/themeMap
21
- * @returns StoopInstance with all API functions
22
- */
23
- export function createStoop(config) {
24
- const { media: configMedia, prefix = "stoop", theme, themeMap: userThemeMap, utils } = config;
25
- const sanitizedPrefix = sanitizePrefix(prefix);
26
- const validatedTheme = validateTheme(theme);
27
- const media = validatedTheme.media || configMedia;
28
- const mergedThemeMap = {
29
- ...DEFAULT_THEME_MAP,
30
- ...userThemeMap,
31
- };
32
- registerDefaultTheme(validatedTheme, sanitizedPrefix);
33
- registerTheme(validatedTheme, sanitizedPrefix);
34
- const css = createCSSFunction(validatedTheme, sanitizedPrefix, media, utils, mergedThemeMap);
35
- const createTheme = createThemeFactory(validatedTheme);
36
- const globalCss = createGlobalCSSFunction(validatedTheme, sanitizedPrefix, media, utils, mergedThemeMap);
37
- const keyframes = createKeyframesFunction(sanitizedPrefix, validatedTheme, mergedThemeMap);
38
- const themeObject = Object.freeze({ ...validatedTheme });
39
- /**
40
- * Pre-compiles CSS objects to warm the cache.
41
- * Useful for eliminating FOUC by pre-compiling common styles.
42
- *
43
- * @param styles - Array of CSS objects to pre-compile
44
- */
45
- function warmCache(styles) {
46
- for (const style of styles) {
47
- try {
48
- compileCSS(style, validatedTheme, sanitizedPrefix, media, utils, mergedThemeMap);
49
- }
50
- catch {
51
- // Skip invalid styles
52
- }
53
- }
54
- }
55
- /**
56
- * Preloads a theme by injecting its CSS variables before React renders.
57
- * Useful for preventing FOUC when loading a non-default theme from localStorage.
58
- *
59
- * @param theme - Theme to preload (can be theme name string or Theme object)
60
- */
61
- function preloadTheme(theme) {
62
- let themeToInject;
63
- if (typeof theme === "string") {
64
- if (config.themes && config.themes[theme]) {
65
- themeToInject = config.themes[theme];
66
- }
67
- else {
68
- if (typeof process !== "undefined" && process.env?.NODE_ENV !== "production") {
69
- // eslint-disable-next-line no-console
70
- console.warn(`[Stoop] Theme "${theme}" not found. Available themes: ${config.themes ? Object.keys(config.themes).join(", ") : "none"}`);
71
- }
72
- return;
73
- }
74
- }
75
- else {
76
- themeToInject = theme;
77
- }
78
- updateThemeVariables(themeToInject, sanitizedPrefix);
79
- }
80
- /**
81
- * Gets all injected CSS text for server-side rendering.
82
- * Always includes theme CSS variables.
83
- *
84
- * @param theme - Optional theme (name or object) to include vars for (defaults to default theme)
85
- * @returns CSS text string with theme variables and component styles
86
- */
87
- function getCssText(theme) {
88
- let themeToUse = validatedTheme;
89
- if (theme) {
90
- if (typeof theme === "string") {
91
- if (config.themes && config.themes[theme]) {
92
- themeToUse = config.themes[theme];
93
- }
94
- else if (typeof process !== "undefined" && process.env?.NODE_ENV !== "production") {
95
- // eslint-disable-next-line no-console
96
- console.warn(`[Stoop] Theme "${theme}" not found. Using default theme. Available: ${config.themes ? Object.keys(config.themes).join(", ") : "none"}`);
97
- }
98
- }
99
- else {
100
- themeToUse = theme;
101
- }
102
- }
103
- let result = "";
104
- const themeVars = generateCSSVariables(themeToUse, sanitizedPrefix);
105
- if (themeVars) {
106
- result += themeVars + "\n";
107
- }
108
- const baseCss = getCssTextBase();
109
- const rootRegex = getRootRegex(sanitizedPrefix);
110
- const cssWithoutThemeVars = baseCss.replace(rootRegex, "").trim();
111
- if (cssWithoutThemeVars) {
112
- result += (result ? "\n" : "") + cssWithoutThemeVars;
113
- }
114
- return result;
115
- }
116
- // Create Provider and useTheme if themes are configured
117
- let Provider;
118
- let useTheme;
119
- let themeContext;
120
- if (config.themes) {
121
- const mergedThemesForProvider = {};
122
- for (const [themeName, themeOverride] of Object.entries(config.themes)) {
123
- mergedThemesForProvider[themeName] = createTheme(themeOverride);
124
- }
125
- const { Provider: ProviderComponent, ThemeContext, ThemeManagementContext, } = createProvider(mergedThemesForProvider, validatedTheme, sanitizedPrefix);
126
- themeContext = ThemeContext;
127
- Provider = ProviderComponent;
128
- useTheme = createUseThemeHook(ThemeManagementContext);
129
- }
130
- // Create styled function
131
- const styled = createStyledFunction(validatedTheme, sanitizedPrefix, media, utils, mergedThemeMap, themeContext);
132
- // Return instance with all APIs
133
- return {
134
- config: { ...config, prefix: sanitizedPrefix },
135
- createTheme,
136
- css,
137
- getCssText,
138
- globalCss,
139
- keyframes,
140
- preloadTheme,
141
- Provider,
142
- styled,
143
- theme: themeObject,
144
- useTheme,
145
- warmCache,
146
- };
147
- }
1
+ var r=Object.freeze({}),s=1e4,T0=5000,C0=10,f0=500,c=1000,k0=31536000,S0="/",W0=["colors","opacities","space","radii","sizes","fonts","fontWeights","fontSizes","lineHeights","letterSpacings","shadows","zIndices","transitions"],n={accentColor:"colors",animation:"transitions",animationDelay:"transitions",animationDuration:"transitions",animationTimingFunction:"transitions",backdropFilter:"shadows",background:"colors",backgroundColor:"colors",blockSize:"sizes",border:"colors",borderBlockColor:"colors",borderBlockEndColor:"colors",borderBlockStartColor:"colors",borderBottomColor:"colors",borderBottomLeftRadius:"radii",borderBottomRightRadius:"radii",borderColor:"colors",borderEndEndRadius:"radii",borderEndStartRadius:"radii",borderInlineColor:"colors",borderInlineEndColor:"colors",borderInlineStartColor:"colors",borderLeftColor:"colors",borderRadius:"radii",borderRightColor:"colors",borderStartEndRadius:"radii",borderStartStartRadius:"radii",borderTopColor:"colors",borderTopLeftRadius:"radii",borderTopRightRadius:"radii",bottom:"space",boxShadow:"shadows",caretColor:"colors",color:"colors",columnGap:"space",columnRuleColor:"colors",fill:"colors",filter:"shadows",flexBasis:"sizes",floodColor:"colors",font:"fontSizes",fontFamily:"fonts",fontSize:"fontSizes",fontWeight:"fontWeights",gap:"space",gridColumnGap:"space",gridGap:"space",gridRowGap:"space",height:"sizes",inlineSize:"sizes",inset:"space",insetBlock:"space",insetBlockEnd:"space",insetBlockStart:"space",insetInline:"space",insetInlineEnd:"space",insetInlineStart:"space",left:"space",letterSpacing:"letterSpacings",lightingColor:"colors",lineHeight:"lineHeights",margin:"space",marginBlock:"space",marginBlockEnd:"space",marginBlockStart:"space",marginBottom:"space",marginInline:"space",marginInlineEnd:"space",marginInlineStart:"space",marginLeft:"space",marginRight:"space",marginTop:"space",maxBlockSize:"sizes",maxHeight:"sizes",maxInlineSize:"sizes",maxWidth:"sizes",minBlockSize:"sizes",minHeight:"sizes",minInlineSize:"sizes",minWidth:"sizes",opacity:"opacities",outline:"colors",outlineColor:"colors",padding:"space",paddingBlock:"space",paddingBlockEnd:"space",paddingBlockStart:"space",paddingBottom:"space",paddingInline:"space",paddingInlineEnd:"space",paddingInlineStart:"space",paddingLeft:"space",paddingRight:"space",paddingTop:"space",right:"space",rowGap:"space",size:"sizes",stopColor:"colors",stroke:"colors",textDecorationColor:"colors",textEmphasisColor:"colors",textShadow:"shadows",top:"space",transition:"transitions",transitionDelay:"transitions",transitionDuration:"transitions",transitionProperty:"transitions",transitionTimingFunction:"transitions",width:"sizes",zIndex:"zIndices"},a=Symbol.for("stoop.component");class E extends Map{maxSize;constructor($){super();this.maxSize=$}get($){let J=super.get($);if(J!==void 0)super.delete($),super.set($,J);return J}set($,J){if(super.has($))super.delete($);else if(this.size>=this.maxSize){let q=this.keys().next().value;if(q!==void 0)super.delete(q)}return super.set($,J),this}}var d0=new E(T0),D0=new E(s);function w(){return typeof window!=="undefined"&&typeof document!=="undefined"&&typeof window.document==="object"&&typeof document.createElement==="function"}function u(){return typeof process!=="undefined"&&process.env?.NODE_ENV==="production"}function t($){return typeof $==="object"&&$!==null}function m($){return typeof $==="object"&&$!==null&&"__isStoopStyled"in $&&"__stoopClassName"in $&&$.__isStoopStyled===!0}function U0($){return t($)&&!m($)}function H0($){return typeof $==="object"&&$!==null&&!Array.isArray($)}function e($){if(!$||typeof $!=="object"||Array.isArray($))throw new Error("[Stoop] Theme must be a non-null object");if(u())return $;let J=$,q=[];for(let X in J){if(X==="media")continue;if(!W0.includes(X))q.push(X)}if(q.length>0){let X=`[Stoop] Theme contains invalid scales: ${q.join(", ")}. Only these scales are allowed: ${W0.join(", ")}`;throw new Error(X)}return $}function i($,J){if(!J||!$||typeof $!=="object")return $;let q={},X=Object.keys(J);for(let Y in $){let Q=$[Y];if(X.includes(Y)&&J[Y])try{let G=J[Y](Q);if(G&&typeof G==="object")for(let Z in G)q[Z]=G[Z]}catch{q[Y]=Q}else if(t(Q))q[Y]=i(Q,J);else q[Y]=Q}return q}var F0=null,u0=new E(c),y0=new E(c),p0=new E(c),h0=new E(c);function y($){let X=2166136261;for(let Y=0;Y<$.length;Y++)X^=$.charCodeAt(Y),X=Math.imul(X,16777619);return X^=$.length,(X>>>0).toString(36)}function $0($){try{return y(JSON.stringify($))}catch{return y(String($))}}function O1($){return $.replace(/([A-Z])/g,"-$1").toLowerCase()}function c0($,J=!1){let X=String($).replace(/\\/g,"\\\\").replace(/"/g,"\\\"").replace(/'/g,"\\'").replace(/;/g,"\\;").replace(/\n/g,"\\A ").replace(/\r/g,"").replace(/\f/g,"\\C ");if(J)X=X.replace(/\{/g,"\\7B ").replace(/\}/g,"\\7D ");return X}function n0($){return c0($,!1)}function T($){let J=u0.get($);if(J!==void 0)return J;let q=$.replace(/[^a-zA-Z0-9\s\-_>+~:.#[\]&@()]/g,""),X=!q.trim()||/^[>+~:.#[\]&@()\s]+$/.test(q)?"":q;return u0.set($,X),X}function C($){let J=h0.get($);if(J!==void 0)return J;let Y=$.replace(/[^a-zA-Z0-9-_]/g,"-").replace(/^[\d-]+/,"").replace(/^-+/,"")||"invalid";return h0.set($,Y),Y}function m0($){return c0($,!0)}function R($){if(!$)return"stoop";return $.replace(/[^a-zA-Z0-9-_]/g,"").replace(/^[\d-]+/,"").replace(/^-+/,"")||"stoop"}function i0($){if(!$||typeof $!=="string")return"";let J=$.replace(/[^a-zA-Z0-9\s():,<>=\-@]/g,"");if(!J.trim()||!/[a-zA-Z]/.test(J))return"";return J}function o0($){if(!$||typeof $!=="string")return"";let J=p0.get($);if(J!==void 0)return J;let q=$.trim().split(/\s+/),X=[];for(let Q of q){if(!Q)continue;let Z=Q.replace(/[^a-zA-Z0-9-_]/g,"").replace(/^\d+/,"");if(Z&&/^[a-zA-Z-_]/.test(Z))X.push(Z)}let Y=X.join(" ");return p0.set($,Y),Y}function J0($){if(!$||typeof $!=="string")return"";let J=y0.get($);if(J!==void 0)return J;let Y=O1($).replace(/[^a-zA-Z0-9-]/g,"").replace(/^-+|-+$/g,"").replace(/^\d+/,"")||"";return y0.set($,Y),Y}function l0($){if(!$||typeof $!=="string")return!1;if($==="from"||$==="to")return!0;if(/^\d+(\.\d+)?%$/.test($)){let q=parseFloat($);return q>=0&&q<=100}return!1}function r0($=""){if(!F0){let q=":root".replace(/[.*+?^${}()|[\]\\]/g,"\\$&");F0=new RegExp(`${q}\\s*\\{[\\s\\S]*\\}`)}return F0}function M1($){if($.includes("Color")||$==="fill"||$==="stroke"||$==="accentColor"||$==="caretColor"||$==="border"||$==="outline"||$.includes("background")&&!$.includes("Size")&&!$.includes("Image"))return"colors";if(/^(margin|padding|gap|inset|top|right|bottom|left|rowGap|columnGap|gridGap|gridRowGap|gridColumnGap)/.test($)||$.includes("Block")||$.includes("Inline"))return"space";if(/(width|height|size|basis)$/i.test($)||$.includes("BlockSize")||$.includes("InlineSize"))return"sizes";if($==="fontSize"||$==="font"&&!$.includes("Family"))return"fontSizes";if($==="fontFamily"||$.includes("FontFamily"))return"fonts";if($==="fontWeight"||$.includes("FontWeight"))return"fontWeights";if($==="letterSpacing"||$.includes("LetterSpacing"))return"letterSpacings";if($.includes("Radius")||$.includes("radius"))return"radii";if($.includes("Shadow")||$.includes("shadow")||$==="filter"||$==="backdropFilter")return"shadows";if($==="zIndex"||$.includes("ZIndex")||$.includes("z-index"))return"zIndices";if($==="opacity"||$.includes("Opacity"))return"opacities";if($.startsWith("transition")||$.startsWith("animation")||$.includes("Transition")||$.includes("Animation"))return"transitions";return}function s0($,J){if(J&&$ in J)return J[$];if($ in n)return n[$];return M1($)}var w0=new Map;function Y0($){return w0.has($)}function X0($,J){w0.set($,J)}var L0=new E(s);function e0($){if(!L0.has($))L0.set($,!0)}function a0(){return Array.from(L0.keys()).join(`
2
+ `)}var q0=new Map;var t0=new Map;function $1($="stoop"){if(!w())throw new Error("Cannot access document in SSR context");let J=R($),q=q0.get(J);if(!q||!q.parentNode){let X=document.getElementById("stoop-ssr");if(X){let Y=X.getAttribute("data-stoop");if(!Y||Y===J)return q=X,q.setAttribute("data-stoop",J),q0.set(J,q),q}q=document.createElement("style"),q.setAttribute("data-stoop",J),q.setAttribute("id",`stoop-${J}`),document.head.appendChild(q),q0.set(J,q)}return q}function B0($){let J=$,q=r0("");J=J.replace(q,"").trim();let X=J.indexOf("[data-theme=");while(X!==-1){let Y=J.indexOf("{",X);if(Y===-1)break;let Q=1,G=Y+1;while(G<J.length&&Q>0){if(J[G]==="{")Q++;else if(J[G]==="}")Q--;G++}if(Q===0){let Z=J.substring(0,X).trim(),W=J.substring(G).trim();J=(Z+`
3
+ `+W).trim()}else break;X=J.indexOf("[data-theme=")}return J.trim()}function J1($,J="stoop"){if(!$)return;let q=R(J),X=`__all_theme_vars_${q}`;if((t0.get(X)??null)===$)return;if(t0.set(X,$),!w()){e0($);return}let Q=$1(q),G=Q.textContent||"",Z=G.includes(":root")||G.includes("[data-theme=");if(Y0(X)||Z){let W=B0(G);Q.textContent=$+(W?`
4
+
5
+ `+W:""),X0(X,$)}else Q.textContent=$+(G?`
6
+
7
+ `+G:""),X0(X,$)}function z1($,J,q="stoop"){if(!w())return;let X=R(q);if(Y0(J))return;let Y=$1(X),Q=Y.textContent||"";Y.textContent=Q+(Q?`
8
+ `:"")+$,X0(J,$)}function E1($,J,q="stoop"){if(Y0(J))return;let X=R(q);z1($,J,X)}function K1($="stoop"){let J=R($);return q0.get(J)||null}function j1(){return new Map(w0)}function f($,J="stoop",q){let X=q||$;if(!w()){if(!Y0(X))X0(X,$);e0($);return}E1($,X,J)}function q1($="stoop"){if(w()){let J=R($),q=K1(J);if(q&&q.parentNode){let X=q.textContent||"";if(!X&&j1().size>0)return a0();return X}}return a0()}var P1=/(-?\$[a-zA-Z][a-zA-Z0-9]*(?:\$[a-zA-Z][a-zA-Z0-9]*)?(?:\.[a-zA-Z][a-zA-Z0-9]*)?)/g;function _0($){let J=new Map;function q(X,Y=[]){let Q=Object.keys(X);for(let G of Q){let Z=X[G],W=[...Y,G];if(H0(Z))q(Z,W);else{let U=J.get(G);if(U)U.push(W);else J.set(G,[W])}}}q($);for(let[,X]of J.entries())if(X.length>1)X.sort((Y,Q)=>{let G=Y.length-Q.length;if(G!==0)return G;let Z=Y.join("."),W=Q.join(".");return Z.localeCompare(W)});return J}function V1($,J){let q=Object.keys($).filter((Y)=>Y!=="media"),X=Object.keys(J).filter((Y)=>Y!=="media");if(q.length!==X.length)return!1;for(let Y of q)if(!(Y in J))return!1;return!0}function Y1($,J){if($===J)return!0;if(!$||!J)return!1;if(!V1($,J))return!1;let q={...$},X={...J};return delete q.media,delete X.media,JSON.stringify(q)===JSON.stringify(X)}function A0($,J,q){if(q&&q in $){let Q=$[q];if(Q&&typeof Q==="object"&&!Array.isArray(Q)&&J in Q)return[q,J]}let Y=_0($).get(J);if(!Y||Y.length===0)return null;return Y[0]}function X1($,J,q,X){if(!$.startsWith("$"))return $;let Y=$.slice(1);if(Y.includes("$")||Y.includes("."))return`var(${`--${(Y.includes("$")?Y.split("$"):Y.split(".")).map((D)=>C(D)).join("-")}`})`;if(J&&q){let Z=s0(q,X);if(Z){let H=A0(J,Y,Z);if(H)return`var(${`--${H.map((O)=>C(O)).join("-")}`})`}let U=_0(J).get(Y);if(U&&U.length>1){if(!u()){let H=Z?`Property "${q}" maps to "${Z}" scale, but token not found there. `:`No scale mapping found for property "${q}". `;console.warn(`[Stoop] Ambiguous token "$${Y}" found in multiple categories: ${U.map((F)=>F.join(".")).join(", ")}. ${H}Using "${U[0].join(".")}" (deterministic: shorter paths first, then alphabetical). Use full path "$${U[0].join(".")}" to be explicit.`)}}let D=A0(J,Y);if(D)return`var(${`--${D.map((L)=>C(L)).join("-")}`})`}else if(J){let W=_0(J).get(Y);if(W&&W.length>1){if(!u())console.warn(`[Stoop] Ambiguous token "$${Y}" found in multiple categories: ${W.map((D)=>D.join(".")).join(", ")}. Using "${W[0].join(".")}" (deterministic: shorter paths first, then alphabetical). Use full path "$${W[0].join(".")}" to be explicit, or use with a CSS property for automatic resolution.`)}let U=A0(J,Y);if(U)return`var(${`--${U.map((F)=>C(F)).join("-")}`})`}return`var(${`--${C(Y)}`})`}function I0($,J="stoop",q){let X=q||":root",Y=[];function Q(G,Z=[]){let W=Object.keys(G).sort();for(let U of W){if(U==="media")continue;let D=G[U],H=[...Z,U];if(H0(D))Q(D,H);else{let L=`--${H.map((_)=>C(_)).join("-")}`,O=typeof D==="string"||typeof D==="number"?m0(D):String(D);Y.push(` ${L}: ${O};`)}}}if(Q($),Y.length===0)return"";return`${X} {
9
+ ${Y.join(`
10
+ `)}
11
+ }`}function G0($,J="stoop",q="data-theme"){let X=[];for(let[Y,Q]of Object.entries($)){let G=`[${q}="${Y}"]`,Z=I0(Q,J,G);if(Z)X.push(Z)}return X.join(`
12
+
13
+ `)}function k($,J,q,X){if(!$||typeof $!=="object")return $;let Y={},Q=!1,G=Object.keys($).sort();for(let Z of G){let W=$[Z];if(t(W)){let U=k(W,J,q,void 0);if(Y[Z]=U,U!==W)Q=!0}else if(typeof W==="string"&&W.includes("$")){Q=!0;let U=X||Z;Y[Z]=W.replace(P1,(D)=>{if(D.startsWith("-$")){let H=D.slice(1);return`calc(-1 * ${X1(H,J,U,q)})`}return X1(D,J,U,q)})}else Y[Z]=W}if(!Q)return $;return Y}function N1($,J){if(typeof $==="symbol"&&$===a)return!0;if(m(J))return!0;if(typeof $==="string"&&$.startsWith("__STOOP_COMPONENT_"))return!0;return!1}function x1($,J){if(typeof J==="object"&&J!==null&&"__stoopClassName"in J&&typeof J.__stoopClassName==="string")return J.__stoopClassName;if(typeof $==="string"&&$.startsWith("__STOOP_COMPONENT_"))return $.replace("__STOOP_COMPONENT_","");return""}function K($,J="",q=0,X){if(!$||typeof $!=="object")return"";if(q>C0)return"";let Y=[],Q=[],G=Object.keys($).sort();for(let W of G){let U=$[W];if(N1(W,U)){let D=x1(W,U);if(!D)continue;let H=T(D);if(!H)continue;let F=J?`${J} .${H}`:`.${H}`,L=U0(U)?K(U,F,q+1,X):"";if(L)Q.push(L);continue}if(U0(U))if(X&&W in X){let D=i0(X[W]);if(D){let H=K(U,J,q+1,X);if(H)Q.push(`${D} { ${H} }`)}}else if(W.startsWith("@")){let D=T(W);if(D){let H=K(U,J,q+1,X);if(H)Q.push(`${D} { ${H} }`)}}else if(W.includes("&")){let D=T(W);if(D){let F=D.split("&").join(J),L=K(U,F,q+1,X);if(L)Q.push(L)}}else if(W.startsWith(":")){let D=T(W);if(D){let H=`${J}${D}`,F=K(U,H,q+1,X);if(F)Q.push(F)}}else if(W.includes(" ")||W.includes(">")||W.includes("+")||W.includes("~")){let D=T(W);if(D){let F=/^[\s>+~]/.test(D.trim())?`${J}${D}`:`${J} ${D}`,L=K(U,F,q+1,X);if(L)Q.push(L)}}else{let D=T(W);if(D){let H=J?`${J} ${D}`:D,F=K(U,H,q+1,X);if(F)Q.push(F)}}else if(U!==void 0){let D=J0(W);if(D&&(typeof U==="string"||typeof U==="number")){let H=n0(U);Y.push(`${D}: ${H};`)}}}let Z=[];if(Y.length>0)Z.push(`${J} { ${Y.join(" ")} }`);return Z.push(...Q),Z.join("")}function p($,J,q="stoop",X,Y,Q){let G=R(q),Z=i($,Y),W=k(Z,J,Q),U=K(W,"",0,X),D=y(U),H=G?`${G}-${D}`:`css-${D}`,F=`${G}:${H}`,L=D0.get(F);if(L)return f(L,G,F),H;let O=K(W,`.${H}`,0,X);return D0.set(F,O),d0.set(F,H),f(O,G,F),H}var G1=new Map;function Q1($,J="stoop"){let q=J||"";G1.set(q,$)}function v1($="stoop"){let J=$||"";return G1.get(J)||null}function R0($,J){let q={...$},X=Object.keys(J);for(let Y of X){if(Y==="media")continue;let Q=J[Y],G=$[Y];if(Q&&typeof Q==="object"&&!Array.isArray(Q)&&G&&typeof G==="object"&&!Array.isArray(G))q[Y]={...G,...Q};else if(Q!==void 0)q[Y]=Q}return q}function O0($,J="stoop"){let q=v1(J);if(!q)return $;if(Y1($,q))return $;return R0(q,$)}function Q0($,J="stoop",q="data-theme"){if(!w())return;let X={};for(let[Q,G]of Object.entries($))X[Q]=O0(G,J);let Y=G0(X,J,q);J1(Y,J)}function Z1($){return function J(q={}){let X=e(q);return R0($,X)}}function W1($,J="stoop",q,X,Y){return function Q(G){return p(G,$,J,q,X,Y)}}function b1($,J,q,X){let Y=`@keyframes ${J} {`,Q=Object.keys($).sort((G,Z)=>{let W=parseFloat(G.replace("%","")),U=parseFloat(Z.replace("%",""));if(G==="from")return-1;if(Z==="from")return 1;if(G==="to")return 1;if(Z==="to")return-1;return W-U});for(let G of Q){if(!l0(G))continue;let Z=$[G];if(!Z||typeof Z!=="object")continue;Y+=` ${G} {`;let W=k(Z,q,X),U=Object.keys(W).sort();for(let D of U){let H=W[D];if(H!==void 0&&(typeof H==="string"||typeof H==="number")){let F=J0(D);if(F){let L=String(H);Y+=` ${F}: ${L};`}}}Y+=" }"}return Y+=" }",Y}function D1($="stoop",J,q){let X=R($),Y=new E(f0);return function Q(G){let Z=$0(G),W=Y.get(Z);if(W)return W;let U=Z.slice(0,8),D=X?`${X}-${U}`:`stoop-${U}`,H=b1(G,D,J,q),F=`__keyframes_${D}`;return f(H,X,F),Y.set(Z,D),D}}var M0=new Set;function U1($,J="stoop",q,X,Y){return function Q(G){let Z=$0(G);if(M0.has(Z))return()=>{};M0.add(Z);let W=R(J),U=i(G,X),D=k(U,$,Y),H=K(D,"",0,q);return f(H,W,`__global_${Z}`),()=>{M0.delete(Z)}}}import{useMemo as Z0,forwardRef as g1,createElement as T1,useContext as C1,createContext as f1}from"react";function H1($,J,q){let X=!1,Y=[];for(let G in $){let Z=J[G];if(Z===void 0)continue;let W=$[G],U=Z===!0?"true":Z===!1?"false":String(Z);if(W[U])Y.push(W[U]),X=!0}if(!X)return q;let Q={...Y[0]};for(let G=1;G<Y.length;G++)Object.assign(Q,Y[G]);return{...q,...Q}}var z0=null;function k1(){if(!z0)z0=f1(null);return z0}function S1($){return{__isStoopStyled:!0,__stoopClassName:$,[a]:$,toString:()=>`__STOOP_COMPONENT_${$}`}}function d1($){return m($)}var u1=new Set(["alignContent","alignItems","alignSelf","animation","animationDelay","animationDirection","animationDuration","animationFillMode","animationIterationCount","animationName","animationPlayState","animationTimingFunction","aspectRatio","backdropFilter","backfaceVisibility","background","backgroundAttachment","backgroundBlendMode","backgroundClip","backgroundColor","backgroundImage","backgroundOrigin","backgroundPosition","backgroundRepeat","backgroundSize","border","borderBottom","borderBottomColor","borderBottomLeftRadius","borderBottomRightRadius","borderBottomStyle","borderBottomWidth","borderCollapse","borderColor","borderImage","borderImageOutset","borderImageRepeat","borderImageSlice","borderImageSource","borderImageWidth","borderLeft","borderLeftColor","borderLeftStyle","borderLeftWidth","borderRadius","borderRight","borderRightColor","borderRightStyle","borderRightWidth","borderSpacing","borderStyle","borderTop","borderTopColor","borderTopLeftRadius","borderTopRightRadius","borderTopStyle","borderTopWidth","borderWidth","bottom","boxShadow","boxSizing","captionSide","caretColor","clear","clip","clipPath","color","columnCount","columnFill","columnGap","columnRule","columnRuleColor","columnRuleStyle","columnRuleWidth","columnSpan","columnWidth","columns","content","counterIncrement","counterReset","cursor","direction","display","emptyCells","filter","flex","flexBasis","flexDirection","flexFlow","flexGrow","flexShrink","flexWrap","float","font","fontFamily","fontFeatureSettings","fontKerning","fontLanguageOverride","fontSize","fontSizeAdjust","fontStretch","fontStyle","fontSynthesis","fontVariant","fontVariantAlternates","fontVariantCaps","fontVariantEastAsian","fontVariantLigatures","fontVariantNumeric","fontVariantPosition","fontWeight","gap","grid","gridArea","gridAutoColumns","gridAutoFlow","gridAutoRows","gridColumn","gridColumnEnd","gridColumnGap","gridColumnStart","gridGap","gridRow","gridRowEnd","gridRowGap","gridRowStart","gridTemplate","gridTemplateAreas","gridTemplateColumns","gridTemplateRows","height","hyphens","imageOrientation","imageRendering","imageResolution","imeMode","inlineSize","isolation","justifyContent","justifyItems","justifySelf","left","letterSpacing","lineHeight","listStyle","listStyleImage","listStylePosition","listStyleType","margin","marginBottom","marginLeft","marginRight","marginTop","maxHeight","maxWidth","minHeight","minWidth","objectFit","objectPosition","opacity","order","orphans","outline","outlineColor","outlineOffset","outlineStyle","outlineWidth","overflow","overflowWrap","overflowX","overflowY","padding","paddingBottom","paddingLeft","paddingRight","paddingTop","pageBreakAfter","pageBreakBefore","pageBreakInside","perspective","perspectiveOrigin","placeContent","placeItems","placeSelf","pointerEvents","position","quotes","resize","right","rowGap","scrollBehavior","tabSize","tableLayout","textAlign","textAlignLast","textDecoration","textDecorationColor","textDecorationLine","textDecorationStyle","textIndent","textJustify","textOverflow","textShadow","textTransform","textUnderlinePosition","top","transform","transformOrigin","transformStyle","transition","transitionDelay","transitionDuration","transitionProperty","transitionTimingFunction","unicodeBidi","userSelect","verticalAlign","visibility","whiteSpace","width","wordBreak","wordSpacing","wordWrap","writingMode","zIndex"]);function y1($){return u1.has($)}function p1($,J){let q=J?new Set(Object.keys(J)):new Set,X={},Y={},Q={};for(let G in $)if(q.has(G))X[G]=$[G];else if(y1(G))Y[G]=$[G];else Q[G]=$[G];return{cssProps:Y,elementProps:Q,variantProps:X}}function F1($,J="stoop",q,X,Y,Q){return function G(Z,W,U){let D=W||r,H=U;if(W&&"variants"in W&&typeof W.variants==="object"){H=W.variants;let{variants:v,...x}=W;D=x}let F;if(typeof Z!=="string"&&d1(Z))F=Z.__stoopClassName;let L=g1(function v(x,j){let{as:z,className:P,css:M,...N}=x,b=z||Z,g=Z0(()=>M&&typeof M==="object"&&M!==null?M:r,[M]),{cssProps:B,elementProps:V,variantProps:S}=p1(N,H),l=C1(Q||k1())?.theme||$,x0=l.media?{...q,...l.media}:q,v0=Z0(()=>{if(!H)return"";let I=Object.entries(S);if(I.length===0)return"";return I.sort(([d],[h])=>d.localeCompare(h)).map(([d,h])=>`${d}:${String(h)}`).join("|")},[S]),b0=Z0(()=>{let I=D;if(H&&v0)I=H1(H,S,D);if(Object.keys(B).length>0)I=Object.assign({},I,B);if(g!==r)I=Object.assign({},I,g);return I},[v0,g,B,D,H,S]),R1=Z0(()=>{let I=[];if(F)I.push(F);let d=p(b0,l,J,x0,X,Y);if(d)I.push(d);if(P){let h=typeof P==="string"?P:String(P),g0=o0(h);if(g0)I.push(g0)}return I.length>0?I.join(" "):void 0},[b0,P,F,l,J,x0,X,Y]);return T1(b,{...V,className:R1,ref:j})}),O=y(JSON.stringify(D)),_=`${J}-${O}`,A=L;return A.selector=S1(_),A}}import{createContext as w1,useCallback as B1,useContext as h1,useLayoutEffect as o,useMemo as P0,useRef as V0,useState as c1}from"react";function E0($){if(!w())return{error:"Not in browser environment",success:!1,value:null};try{return{source:"localStorage",success:!0,value:localStorage.getItem($)}}catch(J){return{error:J instanceof Error?J.message:"localStorage access failed",success:!1,value:null}}}function K0($,J){if(!w())return{error:"Not in browser environment",success:!1,value:void 0};try{return localStorage.setItem($,J),{success:!0,value:void 0}}catch(q){return{error:q instanceof Error?q.message:"localStorage write failed",success:!1,value:void 0}}}function j0($){if(!w())return null;let q=`; ${document.cookie}`.split(`; ${$}=`);if(q.length===2)return q.pop()?.split(";").shift()||null;return null}function L1($,J,q={}){if(!w())return!1;let{maxAge:X=k0,path:Y=S0,secure:Q=!1}=q;try{return document.cookie=`${$}=${J}; path=${Y}; max-age=${X}${Q?"; secure":""}`,!0}catch{return!1}}import{jsx as A1}from"react/jsx-runtime";function N0($,J,q){if(!w())return;let X=J?j0(J):null,Y=E0(q),Q=Y.success?Y.value:null;if(X===$&&Q!==$)K0(q,$);if(Q===$&&J&&X!==$)L1(J,$)}function n1($,J,q){if(!w())return null;if($!==void 0){let Q=j0($);if(Q&&q[Q])return Q}let X=E0(J),Y=X.success?X.value:null;if(Y&&q[Y])return Y;return null}function _1($,J,q="stoop",X,Y){let Q=w1(null),G=w1(null),Z=Object.keys($),W=Z[0]||"default",U=X&&Y?Y(X):void 0;function D({attribute:H="data-theme",children:F,cookieKey:L,defaultTheme:O,storageKey:_="stoop-theme"}){let[A,v]=c1(O||W),x=V0(!1);o(()=>{if(!w()||x.current)return;let B=n1(L,_,$);if(B){if(N0(B,L,_),B!==A)v(B)}x.current=!0},[L,_,$]),o(()=>{if(!w())return;let B=(V)=>{if(V.key===_&&V.newValue&&$[V.newValue]&&V.newValue!==A)v(V.newValue),N0(V.newValue,L,_)};return window.addEventListener("storage",B),()=>{window.removeEventListener("storage",B)}},[_,L,A,$]);let j=P0(()=>{return $[A]||$[O||W]||J},[A,O,W,$,J]),z=V0(!1),P=V0(!1);o(()=>{if(!w()||z.current)return;Q0($,q,H),z.current=!0},[$,q,H]),o(()=>{if(!w()||P.current)return;if(U)U(),P.current=!0},[U]),o(()=>{if(!w())return;if(H)document.documentElement.setAttribute(H,A)},[A,H]);let M=B1((B)=>{if($[B])v(B),K0(_,B),N0(B,L,_);else if(!u())console.warn(`[Stoop] Theme "${B}" not found. Available themes: ${Z.join(", ")}`)},[_,L,$,Z,A]),N=P0(()=>({theme:j,themeName:A}),[j,A]),b=B1(()=>{let V=(Z.indexOf(A)+1)%Z.length,S=Z[V];M(S)},[A,M,Z]),g=P0(()=>({availableThemes:Z,setTheme:M,theme:j,themeName:A,toggleTheme:b}),[j,A,M,b]);return A1(Q.Provider,{value:N,children:A1(G.Provider,{value:g,children:F})})}return{Provider:D,ThemeContext:Q,ThemeManagementContext:G}}function I1($){return function J(){let q=h1($);if(!q)throw new Error("useTheme must be used within a Provider");return q}}function m1($){let{globalCss:J,media:q,prefix:X="stoop",theme:Y,themeMap:Q,utils:G}=$,Z=R(X),W=e(Y),U=W.media||q,D={...n,...Q};Q1(W,Z);let H=W1(W,Z,U,G,D),F=Z1(W),L=U1(W,Z,U,G,D),O=D1(Z,W,D),_=Object.freeze({...W});function A(j){for(let z of j)try{p(z,W,Z,U,G,D)}catch{}}function v(j){if(!$.themes||Object.keys($.themes).length===0)return;Q0($.themes,Z)}function x(j){let z="";if($.themes&&Object.keys($.themes).length>0){let N={};for(let[g,B]of Object.entries($.themes))N[g]=O0(B,Z);let b=G0(N,Z,"data-theme");if(b)z+=b+`
14
+ `}else{let N=I0(W,Z);if(N)z+=N+`
15
+ `}let P=q1(),M=B0(P).trim();if(M)z+=(z?`
16
+ `:"")+M;return z}return{config:{...$,prefix:Z},createTheme:F,css:H,getCssText:x,globalCss:L,globalCssConfig:J,keyframes:O,media:U,mergedThemeMap:D,preloadTheme:v,sanitizedPrefix:Z,theme:_,utils:G,validatedTheme:W,warmCache:A}}function U5($){let J=m1($),q,X,Y;if($.themes){let G={};for(let[D,H]of Object.entries($.themes))G[D]=J.createTheme(H);let{Provider:Z,ThemeContext:W,ThemeManagementContext:U}=_1(G,J.validatedTheme,J.sanitizedPrefix,J.globalCssConfig,J.globalCss);Y=W,q=Z,X=I1(U)}let Q=F1(J.validatedTheme,J.sanitizedPrefix,J.media,J.utils,J.mergedThemeMap,Y);return{config:J.config,createTheme:J.createTheme,css:J.css,getCssText:J.getCssText,globalCss:J.globalCss,keyframes:J.keyframes,preloadTheme:J.preloadTheme,Provider:q,styled:Q,theme:J.theme,useTheme:X,warmCache:J.warmCache}}export{m1 as createStoopBase,U5 as createStoop};
@@ -0,0 +1,113 @@
1
+ /**
2
+ * CSS injection implementation.
3
+ * Consolidates browser-specific and SSR-specific CSS injection logic.
4
+ * Handles stylesheet management, theme variable injection, deduplication, and SSR caching.
5
+ */
6
+ /**
7
+ * Checks if a CSS rule has already been injected.
8
+ *
9
+ * @param key - Rule key to check
10
+ * @returns True if rule is already injected
11
+ */
12
+ export declare function isInjectedRule(key: string): boolean;
13
+ /**
14
+ * Marks a CSS rule as injected.
15
+ *
16
+ * @param key - Rule key
17
+ * @param css - CSS string
18
+ */
19
+ export declare function markRuleAsInjected(key: string, css: string): void;
20
+ /**
21
+ * Adds CSS to the SSR cache with LRU eviction.
22
+ *
23
+ * @param css - CSS string to cache
24
+ */
25
+ export declare function addToSSRCache(css: string): void;
26
+ /**
27
+ * Gets all cached CSS text for SSR.
28
+ *
29
+ * @returns Joined CSS text string
30
+ */
31
+ export declare function getSSRCacheText(): string;
32
+ /**
33
+ * Clears the SSR cache.
34
+ */
35
+ export declare function clearSSRCache(): void;
36
+ /**
37
+ * Checks if CSS is already in the SSR cache.
38
+ *
39
+ * @param css - CSS string to check
40
+ * @returns True if CSS is cached
41
+ */
42
+ export declare function isInSSRCache(css: string): boolean;
43
+ /**
44
+ * Gets or creates the stylesheet element for CSS injection.
45
+ * Reuses the SSR stylesheet if it exists to prevent FOUC.
46
+ * Supports multiple Stoop instances with different prefixes.
47
+ *
48
+ * @param prefix - Optional prefix for stylesheet identification
49
+ * @returns HTMLStyleElement
50
+ * @throws Error if called in SSR context
51
+ */
52
+ export declare function getStylesheet(prefix?: string): HTMLStyleElement;
53
+ /**
54
+ * Removes all theme variable blocks (both :root and attribute selectors) from CSS.
55
+ *
56
+ * @param css - CSS string to clean
57
+ * @returns CSS string without theme variable blocks
58
+ */
59
+ export declare function removeThemeVariableBlocks(css: string): string;
60
+ /**
61
+ * Injects CSS variables for all themes using attribute selectors.
62
+ * This allows all themes to be available simultaneously, with theme switching
63
+ * handled by changing the data-theme attribute.
64
+ *
65
+ * @param allThemeVars - CSS string containing all theme CSS variables
66
+ * @param prefix - Optional prefix for CSS variables
67
+ */
68
+ export declare function injectAllThemeVariables(allThemeVars: string, prefix?: string): void;
69
+ /**
70
+ * Updates the stylesheet with new CSS rules.
71
+ *
72
+ * @param css - CSS string to inject
73
+ * @param ruleKey - Unique key for deduplication
74
+ * @param prefix - Optional prefix for CSS rules
75
+ */
76
+ export declare function updateStylesheet(css: string, ruleKey: string, prefix?: string): void;
77
+ /**
78
+ * Injects CSS into the browser stylesheet with deduplication.
79
+ *
80
+ * @param css - CSS string to inject
81
+ * @param ruleKey - Unique key for deduplication
82
+ * @param prefix - Optional prefix for CSS rules
83
+ */
84
+ export declare function injectBrowserCSS(css: string, ruleKey: string, prefix?: string): void;
85
+ /**
86
+ * Gets the current stylesheet element for a given prefix.
87
+ *
88
+ * @param prefix - Optional prefix for stylesheet identification
89
+ * @returns HTMLStyleElement or null if not created
90
+ */
91
+ export declare function getStylesheetElement(prefix?: string): HTMLStyleElement | null;
92
+ /**
93
+ * Gets all injected rules (for internal use).
94
+ */
95
+ export declare function getAllInjectedRules(): Map<string, string>;
96
+ /**
97
+ * Injects CSS into the document with automatic SSR support.
98
+ *
99
+ * @param css - CSS string to inject
100
+ * @param prefix - Optional prefix for CSS rules
101
+ * @param ruleKey - Optional unique key for deduplication
102
+ */
103
+ export declare function injectCSS(css: string, prefix?: string, ruleKey?: string): void;
104
+ /**
105
+ * Gets all injected CSS text (browser or SSR).
106
+ *
107
+ * @returns CSS text string
108
+ */
109
+ export declare function getCssText(prefix?: string): string;
110
+ /**
111
+ * Clears all injected CSS and caches.
112
+ */
113
+ export declare function clearStylesheet(): void;
@@ -4,11 +4,6 @@
4
4
  */
5
5
  import type { ComponentType, ElementType, JSX, ReactNode } from "react";
6
6
  import type { PolymorphicPropsWithRef } from "react-polymorphic-types";
7
- import type { createTheme } from "../api/create-theme";
8
- import type { createCSSFunction } from "../api/css";
9
- import type { createGlobalCSSFunction } from "../api/global-css";
10
- import type { createKeyframesFunction } from "../api/keyframes";
11
- import type { createStyledFunction } from "../api/styled";
12
7
  export type CSSPropertyValue = string | number;
13
8
  export interface StyledComponentRef {
14
9
  readonly __stoopClassName: string;
@@ -70,10 +65,12 @@ export interface StoopConfig {
70
65
  utils?: Record<string, UtilityFunction>;
71
66
  prefix?: string;
72
67
  themeMap?: Record<string, ThemeScale>;
68
+ globalCss?: CSS;
73
69
  }
74
70
  export type VariantKeys<T extends Variants> = keyof T;
71
+ type ExtractVariantKeys<T> = T extends Record<infer K, CSS> ? K extends string | number | boolean ? K : T extends Record<string, CSS> ? string : never : T extends Record<string, CSS> ? keyof T : never;
75
72
  export type VariantPropsFromConfig<T extends Variants> = {
76
- [K in VariantKeys<T>]?: keyof T[K] | boolean | number;
73
+ [K in VariantKeys<T>]?: ExtractVariantKeys<T[K]>;
77
74
  };
78
75
  type StyledOwnProps<VariantsConfig extends Variants> = StyledBaseProps & (VariantsConfig extends Record<string, never> ? {} : VariantPropsFromConfig<VariantsConfig>);
79
76
  export type StyledComponentProps<DefaultElement extends ElementType, VariantsConfig extends Variants = {}> = PolymorphicPropsWithRef<StyledOwnProps<VariantsConfig>, DefaultElement>;
@@ -88,6 +85,119 @@ export interface ThemeManagementContextValue {
88
85
  toggleTheme: () => void;
89
86
  availableThemes: readonly string[];
90
87
  }
88
+ /**
89
+ * Server-side Stoop instance.
90
+ * Only includes APIs that work without React dependencies.
91
+ */
92
+ export interface StoopServerInstance {
93
+ config: StoopConfig & {
94
+ prefix: string;
95
+ };
96
+ createTheme: (themeOverride: Partial<Theme>) => Theme;
97
+ css: (styles: CSS) => string;
98
+ getCssText: (theme?: string | Theme) => string;
99
+ globalCss: (...args: CSS[]) => () => void;
100
+ keyframes: (definition: Record<string, CSS>) => string;
101
+ preloadTheme: (theme: string | Theme) => void;
102
+ theme: Theme;
103
+ warmCache: (styles: CSS[]) => void;
104
+ }
105
+ /**
106
+ * Theme detection options for automatic theme selection.
107
+ */
108
+ export interface ThemeDetectionOptions {
109
+ /** localStorage key to check for stored theme preference */
110
+ localStorage?: string;
111
+ /** Cookie name to check for stored theme preference */
112
+ cookie?: string;
113
+ /** Whether to check system color scheme preference */
114
+ systemPreference?: boolean;
115
+ /** Default theme name to fall back to */
116
+ default?: string;
117
+ /** Available themes map for validation */
118
+ themes?: Record<string, Theme>;
119
+ }
120
+ /**
121
+ * Result of theme detection.
122
+ */
123
+ export interface ThemeDetectionResult {
124
+ /** Detected theme name */
125
+ theme: string;
126
+ /** Source of the theme detection */
127
+ source: "cookie" | "localStorage" | "system" | "default";
128
+ /** Confidence level (0-1) of the detection */
129
+ confidence: number;
130
+ }
131
+ /**
132
+ * Storage type enumeration.
133
+ */
134
+ export type StorageType = "localStorage" | "cookie";
135
+ /**
136
+ * Options for storage operations.
137
+ */
138
+ export interface StorageOptions {
139
+ /** Storage type */
140
+ type?: StorageType;
141
+ /** Cookie max age in seconds (only for cookies) */
142
+ maxAge?: number;
143
+ /** Cookie path (only for cookies) */
144
+ path?: string;
145
+ /** Whether to use secure cookies (only for cookies) */
146
+ secure?: boolean;
147
+ }
148
+ /**
149
+ * Storage result with metadata.
150
+ */
151
+ export interface StorageResult<T = string> {
152
+ /** The stored value */
153
+ value: T;
154
+ /** Whether the operation succeeded */
155
+ success: boolean;
156
+ /** Error message if operation failed */
157
+ error?: string;
158
+ /** Source of the value */
159
+ source?: StorageType;
160
+ }
161
+ /**
162
+ * Options for auto-preloading.
163
+ */
164
+ export interface AutoPreloadOptions {
165
+ /** Theme detection options */
166
+ themeDetection?: ThemeDetectionOptions;
167
+ /** Common styles to warm the cache with */
168
+ commonStyles?: CSS[];
169
+ /** Whether to enable automatic theme preloading */
170
+ enableThemePreload?: boolean;
171
+ /** Whether to enable automatic cache warming */
172
+ enableCacheWarm?: boolean;
173
+ /** Whether to run in SSR context (limits available APIs) */
174
+ ssr?: boolean;
175
+ }
176
+ /**
177
+ * Result of auto-preloading operations.
178
+ */
179
+ export interface AutoPreloadResult {
180
+ /** Detected theme information */
181
+ themeDetection: ThemeDetectionResult;
182
+ /** Whether cache was warmed */
183
+ cacheWarmed: boolean;
184
+ /** Whether theme was preloaded */
185
+ themePreloaded: boolean;
186
+ /** Any errors that occurred */
187
+ errors: string[];
188
+ }
189
+ /**
190
+ * Styled component type - the return type of styled()
191
+ */
192
+ export type StyledComponent<DefaultElement extends ElementType, VariantsConfig extends Variants = {}> = ComponentType<StyledComponentProps<DefaultElement, VariantsConfig>> & {
193
+ selector: StyledComponentRef;
194
+ };
195
+ /**
196
+ * Styled function type - the main styled() function signature
197
+ */
198
+ export interface StyledFunction {
199
+ <DefaultElement extends StylableElement, VariantsConfig extends Variants = {}>(defaultElement: DefaultElement, baseStyles?: CSS, variants?: VariantsConfig): StyledComponent<DefaultElement, VariantsConfig>;
200
+ }
91
201
  export interface GetCssTextOptions {
92
202
  theme?: Theme;
93
203
  includeThemeVars?: boolean;
@@ -96,24 +206,49 @@ export interface ProviderProps {
96
206
  children: ReactNode;
97
207
  defaultTheme?: string;
98
208
  storageKey?: string;
209
+ cookieKey?: string;
99
210
  attribute?: string;
100
211
  }
212
+ /**
213
+ * CSS function type
214
+ */
215
+ export interface CSSFunction {
216
+ (styles: CSS): string;
217
+ }
218
+ /**
219
+ * Global CSS function type
220
+ */
221
+ export interface GlobalCSSFunction {
222
+ (styles: CSS): () => void;
223
+ }
224
+ /**
225
+ * Keyframes function type
226
+ */
227
+ export interface KeyframesFunction {
228
+ (keyframes: Record<string, CSS>): string;
229
+ }
230
+ /**
231
+ * Create theme function type
232
+ */
233
+ export interface CreateThemeFunction {
234
+ (theme: Partial<DefaultTheme>): DefaultTheme;
235
+ }
101
236
  /**
102
237
  * Stoop instance.
103
238
  * Includes all APIs: styled, Provider, useTheme, css, globalCss, keyframes, etc.
104
239
  */
105
240
  export interface StoopInstance {
106
- styled: ReturnType<typeof createStyledFunction>;
107
- css: ReturnType<typeof createCSSFunction>;
108
- createTheme: ReturnType<typeof createTheme>;
109
- globalCss: ReturnType<typeof createGlobalCSSFunction>;
110
- keyframes: ReturnType<typeof createKeyframesFunction>;
241
+ styled: StyledFunction;
242
+ css: CSSFunction;
243
+ createTheme: CreateThemeFunction;
244
+ globalCss: GlobalCSSFunction;
245
+ keyframes: KeyframesFunction;
111
246
  theme: DefaultTheme;
112
247
  /**
113
248
  * Gets all generated CSS text for server-side rendering.
114
249
  * Always includes theme CSS variables.
115
250
  *
116
- * @param theme - Optional theme (name or object) to include vars for (defaults to default theme)
251
+ * @param theme - Deprecated parameter, kept for backward compatibility but ignored
117
252
  * @returns CSS text string with theme variables and component styles
118
253
  */
119
254
  getCssText: (theme?: string | Theme) => string;
@@ -1,13 +1,24 @@
1
1
  /**
2
2
  * Type declaration for react-polymorphic-types to work around package.json exports issue.
3
+ * Properly extends native element props while preserving custom variant props.
3
4
  */
4
5
 
5
6
  declare module "react-polymorphic-types" {
6
7
  import type { ElementType, ComponentPropsWithRef, ComponentPropsWithoutRef } from "react";
7
8
 
9
+ /**
10
+ * Polymorphic props with ref support.
11
+ * Extends native element props while preserving custom props (like variants).
12
+ * Variant props take precedence over native props with the same name.
13
+ */
8
14
  export type PolymorphicPropsWithRef<OwnProps, DefaultElement extends ElementType> = OwnProps &
9
- ComponentPropsWithRef<DefaultElement>;
15
+ Omit<ComponentPropsWithRef<DefaultElement>, keyof OwnProps>;
10
16
 
17
+ /**
18
+ * Polymorphic props without ref support.
19
+ * Extends native element props while preserving custom props (like variants).
20
+ * Variant props take precedence over native props with the same name.
21
+ */
11
22
  export type PolymorphicPropsWithoutRef<OwnProps, DefaultElement extends ElementType> = OwnProps &
12
- ComponentPropsWithoutRef<DefaultElement>;
23
+ Omit<ComponentPropsWithoutRef<DefaultElement>, keyof OwnProps>;
13
24
  }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Auto-preloading utilities for cache warming and theme preloading.
3
+ * Helps eliminate FOUC (Flash of Unstyled Content) by pre-compiling styles and preloading themes.
4
+ */
5
+ import type { CSS, Theme, ThemeDetectionOptions, ThemeDetectionResult, AutoPreloadOptions, AutoPreloadResult } from "../types";
6
+ /**
7
+ * Common UI component styles that are frequently used.
8
+ * These represent typical design system patterns.
9
+ */
10
+ export declare const COMMON_UI_STYLES: CSS[];
11
+ /**
12
+ * Automatically warms the cache with common styles.
13
+ *
14
+ * @param warmCacheFn - The warmCache function from Stoop instance
15
+ * @param styles - Styles to warm (defaults to COMMON_UI_STYLES)
16
+ * @returns Promise that resolves when warming is complete
17
+ */
18
+ export declare function autoWarmCache(warmCacheFn: (styles: CSS[]) => void, styles?: CSS[]): Promise<void>;
19
+ /**
20
+ * Automatically preloads a detected theme.
21
+ *
22
+ * @param preloadThemeFn - The preloadTheme function from Stoop instance
23
+ * @param options - Theme detection options
24
+ * @param ssr - Whether running in SSR context
25
+ * @returns Promise that resolves when preloading is complete
26
+ */
27
+ export declare function autoPreloadTheme(preloadThemeFn: (theme: string | Theme) => void, options?: ThemeDetectionOptions, ssr?: boolean): Promise<ThemeDetectionResult>;
28
+ /**
29
+ * Performs automatic preloading operations based on configuration.
30
+ *
31
+ * @param warmCacheFn - The warmCache function from Stoop instance
32
+ * @param preloadThemeFn - The preloadTheme function from Stoop instance
33
+ * @param options - Auto-preload options
34
+ * @returns Promise that resolves with preload results
35
+ */
36
+ export declare function autoPreload(warmCacheFn: (styles: CSS[]) => void, preloadThemeFn: (theme: string | Theme) => void, options?: AutoPreloadOptions): Promise<AutoPreloadResult>;
37
+ /**
38
+ * Creates an auto-preloader with pre-configured options.
39
+ *
40
+ * @param warmCacheFn - The warmCache function from Stoop instance
41
+ * @param preloadThemeFn - The preloadTheme function from Stoop instance
42
+ * @param defaultOptions - Default auto-preload options
43
+ * @returns Auto-preloader function
44
+ */
45
+ export declare function createAutoPreloader(warmCacheFn: (styles: CSS[]) => void, preloadThemeFn: (theme: string | Theme) => void, defaultOptions?: AutoPreloadOptions): (options?: Partial<AutoPreloadOptions>) => Promise<AutoPreloadResult>;