stoop 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +125 -0
  2. package/dist/api/core-api.d.ts +34 -0
  3. package/dist/api/styled.d.ts +0 -1
  4. package/dist/api/theme-provider.d.ts +41 -0
  5. package/dist/constants.d.ts +11 -1
  6. package/dist/core/compiler.d.ts +11 -0
  7. package/dist/core/theme-manager.d.ts +34 -3
  8. package/dist/create-stoop-internal.d.ts +30 -0
  9. package/dist/create-stoop-ssr.d.ts +10 -0
  10. package/dist/create-stoop-ssr.js +16 -0
  11. package/dist/create-stoop.d.ts +32 -1
  12. package/dist/create-stoop.js +16 -147
  13. package/dist/inject.d.ts +113 -0
  14. package/dist/types/index.d.ts +147 -12
  15. package/dist/types/react-polymorphic-types.d.ts +13 -2
  16. package/dist/utils/auto-preload.d.ts +45 -0
  17. package/dist/utils/helpers.d.ts +64 -0
  18. package/dist/utils/storage.d.ts +148 -0
  19. package/dist/utils/{string.d.ts → theme-utils.d.ts} +20 -3
  20. package/dist/utils/theme.d.ts +14 -2
  21. package/package.json +44 -17
  22. package/dist/api/create-theme.d.ts +0 -13
  23. package/dist/api/create-theme.js +0 -43
  24. package/dist/api/css.d.ts +0 -16
  25. package/dist/api/css.js +0 -20
  26. package/dist/api/global-css.js +0 -89
  27. package/dist/api/keyframes.d.ts +0 -16
  28. package/dist/api/keyframes.js +0 -95
  29. package/dist/api/provider.d.ts +0 -19
  30. package/dist/api/provider.js +0 -109
  31. package/dist/api/styled.js +0 -170
  32. package/dist/api/use-theme.d.ts +0 -13
  33. package/dist/api/use-theme.js +0 -21
  34. package/dist/constants.js +0 -144
  35. package/dist/core/cache.js +0 -68
  36. package/dist/core/compiler.js +0 -198
  37. package/dist/core/theme-manager.js +0 -97
  38. package/dist/core/variants.js +0 -32
  39. package/dist/create-stoop-server.d.ts +0 -33
  40. package/dist/create-stoop-server.js +0 -130
  41. package/dist/index.d.ts +0 -6
  42. package/dist/index.js +0 -5
  43. package/dist/inject/browser.d.ts +0 -58
  44. package/dist/inject/browser.js +0 -149
  45. package/dist/inject/dedup.d.ts +0 -29
  46. package/dist/inject/dedup.js +0 -38
  47. package/dist/inject/index.d.ts +0 -40
  48. package/dist/inject/index.js +0 -75
  49. package/dist/inject/ssr.d.ts +0 -27
  50. package/dist/inject/ssr.js +0 -46
  51. package/dist/ssr.d.ts +0 -21
  52. package/dist/ssr.js +0 -19
  53. package/dist/types/index.js +0 -5
  54. package/dist/utils/environment.d.ts +0 -6
  55. package/dist/utils/environment.js +0 -12
  56. package/dist/utils/string.js +0 -253
  57. package/dist/utils/theme-map.d.ts +0 -22
  58. package/dist/utils/theme-map.js +0 -97
  59. package/dist/utils/theme-validation.d.ts +0 -13
  60. package/dist/utils/theme-validation.js +0 -36
  61. package/dist/utils/theme.js +0 -279
  62. package/dist/utils/type-guards.d.ts +0 -26
  63. package/dist/utils/type-guards.js +0 -38
  64. package/dist/utils/utilities.d.ts +0 -14
  65. package/dist/utils/utilities.js +0 -43
@@ -1,279 +0,0 @@
1
- /**
2
- * Theme token resolution utilities.
3
- * Converts theme tokens to CSS variables for runtime theme switching.
4
- * Uses cached token index for efficient lookups and theme comparison.
5
- */
6
- import { escapeCSSVariableValue, sanitizeCSSVariableName } from "./string";
7
- import { getScaleForProperty } from "./theme-map";
8
- import { isCSSObject, isThemeObject } from "./type-guards";
9
- const tokenIndexCache = new WeakMap();
10
- // Pre-compiled regex for token replacement (matches $primary, -$medium, $colors.primary, etc.)
11
- const TOKEN_REGEX = /(-?\$[a-zA-Z][a-zA-Z0-9]*(?:\$[a-zA-Z][a-zA-Z0-9]*)?(?:\.[a-zA-Z][a-zA-Z0-9]*)?)/g;
12
- /**
13
- * Builds an index of all tokens in a theme for fast lookups.
14
- * Caches the result to avoid rebuilding on every token resolution.
15
- *
16
- * @param theme - Theme to index
17
- * @returns Map of token names to their paths in the theme
18
- */
19
- function buildTokenIndex(theme) {
20
- const cached = tokenIndexCache.get(theme);
21
- if (cached) {
22
- return cached;
23
- }
24
- const index = new Map();
25
- function processThemeObject(obj, path = []) {
26
- const keys = Object.keys(obj);
27
- for (const key of keys) {
28
- const value = obj[key];
29
- const currentPath = [...path, key];
30
- if (isThemeObject(value)) {
31
- processThemeObject(value, currentPath);
32
- }
33
- else {
34
- const existing = index.get(key);
35
- if (existing) {
36
- existing.push(currentPath);
37
- }
38
- else {
39
- index.set(key, [currentPath]);
40
- }
41
- }
42
- }
43
- }
44
- processThemeObject(theme);
45
- for (const [, paths] of index.entries()) {
46
- if (paths.length > 1) {
47
- paths.sort((a, b) => {
48
- const depthDiff = a.length - b.length;
49
- if (depthDiff !== 0) {
50
- return depthDiff;
51
- }
52
- const pathA = a.join(".");
53
- const pathB = b.join(".");
54
- return pathA.localeCompare(pathB);
55
- });
56
- }
57
- }
58
- tokenIndexCache.set(theme, index);
59
- return index;
60
- }
61
- /**
62
- * Checks if two themes have the same top-level keys (excluding 'media').
63
- *
64
- * @param theme1 - First theme
65
- * @param theme2 - Second theme
66
- * @returns True if themes have same keys
67
- */
68
- function themesHaveSameKeys(theme1, theme2) {
69
- const keys1 = Object.keys(theme1).filter((key) => key !== "media");
70
- const keys2 = Object.keys(theme2).filter((key) => key !== "media");
71
- if (keys1.length !== keys2.length) {
72
- return false;
73
- }
74
- for (const key of keys1) {
75
- if (!(key in theme2)) {
76
- return false;
77
- }
78
- }
79
- return true;
80
- }
81
- /**
82
- * Compares two themes for structural and value equality.
83
- * Excludes 'media' property from comparison.
84
- *
85
- * @param theme1 - First theme to compare
86
- * @param theme2 - Second theme to compare
87
- * @returns True if themes are equal
88
- */
89
- export function themesAreEqual(theme1, theme2) {
90
- if (theme1 === theme2) {
91
- return true;
92
- }
93
- if (!theme1 || !theme2) {
94
- return false;
95
- }
96
- if (!themesHaveSameKeys(theme1, theme2)) {
97
- return false;
98
- }
99
- const theme1WithoutMedia = { ...theme1 };
100
- const theme2WithoutMedia = { ...theme2 };
101
- delete theme1WithoutMedia.media;
102
- delete theme2WithoutMedia.media;
103
- return JSON.stringify(theme1WithoutMedia) === JSON.stringify(theme2WithoutMedia);
104
- }
105
- /**
106
- * Finds a token in the theme, optionally scoped to a specific scale.
107
- *
108
- * @param theme - Theme to search
109
- * @param tokenName - Token name to find
110
- * @param scale - Optional scale to search within first
111
- * @returns Path to token or null if not found
112
- */
113
- function findTokenInTheme(theme, tokenName, scale) {
114
- if (scale && scale in theme) {
115
- const scaleValue = theme[scale];
116
- if (scaleValue &&
117
- typeof scaleValue === "object" &&
118
- !Array.isArray(scaleValue) &&
119
- tokenName in scaleValue) {
120
- return [scale, tokenName];
121
- }
122
- }
123
- const index = buildTokenIndex(theme);
124
- const paths = index.get(tokenName);
125
- if (!paths || paths.length === 0) {
126
- return null;
127
- }
128
- return paths[0];
129
- }
130
- /**
131
- * Converts a theme token string to a CSS variable reference.
132
- *
133
- * @param token - Token string (e.g., "$primary" or "$colors$primary")
134
- * @param theme - Optional theme for token resolution
135
- * @param property - Optional CSS property name for scale detection
136
- * @param themeMap - Optional theme scale mappings
137
- * @returns CSS variable reference string
138
- */
139
- export function tokenToCSSVar(token, theme, property, themeMap) {
140
- if (!token.startsWith("$")) {
141
- return token;
142
- }
143
- const tokenName = token.slice(1);
144
- // Handle explicit scale: $colors$primary or $colors.primary
145
- if (tokenName.includes("$") || tokenName.includes(".")) {
146
- const parts = tokenName.includes("$") ? tokenName.split("$") : tokenName.split(".");
147
- const sanitizedParts = parts.map((part) => sanitizeCSSVariableName(part));
148
- const cssVarName = `--${sanitizedParts.join("-")}`;
149
- return `var(${cssVarName})`;
150
- }
151
- // Handle shorthand token: $primary
152
- if (theme && property) {
153
- const scale = getScaleForProperty(property, themeMap);
154
- if (scale) {
155
- const foundPath = findTokenInTheme(theme, tokenName, scale);
156
- if (foundPath) {
157
- const sanitizedParts = foundPath.map((part) => sanitizeCSSVariableName(part));
158
- const cssVarName = `--${sanitizedParts.join("-")}`;
159
- return `var(${cssVarName})`;
160
- }
161
- }
162
- const index = buildTokenIndex(theme);
163
- const paths = index.get(tokenName);
164
- if (paths && paths.length > 1) {
165
- if (typeof process !== "undefined" && process.env?.NODE_ENV !== "production") {
166
- const scaleInfo = scale
167
- ? `Property "${property}" maps to "${scale}" scale, but token not found there. `
168
- : `No scale mapping found for property "${property}". `;
169
- // eslint-disable-next-line no-console
170
- console.warn(`[Stoop] Ambiguous token "$${tokenName}" found in multiple categories: ${paths.map((p) => p.join(".")).join(", ")}. ` +
171
- `${scaleInfo}` +
172
- `Using "${paths[0].join(".")}" (deterministic: shorter paths first, then alphabetical). ` +
173
- `Use full path "$${paths[0].join(".")}" to be explicit.`);
174
- }
175
- }
176
- const foundPath = findTokenInTheme(theme, tokenName);
177
- if (foundPath) {
178
- const sanitizedParts = foundPath.map((part) => sanitizeCSSVariableName(part));
179
- const cssVarName = `--${sanitizedParts.join("-")}`;
180
- return `var(${cssVarName})`;
181
- }
182
- }
183
- else if (theme) {
184
- const index = buildTokenIndex(theme);
185
- const paths = index.get(tokenName);
186
- if (paths && paths.length > 1) {
187
- if (typeof process !== "undefined" && process.env?.NODE_ENV !== "production") {
188
- // eslint-disable-next-line no-console
189
- console.warn(`[Stoop] Ambiguous token "$${tokenName}" found in multiple categories: ${paths.map((p) => p.join(".")).join(", ")}. ` +
190
- `Using "${paths[0].join(".")}" (deterministic: shorter paths first, then alphabetical). ` +
191
- `Use full path "$${paths[0].join(".")}" to be explicit, or use with a CSS property for automatic resolution.`);
192
- }
193
- }
194
- const foundPath = findTokenInTheme(theme, tokenName);
195
- if (foundPath) {
196
- const sanitizedParts = foundPath.map((part) => sanitizeCSSVariableName(part));
197
- const cssVarName = `--${sanitizedParts.join("-")}`;
198
- return `var(${cssVarName})`;
199
- }
200
- }
201
- const sanitizedTokenName = sanitizeCSSVariableName(tokenName);
202
- const cssVarName = `--${sanitizedTokenName}`;
203
- return `var(${cssVarName})`;
204
- }
205
- /**
206
- * Generates CSS custom properties from a theme object.
207
- *
208
- * @param theme - Theme object to convert to CSS variables
209
- * @param prefix - Optional prefix for CSS variable names
210
- * @returns CSS string with :root selector and CSS variables
211
- */
212
- export function generateCSSVariables(theme, prefix = "stoop") {
213
- const rootSelector = ":root";
214
- const variables = [];
215
- function processThemeObject(obj, path = []) {
216
- const keys = Object.keys(obj).sort();
217
- for (const key of keys) {
218
- // Media queries cannot be CSS variables
219
- if (key === "media") {
220
- continue;
221
- }
222
- const value = obj[key];
223
- const currentPath = [...path, key];
224
- if (isThemeObject(value)) {
225
- processThemeObject(value, currentPath);
226
- }
227
- else {
228
- const sanitizedParts = currentPath.map((part) => sanitizeCSSVariableName(part));
229
- const varName = `--${sanitizedParts.join("-")}`;
230
- const escapedValue = typeof value === "string" || typeof value === "number"
231
- ? escapeCSSVariableValue(value)
232
- : String(value);
233
- variables.push(` ${varName}: ${escapedValue};`);
234
- }
235
- }
236
- }
237
- processThemeObject(theme);
238
- if (variables.length === 0) {
239
- return "";
240
- }
241
- return `${rootSelector} {\n${variables.join("\n")}\n}`;
242
- }
243
- /**
244
- * Recursively replaces theme tokens with CSS variable references in a CSS object.
245
- *
246
- * @param obj - CSS object to process
247
- * @param theme - Optional theme for token resolution
248
- * @param themeMap - Optional theme scale mappings
249
- * @param property - Optional CSS property name for scale detection
250
- * @returns CSS object with tokens replaced by CSS variables
251
- */
252
- export function replaceThemeTokensWithVars(obj, theme, themeMap, property) {
253
- if (!obj || typeof obj !== "object") {
254
- return obj;
255
- }
256
- const result = {};
257
- const keys = Object.keys(obj).sort();
258
- for (const key of keys) {
259
- const value = obj[key];
260
- if (isCSSObject(value)) {
261
- result[key] = replaceThemeTokensWithVars(value, theme, themeMap, undefined);
262
- }
263
- else if (typeof value === "string" && value.includes("$")) {
264
- const cssProperty = property || key;
265
- result[key] = value.replace(TOKEN_REGEX, (token) => {
266
- if (token.startsWith("-$")) {
267
- const positiveToken = token.slice(1);
268
- const cssVar = tokenToCSSVar(positiveToken, theme, cssProperty, themeMap);
269
- return `calc(-1 * ${cssVar})`;
270
- }
271
- return tokenToCSSVar(token, theme, cssProperty, themeMap);
272
- });
273
- }
274
- else {
275
- result[key] = value;
276
- }
277
- }
278
- return result;
279
- }
@@ -1,26 +0,0 @@
1
- /**
2
- * Type guard utilities.
3
- * Provides runtime type checking for CSS objects, themes, and styled component references.
4
- */
5
- import type { CSS, Theme } from "../types";
6
- /**
7
- * Type guard for CSS objects.
8
- *
9
- * @param value - Value to check
10
- * @returns True if value is a CSS object
11
- */
12
- export declare function isCSSObject(value: unknown): value is CSS;
13
- /**
14
- * Type guard for valid CSS objects (excludes styled component references).
15
- *
16
- * @param value - Value to check
17
- * @returns True if value is a valid CSS object
18
- */
19
- export declare function isValidCSSObject(value: unknown): value is CSS;
20
- /**
21
- * Type guard for theme objects.
22
- *
23
- * @param value - Value to check
24
- * @returns True if value is a theme object
25
- */
26
- export declare function isThemeObject(value: unknown): value is Theme;
@@ -1,38 +0,0 @@
1
- /**
2
- * Type guard utilities.
3
- * Provides runtime type checking for CSS objects, themes, and styled component references.
4
- */
5
- /**
6
- * Type guard for CSS objects.
7
- *
8
- * @param value - Value to check
9
- * @returns True if value is a CSS object
10
- */
11
- export function isCSSObject(value) {
12
- return typeof value === "object" && value !== null;
13
- }
14
- function isStyledComponentRef(value) {
15
- return (typeof value === "object" &&
16
- value !== null &&
17
- "__isStoopStyled" in value &&
18
- "__stoopClassName" in value &&
19
- value.__isStoopStyled === true);
20
- }
21
- /**
22
- * Type guard for valid CSS objects (excludes styled component references).
23
- *
24
- * @param value - Value to check
25
- * @returns True if value is a valid CSS object
26
- */
27
- export function isValidCSSObject(value) {
28
- return isCSSObject(value) && !isStyledComponentRef(value);
29
- }
30
- /**
31
- * Type guard for theme objects.
32
- *
33
- * @param value - Value to check
34
- * @returns True if value is a theme object
35
- */
36
- export function isThemeObject(value) {
37
- return typeof value === "object" && value !== null && !Array.isArray(value);
38
- }
@@ -1,14 +0,0 @@
1
- /**
2
- * Utility function application.
3
- * Applies utility functions (e.g., px, py) to transform shorthand properties into CSS.
4
- * Recursively processes nested CSS objects.
5
- */
6
- import type { CSS, UtilityFunction } from "../types";
7
- /**
8
- * Applies utility functions to transform shorthand properties into CSS.
9
- *
10
- * @param styles - CSS object to process
11
- * @param utils - Optional utility functions object
12
- * @returns CSS object with utilities applied
13
- */
14
- export declare function applyUtilities(styles: CSS, utils?: Record<string, UtilityFunction>): CSS;
@@ -1,43 +0,0 @@
1
- /**
2
- * Utility function application.
3
- * Applies utility functions (e.g., px, py) to transform shorthand properties into CSS.
4
- * Recursively processes nested CSS objects.
5
- */
6
- import { isCSSObject } from "./type-guards";
7
- /**
8
- * Applies utility functions to transform shorthand properties into CSS.
9
- *
10
- * @param styles - CSS object to process
11
- * @param utils - Optional utility functions object
12
- * @returns CSS object with utilities applied
13
- */
14
- export function applyUtilities(styles, utils) {
15
- if (!utils || !styles || typeof styles !== "object") {
16
- return styles;
17
- }
18
- const result = {};
19
- const utilityKeys = Object.keys(utils);
20
- for (const key in styles) {
21
- const value = styles[key];
22
- if (utilityKeys.includes(key) && utils[key]) {
23
- try {
24
- const utilityResult = utils[key](value);
25
- if (utilityResult && typeof utilityResult === "object") {
26
- for (const utilKey in utilityResult) {
27
- result[utilKey] = utilityResult[utilKey];
28
- }
29
- }
30
- }
31
- catch {
32
- result[key] = value;
33
- }
34
- }
35
- else if (isCSSObject(value)) {
36
- result[key] = applyUtilities(value, utils);
37
- }
38
- else {
39
- result[key] = value;
40
- }
41
- }
42
- return result;
43
- }