Skip to content

Commit 3091d35

Browse files
authored
feat: inline rtl support (#574)
* feat: inline rtl support * chore: exclude inherit dir
1 parent 86e0048 commit 3091d35

4 files changed

Lines changed: 88 additions & 3 deletions

File tree

packages/uniwind/src/bundler/css-processor/processor.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { UNIWIND_PLATFORM_VARIABLES, UNIWIND_THEME_VARIABLES } from '@/common/consts'
2+
import { isDefined } from '@/common/utils'
23
import type { Declaration, MediaQuery, Rule } from 'lightningcss'
34
import { transform } from 'lightningcss'
45
import type { UniwindBundlerConfig } from '../config'
@@ -195,7 +196,7 @@ export class ProcessorBuilder {
195196
}
196197
})
197198

198-
if ([rtl, theme, active, focus, disabled, dataAttributes].some(Boolean)) {
199+
if ([rtl, theme, active, focus, disabled, dataAttributes].some(isDefined)) {
199200
this.declarationConfig.rtl ??= rtl
200201
this.declarationConfig.theme ??= theme
201202
this.declarationConfig.active ??= active

packages/uniwind/src/core/native/store.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { Dimensions, Platform } from 'react-native'
1+
import type { ViewStyle } from 'react-native'
2+
import { Dimensions, Platform, StyleSheet } from 'react-native'
23
import { Orientation, Platform as UniwindPlatform, StyleDependency, UNIWIND_PLATFORM_VARIABLES, UNIWIND_THEME_VARIABLES } from '../../common/consts'
34
import { UniwindListener } from '../listener'
45
import type { ComponentState, GenerateStyleSheetsCallback, RNStyle, Style, StyleSheets, ThemeName, UniwindContextType, Var, Vars } from '../types'
@@ -133,7 +134,7 @@ class UniwindStoreBuilder {
133134
|| style.maxWidth < this.runtime.screen.width
134135
|| (style.theme !== null && theme !== style.theme)
135136
|| (style.orientation !== null && this.runtime.orientation !== style.orientation)
136-
|| (style.rtl !== null && this.runtime.rtl !== style.rtl)
137+
|| (style.rtl !== null && !this.validateDir(style.rtl, componentProps))
137138
|| (style.active !== null && state?.isPressed !== style.active)
138139
|| (style.focus !== null && state?.isFocused !== style.focus)
139140
|| (style.disabled !== null && state?.isDisabled !== style.disabled)
@@ -250,6 +251,18 @@ class UniwindStoreBuilder {
250251
return true
251252
}
252253

254+
private validateDir(rtl: boolean, props: Record<string, any> = {}) {
255+
const inlineDir = 'style' in props ? (StyleSheet.flatten(props.style) as ViewStyle)?.direction : undefined
256+
257+
if (inlineDir !== undefined && inlineDir !== 'inherit') {
258+
const isInlineRtl = inlineDir === 'rtl'
259+
260+
return isInlineRtl === rtl
261+
}
262+
263+
return rtl === this.runtime.rtl
264+
}
265+
253266
private getCurrentPlatform() {
254267
const platform = Platform.OS
255268

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import * as React from 'react'
2+
import { I18nManager } from 'react-native'
3+
import View from '../../../src/components/native/View'
4+
import { UniwindStore } from '../../../src/core/native'
5+
import { TW_RED_500 } from '../../consts'
6+
import { renderUniwind } from '../utils'
7+
8+
describe('Dir', () => {
9+
const mockRTL = (isRTL: boolean) => {
10+
jest.replaceProperty(I18nManager, 'isRTL', isRTL)
11+
UniwindStore.runtime.rtl = I18nManager.isRTL
12+
}
13+
14+
afterEach(() => {
15+
jest.restoreAllMocks()
16+
})
17+
18+
test('RTL global', () => {
19+
mockRTL(true)
20+
21+
const { getStylesFromId } = renderUniwind(
22+
<React.Fragment>
23+
<View className="rtl:bg-red-500 bg-blue-500" testID="rtl-red" />
24+
</React.Fragment>,
25+
)
26+
27+
expect(getStylesFromId('rtl-red').backgroundColor).toBe(TW_RED_500)
28+
})
29+
30+
test('LTR global', () => {
31+
mockRTL(false)
32+
33+
const { getStylesFromId } = renderUniwind(
34+
<React.Fragment>
35+
<View className="ltr:bg-red-500 bg-blue-500" testID="ltr-red" />
36+
</React.Fragment>,
37+
)
38+
39+
expect(getStylesFromId('ltr-red').backgroundColor).toBe(TW_RED_500)
40+
})
41+
42+
test('inline RTL', () => {
43+
mockRTL(false)
44+
45+
const { getStylesFromId } = renderUniwind(
46+
<React.Fragment>
47+
<View className="rtl:bg-red-500 bg-blue-500" testID="rtl-red" style={{ direction: 'rtl' }} />
48+
</React.Fragment>,
49+
)
50+
51+
expect(getStylesFromId('rtl-red').backgroundColor).toBe(TW_RED_500)
52+
})
53+
54+
test('inline LTR', () => {
55+
mockRTL(true)
56+
57+
const { getStylesFromId } = renderUniwind(
58+
<React.Fragment>
59+
<View className="ltr:bg-red-500 bg-blue-500" testID="ltr-red" style={{ direction: 'ltr' }} />
60+
</React.Fragment>,
61+
)
62+
63+
expect(getStylesFromId('ltr-red').backgroundColor).toBe(TW_RED_500)
64+
})
65+
})

packages/uniwind/tests/setup.native.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,9 @@ beforeAll(async () => {
2727
`,
2828
)
2929
})
30+
31+
afterEach(() => {
32+
const { UniwindStore } = require('../src/core/native')
33+
34+
UniwindStore.cache = Object.fromEntries(Object.keys(UniwindStore.cache).map(theme => [theme, new Map()]))
35+
})

0 commit comments

Comments
 (0)