import { Params , Scheme , getScheme , defaultParams , ColorBlindnessMode , colorBlindness , } from '@thematic/color' ; import { merge , set } from 'lodash' ; import defaults from './themes/defaults.json' ; import { ThemeDefinition , ThemeSpec , ThemeVariant } from './types' ; const DEFAULT_NOMINAL_ITEMS = 10 ; const DEFAULT_SEQUENTIAL_ITEMS = 100 ; param themeDefinition export function applyParams ( spec ) { const { params = defaultParams } = spec ; return { accentHue : params . accentHue , accentSaturation : params . accentSaturation , accentLuminance : params . accentLuminance , backgroundHueShift : params . backgroundHueShift , backgroundLevel : params . backgroundLevel , nominalHueStep : params . nominalHueStep , } ; } param themeDefinition export function createScheme ( spec , variant ? , colorBlindnessMode ? , nominalItemCount = DEFAULT_NOMINAL_ITEMS , sequentialItemCount = DEFAULT_SEQUENTIAL_ITEMS ) { const params = applyParams ( spec ) ; const scheme = getScheme ( params , nominalItemCount , sequentialItemCount , variant === undefined ? true : variant === ThemeVariant . Light ) ; return colorBlindness ( scheme , colorBlindnessMode ) ; } export function applyScheme ( spec , nominalItemCount = DEFAULT_NOMINAL_ITEMS , sequentialItemCount = DEFAULT_SEQUENTIAL_ITEMS ) { const light = getScheme ( spec . params ! , nominalItemCount , sequentialItemCount , true ) ; const dark = getScheme ( spec . params ! , nominalItemCount , sequentialItemCount , false ) ; return { ... spec , light , dark , } ; } param spec param overrides param scheme export function computeDefinition ( overrides , scheme ) { const baseConfigs = [ { value : scheme . background , paths : [ 'application.background' ] , } , { value : scheme . foreground , paths : [ 'application.foreground' ] , } , { value : scheme . offsetBackground , paths : [ 'plotArea.fill' ] , } , { value : scheme . accent , paths : [ 'application.accent' , 'application.success' ] , } , { value : scheme . warning , paths : [ 'application.warning' ] , } , { value : scheme . error , paths : [ 'application.error' ] , } , { value : scheme . nominal [ 0 ] , paths : [ 'rect.fill' , 'area.fill' , 'arc.fill' , 'node.fill' , 'circle.stroke' , 'line.stroke' , ] , } , { value : scheme . faintAnnotation , paths : [ 'application.faint' ] , } , { value : scheme . lowContrastAnnotation , paths : [ 'tooltip.fill' , 'plotArea.stroke' , 'axisLine.stroke' , 'axisTicks.stroke' , 'gridLines.stroke' , 'arc.stroke' , 'application.border' , 'application.lowContrast' , ] , } , { value : scheme . lowMidContrastAnnotation , paths : [ 'application.lowMidContrast' ] , } , { value : scheme . midContrastAnnotation , paths : [ 'axisTickLabels.fill' , 'axisTitle.fill' , 'process.fill' , 'tooltip.stroke' , 'application.midContrast' , ] , } , { value : scheme . midHighContrastAnnotation , paths : [ 'application.midHighContrast' ] , } , { value : scheme . highContrastAnnotation , paths : [ 'text.fill' , 'node.stroke' , 'link.stroke' , 'process.stroke' , 'flow.stroke' , 'rule.stroke' , 'application.highContrast' , ] , } , ] ; const base = baseConfigs . reduce ( ( acc , cur ) => { const { value , paths } = cur ; paths . forEach ( path => set ( acc , path , value ) ) ; return acc ; } , { } ) ; const baseOverlay = merge ( { } , defaults , base , overrides ) ; const signalConfigs = [ { value : scheme . nominalBold [ 0 ] , paths : [ 'rect.hovered.fill' , 'area.hovered.fill' , 'arc.hovered.fill' , 'node.hovered.fill' , 'circle.hovered.stroke' , 'line.hovered.stroke' , 'rect.selected.fill' , 'area.selected.fill' , 'arc.selected.fill' , 'node.selected.fill' , 'circle.selected.stroke' , 'line.selected.stroke' , ] , } , { value : scheme . nominalMuted [ 0 ] , paths : [ 'rect.suppressed.fill' , 'area.suppressed.fill' , 'arc.suppressed.fill' , 'node.suppressed.fill' , 'circle.suppressed.stroke' , 'line.suppressed.stroke' , ] , } , { value : scheme . faintAnnotation , paths : [ 'rect.nodata.fill' , 'area.nodata.fill' , 'arc.nodata.fill' , 'node.nodata.fill' , 'text.nodata.fill' , 'process.nodata.fill' , 'arc.nodata.stroke' , 'circle.nodata.stroke' , 'line.nodata.stroke' , 'link.nodata.stroke' , 'rule.nodata.stroke' , 'flow.nodata.stroke' , ] , } , { value : scheme . lowContrastAnnotation , paths : [ 'process.suppressed.fill' , 'rule.suppressed.stroke' , 'flow.suppressed.stroke' , 'node.nodata.stroke' , 'process.nodata.stroke' , ] , } , { value : scheme . midContrastAnnotation , paths : [ 'text.suppressed.fill' , 'node.suppressed.stroke' , 'link.suppressed.stroke' , 'process.suppressed.stroke' , 'rule.hovered.stroke' , 'flow.hovered.stroke' , 'process.hovered.stroke' , 'rule.selected.stroke' , 'flow.selected.stroke' , 'process.selected.stroke' , ] , } , { value : scheme . highContrastAnnotation , paths : [ 'process.hovered.fill' , 'process.selected.fill' ] , } , { value : 1 , paths : [ 'rect.selected.fillOpacity' , 'area.selected.fillOpacity' , 'arc.selected.fillOpacity' , 'node.selected.fillOpacity' , 'circle.selected.fillOpacity' , 'line.selected.fillOpacity' , 'link.selected.fillOpacity' , 'text.selected.fillOpacity' , 'rect.selected.strokeOpacity' , 'area.selected.strokeOpacity' , 'arc.selected.strokeOpacity' , 'node.selected.strokeOpacity' , 'circle.selected.strokeOpacity' , 'line.selected.strokeOpacity' , 'link.selected.strokeOpacity' , 'rect.hovered.fillOpacity' , 'area.hovered.fillOpacity' , 'arc.hovered.fillOpacity' , 'node.hovered.fillOpacity' , 'circle.hovered.fillOpacity' , 'line.hovered.fillOpacity' , 'link.hovered.fillOpacity' , 'rect.hovered.strokeOpacity' , 'area.hovered.strokeOpacity' , 'arc.hovered.strokeOpacity' , 'node.hovered.strokeOpacity' , 'circle.hovered.strokeOpacity' , 'line.hovered.strokeOpacity' , 'link.hovered.strokeOpacity' , ] , } , { value : 0.5 , paths : [ 'rect.suppressed.fillOpacity' , 'area.suppressed.fillOpacity' , 'arc.suppressed.fillOpacity' , 'node.suppressed.fillOpacity' , 'circle.suppressed.fillOpacity' , 'line.suppressed.fillOpacity' , 'link.suppressed.fillOpacity' , 'process.suppressed.fillOpacity' , 'rect.suppressed.strokeOpacity' , 'area.suppressed.strokeOpacity' , 'arc.suppressed.strokeOpacity' , 'node.suppressed.strokeOpacity' , 'circle.suppressed.strokeOpacity' , 'line.suppressed.strokeOpacity' , 'link.suppressed.strokeOpacity' , 'process.suppressed.strokeOpacity' , 'flow.suppressed.strokeOpacity' , 'rule.suppressed.strokeOpacity' , ] , } , { value : 0 , paths : [ 'rect.hidden.fillOpacity' , 'area.hidden.fillOpacity' , 'arc.hidden.fillOpacity' , 'node.hidden.fillOpacity' , 'circle.hidden.fillOpacity' , 'line.hidden.fillOpacity' , 'process.hidden.fillOpacity' , 'text.hidden.fillOpacity' , 'rect.hidden.strokeOpacity' , 'area.hidden.strokeOpacity' , 'arc.hidden.strokeOpacity' , 'node.hidden.strokeOpacity' , 'circle.hidden.strokeOpacity' , 'line.hidden.strokeOpacity' , 'link.hidden.strokeOpacity' , 'process.hidden.strokeOpacity' , 'flow.hidden.strokeOpacity' , 'rule.hidden.strokeOpacity' , ] , } , { value : 'none' , paths : [ 'rect.hidden.fill' , 'area.hidden.fill' , 'arc.hidden.fill' , 'node.hidden.fill' , 'circle.hidden.fill' , 'line.hidden.fill' , 'process.hidden.fill' , 'text.hidden.fill' , 'rect.hidden.stroke' , 'area.hidden.stroke' , 'arc.hidden.stroke' , 'node.hidden.stroke' , 'circle.hidden.stroke' , 'line.hidden.stroke' , 'process.hidden.stroke' , 'flow.hidden.stroke' , 'text.hidden.stroke' , 'rule.hidden.stroke' , ] , } , { value : 'bold' , paths : [ 'text.hovered.fontWeight' , 'text.selected.fontWeight' ] , } , ] ; const signalOverlay = signalConfigs . reduce ( ( acc , cur ) => { const { value , paths } = cur ; paths . forEach ( path => set ( acc , path , value ) ) ; return acc ; } , { } ) ; const signalMarks = [ 'circle' , 'rect' , 'line' , 'area' , 'arc' , 'node' , 'link' , 'process' , 'flow' , 'text' , 'rule' , ] ; const signalDefaultsOverlay = signalMarks . reduce ( ( acc , cur ) => { const b = ( baseOverlay as any ) [ cur ] ; const s = { hovered : { ... b } , selected : { ... b } , suppressed : { ... b } , hidden : { ... b } , nodata : { ... b } , } ; acc [ cur ] = s ; return acc ; } , { } ) ; const merged = merge ( baseOverlay , signalDefaultsOverlay , signalOverlay ) ; return merged ; }