stoop 0.4.0 → 0.5.0
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 +9 -4
- package/dist/api/core-api.d.ts +1 -0
- package/dist/api/styled.d.ts +2 -8
- package/dist/core/cache.d.ts +0 -1
- package/dist/core/stringify.d.ts +19 -0
- package/dist/core/theme-manager.d.ts +3 -11
- package/dist/create-stoop-internal.d.ts +3 -5
- package/dist/create-stoop-ssr.d.ts +0 -2
- package/dist/create-stoop-ssr.js +16 -26
- package/dist/create-stoop.d.ts +3 -7
- package/dist/create-stoop.js +16 -156
- package/dist/inject.d.ts +2 -4
- package/dist/types/index.d.ts +20 -9
- package/dist/utils/helpers.d.ts +0 -3
- package/dist/utils/storage.d.ts +2 -95
- package/dist/utils/theme-utils.d.ts +0 -13
- package/dist/utils/theme.d.ts +1 -3
- package/package.json +11 -13
- package/dist/api/core-api.js +0 -135
- package/dist/api/global-css.d.ts +0 -7
- package/dist/api/global-css.js +0 -42
- package/dist/api/styled.js +0 -419
- package/dist/api/theme-provider.js +0 -223
- package/dist/constants.js +0 -154
- package/dist/core/cache.js +0 -68
- package/dist/core/compiler.js +0 -206
- package/dist/core/theme-manager.js +0 -107
- package/dist/core/variants.d.ts +0 -15
- package/dist/core/variants.js +0 -38
- package/dist/create-stoop-internal.js +0 -123
- package/dist/inject.js +0 -308
- package/dist/types/index.js +0 -5
- package/dist/utils/auto-preload.d.ts +0 -45
- package/dist/utils/auto-preload.js +0 -167
- package/dist/utils/helpers.js +0 -150
- package/dist/utils/storage.js +0 -396
- package/dist/utils/theme-utils.js +0 -353
- package/dist/utils/theme.js +0 -304
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Internal implementation for creating Stoop instances.
|
|
3
|
-
* This file is used by the SSR entry point and does NOT import React types at module level.
|
|
4
|
-
* React types are only imported conditionally when creating client instances.
|
|
5
|
-
*/
|
|
6
|
-
import { createTheme as createThemeFactory, createCSSFunction, createKeyframesFunction, } from "./api/core-api";
|
|
7
|
-
import { createGlobalCSSFunction } from "./api/global-css";
|
|
8
|
-
// Note: React APIs (styled, Provider) are NOT imported here for SSR safety
|
|
9
|
-
import { DEFAULT_THEME_MAP } from "./constants";
|
|
10
|
-
import { compileCSS } from "./core/compiler";
|
|
11
|
-
import { mergeWithDefaultTheme, registerDefaultTheme, injectAllThemes } from "./core/theme-manager";
|
|
12
|
-
import { getCssText as getCssTextBase, removeThemeVariableBlocks } from "./inject";
|
|
13
|
-
import { validateTheme } from "./utils/helpers";
|
|
14
|
-
import { generateAllThemeVariables, generateCSSVariables } from "./utils/theme";
|
|
15
|
-
import { sanitizePrefix } from "./utils/theme-utils";
|
|
16
|
-
/**
|
|
17
|
-
* Shared implementation for creating Stoop instances.
|
|
18
|
-
* Handles common setup logic for both client and server instances.
|
|
19
|
-
* Exported for use in SSR entry point.
|
|
20
|
-
*/
|
|
21
|
-
export function createStoopBase(config) {
|
|
22
|
-
const { globalCss: globalCssConfig, media: configMedia, prefix = "stoop", theme, themeMap: userThemeMap, utils, } = config;
|
|
23
|
-
const sanitizedPrefix = sanitizePrefix(prefix);
|
|
24
|
-
const validatedTheme = validateTheme(theme);
|
|
25
|
-
const media = validatedTheme.media || configMedia;
|
|
26
|
-
const mergedThemeMap = {
|
|
27
|
-
...DEFAULT_THEME_MAP,
|
|
28
|
-
...userThemeMap,
|
|
29
|
-
};
|
|
30
|
-
registerDefaultTheme(validatedTheme, sanitizedPrefix);
|
|
31
|
-
const css = createCSSFunction(validatedTheme, sanitizedPrefix, media, utils, mergedThemeMap);
|
|
32
|
-
const createTheme = createThemeFactory(validatedTheme);
|
|
33
|
-
const globalCss = createGlobalCSSFunction(validatedTheme, sanitizedPrefix, media, utils, mergedThemeMap);
|
|
34
|
-
const keyframes = createKeyframesFunction(sanitizedPrefix, validatedTheme, mergedThemeMap);
|
|
35
|
-
const themeObject = Object.freeze({ ...validatedTheme });
|
|
36
|
-
/**
|
|
37
|
-
* Pre-compiles CSS objects to warm the cache.
|
|
38
|
-
* Useful for eliminating FOUC by pre-compiling common styles.
|
|
39
|
-
*
|
|
40
|
-
* @param styles - Array of CSS objects to pre-compile
|
|
41
|
-
*/
|
|
42
|
-
function warmCache(styles) {
|
|
43
|
-
for (const style of styles) {
|
|
44
|
-
try {
|
|
45
|
-
compileCSS(style, validatedTheme, sanitizedPrefix, media, utils, mergedThemeMap);
|
|
46
|
-
}
|
|
47
|
-
catch {
|
|
48
|
-
// Skip invalid styles
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Preloads a theme by injecting its CSS variables before React renders.
|
|
54
|
-
* Useful for preventing FOUC when loading a non-default theme from localStorage.
|
|
55
|
-
* Uses injectAllThemes to ensure all themes are available.
|
|
56
|
-
*
|
|
57
|
-
* @param theme - Theme to preload (can be theme name string or Theme object)
|
|
58
|
-
*/
|
|
59
|
-
function preloadTheme(theme) {
|
|
60
|
-
if (!config.themes || Object.keys(config.themes).length === 0) {
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
// Always inject all themes for consistency and to prevent FOUC
|
|
64
|
-
injectAllThemes(config.themes, sanitizedPrefix);
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Gets all injected CSS text for server-side rendering.
|
|
68
|
-
* Always includes all theme CSS variables using attribute selectors.
|
|
69
|
-
*
|
|
70
|
-
* @param theme - Deprecated parameter, kept for backward compatibility but ignored
|
|
71
|
-
* @returns CSS text string with theme variables and component styles
|
|
72
|
-
*/
|
|
73
|
-
function getCssText(theme) {
|
|
74
|
-
let result = "";
|
|
75
|
-
// Always include all themes using attribute selectors for consistency
|
|
76
|
-
if (config.themes && Object.keys(config.themes).length > 0) {
|
|
77
|
-
// Merge all themes with default theme for consistency with client-side behavior
|
|
78
|
-
const mergedThemes = {};
|
|
79
|
-
for (const [themeName, theme] of Object.entries(config.themes)) {
|
|
80
|
-
mergedThemes[themeName] = mergeWithDefaultTheme(theme, sanitizedPrefix);
|
|
81
|
-
}
|
|
82
|
-
const allThemeVars = generateAllThemeVariables(mergedThemes, sanitizedPrefix, "data-theme");
|
|
83
|
-
if (allThemeVars) {
|
|
84
|
-
result += allThemeVars + "\n";
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
// No themes configured, just use default theme
|
|
89
|
-
const themeVars = generateCSSVariables(validatedTheme, sanitizedPrefix);
|
|
90
|
-
if (themeVars) {
|
|
91
|
-
result += themeVars + "\n";
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
const baseCss = getCssTextBase();
|
|
95
|
-
// Remove any existing theme variable blocks (they're already included above)
|
|
96
|
-
const cleanedCss = removeThemeVariableBlocks(baseCss).trim();
|
|
97
|
-
if (cleanedCss) {
|
|
98
|
-
result += (result ? "\n" : "") + cleanedCss;
|
|
99
|
-
}
|
|
100
|
-
return result;
|
|
101
|
-
}
|
|
102
|
-
return {
|
|
103
|
-
config: { ...config, prefix: sanitizedPrefix },
|
|
104
|
-
createTheme,
|
|
105
|
-
css,
|
|
106
|
-
getCssText,
|
|
107
|
-
globalCss,
|
|
108
|
-
globalCssConfig,
|
|
109
|
-
keyframes,
|
|
110
|
-
media,
|
|
111
|
-
mergedThemeMap,
|
|
112
|
-
preloadTheme,
|
|
113
|
-
sanitizedPrefix,
|
|
114
|
-
theme: themeObject,
|
|
115
|
-
utils,
|
|
116
|
-
// Internal values for React API creation
|
|
117
|
-
validatedTheme,
|
|
118
|
-
warmCache,
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
// Export createStoopBase for use in SSR entry point
|
|
122
|
-
// Note: This file does NOT export createStoop() - that's in create-stoop.ts
|
|
123
|
-
// This separation allows SSR entry point to avoid bundling React code
|
package/dist/inject.js
DELETED
|
@@ -1,308 +0,0 @@
|
|
|
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
|
-
import { MAX_CSS_CACHE_SIZE } from "./constants";
|
|
7
|
-
import { LRUCache, clearStyleCache } from "./core/cache";
|
|
8
|
-
import { isBrowser } from "./utils/helpers";
|
|
9
|
-
import { getRootRegex, sanitizePrefix } from "./utils/theme-utils";
|
|
10
|
-
// ============================================================================
|
|
11
|
-
// Internal Deduplication
|
|
12
|
-
// ============================================================================
|
|
13
|
-
const injectedRules = new Map();
|
|
14
|
-
/**
|
|
15
|
-
* Checks if a CSS rule has already been injected.
|
|
16
|
-
*
|
|
17
|
-
* @param key - Rule key to check
|
|
18
|
-
* @returns True if rule is already injected
|
|
19
|
-
*/
|
|
20
|
-
export function isInjectedRule(key) {
|
|
21
|
-
return injectedRules.has(key);
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Marks a CSS rule as injected.
|
|
25
|
-
*
|
|
26
|
-
* @param key - Rule key
|
|
27
|
-
* @param css - CSS string
|
|
28
|
-
*/
|
|
29
|
-
export function markRuleAsInjected(key, css) {
|
|
30
|
-
injectedRules.set(key, css);
|
|
31
|
-
}
|
|
32
|
-
// ============================================================================
|
|
33
|
-
// SSR Cache Management
|
|
34
|
-
// ============================================================================
|
|
35
|
-
// Use LRUCache for reliable FIFO eviction (Map iteration order not guaranteed)
|
|
36
|
-
const cssTextCache = new LRUCache(MAX_CSS_CACHE_SIZE);
|
|
37
|
-
/**
|
|
38
|
-
* Adds CSS to the SSR cache with LRU eviction.
|
|
39
|
-
*
|
|
40
|
-
* @param css - CSS string to cache
|
|
41
|
-
*/
|
|
42
|
-
export function addToSSRCache(css) {
|
|
43
|
-
if (!cssTextCache.has(css)) {
|
|
44
|
-
cssTextCache.set(css, true);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Gets all cached CSS text for SSR.
|
|
49
|
-
*
|
|
50
|
-
* @returns Joined CSS text string
|
|
51
|
-
*/
|
|
52
|
-
export function getSSRCacheText() {
|
|
53
|
-
return Array.from(cssTextCache.keys()).join("\n");
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Clears the SSR cache.
|
|
57
|
-
*/
|
|
58
|
-
export function clearSSRCache() {
|
|
59
|
-
cssTextCache.clear();
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Checks if CSS is already in the SSR cache.
|
|
63
|
-
*
|
|
64
|
-
* @param css - CSS string to check
|
|
65
|
-
* @returns True if CSS is cached
|
|
66
|
-
*/
|
|
67
|
-
export function isInSSRCache(css) {
|
|
68
|
-
return cssTextCache.has(css);
|
|
69
|
-
}
|
|
70
|
-
// ============================================================================
|
|
71
|
-
// Browser-Specific Injection
|
|
72
|
-
// ============================================================================
|
|
73
|
-
// Map of prefix -> stylesheet element to support multiple Stoop instances
|
|
74
|
-
const stylesheetElements = new Map();
|
|
75
|
-
const lastInjectedThemes = new Map();
|
|
76
|
-
const lastInjectedCSSVars = new Map();
|
|
77
|
-
/**
|
|
78
|
-
* Gets or creates the stylesheet element for CSS injection.
|
|
79
|
-
* Reuses the SSR stylesheet if it exists to prevent FOUC.
|
|
80
|
-
* Supports multiple Stoop instances with different prefixes.
|
|
81
|
-
*
|
|
82
|
-
* @param prefix - Optional prefix for stylesheet identification
|
|
83
|
-
* @returns HTMLStyleElement
|
|
84
|
-
* @throws Error if called in SSR context
|
|
85
|
-
*/
|
|
86
|
-
export function getStylesheet(prefix = "stoop") {
|
|
87
|
-
if (!isBrowser()) {
|
|
88
|
-
throw new Error("Cannot access document in SSR context");
|
|
89
|
-
}
|
|
90
|
-
const sanitizedPrefix = sanitizePrefix(prefix);
|
|
91
|
-
let stylesheetElement = stylesheetElements.get(sanitizedPrefix);
|
|
92
|
-
if (!stylesheetElement || !stylesheetElement.parentNode) {
|
|
93
|
-
// Check if SSR stylesheet exists and matches this prefix
|
|
94
|
-
const ssrStylesheet = document.getElementById("stoop-ssr");
|
|
95
|
-
if (ssrStylesheet) {
|
|
96
|
-
const existingPrefix = ssrStylesheet.getAttribute("data-stoop");
|
|
97
|
-
// Only reuse if prefix matches or no prefix set yet
|
|
98
|
-
if (!existingPrefix || existingPrefix === sanitizedPrefix) {
|
|
99
|
-
stylesheetElement = ssrStylesheet;
|
|
100
|
-
stylesheetElement.setAttribute("data-stoop", sanitizedPrefix);
|
|
101
|
-
stylesheetElements.set(sanitizedPrefix, stylesheetElement);
|
|
102
|
-
return stylesheetElement;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
// Create new stylesheet for this prefix
|
|
106
|
-
stylesheetElement = document.createElement("style");
|
|
107
|
-
stylesheetElement.setAttribute("data-stoop", sanitizedPrefix);
|
|
108
|
-
stylesheetElement.setAttribute("id", `stoop-${sanitizedPrefix}`);
|
|
109
|
-
document.head.appendChild(stylesheetElement);
|
|
110
|
-
stylesheetElements.set(sanitizedPrefix, stylesheetElement);
|
|
111
|
-
}
|
|
112
|
-
return stylesheetElement;
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Removes all theme variable blocks (both :root and attribute selectors) from CSS.
|
|
116
|
-
*
|
|
117
|
-
* @param css - CSS string to clean
|
|
118
|
-
* @returns CSS string without theme variable blocks
|
|
119
|
-
*/
|
|
120
|
-
export function removeThemeVariableBlocks(css) {
|
|
121
|
-
let result = css;
|
|
122
|
-
// Remove :root blocks using regex
|
|
123
|
-
const rootRegex = getRootRegex("");
|
|
124
|
-
result = result.replace(rootRegex, "").trim();
|
|
125
|
-
// Remove attribute selector blocks manually (handles nested braces)
|
|
126
|
-
let startIndex = result.indexOf("[data-theme=");
|
|
127
|
-
while (startIndex !== -1) {
|
|
128
|
-
const openBrace = result.indexOf("{", startIndex);
|
|
129
|
-
if (openBrace === -1) {
|
|
130
|
-
break;
|
|
131
|
-
}
|
|
132
|
-
let braceCount = 1;
|
|
133
|
-
let closeBrace = openBrace + 1;
|
|
134
|
-
while (closeBrace < result.length && braceCount > 0) {
|
|
135
|
-
if (result[closeBrace] === "{") {
|
|
136
|
-
braceCount++;
|
|
137
|
-
}
|
|
138
|
-
else if (result[closeBrace] === "}") {
|
|
139
|
-
braceCount--;
|
|
140
|
-
}
|
|
141
|
-
closeBrace++;
|
|
142
|
-
}
|
|
143
|
-
if (braceCount === 0) {
|
|
144
|
-
const before = result.substring(0, startIndex).trim();
|
|
145
|
-
const after = result.substring(closeBrace).trim();
|
|
146
|
-
result = (before + "\n" + after).trim();
|
|
147
|
-
}
|
|
148
|
-
else {
|
|
149
|
-
break;
|
|
150
|
-
}
|
|
151
|
-
startIndex = result.indexOf("[data-theme=");
|
|
152
|
-
}
|
|
153
|
-
return result.trim();
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* Injects CSS variables for all themes using attribute selectors.
|
|
157
|
-
* This allows all themes to be available simultaneously, with theme switching
|
|
158
|
-
* handled by changing the data-theme attribute.
|
|
159
|
-
*
|
|
160
|
-
* @param allThemeVars - CSS string containing all theme CSS variables
|
|
161
|
-
* @param prefix - Optional prefix for CSS variables
|
|
162
|
-
*/
|
|
163
|
-
export function injectAllThemeVariables(allThemeVars, prefix = "stoop") {
|
|
164
|
-
if (!allThemeVars) {
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
const sanitizedPrefix = sanitizePrefix(prefix);
|
|
168
|
-
const key = `__all_theme_vars_${sanitizedPrefix}`;
|
|
169
|
-
const lastCSSVars = lastInjectedCSSVars.get(key) ?? null;
|
|
170
|
-
// Only skip if CSS vars string is exactly the same
|
|
171
|
-
if (lastCSSVars === allThemeVars) {
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
lastInjectedCSSVars.set(key, allThemeVars);
|
|
175
|
-
if (!isBrowser()) {
|
|
176
|
-
addToSSRCache(allThemeVars);
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
const sheet = getStylesheet(sanitizedPrefix);
|
|
180
|
-
const currentCSS = sheet.textContent || "";
|
|
181
|
-
// Check if theme variable blocks exist
|
|
182
|
-
const hasThemeBlocks = currentCSS.includes(":root") || currentCSS.includes("[data-theme=");
|
|
183
|
-
if (isInjectedRule(key) || hasThemeBlocks) {
|
|
184
|
-
// Remove all existing theme variable blocks
|
|
185
|
-
const withoutVars = removeThemeVariableBlocks(currentCSS);
|
|
186
|
-
// Update stylesheet synchronously - prepend all theme vars, then append rest
|
|
187
|
-
sheet.textContent = allThemeVars + (withoutVars ? "\n\n" + withoutVars : "");
|
|
188
|
-
markRuleAsInjected(key, allThemeVars);
|
|
189
|
-
}
|
|
190
|
-
else {
|
|
191
|
-
// First injection - no existing theme blocks
|
|
192
|
-
sheet.textContent = allThemeVars + (currentCSS ? "\n\n" + currentCSS : "");
|
|
193
|
-
markRuleAsInjected(key, allThemeVars);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* Updates the stylesheet with new CSS rules.
|
|
198
|
-
*
|
|
199
|
-
* @param css - CSS string to inject
|
|
200
|
-
* @param ruleKey - Unique key for deduplication
|
|
201
|
-
* @param prefix - Optional prefix for CSS rules
|
|
202
|
-
*/
|
|
203
|
-
export function updateStylesheet(css, ruleKey, prefix = "stoop") {
|
|
204
|
-
if (!isBrowser()) {
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
const sanitizedPrefix = sanitizePrefix(prefix);
|
|
208
|
-
if (isInjectedRule(ruleKey)) {
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
const sheet = getStylesheet(sanitizedPrefix);
|
|
212
|
-
const currentCSS = sheet.textContent || "";
|
|
213
|
-
sheet.textContent = currentCSS + (currentCSS ? "\n" : "") + css;
|
|
214
|
-
markRuleAsInjected(ruleKey, css);
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Injects CSS into the browser stylesheet with deduplication.
|
|
218
|
-
*
|
|
219
|
-
* @param css - CSS string to inject
|
|
220
|
-
* @param ruleKey - Unique key for deduplication
|
|
221
|
-
* @param prefix - Optional prefix for CSS rules
|
|
222
|
-
*/
|
|
223
|
-
export function injectBrowserCSS(css, ruleKey, prefix = "stoop") {
|
|
224
|
-
if (isInjectedRule(ruleKey)) {
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
const sanitizedPrefix = sanitizePrefix(prefix);
|
|
228
|
-
updateStylesheet(css, ruleKey, sanitizedPrefix);
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* Gets the current stylesheet element for a given prefix.
|
|
232
|
-
*
|
|
233
|
-
* @param prefix - Optional prefix for stylesheet identification
|
|
234
|
-
* @returns HTMLStyleElement or null if not created
|
|
235
|
-
*/
|
|
236
|
-
export function getStylesheetElement(prefix = "stoop") {
|
|
237
|
-
const sanitizedPrefix = sanitizePrefix(prefix);
|
|
238
|
-
return stylesheetElements.get(sanitizedPrefix) || null;
|
|
239
|
-
}
|
|
240
|
-
/**
|
|
241
|
-
* Clears the stylesheet and all caches (internal).
|
|
242
|
-
*/
|
|
243
|
-
function clearStylesheetInternal() {
|
|
244
|
-
// Remove all stylesheet elements
|
|
245
|
-
for (const [, element] of stylesheetElements.entries()) {
|
|
246
|
-
if (element && element.parentNode) {
|
|
247
|
-
element.parentNode.removeChild(element);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
stylesheetElements.clear();
|
|
251
|
-
lastInjectedThemes.clear();
|
|
252
|
-
lastInjectedCSSVars.clear();
|
|
253
|
-
injectedRules.clear();
|
|
254
|
-
}
|
|
255
|
-
/**
|
|
256
|
-
* Gets all injected rules (for internal use).
|
|
257
|
-
*/
|
|
258
|
-
export function getAllInjectedRules() {
|
|
259
|
-
return new Map(injectedRules);
|
|
260
|
-
}
|
|
261
|
-
// ============================================================================
|
|
262
|
-
// Public API Functions
|
|
263
|
-
// ============================================================================
|
|
264
|
-
/**
|
|
265
|
-
* Injects CSS into the document with automatic SSR support.
|
|
266
|
-
*
|
|
267
|
-
* @param css - CSS string to inject
|
|
268
|
-
* @param prefix - Optional prefix for CSS rules
|
|
269
|
-
* @param ruleKey - Optional unique key for deduplication
|
|
270
|
-
*/
|
|
271
|
-
export function injectCSS(css, prefix = "stoop", ruleKey) {
|
|
272
|
-
const key = ruleKey || css;
|
|
273
|
-
if (!isBrowser()) {
|
|
274
|
-
if (!isInjectedRule(key)) {
|
|
275
|
-
markRuleAsInjected(key, css);
|
|
276
|
-
}
|
|
277
|
-
addToSSRCache(css);
|
|
278
|
-
return;
|
|
279
|
-
}
|
|
280
|
-
injectBrowserCSS(css, key, prefix);
|
|
281
|
-
}
|
|
282
|
-
/**
|
|
283
|
-
* Gets all injected CSS text (browser or SSR).
|
|
284
|
-
*
|
|
285
|
-
* @returns CSS text string
|
|
286
|
-
*/
|
|
287
|
-
export function getCssText(prefix = "stoop") {
|
|
288
|
-
if (isBrowser()) {
|
|
289
|
-
const sanitizedPrefix = sanitizePrefix(prefix);
|
|
290
|
-
const sheetElement = getStylesheetElement(sanitizedPrefix);
|
|
291
|
-
if (sheetElement && sheetElement.parentNode) {
|
|
292
|
-
const sheetCSS = sheetElement.textContent || "";
|
|
293
|
-
if (!sheetCSS && getAllInjectedRules().size > 0) {
|
|
294
|
-
return getSSRCacheText();
|
|
295
|
-
}
|
|
296
|
-
return sheetCSS;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
return getSSRCacheText();
|
|
300
|
-
}
|
|
301
|
-
/**
|
|
302
|
-
* Clears all injected CSS and caches.
|
|
303
|
-
*/
|
|
304
|
-
export function clearStylesheet() {
|
|
305
|
-
clearStylesheetInternal();
|
|
306
|
-
clearSSRCache();
|
|
307
|
-
clearStyleCache();
|
|
308
|
-
}
|
package/dist/types/index.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
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>;
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
/**
|
|
3
|
-
* Auto-preloading utilities for cache warming and theme preloading.
|
|
4
|
-
* Helps eliminate FOUC (Flash of Unstyled Content) by pre-compiling styles and preloading themes.
|
|
5
|
-
*/
|
|
6
|
-
import { detectTheme, detectThemeForSSR } from "./storage";
|
|
7
|
-
/**
|
|
8
|
-
* Common UI component styles that are frequently used.
|
|
9
|
-
* These represent typical design system patterns.
|
|
10
|
-
*/
|
|
11
|
-
export const COMMON_UI_STYLES = [
|
|
12
|
-
// Layout primitives
|
|
13
|
-
{ alignItems: "center", display: "flex", justifyContent: "center" },
|
|
14
|
-
{ display: "flex", flexDirection: "column" },
|
|
15
|
-
{ position: "relative" },
|
|
16
|
-
// Spacing utilities
|
|
17
|
-
{ padding: "$small" },
|
|
18
|
-
{ padding: "$medium" },
|
|
19
|
-
{ padding: "$large" },
|
|
20
|
-
{ margin: "$small" },
|
|
21
|
-
{ margin: "$medium" },
|
|
22
|
-
{ margin: "$large" },
|
|
23
|
-
// Typography
|
|
24
|
-
{ fontSize: "$small" },
|
|
25
|
-
{ fontSize: "$medium" },
|
|
26
|
-
{ fontSize: "$large" },
|
|
27
|
-
{ fontWeight: "$normal" },
|
|
28
|
-
{ fontWeight: "$bold" },
|
|
29
|
-
// Colors (using theme tokens)
|
|
30
|
-
{ color: "$text" },
|
|
31
|
-
{ color: "$textSecondary" },
|
|
32
|
-
{ backgroundColor: "$surface" },
|
|
33
|
-
{ backgroundColor: "$surfaceHover" },
|
|
34
|
-
{ border: "1px solid $border" },
|
|
35
|
-
{ borderColor: "$border" },
|
|
36
|
-
// Interactive states
|
|
37
|
-
{ cursor: "pointer" },
|
|
38
|
-
{ opacity: 0.5 },
|
|
39
|
-
{ opacity: 0.7 },
|
|
40
|
-
// Positioning
|
|
41
|
-
{ bottom: 0, left: 0, right: 0, top: 0 },
|
|
42
|
-
{ height: "100%", width: "100%" },
|
|
43
|
-
// Borders and radii
|
|
44
|
-
{ borderRadius: "$small" },
|
|
45
|
-
{ borderRadius: "$medium" },
|
|
46
|
-
{ borderRadius: "$large" },
|
|
47
|
-
];
|
|
48
|
-
/**
|
|
49
|
-
* Automatically warms the cache with common styles.
|
|
50
|
-
*
|
|
51
|
-
* @param warmCacheFn - The warmCache function from Stoop instance
|
|
52
|
-
* @param styles - Styles to warm (defaults to COMMON_UI_STYLES)
|
|
53
|
-
* @returns Promise that resolves when warming is complete
|
|
54
|
-
*/
|
|
55
|
-
export async function autoWarmCache(warmCacheFn, styles = COMMON_UI_STYLES) {
|
|
56
|
-
// Warm cache asynchronously to avoid blocking
|
|
57
|
-
return new Promise((resolve) => {
|
|
58
|
-
setTimeout(() => {
|
|
59
|
-
try {
|
|
60
|
-
warmCacheFn(styles);
|
|
61
|
-
resolve();
|
|
62
|
-
}
|
|
63
|
-
catch (error) {
|
|
64
|
-
// Silently fail - cache warming is not critical
|
|
65
|
-
console.warn("[Stoop] Cache warming failed:", error);
|
|
66
|
-
resolve();
|
|
67
|
-
}
|
|
68
|
-
}, 0);
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Automatically preloads a detected theme.
|
|
73
|
-
*
|
|
74
|
-
* @param preloadThemeFn - The preloadTheme function from Stoop instance
|
|
75
|
-
* @param options - Theme detection options
|
|
76
|
-
* @param ssr - Whether running in SSR context
|
|
77
|
-
* @returns Promise that resolves when preloading is complete
|
|
78
|
-
*/
|
|
79
|
-
export async function autoPreloadTheme(preloadThemeFn, options = {}, ssr = false) {
|
|
80
|
-
return new Promise((resolve) => {
|
|
81
|
-
setTimeout(() => {
|
|
82
|
-
try {
|
|
83
|
-
if (ssr) {
|
|
84
|
-
const themeName = detectThemeForSSR(options);
|
|
85
|
-
if (themeName && themeName !== options.default) {
|
|
86
|
-
preloadThemeFn(themeName);
|
|
87
|
-
}
|
|
88
|
-
resolve({
|
|
89
|
-
confidence: 0.3,
|
|
90
|
-
source: "default",
|
|
91
|
-
theme: themeName,
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
const detection = detectTheme(options);
|
|
96
|
-
if (detection.theme) {
|
|
97
|
-
preloadThemeFn(detection.theme);
|
|
98
|
-
}
|
|
99
|
-
resolve(detection);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
catch (error) {
|
|
103
|
-
console.warn("[Stoop] Theme preloading failed:", error);
|
|
104
|
-
resolve({
|
|
105
|
-
confidence: 0.3,
|
|
106
|
-
source: "default",
|
|
107
|
-
theme: options.default || "light",
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
}, 0);
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Performs automatic preloading operations based on configuration.
|
|
115
|
-
*
|
|
116
|
-
* @param warmCacheFn - The warmCache function from Stoop instance
|
|
117
|
-
* @param preloadThemeFn - The preloadTheme function from Stoop instance
|
|
118
|
-
* @param options - Auto-preload options
|
|
119
|
-
* @returns Promise that resolves with preload results
|
|
120
|
-
*/
|
|
121
|
-
export async function autoPreload(warmCacheFn, preloadThemeFn, options = {}) {
|
|
122
|
-
const { commonStyles = COMMON_UI_STYLES, enableCacheWarm = true, enableThemePreload = true, ssr = false, themeDetection = {}, } = options;
|
|
123
|
-
const result = {
|
|
124
|
-
cacheWarmed: false,
|
|
125
|
-
errors: [],
|
|
126
|
-
themeDetection: { confidence: 0.3, source: "default", theme: "light" },
|
|
127
|
-
themePreloaded: false,
|
|
128
|
-
};
|
|
129
|
-
const operations = [];
|
|
130
|
-
// Auto-warm cache
|
|
131
|
-
if (enableCacheWarm && commonStyles.length > 0) {
|
|
132
|
-
operations.push(autoWarmCache(warmCacheFn, commonStyles)
|
|
133
|
-
.then(() => {
|
|
134
|
-
result.cacheWarmed = true;
|
|
135
|
-
})
|
|
136
|
-
.catch((error) => {
|
|
137
|
-
result.errors.push(`Cache warming failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
138
|
-
}));
|
|
139
|
-
}
|
|
140
|
-
// Auto-preload theme
|
|
141
|
-
if (enableThemePreload) {
|
|
142
|
-
operations.push(autoPreloadTheme(preloadThemeFn, themeDetection, ssr)
|
|
143
|
-
.then((detection) => {
|
|
144
|
-
result.themeDetection = detection;
|
|
145
|
-
result.themePreloaded = true;
|
|
146
|
-
})
|
|
147
|
-
.catch((error) => {
|
|
148
|
-
result.errors.push(`Theme preloading failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
149
|
-
}));
|
|
150
|
-
}
|
|
151
|
-
// Wait for all operations to complete
|
|
152
|
-
await Promise.allSettled(operations);
|
|
153
|
-
return result;
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* Creates an auto-preloader with pre-configured options.
|
|
157
|
-
*
|
|
158
|
-
* @param warmCacheFn - The warmCache function from Stoop instance
|
|
159
|
-
* @param preloadThemeFn - The preloadTheme function from Stoop instance
|
|
160
|
-
* @param defaultOptions - Default auto-preload options
|
|
161
|
-
* @returns Auto-preloader function
|
|
162
|
-
*/
|
|
163
|
-
export function createAutoPreloader(warmCacheFn, preloadThemeFn, defaultOptions = {}) {
|
|
164
|
-
return (options = {}) => {
|
|
165
|
-
return autoPreload(warmCacheFn, preloadThemeFn, { ...defaultOptions, ...options });
|
|
166
|
-
};
|
|
167
|
-
}
|