@@ -7,9 +7,11 @@ import Color from './Color';
77import Colorscale from './Colorscale' ;
88import Numeric from './Numeric' ;
99import Radio from './Radio' ;
10+ import Info from './Info' ;
1011import DataSelector from './DataSelector' ;
1112import VisibilitySelect from './VisibilitySelect' ;
1213import { MULTI_VALUED , COLORS } from 'lib/constants' ;
14+ import { getColorscale } from 'react-colorscales' ;
1315
1416class UnconnectedMarkerColor extends Component {
1517 constructor ( props , context ) {
@@ -36,28 +38,33 @@ class UnconnectedMarkerColor extends Component {
3638 constant : type === 'constant' ? props . fullValue : COLORS . mutedBlue ,
3739 variable : type === 'variable' ? props . fullValue : null ,
3840 } ,
41+ constantSelectedOption :
42+ type === 'constant' && props . multiValued ? 'multiple' : 'single' ,
3943 } ;
4044
4145 this . setType = this . setType . bind ( this ) ;
4246 this . setValue = this . setValue . bind ( this ) ;
4347 this . setColorScale = this . setColorScale . bind ( this ) ;
48+ this . setColors = this . setColors . bind ( this ) ;
4449 }
4550
4651 setType ( type ) {
47- this . setState ( { type : type } ) ;
48- this . props . updatePlot ( this . state . value [ type ] ) ;
49- if ( type === 'constant' ) {
50- this . context . updateContainer ( {
51- [ 'marker.colorsrc' ] : null ,
52- [ 'marker.colorscale' ] : null ,
53- } ) ;
54- this . setState ( { colorscale : null } ) ;
55- } else {
56- this . context . updateContainer ( {
57- [ 'marker.color' ] : null ,
58- [ 'marker.colorsrc' ] : null ,
59- [ 'marker.colorscale' ] : [ ] ,
60- } ) ;
52+ if ( this . state . type !== type ) {
53+ this . setState ( { type : type } ) ;
54+ this . props . updatePlot ( this . state . value [ type ] ) ;
55+ if ( type === 'constant' ) {
56+ this . context . updateContainer ( {
57+ [ 'marker.colorsrc' ] : null ,
58+ [ 'marker.colorscale' ] : null ,
59+ } ) ;
60+ this . setState ( { colorscale : null } ) ;
61+ } else {
62+ this . context . updateContainer ( {
63+ [ 'marker.color' ] : null ,
64+ [ 'marker.colorsrc' ] : null ,
65+ [ 'marker.colorscale' ] : [ ] ,
66+ } ) ;
67+ }
6168 }
6269 }
6370
@@ -77,58 +84,158 @@ class UnconnectedMarkerColor extends Component {
7784 this . context . updateContainer ( { [ 'marker.colorscale' ] : inputValue } ) ;
7885 }
7986
87+ isMultiValued ( ) {
88+ return (
89+ this . props . multiValued ||
90+ ( Array . isArray ( this . props . fullValue ) &&
91+ this . props . fullValue . includes ( MULTI_VALUED ) ) ||
92+ ( this . props . container . marker &&
93+ this . props . container . marker . colorscale === MULTI_VALUED ) ||
94+ ( this . props . container . marker &&
95+ this . props . container . marker . colorsrc === MULTI_VALUED ) ||
96+ ( this . props . container . marker &&
97+ this . props . container . marker . color &&
98+ Array . isArray ( this . props . container . marker . color ) &&
99+ this . props . container . marker . color . includes ( MULTI_VALUED ) )
100+ ) ;
101+ }
102+
103+ setColors ( colorscale ) {
104+ const numberOfTraces = this . context . traceIndexes . length ;
105+ const colors = colorscale . map ( c => c [ 1 ] ) ;
106+
107+ let adjustedColors = getColorscale ( colors , numberOfTraces ) ;
108+ if ( adjustedColors . every ( c => c === adjustedColors [ 0 ] ) ) {
109+ adjustedColors = colors ;
110+ }
111+
112+ const updates = adjustedColors . map ( color => ( {
113+ [ 'marker.color' ] : color ,
114+ } ) ) ;
115+
116+ this . setState ( {
117+ colorscale : adjustedColors ,
118+ } ) ;
119+
120+ this . context . updateContainer ( updates ) ;
121+ }
122+
123+ renderConstantControls ( ) {
124+ const _ = this . context . localize ;
125+ const constantOptions = [
126+ { label : _ ( 'Single' ) , value : 'single' } ,
127+ { label : _ ( 'Multiple' ) , value : 'multiple' } ,
128+ ] ;
129+
130+ if ( this . context . traceIndexes . length > 1 ) {
131+ return (
132+ < div className = "markercolor-constantcontrols__container" >
133+ < RadioBlocks
134+ options = { constantOptions }
135+ activeOption = { this . state . constantSelectedOption }
136+ onOptionChange = { value =>
137+ this . setState ( { constantSelectedOption : value } )
138+ }
139+ />
140+ < Info >
141+ { this . state . constantSelectedOption === 'single'
142+ ? _ ( 'All traces will be colored in the the same color.' )
143+ : _ (
144+ 'Each trace will be colored according to the selected colorscale.'
145+ ) }
146+ </ Info >
147+ { this . state . constantSelectedOption === 'single' ? (
148+ < Color
149+ attr = "marker.color"
150+ updatePlot = { this . setValue }
151+ fullValue = { this . state . value . constant }
152+ />
153+ ) : (
154+ < Colorscale
155+ suppressMultiValuedMessage
156+ attr = "marker.color"
157+ updatePlot = { this . setColors }
158+ colorscale = { this . state . colorscale }
159+ initialCategory = { 'categorical' }
160+ />
161+ ) }
162+ </ div >
163+ ) ;
164+ }
165+
166+ return (
167+ < Color
168+ attr = "marker.color"
169+ updatePlot = { this . setValue }
170+ fullValue = { this . state . value . constant }
171+ />
172+ ) ;
173+ }
174+
175+ renderVariableControls ( ) {
176+ const _ = this . context . localize ;
177+ const multiValued =
178+ ( this . props . container &&
179+ this . props . container . marker &&
180+ ( this . props . container . marker . colorscale &&
181+ this . props . container . marker . colorscale === MULTI_VALUED ) ) ||
182+ ( this . props . container . marker . colorsrc &&
183+ this . props . container . marker . colorsrc === MULTI_VALUED ) ;
184+ return (
185+ < Field multiValued = { multiValued } >
186+ < DataSelector
187+ suppressMultiValuedMessage
188+ attr = "marker.color"
189+ placeholder = { _ ( 'Select a Data Option' ) }
190+ />
191+ { this . props . container . marker &&
192+ this . props . container . marker . colorscale === MULTI_VALUED ? null : (
193+ < Colorscale
194+ suppressMultiValuedMessage
195+ attr = "marker.colorscale"
196+ updatePlot = { this . setColorScale }
197+ colorscale = { this . state . colorscale }
198+ />
199+ ) }
200+ </ Field >
201+ ) ;
202+ }
203+
80204 render ( ) {
81- const { attr, fullValue , container } = this . props ;
205+ const { attr} = this . props ;
82206 const { localize : _ } = this . context ;
83- const { type, value , colorscale } = this . state ;
207+ const { type} = this . state ;
84208 const options = [
85209 { label : _ ( 'Constant' ) , value : 'constant' } ,
86210 { label : _ ( 'Variable' ) , value : 'variable' } ,
87211 ] ;
88- const multiValued =
89- this . props . multiValued ||
90- ( Array . isArray ( fullValue ) && fullValue . includes ( MULTI_VALUED ) ) ||
91- ( container . marker && container . marker . colorscale === MULTI_VALUED ) ||
92- ( container . marker && container . marker . colorsrc === MULTI_VALUED ) ||
93- ( container . marker &&
94- container . marker . color &&
95- Array . isArray ( container . marker . color ) &&
96- container . marker . color . includes ( MULTI_VALUED ) ) ;
97212
98213 return (
99214 < Fragment >
100- < Field { ...this . props } multiValued = { multiValued } attr = { attr } >
101- < RadioBlocks
102- options = { options }
103- activeOption = { type }
104- onOptionChange = { this . setType }
105- />
106- { ! type ? null : type === 'constant' ? (
107- < Color
108- suppressMultiValuedMessage
109- attr = "marker.color"
110- updatePlot = { this . setValue }
111- fullValue = { value . constant }
215+ < Field { ...this . props } attr = { attr } >
216+ < Field multiValued = { this . isMultiValued ( ) && ! this . state . type } >
217+ < RadioBlocks
218+ options = { options }
219+ activeOption = { type }
220+ onOptionChange = { this . setType }
112221 />
113- ) : container . marker &&
114- container . marker . colorsrc === MULTI_VALUED ? null : (
115- < Fragment >
116- < DataSelector suppressMultiValuedMessage attr = "marker.color" />
117- { container . marker &&
118- container . marker . colorscale === MULTI_VALUED ? null : (
119- < Colorscale
120- suppressMultiValuedMessage
121- attr = "marker.colorscale"
122- updatePlot = { this . setColorScale }
123- colorscale = { colorscale }
124- />
125- ) }
126- </ Fragment >
127- ) }
222+
223+ { ! type ? null : (
224+ < Info >
225+ { type === 'constant'
226+ ? _ ( 'All points in a trace are colored in the same color.' )
227+ : _ ( 'Each point in a trace is colored according to data.' ) }
228+ </ Info >
229+ ) }
230+ </ Field >
231+
232+ { ! type
233+ ? null
234+ : type === 'constant'
235+ ? this . renderConstantControls ( )
236+ : this . renderVariableControls ( ) }
128237 </ Field >
129- { type === 'constant' ? (
130- ''
131- ) : (
238+ { type === 'constant' ? null : (
132239 < Fragment >
133240 < Radio
134241 label = { _ ( 'Colorscale Direction' ) }
@@ -175,6 +282,7 @@ UnconnectedMarkerColor.propTypes = {
175282UnconnectedMarkerColor . contextTypes = {
176283 localize : PropTypes . func ,
177284 updateContainer : PropTypes . func ,
285+ traceIndexes : PropTypes . array ,
178286} ;
179287
180288export default connectToContainer ( UnconnectedMarkerColor ) ;
0 commit comments