1/** 2 * Copyright (c) Meta Platforms, Inc. and affiliates. 3 * 4 * This source code is licensed under the MIT license found in the 5 * LICENSE file in the root directory of this source tree. 6 * 7 * @format 8 */ 9 10import {ImageStyle, TextStyle, ViewStyle} from './StyleSheetTypes'; 11 12export interface StyleSheetProperties { 13 hairlineWidth: number; 14 flatten<T extends string>(style: T): T; 15} 16 17type Falsy = undefined | null | false; 18interface RecursiveArray<T> 19 extends Array<T | ReadonlyArray<T> | RecursiveArray<T>> {} 20/** Keep a brand of 'T' so that calls to `StyleSheet.flatten` can take `RegisteredStyle<T>` and return `T`. */ 21type RegisteredStyle<T> = number & {__registeredStyleBrand: T}; 22export type StyleProp<T> = 23 | T 24 | RegisteredStyle<T> 25 | RecursiveArray<T | RegisteredStyle<T> | Falsy> 26 | Falsy; 27 28type OpaqueColorValue = symbol & {__TYPE__: 'Color'}; 29export type ColorValue = string | OpaqueColorValue; 30 31export namespace StyleSheet { 32 type NamedStyles<T> = {[P in keyof T]: ViewStyle | TextStyle | ImageStyle}; 33 34 /** 35 * Creates a StyleSheet style reference from the given object. 36 */ 37 export function create<T extends NamedStyles<T> | NamedStyles<any>>( 38 styles: T | NamedStyles<T>, 39 ): T; 40 41 /** 42 * Flattens an array of style objects, into one aggregated style object. 43 * Alternatively, this method can be used to lookup IDs, returned by 44 * StyleSheet.register. 45 * 46 * > **NOTE**: Exercise caution as abusing this can tax you in terms of 47 * > optimizations. 48 * > 49 * > IDs enable optimizations through the bridge and memory in general. Referring 50 * > to style objects directly will deprive you of these optimizations. 51 * 52 * Example: 53 * ``` 54 * const styles = StyleSheet.create({ 55 * listItem: { 56 * flex: 1, 57 * fontSize: 16, 58 * color: 'white' 59 * }, 60 * selectedListItem: { 61 * color: 'green' 62 * } 63 * }); 64 * 65 * StyleSheet.flatten([styles.listItem, styles.selectedListItem]) 66 * // returns { flex: 1, fontSize: 16, color: 'green' } 67 * ``` 68 * Alternative use: 69 * ``` 70 * StyleSheet.flatten(styles.listItem); 71 * // return { flex: 1, fontSize: 16, color: 'white' } 72 * // Simply styles.listItem would return its ID (number) 73 * ``` 74 * This method internally uses `StyleSheetRegistry.getStyleByID(style)` 75 * to resolve style objects represented by IDs. Thus, an array of style 76 * objects (instances of StyleSheet.create), are individually resolved to, 77 * their respective objects, merged as one and then returned. This also explains 78 * the alternative use. 79 */ 80 export function flatten<T>( 81 style?: StyleProp<T>, 82 ): T extends (infer U)[] ? U : T; 83 84 /** 85 * Combines two styles such that style2 will override any styles in style1. 86 * If either style is falsy, the other one is returned without allocating 87 * an array, saving allocations and maintaining reference equality for 88 * PureComponent checks. 89 */ 90 export function compose< 91 T extends ViewStyle | TextStyle | ImageStyle, 92 U extends T, 93 V extends T, 94 >( 95 style1: StyleProp<U> | Array<StyleProp<U>>, 96 style2: StyleProp<V> | Array<StyleProp<V>>, 97 ): StyleProp<T>; 98 99 /** 100 * WARNING: EXPERIMENTAL. Breaking changes will probably happen a lot and will 101 * not be reliably announced. The whole thing might be deleted, who knows? Use 102 * at your own risk. 103 * 104 * Sets a function to use to pre-process a style property value. This is used 105 * internally to process color and transform values. You should not use this 106 * unless you really know what you are doing and have exhausted other options. 107 */ 108 export function setStyleAttributePreprocessor( 109 property: string, 110 process: (nextProp: any) => any, 111 ): void; 112 113 /** 114 * This is defined as the width of a thin line on the platform. It can be 115 * used as the thickness of a border or division between two elements. 116 * Example: 117 * ``` 118 * { 119 * borderBottomColor: '#bbb', 120 * borderBottomWidth: StyleSheet.hairlineWidth 121 * } 122 * ``` 123 * 124 * This constant will always be a round number of pixels (so a line defined 125 * by it look crisp) and will try to match the standard width of a thin line 126 * on the underlying platform. However, you should not rely on it being a 127 * constant size, because on different platforms and screen densities its 128 * value may be calculated differently. 129 */ 130 export const hairlineWidth: number; 131 132 interface AbsoluteFillStyle { 133 position: 'absolute'; 134 left: 0; 135 right: 0; 136 top: 0; 137 bottom: 0; 138 } 139 140 /** 141 * Sometimes you may want `absoluteFill` but with a couple tweaks - `absoluteFillObject` can be 142 * used to create a customized entry in a `StyleSheet`, e.g.: 143 * 144 * const styles = StyleSheet.create({ 145 * wrapper: { 146 * ...StyleSheet.absoluteFillObject, 147 * top: 10, 148 * backgroundColor: 'transparent', 149 * }, 150 * }); 151 */ 152 export const absoluteFillObject: AbsoluteFillStyle; 153 154 /** 155 * A very common pattern is to create overlays with position absolute and zero positioning, 156 * so `absoluteFill` can be used for convenience and to reduce duplication of these repeated 157 * styles. 158 */ 159 export const absoluteFill: RegisteredStyle<AbsoluteFillStyle>; 160} 161