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