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
6 changes: 3 additions & 3 deletions packages/uniwind/src/bundler/css-compiler/compileNativeCSS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@ export const compileNativeCSS = (bundlerConfig: UniwindBundlerConfig, tailwindCS
)
const vars = serializeJSObject(
Processor.vars,
(key, value) => `get "${key}"() { return ${value} }`,
(key, value) => `"${key}": vars => ${value}`,
)
const scopedVars = Object.fromEntries(
Object.entries(Processor.scopedVars)
.map(([scopedVarsName, scopedVars]) => [
scopedVarsName,
serializeJSObject(scopedVars, (key, value) => `get "${key}"() { return ${value} }`),
serializeJSObject(scopedVars, (key, value) => `"${key}": vars => ${value}`),
]),
)
const serializedScopedVars = Object.entries(scopedVars)
.map(([scopedVarsName, scopedVars]) => `"${scopedVarsName}": ({ ${scopedVars} }),`)
.join('')
const currentColorVar = `get currentColor() { return rt.colorScheme === 'dark' ? '#ffffff' : '#000000' },`
const currentColorVar = `currentColor: () => rt.colorScheme === 'dark' ? '#ffffff' : '#000000',`

return [
'({',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import type { StyleSheetTemplate } from './types'
import { toCamelCase } from './utils'

const extractVarsFromString = (value: string) => {
const thisIndexes = [...value.matchAll(/this\[/g)].map(m => m.index)
const varsIndexes = [...value.matchAll(/vars\[/g)].map(m => m.index)

return thisIndexes.map(index => {
return varsIndexes.map(index => {
const afterIndex = value.slice(index + 5)
const closingIndex = afterIndex.indexOf(']')
const varName = afterIndex.slice(0, closingIndex)
Expand Down Expand Up @@ -76,7 +76,7 @@ export const addMetaToStylesTemplate = (Processor: ProcessorBuilder, currentPlat

const entries = Object.entries(rest)
.flatMap(([property, value]) => Processor.RN.cssToRN(property, value))
.map(([property, value]) => [`"${property}"`, `function() { return ${serialize(value)} }`])
.map(([property, value]) => [`"${property}"`, `function(vars) { return ${serialize(value)} }`])

if (platform) {
const isTV = currentPlatform === Platform.AndroidTV || currentPlatform === Platform.AppleTV
Expand Down
2 changes: 1 addition & 1 deletion packages/uniwind/src/bundler/css-processor/color.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class Color {

try {
if (color.type === 'currentcolor') {
return 'this["currentColor"]'
return 'vars["currentColor"]?.(vars)'
}

if (color.type === 'rgb' || color.type === 'srgb') {
Expand Down
4 changes: 2 additions & 2 deletions packages/uniwind/src/bundler/css-processor/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ export class CSS {
}

if (declarationValue.value === 'currentcolor') {
return 'this["currentColor"]'
return 'vars["currentColor"]?.(vars)'
}

return declarationValue.value
Expand Down Expand Up @@ -212,7 +212,7 @@ export class CSS {
case 'pair':
return declarationValue.inside.type
case 'currentcolor':
return 'this["currentColor"]'
return 'vars["currentColor"]?.(vars)'
case 'calc':
return this.Processor.Functions.processCalc(declarationValue.value)
case 'min':
Expand Down
2 changes: 1 addition & 1 deletion packages/uniwind/src/bundler/css-processor/units.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class Units {
case 'rem':
return length.value * this.Processor.vars['--uniwind-em']
case 'em':
return `this[\`--uniwind-em\`] * ${length.value}`
return `vars["--uniwind-em"]?.(vars) * ${length.value}`
default:
this.logger.warn(`Unsupported unit - ${length.unit}`)

Expand Down
7 changes: 2 additions & 5 deletions packages/uniwind/src/bundler/css-processor/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,12 @@ export const smartSplit = (str: string, separator = ' ' as string | RegExp) => {
export const addMissingSpaces = (str: string) =>
pipe(str)(
x => x.trim(),
x => x.replace(/([^ {])this/g, '$1 this'),
x => x.replace(/\](?=\d)/g, '] '),
x => x.replace(/\](?=")/g, '] '),
x => x.replace(/\)(?=\S)/g, ') '),
x => x.replace(/\)(?=[^\s,])/g, ') '),
x => x.replace(/(?<!^)(?<!\s)"(?=\d)/g, '" '),
)

export const uniq = <T>(arr: Array<T>) => Array.from(new Set(arr))

export const isValidJSValue = (jsValueString: string) => {
try {
new Function(`const test = ${jsValueString}`)
Expand All @@ -67,7 +64,7 @@ export const shouldBeSerialized = (value: string) => {

return [
isNumber(value),
value.startsWith('this['),
value.startsWith('vars['),
value.startsWith('rt.'),
/[*/+-]/.test(value),
value.includes('"'),
Expand Down
2 changes: 1 addition & 1 deletion packages/uniwind/src/bundler/css-processor/var.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export class Var {
constructor(private readonly Processor: ProcessorBuilder) {}

processVar(variable: Variable): string {
const value = `this[\`${variable.name.ident}\`]`
const value = `vars[${JSON.stringify(variable.name.ident)}]?.(vars)`

if (!variable.fallback || variable.fallback.length === 0) {
return value
Expand Down
6 changes: 1 addition & 5 deletions packages/uniwind/src/core/config/config.native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,7 @@ class UniwindConfigBuilder extends UniwindConfigBuilderBase {
}

UniwindStore.vars[theme] ??= {}
Object.defineProperty(UniwindStore.vars[theme], varName, {
configurable: true,
enumerable: true,
get: getValue,
})
UniwindStore.vars[theme][varName] = getValue
})

UniwindListener.notify([StyleDependency.Variables])
Expand Down
9 changes: 0 additions & 9 deletions packages/uniwind/src/core/native/native-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,6 @@ export function lightDark(this: UniwindRuntime, light: string, dark: string) {
return light
}

export const cloneWithAccessors = <T extends object>(obj: T) => {
const proto = Object.getPrototypeOf(obj)
const clone = Object.create(proto)

Object.defineProperties(clone, Object.getOwnPropertyDescriptors(obj))

return clone
}

export const parseColor = (type: string, color: string) => {
try {
const parsedColor = parse(`${type}(${color})`)
Expand Down
24 changes: 6 additions & 18 deletions packages/uniwind/src/core/native/parsers/textShadow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,16 @@ export const parseTextShadowMutation = (styles: Record<string, any>) => {
const [offsetX, offsetY, radius] = offsets

if (offsetX !== undefined && offsetY !== undefined) {
Object.defineProperty(styles, 'textShadowOffset', {
configurable: true,
enumerable: true,
value: {
width: Number(offsetX),
height: Number(offsetY),
},
})
styles.textShadowOffset = {
width: Number(offsetX),
height: Number(offsetY),
}
delete styles.textShadow
}

if (radius !== undefined) {
Object.defineProperty(styles, 'textShadowRadius', {
configurable: true,
enumerable: true,
value: Number(radius),
})
styles.textShadowRadius = Number(radius)
}

Object.defineProperty(styles, 'textShadowColor', {
configurable: true,
enumerable: true,
value: color,
})
styles.textShadowColor = color
}
6 changes: 1 addition & 5 deletions packages/uniwind/src/core/native/parsers/transforms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,6 @@ export const parseTransformsMutation = (styles: Record<string, any>) => {
}

if (transformsResult.length > 0) {
Object.defineProperty(styles, 'transform', {
configurable: true,
enumerable: true,
value: transformsResult,
})
styles.transform = transformsResult
}
}
77 changes: 22 additions & 55 deletions packages/uniwind/src/core/native/store.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Dimensions, Platform } from 'react-native'
import { Orientation, Platform as UniwindPlatform, StyleDependency, UNIWIND_PLATFORM_VARIABLES, UNIWIND_THEME_VARIABLES } from '../../common/consts'
import { UniwindListener } from '../listener'
import type { ComponentState, GenerateStyleSheetsCallback, RNStyle, Style, StyleSheets, ThemeName, UniwindContextType } from '../types'
import { cloneWithAccessors } from './native-utils'
import type { ComponentState, GenerateStyleSheetsCallback, RNStyle, Style, StyleSheets, ThemeName, UniwindContextType, Var, Vars } from '../types'
import { parseBoxShadow, parseFontVariant, parseTextShadowMutation, parseTransformsMutation, resolveGradient } from './parsers'
import { UniwindRuntime } from './runtime'

Expand All @@ -16,7 +15,7 @@ const emptyState: StylesResult = { styles: {}, dependencies: [], dependencySum:

class UniwindStoreBuilder {
runtime = UniwindRuntime
vars = {} as Record<ThemeName, Record<string, unknown>>
vars = {} as Record<ThemeName, Vars>
private stylesheet = {} as StyleSheets
private cache = {} as Record<ThemeName, Map<string, StylesResult>>

Expand Down Expand Up @@ -66,20 +65,20 @@ class UniwindStoreBuilder {
const platformVars = scopedVars[`${UNIWIND_PLATFORM_VARIABLES}${platform}`]

if (commonPlatformVars) {
Object.defineProperties(vars, Object.getOwnPropertyDescriptors(commonPlatformVars))
Object.assign(vars, commonPlatformVars)
}

if (platformVars) {
Object.defineProperties(vars, Object.getOwnPropertyDescriptors(platformVars))
Object.assign(vars, platformVars)
}

this.stylesheet = stylesheet
this.vars = Object.fromEntries(themes.map(theme => {
const clonedVars = cloneWithAccessors(vars)
const clonedVars = Object.create(vars) as Vars
const themeVars = scopedVars[`${UNIWIND_THEME_VARIABLES}${theme}`]

if (themeVars) {
Object.defineProperties(clonedVars, Object.getOwnPropertyDescriptors(themeVars))
Object.assign(clonedVars, themeVars)
}

return [theme, clonedVars]
Expand All @@ -97,7 +96,7 @@ class UniwindStoreBuilder {
state: ComponentState | undefined,
uniwindContext: UniwindContextType,
) {
const result = {} as Record<string, any>
const resultGetters = {} as Record<string, Var>
const theme = uniwindContext.scopedTheme ?? this.runtime.currentThemeName
// At this point we're sure that theme is correct
let vars = this.vars[theme]!
Expand Down Expand Up @@ -160,95 +159,63 @@ class UniwindStoreBuilder {
if (property[0] === '-') {
// Clone vars object if we are adding inline variables
if (vars === originalVars) {
vars = cloneWithAccessors(originalVars)
vars = Object.create(originalVars)
}

Object.defineProperty(vars, property, {
configurable: true,
enumerable: true,
get: valueGetter,
})
vars[property] = valueGetter
} else {
Object.defineProperty(result, property, {
configurable: true,
enumerable: true,
get: () => valueGetter.call(vars),
})
resultGetters[property] = valueGetter
}

bestBreakpoints.set(property, style)
}
}
}

const result = Object.fromEntries(
Object.entries(resultGetters).map(([property, valueGetter]) => [property, valueGetter(vars)]),
) as Record<string, any>

if (result.lineHeight !== undefined && result.lineHeight < 6) {
Object.defineProperty(result, 'lineHeight', {
value: result.fontSize * result.lineHeight,
configurable: true,
enumerable: true,
})
result.lineHeight *= result.fontSize
}

if (result.boxShadow !== undefined) {
Object.defineProperty(result, 'boxShadow', {
value: parseBoxShadow(result.boxShadow),
configurable: true,
enumerable: true,
})
result.boxShadow = parseBoxShadow(result.boxShadow)
}

if (result.visibility === 'hidden') {
Object.defineProperty(result, 'display', {
value: 'none',
configurable: true,
enumerable: true,
})
result.display = 'none'
}

if (
result.borderStyle !== undefined && result.borderColor === undefined
) {
Object.defineProperty(result, 'borderColor', {
value: '#000000',
configurable: true,
enumerable: true,
})
result.borderColor = '#000000'
}

if (
result.outlineStyle !== undefined && result.outlineColor === undefined
) {
Object.defineProperty(result, 'outlineColor', {
value: '#000000',
configurable: true,
enumerable: true,
})
result.outlineColor = '#000000'
}

if (result.fontVariant !== undefined) {
Object.defineProperty(result, 'fontVariant', {
value: parseFontVariant(result.fontVariant),
configurable: true,
enumerable: true,
})
result.fontVariant = parseFontVariant(result.fontVariant)
}

parseTransformsMutation(result)

if (result.experimental_backgroundImage !== undefined) {
Object.defineProperty(result, 'experimental_backgroundImage', {
value: resolveGradient(result.experimental_backgroundImage),
configurable: true,
enumerable: true,
})
result.experimental_backgroundImage = resolveGradient(result.experimental_backgroundImage)
}

if (result.textShadow !== undefined) {
parseTextShadowMutation(result)
}

return {
styles: { ...result } as RNStyle,
styles: result,
dependencies: Array.from(dependencies),
dependencySum,
hasDataAttributes,
Expand Down
9 changes: 6 additions & 3 deletions packages/uniwind/src/core/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ import type { ImageStyle, StyleProp, TextStyle, ViewStyle } from 'react-native'
import type { ColorScheme, Orientation, StyleDependency } from '../common/consts'
import type { UniwindContext } from './context'

export type Vars = Record<PropertyKey, Var>
export type Var = (vars: Vars) => unknown

export type Style = {
entries: Array<[string, () => unknown]>
entries: Array<[string, Var]>
minWidth: number
maxWidth: number
orientation: Orientation | null
Expand All @@ -26,8 +29,8 @@ export type StyleSheets = Record<string, Array<Style>>

export type GenerateStyleSheetsCallback = (rt: UniwindRuntime) => {
stylesheet: StyleSheets
vars: Record<string, unknown>
scopedVars: Partial<Record<string, Record<string, unknown>>>
vars: Vars
scopedVars: Partial<Record<string, Vars>>
}

export interface UniwindConfig {}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { UniwindRuntime, UniwindStore } from '../../core/native'
import type { UniwindContextType } from '../../core/types'

export const getVariableValue = (name: string, uniwindContext: UniwindContextType) =>
UniwindStore.vars[uniwindContext.scopedTheme ?? UniwindRuntime.currentThemeName]?.[name]
export const getVariableValue = (name: string, uniwindContext: UniwindContextType) => {
const vars = UniwindStore.vars[uniwindContext.scopedTheme ?? UniwindRuntime.currentThemeName]

return vars?.[name]?.(vars)
}
Loading