@formepdf/tailwind 0.7.10 → 0.7.12

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.
package/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # @formepdf/tailwind
2
+
3
+ Style [Forme](https://formepdf.com) PDF components with Tailwind CSS utility classes.
4
+
5
+ ```bash
6
+ npm install @formepdf/tailwind
7
+ ```
8
+
9
+ ```tsx
10
+ import { tw } from '@formepdf/tailwind';
11
+ import { Document, Page, View, Text } from '@formepdf/react';
12
+
13
+ <Document>
14
+ <Page size="Letter" margin={54}>
15
+ <View style={tw("flex-row items-center justify-between p-6 bg-slate-100 rounded-lg")}>
16
+ <Text style={tw("text-2xl font-bold text-slate-900")}>Invoice #001</Text>
17
+ <Text style={tw("text-sm text-slate-500")}>March 2026</Text>
18
+ </View>
19
+ </Page>
20
+ </Document>
21
+ ```
22
+
23
+ `tw()` parses a space-separated string of Tailwind classes and returns a plain style object. Unknown classes are silently ignored. When classes conflict, the last one wins.
24
+
25
+ ```tsx
26
+ tw("p-4 text-lg font-bold text-blue-500")
27
+ // → { padding: 16, fontSize: 18, fontWeight: 700, color: '#3b82f6' }
28
+ ```
29
+
30
+ ## Supported classes
31
+
32
+ **Spacing** — `p-{n}`, `px-{n}`, `py-{n}`, `pt-{n}`, `m-{n}`, `mx-{n}`, `mx-auto`, `space-y-{n}`, `space-x-{n}`, negative values (`-mt-4`), `p-px`
33
+
34
+ **Typography** — `text-xs` through `text-9xl`, `font-thin` through `font-black`, `italic`, `text-left/center/right/justify`, `leading-*`, `tracking-*`, `underline`, `line-through`, `uppercase`, `lowercase`, `capitalize`
35
+
36
+ **Colors** — Full Tailwind palette (slate, gray, red, blue, etc.) with shades 50–950: `text-{color}-{shade}`, `bg-{color}-{shade}`, `border-{color}-{shade}`
37
+
38
+ **Layout** — `flex-row`, `flex-col`, `items-*`, `justify-*`, `self-*`, `flex-1`, `flex-wrap`, `gap-{n}`
39
+
40
+ **Dimensions** — `w-{n}`, `h-{n}`, `w-full`, `w-auto`, `w-1/2`, `min-w-{n}`, `max-w-{n}`
41
+
42
+ **Grid** — `grid`, `grid-cols-{n}`, `col-span-{n}`, `col-start-{n}`, `row-span-{n}`
43
+
44
+ **Borders** — `border`, `border-{n}`, `border-t`, `rounded`, `rounded-lg`, `rounded-full`
45
+
46
+ **Other** — `relative`, `absolute`, `top-{n}`, `overflow-hidden`, `opacity-{n}`
47
+
48
+ **Arbitrary values** — `w-[200]`, `text-[14px]`, `p-[20]`, `text-[#333]`, `bg-[#ff0000]`
49
+
50
+ ## Auto margins
51
+
52
+ Horizontal centering with `mx-auto`:
53
+
54
+ ```tsx
55
+ <View style={tw("mx-auto w-64")}>
56
+ <Text>Centered content</Text>
57
+ </View>
58
+ ```
59
+
60
+ Also supports `my-auto`, `mt-auto`, `mr-auto`, `mb-auto`, `ml-auto`, `m-auto`.
61
+
62
+ ## TypeScript
63
+
64
+ `tw()` returns a `FormeStyle` compatible with Forme component `style` props — no type casting needed:
65
+
66
+ ```tsx
67
+ import { tw, type FormeStyle } from '@formepdf/tailwind';
68
+
69
+ const style: FormeStyle = tw("p-4 bg-white rounded-lg");
70
+ ```
71
+
72
+ ## What's not supported
73
+
74
+ Tailwind features that don't apply to PDF rendering: responsive prefixes (`sm:`, `md:`), state variants (`hover:`, `focus:`), dark mode, `z-index`, `aspect-ratio`.
75
+
76
+ ## Docs
77
+
78
+ Full documentation: [docs.formepdf.com/tailwind](https://docs.formepdf.com/tailwind)
package/dist/parsers.js CHANGED
@@ -45,9 +45,20 @@ function parseSpacing(cls) {
45
45
  return null;
46
46
  }
47
47
  // ── Typography ───────────────────────────────────────────────────────
48
- const textSizes = {
49
- xs: 12, sm: 14, base: 16, lg: 18, xl: 20,
50
- "2xl": 24, "3xl": 30, "4xl": 36, "5xl": 48, "6xl": 60, "7xl": 72, "8xl": 96, "9xl": 128,
48
+ const textSizeDefaults = {
49
+ xs: { fontSize: 12, lineHeight: 16 },
50
+ sm: { fontSize: 14, lineHeight: 20 },
51
+ base: { fontSize: 16, lineHeight: 24 },
52
+ lg: { fontSize: 18, lineHeight: 28 },
53
+ xl: { fontSize: 20, lineHeight: 28 },
54
+ "2xl": { fontSize: 24, lineHeight: 32 },
55
+ "3xl": { fontSize: 30, lineHeight: 36 },
56
+ "4xl": { fontSize: 36, lineHeight: 40 },
57
+ "5xl": { fontSize: 48, lineHeight: 48 },
58
+ "6xl": { fontSize: 60, lineHeight: 60 },
59
+ "7xl": { fontSize: 72, lineHeight: 72 },
60
+ "8xl": { fontSize: 96, lineHeight: 96 },
61
+ "9xl": { fontSize: 128, lineHeight: 128 },
51
62
  };
52
63
  const fontWeights = {
53
64
  thin: 100, extralight: 200, light: 300, normal: 400, medium: 500,
@@ -63,8 +74,9 @@ function parseTypography(cls) {
63
74
  // text-{size}
64
75
  if (cls.startsWith("text-")) {
65
76
  const rest = cls.substring(5);
66
- if (textSizes[rest] !== undefined)
67
- return { fontSize: textSizes[rest] };
77
+ const def = textSizeDefaults[rest];
78
+ if (def)
79
+ return { fontSize: def.fontSize, lineHeight: def.lineHeight / def.fontSize };
68
80
  // text-left/center/right/justify
69
81
  if (rest === "left" || rest === "center" || rest === "right" || rest === "justify") {
70
82
  return { textAlign: rest };
@@ -89,7 +101,7 @@ function parseTypography(cls) {
89
101
  return { lineHeight: namedLeading[rest] };
90
102
  const n = parseFloat(rest);
91
103
  if (!isNaN(n))
92
- return { lineHeight: n * 4 };
104
+ return { lineHeight: n * 0.25 };
93
105
  return null;
94
106
  }
95
107
  // tracking-{value}
@@ -123,7 +135,7 @@ function parseColorClass(cls) {
123
135
  if (cls.startsWith("text-")) {
124
136
  const rest = cls.substring(5);
125
137
  // Skip size and alignment keywords
126
- if (textSizes[rest] !== undefined)
138
+ if (textSizeDefaults[rest] !== undefined)
127
139
  return null;
128
140
  if (rest === "left" || rest === "center" || rest === "right" || rest === "justify")
129
141
  return null;
@@ -226,6 +238,19 @@ function parseLayout(cls) {
226
238
  return { flexWrap: "wrap" };
227
239
  if (cls === "flex-nowrap")
228
240
  return { flexWrap: "nowrap" };
241
+ // space-y-{n} / space-x-{n} → map to gap (flex container spacing)
242
+ if (cls.startsWith("space-y-")) {
243
+ const n = parseFloat(cls.substring(8));
244
+ if (!isNaN(n))
245
+ return { rowGap: n * 4 };
246
+ return null;
247
+ }
248
+ if (cls.startsWith("space-x-")) {
249
+ const n = parseFloat(cls.substring(8));
250
+ if (!isNaN(n))
251
+ return { columnGap: n * 4 };
252
+ return null;
253
+ }
229
254
  // gap
230
255
  if (cls.startsWith("gap-x-")) {
231
256
  const n = parseFloat(cls.substring(6));
@@ -460,6 +485,7 @@ const arbitraryPrefixMap = {
460
485
  m: "margin", mx: "marginHorizontal", my: "marginVertical",
461
486
  mt: "marginTop", mr: "marginRight", mb: "marginBottom", ml: "marginLeft",
462
487
  gap: "gap", "gap-x": "columnGap", "gap-y": "rowGap",
488
+ "space-x": "columnGap", "space-y": "rowGap",
463
489
  top: "top", right: "right", bottom: "bottom", left: "left",
464
490
  rounded: "borderRadius",
465
491
  opacity: "opacity",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formepdf/tailwind",
3
- "version": "0.7.10",
3
+ "version": "0.7.12",
4
4
  "description": "Tailwind CSS class support for Forme PDF templates",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",