stoop 0.3.0 → 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 (69) hide show
  1. package/README.md +125 -0
  2. package/dist/api/core-api.d.ts +34 -0
  3. package/dist/api/{keyframes.js → core-api.js} +45 -5
  4. package/dist/api/global-css.js +11 -58
  5. package/dist/api/styled.d.ts +0 -1
  6. package/dist/api/styled.js +265 -16
  7. package/dist/api/theme-provider.d.ts +41 -0
  8. package/dist/api/theme-provider.js +223 -0
  9. package/dist/constants.d.ts +11 -1
  10. package/dist/constants.js +11 -1
  11. package/dist/core/compiler.d.ts +11 -0
  12. package/dist/core/compiler.js +15 -7
  13. package/dist/core/theme-manager.d.ts +34 -3
  14. package/dist/core/theme-manager.js +55 -45
  15. package/dist/core/variants.js +9 -3
  16. package/dist/create-stoop-internal.d.ts +30 -0
  17. package/dist/create-stoop-internal.js +123 -0
  18. package/dist/create-stoop-ssr.d.ts +10 -0
  19. package/dist/create-stoop-ssr.js +26 -0
  20. package/dist/create-stoop.d.ts +32 -1
  21. package/dist/create-stoop.js +78 -69
  22. package/dist/inject.d.ts +113 -0
  23. package/dist/inject.js +308 -0
  24. package/dist/types/index.d.ts +147 -12
  25. package/dist/types/react-polymorphic-types.d.ts +13 -2
  26. package/dist/utils/auto-preload.d.ts +45 -0
  27. package/dist/utils/auto-preload.js +167 -0
  28. package/dist/utils/helpers.d.ts +64 -0
  29. package/dist/utils/helpers.js +150 -0
  30. package/dist/utils/storage.d.ts +148 -0
  31. package/dist/utils/storage.js +396 -0
  32. package/dist/utils/{string.d.ts → theme-utils.d.ts} +20 -3
  33. package/dist/utils/{string.js → theme-utils.js} +109 -9
  34. package/dist/utils/theme.d.ts +14 -2
  35. package/dist/utils/theme.js +41 -16
  36. package/package.json +48 -23
  37. package/dist/api/create-theme.d.ts +0 -13
  38. package/dist/api/create-theme.js +0 -43
  39. package/dist/api/css.d.ts +0 -16
  40. package/dist/api/css.js +0 -20
  41. package/dist/api/keyframes.d.ts +0 -16
  42. package/dist/api/provider.d.ts +0 -19
  43. package/dist/api/provider.js +0 -109
  44. package/dist/api/use-theme.d.ts +0 -13
  45. package/dist/api/use-theme.js +0 -21
  46. package/dist/create-stoop-server.d.ts +0 -33
  47. package/dist/create-stoop-server.js +0 -130
  48. package/dist/index.d.ts +0 -6
  49. package/dist/index.js +0 -5
  50. package/dist/inject/browser.d.ts +0 -58
  51. package/dist/inject/browser.js +0 -149
  52. package/dist/inject/dedup.d.ts +0 -29
  53. package/dist/inject/dedup.js +0 -38
  54. package/dist/inject/index.d.ts +0 -40
  55. package/dist/inject/index.js +0 -75
  56. package/dist/inject/ssr.d.ts +0 -27
  57. package/dist/inject/ssr.js +0 -46
  58. package/dist/ssr.d.ts +0 -21
  59. package/dist/ssr.js +0 -19
  60. package/dist/utils/environment.d.ts +0 -6
  61. package/dist/utils/environment.js +0 -12
  62. package/dist/utils/theme-map.d.ts +0 -22
  63. package/dist/utils/theme-map.js +0 -97
  64. package/dist/utils/theme-validation.d.ts +0 -13
  65. package/dist/utils/theme-validation.js +0 -36
  66. package/dist/utils/type-guards.d.ts +0 -26
  67. package/dist/utils/type-guards.js +0 -38
  68. package/dist/utils/utilities.d.ts +0 -14
  69. package/dist/utils/utilities.js +0 -43
@@ -3,24 +3,17 @@
3
3
  * Converts theme tokens to CSS variables for runtime theme switching.
4
4
  * Uses cached token index for efficient lookups and theme comparison.
5
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();
6
+ import { isCSSObject, isThemeObject, isProduction } from "./helpers";
7
+ import { escapeCSSVariableValue, getScaleForProperty, sanitizeCSSVariableName, } from "./theme-utils";
10
8
  // Pre-compiled regex for token replacement (matches $primary, -$medium, $colors.primary, etc.)
11
9
  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
10
  /**
13
11
  * Builds an index of all tokens in a theme for fast lookups.
14
- * Caches the result to avoid rebuilding on every token resolution.
15
12
  *
16
13
  * @param theme - Theme to index
17
14
  * @returns Map of token names to their paths in the theme
18
15
  */
19
16
  function buildTokenIndex(theme) {
20
- const cached = tokenIndexCache.get(theme);
21
- if (cached) {
22
- return cached;
23
- }
24
17
  const index = new Map();
25
18
  function processThemeObject(obj, path = []) {
26
19
  const keys = Object.keys(obj);
@@ -55,7 +48,6 @@ function buildTokenIndex(theme) {
55
48
  });
56
49
  }
57
50
  }
58
- tokenIndexCache.set(theme, index);
59
51
  return index;
60
52
  }
61
53
  /**
@@ -162,7 +154,7 @@ export function tokenToCSSVar(token, theme, property, themeMap) {
162
154
  const index = buildTokenIndex(theme);
163
155
  const paths = index.get(tokenName);
164
156
  if (paths && paths.length > 1) {
165
- if (typeof process !== "undefined" && process.env?.NODE_ENV !== "production") {
157
+ if (!isProduction()) {
166
158
  const scaleInfo = scale
167
159
  ? `Property "${property}" maps to "${scale}" scale, but token not found there. `
168
160
  : `No scale mapping found for property "${property}". `;
@@ -184,7 +176,7 @@ export function tokenToCSSVar(token, theme, property, themeMap) {
184
176
  const index = buildTokenIndex(theme);
185
177
  const paths = index.get(tokenName);
186
178
  if (paths && paths.length > 1) {
187
- if (typeof process !== "undefined" && process.env?.NODE_ENV !== "production") {
179
+ if (!isProduction()) {
188
180
  // eslint-disable-next-line no-console
189
181
  console.warn(`[Stoop] Ambiguous token "$${tokenName}" found in multiple categories: ${paths.map((p) => p.join(".")).join(", ")}. ` +
190
182
  `Using "${paths[0].join(".")}" (deterministic: shorter paths first, then alphabetical). ` +
@@ -207,10 +199,11 @@ export function tokenToCSSVar(token, theme, property, themeMap) {
207
199
  *
208
200
  * @param theme - Theme object to convert to CSS variables
209
201
  * @param prefix - Optional prefix for CSS variable names
210
- * @returns CSS string with :root selector and CSS variables
202
+ * @param attributeSelector - Optional attribute selector (e.g., '[data-theme="light"]'). Defaults to ':root'
203
+ * @returns CSS string with selector and CSS variables
211
204
  */
212
- export function generateCSSVariables(theme, prefix = "stoop") {
213
- const rootSelector = ":root";
205
+ export function generateCSSVariables(theme, prefix = "stoop", attributeSelector) {
206
+ const rootSelector = attributeSelector || ":root";
214
207
  const variables = [];
215
208
  function processThemeObject(obj, path = []) {
216
209
  const keys = Object.keys(obj).sort();
@@ -240,6 +233,27 @@ export function generateCSSVariables(theme, prefix = "stoop") {
240
233
  }
241
234
  return `${rootSelector} {\n${variables.join("\n")}\n}`;
242
235
  }
236
+ /**
237
+ * Generates CSS custom properties for all themes using attribute selectors.
238
+ * This allows all themes to be available simultaneously, with theme switching
239
+ * handled by changing the data-theme attribute.
240
+ *
241
+ * @param themes - Map of theme names to theme objects
242
+ * @param prefix - Optional prefix for CSS variable names
243
+ * @param attribute - Attribute name for theme selection (defaults to 'data-theme')
244
+ * @returns CSS string with all theme CSS variables
245
+ */
246
+ export function generateAllThemeVariables(themes, prefix = "stoop", attribute = "data-theme") {
247
+ const themeBlocks = [];
248
+ for (const [themeName, theme] of Object.entries(themes)) {
249
+ const attributeSelector = `[${attribute}="${themeName}"]`;
250
+ const cssVars = generateCSSVariables(theme, prefix, attributeSelector);
251
+ if (cssVars) {
252
+ themeBlocks.push(cssVars);
253
+ }
254
+ }
255
+ return themeBlocks.join("\n\n");
256
+ }
243
257
  /**
244
258
  * Recursively replaces theme tokens with CSS variable references in a CSS object.
245
259
  *
@@ -254,13 +268,20 @@ export function replaceThemeTokensWithVars(obj, theme, themeMap, property) {
254
268
  return obj;
255
269
  }
256
270
  const result = {};
271
+ let hasTokens = false;
257
272
  const keys = Object.keys(obj).sort();
258
273
  for (const key of keys) {
259
274
  const value = obj[key];
260
275
  if (isCSSObject(value)) {
261
- result[key] = replaceThemeTokensWithVars(value, theme, themeMap, undefined);
276
+ const processed = replaceThemeTokensWithVars(value, theme, themeMap, undefined);
277
+ result[key] = processed;
278
+ // Check if processing changed anything (indicates tokens were found)
279
+ if (processed !== value) {
280
+ hasTokens = true;
281
+ }
262
282
  }
263
283
  else if (typeof value === "string" && value.includes("$")) {
284
+ hasTokens = true;
264
285
  const cssProperty = property || key;
265
286
  result[key] = value.replace(TOKEN_REGEX, (token) => {
266
287
  if (token.startsWith("-$")) {
@@ -275,5 +296,9 @@ export function replaceThemeTokensWithVars(obj, theme, themeMap, property) {
275
296
  result[key] = value;
276
297
  }
277
298
  }
299
+ // Early exit: if no tokens were found, return original object to avoid unnecessary copying
300
+ if (!hasTokens) {
301
+ return obj;
302
+ }
278
303
  return result;
279
304
  }
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "stoop",
3
3
  "description": "CSS-in-JS library with type inference, theme creation, and variants support.",
4
- "version": "0.3.0",
4
+ "version": "0.4.0",
5
5
  "author": "Jackson Dolman <mail@dolmios.com>",
6
- "main": "./dist/index.js",
6
+ "main": "./dist/create-stoop.js",
7
+ "types": "./dist/create-stoop.d.ts",
7
8
  "repository": {
8
9
  "type": "git",
9
10
  "url": "https://github.com/dolmios/stoop.git"
@@ -16,24 +17,48 @@
16
17
  "react-polymorphic-types": "^2.0.0"
17
18
  },
18
19
  "devDependencies": {
19
- "@types/node": "^22.10.5",
20
- "@types/react": "^19.0.6",
21
- "@types/react-dom": "^19.0.2",
22
- "bun-types": "^1.2.6",
23
- "typescript": "^5.7.2"
20
+ "@types/node": "^25.0.3",
21
+ "@types/react": "^19.2.7",
22
+ "@types/react-dom": "^19.2.3",
23
+ "bun-types": "^1.3.5",
24
+ "typescript": "^5.9.3"
24
25
  },
25
26
  "exports": {
26
27
  ".": {
27
- "types": "./dist/index.d.ts",
28
- "import": "./dist/index.js",
29
- "require": "./dist/index.js",
30
- "default": "./dist/index.js"
28
+ "types": "./dist/create-stoop.d.ts",
29
+ "import": "./dist/create-stoop.js",
30
+ "require": "./dist/create-stoop.js",
31
+ "default": "./dist/create-stoop.js"
32
+ },
33
+ "./utils/storage": {
34
+ "types": "./dist/utils/storage.d.ts",
35
+ "import": "./dist/utils/storage.js",
36
+ "require": "./dist/utils/storage.js",
37
+ "default": "./dist/utils/storage.js"
38
+ },
39
+ "./utils/auto-preload": {
40
+ "types": "./dist/utils/auto-preload.d.ts",
41
+ "import": "./dist/utils/auto-preload.js",
42
+ "require": "./dist/utils/auto-preload.js",
43
+ "default": "./dist/utils/auto-preload.js"
44
+ },
45
+ "./types": {
46
+ "types": "./dist/types/index.d.ts",
47
+ "import": "./dist/types/index.js",
48
+ "require": "./dist/types/index.js",
49
+ "default": "./dist/types/index.js"
50
+ },
51
+ "./inject": {
52
+ "types": "./dist/inject.d.ts",
53
+ "import": "./dist/inject.js",
54
+ "require": "./dist/inject.js",
55
+ "default": "./dist/inject.js"
31
56
  },
32
57
  "./ssr": {
33
- "types": "./dist/ssr.d.ts",
34
- "import": "./dist/ssr.js",
35
- "require": "./dist/ssr.js",
36
- "default": "./dist/ssr.js"
58
+ "types": "./dist/create-stoop-ssr.d.ts",
59
+ "import": "./dist/create-stoop-ssr.js",
60
+ "require": "./dist/create-stoop-ssr.js",
61
+ "default": "./dist/create-stoop-ssr.js"
37
62
  }
38
63
  },
39
64
  "files": [
@@ -71,18 +96,18 @@
71
96
  "react": ">=16.8.0",
72
97
  "react-dom": ">=16.8.0"
73
98
  },
99
+ "sideEffects": false,
100
+ "type": "module",
74
101
  "scripts": {
75
- "build": "bun run build:clean && bun run build:types",
102
+ "build": "bun run build:clean && bun run build:js && bun run build:js:ssr && bun run build:types",
76
103
  "build:clean": "rm -rf dist",
77
104
  "build:copy-declarations": "mkdir -p dist/types && cp src/types/react-polymorphic-types.d.ts dist/types/react-polymorphic-types.d.ts 2>/dev/null || :",
78
- "build:js": "NODE_ENV=production bun build ./src/index.ts --outdir ./dist --target node --minify --jsx=automatic --splitting --external react --external react-dom --external react/jsx-runtime --define process.env.NODE_ENV='\"production\"'",
105
+ "build:js": "NODE_ENV=production bun build ./src/create-stoop.ts --outdir ./dist --target node --minify --jsx=automatic --splitting --external react --external react-dom --external react/jsx-runtime --define process.env.NODE_ENV='\"production\"'",
106
+ "build:js:ssr": "NODE_ENV=production bun build ./src/create-stoop-ssr.ts --outdir ./dist --target node --minify --jsx=automatic --external react --external react-dom --external react/jsx-runtime --define process.env.NODE_ENV='\"production\"'",
79
107
  "build:types": "bunx tsc --project tsconfig.build.json && bun run build:copy-declarations",
80
- "prepare": "bun run build",
108
+ "lint": "eslint src --fix",
81
109
  "test": "bun test",
82
110
  "test:coverage": "bun test --coverage",
83
111
  "test:watch": "bun test --watch"
84
- },
85
- "sideEffects": false,
86
- "type": "module"
87
- }
88
-
112
+ }
113
+ }
@@ -1,13 +0,0 @@
1
- /**
2
- * Theme extension API.
3
- * Creates a function that deep merges theme overrides with a base theme.
4
- */
5
- import type { Theme } from "../types";
6
- /**
7
- * Creates a function that extends a base theme with overrides.
8
- * The returned function deep merges theme overrides with the base theme.
9
- *
10
- * @param baseTheme - Base theme to extend
11
- * @returns Function that accepts theme overrides and returns a merged theme
12
- */
13
- export declare function createTheme(baseTheme: Theme): (themeOverrides: Partial<Theme>) => Theme;
@@ -1,43 +0,0 @@
1
- /**
2
- * Theme extension API.
3
- * Creates a function that deep merges theme overrides with a base theme.
4
- */
5
- import { validateTheme } from "../utils/theme-validation";
6
- import { isThemeObject } from "../utils/type-guards";
7
- /**
8
- * Creates a function that extends a base theme with overrides.
9
- * The returned function deep merges theme overrides with the base theme.
10
- *
11
- * @param baseTheme - Base theme to extend
12
- * @returns Function that accepts theme overrides and returns a merged theme
13
- */
14
- export function createTheme(baseTheme) {
15
- return function createTheme(themeOverrides) {
16
- const validatedOverrides = validateTheme(themeOverrides);
17
- function deepMerge(target, source) {
18
- const result = { ...target };
19
- const sourceKeys = Object.keys(source);
20
- for (const key of sourceKeys) {
21
- const sourceValue = source[key];
22
- const targetValue = target[key];
23
- if (isThemeObject(sourceValue) && isThemeObject(targetValue)) {
24
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
25
- result[key] = { ...targetValue, ...sourceValue };
26
- }
27
- else if (sourceValue !== undefined) {
28
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
- result[key] = sourceValue;
30
- }
31
- }
32
- const targetKeys = Object.keys(target);
33
- for (const key of targetKeys) {
34
- if (!(key in result)) {
35
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
- result[key] = target[key];
37
- }
38
- }
39
- return result;
40
- }
41
- return deepMerge(baseTheme, validatedOverrides);
42
- };
43
- }
package/dist/api/css.d.ts DELETED
@@ -1,16 +0,0 @@
1
- /**
2
- * CSS class generation API.
3
- * Creates a function that compiles CSS objects into class names.
4
- */
5
- import type { CSS, Theme, ThemeScale, UtilityFunction } from "../types";
6
- /**
7
- * Creates a CSS function that compiles CSS objects into class names.
8
- *
9
- * @param defaultTheme - Default theme for token resolution
10
- * @param prefix - Optional prefix for generated class names
11
- * @param media - Optional media query breakpoints
12
- * @param utils - Optional utility functions
13
- * @param themeMap - Optional theme scale mappings
14
- * @returns Function that accepts CSS objects and returns class names
15
- */
16
- export declare function createCSSFunction(defaultTheme: Theme, prefix?: string, media?: Record<string, string>, utils?: Record<string, UtilityFunction>, themeMap?: Record<string, ThemeScale>): (styles: CSS) => string;
package/dist/api/css.js DELETED
@@ -1,20 +0,0 @@
1
- /**
2
- * CSS class generation API.
3
- * Creates a function that compiles CSS objects into class names.
4
- */
5
- import { compileCSS } from "../core/compiler";
6
- /**
7
- * Creates a CSS function that compiles CSS objects into class names.
8
- *
9
- * @param defaultTheme - Default theme for token resolution
10
- * @param prefix - Optional prefix for generated class names
11
- * @param media - Optional media query breakpoints
12
- * @param utils - Optional utility functions
13
- * @param themeMap - Optional theme scale mappings
14
- * @returns Function that accepts CSS objects and returns class names
15
- */
16
- export function createCSSFunction(defaultTheme, prefix = "stoop", media, utils, themeMap) {
17
- return function css(styles) {
18
- return compileCSS(styles, defaultTheme, prefix, media, utils, themeMap);
19
- };
20
- }
@@ -1,16 +0,0 @@
1
- /**
2
- * CSS keyframes animation API.
3
- * Creates a function that generates and injects @keyframes rules.
4
- * Caches animations by content hash to prevent duplicates.
5
- */
6
- import type { CSS, Theme, ThemeScale } from "../types";
7
- /**
8
- * Creates a keyframes animation function.
9
- * Generates and injects @keyframes rules with caching to prevent duplicates.
10
- *
11
- * @param prefix - Optional prefix for animation names
12
- * @param theme - Optional theme for token resolution
13
- * @param themeMap - Optional theme scale mappings
14
- * @returns Function that accepts keyframes objects and returns animation names
15
- */
16
- export declare function createKeyframesFunction(prefix?: string, theme?: Theme, themeMap?: Record<string, ThemeScale>): (keyframes: Record<string, CSS>) => string;
@@ -1,19 +0,0 @@
1
- /**
2
- * Theme Provider component.
3
- * Manages theme state, localStorage persistence, and centralized theme variable updates.
4
- */
5
- import { type ComponentType, type Context } from "react";
6
- import type { ProviderProps, Theme, ThemeContextValue, ThemeManagementContextValue } from "../types";
7
- /**
8
- * Creates a Provider component for theme management.
9
- *
10
- * @param themes - Map of theme names to theme objects
11
- * @param defaultTheme - Default theme object
12
- * @param prefix - Optional prefix for CSS variable scoping
13
- * @returns Provider component, theme context, and theme management context
14
- */
15
- export declare function createProvider(themes: Record<string, Theme>, defaultTheme: Theme, prefix?: string): {
16
- Provider: ComponentType<ProviderProps>;
17
- ThemeContext: Context<ThemeContextValue | null>;
18
- ThemeManagementContext: Context<ThemeManagementContextValue | null>;
19
- };
@@ -1,109 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx } from "react/jsx-runtime";
3
- /**
4
- * Theme Provider component.
5
- * Manages theme state, localStorage persistence, and centralized theme variable updates.
6
- */
7
- import { createContext, useCallback, useLayoutEffect, useMemo, useState, } from "react";
8
- import { updateThemeVariables } from "../core/theme-manager";
9
- import { isBrowser } from "../utils/environment";
10
- /**
11
- * Creates a Provider component for theme management.
12
- *
13
- * @param themes - Map of theme names to theme objects
14
- * @param defaultTheme - Default theme object
15
- * @param prefix - Optional prefix for CSS variable scoping
16
- * @returns Provider component, theme context, and theme management context
17
- */
18
- export function createProvider(themes, defaultTheme, prefix = "stoop") {
19
- const ThemeContext = createContext(null);
20
- const ThemeManagementContext = createContext(null);
21
- const availableThemeNames = Object.keys(themes);
22
- const firstThemeName = availableThemeNames[0] || "default";
23
- function Provider({ attribute = "data-theme", children, defaultTheme: defaultThemeProp, storageKey = "stoop-theme", }) {
24
- // SSR-safe initialization: always start with default, then hydrate from localStorage
25
- const [themeName, setThemeNameState] = useState(() => {
26
- // During SSR, always return the default theme
27
- if (!isBrowser()) {
28
- return defaultThemeProp || firstThemeName;
29
- }
30
- // On client, try to read from localStorage
31
- try {
32
- const stored = localStorage.getItem(storageKey);
33
- if (stored && themes[stored]) {
34
- return stored;
35
- }
36
- }
37
- catch {
38
- // localStorage access failed (e.g., in private browsing mode)
39
- }
40
- return defaultThemeProp || firstThemeName;
41
- });
42
- // Hydrate from localStorage after mount to prevent hydration mismatch
43
- useLayoutEffect(() => {
44
- if (!isBrowser()) {
45
- return;
46
- }
47
- try {
48
- const stored = localStorage.getItem(storageKey);
49
- if (stored && themes[stored] && stored !== themeName) {
50
- setThemeNameState(stored);
51
- }
52
- }
53
- catch {
54
- // localStorage access failed
55
- }
56
- }, [storageKey, themeName]);
57
- const currentTheme = useMemo(() => {
58
- return themes[themeName] || themes[defaultThemeProp || firstThemeName] || defaultTheme;
59
- }, [themeName, defaultThemeProp, firstThemeName, themes]);
60
- useLayoutEffect(() => {
61
- if (currentTheme) {
62
- updateThemeVariables(currentTheme, prefix);
63
- }
64
- }, [currentTheme, prefix]);
65
- useLayoutEffect(() => {
66
- if (isBrowser() && attribute) {
67
- document.documentElement.setAttribute(attribute, themeName);
68
- }
69
- }, [themeName, attribute]);
70
- const setTheme = useCallback((newThemeName) => {
71
- if (themes[newThemeName]) {
72
- setThemeNameState(newThemeName);
73
- try {
74
- localStorage.setItem(storageKey, newThemeName);
75
- }
76
- catch {
77
- // localStorage access failed (e.g., in private browsing mode)
78
- }
79
- }
80
- else if (typeof process !== "undefined" && process.env?.NODE_ENV !== "production") {
81
- // eslint-disable-next-line no-console
82
- console.warn(`[Stoop] Theme "${newThemeName}" not found. Available themes: ${availableThemeNames.join(", ")}`);
83
- }
84
- }, [storageKey, themes, availableThemeNames]);
85
- const themeContextValue = useMemo(() => ({
86
- theme: currentTheme,
87
- themeName,
88
- }), [currentTheme, themeName]);
89
- const toggleTheme = useCallback(() => {
90
- const currentIndex = availableThemeNames.indexOf(themeName);
91
- const nextIndex = (currentIndex + 1) % availableThemeNames.length;
92
- const newTheme = availableThemeNames[nextIndex];
93
- setTheme(newTheme);
94
- }, [themeName, setTheme]);
95
- const managementContextValue = useMemo(() => ({
96
- availableThemes: availableThemeNames,
97
- setTheme,
98
- theme: currentTheme,
99
- themeName,
100
- toggleTheme,
101
- }), [currentTheme, themeName, setTheme, toggleTheme]);
102
- return (_jsx(ThemeContext.Provider, { value: themeContextValue, children: _jsx(ThemeManagementContext.Provider, { value: managementContextValue, children: children }) }));
103
- }
104
- return {
105
- Provider,
106
- ThemeContext,
107
- ThemeManagementContext,
108
- };
109
- }
@@ -1,13 +0,0 @@
1
- /**
2
- * Theme management hook.
3
- * Provides access to theme state and theme switching functions.
4
- */
5
- import { type Context } from "react";
6
- import type { ThemeManagementContextValue } from "../types";
7
- /**
8
- * Creates a useTheme hook for a specific theme management context.
9
- *
10
- * @param ThemeManagementContext - React context for theme management
11
- * @returns Hook function that returns theme management context value
12
- */
13
- export declare function createUseThemeHook(ThemeManagementContext: Context<ThemeManagementContextValue | null>): () => ThemeManagementContextValue;
@@ -1,21 +0,0 @@
1
- "use client";
2
- /**
3
- * Theme management hook.
4
- * Provides access to theme state and theme switching functions.
5
- */
6
- import { useContext } from "react";
7
- /**
8
- * Creates a useTheme hook for a specific theme management context.
9
- *
10
- * @param ThemeManagementContext - React context for theme management
11
- * @returns Hook function that returns theme management context value
12
- */
13
- export function createUseThemeHook(ThemeManagementContext) {
14
- return function useTheme() {
15
- const context = useContext(ThemeManagementContext);
16
- if (!context) {
17
- throw new Error("useTheme must be used within a Provider");
18
- }
19
- return context;
20
- };
21
- }
@@ -1,33 +0,0 @@
1
- /**
2
- * Server-safe factory function that creates a Stoop instance.
3
- * Only includes APIs that work without React: css, globalCss, keyframes, getCssText, etc.
4
- * Does NOT include: styled, Provider, useTheme
5
- *
6
- * This is the entry point for Server Components in Next.js App Router.
7
- */
8
- import type { CSS, StoopConfig, Theme } from "./types";
9
- /**
10
- * Server-safe Stoop instance interface.
11
- * Only includes APIs that work without React dependencies.
12
- */
13
- export interface StoopServerInstance {
14
- config: StoopConfig & {
15
- prefix: string;
16
- };
17
- createTheme: (themeOverride: Partial<Theme>) => Theme;
18
- css: (styles: CSS) => string;
19
- getCssText: (theme?: string | Theme) => string;
20
- globalCss: (...args: CSS[]) => () => void;
21
- keyframes: (definition: Record<string, CSS>) => string;
22
- preloadTheme: (theme: string | Theme) => void;
23
- theme: Theme;
24
- warmCache: (styles: CSS[]) => void;
25
- }
26
- /**
27
- * Creates a server-safe Stoop instance with the provided configuration.
28
- * Only includes APIs that work without React: css, globalCss, keyframes, getCssText, etc.
29
- *
30
- * @param config - Configuration object containing theme, media queries, utilities, and optional prefix/themeMap
31
- * @returns StoopServerInstance with server-safe API functions
32
- */
33
- export declare function createStoop(config: StoopConfig): StoopServerInstance;