[pre-req] Convert Palettes and Components (#69065)

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
Clint Andrew Hall 2020-06-24 11:47:56 -04:00 committed by GitHub
parent 5e3798ccd9
commit 9e00da35b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 898 additions and 384 deletions

View file

@ -59,6 +59,9 @@ function loadStories() {
// Find all files ending in *.examples.ts
const req = require.context('./..', true, /.(stories|examples).tsx$/);
req.keys().forEach(filename => req(filename));
// Import Canvas CSS
require('../public/style/index.scss')
}
// Set up the Storybook environment with custom settings.

View file

@ -199,6 +199,7 @@ module.exports = async ({ config }) => {
config.resolve.alias['ui/url/absolute_to_parsed_url'] = path.resolve(__dirname, '../tasks/mocks/uiAbsoluteToParsedUrl');
config.resolve.alias['ui/chrome'] = path.resolve(__dirname, '../tasks/mocks/uiChrome');
config.resolve.alias.ui = path.resolve(KIBANA_ROOT, 'src/legacy/ui/public');
config.resolve.alias['src/legacy/ui/public/styles/styling_constants'] = path.resolve(KIBANA_ROOT, 'src/legacy/ui/public/styles/_styling_constants.scss');
config.resolve.alias.ng_mock$ = path.resolve(KIBANA_ROOT, 'src/test_utils/public/ng_mock');
return config;

View file

@ -5,7 +5,7 @@
*/
import { functionWrapper } from '../../../__tests__/helpers/function_wrapper';
import { palettes } from '../../../common/lib/palettes';
import { paulTor14 } from '../../../common/lib/palettes';
import { palette } from './palette';
describe('palette', () => {
@ -25,7 +25,7 @@ describe('palette', () => {
it('defaults to pault_tor_14 colors', () => {
const result = fn(null);
expect(result.colors).toEqual(palettes.paul_tor_14.colors);
expect(result.colors).toEqual(paulTor14.colors);
});
});
@ -47,17 +47,17 @@ describe('palette', () => {
describe('reverse', () => {
it('reverses order of the colors', () => {
const result = fn(null, { reverse: true });
expect(result.colors).toEqual(palettes.paul_tor_14.colors.reverse());
expect(result.colors).toEqual(paulTor14.colors.reverse());
});
it('keeps the original order of the colors', () => {
const result = fn(null, { reverse: false });
expect(result.colors).toEqual(palettes.paul_tor_14.colors);
expect(result.colors).toEqual(paulTor14.colors);
});
it(`defaults to 'false`, () => {
const result = fn(null);
expect(result.colors).toEqual(palettes.paul_tor_14.colors);
expect(result.colors).toEqual(paulTor14.colors);
});
});
});

View file

@ -5,8 +5,7 @@
*/
import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common';
// @ts-expect-error untyped local
import { palettes } from '../../../common/lib/palettes';
import { paulTor14 } from '../../../common/lib/palettes';
import { getFunctionHelp } from '../../../i18n';
interface Arguments {
@ -52,7 +51,7 @@ export function palette(): ExpressionFunctionDefinition<'palette', null, Argumen
},
fn: (input, args) => {
const { color, reverse, gradient } = args;
const colors = ([] as string[]).concat(color || palettes.paul_tor_14.colors);
const colors = ([] as string[]).concat(color || paulTor14.colors);
return {
type: 'palette',

View file

@ -0,0 +1,86 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Storyshots arguments/Palette default 1`] = `
<div
className="canvasContainerWrapper"
style={
Object {
"width": "200px",
}
}
>
<div
className="euiPopover euiPopover--anchorDownCenter euiPopover--displayBlock euiSuperSelect"
onKeyDown={[Function]}
onMouseDown={[Function]}
onMouseUp={[Function]}
onTouchEnd={[Function]}
onTouchStart={[Function]}
>
<div
className="euiPopover__anchor"
>
<input
type="hidden"
value="paul_tor_14"
/>
<div
className="euiFormControlLayout euiFormControlLayout--compressed"
>
<div
className="euiFormControlLayout__childrenWrapper"
>
<span
className="euiScreenReaderOnly"
id="generated-id"
>
Select an option:
<div
className="euiColorPalettePicker__itemGradient"
style={
Object {
"background": "linear-gradient(to right, #882E72 0%, #882E72 7%, #B178A6 7%, #B178A6 14%, #D6C1DE 14%, #D6C1DE 21%, #1965B0 21%, #1965B0 28%, #5289C7 28%, #5289C7 35%, #7BAFDE 35%, #7BAFDE 42%, #4EB265 42%, #4EB265 50%, #90C987 50%, #90C987 57%, #CAE0AB 57%, #CAE0AB 64%, #F7EE55 64%, #F7EE55 71%, #F6C141 71%, #F6C141 78%, #F1932D 78%, #F1932D 85%, #E8601C 85%, #E8601C 92%, #DC050C 92%, #DC050C 100%)",
}
}
/>
, is selected
</span>
<button
aria-haspopup="true"
aria-labelledby="undefined generated-id"
aria-selected={true}
className="euiSuperSelectControl euiSuperSelectControl--compressed"
onClick={[Function]}
onKeyDown={[Function]}
readOnly={false}
role="option"
type="button"
>
<div
className="euiColorPalettePicker__itemGradient"
style={
Object {
"background": "linear-gradient(to right, #882E72 0%, #882E72 7%, #B178A6 7%, #B178A6 14%, #D6C1DE 14%, #D6C1DE 21%, #1965B0 21%, #1965B0 28%, #5289C7 28%, #5289C7 35%, #7BAFDE 35%, #7BAFDE 42%, #4EB265 42%, #4EB265 50%, #90C987 50%, #90C987 57%, #CAE0AB 57%, #CAE0AB 64%, #F7EE55 64%, #F7EE55 71%, #F6C141 71%, #F6C141 78%, #F1932D 78%, #F1932D 85%, #E8601C 85%, #E8601C 92%, #DC050C 92%, #DC050C 100%)",
}
}
/>
</button>
<div
className="euiFormControlLayoutIcons euiFormControlLayoutIcons--right"
>
<span
className="euiFormControlLayoutCustomIcon"
>
<div
aria-hidden="true"
className="euiFormControlLayoutCustomIcon__icon"
data-euiicon-type="arrowDown"
/>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
`;

View file

@ -0,0 +1,32 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { storiesOf } from '@storybook/react';
import React from 'react';
import { action } from '@storybook/addon-actions';
import { PaletteArgInput } from '../palette';
import { paulTor14 } from '../../../../common/lib/palettes';
storiesOf('arguments/Palette', module).add('default', () => (
<div className="canvasContainerWrapper" style={{ width: '200px' }}>
<PaletteArgInput
argValue={{
type: 'expression',
chain: [
{
arguments: {
_: paulTor14.colors,
gradient: [paulTor14.gradient],
},
function: 'palette',
type: 'function',
},
],
}}
onValueChange={action('onValueChange')}
renderError={action('renderError')}
/>
</div>
));

View file

@ -15,7 +15,6 @@ import { imageUpload } from './image_upload';
// @ts-expect-error untyped local
import { number } from './number';
import { numberFormatInitializer } from './number_format';
// @ts-expect-error untyped local
import { palette } from './palette';
// @ts-expect-error untyped local
import { percentage } from './percentage';

View file

@ -4,45 +4,63 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import React, { FC } from 'react';
import PropTypes from 'prop-types';
import { get } from 'lodash';
import { getType } from '@kbn/interpreter/common';
import { ExpressionAstFunction, ExpressionAstExpression } from 'src/plugins/expressions';
import { PalettePicker } from '../../../public/components/palette_picker';
import { templateFromReactComponent } from '../../../public/lib/template_from_react_component';
import { ArgumentStrings } from '../../../i18n';
import { identifyPalette, ColorPalette } from '../../../common/lib';
const { Palette: strings } = ArgumentStrings;
const PaletteArgInput = ({ onValueChange, argValue, renderError }) => {
// Why is this neccesary? Does the dialog really need to know what parameter it is setting?
const throwNotParsed = () => renderError();
interface Props {
onValueChange: (value: ExpressionAstExpression) => void;
argValue: ExpressionAstExpression;
renderError: () => void;
argId?: string;
}
export const PaletteArgInput: FC<Props> = ({ onValueChange, argId, argValue, renderError }) => {
// TODO: This is weird, its basically a reimplementation of what the interpretter would return.
// Probably a better way todo this, and maybe a better way to handle template stype objects in general?
function astToPalette({ chain }) {
// Probably a better way todo this, and maybe a better way to handle template type objects in general?
const astToPalette = ({ chain }: { chain: ExpressionAstFunction[] }): ColorPalette | null => {
if (chain.length !== 1 || chain[0].function !== 'palette') {
throwNotParsed();
renderError();
return null;
}
try {
const colors = chain[0].arguments._.map((astObj) => {
if (getType(astObj) !== 'string') {
throwNotParsed();
renderError();
}
return astObj;
});
}) as string[];
const gradient = get(chain[0].arguments.gradient, '[0]');
const gradient = get<boolean>(chain[0].arguments.gradient, '[0]');
const palette = identifyPalette({ colors, gradient });
return { colors, gradient };
if (palette) {
return palette;
}
return ({
id: 'custom',
label: strings.getCustomPaletteLabel(),
colors,
gradient,
} as any) as ColorPalette;
} catch (e) {
throwNotParsed();
renderError();
}
}
return null;
};
function handleChange(palette) {
const astObj = {
const handleChange = (palette: ColorPalette): void => {
const astObj: ExpressionAstExpression = {
type: 'expression',
chain: [
{
@ -57,16 +75,20 @@ const PaletteArgInput = ({ onValueChange, argValue, renderError }) => {
};
onValueChange(astObj);
}
};
const palette = astToPalette(argValue);
return (
<PalettePicker value={palette} onChange={handleChange} ariaLabel={strings.getDisplayName()} />
);
if (!palette) {
renderError();
return null;
}
return <PalettePicker id={argId} palette={palette} onChange={handleChange} />;
};
PaletteArgInput.propTypes = {
argId: PropTypes.string,
onValueChange: PropTypes.func.isRequired,
argValue: PropTypes.any.isRequired,
renderError: PropTypes.func,

View file

@ -26,7 +26,6 @@ export * from './hex_to_rgb';
export * from './httpurl';
// @ts-expect-error missing local definition
export * from './missing_asset';
// @ts-expect-error missing local definition
export * from './palettes';
export * from './pivot_object_array';
// @ts-expect-error missing local definition

View file

@ -1,152 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
/*
This should be pluggable
*/
export const palettes = {
paul_tor_14: {
colors: [
'#882E72',
'#B178A6',
'#D6C1DE',
'#1965B0',
'#5289C7',
'#7BAFDE',
'#4EB265',
'#90C987',
'#CAE0AB',
'#F7EE55',
'#F6C141',
'#F1932D',
'#E8601C',
'#DC050C',
],
gradient: false,
},
paul_tor_21: {
colors: [
'#771155',
'#AA4488',
'#CC99BB',
'#114477',
'#4477AA',
'#77AADD',
'#117777',
'#44AAAA',
'#77CCCC',
'#117744',
'#44AA77',
'#88CCAA',
'#777711',
'#AAAA44',
'#DDDD77',
'#774411',
'#AA7744',
'#DDAA77',
'#771122',
'#AA4455',
'#DD7788',
],
gradient: false,
},
earth_tones: {
colors: [
'#842113',
'#984d23',
'#32221c',
'#739379',
'#dab150',
'#4d2521',
'#716c49',
'#bb3918',
'#7e5436',
'#c27c34',
'#72392e',
'#8f8b7e',
],
gradient: false,
},
canvas: {
colors: [
'#01A4A4',
'#CC6666',
'#D0D102',
'#616161',
'#00A1CB',
'#32742C',
'#F18D05',
'#113F8C',
'#61AE24',
'#D70060',
],
gradient: false,
},
color_blind: {
colors: [
'#1ea593',
'#2b70f7',
'#ce0060',
'#38007e',
'#fca5d3',
'#f37020',
'#e49e29',
'#b0916f',
'#7b000b',
'#34130c',
],
gradient: false,
},
elastic_teal: {
colors: ['#C5FAF4', '#0F6259'],
gradient: true,
},
elastic_blue: {
colors: ['#7ECAE3', '#003A4D'],
gradient: true,
},
elastic_yellow: {
colors: ['#FFE674', '#4D3F00'],
gradient: true,
},
elastic_pink: {
colors: ['#FEA8D5', '#531E3A'],
gradient: true,
},
elastic_green: {
colors: ['#D3FB71', '#131A00'],
gradient: true,
},
elastic_orange: {
colors: ['#FFC68A', '#7B3F00'],
gradient: true,
},
elastic_purple: {
colors: ['#CCC7DF', '#130351'],
gradient: true,
},
green_blue_red: {
colors: ['#D3FB71', '#7ECAE3', '#f03b20'],
gradient: true,
},
yellow_green: {
colors: ['#f7fcb9', '#addd8e', '#31a354'],
gradient: true,
},
yellow_blue: {
colors: ['#edf8b1', '#7fcdbb', '#2c7fb8'],
gradient: true,
},
yellow_red: {
colors: ['#ffeda0', '#feb24c', '#f03b20'],
gradient: true,
},
instagram: {
colors: ['#833ab4', '#fd1d1d', '#fcb045'],
gradient: true,
},
};

View file

@ -0,0 +1,263 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { isEqual } from 'lodash';
import { LibStrings } from '../../i18n';
const { Palettes: strings } = LibStrings;
/**
* This type contains a unions of all supported palette ids.
*/
export type PaletteID = typeof palettes[number]['id'];
/**
* An interface representing a color palette in Canvas, with a textual label and a set of
* hex values.
*/
export interface ColorPalette {
id: PaletteID;
label: string;
colors: string[];
gradient: boolean;
}
// This function allows one to create a strongly-typed palette for inclusion in
// the palette collection. As a result, the values and labels are known to the
// type system, preventing one from specifying a non-existent palette at build
// time.
function createPalette<
RawPalette extends {
id: RawPaletteID;
},
RawPaletteID extends string
>(palette: RawPalette) {
return palette;
}
/**
* Return a palette given a set of colors and gradient. Returns undefined if the
* palette doesn't match.
*/
export const identifyPalette = (
input: Pick<ColorPalette, 'colors' | 'gradient'>
): ColorPalette | undefined => {
return palettes.find((palette) => {
const { colors, gradient } = palette;
return gradient === input.gradient && isEqual(colors, input.colors);
});
};
export const paulTor14 = createPalette({
id: 'paul_tor_14',
label: 'Paul Tor 14',
colors: [
'#882E72',
'#B178A6',
'#D6C1DE',
'#1965B0',
'#5289C7',
'#7BAFDE',
'#4EB265',
'#90C987',
'#CAE0AB',
'#F7EE55',
'#F6C141',
'#F1932D',
'#E8601C',
'#DC050C',
],
gradient: false,
});
export const paulTor21 = createPalette({
id: 'paul_tor_21',
label: 'Paul Tor 21',
colors: [
'#771155',
'#AA4488',
'#CC99BB',
'#114477',
'#4477AA',
'#77AADD',
'#117777',
'#44AAAA',
'#77CCCC',
'#117744',
'#44AA77',
'#88CCAA',
'#777711',
'#AAAA44',
'#DDDD77',
'#774411',
'#AA7744',
'#DDAA77',
'#771122',
'#AA4455',
'#DD7788',
],
gradient: false,
});
export const earthTones = createPalette({
id: 'earth_tones',
label: strings.getEarthTones(),
colors: [
'#842113',
'#984d23',
'#32221c',
'#739379',
'#dab150',
'#4d2521',
'#716c49',
'#bb3918',
'#7e5436',
'#c27c34',
'#72392e',
'#8f8b7e',
],
gradient: false,
});
export const canvas = createPalette({
id: 'canvas',
label: strings.getCanvas(),
colors: [
'#01A4A4',
'#CC6666',
'#D0D102',
'#616161',
'#00A1CB',
'#32742C',
'#F18D05',
'#113F8C',
'#61AE24',
'#D70060',
],
gradient: false,
});
export const colorBlind = createPalette({
id: 'color_blind',
label: strings.getColorBlind(),
colors: [
'#1ea593',
'#2b70f7',
'#ce0060',
'#38007e',
'#fca5d3',
'#f37020',
'#e49e29',
'#b0916f',
'#7b000b',
'#34130c',
],
gradient: false,
});
export const elasticTeal = createPalette({
id: 'elastic_teal',
label: strings.getElasticTeal(),
colors: ['#7ECAE3', '#003A4D'],
gradient: true,
});
export const elasticBlue = createPalette({
id: 'elastic_blue',
label: strings.getElasticBlue(),
colors: ['#C5FAF4', '#0F6259'],
gradient: true,
});
export const elasticYellow = createPalette({
id: 'elastic_yellow',
label: strings.getElasticYellow(),
colors: ['#FFE674', '#4D3F00'],
gradient: true,
});
export const elasticPink = createPalette({
id: 'elastic_pink',
label: strings.getElasticPink(),
colors: ['#FEA8D5', '#531E3A'],
gradient: true,
});
export const elasticGreen = createPalette({
id: 'elastic_green',
label: strings.getElasticGreen(),
colors: ['#D3FB71', '#131A00'],
gradient: true,
});
export const elasticOrange = createPalette({
id: 'elastic_orange',
label: strings.getElasticOrange(),
colors: ['#FFC68A', '#7B3F00'],
gradient: true,
});
export const elasticPurple = createPalette({
id: 'elastic_purple',
label: strings.getElasticPurple(),
colors: ['#CCC7DF', '#130351'],
gradient: true,
});
export const greenBlueRed = createPalette({
id: 'green_blue_red',
label: strings.getGreenBlueRed(),
colors: ['#D3FB71', '#7ECAE3', '#f03b20'],
gradient: true,
});
export const yellowGreen = createPalette({
id: 'yellow_green',
label: strings.getYellowGreen(),
colors: ['#f7fcb9', '#addd8e', '#31a354'],
gradient: true,
});
export const yellowBlue = createPalette({
id: 'yellow_blue',
label: strings.getYellowBlue(),
colors: ['#edf8b1', '#7fcdbb', '#2c7fb8'],
gradient: true,
});
export const yellowRed = createPalette({
id: 'yellow_red',
label: strings.getYellowRed(),
colors: ['#ffeda0', '#feb24c', '#f03b20'],
gradient: true,
});
export const instagram = createPalette({
id: 'instagram',
label: strings.getInstagram(),
colors: ['#833ab4', '#fd1d1d', '#fcb045'],
gradient: true,
});
export const palettes = [
paulTor14,
paulTor21,
earthTones,
canvas,
colorBlind,
elasticTeal,
elasticBlue,
elasticYellow,
elasticPink,
elasticGreen,
elasticOrange,
elasticPurple,
greenBlueRed,
yellowGreen,
yellowBlue,
yellowRed,
instagram,
];

View file

@ -586,6 +586,16 @@ export const ComponentStrings = {
defaultMessage: 'Delete',
}),
},
PalettePicker: {
getEmptyPaletteLabel: () =>
i18n.translate('xpack.canvas.palettePicker.emptyPaletteLabel', {
defaultMessage: 'None',
}),
getNoPaletteFoundErrorTitle: () =>
i18n.translate('xpack.canvas.palettePicker.noPaletteFoundErrorTitle', {
defaultMessage: 'Color palette not found',
}),
},
SavedElementsModal: {
getAddNewElementDescription: () =>
i18n.translate('xpack.canvas.savedElementsModal.addNewElementDescription', {

View file

@ -20,6 +20,7 @@ export const FONT_FAMILY = '`font-family`';
export const FONT_WEIGHT = '`font-weight`';
export const HEX = 'HEX';
export const HTML = 'HTML';
export const INSTAGRAM = 'Instagram';
export const ISO8601 = 'ISO8601';
export const JS = 'JavaScript';
export const JSON = 'JSON';

View file

@ -11,6 +11,7 @@ export * from './errors';
export * from './expression_types';
export * from './elements';
export * from './functions';
export * from './lib';
export * from './renderers';
export * from './shortcuts';
export * from './tags';

View file

@ -0,0 +1,92 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { i18n } from '@kbn/i18n';
import { CANVAS, INSTAGRAM } from './constants';
export const LibStrings = {
Palettes: {
getEarthTones: () =>
i18n.translate('xpack.canvas.lib.palettes.earthTonesLabel', {
defaultMessage: 'Earth Tones',
}),
getCanvas: () =>
i18n.translate('xpack.canvas.lib.palettes.canvasLabel', {
defaultMessage: '{CANVAS}',
values: {
CANVAS,
},
}),
getColorBlind: () =>
i18n.translate('xpack.canvas.lib.palettes.colorBlindLabel', {
defaultMessage: 'Color Blind',
}),
getElasticTeal: () =>
i18n.translate('xpack.canvas.lib.palettes.elasticTealLabel', {
defaultMessage: 'Elastic Teal',
}),
getElasticBlue: () =>
i18n.translate('xpack.canvas.lib.palettes.elasticBlueLabel', {
defaultMessage: 'Elastic Blue',
}),
getElasticYellow: () =>
i18n.translate('xpack.canvas.lib.palettes.elasticYellowLabel', {
defaultMessage: 'Elastic Yellow',
}),
getElasticPink: () =>
i18n.translate('xpack.canvas.lib.palettes.elasticPinkLabel', {
defaultMessage: 'Elastic Pink',
}),
getElasticGreen: () =>
i18n.translate('xpack.canvas.lib.palettes.elasticGreenLabel', {
defaultMessage: 'Elastic Green',
}),
getElasticOrange: () =>
i18n.translate('xpack.canvas.lib.palettes.elasticOrangeLabel', {
defaultMessage: 'Elastic Orange',
}),
getElasticPurple: () =>
i18n.translate('xpack.canvas.lib.palettes.elasticPurpleLabel', {
defaultMessage: 'Elastic Purple',
}),
getGreenBlueRed: () =>
i18n.translate('xpack.canvas.lib.palettes.greenBlueRedLabel', {
defaultMessage: 'Green, Blue, Red',
}),
getYellowGreen: () =>
i18n.translate('xpack.canvas.lib.palettes.yellowGreenLabel', {
defaultMessage: 'Yellow, Green',
}),
getYellowBlue: () =>
i18n.translate('xpack.canvas.lib.palettes.yellowBlueLabel', {
defaultMessage: 'Yellow, Blue',
}),
getYellowRed: () =>
i18n.translate('xpack.canvas.lib.palettes.yellowRedLabel', {
defaultMessage: 'Yellow, Red',
}),
getInstagram: () =>
i18n.translate('xpack.canvas.lib.palettes.instagramLabel', {
defaultMessage: '{INSTAGRAM}',
values: {
INSTAGRAM,
},
}),
},
};

View file

@ -232,7 +232,11 @@ export const ArgumentStrings = {
}),
getHelp: () =>
i18n.translate('xpack.canvas.uis.arguments.paletteLabel', {
defaultMessage: 'Choose a color palette',
defaultMessage: 'The collection of colors used to render the element',
}),
getCustomPaletteLabel: () =>
i18n.translate('xpack.canvas.uis.arguments.customPaletteLabel', {
defaultMessage: 'Custom',
}),
},
Percentage: {

View file

@ -0,0 +1,237 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Storyshots components/Color/PalettePicker clearable 1`] = `
<div
style={
Object {
"width": "350px",
}
}
>
<div
className="euiPopover euiPopover--anchorDownCenter euiPopover--displayBlock euiSuperSelect"
onKeyDown={[Function]}
onMouseDown={[Function]}
onMouseUp={[Function]}
onTouchEnd={[Function]}
onTouchStart={[Function]}
>
<div
className="euiPopover__anchor"
>
<input
type="hidden"
value="clear"
/>
<div
className="euiFormControlLayout euiFormControlLayout--compressed"
>
<div
className="euiFormControlLayout__childrenWrapper"
>
<span
className="euiScreenReaderOnly"
id="generated-id"
>
Select an option: None, is selected
</span>
<button
aria-haspopup="true"
aria-labelledby="undefined generated-id"
aria-selected={true}
className="euiSuperSelectControl euiSuperSelectControl--compressed"
onClick={[Function]}
onKeyDown={[Function]}
readOnly={false}
role="option"
type="button"
>
None
</button>
<div
className="euiFormControlLayoutIcons euiFormControlLayoutIcons--right"
>
<span
className="euiFormControlLayoutCustomIcon"
>
<div
aria-hidden="true"
className="euiFormControlLayoutCustomIcon__icon"
data-euiicon-type="arrowDown"
/>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`Storyshots components/Color/PalettePicker default 1`] = `
<div
style={
Object {
"width": "350px",
}
}
>
<div
className="euiPopover euiPopover--anchorDownCenter euiPopover--displayBlock euiSuperSelect"
onKeyDown={[Function]}
onMouseDown={[Function]}
onMouseUp={[Function]}
onTouchEnd={[Function]}
onTouchStart={[Function]}
>
<div
className="euiPopover__anchor"
>
<input
type="hidden"
value="paul_tor_14"
/>
<div
className="euiFormControlLayout euiFormControlLayout--compressed"
>
<div
className="euiFormControlLayout__childrenWrapper"
>
<span
className="euiScreenReaderOnly"
id="generated-id"
>
Select an option:
<div
className="euiColorPalettePicker__itemGradient"
style={
Object {
"background": "linear-gradient(to right, #882E72 0%, #882E72 7%, #B178A6 7%, #B178A6 14%, #D6C1DE 14%, #D6C1DE 21%, #1965B0 21%, #1965B0 28%, #5289C7 28%, #5289C7 35%, #7BAFDE 35%, #7BAFDE 42%, #4EB265 42%, #4EB265 50%, #90C987 50%, #90C987 57%, #CAE0AB 57%, #CAE0AB 64%, #F7EE55 64%, #F7EE55 71%, #F6C141 71%, #F6C141 78%, #F1932D 78%, #F1932D 85%, #E8601C 85%, #E8601C 92%, #DC050C 92%, #DC050C 100%)",
}
}
/>
, is selected
</span>
<button
aria-haspopup="true"
aria-labelledby="undefined generated-id"
aria-selected={true}
className="euiSuperSelectControl euiSuperSelectControl--compressed"
onClick={[Function]}
onKeyDown={[Function]}
readOnly={false}
role="option"
type="button"
>
<div
className="euiColorPalettePicker__itemGradient"
style={
Object {
"background": "linear-gradient(to right, #882E72 0%, #882E72 7%, #B178A6 7%, #B178A6 14%, #D6C1DE 14%, #D6C1DE 21%, #1965B0 21%, #1965B0 28%, #5289C7 28%, #5289C7 35%, #7BAFDE 35%, #7BAFDE 42%, #4EB265 42%, #4EB265 50%, #90C987 50%, #90C987 57%, #CAE0AB 57%, #CAE0AB 64%, #F7EE55 64%, #F7EE55 71%, #F6C141 71%, #F6C141 78%, #F1932D 78%, #F1932D 85%, #E8601C 85%, #E8601C 92%, #DC050C 92%, #DC050C 100%)",
}
}
/>
</button>
<div
className="euiFormControlLayoutIcons euiFormControlLayoutIcons--right"
>
<span
className="euiFormControlLayoutCustomIcon"
>
<div
aria-hidden="true"
className="euiFormControlLayoutCustomIcon__icon"
data-euiicon-type="arrowDown"
/>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`Storyshots components/Color/PalettePicker interactive 1`] = `
<div
style={
Object {
"width": "350px",
}
}
>
<div
className="euiPopover euiPopover--anchorDownCenter euiPopover--displayBlock euiSuperSelect"
onKeyDown={[Function]}
onMouseDown={[Function]}
onMouseUp={[Function]}
onTouchEnd={[Function]}
onTouchStart={[Function]}
>
<div
className="euiPopover__anchor"
>
<input
type="hidden"
value="paul_tor_14"
/>
<div
className="euiFormControlLayout euiFormControlLayout--compressed"
>
<div
className="euiFormControlLayout__childrenWrapper"
>
<span
className="euiScreenReaderOnly"
id="generated-id"
>
Select an option:
<div
className="euiColorPalettePicker__itemGradient"
style={
Object {
"background": "linear-gradient(to right, #882E72 0%, #882E72 7%, #B178A6 7%, #B178A6 14%, #D6C1DE 14%, #D6C1DE 21%, #1965B0 21%, #1965B0 28%, #5289C7 28%, #5289C7 35%, #7BAFDE 35%, #7BAFDE 42%, #4EB265 42%, #4EB265 50%, #90C987 50%, #90C987 57%, #CAE0AB 57%, #CAE0AB 64%, #F7EE55 64%, #F7EE55 71%, #F6C141 71%, #F6C141 78%, #F1932D 78%, #F1932D 85%, #E8601C 85%, #E8601C 92%, #DC050C 92%, #DC050C 100%)",
}
}
/>
, is selected
</span>
<button
aria-haspopup="true"
aria-labelledby="undefined generated-id"
aria-selected={true}
className="euiSuperSelectControl euiSuperSelectControl--compressed"
onClick={[Function]}
onKeyDown={[Function]}
readOnly={false}
role="option"
type="button"
>
<div
className="euiColorPalettePicker__itemGradient"
style={
Object {
"background": "linear-gradient(to right, #882E72 0%, #882E72 7%, #B178A6 7%, #B178A6 14%, #D6C1DE 14%, #D6C1DE 21%, #1965B0 21%, #1965B0 28%, #5289C7 28%, #5289C7 35%, #7BAFDE 35%, #7BAFDE 42%, #4EB265 42%, #4EB265 50%, #90C987 50%, #90C987 57%, #CAE0AB 57%, #CAE0AB 64%, #F7EE55 64%, #F7EE55 71%, #F6C141 71%, #F6C141 78%, #F1932D 78%, #F1932D 85%, #E8601C 85%, #E8601C 92%, #DC050C 92%, #DC050C 100%)",
}
}
/>
</button>
<div
className="euiFormControlLayoutIcons euiFormControlLayoutIcons--right"
>
<span
className="euiFormControlLayoutCustomIcon"
>
<div
aria-hidden="true"
className="euiFormControlLayoutCustomIcon__icon"
data-euiicon-type="arrowDown"
/>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
`;

View file

@ -0,0 +1,25 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React, { FC, useState } from 'react';
import { action } from '@storybook/addon-actions';
import { storiesOf } from '@storybook/react';
import { PalettePicker } from '../palette_picker';
import { paulTor14, ColorPalette } from '../../../../common/lib/palettes';
const Interactive: FC = () => {
const [palette, setPalette] = useState<ColorPalette | null>(paulTor14);
return <PalettePicker palette={palette} onChange={setPalette} clearable={true} />;
};
storiesOf('components/Color/PalettePicker', module)
.addDecorator((fn) => <div style={{ width: '350px' }}>{fn()}</div>)
.add('default', () => <PalettePicker palette={paulTor14} onChange={action('onChange')} />)
.add('clearable', () => (
<PalettePicker palette={null} onChange={action('onChange')} clearable={true} />
))
.add('interactive', () => <Interactive />);

View file

@ -1,11 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { pure } from 'recompose';
import { PalettePicker as Component } from './palette_picker';
export const PalettePicker = pure(Component);

View file

@ -4,8 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { pure } from 'recompose';
import { PaletteSwatch as Component } from './palette_swatch';
export const PaletteSwatch = pure(Component);
export { PalettePicker } from './palette_picker';

View file

@ -1,60 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import PropTypes from 'prop-types';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { map } from 'lodash';
import { Popover } from '../popover';
import { PaletteSwatch } from '../palette_swatch';
import { palettes } from '../../../common/lib/palettes';
export const PalettePicker = ({ onChange, value, anchorPosition, ariaLabel }) => {
const button = (handleClick) => (
<button aria-label={ariaLabel} style={{ width: '100%', height: 16 }} onClick={handleClick}>
<PaletteSwatch colors={value.colors} gradient={value.gradient} />
</button>
);
return (
<Popover
id="palette-picker-popover"
button={button}
anchorPosition={anchorPosition}
panelClassName="canvasPalettePicker__swatchesPanel"
className="canvasPalettePicker__swatchesPopover"
anchorClassName="canvasPalettePicker__swatchesPopoverAnchor"
>
{() => (
<div className="canvas canvasPalettePicker__swatches">
{map(palettes, (palette, name) => (
<button
key={name}
onClick={() => onChange(palette)}
className="canvasPalettePicker__swatch"
style={{ width: '100%' }}
>
<EuiFlexGroup gutterSize="s" alignItems="center">
<EuiFlexItem grow={1}>
<span className="canvasPalettePicker__label">{name.replace(/_/g, ' ')}</span>
</EuiFlexItem>
<EuiFlexItem grow={2}>
<PaletteSwatch colors={palette.colors} gradient={palette.gradient} />
</EuiFlexItem>
</EuiFlexGroup>
</button>
))}
</div>
)}
</Popover>
);
};
PalettePicker.propTypes = {
value: PropTypes.object,
onChange: PropTypes.func,
anchorPosition: PropTypes.string,
};

View file

@ -1,42 +0,0 @@
.canvasPalettePicker {
display: inline-block;
width: 100%;
}
.canvasPalettePicker__swatches {
@include euiScrollBar;
width: 280px;
height: 250px;
overflow-y: scroll;
}
.canvasPalettePicker__swatchesPanel {
padding: $euiSizeS 0 !important; // sass-lint:disable-line no-important
}
.canvasPalettePicker__swatch {
padding: $euiSizeS $euiSize;
&:hover,
&:focus {
text-decoration: underline;
background-color: $euiColorLightestShade;
.canvasPaletteSwatch,
.canvasPaletteSwatch__background {
transform: scaleY(2);
}
.canvasPalettePicker__label {
color: $euiTextColor;
}
}
}
.canvasPalettePicker__label {
font-size: $euiFontSizeXS;
text-transform: capitalize;
text-align: left;
color: $euiColorDarkShade;
}

View file

@ -0,0 +1,92 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React, { FC } from 'react';
import PropTypes from 'prop-types';
import { EuiColorPalettePicker, EuiColorPalettePickerPaletteProps } from '@elastic/eui';
import { palettes, ColorPalette } from '../../../common/lib/palettes';
import { ComponentStrings } from '../../../i18n';
const { PalettePicker: strings } = ComponentStrings;
interface RequiredProps {
id?: string;
onChange?: (palette: ColorPalette) => void;
palette: ColorPalette;
clearable?: false;
}
interface ClearableProps {
id?: string;
onChange?: (palette: ColorPalette | null) => void;
palette: ColorPalette | null;
clearable: true;
}
type Props = RequiredProps | ClearableProps;
export const PalettePicker: FC<Props> = (props) => {
const colorPalettes: EuiColorPalettePickerPaletteProps[] = palettes.map((item) => ({
value: item.id,
title: item.label,
type: item.gradient ? 'gradient' : 'fixed',
palette: item.colors,
}));
if (props.clearable) {
const { palette, onChange = () => {} } = props;
colorPalettes.unshift({
value: 'clear',
title: strings.getEmptyPaletteLabel(),
type: 'text',
});
const onPickerChange = (value: string) => {
const canvasPalette = palettes.find((item) => item.id === value);
onChange(canvasPalette || null);
};
return (
<EuiColorPalettePicker
id={props.id}
compressed={true}
palettes={colorPalettes}
onChange={onPickerChange}
valueOfSelected={palette ? palette.id : 'clear'}
/>
);
}
const { palette, onChange = () => {} } = props;
const onPickerChange = (value: string) => {
const canvasPalette = palettes.find((item) => item.id === value);
if (!canvasPalette) {
throw new Error(strings.getNoPaletteFoundErrorTitle());
}
onChange(canvasPalette);
};
return (
<EuiColorPalettePicker
id={props.id}
compressed={true}
palettes={colorPalettes}
onChange={onPickerChange}
valueOfSelected={palette.id}
/>
);
};
PalettePicker.propTypes = {
id: PropTypes.string,
palette: PropTypes.object,
onChange: PropTypes.func,
clearable: PropTypes.bool,
};

View file

@ -1,46 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import PropTypes from 'prop-types';
export const PaletteSwatch = ({ colors, gradient }) => {
let colorBoxes;
if (!gradient) {
colorBoxes = colors.map((color) => (
<div
key={color}
className="canvasPaletteSwatch__box"
style={{
backgroundColor: color,
}}
/>
));
} else {
colorBoxes = [
<div
key="gradient"
className="canvasPaletteSwatch__box"
style={{
background: `linear-gradient(90deg, ${colors.join(', ')})`,
}}
/>,
];
}
return (
<div className="canvasPaletteSwatch">
<div className="canvasPaletteSwatch__background canvasCheckered" />
<div className="canvasPaletteSwatch__foreground">{colorBoxes}</div>
</div>
);
};
PaletteSwatch.propTypes = {
colors: PropTypes.array,
gradient: PropTypes.bool,
};

View file

@ -1,35 +0,0 @@
.canvasPaletteSwatch {
display: inline-block;
position: relative;
height: $euiSizeXS;
width: 100%;
overflow: hidden;
text-align: left;
transform: scaleY(1);
transition: transform $euiAnimSlightResistance $euiAnimSpeedExtraFast;
.canvasPaletteSwatch__background {
position: absolute;
height: $euiSizeXS;
top: 0;
left: 0;
width: 100%;
transform: scaleY(1);
transition: transform $euiAnimSlightResistance $euiAnimSpeedExtraFast;
}
.canvasPaletteSwatch__foreground {
position: absolute;
height: 100%; // TODO: No idea why this can't be 25, but it leaves a 1px white spot in the palettePicker if its 25
top: 0;
left: 0;
white-space: nowrap;
width: 100%;
display: flex;
}
.canvasPaletteSwatch__box {
display: inline-block;
width: 100%;
}
}

View file

@ -39,8 +39,6 @@
@import '../components/loading/loading';
@import '../components/navbar/navbar';
@import '../components/page_manager/page_manager';
@import '../components/palette_picker/palette_picker';
@import '../components/palette_swatch/palette_swatch';
@import '../components/positionable/positionable';
@import '../components/rotation_handle/rotation_handle';
@import '../components/shape_preview/shape_preview';