tailwind-to-style 4.0.2 → 5.0.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.
- package/README.md +3 -0
- package/dist/animations/index.cjs +793 -469
- package/dist/animations/index.esm.js +793 -469
- package/dist/animations/index.esm.js.map +1 -1
- package/dist/className/index.cjs +793 -469
- package/dist/className/index.d.ts +41 -0
- package/dist/className/index.esm.js +793 -469
- package/dist/className/index.esm.js.map +1 -1
- package/dist/core/tws.cjs +322 -182
- package/dist/core/tws.esm.js +322 -182
- package/dist/core/tws.esm.js.map +1 -1
- package/dist/cx.cjs +1 -1
- package/dist/cx.esm.js +1 -1
- package/dist/index.cjs +882 -505
- package/dist/index.esm.js +882 -505
- package/dist/index.esm.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/react/index.cjs +882 -505
- package/dist/react/index.esm.js +882 -505
- package/dist/react/index.esm.js.map +1 -1
- package/dist/tokens/index.cjs +1 -1
- package/dist/tokens/index.esm.js +1 -1
- package/package.json +12 -4
- package/types/README.md +214 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* tailwind-to-style
|
|
2
|
+
* tailwind-to-style v5.0.0
|
|
3
3
|
* Zero-build runtime Tailwind CSS engine
|
|
4
4
|
*
|
|
5
5
|
* @author Bigetion
|
|
@@ -2149,6 +2149,182 @@ function getActiveCollector() {
|
|
|
2149
2149
|
return _activeCollector;
|
|
2150
2150
|
}
|
|
2151
2151
|
|
|
2152
|
+
/**
|
|
2153
|
+
* Shared Constants
|
|
2154
|
+
*
|
|
2155
|
+
* All constant values used across the library.
|
|
2156
|
+
* Extracted from monolithic index.js for better maintainability.
|
|
2157
|
+
*
|
|
2158
|
+
* @module shared/constants
|
|
2159
|
+
*/
|
|
2160
|
+
|
|
2161
|
+
// ============================================================================
|
|
2162
|
+
// Environment Detection
|
|
2163
|
+
// ============================================================================
|
|
2164
|
+
|
|
2165
|
+
/**
|
|
2166
|
+
* True when running in a browser environment (window & document available)
|
|
2167
|
+
*/
|
|
2168
|
+
const IS_BROWSER$1 = typeof window !== "undefined" && typeof document !== "undefined";
|
|
2169
|
+
|
|
2170
|
+
/**
|
|
2171
|
+
* Maximum number of entries in Set-based caches
|
|
2172
|
+
*/
|
|
2173
|
+
const MAX_SET_SIZE$1 = 10000;
|
|
2174
|
+
|
|
2175
|
+
// ============================================================================
|
|
2176
|
+
// Built-in Animation Keyframes
|
|
2177
|
+
// ============================================================================
|
|
2178
|
+
|
|
2179
|
+
/**
|
|
2180
|
+
* Mapping of animation names to their keyframe definitions
|
|
2181
|
+
*/
|
|
2182
|
+
const BUILTIN_KEYFRAMES = {
|
|
2183
|
+
spin: {
|
|
2184
|
+
"0%": {
|
|
2185
|
+
transform: "rotate(0deg)"
|
|
2186
|
+
},
|
|
2187
|
+
"100%": {
|
|
2188
|
+
transform: "rotate(360deg)"
|
|
2189
|
+
}
|
|
2190
|
+
},
|
|
2191
|
+
ping: {
|
|
2192
|
+
"75%, 100%": {
|
|
2193
|
+
transform: "scale(2)",
|
|
2194
|
+
opacity: "0"
|
|
2195
|
+
}
|
|
2196
|
+
},
|
|
2197
|
+
pulse: {
|
|
2198
|
+
"50%": {
|
|
2199
|
+
opacity: ".5"
|
|
2200
|
+
}
|
|
2201
|
+
},
|
|
2202
|
+
bounce: {
|
|
2203
|
+
"0%, 100%": {
|
|
2204
|
+
transform: "translateY(-25%)",
|
|
2205
|
+
animationTimingFunction: "cubic-bezier(0.8,0,1,1)"
|
|
2206
|
+
},
|
|
2207
|
+
"50%": {
|
|
2208
|
+
transform: "none",
|
|
2209
|
+
animationTimingFunction: "cubic-bezier(0,0,0.2,1)"
|
|
2210
|
+
}
|
|
2211
|
+
},
|
|
2212
|
+
fadeIn: {
|
|
2213
|
+
"0%": {
|
|
2214
|
+
opacity: "0"
|
|
2215
|
+
},
|
|
2216
|
+
"50%": {
|
|
2217
|
+
opacity: "1"
|
|
2218
|
+
},
|
|
2219
|
+
"100%": {
|
|
2220
|
+
opacity: "0"
|
|
2221
|
+
}
|
|
2222
|
+
},
|
|
2223
|
+
slideUp: {
|
|
2224
|
+
"0%": {
|
|
2225
|
+
transform: "translateY(20px)",
|
|
2226
|
+
opacity: "0"
|
|
2227
|
+
},
|
|
2228
|
+
"50%": {
|
|
2229
|
+
transform: "translateY(0)",
|
|
2230
|
+
opacity: "1"
|
|
2231
|
+
},
|
|
2232
|
+
"100%": {
|
|
2233
|
+
transform: "translateY(-20px)",
|
|
2234
|
+
opacity: "0"
|
|
2235
|
+
}
|
|
2236
|
+
}
|
|
2237
|
+
};
|
|
2238
|
+
|
|
2239
|
+
/**
|
|
2240
|
+
* Opacity modifiers
|
|
2241
|
+
*/
|
|
2242
|
+
const OPACITY_MODIFIER_REGEX = /\/(\d+)$/;
|
|
2243
|
+
|
|
2244
|
+
/**
|
|
2245
|
+
* Opacity property patterns for substitution
|
|
2246
|
+
*/
|
|
2247
|
+
const OPACITY_PROP_REGEXES = {
|
|
2248
|
+
"--text-opacity": /--text-opacity\s*:\s*[\d.]+/gi,
|
|
2249
|
+
"--bg-opacity": /--bg-opacity\s*:\s*[\d.]+/gi,
|
|
2250
|
+
"--border-opacity": /--border-opacity\s*:\s*[\d.]+/gi,
|
|
2251
|
+
"--ring-opacity": /--ring-opacity\s*:\s*[\d.]+/gi,
|
|
2252
|
+
"--placeholder-opacity": /--placeholder-opacity\s*:\s*[\d.]+/gi,
|
|
2253
|
+
"--divide-opacity": /--divide-opacity\s*:\s*[\d.]+/gi
|
|
2254
|
+
};
|
|
2255
|
+
|
|
2256
|
+
/**
|
|
2257
|
+
* Bracket encoding/decoding
|
|
2258
|
+
*/
|
|
2259
|
+
const BRACKET_CONTENT_REGEX = /\[([^\]]+)\]/g;
|
|
2260
|
+
const OPENING_PAREN_REGEX = /\(/g;
|
|
2261
|
+
const CLOSING_PAREN_REGEX = /\)/g;
|
|
2262
|
+
const ENCODED_PAREN_OPEN_REGEX = /__P__/g;
|
|
2263
|
+
const ENCODED_PAREN_CLOSE_REGEX = /__C__/g;
|
|
2264
|
+
|
|
2265
|
+
/**
|
|
2266
|
+
* Animation detection
|
|
2267
|
+
*/
|
|
2268
|
+
const ANIMATION_NAME_REGEX = /animation(?:-name)?:\s*([a-zA-Z0-9-]+)/gi;
|
|
2269
|
+
|
|
2270
|
+
/**
|
|
2271
|
+
* Color property regex patterns (pre-compiled for each color property)
|
|
2272
|
+
* Used in processOpacityModifier for 50-100x performance improvement
|
|
2273
|
+
*/
|
|
2274
|
+
const COLOR_PROPERTIES$1 = ["color", "background-color", "border-color", "border-top-color", "border-right-color", "border-bottom-color", "border-left-color"];
|
|
2275
|
+
|
|
2276
|
+
/**
|
|
2277
|
+
* CSS property name conversion
|
|
2278
|
+
*/
|
|
2279
|
+
const UPPERCASE_LETTER_REGEX = /([A-Z])/g;
|
|
2280
|
+
|
|
2281
|
+
/**
|
|
2282
|
+
* Hash Utilities
|
|
2283
|
+
*
|
|
2284
|
+
* Fast hashing functions for string and object caching.
|
|
2285
|
+
* Extracted from monolithic index.js for reusability.
|
|
2286
|
+
*
|
|
2287
|
+
* @module shared/hash
|
|
2288
|
+
*/
|
|
2289
|
+
|
|
2290
|
+
/**
|
|
2291
|
+
* Fast string hash using FNV-1a algorithm.
|
|
2292
|
+
* Produces 32-bit hash values for cache keys.
|
|
2293
|
+
*
|
|
2294
|
+
* @param {string} str - String to hash
|
|
2295
|
+
* @returns {number} 32-bit hash
|
|
2296
|
+
*
|
|
2297
|
+
* @example
|
|
2298
|
+
* hashString('bg-blue-500') // → 2845719273
|
|
2299
|
+
* hashString('hover:bg-red-600') // → 3927461034
|
|
2300
|
+
*/
|
|
2301
|
+
function hashString$2(str) {
|
|
2302
|
+
let hash = 2166136261; // FNV offset basis
|
|
2303
|
+
for (let i = 0; i < str.length; i++) {
|
|
2304
|
+
hash ^= str.charCodeAt(i);
|
|
2305
|
+
// FNV prime: 16777619
|
|
2306
|
+
hash = hash * 16777619 >>> 0; // >>> 0 keeps it a 32-bit unsigned integer
|
|
2307
|
+
}
|
|
2308
|
+
return hash;
|
|
2309
|
+
}
|
|
2310
|
+
|
|
2311
|
+
/**
|
|
2312
|
+
* Generate a short hash for CSS class names.
|
|
2313
|
+
* Uses base36 encoding for compact, URL-safe identifiers.
|
|
2314
|
+
*
|
|
2315
|
+
* @param {string} str - Input string
|
|
2316
|
+
* @param {number} length - Desired hash length (default: 8)
|
|
2317
|
+
* @returns {string} Short hash string
|
|
2318
|
+
*
|
|
2319
|
+
* @example
|
|
2320
|
+
* getCssHash('bg-blue-500 p-4 rounded') // → 'x7k2m9n1'
|
|
2321
|
+
*/
|
|
2322
|
+
function getCssHash(str) {
|
|
2323
|
+
let length = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 8;
|
|
2324
|
+
const hash = hashString$2(str);
|
|
2325
|
+
return hash.toString(36).substring(0, length);
|
|
2326
|
+
}
|
|
2327
|
+
|
|
2152
2328
|
/**
|
|
2153
2329
|
* Proper LRU (Least Recently Used) Cache implementation
|
|
2154
2330
|
* Efficiently manages memory by removing least recently used items
|
|
@@ -2175,49 +2351,496 @@ class LRUCache {
|
|
|
2175
2351
|
return value;
|
|
2176
2352
|
}
|
|
2177
2353
|
|
|
2178
|
-
/**
|
|
2179
|
-
* Set value in cache
|
|
2180
|
-
* Removes least recently used item if cache is full
|
|
2181
|
-
*/
|
|
2182
|
-
set(key, value) {
|
|
2183
|
-
// If key exists, delete it first to update position
|
|
2184
|
-
if (this.cache.has(key)) {
|
|
2185
|
-
this.cache.delete(key);
|
|
2186
|
-
} else if (this.cache.size >= this.maxSize) {
|
|
2187
|
-
// Remove least recently used (first item)
|
|
2188
|
-
const firstKey = this.cache.keys().next().value;
|
|
2189
|
-
this.cache.delete(firstKey);
|
|
2354
|
+
/**
|
|
2355
|
+
* Set value in cache
|
|
2356
|
+
* Removes least recently used item if cache is full
|
|
2357
|
+
*/
|
|
2358
|
+
set(key, value) {
|
|
2359
|
+
// If key exists, delete it first to update position
|
|
2360
|
+
if (this.cache.has(key)) {
|
|
2361
|
+
this.cache.delete(key);
|
|
2362
|
+
} else if (this.cache.size >= this.maxSize) {
|
|
2363
|
+
// Remove least recently used (first item)
|
|
2364
|
+
const firstKey = this.cache.keys().next().value;
|
|
2365
|
+
this.cache.delete(firstKey);
|
|
2366
|
+
}
|
|
2367
|
+
this.cache.set(key, value);
|
|
2368
|
+
}
|
|
2369
|
+
|
|
2370
|
+
/**
|
|
2371
|
+
* Check if key exists in cache
|
|
2372
|
+
*/
|
|
2373
|
+
has(key) {
|
|
2374
|
+
return this.cache.has(key);
|
|
2375
|
+
}
|
|
2376
|
+
|
|
2377
|
+
/**
|
|
2378
|
+
* Clear all cache entries
|
|
2379
|
+
*/
|
|
2380
|
+
clear() {
|
|
2381
|
+
this.cache.clear();
|
|
2382
|
+
}
|
|
2383
|
+
|
|
2384
|
+
/**
|
|
2385
|
+
* Get current cache size
|
|
2386
|
+
*/
|
|
2387
|
+
get size() {
|
|
2388
|
+
return this.cache.size;
|
|
2389
|
+
}
|
|
2390
|
+
|
|
2391
|
+
/**
|
|
2392
|
+
* Delete specific key
|
|
2393
|
+
*/
|
|
2394
|
+
delete(key) {
|
|
2395
|
+
return this.cache.delete(key);
|
|
2396
|
+
}
|
|
2397
|
+
}
|
|
2398
|
+
|
|
2399
|
+
/**
|
|
2400
|
+
* Cache Management
|
|
2401
|
+
*
|
|
2402
|
+
* Global caches and cache utilities for performance optimization.
|
|
2403
|
+
* Uses LRU (Least Recently Used) strategy to prevent memory leaks.
|
|
2404
|
+
*
|
|
2405
|
+
* @module shared/cache
|
|
2406
|
+
*/
|
|
2407
|
+
|
|
2408
|
+
|
|
2409
|
+
/**
|
|
2410
|
+
* Cache for bracket value encoding
|
|
2411
|
+
* @type {LRUCache}
|
|
2412
|
+
*/
|
|
2413
|
+
const encodeBracketCache = new LRUCache(1000);
|
|
2414
|
+
|
|
2415
|
+
/**
|
|
2416
|
+
* Cache for bracket value decoding
|
|
2417
|
+
* @type {LRUCache}
|
|
2418
|
+
*/
|
|
2419
|
+
const decodeBracketCache = new LRUCache(1000);
|
|
2420
|
+
|
|
2421
|
+
/**
|
|
2422
|
+
* Set of injected CSS hashes (prevents duplicate injection)
|
|
2423
|
+
* @type {Set<string>}
|
|
2424
|
+
*/
|
|
2425
|
+
const injectedCssHashSet = new Set();
|
|
2426
|
+
|
|
2427
|
+
/**
|
|
2428
|
+
* Registry of sourceKey → cssBlock for smart slot-based replacement
|
|
2429
|
+
* Prevents stale CSS chunks from accumulating across HMR cycles
|
|
2430
|
+
* @type {Map<string, string>}
|
|
2431
|
+
*/
|
|
2432
|
+
const cssBlockRegistry = new Map();
|
|
2433
|
+
|
|
2434
|
+
/**
|
|
2435
|
+
* Evict old entries from a Set when size exceeds maxSize.
|
|
2436
|
+
*
|
|
2437
|
+
* @deprecated Use LRUCache instead - kept for backward compatibility
|
|
2438
|
+
* @param {Set|LRUCache} set - Set to evict from
|
|
2439
|
+
* @param {number} maxSize - Maximum size
|
|
2440
|
+
*/
|
|
2441
|
+
function evictSet(set) {
|
|
2442
|
+
let maxSize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : MAX_SET_SIZE$1;
|
|
2443
|
+
if (set instanceof LRUCache) return; // LRUCache handles its own eviction
|
|
2444
|
+
if (set.size <= maxSize) return;
|
|
2445
|
+
const excess = set.size - maxSize;
|
|
2446
|
+
const iter = set.values();
|
|
2447
|
+
for (let i = 0; i < excess; i++) {
|
|
2448
|
+
set.delete(iter.next().value);
|
|
2449
|
+
}
|
|
2450
|
+
}
|
|
2451
|
+
|
|
2452
|
+
/**
|
|
2453
|
+
* Generate minified CSS keyframes for animations.
|
|
2454
|
+
* Converts camelCase property names to kebab-case.
|
|
2455
|
+
*
|
|
2456
|
+
* @param {string[]} animationNames - Array of animation names to generate
|
|
2457
|
+
* @returns {string} Minified CSS @keyframes rules
|
|
2458
|
+
*
|
|
2459
|
+
* @example
|
|
2460
|
+
* generateMinifiedKeyframes(['spin', 'pulse'])
|
|
2461
|
+
* // → '@keyframes spin{0%{transform:rotate(0deg);}100%{transform:rotate(360deg);}}
|
|
2462
|
+
* // @keyframes pulse{50%{opacity:.5;}}'
|
|
2463
|
+
*
|
|
2464
|
+
* @example
|
|
2465
|
+
* generateMinifiedKeyframes(['fadeIn'])
|
|
2466
|
+
* // → '@keyframes fadeIn{0%{opacity:0;}50%{opacity:1;}100%{opacity:0;}}'
|
|
2467
|
+
*/
|
|
2468
|
+
function generateMinifiedKeyframes(animationNames) {
|
|
2469
|
+
let css = "";
|
|
2470
|
+
for (const name of animationNames) {
|
|
2471
|
+
const keyframe = BUILTIN_KEYFRAMES[name];
|
|
2472
|
+
if (!keyframe) continue;
|
|
2473
|
+
css += "@keyframes ".concat(name, "{");
|
|
2474
|
+
for (const _ref of Object.entries(keyframe)) {
|
|
2475
|
+
var _ref2 = _slicedToArray(_ref, 2);
|
|
2476
|
+
const percentage = _ref2[0];
|
|
2477
|
+
const styles = _ref2[1];
|
|
2478
|
+
css += "".concat(percentage, "{");
|
|
2479
|
+
for (const _ref3 of Object.entries(styles)) {
|
|
2480
|
+
var _ref4 = _slicedToArray(_ref3, 2);
|
|
2481
|
+
const prop = _ref4[0];
|
|
2482
|
+
const value = _ref4[1];
|
|
2483
|
+
const cssProp = prop.replace(UPPERCASE_LETTER_REGEX, "-$1").toLowerCase();
|
|
2484
|
+
css += "".concat(cssProp, ":").concat(value, ";");
|
|
2485
|
+
}
|
|
2486
|
+
css += "}";
|
|
2487
|
+
}
|
|
2488
|
+
css += "}";
|
|
2489
|
+
}
|
|
2490
|
+
return css;
|
|
2491
|
+
}
|
|
2492
|
+
|
|
2493
|
+
/**
|
|
2494
|
+
* Opacity Modifier Processing
|
|
2495
|
+
*
|
|
2496
|
+
* Handles Tailwind opacity modifiers (e.g., bg-blue-500/50).
|
|
2497
|
+
* Converts color values to rgba/hsla with specified opacity.
|
|
2498
|
+
*
|
|
2499
|
+
* @module generator/opacity
|
|
2500
|
+
*/
|
|
2501
|
+
|
|
2502
|
+
|
|
2503
|
+
// Pre-compile regex patterns for each color property
|
|
2504
|
+
const COLOR_REGEX_PATTERNS$1 = new Map();
|
|
2505
|
+
for (const prop of COLOR_PROPERTIES$1) {
|
|
2506
|
+
const escapedProp = prop.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2507
|
+
COLOR_REGEX_PATTERNS$1.set(prop, {
|
|
2508
|
+
rgb: new RegExp("(".concat(escapedProp, "\\s*:\\s*)rgb\\((\\d+),\\s*(\\d+),\\s*(\\d+)\\)"), "gi"),
|
|
2509
|
+
rgba: new RegExp("(".concat(escapedProp, "\\s*:\\s*)rgba\\((\\d+),\\s*(\\d+),\\s*(\\d+),\\s*[\\d.]+\\)"), "gi"),
|
|
2510
|
+
hsl: new RegExp("(".concat(escapedProp, "\\s*:\\s*)hsl\\((\\d+),\\s*([\\d.]+%),\\s*([\\d.]+%)\\)"), "gi"),
|
|
2511
|
+
hsla: new RegExp("(".concat(escapedProp, "\\s*:\\s*)hsla\\((\\d+),\\s*([\\d.]+%),\\s*([\\d.]+%),\\s*[\\d.]+\\)"), "gi"),
|
|
2512
|
+
hex: new RegExp("(".concat(escapedProp, "\\s*:\\s*)(#[0-9a-fA-F]{3,6})"), "gi")
|
|
2513
|
+
});
|
|
2514
|
+
}
|
|
2515
|
+
|
|
2516
|
+
/**
|
|
2517
|
+
* Process opacity modifiers in Tailwind classes.
|
|
2518
|
+
*
|
|
2519
|
+
* Handles:
|
|
2520
|
+
* - Tailwind CSS custom properties (--text-opacity, --bg-opacity, etc.)
|
|
2521
|
+
* - Direct color values (rgb, rgba, hsl, hsla, hex)
|
|
2522
|
+
* - Converts colors to rgba/hsla with specified opacity
|
|
2523
|
+
*
|
|
2524
|
+
* @param {string} className - Tailwind class name (e.g., 'bg-blue-500/50')
|
|
2525
|
+
* @param {string} cssDeclaration - CSS declaration to modify
|
|
2526
|
+
* @returns {string} Modified CSS declaration with opacity applied
|
|
2527
|
+
*
|
|
2528
|
+
* @example
|
|
2529
|
+
* processOpacityModifier('bg-blue-500/50', 'background-color: rgb(59, 130, 246);')
|
|
2530
|
+
* // → 'background-color: rgba(59, 130, 246, 0.5);'
|
|
2531
|
+
*
|
|
2532
|
+
* @example
|
|
2533
|
+
* processOpacityModifier('text-red-600/75', 'color: #dc2626;')
|
|
2534
|
+
* // → 'color: rgba(220, 38, 38, 0.75);'
|
|
2535
|
+
*
|
|
2536
|
+
* @example
|
|
2537
|
+
* processOpacityModifier('bg-blue-500', 'background-color: rgb(59, 130, 246);')
|
|
2538
|
+
* // → 'background-color: rgb(59, 130, 246);' (no change - no opacity modifier)
|
|
2539
|
+
*/
|
|
2540
|
+
function processOpacityModifier(className, cssDeclaration) {
|
|
2541
|
+
const opacityMatch = OPACITY_MODIFIER_REGEX.exec(className);
|
|
2542
|
+
if (!opacityMatch) return cssDeclaration;
|
|
2543
|
+
const opacityValue = parseInt(opacityMatch[1], 10);
|
|
2544
|
+
if (opacityValue < 0 || opacityValue > 100) return cssDeclaration;
|
|
2545
|
+
const alphaValue = (opacityValue / 100).toString();
|
|
2546
|
+
|
|
2547
|
+
// Handle Tailwind's CSS custom property pattern
|
|
2548
|
+
let modifiedDeclaration = cssDeclaration;
|
|
2549
|
+
|
|
2550
|
+
// Replace opacity custom properties using pre-compiled regexes
|
|
2551
|
+
for (const prop in OPACITY_PROP_REGEXES) {
|
|
2552
|
+
const regex = OPACITY_PROP_REGEXES[prop];
|
|
2553
|
+
regex.lastIndex = 0; // Reset global regex
|
|
2554
|
+
modifiedDeclaration = modifiedDeclaration.replace(regex, "".concat(prop, ": ").concat(alphaValue));
|
|
2555
|
+
}
|
|
2556
|
+
|
|
2557
|
+
// Also handle direct color values using pre-compiled regex patterns
|
|
2558
|
+
for (const prop of COLOR_PROPERTIES$1) {
|
|
2559
|
+
const patterns = COLOR_REGEX_PATTERNS$1.get(prop);
|
|
2560
|
+
if (!patterns) continue;
|
|
2561
|
+
|
|
2562
|
+
// Reset all regex lastIndex for reuse
|
|
2563
|
+
patterns.rgb.lastIndex = 0;
|
|
2564
|
+
patterns.rgba.lastIndex = 0;
|
|
2565
|
+
patterns.hsl.lastIndex = 0;
|
|
2566
|
+
patterns.hsla.lastIndex = 0;
|
|
2567
|
+
patterns.hex.lastIndex = 0;
|
|
2568
|
+
|
|
2569
|
+
// Convert rgb to rgba with opacity
|
|
2570
|
+
modifiedDeclaration = modifiedDeclaration.replace(patterns.rgb, "$1rgba($2, $3, $4, ".concat(alphaValue, ")"));
|
|
2571
|
+
|
|
2572
|
+
// Update existing rgba opacity
|
|
2573
|
+
modifiedDeclaration = modifiedDeclaration.replace(patterns.rgba, "$1rgba($2, $3, $4, ".concat(alphaValue, ")"));
|
|
2574
|
+
|
|
2575
|
+
// Convert hsl to hsla with opacity
|
|
2576
|
+
modifiedDeclaration = modifiedDeclaration.replace(patterns.hsl, "$1hsla($2, $3, $4, ".concat(alphaValue, ")"));
|
|
2577
|
+
|
|
2578
|
+
// Update existing hsla opacity
|
|
2579
|
+
modifiedDeclaration = modifiedDeclaration.replace(patterns.hsla, "$1hsla($2, $3, $4, ".concat(alphaValue, ")"));
|
|
2580
|
+
|
|
2581
|
+
// Handle hex colors - convert to rgba
|
|
2582
|
+
modifiedDeclaration = modifiedDeclaration.replace(patterns.hex, (match, propPart, hexColor) => {
|
|
2583
|
+
// Convert hex to rgba
|
|
2584
|
+
const hex = hexColor.replace("#", "");
|
|
2585
|
+
let r, g, b;
|
|
2586
|
+
if (hex.length === 3) {
|
|
2587
|
+
r = parseInt(hex[0] + hex[0], 16);
|
|
2588
|
+
g = parseInt(hex[1] + hex[1], 16);
|
|
2589
|
+
b = parseInt(hex[2] + hex[2], 16);
|
|
2590
|
+
} else {
|
|
2591
|
+
r = parseInt(hex.substring(0, 2), 16);
|
|
2592
|
+
g = parseInt(hex.substring(2, 4), 16);
|
|
2593
|
+
b = parseInt(hex.substring(4, 6), 16);
|
|
2594
|
+
}
|
|
2595
|
+
return "".concat(propPart, "rgba(").concat(r, ", ").concat(g, ", ").concat(b, ", ").concat(alphaValue, ")");
|
|
2596
|
+
});
|
|
2597
|
+
}
|
|
2598
|
+
return modifiedDeclaration;
|
|
2599
|
+
}
|
|
2600
|
+
|
|
2601
|
+
/**
|
|
2602
|
+
* Performance Monitoring Utilities
|
|
2603
|
+
*
|
|
2604
|
+
* Tracks and logs performance metrics for optimization analysis.
|
|
2605
|
+
*
|
|
2606
|
+
* @module utils/performanceMonitor
|
|
2607
|
+
*/
|
|
2608
|
+
|
|
2609
|
+
|
|
2610
|
+
/**
|
|
2611
|
+
* Performance monitoring system
|
|
2612
|
+
*
|
|
2613
|
+
* Provides start/end timing and automatic slow operation logging.
|
|
2614
|
+
*/
|
|
2615
|
+
const performanceMonitor$1 = {
|
|
2616
|
+
enabled: typeof performance !== "undefined",
|
|
2617
|
+
/**
|
|
2618
|
+
* Start performance measurement
|
|
2619
|
+
*
|
|
2620
|
+
* @param {string} label - Label for the measurement
|
|
2621
|
+
* @returns {Object|null} Marker object with label and start time
|
|
2622
|
+
*/
|
|
2623
|
+
start(label) {
|
|
2624
|
+
if (!this.enabled) return null;
|
|
2625
|
+
return {
|
|
2626
|
+
label,
|
|
2627
|
+
startTime: performance.now()
|
|
2628
|
+
};
|
|
2629
|
+
},
|
|
2630
|
+
/**
|
|
2631
|
+
* End performance measurement and log if slow
|
|
2632
|
+
*
|
|
2633
|
+
* @param {Object} marker - Marker from start()
|
|
2634
|
+
*/
|
|
2635
|
+
end(marker) {
|
|
2636
|
+
if (!this.enabled || !marker) return;
|
|
2637
|
+
const duration = performance.now() - marker.startTime;
|
|
2638
|
+
if (duration > 5) {
|
|
2639
|
+
// Only log if > 5ms
|
|
2640
|
+
logger.warn("Slow ".concat(marker.label, ": ").concat(duration.toFixed(2), "ms"));
|
|
2641
|
+
}
|
|
2642
|
+
},
|
|
2643
|
+
/**
|
|
2644
|
+
* Measure function execution time
|
|
2645
|
+
*
|
|
2646
|
+
* @param {Function} fn - Function to measure
|
|
2647
|
+
* @param {string} label - Label for measurement
|
|
2648
|
+
* @returns {*} Function result
|
|
2649
|
+
*/
|
|
2650
|
+
measure(fn, label) {
|
|
2651
|
+
const marker = this.start(label);
|
|
2652
|
+
try {
|
|
2653
|
+
const result = fn();
|
|
2654
|
+
this.end(marker);
|
|
2655
|
+
return result;
|
|
2656
|
+
} catch (error) {
|
|
2657
|
+
this.end(marker);
|
|
2658
|
+
throw error;
|
|
2659
|
+
}
|
|
2660
|
+
}
|
|
2661
|
+
};
|
|
2662
|
+
|
|
2663
|
+
/**
|
|
2664
|
+
* DOM CSS Injector
|
|
2665
|
+
*
|
|
2666
|
+
* Handles automatic CSS injection into the DOM.
|
|
2667
|
+
* Supports SSR mode, HMR-friendly block registry, and hash-based deduplication.
|
|
2668
|
+
*
|
|
2669
|
+
* @module injector/dom
|
|
2670
|
+
*/
|
|
2671
|
+
|
|
2672
|
+
|
|
2673
|
+
/**
|
|
2674
|
+
* Rebuild the style tag from the CSS block registry.
|
|
2675
|
+
*
|
|
2676
|
+
* Used for slot-based updates where each twsx() call owns its own CSS block.
|
|
2677
|
+
* Rebuilds the entire style tag to avoid stale CSS from previous HMR cycles.
|
|
2678
|
+
*
|
|
2679
|
+
* @private
|
|
2680
|
+
*/
|
|
2681
|
+
function rebuildStyleTag$1() {
|
|
2682
|
+
let styleTag = document.getElementById("twsx-auto-style");
|
|
2683
|
+
if (!styleTag) {
|
|
2684
|
+
styleTag = document.createElement("style");
|
|
2685
|
+
styleTag.id = "twsx-auto-style";
|
|
2686
|
+
styleTag.setAttribute("data-twsx", "");
|
|
2687
|
+
document.head.appendChild(styleTag);
|
|
2688
|
+
}
|
|
2689
|
+
styleTag.textContent = [...cssBlockRegistry.values()].join("\n");
|
|
2690
|
+
}
|
|
2691
|
+
|
|
2692
|
+
/**
|
|
2693
|
+
* Automatically inject CSS into the DOM or collect for SSR.
|
|
2694
|
+
*
|
|
2695
|
+
* Supports three modes:
|
|
2696
|
+
* 1. SSR mode: Delegates to utils/ssr.js collector
|
|
2697
|
+
* 2. Slot-based mode (with sourceKey): HMR-friendly block registry
|
|
2698
|
+
* 3. Hash-based mode (no sourceKey): Legacy deduplication
|
|
2699
|
+
*
|
|
2700
|
+
* @param {string} cssString - CSS to inject
|
|
2701
|
+
* @param {string|null} sourceKey - Optional unique key for slot-based updates
|
|
2702
|
+
*
|
|
2703
|
+
* @example
|
|
2704
|
+
* // Slot-based (HMR-friendly)
|
|
2705
|
+
* autoInjectCss('.btn { color: blue; }', 'twsx-call-123');
|
|
2706
|
+
*
|
|
2707
|
+
* @example
|
|
2708
|
+
* // Hash-based (legacy)
|
|
2709
|
+
* autoInjectCss('.btn { color: blue; }');
|
|
2710
|
+
*
|
|
2711
|
+
* @example
|
|
2712
|
+
* // SSR mode (delegates to ssr.js)
|
|
2713
|
+
* startSSR();
|
|
2714
|
+
* autoInjectCss('.btn { color: blue; }');
|
|
2715
|
+
* const css = stopSSR();
|
|
2716
|
+
*/
|
|
2717
|
+
function autoInjectCss(cssString) {
|
|
2718
|
+
let sourceKey = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
2719
|
+
const marker = performanceMonitor$1.start("css:inject");
|
|
2720
|
+
try {
|
|
2721
|
+
// SSR mode: collect CSS strings instead of DOM injection. Delegates to
|
|
2722
|
+
// the shared collector in ./utils/ssr.js so both the legacy
|
|
2723
|
+
// startSSR()/stopSSR() pair and the modern createSSRCollector() actually
|
|
2724
|
+
// receive the CSS generated by tw()/twsx().
|
|
2725
|
+
if (isSSRCollecting()) {
|
|
2726
|
+
collectSSRCSS(cssString);
|
|
2727
|
+
performanceMonitor$1.end(marker);
|
|
2728
|
+
return;
|
|
2729
|
+
}
|
|
2730
|
+
if (IS_BROWSER$1) {
|
|
2731
|
+
if (sourceKey) {
|
|
2732
|
+
// Slot-based update: each unique twsx(obj) call owns its own CSS block.
|
|
2733
|
+
// When styles change (new content, same logical call site via cacheKey)
|
|
2734
|
+
// the old slot is replaced and the style tag is fully rebuilt, so no
|
|
2735
|
+
// stale rules from previous HMR cycles can pile up.
|
|
2736
|
+
const existing = cssBlockRegistry.get(sourceKey);
|
|
2737
|
+
if (existing === cssString) {
|
|
2738
|
+
// Identical content – nothing to do.
|
|
2739
|
+
performanceMonitor$1.end(marker);
|
|
2740
|
+
return;
|
|
2741
|
+
}
|
|
2742
|
+
cssBlockRegistry.set(sourceKey, cssString);
|
|
2743
|
+
rebuildStyleTag$1();
|
|
2744
|
+
if (cssBlockRegistry.size % 10 === 0) {
|
|
2745
|
+
logger.debug("CSS registry stats: ".concat(cssBlockRegistry.size, " blocks registered"));
|
|
2746
|
+
}
|
|
2747
|
+
performanceMonitor$1.end(marker);
|
|
2748
|
+
return;
|
|
2749
|
+
}
|
|
2750
|
+
|
|
2751
|
+
// Fallback path (e.g. direct autoInjectCss calls without a sourceKey):
|
|
2752
|
+
// keep the original hash-based dedup + append behaviour.
|
|
2753
|
+
const cssHash = getCssHash(cssString);
|
|
2754
|
+
if (injectedCssHashSet.has(cssHash)) {
|
|
2755
|
+
performanceMonitor$1.end(marker);
|
|
2756
|
+
return;
|
|
2757
|
+
}
|
|
2758
|
+
injectedCssHashSet.add(cssHash);
|
|
2759
|
+
evictSet(injectedCssHashSet);
|
|
2760
|
+
let styleTag = document.getElementById("twsx-auto-style");
|
|
2761
|
+
if (!styleTag) {
|
|
2762
|
+
styleTag = document.createElement("style");
|
|
2763
|
+
styleTag.id = "twsx-auto-style";
|
|
2764
|
+
styleTag.setAttribute("data-twsx", "");
|
|
2765
|
+
document.head.appendChild(styleTag);
|
|
2766
|
+
}
|
|
2767
|
+
|
|
2768
|
+
// Append CSS to style tag using textContent for reliability
|
|
2769
|
+
// Note: insertRule + textContent mixing destroys CSSOM rules,
|
|
2770
|
+
// so we use textContent exclusively for consistent behavior
|
|
2771
|
+
// with @keyframes, @media, and other nested CSS blocks.
|
|
2772
|
+
styleTag.textContent += "\n".concat(cssString);
|
|
2773
|
+
|
|
2774
|
+
// Log injection stats periodically
|
|
2775
|
+
if (injectedCssHashSet.size % 10 === 0) {
|
|
2776
|
+
logger.debug("CSS injection stats: ".concat(injectedCssHashSet.size, " unique stylesheets injected"));
|
|
2777
|
+
}
|
|
2190
2778
|
}
|
|
2191
|
-
|
|
2779
|
+
performanceMonitor$1.end(marker);
|
|
2780
|
+
} catch (error) {
|
|
2781
|
+
performanceMonitor$1.end(marker);
|
|
2782
|
+
logger.error("Error injecting CSS:", error);
|
|
2192
2783
|
}
|
|
2784
|
+
}
|
|
2193
2785
|
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2786
|
+
/**
|
|
2787
|
+
* Bracket Value Encoding/Decoding
|
|
2788
|
+
*
|
|
2789
|
+
* Handles encoding and decoding of bracket values in Tailwind classes.
|
|
2790
|
+
* Example: bg-[rgb(255,0,0)] → bg-[rgb__P__255%2C0%2C0__C__]
|
|
2791
|
+
*
|
|
2792
|
+
* @module parser/bracket
|
|
2793
|
+
*/
|
|
2200
2794
|
|
|
2201
|
-
/**
|
|
2202
|
-
* Clear all cache entries
|
|
2203
|
-
*/
|
|
2204
|
-
clear() {
|
|
2205
|
-
this.cache.clear();
|
|
2206
|
-
}
|
|
2207
2795
|
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2796
|
+
/**
|
|
2797
|
+
* Encode bracket values to prevent parsing issues.
|
|
2798
|
+
* Encodes parentheses within brackets to special markers.
|
|
2799
|
+
*
|
|
2800
|
+
* @param {string} input - Class string with brackets
|
|
2801
|
+
* @returns {string} Encoded string
|
|
2802
|
+
*
|
|
2803
|
+
* @example
|
|
2804
|
+
* encodeBracketValues('bg-[rgb(255,0,0)]')
|
|
2805
|
+
* // → 'bg-[rgb__P__255%2C0%2C0__C__]'
|
|
2806
|
+
*
|
|
2807
|
+
* @example
|
|
2808
|
+
* encodeBracketValues('w-[calc(100%-20px)]')
|
|
2809
|
+
* // → 'w-[calc__P__100%25-20px__C__]'
|
|
2810
|
+
*/
|
|
2811
|
+
function encodeBracketValues(input) {
|
|
2812
|
+
if (!input) return input;
|
|
2813
|
+
if (encodeBracketCache.has(input)) return encodeBracketCache.get(input);
|
|
2814
|
+
BRACKET_CONTENT_REGEX.lastIndex = 0; // Reset global regex
|
|
2815
|
+
const result = input.replace(BRACKET_CONTENT_REGEX, (_, content) => {
|
|
2816
|
+
const encoded = encodeURIComponent(content).replace(OPENING_PAREN_REGEX, "__P__").replace(CLOSING_PAREN_REGEX, "__C__");
|
|
2817
|
+
return "[".concat(encoded, "]");
|
|
2818
|
+
});
|
|
2819
|
+
encodeBracketCache.set(input, result);
|
|
2820
|
+
return result;
|
|
2821
|
+
}
|
|
2214
2822
|
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2823
|
+
/**
|
|
2824
|
+
* Decode previously encoded bracket values.
|
|
2825
|
+
* Reverses the encoding done by encodeBracketValues().
|
|
2826
|
+
*
|
|
2827
|
+
* @param {string} input - Encoded class string
|
|
2828
|
+
* @returns {string} Decoded string
|
|
2829
|
+
*
|
|
2830
|
+
* @example
|
|
2831
|
+
* decodeBracketValues('bg-[rgb__P__255%2C0%2C0__C__]')
|
|
2832
|
+
* // → 'bg-[rgb(255,0,0)]'
|
|
2833
|
+
*
|
|
2834
|
+
* @example
|
|
2835
|
+
* decodeBracketValues('w-[calc__P__100%25-20px__C__]')
|
|
2836
|
+
* // → 'w-[calc(100%-20px)]'
|
|
2837
|
+
*/
|
|
2838
|
+
function decodeBracketValues(input) {
|
|
2839
|
+
if (!input) return input;
|
|
2840
|
+
if (decodeBracketCache.has(input)) return decodeBracketCache.get(input);
|
|
2841
|
+
const result = decodeURIComponent(input).replace(ENCODED_PAREN_OPEN_REGEX, "(").replace(ENCODED_PAREN_CLOSE_REGEX, ")");
|
|
2842
|
+
decodeBracketCache.set(input, result);
|
|
2843
|
+
return result;
|
|
2221
2844
|
}
|
|
2222
2845
|
|
|
2223
2846
|
function generator$2S() {
|
|
@@ -5956,220 +6579,94 @@ const patterns = _objectSpread2(_objectSpread2({}, transition), fontFamily);
|
|
|
5956
6579
|
* // Arrays (nested)
|
|
5957
6580
|
* cx(['p-4', 'bg-white'], isActive && ['ring-2', 'ring-blue-500'])
|
|
5958
6581
|
* // → 'p-4 bg-white ring-2 ring-blue-500'
|
|
5959
|
-
*
|
|
5960
|
-
* @example
|
|
5961
|
-
* // Mixed
|
|
5962
|
-
* cx(
|
|
5963
|
-
* 'base-class',
|
|
5964
|
-
* condition && 'conditional-class',
|
|
5965
|
-
* { 'object-class': true, 'ignored-class': false },
|
|
5966
|
-
* ['array-class-1', 'array-class-2']
|
|
5967
|
-
* )
|
|
5968
|
-
*/
|
|
5969
|
-
function cx() {
|
|
5970
|
-
const classes = [];
|
|
5971
|
-
for (let i = 0; i < arguments.length; i++) {
|
|
5972
|
-
const arg = i < 0 || arguments.length <= i ? undefined : arguments[i];
|
|
5973
|
-
|
|
5974
|
-
// Skip falsy values
|
|
5975
|
-
if (!arg) continue;
|
|
5976
|
-
const type = typeof arg;
|
|
5977
|
-
if (type === 'string') {
|
|
5978
|
-
classes.push(arg);
|
|
5979
|
-
} else if (Array.isArray(arg)) {
|
|
5980
|
-
// Recursively process arrays
|
|
5981
|
-
const inner = cx(...arg);
|
|
5982
|
-
if (inner) classes.push(inner);
|
|
5983
|
-
} else if (type === 'object') {
|
|
5984
|
-
// Object: keys are class names, values are conditions
|
|
5985
|
-
const keys = Object.keys(arg);
|
|
5986
|
-
for (let j = 0; j < keys.length; j++) {
|
|
5987
|
-
if (arg[keys[j]]) {
|
|
5988
|
-
classes.push(keys[j]);
|
|
5989
|
-
}
|
|
5990
|
-
}
|
|
5991
|
-
}
|
|
5992
|
-
}
|
|
5993
|
-
return classes.join(' ');
|
|
5994
|
-
}
|
|
5995
|
-
|
|
5996
|
-
/**
|
|
5997
|
-
* Create a cx function bound with base classes.
|
|
5998
|
-
* Useful for component-level class composition.
|
|
5999
|
-
*
|
|
6000
|
-
* @param {...(string|Object|Array)} baseArgs - Base class arguments always included
|
|
6001
|
-
* @returns {Function} A cx function pre-filled with base classes
|
|
6002
|
-
*
|
|
6003
|
-
* @example
|
|
6004
|
-
* const btnClasses = cx.with('px-4 py-2 rounded font-medium transition-colors')
|
|
6005
|
-
*
|
|
6006
|
-
* btnClasses('bg-blue-500 text-white')
|
|
6007
|
-
* // → 'px-4 py-2 rounded font-medium transition-colors bg-blue-500 text-white'
|
|
6008
|
-
*
|
|
6009
|
-
* btnClasses({ 'opacity-50 cursor-not-allowed': isDisabled })
|
|
6010
|
-
* // → 'px-4 py-2 rounded font-medium transition-colors opacity-50 cursor-not-allowed'
|
|
6011
|
-
*/
|
|
6012
|
-
cx.with = function () {
|
|
6013
|
-
for (var _len = arguments.length, baseArgs = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
6014
|
-
baseArgs[_key] = arguments[_key];
|
|
6015
|
-
}
|
|
6016
|
-
return function () {
|
|
6017
|
-
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
6018
|
-
args[_key2] = arguments[_key2];
|
|
6019
|
-
}
|
|
6020
|
-
return cx(...baseArgs, ...args);
|
|
6021
|
-
};
|
|
6022
|
-
};
|
|
6023
|
-
|
|
6024
|
-
// ============================================================================
|
|
6025
|
-
// SSR (Server-Side Rendering) Support
|
|
6026
|
-
// Detect environment once at module load for zero-cost runtime checks
|
|
6027
|
-
// ============================================================================
|
|
6028
|
-
const IS_BROWSER$1 = typeof window !== "undefined" && typeof document !== "undefined";
|
|
6029
|
-
const MAX_CACHE_SIZE$1 = 5000;
|
|
6030
|
-
const MAX_SET_SIZE = 10000;
|
|
6031
|
-
|
|
6032
|
-
// Global registry to track injected keyframes (prevents duplication) - now with LRU
|
|
6033
|
-
const _injectedKeyframes = new LRUCache(MAX_SET_SIZE);
|
|
6034
|
-
|
|
6035
|
-
// Global LRU cache instances (true LRU, not FIFO)
|
|
6036
|
-
const _twsxInputCache = new LRUCache(MAX_CACHE_SIZE$1);
|
|
6037
|
-
|
|
6038
|
-
// WeakMap for object identity-based caching (fast lookup for repeated objects)
|
|
6039
|
-
const _objectIdentityCache = new WeakMap();
|
|
6040
|
-
|
|
6041
|
-
/** @deprecated Use LRUCache instead - kept for backward compatibility */
|
|
6042
|
-
function evictSet(set) {
|
|
6043
|
-
let maxSize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : MAX_SET_SIZE;
|
|
6044
|
-
if (set instanceof LRUCache) return; // LRUCache handles its own eviction
|
|
6045
|
-
if (set.size <= maxSize) return;
|
|
6046
|
-
const excess = set.size - maxSize;
|
|
6047
|
-
const iter = set.values();
|
|
6048
|
-
for (let i = 0; i < excess; i++) {
|
|
6049
|
-
set.delete(iter.next().value);
|
|
6050
|
-
}
|
|
6051
|
-
}
|
|
6052
|
-
|
|
6053
|
-
// Mapping of animation names to their keyframe definitions
|
|
6054
|
-
const BUILTIN_KEYFRAMES = {
|
|
6055
|
-
spin: {
|
|
6056
|
-
"0%": {
|
|
6057
|
-
transform: "rotate(0deg)"
|
|
6058
|
-
},
|
|
6059
|
-
"100%": {
|
|
6060
|
-
transform: "rotate(360deg)"
|
|
6061
|
-
}
|
|
6062
|
-
},
|
|
6063
|
-
ping: {
|
|
6064
|
-
"75%, 100%": {
|
|
6065
|
-
transform: "scale(2)",
|
|
6066
|
-
opacity: "0"
|
|
6067
|
-
}
|
|
6068
|
-
},
|
|
6069
|
-
pulse: {
|
|
6070
|
-
"50%": {
|
|
6071
|
-
opacity: ".5"
|
|
6072
|
-
}
|
|
6073
|
-
},
|
|
6074
|
-
bounce: {
|
|
6075
|
-
"0%, 100%": {
|
|
6076
|
-
transform: "translateY(-25%)",
|
|
6077
|
-
animationTimingFunction: "cubic-bezier(0.8,0,1,1)"
|
|
6078
|
-
},
|
|
6079
|
-
"50%": {
|
|
6080
|
-
transform: "none",
|
|
6081
|
-
animationTimingFunction: "cubic-bezier(0,0,0.2,1)"
|
|
6082
|
-
}
|
|
6083
|
-
},
|
|
6084
|
-
fadeIn: {
|
|
6085
|
-
"0%": {
|
|
6086
|
-
opacity: "0"
|
|
6087
|
-
},
|
|
6088
|
-
"50%": {
|
|
6089
|
-
opacity: "1"
|
|
6090
|
-
},
|
|
6091
|
-
"100%": {
|
|
6092
|
-
opacity: "0"
|
|
6093
|
-
}
|
|
6094
|
-
},
|
|
6095
|
-
slideUp: {
|
|
6096
|
-
"0%": {
|
|
6097
|
-
transform: "translateY(20px)",
|
|
6098
|
-
opacity: "0"
|
|
6099
|
-
},
|
|
6100
|
-
"50%": {
|
|
6101
|
-
transform: "translateY(0)",
|
|
6102
|
-
opacity: "1"
|
|
6103
|
-
},
|
|
6104
|
-
"100%": {
|
|
6105
|
-
transform: "translateY(-20px)",
|
|
6106
|
-
opacity: "0"
|
|
6107
|
-
}
|
|
6108
|
-
}
|
|
6109
|
-
};
|
|
6110
|
-
|
|
6111
|
-
// Generate minified keyframes CSS
|
|
6112
|
-
function generateMinifiedKeyframes(animationNames) {
|
|
6113
|
-
let css = "";
|
|
6114
|
-
for (const name of animationNames) {
|
|
6115
|
-
const keyframe = BUILTIN_KEYFRAMES[name];
|
|
6116
|
-
if (!keyframe) continue;
|
|
6117
|
-
css += "@keyframes ".concat(name, "{");
|
|
6118
|
-
for (const _ref of Object.entries(keyframe)) {
|
|
6119
|
-
var _ref2 = _slicedToArray(_ref, 2);
|
|
6120
|
-
const percentage = _ref2[0];
|
|
6121
|
-
const styles = _ref2[1];
|
|
6122
|
-
css += "".concat(percentage, "{");
|
|
6123
|
-
for (const _ref3 of Object.entries(styles)) {
|
|
6124
|
-
var _ref4 = _slicedToArray(_ref3, 2);
|
|
6125
|
-
const prop = _ref4[0];
|
|
6126
|
-
const value = _ref4[1];
|
|
6127
|
-
const cssProp = prop.replace(UPPERCASE_LETTER_REGEX, "-$1").toLowerCase();
|
|
6128
|
-
css += "".concat(cssProp, ":").concat(value, ";");
|
|
6582
|
+
*
|
|
6583
|
+
* @example
|
|
6584
|
+
* // Mixed
|
|
6585
|
+
* cx(
|
|
6586
|
+
* 'base-class',
|
|
6587
|
+
* condition && 'conditional-class',
|
|
6588
|
+
* { 'object-class': true, 'ignored-class': false },
|
|
6589
|
+
* ['array-class-1', 'array-class-2']
|
|
6590
|
+
* )
|
|
6591
|
+
*/
|
|
6592
|
+
function cx() {
|
|
6593
|
+
const classes = [];
|
|
6594
|
+
for (let i = 0; i < arguments.length; i++) {
|
|
6595
|
+
const arg = i < 0 || arguments.length <= i ? undefined : arguments[i];
|
|
6596
|
+
|
|
6597
|
+
// Skip falsy values
|
|
6598
|
+
if (!arg) continue;
|
|
6599
|
+
const type = typeof arg;
|
|
6600
|
+
if (type === 'string') {
|
|
6601
|
+
classes.push(arg);
|
|
6602
|
+
} else if (Array.isArray(arg)) {
|
|
6603
|
+
// Recursively process arrays
|
|
6604
|
+
const inner = cx(...arg);
|
|
6605
|
+
if (inner) classes.push(inner);
|
|
6606
|
+
} else if (type === 'object') {
|
|
6607
|
+
// Object: keys are class names, values are conditions
|
|
6608
|
+
const keys = Object.keys(arg);
|
|
6609
|
+
for (let j = 0; j < keys.length; j++) {
|
|
6610
|
+
if (arg[keys[j]]) {
|
|
6611
|
+
classes.push(keys[j]);
|
|
6612
|
+
}
|
|
6129
6613
|
}
|
|
6130
|
-
css += "}";
|
|
6131
6614
|
}
|
|
6132
|
-
css += "}";
|
|
6133
6615
|
}
|
|
6134
|
-
return
|
|
6616
|
+
return classes.join(' ');
|
|
6135
6617
|
}
|
|
6136
6618
|
|
|
6137
|
-
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
|
|
6143
|
-
|
|
6144
|
-
|
|
6145
|
-
|
|
6146
|
-
|
|
6147
|
-
|
|
6148
|
-
|
|
6149
|
-
|
|
6619
|
+
/**
|
|
6620
|
+
* Create a cx function bound with base classes.
|
|
6621
|
+
* Useful for component-level class composition.
|
|
6622
|
+
*
|
|
6623
|
+
* @param {...(string|Object|Array)} baseArgs - Base class arguments always included
|
|
6624
|
+
* @returns {Function} A cx function pre-filled with base classes
|
|
6625
|
+
*
|
|
6626
|
+
* @example
|
|
6627
|
+
* const btnClasses = cx.with('px-4 py-2 rounded font-medium transition-colors')
|
|
6628
|
+
*
|
|
6629
|
+
* btnClasses('bg-blue-500 text-white')
|
|
6630
|
+
* // → 'px-4 py-2 rounded font-medium transition-colors bg-blue-500 text-white'
|
|
6631
|
+
*
|
|
6632
|
+
* btnClasses({ 'opacity-50 cursor-not-allowed': isDisabled })
|
|
6633
|
+
* // → 'px-4 py-2 rounded font-medium transition-colors opacity-50 cursor-not-allowed'
|
|
6634
|
+
*/
|
|
6635
|
+
cx.with = function () {
|
|
6636
|
+
for (var _len = arguments.length, baseArgs = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
6637
|
+
baseArgs[_key] = arguments[_key];
|
|
6638
|
+
}
|
|
6639
|
+
return function () {
|
|
6640
|
+
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
6641
|
+
args[_key2] = arguments[_key2];
|
|
6642
|
+
}
|
|
6643
|
+
return cx(...baseArgs, ...args);
|
|
6644
|
+
};
|
|
6150
6645
|
};
|
|
6151
6646
|
|
|
6647
|
+
const MAX_CACHE_SIZE$1 = 5000;
|
|
6648
|
+
const MAX_SET_SIZE = 10000;
|
|
6649
|
+
|
|
6650
|
+
// Global registry to track injected keyframes (prevents duplication) - now with LRU
|
|
6651
|
+
const _injectedKeyframes = new LRUCache(MAX_SET_SIZE);
|
|
6652
|
+
|
|
6653
|
+
// Global LRU cache instances (true LRU, not FIFO)
|
|
6654
|
+
const _twsxInputCache = new LRUCache(MAX_CACHE_SIZE$1);
|
|
6655
|
+
|
|
6656
|
+
// WeakMap for object identity-based caching (fast lookup for repeated objects)
|
|
6657
|
+
const _objectIdentityCache = new WeakMap();
|
|
6658
|
+
|
|
6152
6659
|
// CSS parsing
|
|
6153
6660
|
const CSS_CLASS_REGEX = /([a-zA-Z0-9\-_\\/.]+)\s*{\s*([^}]+)\s*}/g;
|
|
6154
6661
|
const DOUBLE_BACKSLASH_REGEX = /\\\\/g;
|
|
6155
6662
|
const LEADING_UNDERSCORE_REGEX = /^_/;
|
|
6156
6663
|
const MULTIPLE_SPACES_REGEX = /\s+/g;
|
|
6157
6664
|
|
|
6158
|
-
// Bracket encoding/decoding
|
|
6159
|
-
const BRACKET_CONTENT_REGEX = /\[([^\]]+)\]/g;
|
|
6160
|
-
const OPENING_PAREN_REGEX = /\(/g;
|
|
6161
|
-
const CLOSING_PAREN_REGEX = /\)/g;
|
|
6162
|
-
const ENCODED_PAREN_OPEN_REGEX = /__P__/g;
|
|
6163
|
-
const ENCODED_PAREN_CLOSE_REGEX = /__C__/g;
|
|
6164
|
-
|
|
6165
6665
|
// Variant expansion
|
|
6166
6666
|
const DIRECTIVE_GROUP_REGEX = /(\w+)\(([^()]+)\)/g;
|
|
6167
6667
|
const VARIANT_GROUP_REGEX = /(\w+):\(([^()]+(?:\((?:[^()]+)\))?[^()]*)\)/g;
|
|
6168
6668
|
const WHITESPACE_SPLIT_REGEX = /\s+/;
|
|
6169
6669
|
const VARIANT_COLON_SPLIT_REGEX = /:/;
|
|
6170
|
-
|
|
6171
|
-
// Animation detection
|
|
6172
|
-
const ANIMATION_NAME_REGEX = /animation(?:-name)?:\s*([a-zA-Z0-9-]+)/gi;
|
|
6173
6670
|
const CUSTOM_VALUE_FULL_REGEX = /^(.+?)\[(.+)\]$/;
|
|
6174
6671
|
|
|
6175
6672
|
// Selector variants
|
|
@@ -6194,9 +6691,6 @@ for (const prop of COLOR_PROPERTIES) {
|
|
|
6194
6691
|
});
|
|
6195
6692
|
}
|
|
6196
6693
|
|
|
6197
|
-
// CSS property name conversion
|
|
6198
|
-
const UPPERCASE_LETTER_REGEX = /([A-Z])/g;
|
|
6199
|
-
|
|
6200
6694
|
// Escape characters
|
|
6201
6695
|
const ESCAPE_SLASH_REGEX = /\//g;
|
|
6202
6696
|
const ESCAPE_DOT_REGEX = /\./g;
|
|
@@ -6400,6 +6894,14 @@ function parseCustomClassWithPatterns(className) {
|
|
|
6400
6894
|
return null;
|
|
6401
6895
|
}
|
|
6402
6896
|
|
|
6897
|
+
/**
|
|
6898
|
+
* Resolve all CSS custom properties (var) in a CSS string and output only clear CSS (no custom property)
|
|
6899
|
+
* Optimized with for loops and indexOf for 2-3x better performance
|
|
6900
|
+
* @param {string} cssString
|
|
6901
|
+
* @returns {string} e.g. 'color: rgba(255,255,255,1); background: #fff;'
|
|
6902
|
+
*/
|
|
6903
|
+
// NOTE: resolveCssToClearCss now imported from ./generator/css-string.js
|
|
6904
|
+
|
|
6403
6905
|
// Cache for getConfigOptions - use LRU cache
|
|
6404
6906
|
const configOptionsCache = new LRUCache(500);
|
|
6405
6907
|
function generateTailwindCssString() {
|
|
@@ -6489,27 +6991,9 @@ const selectorVariants = {
|
|
|
6489
6991
|
number: arg => "> :nth-child(".concat(arg, ")")
|
|
6490
6992
|
};
|
|
6491
6993
|
|
|
6492
|
-
//
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
if (!input) return input;
|
|
6496
|
-
if (encodeBracketCache.has(input)) return encodeBracketCache.get(input);
|
|
6497
|
-
BRACKET_CONTENT_REGEX.lastIndex = 0; // Reset global regex
|
|
6498
|
-
const result = input.replace(BRACKET_CONTENT_REGEX, (_, content) => {
|
|
6499
|
-
const encoded = encodeURIComponent(content).replace(OPENING_PAREN_REGEX, "__P__").replace(CLOSING_PAREN_REGEX, "__C__");
|
|
6500
|
-
return "[".concat(encoded, "]");
|
|
6501
|
-
});
|
|
6502
|
-
encodeBracketCache.set(input, result);
|
|
6503
|
-
return result;
|
|
6504
|
-
}
|
|
6505
|
-
const decodeBracketCache = new LRUCache(1000);
|
|
6506
|
-
function decodeBracketValues(input) {
|
|
6507
|
-
if (!input) return input;
|
|
6508
|
-
if (decodeBracketCache.has(input)) return decodeBracketCache.get(input);
|
|
6509
|
-
const result = decodeURIComponent(input).replace(ENCODED_PAREN_OPEN_REGEX, "(").replace(ENCODED_PAREN_CLOSE_REGEX, ")");
|
|
6510
|
-
decodeBracketCache.set(input, result);
|
|
6511
|
-
return result;
|
|
6512
|
-
}
|
|
6994
|
+
// NOTE: encodeBracketValues and decodeBracketValues now imported from ./parser/bracket.js
|
|
6995
|
+
// NOTE: encodeBracketCache and decodeBracketCache are in ./parser/bracket.js
|
|
6996
|
+
|
|
6513
6997
|
function replaceSelector(selector) {
|
|
6514
6998
|
SELECTOR_VARIANT_REGEX.lastIndex = 0; // Reset global regex
|
|
6515
6999
|
return selector.replace(SELECTOR_VARIANT_REGEX, (_, raw) => {
|
|
@@ -6547,73 +7031,6 @@ function resolveVariants(selector, variants) {
|
|
|
6547
7031
|
};
|
|
6548
7032
|
}
|
|
6549
7033
|
|
|
6550
|
-
/**
|
|
6551
|
-
* Process opacity modifier from class name (e.g., text-red-500/50 -> 50% opacity)
|
|
6552
|
-
* @param {string} className - Class name with potential opacity modifier
|
|
6553
|
-
* @param {string} cssDeclaration - CSS declaration to modify
|
|
6554
|
-
* @returns {string} Modified CSS declaration with opacity applied
|
|
6555
|
-
*/
|
|
6556
|
-
function processOpacityModifier(className, cssDeclaration) {
|
|
6557
|
-
const opacityMatch = OPACITY_MODIFIER_REGEX.exec(className);
|
|
6558
|
-
if (!opacityMatch) return cssDeclaration;
|
|
6559
|
-
const opacityValue = parseInt(opacityMatch[1], 10);
|
|
6560
|
-
if (opacityValue < 0 || opacityValue > 100) return cssDeclaration;
|
|
6561
|
-
const alphaValue = (opacityValue / 100).toString();
|
|
6562
|
-
|
|
6563
|
-
// Handle Tailwind's CSS custom property pattern
|
|
6564
|
-
let modifiedDeclaration = cssDeclaration;
|
|
6565
|
-
|
|
6566
|
-
// Replace opacity custom properties using pre-compiled regexes
|
|
6567
|
-
for (const prop in OPACITY_PROP_REGEXES) {
|
|
6568
|
-
const regex = OPACITY_PROP_REGEXES[prop];
|
|
6569
|
-
regex.lastIndex = 0; // Reset global regex
|
|
6570
|
-
modifiedDeclaration = modifiedDeclaration.replace(regex, "".concat(prop, ": ").concat(alphaValue));
|
|
6571
|
-
}
|
|
6572
|
-
|
|
6573
|
-
// Also handle direct color values using pre-compiled regex patterns
|
|
6574
|
-
for (const prop of COLOR_PROPERTIES) {
|
|
6575
|
-
const patterns = COLOR_REGEX_PATTERNS.get(prop);
|
|
6576
|
-
if (!patterns) continue;
|
|
6577
|
-
|
|
6578
|
-
// Reset all regex lastIndex for reuse
|
|
6579
|
-
patterns.rgb.lastIndex = 0;
|
|
6580
|
-
patterns.rgba.lastIndex = 0;
|
|
6581
|
-
patterns.hsl.lastIndex = 0;
|
|
6582
|
-
patterns.hsla.lastIndex = 0;
|
|
6583
|
-
patterns.hex.lastIndex = 0;
|
|
6584
|
-
|
|
6585
|
-
// Convert rgb to rgba with opacity
|
|
6586
|
-
modifiedDeclaration = modifiedDeclaration.replace(patterns.rgb, "$1rgba($2, $3, $4, ".concat(alphaValue, ")"));
|
|
6587
|
-
|
|
6588
|
-
// Update existing rgba opacity
|
|
6589
|
-
modifiedDeclaration = modifiedDeclaration.replace(patterns.rgba, "$1rgba($2, $3, $4, ".concat(alphaValue, ")"));
|
|
6590
|
-
|
|
6591
|
-
// Convert hsl to hsla with opacity
|
|
6592
|
-
modifiedDeclaration = modifiedDeclaration.replace(patterns.hsl, "$1hsla($2, $3, $4, ".concat(alphaValue, ")"));
|
|
6593
|
-
|
|
6594
|
-
// Update existing hsla opacity
|
|
6595
|
-
modifiedDeclaration = modifiedDeclaration.replace(patterns.hsla, "$1hsla($2, $3, $4, ".concat(alphaValue, ")"));
|
|
6596
|
-
|
|
6597
|
-
// Handle hex colors - convert to rgba
|
|
6598
|
-
modifiedDeclaration = modifiedDeclaration.replace(patterns.hex, (match, propPart, hexColor) => {
|
|
6599
|
-
// Convert hex to rgba
|
|
6600
|
-
const hex = hexColor.replace("#", "");
|
|
6601
|
-
let r, g, b;
|
|
6602
|
-
if (hex.length === 3) {
|
|
6603
|
-
r = parseInt(hex[0] + hex[0], 16);
|
|
6604
|
-
g = parseInt(hex[1] + hex[1], 16);
|
|
6605
|
-
b = parseInt(hex[2] + hex[2], 16);
|
|
6606
|
-
} else {
|
|
6607
|
-
r = parseInt(hex.substring(0, 2), 16);
|
|
6608
|
-
g = parseInt(hex.substring(2, 4), 16);
|
|
6609
|
-
b = parseInt(hex.substring(4, 6), 16);
|
|
6610
|
-
}
|
|
6611
|
-
return "".concat(propPart, "rgba(").concat(r, ", ").concat(g, ", ").concat(b, ", ").concat(alphaValue, ")");
|
|
6612
|
-
});
|
|
6613
|
-
}
|
|
6614
|
-
return modifiedDeclaration;
|
|
6615
|
-
}
|
|
6616
|
-
|
|
6617
7034
|
// Performance monitoring utilities
|
|
6618
7035
|
const performanceMonitor = {
|
|
6619
7036
|
enabled: typeof performance !== "undefined",
|
|
@@ -6690,9 +7107,11 @@ function expandGroupedClass(input) {
|
|
|
6690
7107
|
} while (result !== prev);
|
|
6691
7108
|
return result;
|
|
6692
7109
|
}
|
|
6693
|
-
// CSS Processing utilities
|
|
7110
|
+
// CSS Processing utilities
|
|
6694
7111
|
const parseSelectorCache = new LRUCache(500);
|
|
6695
|
-
|
|
7112
|
+
|
|
7113
|
+
// Parse selector with @css property support (different from parser/selector.js)
|
|
7114
|
+
function parseSelectorWithCssProperty(selector) {
|
|
6696
7115
|
if (parseSelectorCache.has(selector)) {
|
|
6697
7116
|
return parseSelectorCache.get(selector);
|
|
6698
7117
|
}
|
|
@@ -6717,10 +7136,10 @@ function parseSelector(selector) {
|
|
|
6717
7136
|
}
|
|
6718
7137
|
function processClass(cls, selector, styles) {
|
|
6719
7138
|
if (cls.trim() === "") return;
|
|
6720
|
-
const
|
|
6721
|
-
|
|
6722
|
-
rawVariants =
|
|
6723
|
-
className =
|
|
7139
|
+
const _ref = cls.includes(":") ? [cls.split(":").slice(0, -1), cls.split(":").slice(-1)[0]] : [[], cls],
|
|
7140
|
+
_ref2 = _slicedToArray(_ref, 2),
|
|
7141
|
+
rawVariants = _ref2[0],
|
|
7142
|
+
className = _ref2[1];
|
|
6724
7143
|
let isImportant = false;
|
|
6725
7144
|
let pureClassName = className;
|
|
6726
7145
|
if (className.startsWith("!")) {
|
|
@@ -6798,10 +7217,10 @@ function processNestedSelectors(nested, selector, styles, walk) {
|
|
|
6798
7217
|
const nestedVal = nested[nestedSel];
|
|
6799
7218
|
if (nestedSel === "@css" && typeof nestedVal === "object") {
|
|
6800
7219
|
// For @css directive, use raw CSS values without any processing
|
|
6801
|
-
const cssDeclarations = Object.entries(nestedVal).map(
|
|
6802
|
-
let
|
|
6803
|
-
key =
|
|
6804
|
-
value =
|
|
7220
|
+
const cssDeclarations = Object.entries(nestedVal).map(_ref3 => {
|
|
7221
|
+
let _ref4 = _slicedToArray(_ref3, 2),
|
|
7222
|
+
key = _ref4[0],
|
|
7223
|
+
value = _ref4[1];
|
|
6805
7224
|
// Convert camelCase to kebab-case (e.g., borderTopColor -> border-top-color)
|
|
6806
7225
|
const cssKey = key.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
6807
7226
|
// Ensure CSS values are properly formatted and not processed through Tailwind conversion
|
|
@@ -6824,9 +7243,9 @@ function walkStyleTree(selector, val, styles, walk) {
|
|
|
6824
7243
|
logger.warn("Invalid selector in walk function:", selector);
|
|
6825
7244
|
return;
|
|
6826
7245
|
}
|
|
6827
|
-
const
|
|
6828
|
-
baseSelector =
|
|
6829
|
-
cssProperty =
|
|
7246
|
+
const _parseSelectorWithCss = parseSelectorWithCssProperty(selector),
|
|
7247
|
+
baseSelector = _parseSelectorWithCss.baseSelector,
|
|
7248
|
+
cssProperty = _parseSelectorWithCss.cssProperty;
|
|
6830
7249
|
if (cssProperty && typeof val === "object" && Array.isArray(val) && val.length > 0) {
|
|
6831
7250
|
const cssValue = val[0];
|
|
6832
7251
|
if (typeof cssValue === "string") {
|
|
@@ -6865,9 +7284,9 @@ function walkStyleTree(selector, val, styles, walk) {
|
|
|
6865
7284
|
}
|
|
6866
7285
|
walk(selector, [expandGroupedClass(val)]);
|
|
6867
7286
|
} else if (typeof val === "object" && val !== null) {
|
|
6868
|
-
const
|
|
6869
|
-
baseSelector =
|
|
6870
|
-
cssProperty =
|
|
7287
|
+
const _parseSelectorWithCss2 = parseSelectorWithCssProperty(selector),
|
|
7288
|
+
baseSelector = _parseSelectorWithCss2.baseSelector,
|
|
7289
|
+
cssProperty = _parseSelectorWithCss2.cssProperty;
|
|
6871
7290
|
if (cssProperty) {
|
|
6872
7291
|
const cssValue = Object.values(val).join(" ");
|
|
6873
7292
|
styles[baseSelector] = styles[baseSelector] || "";
|
|
@@ -6878,10 +7297,10 @@ function walkStyleTree(selector, val, styles, walk) {
|
|
|
6878
7297
|
// Check if this is a @css object within the current object
|
|
6879
7298
|
if (val["@css"] && typeof val["@css"] === "object") {
|
|
6880
7299
|
// Handle object with @css directive - process the @css part specially
|
|
6881
|
-
const cssDeclarations = Object.entries(val["@css"]).map(
|
|
6882
|
-
let
|
|
6883
|
-
key =
|
|
6884
|
-
value =
|
|
7300
|
+
const cssDeclarations = Object.entries(val["@css"]).map(_ref5 => {
|
|
7301
|
+
let _ref6 = _slicedToArray(_ref5, 2),
|
|
7302
|
+
key = _ref6[0],
|
|
7303
|
+
value = _ref6[1];
|
|
6885
7304
|
// Convert camelCase to kebab-case (e.g., borderTopColor -> border-top-color)
|
|
6886
7305
|
const cssKey = key.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
6887
7306
|
// Keep CSS values intact without any processing
|
|
@@ -7027,9 +7446,9 @@ function generateCssString(styles) {
|
|
|
7027
7446
|
let cssString = "";
|
|
7028
7447
|
|
|
7029
7448
|
// Add base styles
|
|
7030
|
-
for (const
|
|
7031
|
-
const sel =
|
|
7032
|
-
const css =
|
|
7449
|
+
for (const _ref7 of baseStyles) {
|
|
7450
|
+
const sel = _ref7.sel;
|
|
7451
|
+
const css = _ref7.css;
|
|
7033
7452
|
cssString += "".concat(sel, "{").concat(css.trim().replace(/\n/g, ""), "}");
|
|
7034
7453
|
}
|
|
7035
7454
|
|
|
@@ -7039,9 +7458,9 @@ function generateCssString(styles) {
|
|
|
7039
7458
|
return match ? parseInt(match[1], 10) : 99999;
|
|
7040
7459
|
}
|
|
7041
7460
|
mediaStyles.sort((a, b) => mediaPriority(a.sel) - mediaPriority(b.sel));
|
|
7042
|
-
for (const
|
|
7043
|
-
const sel =
|
|
7044
|
-
const content =
|
|
7461
|
+
for (const _ref8 of mediaStyles) {
|
|
7462
|
+
const sel = _ref8.sel;
|
|
7463
|
+
const content = _ref8.content;
|
|
7045
7464
|
cssString += "".concat(sel, "{");
|
|
7046
7465
|
for (const subSel in content) {
|
|
7047
7466
|
cssString += "".concat(subSel, "{").concat(content[subSel].trim().replace(/\n/g, ""), "}");
|
|
@@ -7238,14 +7657,14 @@ function twsxNoCache(obj) {
|
|
|
7238
7657
|
})
|
|
7239
7658
|
});
|
|
7240
7659
|
const configOptions = getConfigOptions(mergedOptions, Object.keys(plugins));
|
|
7241
|
-
const
|
|
7242
|
-
|
|
7243
|
-
keyframes =
|
|
7660
|
+
const _ref9 = configOptions.theme || {},
|
|
7661
|
+
_ref9$keyframes = _ref9.keyframes,
|
|
7662
|
+
keyframes = _ref9$keyframes === void 0 ? {} : _ref9$keyframes;
|
|
7244
7663
|
let customKeyframesCSS = "";
|
|
7245
|
-
for (const
|
|
7246
|
-
var
|
|
7247
|
-
const name =
|
|
7248
|
-
const keyframe =
|
|
7664
|
+
for (const _ref0 of Object.entries(keyframes)) {
|
|
7665
|
+
var _ref1 = _slicedToArray(_ref0, 2);
|
|
7666
|
+
const name = _ref1[0];
|
|
7667
|
+
const keyframe = _ref1[1];
|
|
7249
7668
|
// Skip if already in built-in keyframes or already injected
|
|
7250
7669
|
if (BUILTIN_KEYFRAMES[name] || _injectedKeyframes.has(name)) continue;
|
|
7251
7670
|
|
|
@@ -7256,15 +7675,15 @@ function twsxNoCache(obj) {
|
|
|
7256
7675
|
|
|
7257
7676
|
// Generate minified custom keyframe
|
|
7258
7677
|
customKeyframesCSS += "@keyframes ".concat(name, "{");
|
|
7259
|
-
for (const
|
|
7260
|
-
var
|
|
7261
|
-
const percentage =
|
|
7262
|
-
const styles =
|
|
7678
|
+
for (const _ref10 of Object.entries(keyframe)) {
|
|
7679
|
+
var _ref11 = _slicedToArray(_ref10, 2);
|
|
7680
|
+
const percentage = _ref11[0];
|
|
7681
|
+
const styles = _ref11[1];
|
|
7263
7682
|
customKeyframesCSS += "".concat(percentage, "{");
|
|
7264
|
-
for (const
|
|
7265
|
-
var
|
|
7266
|
-
const prop =
|
|
7267
|
-
const value =
|
|
7683
|
+
for (const _ref12 of Object.entries(styles)) {
|
|
7684
|
+
var _ref13 = _slicedToArray(_ref12, 2);
|
|
7685
|
+
const prop = _ref13[0];
|
|
7686
|
+
const value = _ref13[1];
|
|
7268
7687
|
const cssProp = prop.replace(UPPERCASE_LETTER_REGEX, "-$1").toLowerCase();
|
|
7269
7688
|
customKeyframesCSS += "".concat(cssProp, ":").concat(value, ";");
|
|
7270
7689
|
}
|
|
@@ -7420,109 +7839,14 @@ function twsx(obj) {
|
|
|
7420
7839
|
return result;
|
|
7421
7840
|
}
|
|
7422
7841
|
|
|
7423
|
-
//
|
|
7424
|
-
|
|
7425
|
-
|
|
7426
|
-
|
|
7427
|
-
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
|
|
7431
|
-
hash = (hash << 5) - hash + chr;
|
|
7432
|
-
hash |= 0; // Convert to 32bit integer
|
|
7433
|
-
}
|
|
7434
|
-
return hash;
|
|
7435
|
-
}
|
|
7436
|
-
|
|
7437
|
-
// Enhanced auto-inject CSS with performance monitoring & SSR support
|
|
7438
|
-
const injectedCssHashSet = new Set();
|
|
7439
|
-
|
|
7440
|
-
// Registry of sourceKey → cssBlock for smart slot-based replacement.
|
|
7441
|
-
// Prevents stale CSS chunks from accumulating across HMR cycles.
|
|
7442
|
-
const _cssBlockRegistry = new Map();
|
|
7443
|
-
|
|
7444
|
-
/**
|
|
7445
|
-
* Rebuild the single twsx style tag from the full CSS block registry.
|
|
7446
|
-
* Called whenever a block is added or updated.
|
|
7447
|
-
*/
|
|
7448
|
-
function rebuildStyleTag$1() {
|
|
7449
|
-
let styleTag = document.getElementById("twsx-auto-style");
|
|
7450
|
-
if (!styleTag) {
|
|
7451
|
-
styleTag = document.createElement("style");
|
|
7452
|
-
styleTag.id = "twsx-auto-style";
|
|
7453
|
-
styleTag.setAttribute("data-twsx", "");
|
|
7454
|
-
document.head.appendChild(styleTag);
|
|
7455
|
-
}
|
|
7456
|
-
styleTag.textContent = [..._cssBlockRegistry.values()].join("\n");
|
|
7457
|
-
}
|
|
7458
|
-
function autoInjectCss(cssString) {
|
|
7459
|
-
let sourceKey = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
7460
|
-
const marker = performanceMonitor.start("css:inject");
|
|
7461
|
-
try {
|
|
7462
|
-
// SSR mode: collect CSS strings instead of DOM injection. Delegates to
|
|
7463
|
-
// the shared collector in ./utils/ssr.js so both the legacy
|
|
7464
|
-
// startSSR()/stopSSR() pair and the modern createSSRCollector() actually
|
|
7465
|
-
// receive the CSS generated by tw()/twsx().
|
|
7466
|
-
if (isSSRCollecting()) {
|
|
7467
|
-
collectSSRCSS(cssString);
|
|
7468
|
-
performanceMonitor.end(marker);
|
|
7469
|
-
return;
|
|
7470
|
-
}
|
|
7471
|
-
if (IS_BROWSER$1) {
|
|
7472
|
-
if (sourceKey) {
|
|
7473
|
-
// Slot-based update: each unique twsx(obj) call owns its own CSS block.
|
|
7474
|
-
// When styles change (new content, same logical call site via cacheKey)
|
|
7475
|
-
// the old slot is replaced and the style tag is fully rebuilt, so no
|
|
7476
|
-
// stale rules from previous HMR cycles can pile up.
|
|
7477
|
-
const existing = _cssBlockRegistry.get(sourceKey);
|
|
7478
|
-
if (existing === cssString) {
|
|
7479
|
-
// Identical content – nothing to do.
|
|
7480
|
-
performanceMonitor.end(marker);
|
|
7481
|
-
return;
|
|
7482
|
-
}
|
|
7483
|
-
_cssBlockRegistry.set(sourceKey, cssString);
|
|
7484
|
-
rebuildStyleTag$1();
|
|
7485
|
-
if (_cssBlockRegistry.size % 10 === 0) {
|
|
7486
|
-
logger.debug("CSS registry stats: ".concat(_cssBlockRegistry.size, " blocks registered"));
|
|
7487
|
-
}
|
|
7488
|
-
performanceMonitor.end(marker);
|
|
7489
|
-
return;
|
|
7490
|
-
}
|
|
7491
|
-
|
|
7492
|
-
// Fallback path (e.g. direct autoInjectCss calls without a sourceKey):
|
|
7493
|
-
// keep the original hash-based dedup + append behaviour.
|
|
7494
|
-
const cssHash = getCssHash(cssString);
|
|
7495
|
-
if (injectedCssHashSet.has(cssHash)) {
|
|
7496
|
-
performanceMonitor.end(marker);
|
|
7497
|
-
return;
|
|
7498
|
-
}
|
|
7499
|
-
injectedCssHashSet.add(cssHash);
|
|
7500
|
-
evictSet(injectedCssHashSet);
|
|
7501
|
-
let styleTag = document.getElementById("twsx-auto-style");
|
|
7502
|
-
if (!styleTag) {
|
|
7503
|
-
styleTag = document.createElement("style");
|
|
7504
|
-
styleTag.id = "twsx-auto-style";
|
|
7505
|
-
styleTag.setAttribute("data-twsx", "");
|
|
7506
|
-
document.head.appendChild(styleTag);
|
|
7507
|
-
}
|
|
7508
|
-
|
|
7509
|
-
// Append CSS to style tag using textContent for reliability
|
|
7510
|
-
// Note: insertRule + textContent mixing destroys CSSOM rules,
|
|
7511
|
-
// so we use textContent exclusively for consistent behavior
|
|
7512
|
-
// with @keyframes, @media, and other nested CSS blocks.
|
|
7513
|
-
styleTag.textContent += "\n".concat(cssString);
|
|
7514
|
-
|
|
7515
|
-
// Log injection stats periodically
|
|
7516
|
-
if (injectedCssHashSet.size % 10 === 0) {
|
|
7517
|
-
logger.debug("CSS injection stats: ".concat(injectedCssHashSet.size, " unique stylesheets injected"));
|
|
7518
|
-
}
|
|
7519
|
-
}
|
|
7520
|
-
performanceMonitor.end(marker);
|
|
7521
|
-
} catch (error) {
|
|
7522
|
-
performanceMonitor.end(marker);
|
|
7523
|
-
logger.error("Error injecting CSS:", error);
|
|
7524
|
-
}
|
|
7525
|
-
}
|
|
7842
|
+
// ============================================================================
|
|
7843
|
+
// Main API Exports
|
|
7844
|
+
// ============================================================================
|
|
7845
|
+
// twsxClassName - Unified CSS-in-JS API with variants and slots
|
|
7846
|
+
// tw - Atomic CSS class generator with pseudo-class support
|
|
7847
|
+
// REMOVED: Re-export removed to break circular dependency
|
|
7848
|
+
// Import directly from './className/index.js' if needed
|
|
7849
|
+
// export { twsxClassName, tw } from "./className/index.js";
|
|
7526
7850
|
|
|
7527
7851
|
const _excluded = ["name", "prefix", "hash", "hashLength", "inject", "_"],
|
|
7528
7852
|
_excluded2 = ["class", "className"],
|