@react-native-ohos/react-native-unistyles
Version:
Level up your React Native StyleSheet
285 lines (248 loc) • 8.56 kB
text/typescript
import { ScreenOrientation, UnistylesError } from '../common'
import type { Color, UnistylesBridge, UnistylesPlugin } from '../types'
import type { UnistylesThemes } from '../global'
import type { UnistyleRegistry } from './UnistyleRegistry'
import { parseColor } from '../utils/parseColor'
/**
* Utility to interact with the Unistyles during runtime
*/
export class UnistylesRuntime {
constructor(private unistylesBridge: UnistylesBridge, private unistylesRegistry: UnistyleRegistry) {}
/**
* Get the mini runtime injected to creteStyleSheet
* @returns - The mini runtime
*/
public get miniRuntime() {
return {
contentSizeCategory: this.contentSizeCategory,
breakpoint: this.breakpoint,
screen: this.screen,
insets: this.insets,
statusBar: {
width: this.statusBar.width,
height: this.statusBar.height
},
navigationBar: {
width: this.navigationBar.width,
height: this.navigationBar.height
},
orientation: this.orientation,
pixelRatio: this.pixelRatio,
fontScale: this.fontScale,
hairlineWidth: this.hairlineWidth,
rtl: this.rtl
}
}
/**
* Get the current color scheme
* @returns - The current color scheme
*/
public get colorScheme() {
return this.unistylesBridge.colorScheme
}
/**
* Get the layout direction
* @returns - Boolean indicating if the layout direction is RTL
*/
public get rtl() {
return this.unistylesBridge.rtl
}
/**
* Get info about adaptive themes
* @returns - boolean indicating if the adaptive themes are enabled
*/
public get hasAdaptiveThemes() {
return this.unistylesBridge.hasAdaptiveThemes
}
/**
* Get the current theme name
* @returns - The current theme name
*/
public get themeName() {
return this.unistylesBridge.themeName
}
/**
* Get the current content size category
* @returns - The current content size category
*/
public get contentSizeCategory() {
return this.unistylesBridge.contentSizeCategory
}
/**
* Get the current breakpoint based on device size
* @returns - The current breakpoint
*/
public get breakpoint() {
return this.unistylesBridge.breakpoint
}
/**
* Get registered breakpoints with UnitylesRegistry
* @returns - The registered breakpoints
*/
public get breakpoints() {
return this.unistylesRegistry.breakpoints
}
/**
* Get the names of currently enabled plugins
* @deprecated - Plugins will be removed in the next major release
* @returns - The names of currently enabled plugins
*/
public get enabledPlugins() {
return this.unistylesBridge.enabledPlugins
}
/**
* Get the screen size
* @returns - The screen size { width, height }
*/
public get screen() {
return {
width: this.unistylesBridge.screenWidth,
height: this.unistylesBridge.screenHeight
}
}
/**
* Get the safe area insets
* @returns - The safe area insets { top, bottom, left, right }
*/
public get insets() {
return this.unistylesBridge.insets
}
/**
* Get the status bar info
* @returns - The status bar api { width, height, setColor, setHidden }
*/
public get statusBar() {
return {
width: this.unistylesBridge.statusBar.width,
height: this.unistylesBridge.statusBar.height,
setColor: (color?: Color, alpha?: number) => {
const [parsedColor, parsedAlpha] = parseColor(color, alpha)
this.unistylesBridge.statusBar.setColor(parsedColor, parsedAlpha)
},
setHidden: (hidden: boolean) => this.unistylesBridge.statusBar.setHidden(hidden)
}
}
/**
* Get the navigation bar info (Android)
* @returns - The navigation bar api { width, height, setColor, setHidden }
*/
public get navigationBar() {
return {
width: this.unistylesBridge.navigationBar.width,
height: this.unistylesBridge.navigationBar.height,
setColor: (color?: Color, alpha?: number) => {
const [parsedColor, parsedAlpha] = parseColor(color, alpha)
this.unistylesBridge.navigationBar.setColor(parsedColor, parsedAlpha)
},
setHidden: (hidden: boolean) => this.unistylesBridge.navigationBar.setHidden(hidden)
}
}
/**
* Get the screen orientation
* @returns - The screen orientation
*/
public get orientation() {
const { width, height } = this.screen
if (width > height) {
return ScreenOrientation.Landscape
}
return ScreenOrientation.Portrait
}
/**
* Get the pixel ratio
* @returns - The pixel ratio
*/
public get pixelRatio() {
return this.unistylesBridge.pixelRatio
}
/**
* Get the font scale
* @returns - The font scale
*/
public get fontScale() {
return parseFloat(this.unistylesBridge.fontScale.toFixed(2))
}
/**
* Get the hairline width
* @returns - The thinnest width of the platform
*/
public get hairlineWidth() {
const pixelRatio = this.pixelRatio
const nearestPixel = Math.trunc(pixelRatio * 0.4) || 1
return nearestPixel / pixelRatio
}
/**
* Get theme by name
* @param themeName - The name of the theme to get or current theme if not specified
* @returns - The theme
*/
public getTheme(themeName?: keyof UnistylesThemes) {
if (!themeName) {
return this.unistylesRegistry.getTheme(this.themeName)
}
return this.unistylesRegistry.getTheme(themeName)
}
/**
* Get the immersive mode (both status bar and navigation bar hidden (Android))
* @param isEnabled
*/
public setImmersiveMode(isEnabled: boolean) {
return this.unistylesBridge.setImmersiveMode(isEnabled)
}
/**
* Set the root view background color
* @param color - The color to set
* @param alpha - Color alpha - default is 1
*/
public setRootViewBackgroundColor = (color?: Color, alpha?: number) => {
const [parsedColor, parsedAlpha] = parseColor(color, alpha)
this.unistylesBridge.setRootViewBackgroundColor(parsedColor, parsedAlpha)
}
/**
* Switch to a different theme
* @param name - The name of the theme to switch to
* @returns - boolean indicating if the theme was switched
*/
public setTheme = (name: keyof UnistylesThemes) => {
if (name === this.themeName) {
return
}
if (this.unistylesRegistry.hasTheme(name)) {
this.unistylesBridge.useTheme(name)
return true
}
throw new Error(UnistylesError.ThemeNotRegistered)
}
/**
* Update the theme at runtime
* If current theme is updated, the changes will be applied immediately
* @param name - The name of the theme to update
* @param updater - Function that receives the current theme and expect modified theme to be returned
*/
public updateTheme = (name: keyof UnistylesThemes, updater: (theme: UnistylesThemes[keyof UnistylesThemes]) => UnistylesThemes[keyof UnistylesThemes]) => {
this.unistylesRegistry.updateTheme(name, updater(this.unistylesRegistry.getTheme(name)))
}
/**
* Enable or disable adaptive themes
* @param enable - boolean indicating if adaptive themes should be enabled
*/
public setAdaptiveThemes = (enable: boolean) => {
this.unistylesBridge.useAdaptiveThemes(enable)
}
/**
* Enable a plugin
* @deprecated - Plugins will be removed in the next major release
* @param plugin - Plugin that conforms to UnistylesPlugin interface
*/
public addPlugin = (plugin: UnistylesPlugin) => {
this.unistylesRegistry.addPlugin(plugin)
}
/**
* Disable a plugin
* @deprecated - Plugins will be removed in the next major release
* @param plugin - Plugin that conforms to UnistylesPlugin interface
*/
public removePlugin = (plugin: UnistylesPlugin) => {
this.unistylesRegistry.removePlugin(plugin)
}
}