@mgcrea/react-native-tailwind 0.11.1 → 0.12.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.
@@ -1194,14 +1194,14 @@ var SPACING_SCALE = {
1194
1194
  96: 384
1195
1195
  };
1196
1196
  function parseArbitrarySpacing(value) {
1197
- const pxMatch = value.match(/^\[(\d+)(?:px)?\]$/);
1197
+ const pxMatch = value.match(/^\[(-?\d+(?:\.\d+)?)(?:px)?\]$/);
1198
1198
  if (pxMatch) {
1199
- return parseInt(pxMatch[1], 10);
1199
+ return parseFloat(pxMatch[1]);
1200
1200
  }
1201
1201
  if (value.startsWith("[") && value.endsWith("]")) {
1202
1202
  if (process.env.NODE_ENV !== "production") {
1203
1203
  console.warn(
1204
- `[react-native-tailwind] Unsupported arbitrary spacing value: ${value}. Only px values are supported (e.g., [16px] or [16]).`
1204
+ `[react-native-tailwind] Unsupported arbitrary spacing value: ${value}. Only px values are supported (e.g., [16px], [16], [4.5px], [4.5]).`
1205
1205
  );
1206
1206
  }
1207
1207
  return null;
@@ -2725,7 +2725,7 @@ function addOrMergePlaceholderTextColorProp(jsxOpeningElement, color, t) {
2725
2725
  }
2726
2726
 
2727
2727
  // src/babel/utils/twProcessing.ts
2728
- function processTwCall(className, path2, state, parseClassName2, generateStyleKey2, splitModifierClasses2, t) {
2728
+ function processTwCall(className, path2, state, parseClassName2, generateStyleKey2, splitModifierClasses2, findComponentScope2, t) {
2729
2729
  const { baseClasses, modifierClasses: rawModifierClasses } = splitModifierClasses2(className);
2730
2730
  const modifierClasses = [];
2731
2731
  for (const modifier of rawModifierClasses) {
@@ -2756,8 +2756,145 @@ function processTwCall(className, path2, state, parseClassName2, generateStyleKe
2756
2756
  } else {
2757
2757
  objectProperties.push(t.objectProperty(t.identifier("style"), t.objectExpression([])));
2758
2758
  }
2759
+ const colorSchemeModifiers = modifierClasses.filter((m) => isColorSchemeModifier(m.modifier));
2760
+ const platformModifiers = modifierClasses.filter((m) => isPlatformModifier(m.modifier));
2761
+ const otherModifiers = modifierClasses.filter(
2762
+ (m) => !isColorSchemeModifier(m.modifier) && !isPlatformModifier(m.modifier)
2763
+ );
2764
+ const hasColorSchemeModifiers = colorSchemeModifiers.length > 0;
2765
+ let componentScope = null;
2766
+ if (hasColorSchemeModifiers) {
2767
+ componentScope = findComponentScope2(path2, t);
2768
+ if (!componentScope) {
2769
+ if (process.env.NODE_ENV !== "production") {
2770
+ console.warn(
2771
+ `[react-native-tailwind] Color scheme modifiers (dark:, light:) in tw/twStyle calls must be used inside a React component. Modifiers will be ignored.`
2772
+ );
2773
+ }
2774
+ } else {
2775
+ state.functionComponentsNeedingColorScheme.add(componentScope);
2776
+ }
2777
+ }
2778
+ if (hasColorSchemeModifiers && componentScope) {
2779
+ const colorSchemeConditionals = processColorSchemeModifiers(
2780
+ colorSchemeModifiers,
2781
+ state,
2782
+ parseClassName2,
2783
+ generateStyleKey2,
2784
+ t
2785
+ );
2786
+ const styleArrayElements = [];
2787
+ if (baseClasses.length > 0) {
2788
+ const baseClassName = baseClasses.join(" ");
2789
+ const baseStyleObject = parseClassName2(baseClassName, state.customTheme);
2790
+ const baseStyleKey = generateStyleKey2(baseClassName);
2791
+ state.styleRegistry.set(baseStyleKey, baseStyleObject);
2792
+ styleArrayElements.push(
2793
+ t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(baseStyleKey))
2794
+ );
2795
+ }
2796
+ styleArrayElements.push(...colorSchemeConditionals);
2797
+ objectProperties[0] = t.objectProperty(t.identifier("style"), t.arrayExpression(styleArrayElements));
2798
+ const darkModifiers = colorSchemeModifiers.filter((m) => m.modifier === "dark");
2799
+ const lightModifiers = colorSchemeModifiers.filter((m) => m.modifier === "light");
2800
+ if (darkModifiers.length > 0) {
2801
+ const darkClassNames = darkModifiers.map((m) => m.baseClass).join(" ");
2802
+ const darkStyleObject = parseClassName2(darkClassNames, state.customTheme);
2803
+ const darkStyleKey = generateStyleKey2(`dark_${darkClassNames}`);
2804
+ state.styleRegistry.set(darkStyleKey, darkStyleObject);
2805
+ objectProperties.push(
2806
+ t.objectProperty(
2807
+ t.identifier("darkStyle"),
2808
+ t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(darkStyleKey))
2809
+ )
2810
+ );
2811
+ }
2812
+ if (lightModifiers.length > 0) {
2813
+ const lightClassNames = lightModifiers.map((m) => m.baseClass).join(" ");
2814
+ const lightStyleObject = parseClassName2(lightClassNames, state.customTheme);
2815
+ const lightStyleKey = generateStyleKey2(`light_${lightClassNames}`);
2816
+ state.styleRegistry.set(lightStyleKey, lightStyleObject);
2817
+ objectProperties.push(
2818
+ t.objectProperty(
2819
+ t.identifier("lightStyle"),
2820
+ t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(lightStyleKey))
2821
+ )
2822
+ );
2823
+ }
2824
+ }
2825
+ const hasPlatformModifiers = platformModifiers.length > 0;
2826
+ if (hasPlatformModifiers) {
2827
+ state.needsPlatformImport = true;
2828
+ const platformSelectExpression = processPlatformModifiers(
2829
+ platformModifiers,
2830
+ state,
2831
+ parseClassName2,
2832
+ generateStyleKey2,
2833
+ t
2834
+ );
2835
+ if (hasColorSchemeModifiers && componentScope) {
2836
+ const styleProperty = objectProperties.find(
2837
+ (prop) => t.isIdentifier(prop.key) && prop.key.name === "style"
2838
+ );
2839
+ if (styleProperty && t.isArrayExpression(styleProperty.value)) {
2840
+ styleProperty.value.elements.push(platformSelectExpression);
2841
+ }
2842
+ } else {
2843
+ const styleArrayElements = [];
2844
+ if (baseClasses.length > 0) {
2845
+ const baseClassName = baseClasses.join(" ");
2846
+ const baseStyleObject = parseClassName2(baseClassName, state.customTheme);
2847
+ const baseStyleKey = generateStyleKey2(baseClassName);
2848
+ state.styleRegistry.set(baseStyleKey, baseStyleObject);
2849
+ styleArrayElements.push(
2850
+ t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(baseStyleKey))
2851
+ );
2852
+ }
2853
+ styleArrayElements.push(platformSelectExpression);
2854
+ objectProperties[0] = t.objectProperty(t.identifier("style"), t.arrayExpression(styleArrayElements));
2855
+ }
2856
+ const iosModifiers = platformModifiers.filter((m) => m.modifier === "ios");
2857
+ const androidModifiers = platformModifiers.filter((m) => m.modifier === "android");
2858
+ const webModifiers = platformModifiers.filter((m) => m.modifier === "web");
2859
+ if (iosModifiers.length > 0) {
2860
+ const iosClassNames = iosModifiers.map((m) => m.baseClass).join(" ");
2861
+ const iosStyleObject = parseClassName2(iosClassNames, state.customTheme);
2862
+ const iosStyleKey = generateStyleKey2(`ios_${iosClassNames}`);
2863
+ state.styleRegistry.set(iosStyleKey, iosStyleObject);
2864
+ objectProperties.push(
2865
+ t.objectProperty(
2866
+ t.identifier("iosStyle"),
2867
+ t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(iosStyleKey))
2868
+ )
2869
+ );
2870
+ }
2871
+ if (androidModifiers.length > 0) {
2872
+ const androidClassNames = androidModifiers.map((m) => m.baseClass).join(" ");
2873
+ const androidStyleObject = parseClassName2(androidClassNames, state.customTheme);
2874
+ const androidStyleKey = generateStyleKey2(`android_${androidClassNames}`);
2875
+ state.styleRegistry.set(androidStyleKey, androidStyleObject);
2876
+ objectProperties.push(
2877
+ t.objectProperty(
2878
+ t.identifier("androidStyle"),
2879
+ t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(androidStyleKey))
2880
+ )
2881
+ );
2882
+ }
2883
+ if (webModifiers.length > 0) {
2884
+ const webClassNames = webModifiers.map((m) => m.baseClass).join(" ");
2885
+ const webStyleObject = parseClassName2(webClassNames, state.customTheme);
2886
+ const webStyleKey = generateStyleKey2(`web_${webClassNames}`);
2887
+ state.styleRegistry.set(webStyleKey, webStyleObject);
2888
+ objectProperties.push(
2889
+ t.objectProperty(
2890
+ t.identifier("webStyle"),
2891
+ t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(webStyleKey))
2892
+ )
2893
+ );
2894
+ }
2895
+ }
2759
2896
  const modifiersByType = /* @__PURE__ */ new Map();
2760
- for (const mod of modifierClasses) {
2897
+ for (const mod of otherModifiers) {
2761
2898
  if (!modifiersByType.has(mod.modifier)) {
2762
2899
  modifiersByType.set(mod.modifier, []);
2763
2900
  }
@@ -2876,6 +3013,10 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
2876
3013
  state.twImportNames = /* @__PURE__ */ new Set();
2877
3014
  state.hasTwImport = false;
2878
3015
  state.functionComponentsNeedingColorScheme = /* @__PURE__ */ new Set();
3016
+ state.hasColorSchemeImport = false;
3017
+ state.colorSchemeLocalIdentifier = void 0;
3018
+ state.needsPlatformImport = false;
3019
+ state.hasPlatformImport = false;
2879
3020
  state.customTheme = extractCustomTheme(state.file.opts.filename ?? "");
2880
3021
  state.schemeModifierConfig = schemeModifierConfig;
2881
3022
  },
@@ -2934,7 +3075,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
2934
3075
  }
2935
3076
  state.reactNativeImportPath = path2;
2936
3077
  }
2937
- if (node.source.value === state.colorSchemeImportSource) {
3078
+ if (node.source.value === state.colorSchemeImportSource && node.importKind !== "type") {
2938
3079
  const specifiers = node.specifiers;
2939
3080
  for (const spec of specifiers) {
2940
3081
  if (t.isImportSpecifier(spec) && t.isIdentifier(spec.imported)) {
@@ -2990,7 +3131,16 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
2990
3131
  return;
2991
3132
  }
2992
3133
  state.hasClassNames = true;
2993
- processTwCall(className, path2, state, parseClassName, generateStyleKey, splitModifierClasses, t);
3134
+ processTwCall(
3135
+ className,
3136
+ path2,
3137
+ state,
3138
+ parseClassName,
3139
+ generateStyleKey,
3140
+ splitModifierClasses,
3141
+ findComponentScope,
3142
+ t
3143
+ );
2994
3144
  },
2995
3145
  // Handle twStyle('...') call expressions
2996
3146
  CallExpression(path2, state) {
@@ -3025,7 +3175,16 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
3025
3175
  return;
3026
3176
  }
3027
3177
  state.hasClassNames = true;
3028
- processTwCall(className, path2, state, parseClassName, generateStyleKey, splitModifierClasses, t);
3178
+ processTwCall(
3179
+ className,
3180
+ path2,
3181
+ state,
3182
+ parseClassName,
3183
+ generateStyleKey,
3184
+ splitModifierClasses,
3185
+ findComponentScope,
3186
+ t
3187
+ );
3029
3188
  },
3030
3189
  JSXAttribute(path2, state) {
3031
3190
  const node = path2.node;
@@ -3038,14 +3197,14 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
3038
3197
  }
3039
3198
  const value = node.value;
3040
3199
  const targetStyleProp = getTargetStyleProp(attributeName);
3041
- if (t.isStringLiteral(value)) {
3042
- const className = value.value.trim();
3043
- if (!className) {
3200
+ const processStaticClassName = (className) => {
3201
+ const trimmedClassName = className.trim();
3202
+ if (!trimmedClassName) {
3044
3203
  path2.remove();
3045
- return;
3204
+ return true;
3046
3205
  }
3047
3206
  state.hasClassNames = true;
3048
- const { baseClasses, modifierClasses: rawModifierClasses } = splitModifierClasses(className);
3207
+ const { baseClasses, modifierClasses: rawModifierClasses } = splitModifierClasses(trimmedClassName);
3049
3208
  const modifierClasses = [];
3050
3209
  for (const modifier of rawModifierClasses) {
3051
3210
  if (isSchemeModifier(modifier.modifier)) {
@@ -3169,7 +3328,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
3169
3328
  } else {
3170
3329
  replaceWithStyleFunctionAttribute(path2, styleFunctionExpression, targetStyleProp, t);
3171
3330
  }
3172
- return;
3331
+ return true;
3173
3332
  } else {
3174
3333
  }
3175
3334
  }
@@ -3220,7 +3379,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
3220
3379
  path2.node.name = t.jsxIdentifier(targetStyleProp);
3221
3380
  path2.node.value = t.jsxExpressionContainer(styleExpression);
3222
3381
  }
3223
- return;
3382
+ return true;
3224
3383
  }
3225
3384
  if (hasStateModifiers) {
3226
3385
  const jsxOpeningElement = path2.parent;
@@ -3258,11 +3417,11 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
3258
3417
  } else {
3259
3418
  replaceWithStyleFunctionAttribute(path2, styleFunctionExpression, targetStyleProp, t);
3260
3419
  }
3261
- return;
3420
+ return true;
3262
3421
  }
3263
3422
  } else {
3264
3423
  const styleExpression = processStaticClassNameWithModifiers(
3265
- className,
3424
+ trimmedClassName,
3266
3425
  state,
3267
3426
  parseClassName,
3268
3427
  generateStyleKey,
@@ -3277,7 +3436,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
3277
3436
  } else {
3278
3437
  replaceWithStyleFunctionAttribute(path2, styleFunctionExpression, targetStyleProp, t);
3279
3438
  }
3280
- return;
3439
+ return true;
3281
3440
  }
3282
3441
  } else {
3283
3442
  if (process.env.NODE_ENV !== "production") {
@@ -3291,7 +3450,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
3291
3450
  const classNameForStyle = baseClasses.join(" ");
3292
3451
  if (!classNameForStyle) {
3293
3452
  path2.remove();
3294
- return;
3453
+ return true;
3295
3454
  }
3296
3455
  const styleObject = parseClassName(classNameForStyle, state.customTheme);
3297
3456
  const styleKey = generateStyleKey(classNameForStyle);
@@ -3302,13 +3461,23 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
3302
3461
  } else {
3303
3462
  replaceWithStyleAttribute(path2, styleKey, targetStyleProp, state.stylesIdentifier, t);
3304
3463
  }
3305
- return;
3464
+ return true;
3465
+ };
3466
+ if (t.isStringLiteral(value)) {
3467
+ if (processStaticClassName(value.value)) {
3468
+ return;
3469
+ }
3306
3470
  }
3307
3471
  if (t.isJSXExpressionContainer(value)) {
3308
3472
  const expression = value.expression;
3309
3473
  if (t.isJSXEmptyExpression(expression)) {
3310
3474
  return;
3311
3475
  }
3476
+ if (t.isStringLiteral(expression)) {
3477
+ if (processStaticClassName(expression.value)) {
3478
+ return;
3479
+ }
3480
+ }
3312
3481
  try {
3313
3482
  const componentScope = findComponentScope(path2, t);
3314
3483
  const result = processDynamicExpression(