stoop 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +125 -0
- package/dist/api/core-api.d.ts +34 -0
- package/dist/api/styled.d.ts +0 -1
- package/dist/api/theme-provider.d.ts +41 -0
- package/dist/constants.d.ts +11 -1
- package/dist/core/compiler.d.ts +11 -0
- package/dist/core/theme-manager.d.ts +34 -3
- package/dist/create-stoop-internal.d.ts +30 -0
- package/dist/create-stoop-ssr.d.ts +10 -0
- package/dist/create-stoop-ssr.js +16 -0
- package/dist/create-stoop.d.ts +32 -1
- package/dist/create-stoop.js +16 -147
- package/dist/inject.d.ts +113 -0
- package/dist/types/index.d.ts +147 -12
- package/dist/types/react-polymorphic-types.d.ts +13 -2
- package/dist/utils/auto-preload.d.ts +45 -0
- package/dist/utils/helpers.d.ts +64 -0
- package/dist/utils/storage.d.ts +148 -0
- package/dist/utils/{string.d.ts → theme-utils.d.ts} +20 -3
- package/dist/utils/theme.d.ts +14 -2
- package/package.json +44 -17
- package/dist/api/create-theme.d.ts +0 -13
- package/dist/api/create-theme.js +0 -43
- package/dist/api/css.d.ts +0 -16
- package/dist/api/css.js +0 -20
- package/dist/api/global-css.js +0 -89
- package/dist/api/keyframes.d.ts +0 -16
- package/dist/api/keyframes.js +0 -95
- package/dist/api/provider.d.ts +0 -19
- package/dist/api/provider.js +0 -109
- package/dist/api/styled.js +0 -170
- package/dist/api/use-theme.d.ts +0 -13
- package/dist/api/use-theme.js +0 -21
- package/dist/constants.js +0 -144
- package/dist/core/cache.js +0 -68
- package/dist/core/compiler.js +0 -198
- package/dist/core/theme-manager.js +0 -97
- package/dist/core/variants.js +0 -32
- package/dist/create-stoop-server.d.ts +0 -33
- package/dist/create-stoop-server.js +0 -130
- package/dist/index.d.ts +0 -6
- package/dist/index.js +0 -5
- package/dist/inject/browser.d.ts +0 -58
- package/dist/inject/browser.js +0 -149
- package/dist/inject/dedup.d.ts +0 -29
- package/dist/inject/dedup.js +0 -38
- package/dist/inject/index.d.ts +0 -40
- package/dist/inject/index.js +0 -75
- package/dist/inject/ssr.d.ts +0 -27
- package/dist/inject/ssr.js +0 -46
- package/dist/ssr.d.ts +0 -21
- package/dist/ssr.js +0 -19
- package/dist/types/index.js +0 -5
- package/dist/utils/environment.d.ts +0 -6
- package/dist/utils/environment.js +0 -12
- package/dist/utils/string.js +0 -253
- package/dist/utils/theme-map.d.ts +0 -22
- package/dist/utils/theme-map.js +0 -97
- package/dist/utils/theme-validation.d.ts +0 -13
- package/dist/utils/theme-validation.js +0 -36
- package/dist/utils/theme.js +0 -279
- package/dist/utils/type-guards.d.ts +0 -26
- package/dist/utils/type-guards.js +0 -38
- package/dist/utils/utilities.d.ts +0 -14
- package/dist/utils/utilities.js +0 -43
package/README.md
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# stoop
|
|
2
|
+
|
|
3
|
+
A lightweight, type-safe CSS-in-JS library for React with theme support, variants, and SSR capabilities.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install stoop
|
|
9
|
+
# or
|
|
10
|
+
bun add stoop
|
|
11
|
+
# or
|
|
12
|
+
yarn add stoop
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { createStoop } from "stoop";
|
|
19
|
+
|
|
20
|
+
const { styled, css, Provider, useTheme } = createStoop({
|
|
21
|
+
theme: {
|
|
22
|
+
colors: {
|
|
23
|
+
primary: "#0070f3",
|
|
24
|
+
background: "#ffffff",
|
|
25
|
+
text: "#000000",
|
|
26
|
+
},
|
|
27
|
+
space: {
|
|
28
|
+
small: "8px",
|
|
29
|
+
medium: "16px",
|
|
30
|
+
large: "24px",
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
themes: {
|
|
34
|
+
light: {
|
|
35
|
+
/* ... */
|
|
36
|
+
},
|
|
37
|
+
dark: {
|
|
38
|
+
/* ... */
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const Button = styled("button", {
|
|
44
|
+
padding: "$medium",
|
|
45
|
+
backgroundColor: "$primary",
|
|
46
|
+
color: "$text",
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
<Button>Click me</Button>;
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Features
|
|
53
|
+
|
|
54
|
+
- **Type-safe theming** with TypeScript inference
|
|
55
|
+
- **CSS variables** for instant theme switching
|
|
56
|
+
- **Variant system** for component variations
|
|
57
|
+
- **SSR support** via `getCssText()`
|
|
58
|
+
- **Multiple themes** with built-in Provider
|
|
59
|
+
- **Utility functions** for custom CSS transformations
|
|
60
|
+
- **Zero runtime overhead** for theme switching
|
|
61
|
+
|
|
62
|
+
## Documentation
|
|
63
|
+
|
|
64
|
+
- **[GUIDE.md](./docs/GUIDE.md)** - Step-by-step setup and usage guide
|
|
65
|
+
- **[API.md](./docs/API.md)** - Complete API reference
|
|
66
|
+
- **[ARCHITECTURE.md](./docs/ARCHITECTURE.md)** - Internal implementation details
|
|
67
|
+
- **[TESTING.md](./docs/TESTING.md)** - Testing guide and test suite documentation
|
|
68
|
+
|
|
69
|
+
## API Overview
|
|
70
|
+
|
|
71
|
+
### `createStoop(config)`
|
|
72
|
+
|
|
73
|
+
Creates a Stoop instance. Returns: `styled`, `css`, `createTheme`, `globalCss`, `keyframes`, `getCssText`, `warmCache`, `preloadTheme`, `theme`, `config`. If `themes` config is provided, also returns `Provider` and `useTheme`.
|
|
74
|
+
|
|
75
|
+
### Theme Tokens
|
|
76
|
+
|
|
77
|
+
Use `$` prefix for theme tokens. Shorthand `$token` uses property-aware resolution (preferred); explicit `$scale.token` specifies the scale.
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
{
|
|
81
|
+
color: "$primary", // Shorthand (preferred, property-aware)
|
|
82
|
+
padding: "$medium", // Property-aware → space scale
|
|
83
|
+
fontSize: "$fontSizes.small", // Explicit scale
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Variants
|
|
88
|
+
|
|
89
|
+
Variants create component variations via props:
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
const Button = styled(
|
|
93
|
+
"button",
|
|
94
|
+
{},
|
|
95
|
+
{
|
|
96
|
+
variant: {
|
|
97
|
+
primary: { backgroundColor: "$primary" },
|
|
98
|
+
secondary: { backgroundColor: "$secondary" },
|
|
99
|
+
},
|
|
100
|
+
size: {
|
|
101
|
+
small: { padding: "$small" },
|
|
102
|
+
large: { padding: "$large" },
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
<Button variant="primary" size="small" />;
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Development
|
|
111
|
+
|
|
112
|
+
```sh
|
|
113
|
+
# Build
|
|
114
|
+
bun run build
|
|
115
|
+
|
|
116
|
+
# Test
|
|
117
|
+
bun run test
|
|
118
|
+
|
|
119
|
+
# Watch mode
|
|
120
|
+
bun run test:watch
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## License
|
|
124
|
+
|
|
125
|
+
MIT
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core API functions.
|
|
3
|
+
* Consolidates theme creation, CSS class generation, and keyframes animation APIs.
|
|
4
|
+
*/
|
|
5
|
+
import type { CSS, Theme, ThemeScale, UtilityFunction } 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;
|
|
14
|
+
/**
|
|
15
|
+
* Creates a CSS function that compiles CSS objects into class names.
|
|
16
|
+
*
|
|
17
|
+
* @param defaultTheme - Default theme for token resolution
|
|
18
|
+
* @param prefix - Optional prefix for generated class names
|
|
19
|
+
* @param media - Optional media query breakpoints
|
|
20
|
+
* @param utils - Optional utility functions
|
|
21
|
+
* @param themeMap - Optional theme scale mappings
|
|
22
|
+
* @returns Function that accepts CSS objects and returns class names
|
|
23
|
+
*/
|
|
24
|
+
export declare function createCSSFunction(defaultTheme: Theme, prefix?: string, media?: Record<string, string>, utils?: Record<string, UtilityFunction>, themeMap?: Record<string, ThemeScale>): (styles: CSS) => string;
|
|
25
|
+
/**
|
|
26
|
+
* Creates a keyframes animation function.
|
|
27
|
+
* Generates and injects @keyframes rules with caching to prevent duplicates.
|
|
28
|
+
*
|
|
29
|
+
* @param prefix - Optional prefix for animation names
|
|
30
|
+
* @param theme - Optional theme for token resolution
|
|
31
|
+
* @param themeMap - Optional theme scale mappings
|
|
32
|
+
* @returns Function that accepts keyframes objects and returns animation names
|
|
33
|
+
*/
|
|
34
|
+
export declare function createKeyframesFunction(prefix?: string, theme?: Theme, themeMap?: Record<string, ThemeScale>): (keyframes: Record<string, CSS>) => string;
|
package/dist/api/styled.d.ts
CHANGED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Provider component and hook.
|
|
3
|
+
* Manages theme state, localStorage persistence, cookie sync, and centralized theme variable updates.
|
|
4
|
+
* Includes the useTheme hook for accessing theme management context.
|
|
5
|
+
*/
|
|
6
|
+
import { type ComponentType, type Context } from "react";
|
|
7
|
+
import type { ProviderProps, Theme, ThemeContextValue, ThemeManagementContextValue } from "../types";
|
|
8
|
+
/**
|
|
9
|
+
* Creates a Provider component for theme management.
|
|
10
|
+
*
|
|
11
|
+
* @param themes - Map of theme names to theme objects
|
|
12
|
+
* @param defaultTheme - Default theme object
|
|
13
|
+
* @param prefix - Optional prefix for CSS variable scoping
|
|
14
|
+
* @param globalCss - Optional global CSS object from config
|
|
15
|
+
* @param globalCssFunction - Optional globalCss function from createStoop
|
|
16
|
+
* @returns Provider component, theme context, and theme management context
|
|
17
|
+
*
|
|
18
|
+
* @remarks
|
|
19
|
+
* To prevent FOUC (Flash of Unstyled Content) when a user has a non-default theme stored,
|
|
20
|
+
* call `preloadTheme()` from your stoop instance in a script tag before React hydrates:
|
|
21
|
+
*
|
|
22
|
+
* ```html
|
|
23
|
+
* <script>
|
|
24
|
+
* // Read theme from storage and preload before React renders
|
|
25
|
+
* const storedTheme = localStorage.getItem('stoop-theme') || 'light';
|
|
26
|
+
* stoopInstance.preloadTheme(storedTheme);
|
|
27
|
+
* </script>
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function createProvider(themes: Record<string, Theme>, defaultTheme: Theme, prefix?: string, globalCss?: import("../types").CSS, globalCssFunction?: import("../types").GlobalCSSFunction): {
|
|
31
|
+
Provider: ComponentType<ProviderProps>;
|
|
32
|
+
ThemeContext: Context<ThemeContextValue | null>;
|
|
33
|
+
ThemeManagementContext: Context<ThemeManagementContextValue | null>;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Creates a useTheme hook for a specific theme management context.
|
|
37
|
+
*
|
|
38
|
+
* @param ThemeManagementContext - React context for theme management
|
|
39
|
+
* @returns Hook function that returns theme management context value
|
|
40
|
+
*/
|
|
41
|
+
export declare function createUseThemeHook(ThemeManagementContext: Context<ThemeManagementContextValue | null>): () => ThemeManagementContextValue;
|
package/dist/constants.d.ts
CHANGED
|
@@ -7,13 +7,23 @@ export declare const EMPTY_CSS: CSS;
|
|
|
7
7
|
export declare const MAX_CSS_CACHE_SIZE = 10000;
|
|
8
8
|
export declare const MAX_CLASS_NAME_CACHE_SIZE = 5000;
|
|
9
9
|
export declare const MAX_CSS_NESTING_DEPTH = 10;
|
|
10
|
+
/**
|
|
11
|
+
* Cache size limits for various LRU caches.
|
|
12
|
+
*/
|
|
13
|
+
export declare const KEYFRAME_CACHE_LIMIT = 500;
|
|
14
|
+
export declare const SANITIZE_CACHE_SIZE_LIMIT = 1000;
|
|
15
|
+
/**
|
|
16
|
+
* Cookie defaults.
|
|
17
|
+
*/
|
|
18
|
+
export declare const DEFAULT_COOKIE_MAX_AGE = 31536000;
|
|
19
|
+
export declare const DEFAULT_COOKIE_PATH = "/";
|
|
10
20
|
/**
|
|
11
21
|
* Approved theme scales - only these scales are allowed in theme objects.
|
|
12
22
|
*/
|
|
13
23
|
export declare const APPROVED_THEME_SCALES: ReadonlyArray<ThemeScale>;
|
|
14
24
|
/**
|
|
15
25
|
* Default themeMap mapping CSS properties to theme scales.
|
|
16
|
-
* Covers
|
|
26
|
+
* Covers common CSS properties for zero-config experience.
|
|
17
27
|
* Missing properties gracefully fallback to pattern-based auto-detection.
|
|
18
28
|
*/
|
|
19
29
|
export declare const DEFAULT_THEME_MAP: Record<string, ThemeScale>;
|
package/dist/core/compiler.d.ts
CHANGED
|
@@ -4,6 +4,17 @@
|
|
|
4
4
|
* Handles nested selectors, media queries, styled component targeting, and theme tokens.
|
|
5
5
|
*/
|
|
6
6
|
import type { CSS, Theme, ThemeScale, UtilityFunction } from "../types";
|
|
7
|
+
/**
|
|
8
|
+
* Converts a CSS object to a CSS string with proper nesting and selectors.
|
|
9
|
+
* Handles pseudo-selectors, media queries, combinators, and styled component targeting.
|
|
10
|
+
*
|
|
11
|
+
* @param obj - CSS object to convert
|
|
12
|
+
* @param selector - Current selector context
|
|
13
|
+
* @param depth - Current nesting depth
|
|
14
|
+
* @param media - Media query breakpoints
|
|
15
|
+
* @returns CSS string
|
|
16
|
+
*/
|
|
17
|
+
export declare function cssObjectToString(obj: CSS, selector?: string, depth?: number, media?: Record<string, string>): string;
|
|
7
18
|
/**
|
|
8
19
|
* Compiles CSS objects into CSS strings and generates unique class names.
|
|
9
20
|
* Handles nested selectors, media queries, styled component targeting, and theme tokens.
|
|
@@ -14,9 +14,40 @@ import type { Theme } from "../types";
|
|
|
14
14
|
*/
|
|
15
15
|
export declare function registerDefaultTheme(theme: Theme, prefix?: string): void;
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* Gets the default theme for a given prefix.
|
|
18
|
+
*
|
|
19
|
+
* @param prefix - Optional prefix for theme scoping
|
|
20
|
+
* @returns Default theme or null if not registered
|
|
21
|
+
*/
|
|
22
|
+
export declare function getDefaultTheme(prefix?: string): Theme | null;
|
|
23
|
+
/**
|
|
24
|
+
* Core theme merging logic.
|
|
25
|
+
* Merges source theme into target theme, handling nested objects.
|
|
26
|
+
* Shared implementation used by both mergeWithDefaultTheme and createTheme.
|
|
27
|
+
*
|
|
28
|
+
* @param target - Target theme to merge into
|
|
29
|
+
* @param source - Source theme to merge from
|
|
30
|
+
* @returns Merged theme
|
|
31
|
+
*/
|
|
32
|
+
export declare function mergeThemes(target: Theme, source: Theme | Partial<Theme>): Theme;
|
|
33
|
+
/**
|
|
34
|
+
* Merges a theme with the default theme if it's not already the default theme.
|
|
35
|
+
* This ensures all themes extend the default theme, keeping all original properties.
|
|
36
|
+
* Uses caching to avoid repeated merging of the same theme objects.
|
|
37
|
+
*
|
|
38
|
+
* @param theme - Theme to merge
|
|
39
|
+
* @param prefix - Optional prefix for theme scoping
|
|
40
|
+
* @returns Merged theme (or original if it's the default theme)
|
|
41
|
+
*/
|
|
42
|
+
export declare function mergeWithDefaultTheme(theme: Theme, prefix?: string): Theme;
|
|
43
|
+
/**
|
|
44
|
+
* Injects CSS variables for all themes using attribute selectors.
|
|
45
|
+
* This allows all themes to be available simultaneously, with theme switching
|
|
46
|
+
* handled by changing the data-theme attribute. This prevents layout shifts
|
|
47
|
+
* and eliminates the need to replace CSS variables on theme change.
|
|
18
48
|
*
|
|
19
|
-
* @param
|
|
49
|
+
* @param themes - Map of theme names to theme objects
|
|
20
50
|
* @param prefix - Optional prefix for CSS variable names
|
|
51
|
+
* @param attribute - Attribute name for theme selection (defaults to 'data-theme')
|
|
21
52
|
*/
|
|
22
|
-
export declare function
|
|
53
|
+
export declare function injectAllThemes(themes: Record<string, Theme>, prefix?: string, attribute?: string): void;
|
|
@@ -0,0 +1,30 @@
|
|
|
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 type { CSS, StoopConfig, Theme, ThemeScale } from "./types";
|
|
7
|
+
import { createCSSFunction, createKeyframesFunction } from "./api/core-api";
|
|
8
|
+
import { createGlobalCSSFunction } from "./api/global-css";
|
|
9
|
+
/**
|
|
10
|
+
* Shared implementation for creating Stoop instances.
|
|
11
|
+
* Handles common setup logic for both client and server instances.
|
|
12
|
+
* Exported for use in SSR entry point.
|
|
13
|
+
*/
|
|
14
|
+
export declare function createStoopBase(config: StoopConfig): {
|
|
15
|
+
config: StoopConfig;
|
|
16
|
+
createTheme: (overrides?: Partial<Theme>) => Theme;
|
|
17
|
+
css: ReturnType<typeof createCSSFunction>;
|
|
18
|
+
getCssText: (theme?: string | Theme) => string;
|
|
19
|
+
globalCss: ReturnType<typeof createGlobalCSSFunction>;
|
|
20
|
+
globalCssConfig: StoopConfig["globalCss"];
|
|
21
|
+
keyframes: ReturnType<typeof createKeyframesFunction>;
|
|
22
|
+
media: StoopConfig["media"];
|
|
23
|
+
mergedThemeMap: Record<string, ThemeScale>;
|
|
24
|
+
preloadTheme: (theme: string | Theme) => void;
|
|
25
|
+
sanitizedPrefix: string;
|
|
26
|
+
theme: Theme;
|
|
27
|
+
utils: StoopConfig["utils"];
|
|
28
|
+
validatedTheme: Theme;
|
|
29
|
+
warmCache: (styles: CSS[]) => void;
|
|
30
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSR-safe entry point for Stoop.
|
|
3
|
+
* Exports only server-safe APIs that don't require React.
|
|
4
|
+
* Use this import in Server Components: import { createStoop } from "stoop/ssr"
|
|
5
|
+
*
|
|
6
|
+
* This file does NOT import React types or create React components.
|
|
7
|
+
*/
|
|
8
|
+
import type { StoopConfig, StoopServerInstance } from "./types";
|
|
9
|
+
export type { CSS, Theme, StoopConfig, StoopServerInstance, UtilityFunction, ThemeScale, DefaultTheme, } from "./types";
|
|
10
|
+
export declare function createStoop(config: StoopConfig): StoopServerInstance;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
var J0=Object.freeze({}),j=1e4,GJ=5000,QJ=10,FJ=500,P=1000;var c=["colors","opacities","space","radii","sizes","fonts","fontWeights","fontSizes","lineHeights","letterSpacings","shadows","zIndices","transitions"],N={accentColor:"colors",animation:"transitions",animationDelay:"transitions",animationDuration:"transitions",animationTimingFunction:"transitions",backdropFilter:"shadows",background:"colors",backgroundColor:"colors",blockSize:"sizes",border:"colors",borderBlockColor:"colors",borderBlockEndColor:"colors",borderBlockStartColor:"colors",borderBottomColor:"colors",borderBottomLeftRadius:"radii",borderBottomRightRadius:"radii",borderColor:"colors",borderEndEndRadius:"radii",borderEndStartRadius:"radii",borderInlineColor:"colors",borderInlineEndColor:"colors",borderInlineStartColor:"colors",borderLeftColor:"colors",borderRadius:"radii",borderRightColor:"colors",borderStartEndRadius:"radii",borderStartStartRadius:"radii",borderTopColor:"colors",borderTopLeftRadius:"radii",borderTopRightRadius:"radii",bottom:"space",boxShadow:"shadows",caretColor:"colors",color:"colors",columnGap:"space",columnRuleColor:"colors",fill:"colors",filter:"shadows",flexBasis:"sizes",floodColor:"colors",font:"fontSizes",fontFamily:"fonts",fontSize:"fontSizes",fontWeight:"fontWeights",gap:"space",gridColumnGap:"space",gridGap:"space",gridRowGap:"space",height:"sizes",inlineSize:"sizes",inset:"space",insetBlock:"space",insetBlockEnd:"space",insetBlockStart:"space",insetInline:"space",insetInlineEnd:"space",insetInlineStart:"space",left:"space",letterSpacing:"letterSpacings",lightingColor:"colors",lineHeight:"lineHeights",margin:"space",marginBlock:"space",marginBlockEnd:"space",marginBlockStart:"space",marginBottom:"space",marginInline:"space",marginInlineEnd:"space",marginInlineStart:"space",marginLeft:"space",marginRight:"space",marginTop:"space",maxBlockSize:"sizes",maxHeight:"sizes",maxInlineSize:"sizes",maxWidth:"sizes",minBlockSize:"sizes",minHeight:"sizes",minInlineSize:"sizes",minWidth:"sizes",opacity:"opacities",outline:"colors",outlineColor:"colors",padding:"space",paddingBlock:"space",paddingBlockEnd:"space",paddingBlockStart:"space",paddingBottom:"space",paddingInline:"space",paddingInlineEnd:"space",paddingInlineStart:"space",paddingLeft:"space",paddingRight:"space",paddingTop:"space",right:"space",rowGap:"space",size:"sizes",stopColor:"colors",stroke:"colors",textDecorationColor:"colors",textEmphasisColor:"colors",textShadow:"shadows",top:"space",transition:"transitions",transitionDelay:"transitions",transitionDuration:"transitions",transitionProperty:"transitions",transitionTimingFunction:"transitions",width:"sizes",zIndex:"zIndices"},ZJ=Symbol.for("stoop.component");class L extends Map{maxSize;constructor(J){super();this.maxSize=J}get(J){let $=super.get(J);if($!==void 0)super.delete(J),super.set(J,$);return $}set(J,$){if(super.has(J))super.delete(J);else if(this.size>=this.maxSize){let Y=this.keys().next().value;if(Y!==void 0)super.delete(Y)}return super.set(J,$),this}}var WJ=new L(GJ),n=new L(j);function K(){return typeof window!=="undefined"&&typeof document!=="undefined"&&typeof window.document==="object"&&typeof document.createElement==="function"}function g(){return typeof process!=="undefined"&&process.env?.NODE_ENV==="production"}function v(J){return typeof J==="object"&&J!==null}function p(J){return typeof J==="object"&&J!==null&&"__isStoopStyled"in J&&"__stoopClassName"in J&&J.__isStoopStyled===!0}function m(J){return v(J)&&!p(J)}function o(J){return typeof J==="object"&&J!==null&&!Array.isArray(J)}function x(J){if(!J||typeof J!=="object"||Array.isArray(J))throw new Error("[Stoop] Theme must be a non-null object");if(g())return J;let $=J,Y=[];for(let q in $){if(q==="media")continue;if(!c.includes(q))Y.push(q)}if(Y.length>0){let q=`[Stoop] Theme contains invalid scales: ${Y.join(", ")}. Only these scales are allowed: ${c.join(", ")}`;throw new Error(q)}return J}function z(J,$){if(!$||!J||typeof J!=="object")return J;let Y={},q=Object.keys($);for(let X in J){let F=J[X];if(q.includes(X)&&$[X])try{let Q=$[X](F);if(Q&&typeof Q==="object")for(let Z in Q)Y[Z]=Q[Z]}catch{Y[X]=F}else if(v(F))Y[X]=z(F,$);else Y[X]=F}return Y}var l=null,DJ=new L(P),wJ=new L(P),Z0=new L(P),HJ=new L(P);function b(J){let q=2166136261;for(let X=0;X<J.length;X++)q^=J.charCodeAt(X),q=Math.imul(q,16777619);return q^=J.length,(q>>>0).toString(36)}function T(J){try{return b(JSON.stringify(J))}catch{return b(String(J))}}function cJ(J){return J.replace(/([A-Z])/g,"-$1").toLowerCase()}function UJ(J,$=!1){let q=String(J).replace(/\\/g,"\\\\").replace(/"/g,"\\\"").replace(/'/g,"\\'").replace(/;/g,"\\;").replace(/\n/g,"\\A ").replace(/\r/g,"").replace(/\f/g,"\\C ");if($)q=q.replace(/\{/g,"\\7B ").replace(/\}/g,"\\7D ");return q}function BJ(J){return UJ(J,!1)}function I(J){let $=DJ.get(J);if($!==void 0)return $;let Y=J.replace(/[^a-zA-Z0-9\s\-_>+~:.#[\]&@()]/g,""),q=!Y.trim()||/^[>+~:.#[\]&@()\s]+$/.test(Y)?"":Y;return DJ.set(J,q),q}function R(J){let $=HJ.get(J);if($!==void 0)return $;let X=J.replace(/[^a-zA-Z0-9-_]/g,"-").replace(/^[\d-]+/,"").replace(/^-+/,"")||"invalid";return HJ.set(J,X),X}function LJ(J){return UJ(J,!0)}function B(J){if(!J)return"stoop";return J.replace(/[^a-zA-Z0-9-_]/g,"").replace(/^[\d-]+/,"").replace(/^-+/,"")||"stoop"}function _J(J){if(!J||typeof J!=="string")return"";let $=J.replace(/[^a-zA-Z0-9\s():,<>=\-@]/g,"");if(!$.trim()||!/[a-zA-Z]/.test($))return"";return $}function C(J){if(!J||typeof J!=="string")return"";let $=wJ.get(J);if($!==void 0)return $;let X=cJ(J).replace(/[^a-zA-Z0-9-]/g,"").replace(/^-+|-+$/g,"").replace(/^\d+/,"")||"";return wJ.set(J,X),X}function AJ(J){if(!J||typeof J!=="string")return!1;if(J==="from"||J==="to")return!0;if(/^\d+(\.\d+)?%$/.test(J)){let Y=parseFloat(J);return Y>=0&&Y<=100}return!1}function KJ(J=""){if(!l){let Y=":root".replace(/[.*+?^${}()|[\]\\]/g,"\\$&");l=new RegExp(`${Y}\\s*\\{[\\s\\S]*\\}`)}return l}function nJ(J){if(J.includes("Color")||J==="fill"||J==="stroke"||J==="accentColor"||J==="caretColor"||J==="border"||J==="outline"||J.includes("background")&&!J.includes("Size")&&!J.includes("Image"))return"colors";if(/^(margin|padding|gap|inset|top|right|bottom|left|rowGap|columnGap|gridGap|gridRowGap|gridColumnGap)/.test(J)||J.includes("Block")||J.includes("Inline"))return"space";if(/(width|height|size|basis)$/i.test(J)||J.includes("BlockSize")||J.includes("InlineSize"))return"sizes";if(J==="fontSize"||J==="font"&&!J.includes("Family"))return"fontSizes";if(J==="fontFamily"||J.includes("FontFamily"))return"fonts";if(J==="fontWeight"||J.includes("FontWeight"))return"fontWeights";if(J==="letterSpacing"||J.includes("LetterSpacing"))return"letterSpacings";if(J.includes("Radius")||J.includes("radius"))return"radii";if(J.includes("Shadow")||J.includes("shadow")||J==="filter"||J==="backdropFilter")return"shadows";if(J==="zIndex"||J.includes("ZIndex")||J.includes("z-index"))return"zIndices";if(J==="opacity"||J.includes("Opacity"))return"opacities";if(J.startsWith("transition")||J.startsWith("animation")||J.includes("Transition")||J.includes("Animation"))return"transitions";return}function OJ(J,$){if($&&J in $)return $[J];if(J in N)return N[J];return nJ(J)}var r=new Map;function S(J){return r.has(J)}function f(J,$){r.set(J,$)}var i=new L(j);function MJ(J){if(!i.has(J))i.set(J,!0)}function IJ(){return Array.from(i.keys()).join(`
|
|
2
|
+
`)}var k=new Map;var RJ=new Map;function EJ(J="stoop"){if(!K())throw new Error("Cannot access document in SSR context");let $=B(J),Y=k.get($);if(!Y||!Y.parentNode){let q=document.getElementById("stoop-ssr");if(q){let X=q.getAttribute("data-stoop");if(!X||X===$)return Y=q,Y.setAttribute("data-stoop",$),k.set($,Y),Y}Y=document.createElement("style"),Y.setAttribute("data-stoop",$),Y.setAttribute("id",`stoop-${$}`),document.head.appendChild(Y),k.set($,Y)}return Y}function a(J){let $=J,Y=KJ("");$=$.replace(Y,"").trim();let q=$.indexOf("[data-theme=");while(q!==-1){let X=$.indexOf("{",q);if(X===-1)break;let F=1,Q=X+1;while(Q<$.length&&F>0){if($[Q]==="{")F++;else if($[Q]==="}")F--;Q++}if(F===0){let Z=$.substring(0,q).trim(),G=$.substring(Q).trim();$=(Z+`
|
|
3
|
+
`+G).trim()}else break;q=$.indexOf("[data-theme=")}return $.trim()}function VJ(J,$="stoop"){if(!J)return;let Y=B($),q=`__all_theme_vars_${Y}`;if((RJ.get(q)??null)===J)return;if(RJ.set(q,J),!K()){MJ(J);return}let F=EJ(Y),Q=F.textContent||"",Z=Q.includes(":root")||Q.includes("[data-theme=");if(S(q)||Z){let G=a(Q);F.textContent=J+(G?`
|
|
4
|
+
|
|
5
|
+
`+G:""),f(q,J)}else F.textContent=J+(Q?`
|
|
6
|
+
|
|
7
|
+
`+Q:""),f(q,J)}function pJ(J,$,Y="stoop"){if(!K())return;let q=B(Y);if(S($))return;let X=EJ(q),F=X.textContent||"";X.textContent=F+(F?`
|
|
8
|
+
`:"")+J,f($,J)}function mJ(J,$,Y="stoop"){if(S($))return;let q=B(Y);pJ(J,$,q)}function oJ(J="stoop"){let $=B(J);return k.get($)||null}function lJ(){return new Map(r)}function M(J,$="stoop",Y){let q=Y||J;if(!K()){if(!S(q))f(q,J);MJ(J);return}mJ(J,q,$)}function PJ(J="stoop"){if(K()){let $=B(J),Y=oJ($);if(Y&&Y.parentNode){let q=Y.textContent||"";if(!q&&lJ().size>0)return IJ();return q}}return IJ()}var iJ=/(-?\$[a-zA-Z][a-zA-Z0-9]*(?:\$[a-zA-Z][a-zA-Z0-9]*)?(?:\.[a-zA-Z][a-zA-Z0-9]*)?)/g;function t(J){let $=new Map;function Y(q,X=[]){let F=Object.keys(q);for(let Q of F){let Z=q[Q],G=[...X,Q];if(o(Z))Y(Z,G);else{let D=$.get(Q);if(D)D.push(G);else $.set(Q,[G])}}}Y(J);for(let[,q]of $.entries())if(q.length>1)q.sort((X,F)=>{let Q=X.length-F.length;if(Q!==0)return Q;let Z=X.join("."),G=F.join(".");return Z.localeCompare(G)});return $}function rJ(J,$){let Y=Object.keys(J).filter((X)=>X!=="media"),q=Object.keys($).filter((X)=>X!=="media");if(Y.length!==q.length)return!1;for(let X of Y)if(!(X in $))return!1;return!0}function zJ(J,$){if(J===$)return!0;if(!J||!$)return!1;if(!rJ(J,$))return!1;let Y={...J},q={...$};return delete Y.media,delete q.media,JSON.stringify(Y)===JSON.stringify(q)}function s(J,$,Y){if(Y&&Y in J){let F=J[Y];if(F&&typeof F==="object"&&!Array.isArray(F)&&$ in F)return[Y,$]}let X=t(J).get($);if(!X||X.length===0)return null;return X[0]}function NJ(J,$,Y,q){if(!J.startsWith("$"))return J;let X=J.slice(1);if(X.includes("$")||X.includes("."))return`var(${`--${(X.includes("$")?X.split("$"):X.split(".")).map((W)=>R(W)).join("-")}`})`;if($&&Y){let Z=OJ(Y,q);if(Z){let w=s($,X,Z);if(w)return`var(${`--${w.map((A)=>R(A)).join("-")}`})`}let D=t($).get(X);if(D&&D.length>1){if(!g()){let w=Z?`Property "${Y}" maps to "${Z}" scale, but token not found there. `:`No scale mapping found for property "${Y}". `;console.warn(`[Stoop] Ambiguous token "$${X}" found in multiple categories: ${D.map((H)=>H.join(".")).join(", ")}. ${w}Using "${D[0].join(".")}" (deterministic: shorter paths first, then alphabetical). Use full path "$${D[0].join(".")}" to be explicit.`)}}let W=s($,X);if(W)return`var(${`--${W.map((U)=>R(U)).join("-")}`})`}else if($){let G=t($).get(X);if(G&&G.length>1){if(!g())console.warn(`[Stoop] Ambiguous token "$${X}" found in multiple categories: ${G.map((W)=>W.join(".")).join(", ")}. Using "${G[0].join(".")}" (deterministic: shorter paths first, then alphabetical). Use full path "$${G[0].join(".")}" to be explicit, or use with a CSS property for automatic resolution.`)}let D=s($,X);if(D)return`var(${`--${D.map((H)=>R(H)).join("-")}`})`}return`var(${`--${R(X)}`})`}function e(J,$="stoop",Y){let q=Y||":root",X=[];function F(Q,Z=[]){let G=Object.keys(Q).sort();for(let D of G){if(D==="media")continue;let W=Q[D],w=[...Z,D];if(o(W))F(W,w);else{let U=`--${w.map((y)=>R(y)).join("-")}`,A=typeof W==="string"||typeof W==="number"?LJ(W):String(W);X.push(` ${U}: ${A};`)}}}if(F(J),X.length===0)return"";return`${q} {
|
|
9
|
+
${X.join(`
|
|
10
|
+
`)}
|
|
11
|
+
}`}function d(J,$="stoop",Y="data-theme"){let q=[];for(let[X,F]of Object.entries(J)){let Q=`[${Y}="${X}"]`,Z=e(F,$,Q);if(Z)q.push(Z)}return q.join(`
|
|
12
|
+
|
|
13
|
+
`)}function E(J,$,Y,q){if(!J||typeof J!=="object")return J;let X={},F=!1,Q=Object.keys(J).sort();for(let Z of Q){let G=J[Z];if(v(G)){let D=E(G,$,Y,void 0);if(X[Z]=D,D!==G)F=!0}else if(typeof G==="string"&&G.includes("$")){F=!0;let D=q||Z;X[Z]=G.replace(iJ,(W)=>{if(W.startsWith("-$")){let w=W.slice(1);return`calc(-1 * ${NJ(w,$,D,Y)})`}return NJ(W,$,D,Y)})}else X[Z]=G}if(!F)return J;return X}function aJ(J,$){if(typeof J==="symbol"&&J===ZJ)return!0;if(p($))return!0;if(typeof J==="string"&&J.startsWith("__STOOP_COMPONENT_"))return!0;return!1}function sJ(J,$){if(typeof $==="object"&&$!==null&&"__stoopClassName"in $&&typeof $.__stoopClassName==="string")return $.__stoopClassName;if(typeof J==="string"&&J.startsWith("__STOOP_COMPONENT_"))return J.replace("__STOOP_COMPONENT_","");return""}function _(J,$="",Y=0,q){if(!J||typeof J!=="object")return"";if(Y>QJ)return"";let X=[],F=[],Q=Object.keys(J).sort();for(let G of Q){let D=J[G];if(aJ(G,D)){let W=sJ(G,D);if(!W)continue;let w=I(W);if(!w)continue;let H=$?`${$} .${w}`:`.${w}`,U=m(D)?_(D,H,Y+1,q):"";if(U)F.push(U);continue}if(m(D))if(q&&G in q){let W=_J(q[G]);if(W){let w=_(D,$,Y+1,q);if(w)F.push(`${W} { ${w} }`)}}else if(G.startsWith("@")){let W=I(G);if(W){let w=_(D,$,Y+1,q);if(w)F.push(`${W} { ${w} }`)}}else if(G.includes("&")){let W=I(G);if(W){let H=W.split("&").join($),U=_(D,H,Y+1,q);if(U)F.push(U)}}else if(G.startsWith(":")){let W=I(G);if(W){let w=`${$}${W}`,H=_(D,w,Y+1,q);if(H)F.push(H)}}else if(G.includes(" ")||G.includes(">")||G.includes("+")||G.includes("~")){let W=I(G);if(W){let H=/^[\s>+~]/.test(W.trim())?`${$}${W}`:`${$} ${W}`,U=_(D,H,Y+1,q);if(U)F.push(U)}}else{let W=I(G);if(W){let w=$?`${$} ${W}`:W,H=_(D,w,Y+1,q);if(H)F.push(H)}}else if(D!==void 0){let W=C(G);if(W&&(typeof D==="string"||typeof D==="number")){let w=BJ(D);X.push(`${W}: ${w};`)}}}let Z=[];if(X.length>0)Z.push(`${$} { ${X.join(" ")} }`);return Z.push(...F),Z.join("")}function u(J,$,Y="stoop",q,X,F){let Q=B(Y),Z=z(J,X),G=E(Z,$,F),D=_(G,"",0,q),W=b(D),w=Q?`${Q}-${W}`:`css-${W}`,H=`${Q}:${w}`,U=n.get(H);if(U)return M(U,Q,H),w;let A=_(G,`.${w}`,0,q);return n.set(H,A),WJ.set(H,w),M(A,Q,H),w}var jJ=new Map;function gJ(J,$="stoop"){let Y=$||"";jJ.set(Y,J)}function tJ(J="stoop"){let $=J||"";return jJ.get($)||null}function JJ(J,$){let Y={...J},q=Object.keys($);for(let X of q){if(X==="media")continue;let F=$[X],Q=J[X];if(F&&typeof F==="object"&&!Array.isArray(F)&&Q&&typeof Q==="object"&&!Array.isArray(Q))Y[X]={...Q,...F};else if(F!==void 0)Y[X]=F}return Y}function $J(J,$="stoop"){let Y=tJ($);if(!Y)return J;if(zJ(J,Y))return J;return JJ(Y,J)}function vJ(J,$="stoop",Y="data-theme"){if(!K())return;let q={};for(let[F,Q]of Object.entries(J))q[F]=$J(Q,$);let X=d(q,$,Y);VJ(X,$)}function xJ(J){return function $(Y={}){let q=x(Y);return JJ(J,q)}}function bJ(J,$="stoop",Y,q,X){return function F(Q){return u(Q,J,$,Y,q,X)}}function eJ(J,$,Y,q){let X=`@keyframes ${$} {`,F=Object.keys(J).sort((Q,Z)=>{let G=parseFloat(Q.replace("%","")),D=parseFloat(Z.replace("%",""));if(Q==="from")return-1;if(Z==="from")return 1;if(Q==="to")return 1;if(Z==="to")return-1;return G-D});for(let Q of F){if(!AJ(Q))continue;let Z=J[Q];if(!Z||typeof Z!=="object")continue;X+=` ${Q} {`;let G=E(Z,Y,q),D=Object.keys(G).sort();for(let W of D){let w=G[W];if(w!==void 0&&(typeof w==="string"||typeof w==="number")){let H=C(W);if(H){let U=String(w);X+=` ${H}: ${U};`}}}X+=" }"}return X+=" }",X}function TJ(J="stoop",$,Y){let q=B(J),X=new L(FJ);return function F(Q){let Z=T(Q),G=X.get(Z);if(G)return G;let D=Z.slice(0,8),W=q?`${q}-${D}`:`stoop-${D}`,w=eJ(Q,W,$,Y),H=`__keyframes_${W}`;return M(w,q,H),X.set(Z,W),W}}var YJ=new Set;function CJ(J,$="stoop",Y,q,X){return function F(Q){let Z=T(Q);if(YJ.has(Z))return()=>{};YJ.add(Z);let G=B($),D=z(Q,q),W=E(D,J,X),w=_(W,"",0,Y);return M(w,G,`__global_${Z}`),()=>{YJ.delete(Z)}}}function kJ(J){let{globalCss:$,media:Y,prefix:q="stoop",theme:X,themeMap:F,utils:Q}=J,Z=B(q),G=x(X),D=G.media||Y,W={...N,...F};gJ(G,Z);let w=bJ(G,Z,D,Q,W),H=xJ(G),U=CJ(G,Z,D,Q,W),A=TJ(Z,G,W),y=Object.freeze({...G});function fJ(h){for(let O of h)try{u(O,G,Z,D,Q,W)}catch{}}function SJ(h){if(!J.themes||Object.keys(J.themes).length===0)return;vJ(J.themes,Z)}function dJ(h){let O="";if(J.themes&&Object.keys(J.themes).length>0){let V={};for(let[yJ,hJ]of Object.entries(J.themes))V[yJ]=$J(hJ,Z);let XJ=d(V,Z,"data-theme");if(XJ)O+=XJ+`
|
|
14
|
+
`}else{let V=e(G,Z);if(V)O+=V+`
|
|
15
|
+
`}let uJ=PJ(),qJ=a(uJ).trim();if(qJ)O+=(O?`
|
|
16
|
+
`:"")+qJ;return O}return{config:{...J,prefix:Z},createTheme:H,css:w,getCssText:dJ,globalCss:U,globalCssConfig:$,keyframes:A,media:D,mergedThemeMap:W,preloadTheme:SJ,sanitizedPrefix:Z,theme:y,utils:Q,validatedTheme:G,warmCache:fJ}}function Y1(J){let $=kJ(J);return{config:{...$.config,prefix:$.sanitizedPrefix},createTheme:$.createTheme,css:$.css,getCssText:$.getCssText,globalCss:$.globalCss,keyframes:$.keyframes,preloadTheme:$.preloadTheme,theme:$.theme,warmCache:$.warmCache}}export{Y1 as createStoop};
|
package/dist/create-stoop.d.ts
CHANGED
|
@@ -1,9 +1,40 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Factory function that creates a Stoop instance.
|
|
3
|
+
* Supports both client-side (with React APIs) and server-side (without React) usage.
|
|
4
|
+
* Automatically detects environment and includes appropriate APIs.
|
|
5
|
+
*/
|
|
6
|
+
import type { CSS, StoopConfig, StoopInstance, Theme, ThemeScale } from "./types";
|
|
7
|
+
import { createCSSFunction, createKeyframesFunction } from "./api/core-api";
|
|
8
|
+
import { createGlobalCSSFunction } from "./api/global-css";
|
|
9
|
+
/**
|
|
10
|
+
* Shared implementation for creating Stoop instances.
|
|
11
|
+
* Handles common setup logic for both client and server instances.
|
|
12
|
+
* Exported for use in SSR entry point.
|
|
13
|
+
*/
|
|
14
|
+
export declare function createStoopBase(config: StoopConfig): {
|
|
15
|
+
config: StoopConfig;
|
|
16
|
+
createTheme: (overrides?: Partial<Theme>) => Theme;
|
|
17
|
+
css: ReturnType<typeof createCSSFunction>;
|
|
18
|
+
getCssText: (theme?: string | Theme) => string;
|
|
19
|
+
globalCss: ReturnType<typeof createGlobalCSSFunction>;
|
|
20
|
+
globalCssConfig: StoopConfig["globalCss"];
|
|
21
|
+
keyframes: ReturnType<typeof createKeyframesFunction>;
|
|
22
|
+
media: StoopConfig["media"];
|
|
23
|
+
mergedThemeMap: Record<string, ThemeScale>;
|
|
24
|
+
preloadTheme: (theme: string | Theme) => void;
|
|
25
|
+
sanitizedPrefix: string;
|
|
26
|
+
theme: Theme;
|
|
27
|
+
utils: StoopConfig["utils"];
|
|
28
|
+
validatedTheme: Theme;
|
|
29
|
+
warmCache: (styles: CSS[]) => void;
|
|
30
|
+
};
|
|
2
31
|
/**
|
|
3
32
|
* Creates a Stoop instance with the provided configuration.
|
|
4
33
|
* Includes all APIs: styled, Provider, useTheme, etc.
|
|
34
|
+
* In server contexts without React, React APIs will be undefined.
|
|
5
35
|
*
|
|
6
36
|
* @param config - Configuration object containing theme, media queries, utilities, and optional prefix/themeMap
|
|
7
37
|
* @returns StoopInstance with all API functions
|
|
8
38
|
*/
|
|
39
|
+
export type { CSS, Theme, StoopConfig, StoopInstance, UtilityFunction, ThemeScale, DefaultTheme, } from "./types";
|
|
9
40
|
export declare function createStoop(config: StoopConfig): StoopInstance;
|