@mgcrea/react-native-tailwind 0.11.0 → 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.
@@ -238,6 +238,68 @@ describe("parseSpacing - edge cases", () => {
238
238
  });
239
239
  });
240
240
 
241
+ describe("parseSpacing - decimal arbitrary values", () => {
242
+ it("should parse margin with decimal arbitrary values", () => {
243
+ expect(parseSpacing("m-[4.5px]")).toEqual({ margin: 4.5 });
244
+ expect(parseSpacing("m-[4.5]")).toEqual({ margin: 4.5 });
245
+ expect(parseSpacing("m-[16.75px]")).toEqual({ margin: 16.75 });
246
+ expect(parseSpacing("m-[16.75]")).toEqual({ margin: 16.75 });
247
+ expect(parseSpacing("m-[100.25px]")).toEqual({ margin: 100.25 });
248
+ expect(parseSpacing("m-[0.5]")).toEqual({ margin: 0.5 });
249
+ });
250
+
251
+ it("should parse padding with decimal arbitrary values", () => {
252
+ expect(parseSpacing("p-[4.5px]")).toEqual({ padding: 4.5 });
253
+ expect(parseSpacing("p-[4.5]")).toEqual({ padding: 4.5 });
254
+ expect(parseSpacing("pl-[4.5px]")).toEqual({ paddingLeft: 4.5 });
255
+ expect(parseSpacing("pl-[4.5]")).toEqual({ paddingLeft: 4.5 });
256
+ expect(parseSpacing("pr-[16.75px]")).toEqual({ paddingRight: 16.75 });
257
+ expect(parseSpacing("pt-[10.5]")).toEqual({ paddingTop: 10.5 });
258
+ expect(parseSpacing("pb-[20.25px]")).toEqual({ paddingBottom: 20.25 });
259
+ });
260
+
261
+ it("should parse padding horizontal/vertical with decimal arbitrary values", () => {
262
+ expect(parseSpacing("px-[4.5px]")).toEqual({ paddingHorizontal: 4.5 });
263
+ expect(parseSpacing("py-[10.75]")).toEqual({ paddingVertical: 10.75 });
264
+ });
265
+
266
+ it("should parse gap with decimal arbitrary values", () => {
267
+ expect(parseSpacing("gap-[4.5px]")).toEqual({ gap: 4.5 });
268
+ expect(parseSpacing("gap-[4.5]")).toEqual({ gap: 4.5 });
269
+ expect(parseSpacing("gap-[16.75px]")).toEqual({ gap: 16.75 });
270
+ expect(parseSpacing("gap-[0.5]")).toEqual({ gap: 0.5 });
271
+ });
272
+
273
+ it("should parse negative margin with decimal arbitrary values", () => {
274
+ expect(parseSpacing("-m-[4.5px]")).toEqual({ margin: -4.5 });
275
+ expect(parseSpacing("-m-[4.5]")).toEqual({ margin: -4.5 });
276
+ expect(parseSpacing("-m-[10.5px]")).toEqual({ margin: -10.5 });
277
+ expect(parseSpacing("-mt-[16.75px]")).toEqual({ marginTop: -16.75 });
278
+ expect(parseSpacing("-ml-[8.25]")).toEqual({ marginLeft: -8.25 });
279
+ expect(parseSpacing("-mx-[12.5px]")).toEqual({ marginHorizontal: -12.5 });
280
+ expect(parseSpacing("-my-[20.75]")).toEqual({ marginVertical: -20.75 });
281
+ });
282
+
283
+ it("should parse margin directional with decimal arbitrary values", () => {
284
+ expect(parseSpacing("mt-[4.5px]")).toEqual({ marginTop: 4.5 });
285
+ expect(parseSpacing("mr-[8.25]")).toEqual({ marginRight: 8.25 });
286
+ expect(parseSpacing("mb-[16.75px]")).toEqual({ marginBottom: 16.75 });
287
+ expect(parseSpacing("ml-[12.5]")).toEqual({ marginLeft: 12.5 });
288
+ });
289
+
290
+ it("should parse margin horizontal/vertical with decimal arbitrary values", () => {
291
+ expect(parseSpacing("mx-[4.5px]")).toEqual({ marginHorizontal: 4.5 });
292
+ expect(parseSpacing("my-[10.75]")).toEqual({ marginVertical: 10.75 });
293
+ });
294
+
295
+ it("should handle edge case decimal values", () => {
296
+ expect(parseSpacing("m-[0.1px]")).toEqual({ margin: 0.1 });
297
+ expect(parseSpacing("p-[0.001]")).toEqual({ padding: 0.001 });
298
+ expect(parseSpacing("gap-[999.999px]")).toEqual({ gap: 999.999 });
299
+ expect(parseSpacing("-m-[0.5]")).toEqual({ margin: -0.5 });
300
+ });
301
+ });
302
+
241
303
  describe("parseSpacing - comprehensive coverage", () => {
242
304
  it("should parse all margin directions with same value", () => {
243
305
  const value = 16;
@@ -43,14 +43,14 @@ export const SPACING_SCALE: Record<string, number> = {
43
43
  };
44
44
 
45
45
  /**
46
- * Parse arbitrary spacing value: [16px], [20]
47
- * Returns number for px values, null for unsupported formats
46
+ * Parse arbitrary spacing value: [16px], [20], [4.5px], [16.75]
47
+ * Returns number for px values (including decimals), null for unsupported formats
48
48
  */
49
49
  function parseArbitrarySpacing(value: string): number | null {
50
- // Match: [16px] or [16] (pixels only)
51
- const pxMatch = value.match(/^\[(\d+)(?:px)?\]$/);
50
+ // Match: [16px], [16], [4.5px], [4.5] (pixels, including decimals)
51
+ const pxMatch = value.match(/^\[(-?\d+(?:\.\d+)?)(?:px)?\]$/);
52
52
  if (pxMatch) {
53
- return parseInt(pxMatch[1], 10);
53
+ return parseFloat(pxMatch[1]);
54
54
  }
55
55
 
56
56
  // Warn about unsupported formats
@@ -58,7 +58,7 @@ function parseArbitrarySpacing(value: string): number | null {
58
58
  /* v8 ignore next 5 */
59
59
  if (process.env.NODE_ENV !== "production") {
60
60
  console.warn(
61
- `[react-native-tailwind] Unsupported arbitrary spacing value: ${value}. Only px values are supported (e.g., [16px] or [16]).`,
61
+ `[react-native-tailwind] Unsupported arbitrary spacing value: ${value}. Only px values are supported (e.g., [16px], [16], [4.5px], [4.5]).`,
62
62
  );
63
63
  }
64
64
  return null;
@@ -69,7 +69,7 @@ function parseArbitrarySpacing(value: string): number | null {
69
69
 
70
70
  /**
71
71
  * Parse spacing classes (margin, padding, gap)
72
- * Examples: m-4, mx-2, mt-8, p-4, px-2, pt-8, gap-4, m-[16px], -m-4, -mt-[10px]
72
+ * Examples: m-4, mx-2, mt-8, p-4, px-2, pt-8, gap-4, m-[16px], pl-[4.5px], -m-4, -mt-[10px]
73
73
  */
74
74
  export function parseSpacing(cls: string): StyleObject | null {
75
75
  // Margin: m-4, mx-2, mt-8, m-[16px], -m-4, -mt-2, etc.
@@ -317,7 +317,10 @@ describe("runtime", () => {
317
317
  it("should provide raw hex values for animations", () => {
318
318
  const result = tw`bg-blue-500 active:bg-blue-700`;
319
319
  // Access raw backgroundColor value for use with reanimated
320
- expect(result?.style.backgroundColor).toBe("#2b7fff");
320
+ const style = Array.isArray(result?.style) ? result.style.find((s) => s !== false) : result?.style;
321
+ expect(
322
+ style && typeof style === "object" && "backgroundColor" in style ? style.backgroundColor : undefined,
323
+ ).toBe("#2b7fff");
321
324
  expect(result?.activeStyle?.backgroundColor).toBe("#1447e6");
322
325
  });
323
326
 
@@ -7,11 +7,18 @@ export type NativeStyle = ViewStyle | TextStyle | ImageStyle;
7
7
 
8
8
  /**
9
9
  * Return type for tw/twStyle functions with separate style properties for modifiers
10
+ * When color-scheme modifiers (dark:, light:) are present, style becomes an array with runtime conditionals
11
+ * When platform modifiers (ios:, android:, web:) are present, style becomes an array with Platform.select()
10
12
  */
11
13
  export type TwStyle<T extends NativeStyle = NativeStyle> = {
12
- style: T;
14
+ style: T | Array<T | false>;
13
15
  activeStyle?: T;
14
16
  focusStyle?: T;
15
17
  disabledStyle?: T;
16
18
  placeholderStyle?: TextStyle;
19
+ lightStyle?: T;
20
+ darkStyle?: T;
21
+ iosStyle?: T;
22
+ androidStyle?: T;
23
+ webStyle?: T;
17
24
  };