@react-native-ohos/react-native-unistyles
Version:
Level up your React Native StyleSheet
131 lines (100 loc) • 4.34 kB
text/typescript
import type { UnistylesBridge, UnistylesConfig, UnistylesPlugin } from '../types'
import type { UnistylesBreakpoints, UnistylesThemes } from '../global'
import { isAndroid, isDev, isWeb, UnistylesError } from '../common'
import { cssMediaQueriesPlugin, normalizeWebStylesPlugin } from '../plugins'
export class UnistyleRegistry {
public config: UnistylesConfig = {}
public plugins: Array<UnistylesPlugin> = isWeb
? [normalizeWebStylesPlugin]
: []
public themeNames: Array<keyof UnistylesThemes> = []
public themes: UnistylesThemes = {} as UnistylesThemes
public breakpoints: UnistylesBreakpoints = {} as UnistylesBreakpoints
public sortedBreakpointPairs: Array<[keyof UnistylesBreakpoints, UnistylesBreakpoints[keyof UnistylesBreakpoints]]> = []
constructor(private unistylesBridge: UnistylesBridge) {}
public addThemes = (themes: UnistylesThemes) => {
this.themes = themes
const keys = Object.keys(themes) as Array<keyof UnistylesThemes>
this.unistylesBridge.themes = keys
this.themeNames = keys
return {
addBreakpoints: this.addBreakpoints,
addConfig: this.addConfig
}
}
public addBreakpoints = (breakpoints: UnistylesBreakpoints) => {
this.breakpoints = breakpoints
this.unistylesBridge.useBreakpoints(breakpoints)
this.sortedBreakpointPairs = this.unistylesBridge.sortedBreakpointPairs
return {
addThemes: this.addThemes,
addConfig: this.addConfig
}
}
public addConfig = (config: UnistylesConfig) => {
this.config = config
if (config.adaptiveThemes) {
this.unistylesBridge.useAdaptiveThemes(config.adaptiveThemes)
}
if (config.plugins) {
config.plugins.forEach(plugin => this.addPlugin(plugin, false))
}
if (config.initialTheme) {
this.unistylesBridge.useTheme(config.initialTheme)
}
if (config.experimentalCSSMediaQueries) {
this.plugins = [cssMediaQueriesPlugin].concat(this.plugins)
this.unistylesBridge.addPlugin(cssMediaQueriesPlugin.name, false)
}
if (isWeb && config.windowResizeDebounceTimeMs !== undefined) {
this.unistylesBridge.setWindowResizeDebounceTimeMs(config.windowResizeDebounceTimeMs)
}
if (isAndroid && config.disableAnimatedInsets) {
this.unistylesBridge.disableAnimatedInsets()
}
return {
addBreakpoints: this.addBreakpoints,
addThemes: this.addThemes
}
}
public getTheme = (forName: keyof UnistylesThemes) => {
if (this.themeNames.length === 0) {
return {} as UnistylesThemes[keyof UnistylesThemes]
}
if (this.hasTheme(forName)) {
return this.themes[forName]
}
if (this.unistylesBridge.themeName) {
throw new Error(UnistylesError.ThemeNotFound)
}
throw new Error(UnistylesError.ThemeNotSelected)
}
public addPlugin = (plugin: UnistylesPlugin, notify: boolean = true) => {
if (plugin.name.startsWith('__unistyles')) {
throw new Error(UnistylesError.InvalidPluginName)
}
const isAlreadyRegistered = this.plugins.some(({ name }) => name === plugin.name)
if (!isAlreadyRegistered) {
this.plugins = [plugin].concat(this.plugins)
this.unistylesBridge.addPlugin(plugin.name, notify)
return
}
if (!isDev) {
throw new Error(UnistylesError.DuplicatePluginName)
}
}
public removePlugin = (plugin: UnistylesPlugin) => {
if (plugin.name.startsWith('__unistyles')) {
throw new Error(UnistylesError.CantRemoveInternalPlugin)
}
this.plugins = this.plugins.filter(({ name }) => name !== plugin.name)
this.unistylesBridge.removePlugin(plugin.name)
}
public updateTheme = (name: keyof UnistylesThemes, theme: UnistylesThemes[keyof UnistylesThemes]) => {
this.themes[name] = theme
if (this.unistylesBridge.themeName === name) {
this.unistylesBridge.updateTheme(name)
}
}
public hasTheme = (name: keyof UnistylesThemes) => name in this.themes
}