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.
package/dist/cx.cjs CHANGED
@@ -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
package/dist/cx.esm.js CHANGED
@@ -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
package/dist/index.cjs CHANGED
@@ -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
@@ -10720,27 +10720,40 @@ function fastObjectHash(obj) {
10720
10720
  */
10721
10721
  function twsx(obj) {
10722
10722
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
10723
- // Create fast hash key from input (100x faster than JSON.stringify)
10723
+ // Create fast hash key from input content (100x faster than JSON.stringify)
10724
10724
  const cacheKey = fastObjectHash(obj, options);
10725
+ const {
10726
+ inject = true
10727
+ } = options;
10728
+
10729
+ // Derive a STABLE registry key from the object's top-level selector KEYS only.
10730
+ // This key is independent of the CSS class values, so when styles are edited
10731
+ // during HMR (same selectors, different Tailwind classes) the old slot is
10732
+ // replaced rather than a new slot being created — preventing CSS accumulation.
10733
+ const registryKey = obj && typeof obj === "object" && !Array.isArray(obj) ? Object.keys(obj).sort().join("|") : cacheKey; // fallback for edge cases
10725
10734
 
10726
10735
  // Check cache first
10727
10736
  if (_twsxInputCache.has(cacheKey)) {
10728
10737
  const cached = _twsxInputCache.get(cacheKey);
10729
10738
 
10730
- // Handle injection for cached result
10731
- const {
10732
- inject = true
10733
- } = options;
10739
+ // Re-inject with registryKey so the slot stays registered (no-op when unchanged).
10734
10740
  if (inject && (IS_BROWSER || _ssrCollecting)) {
10735
- autoInjectCss(cached);
10741
+ autoInjectCss(cached, registryKey);
10736
10742
  }
10737
10743
  return cached;
10738
10744
  }
10739
10745
 
10740
- // Cache miss: call original twsxNoCache and cache result
10741
- const result = twsxNoCache(obj, options);
10746
+ // Cache miss: generate CSS without internal auto-injection so that twsx owns
10747
+ // the injection and can pass the selector-based registryKey for slot replacement.
10748
+ const result = twsxNoCache(obj, {
10749
+ ...options,
10750
+ inject: false
10751
+ });
10742
10752
  _twsxInputCache.set(cacheKey, result);
10743
10753
  evictMap(_twsxInputCache);
10754
+ if (inject && (IS_BROWSER || _ssrCollecting)) {
10755
+ autoInjectCss(result, registryKey);
10756
+ }
10744
10757
  return result;
10745
10758
  }
10746
10759
 
@@ -10796,7 +10809,27 @@ function getCssHash(str) {
10796
10809
 
10797
10810
  // Enhanced auto-inject CSS with performance monitoring & SSR support
10798
10811
  const injectedCssHashSet = new Set();
10812
+
10813
+ // Registry of sourceKey → cssBlock for smart slot-based replacement.
10814
+ // Prevents stale CSS chunks from accumulating across HMR cycles.
10815
+ const _cssBlockRegistry = new Map();
10816
+
10817
+ /**
10818
+ * Rebuild the single twsx style tag from the full CSS block registry.
10819
+ * Called whenever a block is added or updated.
10820
+ */
10821
+ function rebuildStyleTag() {
10822
+ let styleTag = document.getElementById("twsx-auto-style");
10823
+ if (!styleTag) {
10824
+ styleTag = document.createElement("style");
10825
+ styleTag.id = "twsx-auto-style";
10826
+ styleTag.setAttribute("data-twsx", "");
10827
+ document.head.appendChild(styleTag);
10828
+ }
10829
+ styleTag.textContent = [..._cssBlockRegistry.values()].join("\n");
10830
+ }
10799
10831
  function autoInjectCss(cssString) {
10832
+ let sourceKey = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
10800
10833
  const marker = performanceMonitor.start("css:inject");
10801
10834
  try {
10802
10835
  // SSR mode: collect CSS strings instead of DOM injection
@@ -10813,6 +10846,28 @@ function autoInjectCss(cssString) {
10813
10846
  return;
10814
10847
  }
10815
10848
  if (IS_BROWSER) {
10849
+ if (sourceKey) {
10850
+ // Slot-based update: each unique twsx(obj) call owns its own CSS block.
10851
+ // When styles change (new content, same logical call site via cacheKey)
10852
+ // the old slot is replaced and the style tag is fully rebuilt, so no
10853
+ // stale rules from previous HMR cycles can pile up.
10854
+ const existing = _cssBlockRegistry.get(sourceKey);
10855
+ if (existing === cssString) {
10856
+ // Identical content – nothing to do.
10857
+ performanceMonitor.end(marker);
10858
+ return;
10859
+ }
10860
+ _cssBlockRegistry.set(sourceKey, cssString);
10861
+ rebuildStyleTag();
10862
+ if (_cssBlockRegistry.size % 10 === 0) {
10863
+ logger.debug(`CSS registry stats: ${_cssBlockRegistry.size} blocks registered`);
10864
+ }
10865
+ performanceMonitor.end(marker);
10866
+ return;
10867
+ }
10868
+
10869
+ // Fallback path (e.g. direct autoInjectCss calls without a sourceKey):
10870
+ // keep the original hash-based dedup + append behaviour.
10816
10871
  const cssHash = getCssHash(cssString);
10817
10872
  if (injectedCssHashSet.has(cssHash)) {
10818
10873
  performanceMonitor.end(marker);
@@ -10878,6 +10933,7 @@ const performanceUtils = {
10878
10933
  },
10879
10934
  injectionStats: {
10880
10935
  uniqueStylesheets: injectedCssHashSet.size,
10936
+ cssBlocks: _cssBlockRegistry.size,
10881
10937
  keyframes: _injectedKeyframes.size
10882
10938
  }
10883
10939
  };
@@ -10892,6 +10948,14 @@ const performanceUtils = {
10892
10948
  // Clear new input-level caches
10893
10949
  _twsxInputCache.clear();
10894
10950
  _twsxVariantsResultCache.clear();
10951
+
10952
+ // Clear CSS block registry and rebuild (empty) the style tag
10953
+ _cssBlockRegistry.clear();
10954
+ injectedCssHashSet.clear();
10955
+ if (IS_BROWSER) {
10956
+ const styleTag = document.getElementById("twsx-auto-style");
10957
+ if (styleTag) styleTag.textContent = "";
10958
+ }
10895
10959
  logger.info("All caches cleared");
10896
10960
  performanceMonitor.end(marker);
10897
10961
  },
package/dist/index.esm.js CHANGED
@@ -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
@@ -10718,27 +10718,40 @@ function fastObjectHash(obj) {
10718
10718
  */
10719
10719
  function twsx(obj) {
10720
10720
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
10721
- // Create fast hash key from input (100x faster than JSON.stringify)
10721
+ // Create fast hash key from input content (100x faster than JSON.stringify)
10722
10722
  const cacheKey = fastObjectHash(obj, options);
10723
+ const {
10724
+ inject = true
10725
+ } = options;
10726
+
10727
+ // Derive a STABLE registry key from the object's top-level selector KEYS only.
10728
+ // This key is independent of the CSS class values, so when styles are edited
10729
+ // during HMR (same selectors, different Tailwind classes) the old slot is
10730
+ // replaced rather than a new slot being created — preventing CSS accumulation.
10731
+ const registryKey = obj && typeof obj === "object" && !Array.isArray(obj) ? Object.keys(obj).sort().join("|") : cacheKey; // fallback for edge cases
10723
10732
 
10724
10733
  // Check cache first
10725
10734
  if (_twsxInputCache.has(cacheKey)) {
10726
10735
  const cached = _twsxInputCache.get(cacheKey);
10727
10736
 
10728
- // Handle injection for cached result
10729
- const {
10730
- inject = true
10731
- } = options;
10737
+ // Re-inject with registryKey so the slot stays registered (no-op when unchanged).
10732
10738
  if (inject && (IS_BROWSER || _ssrCollecting)) {
10733
- autoInjectCss(cached);
10739
+ autoInjectCss(cached, registryKey);
10734
10740
  }
10735
10741
  return cached;
10736
10742
  }
10737
10743
 
10738
- // Cache miss: call original twsxNoCache and cache result
10739
- const result = twsxNoCache(obj, options);
10744
+ // Cache miss: generate CSS without internal auto-injection so that twsx owns
10745
+ // the injection and can pass the selector-based registryKey for slot replacement.
10746
+ const result = twsxNoCache(obj, {
10747
+ ...options,
10748
+ inject: false
10749
+ });
10740
10750
  _twsxInputCache.set(cacheKey, result);
10741
10751
  evictMap(_twsxInputCache);
10752
+ if (inject && (IS_BROWSER || _ssrCollecting)) {
10753
+ autoInjectCss(result, registryKey);
10754
+ }
10742
10755
  return result;
10743
10756
  }
10744
10757
 
@@ -10794,7 +10807,27 @@ function getCssHash(str) {
10794
10807
 
10795
10808
  // Enhanced auto-inject CSS with performance monitoring & SSR support
10796
10809
  const injectedCssHashSet = new Set();
10810
+
10811
+ // Registry of sourceKey → cssBlock for smart slot-based replacement.
10812
+ // Prevents stale CSS chunks from accumulating across HMR cycles.
10813
+ const _cssBlockRegistry = new Map();
10814
+
10815
+ /**
10816
+ * Rebuild the single twsx style tag from the full CSS block registry.
10817
+ * Called whenever a block is added or updated.
10818
+ */
10819
+ function rebuildStyleTag() {
10820
+ let styleTag = document.getElementById("twsx-auto-style");
10821
+ if (!styleTag) {
10822
+ styleTag = document.createElement("style");
10823
+ styleTag.id = "twsx-auto-style";
10824
+ styleTag.setAttribute("data-twsx", "");
10825
+ document.head.appendChild(styleTag);
10826
+ }
10827
+ styleTag.textContent = [..._cssBlockRegistry.values()].join("\n");
10828
+ }
10797
10829
  function autoInjectCss(cssString) {
10830
+ let sourceKey = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
10798
10831
  const marker = performanceMonitor.start("css:inject");
10799
10832
  try {
10800
10833
  // SSR mode: collect CSS strings instead of DOM injection
@@ -10811,6 +10844,28 @@ function autoInjectCss(cssString) {
10811
10844
  return;
10812
10845
  }
10813
10846
  if (IS_BROWSER) {
10847
+ if (sourceKey) {
10848
+ // Slot-based update: each unique twsx(obj) call owns its own CSS block.
10849
+ // When styles change (new content, same logical call site via cacheKey)
10850
+ // the old slot is replaced and the style tag is fully rebuilt, so no
10851
+ // stale rules from previous HMR cycles can pile up.
10852
+ const existing = _cssBlockRegistry.get(sourceKey);
10853
+ if (existing === cssString) {
10854
+ // Identical content – nothing to do.
10855
+ performanceMonitor.end(marker);
10856
+ return;
10857
+ }
10858
+ _cssBlockRegistry.set(sourceKey, cssString);
10859
+ rebuildStyleTag();
10860
+ if (_cssBlockRegistry.size % 10 === 0) {
10861
+ logger.debug(`CSS registry stats: ${_cssBlockRegistry.size} blocks registered`);
10862
+ }
10863
+ performanceMonitor.end(marker);
10864
+ return;
10865
+ }
10866
+
10867
+ // Fallback path (e.g. direct autoInjectCss calls without a sourceKey):
10868
+ // keep the original hash-based dedup + append behaviour.
10814
10869
  const cssHash = getCssHash(cssString);
10815
10870
  if (injectedCssHashSet.has(cssHash)) {
10816
10871
  performanceMonitor.end(marker);
@@ -10876,6 +10931,7 @@ const performanceUtils = {
10876
10931
  },
10877
10932
  injectionStats: {
10878
10933
  uniqueStylesheets: injectedCssHashSet.size,
10934
+ cssBlocks: _cssBlockRegistry.size,
10879
10935
  keyframes: _injectedKeyframes.size
10880
10936
  }
10881
10937
  };
@@ -10890,6 +10946,14 @@ const performanceUtils = {
10890
10946
  // Clear new input-level caches
10891
10947
  _twsxInputCache.clear();
10892
10948
  _twsxVariantsResultCache.clear();
10949
+
10950
+ // Clear CSS block registry and rebuild (empty) the style tag
10951
+ _cssBlockRegistry.clear();
10952
+ injectedCssHashSet.clear();
10953
+ if (IS_BROWSER) {
10954
+ const styleTag = document.getElementById("twsx-auto-style");
10955
+ if (styleTag) styleTag.textContent = "";
10956
+ }
10893
10957
  logger.info("All caches cleared");
10894
10958
  performanceMonitor.end(marker);
10895
10959
  },