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.
- package/README.md +125 -0
- package/dist/api/core-api.d.ts +34 -0
- package/dist/api/styled.d.ts +0 -1
- package/dist/api/theme-provider.d.ts +41 -0
- package/dist/constants.d.ts +11 -1
- package/dist/core/compiler.d.ts +11 -0
- package/dist/core/theme-manager.d.ts +34 -3
- package/dist/create-stoop-internal.d.ts +30 -0
- package/dist/create-stoop-ssr.d.ts +10 -0
- package/dist/create-stoop-ssr.js +16 -0
- package/dist/create-stoop.d.ts +32 -1
- package/dist/create-stoop.js +16 -147
- package/dist/inject.d.ts +113 -0
- package/dist/types/index.d.ts +147 -12
- package/dist/types/react-polymorphic-types.d.ts +13 -2
- package/dist/utils/auto-preload.d.ts +45 -0
- package/dist/utils/helpers.d.ts +64 -0
- package/dist/utils/storage.d.ts +148 -0
- package/dist/utils/{string.d.ts → theme-utils.d.ts} +20 -3
- package/dist/utils/theme.d.ts +14 -2
- package/package.json +44 -17
- package/dist/api/create-theme.d.ts +0 -13
- package/dist/api/create-theme.js +0 -43
- package/dist/api/css.d.ts +0 -16
- package/dist/api/css.js +0 -20
- package/dist/api/global-css.js +0 -89
- package/dist/api/keyframes.d.ts +0 -16
- package/dist/api/keyframes.js +0 -95
- package/dist/api/provider.d.ts +0 -19
- package/dist/api/provider.js +0 -109
- package/dist/api/styled.js +0 -170
- package/dist/api/use-theme.d.ts +0 -13
- package/dist/api/use-theme.js +0 -21
- package/dist/constants.js +0 -144
- package/dist/core/cache.js +0 -68
- package/dist/core/compiler.js +0 -198
- package/dist/core/theme-manager.js +0 -97
- package/dist/core/variants.js +0 -32
- package/dist/create-stoop-server.d.ts +0 -33
- package/dist/create-stoop-server.js +0 -130
- package/dist/index.d.ts +0 -6
- package/dist/index.js +0 -5
- package/dist/inject/browser.d.ts +0 -58
- package/dist/inject/browser.js +0 -149
- package/dist/inject/dedup.d.ts +0 -29
- package/dist/inject/dedup.js +0 -38
- package/dist/inject/index.d.ts +0 -40
- package/dist/inject/index.js +0 -75
- package/dist/inject/ssr.d.ts +0 -27
- package/dist/inject/ssr.js +0 -46
- package/dist/ssr.d.ts +0 -21
- package/dist/ssr.js +0 -19
- package/dist/types/index.js +0 -5
- package/dist/utils/environment.d.ts +0 -6
- package/dist/utils/environment.js +0 -12
- package/dist/utils/string.js +0 -253
- package/dist/utils/theme-map.d.ts +0 -22
- package/dist/utils/theme-map.js +0 -97
- package/dist/utils/theme-validation.d.ts +0 -13
- package/dist/utils/theme-validation.js +0 -36
- package/dist/utils/theme.js +0 -279
- package/dist/utils/type-guards.d.ts +0 -26
- package/dist/utils/type-guards.js +0 -38
- package/dist/utils/utilities.d.ts +0 -14
- package/dist/utils/utilities.js +0 -43
package/dist/create-stoop.js
CHANGED
|
@@ -1,147 +1,16 @@
|
|
|
1
|
-
"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
import { getRootRegex, sanitizePrefix } from "./utils/string";
|
|
14
|
-
|
|
15
|
-
|
|
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};
|
package/dist/inject.d.ts
ADDED
|
@@ -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;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -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>]?:
|
|
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:
|
|
107
|
-
css:
|
|
108
|
-
createTheme:
|
|
109
|
-
globalCss:
|
|
110
|
-
keyframes:
|
|
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 -
|
|
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>;
|