stoop 0.2.1 → 0.4.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.
Files changed (56) hide show
  1. package/README.md +48 -103
  2. package/dist/api/core-api.d.ts +34 -0
  3. package/dist/api/core-api.js +135 -0
  4. package/dist/api/global-css.d.ts +0 -11
  5. package/dist/api/global-css.js +42 -0
  6. package/dist/api/styled.d.ts +0 -1
  7. package/dist/api/styled.js +419 -0
  8. package/dist/api/theme-provider.d.ts +41 -0
  9. package/dist/api/theme-provider.js +223 -0
  10. package/dist/constants.d.ts +13 -4
  11. package/dist/constants.js +154 -0
  12. package/dist/core/cache.d.ts +5 -9
  13. package/dist/core/cache.js +68 -0
  14. package/dist/core/compiler.d.ts +11 -0
  15. package/dist/core/compiler.js +206 -0
  16. package/dist/core/theme-manager.d.ts +27 -4
  17. package/dist/core/theme-manager.js +107 -0
  18. package/dist/core/variants.js +38 -0
  19. package/dist/create-stoop-internal.d.ts +30 -0
  20. package/dist/create-stoop-internal.js +123 -0
  21. package/dist/create-stoop-ssr.d.ts +10 -0
  22. package/dist/create-stoop-ssr.js +26 -0
  23. package/dist/create-stoop.d.ts +32 -4
  24. package/dist/create-stoop.js +156 -0
  25. package/dist/inject.d.ts +113 -0
  26. package/dist/inject.js +308 -0
  27. package/dist/types/index.d.ts +157 -17
  28. package/dist/types/index.js +5 -0
  29. package/dist/types/react-polymorphic-types.d.ts +15 -8
  30. package/dist/utils/auto-preload.d.ts +45 -0
  31. package/dist/utils/auto-preload.js +167 -0
  32. package/dist/utils/helpers.d.ts +64 -0
  33. package/dist/utils/helpers.js +150 -0
  34. package/dist/utils/storage.d.ts +148 -0
  35. package/dist/utils/storage.js +396 -0
  36. package/dist/utils/{string.d.ts → theme-utils.d.ts} +36 -12
  37. package/dist/utils/theme-utils.js +353 -0
  38. package/dist/utils/theme.d.ts +17 -5
  39. package/dist/utils/theme.js +304 -0
  40. package/package.json +48 -24
  41. package/LICENSE.md +0 -21
  42. package/dist/api/create-theme.d.ts +0 -13
  43. package/dist/api/css.d.ts +0 -16
  44. package/dist/api/keyframes.d.ts +0 -16
  45. package/dist/api/provider.d.ts +0 -19
  46. package/dist/api/use-theme.d.ts +0 -13
  47. package/dist/index.d.ts +0 -6
  48. package/dist/index.js +0 -13
  49. package/dist/inject/browser.d.ts +0 -59
  50. package/dist/inject/dedup.d.ts +0 -29
  51. package/dist/inject/index.d.ts +0 -41
  52. package/dist/inject/ssr.d.ts +0 -28
  53. package/dist/utils/theme-map.d.ts +0 -25
  54. package/dist/utils/theme-validation.d.ts +0 -13
  55. package/dist/utils/type-guards.d.ts +0 -26
  56. package/dist/utils/utilities.d.ts +0 -14
@@ -0,0 +1,167 @@
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
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Helper utilities for Stoop.
3
+ * Consolidates environment detection, type guards, theme validation, and utility function application.
4
+ */
5
+ import type { CSS, DefaultTheme, StyledComponentRef, Theme, UtilityFunction } from "../types";
6
+ /**
7
+ * Checks if code is running in a browser environment.
8
+ *
9
+ * @returns True if running in browser, false if in SSR/Node environment
10
+ */
11
+ export declare function isBrowser(): boolean;
12
+ /**
13
+ * Checks if running in production mode.
14
+ * Extracted to helper function for consistency.
15
+ *
16
+ * @returns True if running in production mode
17
+ */
18
+ export declare function isProduction(): boolean;
19
+ /**
20
+ * Type guard for CSS objects.
21
+ *
22
+ * @param value - Value to check
23
+ * @returns True if value is a CSS object
24
+ */
25
+ export declare function isCSSObject(value: unknown): value is CSS;
26
+ /**
27
+ * Checks if a value is a styled component reference.
28
+ * Consolidated function used across the codebase.
29
+ *
30
+ * @param value - Value to check
31
+ * @returns True if value is a styled component reference
32
+ */
33
+ export declare function isStyledComponentRef(value: unknown): value is StyledComponentRef;
34
+ /**
35
+ * Type guard for valid CSS objects (excludes styled component references).
36
+ *
37
+ * @param value - Value to check
38
+ * @returns True if value is a valid CSS object
39
+ */
40
+ export declare function isValidCSSObject(value: unknown): value is CSS;
41
+ /**
42
+ * Type guard for theme objects.
43
+ *
44
+ * @param value - Value to check
45
+ * @returns True if value is a theme object
46
+ */
47
+ export declare function isThemeObject(value: unknown): value is Theme;
48
+ /**
49
+ * Validates that a theme object only contains approved scales.
50
+ * In production, skips all validation for performance.
51
+ *
52
+ * @param theme - Theme object to validate
53
+ * @returns Validated theme as DefaultTheme
54
+ * @throws Error if theme contains invalid scales (development only)
55
+ */
56
+ export declare function validateTheme(theme: unknown): DefaultTheme;
57
+ /**
58
+ * Applies utility functions to transform shorthand properties into CSS.
59
+ *
60
+ * @param styles - CSS object to process
61
+ * @param utils - Optional utility functions object
62
+ * @returns CSS object with utilities applied
63
+ */
64
+ export declare function applyUtilities(styles: CSS, utils?: Record<string, UtilityFunction>): CSS;
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Helper utilities for Stoop.
3
+ * Consolidates environment detection, type guards, theme validation, and utility function application.
4
+ */
5
+ import { APPROVED_THEME_SCALES } from "../constants";
6
+ // ============================================================================
7
+ // Environment Detection
8
+ // ============================================================================
9
+ /**
10
+ * Checks if code is running in a browser environment.
11
+ *
12
+ * @returns True if running in browser, false if in SSR/Node environment
13
+ */
14
+ export function isBrowser() {
15
+ return (typeof window !== "undefined" &&
16
+ typeof document !== "undefined" &&
17
+ typeof window.document === "object" &&
18
+ // Use document.createElement instead of requestAnimationFrame for better compatibility
19
+ // requestAnimationFrame may not exist in test environments (jsdom)
20
+ typeof document.createElement === "function");
21
+ }
22
+ /**
23
+ * Checks if running in production mode.
24
+ * Extracted to helper function for consistency.
25
+ *
26
+ * @returns True if running in production mode
27
+ */
28
+ export function isProduction() {
29
+ return typeof process !== "undefined" && process.env?.NODE_ENV === "production";
30
+ }
31
+ // ============================================================================
32
+ // Type Guards
33
+ // ============================================================================
34
+ /**
35
+ * Type guard for CSS objects.
36
+ *
37
+ * @param value - Value to check
38
+ * @returns True if value is a CSS object
39
+ */
40
+ export function isCSSObject(value) {
41
+ return typeof value === "object" && value !== null;
42
+ }
43
+ /**
44
+ * Checks if a value is a styled component reference.
45
+ * Consolidated function used across the codebase.
46
+ *
47
+ * @param value - Value to check
48
+ * @returns True if value is a styled component reference
49
+ */
50
+ export function isStyledComponentRef(value) {
51
+ return (typeof value === "object" &&
52
+ value !== null &&
53
+ "__isStoopStyled" in value &&
54
+ "__stoopClassName" in value &&
55
+ value.__isStoopStyled === true);
56
+ }
57
+ /**
58
+ * Type guard for valid CSS objects (excludes styled component references).
59
+ *
60
+ * @param value - Value to check
61
+ * @returns True if value is a valid CSS object
62
+ */
63
+ export function isValidCSSObject(value) {
64
+ return isCSSObject(value) && !isStyledComponentRef(value);
65
+ }
66
+ /**
67
+ * Type guard for theme objects.
68
+ *
69
+ * @param value - Value to check
70
+ * @returns True if value is a theme object
71
+ */
72
+ export function isThemeObject(value) {
73
+ return typeof value === "object" && value !== null && !Array.isArray(value);
74
+ }
75
+ // ============================================================================
76
+ // Theme Validation
77
+ // ============================================================================
78
+ /**
79
+ * Validates that a theme object only contains approved scales.
80
+ * In production, skips all validation for performance.
81
+ *
82
+ * @param theme - Theme object to validate
83
+ * @returns Validated theme as DefaultTheme
84
+ * @throws Error if theme contains invalid scales (development only)
85
+ */
86
+ export function validateTheme(theme) {
87
+ if (!theme || typeof theme !== "object" || Array.isArray(theme)) {
88
+ throw new Error("[Stoop] Theme must be a non-null object");
89
+ }
90
+ // Skip all validation in production for performance
91
+ if (isProduction()) {
92
+ return theme;
93
+ }
94
+ const themeObj = theme;
95
+ const invalidScales = [];
96
+ for (const key in themeObj) {
97
+ if (key === "media") {
98
+ continue;
99
+ }
100
+ if (!APPROVED_THEME_SCALES.includes(key)) {
101
+ invalidScales.push(key);
102
+ }
103
+ }
104
+ if (invalidScales.length > 0) {
105
+ const errorMessage = `[Stoop] Theme contains invalid scales: ${invalidScales.join(", ")}. ` +
106
+ `Only these scales are allowed: ${APPROVED_THEME_SCALES.join(", ")}`;
107
+ throw new Error(errorMessage);
108
+ }
109
+ return theme;
110
+ }
111
+ // ============================================================================
112
+ // Utility Function Application
113
+ // ============================================================================
114
+ /**
115
+ * Applies utility functions to transform shorthand properties into CSS.
116
+ *
117
+ * @param styles - CSS object to process
118
+ * @param utils - Optional utility functions object
119
+ * @returns CSS object with utilities applied
120
+ */
121
+ export function applyUtilities(styles, utils) {
122
+ if (!utils || !styles || typeof styles !== "object") {
123
+ return styles;
124
+ }
125
+ const result = {};
126
+ const utilityKeys = Object.keys(utils);
127
+ for (const key in styles) {
128
+ const value = styles[key];
129
+ if (utilityKeys.includes(key) && utils[key]) {
130
+ try {
131
+ const utilityResult = utils[key](value);
132
+ if (utilityResult && typeof utilityResult === "object") {
133
+ for (const utilKey in utilityResult) {
134
+ result[utilKey] = utilityResult[utilKey];
135
+ }
136
+ }
137
+ }
138
+ catch {
139
+ result[key] = value;
140
+ }
141
+ }
142
+ else if (isCSSObject(value)) {
143
+ result[key] = applyUtilities(value, utils);
144
+ }
145
+ else {
146
+ result[key] = value;
147
+ }
148
+ }
149
+ return result;
150
+ }
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Storage and theme detection utilities.
3
+ * Provides simplified localStorage and cookie management, plus automatic theme selection.
4
+ * Supports SSR compatibility and error handling.
5
+ */
6
+ import type { ThemeDetectionOptions, ThemeDetectionResult, StorageOptions, StorageResult } from "../types";
7
+ /**
8
+ * Safely gets a value from localStorage.
9
+ *
10
+ * @param key - Storage key
11
+ * @returns Storage result
12
+ */
13
+ export declare function getFromStorage(key: string): StorageResult<string | null>;
14
+ /**
15
+ * Safely sets a value in localStorage.
16
+ *
17
+ * @param key - Storage key
18
+ * @param value - Value to store
19
+ * @returns Storage result
20
+ */
21
+ export declare function setInStorage(key: string, value: string): StorageResult<void>;
22
+ /**
23
+ * Safely removes a value from localStorage.
24
+ *
25
+ * @param key - Storage key
26
+ * @returns Storage result
27
+ */
28
+ export declare function removeFromStorage(key: string): StorageResult<void>;
29
+ /**
30
+ * Gets a cookie value.
31
+ *
32
+ * @param name - Cookie name
33
+ * @returns Cookie value or null if not found
34
+ */
35
+ export declare function getCookie(name: string): string | null;
36
+ /**
37
+ * Sets a cookie value.
38
+ *
39
+ * @param name - Cookie name
40
+ * @param value - Cookie value
41
+ * @param options - Cookie options
42
+ * @returns Success status
43
+ */
44
+ export declare function setCookie(name: string, value: string, options?: Omit<StorageOptions, "type"> & {
45
+ maxAge?: number;
46
+ path?: string;
47
+ secure?: boolean;
48
+ }): boolean;
49
+ /**
50
+ * Removes a cookie by setting it to expire.
51
+ *
52
+ * @param name - Cookie name
53
+ * @param path - Cookie path
54
+ * @returns Success status
55
+ */
56
+ export declare function removeCookie(name: string, path?: string): boolean;
57
+ /**
58
+ * Unified storage API that works with both localStorage and cookies.
59
+ *
60
+ * @param key - Storage key
61
+ * @param options - Storage options
62
+ * @returns Storage result
63
+ */
64
+ export declare function getStorage(key: string, options?: StorageOptions): StorageResult<string | null>;
65
+ /**
66
+ * Unified storage API that works with both localStorage and cookies.
67
+ *
68
+ * @param key - Storage key
69
+ * @param value - Value to store
70
+ * @param options - Storage options
71
+ * @returns Storage result
72
+ */
73
+ export declare function setStorage(key: string, value: string, options?: StorageOptions): StorageResult<void>;
74
+ /**
75
+ * Unified storage API that works with both localStorage and cookies.
76
+ *
77
+ * @param key - Storage key
78
+ * @param options - Storage options
79
+ * @returns Storage result
80
+ */
81
+ export declare function removeStorage(key: string, options?: StorageOptions): StorageResult<void>;
82
+ /**
83
+ * Gets a JSON value from storage with automatic parsing.
84
+ *
85
+ * @param key - Storage key
86
+ * @param fallback - Fallback value if parsing fails or key not found
87
+ * @param options - Storage options
88
+ * @returns Parsed JSON value or fallback
89
+ */
90
+ export declare function getJsonFromStorage<T>(key: string, fallback: T, options?: StorageOptions): StorageResult<T>;
91
+ /**
92
+ * Sets a JSON value in storage with automatic serialization.
93
+ *
94
+ * @param key - Storage key
95
+ * @param value - Value to serialize and store
96
+ * @param options - Storage options
97
+ * @returns Storage result
98
+ */
99
+ export declare function setJsonInStorage<T>(key: string, value: T, options?: StorageOptions): StorageResult<void>;
100
+ /**
101
+ * Creates a typed storage interface for a specific key.
102
+ *
103
+ * @param key - Storage key
104
+ * @param options - Storage options
105
+ * @returns Typed storage interface
106
+ */
107
+ export declare function createStorage<T = string>(key: string, options?: StorageOptions): {
108
+ get: () => StorageResult<string | null>;
109
+ getJson: (fallback: T) => StorageResult<T>;
110
+ remove: () => StorageResult<void>;
111
+ set: (value: string) => StorageResult<void>;
112
+ setJson: (value: T) => StorageResult<void>;
113
+ };
114
+ /**
115
+ * Detects the best theme to use based on multiple sources with priority.
116
+ *
117
+ * Priority order (highest to lowest):
118
+ * 1. Explicit localStorage preference
119
+ * 2. Cookie preference (for SSR compatibility)
120
+ * 3. System color scheme preference
121
+ * 4. Default theme
122
+ *
123
+ * @param options - Theme detection options
124
+ * @returns Theme detection result
125
+ */
126
+ export declare function detectTheme(options?: ThemeDetectionOptions): ThemeDetectionResult;
127
+ /**
128
+ * Creates a theme detector function with pre-configured options.
129
+ *
130
+ * @param options - Theme detection options
131
+ * @returns Theme detection function
132
+ */
133
+ export declare function createThemeDetector(options: ThemeDetectionOptions): () => ThemeDetectionResult;
134
+ /**
135
+ * Auto-detects theme for SSR contexts (server-side or during hydration).
136
+ * Uses only cookie and default sources since localStorage isn't available.
137
+ *
138
+ * @param options - Theme detection options
139
+ * @returns Theme name
140
+ */
141
+ export declare function detectThemeForSSR(options?: ThemeDetectionOptions): string;
142
+ /**
143
+ * Listens for system theme changes and calls callback when changed.
144
+ *
145
+ * @param callback - Function to call when system theme changes
146
+ * @returns Cleanup function
147
+ */
148
+ export declare function onSystemThemeChange(callback: (theme: "dark" | "light") => void): () => void;