mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[canvas] Color Widgets - TS + Examples (#31391)
* [canvas] Color Widgets - TS + Examples * Addressing feedback
This commit is contained in:
parent
4309a8b4fd
commit
a807511d59
29 changed files with 4018 additions and 178 deletions
|
@ -111,6 +111,7 @@
|
|||
"@kbn/ui-framework": "1.0.0",
|
||||
"@types/json-stable-stringify": "^1.0.32",
|
||||
"@types/lodash.clonedeep": "^4.5.4",
|
||||
"@types/recompose": "^0.30.5",
|
||||
"JSONStream": "1.1.1",
|
||||
"abortcontroller-polyfill": "^1.1.9",
|
||||
"angular": "1.6.9",
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
"@storybook/react": "^4.0.7",
|
||||
"@types/angular": "1.6.50",
|
||||
"@types/cheerio": "^0.22.10",
|
||||
"@types/chroma-js": "^1.4.1",
|
||||
"@types/color": "^3.0.0",
|
||||
"@types/d3-array": "^1.2.1",
|
||||
"@types/d3-scale": "^2.0.0",
|
||||
"@types/d3-shape": "^1.3.1",
|
||||
|
@ -65,6 +67,7 @@
|
|||
"@types/storybook__addon-info": "^3.4.2",
|
||||
"@types/storybook__react": "^4.0.0",
|
||||
"@types/supertest": "^2.0.5",
|
||||
"@types/tinycolor2": "^1.4.1",
|
||||
"@types/uuid": "^3.4.4",
|
||||
"abab": "^1.0.4",
|
||||
"ansi-colors": "^3.0.5",
|
||||
|
|
|
@ -0,0 +1,209 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Storyshots components/ColorDot color dots 1`] = `
|
||||
Array [
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "rgb(255, 255, 255)",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>,
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "rgb(100, 150, 250)",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>,
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "rgba(100, 150, 250, 0.5)",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>,
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "rgb(0, 0, 0)",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Storyshots components/ColorDot color dots with children 1`] = `
|
||||
Array [
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "rgb(255, 255, 255)",
|
||||
}
|
||||
}
|
||||
>
|
||||
<svg
|
||||
className="euiIcon euiIcon--medium"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={
|
||||
Object {
|
||||
"fill": "#000",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M8 7h3.5a.5.5 0 1 1 0 1H8v3.5a.5.5 0 1 1-1 0V8H3.5a.5.5 0 0 1 0-1H7V3.5a.5.5 0 0 1 1 0V7zm-.5-7C11.636 0 15 3.364 15 7.5S11.636 15 7.5 15 0 11.636 0 7.5 3.364 0 7.5 0zm0 .882a6.618 6.618 0 1 0 0 13.236A6.618 6.618 0 0 0 7.5.882z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "rgb(102, 102, 102)",
|
||||
}
|
||||
}
|
||||
>
|
||||
<svg
|
||||
className="euiIcon euiIcon--medium"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={
|
||||
Object {
|
||||
"fill": "#fff",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M7.5 0C11.636 0 15 3.364 15 7.5S11.636 15 7.5 15 0 11.636 0 7.5 3.364 0 7.5 0zm0 .882a6.618 6.618 0 1 0 0 13.236A6.618 6.618 0 0 0 7.5.882zM3.5 7h8a.5.5 0 1 1 0 1h-8a.5.5 0 0 1 0-1z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "rgba(100, 150, 250, 0.5)",
|
||||
}
|
||||
}
|
||||
>
|
||||
<svg
|
||||
className="euiIcon euiIcon--medium"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={
|
||||
Object {
|
||||
"fill": "#fff",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M8.378 1.496l6.695 10.984A1 1 0 0 1 14.22 14H1.667a1 1 0 0 1-.883-1.47L6.642 1.545a1 1 0 0 1 1.736-.05zm-.853.52L1.667 13h12.552L7.525 2.016zM7.14 10.06L6.9 5.18h1.3l-.25 4.878h-.81zm.394 1.901a.61.61 0 0 1-.448-.186.606.606 0 0 1-.186-.444c0-.174.062-.323.186-.446a.614.614 0 0 1 .448-.184c.169 0 .315.06.44.182.124.122.186.27.186.448a.6.6 0 0 1-.189.446.607.607 0 0 1-.437.184z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "rgb(0, 0, 0)",
|
||||
}
|
||||
}
|
||||
>
|
||||
<svg
|
||||
className="euiIcon euiIcon--medium"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={
|
||||
Object {
|
||||
"fill": "#fff",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M6.5 12a.502.502 0 0 1-.354-.146l-4-4a.502.502 0 0 1 .708-.708L6.5 10.793l6.646-6.647a.502.502 0 0 1 .708.708l-7 7A.502.502 0 0 1 6.5 12"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Storyshots components/ColorDot invalid dots 1`] = `null`;
|
|
@ -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;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { EuiIcon } from '@elastic/eui';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import React from 'react';
|
||||
import { ColorDot } from '../color_dot';
|
||||
|
||||
storiesOf('components/ColorDot', module)
|
||||
.addParameters({ info: { propTablesExclude: [EuiIcon] } })
|
||||
.add('color dots', () => [
|
||||
<ColorDot key="1" value="white" />,
|
||||
<ColorDot key="2" value="rgb(100, 150, 250)" />,
|
||||
<ColorDot key="3" value="rgba(100, 150, 250, .5)" />,
|
||||
<ColorDot key="4" value="#000" />,
|
||||
])
|
||||
.add('invalid dots', () => [
|
||||
<ColorDot key="1" value="elastic" />,
|
||||
<ColorDot key="2" value="#canvas" />,
|
||||
<ColorDot key="3" value="#abcd" />,
|
||||
])
|
||||
.add('color dots with children', () => [
|
||||
<ColorDot key="1" value="#FFF">
|
||||
<EuiIcon type="plusInCircle" color="#000" />
|
||||
</ColorDot>,
|
||||
<ColorDot key="2" value="#666">
|
||||
<EuiIcon type="minusInCircle" color="#fff" />
|
||||
</ColorDot>,
|
||||
<ColorDot key="3" value="rgba(100, 150, 250, .5)">
|
||||
<EuiIcon type="alert" color="#fff" />
|
||||
</ColorDot>,
|
||||
<ColorDot key="4" value="#000">
|
||||
<EuiIcon type="check" color="#fff" />
|
||||
</ColorDot>,
|
||||
]);
|
|
@ -4,14 +4,27 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { ReactNode, SFC } from 'react';
|
||||
import tinycolor from 'tinycolor2';
|
||||
|
||||
export interface Props {
|
||||
/** Any valid CSS color. If not a valid CSS string, the dot will not render */
|
||||
value: string;
|
||||
/** Nodes to display within the dot. Should fit within the constraints. */
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
export const ColorDot: SFC<Props> = ({ value, children }) => {
|
||||
const tc = tinycolor(value);
|
||||
if (!tc.isValid()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
export const ColorDot = ({ value, children }) => {
|
||||
return (
|
||||
<div className="canvasColorDot">
|
||||
<div className="canvasColorDot__background canvasCheckered" />
|
||||
<div className="canvasColorDot__foreground" style={{ background: value }}>
|
||||
<div className="canvasColorDot__foreground" style={{ background: tc.toRgbString() }}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -21,5 +34,4 @@ export const ColorDot = ({ value, children }) => {
|
|||
ColorDot.propTypes = {
|
||||
value: PropTypes.string,
|
||||
children: PropTypes.node,
|
||||
handleClick: PropTypes.func,
|
||||
};
|
|
@ -0,0 +1,795 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Storyshots components/ColorManager default 1`] = `
|
||||
Array [
|
||||
<div
|
||||
className="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive"
|
||||
>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "rgb(171, 205, 239)",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
style={
|
||||
Object {
|
||||
"display": "inline-block",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="euiFormControlLayout"
|
||||
>
|
||||
<div
|
||||
className="euiFormControlLayout__childrenWrapper"
|
||||
>
|
||||
<input
|
||||
className="euiFieldText"
|
||||
onChange={[Function]}
|
||||
placeholder="#hex color"
|
||||
type="text"
|
||||
value="#abcdef"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<button
|
||||
aria-label="Add Color"
|
||||
className="euiButtonIcon euiButtonIcon--primary"
|
||||
disabled={true}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiButtonIcon__icon"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M8 7h3.5a.5.5 0 1 1 0 1H8v3.5a.5.5 0 1 1-1 0V8H3.5a.5.5 0 0 1 0-1H7V3.5a.5.5 0 0 1 1 0V7zm-.5-7C11.636 0 15 3.364 15 7.5S11.636 15 7.5 15 0 11.636 0 7.5 3.364 0 7.5 0zm0 .882a6.618 6.618 0 1 0 0 13.236A6.618 6.618 0 0 0 7.5.882z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Remove Color"
|
||||
className="euiButtonIcon euiButtonIcon--primary"
|
||||
disabled={true}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiButtonIcon__icon"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M7.5 0C11.636 0 15 3.364 15 7.5S11.636 15 7.5 15 0 11.636 0 7.5 3.364 0 7.5 0zm0 .882a6.618 6.618 0 1 0 0 13.236A6.618 6.618 0 0 0 7.5.882zM3.5 7h8a.5.5 0 1 1 0 1h-8a.5.5 0 0 1 0-1z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
className="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive"
|
||||
>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "rgb(170, 187, 204)",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
style={
|
||||
Object {
|
||||
"display": "inline-block",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="euiFormControlLayout"
|
||||
>
|
||||
<div
|
||||
className="euiFormControlLayout__childrenWrapper"
|
||||
>
|
||||
<input
|
||||
className="euiFieldText"
|
||||
onChange={[Function]}
|
||||
placeholder="#hex color"
|
||||
type="text"
|
||||
value="#abc"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<button
|
||||
aria-label="Add Color"
|
||||
className="euiButtonIcon euiButtonIcon--primary"
|
||||
disabled={true}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiButtonIcon__icon"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M8 7h3.5a.5.5 0 1 1 0 1H8v3.5a.5.5 0 1 1-1 0V8H3.5a.5.5 0 0 1 0-1H7V3.5a.5.5 0 0 1 1 0V7zm-.5-7C11.636 0 15 3.364 15 7.5S11.636 15 7.5 15 0 11.636 0 7.5 3.364 0 7.5 0zm0 .882a6.618 6.618 0 1 0 0 13.236A6.618 6.618 0 0 0 7.5.882z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Remove Color"
|
||||
className="euiButtonIcon euiButtonIcon--primary"
|
||||
disabled={true}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiButtonIcon__icon"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M7.5 0C11.636 0 15 3.364 15 7.5S11.636 15 7.5 15 0 11.636 0 7.5 3.364 0 7.5 0zm0 .882a6.618 6.618 0 1 0 0 13.236A6.618 6.618 0 0 0 7.5.882zM3.5 7h8a.5.5 0 1 1 0 1h-8a.5.5 0 0 1 0-1z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Storyshots components/ColorManager interactive 1`] = `
|
||||
<div
|
||||
className="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive"
|
||||
>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "rgba(255, 255, 255, 0)",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
style={
|
||||
Object {
|
||||
"display": "inline-block",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="euiFormControlLayout"
|
||||
>
|
||||
<div
|
||||
className="euiFormControlLayout__childrenWrapper"
|
||||
>
|
||||
<input
|
||||
className="euiFieldText"
|
||||
onChange={[Function]}
|
||||
placeholder="#hex color"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<button
|
||||
aria-label="Add Color"
|
||||
className="euiButtonIcon euiButtonIcon--primary"
|
||||
disabled={true}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiButtonIcon__icon"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M8 7h3.5a.5.5 0 1 1 0 1H8v3.5a.5.5 0 1 1-1 0V8H3.5a.5.5 0 0 1 0-1H7V3.5a.5.5 0 0 1 1 0V7zm-.5-7C11.636 0 15 3.364 15 7.5S11.636 15 7.5 15 0 11.636 0 7.5 3.364 0 7.5 0zm0 .882a6.618 6.618 0 1 0 0 13.236A6.618 6.618 0 0 0 7.5.882z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Remove Color"
|
||||
className="euiButtonIcon euiButtonIcon--primary"
|
||||
disabled={true}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiButtonIcon__icon"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M7.5 0C11.636 0 15 3.364 15 7.5S11.636 15 7.5 15 0 11.636 0 7.5 3.364 0 7.5 0zm0 .882a6.618 6.618 0 1 0 0 13.236A6.618 6.618 0 0 0 7.5.882zM3.5 7h8a.5.5 0 1 1 0 1h-8a.5.5 0 0 1 0-1z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Storyshots components/ColorManager invalid colors 1`] = `
|
||||
Array [
|
||||
<div
|
||||
className="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive"
|
||||
>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "rgba(255, 255, 255, 0)",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
style={
|
||||
Object {
|
||||
"display": "inline-block",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="euiFormControlLayout"
|
||||
>
|
||||
<div
|
||||
className="euiFormControlLayout__childrenWrapper"
|
||||
>
|
||||
<input
|
||||
className="euiFieldText"
|
||||
onChange={[Function]}
|
||||
placeholder="#hex color"
|
||||
type="text"
|
||||
value="#abcd"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<button
|
||||
aria-label="Add Color"
|
||||
className="euiButtonIcon euiButtonIcon--primary"
|
||||
disabled={true}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiButtonIcon__icon"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M8 7h3.5a.5.5 0 1 1 0 1H8v3.5a.5.5 0 1 1-1 0V8H3.5a.5.5 0 0 1 0-1H7V3.5a.5.5 0 0 1 1 0V7zm-.5-7C11.636 0 15 3.364 15 7.5S11.636 15 7.5 15 0 11.636 0 7.5 3.364 0 7.5 0zm0 .882a6.618 6.618 0 1 0 0 13.236A6.618 6.618 0 0 0 7.5.882z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Remove Color"
|
||||
className="euiButtonIcon euiButtonIcon--primary"
|
||||
disabled={true}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiButtonIcon__icon"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M7.5 0C11.636 0 15 3.364 15 7.5S11.636 15 7.5 15 0 11.636 0 7.5 3.364 0 7.5 0zm0 .882a6.618 6.618 0 1 0 0 13.236A6.618 6.618 0 0 0 7.5.882zM3.5 7h8a.5.5 0 1 1 0 1h-8a.5.5 0 0 1 0-1z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
className="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive"
|
||||
>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "rgba(255, 255, 255, 0)",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
style={
|
||||
Object {
|
||||
"display": "inline-block",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="euiFormControlLayout"
|
||||
>
|
||||
<div
|
||||
className="euiFormControlLayout__childrenWrapper"
|
||||
>
|
||||
<input
|
||||
className="euiFieldText"
|
||||
onChange={[Function]}
|
||||
placeholder="#hex color"
|
||||
type="text"
|
||||
value="#canvas"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<button
|
||||
aria-label="Add Color"
|
||||
className="euiButtonIcon euiButtonIcon--primary"
|
||||
disabled={true}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiButtonIcon__icon"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M8 7h3.5a.5.5 0 1 1 0 1H8v3.5a.5.5 0 1 1-1 0V8H3.5a.5.5 0 0 1 0-1H7V3.5a.5.5 0 0 1 1 0V7zm-.5-7C11.636 0 15 3.364 15 7.5S11.636 15 7.5 15 0 11.636 0 7.5 3.364 0 7.5 0zm0 .882a6.618 6.618 0 1 0 0 13.236A6.618 6.618 0 0 0 7.5.882z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Remove Color"
|
||||
className="euiButtonIcon euiButtonIcon--primary"
|
||||
disabled={true}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiButtonIcon__icon"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M7.5 0C11.636 0 15 3.364 15 7.5S11.636 15 7.5 15 0 11.636 0 7.5 3.364 0 7.5 0zm0 .882a6.618 6.618 0 1 0 0 13.236A6.618 6.618 0 0 0 7.5.882zM3.5 7h8a.5.5 0 1 1 0 1h-8a.5.5 0 0 1 0-1z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Storyshots components/ColorManager with buttons 1`] = `
|
||||
Array [
|
||||
<div
|
||||
className="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive"
|
||||
>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "rgb(171, 205, 239)",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
style={
|
||||
Object {
|
||||
"display": "inline-block",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="euiFormControlLayout"
|
||||
>
|
||||
<div
|
||||
className="euiFormControlLayout__childrenWrapper"
|
||||
>
|
||||
<input
|
||||
className="euiFieldText"
|
||||
onChange={[Function]}
|
||||
placeholder="#hex color"
|
||||
type="text"
|
||||
value="#abcdef"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<button
|
||||
aria-label="Add Color"
|
||||
className="euiButtonIcon euiButtonIcon--primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiButtonIcon__icon"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M8 7h3.5a.5.5 0 1 1 0 1H8v3.5a.5.5 0 1 1-1 0V8H3.5a.5.5 0 0 1 0-1H7V3.5a.5.5 0 0 1 1 0V7zm-.5-7C11.636 0 15 3.364 15 7.5S11.636 15 7.5 15 0 11.636 0 7.5 3.364 0 7.5 0zm0 .882a6.618 6.618 0 1 0 0 13.236A6.618 6.618 0 0 0 7.5.882z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Remove Color"
|
||||
className="euiButtonIcon euiButtonIcon--primary"
|
||||
disabled={true}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiButtonIcon__icon"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M7.5 0C11.636 0 15 3.364 15 7.5S11.636 15 7.5 15 0 11.636 0 7.5 3.364 0 7.5 0zm0 .882a6.618 6.618 0 1 0 0 13.236A6.618 6.618 0 0 0 7.5.882zM3.5 7h8a.5.5 0 1 1 0 1h-8a.5.5 0 0 1 0-1z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
className="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive"
|
||||
>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "rgb(171, 205, 239)",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
style={
|
||||
Object {
|
||||
"display": "inline-block",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="euiFormControlLayout"
|
||||
>
|
||||
<div
|
||||
className="euiFormControlLayout__childrenWrapper"
|
||||
>
|
||||
<input
|
||||
className="euiFieldText"
|
||||
onChange={[Function]}
|
||||
placeholder="#hex color"
|
||||
type="text"
|
||||
value="#abcdef"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<button
|
||||
aria-label="Add Color"
|
||||
className="euiButtonIcon euiButtonIcon--primary"
|
||||
disabled={true}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiButtonIcon__icon"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M8 7h3.5a.5.5 0 1 1 0 1H8v3.5a.5.5 0 1 1-1 0V8H3.5a.5.5 0 0 1 0-1H7V3.5a.5.5 0 0 1 1 0V7zm-.5-7C11.636 0 15 3.364 15 7.5S11.636 15 7.5 15 0 11.636 0 7.5 3.364 0 7.5 0zm0 .882a6.618 6.618 0 1 0 0 13.236A6.618 6.618 0 0 0 7.5.882z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Remove Color"
|
||||
className="euiButtonIcon euiButtonIcon--primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiButtonIcon__icon"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M7.5 0C11.636 0 15 3.364 15 7.5S11.636 15 7.5 15 0 11.636 0 7.5 3.364 0 7.5 0zm0 .882a6.618 6.618 0 1 0 0 13.236A6.618 6.618 0 0 0 7.5.882zM3.5 7h8a.5.5 0 1 1 0 1h-8a.5.5 0 0 1 0-1z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
className="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive"
|
||||
>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "rgb(171, 205, 239)",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
style={
|
||||
Object {
|
||||
"display": "inline-block",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="euiFormControlLayout"
|
||||
>
|
||||
<div
|
||||
className="euiFormControlLayout__childrenWrapper"
|
||||
>
|
||||
<input
|
||||
className="euiFieldText"
|
||||
onChange={[Function]}
|
||||
placeholder="#hex color"
|
||||
type="text"
|
||||
value="#abcdef"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<button
|
||||
aria-label="Add Color"
|
||||
className="euiButtonIcon euiButtonIcon--primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiButtonIcon__icon"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M8 7h3.5a.5.5 0 1 1 0 1H8v3.5a.5.5 0 1 1-1 0V8H3.5a.5.5 0 0 1 0-1H7V3.5a.5.5 0 0 1 1 0V7zm-.5-7C11.636 0 15 3.364 15 7.5S11.636 15 7.5 15 0 11.636 0 7.5 3.364 0 7.5 0zm0 .882a6.618 6.618 0 1 0 0 13.236A6.618 6.618 0 0 0 7.5.882z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Remove Color"
|
||||
className="euiButtonIcon euiButtonIcon--primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="euiIcon euiIcon--medium euiButtonIcon__icon"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M7.5 0C11.636 0 15 3.364 15 7.5S11.636 15 7.5 15 0 11.636 0 7.5 3.364 0 7.5 0zm0 .882a6.618 6.618 0 1 0 0 13.236A6.618 6.618 0 0 0 7.5.882zM3.5 7h8a.5.5 0 1 1 0 1h-8a.5.5 0 0 1 0-1z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* 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 { action } from '@storybook/addon-actions';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import React from 'react';
|
||||
import { ColorManager } from '../color_manager';
|
||||
|
||||
class Interactive extends React.Component<{}, { value: string }> {
|
||||
public state = {
|
||||
value: '',
|
||||
};
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<ColorManager
|
||||
onAddColor={action('onAddColor')}
|
||||
onRemoveColor={action('onRemoveColor')}
|
||||
onChange={value => this.setState({ value })}
|
||||
value={this.state.value}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
storiesOf('components/ColorManager', module)
|
||||
.addParameters({
|
||||
info: {
|
||||
inline: true,
|
||||
styles: {
|
||||
infoBody: {
|
||||
margin: 20,
|
||||
},
|
||||
infoStory: {
|
||||
margin: '40px 60px',
|
||||
width: '320px',
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
.add('default', () => [
|
||||
<ColorManager key="1" onChange={action('onChange')} value="#abcdef" />,
|
||||
<ColorManager key="2" onChange={action('onChange')} value="#abc" />,
|
||||
])
|
||||
.add('invalid colors', () => [
|
||||
<ColorManager key="1" onChange={action('onChange')} value="#abcd" />,
|
||||
<ColorManager key="2" onChange={action('onChange')} value="canvas" />,
|
||||
])
|
||||
.add('with buttons', () => [
|
||||
<ColorManager
|
||||
key="1"
|
||||
onAddColor={action('onAddColor')}
|
||||
onChange={action('onChange')}
|
||||
value="#abcdef"
|
||||
/>,
|
||||
<ColorManager
|
||||
key="2"
|
||||
onChange={action('onChange')}
|
||||
onRemoveColor={action('onRemoveColor')}
|
||||
value="#abcdef"
|
||||
/>,
|
||||
<ColorManager
|
||||
key="3"
|
||||
onAddColor={action('onAddColor')}
|
||||
onChange={action('onChange')}
|
||||
onRemoveColor={action('onRemoveColor')}
|
||||
value="#abcdef"
|
||||
/>,
|
||||
])
|
||||
.add('interactive', () => <Interactive />, {
|
||||
info: {
|
||||
inline: true,
|
||||
source: false,
|
||||
propTablesExclude: [Interactive],
|
||||
styles: {
|
||||
infoBody: {
|
||||
margin: 20,
|
||||
},
|
||||
infoStory: {
|
||||
margin: '40px 60px',
|
||||
width: '320px',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,51 +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 { EuiFieldText, EuiButtonIcon, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { ColorDot } from '../color_dot/color_dot';
|
||||
|
||||
export const ColorManager = ({ value, addColor, removeColor, onChange }) => (
|
||||
<EuiFlexGroup gutterSize="xs" alignItems="center">
|
||||
<EuiFlexItem grow={1}>
|
||||
<ColorDot value={value} />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={5} style={{ display: 'inline-block' }}>
|
||||
<EuiFieldText
|
||||
compressed
|
||||
value={value || ''}
|
||||
placeholder="#hex color"
|
||||
onChange={e => onChange(e.target.value)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
{(addColor || removeColor) && (
|
||||
<EuiFlexItem grow={false}>
|
||||
{addColor && (
|
||||
<EuiButtonIcon
|
||||
aria-label="Add Color"
|
||||
iconType="plusInCircle"
|
||||
onClick={() => addColor(value)}
|
||||
/>
|
||||
)}
|
||||
{removeColor && (
|
||||
<EuiButtonIcon
|
||||
aria-label="Remove Color"
|
||||
iconType="minusInCircle"
|
||||
onClick={() => removeColor(value)}
|
||||
/>
|
||||
)}
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
|
||||
ColorManager.propTypes = {
|
||||
value: PropTypes.string,
|
||||
addColor: PropTypes.func,
|
||||
removeColor: PropTypes.func,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
};
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* 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 { EuiButtonIcon, EuiFieldText, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { SFC } from 'react';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import { ColorDot } from '../color_dot/color_dot';
|
||||
|
||||
export interface Props {
|
||||
/** The function to call when the Add Color button is clicked. The button will not appear if there is no handler. */
|
||||
onAddColor?: (value: string) => void;
|
||||
/** The function to call when the value is changed */
|
||||
onChange: (value: string) => void;
|
||||
/** The function to call when the Remove Color button is clicked. The button will not appear if there is no handler. */
|
||||
onRemoveColor?: (value: string) => void;
|
||||
/**
|
||||
* The value of the color manager. Only honors hexadecimal values.
|
||||
* @default ''
|
||||
*/
|
||||
value?: string;
|
||||
}
|
||||
|
||||
export const ColorManager: SFC<Props> = ({ value = '', onAddColor, onRemoveColor, onChange }) => {
|
||||
const tc = tinycolor(value);
|
||||
const validColor = tc.isValid() && tc.getFormat() === 'hex';
|
||||
|
||||
if (value.length > 0 && !value.startsWith('#')) {
|
||||
value = '#' + value;
|
||||
}
|
||||
|
||||
const add = (
|
||||
<EuiButtonIcon
|
||||
aria-label="Add Color"
|
||||
iconType="plusInCircle"
|
||||
isDisabled={!validColor || !onAddColor}
|
||||
onClick={() => onAddColor && onAddColor(value)}
|
||||
/>
|
||||
);
|
||||
|
||||
const remove = (
|
||||
<EuiButtonIcon
|
||||
aria-label="Remove Color"
|
||||
iconType="minusInCircle"
|
||||
isDisabled={!validColor || !onRemoveColor}
|
||||
onClick={() => onRemoveColor && onRemoveColor(value)}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<EuiFlexGroup gutterSize="xs" alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<ColorDot value={validColor ? value : 'rgba(255,255,255,0)'} />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem style={{ display: 'inline-block' }}>
|
||||
<EuiFieldText
|
||||
value={value}
|
||||
isInvalid={!validColor && value.length > 0}
|
||||
placeholder="#hex color"
|
||||
onChange={e => onChange(e.target.value)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
{(add || remove) && (
|
||||
<EuiFlexItem grow={false}>
|
||||
{add}
|
||||
{remove}
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
||||
|
||||
ColorManager.propTypes = {
|
||||
onAddColor: PropTypes.func,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onRemoveColor: PropTypes.func,
|
||||
value: PropTypes.string,
|
||||
};
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import { pure } from 'recompose';
|
||||
import { ItemGrid as Component } from './item_grid';
|
||||
|
||||
export const ItemGrid = pure(Component);
|
||||
import { ColorManager as Component } from './color_manager';
|
||||
|
||||
export const ColorManager = pure(Component);
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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 { action } from '@storybook/addon-actions';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import React from 'react';
|
||||
import { ColorPalette } from '../color_palette';
|
||||
|
||||
const THREE_COLORS = ['#fff', '#666', '#000'];
|
||||
const SIX_COLORS = ['#fff', '#666', '#000', '#abc', '#def', '#abcdef'];
|
||||
|
||||
class Interactive extends React.Component<{}, { value: string }> {
|
||||
public state = {
|
||||
value: '',
|
||||
};
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<ColorPalette
|
||||
colors={SIX_COLORS}
|
||||
onChange={value => this.setState({ value })}
|
||||
value={this.state.value}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
storiesOf('components/ColorPalette', module)
|
||||
.add('three colors', () => [
|
||||
<ColorPalette key="1" onChange={action('onChange')} colors={THREE_COLORS} />,
|
||||
<ColorPalette key="2" value="#fff" onChange={action('onChange')} colors={THREE_COLORS} />,
|
||||
])
|
||||
.add('six colors', () => [
|
||||
<ColorPalette key="1" onChange={action('onChange')} colors={SIX_COLORS} />,
|
||||
<ColorPalette key="2" value="#fff" onChange={action('onChange')} colors={SIX_COLORS} />,
|
||||
])
|
||||
.add('six colors, wrap at 4', () => (
|
||||
<ColorPalette value="#fff" onChange={action('onChange')} colors={SIX_COLORS} colorsPerRow={4} />
|
||||
))
|
||||
.add('six colors, value missing', () => (
|
||||
<ColorPalette value="#f00" onChange={action('onChange')} colors={SIX_COLORS} />
|
||||
))
|
||||
.add('interactive', () => <Interactive />, {
|
||||
info: {
|
||||
inline: true,
|
||||
source: false,
|
||||
propTablesExclude: [Interactive],
|
||||
styles: {
|
||||
infoBody: {
|
||||
margin: 20,
|
||||
},
|
||||
infoStory: {
|
||||
margin: '40px 60px',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,40 +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 { EuiIcon, EuiLink } from '@elastic/eui';
|
||||
import { readableColor } from '../../lib/readable_color';
|
||||
import { ColorDot } from '../color_dot';
|
||||
import { ItemGrid } from '../item_grid';
|
||||
|
||||
export const ColorPalette = ({ value, colors, colorsPerRow, onChange }) => (
|
||||
<div className="canvasColorPalette">
|
||||
<ItemGrid items={colors} itemsPerRow={colorsPerRow || 6}>
|
||||
{({ item: color }) => (
|
||||
<EuiLink
|
||||
style={{ fontSize: 0 }}
|
||||
key={color}
|
||||
onClick={() => onChange(color)}
|
||||
className="canvasColorPalette__dot"
|
||||
>
|
||||
<ColorDot value={color}>
|
||||
{color === value && (
|
||||
<EuiIcon type="check" className="selected-color" color={readableColor(value)} />
|
||||
)}
|
||||
</ColorDot>
|
||||
</EuiLink>
|
||||
)}
|
||||
</ItemGrid>
|
||||
</div>
|
||||
);
|
||||
|
||||
ColorPalette.propTypes = {
|
||||
colors: PropTypes.array.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
value: PropTypes.string,
|
||||
colorsPerRow: PropTypes.number,
|
||||
};
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* 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 { EuiIcon, EuiLink } from '@elastic/eui';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { SFC } from 'react';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import { readableColor } from '../../lib/readable_color';
|
||||
import { ColorDot } from '../color_dot';
|
||||
import { ItemGrid } from '../item_grid';
|
||||
|
||||
export interface Props {
|
||||
/**
|
||||
* An array of hexadecimal color values. Non-hex will be ignored.
|
||||
* @default []
|
||||
*/
|
||||
colors?: string[];
|
||||
/**
|
||||
* The number of colors to display before wrapping to a new row.
|
||||
* @default 6
|
||||
*/
|
||||
colorsPerRow?: number;
|
||||
/** The function to call when the color is changed. */
|
||||
onChange: (value: string) => void;
|
||||
/**
|
||||
* The value of the color in the selector. Should be hexadecimal. If it is not in the colors array, it will be ignored.
|
||||
* @default ''
|
||||
*/
|
||||
value?: string;
|
||||
}
|
||||
|
||||
export const ColorPalette: SFC<Props> = ({
|
||||
colors = [],
|
||||
colorsPerRow = 6,
|
||||
onChange,
|
||||
value = '',
|
||||
}) => {
|
||||
if (colors.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
colors = colors.filter(color => {
|
||||
const providedColor = tinycolor(color);
|
||||
return providedColor.isValid() && providedColor.getFormat() === 'hex';
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="canvasColorPalette">
|
||||
<ItemGrid items={colors} itemsPerRow={colorsPerRow}>
|
||||
{color => {
|
||||
const match = tinycolor.equals(color, value);
|
||||
const icon = match ? (
|
||||
<EuiIcon type="check" className="selected-color" color={readableColor(value)} />
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<EuiLink
|
||||
style={{ fontSize: 0 }}
|
||||
key={color}
|
||||
onClick={() => !match && onChange(color)}
|
||||
className="canvasColorPalette__dot"
|
||||
>
|
||||
<ColorDot value={color}>{icon}</ColorDot>
|
||||
</EuiLink>
|
||||
);
|
||||
}}
|
||||
</ItemGrid>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ColorPalette.propTypes = {
|
||||
colors: PropTypes.array,
|
||||
colorsPerRow: PropTypes.number,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
value: PropTypes.string,
|
||||
};
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* 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 { action } from '@storybook/addon-actions';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import React from 'react';
|
||||
import { ColorPicker } from '../color_picker';
|
||||
|
||||
const THREE_COLORS = ['#fff', '#666', '#000'];
|
||||
const SIX_COLORS = ['#fff', '#666', '#000', '#abc', '#def', '#abcdef'];
|
||||
|
||||
class Interactive extends React.Component<{}, { value: string; colors: string[] }> {
|
||||
public state = {
|
||||
value: '',
|
||||
colors: SIX_COLORS,
|
||||
};
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<ColorPicker
|
||||
colors={this.state.colors}
|
||||
onAddColor={value => this.setState({ colors: this.state.colors.concat(value) })}
|
||||
onRemoveColor={value =>
|
||||
this.setState({ colors: this.state.colors.filter(color => color !== value) })
|
||||
}
|
||||
onChange={value => this.setState({ value })}
|
||||
value={this.state.value}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
storiesOf('components/ColorPicker', module)
|
||||
.addParameters({
|
||||
info: {
|
||||
inline: true,
|
||||
styles: {
|
||||
infoBody: {
|
||||
margin: 20,
|
||||
},
|
||||
infoStory: {
|
||||
margin: '40px 60px',
|
||||
width: '320px',
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
.add('three colors', () => (
|
||||
<ColorPicker
|
||||
value="#fff"
|
||||
onAddColor={action('onAddColor')}
|
||||
onRemoveColor={action('onRemoveColor')}
|
||||
onChange={action('onChange')}
|
||||
colors={THREE_COLORS}
|
||||
/>
|
||||
))
|
||||
.add('six colors', () => (
|
||||
<ColorPicker
|
||||
value="#fff"
|
||||
onAddColor={action('onAddColor')}
|
||||
onRemoveColor={action('onRemoveColor')}
|
||||
onChange={action('onChange')}
|
||||
colors={SIX_COLORS}
|
||||
/>
|
||||
))
|
||||
.add('six colors, value missing', () => (
|
||||
<ColorPicker
|
||||
value="#a1b2c3"
|
||||
onAddColor={action('onAddColor')}
|
||||
onRemoveColor={action('onRemoveColor')}
|
||||
onChange={action('onChange')}
|
||||
colors={SIX_COLORS}
|
||||
/>
|
||||
))
|
||||
.add('interactive', () => <Interactive />, {
|
||||
info: {
|
||||
inline: true,
|
||||
source: false,
|
||||
propTablesExclude: [Interactive],
|
||||
styles: {
|
||||
infoBody: {
|
||||
margin: 20,
|
||||
},
|
||||
infoStory: {
|
||||
margin: '40px 60px',
|
||||
width: '320px',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,32 +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 { ColorPalette } from '../color_palette';
|
||||
import { ColorManager } from '../color_manager';
|
||||
|
||||
export const ColorPicker = ({ onChange, value, colors, addColor, removeColor }) => {
|
||||
return (
|
||||
<div>
|
||||
<ColorPalette onChange={onChange} value={value} colors={colors} />
|
||||
<ColorManager
|
||||
onChange={onChange}
|
||||
value={value}
|
||||
addColor={addColor}
|
||||
removeColor={removeColor}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ColorPicker.propTypes = {
|
||||
value: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
colors: PropTypes.array,
|
||||
addColor: PropTypes.func,
|
||||
removeColor: PropTypes.func,
|
||||
};
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* 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 PropTypes from 'prop-types';
|
||||
import React, { SFC } from 'react';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import { ColorManager } from '../color_manager';
|
||||
import { ColorPalette } from '../color_palette';
|
||||
|
||||
export interface Props {
|
||||
/**
|
||||
* An array of hexadecimal color values. Non-hex will be ignored.
|
||||
* @default []
|
||||
*/
|
||||
colors?: string[];
|
||||
/** The function to call when the Add Color button is clicked. The button will not appear if there is no handler. */
|
||||
onAddColor?: (value: string) => void;
|
||||
/** The function to call when the color is changed. */
|
||||
onChange: (value: string) => void;
|
||||
/** The function to call when the Remove Color button is clicked. The button will not appear if there is no handler. */
|
||||
onRemoveColor?: (value: string) => void;
|
||||
/**
|
||||
* The value of the color in the selector. Should be hexadecimal. If it is not in the colors array, it will be ignored.
|
||||
* @default ''
|
||||
*/
|
||||
value?: string;
|
||||
}
|
||||
|
||||
export const ColorPicker: SFC<Props> = ({
|
||||
colors = [],
|
||||
value = '',
|
||||
onAddColor,
|
||||
onChange,
|
||||
onRemoveColor,
|
||||
}) => {
|
||||
const tc = tinycolor(value);
|
||||
const isValidColor = tc.isValid() && tc.getFormat() === 'hex';
|
||||
|
||||
colors = colors.filter(color => {
|
||||
const providedColor = tinycolor(color);
|
||||
return providedColor.isValid() && providedColor.getFormat() === 'hex';
|
||||
});
|
||||
|
||||
let canRemove = false;
|
||||
let canAdd = false;
|
||||
|
||||
if (isValidColor) {
|
||||
const match = colors.filter(color => tinycolor.equals(value, color));
|
||||
canRemove = match.length > 0;
|
||||
canAdd = match.length === 0;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ColorPalette onChange={onChange} value={value} colors={colors} />
|
||||
<ColorManager
|
||||
onChange={onChange}
|
||||
value={value}
|
||||
onAddColor={canAdd ? onAddColor : undefined}
|
||||
onRemoveColor={canRemove ? onRemoveColor : undefined}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ColorPicker.propTypes = {
|
||||
colors: PropTypes.array,
|
||||
onAddColor: PropTypes.func,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onRemoveColor: PropTypes.func,
|
||||
value: PropTypes.string,
|
||||
};
|
|
@ -0,0 +1,227 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Storyshots components/ItemGrid color dot grid 1`] = `
|
||||
<div
|
||||
className="item-grid-row"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "rgb(255, 255, 255)",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "rgb(102, 102, 102)",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "rgb(0, 0, 0)",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Storyshots components/ItemGrid complex grid 1`] = `
|
||||
<div
|
||||
className="item-grid-row"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "rgb(255, 255, 255)",
|
||||
}
|
||||
}
|
||||
>
|
||||
<svg
|
||||
className="euiIcon euiIcon--medium"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={
|
||||
Object {
|
||||
"fill": "#333",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M8 7h3.5a.5.5 0 1 1 0 1H8v3.5a.5.5 0 1 1-1 0V8H3.5a.5.5 0 0 1 0-1H7V3.5a.5.5 0 0 1 1 0V7zm-.5-7C11.636 0 15 3.364 15 7.5S11.636 15 7.5 15 0 11.636 0 7.5 3.364 0 7.5 0zm0 .882a6.618 6.618 0 1 0 0 13.236A6.618 6.618 0 0 0 7.5.882z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "rgb(102, 102, 102)",
|
||||
}
|
||||
}
|
||||
>
|
||||
<svg
|
||||
className="euiIcon euiIcon--medium"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={
|
||||
Object {
|
||||
"fill": "#FFF",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M7.5 0C11.636 0 15 3.364 15 7.5S11.636 15 7.5 15 0 11.636 0 7.5 3.364 0 7.5 0zm0 .882a6.618 6.618 0 1 0 0 13.236A6.618 6.618 0 0 0 7.5.882zM3.5 7h8a.5.5 0 1 1 0 1h-8a.5.5 0 0 1 0-1z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="canvasColorDot"
|
||||
>
|
||||
<div
|
||||
className="canvasColorDot__background canvasCheckered"
|
||||
/>
|
||||
<div
|
||||
className="canvasColorDot__foreground"
|
||||
style={
|
||||
Object {
|
||||
"background": "rgb(0, 0, 0)",
|
||||
}
|
||||
}
|
||||
>
|
||||
<svg
|
||||
className="euiIcon euiIcon--medium"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={
|
||||
Object {
|
||||
"fill": "#FFF",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M6.5 12a.502.502 0 0 1-.354-.146l-4-4a.502.502 0 0 1 .708-.708L6.5 10.793l6.646-6.647a.502.502 0 0 1 .708.708l-7 7A.502.502 0 0 1 6.5 12"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Storyshots components/ItemGrid icon grid 1`] = `
|
||||
<div
|
||||
className="item-grid-row"
|
||||
>
|
||||
<svg
|
||||
className="euiIcon euiIcon--medium"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M8 7h3.5a.5.5 0 1 1 0 1H8v3.5a.5.5 0 1 1-1 0V8H3.5a.5.5 0 0 1 0-1H7V3.5a.5.5 0 0 1 1 0V7zm-.5-7C11.636 0 15 3.364 15 7.5S11.636 15 7.5 15 0 11.636 0 7.5 3.364 0 7.5 0zm0 .882a6.618 6.618 0 1 0 0 13.236A6.618 6.618 0 0 0 7.5.882z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
className="euiIcon euiIcon--medium"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M7.5 0C11.636 0 15 3.364 15 7.5S11.636 15 7.5 15 0 11.636 0 7.5 3.364 0 7.5 0zm0 .882a6.618 6.618 0 1 0 0 13.236A6.618 6.618 0 0 0 7.5.882zM3.5 7h8a.5.5 0 1 1 0 1h-8a.5.5 0 0 1 0-1z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
className="euiIcon euiIcon--medium"
|
||||
focusable="false"
|
||||
height="16"
|
||||
style={null}
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M6.5 12a.502.502 0 0 1-.354-.146l-4-4a.502.502 0 0 1 .708-.708L6.5 10.793l6.646-6.647a.502.502 0 0 1 .708.708l-7 7A.502.502 0 0 1 6.5 12"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Storyshots components/ItemGrid simple grid 1`] = `
|
||||
<div
|
||||
className="item-grid-row"
|
||||
>
|
||||
<div>
|
||||
a
|
||||
</div>
|
||||
<div>
|
||||
b
|
||||
</div>
|
||||
<div>
|
||||
c
|
||||
</div>
|
||||
</div>
|
||||
`;
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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 { EuiIcon, IconType } from '@elastic/eui';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import React from 'react';
|
||||
import { readableColor } from '../../../lib/readable_color';
|
||||
import { ColorDot } from '../../color_dot';
|
||||
import { ItemGrid } from '../item_grid';
|
||||
|
||||
storiesOf('components/ItemGrid', module)
|
||||
.add('simple grid', () => (
|
||||
<ItemGrid items={['a', 'b', 'c']} children={item => <div key={item}>{item}</div>} />
|
||||
))
|
||||
.add('icon grid', () => (
|
||||
<ItemGrid
|
||||
items={['plusInCircle', 'minusInCircle', 'check'] as IconType[]}
|
||||
children={(item: IconType) => <EuiIcon key={item} type={item} />}
|
||||
/>
|
||||
))
|
||||
.add('color dot grid', () => (
|
||||
<ItemGrid items={['#fff', '#666', '#000']}>
|
||||
{item => <ColorDot key={item} value={item} />}
|
||||
</ItemGrid>
|
||||
))
|
||||
.add('complex grid', () => (
|
||||
<ItemGrid
|
||||
items={
|
||||
[
|
||||
{ color: '#fff', icon: 'plusInCircle' },
|
||||
{ color: '#666', icon: 'minusInCircle' },
|
||||
{ color: '#000', icon: 'check' },
|
||||
] as Array<{ color: string; icon: IconType }>
|
||||
}
|
||||
>
|
||||
{item => (
|
||||
<ColorDot key={item.color} value={item.color}>
|
||||
<EuiIcon type={item.icon} color={readableColor(item.color)} />
|
||||
</ColorDot>
|
||||
)}
|
||||
</ItemGrid>
|
||||
));
|
|
@ -4,8 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { compose, withState } from 'recompose';
|
||||
import { pure } from 'recompose';
|
||||
import { ItemGrid as Component, Props as ComponentProps } from './item_grid';
|
||||
|
||||
import { ColorManager as Component } from './color_manager';
|
||||
|
||||
export const ColorManager = compose(withState('adding', 'setAdding', false))(Component);
|
||||
export const ItemGrid = pure<ComponentProps<any>>(Component);
|
|
@ -1,42 +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 { last } from 'lodash';
|
||||
|
||||
const defaultPerRow = 6;
|
||||
|
||||
export const ItemGrid = ({ items, itemsPerRow, children }) => {
|
||||
if (!items) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const rows = items.reduce(
|
||||
(rows, item) => {
|
||||
if (last(rows).length >= (itemsPerRow || defaultPerRow)) {
|
||||
rows.push([]);
|
||||
}
|
||||
|
||||
last(rows).push(children({ item }));
|
||||
|
||||
return rows;
|
||||
},
|
||||
[[]]
|
||||
);
|
||||
|
||||
return rows.map((row, i) => (
|
||||
<div key={`item-grid-row-${i}`} className="item-grid-row">
|
||||
{row}
|
||||
</div>
|
||||
));
|
||||
};
|
||||
|
||||
ItemGrid.propTypes = {
|
||||
items: PropTypes.array.isRequired,
|
||||
itemsPerRow: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
||||
children: PropTypes.func.isRequired,
|
||||
};
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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 { last } from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Fragment, ReactElement, ValidationMap } from 'react';
|
||||
|
||||
const PER_ROW_DEFAULT = 6;
|
||||
|
||||
export interface Props<T> {
|
||||
/** A collection of 'things' to be iterated upon by the children prop function. */
|
||||
items: T[];
|
||||
/**
|
||||
* The number of items per row.
|
||||
* @default 6
|
||||
*/
|
||||
itemsPerRow?: number;
|
||||
/** A function with which to iterate upon the items collection, producing nodes. */
|
||||
children: (item: T) => ReactElement<any>;
|
||||
}
|
||||
|
||||
// We need this type in order to define propTypes on the object. It's a bit redundant,
|
||||
// but TS needs to know that ItemGrid can have propTypes defined on it.
|
||||
interface ItemGridType {
|
||||
<T>(props: Props<T>): ReactElement<any>;
|
||||
propTypes?: ValidationMap<Props<any>>;
|
||||
}
|
||||
|
||||
export const ItemGrid: ItemGridType = function ItemGridFunc<T>({
|
||||
items = [],
|
||||
itemsPerRow = PER_ROW_DEFAULT,
|
||||
children,
|
||||
}: Props<T>) {
|
||||
const reducedRows = items.reduce(
|
||||
(rows: Array<Array<ReactElement<any>>>, item: any) => {
|
||||
if (last(rows).length >= itemsPerRow) {
|
||||
rows.push([]);
|
||||
}
|
||||
|
||||
last(rows).push(children(item));
|
||||
|
||||
return rows;
|
||||
},
|
||||
[[]] as Array<Array<ReactElement<any>>>
|
||||
);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{reducedRows.map((row, i) => (
|
||||
<div key={`item-grid-row-${i}`} className="item-grid-row">
|
||||
{row}
|
||||
</div>
|
||||
))}
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
ItemGrid.propTypes = {
|
||||
items: PropTypes.array,
|
||||
itemsPerRow: PropTypes.number,
|
||||
children: PropTypes.func.isRequired,
|
||||
};
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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 { readableColor } from '../readable_color';
|
||||
|
||||
describe('readableColor', () => {
|
||||
test('light', () => {
|
||||
expect(readableColor('#000')).toEqual('#FFF');
|
||||
expect(readableColor('#000', '#EEE', '#111')).toEqual('#EEE');
|
||||
expect(readableColor('#111')).toEqual('#FFF');
|
||||
expect(readableColor('#111', '#EEE', '#111')).toEqual('#EEE');
|
||||
});
|
||||
test('dark', () => {
|
||||
expect(readableColor('#FFF')).toEqual('#333');
|
||||
expect(readableColor('#FFF', '#EEE', '#111')).toEqual('#111');
|
||||
expect(readableColor('#EEE')).toEqual('#333');
|
||||
expect(readableColor('#EEE', '#EEE', '#111')).toEqual('#111');
|
||||
});
|
||||
});
|
|
@ -6,9 +6,7 @@
|
|||
|
||||
import chroma from 'chroma-js';
|
||||
|
||||
export function readableColor(background, light, dark) {
|
||||
light = light || '#FFF';
|
||||
dark = dark || '#333';
|
||||
export function readableColor(background: string, light: string = '#FFF', dark: string = '#333') {
|
||||
try {
|
||||
return chroma.contrast(background, '#000') < 7 ? light : dark;
|
||||
} catch (e) {
|
17
yarn.lock
17
yarn.lock
|
@ -1648,6 +1648,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/cheerio/-/cheerio-0.22.10.tgz#780d552467824be4a241b29510a7873a7432c4a6"
|
||||
integrity sha512-fOM/Jhv51iyugY7KOBZz2ThfT1gwvsGCfWxpLpZDgkGjpEO4Le9cld07OdskikLjDUQJ43dzDaVRSFwQlpdqVg==
|
||||
|
||||
"@types/chroma-js@^1.4.1":
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/chroma-js/-/chroma-js-1.4.1.tgz#7c52d461173d569ba1f27e0c2dd26ee76691ec82"
|
||||
integrity sha512-i9hUiO3bwgmzZUDwBuR65WqsBQ/nwN+H2fKX0bykXCdd8cFQEuIj8vI7FXjyb2f5z5h+pv76I/uakikKSgaqTA==
|
||||
|
||||
"@types/chromedriver@^2.38.0":
|
||||
version "2.38.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/chromedriver/-/chromedriver-2.38.0.tgz#971032b73eb7f44036f4f5bed59a7fd5b468014f"
|
||||
|
@ -2236,6 +2241,13 @@
|
|||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/recompose@^0.30.5":
|
||||
version "0.30.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/recompose/-/recompose-0.30.5.tgz#09890e3c504546b38193479e610e427ac0888393"
|
||||
integrity sha512-PEQvFmudB9n0+ZvD8l7lh0olGAWmVAuVwCM4eotzWouH8/Kcr8/EcZyLhYILqoTlqzi6ey/3kbKQzJ/h3KkyXw==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/reduce-reducers@^0.1.3":
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/reduce-reducers/-/reduce-reducers-0.1.3.tgz#69f252207622ced7e063c7526ad46ec60b69f0c0"
|
||||
|
@ -2343,6 +2355,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/tempy/-/tempy-0.1.0.tgz#8ba0339dcd5abb554f301683dc3396d153ec5bfd"
|
||||
integrity sha512-2qeSxI2bMucW58Jsj8jrBXZxobtcKkvO44AvJzKGaD8+m/3KRuBqeKitJ5U6sqy3a9tFsqhzsxMkqR4Wcl6AmQ==
|
||||
|
||||
"@types/tinycolor2@^1.4.1":
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/tinycolor2/-/tinycolor2-1.4.1.tgz#2f5670c9d1d6e558897a810ed284b44918fc1253"
|
||||
integrity sha512-25L/RL5tqZkquKXVHM1fM2bd23qjfbcPpAZ2N/H05Y45g3UEi+Hw8CbDV28shKY8gH1SHiLpZSxPI1lacqdpGg==
|
||||
|
||||
"@types/type-detect@^4.0.1":
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/type-detect/-/type-detect-4.0.1.tgz#3b0f5ac82ea630090cbf57c57a1bf5a63a29b9b6"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue