您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

functions.js 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /* @flow */
  2. import Platform from '../react/Platform';
  3. import { ColorPalette } from './components';
  4. declare type StyleSheet = Object;
  5. export type StyleType = StyleSheet | Array<StyleSheet>;
  6. /**
  7. * RegExp pattern for long HEX color format.
  8. */
  9. const HEX_LONG_COLOR_FORMAT
  10. = /^#([0-9A-F]{2,2})([0-9A-F]{2,2})([0-9A-F]{2,2})$/i;
  11. /**
  12. * RegExp pattern for short HEX color format.
  13. */
  14. const HEX_SHORT_COLOR_FORMAT
  15. = /^#([0-9A-F]{1,1})([0-9A-F]{1,1})([0-9A-F]{1,1})$/i;
  16. /**
  17. * RegExp pattern for RGB color format.
  18. */
  19. const RGB_COLOR_FORMAT = /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/i;
  20. /**
  21. * The list of the well-known style properties which may not be numbers on Web
  22. * but must be numbers on React Native.
  23. *
  24. * @private
  25. */
  26. const _WELL_KNOWN_NUMBER_PROPERTIES = [ 'height', 'width' ];
  27. /**
  28. * Combines the given 2 styles into a single one.
  29. *
  30. * @param {StyleType} a - An object or array of styles.
  31. * @param {StyleType} b - An object or array of styles.
  32. * @private
  33. * @returns {StyleType} - The merged styles.
  34. */
  35. export function combineStyles(a: StyleType, b: StyleType): StyleType {
  36. const result = [];
  37. if (a) {
  38. if (Array.isArray(a)) {
  39. result.push(...a);
  40. } else {
  41. result.push(a);
  42. }
  43. }
  44. if (b) {
  45. if (Array.isArray(b)) {
  46. result.push(...b);
  47. } else {
  48. result.push(b);
  49. }
  50. }
  51. return result;
  52. }
  53. /**
  54. * Create a style sheet using the provided style definitions.
  55. *
  56. * @param {StyleSheet} styles - A dictionary of named style definitions.
  57. * @param {StyleSheet} [overrides={}] - Optional set of additional (often
  58. * platform-dependent/specific) style definitions that will override the base
  59. * (often platform-independent) styles.
  60. * @returns {StyleSheet}
  61. */
  62. export function createStyleSheet(
  63. styles: StyleSheet, overrides: StyleSheet = {}): StyleSheet {
  64. const combinedStyles = {};
  65. for (const k of Object.keys(styles)) {
  66. combinedStyles[k]
  67. = _shimStyles({
  68. ...styles[k],
  69. ...overrides[k]
  70. });
  71. }
  72. return combinedStyles;
  73. }
  74. /**
  75. * Works around a bug in react-native or react-native-webrtc on Android which
  76. * causes Views overlaying RTCView to be clipped. Even though we (may) display
  77. * multiple RTCViews, it is enough to apply the fix only to a View with a
  78. * bounding rectangle containing all RTCviews and their overlaying Views.
  79. *
  80. * @param {StyleSheet} styles - An object which represents a stylesheet.
  81. * @public
  82. * @returns {StyleSheet}
  83. */
  84. export function fixAndroidViewClipping<T: StyleSheet>(styles: T): T {
  85. if (Platform.OS === 'android') {
  86. styles.borderColor = ColorPalette.appBackground;
  87. styles.borderWidth = 1;
  88. }
  89. return styles;
  90. }
  91. /**
  92. * Returns an rgba format of the provided color if it's in hex or rgb format.
  93. *
  94. * NOTE: The function will return the same color if it's not in one of those
  95. * two formats (e.g. 'white').
  96. *
  97. * @param {string} color - The string representation of the color in rgb or hex
  98. * format.
  99. * @param {number} alpha - The alpha value to apply.
  100. * @returns {string}
  101. */
  102. export function getRGBAFormat(color: string, alpha: number): string {
  103. let match = color.match(HEX_LONG_COLOR_FORMAT);
  104. if (match) {
  105. return `#${match[1]}${match[2]}${match[3]}${_getAlphaInHex(alpha)}`;
  106. }
  107. match = color.match(HEX_SHORT_COLOR_FORMAT);
  108. if (match) {
  109. return `#${match[1]}${match[1]}${match[2]}${match[2]}${match[3]}${
  110. match[3]}${_getAlphaInHex(alpha)}`;
  111. }
  112. match = color.match(RGB_COLOR_FORMAT);
  113. if (match) {
  114. return `rgba(${match[1]}, ${match[2]}, ${match[3]}, ${alpha})`;
  115. }
  116. return color;
  117. }
  118. /**
  119. * Converts an [0..1] alpha value into HEX.
  120. *
  121. * @param {number} alpha - The alpha value to convert.
  122. * @returns {string}
  123. */
  124. function _getAlphaInHex(alpha: number): string {
  125. return Number(Math.round(255 * alpha)).toString(16)
  126. .padStart(2, '0');
  127. }
  128. /**
  129. * Shims style properties to work correctly on native. Allows us to minimize the
  130. * number of style declarations that need to be set or overridden for specific
  131. * platforms.
  132. *
  133. * @param {StyleSheet} styles - An object which represents a stylesheet.
  134. * @private
  135. * @returns {StyleSheet}
  136. */
  137. function _shimStyles<T: StyleSheet>(styles: T): T {
  138. // Certain style properties may not be numbers on Web but must be numbers on
  139. // React Native. For example, height and width may be expressed in percent
  140. // on Web but React Native will not understand them and we will get errors
  141. // (at least during development). Convert such well-known properties to
  142. // numbers if possible; otherwise, remove them to avoid runtime errors.
  143. for (const k of _WELL_KNOWN_NUMBER_PROPERTIES) {
  144. const v = styles[k];
  145. const typeofV = typeof v;
  146. if (typeofV !== 'undefined' && typeofV !== 'number') {
  147. const numberV = Number(v);
  148. if (Number.isNaN(numberV)) {
  149. delete styles[k];
  150. } else {
  151. styles[k] = numberV;
  152. }
  153. }
  154. }
  155. return styles;
  156. }