Pick colors in mscreen from pallet

Summary:
{F226170897}
Color picker based on Lite's color table
We can't use standard color picker because of FB Lite's limitation: color set is predefined and sent from the server
'extra' field and 'color-lite' type are added to field description

Reviewed By: jknoxville

Differential Revision: D19330480

fbshipit-source-id: 695d288b4b8409e8b63a9e461a41914379d75a8c
This commit is contained in:
Timur Valiev
2020-01-13 15:07:59 -08:00
committed by Facebook Github Bot
parent 850bc3fe76
commit 11e134e87c
3 changed files with 121 additions and 39 deletions

View File

@@ -11,7 +11,7 @@ import Link from '../Link';
import {DataInspectorSetValue} from './DataInspector'; import {DataInspectorSetValue} from './DataInspector';
import {PureComponent} from 'react'; import {PureComponent} from 'react';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import {SketchPicker} from 'react-color'; import {SketchPicker, CompactPicker} from 'react-color';
import {Component, Fragment} from 'react'; import {Component, Fragment} from 'react';
import Popover from '../Popover'; import Popover from '../Popover';
import {colors} from '../colors'; import {colors} from '../colors';
@@ -80,6 +80,7 @@ type DataDescriptionProps = {
path?: Array<string>; path?: Array<string>;
type: string; type: string;
value: any; value: any;
extra?: any;
setValue: DataInspectorSetValue | null | undefined; setValue: DataInspectorSetValue | null | undefined;
}; };
@@ -207,7 +208,7 @@ export default class DataDescription extends PureComponent<
}; };
_renderEditing() { _renderEditing() {
const {type} = this.props; const {type, extra} = this.props;
const {origValue, value} = this.state; const {origValue, value} = this.state;
if ( if (
@@ -230,6 +231,16 @@ export default class DataDescription extends PureComponent<
return <ColorEditor value={value} commit={this.commit} />; return <ColorEditor value={value} commit={this.commit} />;
} }
if (type === 'color_lite') {
return (
<ColorEditor
value={value}
colorSet={extra.colorSet}
commit={this.commit}
/>
);
}
return null; return null;
} }
@@ -240,7 +251,8 @@ export default class DataDescription extends PureComponent<
type === 'text' || type === 'text' ||
type === 'number' || type === 'number' ||
type === 'enum' || type === 'enum' ||
type === 'color' type === 'color' ||
type === 'color_lite'
); );
} }
@@ -260,6 +272,7 @@ export default class DataDescription extends PureComponent<
<DataDescriptionPreview <DataDescriptionPreview
type={this.props.type} type={this.props.type}
value={this.props.value} value={this.props.value}
extra={this.props.extra}
editable={Boolean(this.props.setValue)} editable={Boolean(this.props.setValue)}
commit={this.commit} commit={this.commit}
onEdit={this.onEditStart} onEdit={this.onEditStart}
@@ -271,6 +284,7 @@ export default class DataDescription extends PureComponent<
class ColorEditor extends Component<{ class ColorEditor extends Component<{
value: any; value: any;
colorSet?: Array<string | number>;
commit: (opts: DescriptionCommitOptions) => void; commit: (opts: DescriptionCommitOptions) => void;
}> { }> {
onBlur = () => { onBlur = () => {
@@ -320,6 +334,25 @@ class ColorEditor extends Component<{
this.props.commit({clear: false, keep: true, value: val, set: true}); this.props.commit({clear: false, keep: true, value: val, set: true});
}; };
onChangeLite = ({
rgb: {a, b, g, r},
}: {
rgb: {a: number; b: number; g: number; r: number};
}) => {
const prev = this.props.value;
if (typeof prev !== 'number') {
return;
}
// compute RRGGBBAA value
let val = (Math.round(a * 255) & 0xff) << 24;
val |= (r & 0xff) << 16;
val |= (g & 0xff) << 8;
val |= b & 0xff;
this.props.commit({clear: false, keep: true, value: val, set: true});
};
render() { render() {
const colorInfo = parseColor(this.props.value); const colorInfo = parseColor(this.props.value);
if (!colorInfo) { if (!colorInfo) {
@@ -331,10 +364,37 @@ class ColorEditor extends Component<{
<DataDescriptionPreview <DataDescriptionPreview
type="color" type="color"
value={this.props.value} value={this.props.value}
extra={this.props.colorSet}
editable={false} editable={false}
commit={this.props.commit} commit={this.props.commit}
/> />
<Popover onDismiss={this.onBlur}> <Popover onDismiss={this.onBlur}>
{this.props.colorSet ? (
<CompactPicker
color={colorInfo}
colors={this.props.colorSet
.filter(x => x != 0)
.map(parseColor)
.map(rgba => {
if (!rgba) {
return '';
}
return `rgba(${rgba.r}, ${rgba.g}, ${rgba.b}, ${rgba.a})`;
})}
onChange={(color: {
hex: string;
hsl: {
a?: number;
h: number;
l: number;
s: number;
};
rgb: {a?: number; b: number; g: number; r: number};
}) => {
this.onChangeLite({rgb: {...color.rgb, a: color.rgb.a || 0}});
}}
/>
) : (
<SketchPicker <SketchPicker
color={colorInfo} color={colorInfo}
presetColors={[ presetColors={[
@@ -370,6 +430,7 @@ class ColorEditor extends Component<{
}); });
}} }}
/> />
)}
</Popover> </Popover>
</ColorPickerDescription> </ColorPickerDescription>
); );
@@ -379,6 +440,7 @@ class ColorEditor extends Component<{
class DataDescriptionPreview extends Component<{ class DataDescriptionPreview extends Component<{
type: string; type: string;
value: any; value: any;
extra?: any;
editable: boolean; editable: boolean;
commit: (opts: DescriptionCommitOptions) => void; commit: (opts: DescriptionCommitOptions) => void;
onEdit?: () => void; onEdit?: () => void;
@@ -513,6 +575,23 @@ class DataDescriptionContainer extends Component<{
} }
} }
case 'color_lite': {
const colorInfo = parseColor(val);
if (typeof val === 'number' && val === 0) {
return <UndefinedValue>(not set)</UndefinedValue>;
} else if (colorInfo) {
const {a, b, g, r} = colorInfo;
return [
<ColorBox key="color-box" color={`rgba(${r}, ${g}, ${b}, ${a})`} />,
<ColorValue key="value">
rgba({r}, {g}, {b}, {a === 1 ? '1' : a.toFixed(2)})
</ColorValue>,
];
} else {
return <span>Malformed color</span>;
}
}
case 'text': case 'text':
case 'string': case 'string':
if (val.startsWith('http://') || val.startsWith('https://')) { if (val.startsWith('http://') || val.startsWith('https://')) {

View File

@@ -439,12 +439,13 @@ export default class DataInspector extends Component<DataInspectorProps> {
let type; let type;
let value; let value;
let extra;
if (res) { if (res) {
if (!res.mutable) { if (!res.mutable) {
setValue = null; setValue = null;
} }
({type, value} = res); ({type, value, extra} = res);
} else { } else {
return null; return null;
} }
@@ -566,6 +567,7 @@ export default class DataInspector extends Component<DataInspectorProps> {
setValue={setValue} setValue={setValue}
type={type} type={type}
value={value} value={value}
extra={extra}
/> />
); );
} else { } else {

View File

@@ -22,6 +22,7 @@ export type DataValueExtractor = (
mutable: boolean; mutable: boolean;
type: string; type: string;
value: any; value: any;
extra?: any;
} }
| undefined | undefined
| null; | null;