diff --git a/packages/uniwind/src/core/native/native-utils.ts b/packages/uniwind/src/core/native/native-utils.ts index 661b94c4..52aaba78 100644 --- a/packages/uniwind/src/core/native/native-utils.ts +++ b/packages/uniwind/src/core/native/native-utils.ts @@ -26,3 +26,12 @@ export function lightDark(this: UniwindRuntime, light: string, dark: string) { return light } + +export const cloneWithAccessors = (obj: T) => { + const proto = Object.getPrototypeOf(obj) + const clone = Object.create(proto) + + Object.defineProperties(clone, Object.getOwnPropertyDescriptors(obj)) + + return clone +} diff --git a/packages/uniwind/src/core/native/store.ts b/packages/uniwind/src/core/native/store.ts index 88e55b06..9d0cbc51 100644 --- a/packages/uniwind/src/core/native/store.ts +++ b/packages/uniwind/src/core/native/store.ts @@ -2,6 +2,7 @@ import { Dimensions, Platform } from 'react-native' import { Orientation, StyleDependency } from '../../types' import { ComponentState, GenerateStyleSheetsCallback, RNStyle, Style, StyleSheets } from '../types' +import { cloneWithAccessors } from './native-utils' import { parseBoxShadow, parseFontVariant, parseTransformsMutation, resolveGradient } from './parsers' import { UniwindRuntime } from './runtime' @@ -11,8 +12,10 @@ type StylesResult = { } class UniwindStoreBuilder { - stylesheets = {} as StyleSheets - listeners = { + runtime = UniwindRuntime + private stylesheet = {} as StyleSheets + private vars = {} as Record + private listeners = { [StyleDependency.ColorScheme]: new Set<() => void>(), [StyleDependency.Theme]: new Set<() => void>(), [StyleDependency.Dimensions]: new Set<() => void>(), @@ -21,8 +24,8 @@ class UniwindStoreBuilder { [StyleDependency.FontScale]: new Set<() => void>(), [StyleDependency.Rtl]: new Set<() => void>(), } - runtime = UniwindRuntime - cache = new Map() + private cache = new Map() + private generateStyleSheetCallbackResult: ReturnType | null = null subscribe(onStoreChange: () => void, dependencies: Array) { dependencies.forEach(dep => { @@ -65,19 +68,28 @@ class UniwindStoreBuilder { } reinit = (generateStyleSheetCallback?: GenerateStyleSheetsCallback) => { - const styleSheet = generateStyleSheetCallback?.(this.runtime) ?? this.stylesheets - const themeVars = styleSheet[`__uniwind-theme-${this.runtime.currentThemeName}`] - const platformVars = styleSheet[`__uniwind-platform-${Platform.OS}`] + const config = generateStyleSheetCallback?.(this.runtime) ?? this.generateStyleSheetCallbackResult + + if (!config) { + return + } + + const { scopedVars, stylesheet, vars } = config + + this.generateStyleSheetCallbackResult = config + this.stylesheet = stylesheet + this.vars = vars + + const themeVars = scopedVars[`__uniwind-theme-${this.runtime.currentThemeName}`] + const platformVars = scopedVars[`__uniwind-platform-${Platform.OS}`] if (themeVars) { - Object.assign(styleSheet, themeVars) + Object.defineProperties(this.vars, Object.getOwnPropertyDescriptors(themeVars)) } if (platformVars) { - Object.assign(styleSheet, platformVars) + Object.defineProperties(this.vars, Object.getOwnPropertyDescriptors(platformVars)) } - - this.stylesheets = styleSheet } notifyListeners = (dependencies: Array) => { @@ -86,15 +98,16 @@ class UniwindStoreBuilder { private resolveStyles(classNames: string, state?: ComponentState) { const result = {} as Record + let vars = this.vars const dependencies = [] as Array const bestBreakpoints = new Map() for (const className of classNames.split(' ')) { - if (!(className in this.stylesheets)) { + if (!(className in this.stylesheet)) { continue } - for (const style of this.stylesheets[className] as Array