mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Moved colorpicker to ui/components
This commit is contained in:
@@ -23,7 +23,9 @@
|
||||
"react-highlight-words": "0.11.0",
|
||||
"react-popper": "^1.3.0",
|
||||
"react-transition-group": "^2.2.1",
|
||||
"react-virtualized": "^9.21.0"
|
||||
"react-virtualized": "^9.21.0",
|
||||
"tether-drop": "https://github.com/torkelo/drop/tarball/master",
|
||||
"tinycolor2": "^1.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/classnames": "^2.2.6",
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import { ColorPalette } from './ColorPalette';
|
||||
|
||||
describe('CollorPalette', () => {
|
||||
it('renders correctly', () => {
|
||||
const tree = renderer.create(<ColorPalette color="#EAB839" onColorSelect={jest.fn()} />).toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
import React from 'react';
|
||||
import { sortedColors } from '../../utils';
|
||||
|
||||
export interface Props {
|
||||
color: string;
|
||||
onColorSelect: (c: string) => void;
|
||||
}
|
||||
|
||||
export class ColorPalette extends React.Component<Props, any> {
|
||||
paletteColors: string[];
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.paletteColors = sortedColors;
|
||||
this.onColorSelect = this.onColorSelect.bind(this);
|
||||
}
|
||||
|
||||
onColorSelect(color: string) {
|
||||
return () => {
|
||||
this.props.onColorSelect(color);
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const colorPaletteItems = this.paletteColors.map(paletteColor => {
|
||||
const cssClass = paletteColor.toLowerCase() === this.props.color.toLowerCase() ? 'fa-circle-o' : 'fa-circle';
|
||||
return (
|
||||
<i
|
||||
key={paletteColor}
|
||||
className={'pointer fa ' + cssClass}
|
||||
style={{ color: paletteColor }}
|
||||
onClick={this.onColorSelect(paletteColor)}
|
||||
>
|
||||
|
||||
</i>
|
||||
);
|
||||
});
|
||||
return (
|
||||
<div className="graph-legend-popover">
|
||||
<p className="m-b-0">{colorPaletteItems}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import Drop from 'tether-drop';
|
||||
import { ColorPickerPopover } from './ColorPickerPopover';
|
||||
|
||||
export interface Props {
|
||||
color: string;
|
||||
onChange: (c: string) => void;
|
||||
}
|
||||
|
||||
export class ColorPicker extends React.Component<Props, any> {
|
||||
pickerElem: HTMLElement | null;
|
||||
colorPickerDrop: any;
|
||||
|
||||
openColorPicker = () => {
|
||||
const dropContent = <ColorPickerPopover color={this.props.color} onColorSelect={this.onColorSelect} />;
|
||||
|
||||
const dropContentElem = document.createElement('div');
|
||||
ReactDOM.render(dropContent, dropContentElem);
|
||||
|
||||
const drop = new Drop({
|
||||
target: this.pickerElem,
|
||||
content: dropContentElem,
|
||||
position: 'top center',
|
||||
classes: 'drop-popover',
|
||||
openOn: 'click',
|
||||
hoverCloseDelay: 200,
|
||||
tetherOptions: {
|
||||
constraints: [{ to: 'scrollParent', attachment: 'none both' }],
|
||||
},
|
||||
});
|
||||
|
||||
drop.on('close', this.closeColorPicker);
|
||||
|
||||
this.colorPickerDrop = drop;
|
||||
this.colorPickerDrop.open();
|
||||
};
|
||||
|
||||
closeColorPicker = () => {
|
||||
setTimeout(() => {
|
||||
if (this.colorPickerDrop && this.colorPickerDrop.tether) {
|
||||
this.colorPickerDrop.destroy();
|
||||
}
|
||||
}, 100);
|
||||
};
|
||||
|
||||
onColorSelect = (color: string) => {
|
||||
this.props.onChange(color);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="sp-replacer sp-light" onClick={this.openColorPicker} ref={element => (this.pickerElem = element)}>
|
||||
<div className="sp-preview">
|
||||
<div className="sp-preview-inner" style={{ backgroundColor: this.props.color }} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
import React from 'react';
|
||||
import $ from 'jquery';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import { ColorPalette } from './ColorPalette';
|
||||
import { SpectrumPicker } from './SpectrumPicker';
|
||||
|
||||
const DEFAULT_COLOR = '#000000';
|
||||
|
||||
export interface Props {
|
||||
color: string;
|
||||
onColorSelect: (c: string) => void;
|
||||
}
|
||||
|
||||
export class ColorPickerPopover extends React.Component<Props, any> {
|
||||
pickerNavElem: any;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
tab: 'palette',
|
||||
color: this.props.color || DEFAULT_COLOR,
|
||||
colorString: this.props.color || DEFAULT_COLOR,
|
||||
};
|
||||
}
|
||||
|
||||
setPickerNavElem(elem: any) {
|
||||
this.pickerNavElem = $(elem);
|
||||
}
|
||||
|
||||
setColor(color: string) {
|
||||
const newColor = tinycolor(color);
|
||||
if (newColor.isValid()) {
|
||||
this.setState({ color: newColor.toString(), colorString: newColor.toString() });
|
||||
this.props.onColorSelect(color);
|
||||
}
|
||||
}
|
||||
|
||||
sampleColorSelected(color: string) {
|
||||
this.setColor(color);
|
||||
}
|
||||
|
||||
spectrumColorSelected(color: any) {
|
||||
const rgbColor = color.toRgbString();
|
||||
this.setColor(rgbColor);
|
||||
}
|
||||
|
||||
onColorStringChange(e: any) {
|
||||
const colorString = e.target.value;
|
||||
this.setState({ colorString: colorString });
|
||||
|
||||
const newColor = tinycolor(colorString);
|
||||
if (newColor.isValid()) {
|
||||
// Update only color state
|
||||
const newColorString = newColor.toString();
|
||||
this.setState({ color: newColorString });
|
||||
this.props.onColorSelect(newColorString);
|
||||
}
|
||||
}
|
||||
|
||||
onColorStringBlur(e: any) {
|
||||
const colorString = e.target.value;
|
||||
this.setColor(colorString);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.pickerNavElem.find('li:first').addClass('active');
|
||||
this.pickerNavElem.on('show', (e: any) => {
|
||||
// use href attr (#name => name)
|
||||
const tab = e.target.hash.slice(1);
|
||||
this.setState({ tab: tab });
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const paletteTab = (
|
||||
<div id="palette">
|
||||
<ColorPalette color={this.state.color} onColorSelect={this.sampleColorSelected.bind(this)} />
|
||||
</div>
|
||||
);
|
||||
const spectrumTab = (
|
||||
<div id="spectrum">
|
||||
<SpectrumPicker color={this.state.color} onColorSelect={this.spectrumColorSelected.bind(this)} options={{}} />
|
||||
</div>
|
||||
);
|
||||
const currentTab = this.state.tab === 'palette' ? paletteTab : spectrumTab;
|
||||
|
||||
return (
|
||||
<div className="gf-color-picker">
|
||||
<ul className="nav nav-tabs" id="colorpickernav" ref={this.setPickerNavElem.bind(this)}>
|
||||
<li className="gf-tabs-item-colorpicker">
|
||||
<a href="#palette" data-toggle="tab">
|
||||
Colors
|
||||
</a>
|
||||
</li>
|
||||
<li className="gf-tabs-item-colorpicker">
|
||||
<a href="#spectrum" data-toggle="tab">
|
||||
Custom
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div className="gf-color-picker__body">{currentTab}</div>
|
||||
<div>
|
||||
<input
|
||||
className="gf-form-input gf-form-input--small"
|
||||
value={this.state.colorString}
|
||||
onChange={this.onColorStringChange.bind(this)}
|
||||
onBlur={this.onColorStringBlur.bind(this)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import Drop from 'tether-drop';
|
||||
import { SeriesColorPickerPopover } from './SeriesColorPickerPopover';
|
||||
|
||||
export interface SeriesColorPickerProps {
|
||||
color: string;
|
||||
yaxis?: number;
|
||||
optionalClass?: string;
|
||||
onColorChange: (newColor: string) => void;
|
||||
onToggleAxis: () => void;
|
||||
}
|
||||
|
||||
export class SeriesColorPicker extends React.Component<SeriesColorPickerProps> {
|
||||
pickerElem: any;
|
||||
colorPickerDrop: any;
|
||||
|
||||
static defaultProps = {
|
||||
optionalClass: '',
|
||||
yaxis: undefined,
|
||||
onToggleAxis: () => {},
|
||||
};
|
||||
|
||||
constructor(props: SeriesColorPickerProps) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.destroyDrop();
|
||||
}
|
||||
|
||||
onClickToOpen = () => {
|
||||
if (this.colorPickerDrop) {
|
||||
this.destroyDrop();
|
||||
}
|
||||
|
||||
const { color, yaxis, onColorChange, onToggleAxis } = this.props;
|
||||
const dropContent = (
|
||||
<SeriesColorPickerPopover color={color} yaxis={yaxis} onColorChange={onColorChange} onToggleAxis={onToggleAxis} />
|
||||
);
|
||||
const dropContentElem = document.createElement('div');
|
||||
ReactDOM.render(dropContent, dropContentElem);
|
||||
|
||||
const drop = new Drop({
|
||||
target: this.pickerElem,
|
||||
content: dropContentElem,
|
||||
position: 'bottom center',
|
||||
classes: 'drop-popover',
|
||||
openOn: 'hover',
|
||||
hoverCloseDelay: 200,
|
||||
remove: true,
|
||||
tetherOptions: {
|
||||
constraints: [{ to: 'scrollParent', attachment: 'none both' }],
|
||||
},
|
||||
});
|
||||
|
||||
drop.on('close', this.closeColorPicker.bind(this));
|
||||
|
||||
this.colorPickerDrop = drop;
|
||||
this.colorPickerDrop.open();
|
||||
};
|
||||
|
||||
closeColorPicker() {
|
||||
setTimeout(() => {
|
||||
this.destroyDrop();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
destroyDrop() {
|
||||
if (this.colorPickerDrop && this.colorPickerDrop.tether) {
|
||||
this.colorPickerDrop.destroy();
|
||||
this.colorPickerDrop = null;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { optionalClass, children } = this.props;
|
||||
return (
|
||||
<div className={optionalClass} ref={e => (this.pickerElem = e)} onClick={this.onClickToOpen}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import React from 'react';
|
||||
import { ColorPickerPopover } from './ColorPickerPopover';
|
||||
|
||||
export interface SeriesColorPickerPopoverProps {
|
||||
color: string;
|
||||
yaxis?: number;
|
||||
onColorChange: (color: string) => void;
|
||||
onToggleAxis: () => void;
|
||||
}
|
||||
|
||||
export class SeriesColorPickerPopover extends React.PureComponent<SeriesColorPickerPopoverProps, any> {
|
||||
render() {
|
||||
return (
|
||||
<div className="graph-legend-popover">
|
||||
{this.props.yaxis && <AxisSelector yaxis={this.props.yaxis} onToggleAxis={this.props.onToggleAxis} />}
|
||||
<ColorPickerPopover color={this.props.color} onColorSelect={this.props.onColorChange} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
interface AxisSelectorProps {
|
||||
yaxis: number;
|
||||
onToggleAxis: () => void;
|
||||
}
|
||||
|
||||
interface AxisSelectorState {
|
||||
yaxis: number;
|
||||
}
|
||||
|
||||
export class AxisSelector extends React.PureComponent<AxisSelectorProps, AxisSelectorState> {
|
||||
constructor(props: AxisSelectorProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
yaxis: this.props.yaxis,
|
||||
};
|
||||
this.onToggleAxis = this.onToggleAxis.bind(this);
|
||||
}
|
||||
|
||||
onToggleAxis() {
|
||||
this.setState({
|
||||
yaxis: this.state.yaxis === 2 ? 1 : 2,
|
||||
});
|
||||
this.props.onToggleAxis();
|
||||
}
|
||||
|
||||
render() {
|
||||
const leftButtonClass = this.state.yaxis === 1 ? 'btn-success' : 'btn-inverse';
|
||||
const rightButtonClass = this.state.yaxis === 2 ? 'btn-success' : 'btn-inverse';
|
||||
|
||||
return (
|
||||
<div className="p-b-1">
|
||||
<label className="small p-r-1">Y Axis:</label>
|
||||
<button onClick={this.onToggleAxis} className={'btn btn-small ' + leftButtonClass}>
|
||||
Left
|
||||
</button>
|
||||
<button onClick={this.onToggleAxis} className={'btn btn-small ' + rightButtonClass}>
|
||||
Right
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import $ from 'jquery';
|
||||
import 'vendor/spectrum';
|
||||
|
||||
export interface Props {
|
||||
color: string;
|
||||
options: object;
|
||||
onColorSelect: (c: string) => void;
|
||||
}
|
||||
|
||||
export class SpectrumPicker extends React.Component<Props, any> {
|
||||
elem: any;
|
||||
isMoving: boolean;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.onSpectrumMove = this.onSpectrumMove.bind(this);
|
||||
this.setComponentElem = this.setComponentElem.bind(this);
|
||||
}
|
||||
|
||||
setComponentElem(elem: any) {
|
||||
this.elem = $(elem);
|
||||
}
|
||||
|
||||
onSpectrumMove(color: any) {
|
||||
this.isMoving = true;
|
||||
this.props.onColorSelect(color);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const spectrumOptions = _.assignIn(
|
||||
{
|
||||
flat: true,
|
||||
showAlpha: true,
|
||||
showButtons: false,
|
||||
color: this.props.color,
|
||||
appendTo: this.elem,
|
||||
move: this.onSpectrumMove,
|
||||
},
|
||||
this.props.options
|
||||
);
|
||||
|
||||
this.elem.spectrum(spectrumOptions);
|
||||
this.elem.spectrum('show');
|
||||
this.elem.spectrum('set', this.props.color);
|
||||
}
|
||||
|
||||
componentWillUpdate(nextProps: any) {
|
||||
// If user move pointer over spectrum field this produce 'move' event and component
|
||||
// may update props.color. We don't want to update spectrum color in this case, so we can use
|
||||
// isMoving flag for tracking moving state. Flag should be cleared in componentDidUpdate() which
|
||||
// is called after updating occurs (when user finished moving).
|
||||
if (!this.isMoving) {
|
||||
this.elem.spectrum('set', nextProps.color);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (this.isMoving) {
|
||||
this.isMoving = false;
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.elem.spectrum('destroy');
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div className="spectrum-container" ref={this.setComponentElem} />;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,628 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`CollorPalette renders correctly 1`] = `
|
||||
<div
|
||||
className="graph-legend-popover"
|
||||
>
|
||||
<p
|
||||
className="m-b-0"
|
||||
>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#890f02",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#58140c",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#99440a",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#c15c17",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#967302",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#cca300",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#3f6833",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#2f575e",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#64b0c8",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#052b51",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#0a50a1",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#584477",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#3f2b5b",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#511749",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#e24d42",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#bf1b00",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#ef843c",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#f4d598",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#e5ac0e",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#9ac48a",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#508642",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#6ed0e0",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#65c5db",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#0a437c",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#447ebc",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#614d93",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#d683ce",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#6d1f62",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#ea6460",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#e0752d",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#f9934e",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#fceaca",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle-o"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#eab839",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#b7dbab",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#629e51",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#70dbed",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#82b5d8",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#1f78c1",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#aea2e0",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#705da0",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#e5a8e2",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#962d82",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#f29191",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#fce2de",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#f9ba8f",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#f9e2d2",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#f2c96d",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#e0f9d7",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#7eb26d",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#cffaff",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#badff4",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#5195ce",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#dedaf7",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#806eb7",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#f9d9f9",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
<i
|
||||
className="pointer fa fa-circle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"color": "#ba43a9",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</i>
|
||||
</p>
|
||||
</div>
|
||||
`;
|
||||
@@ -2,3 +2,6 @@ export { DeleteButton } from './DeleteButton/DeleteButton';
|
||||
export { Tooltip } from './Tooltip/Tooltip';
|
||||
export { Portal } from './Portal/Portal';
|
||||
export { CustomScrollbar } from './CustomScrollbar/CustomScrollbar';
|
||||
export { ColorPicker } from './ColorPicker/ColorPicker';
|
||||
export { SeriesColorPickerPopover } from './ColorPicker/SeriesColorPickerPopover';
|
||||
export { SeriesColorPicker } from './ColorPicker/SeriesColorPicker';
|
||||
|
||||
@@ -2,4 +2,5 @@ export * from './components';
|
||||
export * from './visualizations';
|
||||
export * from './types';
|
||||
export * from './utils';
|
||||
export { default } from './utils';
|
||||
export * from './forms';
|
||||
|
||||
94
packages/grafana-ui/src/utils/colors.ts
Normal file
94
packages/grafana-ui/src/utils/colors.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import _ from 'lodash';
|
||||
import tinycolor from 'tinycolor2';
|
||||
|
||||
export const PALETTE_ROWS = 4;
|
||||
export const PALETTE_COLUMNS = 14;
|
||||
export const DEFAULT_ANNOTATION_COLOR = 'rgba(0, 211, 255, 1)';
|
||||
export const OK_COLOR = 'rgba(11, 237, 50, 1)';
|
||||
export const ALERTING_COLOR = 'rgba(237, 46, 24, 1)';
|
||||
export const NO_DATA_COLOR = 'rgba(150, 150, 150, 1)';
|
||||
export const PENDING_COLOR = 'rgba(247, 149, 32, 1)';
|
||||
export const REGION_FILL_ALPHA = 0.09;
|
||||
|
||||
const colors = [
|
||||
'#7EB26D', // 0: pale green
|
||||
'#EAB839', // 1: mustard
|
||||
'#6ED0E0', // 2: light blue
|
||||
'#EF843C', // 3: orange
|
||||
'#E24D42', // 4: red
|
||||
'#1F78C1', // 5: ocean
|
||||
'#BA43A9', // 6: purple
|
||||
'#705DA0', // 7: violet
|
||||
'#508642', // 8: dark green
|
||||
'#CCA300', // 9: dark sand
|
||||
'#447EBC',
|
||||
'#C15C17',
|
||||
'#890F02',
|
||||
'#0A437C',
|
||||
'#6D1F62',
|
||||
'#584477',
|
||||
'#B7DBAB',
|
||||
'#F4D598',
|
||||
'#70DBED',
|
||||
'#F9BA8F',
|
||||
'#F29191',
|
||||
'#82B5D8',
|
||||
'#E5A8E2',
|
||||
'#AEA2E0',
|
||||
'#629E51',
|
||||
'#E5AC0E',
|
||||
'#64B0C8',
|
||||
'#E0752D',
|
||||
'#BF1B00',
|
||||
'#0A50A1',
|
||||
'#962D82',
|
||||
'#614D93',
|
||||
'#9AC48A',
|
||||
'#F2C96D',
|
||||
'#65C5DB',
|
||||
'#F9934E',
|
||||
'#EA6460',
|
||||
'#5195CE',
|
||||
'#D683CE',
|
||||
'#806EB7',
|
||||
'#3F6833',
|
||||
'#967302',
|
||||
'#2F575E',
|
||||
'#99440A',
|
||||
'#58140C',
|
||||
'#052B51',
|
||||
'#511749',
|
||||
'#3F2B5B',
|
||||
'#E0F9D7',
|
||||
'#FCEACA',
|
||||
'#CFFAFF',
|
||||
'#F9E2D2',
|
||||
'#FCE2DE',
|
||||
'#BADFF4',
|
||||
'#F9D9F9',
|
||||
'#DEDAF7',
|
||||
];
|
||||
|
||||
function sortColorsByHue(hexColors: string[]) {
|
||||
const hslColors = _.map(hexColors, hexToHsl);
|
||||
|
||||
let sortedHSLColors = _.sortBy(hslColors, ['h']);
|
||||
sortedHSLColors = _.chunk(sortedHSLColors, PALETTE_ROWS);
|
||||
sortedHSLColors = _.map(sortedHSLColors, chunk => {
|
||||
return _.sortBy(chunk, 'l');
|
||||
});
|
||||
sortedHSLColors = _.flattenDeep(_.zip(...sortedHSLColors));
|
||||
|
||||
return _.map(sortedHSLColors, hslToHex);
|
||||
}
|
||||
|
||||
function hexToHsl(color: string) {
|
||||
return tinycolor(color).toHsl();
|
||||
}
|
||||
|
||||
function hslToHex(color: string) {
|
||||
return tinycolor(color).toHexString();
|
||||
}
|
||||
|
||||
export let sortedColors = sortColorsByHue(colors);
|
||||
export default colors;
|
||||
@@ -1 +1,3 @@
|
||||
export * from './processTimeSeries';
|
||||
export * from './colors';
|
||||
export { default } from './colors';
|
||||
|
||||
Reference in New Issue
Block a user