@@ -93,6 +93,45 @@ const globalResult = injectGlobal([
9393globalResult .dispose ();
9494```
9595
96+ ### ` createGlobalStyle<Props>(strings, ...interpolations): ComponentType `
97+
98+ Creates a React component that injects global styles when mounted (similar to styled-components).
99+
100+ ``` typescript
101+ import { createGlobalStyle } from ' @cube-dev/ui-kit/tasty/injector' ;
102+
103+ const GlobalReset = createGlobalStyle <{ theme: ' dark' | ' light' }>`
104+ body {
105+ margin: 0;
106+ background: ${props => props .theme === ' dark' ? ' #000' : ' #fff' };
107+ color: ${props => props .theme === ' dark' ? ' #fff' : ' #000' };
108+ }
109+
110+ * {
111+ box-sizing: border-box;
112+ }
113+ ` ;
114+
115+ // Usage in React
116+ < GlobalReset theme = " dark" / >
117+ ```
118+
119+ ### ` createInjector(config?): StyleInjector `
120+
121+ Creates an isolated injector instance with custom configuration.
122+
123+ ``` typescript
124+ import { createInjector } from ' @cube-dev/ui-kit/tasty/injector' ;
125+
126+ // Create isolated instance for testing
127+ const testInjector = createInjector ({
128+ devMode: true ,
129+ forceTextInjection: true ,
130+ });
131+
132+ const result = testInjector .inject (rules );
133+ ```
134+
96135### ` keyframes(steps, nameOrOptions?): KeyframesResult `
97136
98137Injects CSS keyframes with automatic deduplication.
@@ -127,17 +166,27 @@ Configures the global injector instance.
127166
128167``` typescript
129168configure ({
130- devMode: true , // Enable development features
131- maxRulesPerSheet: 8000 , // Cap rules per stylesheet
169+ devMode: true , // Enable development features (auto-detected)
170+ maxRulesPerSheet: 8192 , // Cap rules per stylesheet (default: 8192)
132171 unusedStylesThreshold: 500 , // Trigger cleanup threshold (CSS rules only)
133- bulkCleanupDelay: 5000 , // Cleanup delay (ms)
134- idleCleanup: true , // Use requestIdleCallback
172+ bulkCleanupDelay: 5000 , // Cleanup delay (ms) - ignored if idleCleanup is true
173+ idleCleanup: true , // Use requestIdleCallback for cleanup
135174 bulkCleanupBatchRatio: 0.5 , // Clean up oldest 50% per batch
136- forceTextInjection: false , // Force textContent insertion
175+ unusedStylesMinAgeMs: 10000 , // Minimum age before cleanup (ms)
176+ forceTextInjection: false , // Force textContent insertion (auto-detected for tests)
137177 nonce: ' csp-nonce' , // CSP nonce for security
138178});
139179```
140180
181+ ** Auto-Detection Features:**
182+ - ` devMode ` : Automatically enabled in development environments (detected via ` isDevEnv() ` )
183+ - ` forceTextInjection ` : Automatically enabled in test environments (Jest, Vitest, Mocha, jsdom)
184+
185+ ** Configuration Notes:**
186+ - Most options have sensible defaults and auto-detection
187+ - ` configure() ` is optional - the injector works with defaults
188+ - ` unusedStylesMinAgeMs ` : Minimum time (ms) a style must remain unused before being eligible for cleanup. Helps prevent removal of styles that might be quickly reactivated.
189+
141190---
142191
143192## 🔧 Advanced Features
@@ -240,7 +289,9 @@ const shadowAnimation = keyframes({
240289### Server-Side Rendering
241290
242291``` typescript
243- // Extract CSS for SSR
292+ import { getCssText , getCssTextForNode } from ' @cube-dev/ui-kit/tasty/injector' ;
293+
294+ // Extract all CSS for SSR
244295const cssText = getCssText ();
245296
246297// Extract CSS for specific DOM subtree (like jest-styled-components)
@@ -253,10 +304,12 @@ const componentCSS = getCssTextForNode(container);
253304``` typescript
254305// Automatically detected test environments:
255306// - NODE_ENV === 'test'
256- // - Jest globals (describe, it, expect)
307+ // - Jest globals (jest, describe, it, expect)
257308// - jsdom user agent
258- // - Vitest, Mocha globals
309+ // - Vitest globals (vitest)
310+ // - Mocha globals (mocha)
259311
312+ import { getIsTestEnvironment } from ' @cube-dev/ui-kit/tasty/injector' ;
260313const isTest = getIsTestEnvironment ();
261314
262315// Test-specific optimizations:
@@ -297,10 +350,13 @@ const metrics = injector.instance.getMetrics();
297350console .log ({
298351 cacheHits: metrics .hits , // Successful cache hits
299352 cacheMisses: metrics .misses , // New styles injected
300- unusedHits: metrics .unusedHits , // Current unused styles (calculated)
301- bulkCleanups: metrics .bulkCleanups , // CSS cleanup operations (keyframes disposed immediately)
302- stylesCleanedUp: metrics .stylesCleanedUp , // Total styles removed
353+ unusedHits: metrics .unusedHits , // Current unused styles (calculated on demand )
354+ bulkCleanups: metrics .bulkCleanups , // Number of bulk cleanup operations
355+ stylesCleanedUp: metrics .stylesCleanedUp , // Total styles removed in bulk cleanups
303356 totalInsertions: metrics .totalInsertions , // Lifetime insertions
357+ totalUnused: metrics .totalUnused , // Total styles marked as unused (refCount = 0)
358+ startTime: metrics .startTime , // Metrics collection start timestamp
359+ cleanupHistory: metrics .cleanupHistory , // Detailed cleanup operation history
304360});
305361```
306362
@@ -329,7 +385,7 @@ metrics.cleanupHistory.forEach(cleanup => {
329385 timestamp: new Date (cleanup .timestamp ),
330386 classesDeleted: cleanup .classesDeleted ,
331387 rulesDeleted: cleanup .rulesDeleted ,
332- cssSize: cleanup .cssSize ,
388+ cssSize: cleanup .cssSize , // Total CSS size removed (bytes)
333389 });
334390});
335391```
@@ -356,8 +412,9 @@ injectGlobal([
356412
357413// ✅ Configure appropriate thresholds for your app
358414configure ({
359- unusedStylesThreshold: 200 , // Adjust based on component count
360- bulkCleanupBatchRatio: 0.4 , // Balance cleanup frequency vs performance
415+ unusedStylesThreshold: 500 , // Default threshold (adjust based on app size)
416+ bulkCleanupBatchRatio: 0.5 , // Default: clean oldest 50% per batch
417+ unusedStylesMinAgeMs: 10000 , // Wait 10s before cleanup eligibility
361418});
362419```
363420
0 commit comments