tailwind-to-style 3.2.1 → 3.2.2

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * tailwind-to-style v3.2.1
2
+ * tailwind-to-style v3.2.2
3
3
  * Runtime Tailwind CSS to inline styles converter
4
4
  *
5
5
  * @author Bigetion
@@ -9448,27 +9448,40 @@ function fastObjectHash(obj) {
9448
9448
  */
9449
9449
  function twsx(obj) {
9450
9450
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
9451
- // Create fast hash key from input (100x faster than JSON.stringify)
9451
+ // Create fast hash key from input content (100x faster than JSON.stringify)
9452
9452
  const cacheKey = fastObjectHash(obj, options);
9453
+ const {
9454
+ inject = true
9455
+ } = options;
9456
+
9457
+ // Derive a STABLE registry key from the object's top-level selector KEYS only.
9458
+ // This key is independent of the CSS class values, so when styles are edited
9459
+ // during HMR (same selectors, different Tailwind classes) the old slot is
9460
+ // replaced rather than a new slot being created — preventing CSS accumulation.
9461
+ const registryKey = obj && typeof obj === "object" && !Array.isArray(obj) ? Object.keys(obj).sort().join("|") : cacheKey; // fallback for edge cases
9453
9462
 
9454
9463
  // Check cache first
9455
9464
  if (_twsxInputCache.has(cacheKey)) {
9456
9465
  const cached = _twsxInputCache.get(cacheKey);
9457
9466
 
9458
- // Handle injection for cached result
9459
- const {
9460
- inject = true
9461
- } = options;
9467
+ // Re-inject with registryKey so the slot stays registered (no-op when unchanged).
9462
9468
  if (inject && (IS_BROWSER || _ssrCollecting)) {
9463
- autoInjectCss(cached);
9469
+ autoInjectCss(cached, registryKey);
9464
9470
  }
9465
9471
  return cached;
9466
9472
  }
9467
9473
 
9468
- // Cache miss: call original twsxNoCache and cache result
9469
- const result = twsxNoCache(obj, options);
9474
+ // Cache miss: generate CSS without internal auto-injection so that twsx owns
9475
+ // the injection and can pass the selector-based registryKey for slot replacement.
9476
+ const result = twsxNoCache(obj, {
9477
+ ...options,
9478
+ inject: false
9479
+ });
9470
9480
  _twsxInputCache.set(cacheKey, result);
9471
9481
  evictMap(_twsxInputCache);
9482
+ if (inject && (IS_BROWSER || _ssrCollecting)) {
9483
+ autoInjectCss(result, registryKey);
9484
+ }
9472
9485
  return result;
9473
9486
  }
9474
9487
 
@@ -9524,12 +9537,54 @@ function getCssHash(str) {
9524
9537
 
9525
9538
  // Enhanced auto-inject CSS with performance monitoring & SSR support
9526
9539
  const injectedCssHashSet = new Set();
9540
+
9541
+ // Registry of sourceKey → cssBlock for smart slot-based replacement.
9542
+ // Prevents stale CSS chunks from accumulating across HMR cycles.
9543
+ const _cssBlockRegistry = new Map();
9544
+
9545
+ /**
9546
+ * Rebuild the single twsx style tag from the full CSS block registry.
9547
+ * Called whenever a block is added or updated.
9548
+ */
9549
+ function rebuildStyleTag() {
9550
+ let styleTag = document.getElementById("twsx-auto-style");
9551
+ if (!styleTag) {
9552
+ styleTag = document.createElement("style");
9553
+ styleTag.id = "twsx-auto-style";
9554
+ styleTag.setAttribute("data-twsx", "");
9555
+ document.head.appendChild(styleTag);
9556
+ }
9557
+ styleTag.textContent = [..._cssBlockRegistry.values()].join("\n");
9558
+ }
9527
9559
  function autoInjectCss(cssString) {
9560
+ let sourceKey = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
9528
9561
  const marker = performanceMonitor.start("css:inject");
9529
9562
  try {
9530
9563
  // SSR mode: collect CSS strings instead of DOM injection
9531
9564
  if (_ssrCollecting) ;
9532
9565
  if (IS_BROWSER) {
9566
+ if (sourceKey) {
9567
+ // Slot-based update: each unique twsx(obj) call owns its own CSS block.
9568
+ // When styles change (new content, same logical call site via cacheKey)
9569
+ // the old slot is replaced and the style tag is fully rebuilt, so no
9570
+ // stale rules from previous HMR cycles can pile up.
9571
+ const existing = _cssBlockRegistry.get(sourceKey);
9572
+ if (existing === cssString) {
9573
+ // Identical content – nothing to do.
9574
+ performanceMonitor.end(marker);
9575
+ return;
9576
+ }
9577
+ _cssBlockRegistry.set(sourceKey, cssString);
9578
+ rebuildStyleTag();
9579
+ if (_cssBlockRegistry.size % 10 === 0) {
9580
+ logger.debug(`CSS registry stats: ${_cssBlockRegistry.size} blocks registered`);
9581
+ }
9582
+ performanceMonitor.end(marker);
9583
+ return;
9584
+ }
9585
+
9586
+ // Fallback path (e.g. direct autoInjectCss calls without a sourceKey):
9587
+ // keep the original hash-based dedup + append behaviour.
9533
9588
  const cssHash = getCssHash(cssString);
9534
9589
  if (injectedCssHashSet.has(cssHash)) {
9535
9590
  performanceMonitor.end(marker);
@@ -1,5 +1,5 @@
1
1
  /**
2
- * tailwind-to-style v3.2.1
2
+ * tailwind-to-style v3.2.2
3
3
  * Runtime Tailwind CSS to inline styles converter
4
4
  *
5
5
  * @author Bigetion
@@ -9446,27 +9446,40 @@ function fastObjectHash(obj) {
9446
9446
  */
9447
9447
  function twsx(obj) {
9448
9448
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
9449
- // Create fast hash key from input (100x faster than JSON.stringify)
9449
+ // Create fast hash key from input content (100x faster than JSON.stringify)
9450
9450
  const cacheKey = fastObjectHash(obj, options);
9451
+ const {
9452
+ inject = true
9453
+ } = options;
9454
+
9455
+ // Derive a STABLE registry key from the object's top-level selector KEYS only.
9456
+ // This key is independent of the CSS class values, so when styles are edited
9457
+ // during HMR (same selectors, different Tailwind classes) the old slot is
9458
+ // replaced rather than a new slot being created — preventing CSS accumulation.
9459
+ const registryKey = obj && typeof obj === "object" && !Array.isArray(obj) ? Object.keys(obj).sort().join("|") : cacheKey; // fallback for edge cases
9451
9460
 
9452
9461
  // Check cache first
9453
9462
  if (_twsxInputCache.has(cacheKey)) {
9454
9463
  const cached = _twsxInputCache.get(cacheKey);
9455
9464
 
9456
- // Handle injection for cached result
9457
- const {
9458
- inject = true
9459
- } = options;
9465
+ // Re-inject with registryKey so the slot stays registered (no-op when unchanged).
9460
9466
  if (inject && (IS_BROWSER || _ssrCollecting)) {
9461
- autoInjectCss(cached);
9467
+ autoInjectCss(cached, registryKey);
9462
9468
  }
9463
9469
  return cached;
9464
9470
  }
9465
9471
 
9466
- // Cache miss: call original twsxNoCache and cache result
9467
- const result = twsxNoCache(obj, options);
9472
+ // Cache miss: generate CSS without internal auto-injection so that twsx owns
9473
+ // the injection and can pass the selector-based registryKey for slot replacement.
9474
+ const result = twsxNoCache(obj, {
9475
+ ...options,
9476
+ inject: false
9477
+ });
9468
9478
  _twsxInputCache.set(cacheKey, result);
9469
9479
  evictMap(_twsxInputCache);
9480
+ if (inject && (IS_BROWSER || _ssrCollecting)) {
9481
+ autoInjectCss(result, registryKey);
9482
+ }
9470
9483
  return result;
9471
9484
  }
9472
9485
 
@@ -9522,12 +9535,54 @@ function getCssHash(str) {
9522
9535
 
9523
9536
  // Enhanced auto-inject CSS with performance monitoring & SSR support
9524
9537
  const injectedCssHashSet = new Set();
9538
+
9539
+ // Registry of sourceKey → cssBlock for smart slot-based replacement.
9540
+ // Prevents stale CSS chunks from accumulating across HMR cycles.
9541
+ const _cssBlockRegistry = new Map();
9542
+
9543
+ /**
9544
+ * Rebuild the single twsx style tag from the full CSS block registry.
9545
+ * Called whenever a block is added or updated.
9546
+ */
9547
+ function rebuildStyleTag() {
9548
+ let styleTag = document.getElementById("twsx-auto-style");
9549
+ if (!styleTag) {
9550
+ styleTag = document.createElement("style");
9551
+ styleTag.id = "twsx-auto-style";
9552
+ styleTag.setAttribute("data-twsx", "");
9553
+ document.head.appendChild(styleTag);
9554
+ }
9555
+ styleTag.textContent = [..._cssBlockRegistry.values()].join("\n");
9556
+ }
9525
9557
  function autoInjectCss(cssString) {
9558
+ let sourceKey = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
9526
9559
  const marker = performanceMonitor.start("css:inject");
9527
9560
  try {
9528
9561
  // SSR mode: collect CSS strings instead of DOM injection
9529
9562
  if (_ssrCollecting) ;
9530
9563
  if (IS_BROWSER) {
9564
+ if (sourceKey) {
9565
+ // Slot-based update: each unique twsx(obj) call owns its own CSS block.
9566
+ // When styles change (new content, same logical call site via cacheKey)
9567
+ // the old slot is replaced and the style tag is fully rebuilt, so no
9568
+ // stale rules from previous HMR cycles can pile up.
9569
+ const existing = _cssBlockRegistry.get(sourceKey);
9570
+ if (existing === cssString) {
9571
+ // Identical content – nothing to do.
9572
+ performanceMonitor.end(marker);
9573
+ return;
9574
+ }
9575
+ _cssBlockRegistry.set(sourceKey, cssString);
9576
+ rebuildStyleTag();
9577
+ if (_cssBlockRegistry.size % 10 === 0) {
9578
+ logger.debug(`CSS registry stats: ${_cssBlockRegistry.size} blocks registered`);
9579
+ }
9580
+ performanceMonitor.end(marker);
9581
+ return;
9582
+ }
9583
+
9584
+ // Fallback path (e.g. direct autoInjectCss calls without a sourceKey):
9585
+ // keep the original hash-based dedup + append behaviour.
9531
9586
  const cssHash = getCssHash(cssString);
9532
9587
  if (injectedCssHashSet.has(cssHash)) {
9533
9588
  performanceMonitor.end(marker);