Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions packages/uniwind/specs/colors.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { describe, expect, test } from 'bun:test'
import { getStyleSheetsFromCandidates, injectMocks } from './utils'

describe('Converts tailwind colors to hex', () => {
injectMocks()

test('Tailwind built-in', async () => {
const className = 'bg-red-500 border-blue-500/50 text-black'

await getStyleSheetsFromCandidates(...className.split(' '))

const { UniwindStore } = await import('../src/core/native')
const styles = UniwindStore.getStyles(className).styles

expect(styles).toHaveProperty('backgroundColor', '#fb2c36')
expect(styles).toHaveProperty('borderColor', '#2b7fff80')
expect(styles).toHaveProperty('color', '#000000')
})

test('Custom colors', async () => {
const className = 'bg-[#ff0000] text-[#ff000080]'

await getStyleSheetsFromCandidates(...className.split(' '))

const { UniwindStore } = await import('../src/core/native')
const styles = UniwindStore.getStyles(className).styles

expect(styles).toHaveProperty('backgroundColor', '#ff0000')
expect(styles).toHaveProperty('color', '#ff000080')
})
})
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, test } from 'bun:test'
import { getStyleSheetsFromCandidates, injectMocks } from '../utils'
import { getStyleSheetsFromCandidates, injectMocks } from './utils'

describe('Converts tailwind linear gradients', () => {
injectMocks()
Expand All @@ -9,7 +9,7 @@ describe('Converts tailwind linear gradients', () => {

await getStyleSheetsFromCandidates(...className.split(' '))

const { UniwindStore } = await import('../../src/core/native')
const { UniwindStore } = await import('../src/core/native')
const styles = UniwindStore.getStyles(className).styles

expect(styles).toEqual({
Expand Down Expand Up @@ -41,7 +41,7 @@ describe('Converts tailwind linear gradients', () => {

await getStyleSheetsFromCandidates(...className.split(' '))

const { UniwindStore } = await import('../../src/core/native')
const { UniwindStore } = await import('../src/core/native')
const styles = UniwindStore.getStyles(className).styles

expect(styles).toEqual({
Expand Down Expand Up @@ -79,7 +79,7 @@ describe('Converts tailwind linear gradients', () => {

await getStyleSheetsFromCandidates(...className.split(' '))

const { UniwindStore } = await import('../../src/core/native')
const { UniwindStore } = await import('../src/core/native')
const styles = UniwindStore.getStyles(className).styles

expect(styles).toEqual({
Expand Down Expand Up @@ -111,7 +111,7 @@ describe('Converts tailwind linear gradients', () => {

await getStyleSheetsFromCandidates(...className.split(' '))

const { UniwindStore } = await import('../../src/core/native')
const { UniwindStore } = await import('../src/core/native')
const styles = UniwindStore.getStyles(className).styles

expect(styles).toEqual({
Expand Down
40 changes: 0 additions & 40 deletions packages/uniwind/specs/parser/colors.test.ts

This file was deleted.

46 changes: 0 additions & 46 deletions packages/uniwind/specs/parser/spacing.test.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, test } from 'bun:test'
import { getStyleSheetsFromCandidates, injectMocks } from '../utils'
import { getStyleSheetsFromCandidates, injectMocks } from './utils'

describe('Converts tailwind shadow system', () => {
injectMocks()
Expand All @@ -9,7 +9,7 @@ describe('Converts tailwind shadow system', () => {
'shadow-xl',
)

const { UniwindStore } = await import('../../src/core/native')
const { UniwindStore } = await import('../src/core/native')
const styles = UniwindStore.getStyles('shadow-xl').styles

expect(styles).toEqual({
Expand All @@ -26,7 +26,7 @@ describe('Converts tailwind shadow system', () => {

await getStyleSheetsFromCandidates(...candidates)

const { UniwindStore } = await import('../../src/core/native')
const { UniwindStore } = await import('../src/core/native')
const styles = UniwindStore.getStyles(candidates.join(' ')).styles

expect(styles).toEqual({
Expand All @@ -38,7 +38,7 @@ describe('Converts tailwind shadow system', () => {
test('Ring', async () => {
await getStyleSheetsFromCandidates('ring-2')

const { UniwindStore } = await import('../../src/core/native')
const { UniwindStore } = await import('../src/core/native')
const styles = UniwindStore.getStyles('ring-2').styles

expect(styles).toEqual({
Expand All @@ -56,7 +56,7 @@ describe('Converts tailwind shadow system', () => {

await getStyleSheetsFromCandidates(...candidates)

const { UniwindStore } = await import('../../src/core/native')
const { UniwindStore } = await import('../src/core/native')
const styles = UniwindStore.getStyles(candidates.join(' ')).styles

expect(styles).toEqual({
Expand All @@ -72,7 +72,7 @@ describe('Converts tailwind shadow system', () => {
]
await getStyleSheetsFromCandidates(...candidates)

const { UniwindStore } = await import('../../src/core/native')
const { UniwindStore } = await import('../src/core/native')
const styles = UniwindStore.getStyles(candidates.join(' ')).styles

expect(styles).toEqual({
Expand Down
46 changes: 46 additions & 0 deletions packages/uniwind/specs/spacing.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { describe, expect, test } from 'bun:test'
import { UniwindRuntimeMock } from './mocks'
import { getStyleSheetsFromCandidates, injectMocks, twSize } from './utils'

describe('Converts tailwind spacings', () => {
injectMocks()

test('Built in', async () => {
const className = 'px-4 m-2'

await getStyleSheetsFromCandidates(...className.split(' '))

const { UniwindStore } = await import('../src/core/native')
const styles = UniwindStore.getStyles(className).styles

expect(styles).toHaveProperty('paddingHorizontal', twSize(4))
expect(styles).toHaveProperty('margin', twSize(2))
})

test.only('Custom', async () => {
const className = 'px-[16px] m-[8px]'

await getStyleSheetsFromCandidates(...className.split(' '))

const { UniwindStore } = await import('../src/core/native')
const styles = UniwindStore.getStyles(className).styles

expect(styles).toHaveProperty('paddingHorizontalStart', 16)
expect(styles).toHaveProperty('paddingHorizontalEnd', 16)
expect(styles).toHaveProperty('marginTop', 8)
expect(styles).toHaveProperty('marginBottom', 8)
expect(styles).toHaveProperty('marginLeft', 8)
expect(styles).toHaveProperty('marginRight', 8)
})

test('Safe area', async () => {
const className = 'pt-safe'

await getStyleSheetsFromCandidates(...className.split(' '))

const { UniwindStore } = await import('../src/core/native')
const styles = UniwindStore.getStyles(className).styles

expect(styles).toHaveProperty('paddingTop', UniwindRuntimeMock.insets.top)
})
})
16 changes: 1 addition & 15 deletions packages/uniwind/specs/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { mock } from 'bun:test'
import { readFileSync } from 'fs'
import { RNStyle } from '../src/core/types'
import { compileVirtual } from '../src/metro/compileVirtual'
import { Platform } from '../src/metro/types'
import { UniwindRuntimeMock } from './mocks'
Expand All @@ -15,6 +14,7 @@ export const getStyleSheetsFromCandidates = async <T extends string>(...candidat
candidates,
platform: Platform.iOS,
cssPath: testCSSPath,
polyfills: {},
themes: ['light', 'dark'],
})

Expand All @@ -23,20 +23,6 @@ export const getStyleSheetsFromCandidates = async <T extends string>(...candidat
return globalThis.__uniwind__computeStylesheet(UniwindRuntimeMock)
}

export const getStylesFromCandidates = async <T extends string>(...candidates: Array<T>) => {
const stylesheets = await getStyleSheetsFromCandidates(...candidates)

return Object.fromEntries(
Object.entries(stylesheets).map(([key, value]) => {
if (!Array.isArray(value)) {
return null
}

return [key, value.map(entry => Object.fromEntries(entry.entries))]
}).filter(Boolean),
) as Record<T, Array<RNStyle>>
}

export const twSize = (size: number) => size * 4

export const injectMocks = () => {
Expand Down
14 changes: 10 additions & 4 deletions packages/uniwind/src/components/native/useStyle.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
import { useEffect, useMemo, useReducer } from 'react'
import { UniwindStore } from '../../core/native'
import { ComponentState } from '../../core/types'
import { ComponentState, RNStyle } from '../../core/types'
import { StyleDependency } from '../../types'

const emptyState = { styles: {} as RNStyle, dependencies: [] as Array<StyleDependency> }

export const useStyle = (className?: string, state?: ComponentState) => {
const [_, rerender] = useReducer(() => ({}), {})
const styleState = useMemo(
() => UniwindStore.getStyles(className, state),
() => className ? UniwindStore.getStyles(className, state) : emptyState,
[className, _, state?.isDisabled, state?.isFocused, state?.isPressed],
)

useEffect(() => {
const dispose = UniwindStore.subscribe(() => rerender(), styleState.dependencies)
if (styleState.dependencies.length > 0) {
const dispose = UniwindStore.subscribe(() => rerender(), styleState.dependencies)

return dispose
return dispose
}
}, [styleState])

return styleState.styles
Expand Down
34 changes: 21 additions & 13 deletions packages/uniwind/src/core/native/parsers/transforms.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable max-depth */
const transforms = [
'translateX',
'translateY',
Expand All @@ -18,28 +19,35 @@ export const parseTransformsMutation = (styles: Record<string, any>) => {
const transformTokens = typeof styles.transform === 'string'
? styles.transform
.split(' ')
.filter(token => token !== 'undefined')
.filter(token => token === 'undefined')
: []
const transformsResult = transforms.reduce<Array<Record<string, any>>>((acc, transform) => {
// Transforms inside transform - transform: rotate(45deg);
transformTokens
.filter(token => token.startsWith(transform))
.forEach(token => {

const transformsResult = []

for (const transform of transforms) {
if (transformTokens.length > 0) {
// Transforms inside transform - transform: rotate(45deg);
for (const token of transformTokens) {
if (!token.startsWith(transform)) {
continue
}

const transformValue = token.slice(transform.length + 1, -1)

acc.push({ [transform]: transformValue })
})
transformsResult.push({ [transform]: transformValue })
}
}

// Transforms outside of transform - { rotate: '45deg' }
if (styles[transform] !== undefined) {
acc.push({ [transform]: styles[transform] })
transformsResult.push({ [transform]: styles[transform] })
delete styles[transform]
}

return acc
}, [])
}

if (transformsResult.length > 0) {
styles.transform = transformsResult
Object.defineProperty(styles, 'transform', {
value: transformsResult,
})
}
}
Loading