tailwind-to-style 2.12.0 → 2.12.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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * tailwind-to-style v2.12.0
2
+ * tailwind-to-style v2.12.1
3
3
  * Convert tailwind classes to inline style
4
4
  *
5
5
  * @author Bigetion
@@ -7992,10 +7992,10 @@ function parseCustomClassWithPatterns(className) {
7992
7992
  return null;
7993
7993
  }
7994
7994
 
7995
- /**
7996
- * Resolve all CSS custom properties (var) in a CSS string and output only clear CSS (no custom property)
7997
- * @param {string} cssString
7998
- * @returns {string} e.g. 'color: rgba(255,255,255,1); background: #fff;'
7995
+ /**
7996
+ * Resolve all CSS custom properties (var) in a CSS string and output only clear CSS (no custom property)
7997
+ * @param {string} cssString
7998
+ * @returns {string} e.g. 'color: rgba(255,255,255,1); background: #fff;'
7999
7999
  */
8000
8000
  function resolveCssToClearCss(cssString) {
8001
8001
  const customVars = {};
@@ -8362,11 +8362,11 @@ function separateAndResolveCSS(arr) {
8362
8362
  }
8363
8363
  }
8364
8364
 
8365
- /**
8366
- * Process opacity modifier from class name (e.g., text-red-500/50 -> 50% opacity)
8367
- * @param {string} className - Class name with potential opacity modifier
8368
- * @param {string} cssDeclaration - CSS declaration to modify
8369
- * @returns {string} Modified CSS declaration with opacity applied
8365
+ /**
8366
+ * Process opacity modifier from class name (e.g., text-red-500/50 -> 50% opacity)
8367
+ * @param {string} className - Class name with potential opacity modifier
8368
+ * @param {string} cssDeclaration - CSS declaration to modify
8369
+ * @returns {string} Modified CSS declaration with opacity applied
8370
8370
  */
8371
8371
  function processOpacityModifier(className, cssDeclaration) {
8372
8372
  const opacityMatch = className.match(/\/(\d+)$/);
@@ -8427,11 +8427,11 @@ function processOpacityModifier(className, cssDeclaration) {
8427
8427
  return modifiedDeclaration;
8428
8428
  }
8429
8429
 
8430
- /**
8431
- * Convert Tailwind class string to inline CSS styles or JSON object
8432
- * @param {string} classNames - String containing Tailwind classes to convert
8433
- * @param {boolean} convertToJson - If true, result will be JSON object, if false becomes CSS string
8434
- * @returns {string|Object} Inline CSS string or style JSON object
8430
+ /**
8431
+ * Convert Tailwind class string to inline CSS styles or JSON object
8432
+ * @param {string} classNames - String containing Tailwind classes to convert
8433
+ * @param {boolean} convertToJson - If true, result will be JSON object, if false becomes CSS string
8434
+ * @returns {string|Object} Inline CSS string or style JSON object
8435
8435
  */
8436
8436
  function tws(classNames, convertToJson) {
8437
8437
  const totalMarker = performanceMonitor.start("tws:total");
@@ -8875,12 +8875,12 @@ function generateCssString(styles) {
8875
8875
  return cssString.trim();
8876
8876
  }
8877
8877
 
8878
- /**
8879
- * Generate CSS string from style object with SCSS-like syntax
8880
- * Supports nested selectors, state variants, responsive variants, and @css directives
8881
- * @param {Object} obj - Object with SCSS-like style format
8882
- * @param {Object} [options] - Additional options, e.g. { inject: true/false }
8883
- * @returns {string} Generated CSS string
8878
+ /**
8879
+ * Generate CSS string from style object with SCSS-like syntax
8880
+ * Supports nested selectors, state variants, responsive variants, and @css directives
8881
+ * @param {Object} obj - Object with SCSS-like style format
8882
+ * @param {Object} [options] - Additional options, e.g. { inject: true/false }
8883
+ * @returns {string} Generated CSS string
8884
8884
  */
8885
8885
  function twsx(obj) {
8886
8886
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
@@ -9072,7 +9072,9 @@ function autoInjectCss(cssString) {
9072
9072
 
9073
9073
  // Global CSS cache to prevent duplicate injections
9074
9074
  const globalCssCache = new Map();
9075
+ const globalKeyframesCache = new Map(); // Track injected keyframes: name -> css
9075
9076
  let globalStyleElement = null;
9077
+ let globalKeyframesElement = null;
9076
9078
 
9077
9079
  /**
9078
9080
  * Simple hash function for CSS content
@@ -9089,6 +9091,7 @@ function simpleHash$1(str) {
9089
9091
  return Math.abs(hash).toString(36);
9090
9092
  }
9091
9093
  function getOrCreateGlobalStyleElement() {
9094
+ if (typeof document === "undefined") return null;
9092
9095
  if (!globalStyleElement) {
9093
9096
  globalStyleElement = document.createElement("style");
9094
9097
  globalStyleElement.setAttribute("data-twsx-global", "true");
@@ -9096,6 +9099,103 @@ function getOrCreateGlobalStyleElement() {
9096
9099
  }
9097
9100
  return globalStyleElement;
9098
9101
  }
9102
+ function getOrCreateGlobalKeyframesElement() {
9103
+ if (typeof document === "undefined") return null;
9104
+ if (!globalKeyframesElement) {
9105
+ globalKeyframesElement = document.createElement("style");
9106
+ globalKeyframesElement.setAttribute("data-twsx-keyframes", "true");
9107
+ document.head.appendChild(globalKeyframesElement);
9108
+ }
9109
+ return globalKeyframesElement;
9110
+ }
9111
+ function extractKeyframes(cssString) {
9112
+ const keyframesRegex = /@keyframes\s+([^\s{]+)\s*\{/g;
9113
+ const keyframes = [];
9114
+ let match;
9115
+ while ((match = keyframesRegex.exec(cssString)) !== null) {
9116
+ const keyframeName = match[1];
9117
+ const start = match.index;
9118
+
9119
+ // Find matching closing brace
9120
+ let braceCount = 0;
9121
+ let endIndex = start;
9122
+ let inKeyframe = false;
9123
+ for (let i = start; i < cssString.length; i++) {
9124
+ if (cssString[i] === "{") {
9125
+ braceCount++;
9126
+ inKeyframe = true;
9127
+ } else if (cssString[i] === "}") {
9128
+ braceCount--;
9129
+ if (inKeyframe && braceCount === 0) {
9130
+ endIndex = i + 1;
9131
+ break;
9132
+ }
9133
+ }
9134
+ }
9135
+ const keyframeBlock = cssString.substring(start, endIndex);
9136
+ keyframes.push({
9137
+ name: keyframeName,
9138
+ css: keyframeBlock
9139
+ });
9140
+ }
9141
+ return keyframes;
9142
+ }
9143
+ function removeKeyframes(cssString) {
9144
+ // Remove keyframes but keep the rest
9145
+ let result = cssString;
9146
+ const keyframesRegex = /@keyframes\s+([^\s{]+)\s*\{/g;
9147
+ let match;
9148
+ const toRemove = [];
9149
+ while ((match = keyframesRegex.exec(cssString)) !== null) {
9150
+ const start = match.index;
9151
+ let braceCount = 0;
9152
+ let inKeyframe = false;
9153
+ for (let i = start; i < cssString.length; i++) {
9154
+ if (cssString[i] === "{") {
9155
+ braceCount++;
9156
+ inKeyframe = true;
9157
+ } else if (cssString[i] === "}") {
9158
+ braceCount--;
9159
+ if (inKeyframe && braceCount === 0) {
9160
+ toRemove.push({
9161
+ start,
9162
+ end: i + 1
9163
+ });
9164
+ break;
9165
+ }
9166
+ }
9167
+ }
9168
+ }
9169
+
9170
+ // Remove from end to start to preserve indices
9171
+ for (let i = toRemove.length - 1; i >= 0; i--) {
9172
+ const {
9173
+ start,
9174
+ end
9175
+ } = toRemove[i];
9176
+ result = result.substring(0, start) + result.substring(end);
9177
+ }
9178
+ return result.trim();
9179
+ }
9180
+ function updateGlobalKeyframes(keyframes) {
9181
+ if (typeof document === "undefined") return;
9182
+ const keyframesElement = getOrCreateGlobalKeyframesElement();
9183
+ let hasNewKeyframes = false;
9184
+ for (const {
9185
+ name,
9186
+ css
9187
+ } of keyframes) {
9188
+ if (!globalKeyframesCache.has(name)) {
9189
+ globalKeyframesCache.set(name, css);
9190
+ hasNewKeyframes = true;
9191
+ }
9192
+ }
9193
+ if (hasNewKeyframes) {
9194
+ // Rebuild all keyframes CSS from cache
9195
+ const allKeyframesCSS = Array.from(globalKeyframesCache.values()).join("\n");
9196
+ keyframesElement.textContent = allKeyframesCSS;
9197
+ }
9198
+ }
9099
9199
  function updateGlobalCSS() {
9100
9200
  if (typeof document === "undefined") return;
9101
9201
  const styleElement = getOrCreateGlobalStyleElement();
@@ -9143,9 +9243,18 @@ function useTwsx(styles) {
9143
9243
  useEffect(() => {
9144
9244
  if (!css || !cssKey || options.inject === false) return;
9145
9245
 
9146
- // Only add to cache if not already present
9246
+ // Extract keyframes from CSS
9247
+ const keyframes = extractKeyframes(css);
9248
+ const cssWithoutKeyframes = removeKeyframes(css);
9249
+
9250
+ // Inject keyframes separately (once per keyframe name)
9251
+ if (keyframes.length > 0) {
9252
+ updateGlobalKeyframes(keyframes);
9253
+ }
9254
+
9255
+ // Only add component CSS to cache if not already present
9147
9256
  if (!globalCssCache.has(cssKey)) {
9148
- globalCssCache.set(cssKey, css);
9257
+ globalCssCache.set(cssKey, cssWithoutKeyframes);
9149
9258
  updateGlobalCSS();
9150
9259
  console.log("useTwsx - Injected NEW CSS with key:", cssKey);
9151
9260
  } else {
@@ -9263,31 +9372,31 @@ function useUpdateTwsxConfig() {
9263
9372
  return updateConfig;
9264
9373
  }
9265
9374
 
9266
- /**
9267
- * styled() - Component factory for tailwind-to-style
9268
- * Create styled components with Tailwind classes and variants
9269
- *
9270
- * @example
9271
- * const Button = styled('button', {
9272
- * base: 'px-4 py-2 rounded-lg',
9273
- * hover: 'bg-blue-600',
9274
- * variants: {
9275
- * color: {
9276
- * primary: 'bg-blue-500 text-white',
9277
- * secondary: 'bg-gray-500 text-white'
9278
- * }
9279
- * },
9280
- * nested: {
9281
- * '.icon': 'w-4 h-4'
9282
- * }
9283
- * })
9375
+ /**
9376
+ * styled() - Component factory for tailwind-to-style
9377
+ * Create styled components with Tailwind classes and variants
9378
+ *
9379
+ * @example
9380
+ * const Button = styled('button', {
9381
+ * base: 'px-4 py-2 rounded-lg',
9382
+ * hover: 'bg-blue-600',
9383
+ * variants: {
9384
+ * color: {
9385
+ * primary: 'bg-blue-500 text-white',
9386
+ * secondary: 'bg-gray-500 text-white'
9387
+ * }
9388
+ * },
9389
+ * nested: {
9390
+ * '.icon': 'w-4 h-4'
9391
+ * }
9392
+ * })
9284
9393
  */
9285
9394
 
9286
9395
 
9287
- /**
9288
- * Simple hash function for deterministic class names
9289
- * @param {string} str - String to hash
9290
- * @returns {string} Hash string
9396
+ /**
9397
+ * Simple hash function for deterministic class names
9398
+ * @param {string} str - String to hash
9399
+ * @returns {string} Hash string
9291
9400
  */
9292
9401
  function simpleHash(str) {
9293
9402
  let hash = 0;
@@ -9299,12 +9408,12 @@ function simpleHash(str) {
9299
9408
  return Math.abs(hash).toString(36).substr(0, 6);
9300
9409
  }
9301
9410
 
9302
- /**
9303
- * Generate deterministic class name based on config and component instance
9304
- * @param {Object|Function} config - Style configuration
9305
- * @param {string} componentType - Component type (e.g., 'button', 'div')
9306
- * @param {string} instanceId - Unique instance identifier (optional)
9307
- * @returns {string} Deterministic class name
9411
+ /**
9412
+ * Generate deterministic class name based on config and component instance
9413
+ * @param {Object|Function} config - Style configuration
9414
+ * @param {string} componentType - Component type (e.g., 'button', 'div')
9415
+ * @param {string} instanceId - Unique instance identifier (optional)
9416
+ * @returns {string} Deterministic class name
9308
9417
  */
9309
9418
  function generateClassName(config) {
9310
9419
  let componentType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "component";
@@ -9321,14 +9430,14 @@ function generateClassName(config) {
9321
9430
  return `twsx-${componentType}-${hash}${suffix}`;
9322
9431
  }
9323
9432
 
9324
- /**
9325
- * Create a styled component with Tailwind classes
9326
- * @param {string|React.Component} component - HTML tag or React component
9327
- * @param {Object} config - Style configuration
9328
- * @param {Object} options - Additional options
9329
- * @param {string} options.scope - Component scope for isolation (optional)
9330
- * @param {boolean} options.isolate - Whether to isolate from other components (default: false)
9331
- * @returns {React.Component} Styled component
9433
+ /**
9434
+ * Create a styled component with Tailwind classes
9435
+ * @param {string|React.Component} component - HTML tag or React component
9436
+ * @param {Object} config - Style configuration
9437
+ * @param {Object} options - Additional options
9438
+ * @param {string} options.scope - Component scope for isolation (optional)
9439
+ * @param {boolean} options.isolate - Whether to isolate from other components (default: false)
9440
+ * @returns {React.Component} Styled component
9332
9441
  */
9333
9442
  function styled(component) {
9334
9443
  let config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
@@ -9618,21 +9727,21 @@ function styled(component) {
9618
9727
  return StyledComponent;
9619
9728
  }
9620
9729
 
9621
- /**
9622
- * Create a styled component factory for a specific tag
9623
- * @param {string} tag - HTML tag name
9624
- * @returns {Function} Styled component factory
9730
+ /**
9731
+ * Create a styled component factory for a specific tag
9732
+ * @param {string} tag - HTML tag name
9733
+ * @returns {Function} Styled component factory
9625
9734
  */
9626
9735
  function createStyledTag(tag) {
9627
9736
  return (config, options) => styled(tag, config, options);
9628
9737
  }
9629
9738
 
9630
- /**
9631
- * Create an isolated styled component (automatically scoped)
9632
- * @param {string|React.Component} component - HTML tag or React component
9633
- * @param {Object} config - Style configuration
9634
- * @param {string} scope - Optional scope name
9635
- * @returns {React.Component} Isolated styled component
9739
+ /**
9740
+ * Create an isolated styled component (automatically scoped)
9741
+ * @param {string|React.Component} component - HTML tag or React component
9742
+ * @param {Object} config - Style configuration
9743
+ * @param {string} scope - Optional scope name
9744
+ * @returns {React.Component} Isolated styled component
9636
9745
  */
9637
9746
  function isolatedStyled(component) {
9638
9747
  let config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
@@ -9643,10 +9752,10 @@ function isolatedStyled(component) {
9643
9752
  });
9644
9753
  }
9645
9754
 
9646
- /**
9647
- * Create a scoped styled component
9648
- * @param {string} scope - Scope name for component isolation
9649
- * @returns {Function} Scoped styled function
9755
+ /**
9756
+ * Create a scoped styled component
9757
+ * @param {string} scope - Scope name for component isolation
9758
+ * @returns {Function} Scoped styled function
9650
9759
  */
9651
9760
  function createScopedStyled(scope) {
9652
9761
  return function (component) {