,
+ };
+};
+
+export interface WithEuiThemeProps {
+ theme: {
+ euiTheme: EuiThemeComputed
;
+ colorMode: EuiThemeColorMode;
+ };
+}
+export const withEuiTheme = (
+ Component: React.ComponentType>
+) => {
+ const componentName = Component.displayName || Component.name || 'Component';
+ const Render = (
+ props: Omit>,
+ ref: React.Ref>>
+ ) => {
+ const { euiTheme, colorMode } = useEuiTheme();
+ return (
+
+ );
+ };
+
+ const WithEuiTheme = forwardRef(Render);
+
+ WithEuiTheme.displayName = `WithEuiTheme(${componentName})`;
+
+ return WithEuiTheme;
+};
diff --git a/src/services/theme/index.ts b/src/services/theme/index.ts
new file mode 100644
index 00000000000..c62d3ad6565
--- /dev/null
+++ b/src/services/theme/index.ts
@@ -0,0 +1,37 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+export {
+ EuiSystemContext,
+ EuiThemeContext,
+ EuiModificationsContext,
+ EuiColorModeContext,
+} from './context';
+export { useEuiTheme, withEuiTheme, WithEuiThemeProps } from './hooks';
+export { EuiThemeProvider } from './provider';
+export {
+ buildTheme,
+ computed,
+ isInverseColorMode,
+ getColorMode,
+ getComputed,
+ getOn,
+ mergeDeep,
+ setOn,
+ Computed,
+} from './utils';
+export {
+ ComputedThemeShape,
+ EuiThemeColorMode,
+ EuiThemeComputed,
+ EuiThemeModifications,
+ EuiThemeShape,
+ EuiThemeSystem,
+} from './types';
+export { lineHeightFromBaseline } from './typography';
+export { sizeToPixel } from './size';
diff --git a/src/services/theme/provider.tsx b/src/services/theme/provider.tsx
new file mode 100644
index 00000000000..826b72da0a9
--- /dev/null
+++ b/src/services/theme/provider.tsx
@@ -0,0 +1,128 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import React, {
+ useContext,
+ useEffect,
+ useRef,
+ useState,
+ PropsWithChildren,
+} from 'react';
+import isEqual from 'lodash/isEqual';
+
+import {
+ EuiSystemContext,
+ EuiThemeContext,
+ EuiModificationsContext,
+ EuiColorModeContext,
+} from './context';
+import { buildTheme, getColorMode, getComputed, mergeDeep } from './utils';
+import {
+ EuiThemeColorMode,
+ EuiThemeSystem,
+ EuiThemeModifications,
+} from './types';
+
+export interface EuiThemeProviderProps {
+ theme?: EuiThemeSystem;
+ colorMode?: EuiThemeColorMode;
+ modify?: EuiThemeModifications;
+ children: any;
+}
+
+export function EuiThemeProvider({
+ theme: _system,
+ colorMode: _colorMode,
+ modify: _modifications,
+ children,
+}: PropsWithChildren>) {
+ const parentSystem = useContext(EuiSystemContext);
+ const parentModifications = useContext(EuiModificationsContext);
+ const parentColorMode = useContext(EuiColorModeContext);
+ const parentTheme = useContext(EuiThemeContext);
+
+ const [system, setSystem] = useState(_system || parentSystem);
+ const prevSystemKey = useRef(system.key);
+
+ const [modifications, setModifications] = useState(
+ mergeDeep(parentModifications, _modifications)
+ );
+ const prevModifications = useRef(modifications);
+
+ const [colorMode, setColorMode] = useState(
+ getColorMode(_colorMode, parentColorMode)
+ );
+ const prevColorMode = useRef(colorMode);
+
+ const isParentTheme = useRef(
+ prevSystemKey.current === parentSystem.key &&
+ colorMode === parentColorMode &&
+ isEqual(parentModifications, modifications)
+ );
+
+ const [theme, setTheme] = useState(
+ isParentTheme.current && Object.keys(parentTheme).length
+ ? parentTheme
+ : getComputed(
+ system,
+ buildTheme(modifications, `_${system.key}`) as typeof system,
+ colorMode
+ )
+ );
+
+ useEffect(() => {
+ const newSystem = _system || parentSystem;
+ if (prevSystemKey.current !== newSystem.key) {
+ setSystem(newSystem);
+ prevSystemKey.current = newSystem.key;
+ isParentTheme.current = false;
+ }
+ }, [_system, parentSystem]);
+
+ useEffect(() => {
+ const newModifications = mergeDeep(parentModifications, _modifications);
+ if (!isEqual(prevModifications.current, newModifications)) {
+ setModifications(newModifications);
+ prevModifications.current = newModifications;
+ isParentTheme.current = false;
+ }
+ }, [_modifications, parentModifications]);
+
+ useEffect(() => {
+ const newColorMode = getColorMode(_colorMode, parentColorMode);
+ if (!isEqual(newColorMode, prevColorMode.current)) {
+ setColorMode(newColorMode);
+ prevColorMode.current = newColorMode;
+ isParentTheme.current = false;
+ }
+ }, [_colorMode, parentColorMode]);
+
+ useEffect(() => {
+ if (!isParentTheme.current) {
+ setTheme(
+ getComputed(
+ system,
+ buildTheme(modifications, `_${system.key}`) as typeof system,
+ colorMode
+ )
+ );
+ }
+ }, [colorMode, system, modifications]);
+
+ return (
+
+
+
+
+ {children}
+
+
+
+
+ );
+}
diff --git a/src/services/theme/size.ts b/src/services/theme/size.ts
new file mode 100644
index 00000000000..5b3075d976b
--- /dev/null
+++ b/src/services/theme/size.ts
@@ -0,0 +1,23 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+/**
+ * Calculates the `px` value based on a scale multiplier
+ * @param scale - The font scale multiplier
+ * *
+ * @param themeOrBase - Theme base value
+ * *
+ * @returns string - Rem unit aligned to baseline
+ */
+
+export const sizeToPixel = (scale: number = 1) => (
+ themeOrBase: number | { base: number; [key: string]: any }
+) => {
+ const base = typeof themeOrBase === 'object' ? themeOrBase.base : themeOrBase;
+ return `${base * scale}px`;
+};
diff --git a/src/services/theme/types.ts b/src/services/theme/types.ts
new file mode 100644
index 00000000000..223f9f2b130
--- /dev/null
+++ b/src/services/theme/types.ts
@@ -0,0 +1,87 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { RecursivePartial, ValueOf } from '../../components/common';
+import { EuiThemeAnimation } from '../../global_styling/variables/_animations';
+import { EuiThemeBreakpoint } from '../../global_styling/variables/_breakpoint';
+import { EuiThemeBorder } from '../../global_styling/variables/_borders';
+import { EuiThemeColors } from '../../global_styling/variables/_colors';
+import {
+ EuiThemeBase,
+ EuiThemeSize,
+} from '../../global_styling/variables/_size';
+import { EuiThemeFont } from '../../global_styling/variables/_typography';
+import { _EuiThemeFocus } from '../../global_styling/variables/_states';
+
+export const COLOR_MODES_STANDARD = {
+ light: 'LIGHT',
+ dark: 'DARK',
+} as const;
+export const COLOR_MODES_INVERSE = 'INVERSE' as const;
+
+type EuiThemeColorModeInverse = typeof COLOR_MODES_INVERSE;
+type EuiThemeColorModeStandard = ValueOf;
+export type EuiThemeColorMode =
+ | string
+ | EuiThemeColorModeStandard
+ | EuiThemeColorModeInverse;
+
+export type ColorModeSwitch =
+ | {
+ [key in EuiThemeColorModeStandard]: T;
+ }
+ | T;
+
+export type StrictColorModeSwitch = {
+ [key in EuiThemeColorModeStandard]: T;
+};
+
+export type EuiThemeShape = {
+ colors: EuiThemeColors;
+ base: EuiThemeBase;
+ size: EuiThemeSize;
+ font: EuiThemeFont;
+ border: EuiThemeBorder;
+ focus?: _EuiThemeFocus;
+ animation: EuiThemeAnimation;
+ breakpoint: EuiThemeBreakpoint;
+};
+
+export type EuiThemeSystem = {
+ root: EuiThemeShape & T;
+ model: EuiThemeShape & T;
+ key: string;
+};
+
+export type EuiThemeModifications = RecursivePartial;
+
+export type ComputedThemeShape<
+ T,
+ P = string | number | bigint | boolean | null | undefined
+> = T extends P | ColorModeSwitch
+ ? T extends ColorModeSwitch
+ ? X extends P
+ ? X
+ : {
+ [K in keyof (X &
+ Exclude<
+ T,
+ keyof X | keyof StrictColorModeSwitch
+ >)]: ComputedThemeShape<
+ (X & Exclude)[K],
+ P
+ >;
+ }
+ : T
+ : {
+ [K in keyof T]: ComputedThemeShape;
+ };
+
+export type EuiThemeComputed = ComputedThemeShape & {
+ themeName: string;
+};
diff --git a/src/services/theme/typography.ts b/src/services/theme/typography.ts
new file mode 100644
index 00000000000..4fab86d443b
--- /dev/null
+++ b/src/services/theme/typography.ts
@@ -0,0 +1,36 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { _EuiThemeFontBase } from '../../global_styling/variables/_typography';
+
+/**
+ * Calculates the line-height to the closest multiple of the baseline
+ * EX: A proper line-height for text is 1.5 times the font-size.
+ * If our base font size (euiFontSize) is 16, and our baseline is 4. To ensure the
+ * text stays on the baseline, we pass a multiplier to calculate a line-height.
+ * @param base - Theme base unit
+ * @param font - Requires numbers for the `lineHeightMultiplier` and `baseline` values
+ * @param scale - The font scale multiplier
+ * *
+ * @returns string - Rem unit aligned to baseline
+ */
+export function lineHeightFromBaseline(
+ base: number,
+ font: {
+ baseline: _EuiThemeFontBase['baseline'];
+ lineHeightMultiplier: _EuiThemeFontBase['lineHeightMultiplier'];
+ },
+ scale: number
+) {
+ const { baseline, lineHeightMultiplier } = font;
+
+ const pixelValue =
+ Math.floor(Math.round(base * scale * lineHeightMultiplier) / baseline) *
+ baseline;
+ return `${pixelValue / base}rem`;
+}
diff --git a/src/services/theme/utils.test.ts b/src/services/theme/utils.test.ts
new file mode 100644
index 00000000000..52bc023cebd
--- /dev/null
+++ b/src/services/theme/utils.test.ts
@@ -0,0 +1,278 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import {
+ isInverseColorMode,
+ getColorMode,
+ getOn,
+ setOn,
+ computed,
+ Computed,
+ getComputed,
+ buildTheme,
+ mergeDeep,
+} from './utils';
+
+describe('isInverseColorMode', () => {
+ it("true only if 'inverse'", () => {
+ expect(isInverseColorMode('LIGHT')).toBe(false);
+ expect(isInverseColorMode('DARK')).toBe(false);
+ expect(isInverseColorMode('custom')).toBe(false);
+ expect(isInverseColorMode()).toBe(false);
+ expect(isInverseColorMode('INVERSE')).toBe(true);
+ });
+});
+
+describe('getColorMode', () => {
+ it("defaults to 'LIGHT'", () => {
+ expect(getColorMode()).toEqual('LIGHT');
+ });
+ it('uses `parentMode` as fallback', () => {
+ expect(getColorMode(undefined, 'DARK')).toEqual('DARK');
+ });
+ it("understands 'INVERSE'", () => {
+ expect(getColorMode('INVERSE', 'DARK')).toEqual('LIGHT');
+ expect(getColorMode('INVERSE', 'LIGHT')).toEqual('DARK');
+ expect(getColorMode('INVERSE')).toEqual('LIGHT');
+ });
+});
+
+describe('getOn', () => {
+ const obj = {
+ parent: {
+ child: 'childVal',
+ },
+ other: {
+ thing: {
+ string: 'stringVal',
+ nested: ['array'],
+ number: 0,
+ func: () => {},
+ },
+ },
+ colors: {
+ LIGHT: { primary: '#000' },
+ DARK: { primary: '#FFF' },
+ },
+ };
+ it('gets values at the given path', () => {
+ expect(getOn(obj, 'parent', '')).toEqual({
+ child: 'childVal',
+ });
+ expect(getOn(obj, 'parent.child', '')).toEqual('childVal');
+ expect(getOn(obj, 'other.thing.string', '')).toEqual('stringVal');
+ });
+ it('gets values of various kinds', () => {
+ expect(getOn(obj, 'other.thing.nested', '')).toEqual(['array']);
+ expect(getOn(obj, 'other.thing.number', '')).toEqual(0);
+ expect(getOn(obj, 'other.thing.func', '')).toBeInstanceOf(Function);
+ });
+ it('can shortcut color modes', () => {
+ expect(getOn(obj, 'colors.primary', 'LIGHT')).toEqual('#000');
+ expect(getOn(obj, 'colors.primary', 'DARK')).toEqual('#FFF');
+ });
+ it('will not error', () => {
+ expect(getOn(obj, 'nope', '')).toBe(undefined);
+ expect(getOn(obj, 'other.nope', '')).toBe(undefined);
+ expect(getOn(obj, 'other.thing.nope', '')).toBe(undefined);
+ });
+});
+
+describe('setOn', () => {
+ let obj: {};
+ beforeEach(() => {
+ obj = {
+ existing: {
+ nested: {
+ val: 'value',
+ },
+ },
+ };
+ });
+ it('sets values at the given path', () => {
+ setOn(obj, 'existing.new', 'value');
+ expect(obj).toEqual({
+ existing: { nested: { val: 'value' }, new: 'value' },
+ });
+ setOn(obj, 'existing.nested.new', 'value');
+ expect(obj).toEqual({
+ existing: { nested: { val: 'value', new: 'value' }, new: 'value' },
+ });
+ });
+ it('deep arbitrary creation', () => {
+ setOn(obj, 'trail.blazing.happening.now', 'wow');
+ expect(obj).toEqual({
+ existing: { nested: { val: 'value' } },
+ trail: { blazing: { happening: { now: 'wow' } } },
+ });
+ });
+ it('overrides existing path value', () => {
+ setOn(obj, 'existing.nested', 'diff');
+ expect(obj).toEqual({
+ existing: {
+ nested: 'diff',
+ },
+ });
+ });
+});
+
+describe('computed', () => {
+ it('should transform to Computed with dependencies array', () => {
+ const output = computed(([path]) => path, ['path.to']);
+ expect(output).toBeInstanceOf(Computed);
+ expect(output.computer).toBeInstanceOf(Function);
+ expect(output.dependencies).toEqual(['path.to']);
+ });
+ it('should transform to Computed with single dependency', () => {
+ const output = computed((path) => path, 'path.to');
+ expect(output).toBeInstanceOf(Computed);
+ expect(output.computer).toBeInstanceOf(Function);
+ expect(output.dependencies).toEqual('path.to');
+ });
+ it('should transform to Computed without dependencies array', () => {
+ const output = computed((path) => path);
+ expect(output).toBeInstanceOf(Computed);
+ });
+});
+
+const theme = buildTheme(
+ {
+ colors: {
+ LIGHT: {
+ primary: '#000',
+ secondary: computed(([primary]) => `${primary}000`, ['colors.primary']),
+ },
+ DARK: {
+ primary: '#FFF',
+ secondary: computed((theme) => `${theme.colors.primary}FFF`),
+ },
+ },
+ sizes: {
+ small: 8,
+ },
+ },
+ 'minimal'
+);
+describe('getComputed', () => {
+ it('computes all values and returns only the current color mode', () => {
+ // @ts-expect-error intentionally not using a full EUI theme definition
+ expect(getComputed(theme, {}, 'LIGHT')).toEqual({
+ colors: { primary: '#000', secondary: '#000000' },
+ sizes: { small: 8 },
+ themeName: 'minimal',
+ });
+ // @ts-expect-error intentionally not using a full EUI theme definition
+ expect(getComputed(theme, {}, 'DARK')).toEqual({
+ colors: { primary: '#FFF', secondary: '#FFFFFF' },
+ sizes: { small: 8 },
+ themeName: 'minimal',
+ });
+ });
+ it('respects simple overrides', () => {
+ expect(
+ // @ts-expect-error intentionally not using a full EUI theme definition
+ getComputed(theme, buildTheme({ sizes: { small: 4 } }, ''), 'LIGHT')
+ ).toEqual({
+ colors: { primary: '#000', secondary: '#000000' },
+ sizes: { small: 4 },
+ themeName: 'minimal',
+ });
+ });
+ it('respects overrides in computation', () => {
+ expect(
+ getComputed(
+ // @ts-expect-error intentionally not using a full EUI theme definition
+ theme,
+ buildTheme({ colors: { LIGHT: { primary: '#CCC' } } }, ''),
+ 'LIGHT'
+ )
+ ).toEqual({
+ colors: { primary: '#CCC', secondary: '#CCC000' },
+ sizes: { small: 8 },
+ themeName: 'minimal',
+ });
+ });
+ it('respects property extensions', () => {
+ expect(
+ getComputed(
+ // @ts-expect-error intentionally not using a full EUI theme definition
+ theme,
+ buildTheme({ colors: { LIGHT: { tertiary: '#333' } } }, ''),
+ 'LIGHT'
+ )
+ ).toEqual({
+ colors: { primary: '#000', secondary: '#000000', tertiary: '#333' },
+ sizes: { small: 8 },
+ themeName: 'minimal',
+ });
+ });
+ it('respects section extensions', () => {
+ expect(
+ getComputed(
+ // @ts-expect-error intentionally not using a full EUI theme definition
+ theme,
+ buildTheme({ custom: { myProp: '#333' } }, ''),
+ 'LIGHT'
+ )
+ ).toEqual({
+ colors: { primary: '#000', secondary: '#000000' },
+ sizes: { small: 8 },
+ custom: { myProp: '#333' },
+ themeName: 'minimal',
+ });
+ });
+ it('respects extensions in computation', () => {
+ expect(
+ getComputed(
+ // @ts-expect-error intentionally not using a full EUI theme definition
+ theme,
+ buildTheme(
+ {
+ colors: {
+ LIGHT: {
+ tertiary: computed(([primary]) => `${primary}333`, [
+ 'colors.primary',
+ ]),
+ },
+ },
+ },
+ ''
+ ),
+ 'LIGHT'
+ )
+ ).toEqual({
+ colors: { primary: '#000', secondary: '#000000', tertiary: '#000333' },
+ sizes: { small: 8 },
+ themeName: 'minimal',
+ });
+ });
+});
+
+describe('buildTheme', () => {
+ it('builds an EUI theme system', () => {
+ // TypeError: 'getOwnPropertyDescriptor' on proxy: trap reported non-configurability for property 'length' which is either non-existant or configurable in the proxy target
+ // expect(theme).toEqual(Proxy); // get() trap returns theme.model
+ // expect(theme.root).toEqual(Proxy);
+ expect(theme.key).toEqual('minimal');
+ });
+});
+
+describe('mergeDeep', () => {
+ it('merge simple objects, second into first', () => {
+ expect(mergeDeep({ a: 1 }, { b: 2 })).toEqual({ a: 1, b: 2 });
+ expect(mergeDeep({ a: 1 }, { a: 2 })).toEqual({ a: 2 });
+ });
+ it('merge complex objects, second into first', () => {
+ expect(
+ mergeDeep({ a: 1, b: { c: { d: 3 } } }, { b: { c: { d: 4 } } })
+ ).toEqual({ a: 1, b: { c: { d: 4 } } });
+ expect(
+ mergeDeep({ a: 1, b: { c: { d: 3 } } }, { b: { c: { e: 5 } } })
+ ).toEqual({ a: 1, b: { c: { d: 3, e: 5 } } });
+ });
+});
diff --git a/src/services/theme/utils.ts b/src/services/theme/utils.ts
new file mode 100644
index 00000000000..9d905cc69f2
--- /dev/null
+++ b/src/services/theme/utils.ts
@@ -0,0 +1,372 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import {
+ EuiThemeColorMode,
+ EuiThemeModifications,
+ EuiThemeSystem,
+ EuiThemeShape,
+ EuiThemeComputed,
+ COLOR_MODES_STANDARD,
+ COLOR_MODES_INVERSE,
+} from './types';
+
+export const DEFAULT_COLOR_MODE = COLOR_MODES_STANDARD.light;
+
+/**
+ * Returns whether the parameter is an object
+ * @param {any} obj - Anything
+ */
+const isObject = (obj: any) => obj && typeof obj === 'object';
+
+/**
+ * Returns whether the provided color mode is `inverse`
+ * @param {string} colorMode - `light`, `dark`, or `inverse`
+ */
+export const isInverseColorMode = (colorMode?: EuiThemeColorMode) => {
+ return colorMode === COLOR_MODES_INVERSE;
+};
+
+/**
+ * Returns the color mode configured in the current EuiThemeProvider.
+ * Returns the parent color mode if none is explicity set.
+ * @param {string} coloMode - `light`, `dark`, or `inverse`
+ * @param {string} parentColorMode - `light`, `dark`, or `inverse`; used as the fallback
+ */
+export const getColorMode = (
+ colorMode?: EuiThemeColorMode,
+ parentColorMode?: EuiThemeColorMode
+) => {
+ const mode = colorMode?.toUpperCase();
+ if (mode == null) {
+ return parentColorMode || DEFAULT_COLOR_MODE;
+ } else if (isInverseColorMode(mode)) {
+ return parentColorMode === COLOR_MODES_STANDARD.dark ||
+ parentColorMode === undefined
+ ? COLOR_MODES_STANDARD.light
+ : COLOR_MODES_STANDARD.dark;
+ } else {
+ return mode;
+ }
+};
+
+/**
+ * Returns a value at a given path on an object.
+ * If `colorMode` is provided, will scope the value to the appropriate color mode key (LIGHT\DARK)
+ * @param {object} model - Object
+ * @param {string} _path - Dot-notated string to a path on the object
+ * @param {string} colorMode - `light` or `dark`
+ */
+export const getOn = (
+ model: { [key: string]: any },
+ _path: string,
+ colorMode?: EuiThemeColorMode
+) => {
+ const path = _path.split('.');
+ let node = model;
+ while (path.length) {
+ const segment = path.shift()!;
+
+ if (node.hasOwnProperty(segment) === false) {
+ if (
+ colorMode &&
+ node.hasOwnProperty(colorMode) === true &&
+ node[colorMode].hasOwnProperty(segment) === true
+ ) {
+ if (node[colorMode][segment] instanceof Computed) {
+ node = node[colorMode][segment].getValue(null, null, node, colorMode);
+ } else {
+ node = node[colorMode][segment];
+ }
+ } else {
+ return undefined;
+ }
+ } else {
+ if (node[segment] instanceof Computed) {
+ node = node[segment].getValue(null, null, node, colorMode);
+ } else {
+ node = node[segment];
+ }
+ }
+ }
+
+ return node;
+};
+
+/**
+ * Sets a value at a given path on an object.
+ * @param {object} model - Object
+ * @param {string} _path - Dot-notated string to a path on the object
+ * @param {any} string - The value to set
+ */
+export const setOn = (
+ model: { [key: string]: any },
+ _path: string,
+ value: any
+) => {
+ const path = _path.split('.');
+ const propertyName = path.pop()!;
+ let node = model;
+
+ while (path.length) {
+ const segment = path.shift()!;
+ if (node.hasOwnProperty(segment) === false) {
+ node[segment] = {};
+ }
+ node = node[segment];
+ }
+
+ node[propertyName] = value;
+ return true;
+};
+
+/**
+ * Creates a class to store the `computer` method and its eventual parameters.
+ * Allows for on-demand computation with up-to-date parameters via `getValue` method.
+ * @constructor
+ * @param {function} computer - Function to be computed
+ * @param {string | array} dependencies - Dependencies passed to the `computer` as parameters
+ */
+export class Computed {
+ constructor(
+ public computer: (...values: any[]) => T,
+ public dependencies: string | string[] = []
+ ) {}
+
+ /**
+ * Executes the `computer` method with the current state of the theme
+ * by taking into account previously computed values and modifications.
+ * @param {Proxy | object} base - Computed or uncomputed theme
+ * @param {Proxy | object} modifications - Theme value overrides
+ * @param {object} working - Partially computed theme
+ * @param {string} colorMode - `light` or `dark`
+ */
+ getValue(
+ base: EuiThemeSystem | EuiThemeShape,
+ modifications: EuiThemeModifications = {},
+ working: EuiThemeComputed,
+ colorMode: EuiThemeColorMode
+ ) {
+ if (!this.dependencies.length) {
+ return this.computer(working);
+ }
+ if (!Array.isArray(this.dependencies)) {
+ return this.computer(
+ getOn(working, this.dependencies) ??
+ getOn(modifications, this.dependencies, colorMode) ??
+ getOn(base, this.dependencies, colorMode)
+ );
+ }
+ return this.computer(
+ this.dependencies.map((dependency) => {
+ return (
+ getOn(working, dependency) ??
+ getOn(modifications, dependency, colorMode) ??
+ getOn(base, dependency, colorMode)
+ );
+ })
+ );
+ }
+}
+
+/**
+ * Returns a Class (`Computed`) that stores the arbitrary computer method
+ * and references to its optional dependecies.
+ * @param {function} computer - Arbitrary method to be called at compute time.
+ * @param {string | array} dependencies - Values that will be provided to `computer` at compute time.
+ */
+export function computed(computer: (value: EuiThemeComputed) => T): T;
+export function computed(
+ computer: (value: any[]) => T,
+ dependencies: string[]
+): T;
+export function computed(
+ computer: (value: any) => T,
+ dependencies: string
+): T;
+export function computed(
+ comp: ((value: T) => T) | ((value: any) => T) | ((value: any[]) => T),
+ dep?: string | string[]
+) {
+ return new Computed(comp, dep);
+}
+
+/**
+ * Takes an uncomputed theme, and computes and returns all values taking
+ * into consideration value overrides and configured color mode.
+ * Overrides take precedence, and only values in the current color mode
+ * are computed and returned.
+ * @param {Proxy} base - Object to transform into Proxy
+ * @param {Proxy | object} over - Unique identifier or name
+ * @param {string} colorMode - `light` or `dark`
+ */
+export const getComputed = (
+ base: EuiThemeSystem,
+ over: Partial>,
+ colorMode: EuiThemeColorMode
+): EuiThemeComputed => {
+ const output = { themeName: base.key };
+
+ function loop(
+ base: { [key: string]: any },
+ over: { [key: string]: any },
+ checkExisting: boolean = false,
+ path?: string
+ ) {
+ Object.keys(base).forEach((key) => {
+ let newPath = path ? `${path}.${key}` : `${key}`;
+ if ([...Object.values(COLOR_MODES_STANDARD), colorMode].includes(key)) {
+ if (key !== colorMode) {
+ return;
+ } else {
+ const colorModeSegment = new RegExp(
+ `(\\.${colorMode}\\b)|(\\b${colorMode}\\.)`
+ );
+ newPath = newPath.replace(colorModeSegment, '');
+ }
+ }
+ const existing = checkExisting && getOn(output, newPath);
+ if (!existing || isObject(existing)) {
+ const baseValue =
+ base[key] instanceof Computed
+ ? base[key].getValue(base.root, over.root, output, colorMode)
+ : base[key];
+ const overValue =
+ over[key] instanceof Computed
+ ? over[key].getValue(base.root, over.root, output, colorMode)
+ : over[key];
+ if (isObject(baseValue) && !Array.isArray(baseValue)) {
+ loop(baseValue, overValue ?? {}, checkExisting, newPath);
+ } else {
+ setOn(output, newPath, overValue ?? baseValue);
+ }
+ }
+ });
+ }
+ // Compute standard theme values and apply overrides
+ loop(base, over);
+ // Compute and apply extension values only
+ loop(over, {}, true);
+ return output as EuiThemeComputed;
+};
+
+/**
+ * Builds a Proxy with a custom `handler` designed to self-reference values
+ * and prevent arbitrary value overrides.
+ * @param {object} model - Object to transform into Proxy
+ * @param {string} key - Unique identifier or name
+ */
+export const buildTheme = (model: T, key: string) => {
+ const handler: ProxyHandler> = {
+ getPrototypeOf(target) {
+ return Reflect.getPrototypeOf(target.model);
+ },
+
+ setPrototypeOf(target, prototype) {
+ return Reflect.setPrototypeOf(target.model, prototype);
+ },
+
+ isExtensible(target) {
+ return Reflect.isExtensible(target);
+ },
+
+ preventExtensions(target) {
+ return Reflect.preventExtensions(target.model);
+ },
+
+ getOwnPropertyDescriptor(target, key) {
+ return Reflect.getOwnPropertyDescriptor(target.model, key);
+ },
+
+ defineProperty(target, property, attributes) {
+ return Reflect.defineProperty(target.model, property, attributes);
+ },
+
+ has(target, property) {
+ return Reflect.has(target.model, property);
+ },
+
+ get(_target, property) {
+ if (property === 'key') {
+ return _target[property];
+ }
+
+ // prevent Safari from locking up when the proxy is used in dev tools
+ // as it doesn't support getPrototypeOf
+ if (property === '__proto__') return {};
+
+ const target = property === 'root' ? _target : _target.model || _target;
+ // @ts-ignore `string` index signature
+ const value = target[property];
+ if (isObject(value) && !Array.isArray(value)) {
+ return new Proxy(
+ {
+ model: value,
+ root: _target.root,
+ key: `_${_target.key}`,
+ },
+ handler
+ );
+ } else {
+ return value;
+ }
+ },
+
+ set(target: any) {
+ return target;
+ },
+
+ deleteProperty(target: any) {
+ return target;
+ },
+
+ ownKeys(target) {
+ return Reflect.ownKeys(target.model);
+ },
+
+ apply(target: any) {
+ return target;
+ },
+
+ construct(target: any) {
+ return target;
+ },
+ };
+ const themeProxy = new Proxy({ model, root: model, key }, handler);
+
+ return themeProxy;
+};
+
+/**
+ * Deeply merges two objects, using `source` values whenever possible.
+ * @param {object} _target - Object with fallback values
+ * @param {object} source - Object with desired values
+ */
+export const mergeDeep = (
+ _target: { [key: string]: any },
+ source: { [key: string]: any } = {}
+) => {
+ const target = { ..._target };
+
+ if (!isObject(target) || !isObject(source)) {
+ return source;
+ }
+
+ Object.keys(source).forEach((key) => {
+ const targetValue = target[key];
+ const sourceValue = source[key];
+
+ if (isObject(targetValue) && isObject(sourceValue)) {
+ target[key] = mergeDeep({ ...targetValue }, { ...sourceValue });
+ } else {
+ target[key] = sourceValue;
+ }
+ });
+
+ return target;
+};
diff --git a/src/themes/eui-amsterdam/global_styling/variables/_borders.ts b/src/themes/eui-amsterdam/global_styling/variables/_borders.ts
new file mode 100644
index 00000000000..8ab04cf7190
--- /dev/null
+++ b/src/themes/eui-amsterdam/global_styling/variables/_borders.ts
@@ -0,0 +1,21 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { computed, sizeToPixel } from '../../../../services/theme';
+import {
+ border,
+ EuiThemeBorder,
+} from '../../../../global_styling/variables/_borders';
+
+export const border_ams: EuiThemeBorder = {
+ ...border,
+ radius: {
+ medium: computed(sizeToPixel(0.375)),
+ small: computed(sizeToPixel(0.25)),
+ },
+};
diff --git a/src/themes/eui-amsterdam/global_styling/variables/_colors.ts b/src/themes/eui-amsterdam/global_styling/variables/_colors.ts
new file mode 100644
index 00000000000..a4f5322f0e3
--- /dev/null
+++ b/src/themes/eui-amsterdam/global_styling/variables/_colors.ts
@@ -0,0 +1,101 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { shade, tint } from '../../../../services/color';
+import { computed } from '../../../../services/theme/utils';
+import {
+ makeHighContrastColor,
+ makeDisabledContrastColor,
+} from '../../../../services/color/contrast';
+import {
+ _EuiThemeColors,
+ brand_text_colors,
+ shade_colors,
+ EuiThemeColors,
+ dark_shades,
+} from '../../../../global_styling/variables/_colors';
+
+/*
+ * LIGHT THEME
+ */
+
+export const light_colors_ams: _EuiThemeColors = {
+ // Brand
+ primary: '#07C',
+ accent: '#F04E98',
+ success: '#00BFB3',
+ warning: '#FEC514',
+ danger: '#BD271E',
+
+ // Shades
+ ...shade_colors,
+ lightestShade: '#f0f4fb',
+
+ // Special
+ body: computed(([lightestShade]) => tint(lightestShade, 0.5), [
+ 'colors.lightestShade',
+ ]),
+ highlight: computed(([warning]) => tint(warning, 0.9), ['colors.warning']),
+ disabled: '#ABB4C4',
+ disabledText: computed(makeDisabledContrastColor('colors.disabled')),
+ shadow: computed(({ colors }) => colors.ink),
+
+ // Need to come after special colors so they can react to `body`
+ ...brand_text_colors,
+
+ // Text
+ text: computed(([darkestShade]) => darkestShade, ['colors.darkestShade']),
+ title: computed(([text]) => shade(text, 0.5), ['colors.text']),
+ subdued: computed(makeHighContrastColor('colors.darkShade')),
+ link: computed(([primaryText]) => primaryText, ['colors.primaryText']),
+};
+
+/*
+ * DARK THEME
+ */
+
+export const dark_colors_ams: _EuiThemeColors = {
+ // Brand
+ primary: '#36A2EF',
+ accent: '#F68FBE',
+ success: '#7DDED8',
+ warning: '#F3D371',
+ danger: '#F86B63',
+
+ // Shades
+ ...dark_shades,
+
+ // Special
+ body: computed(([lightestShade]) => shade(lightestShade, 0.45), [
+ 'colors.lightestShade',
+ ]),
+ highlight: '#2E2D25',
+ disabled: '#515761',
+ disabledText: computed(makeDisabledContrastColor('colors.disabled')),
+ shadow: computed(({ colors }) => colors.ink),
+
+ // Need to come after special colors so they can react to `body`
+ ...brand_text_colors,
+
+ // Text
+ text: '#DFE5EF',
+ title: computed(([text]) => text, ['colors.text']),
+ subdued: computed(makeHighContrastColor('colors.mediumShade')),
+ link: computed(([primaryText]) => primaryText, ['colors.primaryText']),
+};
+
+/*
+ * FULL
+ */
+
+export const colors_ams: EuiThemeColors = {
+ ghost: '#FFF',
+ ink: '#000',
+ LIGHT: light_colors_ams,
+ DARK: dark_colors_ams,
+};
diff --git a/src/themes/eui-amsterdam/global_styling/variables/_states.ts b/src/themes/eui-amsterdam/global_styling/variables/_states.ts
new file mode 100644
index 00000000000..29274e87de4
--- /dev/null
+++ b/src/themes/eui-amsterdam/global_styling/variables/_states.ts
@@ -0,0 +1,33 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { computed } from '../../../../services/theme/utils';
+import { transparentize } from '../../../../services/color';
+import {
+ focus,
+ _EuiThemeFocus,
+} from '../../../../global_styling/variables/_states';
+
+/**
+ * NOTE: These were quick conversions of their Sass counterparts.
+ * They have yet to be used/tested.
+ */
+
+export const focus_ams: _EuiThemeFocus = {
+ ...focus,
+ color: 'currentColor',
+ transparency: { LIGHT: 0.9, DARK: 0.7 },
+ backgroundColor: computed(({ colors, focus }) =>
+ transparentize(colors.primary, focus!.transparency)
+ ),
+
+ // Outline
+ outline: {
+ outline: computed(({ focus }) => `${focus!.width} solid ${focus!.color}`),
+ },
+};
diff --git a/src/themes/eui-amsterdam/global_styling/variables/_typography.ts b/src/themes/eui-amsterdam/global_styling/variables/_typography.ts
new file mode 100644
index 00000000000..ee0c0845ee0
--- /dev/null
+++ b/src/themes/eui-amsterdam/global_styling/variables/_typography.ts
@@ -0,0 +1,17 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { font } from '../../../../global_styling/variables/_typography';
+
+/**
+ * Amsterdam theme just changes the main font from the beta Inter UI to Inter
+ */
+export const font_ams = {
+ ...font,
+ family: "'Inter', BlinkMacSystemFont, Helvetica, Arial, sans-serif",
+};
diff --git a/src/themes/eui-amsterdam/global_styling/variables/title.ts b/src/themes/eui-amsterdam/global_styling/variables/title.ts
new file mode 100644
index 00000000000..fae6e5e9792
--- /dev/null
+++ b/src/themes/eui-amsterdam/global_styling/variables/title.ts
@@ -0,0 +1,30 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+/**
+ * NOTE: These were quick conversions of their Sass counterparts.
+ * They have yet to be used/tested.
+ */
+
+import {
+ title,
+ EuiThemeTitle,
+} from '../../../../global_styling/variables/title';
+import { SCALES } from '../../../../global_styling/variables/_typography';
+import { computed } from '../../../../services/theme/utils';
+
+// For Amsterdam, change all font-weights to bold and remove letter-spacing
+
+export const title_ams: EuiThemeTitle = SCALES.reduce((acc, elem) => {
+ acc[elem] = {
+ ...title[elem],
+ fontWeight: computed(([fontWeight]) => fontWeight, ['font.weight.bold']),
+ letterSpacing: undefined,
+ };
+ return acc;
+}, {} as EuiThemeTitle);
diff --git a/src/themes/eui-amsterdam/theme.ts b/src/themes/eui-amsterdam/theme.ts
new file mode 100644
index 00000000000..9be031362ae
--- /dev/null
+++ b/src/themes/eui-amsterdam/theme.ts
@@ -0,0 +1,31 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { buildTheme, EuiThemeShape } from '../../services/theme';
+import { animation } from '../../global_styling/variables/_animations';
+import { breakpoint } from '../../global_styling/variables/_breakpoint';
+import { base, size } from '../../global_styling/variables/_size';
+
+import { colors_ams } from './global_styling/variables/_colors';
+import { font_ams } from './global_styling/variables/_typography';
+import { border_ams } from './global_styling/variables/_borders';
+
+export const euiThemeAmsterdam: EuiThemeShape = {
+ colors: colors_ams,
+ base,
+ size,
+ font: font_ams,
+ border: border_ams,
+ animation,
+ breakpoint,
+};
+
+export const EuiThemeAmsterdam = buildTheme(
+ euiThemeAmsterdam,
+ 'EUI_THEME_AMSTERDAM'
+);
diff --git a/src/themes/eui/theme.ts b/src/themes/eui/theme.ts
new file mode 100644
index 00000000000..9c51e3f34eb
--- /dev/null
+++ b/src/themes/eui/theme.ts
@@ -0,0 +1,28 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { buildTheme } from '../../services/theme/utils';
+import { EuiThemeShape } from '../../services/theme/types';
+import { animation } from '../../global_styling/variables/_animations';
+import { breakpoint } from '../../global_styling/variables/_breakpoint';
+import { colors } from '../../global_styling/variables/_colors';
+import { base, size } from '../../global_styling/variables/_size';
+import { font } from '../../global_styling/variables/_typography';
+import { border } from '../../global_styling/variables/_borders';
+
+export const euiThemeDefault: EuiThemeShape = {
+ colors,
+ base,
+ size,
+ font,
+ border,
+ animation,
+ breakpoint,
+};
+
+export const EuiThemeDefault = buildTheme(euiThemeDefault, 'EUI_THEME_DEFAULT');
diff --git a/yarn.lock b/yarn.lock
index 3589ced359b..d1db42435a8 100755
--- a/yarn.lock
+++ b/yarn.lock
@@ -103,6 +103,15 @@
"@babel/helper-module-imports" "^7.10.4"
"@babel/types" "^7.10.4"
+"@babel/helper-builder-react-jsx-experimental@^7.12.1":
+ version "7.12.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.12.4.tgz#55fc1ead5242caa0ca2875dcb8eed6d311e50f48"
+ integrity sha512-AjEa0jrQqNk7eDQOo0pTfUOwQBMF+xVqrausQwT9/rTKy0g04ggFNaJpaE09IQMn9yExluigWMJcj0WC7bq+Og==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.10.4"
+ "@babel/helper-module-imports" "^7.12.1"
+ "@babel/types" "^7.12.1"
+
"@babel/helper-builder-react-jsx@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.10.4.tgz#8095cddbff858e6fa9c326daee54a2f2732c1d5d"
@@ -195,6 +204,13 @@
dependencies:
"@babel/types" "^7.10.4"
+"@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.7.0":
+ version "7.12.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz#1bfc0229f794988f76ed0a4d4e90860850b54dfb"
+ integrity sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==
+ dependencies:
+ "@babel/types" "^7.12.5"
+
"@babel/helper-module-transforms@^7.10.4", "@babel/helper-module-transforms@^7.10.5", "@babel/helper-module-transforms@^7.11.0":
version "7.11.0"
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz#b16f250229e47211abdd84b34b64737c2ab2d359"
@@ -456,6 +472,13 @@
dependencies:
"@babel/helper-plugin-utils" "^7.10.4"
+"@babel/plugin-syntax-jsx@^7.12.1", "@babel/plugin-syntax-jsx@^7.2.0":
+ version "7.12.1"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz#9d9d357cc818aa7ae7935917c1257f67677a0926"
+ integrity sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
"@babel/plugin-syntax-logical-assignment-operators@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699"
@@ -738,6 +761,16 @@
"@babel/helper-plugin-utils" "^7.10.4"
"@babel/plugin-syntax-jsx" "^7.10.4"
+"@babel/plugin-transform-react-jsx@^7.12.1":
+ version "7.12.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.5.tgz#39ede0e30159770561b6963be143e40af3bde00c"
+ integrity sha512-2xkcPqqrYiOQgSlM/iwto1paPijjsDbUynN13tI6bosDz/jOW3CRzYguIE8wKX32h+msbBM22Dv5fwrFkUOZjQ==
+ dependencies:
+ "@babel/helper-builder-react-jsx" "^7.10.4"
+ "@babel/helper-builder-react-jsx-experimental" "^7.12.1"
+ "@babel/helper-plugin-utils" "^7.10.4"
+ "@babel/plugin-syntax-jsx" "^7.12.1"
+
"@babel/plugin-transform-react-pure-annotations@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.10.4.tgz#3eefbb73db94afbc075f097523e445354a1c6501"
@@ -961,7 +994,7 @@
dependencies:
regenerator-runtime "^0.13.4"
-"@babel/runtime@^7.12.1":
+"@babel/runtime@^7.12.1", "@babel/runtime@^7.7.2":
version "7.12.13"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.13.tgz#0a21452352b02542db0ffb928ac2d3ca7cb6d66d"
integrity sha512-8+3UMPBrjFa/6TtKi/7sehPKqfAm4g6K+YQjyyFOLUTxzOngcRZTlAVY8sc2CORJYqdHQY8gRPHmn+qo15rCBw==
@@ -992,7 +1025,7 @@
globals "^11.1.0"
lodash "^4.17.19"
-"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.12.10", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.7.1", "@babel/types@^7.9.5":
+"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.12.10", "@babel/types@^7.12.7", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.7.1", "@babel/types@^7.9.5":
version "7.12.10"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.10.tgz#7965e4a7260b26f09c56bcfcb0498af1f6d9b260"
integrity sha512-sf6wboJV5mGyip2hIpDSKsr80RszPinEFjsHTalMxZAZkoQ2/2yQzxlcFN52SJqsyPfLtPmenL4g2KB3KJXPDw==
@@ -1001,6 +1034,15 @@
lodash "^4.17.19"
to-fast-properties "^2.0.0"
+"@babel/types@^7.12.1", "@babel/types@^7.12.5":
+ version "7.12.6"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.6.tgz#ae0e55ef1cce1fbc881cd26f8234eb3e657edc96"
+ integrity sha512-hwyjw6GvjBLiyy3W0YQf0Z5Zf4NpYejUnKFcfcUhZCSffoBBp30w6wP2Wn6pk31jMYZvcOrB/1b7cGXvEoKogA==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.10.4"
+ lodash "^4.17.19"
+ to-fast-properties "^2.0.0"
+
"@cnakazawa/watch@^1.0.3":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a"
@@ -1046,6 +1088,111 @@
resolved "https://registry.yarnpkg.com/@elastic/eslint-config-kibana/-/eslint-config-kibana-0.15.0.tgz#a552793497cdfc1829c2f9b7cd7018eb008f1606"
integrity sha1-pVJ5NJfN/Bgpwvm3zXAY6wCPFgY=
+"@emotion/babel-plugin-jsx-pragmatic@^0.1.5":
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/@emotion/babel-plugin-jsx-pragmatic/-/babel-plugin-jsx-pragmatic-0.1.5.tgz#27debfe9c27c4d83574d509787ae553bf8a34d7e"
+ integrity sha512-y+3AJ0SItMDaAgGPVkQBC/S/BaqaPACkQ6MyCI2CUlrjTxKttTVfD3TMtcs7vLEcLxqzZ1xiG0vzwCXjhopawQ==
+ dependencies:
+ "@babel/plugin-syntax-jsx" "^7.2.0"
+
+"@emotion/babel-plugin@^11.0.0":
+ version "11.0.0"
+ resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.0.0.tgz#e6f40fa81ef52775773a53d50220c597ebc5c2ef"
+ integrity sha512-w3YP0jlqrNwBBaSI6W+r80fOKF6l9QmsPfLNx5YWSHwrxjVZhM+L50gY7YCVAvlfr1/qdD1vsFN+PDZmLvt42Q==
+ dependencies:
+ "@babel/helper-module-imports" "^7.7.0"
+ "@babel/plugin-syntax-jsx" "^7.12.1"
+ "@babel/runtime" "^7.7.2"
+ "@emotion/hash" "^0.8.0"
+ "@emotion/memoize" "^0.7.4"
+ "@emotion/serialize" "^1.0.0"
+ babel-plugin-macros "^2.6.1"
+ convert-source-map "^1.5.0"
+ escape-string-regexp "^4.0.0"
+ find-root "^1.1.0"
+ source-map "^0.5.7"
+ stylis "^4.0.3"
+
+"@emotion/babel-preset-css-prop@^11.0.0":
+ version "11.0.0"
+ resolved "https://registry.yarnpkg.com/@emotion/babel-preset-css-prop/-/babel-preset-css-prop-11.0.0.tgz#25b868affa620b9e97024b67f67ad32c03a0510e"
+ integrity sha512-E7z3jMf1OyThGpp3ngYGxOSGX5AdoSQTuqM9QgJNAHFh3Fi8N5CbWx6g+IdySJ8bjPiMgFQsIeEhkyy+4mDpCQ==
+ dependencies:
+ "@babel/plugin-transform-react-jsx" "^7.12.1"
+ "@babel/runtime" "^7.7.2"
+ "@emotion/babel-plugin" "^11.0.0"
+ "@emotion/babel-plugin-jsx-pragmatic" "^0.1.5"
+
+"@emotion/cache@^11.0.0":
+ version "11.0.0"
+ resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.0.0.tgz#473adcaf9e04c6a0e30fb1421e79a209a96818f8"
+ integrity sha512-NStfcnLkL5vj3mBILvkR2m/5vFxo3G0QEreYKDGHNHm9IMYoT/t3j6xwjx6lMI/S1LUJfVHQqn0m9wSINttTTQ==
+ dependencies:
+ "@emotion/memoize" "^0.7.4"
+ "@emotion/sheet" "^1.0.0"
+ "@emotion/utils" "^1.0.0"
+ "@emotion/weak-memoize" "^0.2.5"
+ stylis "^4.0.3"
+
+"@emotion/eslint-plugin@^11.0.0":
+ version "11.0.0"
+ resolved "https://registry.yarnpkg.com/@emotion/eslint-plugin/-/eslint-plugin-11.0.0.tgz#7666b750df62dc33a93bb1e09086f1caaecadc6f"
+ integrity sha512-V5w/LgV61xta+U6LKht3WQqfjTLueU2mh1aRTcK5OfkRhZ4OZFE0Inq/oVwLCq5g3Hzoaq27PRm+Tk9W18QScw==
+
+"@emotion/hash@^0.8.0":
+ version "0.8.0"
+ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413"
+ integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==
+
+"@emotion/memoize@^0.7.4":
+ version "0.7.4"
+ resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb"
+ integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==
+
+"@emotion/react@^11.1.1":
+ version "11.1.1"
+ resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.1.1.tgz#4b304d494af321b0179e6763830e07cf674f0423"
+ integrity sha512-otA0Np8OnOeU9ChkOS9iuLB6vIxiM+bJiU0id33CsQn3R2Pk9ijVHnxevENIKV/P2S7AhrD8cFbUGysEciWlEA==
+ dependencies:
+ "@babel/runtime" "^7.7.2"
+ "@emotion/cache" "^11.0.0"
+ "@emotion/serialize" "^1.0.0"
+ "@emotion/sheet" "^1.0.0"
+ "@emotion/utils" "^1.0.0"
+ "@emotion/weak-memoize" "^0.2.5"
+ hoist-non-react-statics "^3.3.1"
+
+"@emotion/serialize@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.0.0.tgz#1a61f4f037cf39995c97fc80ebe99abc7b191ca9"
+ integrity sha512-zt1gm4rhdo5Sry8QpCOpopIUIKU+mUSpV9WNmFILUraatm5dttNEaYzUWWSboSMUE6PtN2j1cAsuvcugfdI3mw==
+ dependencies:
+ "@emotion/hash" "^0.8.0"
+ "@emotion/memoize" "^0.7.4"
+ "@emotion/unitless" "^0.7.5"
+ "@emotion/utils" "^1.0.0"
+ csstype "^3.0.2"
+
+"@emotion/sheet@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.0.0.tgz#a0ef06080f339477ad4ba7f56e1c931f7ba50822"
+ integrity sha512-cdCHfZtf/0rahPDCZ9zyq+36EqfD/6c0WUqTFZ/hv9xadTUv2lGE5QK7/Z6Dnx2oRxC0usfVM2/BYn9q9B9wZA==
+
+"@emotion/unitless@^0.7.5":
+ version "0.7.5"
+ resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed"
+ integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==
+
+"@emotion/utils@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.0.0.tgz#abe06a83160b10570816c913990245813a2fd6af"
+ integrity sha512-mQC2b3XLDs6QCW+pDQDiyO/EdGZYOygE8s5N5rrzjSI4M3IejPE/JPndCBwRT9z982aqQNi6beWs1UeayrQxxA==
+
+"@emotion/weak-memoize@^0.2.5":
+ version "0.2.5"
+ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46"
+ integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==
+
"@eslint/eslintrc@^0.1.3":
version "0.1.3"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.1.3.tgz#7d1a2b2358552cc04834c0979bd4275362e37085"
@@ -2914,6 +3061,15 @@ babel-plugin-jest-hoist@^24.9.0:
dependencies:
"@types/babel__traverse" "^7.0.6"
+babel-plugin-macros@^2.6.1:
+ version "2.8.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138"
+ integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==
+ dependencies:
+ "@babel/runtime" "^7.7.2"
+ cosmiconfig "^6.0.0"
+ resolve "^1.12.0"
+
babel-plugin-pegjs-inline-precompile@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/babel-plugin-pegjs-inline-precompile/-/babel-plugin-pegjs-inline-precompile-0.1.1.tgz#f12d1aa9f947945c2bd8c9c1ae503a8fba7d810d"
@@ -4290,7 +4446,7 @@ content-type@~1.0.4:
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
-convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.7.0:
+convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
@@ -4718,6 +4874,11 @@ csstype@^2.2.0:
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.9.tgz#05141d0cd557a56b8891394c1911c40c8a98d098"
integrity sha512-xz39Sb4+OaTsULgUERcCk+TJj8ylkL4aSVDQiX/ksxbELSqwkgt4d4RD7fovIdgJGSuNYqwZEiVjYY5l0ask+Q==
+csstype@^3.0.2:
+ version "3.0.5"
+ resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.5.tgz#7fdec6a28a67ae18647c51668a9ff95bb2fa7bb8"
+ integrity sha512-uVDi8LpBUKQj6sdxNaTetL6FpeCqTjOvAQuQUa/qAqq8oOd4ivkbhgnqayl0dnPal8Tb/yB1tF+gOvCBiicaiQ==
+
currently-unhandled@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
@@ -7804,7 +7965,7 @@ hmac-drbg@^1.0.0:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
-hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
+hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
@@ -14726,7 +14887,7 @@ source-map@^0.4.2:
dependencies:
amdefine ">=0.0.4"
-source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6:
+source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7:
version "0.5.7"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
@@ -15261,6 +15422,11 @@ stylelint@^8.1.1:
svg-tags "^1.0.0"
table "^4.0.1"
+stylis@^4.0.3:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.3.tgz#0d714765f3f694a685550f0c45411ebf90a9bded"
+ integrity sha512-iAxdFyR9cHKp4H5M2dJlDnvcb/3TvPprzlKjvYVbH7Sh+y8hjY/mUu/ssdcvVz6Z4lKI3vsoS0jAkMYmX7ozfA==
+
sudo-block@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/sudo-block/-/sudo-block-1.2.0.tgz#cc539bf8191624d4f507d83eeb45b4cea27f3463"