diff --git a/CHANGELOG.md b/CHANGELOG.md index 10be84a2a0b..d8877a2e9bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## [`master`](https://github.com/elastic/eui/tree/master) - Reinstate ([#1353](https://github.com/elastic/eui/pull/1353)) `onBlur` action on `EuiComboBox` ([#1364](https://github.com/elastic/eui/pull/1364)) +- Convert roughly half of the services to TypeScript ([#1400](https://github.com/elastic/eui/pull/1400)) **Bug fixes** diff --git a/package.json b/package.json index 4fc0682f97d..9020e335ed0 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "url": "https://github.com/elastic/eui.git" }, "dependencies": { + "@types/numeral": "^0.0.25", "classnames": "^2.2.5", "core-js": "^2.5.1", "focus-trap-react": "^3.0.4", @@ -75,6 +76,7 @@ "@types/lodash": "^4.14.116", "@types/react": "^16.3.0", "@types/react-virtualized": "^9.18.6", + "@types/uuid": "^3.4.4", "autoprefixer": "^7.1.5", "babel-core": "7.0.0-bridge.0", "babel-eslint": "^8.0.1", diff --git a/src/components/table/index.d.ts b/src/components/table/index.d.ts index c0885816a3d..6cdb4313ac9 100644 --- a/src/components/table/index.d.ts +++ b/src/components/table/index.d.ts @@ -1,7 +1,7 @@ /// import { CommonProps, NoArgCallback } from '../common'; import { IconType } from '../icon'; -/// +import { HorizontalAlignment } from '../../services/alignment'; import { SFC, diff --git a/src/services/accessibility/accessible_click_keys.js b/src/services/accessibility/accessible_click_keys.ts similarity index 100% rename from src/services/accessibility/accessible_click_keys.js rename to src/services/accessibility/accessible_click_keys.ts diff --git a/src/services/accessibility/cascading_menu_key_codes.js b/src/services/accessibility/cascading_menu_key_codes.ts similarity index 100% rename from src/services/accessibility/cascading_menu_key_codes.js rename to src/services/accessibility/cascading_menu_key_codes.ts diff --git a/src/services/accessibility/combo_box_key_codes.js b/src/services/accessibility/combo_box_key_codes.ts similarity index 100% rename from src/services/accessibility/combo_box_key_codes.js rename to src/services/accessibility/combo_box_key_codes.ts diff --git a/src/services/accessibility/html_id_generator.test.js b/src/services/accessibility/html_id_generator.test.ts similarity index 100% rename from src/services/accessibility/html_id_generator.test.js rename to src/services/accessibility/html_id_generator.test.ts diff --git a/src/services/accessibility/html_id_generator.js b/src/services/accessibility/html_id_generator.ts similarity index 78% rename from src/services/accessibility/html_id_generator.js rename to src/services/accessibility/html_id_generator.ts index 3e5536d504b..21a8d80ac3b 100644 --- a/src/services/accessibility/html_id_generator.js +++ b/src/services/accessibility/html_id_generator.ts @@ -7,7 +7,7 @@ import uuid from 'uuid'; * specify it, it generates a random id prefix. If you specify a custom prefix * it should begin with an letter to be HTML4 compliant. */ -export function htmlIdGenerator(idPrefix) { +export function htmlIdGenerator(idPrefix?: string) { const prefix = idPrefix || `i${uuid.v1()}`; - return (suffix) => `${prefix}_${suffix || uuid.v1()}`; + return (suffix?: string) => `${prefix}_${suffix || uuid.v1()}`; } diff --git a/src/services/accessibility/index.d.ts b/src/services/accessibility/index.d.ts deleted file mode 100644 index 5e6fb3784a3..00000000000 --- a/src/services/accessibility/index.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare module '@elastic/eui' { - export const accessibleClickKeys: { [keyCode: number]: string }; - export const cascadingMenuKeyCodes: { [keyCodeName: string]: keyCodes }; - export const comboBoxKeyCodes: { [keyCodeName: string]: keyCodes }; - export const htmlIdGenerator: (prefix?: string) => (suffix?: string) => string; -} diff --git a/src/services/accessibility/index.js b/src/services/accessibility/index.ts similarity index 100% rename from src/services/accessibility/index.js rename to src/services/accessibility/index.ts diff --git a/src/services/alignment.d.ts b/src/services/alignment.d.ts deleted file mode 100644 index 21a40ab5426..00000000000 --- a/src/services/alignment.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -declare module '@elastic/eui' { - export type HorizontalAlignment = 'left' | 'right' | 'center'; -} diff --git a/src/services/alignment.js b/src/services/alignment.ts similarity index 65% rename from src/services/alignment.js rename to src/services/alignment.ts index 9aa465118f6..64947937028 100644 --- a/src/services/alignment.js +++ b/src/services/alignment.ts @@ -1,3 +1,5 @@ export const LEFT_ALIGNMENT = 'left'; export const RIGHT_ALIGNMENT = 'right'; export const CENTER_ALIGNMENT = 'center'; + +export type HorizontalAlignment = 'left' | 'right' | 'center'; diff --git a/src/services/browser/browser.js b/src/services/browser/browser.js deleted file mode 100644 index 984b3b9fd0c..00000000000 --- a/src/services/browser/browser.js +++ /dev/null @@ -1,7 +0,0 @@ -export const Browser = Object.freeze({ - - isEventSupported: (name, element) => { - return `on${name}` in element; - } - -}); diff --git a/src/services/browser/browser.ts b/src/services/browser/browser.ts new file mode 100644 index 00000000000..3e058050533 --- /dev/null +++ b/src/services/browser/browser.ts @@ -0,0 +1,11 @@ +interface IBrowser { + isEventSupported: (name: string, element: EventTarget) => boolean; +} + +const BrowserImpl: IBrowser = { + isEventSupported: (name, element): boolean => { + return `on${name}` in element; + }, +}; + +export const Browser = Object.freeze(BrowserImpl); diff --git a/src/services/browser/index.js b/src/services/browser/index.ts similarity index 100% rename from src/services/browser/index.js rename to src/services/browser/index.ts diff --git a/src/services/color/color_palette.test.ts b/src/services/color/color_palette.test.ts new file mode 100644 index 00000000000..ccee976eb99 --- /dev/null +++ b/src/services/color/color_palette.test.ts @@ -0,0 +1,31 @@ +import { colorPalette} from './color_palette'; + +describe('colorPalette', () => { + it('should generate the expected palette', () => { + const actualPalette = colorPalette('#FFFF6D', '#1EA593'); + expect(actualPalette).toEqual([ + '#FFFF6D', + '#E6F571', + '#CDEB75', + '#B4E17A', + '#9BD77E', + '#82CD82', + '#69C386', + '#50B98B', + '#37AF8F', + '#1EA593', + ]); + }); + + it('should generate a palette with the specified spread', () => { + const actualPalette = colorPalette('#FFFF6D', '#1EA593', 6); + expect(actualPalette).toEqual([ + '#FFFF6D', + '#D2ED75', + '#A5DB7C', + '#78C984', + '#4BB78B', + '#1EA593', + ]); + }); +}); diff --git a/src/services/color/color_palette.js b/src/services/color/color_palette.ts similarity index 50% rename from src/services/color/color_palette.js rename to src/services/color/color_palette.ts index 82cd10a626e..b686f9d980f 100644 --- a/src/services/color/color_palette.js +++ b/src/services/color/color_palette.ts @@ -1,11 +1,14 @@ +import { rgbDef } from './color_types'; +import { hexToRgb } from './hex_to_rgb'; + /** * Create the color object for manipulation by other functions */ class Color { - constructor(r, g, b) { - this.r = r; // Red value - this.g = g; // Green value - this.b = b; // Blue value + collection: rgbDef; + text: string; + + constructor(public r: number, public g: number, public b: number) { this.collection = [r, g, b]; this.text = createHex(this.collection); } @@ -15,21 +18,19 @@ class Color { * This function takes a color palette name and returns an array of hex color * codes for use in UI elements such as charts. * - * @param {string} hexStart The beginning hexidecimal color code - * @param {string} hexEnd The ending hexidecimal color code + * @param {string} hexStart The beginning hexadecimal color code + * @param {string} hexEnd The ending hexadecimal color code * @param {number} len The number of colors in the resulting array (default 10) - * @returns {Array} Returns an array of hexidecimal color codes + * @returns {Array} Returns an array of hexadecimal color codes */ -function colorPalette(hexStart, hexEnd, len = 10) { +export function colorPalette(hexStart: string, hexEnd: string, len: number = 10) { if (isHex(hexStart) && isHex(hexEnd)) { - const hex1 = formatHex(hexStart); // format to #RRGGBB - const hex2 = formatHex(hexEnd); // format to #RRGGBB - const colorArray = []; - const hexPalette = []; + const colorArray: Color[] = []; + const hexPalette: string[] = []; const count = len - 1; - const startHex = colorParse(hex1); // get RGB equivalent values as array - const endHex = colorParse(hex2); // get RGB equivalent values as array + const startHex = hexToRgb(hexStart); // get RGB equivalent values as array + const endHex = hexToRgb(hexEnd); // get RGB equivalent values as array colorArray[0] = new Color(startHex[0], startHex[1], startHex[2]); // create first color obj colorArray[count] = new Color(endHex[0], endHex[1], endHex[2]); // create last color obj const step = stepCalc(count, colorArray[0], colorArray[count]); // create array of step increments @@ -52,16 +53,16 @@ function colorPalette(hexStart, hexEnd, len = 10) { } /** - * Check if argument is a valid 3 or 6 character hexidecimal color code + * Check if argument is a valid 3 or 6 character hexadecimal color code */ -function isHex(value) { +function isHex(value: string): boolean { return /^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(value); } /** - * Calculate and construct the hexideciaml color code from RGB values + * Calculate and construct the hexadecimal color code from RGB values */ -function createHex(rgbValues) { +function createHex(rgbValues: rgbDef): string { let result = ''; let val = 0; let piece; @@ -69,52 +70,19 @@ function createHex(rgbValues) { for (let k = 0; k < 3; k++) { val = Math.round(rgbValues[k]); piece = val.toString(base); // Converts to radix 16 based value (0-9, A-F) - if (piece.length < 2) {piece = `0${piece}`;} + if (piece.length < 2) {piece = `0${piece}`; } result = result + piece; } - result = `#${result.toUpperCase()}`; // Return in #RRGGBB fomat + result = `#${result.toUpperCase()}`; // Return in #RRGGBB format return result; } /** - * Convert hexideciaml color into an array of RGB integer values - */ -function colorParse(color) { - const base = 16; - let col = color.toUpperCase().replace('#', ''); - - if (col.length === 3) { - const a = col.substr(0, 1); - const b = col.substr(1, 1); - const c = col.substr(2, 1); - col = a + a + b + b + c + c; - } - const num = [col.substr(0, 2), col.substr(2, 2), col.substr(4, 2)]; - const ret = [parseInt(num[0], base), parseInt(num[1], base), parseInt(num[2], base)]; - return(ret); -} - -/** - * Format hexideciaml inputs to #RRGGBB - */ -function formatHex(hex) { - let cleanHex = hex; - if (cleanHex.length === 3 || cleanHex.length === 6) { - cleanHex = `#${cleanHex}`; - } - if (cleanHex.length === 4) { - cleanHex = cleanHex.split(''); - cleanHex = cleanHex[0] + cleanHex[1] + cleanHex[1] + cleanHex[2] + cleanHex[2] + cleanHex[3] + cleanHex[3]; - } - return cleanHex; -} - -/** - * Calculate the step increment for each piece of the hexidecimal color code + * Calculate the step increment for each piece of the hexadecimal color code */ -function stepCalc(st, cStart, cEnd) { +function stepCalc(st: number, cStart: Color, cEnd: Color): rgbDef { const steps = st; - const step = [ + const step: rgbDef = [ (cEnd.r - cStart.r) / steps, // Calc step amount for red value (cEnd.g - cStart.g) / steps, // Calc step amount for green value (cEnd.b - cStart.b) / steps, // Calc step amount for blue value @@ -122,5 +90,3 @@ function stepCalc(st, cStart, cEnd) { return step; } - -export { colorPalette }; diff --git a/src/services/color/color_types.ts b/src/services/color/color_types.ts new file mode 100644 index 00000000000..151461f1ca8 --- /dev/null +++ b/src/services/color/color_types.ts @@ -0,0 +1 @@ +export type rgbDef = [number, number, number]; diff --git a/src/services/color/eui_palettes.js b/src/services/color/eui_palettes.js deleted file mode 100644 index d13597ccba4..00000000000 --- a/src/services/color/eui_palettes.js +++ /dev/null @@ -1,48 +0,0 @@ -export const palettes = { - euiPaletteColorBlind: { - colors: [ - '#1EA593', - '#2B70F7', - '#CE0060', - '#38007E', - '#FCA5D3', - '#F37020', - '#E49E29', - '#B0916F', - '#7B000B', - '#34130C', - ], - }, - euiPaletteForLightBackground: { - colors: [ - '#006BB4', - '#017D73', - '#F5A700', - '#BD271E', - '#DD0A73', - ] - }, - euiPaletteForDarkBackground: { - colors: [ - '#4DA1C0', - '#01B2A4', - '#C06C4C', - '#BF4D4D', - '#F5258C', - ] - }, - euiPaletteForStatus: { - colors: [ - '#58BA6D', - '#6ECE67', - '#A5E26A', - '#D2E26A', - '#EBDF61', - '#EBD361', - '#EBC461', - '#D99D4C', - '#D97E4C', - '#D75949', - ] - }, -}; diff --git a/src/services/color/eui_palettes.ts b/src/services/color/eui_palettes.ts new file mode 100644 index 00000000000..3f59e2101e8 --- /dev/null +++ b/src/services/color/eui_palettes.ts @@ -0,0 +1,60 @@ +interface EuiPalette { + colors: string[]; +} + +const euiPaletteColorBlind: EuiPalette = { + colors: [ + '#1EA593', + '#2B70F7', + '#CE0060', + '#38007E', + '#FCA5D3', + '#F37020', + '#E49E29', + '#B0916F', + '#7B000B', + '#34130C', + ], +}; + +const euiPaletteForLightBackground: EuiPalette = { + colors: [ + '#006BB4', + '#017D73', + '#F5A700', + '#BD271E', + '#DD0A73', + ], +}; + +const euiPaletteForDarkBackground: EuiPalette = { + colors: [ + '#4DA1C0', + '#01B2A4', + '#C06C4C', + '#BF4D4D', + '#F5258C', + ], +}; + +const euiPaletteForStatus: EuiPalette = { + colors: [ + '#58BA6D', + '#6ECE67', + '#A5E26A', + '#D2E26A', + '#EBDF61', + '#EBD361', + '#EBC461', + '#D99D4C', + '#D97E4C', + '#D75949', + ], +}; + +export const palettes = { + euiPaletteColorBlind, + euiPaletteForLightBackground, + euiPaletteForDarkBackground, + euiPaletteForStatus, +}; diff --git a/src/services/color/hex_to_rgb.js b/src/services/color/hex_to_rgb.js deleted file mode 100644 index af90c448fd9..00000000000 --- a/src/services/color/hex_to_rgb.js +++ /dev/null @@ -1,14 +0,0 @@ -// Modified from https://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb - -function hexToRgb(hex) { - // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") - const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; - hex = hex.replace(shorthandRegex, function (m, r, g, b) { - return r + r + g + g + b + b; - }); - - const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); - return [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)]; -} - -export { hexToRgb }; diff --git a/src/services/color/hex_to_rgb.test.ts b/src/services/color/hex_to_rgb.test.ts new file mode 100644 index 00000000000..413b9d70090 --- /dev/null +++ b/src/services/color/hex_to_rgb.test.ts @@ -0,0 +1,20 @@ +import { hexToRgb } from './hex_to_rgb'; + +describe('hexToRgb ', () => { + + it('should handle 3 digit codes without a hash prefix', () => { + expect(hexToRgb('0a8')).toEqual([0, 170, 136]); + }); + + it('should handle 3 digit codes with a hash prefix', () => { + expect(hexToRgb('#0a8')).toEqual([0, 170, 136]); + }); + + it('should handle 6 digit codes without a hash prefix', () => { + expect(hexToRgb('00aa88')).toEqual([0, 170, 136]); + }); + + it('should handle 6 digit codes with a hash prefix', () => { + expect(hexToRgb('#00aa88')).toEqual([0, 170, 136]); + }); +}); diff --git a/src/services/color/hex_to_rgb.ts b/src/services/color/hex_to_rgb.ts new file mode 100644 index 00000000000..1143b462fc2 --- /dev/null +++ b/src/services/color/hex_to_rgb.ts @@ -0,0 +1,13 @@ +// Convert hexadecimal color into an array of RGB integer values +// Modified from https://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb + +import { rgbDef } from './color_types'; + +export function hexToRgb(hex: string): rgbDef { + // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") + const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; + hex = hex.replace(shorthandRegex, (m, r1, g1, b1) => r1 + r1 + g1 + g1 + b1 + b1); + + const [, r, g, b ] = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)!; + return [parseInt(r, 16), parseInt(g, 16), parseInt(b, 16)]; +} diff --git a/src/services/color/index.d.ts b/src/services/color/index.d.ts deleted file mode 100644 index 658ef9ddf69..00000000000 --- a/src/services/color/index.d.ts +++ /dev/null @@ -1,16 +0,0 @@ - -declare module '@elastic/eui' { - export const VISUALIZATION_COLORS: string[]; - - export const DEFAULT_VISUALIZATION_COLOR: string; - - type rgbDef = [number, number, number]; - - export const hexToRbg: (hex: string) => rgbDef; - export const rgbToHex: (rgb: string) => string; - - export const isColorDark: (red: number, green: number, blue: number) => boolean; - - export const calculateLuminance: (red: number, green: number, blue: number) => number; - export const calculateContrast: (rgb1: rgbDef, rgb2: rgbDef) => number; -} diff --git a/src/services/color/index.js b/src/services/color/index.ts similarity index 100% rename from src/services/color/index.js rename to src/services/color/index.ts diff --git a/src/services/color/is_color_dark.test.js b/src/services/color/is_color_dark.test.ts similarity index 78% rename from src/services/color/is_color_dark.test.js rename to src/services/color/is_color_dark.test.ts index 1837d5fcad5..6346a257ae4 100644 --- a/src/services/color/is_color_dark.test.js +++ b/src/services/color/is_color_dark.test.ts @@ -8,7 +8,7 @@ describe('isColorDark', () => { [219, 19, 116], [73, 0, 146], [70, 26, 10], - [146, 0, 0] + [146, 0, 0], ]; const LIGHT_COLORS = [ @@ -18,18 +18,18 @@ describe('isColorDark', () => { [212, 157, 170], [255, 255, 255], [254, 182, 219], - [230, 194, 32] + [230, 194, 32], ]; DARK_COLORS.forEach(color => { it(`should return true for dark color rgb(${color.join(', ')})`, () => { - expect(isColorDark(...color)).toBe(true); + expect(isColorDark(color[0], color[1], color[2])).toBe(true); }); }); LIGHT_COLORS.forEach(color => { it(`should return false for light color rgb(${color.join(', ')})`, () => { - expect(isColorDark(...color)).toBe(false); + expect(isColorDark(color[0], color[1], color[2])).toBe(false); }); }); }); diff --git a/src/services/color/is_color_dark.js b/src/services/color/is_color_dark.ts similarity index 92% rename from src/services/color/is_color_dark.js rename to src/services/color/is_color_dark.ts index e4ecb5a8970..95cabf400a9 100644 --- a/src/services/color/is_color_dark.js +++ b/src/services/color/is_color_dark.ts @@ -12,12 +12,10 @@ * @param {number} blue The blue component in the range 0 to 255 * @returns {boolean} True if the color is dark, false otherwise. */ -function isColorDark(red, green, blue) { +export function isColorDark(red: number, green: number, blue: number): boolean { const [r, g, b] = [red, green, blue] .map(c => c / 255.0) .map(c => c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4); const luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b; return luminance <= 0.179; } - -export { isColorDark }; diff --git a/src/services/color/luminance_and_contrast.js b/src/services/color/luminance_and_contrast.ts similarity index 63% rename from src/services/color/luminance_and_contrast.js rename to src/services/color/luminance_and_contrast.ts index cefc7f5ea52..0b2164c8a07 100644 --- a/src/services/color/luminance_and_contrast.js +++ b/src/services/color/luminance_and_contrast.ts @@ -1,5 +1,7 @@ -function calculateLuminance(r, g, b) { - const a = [r, g, b].map(function (v) { +import { rgbDef } from './color_types'; + +export function calculateLuminance(r: number, g: number, b: number): number { + const a = [r, g, b].map(v => { v /= 255; return v <= 0.03928 ? v / 12.92 @@ -8,7 +10,7 @@ function calculateLuminance(r, g, b) { return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722; } -function calculateContrast(rgb1, rgb2) { +export function calculateContrast(rgb1: rgbDef, rgb2: rgbDef): number { let contrast = ( (calculateLuminance(rgb1[0], rgb1[1], rgb1[2]) + 0.05) / (calculateLuminance(rgb2[0], rgb2[1], rgb2[2]) + 0.05) @@ -19,5 +21,3 @@ function calculateContrast(rgb1, rgb2) { } return contrast; } - -export { calculateLuminance, calculateContrast }; diff --git a/src/services/color/rgb_to_hex.js b/src/services/color/rgb_to_hex.js deleted file mode 100644 index ad716a49a17..00000000000 --- a/src/services/color/rgb_to_hex.js +++ /dev/null @@ -1,9 +0,0 @@ -function rgbToHex(rgb) { - rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i); - return (rgb && rgb.length === 4) ? `#${ - (`0${ parseInt(rgb[1], 10).toString(16)}`).slice(-2) - }${(`0${ parseInt(rgb[2], 10).toString(16)}`).slice(-2) - }${(`0${ parseInt(rgb[3], 10).toString(16)}`).slice(-2)}` : ''; -} - -export { rgbToHex }; diff --git a/src/services/color/rgb_to_hex.test.ts b/src/services/color/rgb_to_hex.test.ts new file mode 100644 index 00000000000..2875def1167 --- /dev/null +++ b/src/services/color/rgb_to_hex.test.ts @@ -0,0 +1,50 @@ +import { rgbToHex } from './rgb_to_hex'; + +describe('rgbToHex ', () => { + describe('validation', () => { + it('should return an empty string for malformed input', () => { + expect(rgbToHex('fred')).toEqual(''); + expect(rgbToHex('rgb(fred')).toEqual(''); + expect(rgbToHex('rgb(fred, bob, banana')).toEqual(''); + expect(rgbToHex('rgb(0, 3, 5')).toEqual(''); + expect(rgbToHex('rgba(0, 3, 5')).toEqual(''); + expect(rgbToHex('rgba(0, 3, 5, 99)')).toEqual(''); + }); + }); + + describe('rgb()', () => { + it('should handle rgb() without whitespace', () => { + expect(rgbToHex('rgb(12,34,56)')).toEqual('#0c2238'); + }); + + it('should handle rgb() with whitespace', () => { + expect(rgbToHex('rgb ( 12 , 34 , 56 )')).toEqual('#0c2238'); + }); + }); + + describe('rgba()', () => { + it('should handle no whitespace', () => { + expect(rgbToHex('rgba(12,34,56,0.4)')).toEqual('#0c2238'); + }); + + it('should handle whitespace', () => { + expect(rgbToHex('rgba ( 12 , 34 , 56 , 0.4 )')).toEqual('#0c2238'); + }); + + it('should handle integer maximum alpha', () => { + expect(rgbToHex('rgba(12,34,56,1)')).toEqual('#0c2238'); + }); + + it('should handle decimal maximum alpha', () => { + expect(rgbToHex('rgba(12,34,56,1.00000)')).toEqual('#0c2238'); + }); + + it('should handle integer zero alpha', () => { + expect(rgbToHex('rgba(12,34,56,0)')).toEqual('#0c2238'); + }); + + it('should handle decimal zero alpha', () => { + expect(rgbToHex('rgba(12,34,56,0.0000)')).toEqual('#0c2238'); + }); + }); +}); diff --git a/src/services/color/rgb_to_hex.ts b/src/services/color/rgb_to_hex.ts new file mode 100644 index 00000000000..70b606f6eb5 --- /dev/null +++ b/src/services/color/rgb_to_hex.ts @@ -0,0 +1,16 @@ +function asHex(value: string): string { + const hex = parseInt(value, 10).toString(16); + return hex.length === 1 ? `0${hex}` : hex; +} + +export function rgbToHex(rgb: string): string { + const withoutWhitespace = rgb.replace(/\s+/g, ''); + const rgbMatch = withoutWhitespace.match(/^rgba?\((\d+),(\d+),(\d+)(?:,(?:1(?:\.0*)?|0(?:\.\d+)?))?\)$/i); + if (!rgbMatch) { + return ''; + } + + const [, r, g, b] = rgbMatch; + + return `#${ asHex(r) }${ asHex(g) }${ asHex(b) }`; +} diff --git a/src/services/color/visualization_colors.js b/src/services/color/visualization_colors.ts similarity index 100% rename from src/services/color/visualization_colors.js rename to src/services/color/visualization_colors.ts diff --git a/src/services/copy_to_clipboard.js b/src/services/copy_to_clipboard.ts similarity index 74% rename from src/services/copy_to_clipboard.js rename to src/services/copy_to_clipboard.ts index 6b383981e86..48aab1f6e77 100644 --- a/src/services/copy_to_clipboard.js +++ b/src/services/copy_to_clipboard.ts @@ -1,22 +1,24 @@ -function createHiddenTextElement(text) { +function createHiddenTextElement(text: string): HTMLSpanElement { const textElement = document.createElement('span'); textElement.textContent = text; + // @ts-ignore .all is a real property - https://drafts.csswg.org/css-cascade/#all-shorthand textElement.style.all = 'unset'; // prevents scrolling to the end of the page textElement.style.position = 'fixed'; - textElement.style.top = 0; + textElement.style.top = '0'; textElement.style.clip = 'rect(0, 0, 0, 0)'; // used to preserve spaces and line breaks textElement.style.whiteSpace = 'pre'; // do not inherit user-select (it may be `none`) textElement.style.webkitUserSelect = 'text'; + // @ts-ignore this one doesn't appear in the TS definitions for some reason textElement.style.MozUserSelect = 'text'; textElement.style.msUserSelect = 'text'; textElement.style.userSelect = 'text'; return textElement; } -export function copyToClipboard(text) { +export function copyToClipboard(text: string): boolean { let isCopied = true; const range = document.createRange(); const selection = window.getSelection(); @@ -29,7 +31,8 @@ export function copyToClipboard(text) { if (!document.execCommand('copy')) { isCopied = false; - console.warn('Unable to copy to clipboard.'); // eslint-disable-line no-console + // tslint:disable-next-line:no-console + console.warn('Unable to copy to clipboard.'); } if (selection) { diff --git a/src/services/format/format_auto.test.js b/src/services/format/format_auto.test.ts similarity index 92% rename from src/services/format/format_auto.test.js rename to src/services/format/format_auto.test.ts index 7f3037e7381..11b5e1a0742 100644 --- a/src/services/format/format_auto.test.js +++ b/src/services/format/format_auto.test.ts @@ -26,6 +26,6 @@ describe('formatAuto', () => { test('object value', () => { const obj = { key: 'value' }; - expect(formatAuto(obj)).toBe(`{\"key\":\"value\"}`); + expect(formatAuto(obj)).toBe('{\"key\":\"value\"}'); }); }); diff --git a/src/services/format/format_auto.js b/src/services/format/format_auto.ts similarity index 94% rename from src/services/format/format_auto.js rename to src/services/format/format_auto.ts index b584785ba55..f0f6bb1af6a 100644 --- a/src/services/format/format_auto.js +++ b/src/services/format/format_auto.ts @@ -4,7 +4,7 @@ import { formatDate } from './format_date'; import { formatNumber } from './format_number'; import { formatText } from './format_text'; -export const formatAuto = value => { +export const formatAuto = (value: any): string => { if (isNil(value) || isNaN(value)) { return ''; } diff --git a/src/services/format/format_boolean.test.js b/src/services/format/format_boolean.test.ts similarity index 100% rename from src/services/format/format_boolean.test.js rename to src/services/format/format_boolean.test.ts diff --git a/src/services/format/format_boolean.ts b/src/services/format/format_boolean.ts index 82c8847d400..6e476dbd374 100644 --- a/src/services/format/format_boolean.ts +++ b/src/services/format/format_boolean.ts @@ -1,6 +1,6 @@ import { isNil } from '../predicate'; -export const formatBoolean = (value: boolean, { yes = 'Yes', no = 'No', nil = '' } = {}) => { +export const formatBoolean = (value: boolean, { yes = 'Yes', no = 'No', nil = '' } = {}): string => { if (isNil(value)) { return nil; } diff --git a/src/services/format/format_date.test.js b/src/services/format/format_date.test.ts similarity index 81% rename from src/services/format/format_date.test.js rename to src/services/format/format_date.test.ts index c0f1c59ad43..f16a7e53a81 100644 --- a/src/services/format/format_date.test.js +++ b/src/services/format/format_date.test.ts @@ -50,7 +50,8 @@ describe('formatDate', () => { }); test('with config - "iso8601" format', () => { - expect(formatDate(value, 'iso8601')).toBe(`1999-01-01T02:03:04.005${formatTimezoneOffset(value.getTimezoneOffset())}`); + expect(formatDate(value, 'iso8601')).toBe( + `1999-01-01T02:03:04.005${formatTimezoneOffset(value.getTimezoneOffset())}`); }); test('with config - "calendarDate" format', () => { @@ -59,25 +60,25 @@ describe('formatDate', () => { }; const oneMonthFromNow = moment(options.refTime).add(1, 'month').toDate(); - expect(formatDate(oneMonthFromNow, { format: 'calendarDate', options })).toBe(`1st Feb 1999`); + expect(formatDate(oneMonthFromNow, { format: 'calendarDate', options })).toBe('1st Feb 1999'); const twoDaysFromNow = moment(options.refTime).add(2, 'day').toDate(); - expect(formatDate(twoDaysFromNow, { format: 'calendarDate', options })).toBe(`Sunday`); + expect(formatDate(twoDaysFromNow, { format: 'calendarDate', options })).toBe('Sunday'); const oneDayFromNow = moment(options.refTime).add(1, 'day').toDate(); - expect(formatDate(oneDayFromNow, { format: 'calendarDate', options })).toBe(`Tomorrow`); + expect(formatDate(oneDayFromNow, { format: 'calendarDate', options })).toBe('Tomorrow'); const anMinuteAgo = moment(options.refTime).subtract(1, 'minute').toDate(); - expect(formatDate(anMinuteAgo, { format: 'calendarDate', options })).toBe(`Today`); + expect(formatDate(anMinuteAgo, { format: 'calendarDate', options })).toBe('Today'); const oneDayAgo = moment(options.refTime).subtract(1, 'day').toDate(); - expect(formatDate(oneDayAgo, { format: 'calendarDate', options })).toBe(`Yesterday`); + expect(formatDate(oneDayAgo, { format: 'calendarDate', options })).toBe('Yesterday'); const twoDaysWeekAgo = moment(options.refTime).subtract(2, 'day').toDate(); - expect(formatDate(twoDaysWeekAgo, { format: 'calendarDate', options })).toBe(`Last Wednesday`); + expect(formatDate(twoDaysWeekAgo, { format: 'calendarDate', options })).toBe('Last Wednesday'); const oneMonthAgo = moment(options.refTime).subtract(1, 'month').toDate(); - expect(formatDate(oneMonthAgo, { format: 'calendarDate', options })).toBe(`1st Dec 1998`); + expect(formatDate(oneMonthAgo, { format: 'calendarDate', options })).toBe('1st Dec 1998'); }); test('with config - "calendarDateTime" format', () => { @@ -86,45 +87,39 @@ describe('formatDate', () => { }; const oneMonthFromNow = moment(options.refTime).add(1, 'month').toDate(); - expect(formatDate(oneMonthFromNow, { format: 'calendarDateTime', options })).toBe(`1st Feb 1999 at 2:03AM`); + expect(formatDate(oneMonthFromNow, { format: 'calendarDateTime', options })).toBe('1st Feb 1999 at 2:03AM'); const twoDaysFromNow = moment(options.refTime).add(2, 'day').toDate(); - expect(formatDate(twoDaysFromNow, { format: 'calendarDateTime', options })).toBe(`Sunday at 2:03AM`); + expect(formatDate(twoDaysFromNow, { format: 'calendarDateTime', options })).toBe('Sunday at 2:03AM'); const oneDayFromNow = moment(options.refTime).add(1, 'day').toDate(); - expect(formatDate(oneDayFromNow, { format: 'calendarDateTime', options })).toBe(`Tomorrow at 2:03AM`); + expect(formatDate(oneDayFromNow, { format: 'calendarDateTime', options })).toBe('Tomorrow at 2:03AM'); const anMinuteAgo = moment(options.refTime).subtract(1, 'minute').toDate(); - expect(formatDate(anMinuteAgo, { format: 'calendarDateTime', options })).toBe(`Today at 2:02AM`); + expect(formatDate(anMinuteAgo, { format: 'calendarDateTime', options })).toBe('Today at 2:02AM'); const oneDayAgo = moment(options.refTime).subtract(1, 'day').toDate(); - expect(formatDate(oneDayAgo, { format: 'calendarDateTime', options })).toBe(`Yesterday at 2:03AM`); + expect(formatDate(oneDayAgo, { format: 'calendarDateTime', options })).toBe('Yesterday at 2:03AM'); const twoDaysWeekAgo = moment(options.refTime).subtract(2, 'day').toDate(); - expect(formatDate(twoDaysWeekAgo, { format: 'calendarDateTime', options })).toBe(`Last Wednesday at 2:03AM`); + expect(formatDate(twoDaysWeekAgo, { format: 'calendarDateTime', options })).toBe('Last Wednesday at 2:03AM'); const oneMonthAgo = moment(options.refTime).subtract(1, 'month').toDate(); - expect(formatDate(oneMonthAgo, { format: 'calendarDateTime', options })).toBe(`1st Dec 1998 at 2:03AM`); + expect(formatDate(oneMonthAgo, { format: 'calendarDateTime', options })).toBe('1st Dec 1998 at 2:03AM'); }); test('with config - custom format', () => { - expect(formatDate(value, 'YYYY-MM-DD')).toBe(`1999-01-01`); + expect(formatDate(value, 'YYYY-MM-DD')).toBe('1999-01-01'); }); }); -function formatTimezoneOffset(offset) { +function formatTimezoneOffset(offset: number) { if (offset === 0) { return '+00:00'; } const sign = offset > 0 ? '-' : '+'; offset = Math.abs(offset); - let hrs = Math.floor(offset / 60); - if (hrs < 9) { - hrs = `0${hrs}`; - } - let mins = offset - hrs * 60; - if (mins < 9) { - mins = `0${mins}`; - } - return `${sign}${hrs}:${mins}`; + const hrs = Math.floor(offset / 60); + const mins = offset - hrs * 60; + return `${sign}${hrs < 9 ? '0' : ''}${hrs}:${mins < 9 ? '0' : ''}${mins}`; } diff --git a/src/services/format/format_date.js b/src/services/format/format_date.ts similarity index 59% rename from src/services/format/format_date.js rename to src/services/format/format_date.ts index 1253b61ad68..88dd47b7fac 100644 --- a/src/services/format/format_date.js +++ b/src/services/format/format_date.ts @@ -1,12 +1,16 @@ import { isNil, isFunction, isString } from '../predicate'; -import moment from 'moment'; +import moment, { CalendarSpec, MomentInput } from 'moment'; -const calendar = (value, options = {}) => { - const refTime = options.refTime || null; +type CalendarOptions = CalendarSpec & { + refTime?: MomentInput +}; + +const calendar = (value: Date, options: CalendarOptions = {}) => { + const refTime = options.refTime; return moment(value).calendar(refTime, options); }; -export const dateFormatAliases = { +export const dateFormatAliases: { [alias: string]: any } = { date: 'D MMM YYYY', longDate: 'DD MMMM YYYY', shortDate: 'D MMM YY', @@ -17,7 +21,7 @@ export const dateFormatAliases = { dobLong: 'Do MMMM YYYY', iso8601: 'YYYY-MM-DDTHH:mm:ss.SSSZ', calendar, - calendarDateTime: (value, options) => { + calendarDateTime: (value: Date, options: CalendarSpec) => { return calendar(value, { sameDay: '[Today at] H:mmA', nextDay: '[Tomorrow at] H:mmA', @@ -25,10 +29,10 @@ export const dateFormatAliases = { lastDay: '[Yesterday at] H:mmA', lastWeek: '[Last] dddd [at] H:mmA', sameElse: 'Do MMM YYYY [at] H:mmA', - ...options + ...options, }); }, - calendarDate: (value, options) => { + calendarDate: (value: Date, options: CalendarSpec) => { return calendar(value, { sameDay: '[Today]', nextDay: '[Tomorrow]', @@ -36,20 +40,31 @@ export const dateFormatAliases = { lastDay: '[Yesterday]', lastWeek: '[Last] dddd', sameElse: 'Do MMM YYYY', - ...options + ...options, }); - } + }, }; -export const formatDate = (value, dateFormatKeyOrConfig = 'dateTime') => { +type DateFormat = keyof typeof dateFormatAliases; + +interface FormatDateConfig { + format: DateFormat; + nil: string; + options: any; +} + +export const formatDate = ( + value?: MomentInput, + dateFormatKeyOrConfig: DateFormat | string | Partial = 'dateTime' +) => { if (isString(dateFormatKeyOrConfig)) { if (isNil(value)) { return ''; } - const dateFormat = dateFormatAliases[dateFormatKeyOrConfig] || dateFormatKeyOrConfig; + const dateFormatStr = dateFormatAliases[dateFormatKeyOrConfig] || dateFormatKeyOrConfig; - return moment(value).format(dateFormat); + return moment(value).format(dateFormatStr); } const { diff --git a/src/services/format/format_number.test.js b/src/services/format/format_number.test.ts similarity index 100% rename from src/services/format/format_number.test.js rename to src/services/format/format_number.test.ts diff --git a/src/services/format/format_number.js b/src/services/format/format_number.ts similarity index 65% rename from src/services/format/format_number.js rename to src/services/format/format_number.ts index c7cd6c4cf8d..a875b73d342 100644 --- a/src/services/format/format_number.js +++ b/src/services/format/format_number.ts @@ -1,15 +1,24 @@ import numeral from 'numeral'; import { isNil, isString } from '../predicate'; -const numberFormatAliases = { +const numberFormatAliases: { [alias: string]: string } = { decimal1: '0,0.0', decimal2: '0,0.00', decimal3: '0,0.000', ordinal: '0o', - integer: '0,0' + integer: '0,0', }; -export const formatNumber = (value, numberFormatOrConfig = {}) => { +interface FormatNumberConfig { + format: string; + nil: string; + round: boolean; +} + +export const formatNumber = ( + value?: number | null, + numberFormatOrConfig: string | Partial = {} +) => { let format; let nil = ''; let round; @@ -23,7 +32,7 @@ export const formatNumber = (value, numberFormatOrConfig = {}) => { } if (!format) { - return isNil(value) ? nil : value.toString(); + return isNil(value) ? nil : value!.toString(); } const roundingFunc = round ? Math.round : Math.floor; diff --git a/src/services/format/format_text.js b/src/services/format/format_text.js deleted file mode 100644 index b8d26a977d9..00000000000 --- a/src/services/format/format_text.js +++ /dev/null @@ -1,5 +0,0 @@ -import { isNil } from '../predicate'; - -export const formatText = (value, { nil = '' } = {}) => { - return isNil(value) ? nil : value.toString(); -}; diff --git a/src/services/format/format_text.test.js b/src/services/format/format_text.test.ts similarity index 100% rename from src/services/format/format_text.test.js rename to src/services/format/format_text.test.ts diff --git a/src/services/format/format_text.ts b/src/services/format/format_text.ts new file mode 100644 index 00000000000..bfc2ed4979e --- /dev/null +++ b/src/services/format/format_text.ts @@ -0,0 +1,9 @@ +import { isNil } from '../predicate'; + +interface FormatTextOptions { + nil: string; +} + +export const formatText = (value?: any, options: Partial = { nil: '' }) => { + return isNil(value) ? options.nil : value.toString(); +}; diff --git a/src/services/format/index.js b/src/services/format/index.ts similarity index 100% rename from src/services/format/index.js rename to src/services/format/index.ts diff --git a/src/services/index.d.ts b/src/services/index.d.ts index 68b0e81d836..ef1c504f570 100644 --- a/src/services/index.d.ts +++ b/src/services/index.d.ts @@ -1,5 +1 @@ -/// -/// -/// -/// /// diff --git a/src/services/key_codes.d.ts b/src/services/key_codes.d.ts deleted file mode 100644 index 2a8697e9124..00000000000 --- a/src/services/key_codes.d.ts +++ /dev/null @@ -1,15 +0,0 @@ - -declare module '@elastic/eui' { - export enum keyCodes { - ENTER = 13, - SPACE = 32, - ESCAPE = 27, - TAB = 9, - BACKSPACE = 8, - - DOWN = 40, - UP = 38, - LEFT = 37, - RIGHT = 39, - } - } diff --git a/src/services/key_codes.js b/src/services/key_codes.ts similarity index 61% rename from src/services/key_codes.js rename to src/services/key_codes.ts index 001f932647c..87afb804c10 100644 --- a/src/services/key_codes.js +++ b/src/services/key_codes.ts @@ -9,3 +9,16 @@ export const DOWN = 40; export const UP = 38; export const LEFT = 37; export const RIGHT = 39; + +export enum keyCodes { + ENTER = 13, + SPACE = 32, + ESCAPE = 27, + TAB = 9, + BACKSPACE = 8, + + DOWN = 40, + UP = 38, + LEFT = 37, + RIGHT = 39, +} diff --git a/src/services/objects.js b/src/services/objects.ts similarity index 100% rename from src/services/objects.js rename to src/services/objects.ts diff --git a/src/services/random.test.ts b/src/services/random.test.ts new file mode 100644 index 00000000000..c26470bcd8e --- /dev/null +++ b/src/services/random.test.ts @@ -0,0 +1,77 @@ +import moment from 'moment'; +import { Random } from './random'; + +describe('Random', () => { + it('should generate booleans', () => { + const trueRandom = new Random(() => 0.51); + const falseRandom = new Random(() => 0.5); + + expect(trueRandom.boolean()).toEqual(true); + expect(falseRandom.boolean()).toEqual(false); + }); + + it('should generate numbers', () => { + const random = new Random(() => 0.42); + + expect(random.number()).toEqual(7.550311166421726e+307); + expect(random.number({ min: 5 })).toEqual(7.550311166421726e+307); + expect(random.number({ max: 10 })).toEqual(4.2); + expect(random.number({ min: 5, max: 10 })).toEqual(7.1); + expect(random.number({ min: -10, max: 10 })).toBeCloseTo(-1.60); + }); + + it('should generate integers', () => { + const random = new Random(() => 0.42); + + expect(random.integer({ min: 0, max: 10 })).toEqual(4); + expect(random.integer({ min: -10, max: 10 })).toEqual(-2); + }); + + it('should select an array value', () => { + const random = new Random(() => 0.42); + const values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + expect(random.oneOf(values)).toEqual(5); + }); + + it('should select the specified array value', () => { + const random = new Random(() => 0.42); + const values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + expect(random.oneToOne(values, 4)).toEqual(5); + }); + + it('should select a set of random size', () => { + const random = new Random(() => 0.42); + const input = [12, 34, 56, 78, 90, 3434, 12313212, 3, 0]; + + expect(random.setOf(input)).toEqual([78, 90, 56, 3434]); + }); + + it('should select a set of random size, with a size constraint', () => { + const random = new Random(() => 0.42); + const input = [12, 34, 56, 78, 90, 3434, 12313212, 3, 0]; + + expect(random.setOf(input, { max: 5 })).toEqual([78, 90]); + }); + + it('should generate a date', () => { + const random = new Random(() => 0.42); + + // The default max value is now, so we must specify a max in order to keep + // the test deterministic. + const actual = random.date({ max: new Date(Date.parse('2018-12-25T12:23:34.123')) }); + + expect(actual).toEqual(new Date(Date.parse('1990-07-29T00:24:17.932Z'))); + }); + + it('should generate a moment', () => { + const random = new Random(() => 0.42); + + // The default max value is now, so we must specify a max in order to keep + // the test deterministic. + const actual = random.moment({ max: moment('2018-12-25T12:23:34.123') }); + + expect(actual.toISOString()).toEqual('1990-07-29T00:24:17.932Z'); + }); +}); diff --git a/src/services/random.js b/src/services/random.ts similarity index 53% rename from src/services/random.js rename to src/services/random.ts index bc0c65e97c3..55372af35d5 100644 --- a/src/services/random.js +++ b/src/services/random.ts @@ -1,42 +1,43 @@ -import moment from 'moment'; +import moment, { Moment } from 'moment'; import { isNil } from './predicate'; import { times } from './utils'; const defaultRand = Math.random; export class Random { + private readonly rand: () => number; constructor(rand = defaultRand) { - this._rand = rand; + this.rand = rand; } - boolean() { - return this._rand() > 0.5; + boolean = () => { + return this.rand() > 0.5; } - number(options = {}) { - const min = isNil(options.min) ? Number.MIN_VALUE : options.min; - const max = isNil(options.max) ? Number.MAX_VALUE : options.max; - const delta = this._rand() * (max - min); + number = (options: { min?: number, max?: number } = {}) => { + const min = isNil(options.min) ? Number.MIN_VALUE : options.min!; + const max = isNil(options.max) ? Number.MAX_VALUE : options.max!; + const delta = this.rand() * (max - min); return min + delta; } - integer(options = {}) { - const min = Math.ceil(isNil(options.min) ? Number.MIN_VALUE : options.min); - const max = Math.floor(isNil(options.max) ? Number.MAX_VALUE : options.max); - const delta = Math.floor(this._rand() * (max - min + 1)); + integer = (options: { min?: number, max?: number } = {}) => { + const min = Math.ceil(isNil(options.min) ? Number.MIN_VALUE : options.min!); + const max = Math.floor(isNil(options.max) ? Number.MAX_VALUE : options.max!); + const delta = Math.floor(this.rand() * (max - min + 1)); return min + delta; } - oneOf(values) { - return values[Math.floor(this._rand() * values.length)]; + oneOf = (values: T[]): T => { + return values[Math.floor(this.rand() * values.length)]; } - oneToOne(values, index) { + oneToOne = (values: T[], index: number): T => { return values[index]; } - setOf(values, options) { + setOf = (values: T[], options: { min?: number, max?: number } = {}): T[] => { const count = this.integer({ min: 0, max: values.length, ...options }); const copy = [...values]; return times(count, () => { @@ -46,18 +47,18 @@ export class Random { }); } - date(options = {}) { - const min = isNil(options.min) ? new Date(0) : options.min; - const max = isNil(options.max) ? new Date(Date.now()) : options.max; + date = (options: { min?: Date, max?: Date } = {}) => { + const min = isNil(options.min) ? new Date(0) : options.min!; + const max = isNil(options.max) ? new Date(Date.now()) : options.max!; const minMls = min.getTime(); const maxMls = max.getTime(); const time = this.integer({ min: minMls, max: maxMls }); return new Date(time); } - moment(options = {}) { - const min = isNil(options.min) ? moment(0) : options.min; - const max = isNil(options.max) ? moment() : options.max; + moment = (options: { min?: Moment, max?: Moment } = {}) => { + const min = isNil(options.min) ? moment(0) : options.min!; + const max = isNil(options.max) ? moment() : options.max!; const minMls = +min; const maxMls = +max; const time = this.integer({ min: minMls, max: maxMls }); diff --git a/src/services/utils.js b/src/services/utils.ts similarity index 56% rename from src/services/utils.js rename to src/services/utils.ts index c49227280c6..c792922dc40 100644 --- a/src/services/utils.js +++ b/src/services/utils.ts @@ -3,6 +3,6 @@ export { memoize } from 'lodash'; -export const browserTick = (callback) => { +export const browserTick = (callback: FrameRequestCallback) => { requestAnimationFrame(callback); }; diff --git a/yarn.lock b/yarn.lock index 6f9b0f43c2f..dc32a39eb95 100644 --- a/yarn.lock +++ b/yarn.lock @@ -877,6 +877,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-9.3.0.tgz#3a129cda7c4e5df2409702626892cb4b96546dd5" integrity sha512-wNBfvNjzsJl4tswIZKXCFQY0lss9nKUyJnG6T94X/eqjRgI2jHZ4evdjhQYBSan/vGtF6XVXPApOmNH2rf0KKw== +"@types/numeral@^0.0.25": + version "0.0.25" + resolved "https://registry.yarnpkg.com/@types/numeral/-/numeral-0.0.25.tgz#b6f55062827a4787fe4ab151cf3412a468e65271" + integrity sha512-ShHzHkYD+Ldw3eyttptCpUhF1/mkInWwasQkCNXZHOsJMJ/UMa8wXrxSrTJaVk0r4pLK/VnESVM0wFsfQzNEKQ== + "@types/prop-types@*": version "15.5.5" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.5.5.tgz#17038dd322c2325f5da650a94d5f9974943625e3" @@ -892,7 +897,7 @@ "@types/prop-types" "*" "@types/react" "*" -"@types/react@^16.3.0", "@types/react@*": +"@types/react@*", "@types/react@^16.3.0": version "16.7.12" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.7.12.tgz#6ed680cdbd42aa14ddb550237de91787ec8445b4" integrity sha512-xIO8Eq7EtDHBBY86W7uyaT2rlmDb8NBVwKn0/9pa2rQMrTCebwn2NJmrxxlWQD6qC5DVQtGwAm3Zt0xZNCRwGg== @@ -900,6 +905,13 @@ "@types/prop-types" "*" csstype "^2.2.0" +"@types/uuid@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.4.tgz#7af69360fa65ef0decb41fd150bf4ca5c0cefdf5" + integrity sha512-tPIgT0GUmdJQNSHxp0X2jnpQfBSTfGxUMc/2CXBU2mnyTFVYVa2ojpoQ74w0U2yn2vw3jnC640+77lkFFpdVDw== + dependencies: + "@types/node" "*" + "@webassemblyjs/ast@1.7.11": version "1.7.11" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.7.11.tgz#b988582cafbb2b095e8b556526f30c90d057cace"