Skip to content

Commit 43e6b1d

Browse files
committed
Merge branch 'master' into transform-origin-and-percentage-translate
2 parents f814fac + d32ffbf commit 43e6b1d

File tree

11 files changed

+232
-16
lines changed

11 files changed

+232
-16
lines changed

changelog.md

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,40 +6,74 @@ on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project ad
66

77
[comment]: # 'Section Titles: Added/Fixed/Changed/Removed'
88

9+
## [4.9.1] - 2025-06-25
10+
11+
### Fixed
12+
13+
- Fixed custom border width [(#325)](https://github.com/jaredh159/twrnc/issues/325) and
14+
[(#339)](https://github.com/jaredh159/twrnc/issues/339).
15+
16+
## [4.9.0] - 2025-06-12
17+
18+
### Added
19+
20+
- support pointer-events-(auto|none|box-only|box-none) (thanks @ferretwithaberet)
21+
[(#349)](https://github.com/jaredh159/tailwind-react-native-classnames/issues/349) and
22+
[(#350)](https://github.com/jaredh159/tailwind-react-native-classnames/pull/350)
23+
24+
## [4.8.0] - 2025-05-27
25+
26+
### Added
27+
28+
- support arbitrary hsl colors and opacity modifiers (thanks @cpotdevin)
29+
[(#347)](https://github.com/jaredh159/tailwind-react-native-classnames/pull/347)
30+
931
## [4.7.0] - 2025-05-06
1032

11-
- support transform scale, rotate, skew, translate
12-
[(#343)](https://github.com/jaredh159/tailwind-react-native-classnames/pulls/343)
33+
### Added
34+
35+
- support transform scale, rotate, skew, translate (thanks @Pedrozxcv)
36+
[(#343)](https://github.com/jaredh159/tailwind-react-native-classnames/pull/343)
1337

1438
## [4.6.1] - 2025-01-24
1539

40+
### Changed
41+
1642
- prevent auto-upgrades to `[email protected]` until we explore/fix compitibility
1743
[(#331)](https://github.com/jaredh159/tailwind-react-native-classnames/issues/331)
1844

1945
## [4.6.0] - 2024-11-07
2046

2147
- added support for fontWeight sub-customization in fontSize theming (thanks @Gyeop)
22-
[(#324)](https://github.com/jaredh159/tailwind-react-native-classnames/pulls/324)
48+
[(#324)](https://github.com/jaredh159/tailwind-react-native-classnames/pull/324)
2349

2450
## [4.5.1] - 2024-08-23
2551

52+
### Changed
53+
2654
- revised minimum RN version to 0.62.2 after testing, see
2755
[(#308)](https://github.com/jaredh159/tailwind-react-native-classnames/issues/308)
2856

2957
## [4.5.0] - 2024-07-22
3058

59+
### Added
60+
3161
- added support for `size-*` shorthand utility
3262
[(#314)](https://github.com/jaredh159/tailwind-react-native-classnames/issues/314) and
3363
[(#315)](https://github.com/jaredh159/tailwind-react-native-classnames/pull/315)
3464

3565
## [4.4.0] - 2024-07-09
3666

67+
### Added
68+
3769
- added support for arbitrary named colors (eg. `text-[lemonchiffon]`)
3870
[(#306)](https://github.com/jaredh159/tailwind-react-native-classnames/issues/306) and
3971
[(#309)](https://github.com/jaredh159/tailwind-react-native-classnames/pull/309)
4072

4173
## [4.3.0] - 2024-06-18
4274

75+
### Added
76+
4377
- added support for line-height shorthand with font-size (eg. `text-sm/6`)
4478
[(#282)](https://github.com/jaredh159/tailwind-react-native-classnames/issues/292) and
4579
[(#293)](https://github.com/jaredh159/tailwind-react-native-classnames/pull/293)

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "twrnc",
3-
"version": "4.7.0",
3+
"version": "4.9.1",
44
"description": "simple, expressive API for tailwindcss + react-native",
55
"author": "Jared Henderson <[email protected]>",
66
"module": "dist/esm/index.js",

readme.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ const MyComponent = () => (
5454
- [RN-Only Additions](#rn-only-additions)
5555
- [JIT-style Arbitrary Values](#jit-style-arbitrary-values)
5656
- [VS Code Intellisense](#vs-code-intellisense)
57+
- [JetBrains IDEs Intellisense](#jetbrains-ides-intellisense)
5758
- [Memo-Busting](#memo-busting)
5859
- [Migrating from previous versions](#migrating-from-previous-versions)
5960
- [Prior Art](#prior-art)
@@ -414,6 +415,7 @@ to web-css, including:
414415
- `align-self: baseline;` via `self-baseline`
415416
- `include-font-padding` and `remove-font-padding` (android only: `includeFontPadding`)
416417
- image tint color control (`tint-{color}` e.g. `tint-red-200`)
418+
- `pointer-events-(box-only|box-none)`
417419

418420
## JIT-Style Arbitrary Values
419421

@@ -451,6 +453,23 @@ for VS Code.
451453
More detailed instructions, including how to add snippets, are available
452454
[here](https://github.com/jaredh159/tailwind-react-native-classnames/discussions/124).
453455

456+
## JetBrains IDEs Intellisense
457+
458+
For JetBrains IDEs (WebStorm, IntelliJ, etc.) Go to Settings | Languages & Frameworks |
459+
Style Sheets | Tailwind CSS. Add the following configuration options:
460+
461+
```jsonc
462+
// ...
463+
"tailwindCSS.classAttributes": [
464+
// ...
465+
"style"
466+
],
467+
"tailwindCSS.classFunctions": ["tw", "tw.color", "tw.style"],
468+
```
469+
470+
It is important that you have a `tailwind.config.js` in the root of the repository even if
471+
the content is just `export default {}`, otherwise the Tailwind LSP won't start correctly.
472+
454473
## Memo Busting
455474

456475
If you're using device-context prefixes (like `dark:`, and `md:`), _memoized_ components

src/UtilityParser.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
transformNone,
2525
translate,
2626
} from './resolve/transform';
27+
import pointerEvents from './resolve/pointer-events';
2728

2829
export default class UtilityParser {
2930
private position = 0;
@@ -337,6 +338,11 @@ export default class UtilityParser {
337338
if (style) return style;
338339
}
339340

341+
if (this.consumePeeked(`pointer-events-`)) {
342+
style = pointerEvents(this.rest);
343+
if (style) return style;
344+
}
345+
340346
h.warn(`\`${this.rest}\` unknown or invalid utility`);
341347
return null;
342348
}

src/__tests__/borders.spec.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,48 @@ describe(`border-radius`, () => {
6969
expect(tw.style(utility)).toEqual(expected);
7070
});
7171
});
72+
73+
describe(`custom borderWidth`, () => {
74+
test(`custom borderWidth values from theme config are applied`, () => {
75+
const tw = create({
76+
theme: {
77+
borderWidth: {
78+
DEFAULT: `1px`,
79+
0: `0`,
80+
2: `2px`,
81+
4: `4px`,
82+
8: `8px`,
83+
10: `10px`,
84+
0.5: `0.5px`,
85+
hw: `0.33`,
86+
foo: `3rem`,
87+
bar: `57px`,
88+
},
89+
},
90+
});
91+
expect(tw.style(`border-bar`)).toEqual({ borderWidth: 57 });
92+
expect(tw.style(`border-foo`)).toEqual({ borderWidth: 48 });
93+
expect(tw.style(`border-hw`)).toEqual({ borderWidth: 0.33 });
94+
expect(tw.style(`border-0.5`)).toEqual({ borderWidth: 0.5 });
95+
expect(tw.style(`border`)).toEqual({ borderWidth: 1 });
96+
});
97+
98+
test(`custom borderWidth and width values from theme.extend are applied`, () => {
99+
const tw = create({
100+
plugins: [],
101+
theme: {
102+
extend: {
103+
borderWidth: {
104+
hw: `0.33`,
105+
foo: `3rem`,
106+
bar: `57px`,
107+
},
108+
width: { hw: `0.33` },
109+
},
110+
},
111+
});
112+
expect(tw.style(`border-hw w-hw`)).toEqual({ borderWidth: 0.33, width: 0.33 });
113+
expect(tw.style(`border-bar`)).toEqual({ borderWidth: 57 });
114+
expect(tw.style(`border-foo`)).toEqual({ borderWidth: 48 });
115+
});
116+
});

src/__tests__/colors.spec.ts

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,16 @@ describe(`colors`, () => {
6969

7070
test(`rgb/a configged colors`, () => {
7171
tw = create({
72-
theme: { colors: { foo: `rgb(1, 2, 3)`, bar: `rgba(4, 5, 6, 0.5)` } },
72+
theme: {
73+
colors: {
74+
foo: `rgb(1, 2, 3)`,
75+
bar: `rgba(4, 5, 6, 0.5)`,
76+
fizz: `rgb(7 8 9)`,
77+
buzz: `rgba(10 11 12 / 0.6)`,
78+
},
79+
},
7380
});
81+
7482
expect(tw`text-foo bg-bar`).toEqual({
7583
color: `rgb(1, 2, 3)`,
7684
backgroundColor: `rgba(4, 5, 6, 0.5)`,
@@ -79,6 +87,66 @@ describe(`colors`, () => {
7987
expect(tw`text-foo text-opacity-75`).toEqual({
8088
color: `rgba(1, 2, 3, 0.75)`,
8189
});
90+
91+
expect(tw`text-foo/50 bg-bar/75`).toEqual({
92+
color: `rgba(1, 2, 3, 0.5)`,
93+
backgroundColor: `rgba(4, 5, 6, 0.75)`,
94+
});
95+
96+
expect(tw`text-fizz bg-buzz`).toEqual({
97+
color: `rgb(7 8 9)`,
98+
backgroundColor: `rgba(10 11 12 / 0.6)`,
99+
});
100+
101+
expect(tw`text-fizz text-opacity-75`).toEqual({
102+
color: `rgba(7 8 9 / 0.75)`,
103+
});
104+
105+
expect(tw`text-fizz/50 bg-buzz/75`).toEqual({
106+
color: `rgba(7 8 9 / 0.5)`,
107+
backgroundColor: `rgba(10 11 12 / 0.75)`,
108+
});
109+
});
110+
111+
test(`hsl/a configged colors`, () => {
112+
tw = create({
113+
theme: {
114+
colors: {
115+
foo: `hsl(1, 2%, 3%)`,
116+
bar: `hsla(4, 5%, 6%, 0.5)`,
117+
fizz: `hsl(7 8% 9%)`,
118+
buzz: `hsla(10 11% 12% / 0.6)`,
119+
},
120+
},
121+
});
122+
123+
expect(tw`text-foo bg-bar`).toEqual({
124+
color: `hsl(1, 2%, 3%)`,
125+
backgroundColor: `hsla(4, 5%, 6%, 0.5)`,
126+
});
127+
128+
expect(tw`text-foo text-opacity-75`).toEqual({
129+
color: `hsla(1, 2%, 3%, 0.75)`,
130+
});
131+
132+
expect(tw`text-foo/50 bg-bar/75`).toEqual({
133+
color: `hsla(1, 2%, 3%, 0.5)`,
134+
backgroundColor: `hsla(4, 5%, 6%, 0.75)`,
135+
});
136+
137+
expect(tw`text-fizz bg-buzz`).toEqual({
138+
color: `hsl(7 8% 9%)`,
139+
backgroundColor: `hsla(10 11% 12% / 0.6)`,
140+
});
141+
142+
expect(tw`text-fizz text-opacity-75`).toEqual({
143+
color: `hsla(7 8% 9% / 0.75)`,
144+
});
145+
146+
expect(tw`text-fizz/50 bg-buzz/75`).toEqual({
147+
color: `hsla(7 8% 9% / 0.5)`,
148+
backgroundColor: `hsla(10 11% 12% / 0.75)`,
149+
});
82150
});
83151

84152
test(`DEFAULT special modifier`, () => {
@@ -97,9 +165,19 @@ describe(`colors`, () => {
97165
expect(tw`bg-[rgba(3,4,5,0.1)]`).toEqual({
98166
backgroundColor: `rgba(3,4,5,0.1)`,
99167
});
168+
expect(tw`bg-[hsla(6,7%,8%,0.2)]`).toEqual({
169+
backgroundColor: `hsla(6,7%,8%,0.2)`,
170+
});
171+
100172
expect(tw`bg-[#012] bg-opacity-50`).toEqual({
101173
backgroundColor: `rgba(0, 17, 34, 0.5)`,
102174
});
175+
expect(tw`bg-[rgba(3,4,5,0.1)] bg-opacity-50`).toEqual({
176+
backgroundColor: `rgba(3,4,5, 0.5)`,
177+
});
178+
expect(tw`bg-[hsla(6,7%,8%,0.2)] bg-opacity-50`).toEqual({
179+
backgroundColor: `hsla(6,7%,8%, 0.5)`,
180+
});
103181
});
104182

105183
test(`non-group dashed custom colors`, () => {
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { describe, test, expect } from '@jest/globals';
2+
import { create } from '../';
3+
4+
describe(`pointer-events utilities`, () => {
5+
let tw = create();
6+
beforeEach(() => (tw = create()));
7+
8+
const cases: Array<[string, Record<string, string>]> = [
9+
[`pointer-events-none`, { pointerEvents: `none` }],
10+
[`pointer-events-auto`, { pointerEvents: `auto` }],
11+
[`pointer-events-box-only`, { pointerEvents: `box-only` }],
12+
[`pointer-events-box-none`, { pointerEvents: `box-none` }],
13+
];
14+
15+
test.each(cases)(`tw\`%s\` -> %s`, (utility, expected) => {
16+
expect(tw.style(utility)).toEqual(expected);
17+
});
18+
});

src/resolve/borders.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ import { color } from './color';
1010

1111
export function border(value: string, theme?: TwTheme): StyleIR | null {
1212
let [rest, direction] = parseAndConsumeDirection(value);
13-
const widthUtilityMatch = rest.match(/^(-?(\d)+)?$/);
14-
if (widthUtilityMatch) {
15-
return borderWidth(rest, direction, theme?.borderWidth);
13+
const config = theme?.borderWidth;
14+
const key = rest.replace(/^-/, ``);
15+
if (config && (config[key] !== undefined || key.match(/^(-?(\d)+)?$/))) {
16+
return borderWidth(key, direction, config);
1617
}
1718

1819
rest = rest.replace(/^-/, ``);

src/resolve/color.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ export function color(
1919

2020
let color = ``;
2121

22-
// arbitrary hex/rgb(a) support: `bg-[#eaeaea]`, `text-[rgba(1, 1, 1, 0.5)]`
23-
if (value.startsWith(`[#`) || value.startsWith(`[rgb`)) {
22+
// arbitrary hex/rgb(a)/hsl(a) support: `bg-[#eaeaea]`, `text-[rgba(1, 1, 1, 0.5)]`, `text-[hsla(1, 1%, 1%, 0.5)]`
23+
if (value.startsWith(`[#`) || value.startsWith(`[rgb`) || value.startsWith(`[hsl`)) {
2424
color = value.slice(1, -1);
2525
// arbitrary named colors: `bg-[lemonchiffon]`
2626
} else if (value.startsWith(`[`) && value.slice(1, -1).match(/^[a-z]{3,}$/)) {
@@ -78,11 +78,15 @@ export function colorOpacity(type: ColorStyleType, value: string): StyleIR | nul
7878
function addOpacity(color: string, opacity: number): string {
7979
if (color.startsWith(`#`)) {
8080
color = hexToRgba(color);
81-
} else if (color.startsWith(`rgb(`)) {
82-
color = color.replace(/^rgb\(/, `rgba(`).replace(/\)$/, `, 1)`);
81+
} else if (color.startsWith(`rgb(`) || color.startsWith(`hsl(`)) {
82+
color = color.replace(/^rgb\(/, `rgba(`).replace(/^hsl\(/, `hsla(`);
83+
if (color.includes(`,`)) {
84+
color = color.replace(/\)$/, `, 1)`);
85+
} else {
86+
color = color.replace(/\)$/, ` / 1)`);
87+
}
8388
}
84-
// @TODO: support hls/hlsa if anyone opens an issue...
85-
return color.replace(/, ?\d*\.?(\d+)\)$/, `, ${opacity})`);
89+
return color.replace(/ ?\d*\.?(\d+)\)$/, ` ${opacity})`);
8690
}
8791

8892
export function removeOpacityHelpers(style: Style): void {

0 commit comments

Comments
 (0)