tailwind-to-style 3.1.0 → 3.1.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/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * tailwind-to-style v3.1.0
2
+ * tailwind-to-style v3.1.1
3
3
  * Runtime Tailwind CSS to inline styles converter
4
4
  * Core only: tws, twsx, configure
5
5
  *
@@ -8313,6 +8313,13 @@ function applyDynamicAnimation(element, templateName) {
8313
8313
  // Global registry to track injected keyframes (prevents duplication)
8314
8314
  const _injectedKeyframes = new Set();
8315
8315
 
8316
+ // Global cache Maps for cached versions (twsxCache, twsxVariantsCache functions)
8317
+ const _twsxInputCache = new Map();
8318
+ const _twsxVariantsResultCache = new Map();
8319
+
8320
+ // WeakMap for object identity-based caching (fast lookup for repeated objects)
8321
+ const _objectIdentityCache = new WeakMap();
8322
+
8316
8323
  // Mapping of animation names to their keyframe definitions
8317
8324
  const BUILTIN_KEYFRAMES = {
8318
8325
  spin: {
@@ -9566,13 +9573,14 @@ function generateCssString(styles) {
9566
9573
  }
9567
9574
 
9568
9575
  /**
9569
- * Generate CSS string from style object with SCSS-like syntax
9576
+ * Generate CSS string from style object with SCSS-like syntax (NO CACHE)
9577
+ * This is the original non-cached version. Use twsx() for cached version.
9570
9578
  * Supports nested selectors, state variants, responsive variants, and @css directives
9571
9579
  * @param {Object} obj - Object with SCSS-like style format
9572
9580
  * @param {Object} [options] - Additional options, e.g. { inject: true/false }
9573
9581
  * @returns {string} Generated CSS string
9574
9582
  */
9575
- function twsx(obj) {
9583
+ function twsxNoCache(obj) {
9576
9584
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
9577
9585
  const totalMarker = performanceMonitor.start("twsx:total");
9578
9586
  try {
@@ -9767,7 +9775,8 @@ function twsx(obj) {
9767
9775
  }
9768
9776
 
9769
9777
  /**
9770
- * Create a variant-based style generator (similar to tailwind-variants)
9778
+ * Create a variant-based style generator (NO CACHE)
9779
+ * This is the original non-cached version. Use twsxVariants() for cached version.
9771
9780
  * Supports base styles, variants, compound variants, and default variants
9772
9781
  *
9773
9782
  * @param {Object} config - Configuration object
@@ -9778,7 +9787,7 @@ function twsx(obj) {
9778
9787
  * @returns {Function} A function that accepts variant props and returns merged classes
9779
9788
  *
9780
9789
  * @example
9781
- * const button = twsxVariants({
9790
+ * const button = twsxVariantsNoCache({
9782
9791
  * base: 'px-4 py-2 rounded font-medium',
9783
9792
  * variants: {
9784
9793
  * color: {
@@ -9802,7 +9811,7 @@ function twsx(obj) {
9802
9811
  * // Usage:
9803
9812
  * button({ color: 'primary', size: 'lg' }) // Returns merged classes
9804
9813
  */
9805
- function twsxVariants(className) {
9814
+ function twsxVariantsNoCache(className) {
9806
9815
  let config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
9807
9816
  const {
9808
9817
  base = "",
@@ -10241,6 +10250,155 @@ function twsxVariants(className) {
10241
10250
  return buildClassName;
10242
10251
  }
10243
10252
 
10253
+ // ============================================================================
10254
+ // FAST HASHING UTILITIES FOR OBJECT CACHING
10255
+ // ============================================================================
10256
+
10257
+ /**
10258
+ * FNV-1a hash algorithm - Fast and good distribution for strings
10259
+ * @param {string} str - String to hash
10260
+ * @returns {number} 32-bit hash
10261
+ */
10262
+ function hashString(str) {
10263
+ let hash = 2166136261; // FNV offset basis
10264
+ for (let i = 0; i < str.length; i++) {
10265
+ hash ^= str.charCodeAt(i);
10266
+ hash = Math.imul(hash, 16777619); // FNV prime
10267
+ }
10268
+ return hash >>> 0; // Convert to unsigned 32-bit
10269
+ }
10270
+
10271
+ /**
10272
+ * Fast deep hash for objects - Optimized for style objects
10273
+ * Strategy:
10274
+ * 1. Use object identity (WeakMap) for exact same object references
10275
+ * 2. For different objects, create stable hash from sorted keys + values
10276
+ * 3. Cache hash per object to avoid recomputation
10277
+ *
10278
+ * @param {any} obj - Object to hash
10279
+ * @param {Object} options - Additional options to include in hash
10280
+ * @returns {string} Hash key for caching
10281
+ */
10282
+ function fastObjectHash(obj) {
10283
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
10284
+ // Handle primitives
10285
+ if (obj === null || obj === undefined) return "null";
10286
+ if (typeof obj !== "object") return String(obj);
10287
+
10288
+ // Try object identity cache first (FASTEST - O(1))
10289
+ const identityKey = _objectIdentityCache.get(obj);
10290
+ if (identityKey) {
10291
+ // Include options in key if provided
10292
+ return options && Object.keys(options).length > 0 ? `${identityKey}:${JSON.stringify(options)}` : identityKey;
10293
+ }
10294
+
10295
+ // Generate hash from object structure
10296
+ const parts = [];
10297
+
10298
+ // Collect keys and sort for stability
10299
+ const keys = Object.keys(obj).sort();
10300
+ for (const key of keys) {
10301
+ const value = obj[key];
10302
+ if (value && typeof value === "object") {
10303
+ // Nested object: recursively hash
10304
+ parts.push(`${key}:${fastObjectHash(value)}`);
10305
+ } else {
10306
+ // Primitive: direct conversion
10307
+ parts.push(`${key}:${value}`);
10308
+ }
10309
+ }
10310
+
10311
+ // Hash the concatenated string (faster than storing full string)
10312
+ const structureStr = parts.join("|");
10313
+ const hash = hashString(structureStr);
10314
+
10315
+ // Create compact key: hash + length (collision detection)
10316
+ const hashKey = `h${hash}_l${keys.length}`;
10317
+
10318
+ // Store in WeakMap for future O(1) lookups
10319
+ _objectIdentityCache.set(obj, hashKey);
10320
+
10321
+ // Include options if provided
10322
+ return options && Object.keys(options).length > 0 ? `${hashKey}:${JSON.stringify(options)}` : hashKey;
10323
+ }
10324
+
10325
+ /**
10326
+ * 🚀 CACHED VERSION OF TWSX (DEFAULT)
10327
+ * Generate CSS string with input-level caching for repeated calls
10328
+ * Uses fast FNV-1a hash + WeakMap for 10-100x performance improvement
10329
+ *
10330
+ * @param {Object} obj - Object with SCSS-like style format
10331
+ * @param {Object} [options] - Additional options, e.g. { inject: true/false }
10332
+ * @returns {string} Generated CSS string
10333
+ *
10334
+ * @example
10335
+ * const styles = { '.btn': 'bg-blue-500 text-white p-4' };
10336
+ * twsx(styles); // First call: ~40ms
10337
+ * twsx(styles); // Cached: ~0.1ms (100x faster!)
10338
+ *
10339
+ * // For non-cached version (rare case):
10340
+ * twsxNoCache(styles);
10341
+ */
10342
+ function twsx(obj) {
10343
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
10344
+ // Create fast hash key from input (100x faster than JSON.stringify)
10345
+ const cacheKey = fastObjectHash(obj, options);
10346
+
10347
+ // Check cache first
10348
+ if (_twsxInputCache.has(cacheKey)) {
10349
+ const cached = _twsxInputCache.get(cacheKey);
10350
+
10351
+ // Handle injection for cached result
10352
+ const {
10353
+ inject = true
10354
+ } = options;
10355
+ if (inject && typeof window !== "undefined" && typeof document !== "undefined") {
10356
+ autoInjectCss(cached);
10357
+ }
10358
+ return cached;
10359
+ }
10360
+
10361
+ // Cache miss: call original twsxNoCache and cache result
10362
+ const result = twsxNoCache(obj, options);
10363
+ _twsxInputCache.set(cacheKey, result);
10364
+ return result;
10365
+ }
10366
+
10367
+ /**
10368
+ * 🚀 CACHED VERSION OF TWSXVARIANTS (DEFAULT)
10369
+ * Create variant-based style generator with config-level caching
10370
+ * Uses fast FNV-1a hash for 10-100x performance improvement
10371
+ *
10372
+ * @param {string} className - Base class name
10373
+ * @param {Object} config - Configuration object (base, variants, compoundVariants, etc.)
10374
+ * @returns {Function} A function that accepts variant props and returns merged classes
10375
+ *
10376
+ * @example
10377
+ * const button = twsxVariants('btn', {
10378
+ * variants: { color: { primary: {...}, secondary: {...} } }
10379
+ * });
10380
+ * // First call: ~50ms to generate function
10381
+ * // Subsequent calls with same config: ~0.1ms (returns cached function)
10382
+ *
10383
+ * // For non-cached version (rare case):
10384
+ * twsxVariantsNoCache('btn', config);
10385
+ */
10386
+ function twsxVariants(className) {
10387
+ let config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
10388
+ // Create fast hash key from className and config (100x faster than JSON.stringify)
10389
+ const cacheKey = `${className}:${fastObjectHash(config)}`;
10390
+
10391
+ // Check cache first
10392
+ if (_twsxVariantsResultCache.has(cacheKey)) {
10393
+ return _twsxVariantsResultCache.get(cacheKey);
10394
+ }
10395
+
10396
+ // Cache miss: call original twsxVariantsNoCache and cache result
10397
+ const result = twsxVariantsNoCache(className, config);
10398
+ _twsxVariantsResultCache.set(cacheKey, result);
10399
+ return result;
10400
+ }
10401
+
10244
10402
  // Simple hashCode function for CSS deduplication
10245
10403
  function getCssHash(str) {
10246
10404
  let hash = 0,
@@ -10313,10 +10471,13 @@ const performanceUtils = {
10313
10471
  configOptions: configOptionsCache.size,
10314
10472
  parseSelector: parseSelectorCache.size,
10315
10473
  encodeBracket: encodeBracketCache.size,
10316
- decodeBracket: decodeBracketCache.size
10474
+ decodeBracket: decodeBracketCache.size,
10475
+ twsxInputCacheSize: _twsxInputCache.size,
10476
+ twsxVariantsCacheSize: _twsxVariantsResultCache.size
10317
10477
  },
10318
10478
  injectionStats: {
10319
- uniqueStylesheets: injectedCssHashSet.size
10479
+ uniqueStylesheets: injectedCssHashSet.size,
10480
+ keyframes: _injectedKeyframes.size
10320
10481
  }
10321
10482
  };
10322
10483
  },
@@ -10326,6 +10487,10 @@ const performanceUtils = {
10326
10487
  parseSelectorCache.clear();
10327
10488
  encodeBracketCache.clear();
10328
10489
  decodeBracketCache.clear();
10490
+
10491
+ // Clear new input-level caches
10492
+ _twsxInputCache.clear();
10493
+ _twsxVariantsResultCache.clear();
10329
10494
  logger.info("All caches cleared");
10330
10495
  performanceMonitor.end(marker);
10331
10496
  },
package/dist/index.esm.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * tailwind-to-style v3.1.0
2
+ * tailwind-to-style v3.1.1
3
3
  * Runtime Tailwind CSS to inline styles converter
4
4
  * Core only: tws, twsx, configure
5
5
  *
@@ -8311,6 +8311,13 @@ function applyDynamicAnimation(element, templateName) {
8311
8311
  // Global registry to track injected keyframes (prevents duplication)
8312
8312
  const _injectedKeyframes = new Set();
8313
8313
 
8314
+ // Global cache Maps for cached versions (twsxCache, twsxVariantsCache functions)
8315
+ const _twsxInputCache = new Map();
8316
+ const _twsxVariantsResultCache = new Map();
8317
+
8318
+ // WeakMap for object identity-based caching (fast lookup for repeated objects)
8319
+ const _objectIdentityCache = new WeakMap();
8320
+
8314
8321
  // Mapping of animation names to their keyframe definitions
8315
8322
  const BUILTIN_KEYFRAMES = {
8316
8323
  spin: {
@@ -9564,13 +9571,14 @@ function generateCssString(styles) {
9564
9571
  }
9565
9572
 
9566
9573
  /**
9567
- * Generate CSS string from style object with SCSS-like syntax
9574
+ * Generate CSS string from style object with SCSS-like syntax (NO CACHE)
9575
+ * This is the original non-cached version. Use twsx() for cached version.
9568
9576
  * Supports nested selectors, state variants, responsive variants, and @css directives
9569
9577
  * @param {Object} obj - Object with SCSS-like style format
9570
9578
  * @param {Object} [options] - Additional options, e.g. { inject: true/false }
9571
9579
  * @returns {string} Generated CSS string
9572
9580
  */
9573
- function twsx(obj) {
9581
+ function twsxNoCache(obj) {
9574
9582
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
9575
9583
  const totalMarker = performanceMonitor.start("twsx:total");
9576
9584
  try {
@@ -9765,7 +9773,8 @@ function twsx(obj) {
9765
9773
  }
9766
9774
 
9767
9775
  /**
9768
- * Create a variant-based style generator (similar to tailwind-variants)
9776
+ * Create a variant-based style generator (NO CACHE)
9777
+ * This is the original non-cached version. Use twsxVariants() for cached version.
9769
9778
  * Supports base styles, variants, compound variants, and default variants
9770
9779
  *
9771
9780
  * @param {Object} config - Configuration object
@@ -9776,7 +9785,7 @@ function twsx(obj) {
9776
9785
  * @returns {Function} A function that accepts variant props and returns merged classes
9777
9786
  *
9778
9787
  * @example
9779
- * const button = twsxVariants({
9788
+ * const button = twsxVariantsNoCache({
9780
9789
  * base: 'px-4 py-2 rounded font-medium',
9781
9790
  * variants: {
9782
9791
  * color: {
@@ -9800,7 +9809,7 @@ function twsx(obj) {
9800
9809
  * // Usage:
9801
9810
  * button({ color: 'primary', size: 'lg' }) // Returns merged classes
9802
9811
  */
9803
- function twsxVariants(className) {
9812
+ function twsxVariantsNoCache(className) {
9804
9813
  let config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
9805
9814
  const {
9806
9815
  base = "",
@@ -10239,6 +10248,155 @@ function twsxVariants(className) {
10239
10248
  return buildClassName;
10240
10249
  }
10241
10250
 
10251
+ // ============================================================================
10252
+ // FAST HASHING UTILITIES FOR OBJECT CACHING
10253
+ // ============================================================================
10254
+
10255
+ /**
10256
+ * FNV-1a hash algorithm - Fast and good distribution for strings
10257
+ * @param {string} str - String to hash
10258
+ * @returns {number} 32-bit hash
10259
+ */
10260
+ function hashString(str) {
10261
+ let hash = 2166136261; // FNV offset basis
10262
+ for (let i = 0; i < str.length; i++) {
10263
+ hash ^= str.charCodeAt(i);
10264
+ hash = Math.imul(hash, 16777619); // FNV prime
10265
+ }
10266
+ return hash >>> 0; // Convert to unsigned 32-bit
10267
+ }
10268
+
10269
+ /**
10270
+ * Fast deep hash for objects - Optimized for style objects
10271
+ * Strategy:
10272
+ * 1. Use object identity (WeakMap) for exact same object references
10273
+ * 2. For different objects, create stable hash from sorted keys + values
10274
+ * 3. Cache hash per object to avoid recomputation
10275
+ *
10276
+ * @param {any} obj - Object to hash
10277
+ * @param {Object} options - Additional options to include in hash
10278
+ * @returns {string} Hash key for caching
10279
+ */
10280
+ function fastObjectHash(obj) {
10281
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
10282
+ // Handle primitives
10283
+ if (obj === null || obj === undefined) return "null";
10284
+ if (typeof obj !== "object") return String(obj);
10285
+
10286
+ // Try object identity cache first (FASTEST - O(1))
10287
+ const identityKey = _objectIdentityCache.get(obj);
10288
+ if (identityKey) {
10289
+ // Include options in key if provided
10290
+ return options && Object.keys(options).length > 0 ? `${identityKey}:${JSON.stringify(options)}` : identityKey;
10291
+ }
10292
+
10293
+ // Generate hash from object structure
10294
+ const parts = [];
10295
+
10296
+ // Collect keys and sort for stability
10297
+ const keys = Object.keys(obj).sort();
10298
+ for (const key of keys) {
10299
+ const value = obj[key];
10300
+ if (value && typeof value === "object") {
10301
+ // Nested object: recursively hash
10302
+ parts.push(`${key}:${fastObjectHash(value)}`);
10303
+ } else {
10304
+ // Primitive: direct conversion
10305
+ parts.push(`${key}:${value}`);
10306
+ }
10307
+ }
10308
+
10309
+ // Hash the concatenated string (faster than storing full string)
10310
+ const structureStr = parts.join("|");
10311
+ const hash = hashString(structureStr);
10312
+
10313
+ // Create compact key: hash + length (collision detection)
10314
+ const hashKey = `h${hash}_l${keys.length}`;
10315
+
10316
+ // Store in WeakMap for future O(1) lookups
10317
+ _objectIdentityCache.set(obj, hashKey);
10318
+
10319
+ // Include options if provided
10320
+ return options && Object.keys(options).length > 0 ? `${hashKey}:${JSON.stringify(options)}` : hashKey;
10321
+ }
10322
+
10323
+ /**
10324
+ * 🚀 CACHED VERSION OF TWSX (DEFAULT)
10325
+ * Generate CSS string with input-level caching for repeated calls
10326
+ * Uses fast FNV-1a hash + WeakMap for 10-100x performance improvement
10327
+ *
10328
+ * @param {Object} obj - Object with SCSS-like style format
10329
+ * @param {Object} [options] - Additional options, e.g. { inject: true/false }
10330
+ * @returns {string} Generated CSS string
10331
+ *
10332
+ * @example
10333
+ * const styles = { '.btn': 'bg-blue-500 text-white p-4' };
10334
+ * twsx(styles); // First call: ~40ms
10335
+ * twsx(styles); // Cached: ~0.1ms (100x faster!)
10336
+ *
10337
+ * // For non-cached version (rare case):
10338
+ * twsxNoCache(styles);
10339
+ */
10340
+ function twsx(obj) {
10341
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
10342
+ // Create fast hash key from input (100x faster than JSON.stringify)
10343
+ const cacheKey = fastObjectHash(obj, options);
10344
+
10345
+ // Check cache first
10346
+ if (_twsxInputCache.has(cacheKey)) {
10347
+ const cached = _twsxInputCache.get(cacheKey);
10348
+
10349
+ // Handle injection for cached result
10350
+ const {
10351
+ inject = true
10352
+ } = options;
10353
+ if (inject && typeof window !== "undefined" && typeof document !== "undefined") {
10354
+ autoInjectCss(cached);
10355
+ }
10356
+ return cached;
10357
+ }
10358
+
10359
+ // Cache miss: call original twsxNoCache and cache result
10360
+ const result = twsxNoCache(obj, options);
10361
+ _twsxInputCache.set(cacheKey, result);
10362
+ return result;
10363
+ }
10364
+
10365
+ /**
10366
+ * 🚀 CACHED VERSION OF TWSXVARIANTS (DEFAULT)
10367
+ * Create variant-based style generator with config-level caching
10368
+ * Uses fast FNV-1a hash for 10-100x performance improvement
10369
+ *
10370
+ * @param {string} className - Base class name
10371
+ * @param {Object} config - Configuration object (base, variants, compoundVariants, etc.)
10372
+ * @returns {Function} A function that accepts variant props and returns merged classes
10373
+ *
10374
+ * @example
10375
+ * const button = twsxVariants('btn', {
10376
+ * variants: { color: { primary: {...}, secondary: {...} } }
10377
+ * });
10378
+ * // First call: ~50ms to generate function
10379
+ * // Subsequent calls with same config: ~0.1ms (returns cached function)
10380
+ *
10381
+ * // For non-cached version (rare case):
10382
+ * twsxVariantsNoCache('btn', config);
10383
+ */
10384
+ function twsxVariants(className) {
10385
+ let config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
10386
+ // Create fast hash key from className and config (100x faster than JSON.stringify)
10387
+ const cacheKey = `${className}:${fastObjectHash(config)}`;
10388
+
10389
+ // Check cache first
10390
+ if (_twsxVariantsResultCache.has(cacheKey)) {
10391
+ return _twsxVariantsResultCache.get(cacheKey);
10392
+ }
10393
+
10394
+ // Cache miss: call original twsxVariantsNoCache and cache result
10395
+ const result = twsxVariantsNoCache(className, config);
10396
+ _twsxVariantsResultCache.set(cacheKey, result);
10397
+ return result;
10398
+ }
10399
+
10242
10400
  // Simple hashCode function for CSS deduplication
10243
10401
  function getCssHash(str) {
10244
10402
  let hash = 0,
@@ -10311,10 +10469,13 @@ const performanceUtils = {
10311
10469
  configOptions: configOptionsCache.size,
10312
10470
  parseSelector: parseSelectorCache.size,
10313
10471
  encodeBracket: encodeBracketCache.size,
10314
- decodeBracket: decodeBracketCache.size
10472
+ decodeBracket: decodeBracketCache.size,
10473
+ twsxInputCacheSize: _twsxInputCache.size,
10474
+ twsxVariantsCacheSize: _twsxVariantsResultCache.size
10315
10475
  },
10316
10476
  injectionStats: {
10317
- uniqueStylesheets: injectedCssHashSet.size
10477
+ uniqueStylesheets: injectedCssHashSet.size,
10478
+ keyframes: _injectedKeyframes.size
10318
10479
  }
10319
10480
  };
10320
10481
  },
@@ -10324,6 +10485,10 @@ const performanceUtils = {
10324
10485
  parseSelectorCache.clear();
10325
10486
  encodeBracketCache.clear();
10326
10487
  decodeBracketCache.clear();
10488
+
10489
+ // Clear new input-level caches
10490
+ _twsxInputCache.clear();
10491
+ _twsxVariantsResultCache.clear();
10327
10492
  logger.info("All caches cleared");
10328
10493
  performanceMonitor.end(marker);
10329
10494
  },