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"