@@ -43,18 +43,38 @@ class MaterialColors {
4343
4444 this . COLORS = require ( './colors.js' ) ;
4545 if ( this . _config . extraColors ) {
46- this . COLORS [ Object . keys ( this . COLORS ) [ 0 ] ] . startGroup = true ;
46+ this . COLORS [ Object . keys ( this . COLORS ) [ 0 ] ] . _startGroup = true ;
4747 this . COLORS = {
4848 ...this . _config . extraColors ,
4949 ...this . COLORS ,
5050 } ;
5151 } ;
5252
53- this . _allMaterialValues = [ ] ;
54- Object . keys ( this . COLORS ) . map ( hueName =>
55- Object . keys ( this . COLORS [ hueName ] ) . map ( valueName =>
56- this . _allMaterialValues . push (
57- Object . assign ( { hueName, valueName } , this . COLORS [ hueName ] [ valueName ] ) ) ) ) ;
53+ this . _searchableValues = [ ] ;
54+ Object . keys ( this . COLORS ) . forEach ( hueName => {
55+ let colorObj = this . COLORS [ hueName ] ;
56+
57+ ( colorObj . _groups || [ ] ) . forEach ( group => {
58+ ( group . colors || [ ] ) . forEach ( color => {
59+ this . _searchableValues . push ( {
60+ hueName,
61+ groupName : group . title || null ,
62+ valueName : color . name ,
63+ ...color
64+ } ) ;
65+ } ) ;
66+ } ) ;
67+
68+ Object . keys ( colorObj )
69+ . filter ( k => ! k . startsWith ( '_' ) )
70+ . forEach ( valueName => {
71+ this . _searchableValues . push ( {
72+ hueName,
73+ valueName,
74+ ...this . COLORS [ hueName ] [ valueName ]
75+ } ) ;
76+ } ) ;
77+ } ) ;
5878
5979 this . CLASS_NAMES = {
6080 closeButton : 'close-button' ,
@@ -84,6 +104,8 @@ class MaterialColors {
84104 separator : 'separator' ,
85105 sidebar : 'sidebar' ,
86106 updateBanner : 'update-banner' ,
107+ valueGroup : 'value-group' ,
108+ valueGroupHeading : 'value-group-heading' ,
87109 valueHeading : 'value-heading' ,
88110 valueList : 'value-list' ,
89111 notFoundIcon : 'not-found-icon' ,
@@ -166,7 +188,7 @@ class MaterialColors {
166188 firstHueName = hueName ;
167189 }
168190
169- if ( color . startGroup ) {
191+ if ( color . _startGroup ) {
170192 $ ( '<div>' )
171193 . addClass ( `${ this . CLASS_NAMES . separator } ` )
172194 . appendTo ( this . $sidebar ) ;
@@ -177,7 +199,9 @@ class MaterialColors {
177199 . click ( ( ) => this . _selectHue ( hueName ) )
178200 . appendTo ( this . $sidebar ) ;
179201
180- let keyColor = color [ this . isDarkMode ? '300' : '500' ] . hex ;
202+ let keyColor = this . isDarkMode
203+ ? color . _selectorDark || color [ '300' ] . hex
204+ : color . _selectorLight || color [ '500' ] . hex ;
181205
182206 let $hueIcon = $ ( '<div>' )
183207 . addClass ( this . CLASS_NAMES . hueIcon )
@@ -270,12 +294,41 @@ class MaterialColors {
270294 // for each value in the hue
271295 let color = this . COLORS [ hueName ] ;
272296 for ( let valueName in this . COLORS [ hueName ] ) {
297+ if ( valueName . startsWith ( '_' ) ) {
298+ continue ;
299+ }
300+
273301 color [ valueName ] . valueName = valueName ;
274302 color [ valueName ] . hueName = hueName ;
275303 this . _buildValueTile ( color [ valueName ] )
276304 . appendTo ( this . $valueList ) ;
277305 }
278306
307+ // build grouped items
308+ for ( let group of color . _groups || [ ] ) {
309+ let $valueGroup = $ ( '<div>' )
310+ . addClass ( this . CLASS_NAMES . valueGroup )
311+ . appendTo ( this . $valueList ) ;
312+
313+ if ( group . title ) {
314+ $ ( '<div>' )
315+ . addClass ( this . CLASS_NAMES . valueGroupHeading )
316+ . text ( group . title )
317+ . appendTo ( $valueGroup ) ;
318+ }
319+
320+ // for each value in the hue
321+ for ( let color of group . colors ) {
322+ color . valueName = color . name ;
323+ if ( group . title ) {
324+ color . groupName = group . title ;
325+ }
326+ color . hueName = hueName ;
327+ this . _buildValueTile ( color )
328+ . appendTo ( $valueGroup ) ;
329+ }
330+ }
331+
279332 // TODO(abhiomkar): use this dom cache instead of re-rendering.
280333 this . $_cache [ hueName ] = this . $valueList . children ( ) ;
281334 }
@@ -293,13 +346,13 @@ class MaterialColors {
293346 // search input is valid.
294347 let hex = inputColor . toHexString ( ) ;
295348 let alpha = inputColor . getAlpha ( ) ;
296- let materialValues = this . _getMaterialValuesByHex ( hex ) ;
349+ let searchResults = this . _getSearchableValuesByHex ( hex ) ;
297350 let $colorTile ;
298351 this . $searchResults . empty ( ) ;
299352
300- if ( materialValues . length ) {
353+ if ( searchResults . length ) {
301354 // material color
302- materialValues . forEach ( value => {
355+ searchResults . forEach ( value => {
303356 // update material color with alpha.
304357 if ( alpha ) {
305358 value = Object . assign ( { alpha} , value ) ;
@@ -309,16 +362,16 @@ class MaterialColors {
309362 } ) ;
310363 } else {
311364 // Non-material color.
312- this . _buildValueTile ( { hex, alpha, white : inputColor . isDark ( ) } , true )
365+ this . _buildValueTile ( { hex, alpha } , true )
313366 . appendTo ( this . $searchResults ) ;
314367
315368 $ ( '<div>' )
316369 . addClass ( this . CLASS_NAMES . matchingMaterialLabel )
317- . text ( 'Nearest Material colors' )
370+ . text ( 'Similar colors' )
318371 . appendTo ( this . $searchResults ) ;
319372
320373 // suggest a closest material color
321- this . _getCloseMaterialValues ( inputColor )
374+ this . _getCloseSearchableValues ( inputColor )
322375 . forEach ( val => this . _buildValueTile ( val , true ) . appendTo ( this . $searchResults ) ) ;
323376 }
324377 } else {
@@ -341,7 +394,7 @@ class MaterialColors {
341394 }
342395 }
343396
344- _showValueContextMenu ( hexValue , hueName , valueName , alpha ) {
397+ _showValueContextMenu ( hexValue , hueName , groupName , valueName , alpha ) {
345398 let withHash = hexValue ;
346399 let noHash = hexValue . replace ( / # / g, '' ) ;
347400
@@ -364,11 +417,12 @@ class MaterialColors {
364417 let valueFormats = [ ] ;
365418 if ( this . _config . copyFormats && this . _config . copyFormats . length ) {
366419 this . _config . copyFormats . forEach ( format => {
367- valueFormats . push ( this . _renderCustomColorFormatString ( format , { hueName, valueName, alpha} ) ) ;
420+ valueFormats . push ( this . _renderCustomColorFormatString ( format ,
421+ { hueName, groupName, valueName, alpha} ) ) ;
368422 } ) ;
369423 } else {
370424 valueFormats . push ( this . _renderCustomColorFormatString (
371- DEFAULT_VALUE_COPY_FORMAT , { hueName, valueName, alpha} ) ) ;
425+ DEFAULT_VALUE_COPY_FORMAT , { hueName, groupName , valueName, alpha} ) ) ;
372426 }
373427
374428 let formatToMenuItemTemplate_ = format => ( {
@@ -389,17 +443,18 @@ class MaterialColors {
389443 _buildValueTile ( value , largeTile ) {
390444 let tileBackground ;
391445 let isWhite ;
446+ let tc = tinycolor ( value . hex ) ;
392447
393448 if ( value . alpha ) {
394- tileBackground = tinycolor ( value . hex ) . setAlpha ( value . alpha ) . toString ( ) ;
449+ tileBackground = tc . setAlpha ( value . alpha ) . toString ( ) ;
395450 } else {
396451 tileBackground = value . hex ;
397452 }
398453
399454 if ( value . alpha && value . alpha < 0.5 ) {
400455 isWhite = false ;
401456 } else {
402- isWhite = value . white ;
457+ isWhite = tc . isDark ( ) ;
403458 }
404459
405460 let $colorTile = $ ( '<div>' )
@@ -409,7 +464,8 @@ class MaterialColors {
409464 . css ( 'background-color' , tileBackground )
410465 . contextmenu ( event => {
411466 event . preventDefault ( ) ;
412- this . _showValueContextMenu ( value . hex , value . hueName , value . valueName , value . alpha ) ;
467+ this . _showValueContextMenu (
468+ value . hex , value . hueName , value . groupName , value . valueName , value . alpha ) ;
413469 } ) ;
414470
415471 let $hex = $ ( '<div>' )
@@ -424,17 +480,18 @@ class MaterialColors {
424480 $colorTile . on ( 'refresh-tile' , ( event , opts ) =>
425481 $hex . text ( value . hex . toUpperCase ( ) . substring ( ( opts && opts . hideHash ) ? 1 : 0 ) ) ) ;
426482
427- if ( value . valueName ) {
483+ if ( value . name || value . valueName ) {
428484 $ ( '<div>' )
429485 . addClass ( this . CLASS_NAMES . colorTileValueName )
430- . text ( value . valueName . toUpperCase ( ) )
486+ . text ( value . name || value . valueName . toUpperCase ( ) )
431487 . click ( ( ) => {
432488 let valueCopyFormat = ( this . _config . copyFormats && this . _config . copyFormats . length )
433489 ? this . _config . copyFormats [ 0 ]
434490 : DEFAULT_VALUE_COPY_FORMAT ;
435491 let copyText = this . _renderCustomColorFormatString ( valueCopyFormat , {
436492 hueName : value . hueName ,
437- valueName : value . valueName ,
493+ groupName : value . groupName || null ,
494+ valueName : value . name || value . valueName ,
438495 alpha : value . alpha ,
439496 } ) ;
440497 electron . clipboard . writeText ( copyText ) ;
@@ -446,7 +503,8 @@ class MaterialColors {
446503 if ( value . hueName && largeTile ) {
447504 $ ( '<span>' )
448505 . addClass ( this . CLASS_NAMES . colorTileHueName )
449- . text ( this . _getDisplayLabelForHue ( value . hueName ) )
506+ . text ( this . _getDisplayLabelForHue ( value . hueName )
507+ + ( value . groupName ? ` – ${ value . groupName } ` : '' ) )
450508 . click ( ( ) => this . _selectHue ( value . hueName ) )
451509 . appendTo ( $colorTile ) ;
452510 }
@@ -479,13 +537,13 @@ class MaterialColors {
479537 Math . pow ( colorA . _b - colorB . _b , 2 ) ) ; // blue
480538 }
481539
482- _getMaterialValuesByHex ( hex ) {
483- return this . _allMaterialValues
540+ _getSearchableValuesByHex ( hex ) {
541+ return this . _searchableValues
484542 . filter ( value => value . hex . toLowerCase ( ) === hex . toLowerCase ( ) ) ;
485543 }
486544
487- _getCloseMaterialValues ( inputColor ) {
488- return this . _allMaterialValues
545+ _getCloseSearchableValues ( inputColor ) {
546+ return this . _searchableValues
489547 . map ( value => ( { value, difference : this . _getColorDifference ( inputColor , value . hex ) } ) )
490548 . sort ( ( a , b ) => ( a . difference - b . difference ) )
491549 . slice ( 0 , 3 )
@@ -525,6 +583,10 @@ class MaterialColors {
525583 data . hueName = data . hueName || '' ;
526584 data . valueName = data . valueName || '' ;
527585
586+ if ( data . groupName ) {
587+ data . valueName = data . groupName + '-' + data . valueName ;
588+ }
589+
528590 if ( data . alpha ) {
529591 data . alpha = ( data . alpha * 100 ) . toFixed ( 0 ) ;
530592 } else {
@@ -544,29 +606,30 @@ class MaterialColors {
544606 }
545607
546608 // text transform, lower, upper or capitalize
609+ let transformers = [ ] ;
547610 if ( textTransform === 'x' ) {
548- data . hueName = data . hueName . toLowerCase ( ) ;
549- data . valueName = data . valueName . toLowerCase ( ) ;
611+ transformers . push ( s => s . toLowerCase ( ) ) ;
550612 } else if ( textTransform === 'X' ) {
551- data . hueName = data . hueName . toUpperCase ( ) ;
552- data . valueName = data . valueName . toUpperCase ( ) ;
613+ transformers . push ( s => s . toUpperCase ( ) ) ;
553614 } else if ( textTransform === 'Xx' ) {
554- // capitalize text
555- data . hueName = this . _sentenceCase ( data . hueName ) ;
556- data . valueName = this . _sentenceCase ( data . valueName ) ;
615+ transformers . push ( s => this . _sentenceCase ( s ) ) ;
557616 }
558617
559618 // Replacer
560619 // d - delete spaces between the hue name (eg: LightBlue)
561620 // * - replace spaces between hue name with any character (eg: LIGHT_BLUE)
562621 // if no replacer found add a space between hue name if any (eg: Light Blue)
563- if ( replacer === 'd' ) {
564- data . hueName = data . hueName . replace ( '-' , '' ) ;
565- } else if ( replacer ) {
566- data . hueName = data . hueName . replace ( '-' , replacer ) ;
567- } else {
568- data . hueName = data . hueName . replace ( '-' , ' ' ) ;
569- }
622+ replacer = replacer
623+ ? ( replacer === 'd'
624+ ? ''
625+ : replacer )
626+ : ' ' ;
627+
628+ transformers . push ( s => s . replace ( / [ - ] / g, replacer ) ) ;
629+
630+ let applyAllTransformers = src => transformers . reduce ( ( s , t ) => t ( s ) , src ) ;
631+ data . hueName = applyAllTransformers ( data . hueName ) ;
632+ data . valueName = applyAllTransformers ( data . valueName ) ;
570633 }
571634
572635 string = string . replace ( / \$ H U E / g, data . hueName )
0 commit comments