@mgcrea/react-native-tailwind 0.10.0 → 0.11.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.
Files changed (45) hide show
  1. package/README.md +159 -13
  2. package/dist/babel/config-loader.d.ts +12 -3
  3. package/dist/babel/config-loader.test.ts +14 -12
  4. package/dist/babel/config-loader.ts +41 -9
  5. package/dist/babel/index.cjs +91 -54
  6. package/dist/babel/plugin.d.ts +39 -1
  7. package/dist/babel/plugin.test.ts +275 -1
  8. package/dist/babel/plugin.ts +84 -25
  9. package/dist/babel/utils/colorSchemeModifierProcessing.d.ts +3 -3
  10. package/dist/babel/utils/colorSchemeModifierProcessing.ts +4 -4
  11. package/dist/babel/utils/dynamicProcessing.d.ts +5 -5
  12. package/dist/babel/utils/dynamicProcessing.ts +11 -11
  13. package/dist/babel/utils/modifierProcessing.d.ts +3 -3
  14. package/dist/babel/utils/modifierProcessing.ts +5 -5
  15. package/dist/babel/utils/platformModifierProcessing.d.ts +3 -3
  16. package/dist/babel/utils/platformModifierProcessing.ts +4 -4
  17. package/dist/babel/utils/styleInjection.d.ts +5 -3
  18. package/dist/babel/utils/styleInjection.ts +38 -23
  19. package/dist/babel/utils/twProcessing.d.ts +3 -3
  20. package/dist/babel/utils/twProcessing.ts +6 -6
  21. package/dist/parser/index.d.ts +11 -4
  22. package/dist/parser/index.js +1 -1
  23. package/dist/parser/typography.d.ts +3 -1
  24. package/dist/parser/typography.js +1 -1
  25. package/dist/runtime.cjs +1 -1
  26. package/dist/runtime.cjs.map +3 -3
  27. package/dist/runtime.d.ts +8 -1
  28. package/dist/runtime.js +1 -1
  29. package/dist/runtime.js.map +3 -3
  30. package/dist/runtime.test.js +1 -1
  31. package/package.json +1 -1
  32. package/src/babel/config-loader.test.ts +14 -12
  33. package/src/babel/config-loader.ts +41 -9
  34. package/src/babel/plugin.test.ts +275 -1
  35. package/src/babel/plugin.ts +84 -25
  36. package/src/babel/utils/colorSchemeModifierProcessing.ts +4 -4
  37. package/src/babel/utils/dynamicProcessing.ts +11 -11
  38. package/src/babel/utils/modifierProcessing.ts +5 -5
  39. package/src/babel/utils/platformModifierProcessing.ts +4 -4
  40. package/src/babel/utils/styleInjection.ts +38 -23
  41. package/src/babel/utils/twProcessing.ts +6 -6
  42. package/src/parser/index.ts +16 -8
  43. package/src/parser/typography.ts +14 -2
  44. package/src/runtime.test.ts +7 -7
  45. package/src/runtime.ts +37 -14
@@ -1678,7 +1678,13 @@ function parseArbitraryLineHeight(value) {
1678
1678
  }
1679
1679
  return null;
1680
1680
  }
1681
- function parseTypography(cls) {
1681
+ function parseTypography(cls, customFontFamily) {
1682
+ const fontFamilyMap = customFontFamily ? {
1683
+ ...FONT_FAMILY_MAP,
1684
+ ...Object.fromEntries(
1685
+ Object.entries(customFontFamily).map(([key, value]) => [`font-${key}`, { fontFamily: value }])
1686
+ )
1687
+ } : FONT_FAMILY_MAP;
1682
1688
  if (cls.startsWith("text-")) {
1683
1689
  const sizeKey = cls.substring(5);
1684
1690
  const arbitraryValue = parseArbitraryFontSize(sizeKey);
@@ -1701,7 +1707,7 @@ function parseTypography(cls) {
1701
1707
  return { lineHeight };
1702
1708
  }
1703
1709
  }
1704
- return FONT_FAMILY_MAP[cls] ?? FONT_WEIGHT_MAP[cls] ?? FONT_STYLE_MAP[cls] ?? TEXT_ALIGN_MAP[cls] ?? TEXT_DECORATION_MAP[cls] ?? TEXT_TRANSFORM_MAP[cls] ?? LINE_HEIGHT_MAP[cls] ?? TRACKING_MAP[cls] ?? null;
1710
+ return fontFamilyMap[cls] ?? FONT_WEIGHT_MAP[cls] ?? FONT_STYLE_MAP[cls] ?? TEXT_ALIGN_MAP[cls] ?? TEXT_DECORATION_MAP[cls] ?? TEXT_TRANSFORM_MAP[cls] ?? LINE_HEIGHT_MAP[cls] ?? TRACKING_MAP[cls] ?? null;
1705
1711
  }
1706
1712
 
1707
1713
  // src/parser/placeholder.ts
@@ -1842,22 +1848,22 @@ function splitModifierClasses(className) {
1842
1848
  }
1843
1849
 
1844
1850
  // src/parser/index.ts
1845
- function parseClassName(className, customColors) {
1851
+ function parseClassName(className, customTheme) {
1846
1852
  const classes = className.split(/\s+/).filter(Boolean);
1847
1853
  const style = {};
1848
1854
  for (const cls of classes) {
1849
- const parsedStyle = parseClass(cls, customColors);
1855
+ const parsedStyle = parseClass(cls, customTheme);
1850
1856
  Object.assign(style, parsedStyle);
1851
1857
  }
1852
1858
  return style;
1853
1859
  }
1854
- function parseClass(cls, customColors) {
1860
+ function parseClass(cls, customTheme) {
1855
1861
  const parsers = [
1856
1862
  parseSpacing,
1857
1863
  parseBorder,
1858
- (cls2) => parseColor(cls2, customColors),
1864
+ (cls2) => parseColor(cls2, customTheme?.colors),
1859
1865
  parseLayout,
1860
- parseTypography,
1866
+ (cls2) => parseTypography(cls2, customTheme?.fontFamily),
1861
1867
  parseSizing,
1862
1868
  parseShadow,
1863
1869
  parseAspectRatio,
@@ -1925,15 +1931,15 @@ function loadTailwindConfig(configPath) {
1925
1931
  return null;
1926
1932
  }
1927
1933
  }
1928
- function extractCustomColors(filename) {
1934
+ function extractCustomTheme(filename) {
1929
1935
  const projectDir = path.dirname(filename);
1930
1936
  const configPath = findTailwindConfig(projectDir);
1931
1937
  if (!configPath) {
1932
- return {};
1938
+ return { colors: {}, fontFamily: {} };
1933
1939
  }
1934
1940
  const config = loadTailwindConfig(configPath);
1935
1941
  if (!config?.theme) {
1936
- return {};
1942
+ return { colors: {}, fontFamily: {} };
1937
1943
  }
1938
1944
  if (config.theme.colors && !config.theme.extend?.colors && process.env.NODE_ENV !== "production") {
1939
1945
  console.warn(
@@ -1941,7 +1947,24 @@ function extractCustomColors(filename) {
1941
1947
  );
1942
1948
  }
1943
1949
  const colors = config.theme.extend?.colors ?? config.theme.colors ?? {};
1944
- return flattenColors(colors);
1950
+ if (config.theme.fontFamily && !config.theme.extend?.fontFamily && process.env.NODE_ENV !== "production") {
1951
+ console.warn(
1952
+ "[react-native-tailwind] Using theme.fontFamily will override all default font families. Use theme.extend.fontFamily to add custom fonts while keeping defaults."
1953
+ );
1954
+ }
1955
+ const fontFamily = config.theme.extend?.fontFamily ?? config.theme.fontFamily ?? {};
1956
+ const fontFamilyResult = {};
1957
+ for (const [key, value] of Object.entries(fontFamily)) {
1958
+ if (Array.isArray(value)) {
1959
+ fontFamilyResult[key] = value[0];
1960
+ } else {
1961
+ fontFamilyResult[key] = value;
1962
+ }
1963
+ }
1964
+ return {
1965
+ colors: flattenColors(colors),
1966
+ fontFamily: fontFamilyResult
1967
+ };
1945
1968
  }
1946
1969
 
1947
1970
  // src/babel/utils/attributeMatchers.ts
@@ -1997,7 +2020,7 @@ function processColorSchemeModifiers(colorSchemeModifiers, state, parseClassName
1997
2020
  const conditionalExpressions = [];
1998
2021
  for (const [scheme, modifiers] of modifiersByScheme) {
1999
2022
  const classNames = modifiers.map((m) => m.baseClass).join(" ");
2000
- const styleObject = parseClassName2(classNames, state.customColors);
2023
+ const styleObject = parseClassName2(classNames, state.customTheme);
2001
2024
  const styleKey = generateStyleKey2(`${scheme}_${classNames}`);
2002
2025
  state.styleRegistry.set(styleKey, styleObject);
2003
2026
  const colorSchemeCheck = t.binaryExpression(
@@ -2252,7 +2275,7 @@ function processStringOrExpressionHelper(node, state, parseClassName2, generateS
2252
2275
  if (isSchemeModifier2(modifier.modifier)) {
2253
2276
  const expanded = expandSchemeModifier2(
2254
2277
  modifier,
2255
- state.customColors,
2278
+ state.customTheme.colors ?? {},
2256
2279
  state.schemeModifierConfig.darkSuffix ?? "-dark",
2257
2280
  state.schemeModifierConfig.lightSuffix ?? "-light"
2258
2281
  );
@@ -2266,7 +2289,7 @@ function processStringOrExpressionHelper(node, state, parseClassName2, generateS
2266
2289
  const styleElements = [];
2267
2290
  if (baseClasses.length > 0) {
2268
2291
  const baseClassName = baseClasses.join(" ");
2269
- const styleObject = parseClassName2(baseClassName, state.customColors);
2292
+ const styleObject = parseClassName2(baseClassName, state.customTheme);
2270
2293
  const styleKey = generateStyleKey2(baseClassName);
2271
2294
  state.styleRegistry.set(styleKey, styleObject);
2272
2295
  styleElements.push(t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(styleKey)));
@@ -2373,7 +2396,7 @@ function processStaticClassNameWithModifiers(className, state, parseClassName2,
2373
2396
  let baseStyleExpression = null;
2374
2397
  if (baseClasses.length > 0) {
2375
2398
  const baseClassName = baseClasses.join(" ");
2376
- const baseStyleObject = parseClassName2(baseClassName, state.customColors);
2399
+ const baseStyleObject = parseClassName2(baseClassName, state.customTheme);
2377
2400
  const baseStyleKey = generateStyleKey2(baseClassName);
2378
2401
  state.styleRegistry.set(baseStyleKey, baseStyleObject);
2379
2402
  baseStyleExpression = t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(baseStyleKey));
@@ -2394,7 +2417,7 @@ function processStaticClassNameWithModifiers(className, state, parseClassName2,
2394
2417
  }
2395
2418
  for (const [modifierType, modifiers] of modifiersByType) {
2396
2419
  const modifierClassNames = modifiers.map((m) => m.baseClass).join(" ");
2397
- const modifierStyleObject = parseClassName2(modifierClassNames, state.customColors);
2420
+ const modifierStyleObject = parseClassName2(modifierClassNames, state.customTheme);
2398
2421
  const modifierStyleKey = generateStyleKey2(`${modifierType}_${modifierClassNames}`);
2399
2422
  state.styleRegistry.set(modifierStyleKey, modifierStyleObject);
2400
2423
  const stateProperty = getStatePropertyForModifier(modifierType);
@@ -2443,7 +2466,7 @@ function processPlatformModifiers(platformModifiers, state, parseClassName2, gen
2443
2466
  const selectProperties = [];
2444
2467
  for (const [platform, modifiers] of modifiersByPlatform) {
2445
2468
  const classNames = modifiers.map((m) => m.baseClass).join(" ");
2446
- const styleObject = parseClassName2(classNames, state.customColors);
2469
+ const styleObject = parseClassName2(classNames, state.customTheme);
2447
2470
  const styleKey = generateStyleKey2(`${platform}_${classNames}`);
2448
2471
  state.styleRegistry.set(styleKey, styleObject);
2449
2472
  const styleReference = t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(styleKey));
@@ -2495,33 +2518,33 @@ function addPlatformImport(path2, t) {
2495
2518
  path2.unshiftContainer("body", importDeclaration);
2496
2519
  }
2497
2520
  }
2498
- function addColorSchemeImport(path2, t) {
2521
+ function addColorSchemeImport(path2, importSource, hookName, t) {
2499
2522
  const body = path2.node.body;
2500
- let reactNativeImport = null;
2523
+ let existingValueImport = null;
2501
2524
  for (const statement of body) {
2502
- if (t.isImportDeclaration(statement) && statement.source.value === "react-native") {
2503
- reactNativeImport = statement;
2504
- break;
2525
+ if (t.isImportDeclaration(statement) && statement.source.value === importSource) {
2526
+ if (statement.importKind !== "type") {
2527
+ existingValueImport = statement;
2528
+ break;
2529
+ }
2505
2530
  }
2506
2531
  }
2507
- if (reactNativeImport) {
2508
- const hasUseColorScheme = reactNativeImport.specifiers.some(
2509
- (spec) => t.isImportSpecifier(spec) && spec.imported.type === "Identifier" && spec.imported.name === "useColorScheme"
2532
+ if (existingValueImport) {
2533
+ const hasHook = existingValueImport.specifiers.some(
2534
+ (spec) => t.isImportSpecifier(spec) && spec.imported.type === "Identifier" && spec.imported.name === hookName
2510
2535
  );
2511
- if (!hasUseColorScheme) {
2512
- reactNativeImport.specifiers.push(
2513
- t.importSpecifier(t.identifier("useColorScheme"), t.identifier("useColorScheme"))
2514
- );
2536
+ if (!hasHook) {
2537
+ existingValueImport.specifiers.push(t.importSpecifier(t.identifier(hookName), t.identifier(hookName)));
2515
2538
  }
2516
2539
  } else {
2517
2540
  const importDeclaration = t.importDeclaration(
2518
- [t.importSpecifier(t.identifier("useColorScheme"), t.identifier("useColorScheme"))],
2519
- t.stringLiteral("react-native")
2541
+ [t.importSpecifier(t.identifier(hookName), t.identifier(hookName))],
2542
+ t.stringLiteral(importSource)
2520
2543
  );
2521
2544
  path2.unshiftContainer("body", importDeclaration);
2522
2545
  }
2523
2546
  }
2524
- function injectColorSchemeHook(functionPath, colorSchemeVariableName, t) {
2547
+ function injectColorSchemeHook(functionPath, colorSchemeVariableName, hookName, localIdentifier, t) {
2525
2548
  let body = functionPath.node.body;
2526
2549
  if (!t.isBlockStatement(body)) {
2527
2550
  if (t.isArrowFunctionExpression(functionPath.node) && t.isExpression(body)) {
@@ -2543,10 +2566,11 @@ function injectColorSchemeHook(functionPath, colorSchemeVariableName, t) {
2543
2566
  if (hasHook) {
2544
2567
  return false;
2545
2568
  }
2569
+ const identifierToCall = localIdentifier ?? hookName;
2546
2570
  const hookCall = t.variableDeclaration("const", [
2547
2571
  t.variableDeclarator(
2548
2572
  t.identifier(colorSchemeVariableName),
2549
- t.callExpression(t.identifier("useColorScheme"), [])
2573
+ t.callExpression(t.identifier(identifierToCall), [])
2550
2574
  )
2551
2575
  ]);
2552
2576
  body.body.unshift(hookCall);
@@ -2708,7 +2732,7 @@ function processTwCall(className, path2, state, parseClassName2, generateStyleKe
2708
2732
  if (isSchemeModifier(modifier.modifier)) {
2709
2733
  const expanded = expandSchemeModifier(
2710
2734
  modifier,
2711
- state.customColors,
2735
+ state.customTheme.colors ?? {},
2712
2736
  state.schemeModifierConfig.darkSuffix ?? "-dark",
2713
2737
  state.schemeModifierConfig.lightSuffix ?? "-light"
2714
2738
  );
@@ -2720,7 +2744,7 @@ function processTwCall(className, path2, state, parseClassName2, generateStyleKe
2720
2744
  const objectProperties = [];
2721
2745
  if (baseClasses.length > 0) {
2722
2746
  const baseClassName = baseClasses.join(" ");
2723
- const baseStyleObject = parseClassName2(baseClassName, state.customColors);
2747
+ const baseStyleObject = parseClassName2(baseClassName, state.customTheme);
2724
2748
  const baseStyleKey = generateStyleKey2(baseClassName);
2725
2749
  state.styleRegistry.set(baseStyleKey, baseStyleObject);
2726
2750
  objectProperties.push(
@@ -2744,7 +2768,7 @@ function processTwCall(className, path2, state, parseClassName2, generateStyleKe
2744
2768
  }
2745
2769
  for (const [modifierType, modifiers] of modifiersByType) {
2746
2770
  const modifierClassNames = modifiers.map((m) => m.baseClass).join(" ");
2747
- const modifierStyleObject = parseClassName2(modifierClassNames, state.customColors);
2771
+ const modifierStyleObject = parseClassName2(modifierClassNames, state.customTheme);
2748
2772
  const modifierStyleKey = generateStyleKey2(`${modifierType}_${modifierClassNames}`);
2749
2773
  state.styleRegistry.set(modifierStyleKey, modifierStyleObject);
2750
2774
  const propertyName = `${modifierType}Style`;
@@ -2829,6 +2853,8 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
2829
2853
  darkSuffix: options?.schemeModifier?.darkSuffix ?? "-dark",
2830
2854
  lightSuffix: options?.schemeModifier?.lightSuffix ?? "-light"
2831
2855
  };
2856
+ const colorSchemeImportSource = options?.colorScheme?.importFrom ?? "react-native";
2857
+ const colorSchemeHookName = options?.colorScheme?.importName ?? "useColorScheme";
2832
2858
  return {
2833
2859
  name: "react-native-tailwind",
2834
2860
  visitor: {
@@ -2842,13 +2868,15 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
2842
2868
  state.hasColorSchemeImport = false;
2843
2869
  state.needsColorSchemeImport = false;
2844
2870
  state.colorSchemeVariableName = "_twColorScheme";
2871
+ state.colorSchemeImportSource = colorSchemeImportSource;
2872
+ state.colorSchemeHookName = colorSchemeHookName;
2845
2873
  state.supportedAttributes = exactMatches;
2846
2874
  state.attributePatterns = patterns;
2847
2875
  state.stylesIdentifier = stylesIdentifier;
2848
2876
  state.twImportNames = /* @__PURE__ */ new Set();
2849
2877
  state.hasTwImport = false;
2850
2878
  state.functionComponentsNeedingColorScheme = /* @__PURE__ */ new Set();
2851
- state.customColors = extractCustomColors(state.file.opts.filename ?? "");
2879
+ state.customTheme = extractCustomTheme(state.file.opts.filename ?? "");
2852
2880
  state.schemeModifierConfig = schemeModifierConfig;
2853
2881
  },
2854
2882
  exit(path2, state) {
@@ -2865,11 +2893,17 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
2865
2893
  addPlatformImport(path2, t);
2866
2894
  }
2867
2895
  if (state.needsColorSchemeImport && !state.hasColorSchemeImport) {
2868
- addColorSchemeImport(path2, t);
2896
+ addColorSchemeImport(path2, state.colorSchemeImportSource, state.colorSchemeHookName, t);
2869
2897
  }
2870
2898
  if (state.needsColorSchemeImport) {
2871
2899
  for (const functionPath of state.functionComponentsNeedingColorScheme) {
2872
- injectColorSchemeHook(functionPath, state.colorSchemeVariableName, t);
2900
+ injectColorSchemeHook(
2901
+ functionPath,
2902
+ state.colorSchemeVariableName,
2903
+ state.colorSchemeHookName,
2904
+ state.colorSchemeLocalIdentifier,
2905
+ t
2906
+ );
2873
2907
  }
2874
2908
  }
2875
2909
  injectStylesAtTop(path2, state.styleRegistry, state.stylesIdentifier, t);
@@ -2892,23 +2926,26 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
2892
2926
  }
2893
2927
  return false;
2894
2928
  });
2895
- const hasUseColorScheme = specifiers.some((spec) => {
2896
- if (t.isImportSpecifier(spec) && t.isIdentifier(spec.imported)) {
2897
- return spec.imported.name === "useColorScheme";
2898
- }
2899
- return false;
2900
- });
2901
2929
  if (hasStyleSheet) {
2902
2930
  state.hasStyleSheetImport = true;
2903
2931
  }
2904
2932
  if (hasPlatform) {
2905
2933
  state.hasPlatformImport = true;
2906
2934
  }
2907
- if (hasUseColorScheme) {
2908
- state.hasColorSchemeImport = true;
2909
- }
2910
2935
  state.reactNativeImportPath = path2;
2911
2936
  }
2937
+ if (node.source.value === state.colorSchemeImportSource) {
2938
+ const specifiers = node.specifiers;
2939
+ for (const spec of specifiers) {
2940
+ if (t.isImportSpecifier(spec) && t.isIdentifier(spec.imported)) {
2941
+ if (spec.imported.name === state.colorSchemeHookName) {
2942
+ state.hasColorSchemeImport = true;
2943
+ state.colorSchemeLocalIdentifier = spec.local.name;
2944
+ break;
2945
+ }
2946
+ }
2947
+ }
2948
+ }
2912
2949
  if (node.source.value === "@mgcrea/react-native-tailwind") {
2913
2950
  const specifiers = node.specifiers;
2914
2951
  specifiers.forEach((spec) => {
@@ -3014,7 +3051,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
3014
3051
  if (isSchemeModifier(modifier.modifier)) {
3015
3052
  const expanded = expandSchemeModifier(
3016
3053
  modifier,
3017
- state.customColors,
3054
+ state.customTheme.colors ?? {},
3018
3055
  state.schemeModifierConfig.darkSuffix,
3019
3056
  state.schemeModifierConfig.lightSuffix
3020
3057
  );
@@ -3034,7 +3071,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
3034
3071
  const componentSupport = getComponentModifierSupport(jsxOpeningElement, t);
3035
3072
  if (componentSupport?.supportedModifiers.includes("placeholder")) {
3036
3073
  const placeholderClasses = placeholderModifiers.map((m) => m.baseClass).join(" ");
3037
- const placeholderColor = parsePlaceholderClasses(placeholderClasses, state.customColors);
3074
+ const placeholderColor = parsePlaceholderClasses(placeholderClasses, state.customTheme.colors);
3038
3075
  if (placeholderColor) {
3039
3076
  addOrMergePlaceholderTextColorProp(jsxOpeningElement, placeholderColor, t);
3040
3077
  }
@@ -3070,7 +3107,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
3070
3107
  const styleArrayElements = [];
3071
3108
  if (hasBaseClasses) {
3072
3109
  const baseClassName = baseClasses.join(" ");
3073
- const baseStyleObject = parseClassName(baseClassName, state.customColors);
3110
+ const baseStyleObject = parseClassName(baseClassName, state.customTheme);
3074
3111
  const baseStyleKey = generateStyleKey(baseClassName);
3075
3112
  state.styleRegistry.set(baseStyleKey, baseStyleObject);
3076
3113
  styleArrayElements.push(
@@ -3110,7 +3147,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
3110
3147
  continue;
3111
3148
  }
3112
3149
  const modifierClassNames = modifiers.map((m) => m.baseClass).join(" ");
3113
- const modifierStyleObject = parseClassName(modifierClassNames, state.customColors);
3150
+ const modifierStyleObject = parseClassName(modifierClassNames, state.customTheme);
3114
3151
  const modifierStyleKey = generateStyleKey(`${modifierType}_${modifierClassNames}`);
3115
3152
  state.styleRegistry.set(modifierStyleKey, modifierStyleObject);
3116
3153
  const stateProperty = getStatePropertyForModifier(modifierType);
@@ -3140,7 +3177,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
3140
3177
  const styleExpressions = [];
3141
3178
  if (hasBaseClasses) {
3142
3179
  const baseClassName = baseClasses.join(" ");
3143
- const baseStyleObject = parseClassName(baseClassName, state.customColors);
3180
+ const baseStyleObject = parseClassName(baseClassName, state.customTheme);
3144
3181
  const baseStyleKey = generateStyleKey(baseClassName);
3145
3182
  state.styleRegistry.set(baseStyleKey, baseStyleObject);
3146
3183
  styleExpressions.push(
@@ -3256,7 +3293,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
3256
3293
  path2.remove();
3257
3294
  return;
3258
3295
  }
3259
- const styleObject = parseClassName(classNameForStyle, state.customColors);
3296
+ const styleObject = parseClassName(classNameForStyle, state.customTheme);
3260
3297
  const styleKey = generateStyleKey(classNameForStyle);
3261
3298
  state.styleRegistry.set(styleKey, styleObject);
3262
3299
  const styleAttribute = findStyleAttribute(path2, targetStyleProp, t);
@@ -5,6 +5,7 @@
5
5
  import type { NodePath, PluginObj, PluginPass } from "@babel/core";
6
6
  import * as BabelTypes from "@babel/types";
7
7
  import type { StyleObject } from "../types/core.js";
8
+ import type { CustomTheme } from "./config-loader.js";
8
9
  import type { SchemeModifierConfig } from "../types/config.js";
9
10
  /**
10
11
  * Plugin options
@@ -40,6 +41,40 @@ export type PluginOptions = {
40
41
  darkSuffix?: string;
41
42
  lightSuffix?: string;
42
43
  };
44
+ /**
45
+ * Configuration for color scheme hook import (dark:/light: modifiers)
46
+ *
47
+ * Allows using custom color scheme hooks from theme providers instead of
48
+ * React Native's built-in useColorScheme.
49
+ *
50
+ * @example
51
+ * // Use custom hook from theme provider
52
+ * {
53
+ * importFrom: '@/hooks/useColorScheme',
54
+ * importName: 'useColorScheme'
55
+ * }
56
+ *
57
+ * @example
58
+ * // Use React Navigation theme
59
+ * {
60
+ * importFrom: '@react-navigation/native',
61
+ * importName: 'useTheme' // You'd wrap this to return ColorSchemeName
62
+ * }
63
+ *
64
+ * @default { importFrom: 'react-native', importName: 'useColorScheme' }
65
+ */
66
+ colorScheme?: {
67
+ /**
68
+ * Module to import the color scheme hook from
69
+ * @default 'react-native'
70
+ */
71
+ importFrom?: string;
72
+ /**
73
+ * Name of the hook to import
74
+ * @default 'useColorScheme'
75
+ */
76
+ importName?: string;
77
+ };
43
78
  };
44
79
  type PluginState = PluginPass & {
45
80
  styleRegistry: Map<string, StyleObject>;
@@ -50,7 +85,10 @@ type PluginState = PluginPass & {
50
85
  hasColorSchemeImport: boolean;
51
86
  needsColorSchemeImport: boolean;
52
87
  colorSchemeVariableName: string;
53
- customColors: Record<string, string>;
88
+ colorSchemeImportSource: string;
89
+ colorSchemeHookName: string;
90
+ colorSchemeLocalIdentifier?: string;
91
+ customTheme: CustomTheme;
54
92
  schemeModifierConfig: SchemeModifierConfig;
55
93
  supportedAttributes: Set<string>;
56
94
  attributePatterns: RegExp[];