@mgcrea/react-native-tailwind 0.4.0 → 0.5.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.
Files changed (71) hide show
  1. package/README.md +443 -13
  2. package/dist/babel/index.cjs +804 -274
  3. package/dist/babel/index.d.ts +2 -1
  4. package/dist/babel/index.ts +319 -16
  5. package/dist/components/Pressable.d.ts +32 -0
  6. package/dist/components/Pressable.js +1 -0
  7. package/dist/components/TextInput.d.ts +56 -0
  8. package/dist/components/TextInput.js +1 -0
  9. package/dist/index.d.ts +9 -2
  10. package/dist/index.js +1 -1
  11. package/dist/parser/aspectRatio.d.ts +16 -0
  12. package/dist/parser/aspectRatio.js +1 -0
  13. package/dist/parser/aspectRatio.test.d.ts +1 -0
  14. package/dist/parser/aspectRatio.test.js +1 -0
  15. package/dist/parser/borders.js +1 -1
  16. package/dist/parser/borders.test.d.ts +1 -0
  17. package/dist/parser/borders.test.js +1 -0
  18. package/dist/parser/colors.d.ts +1 -0
  19. package/dist/parser/colors.js +1 -1
  20. package/dist/parser/colors.test.d.ts +1 -0
  21. package/dist/parser/colors.test.js +1 -0
  22. package/dist/parser/index.d.ts +4 -0
  23. package/dist/parser/index.js +1 -1
  24. package/dist/parser/layout.d.ts +2 -0
  25. package/dist/parser/layout.js +1 -1
  26. package/dist/parser/layout.test.d.ts +1 -0
  27. package/dist/parser/layout.test.js +1 -0
  28. package/dist/parser/modifiers.d.ts +47 -0
  29. package/dist/parser/modifiers.js +1 -0
  30. package/dist/parser/modifiers.test.d.ts +1 -0
  31. package/dist/parser/modifiers.test.js +1 -0
  32. package/dist/parser/shadows.d.ts +26 -0
  33. package/dist/parser/shadows.js +1 -0
  34. package/dist/parser/shadows.test.d.ts +1 -0
  35. package/dist/parser/shadows.test.js +1 -0
  36. package/dist/parser/sizing.test.d.ts +1 -0
  37. package/dist/parser/sizing.test.js +1 -0
  38. package/dist/parser/spacing.d.ts +1 -1
  39. package/dist/parser/spacing.js +1 -1
  40. package/dist/parser/spacing.test.d.ts +1 -0
  41. package/dist/parser/spacing.test.js +1 -0
  42. package/dist/parser/typography.d.ts +2 -1
  43. package/dist/parser/typography.js +1 -1
  44. package/dist/parser/typography.test.d.ts +1 -0
  45. package/dist/parser/typography.test.js +1 -0
  46. package/dist/types.d.ts +5 -2
  47. package/package.json +7 -6
  48. package/src/babel/index.ts +319 -16
  49. package/src/components/Pressable.tsx +46 -0
  50. package/src/components/TextInput.tsx +90 -0
  51. package/src/index.ts +20 -2
  52. package/src/parser/aspectRatio.test.ts +191 -0
  53. package/src/parser/aspectRatio.ts +73 -0
  54. package/src/parser/borders.test.ts +329 -0
  55. package/src/parser/borders.ts +187 -108
  56. package/src/parser/colors.test.ts +335 -0
  57. package/src/parser/colors.ts +117 -6
  58. package/src/parser/index.ts +13 -2
  59. package/src/parser/layout.test.ts +459 -0
  60. package/src/parser/layout.ts +128 -0
  61. package/src/parser/modifiers.test.ts +375 -0
  62. package/src/parser/modifiers.ts +104 -0
  63. package/src/parser/shadows.test.ts +201 -0
  64. package/src/parser/shadows.ts +133 -0
  65. package/src/parser/sizing.test.ts +256 -0
  66. package/src/parser/spacing.test.ts +226 -0
  67. package/src/parser/spacing.ts +93 -138
  68. package/src/parser/typography.test.ts +221 -0
  69. package/src/parser/typography.ts +143 -112
  70. package/src/types.ts +2 -2
  71. package/dist/react-native.d.js +0 -1
@@ -4,8 +4,9 @@
4
4
  */
5
5
  import type { PluginObj, PluginPass } from "@babel/core";
6
6
  import * as BabelTypes from "@babel/types";
7
+ import { StyleObject } from "src/types.js";
7
8
  type PluginState = PluginPass & {
8
- styleRegistry: Map<string, Record<string, string | number>>;
9
+ styleRegistry: Map<string, StyleObject>;
9
10
  hasClassNames: boolean;
10
11
  hasStyleSheetImport: boolean;
11
12
  customColors: Record<string, string>;
@@ -11,12 +11,14 @@
11
11
 
12
12
  import type { NodePath, PluginObj, PluginPass } from "@babel/core";
13
13
  import * as BabelTypes from "@babel/types";
14
- import { parseClassName as parseClassNameFn } from "../parser/index.js";
14
+ import { StyleObject } from "src/types.js";
15
+ import type { ModifierType, ParsedModifier } from "../parser/index.js";
16
+ import { parseClassName as parseClassNameFn, splitModifierClasses } from "../parser/index.js";
15
17
  import { generateStyleKey as generateStyleKeyFn } from "../utils/styleKey.js";
16
18
  import { extractCustomColors } from "./config-loader.js";
17
19
 
18
20
  type PluginState = PluginPass & {
19
- styleRegistry: Map<string, Record<string, string | number>>;
21
+ styleRegistry: Map<string, StyleObject>;
20
22
  hasClassNames: boolean;
21
23
  hasStyleSheetImport: boolean;
22
24
  customColors: Record<string, string>;
@@ -30,6 +32,7 @@ const STYLES_IDENTIFIER = "_twStyles";
30
32
  */
31
33
  const SUPPORTED_CLASS_ATTRIBUTES = [
32
34
  "className",
35
+ "containerClassName",
33
36
  "contentContainerClassName",
34
37
  "columnWrapperClassName",
35
38
  "ListHeaderComponentClassName",
@@ -40,6 +43,9 @@ const SUPPORTED_CLASS_ATTRIBUTES = [
40
43
  * Get the target style prop name based on the className attribute
41
44
  */
42
45
  function getTargetStyleProp(attributeName: string): string {
46
+ if (attributeName === "containerClassName") {
47
+ return "containerStyle";
48
+ }
43
49
  if (attributeName === "contentContainerClassName") {
44
50
  return "contentContainerStyle";
45
51
  }
@@ -55,6 +61,49 @@ function getTargetStyleProp(attributeName: string): string {
55
61
  return "style";
56
62
  }
57
63
 
64
+ /**
65
+ * Check if a JSX element supports modifiers and determine which modifiers are supported
66
+ * Returns an object with component info and supported modifiers
67
+ */
68
+ function getComponentModifierSupport(
69
+ jsxElement: any,
70
+ t: typeof BabelTypes,
71
+ ): { component: string; supportedModifiers: ModifierType[] } | null {
72
+ if (!t.isJSXOpeningElement(jsxElement)) {
73
+ return null;
74
+ }
75
+
76
+ const name = jsxElement.name;
77
+ let componentName: string | null = null;
78
+
79
+ // Handle simple identifier: <Pressable>
80
+ if (t.isJSXIdentifier(name)) {
81
+ componentName = name.name;
82
+ }
83
+
84
+ // Handle member expression: <ReactNative.Pressable>
85
+ if (t.isJSXMemberExpression(name)) {
86
+ const property = name.property;
87
+ if (t.isJSXIdentifier(property)) {
88
+ componentName = property.name;
89
+ }
90
+ }
91
+
92
+ if (!componentName) {
93
+ return null;
94
+ }
95
+
96
+ // Map components to their supported modifiers
97
+ switch (componentName) {
98
+ case "Pressable":
99
+ return { component: "Pressable", supportedModifiers: ["active", "hover", "focus", "disabled"] };
100
+ case "TextInput":
101
+ return { component: "TextInput", supportedModifiers: ["focus", "disabled"] };
102
+ default:
103
+ return null;
104
+ }
105
+ }
106
+
58
107
  /**
59
108
  * Result of processing a dynamic expression
60
109
  */
@@ -242,6 +291,118 @@ function processStringOrExpression(node: any, state: PluginState, t: typeof Babe
242
291
  return null;
243
292
  }
244
293
 
294
+ /**
295
+ * Process a static className string that contains modifiers
296
+ * Returns a style function expression for Pressable components
297
+ */
298
+ function processStaticClassNameWithModifiers(
299
+ className: string,
300
+ state: PluginState,
301
+ t: typeof BabelTypes,
302
+ ): any {
303
+ const { baseClasses, modifierClasses } = splitModifierClasses(className);
304
+
305
+ // Parse and register base classes
306
+ let baseStyleExpression: any = null;
307
+ if (baseClasses.length > 0) {
308
+ const baseClassName = baseClasses.join(" ");
309
+ const baseStyleObject = parseClassName(baseClassName, state.customColors);
310
+ const baseStyleKey = generateStyleKey(baseClassName);
311
+ state.styleRegistry.set(baseStyleKey, baseStyleObject);
312
+ baseStyleExpression = t.memberExpression(t.identifier(STYLES_IDENTIFIER), t.identifier(baseStyleKey));
313
+ }
314
+
315
+ // Parse and register modifier classes
316
+ // Group by modifier type for better organization
317
+ const modifiersByType = new Map<ModifierType, ParsedModifier[]>();
318
+ for (const mod of modifierClasses) {
319
+ if (!modifiersByType.has(mod.modifier)) {
320
+ modifiersByType.set(mod.modifier, []);
321
+ }
322
+ const modGroup = modifiersByType.get(mod.modifier);
323
+ if (modGroup) {
324
+ modGroup.push(mod);
325
+ }
326
+ }
327
+
328
+ // Build style function: ({ pressed }) => [baseStyle, pressed && modifierStyle]
329
+ const styleArrayElements: any[] = [];
330
+
331
+ // Add base style first
332
+ if (baseStyleExpression) {
333
+ styleArrayElements.push(baseStyleExpression);
334
+ }
335
+
336
+ // Add conditional styles for each modifier type
337
+ for (const [modifierType, modifiers] of modifiersByType) {
338
+ // Parse all modifier classes together
339
+ const modifierClassNames = modifiers.map((m) => m.baseClass).join(" ");
340
+ const modifierStyleObject = parseClassName(modifierClassNames, state.customColors);
341
+ const modifierStyleKey = generateStyleKey(`${modifierType}_${modifierClassNames}`);
342
+ state.styleRegistry.set(modifierStyleKey, modifierStyleObject);
343
+
344
+ // Create conditional: pressed && styles._active_bg_blue_700
345
+ const stateProperty = getStatePropertyForModifier(modifierType);
346
+ const conditionalExpression = t.logicalExpression(
347
+ "&&",
348
+ t.identifier(stateProperty),
349
+ t.memberExpression(t.identifier(STYLES_IDENTIFIER), t.identifier(modifierStyleKey)),
350
+ );
351
+
352
+ styleArrayElements.push(conditionalExpression);
353
+ }
354
+
355
+ // If only base style, return it directly; otherwise return array
356
+ if (styleArrayElements.length === 1) {
357
+ return styleArrayElements[0];
358
+ }
359
+
360
+ return t.arrayExpression(styleArrayElements);
361
+ }
362
+
363
+ /**
364
+ * Get the state property name for a modifier type
365
+ * Maps modifier types to component state parameter properties
366
+ */
367
+ function getStatePropertyForModifier(modifier: ModifierType): string {
368
+ switch (modifier) {
369
+ case "active":
370
+ return "pressed";
371
+ case "hover":
372
+ return "hovered";
373
+ case "focus":
374
+ return "focused";
375
+ case "disabled":
376
+ return "disabled";
377
+ default:
378
+ return "pressed"; // fallback
379
+ }
380
+ }
381
+
382
+ /**
383
+ * Create a style function for Pressable: ({ pressed }) => styleExpression
384
+ */
385
+ function createStyleFunction(styleExpression: any, modifierTypes: ModifierType[], t: typeof BabelTypes): any {
386
+ // Build parameter object: { pressed, hovered, focused }
387
+ const paramProperties: any[] = [];
388
+ const usedStateProps = new Set<string>();
389
+
390
+ for (const modifierType of modifierTypes) {
391
+ const stateProperty = getStatePropertyForModifier(modifierType);
392
+ if (!usedStateProps.has(stateProperty)) {
393
+ usedStateProps.add(stateProperty);
394
+ paramProperties.push(
395
+ t.objectProperty(t.identifier(stateProperty), t.identifier(stateProperty), false, true),
396
+ );
397
+ }
398
+ }
399
+
400
+ const param = t.objectPattern(paramProperties);
401
+
402
+ // Create arrow function: ({ pressed }) => styleExpression
403
+ return t.arrowFunctionExpression([param], styleExpression);
404
+ }
405
+
245
406
  export default function reactNativeTailwindBabelPlugin({
246
407
  types: t,
247
408
  }: {
@@ -314,7 +475,7 @@ export default function reactNativeTailwindBabelPlugin({
314
475
  // Determine target style prop based on attribute name
315
476
  const targetStyleProp = getTargetStyleProp(attributeName);
316
477
 
317
- // Handle static string literals (original behavior)
478
+ // Handle static string literals
318
479
  if (t.isStringLiteral(value)) {
319
480
  const className = value.value.trim();
320
481
 
@@ -326,13 +487,99 @@ export default function reactNativeTailwindBabelPlugin({
326
487
 
327
488
  state.hasClassNames = true;
328
489
 
329
- // Parse className to React Native styles
330
- const styleObject = parseClassName(className, state.customColors);
490
+ // Check if className contains modifiers (active:, hover:, focus:)
491
+ const { baseClasses, modifierClasses } = splitModifierClasses(className);
331
492
 
332
- // Generate unique style key
333
- const styleKey = generateStyleKey(className);
493
+ // If there are modifiers, check if this component supports them
494
+ if (modifierClasses.length > 0) {
495
+ // Get the JSX opening element (the direct parent of the attribute)
496
+ const jsxOpeningElement = path.parent;
497
+ const componentSupport = getComponentModifierSupport(jsxOpeningElement, t);
498
+
499
+ if (componentSupport) {
500
+ // Get modifier types used in className
501
+ const usedModifiers = Array.from(new Set(modifierClasses.map((m) => m.modifier)));
502
+
503
+ // Check if all modifiers are supported by this component
504
+ const unsupportedModifiers = usedModifiers.filter(
505
+ (mod) => !componentSupport.supportedModifiers.includes(mod),
506
+ );
507
+
508
+ if (unsupportedModifiers.length > 0) {
509
+ // Warn about unsupported modifiers
510
+ if (process.env.NODE_ENV !== "production") {
511
+ console.warn(
512
+ `[react-native-tailwind] Modifiers (${unsupportedModifiers.map((m) => `${m}:`).join(", ")}) are not supported on ${componentSupport.component} component at ${state.file.opts.filename ?? "unknown"}. ` +
513
+ `Supported modifiers: ${componentSupport.supportedModifiers.join(", ")}`,
514
+ );
515
+ }
516
+ // Filter out unsupported modifiers
517
+ const supportedModifierClasses = modifierClasses.filter((m) =>
518
+ componentSupport.supportedModifiers.includes(m.modifier),
519
+ );
520
+
521
+ // If no supported modifiers remain, fall through to normal processing
522
+ if (supportedModifierClasses.length === 0) {
523
+ // Continue to normal processing
524
+ } else {
525
+ // Process only supported modifiers
526
+ const filteredClassName =
527
+ baseClasses.join(" ") +
528
+ " " +
529
+ supportedModifierClasses.map((m) => `${m.modifier}:${m.baseClass}`).join(" ");
530
+ const styleExpression = processStaticClassNameWithModifiers(
531
+ filteredClassName.trim(),
532
+ state,
533
+ t,
534
+ );
535
+ const modifierTypes = Array.from(new Set(supportedModifierClasses.map((m) => m.modifier)));
536
+ const styleFunctionExpression = createStyleFunction(styleExpression, modifierTypes, t);
537
+
538
+ const parent = path.parent as any;
539
+ const styleAttribute = parent.attributes.find(
540
+ (attr: any) => t.isJSXAttribute(attr) && attr.name.name === targetStyleProp,
541
+ );
542
+
543
+ if (styleAttribute) {
544
+ mergeStyleFunctionAttribute(path, styleAttribute, styleFunctionExpression, t);
545
+ } else {
546
+ replaceWithStyleFunctionAttribute(path, styleFunctionExpression, targetStyleProp, t);
547
+ }
548
+ return;
549
+ }
550
+ } else {
551
+ // All modifiers are supported - process normally
552
+ const styleExpression = processStaticClassNameWithModifiers(className, state, t);
553
+ const modifierTypes = usedModifiers;
554
+ const styleFunctionExpression = createStyleFunction(styleExpression, modifierTypes, t);
555
+
556
+ const parent = path.parent as any;
557
+ const styleAttribute = parent.attributes.find(
558
+ (attr: any) => t.isJSXAttribute(attr) && attr.name.name === targetStyleProp,
559
+ );
560
+
561
+ if (styleAttribute) {
562
+ mergeStyleFunctionAttribute(path, styleAttribute, styleFunctionExpression, t);
563
+ } else {
564
+ replaceWithStyleFunctionAttribute(path, styleFunctionExpression, targetStyleProp, t);
565
+ }
566
+ return;
567
+ }
568
+ } else {
569
+ // Component doesn't support any modifiers
570
+ if (process.env.NODE_ENV !== "production") {
571
+ const usedModifiers = Array.from(new Set(modifierClasses.map((m) => m.modifier)));
572
+ console.warn(
573
+ `[react-native-tailwind] Modifiers (${usedModifiers.map((m) => `${m}:`).join(", ")}) can only be used on compatible components (Pressable, TextInput). Found on unsupported element at ${state.file.opts.filename ?? "unknown"}`,
574
+ );
575
+ }
576
+ // Fall through to normal processing (ignore modifiers)
577
+ }
578
+ }
334
579
 
335
- // Store in registry
580
+ // Normal processing without modifiers
581
+ const styleObject = parseClassName(className, state.customColors);
582
+ const styleKey = generateStyleKey(className);
336
583
  state.styleRegistry.set(styleKey, styleObject);
337
584
 
338
585
  // Check if there's already a style prop on this element
@@ -505,13 +752,72 @@ function mergeDynamicStyleAttribute(
505
752
  }
506
753
 
507
754
  /**
508
- * Inject StyleSheet.create with all collected styles
755
+ * Replace className with style function attribute (for Pressable with modifiers)
756
+ */
757
+ function replaceWithStyleFunctionAttribute(
758
+ classNamePath: NodePath,
759
+ styleFunctionExpression: any,
760
+ targetStyleProp: string,
761
+ t: typeof BabelTypes,
762
+ ) {
763
+ const styleAttribute = t.jsxAttribute(
764
+ t.jsxIdentifier(targetStyleProp),
765
+ t.jsxExpressionContainer(styleFunctionExpression),
766
+ );
767
+
768
+ classNamePath.replaceWith(styleAttribute);
769
+ }
770
+
771
+ /**
772
+ * Merge className style function with existing style prop (for Pressable with modifiers)
509
773
  */
510
- function injectStyles(
511
- path: NodePath,
512
- styleRegistry: Map<string, Record<string, string | number>>,
774
+ function mergeStyleFunctionAttribute(
775
+ classNamePath: NodePath,
776
+ styleAttribute: any,
777
+ styleFunctionExpression: any,
513
778
  t: typeof BabelTypes,
514
779
  ) {
780
+ const existingStyle = styleAttribute.value.expression;
781
+
782
+ // Create a wrapper function that merges both styles
783
+ // ({ pressed }) => [styleFunctionResult, existingStyle]
784
+ // We need to call the style function and merge results
785
+
786
+ // If existing is already a function, we need to handle it specially
787
+ if (t.isArrowFunctionExpression(existingStyle) || t.isFunctionExpression(existingStyle)) {
788
+ // Both are functions - create wrapper that calls both
789
+ // (_state) => [newStyleFn(_state), existingStyleFn(_state)]
790
+ // Create an identifier for the parameter to pass to the function calls
791
+ const paramIdentifier = t.identifier("_state");
792
+
793
+ const newFunctionCall = t.callExpression(styleFunctionExpression, [paramIdentifier]);
794
+ const existingFunctionCall = t.callExpression(existingStyle, [paramIdentifier]);
795
+
796
+ const mergedArray = t.arrayExpression([newFunctionCall, existingFunctionCall]);
797
+ const wrapperFunction = t.arrowFunctionExpression([paramIdentifier], mergedArray);
798
+
799
+ styleAttribute.value = t.jsxExpressionContainer(wrapperFunction);
800
+ } else {
801
+ // Existing is static - create function that returns array
802
+ // (_state) => [styleFunctionResult, existingStyle]
803
+ // Create an identifier for the parameter to pass to the function call
804
+ const paramIdentifier = t.identifier("_state");
805
+
806
+ const functionCall = t.callExpression(styleFunctionExpression, [paramIdentifier]);
807
+ const mergedArray = t.arrayExpression([functionCall, existingStyle]);
808
+ const wrapperFunction = t.arrowFunctionExpression([paramIdentifier], mergedArray);
809
+
810
+ styleAttribute.value = t.jsxExpressionContainer(wrapperFunction);
811
+ }
812
+
813
+ // Remove the className attribute
814
+ classNamePath.remove();
815
+ }
816
+
817
+ /**
818
+ * Inject StyleSheet.create with all collected styles
819
+ */
820
+ function injectStyles(path: NodePath, styleRegistry: Map<string, StyleObject>, t: typeof BabelTypes) {
515
821
  // Build style object properties
516
822
  const styleProperties: any[] = [];
517
823
 
@@ -549,10 +855,7 @@ function injectStyles(
549
855
  }
550
856
 
551
857
  // Helper functions that use the imported parser
552
- function parseClassName(
553
- className: string,
554
- customColors: Record<string, string>,
555
- ): Record<string, string | number> {
858
+ function parseClassName(className: string, customColors: Record<string, string>): StyleObject {
556
859
  return parseClassNameFn(className, customColors);
557
860
  }
558
861
 
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Enhanced Pressable component with modifier support
3
+ * Injects disabled state into style function for disabled: modifier support
4
+ */
5
+ import { type PressableStateCallbackType, type PressableProps as RNPressableProps, type StyleProp, type ViewStyle } from "react-native";
6
+ type EnhancedPressableState = PressableStateCallbackType & {
7
+ disabled: boolean | null | undefined;
8
+ };
9
+ export type PressableProps = Omit<RNPressableProps, "style"> & {
10
+ /**
11
+ * Style can be a static style object/array or a function that receives Pressable state + disabled
12
+ */
13
+ style?: StyleProp<ViewStyle> | ((state: EnhancedPressableState) => StyleProp<ViewStyle>);
14
+ };
15
+ /**
16
+ * Enhanced Pressable that supports the disabled: modifier
17
+ *
18
+ * @example
19
+ * <Pressable
20
+ * disabled={isLoading}
21
+ * className="bg-blue-500 active:bg-blue-700 disabled:bg-gray-400"
22
+ * >
23
+ * <Text>Submit</Text>
24
+ * </Pressable>
25
+ */
26
+ export declare const Pressable: import("react").ForwardRefExoticComponent<Omit<RNPressableProps, "style"> & {
27
+ /**
28
+ * Style can be a static style object/array or a function that receives Pressable state + disabled
29
+ */
30
+ style?: StyleProp<ViewStyle> | ((state: EnhancedPressableState) => StyleProp<ViewStyle>);
31
+ } & import("react").RefAttributes<import("react-native").View>>;
32
+ export {};
@@ -0,0 +1 @@
1
+ var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.Pressable=void 0;var _objectWithoutProperties2=_interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));var _react=require("react");var _reactNative=require("react-native");var _jsxRuntime=require("react/jsx-runtime");var _jsxFileName="/Users/olivier/Projects/github/react-native-tailwind/src/components/Pressable.tsx";var _excluded=["style","disabled"];var Pressable=exports.Pressable=(0,_react.forwardRef)(function Pressable(_ref,ref){var style=_ref.style,_ref$disabled=_ref.disabled,disabled=_ref$disabled===void 0?false:_ref$disabled,props=(0,_objectWithoutProperties2.default)(_ref,_excluded);var resolvedStyle=typeof style==="function"?function(state){return style(Object.assign({},state,{disabled:disabled}));}:style;return(0,_jsxRuntime.jsx)(_reactNative.Pressable,Object.assign({ref:ref,disabled:disabled,style:resolvedStyle},props));});
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Enhanced TextInput component with focus state support for focus: modifier
3
+ *
4
+ * This component wraps React Native's TextInput and manages focus state internally,
5
+ * allowing the style prop to be a function that receives { focused: boolean }.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * import { TextInput } from '@mgcrea/react-native-tailwind';
10
+ *
11
+ * <TextInput
12
+ * className="border-2 border-gray-300 focus:border-blue-500 p-3 rounded-lg"
13
+ * placeholder="Email"
14
+ * />
15
+ * ```
16
+ */
17
+ import { TextInput as RNTextInput, type TextInputProps as RNTextInputProps } from "react-native";
18
+ export type TextInputProps = Omit<RNTextInputProps, "style"> & {
19
+ /**
20
+ * Style can be a static style object/array or a function that receives focus and disabled state
21
+ */
22
+ style?: RNTextInputProps["style"] | ((state: {
23
+ focused: boolean;
24
+ disabled: boolean;
25
+ }) => RNTextInputProps["style"]);
26
+ /**
27
+ * Convenience prop for disabled state (overrides editable if provided)
28
+ * When true, sets editable to false
29
+ */
30
+ disabled?: boolean;
31
+ };
32
+ /**
33
+ * Enhanced TextInput with focus and disabled state support
34
+ *
35
+ * Manages focus state internally and passes it to style functions,
36
+ * enabling the use of focus: and disabled: modifiers in className.
37
+ *
38
+ * Note: TextInput uses `editable` prop internally. You can pass either:
39
+ * - `disabled={true}` - convenience prop (sets editable to false)
40
+ * - `editable={false}` - React Native's native prop
41
+ * If both are provided, `disabled` takes precedence.
42
+ */
43
+ export declare const TextInput: import("react").ForwardRefExoticComponent<Omit<RNTextInputProps, "style"> & {
44
+ /**
45
+ * Style can be a static style object/array or a function that receives focus and disabled state
46
+ */
47
+ style?: RNTextInputProps["style"] | ((state: {
48
+ focused: boolean;
49
+ disabled: boolean;
50
+ }) => RNTextInputProps["style"]);
51
+ /**
52
+ * Convenience prop for disabled state (overrides editable if provided)
53
+ * When true, sets editable to false
54
+ */
55
+ disabled?: boolean;
56
+ } & import("react").RefAttributes<RNTextInput>>;
@@ -0,0 +1 @@
1
+ var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.TextInput=void 0;var _slicedToArray2=_interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));var _objectWithoutProperties2=_interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));var _react=require("react");var _reactNative=require("react-native");var _jsxRuntime=require("react/jsx-runtime");var _jsxFileName="/Users/olivier/Projects/github/react-native-tailwind/src/components/TextInput.tsx";var _excluded=["style","onFocus","onBlur","disabled","editable"];var TextInput=exports.TextInput=(0,_react.forwardRef)(function TextInput(_ref,ref){var style=_ref.style,onFocus=_ref.onFocus,onBlur=_ref.onBlur,disabled=_ref.disabled,_ref$editable=_ref.editable,editable=_ref$editable===void 0?true:_ref$editable,props=(0,_objectWithoutProperties2.default)(_ref,_excluded);var _useState=(0,_react.useState)(false),_useState2=(0,_slicedToArray2.default)(_useState,2),focused=_useState2[0],setFocused=_useState2[1];var handleFocus=(0,_react.useCallback)(function(e){setFocused(true);onFocus==null||onFocus(e);},[onFocus]);var handleBlur=(0,_react.useCallback)(function(e){setFocused(false);onBlur==null||onBlur(e);},[onBlur]);var isEditable=disabled!==undefined?!disabled:editable;var isDisabled=!isEditable;var resolvedStyle=typeof style==="function"?style({focused:focused,disabled:isDisabled}):style;return(0,_jsxRuntime.jsx)(_reactNative.TextInput,Object.assign({ref:ref,style:resolvedStyle,editable:isEditable,onFocus:handleFocus,onBlur:handleBlur},props));});
package/dist/index.d.ts CHANGED
@@ -5,8 +5,15 @@
5
5
  export { parseClass, parseClassName } from "./parser";
6
6
  export { generateStyleKey } from "./utils/styleKey";
7
7
  export type { RNStyle, StyleObject } from "./types";
8
- export { parseBorder, parseColor, parseLayout, parseSizing, parseSpacing, parseTypography } from "./parser";
8
+ export { parseAspectRatio, parseBorder, parseColor, parseLayout, parseShadow, parseSizing, parseSpacing, parseTypography, } from "./parser";
9
+ export { ASPECT_RATIO_PRESETS } from "./parser/aspectRatio";
9
10
  export { COLORS } from "./parser/colors";
11
+ export { INSET_SCALE, Z_INDEX_SCALE } from "./parser/layout";
12
+ export { SHADOW_SCALE } from "./parser/shadows";
10
13
  export { SIZE_PERCENTAGES, SIZE_SCALE } from "./parser/sizing";
11
14
  export { SPACING_SCALE } from "./parser/spacing";
12
- export { FONT_SIZES } from "./parser/typography";
15
+ export { FONT_SIZES, LETTER_SPACING_SCALE } from "./parser/typography";
16
+ export { Pressable } from "./components/Pressable";
17
+ export type { PressableProps } from "./components/Pressable";
18
+ export { TextInput } from "./components/TextInput";
19
+ export type { TextInputProps } from "./components/TextInput";
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"COLORS",{enumerable:true,get:function get(){return _colors.COLORS;}});Object.defineProperty(exports,"FONT_SIZES",{enumerable:true,get:function get(){return _typography.FONT_SIZES;}});Object.defineProperty(exports,"SIZE_PERCENTAGES",{enumerable:true,get:function get(){return _sizing.SIZE_PERCENTAGES;}});Object.defineProperty(exports,"SIZE_SCALE",{enumerable:true,get:function get(){return _sizing.SIZE_SCALE;}});Object.defineProperty(exports,"SPACING_SCALE",{enumerable:true,get:function get(){return _spacing.SPACING_SCALE;}});Object.defineProperty(exports,"generateStyleKey",{enumerable:true,get:function get(){return _styleKey.generateStyleKey;}});Object.defineProperty(exports,"parseBorder",{enumerable:true,get:function get(){return _parser.parseBorder;}});Object.defineProperty(exports,"parseClass",{enumerable:true,get:function get(){return _parser.parseClass;}});Object.defineProperty(exports,"parseClassName",{enumerable:true,get:function get(){return _parser.parseClassName;}});Object.defineProperty(exports,"parseColor",{enumerable:true,get:function get(){return _parser.parseColor;}});Object.defineProperty(exports,"parseLayout",{enumerable:true,get:function get(){return _parser.parseLayout;}});Object.defineProperty(exports,"parseSizing",{enumerable:true,get:function get(){return _parser.parseSizing;}});Object.defineProperty(exports,"parseSpacing",{enumerable:true,get:function get(){return _parser.parseSpacing;}});Object.defineProperty(exports,"parseTypography",{enumerable:true,get:function get(){return _parser.parseTypography;}});var _parser=require("./parser");var _styleKey=require("./utils/styleKey");var _colors=require("./parser/colors");var _sizing=require("./parser/sizing");var _spacing=require("./parser/spacing");var _typography=require("./parser/typography");
1
+ Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"ASPECT_RATIO_PRESETS",{enumerable:true,get:function get(){return _aspectRatio.ASPECT_RATIO_PRESETS;}});Object.defineProperty(exports,"COLORS",{enumerable:true,get:function get(){return _colors.COLORS;}});Object.defineProperty(exports,"FONT_SIZES",{enumerable:true,get:function get(){return _typography.FONT_SIZES;}});Object.defineProperty(exports,"INSET_SCALE",{enumerable:true,get:function get(){return _layout.INSET_SCALE;}});Object.defineProperty(exports,"LETTER_SPACING_SCALE",{enumerable:true,get:function get(){return _typography.LETTER_SPACING_SCALE;}});Object.defineProperty(exports,"Pressable",{enumerable:true,get:function get(){return _Pressable.Pressable;}});Object.defineProperty(exports,"SHADOW_SCALE",{enumerable:true,get:function get(){return _shadows.SHADOW_SCALE;}});Object.defineProperty(exports,"SIZE_PERCENTAGES",{enumerable:true,get:function get(){return _sizing.SIZE_PERCENTAGES;}});Object.defineProperty(exports,"SIZE_SCALE",{enumerable:true,get:function get(){return _sizing.SIZE_SCALE;}});Object.defineProperty(exports,"SPACING_SCALE",{enumerable:true,get:function get(){return _spacing.SPACING_SCALE;}});Object.defineProperty(exports,"TextInput",{enumerable:true,get:function get(){return _TextInput.TextInput;}});Object.defineProperty(exports,"Z_INDEX_SCALE",{enumerable:true,get:function get(){return _layout.Z_INDEX_SCALE;}});Object.defineProperty(exports,"generateStyleKey",{enumerable:true,get:function get(){return _styleKey.generateStyleKey;}});Object.defineProperty(exports,"parseAspectRatio",{enumerable:true,get:function get(){return _parser.parseAspectRatio;}});Object.defineProperty(exports,"parseBorder",{enumerable:true,get:function get(){return _parser.parseBorder;}});Object.defineProperty(exports,"parseClass",{enumerable:true,get:function get(){return _parser.parseClass;}});Object.defineProperty(exports,"parseClassName",{enumerable:true,get:function get(){return _parser.parseClassName;}});Object.defineProperty(exports,"parseColor",{enumerable:true,get:function get(){return _parser.parseColor;}});Object.defineProperty(exports,"parseLayout",{enumerable:true,get:function get(){return _parser.parseLayout;}});Object.defineProperty(exports,"parseShadow",{enumerable:true,get:function get(){return _parser.parseShadow;}});Object.defineProperty(exports,"parseSizing",{enumerable:true,get:function get(){return _parser.parseSizing;}});Object.defineProperty(exports,"parseSpacing",{enumerable:true,get:function get(){return _parser.parseSpacing;}});Object.defineProperty(exports,"parseTypography",{enumerable:true,get:function get(){return _parser.parseTypography;}});var _parser=require("./parser");var _styleKey=require("./utils/styleKey");var _aspectRatio=require("./parser/aspectRatio");var _colors=require("./parser/colors");var _layout=require("./parser/layout");var _shadows=require("./parser/shadows");var _sizing=require("./parser/sizing");var _spacing=require("./parser/spacing");var _typography=require("./parser/typography");var _Pressable=require("./components/Pressable");var _TextInput=require("./components/TextInput");
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Aspect ratio utilities for React Native
3
+ * Uses aspectRatio style property (React Native 0.71+)
4
+ */
5
+ import type { StyleObject } from "../types";
6
+ /**
7
+ * Preset aspect ratios
8
+ */
9
+ declare const ASPECT_RATIO_PRESETS: Record<string, number | undefined>;
10
+ /**
11
+ * Parse aspect ratio classes
12
+ * @param cls - Class name to parse
13
+ * @returns Style object or null if not an aspect ratio class
14
+ */
15
+ export declare function parseAspectRatio(cls: string): StyleObject | null;
16
+ export { ASPECT_RATIO_PRESETS };
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,"__esModule",{value:true});exports.ASPECT_RATIO_PRESETS=void 0;exports.parseAspectRatio=parseAspectRatio;var ASPECT_RATIO_PRESETS=exports.ASPECT_RATIO_PRESETS={"aspect-auto":undefined,"aspect-square":1,"aspect-video":16/9};function parseArbitraryAspectRatio(value){var match=value.match(/^\[(\d+)\/(\d+)\]$/);if(match){var numerator=Number.parseInt(match[1],10);var denominator=Number.parseInt(match[2],10);if(denominator===0){if(process.env.NODE_ENV!=="production"){console.warn(`[react-native-tailwind] Invalid aspect ratio: ${value}. Denominator cannot be zero.`);}return null;}return numerator/denominator;}return null;}function parseAspectRatio(cls){if(!cls.startsWith("aspect-")){return null;}if(cls in ASPECT_RATIO_PRESETS){var _aspectRatio=ASPECT_RATIO_PRESETS[cls];if(_aspectRatio===undefined){return{};}return{aspectRatio:_aspectRatio};}var arbitraryValue=cls.substring(7);var aspectRatio=parseArbitraryAspectRatio(arbitraryValue);if(aspectRatio!==null){return{aspectRatio:aspectRatio};}return null;}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ var _vitest=require("vitest");var _aspectRatio=require("./aspectRatio");(0,_vitest.describe)("ASPECT_RATIO_PRESETS",function(){(0,_vitest.it)("should export aspect ratio presets",function(){(0,_vitest.expect)(_aspectRatio.ASPECT_RATIO_PRESETS).toMatchSnapshot();});(0,_vitest.it)("should have all preset values",function(){(0,_vitest.expect)(_aspectRatio.ASPECT_RATIO_PRESETS).toHaveProperty("aspect-auto");(0,_vitest.expect)(_aspectRatio.ASPECT_RATIO_PRESETS).toHaveProperty("aspect-square");(0,_vitest.expect)(_aspectRatio.ASPECT_RATIO_PRESETS).toHaveProperty("aspect-video");});(0,_vitest.it)("should have correct preset values",function(){(0,_vitest.expect)(_aspectRatio.ASPECT_RATIO_PRESETS["aspect-auto"]).toBeUndefined();(0,_vitest.expect)(_aspectRatio.ASPECT_RATIO_PRESETS["aspect-square"]).toBe(1);(0,_vitest.expect)(_aspectRatio.ASPECT_RATIO_PRESETS["aspect-video"]).toBe(16/9);});});(0,_vitest.describe)("parseAspectRatio - preset values",function(){(0,_vitest.it)("should parse aspect-square",function(){(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-square")).toEqual({aspectRatio:1});});(0,_vitest.it)("should parse aspect-video",function(){(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-video")).toEqual({aspectRatio:16/9});});(0,_vitest.it)("should parse aspect-auto",function(){(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-auto")).toEqual({});});});(0,_vitest.describe)("parseAspectRatio - arbitrary values",function(){(0,_vitest.it)("should parse arbitrary aspect ratio values",function(){(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-[4/3]")).toEqual({aspectRatio:4/3});(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-[16/9]")).toEqual({aspectRatio:16/9});(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-[21/9]")).toEqual({aspectRatio:21/9});(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-[1/1]")).toEqual({aspectRatio:1});});(0,_vitest.it)("should handle arbitrary ratios with different aspect values",function(){(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-[2/1]")).toEqual({aspectRatio:2});(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-[3/2]")).toEqual({aspectRatio:1.5});(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-[9/16]")).toEqual({aspectRatio:9/16});});(0,_vitest.it)("should handle arbitrary ratios with large numbers",function(){(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-[100/50]")).toEqual({aspectRatio:2});(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-[1920/1080]")).toEqual({aspectRatio:1920/1080});});(0,_vitest.it)("should calculate correct aspect ratio values",function(){var result=(0,_aspectRatio.parseAspectRatio)("aspect-[4/3]");(0,_vitest.expect)(result==null?void 0:result.aspectRatio).toBeCloseTo(1.333,3);var result2=(0,_aspectRatio.parseAspectRatio)("aspect-[16/9]");(0,_vitest.expect)(result2==null?void 0:result2.aspectRatio).toBeCloseTo(1.778,3);});});(0,_vitest.describe)("parseAspectRatio - edge cases",function(){(0,_vitest.it)("should return null for division by zero",function(){(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-[4/0]")).toBeNull();(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-[16/0]")).toBeNull();});(0,_vitest.it)("should return null for invalid arbitrary values",function(){(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-[4]")).toBeNull();(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-[/3]")).toBeNull();(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-[4/3/2]")).toBeNull();(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-[abc/def]")).toBeNull();});(0,_vitest.it)("should return null for malformed brackets",function(){(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-[4/3")).toBeNull();(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-4/3]")).toBeNull();(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-4/3")).toBeNull();});(0,_vitest.it)("should return null for invalid class prefixes",function(){(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("ratio-[4/3]")).toBeNull();(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("ar-[4/3]")).toBeNull();(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspectRatio-[4/3]")).toBeNull();});});(0,_vitest.describe)("parseAspectRatio - invalid classes",function(){(0,_vitest.it)("should return null for non-aspect classes",function(){(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("bg-blue-500")).toBeNull();(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("p-4")).toBeNull();(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("text-white")).toBeNull();(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("w-full")).toBeNull();});(0,_vitest.it)("should return null for invalid aspect class names",function(){(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect")).toBeNull();(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-")).toBeNull();(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-invalid")).toBeNull();(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-16-9")).toBeNull();});(0,_vitest.it)("should return null for empty or whitespace input",function(){(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("")).toBeNull();(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)(" ")).toBeNull();});});(0,_vitest.describe)("parseAspectRatio - type validation",function(){(0,_vitest.it)("should return objects with correct property types",function(){var square=(0,_aspectRatio.parseAspectRatio)("aspect-square");(0,_vitest.expect)(typeof(square==null?void 0:square.aspectRatio)).toBe("number");var video=(0,_aspectRatio.parseAspectRatio)("aspect-video");(0,_vitest.expect)(typeof(video==null?void 0:video.aspectRatio)).toBe("number");var arbitrary=(0,_aspectRatio.parseAspectRatio)("aspect-[4/3]");(0,_vitest.expect)(typeof(arbitrary==null?void 0:arbitrary.aspectRatio)).toBe("number");});(0,_vitest.it)("should return null or object, never undefined",function(){var valid=(0,_aspectRatio.parseAspectRatio)("aspect-square");(0,_vitest.expect)(valid).not.toBeUndefined();(0,_vitest.expect)(typeof valid).toBe("object");var invalid=(0,_aspectRatio.parseAspectRatio)("invalid");(0,_vitest.expect)(invalid).toBeNull();});});(0,_vitest.describe)("parseAspectRatio - comprehensive coverage",function(){(0,_vitest.it)("should parse all preset variants without errors",function(){var presets=["aspect-auto","aspect-square","aspect-video"];presets.forEach(function(preset){var result=(0,_aspectRatio.parseAspectRatio)(preset);(0,_vitest.expect)(result).toBeTruthy();(0,_vitest.expect)(typeof result).toBe("object");});});(0,_vitest.it)("should return consistent results for same input",function(){var result1=(0,_aspectRatio.parseAspectRatio)("aspect-square");var result2=(0,_aspectRatio.parseAspectRatio)("aspect-square");(0,_vitest.expect)(result1).toEqual(result2);var result3=(0,_aspectRatio.parseAspectRatio)("aspect-[4/3]");var result4=(0,_aspectRatio.parseAspectRatio)("aspect-[4/3]");(0,_vitest.expect)(result3).toEqual(result4);});(0,_vitest.it)("should handle case-sensitive class names",function(){(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("ASPECT-square")).toBeNull();(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("Aspect-video")).toBeNull();(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-SQUARE")).toBeNull();});(0,_vitest.it)("should handle common aspect ratios",function(){(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-[1/1]")).toBeTruthy();(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-[4/3]")).toBeTruthy();(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-[16/9]")).toBeTruthy();(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-[21/9]")).toBeTruthy();(0,_vitest.expect)((0,_aspectRatio.parseAspectRatio)("aspect-[9/16]")).toBeTruthy();});(0,_vitest.it)("should differentiate between preset and arbitrary values",function(){var preset=(0,_aspectRatio.parseAspectRatio)("aspect-video");(0,_vitest.expect)(preset).toEqual({aspectRatio:16/9});var arbitrary=(0,_aspectRatio.parseAspectRatio)("aspect-[16/9]");(0,_vitest.expect)(arbitrary).toEqual({aspectRatio:16/9});(0,_vitest.expect)(preset).toEqual(arbitrary);});(0,_vitest.it)("should handle fractional results correctly",function(){var result=(0,_aspectRatio.parseAspectRatio)("aspect-[5/7]");(0,_vitest.expect)(result==null?void 0:result.aspectRatio).toBeCloseTo(0.714,3);var result2=(0,_aspectRatio.parseAspectRatio)("aspect-[3/4]");(0,_vitest.expect)(result2==null?void 0:result2.aspectRatio).toBe(0.75);});});
@@ -1 +1 @@
1
- var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.BORDER_WIDTH_SCALE=exports.BORDER_RADIUS_SCALE=void 0;exports.parseBorder=parseBorder;var _defineProperty2=_interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));var BORDER_WIDTH_SCALE=exports.BORDER_WIDTH_SCALE={"":1,"0":0,"2":2,"4":4,"8":8};var BORDER_RADIUS_SCALE=exports.BORDER_RADIUS_SCALE={none:0,sm:2,"":4,md:6,lg:8,xl:12,"2xl":16,"3xl":24,full:9999};function parseBorder(cls){if(cls.startsWith("border-")){return parseBorderWidth(cls);}if(cls==="border"){return{borderWidth:1};}if(cls.startsWith("rounded")){return parseBorderRadius(cls);}if(cls==="border-solid")return{borderStyle:"solid"};if(cls==="border-dotted")return{borderStyle:"dotted"};if(cls==="border-dashed")return{borderStyle:"dashed"};return null;}function parseBorderWidth(cls){var allArbMatch=cls.match(/^border-\[(\d+)(?:px)?\]$/);if(allArbMatch){return{borderWidth:parseInt(allArbMatch[1],10)};}var dirArbMatch=cls.match(/^border-([trbl])-\[(\d+)(?:px)?\]$/);if(dirArbMatch){var dir=dirArbMatch[1];var value=parseInt(dirArbMatch[2],10);var propMap={t:"borderTopWidth",r:"borderRightWidth",b:"borderBottomWidth",l:"borderLeftWidth"};return(0,_defineProperty2.default)({},propMap[dir],value);}var dirMatch=cls.match(/^border-([trbl])-?(\d*)$/);if(dirMatch){var _dir=dirMatch[1];var scaleKey=dirMatch[2]||"";var _value=BORDER_WIDTH_SCALE[scaleKey];if(typeof _value==="number"){var _propMap={t:"borderTopWidth",r:"borderRightWidth",b:"borderBottomWidth",l:"borderLeftWidth"};return(0,_defineProperty2.default)({},_propMap[_dir],_value);}}var allMatch=cls.match(/^border-(\d+)$/);if(allMatch){var _value2=BORDER_WIDTH_SCALE[allMatch[1]];if(_value2!==undefined){return{borderWidth:_value2};}}return null;}function parseBorderRadius(cls){var allArbMatch=cls.match(/^rounded-\[(\d+)(?:px)?\]$/);if(allArbMatch){return{borderRadius:parseInt(allArbMatch[1],10)};}var cornerArbMatch=cls.match(/^rounded-(tl|tr|bl|br)-\[(\d+)(?:px)?\]$/);if(cornerArbMatch){var corner=cornerArbMatch[1];var value=parseInt(cornerArbMatch[2],10);var propMap={tl:"borderTopLeftRadius",tr:"borderTopRightRadius",bl:"borderBottomLeftRadius",br:"borderBottomRightRadius"};return(0,_defineProperty2.default)({},propMap[corner],value);}var sideArbMatch=cls.match(/^rounded-([trbl])-\[(\d+)(?:px)?\]$/);if(sideArbMatch){var side=sideArbMatch[1];var _value3=parseInt(sideArbMatch[2],10);var _propMap2={t:["borderTopLeftRadius","borderTopRightRadius"],r:["borderTopRightRadius","borderBottomRightRadius"],b:["borderBottomLeftRadius","borderBottomRightRadius"],l:["borderTopLeftRadius","borderBottomLeftRadius"]};var result={};_propMap2[side].forEach(function(prop){return result[prop]=_value3;});return result;}var allMatch=cls.match(/^rounded(-\w+)?$/);if(allMatch){var scaleKey=allMatch[1]?allMatch[1].substring(1):"";var _value4=BORDER_RADIUS_SCALE[scaleKey];if(_value4!==undefined){return{borderRadius:_value4};}}var sideMatch=cls.match(/^rounded-([trbl])(?:-(\w+))?$/);if(sideMatch){var _side=sideMatch[1];var _scaleKey=sideMatch[2]||"";var _value5=BORDER_RADIUS_SCALE[_scaleKey];if(_value5!==undefined){var _propMap3={t:["borderTopLeftRadius","borderTopRightRadius"],r:["borderTopRightRadius","borderBottomRightRadius"],b:["borderBottomLeftRadius","borderBottomRightRadius"],l:["borderTopLeftRadius","borderBottomLeftRadius"]};var _result={};_propMap3[_side].forEach(function(prop){return _result[prop]=_value5;});return _result;}}var cornerMatch=cls.match(/^rounded-(tl|tr|bl|br)(?:-(\w+))?$/);if(cornerMatch){var _corner=cornerMatch[1];var _scaleKey2=cornerMatch[2]||"";var _value6=BORDER_RADIUS_SCALE[_scaleKey2];if(_value6!==undefined){var _propMap4={tl:"borderTopLeftRadius",tr:"borderTopRightRadius",bl:"borderBottomLeftRadius",br:"borderBottomRightRadius"};return(0,_defineProperty2.default)({},_propMap4[_corner],_value6);}}return null;}
1
+ var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.BORDER_WIDTH_SCALE=exports.BORDER_RADIUS_SCALE=void 0;exports.parseBorder=parseBorder;var _defineProperty2=_interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));var BORDER_WIDTH_SCALE=exports.BORDER_WIDTH_SCALE={"":1,"0":0,"2":2,"4":4,"8":8};var BORDER_RADIUS_SCALE=exports.BORDER_RADIUS_SCALE={none:0,sm:2,"":4,md:6,lg:8,xl:12,"2xl":16,"3xl":24,full:9999};var BORDER_WIDTH_PROP_MAP={t:"borderTopWidth",r:"borderRightWidth",b:"borderBottomWidth",l:"borderLeftWidth"};var BORDER_RADIUS_CORNER_MAP={tl:"borderTopLeftRadius",tr:"borderTopRightRadius",bl:"borderBottomLeftRadius",br:"borderBottomRightRadius"};var BORDER_RADIUS_SIDE_MAP={t:["borderTopLeftRadius","borderTopRightRadius"],r:["borderTopRightRadius","borderBottomRightRadius"],b:["borderBottomLeftRadius","borderBottomRightRadius"],l:["borderTopLeftRadius","borderBottomLeftRadius"]};function parseArbitraryBorderWidth(value){var pxMatch=value.match(/^\[(\d+)(?:px)?\]$/);if(pxMatch){return parseInt(pxMatch[1],10);}if(value.startsWith("[")&&value.endsWith("]")){if(process.env.NODE_ENV!=="production"){console.warn(`[react-native-tailwind] Unsupported arbitrary border width value: ${value}. Only px values are supported (e.g., [8px] or [8]).`);}return null;}return null;}function parseArbitraryBorderRadius(value){var pxMatch=value.match(/^\[(\d+)(?:px)?\]$/);if(pxMatch){return parseInt(pxMatch[1],10);}if(value.startsWith("[")&&value.endsWith("]")){if(process.env.NODE_ENV!=="production"){console.warn(`[react-native-tailwind] Unsupported arbitrary border radius value: ${value}. Only px values are supported (e.g., [12px] or [12]).`);}return null;}return null;}function parseBorder(cls){if(cls==="border-solid")return{borderStyle:"solid"};if(cls==="border-dotted")return{borderStyle:"dotted"};if(cls==="border-dashed")return{borderStyle:"dashed"};if(cls.startsWith("border-")){return parseBorderWidth(cls);}if(cls==="border"){return{borderWidth:1};}if(cls.startsWith("rounded")){return parseBorderRadius(cls);}return null;}function parseBorderWidth(cls){var dirMatch=cls.match(/^border-([trbl])(?:-(.+))?$/);if(dirMatch){var dir=dirMatch[1];var valueStr=dirMatch[2]||"";if(valueStr.startsWith("[")){var arbitraryValue=parseArbitraryBorderWidth(valueStr);if(arbitraryValue!==null){return(0,_defineProperty2.default)({},BORDER_WIDTH_PROP_MAP[dir],arbitraryValue);}return null;}var scaleValue=BORDER_WIDTH_SCALE[valueStr];if(scaleValue!==undefined){return(0,_defineProperty2.default)({},BORDER_WIDTH_PROP_MAP[dir],scaleValue);}return null;}var allMatch=cls.match(/^border-(\d+)$/);if(allMatch){var value=BORDER_WIDTH_SCALE[allMatch[1]];if(value!==undefined){return{borderWidth:value};}}var allArbMatch=cls.match(/^border-(\[.+\])$/);if(allArbMatch){var _arbitraryValue=parseArbitraryBorderWidth(allArbMatch[1]);if(_arbitraryValue!==null){return{borderWidth:_arbitraryValue};}}return null;}function parseBorderRadius(cls){var withoutPrefix=cls.substring(7);if(withoutPrefix===""){return{borderRadius:BORDER_RADIUS_SCALE[""]};}if(!withoutPrefix.startsWith("-")){return null;}var rest=withoutPrefix.substring(1);if(rest===""){return null;}var cornerMatch=rest.match(/^(tl|tr|bl|br)(?:-(.+))?$/);if(cornerMatch){var corner=cornerMatch[1];var valueStr=cornerMatch[2]||"";if(valueStr.startsWith("[")){var arbitraryValue=parseArbitraryBorderRadius(valueStr);if(arbitraryValue!==null){return(0,_defineProperty2.default)({},BORDER_RADIUS_CORNER_MAP[corner],arbitraryValue);}return null;}var _scaleValue=BORDER_RADIUS_SCALE[valueStr];if(_scaleValue!==undefined){return(0,_defineProperty2.default)({},BORDER_RADIUS_CORNER_MAP[corner],_scaleValue);}return null;}var sideMatch=rest.match(/^([trbl])(?:-(.+))?$/);if(sideMatch){var side=sideMatch[1];var _valueStr=sideMatch[2]||"";var value;if(_valueStr.startsWith("[")){var _arbitraryValue2=parseArbitraryBorderRadius(_valueStr);if(_arbitraryValue2!==null){value=_arbitraryValue2;}else{return null;}}else{value=BORDER_RADIUS_SCALE[_valueStr];}if(value!==undefined){var result={};BORDER_RADIUS_SIDE_MAP[side].forEach(function(prop){return result[prop]=value;});return result;}return null;}if(rest.startsWith("[")){var _arbitraryValue3=parseArbitraryBorderRadius(rest);if(_arbitraryValue3!==null){return{borderRadius:_arbitraryValue3};}return null;}var scaleValue=BORDER_RADIUS_SCALE[rest];if(scaleValue!==undefined){return{borderRadius:scaleValue};}return null;}
@@ -0,0 +1 @@
1
+ export {};