{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}

{-|
Module      : Graphics.Vega.VegaLite.Core
Copyright   : (c) Douglas Burke, 2018-2020
License     : BSD3

Maintainer  : dburke.gw@gmail.com
Stability   : unstable
Portability : CPP, OverloadedStrings

The main fuctionality of VegaLite is provided by
the Foundation and Core modules, but there are types
(and functions) scattered around the place. There is
some logic into what goes where, but it's not perfect.

-}

module Graphics.Vega.VegaLite.Core
       ( transform

       , aggregate
       , joinAggregate
       , opAs
       , timeUnitAs

       , binAs

       , stack

       , calculateAs

       , filter
       , Filter(..)
       , FilterRange(..)

       , flatten
       , flattenAs
       , fold
       , foldAs
       , pivot
       , PivotProperty(..)

       , lookup
       , lookupSelection
       , LookupFields(..)
       , lookupAs

       , impute

       , sample

       , density
       , DensityProperty(..)

       , loess
       , LoessProperty(..)

       , regression
       , RegressionProperty(..)
       , RegressionMethod(..)

       , quantile
       , QuantileProperty(..)

       , window

       , mark

       , encoding

       , position

       , PositionChannel(..)

       , SortProperty(..)

       , AxisProperty(..)
       , ConditionalAxisProperty(..)

       , angle
       , color
       , fill
       , fillOpacity
       , opacity
       , shape
       , size
       , stroke
       , strokeDash
       , strokeOpacity
       , strokeWidth

       , MarkChannel(..)

       , text
       , tooltip
       , tooltips
       , TextChannel(..)

       , hyperlink
       , url
       , HyperlinkChannel(..)

       , order
       , OrderChannel(..)

       , row
       , column

       , detail
       , DetailChannel(..)

       , ariaDescription
       , AriaDescriptionChannel(..)

       , ScaleProperty(..)
       , categoricalDomainMap
       , domainRangeMap

       , layer
       , vlConcat
       , columns
       , hConcat
       , vConcat
       , align
       , alignRC
       , spacing
       , spacingRC
       , center
       , centerRC
       , bounds

       , resolve
       , resolution

       , repeat
       , repeatFlow
       , facet
       , facetFlow
       , FacetMapping(..)
       , FacetChannel(..)

       , BooleanOp(..)

       , name
       , description
       , height
       , heightOfContainer
       , heightStep
       , width
       , widthOfContainer
       , widthStep
       , padding
       , autosize
       , background
       , usermetadata

       , viewBackground

       , configure

       -- not for external export
       , autosizeProperty
       , axisProperty
       , paddingSpec
       , schemeProperty

       )
    where

-- VegaLite uses these symbols.
import Prelude hiding (filter, lookup, repeat)

import qualified Data.Aeson as A
import qualified Data.Text as T

import Data.Aeson (object, toJSON, (.=))
import Data.Maybe (mapMaybe)

#if !(MIN_VERSION_base(4, 12, 0))
import Data.Monoid ((<>))
#endif

-- added in base 4.8.0.0 / ghc 7.10.1
import Numeric.Natural (Natural)

import Graphics.Vega.VegaLite.Data
  ( DataValue(..)
  , DataValues(..)
  , dataValueSpec
  , dataValuesSpecs
  )
import Graphics.Vega.VegaLite.Foundation
  ( Angle
  , Color
  , DashStyle
  , DashOffset
  , FieldName
  , Opacity
  , StyleLabel
  , VegaExpr
  , ZIndex
  , FontWeight
  , Measurement
  , Arrangement
  , APosition
  , Position
  , HAlign
  , VAlign
  , BandAlign
  , Scale
  , OverlapStrategy
  , Side
  , StackProperty
  , StackOffset
  , StrokeCap
  , Channel
  , Resolve
  , Bounds
  , CompositionAlignment
  , Padding
  , Autosize
  , RepeatFields
  , CInterpolate
  , ViewBackground
  , HeaderProperty
  , Symbol
  , fromT
  , fromColor
  , fromDS
  , splitOnNewline
  , field_
  , header_
  , order_
  , fontWeightSpec
  , measurementLabel
  , arrangementLabel
  , anchorLabel
  , hAlignLabel
  , vAlignLabel
  , bandAlignLabel
  , scaleLabel
  , strokeCapLabel
  , positionLabel
  , overlapStrategyLabel
  , sideLabel
  , stackPropertySpecSort
  , stackPropertySpecOffset
  , stackOffset
  , channelLabel
  , resolveProperty
  , boundsSpec
  , compositionAlignmentSpec
  , paddingSpec
  , autosizeProperty
  , repeatFieldsProperty
  , cInterpolateSpec
  , viewBackgroundSpec
  , symbolLabel
  )
import Graphics.Vega.VegaLite.Input
  ( Data
  )
import Graphics.Vega.VegaLite.Legend
  ( LegendProperty
  , legendProp_
  )
import Graphics.Vega.VegaLite.Mark
  ( Mark
  , MarkProperty
  , markLabel
  , markProperty
  )
import Graphics.Vega.VegaLite.Scale
  ( ScaleDomain(..)
  , DomainLimits(..)
  , ScaleRange(..)
  , ScaleNice
  , scaleDomainProperty
  , domainLimitsSpec
  , scaleNiceSpec
  )
import Graphics.Vega.VegaLite.Specification
  ( VLProperty(..)
  , VLSpec
  , PropertySpec
  , LabelledSpec
  , EncodingSpec(..)
  , BuildEncodingSpecs
  , TransformSpec(..)
  , BuildTransformSpecs
  , ConfigureSpec(..)
  , ResolveSpec(..)
  , BuildResolveSpecs
  , SelectionLabel
  )
import Graphics.Vega.VegaLite.Time
  ( DateTime
  , TimeUnit
  , dateTimeSpec
  , timeUnitSpec
  )
import Graphics.Vega.VegaLite.Transform
  ( Operation(Count)
  , Window
  , BinProperty
  , WindowProperty
  , ImputeProperty
  , aggregate_
  , op_
  , binned_
  , impute_
  , bin
  , binProperty
  , operationSpec
  , windowTS
  , joinAggregateTS
  , imputeTS
  )

--- helpers

-- This could be extended to any Ord type but specialize for now to Double
clamped ::
  Double
  -- ^ minimum value allowed
  -> Double
  -- ^ maximum value allowed (must be > the minimum value)
  -> Double
  -- ^ user value
  -> Double
clamped :: Double -> Double -> Double -> Double
clamped Double
xmin Double
xmax Double
x = Double -> Double -> Double
forall a. Ord a => a -> a -> a
max Double
xmin (Double -> Double -> Double
forall a. Ord a => a -> a -> a
min Double
xmax Double
x)


repeat_ :: Arrangement -> LabelledSpec
repeat_ :: Arrangement -> LabelledSpec
repeat_ Arrangement
arr = Text
"repeat" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Arrangement -> Text
arrangementLabel Arrangement
arr

sort_ :: [SortProperty] -> LabelledSpec
sort_ :: [SortProperty] -> LabelledSpec
sort_ [SortProperty]
ops = Text
"sort" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [SortProperty] -> VLSpec
sortPropertySpec [SortProperty]
ops

mchan_ :: T.Text -> [MarkChannel] -> EncodingSpec
mchan_ :: Text -> [MarkChannel] -> EncodingSpec
mchan_ Text
f [MarkChannel]
ms = LabelledSpec -> EncodingSpec
ES (Text
f Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [LabelledSpec] -> VLSpec
object ((MarkChannel -> [LabelledSpec]) -> [MarkChannel] -> [LabelledSpec]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap MarkChannel -> [LabelledSpec]
markChannelProperty [MarkChannel]
ms))

mtype_ :: Measurement -> LabelledSpec
mtype_ :: Measurement -> LabelledSpec
mtype_ Measurement
m = Text
"type" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Measurement -> Text
measurementLabel Measurement
m

timeUnit_ :: TimeUnit -> LabelledSpec
timeUnit_ :: TimeUnit -> LabelledSpec
timeUnit_ TimeUnit
tu = Text
"timeUnit" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= TimeUnit -> VLSpec
timeUnitSpec TimeUnit
tu

-- The assumption at the moment is that it's always correct to
-- replace the empty list by null.
--
scaleProp_ :: [ScaleProperty] -> LabelledSpec
scaleProp_ :: [ScaleProperty] -> LabelledSpec
scaleProp_ [] = Text
"scale" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= VLSpec
A.Null
scaleProp_ [ScaleProperty]
sps = Text
"scale" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [LabelledSpec] -> VLSpec
object ((ScaleProperty -> LabelledSpec)
-> [ScaleProperty] -> [LabelledSpec]
forall a b. (a -> b) -> [a] -> [b]
map ScaleProperty -> LabelledSpec
scaleProperty [ScaleProperty]
sps)


value_ :: T.Text -> LabelledSpec
value_ :: Text -> LabelledSpec
value_ Text
v = Text
"value" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
v


selCond_ :: (a -> [LabelledSpec]) -> BooleanOp -> [a] -> [a] -> [LabelledSpec]
selCond_ :: (a -> [LabelledSpec]) -> BooleanOp -> [a] -> [a] -> [LabelledSpec]
selCond_ a -> [LabelledSpec]
getProps BooleanOp
selName [a]
ifClause [a]
elseClause =
  let h :: LabelledSpec
h = (Text
"condition", VLSpec
hkey)
      toProps :: [a] -> [LabelledSpec]
toProps = (a -> [LabelledSpec]) -> [a] -> [LabelledSpec]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap a -> [LabelledSpec]
getProps
      hkey :: VLSpec
hkey = [LabelledSpec] -> VLSpec
object ((Text
"selection", BooleanOp -> VLSpec
booleanOpSpec BooleanOp
selName) LabelledSpec -> [LabelledSpec] -> [LabelledSpec]
forall a. a -> [a] -> [a]
: [a] -> [LabelledSpec]
toProps [a]
ifClause)
      hs :: [LabelledSpec]
hs = [a] -> [LabelledSpec]
toProps [a]
elseClause
  in LabelledSpec
h LabelledSpec -> [LabelledSpec] -> [LabelledSpec]
forall a. a -> [a] -> [a]
: [LabelledSpec]
hs

-- Special case the single-condition check, so that I don't get false
-- positives when comparing against the Vega-Lite specification. There
-- should be no actionable difference from this special case (i.e.
-- the output being '[object]' and 'object' have the same meaning).
--
-- There is also the simplification to replace
--      test: { selection: xxx }
-- by
--      selection: xxx
-- which happens for the Selection operator.
--
dataCond_ :: (a -> [LabelledSpec]) -> [(BooleanOp, [a])] -> [a] -> [LabelledSpec]
dataCond_ :: (a -> [LabelledSpec])
-> [(BooleanOp, [a])] -> [a] -> [LabelledSpec]
dataCond_ a -> [LabelledSpec]
getProps [(BooleanOp, [a])]
tests [a]
elseClause =
  let h :: LabelledSpec
h = (Text
"condition", VLSpec
condClause)
      condClause :: VLSpec
condClause = case [VLSpec]
conds of
                     [VLSpec
cond] -> VLSpec
cond
                     [VLSpec]
_ -> [VLSpec] -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON [VLSpec]
conds
      conds :: [VLSpec]
conds = ((BooleanOp, [a]) -> VLSpec) -> [(BooleanOp, [a])] -> [VLSpec]
forall a b. (a -> b) -> [a] -> [b]
map (BooleanOp, [a]) -> VLSpec
testClause [(BooleanOp, [a])]
tests
      testClause :: (BooleanOp, [a]) -> VLSpec
testClause (Selection Text
sel, [a]
ifClause) =
        [LabelledSpec] -> VLSpec
object ((Text
"selection" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
sel) LabelledSpec -> [LabelledSpec] -> [LabelledSpec]
forall a. a -> [a] -> [a]
: [a] -> [LabelledSpec]
toProps [a]
ifClause)
      testClause (BooleanOp
predicate, [a]
ifClause) =
        [LabelledSpec] -> VLSpec
object ((Text
"test", BooleanOp -> VLSpec
booleanOpSpec BooleanOp
predicate) LabelledSpec -> [LabelledSpec] -> [LabelledSpec]
forall a. a -> [a] -> [a]
: [a] -> [LabelledSpec]
toProps [a]
ifClause)
      toProps :: [a] -> [LabelledSpec]
toProps = (a -> [LabelledSpec]) -> [a] -> [LabelledSpec]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap a -> [LabelledSpec]
getProps
      hs :: [LabelledSpec]
hs = [a] -> [LabelledSpec]
toProps [a]
elseClause
  in LabelledSpec
h LabelledSpec -> [LabelledSpec] -> [LabelledSpec]
forall a. a -> [a] -> [a]
: [LabelledSpec]
hs



{-|

Create a named aggregation operation on a field that can be added to a transformation.
For further details see the
<https://vega.github.io/vega-lite/docs/aggregate.html#aggregate-op-def Vega-Lite documentation>.

@
'transform'
    . 'aggregate'
        [ 'opAs' 'Graphics.Vega.VegaLite.Min' "people" "lowerBound"
        , 'opAs' 'Graphics.Vega.VegaLite.Max' "people" "upperBound"
        ]
        [ "age" ]
@
-}
opAs ::
  Operation
  -- ^ The aggregation operation to use.
  -> FieldName
  -- ^ The name of the field which is to be aggregated (when the operation
  --   is 'Count' leave as the empty string).
  -> FieldName
  -- ^ The name given to the transformed data.
  -> VLSpec

-- The Count case is special-cased purely to make it easier to compare
-- the hvega output against the Veg-Lite examples. There should be no
-- semantic difference here.
--
opAs :: Operation -> Text -> Text -> VLSpec
opAs Operation
Count Text
_ Text
label =
  [LabelledSpec] -> VLSpec
object [ Operation -> LabelledSpec
op_ Operation
Count, Text
"as" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
label ]
opAs Operation
op Text
field Text
label =
  [LabelledSpec] -> VLSpec
object [ Operation -> LabelledSpec
op_ Operation
op, Text -> LabelledSpec
field_ Text
field, Text
"as" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
label ]


{-|

Create a mark specification. All marks must have a type (first parameter) and
can optionally be customised with a list of mark properties such as interpolation
style for lines. To keep the default style for the mark, just provide an empty list
for the second parameter.

@
'mark' 'Graphics.Vega.VegaLite.Circle' []
'mark' 'Graphics.Vega.VegaLite.Line' ['Graphics.Vega.VegaLite.MInterpolate' 'Graphics.Vega.VegaLite.StepAfter']
@

@
let dvals = 'Graphics.Vega.VegaLite.dataFromUrl' \"city.json\" ['Graphics.Vega.VegaLite.TopojsonFeature' \"boroughs\"] []
    markOpts = 'mark' 'Graphics.Vega.VegaLite.Geoshape' ['Graphics.Vega.VegaLite.MFill' \"lightgrey\", 'Graphics.Vega.VegaLite.MStroke' \"white\"]
in 'Graphics.Vega.VegaLite.toVegaLite' [dvals, markOpts]
@
-}
mark :: Mark -> [MarkProperty] -> PropertySpec
mark :: Mark -> [MarkProperty] -> PropertySpec
mark Mark
mrk [MarkProperty]
props =
  let jsName :: VLSpec
jsName = Text -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON (Mark -> Text
markLabel Mark
mrk)
      vals :: VLSpec
vals = if [MarkProperty] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [MarkProperty]
props
             then VLSpec
jsName
             else [LabelledSpec] -> VLSpec
object ((Text
"type" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= VLSpec
jsName) LabelledSpec -> [LabelledSpec] -> [LabelledSpec]
forall a. a -> [a] -> [a]
: (MarkProperty -> LabelledSpec) -> [MarkProperty] -> [LabelledSpec]
forall a b. (a -> b) -> [a] -> [b]
map MarkProperty -> LabelledSpec
markProperty [MarkProperty]
props)

  in (VLProperty
VLMark, VLSpec
vals)


{-|

Mark channel properties used for creating a mark channel encoding.
-}

-- https://vega.github.io/vega-lite/docs/encoding.html#mark-prop

data MarkChannel
    = MName FieldName
      -- ^ Field used for encoding with a mark property channel.
    | MRepeat Arrangement
      -- ^ Reference in a mark channel to a field name generated by 'repeatFlow'
      --   or 'repeat'. The parameter identifies whether reference is being made to
      --   fields that are to be arranged in columns, in rows, or a with a flow layout.
    | MRepeatDatum Arrangement
      -- ^ Reference in a mark channel to a datum value generated by 'repeatFlow'
      --   or 'repeat'. The parameter identifies whether reference is being made to
      --   a datum that is to be encoded in layers, or in columns or rows in a
      --   flow layout.
      --
      --   @since 0.9.0.0
    | MmType Measurement
      -- ^ Level of measurement when encoding with a mark property channel.
    | MScale [ScaleProperty]
      -- ^ Scaling applied to a field when encoding with a mark property channel.
      --   The scale will transform a field's value into a color, shape, size etc.
      --
      --   Use an empty list to remove the scale.
    | MBin [BinProperty]
      -- ^ Discretize numeric values into bins when encoding with a mark property channel.
    | MBinned
      -- ^ Indicate that data encoding with a mark are already binned.
      --
      --   @since 0.4.0.0
    | MSort [SortProperty]
      -- ^ Sort order.
      --
      --   @since 0.4.0.0
    | MTimeUnit TimeUnit
      -- ^ Time unit aggregation of field values when encoding with a mark property channel.
    | MTitle T.Text
      -- ^ Title of a field when encoding with a mark property channel.
      --
      --   @since 0.4.0.0
    | MNoTitle
      -- ^ Draw no title.
      --
      --   @since 0.4.0.0
    | MAggregate Operation
      -- ^ Compute aggregate summary statistics for a field to be encoded with a
      --   mark property channel.
    | MLegend [LegendProperty]
      -- ^ Properties of a legend that describes a mark's encoding.
      --
      --   For no legend, provide an empty list.
    | MSelectionCondition BooleanOp [MarkChannel] [MarkChannel]
      -- ^ Make a mark channel conditional on interactive selection. The first parameter
      --   is a selection condition to evaluate; the second the encoding to apply if that
      --   selection is true; the third parameter is the encoding if the selection is false.
      --
      -- @
      -- 'color'
      --   [ MSelectionCondition ('SelectionName' \"myBrush\")
      --      [ 'MName' \"myField\", 'MmType' 'Graphics.Vega.VegaLite.Ordinal' ]
      --      [ 'MString' \"grey\" ]
      --   ]
      -- @
    | MDataCondition [(BooleanOp, [MarkChannel])] [MarkChannel]
      -- ^ Make a text channel conditional on one or more predicate expressions. The first
      --   parameter is a list of tuples each pairing an expression to evaluate with the encoding
      --   if that expression is @True@. The second is the encoding if none of the expressions
      --   evaluate as @True@.
      --
      -- @
      -- 'color'
      --   [ MDataCondition [ ( 'Expr' \"datum.myField === null\", [ 'MString' \"grey\" ] ) ]
      --      [ MString \"black\" ]
      --   ]
      -- @
      --
      --   The arguments to this constructor have changed in @0.4.0.0@
      --   to support multiple expressions.
    | MPath T.Text
      -- ^ SVG path string used when encoding with a mark property channel. Useful
      --   for providing custom shapes.
    | MDatum DataValue
      -- ^ Name of a literal data item used for encoding with a mark property channel.
      --   Unlike 'MNumber', 'MString', and 'MBoolean', datum literals represent values in
      --   data space.
      --
      --   @since 0.9.0.0
    | MNumber Double
      -- ^ Literal numeric value when encoding with a mark property channel.
    | MString T.Text
      -- ^ Literal string value when encoding with a mark property channel.
    | MBoolean Bool
      -- ^ Boolean value when encoding with a mark property channel.
    | MNullValue
      -- ^ A null value.
      --
      --   @since 0.11.0.0
    | MSymbol Symbol
      -- ^ A symbol literal. This can be useful when making a symbol dependent on some data or
      --   selection condition (e.g. 'MDataCondition' or 'MSelectionCondition').
      --
      --   For example:
      --
      --   @
      --   'encoding'
      --     . 'position' 'Graphics.Vega.VegaLite.X' [ 'PName' "to", 'PmType' 'Graphics.Vega.VegaLite.Quantitative', 'PAxis' [] ]
      --     . 'shape' ['MDataCondition'
      --               [('Expr' "datum.to > 100", [MSymbol 'Graphics.Vega.VegaLite.SymTriangleRight'])]
      --               [MSymbol 'Graphics.Vega.VegaLite.SymTriangleLeft']
      --   @
      --
      --   @since 0.6.0.0

markChannelProperty :: MarkChannel -> [LabelledSpec]
markChannelProperty :: MarkChannel -> [LabelledSpec]
markChannelProperty (MName Text
s) = [Text -> LabelledSpec
field_ Text
s]
markChannelProperty (MRepeat Arrangement
arr) = [Text
"field" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [LabelledSpec] -> VLSpec
object [Arrangement -> LabelledSpec
repeat_ Arrangement
arr]]
markChannelProperty (MRepeatDatum Arrangement
arr) = [Text
"datum" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [LabelledSpec] -> VLSpec
object [Arrangement -> LabelledSpec
repeat_ Arrangement
arr]]
markChannelProperty (MmType Measurement
t) = [Measurement -> LabelledSpec
mtype_ Measurement
t]
markChannelProperty (MScale [ScaleProperty]
sps) = [[ScaleProperty] -> LabelledSpec
scaleProp_ [ScaleProperty]
sps]
markChannelProperty (MLegend [LegendProperty]
lps) = [[LegendProperty] -> LabelledSpec
legendProp_ [LegendProperty]
lps]
markChannelProperty (MBin [BinProperty]
bps) = [[BinProperty] -> LabelledSpec
bin [BinProperty]
bps]
markChannelProperty MarkChannel
MBinned = [LabelledSpec
binned_]
markChannelProperty (MSort [SortProperty]
ops) = [[SortProperty] -> LabelledSpec
sort_ [SortProperty]
ops]
markChannelProperty (MSelectionCondition BooleanOp
selName [MarkChannel]
ifClause [MarkChannel]
elseClause) =
  (MarkChannel -> [LabelledSpec])
-> BooleanOp -> [MarkChannel] -> [MarkChannel] -> [LabelledSpec]
forall a.
(a -> [LabelledSpec]) -> BooleanOp -> [a] -> [a] -> [LabelledSpec]
selCond_ MarkChannel -> [LabelledSpec]
markChannelProperty BooleanOp
selName [MarkChannel]
ifClause [MarkChannel]
elseClause
markChannelProperty (MDataCondition [(BooleanOp, [MarkChannel])]
tests [MarkChannel]
elseClause) =
  (MarkChannel -> [LabelledSpec])
-> [(BooleanOp, [MarkChannel])] -> [MarkChannel] -> [LabelledSpec]
forall a.
(a -> [LabelledSpec])
-> [(BooleanOp, [a])] -> [a] -> [LabelledSpec]
dataCond_ MarkChannel -> [LabelledSpec]
markChannelProperty [(BooleanOp, [MarkChannel])]
tests [MarkChannel]
elseClause
markChannelProperty (MTimeUnit TimeUnit
tu) = [TimeUnit -> LabelledSpec
timeUnit_ TimeUnit
tu]
markChannelProperty (MAggregate Operation
op) = [Operation -> LabelledSpec
aggregate_ Operation
op]
markChannelProperty (MPath Text
s) = [Text
"value" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
s]
markChannelProperty (MDatum DataValue
d) = [Text
"datum" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= DataValue -> VLSpec
dataValueSpec DataValue
d]
markChannelProperty (MNumber Double
x) = [Text
"value" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x]
markChannelProperty (MString Text
s) = [Text
"value" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
s]
markChannelProperty (MBoolean Bool
b) = [Text
"value" Text -> Bool -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
b]
markChannelProperty (MSymbol Symbol
s) = [Text
"value" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Symbol -> Text
symbolLabel Symbol
s]
markChannelProperty MarkChannel
MNullValue = [Text
"value" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= VLSpec
A.Null]
markChannelProperty (MTitle Text
s) = [Text
"title" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text -> VLSpec
splitOnNewline Text
s]
markChannelProperty MarkChannel
MNoTitle = [Text
"title" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= VLSpec
A.Null]


{-|

Create an encoding specification from a list of channel encodings.

@
enc = 'encoding'
        . 'position' 'Graphics.Vega.VegaLite.X' [ 'PName' \"Animal\", 'PmType' 'Graphics.Vega.VegaLite.Ordinal' ]
        . 'position' 'Graphics.Vega.VegaLite.Y' [ 'PName' \"Age\", 'PmType' 'Graphics.Vega.VegaLite.Quantitative' ]
        . 'shape' [ 'MName' \"Species\", 'MmType' 'Graphics.Vega.VegaLite.Nominal' ]
        . 'size' [ 'MName' \"Population\", 'MmType' 'Graphics.Vega.VegaLite.Quantitative' ]
@

The type of @enc@ in this example is @[EncodingSpec] -> PropertySpec@,
so it can either be used to add further encoding specifications or as
@enc []@ to create a specification.

The supported encodings are:
'ariaDescription', 'angle', 'color', 'column', 'detail', 'fill', 'fillOpacity',
'hyperlink', 'opacity', 'order', 'position', 'row', 'shape', 'size',
'stroke', 'strokeDash', 'strokeOpacity', 'strokeWidth', 'text', 'tooltip',
'tooltips', and 'url'.

There is currently no support for encoding by
<https://vega.github.io/vega-lite/docs/encoding.html#key key>.

-}
encoding ::
  [EncodingSpec]
  -- ^ The channel encodings (the order does not matter).
  --
  --   Prior to @0.5.0.0@ this argument was @['LabelledSpec']@.
  -> PropertySpec
encoding :: [EncodingSpec] -> PropertySpec
encoding [EncodingSpec]
channels = (VLProperty
VLEncoding, [LabelledSpec] -> VLSpec
object ((EncodingSpec -> LabelledSpec) -> [EncodingSpec] -> [LabelledSpec]
forall a b. (a -> b) -> [a] -> [b]
map EncodingSpec -> LabelledSpec
unES [EncodingSpec]
channels))


{-|

Encode an Aria description.

@since 0.9.0.0
-}
ariaDescription ::
  [AriaDescriptionChannel]
  -- ^ The properties for the channel.
  -> BuildEncodingSpecs
ariaDescription :: [AriaDescriptionChannel] -> BuildEncodingSpecs
ariaDescription [AriaDescriptionChannel]
ads [EncodingSpec]
ols =
  LabelledSpec -> EncodingSpec
ES (Text
"description", [LabelledSpec] -> VLSpec
object ((AriaDescriptionChannel -> [LabelledSpec])
-> [AriaDescriptionChannel] -> [LabelledSpec]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap AriaDescriptionChannel -> [LabelledSpec]
ariaDescriptionChannelProperty [AriaDescriptionChannel]
ads)) EncodingSpec -> BuildEncodingSpecs
forall a. a -> [a] -> [a]
: [EncodingSpec]
ols


{-|

Apply a stack transform for positioning multiple values. This is an alternative
to specifying stacking directly when encoding position.

@
'transform'
    . 'aggregate' [ 'opAs' 'Count' \"\" \"count_*\" ] [ \"Origin\", \"Cylinders\" ]
    . 'stack' "count_*"
        []
        \"stack_count_Origin1\"
        \"stack_count_Origin2\"
        [ 'Graphics.Vega.VegaLite.StOffset' 'Graphics.Vega.VegaLite.StNormalize', 'Graphics.Vega.VegaLite.StSort' [ 'Graphics.Vega.VegaLite.WAscending' \"Origin\" ] ]
    . 'window'
        [ ( [ 'Graphics.Vega.VegaLite.WAggregateOp' 'Graphics.Vega.VegaLite.Min', 'Graphics.Vega.VegaLite.WField' \"stack_count_Origin1\" ], \"x\" )
        , ( [ 'Graphics.Vega.VegaLite.WAggregateOp' 'Graphics.Vega.VegaLite.Max', 'Graphics.Vega.VegaLite.WField' \"stack_count_Origin2\" ], \"x2\" )
        ]
        [ 'Graphics.Vega.VegaLite.WFrame' Nothing Nothing, 'Graphics.Vega.VegaLite.WGroupBy' [ \"Origin\" ] ]
    . 'stack' \"count_*\"
        [ \"Origin\" ]
        \"y\"
        \"y2\"
        [ 'Graphics.Vega.VegaLite.StOffset' 'Graphics.Vega.VegaLite.StNormalize', 'Graphics.Vega.VegaLite.StSort' [ 'Graphics.Vega.VegaLite.WAscending' \"Cylinders\" ] ]
@

@since 0.4.0.0

-}

stack ::
  FieldName
  -- ^ The field to be stacked.
  -> [FieldName]
  -- ^ The fields to group by.
  -> FieldName
  -- ^ The output field name (start).
  -> FieldName
  -- ^ The output field name (end).
  -> [StackProperty]
  -- ^ Offset and sort properties.
  -> BuildTransformSpecs
stack :: Text
-> [Text] -> Text -> Text -> [StackProperty] -> BuildTransformSpecs
stack Text
f [Text]
grp Text
start Text
end [StackProperty]
sProps [TransformSpec]
ols =
  let addField :: Text -> [v] -> [a]
addField Text
n [v
x] = [Text
n Text -> v -> a
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= v
x]
      addField Text
_ [v]
_ = []

      mOffset :: [VLSpec]
mOffset = (StackProperty -> Maybe VLSpec) -> [StackProperty] -> [VLSpec]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe StackProperty -> Maybe VLSpec
stackPropertySpecOffset [StackProperty]
sProps
      mSort :: [VLSpec]
mSort = (StackProperty -> Maybe VLSpec) -> [StackProperty] -> [VLSpec]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe StackProperty -> Maybe VLSpec
stackPropertySpecSort [StackProperty]
sProps

      fields :: [LabelledSpec]
fields = [ Text
"stack" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
f
               , Text
"groupby" Text -> [Text] -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [Text]
grp
               , Text
"as" Text -> [Text] -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [ Text
start, Text
end ] ]
               [LabelledSpec] -> [LabelledSpec] -> [LabelledSpec]
forall a. Semigroup a => a -> a -> a
<> Text -> [VLSpec] -> [LabelledSpec]
forall a v. (KeyValue a, ToJSON v) => Text -> [v] -> [a]
addField Text
"offset" [VLSpec]
mOffset
               [LabelledSpec] -> [LabelledSpec] -> [LabelledSpec]
forall a. Semigroup a => a -> a -> a
<> Text -> [VLSpec] -> [LabelledSpec]
forall a v. (KeyValue a, ToJSON v) => Text -> [v] -> [a]
addField Text
"sort" [VLSpec]
mSort

  in VLSpec -> TransformSpec
TS ([LabelledSpec] -> VLSpec
object [LabelledSpec]
fields) TransformSpec -> BuildTransformSpecs
forall a. a -> [a] -> [a]
: [TransformSpec]
ols


{-|

Individual scale property. These are used to customise an individual scale
transformation. To customise all scales use 'configure' and supply relevant
'Graphics.Vega.VegaLite.ScaleConfig' values. For more details see the
<https://vega.github.io/vega-lite/docs/scale.html Vega-Lite documentation>.

There are two utility routines for constructing a list of scale
properties: 'categoricalDomainMap' and 'domainRangeMap'.

The @SRangeStep@ constructor was removed in version @0.5.0.0@. Users
should use the 'heightStep' and 'widthStep' functions instead.

The @SReverse@ constructor was removed in version @0.4.0.0@, as it
represented a Vega, rather than Vega-Lite, property. The order of
a scale can be changed with the 'PSort' constructor.
-}

-- based on schema 3.3.0 #/definitions/Scale

data ScaleProperty
    = SType Scale
      -- ^ Type of scaling to apply.
    | SAlign Double
      -- ^ Alignment of the steps within the scale range. A value of
      --   @0@ shifts the bands to an axis, @1@ away from the axis,
      --   and @0.5@ is centered within the range.
      --
      --   The input is clamped so that values less than 0 are mapped
      --   to 0 and greater than 1 to 1.
      --
      --   @since 0.4.0.0
    | SBase Double
      -- ^ The base to use for log scaling ('Graphics.Vega.VegaLite.ScLog').
      --
      --   Default is @10@.
      --
      --   @since 0.4.0.0
    | SBins [Double]
      -- ^ An array of bin boundaries over the scale domain. If give, axes and legends will use
      --   these boundaries to inform the choice of tick marks and text labels.
      --
      --   @since 0.4.0.0
    | SClamp Bool
      -- ^ Should values outside the data domain be clamped (to the minimum or
      --   maximum value)?
    | SConstant Double
      -- ^ The desired slope of the 'Graphics.Vega.VegaLite.ScSymLog' function at zero.
      --
      --   The default is @1@.
      --
      --   @since 0.4.0.0
    | SDomain DomainLimits
      -- ^ Custom scaling domain. See also 'SDomainOpt'.
      --
      --   In verson @0.11.0.0@ some functionality was moved to 'SDomainOpt'.
    | SDomainMid Double
      -- ^ Set the mid-point of a continuous diverging domain.
      --
      --   This is deprecated as of 0.11.0.0 and @'SDomainOpt' ('DMid' x)@ should be used
      --   instead.
      --
      --   @since 0.6.0.0
    | SDomainOpt ScaleDomain
      -- ^ Custom scaling domain. See also 'SDomain'.
      --
      --   @since 0.11.0.0
    | SExponent Double
      -- ^ The exponent to use for power scaling ('Graphics.Vega.VegaLite.ScPow').
      --
      --   @since 0.4.0.0
    | SInterpolate CInterpolate
      -- ^ Interpolation method for scaling range values.
    | SNice ScaleNice
      -- ^ \"Nice\" minimum and maximum values in a scaling (e.g. multiples of 10).
    | SPadding Double
      -- ^ Padding in pixels to apply to a scaling.
    | SPaddingInner Double
      -- ^ Inner padding to apply to a band scaling.
    | SPaddingOuter Double
      -- ^ Outer padding to apply to a band scaling.
    | SRange ScaleRange
      -- ^ Range of a scaling. The type of range depends on the encoding channel.
    | SReverse Bool
      -- ^ Should the order of the scale range be reversed?
      --
      --   @since 0.6.0.0
    | SRound Bool
      -- ^ Are numeric values in a scaling rounded to integers?
      --
      --   The default is @False@.
    | SScheme T.Text [Double]   -- TODO: review this; what is #/definitions/SchemeParams?
      -- ^  Color scheme used by a color scaling. The first parameter is the
      --    name of the scheme (e.g. \"viridis\") and the second an optional
      --    specification, which can contain 1, 2, or 3 numbers:
      --
      --      - the number of colors to use (list of one number);
      --      - the extent of the color range to use (list of two numbers between 0 and 1);
      --      - the number of colors and extent (three numbers, first is the number of colors).
      --
      --    For the full list of supported schemes, please refer to the
      --    <https://vega.github.io/vega/docs/schemes/#reference Vega Scheme>
      --    reference.
      --
      --    The number of colors was broken prior to @0.4.0.0@ and the option to
      --    define both the count and extent was added in @0.4.0.0@.
    | SZero Bool
      -- ^ Should a numeric scaling be forced to include a zero value?
      --
      --   Not all scales support @SZero@ and the default depends on the type of
      --   channel.


scaleProperty :: ScaleProperty -> LabelledSpec
scaleProperty :: ScaleProperty -> LabelledSpec
scaleProperty (SType Scale
sType) = Text
"type" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Scale -> Text
scaleLabel Scale
sType
scaleProperty (SAlign Double
c) = Text
"align" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double -> Double -> Double -> Double
clamped Double
0 Double
1 Double
c
scaleProperty (SBase Double
x) = Text
"base" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
scaleProperty (SBins [Double]
xs) = Text
"bins" Text -> [Double] -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [Double]
xs
scaleProperty (SClamp Bool
b) = Text
"clamp" Text -> Bool -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
b
scaleProperty (SConstant Double
x) = Text
"constant" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
scaleProperty (SDomain DomainLimits
dl) = Text
"domain" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= DomainLimits -> VLSpec
domainLimitsSpec DomainLimits
dl
scaleProperty (SDomainMid Double
x) = Text
"domainMid" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
scaleProperty (SDomainOpt ScaleDomain
sd) = ScaleDomain -> LabelledSpec
scaleDomainProperty ScaleDomain
sd
scaleProperty (SExponent Double
x) = Text
"exponent" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
scaleProperty (SInterpolate CInterpolate
interp) = Text
"interpolate" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= CInterpolate -> VLSpec
cInterpolateSpec CInterpolate
interp
scaleProperty (SNice ScaleNice
ni) = Text
"nice" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= ScaleNice -> VLSpec
scaleNiceSpec ScaleNice
ni
scaleProperty (SPadding Double
x) = Text
"padding" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
scaleProperty (SPaddingInner Double
x) = Text
"paddingInner" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
scaleProperty (SPaddingOuter Double
x) = Text
"paddingOuter" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
scaleProperty (SRange (RField Text
f)) = Text
"range" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [LabelledSpec] -> VLSpec
object [Text
"field" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
f]
scaleProperty (SRange (RMax Double
x)) = Text
"rangeMax" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
scaleProperty (SRange (RMin Double
x)) = Text
"rangeMin" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
scaleProperty (SRange (RPair Double
lo Double
hi)) = Text
"range" Text -> [Double] -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [Double
lo, Double
hi]
scaleProperty (SRange (RHeight Double
w)) = Text
"range" Text -> [VLSpec] -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [Text -> VLSpec
fromT Text
"height", Double -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON Double
w]
scaleProperty (SRange (RWidth Double
h)) = Text
"range" Text -> [VLSpec] -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [Double -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON Double
h, Text -> VLSpec
fromT Text
"width"]
scaleProperty (SRange (RNumbers [Double]
xs)) = Text
"range" Text -> [Double] -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [Double]
xs
scaleProperty (SRange (RNumberLists [[Double]]
xss)) = Text
"range" Text -> [[Double]] -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [[Double]]
xss
scaleProperty (SRange (RStrings [Text]
ss)) = Text
"range" Text -> [Text] -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [Text]
ss
scaleProperty (SRange (RName Text
s)) = Text
"range" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
s
scaleProperty (SReverse Bool
b) = Text
"reverse" Text -> Bool -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
b
scaleProperty (SRound Bool
b) = Text
"round" Text -> Bool -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
b
scaleProperty (SScheme Text
nme [Double]
extent) = Text -> [Double] -> LabelledSpec
schemeProperty Text
nme [Double]
extent
scaleProperty (SZero Bool
b) = Text
"zero" Text -> Bool -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
b


-- TODO: there should probably be a more-structured way to specify this
--
-- based on schema 3.3.0 #/definitions/SchemeParams

schemeProperty :: T.Text -> [Double] -> LabelledSpec
schemeProperty :: Text -> [Double] -> LabelledSpec
schemeProperty Text
nme [Double
n] = Text
"scheme" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [LabelledSpec] -> VLSpec
object [Text
"name" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
nme, Text
"count" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
n]
schemeProperty Text
nme [Double
mn, Double
mx] = Text
"scheme" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [LabelledSpec] -> VLSpec
object [Text
"name" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
nme, Text
"extent" Text -> [Double] -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [Double
mn, Double
mx]]
schemeProperty Text
nme [Double
n, Double
mn, Double
mx] = Text
"scheme" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [LabelledSpec] -> VLSpec
object [Text
"name" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
nme, Text
"count" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
n, Text
"extent" Text -> [Double] -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [Double
mn, Double
mx]]
schemeProperty Text
nme [Double]
_ = Text
"scheme" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
nme


{-|

Allow type of sorting to be customised. For details see the
<https://vega.github.io/vega-lite/docs/sort.html Vega-Lite documentation>.

The constructors have been changed in version @0.4.0.0@, with
@Op@, @ByField@, and @ByRepeat@ removed, and their functionality
replaced with 'ByRepeatOp', 'ByFieldOp', and 'ByChannel'.

-}
data SortProperty
    = Ascending
      -- ^ Sorting is from low to high.
    | Descending
      -- ^ Sorting is from high to low.
    | CustomSort DataValues
      -- ^ Custom sort order listing data values explicitly.
      --
      --   @since 0.4.0.0
    | ByRepeatOp Arrangement Operation
      -- ^ Sort by the aggregated summaries of the given fields
      --   (referenced by a repeat iterator) using an aggregation
      --   operation.
      --
      --   @since 0.4.0.0
    | ByFieldOp FieldName Operation
      -- ^ Sort by the aggregated summary of a field using an aggregation
      --   operation. The following example sorts the categorical data field
      --   @variety@ by the mean age of the data in each variety category:
      --
      -- @
      -- 'position' 'Graphics.Vega.VegaLite.Y'
      --   [ 'PName' "variety"
      --   , 'PmType' 'Graphics.Vega.VegaLite.Ordinal'
      --   , 'PSort' [ ByFieldOp "age" 'Graphics.Vega.VegaLite.Mean', 'Descending' ]
      --   ]
      -- @
      --
      --   @since 0.4.0.0
    | ByChannel Channel
      -- ^ Sort by another channel.
      --
      -- @
      -- 'position' 'Graphics.Vega.VegaLite.Y'
      --  [ 'PName' "age"
      --  , 'PmType' 'Graphics.Vega.VegaLite.Ordinal'
      --  , 'PSort' [ ByChannel 'Graphics.Vega.VegaLite.ChX' ]
      --  ]
      -- @
      --
      --   @since 0.4.0.0


sortProperty :: SortProperty -> [LabelledSpec]
sortProperty :: SortProperty -> [LabelledSpec]
sortProperty SortProperty
Ascending = [Text -> LabelledSpec
order_ Text
"ascending"]
sortProperty SortProperty
Descending = [Text -> LabelledSpec
order_ Text
"descending"]
sortProperty (ByChannel Channel
ch) = [Text
"encoding" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Channel -> Text
channelLabel Channel
ch]
sortProperty (ByFieldOp Text
field Operation
op) = [Text -> LabelledSpec
field_ Text
field, Operation -> LabelledSpec
op_ Operation
op]
sortProperty (ByRepeatOp Arrangement
arr Operation
op) = [Text
"field" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [LabelledSpec] -> VLSpec
object [Arrangement -> LabelledSpec
repeat_ Arrangement
arr], Operation -> LabelledSpec
op_ Operation
op]
sortProperty (CustomSort DataValues
_) = []


sortPropertySpec :: [SortProperty] -> VLSpec
sortPropertySpec :: [SortProperty] -> VLSpec
sortPropertySpec [] = VLSpec
A.Null
sortPropertySpec [SortProperty
Ascending] = Text -> VLSpec
fromT Text
"ascending"
sortPropertySpec [SortProperty
Descending] = Text -> VLSpec
fromT Text
"descending"
sortPropertySpec [CustomSort DataValues
dvs] = [VLSpec] -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON (DataValues -> [VLSpec]
dataValuesSpecs DataValues
dvs)
sortPropertySpec [SortProperty]
sps = [LabelledSpec] -> VLSpec
object ((SortProperty -> [LabelledSpec])
-> [SortProperty] -> [LabelledSpec]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap SortProperty -> [LabelledSpec]
sortProperty [SortProperty]
sps)


-- | Position channel properties used for creating a position channel encoding.

data PositionChannel
    = PName FieldName
      -- ^ Name of the field used for encoding with a position channel.
    | PHeight
      -- ^ Set the position to the height of the enclosing data space. Useful for placing
      --   a mark relative to the bottom edge of a view.
      --
      --   @since 0.4.0.0
    | PWidth
      -- ^ Set the position to the width of the enclosing data space. Useful for justifying
      --   a mark to the right hand edge of a view. e.g. to position a mark at the right of
      --   the data rectangle:
      --
      -- @
      -- enc =
      --   'encoding'
      --      . 'position' 'Graphics.Vega.VegaLite.X' [ PWidth ]
      -- @
      --
      --   @since 0.4.0.0
    | PDatum DataValue
      -- ^ Set a position to an arbitrary data value. Useful for placing items at a
      --   specific point in the data space. To place in data screen space use
      --   'PNumber'.
      --
      --   @since 0.9.0.0
    | PNumber Double
      -- ^ Set a position to an arbitrary value. Useful for placing items at the top of
      --   a plot area (@PNumber 0@) or a fixed number of pixels from the top.
      --   See also 'PHeight' and 'PWidth'.
      --
      --   Use 'PDatum' to place an item using a data coordinate.
      --
      --   @since 0.4.0.0
    | PRepeat Arrangement
      -- ^ Reference in a position channel to a field name generated by 'repeatFlow'
      --   or 'repeat'. The parameter identifies whether reference is being made to
      --   fields that are to be arranged in columns, in rows, or a with a flow layout.
      --
      --   For example:
      --
      -- @
      -- enc =
      --   'encoding'
      --      . 'position' 'Graphics.Vega.VegaLite.X' [ PRepeat 'Graphics.Vega.VegaLite.Flow', 'PmType' 'Graphics.Vega.VegaLite.Quantitative' ]
      --
      -- spec =
      --    'Graphics.Vega.VegaLite.asSpec' [ dataVals [], 'mark' 'Graphics.Vega.VegaLite.Tick' [], enc [] ]
      --
      -- 'Graphics.Vega.VegaLite.toVegaLite'
      --    [ 'repeatFlow' [ \"Horsepower\", \"Miles_per_Gallon\", \"Acceleration\"]
      --    , 'Graphics.Vega.VegaLite.specification' spec
      --    ]
      -- @
    | PRepeatDatum Arrangement
      -- ^ Reference in a position channel to a datum value generated by 'repeatFlow'
      --   or 'repeat'. The parameter identifies whether reference is being made to
      --   a datum that is to be encoded in layers, or in columns or rows in a
      --   flow layout.
      --
      --   @since 0.9.0.0
    | PmType Measurement
      -- ^ Level of measurement when encoding with a position channel.
    | PBin [BinProperty]
      -- ^ Discretize numeric values into bins when encoding with a
      --   position channel.
      --
      --   For example, to encode a frequency histogram with bins every 5 units:
      --
      --   @
      --   enc = 'encoding'
      --           . 'position' 'Graphics.Vega.VegaLite.X' [ 'PName' \"x\"
      --                        , 'PmType' 'Graphics.Vega.VegaLite.Ordinal'
      --                        , 'PBin' ['Graphics.Vega.VegaLite.Step' 5]
      --                        ]
      --           . 'position' 'Graphics.Vega.VegaLite.Y' [ 'PmType' 'Graphics.Vega.VegaLite.Quantitative'
      --                        , 'PAggregate' 'Count'
      --                        ]
      --   @
    | PBinned
      -- ^ Indicate that the data encoded with position is already binned.
      --
      --   @since 0.4.0.0
    | PTimeUnit TimeUnit
      -- ^ Form of time unit aggregation of field values when encoding with a position channel.
    | PTitle T.Text
      -- ^ Title of a field when encoding with a position channel.
      --
      --   @since 0.4.0.0
    | PNoTitle
      -- ^ Draw no title.
      --
      -- @since 0.4.0.0
    | PAggregate Operation
      -- ^ Compute some aggregate summary statistics for a field to be encoded
      --   with a position channel.
      --
      --   @
      --   enc = 'encoding'
      --           . 'position' 'Graphics.Vega.VegaLite.X' [ 'PName' \"role\", 'PmType' 'Graphics.Vega.VegaLite.Ordinal' ]
      --           . 'position' 'Graphics.Vega.VegaLite.Y' [ 'PName' \"salary\"
      --                        , 'PmType' 'Graphics.Vega.VegaLite.Quantitative'
      --                        , 'PAggregate' 'Graphics.Vega.VegaLite.Mean'
      --                        ]
      --   @
    | PScale [ScaleProperty]
      -- ^ Scaling applied to a field when encoding with a position channel.
      --   The scale will transform a field's value into a position along
      --   one axis.
      --
      --   For example, the following will scale the bars positioned along
      --   a horizontal axis to have an inner spacing of 50% (0.5) of the
      --   total space allocated to each bar:
      --
      --   @
      --   enc = 'encoding'
      --           . 'position' 'Graphics.Vega.VegaLite.X' [ 'PName' \"ageGroup\"
      --                        , 'PmType' 'Graphics.Vega.VegaLite.Nominal'
      --                        , 'PScale' ['SPaddingInner' 0.5]
      --                        ]
      --   @
    | PAxis [AxisProperty]
      -- ^ Axis properties used when encoding with a position channel. For no axis,
      --   provide an empty list.
    | PSort [SortProperty]
      -- ^ Sort order for field when encoding with a position channel.
    | PStack StackOffset
      -- ^ Type of stacking offset for the field when encoding with a
      --   position channel.
      --
      --   For example, stacking areas away from a centreline can be used
      --   to create a
      --   [streamgraph](https://vega.github.io/vega-lite/examples/stacked_area_stream.html):
      --
      --   @
      --   enc = 'encoding'
      --           . 'position' 'Graphics.Vega.VegaLite.X' ['PName' \"week\", 'PmType' 'Graphics.Vega.VegaLite.Ordinal']
      --           . 'position' 'Graphics.Vega.VegaLite.Y' [ 'PName' \"takings\"
      --                        , 'PmType' 'Graphics.Vega.VegaLite.Quantitative'
      --                        , 'PStack' 'Graphics.Vega.VegaLite.StCenter'
      --                        ]
      --           . 'color' ['MName' \"shop\", 'MmType' 'Graphics.Vega.VegaLite.Nominal']
      --   @
      --
      --   Changed from @StackProperty@ in version @0.4.0.0@.
    | PImpute [ImputeProperty]
      -- ^ Set the imputation rules for a position channel. See the
      --   [Vega-Lite impute documentation](https://vega.github.io/vega-lite/docs/impute.html).
      --
      --   @since 0.4.0.0
    | PBand Double
      -- ^ Specify the mark position or size relative to the band size.
      --   The value is in the range 0 to 1, inclusive.
      --
      --   For rectangular-based marks ('Graphics.Vega.VegaLite.Rect', 'Graphics.Vega.VegaLite.Bar', and 'Graphics.Vega.VegaLite.Image'),
      --   the value is the scale factor relative to the band width
      --   (or height), or the time unit interval.
      --
      --   For non-rectangular marks, the relative position on a band of a
      --   stacked, binned, time unit, or band scale is used. A value of
      --   0 positions the band at the beginning of the band, and 1
      --   at the end.
      --
      --   @since 0.5.0.0

positionChannelProperty :: PositionChannel -> LabelledSpec
positionChannelProperty :: PositionChannel -> LabelledSpec
positionChannelProperty (PName Text
s) = Text -> LabelledSpec
field_ Text
s
positionChannelProperty (PmType Measurement
m) = Measurement -> LabelledSpec
mtype_ Measurement
m
positionChannelProperty (PBin [BinProperty]
b) = [BinProperty] -> LabelledSpec
bin [BinProperty]
b
positionChannelProperty PositionChannel
PBinned = LabelledSpec
binned_
positionChannelProperty (PAggregate Operation
op) = Operation -> LabelledSpec
aggregate_ Operation
op
positionChannelProperty (PTimeUnit TimeUnit
tu) = TimeUnit -> LabelledSpec
timeUnit_ TimeUnit
tu
positionChannelProperty (PTitle Text
s) = Text
"title" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text -> VLSpec
splitOnNewline Text
s
positionChannelProperty PositionChannel
PNoTitle = Text
"title" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= VLSpec
A.Null
positionChannelProperty (PSort [SortProperty]
ops) = [SortProperty] -> LabelledSpec
sort_ [SortProperty]
ops
positionChannelProperty (PScale [ScaleProperty]
sps) = [ScaleProperty] -> LabelledSpec
scaleProp_ [ScaleProperty]
sps
positionChannelProperty (PAxis [AxisProperty]
aps) =
  let js :: VLSpec
js = if [AxisProperty] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [AxisProperty]
aps
           then VLSpec
A.Null
           else [LabelledSpec] -> VLSpec
object ((AxisProperty -> LabelledSpec) -> [AxisProperty] -> [LabelledSpec]
forall a b. (a -> b) -> [a] -> [b]
map AxisProperty -> LabelledSpec
axisProperty [AxisProperty]
aps)
  in Text
"axis" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= VLSpec
js
positionChannelProperty (PStack StackOffset
so) = StackOffset -> LabelledSpec
stackOffset StackOffset
so
positionChannelProperty (PRepeat Arrangement
arr) = Text
"field" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [LabelledSpec] -> VLSpec
object [Arrangement -> LabelledSpec
repeat_ Arrangement
arr]
positionChannelProperty (PRepeatDatum Arrangement
arr) = Text
"datum" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [LabelledSpec] -> VLSpec
object [Arrangement -> LabelledSpec
repeat_ Arrangement
arr]
positionChannelProperty PositionChannel
PHeight = Text -> LabelledSpec
value_ Text
"height"
positionChannelProperty PositionChannel
PWidth = Text -> LabelledSpec
value_ Text
"width"
positionChannelProperty (PDatum DataValue
d) = Text
"datum" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= DataValue -> VLSpec
dataValueSpec DataValue
d
positionChannelProperty (PNumber Double
x) = Text
"value" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
positionChannelProperty (PImpute [ImputeProperty]
ips) = [ImputeProperty] -> LabelledSpec
impute_ [ImputeProperty]
ips
positionChannelProperty (PBand Double
x) = Text
"band" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x


{-|

Set the background color of the visualization. If not specified the background
will be white.

@
'Graphics.Vega.VegaLite.toVegaLite'
    [ 'background' "rgb(251,247,238)"
    , 'Graphics.Vega.VegaLite.dataFromUrl' "data/population.json" []
    , 'mark' 'Graphics.Vega.VegaLite.Bar' []
    , enc []
    ]
@
-}
background ::
  Color
  -- ^ The background color. For example, @\"rgba(0,0,0,0)\"@ is
  --   transparent.
  --
  --   This was changed to use the @Color@ type alias in version @0.5.0.0@.
  -> PropertySpec
background :: Text -> PropertySpec
background Text
colour = (VLProperty
VLBackground, Text -> VLSpec
fromColor Text
colour)


{-|

Provides an optional description to be associated with the visualization.

@
'Graphics.Vega.VegaLite.toVegaLite'
    [ 'description' "Population change of key regions since 1900"
    , 'Graphics.Vega.VegaLite.dataFromUrl' "data/population.json" []
    , 'mark' 'Graphics.Vega.VegaLite.Bar' []
    , enc []
    ]
@
-}
description :: T.Text -> PropertySpec
description :: Text -> PropertySpec
description Text
s = (VLProperty
VLDescription, Text -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON Text
s)


-- | Optional metadata.
--
--   @since 0.4.0.0

usermetadata ::
  A.Object
  -- ^ The metadata is passed around but ignored by VegaLite.
  -> PropertySpec
usermetadata :: Object -> PropertySpec
usermetadata Object
o = (VLProperty
VLUserMetadata, Object -> VLSpec
A.Object Object
o)


{-|

Axis customisation properties. These are used for customising individual axes.
To configure all axes, use 'Graphics.Vega.VegaLite.AxisConfig' with a 'Graphics.Vega.VegaLite.configuration' instead. See the
<https://vega.github.io/vega-lite/docs/axis.html#axis-properties Vega-Lite documentation>
for more details.

The @AxTitleMaxLength@ constructor was removed in release @0.4.0.0@. The
'AxTitleLimit' constructor should be used instead.

-}
{-# DEPRECATED AxDates "Please change AxDates to AxValues" #-}
data AxisProperty
    = AxAria Bool
      -- ^ A boolean flag indicating if
      --   [ARIA attributes](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA)
      --   should be included (SVG output only).
      --
      --   If False, the \"aria-hidden\" attribute will be set on the output SVG group, removing
      --   the axis from the ARIA accessibility tree.
      --
      --   __Default value:__ True
      --
      --   @since 0.9.0.0
    | AxAriaDescription T.Text
      -- ^ A text description of this axis for
      --   [ARIA accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA)
      --   (SVG output only).
      --
      --   If the 'AxAria' property is True, for SVG output the
      --   [\"aria-label\" attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute)
      --   will be set to this description.
      --
      --   If the description is unspecified it will be automatically generated.
      --
      --   @since 0.9.0.0
    | AxBandPosition Double
      -- ^ An interpolation fraction indicating where, for @band@ scales, axis ticks should
      --   be position. A value of @0@ places ticks at the left-edge of the band, @0.5@ in
      --   the middle, and @1@ at the right edge.
      --
      --   @since 0.4.0.0
    | AxDataCondition BooleanOp ConditionalAxisProperty
      -- ^ Set conditions on an axis property. The first argument is the
      --   test to apply, and the second is the pair of properties
      --   to set if the condition holds or not.
      --
      --   The test parameter has access to the axis @value@ and @label@
      --   properties: that is
      --
      --   @
      --   'PAxis' [ 'AxDataCondition'
      --             ('Expr' "datum.value <= 2")
      --             ('CAxTickColor' "red" "blue")
      --         , 'AxDataCondition'
      --             ('Expr' "datum.label == '4.0'")
      --             ('CAxTickWidth' 5 2)
      --         ]
      --   @
      --
      --   Inline aggregation can be performed (before the test)
      --   using 'FilterOpTrans', which can be particularly useful for
      --   filtering temporal data. The following example will use solid
      --   grid lines for the first day in January, and dashes for
      --   all other dates (using 'Data.Function.&'):
      --
      --   @
      --   'PAxis' [ 'AxDataCondition'
      --             ('FEqual' "value" ('Graphics.Vega.VegaLite.DateTime' ['Grahics.Vega.VegaLite.DTMonth' 'Graphics.Vega.VegaLite.Jan', 'Graphics.Vega.VegaLite.DTDate' 1])
      --             & 'FilterOpTrans' ('MTimeUnit' ('Graphics.Vega.VegaLite.TU' 'Graphics.Vega.VegaLite.MonthDate')))
      --             ('CAxGridDash' [] [2, 2])
      --         ]
      --   @
      --
      --   @since 0.5.0.0
    | AxDomain Bool
      -- ^ Should the axis domain (the baseline) be displayed?
    | AxDomainCap StrokeCap
      -- ^ The stroke cap for the domain lines' ending style.
      --
      --   @since 0.9.0.0
    | AxDomainColor Color
      -- ^ The axis domain color.
      --
      --   @since 0.4.0.0
    | AxDomainDash DashStyle
      -- ^ The dash pattern of the domain.
      --
      --   @since 0.4.0.0
    | AxDomainDashOffset DashOffset
      -- ^ The offset for the dash pattern.
      --
      --   @since 0.4.0.0
    | AxDomainOpacity Opacity
      -- ^ The axis domain opacity.
      --
      --   @since 0.4.0.0
    | AxDomainWidth Double
      -- ^ The width of the axis domain.
      --
      --   @since 0.4.0.0
    | AxFormat T.Text
      -- ^ [Formatting pattern](https://vega.github.io/vega-lite/docs/format.html) for
      --   axis values. To distinguish between formatting as numeric values
      --   and data/time values, additionally use 'AxFormatAsNum', 'AxFormatAsTemporal',
      --   or 'AxFormatAsCustom'.
      --
      --   When used with a [custom formatType](https://vega.github.io/vega-lite/docs/config.html#custom-format-type),
      --   this value will be passed as \"format\" alongside \"datum.value\" to the
      --   registered function.
    | AxFormatAsNum
      -- ^ Facet headers should be formatted as numbers. Use a
      --   [d3 numeric format string](https://github.com/d3/d3-format#locale_format)
      --   with 'AxFormat'.
      --
      --   @since 0.4.0.0
    | AxFormatAsTemporal
      -- ^ Facet headers should be formatted as dates or times. Use a
      --   [d3 date/time format string](https://github.com/d3/d3-time-format#locale_format)
      --   with 'AxFormat'.
      --
      --   @since 0.4.0.0
    | AxFormatAsCustom T.Text
      -- ^ The [custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type)
      --   for use with with 'AxFormat'.
      --
      --   @since 0.9.0.0
    | AxGrid Bool
      -- ^ Should an axis grid be displayed?
    | AxGridCap StrokeCap
      -- ^ The stroke cap for the grid lines' ending style.
      --
      --   @since 0.9.0.0
    | AxGridColor Color
      -- ^ The color for the grid.
      --
      --   @since 0.4.0.0
    | AxGridDash DashStyle
      -- ^ The dash pattern of the grid.
      --
      --   @since 0.4.0.0
    | AxGridDashOffset DashOffset
      -- ^ The offset for the dash pattern.
      --
      --   @since 0.4.0.0
    | AxGridOpacity Opacity
      -- ^ The opacity of the grid.
      --
      --   @since 0.4.0.0
    | AxGridWidth Double
      -- ^ The width of the grid lines.
      --
      --   @since 0.4.0.0
    | AxLabels Bool
      -- ^ Should labels be added to an axis?
    | AxLabelAlign HAlign
      -- ^ The horizontal alignment for labels.
      --
      --   @since 0.4.0.0
    | AxLabelAngle Angle
      -- ^ The angle at which to draw labels.
    | AxLabelBaseline VAlign
      -- ^ The vertical alignment for labels.
      --
      --   @since 0.4.0.0
    | AxLabelNoBound
      -- ^ No boundary overlap check is applied to labels. This is the
      --   default behavior.
      --
      --   See also 'AxLabelBound' and 'AxLabelBoundValue'.
      --
      --   @since 0.4.0.0
    | AxLabelBound
      -- ^ Labels are hidden if they exceed the axis range by more than 1
      --   pixel.
      --
      --   See also 'AxLabelNoBound' and 'AxLabelBoundValue'.
      --
      --   @since 0.4.0.0
    | AxLabelBoundValue Double
      -- ^ Labels are hidden if they exceed the axis range by more than
      --   the given number of pixels.
      --
      --   See also 'AxLabelNoBound' and 'AxLabelBound'.
      --
      --   @since 0.4.0.0
    | AxLabelColor Color
      -- ^ The label color.
      --
      --   @since 0.4.0.0
    | AxLabelExpr VegaExpr
      -- ^ Provide the expression used to generate axis labels.
      --
      --   The expression can use @datum.value@ and @datum.label@ to access
      --   the data value and default label text respectively.
      --
      --   The following example uses four digit years for decades and
      --   two-digit years for other years:
      --
      --   @
      --   AxLabelExpr "if(year(datum.value) % 10 == 0, utcFormat(datum.value,'%Y'), utcFormat(datum.value,'%y'))"
      --   @
      --
      --   @since 0.5.0.0
    | AxLabelNoFlush
      -- ^ The labels are not aligned flush to the scale. This is the
      --   default for non-continuous X scales.
      --
      --   See also 'AxLabelFlush' and 'AxLabelFlushValue'.
      --
      --   @since 0.4.0.0
    | AxLabelFlush
      -- ^ The first and last axis labels are aligned flush to the scale
      --   range.
      --
      --   See also 'AxLabelNoFlush' and 'AxLabelFlushValue'.
      --
      --   @since 0.4.0.0
    | AxLabelFlushValue Double
      -- ^ The labels are aligned flush, and the parameter determines
      --   the extra offset, in pixels, to apply to the first and last
      --   labels. This can help the labels better group (visually) with
      --   the corresponding axis ticks.
      --
      --   See also 'AxLabelNoFlush' and 'AxLabelFlush'.
      --
      --   @since 0.4.0.0
    | AxLabelFlushOffset Double
      -- ^ The number of pixels to offset flush-adjusted labels.
      --
      --   @since 0.4.0.0
    | AxLabelFont T.Text
      -- ^ The font for the label.
      --
      --   @since 0.4.0.0
    | AxLabelFontSize Double
      -- ^ The font size of the label.
      --
      --   @since 0.4.0.0
    | AxLabelFontStyle T.Text
      -- ^ The font style of the label.
      --
      --   @since 0.4.0.0
    | AxLabelFontWeight FontWeight
      -- ^ The font weight of the label.
      --
      --   @since 0.4.0.0
    | AxLabelLimit Double
      -- ^ The maximum width of a label, in pixels.
      --
      --   @since 0.4.0.0
    | AxLabelLineHeight Double
      -- ^ The line height, in pixels, for multi-line label text.
      --
      --   Added in Vega-Lite 4.6.0.
      --
      --   @since 0.7.0.0
    | AxLabelOffset Double
      -- ^ The pixel offset for labels, in addition to 'AxTickOffset'.
      --
      --   @since 0.6.0.0
    | AxLabelOpacity Opacity
      -- ^ The opacity of the label.
      --
      --   @since 0.4.0.0
    | AxLabelOverlap OverlapStrategy
      -- ^ How should overlapping labels be displayed?
    | AxLabelPadding Double
      -- ^ The padding, in pixels, between the label and the axis.
    | AxLabelSeparation Double
      -- ^ The minimum separation, in pixels, between label bounding boxes
      --   for them to be considered non-overlapping. This is ignored if
      --   the 'AxLabelOverlap' strategy is 'Graphics.Vega.VegaLite.ONone'.
      --
      --   @since 0.4.0.0
    | AxMaxExtent Double
      -- ^ The maximum extent, in pixels, that axis ticks and labels should use.
      --   This determines a maxmium offset value for axis titles.
    | AxMinExtent Double
      -- ^ The minimum extent, in pixels, that axis ticks and labels should use.
      --   This determines a minmium offset value for axis titles.
    | AxOffset Double
      -- ^ The offset, in pixels, between the axis and the edge of the
      --   enclosing group or data rectangle.
    | AxOrient Side
      -- ^ The orientation of the axis.
    | AxPosition Double
      -- ^ The anchor position of the axis in pixels.
    | AxStyle [StyleLabel]
      -- ^ The named styles - generated with 'Graphics.Vega.VegaLite.AxisNamedStyles' -
      --   to apply to the axis.
      --
      --   @since 0.6.0.0
    | AxTicks Bool
      -- ^ Should tick marks be drawn on an axis?
    | AxTickBand BandAlign
      -- ^ For band scales, indicates if ticks and grid lines should be
      --   placed at the center of a band (the default) or at the band
      --   extents to indicate intervals.
      --
      --   @since 0.5.0.0
    | AxTickCap StrokeCap
      -- ^ The stroke cap for the grid lines' ending style.
      --
      --   @since 0.9.0.0
    | AxTickColor Color
      -- ^ The color of the ticks.
      --
      --   @since 0.4.0.0
    | AxTickCount Int
      -- ^ The desired number of ticks for axes visualizing quantitative scales.
      --   This is a hint to the system, and the actual number used will be
      --   adjusted to be \"nice\" (multiples of 2, 5, or 10) and lie within the
      --   underlying scale's range.
      --
      --   The 'AxTickCountTime' option can instead be used for \"time\" or
      --   \"utc\" scales.
    | AxTickCountTime ScaleNice
      -- ^ A specialised version of 'AxTickCount' for \"time\" and \"utc\"
      --   time scales.
      --
      --   The 'Graphics.Vega.VegaLite.IsNice' and 'Graphics.Vega.VegaLte.NTickCount'
      --   options should not be used as they generate invalid VegaLite.
      --
      --   @since 0.9.0.0
    | AxTickDash DashStyle
      -- ^ The dash pattern of the ticks.
      --
      --   @since 0.4.0.0
    | AxTickDashOffset DashOffset
      -- ^ The offset for the dash pattern.
      --
      --   @since 0.4.0.0
    | AxTickExtra Bool
      -- ^ Should an extra axis tick mark be added for the initial position of
      --   the axis?
      --
      --   @since 0.4.0.0
    | AxTickMinStep Double
      -- ^ The minimum desired step between axis ticks, in terms of the scale
      --   domain values.
      --
      --   @since 0.4.0.0
    | AxTickOffset Double
      -- ^ The position offset, in pixels, to apply to ticks, labels, and grid lines.
      --
      --   See also 'AxLabelOffset'.
      --
      --   @since 0.4.0.0
    | AxTickOpacity Opacity
      -- ^ The opacity of the ticks.
      --
      --   @since 0.4.0.0
    | AxTickRound Bool
      -- ^ Should pixel position values be rounded to the nearest integer?
      --
      --   @since 0.4.0.0
    | AxTickSize Double
      -- ^ The size of the tick marks in pixels.
    | AxTickWidth Double
      -- ^ The width of the tick marks in pixels.
      --
      --   @since 0.4.0.0
    | AxTitle T.Text
      -- ^ The axis title.
    | AxNoTitle
      -- ^ Draw no title for the axis.
      --
      --   @since 0.4.0.0
    | AxTitleAlign HAlign
      -- ^ The horizontal alignment of the axis title.
    | AxTitleAnchor APosition
      -- ^ The text anchor position for placing axis titles.
      --
      --   @since 0.4.0.0
    | AxTitleAngle Angle
      -- ^ The angle of the axis title.
    | AxTitleBaseline VAlign
      -- ^ The vertical alignment of the axis title.
      --
      --   @since 0.4.0.0
    | AxTitleColor Color
      -- ^ The color of the axis title.
      --
      --   @since 0.4.0.0
    | AxTitleFont T.Text
      -- ^ The font for the axis title.
      --
      --   @since 0.4.0.0
    | AxTitleFontSize Double
      -- ^ The font size of the axis title.
      --
      --   @since 0.4.0.0
    | AxTitleFontStyle T.Text
      -- ^ The font style of the axis title.
      --
      --   @since 0.4.0.0
    | AxTitleFontWeight FontWeight
      -- ^ The font weight of the axis title.
      --
      --   @since 0.4.0.0
    | AxTitleLimit Double
      -- ^ The maximum allowed width of the axis title, in pixels.
      --
      --   @since 0.4.0.0
    | AxTitleLineHeight Double
      -- ^ Line height, in pixels, for multi-line title text.
      --
      --   @since 0.5.0.0
    | AxTitleOpacity Opacity
      -- ^ The opacity of the axis title.
      --
      --   @since 0.4.0.0
    | AxTitlePadding Double
      -- ^ The padding, in pixels, between title and axis.
    | AxTitleX Double
      -- ^ The X coordinate of the axis title, relative to the axis group.
      --
      --   @since 0.4.0.0
    | AxTitleY Double
      -- ^ The Y coordinate of the axis title, relative to the axis group.
      --
      --   @since 0.4.0.0
    | AxTranslateOffset Double
      -- ^ The translation offset in pixels applied to the axis group
      --   mark x and y. If specified it overrides the default value
      --   of a 0.5 offset to pixel-align stroked lines.
      --
      --   @since 0.5.0.0
    | AxValues DataValues
      -- ^ Set the explicit tick, grid, and label values along an axis.
      --
      --   The following three examples are for an axis displaying a
      --   quantitative, categorical, and temporal field respectively.
      --
      --   @
      --   'PAxis' ['AxValues' ('Numbers' [2, 3, 5, 7, 11, 13, 17])]
      --   'PAxis' ['AxValues' ('Strings' ["cats", "dogs", "elephants"])]
      --   'PAxis' ['AxValues' ('DateTimes' [ ['Graphics.Vega.VegaLite.DTYear' 2019, 'Graphics.Vega.VegaLite.DTMonth' 'Graphics.Vega.VegaLite.Mar', 'Graphics.Vega.VegaLite.DTDate' 31]
      --                              , ['Graphics.Vega.VegaLite.DTYear' 2019, 'Graphics.Vega.VegaLite.DTMonth' 'Graphics.Vega.VegaLite.Jun', 'Graphics.Vega.VegaLite.DTDate' 30]
      --                              , ['Graphics.Vega.VegaLite.DTYear' 2019, 'Graphics.Vega.VegaLite.DTMonth' 'Graphics.Vega.VegaLite.Sep', 'Graphics.Vega.VegaLite.DTDate' 30]
      --                              ])]
      --   @
      --
      --   Changed in @0.4.0.0@ to take 'DataValues' rather than @[Double]@.
    | AxDates [[DateTime]]
      -- ^ The dates or times to appear along the axis.
      --
      --   As of version @0.4.0.0@, this is deprecated. The 'AxValues'
      --   constructor should be used instead.
    | AxZIndex ZIndex
      -- ^ The z-index of the axis, relative to the chart marks.


axisProperty :: AxisProperty -> LabelledSpec
axisProperty :: AxisProperty -> LabelledSpec
axisProperty (AxStyle [Text
s]) = Text
"style" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
s
axisProperty (AxStyle [Text]
s) = Text
"style" Text -> [Text] -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [Text]
s

axisProperty (AxAria Bool
b) = Text
"aria" Text -> Bool -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
b
axisProperty (AxAriaDescription Text
t) = Text
"description" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
t

axisProperty (AxBandPosition Double
x) = Text
"bandPosition" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxDataCondition BooleanOp
predicate ConditionalAxisProperty
cap) =
  let (AxisProperty
ifAxProp, AxisProperty
elseAxProp) = ConditionalAxisProperty -> (AxisProperty, AxisProperty)
conditionalAxisProperty ConditionalAxisProperty
cap
      (Text
axKey, VLSpec
ifProp) = AxisProperty -> LabelledSpec
axisProperty AxisProperty
ifAxProp
      (Text
_, VLSpec
elseProp) = AxisProperty -> LabelledSpec
axisProperty AxisProperty
elseAxProp
  in Text
axKey Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [LabelledSpec] -> VLSpec
object [ Text
"condition" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [LabelledSpec] -> VLSpec
object [ Text
"test" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= BooleanOp -> VLSpec
booleanOpSpec BooleanOp
predicate
                                             , Text
"value" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= VLSpec
ifProp
                                             ]
                     , Text
"value" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= VLSpec
elseProp]
axisProperty (AxDomain Bool
b) = Text
"domain" Text -> Bool -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
b
axisProperty (AxDomainCap StrokeCap
c) = Text
"domainCap" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= StrokeCap -> Text
strokeCapLabel StrokeCap
c
axisProperty (AxDomainColor Text
s) = Text
"domainColor" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text -> VLSpec
fromColor Text
s
axisProperty (AxDomainDash [Double]
ds) = Text
"domainDash" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [Double] -> VLSpec
fromDS [Double]
ds
axisProperty (AxDomainDashOffset Double
x) = Text
"domainDashOffset" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxDomainOpacity Double
x) = Text
"domainOpacity" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxDomainWidth Double
x) = Text
"domainWidth" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxFormat Text
fmt) = Text
"format" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
fmt
axisProperty AxisProperty
AxFormatAsNum = Text
"formatType" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text -> VLSpec
fromT Text
"number"
axisProperty AxisProperty
AxFormatAsTemporal = Text
"formatType" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text -> VLSpec
fromT Text
"time"
axisProperty (AxFormatAsCustom Text
c) = Text
"formatType" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
c
axisProperty (AxGrid Bool
b) = Text
"grid" Text -> Bool -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
b
axisProperty (AxGridCap StrokeCap
c) = Text
"gridCap" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= StrokeCap -> Text
strokeCapLabel StrokeCap
c
axisProperty (AxGridColor Text
s) = Text
"gridColor" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text -> VLSpec
fromColor Text
s
axisProperty (AxGridDash [Double]
ds) = Text
"gridDash" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [Double] -> VLSpec
fromDS [Double]
ds
axisProperty (AxGridDashOffset Double
x) = Text
"gridDashOffset" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxGridOpacity Double
x) = Text
"gridOpacity" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxGridWidth Double
x) = Text
"gridWidth" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxLabels Bool
b) = Text
"labels" Text -> Bool -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
b
axisProperty (AxLabelAlign HAlign
ha) = Text
"labelAlign" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= HAlign -> Text
hAlignLabel HAlign
ha
axisProperty (AxLabelAngle Double
a) = Text
"labelAngle" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
a
axisProperty (AxLabelBaseline VAlign
va) = Text
"labelBaseline" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= VAlign -> Text
vAlignLabel VAlign
va
axisProperty AxisProperty
AxLabelNoBound = Text
"labelBound" Text -> Bool -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
False
axisProperty AxisProperty
AxLabelBound = Text
"labelBound" Text -> Bool -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
True
axisProperty (AxLabelBoundValue Double
x) = Text
"labelBound" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxLabelColor Text
s) = Text
"labelColor" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text -> VLSpec
fromColor Text
s
axisProperty (AxLabelExpr Text
e) = Text
"labelExpr" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
e
axisProperty AxisProperty
AxLabelNoFlush = Text
"labelFlush" Text -> Bool -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
False
axisProperty AxisProperty
AxLabelFlush = Text
"labelFlush" Text -> Bool -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
True
axisProperty (AxLabelFlushValue Double
x) = Text
"labelFlush" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxLabelFlushOffset Double
x) = Text
"labelFlushOffset" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxLabelFont Text
s) = Text
"labelFont" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
s
axisProperty (AxLabelFontSize Double
x) = Text
"labelFontSize" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxLabelFontStyle Text
s) = Text
"labelFontStyle" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
s
axisProperty (AxLabelFontWeight FontWeight
fw) = Text
"labelFontWeight" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= FontWeight -> VLSpec
fontWeightSpec FontWeight
fw
axisProperty (AxLabelLimit Double
x) = Text
"labelLimit" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxLabelLineHeight Double
x) = Text
"labelLineHeight" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxLabelOffset Double
x) = Text
"labelOffset" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxLabelOpacity Double
x) = Text
"labelOpacity" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxLabelOverlap OverlapStrategy
s) = Text
"labelOverlap" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= OverlapStrategy -> VLSpec
overlapStrategyLabel OverlapStrategy
s
axisProperty (AxLabelPadding Double
x) = Text
"labelPadding" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxLabelSeparation Double
x) = Text
"labelSeparation" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxMaxExtent Double
n) = Text
"maxExtent" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
n
axisProperty (AxMinExtent Double
n) = Text
"minExtent" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
n
axisProperty (AxOffset Double
n) = Text
"offset" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
n
axisProperty (AxOrient Side
side) = Text
"orient" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Side -> Text
sideLabel Side
side
axisProperty (AxPosition Double
n) = Text
"position" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
n
axisProperty (AxTicks Bool
b) = Text
"ticks" Text -> Bool -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
b
axisProperty (AxTickBand BandAlign
bnd) = Text
"tickBand" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= BandAlign -> Text
bandAlignLabel BandAlign
bnd
axisProperty (AxTickCap StrokeCap
c) = Text
"tickCap" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= StrokeCap -> Text
strokeCapLabel StrokeCap
c
axisProperty (AxTickColor Text
s) = Text
"tickColor" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text -> VLSpec
fromColor Text
s
axisProperty (AxTickCount Int
n) = Text
"tickCount" Text -> Int -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Int
n
axisProperty (AxTickCountTime ScaleNice
sn) = Text
"tickCount" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= ScaleNice -> VLSpec
scaleNiceSpec ScaleNice
sn
axisProperty (AxTickDash [Double]
ds) = Text
"tickDash" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [Double] -> VLSpec
fromDS [Double]
ds
axisProperty (AxTickDashOffset Double
x) = Text
"tickDashOffset" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxTickExtra Bool
b) = Text
"tickExtra" Text -> Bool -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
b
axisProperty (AxTickMinStep Double
x) = Text
"tickMinStep" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxTickOffset Double
x) = Text
"tickOffset" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxTickOpacity Double
x) = Text
"tickOpacity" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxTickRound Bool
b) = Text
"tickRound" Text -> Bool -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
b
axisProperty (AxTickSize Double
x) = Text
"tickSize" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxTickWidth Double
x) = Text
"tickWidth" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxTitle Text
ttl) = Text
"title" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text -> VLSpec
splitOnNewline Text
ttl
axisProperty AxisProperty
AxNoTitle = Text
"title" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= VLSpec
A.Null
axisProperty (AxTitleAlign HAlign
ha) = Text
"titleAlign" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= HAlign -> Text
hAlignLabel HAlign
ha
axisProperty (AxTitleAnchor APosition
a) = Text
"titleAnchor" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= APosition -> Text
anchorLabel APosition
a
axisProperty (AxTitleAngle Double
x) = Text
"titleAngle" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxTitleBaseline VAlign
va) = Text
"titleBaseline" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= VAlign -> Text
vAlignLabel VAlign
va
axisProperty (AxTitleColor Text
s) = Text
"titleColor" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text -> VLSpec
fromColor Text
s
axisProperty (AxTitleFont Text
s) = Text
"titleFont" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
s
axisProperty (AxTitleFontSize Double
x) = Text
"titleFontSize" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxTitleFontStyle Text
s) = Text
"titleFontStyle" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
s
axisProperty (AxTitleFontWeight FontWeight
fw) = Text
"titleFontWeight" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= FontWeight -> VLSpec
fontWeightSpec FontWeight
fw
axisProperty (AxTitleLimit Double
x) = Text
"titleLimit" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxTitleLineHeight Double
x) = Text
"titleLineHeight" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxTitleOpacity Double
x) = Text
"titleOpacity" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxTitlePadding Double
pad) = Text
"titlePadding" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
pad
axisProperty (AxTitleX Double
x) = Text
"titleX" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxTitleY Double
x) = Text
"titleY" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxTranslateOffset Double
x) = Text
"translate" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
axisProperty (AxValues DataValues
vals) = Text
"values" Text -> [VLSpec] -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= DataValues -> [VLSpec]
dataValuesSpecs DataValues
vals
axisProperty (AxDates [[DateTime]]
dtss) = Text
"values" Text -> [VLSpec] -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= ([DateTime] -> VLSpec) -> [[DateTime]] -> [VLSpec]
forall a b. (a -> b) -> [a] -> [b]
map [DateTime] -> VLSpec
dateTimeSpec [[DateTime]]
dtss
axisProperty (AxZIndex ZIndex
z) = Text
"zindex" Text -> ZIndex -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= ZIndex
z


{-|

For use with 'AxDataCondition', and defines those axis properties
which can be conditioned on their position (or label).

The constuctor determines the axis property (a label, tick, or
grid element), and the two arguments are the value to set if the condition
is 'True' (first), and for when it is 'False' (second).

@since 0.5.0.0
-}

data ConditionalAxisProperty
  = CAxGridColor Color Color
    -- ^ The color for the axis grid.
  | CAxGridDash DashStyle DashStyle
    -- ^ The dash pattern for the axis grid.
  | CAxGridDashOffset DashOffset DashOffset
    -- ^ The offset for the dash pattern.
  | CAxGridOpacity Opacity Opacity
    -- ^ The opacity of the axis grid.
  | CAxGridWidth Double Double
    -- ^ The width of the axis grid.
  | CAxLabelAlign HAlign HAlign
    -- ^ Axis label horizontal alignment.
  | CAxLabelBaseline VAlign VAlign
    -- ^ Axis label vertical alignment.
  | CAxLabelColor Color Color
    -- ^ Axis label color.
  | CAxLabelFont T.Text T.Text
    -- ^ Axis label font.
  | CAxLabelFontSize Double Double
    -- ^ Axis label font.
  | CAxLabelFontStyle T.Text T.Text
    -- ^ Axis label font style.
  | CAxLabelFontWeight FontWeight FontWeight
    -- ^ Axis label font weight.
  | CAxLabelOffset Double Double
    -- ^ Axis label offset.
    --
    --  @since 0.6.0.0
  | CAxLabelOpacity Opacity Opacity
    -- ^ Axis label opacity.
  | CAxLabelPadding Double Double
    -- ^ Axis label padding.
    --
    --   @since 0.6.0.0
  | CAxTickColor T.Text T.Text
    -- ^ Tick color for the axis.
  | CAxTickDash DashStyle DashStyle
    -- ^ The dash pattern for the axis ticks.
  | CAxTickDashOffset DashOffset DashOffset
    -- ^ The offset for the dash pattern.
  | CAxTickOpacity Opacity Opacity
    -- ^ Opacity of the axis tick marks.
  | CAxTickSize Double Double
    -- ^ Size, in pixels, of the axis tick marks.
    --
    --   @since 0.6.0.0
  | CAxTickWidth Double Double
    -- ^ Width, in pixels, of the axis tick marks.


conditionalAxisProperty :: ConditionalAxisProperty -> (AxisProperty, AxisProperty)
conditionalAxisProperty :: ConditionalAxisProperty -> (AxisProperty, AxisProperty)
conditionalAxisProperty (CAxGridColor Text
t Text
f) = (Text -> AxisProperty
AxGridColor Text
t, Text -> AxisProperty
AxGridColor Text
f)
conditionalAxisProperty (CAxGridDash [Double]
t [Double]
f) = ([Double] -> AxisProperty
AxGridDash [Double]
t, [Double] -> AxisProperty
AxGridDash [Double]
f)
conditionalAxisProperty (CAxGridDashOffset Double
t Double
f) = (Double -> AxisProperty
AxGridDashOffset Double
t, Double -> AxisProperty
AxGridDashOffset Double
f)
conditionalAxisProperty (CAxGridOpacity Double
t Double
f) = (Double -> AxisProperty
AxGridOpacity Double
t, Double -> AxisProperty
AxGridOpacity Double
f)
conditionalAxisProperty (CAxGridWidth Double
t Double
f) = (Double -> AxisProperty
AxGridWidth Double
t, Double -> AxisProperty
AxGridWidth Double
f)
conditionalAxisProperty (CAxLabelAlign HAlign
t HAlign
f) = (HAlign -> AxisProperty
AxLabelAlign HAlign
t, HAlign -> AxisProperty
AxLabelAlign HAlign
f)
conditionalAxisProperty (CAxLabelBaseline VAlign
t VAlign
f) = (VAlign -> AxisProperty
AxLabelBaseline VAlign
t, VAlign -> AxisProperty
AxLabelBaseline VAlign
f)
conditionalAxisProperty (CAxLabelColor Text
t Text
f) = (Text -> AxisProperty
AxLabelColor Text
t, Text -> AxisProperty
AxLabelColor Text
f)
conditionalAxisProperty (CAxLabelFont Text
t Text
f) = (Text -> AxisProperty
AxLabelFont Text
t, Text -> AxisProperty
AxLabelFont Text
f)
conditionalAxisProperty (CAxLabelFontSize Double
t Double
f) = (Double -> AxisProperty
AxLabelFontSize Double
t, Double -> AxisProperty
AxLabelFontSize Double
f)
conditionalAxisProperty (CAxLabelFontStyle Text
t Text
f) = (Text -> AxisProperty
AxLabelFontStyle Text
t, Text -> AxisProperty
AxLabelFontStyle Text
f)
conditionalAxisProperty (CAxLabelFontWeight FontWeight
t FontWeight
f) = (FontWeight -> AxisProperty
AxLabelFontWeight FontWeight
t, FontWeight -> AxisProperty
AxLabelFontWeight FontWeight
f)
conditionalAxisProperty (CAxLabelOffset Double
t Double
f) = (Double -> AxisProperty
AxLabelOffset Double
t, Double -> AxisProperty
AxLabelOffset Double
f)
conditionalAxisProperty (CAxLabelOpacity Double
t Double
f) = (Double -> AxisProperty
AxLabelOpacity Double
t, Double -> AxisProperty
AxLabelOpacity Double
f)
conditionalAxisProperty (CAxLabelPadding Double
t Double
f) = (Double -> AxisProperty
AxLabelPadding Double
t, Double -> AxisProperty
AxLabelPadding Double
f)
conditionalAxisProperty (CAxTickColor Text
t Text
f) = (Text -> AxisProperty
AxTickColor Text
t, Text -> AxisProperty
AxTickColor Text
f)
conditionalAxisProperty (CAxTickDash [Double]
t [Double]
f) = ([Double] -> AxisProperty
AxTickDash [Double]
t, [Double] -> AxisProperty
AxTickDash [Double]
f)
conditionalAxisProperty (CAxTickDashOffset Double
t Double
f) = (Double -> AxisProperty
AxTickDashOffset Double
t, Double -> AxisProperty
AxTickDashOffset Double
f)
conditionalAxisProperty (CAxTickOpacity Double
t Double
f) = (Double -> AxisProperty
AxTickOpacity Double
t, Double -> AxisProperty
AxTickOpacity Double
f)
conditionalAxisProperty (CAxTickSize Double
t Double
f) = (Double -> AxisProperty
AxTickSize Double
t, Double -> AxisProperty
AxTickSize Double
f)
conditionalAxisProperty (CAxTickWidth Double
t Double
f) = (Double -> AxisProperty
AxTickWidth Double
t, Double -> AxisProperty
AxTickWidth Double
f)


{-|

Declare the way the view is sized. See the
<https://vega.github.io/vega-lite/docs/size.html#autosize Vega-Lite documentation>
for details.

@
'Graphics.Vega.VegaLite.toVegaLite'
    [ 'width' 250
    , 'height' 300
    , 'autosize' [ 'Graphics.Vega.VegaLite.AFit', 'Graphics.Vega.VegaLite.APadding', 'Graphics.Vega.VegaLite.AResize' ]
    , 'Graphics.Vega.VegaLite.dataFromUrl' "data/population.json" []
    , 'mark' 'Graphics.Vega.VegaLite.Bar' []
    , enc []
    ]
@
-}
autosize :: [Autosize] -> PropertySpec
autosize :: [Autosize] -> PropertySpec
autosize [Autosize]
aus = (VLProperty
VLAutosize, [LabelledSpec] -> VLSpec
object ((Autosize -> LabelledSpec) -> [Autosize] -> [LabelledSpec]
forall a b. (a -> b) -> [a] -> [b]
map Autosize -> LabelledSpec
autosizeProperty [Autosize]
aus))


-- | The background style of a single view or layer in a view composition.
--
--   @since 0.4.0.0

viewBackground :: [ViewBackground] -> PropertySpec
viewBackground :: [ViewBackground] -> PropertySpec
viewBackground [ViewBackground]
vbs = (VLProperty
VLViewBackground, [LabelledSpec] -> VLSpec
object ((ViewBackground -> LabelledSpec)
-> [ViewBackground] -> [LabelledSpec]
forall a b. (a -> b) -> [a] -> [b]
map ViewBackground -> LabelledSpec
viewBackgroundSpec [ViewBackground]
vbs))


{-|

Used for creating logical compositions. For example

@
'color'
    [ 'MSelectionCondition' (Or ('SelectionName' "alex") (SelectionName "morgan"))
        ['MAggregate' 'Count', 'MName' "*", 'MmType' 'Graphics.Vega.VegaLite.Quantitative']
        ['MString' "gray"]
    ]
@

Logical compositions can be nested to any level as shown in this example

@
'Not' ('And' ('Expr' "datum.IMDB_Rating === null") ('Expr' "datum.Rotten_Tomatoes_Rating === null") )
@
-}
data BooleanOp
    = Expr VegaExpr
      -- ^ Expression that should evaluate to either true or false.
    | FilterOp Filter
      -- ^ Convert a 'Filter' into a 'BooleanOp' so that it may be used as
      --   part of a more complex expression.
      --
      --   For example (using 'Data.Function.&' to apply 'FilterOp' to a filter):
      --
      --   @
      --   trans = 'transform'
      --             . 'filter' ('FCompose'
      --                        ('And'
      --                          ('FValid' "IMDB_Rating" & 'FilterOp')
      --                          ('FValid' "Rotten_Tomatoes_Rating" & 'FilterOp')
      --                        )
      --                      )
      --   @
      --
      --   @since 0.4.0.0
    | FilterOpTrans MarkChannel Filter
      -- ^ Combine a data-transformation operation with a filter before
      --   converting into a boolean operation. This can be useful when
      --   working with dates, such as the following exampe, which aggregates
      --   a set of dates into years, and filters only those years between
      --   2010 and 2017 (inclusive). The final expression is converted
      --   back into a 'BooleanOp' with 'FCompose' (combined using
      --   'Data.Function.&').
      --
      --   @
      --   'filter' ('FRange' "date" ('NumberRange' 2010 2017)
      --           & 'FilterOpTrans' ('MTimeUnit' ('Graphics.Vega.VegaLite.TU' 'Graphics.Vega.VegaLite.Year'))
      --           & 'FCompose'
      --           )
      --   @
      --
      --   @since 0.4.0.0
    | Selection SelectionLabel  -- TODO: rename Selected since collides with Selection type
      -- ^ Interactive selection that will be true or false as part of
      --   a logical composition.  For example: to filter a dataset so
      --   that only items selected interactively and that have a
      --   weight of more than 30:
      --
      -- @
      -- 'transform'
      --    . 'filter' ('FCompose' ('And' ('Selection' "brush") ('Expr' "datum.weight > 30")))
      -- @
    | SelectionName SelectionLabel
    -- ^  Name a selection that is used as part of a conditional encoding.
    --
    -- @
    -- 'color'
    --    [ 'MSelectionCondition' ('SelectionName' \"myBrush\")
    --        ['MName' \"myField\", 'MmType' 'Graphics.Vega.VegaLite.Nominal']
    --        ['MString' \"grey\"]
    --    ]
    -- @
    | And BooleanOp BooleanOp
      -- ^ Apply an \'and\' Boolean operation as part of a logical composition.
      --
      -- @
      -- 'And' ('Expr' "datum.IMDB_Rating === null") ('Expr' "datum.Rotten_Tomatoes_Rating === null")
      -- @
    | Or BooleanOp BooleanOp
      -- ^ Apply an \'or\' Boolean operation as part of a logical composition.
    | Not BooleanOp
      -- ^ Negate the given expression.
      --
      -- @
      -- 'Not' ('And' ('Expr' "datum.IMDB_Rating === null") ('Expr' "datum.Rotten_Tomatoes_Rating === null"))
      -- @

booleanOpSpec :: BooleanOp -> VLSpec
booleanOpSpec :: BooleanOp -> VLSpec
booleanOpSpec (Expr Text
expr) = Text -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON Text
expr
booleanOpSpec (FilterOp Filter
f) = Filter -> VLSpec
filterSpec Filter
f
booleanOpSpec (FilterOpTrans MarkChannel
tr Filter
f) = MarkChannel -> Filter -> VLSpec
trFilterSpec MarkChannel
tr Filter
f
booleanOpSpec (SelectionName Text
selName) = Text -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON Text
selName
booleanOpSpec (Selection Text
sel) = [LabelledSpec] -> VLSpec
object [Text
"selection" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
sel]
booleanOpSpec (And BooleanOp
operand1 BooleanOp
operand2) = [LabelledSpec] -> VLSpec
object [Text
"and" Text -> [VLSpec] -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [BooleanOp -> VLSpec
booleanOpSpec BooleanOp
operand1, BooleanOp -> VLSpec
booleanOpSpec BooleanOp
operand2]]
booleanOpSpec (Or BooleanOp
operand1 BooleanOp
operand2) = [LabelledSpec] -> VLSpec
object [Text
"or" Text -> [VLSpec] -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [BooleanOp -> VLSpec
booleanOpSpec BooleanOp
operand1, BooleanOp -> VLSpec
booleanOpSpec BooleanOp
operand2]]
booleanOpSpec (Not BooleanOp
operand) = [LabelledSpec] -> VLSpec
object [Text
"not" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= BooleanOp -> VLSpec
booleanOpSpec BooleanOp
operand]


{-|

Type of filtering operation. See the
<https://vega.github.io/vega-lite/docs/filter.html Vega-Lite documentation>
for details.

These can also be included into a 'BooleanOp' expression using 'FilterOp'
and 'FilterOpTrans'
(as of version @0.4.0.0@).

-}
data Filter
    = FEqual FieldName DataValue
      -- ^ Filter a data stream so that only data in a given field equal to
      --   the given value are used.
    | FLessThan FieldName DataValue
      -- ^ Filter a data stream so that only data in a given field less than the given
      --   value are used.
      --
      --   @since 0.4.0.0
    | FLessThanEq FieldName DataValue
      -- ^ Filter a data stream so that only data in a given field less than,
      --   or equal to, the given value are used.
      --
      --   @since 0.4.0.0
    | FGreaterThan FieldName DataValue
      -- ^ Filter a data stream so that only data in a given field greater than the given
      --   value are used.
      --
      --   @since 0.4.0.0
    | FGreaterThanEq FieldName DataValue
      -- ^ Filter a data stream so that only data in a given field greater than,
      --   or equal to, the given value are used.
      --
      --   @since 0.4.0.0
    | FExpr VegaExpr
      -- ^ Filter a data stream so that only data that satisfy the given predicate
      --   expression are used.
    | FCompose BooleanOp
      -- ^ Build up a filtering predicate through logical composition such
      --   as 'And' and 'Or'.
      --
      --   The following fgragment will apply a filter to identify only
      --   those items selected interactively and that represent ages
      --   over 65:
      --
      --   @
      --   trans = 'transform'
      --             . 'filter'
      --                 ('FCompose'
      --                   ('And' ('Selection' "brush") ('Expr' "datum.age > 65"))
      --                 )
      --   @
    | FSelection SelectionLabel
      -- ^ Filter a data stream so that only data in a given field that are
      --   within the given interactive selection are used.
      --
      --   @
      --   sel = 'Graphics.Vega.VegaLite.selection' . 'Graphics.Vega.VegaLite.select' \"myBrush\" 'Graphics.Vega.VegaLite.Interval' ['Graphics.Vega.VegaLite.Encodings' ['Graphics.Vega.VegaLite.ChX']]
      --   trans = 'transform' . 'filter' ('FSelection' \"myBrush\")
      --   @
    | FOneOf FieldName DataValues
      -- ^ Filter a data stream so that only data in a given field contained in the given
      --   list of values are used.
    | FRange FieldName FilterRange
      -- ^ Filter a data stream so that only data in a given field
      --   that are within the given range are used.
      --
      --   For example:
      --
      --   @
      --   'filter' ('FRange' "date" ('DateRange' ['Graphics.Vega.VegaLite.DTYear' 2006] ['Graphics.Vega.VegaLite.DTYear' 2016])
      --   @
      --
      --   See 'FilterOpTrans' for more use cases.
    | FValid FieldName
      -- ^ Filter a data stream so that only valid data (i.e. not null or NaN) in a given
      --   field are used.
      --
      --   @since 0.4.0.0


fop_ :: FieldName -> T.Text -> DataValue -> [LabelledSpec]
fop_ :: Text -> Text -> DataValue -> [LabelledSpec]
fop_ Text
field Text
label DataValue
val = [Text -> LabelledSpec
field_ Text
field, Text
label Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= DataValue -> VLSpec
dataValueSpec DataValue
val]

filterProperty :: Filter -> [LabelledSpec]

filterProperty :: Filter -> [LabelledSpec]
filterProperty (FEqual Text
field DataValue
val) = Text -> Text -> DataValue -> [LabelledSpec]
fop_ Text
field Text
"equal" DataValue
val
filterProperty (FLessThan Text
field DataValue
val) = Text -> Text -> DataValue -> [LabelledSpec]
fop_ Text
field Text
"lt" DataValue
val
filterProperty (FLessThanEq Text
field DataValue
val) = Text -> Text -> DataValue -> [LabelledSpec]
fop_ Text
field Text
"lte" DataValue
val
filterProperty (FGreaterThan Text
field DataValue
val) = Text -> Text -> DataValue -> [LabelledSpec]
fop_ Text
field Text
"gt" DataValue
val
filterProperty (FGreaterThanEq Text
field DataValue
val) = Text -> Text -> DataValue -> [LabelledSpec]
fop_ Text
field Text
"gte" DataValue
val

filterProperty (FSelection Text
selName) = [Text
"selection" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
selName]

filterProperty (FRange Text
field FilterRange
vals) =
  let ans :: [VLSpec]
ans = case FilterRange
vals of
              NumberRange Double
mn Double
mx -> (Double -> VLSpec) -> [Double] -> [VLSpec]
forall a b. (a -> b) -> [a] -> [b]
map Double -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON [Double
mn, Double
mx]
              NumberRangeLL Double
mn -> [Double -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON Double
mn, VLSpec
A.Null]
              NumberRangeUL Double
mx -> [VLSpec
A.Null, Double -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON Double
mx]
              DateRange [DateTime]
dMin [DateTime]
dMax -> [[DateTime] -> VLSpec
process [DateTime]
dMin, [DateTime] -> VLSpec
process [DateTime]
dMax]

      process :: [DateTime] -> VLSpec
process [] = VLSpec
A.Null
      process [DateTime]
dts = [DateTime] -> VLSpec
dateTimeSpec [DateTime]
dts

  in [Text -> LabelledSpec
field_ Text
field, Text
"range" Text -> [VLSpec] -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [VLSpec]
ans]

filterProperty (FOneOf Text
field DataValues
vals) =
  let ans :: [VLSpec]
ans = case DataValues
vals of
              Numbers [Double]
xs -> (Double -> VLSpec) -> [Double] -> [VLSpec]
forall a b. (a -> b) -> [a] -> [b]
map Double -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON [Double]
xs
              DateTimes [[DateTime]]
dts -> ([DateTime] -> VLSpec) -> [[DateTime]] -> [VLSpec]
forall a b. (a -> b) -> [a] -> [b]
map [DateTime] -> VLSpec
dateTimeSpec [[DateTime]]
dts
              Strings [Text]
ss -> (Text -> VLSpec) -> [Text] -> [VLSpec]
forall a b. (a -> b) -> [a] -> [b]
map Text -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON [Text]
ss
              Booleans [Bool]
bs -> (Bool -> VLSpec) -> [Bool] -> [VLSpec]
forall a b. (a -> b) -> [a] -> [b]
map Bool -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON [Bool]
bs

  in [Text -> LabelledSpec
field_ Text
field, Text
"oneOf" Text -> [VLSpec] -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [VLSpec]
ans]

filterProperty (FValid Text
field) = [Text -> LabelledSpec
field_ Text
field, Text
"valid" Text -> Bool -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
True]
filterProperty Filter
_ = []  -- ignore FExpr and FCompose


filterSpec :: Filter -> VLSpec
filterSpec :: Filter -> VLSpec
filterSpec (FExpr Text
expr) = Text -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON Text
expr
filterSpec (FCompose BooleanOp
boolExpr) = BooleanOp -> VLSpec
booleanOpSpec BooleanOp
boolExpr
filterSpec Filter
f = [LabelledSpec] -> VLSpec
object (Filter -> [LabelledSpec]
filterProperty Filter
f)

trFilterSpec :: MarkChannel -> Filter -> VLSpec
trFilterSpec :: MarkChannel -> Filter -> VLSpec
trFilterSpec MarkChannel
_ (FExpr Text
expr) = Text -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON Text
expr
trFilterSpec MarkChannel
_ (FCompose BooleanOp
boolExpr) = BooleanOp -> VLSpec
booleanOpSpec BooleanOp
boolExpr
trFilterSpec MarkChannel
mchan Filter
fi = [LabelledSpec] -> VLSpec
object (MarkChannel -> [LabelledSpec]
markChannelProperty MarkChannel
mchan [LabelledSpec] -> [LabelledSpec] -> [LabelledSpec]
forall a. Semigroup a => a -> a -> a
<> Filter -> [LabelledSpec]
filterProperty Filter
fi)


-- | A pair of filter range data values, used with 'FRange'.

data FilterRange
    = NumberRange Double Double
      -- ^ Select between these two values (both limits are inclusive).
    | NumberRangeLL Double
      -- ^ A lower limit (inclusive).
      --
      --   @since 0.7.0.0
    | NumberRangeUL Double
      -- ^ An upper limit (inclusive).
      --
      --   @since 0.7.0.0
    | DateRange [DateTime] [DateTime]
      -- ^ Select between these two dates (both limits are inclusive).
      --
      --   If a limit is the empty list then the filter is treated as
      --   a limit only on the other value, so
      --   @DateRange [] ['Graphics.Vega.VegaLite.DTYear' 2019]@
      --   acts as an upper-limit on the date range. One of the two
      --   limits __should__ be defined, but there is no enforcement
      --   of this.


-- | Types of hyperlink channel property used for linking marks or text to URLs.
--
--   Unfortunately there is a split between @H@ and @Hy@ as the prefix.
data HyperlinkChannel
    = HName FieldName
      -- ^ Field used for encoding with a hyperlink channel.
    | HRepeat Arrangement
      -- ^ Reference in a hyperlink channel to a field name generated by 'repeatFlow'
      --   or 'repeat'. The parameter identifies whether reference is being made to
      --   fields that are to be arranged in columns, in rows, or a with a flow layout.
    | HmType Measurement
      -- ^ Level of measurement when encoding with a hyperlink channel.
    | HAggregate Operation
      -- ^ Compute aggregate summary statistics for a field to be encoded with a
      --   hyperlink channel.
    | HyBand Double
      -- ^ Specify the mark position or size relative to the band size.
      --   The value is in the range 0 to 1, inclusive.
      --
      --   @since 0.9.0.0
    | HBin [BinProperty]
      -- ^ Discretize numeric values into bins when encoding with a hyperlink channel.
    | HBinned
      -- ^ Indicate that data encoded with a hyperlink channel are already binned.
      --
      --   @since 0.4.0.0
    | HSelectionCondition BooleanOp [HyperlinkChannel] [HyperlinkChannel]
      -- ^ Make a hyperlink channel conditional on interactive selection. The first parameter
      --   provides the selection to evaluate, the second the encoding to apply if the hyperlink
      --   has been selected, the third the encoding if it is not selected.
    | HDataCondition [(BooleanOp, [HyperlinkChannel])] [HyperlinkChannel]
      -- ^ Make a hyperlink channel conditional on one or more predicate expressions. The first
      --   parameter is a list of tuples each pairing an expression to evaluate with the encoding
      --   if that expression is @True@. The second is the encoding if none of the expressions
      --   evaluate as @True@.
      --
      --   The arguments to this constructor have changed in @0.4.0.0@
      --   to support multiple expressions.
    | HyFormat T.Text
      -- ^ [Formatting pattern](https://vega.github.io/vega-lite/docs/format.html)
      --   for hyperlink properties. To distinguish between formatting as numeric values and data/time
      --   values, additionally use 'HyFormatAsNum', 'HyFormatAsTemporal', and
      --   'HyFormatAsCustom'.
      --
      --   @since 0.9.0.0
    | HyFormatAsNum
      -- ^ The marks should be formatted as numbers. Use a
      --   [d3 numeric format string](https://github.com/d3/d3-format#locale_format)
      --   with 'HyFormat'.
      --
      --   @since 0.9.0.0
    | HyFormatAsTemporal
      -- ^ The marks should be formatted as dates or times. Use a
      --   [d3 date/time format string](https://github.com/d3/d3-time-format#locale_format)
      --   with 'HyFormat'.
      --
      --   @since 0.9.0.0
    | HyFormatAsCustom T.Text
      -- ^ The [custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type)
      --   for use with with 'HyFormat'.
      --
      --   @since 0.9.0.0
    | HyLabelExpr VegaExpr
      -- ^ Provide the expression used to generate labels.
      --
      --   @since 0.9.0.0
    | HString T.Text
      -- ^ Literal string value when encoding with a hyperlink channel.
    | HTimeUnit TimeUnit
      -- ^ Time unit aggregation of field values when encoding with a
      --   hyperlink channel.
    | HyTitle T.Text
      -- ^ Title of a field when encoding with a hyperlink channel.
      --
      --   @since 0.9.0.0
    | HyNoTitle
      -- ^ Display no title.
      --
      --   @since 0.9.0.0

hyperlinkChannelProperty :: HyperlinkChannel -> [LabelledSpec]
hyperlinkChannelProperty :: HyperlinkChannel -> [LabelledSpec]
hyperlinkChannelProperty (HName Text
s) = [Text -> LabelledSpec
field_ Text
s]
hyperlinkChannelProperty (HRepeat Arrangement
arr) = [Text
"field" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [LabelledSpec] -> VLSpec
object [Arrangement -> LabelledSpec
repeat_ Arrangement
arr]]
hyperlinkChannelProperty (HmType Measurement
t) = [Measurement -> LabelledSpec
mtype_ Measurement
t]
hyperlinkChannelProperty (HAggregate Operation
op) = [Operation -> LabelledSpec
aggregate_ Operation
op]
hyperlinkChannelProperty (HyBand Double
x) = [Text
"band" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x]
hyperlinkChannelProperty (HBin [BinProperty]
bps) = [[BinProperty] -> LabelledSpec
bin [BinProperty]
bps]
hyperlinkChannelProperty HyperlinkChannel
HBinned = [LabelledSpec
binned_]
hyperlinkChannelProperty (HSelectionCondition BooleanOp
selName [HyperlinkChannel]
ifClause [HyperlinkChannel]
elseClause) =
  (HyperlinkChannel -> [LabelledSpec])
-> BooleanOp
-> [HyperlinkChannel]
-> [HyperlinkChannel]
-> [LabelledSpec]
forall a.
(a -> [LabelledSpec]) -> BooleanOp -> [a] -> [a] -> [LabelledSpec]
selCond_ HyperlinkChannel -> [LabelledSpec]
hyperlinkChannelProperty BooleanOp
selName [HyperlinkChannel]
ifClause [HyperlinkChannel]
elseClause
hyperlinkChannelProperty (HDataCondition [(BooleanOp, [HyperlinkChannel])]
tests [HyperlinkChannel]
elseClause) =
  (HyperlinkChannel -> [LabelledSpec])
-> [(BooleanOp, [HyperlinkChannel])]
-> [HyperlinkChannel]
-> [LabelledSpec]
forall a.
(a -> [LabelledSpec])
-> [(BooleanOp, [a])] -> [a] -> [LabelledSpec]
dataCond_ HyperlinkChannel -> [LabelledSpec]
hyperlinkChannelProperty [(BooleanOp, [HyperlinkChannel])]
tests [HyperlinkChannel]
elseClause
hyperlinkChannelProperty (HyFormat Text
fmt) = [Text
"format" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
fmt]
hyperlinkChannelProperty HyperlinkChannel
HyFormatAsNum = [Text
"formatType" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text -> VLSpec
fromT Text
"number"]
hyperlinkChannelProperty HyperlinkChannel
HyFormatAsTemporal = [Text
"formatType" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text -> VLSpec
fromT Text
"time"]
hyperlinkChannelProperty (HyFormatAsCustom Text
c) = [Text
"formatType" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
c]
hyperlinkChannelProperty (HyLabelExpr Text
lbl) = [Text
"labelExpr" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
lbl]
hyperlinkChannelProperty (HString Text
s) = [Text -> LabelledSpec
value_ Text
s]
hyperlinkChannelProperty (HTimeUnit TimeUnit
tu) = [TimeUnit -> LabelledSpec
timeUnit_ TimeUnit
tu]
hyperlinkChannelProperty (HyTitle Text
t) = [Text
"title" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
t]
hyperlinkChannelProperty HyperlinkChannel
HyNoTitle = [Text
"title" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= VLSpec
A.Null]


-- | A text description of this mark for ARIA accessibility.
--
--   @since 0.9.0.0
data AriaDescriptionChannel
    = ADName FieldName
      -- ^ Field used for encoding with an Aria description.
    | ADRepeat Arrangement
      -- ^ Reference in an Aria description channel to a field name generated by 'repeatFlow'
      --   or 'repeat'. The parameter identifies whether reference is being made to
      --   fields that are to be arranged in columns, in rows, or a with a flow layout.
    | ADmType Measurement
      -- ^ Level of measurement.
    | ADAggregate Operation
      -- ^ Compute aggregate summary statistics for a field to be encoded.
    | ADBand Double
      -- ^ Specify the mark position or size relative to the band size.
      --   The value is in the range 0 to 1, inclusive.
    | ADBin [BinProperty]
      -- ^ Discretize numeric values into bins.
    | ADBinned
      -- ^ Indicate that data encoded are already binned.
    | ADSelectionCondition BooleanOp [AriaDescriptionChannel] [AriaDescriptionChannel]
      -- ^ Make the channel conditional on interactive selection. The first parameter
      --   provides the selection to evaluate, the second the encoding to apply if the description
      --   has been selected, the third the encoding if it is not selected.
    | ADDataCondition [(BooleanOp, [AriaDescriptionChannel])] [AriaDescriptionChannel]
      -- ^ Make the channel conditional on one or more predicate expressions. The first
      --   parameter is a list of tuples each pairing an expression to evaluate with the encoding
      --   if that expression is @True@. The second is the encoding if none of the expressions
      --   evaluate as @True@.
    | ADFormat T.Text
      -- ^ [Formatting pattern](https://vega.github.io/vega-lite/docs/format.html)
      --   for descriptions. To distinguish between formatting as numeric values and data/time
      --   values, additionally use 'ADFormatAsNum', 'ADFormatAsTemporal', and
      --   'ADFormatAsCustom'.
    | ADFormatAsNum
      -- ^ The marks should be formatted as numbers. Use a
      --   [d3 numeric format string](https://github.com/d3/d3-format#locale_format)
      --   with 'ADFormat'.
    | ADFormatAsTemporal
      -- ^ The marks should be formatted as dates or times. Use a
      --   [d3 date/time format string](https://github.com/d3/d3-time-format#locale_format)
      --   with 'ADFormat'.
    | ADFormatAsCustom T.Text
      -- ^ The [custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type)
      --   for use with with 'ADFormat'.
    | ADLabelExpr VegaExpr
      -- ^ Provide the expression used to generate labels.
    | ADString T.Text
      -- ^ Literal string value.
    | ADTimeUnit TimeUnit
      -- ^ Time unit aggregation of field values when encoding with an Aria
      --   description channel.
    | ADTitle T.Text
      -- ^ Title of a field when encoding with an Aria description channel.
    | ADNoTitle
      -- ^ Display no title.


ariaDescriptionChannelProperty :: AriaDescriptionChannel -> [LabelledSpec]
ariaDescriptionChannelProperty :: AriaDescriptionChannel -> [LabelledSpec]
ariaDescriptionChannelProperty (ADName Text
s) = [Text -> LabelledSpec
field_ Text
s]
ariaDescriptionChannelProperty (ADRepeat Arrangement
arr) = [Text
"field" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [LabelledSpec] -> VLSpec
object [Arrangement -> LabelledSpec
repeat_ Arrangement
arr]]
ariaDescriptionChannelProperty (ADmType Measurement
t) = [Measurement -> LabelledSpec
mtype_ Measurement
t]
ariaDescriptionChannelProperty (ADAggregate Operation
op) = [Operation -> LabelledSpec
aggregate_ Operation
op]
ariaDescriptionChannelProperty (ADBand Double
x) = [Text
"band" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x]
ariaDescriptionChannelProperty (ADBin [BinProperty]
bps) = [[BinProperty] -> LabelledSpec
bin [BinProperty]
bps]
ariaDescriptionChannelProperty AriaDescriptionChannel
ADBinned = [LabelledSpec
binned_]
ariaDescriptionChannelProperty (ADSelectionCondition BooleanOp
selName [AriaDescriptionChannel]
ifClause [AriaDescriptionChannel]
elseClause) =
  (AriaDescriptionChannel -> [LabelledSpec])
-> BooleanOp
-> [AriaDescriptionChannel]
-> [AriaDescriptionChannel]
-> [LabelledSpec]
forall a.
(a -> [LabelledSpec]) -> BooleanOp -> [a] -> [a] -> [LabelledSpec]
selCond_ AriaDescriptionChannel -> [LabelledSpec]
ariaDescriptionChannelProperty BooleanOp
selName [AriaDescriptionChannel]
ifClause [AriaDescriptionChannel]
elseClause
ariaDescriptionChannelProperty (ADDataCondition [(BooleanOp, [AriaDescriptionChannel])]
tests [AriaDescriptionChannel]
elseClause) =
  (AriaDescriptionChannel -> [LabelledSpec])
-> [(BooleanOp, [AriaDescriptionChannel])]
-> [AriaDescriptionChannel]
-> [LabelledSpec]
forall a.
(a -> [LabelledSpec])
-> [(BooleanOp, [a])] -> [a] -> [LabelledSpec]
dataCond_ AriaDescriptionChannel -> [LabelledSpec]
ariaDescriptionChannelProperty [(BooleanOp, [AriaDescriptionChannel])]
tests [AriaDescriptionChannel]
elseClause
ariaDescriptionChannelProperty (ADFormat Text
fmt) = [Text
"format" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
fmt]
ariaDescriptionChannelProperty AriaDescriptionChannel
ADFormatAsNum = [Text
"formatType" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text -> VLSpec
fromT Text
"number"]
ariaDescriptionChannelProperty AriaDescriptionChannel
ADFormatAsTemporal = [Text
"formatType" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text -> VLSpec
fromT Text
"time"]
ariaDescriptionChannelProperty (ADFormatAsCustom Text
c) = [Text
"formatType" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
c]
ariaDescriptionChannelProperty (ADLabelExpr Text
lbl) = [Text
"labelExpr" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
lbl]
ariaDescriptionChannelProperty (ADString Text
s) = [Text -> LabelledSpec
value_ Text
s]
ariaDescriptionChannelProperty (ADTimeUnit TimeUnit
tu) = [TimeUnit -> LabelledSpec
timeUnit_ TimeUnit
tu]
ariaDescriptionChannelProperty (ADTitle Text
t) = [Text
"title" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
t]
ariaDescriptionChannelProperty AriaDescriptionChannel
ADNoTitle = [Text
"title" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= VLSpec
A.Null]


----

{-|

Create a pair of continuous domain to color mappings suitable for customising
ordered scales. The first parameter is a tuple representing the mapping of the lowest
numeric value in the domain to its equivalent color; the second tuple the mapping
of the highest numeric value to color. If the domain contains any values between
these lower and upper bounds they are interpolated according to the scale's interpolation
function. This is a convenience function equivalent to specifying separate 'SDomain'
and 'SRange' lists and is safer as it guarantees a one-to-one correspondence between
domain and range values.

@
'color'
    [ 'MName' "year"
    , 'MmType' 'Graphics.Vega.VegaLite.Ordinal'
    , 'MScale' (domainRangeMap (1955, \"rgb(230,149,156)\") (2000, \"rgb(145,26,36)\"))
    ]
@
-}

domainRangeMap :: (Double, Color) -> (Double, Color) -> [ScaleProperty]
domainRangeMap :: (Double, Text) -> (Double, Text) -> [ScaleProperty]
domainRangeMap (Double, Text)
lowerMap (Double, Text)
upperMap =
  let ([Double]
domain, [Text]
range) = [(Double, Text)] -> ([Double], [Text])
forall a b. [(a, b)] -> ([a], [b])
unzip [(Double, Text)
lowerMap, (Double, Text)
upperMap]
  in [DomainLimits -> ScaleProperty
SDomain ([Double] -> DomainLimits
DNumbers [Double]
domain), ScaleRange -> ScaleProperty
SRange ([Text] -> ScaleRange
RStrings [Text]
range)]


{-|

Create a set of discrete domain to color mappings suitable for customising categorical
scales. The first item in each tuple should be a domain value and the second the
color value with which it should be associated. It is a convenience function equivalent
to specifying separate 'SDomain' and 'SRange' lists and is safer as it guarantees
a one-to-one correspondence between domain and range values.

@
'color'
    [ 'MName' "weather"
    , 'MmType' Nominal
    , 'MScale' (
        categoricalDomainMap
            [ ( "sun", "yellow" )
            , ( "rain", "blue" )
            , ( "fog", "grey" )
            ]
        )
    ]
@
-}

categoricalDomainMap :: [(T.Text, Color)] -> [ScaleProperty]
categoricalDomainMap :: [(Text, Text)] -> [ScaleProperty]
categoricalDomainMap [(Text, Text)]
scaleDomainPairs =
  let ([Text]
domain, [Text]
range) = [(Text, Text)] -> ([Text], [Text])
forall a b. [(a, b)] -> ([a], [b])
unzip [(Text, Text)]
scaleDomainPairs
  in [DomainLimits -> ScaleProperty
SDomain ([Text] -> DomainLimits
DStrings [Text]
domain), ScaleRange -> ScaleProperty
SRange ([Text] -> ScaleRange
RStrings [Text]
range)]


{-|

Types of facet channel property used for creating a composed facet view of small
multiples.

-}

-- based on schema 3.3.0 #/definitions/FacetFieldDef
-- although it's a bit different now (maybe RowColumnEncodingFieldDef in 4.2.0)


data FacetChannel
    = FName FieldName
      -- ^ The name of the field from which to pull a data value.
    | FmType Measurement
      -- ^ The encoded field's type of measurement.
    | FAggregate Operation
      -- ^ Aggregation function for the field.
    | FAlign CompositionAlignment
      -- ^ The alignment to apply to the row- or column- facet's subplot.
      --
      --   @since 0.6.0.0
    | FBin [BinProperty]
      -- ^ Describe how to bin quantitative fields, or whether the
      --   channels are already binned.
    | FCenter Bool
      -- ^ Should sub-views be centered relative to their respective rows or
      --   columns.
      --
      --   @since 0.6.0.0
    | FHeader [HeaderProperty]
      -- ^ The properties of a facet's header.
    | FSort [SortProperty]
      -- ^ Sort order for the encoded field.
      --
      --   @since 0.4.0.0
    | FSpacing Double
      -- ^ The pixel spacing between sub-views.
      --
      --   If you have code from a version of @hvega@ before @0.6.0.0@ that
      --   uses @FSpacing@ (with 'Graphics.Vega.VegaLite.FacetStyle'), please
      --   use 'Graphics.Vega.VegaLite.CompSpacing' as a replacement.
      --
      --   @since 0.6.0.0
    | FTimeUnit TimeUnit
      -- ^ The time-unit for a temporal field.
    | FTitle T.Text
      -- ^ The title for the field.
      --
      --   @since 0.4.0.0
    | FNoTitle
      -- ^ Draw no title.
      --
      -- @since 0.4.0.0

facetChannelProperty :: FacetChannel -> LabelledSpec
facetChannelProperty :: FacetChannel -> LabelledSpec
facetChannelProperty (FName Text
s) = Text -> LabelledSpec
field_ Text
s
facetChannelProperty (FmType Measurement
measure) = Measurement -> LabelledSpec
mtype_ Measurement
measure
facetChannelProperty (FAlign CompositionAlignment
algn) = Text
"align" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= CompositionAlignment -> VLSpec
compositionAlignmentSpec CompositionAlignment
algn
facetChannelProperty (FAggregate Operation
op) = Operation -> LabelledSpec
aggregate_ Operation
op
facetChannelProperty (FBin [BinProperty]
bps) = [BinProperty] -> LabelledSpec
bin [BinProperty]
bps
facetChannelProperty (FCenter Bool
b) = Text
"center" Text -> Bool -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
b
facetChannelProperty (FHeader [HeaderProperty]
hps) = Text -> [HeaderProperty] -> LabelledSpec
header_ Text
"" [HeaderProperty]
hps
facetChannelProperty (FSort [SortProperty]
sps) = [SortProperty] -> LabelledSpec
sort_ [SortProperty]
sps
facetChannelProperty (FSpacing Double
x) = Text
"spacing" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x
facetChannelProperty (FTitle Text
s) = Text
"title" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
s
facetChannelProperty FacetChannel
FNoTitle = Text
"title" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= VLSpec
A.Null
facetChannelProperty (FTimeUnit TimeUnit
tu) = TimeUnit -> LabelledSpec
timeUnit_ TimeUnit
tu


-- | Types of text channel property used for displaying text as part of the visualization.

-- Basing the following partly on vega-lite-3.3.0.json / TextFieldDef
-- but that doesn't seem to be sufficient.

data TextChannel
    = TName FieldName
      -- ^ Name of the field used for encoding with a text channel.
    | TRepeat Arrangement
      -- ^ Reference in a text channel to a field name generated by 'repeatFlow'
      --   or 'repeat'. The parameter identifies whether reference is being made to
      --   fields that are to be arranged in columns, in rows, or a with a flow layout.
    | TRepeatDatum Arrangement
      -- ^ Reference in a text channel to a datum value generated by 'repeatFlow'
      --   or 'repeat'. The parameter identifies whether reference is being made to
      --   a datum that is to be encoded in layers, or in columns or rows in a
      --   flow layout.
      --
      --   @since 0.9.0.0
    | TmType Measurement
      -- ^ Level of measurement when encoding with a text channel.
    | TAggregate Operation
      -- ^ Compute some aggregate summary statistics for a field to be encoded with a
      --   text channel. The type of aggregation is determined by the given operation
      --   parameter.
    | TBand Double
      -- ^ Specify the mark position or size relative to the band size.
      --   The value is in the range 0 to 1, inclusive.
      --
      --   @since 0.9.0.0
    | TBin [BinProperty]
      -- ^ Discretize numeric values into bins when encoding with a text channel.
    | TBinned
      -- ^ Indicate that data encoded with a text channel are already binned.
      --
      --   @since 0.4.0.0
    | TDataCondition [(BooleanOp, [TextChannel])] [TextChannel]
      -- ^ Make a text channel conditional on one or more predicate expressions. The first
      --   parameter is a list of tuples each pairing an expression to evaluate with the encoding
      --   if that expression is @True@. The second is the encoding if none of the expressions
      --   evaluate as @True@.
      --
      --   The arguments to this constructor have changed in @0.4.0.0@
      --   to support multiple expressions.
    | TSelectionCondition BooleanOp [TextChannel] [TextChannel]
      -- ^ Make a text channel conditional on interactive selection. The first parameter
      --   is a selection condition to evaluate; the second the encoding to apply if that
      --   selection is true; the third parameter is the encoding if the selection is false.
    | TDatum DataValue
      -- ^ A constant value in the data domain.
      --
      --   @since 0.9.0.0
    | TFormat T.Text
      -- ^ [Formatting pattern](https://vega.github.io/vega-lite/docs/format.html)
      --   for text marks. To distinguish between formatting as numeric values and data/time
      --   values, additionally use 'TFormatAsNum', 'TFormatAsTemporal', and
      --   'TFormatAsCustom'.
    | TFormatAsNum
      -- ^ The text marks should be formatted as numbers. Use a
      --   [d3 numeric format string](https://github.com/d3/d3-format#locale_format)
      --   with 'TFormat'.
      --
      --   @since 0.4.0.0
    | TFormatAsTemporal
      -- ^ The text marks should be formatted as dates or times. Use a
      --   [d3 date/time format string](https://github.com/d3/d3-time-format#locale_format)
      --   with 'TFormat'.
      --
      --   @since 0.4.0.0
    | TFormatAsCustom T.Text
      -- ^ The [custom format type](https://vega.github.io/vega-lite/docs/config.html#custom-format-type)
      --   for use with with 'TFormat'.
      --
      --   @since 0.9.0.0
    | TLabelExpr VegaExpr
      -- ^ Provide the expression used to generate labels.
      --
      --   @since 0.9.0.0
    | TString T.Text
      -- ^ A literal value for encoding a text property channel. See also 'TStrings'.
      --
      --   This can be useful for a text annotation, such as:
      --
      --   @
      --   'encoding'
      --      . 'position' 'Graphics.Vega.VegaLite.X' [ 'PNumber' 300 ]
      --      . 'position' 'Graphics.Vega.VegaLite.Y' [ 'PNumber' 1234 ]
      --      . 'text' [ 'TString' \"Upper limit\" ]
      --   @
      --
      --   @since 0.5.0.0
    | TStrings [T.Text]
      -- ^ A multi-line value. See also 'TString'.
      --
      --   @since 0.7.0.0
    | TTimeUnit TimeUnit
      -- ^ Time unit aggregation of field values when encoding with a text channel.
    | TTitle T.Text
      -- ^ Title of a field when encoding with a text or tooltip channel.
      --
      --   @since 0.4.0.0
    | TNoTitle
      -- ^ Display no title.
      --
      --   @since 0.4.0.0

textChannelProperty :: TextChannel -> [LabelledSpec]
textChannelProperty :: TextChannel -> [LabelledSpec]
textChannelProperty (TName Text
s) = [Text -> LabelledSpec
field_  Text
s]
textChannelProperty (TRepeat Arrangement
arr) = [Text
"field" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [LabelledSpec] -> VLSpec
object [Arrangement -> LabelledSpec
repeat_ Arrangement
arr]]
textChannelProperty (TRepeatDatum Arrangement
arr) = [Text
"datum" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [LabelledSpec] -> VLSpec
object [Arrangement -> LabelledSpec
repeat_ Arrangement
arr]]
textChannelProperty (TmType Measurement
measure) = [Measurement -> LabelledSpec
mtype_ Measurement
measure]
textChannelProperty (TAggregate Operation
op) = [Operation -> LabelledSpec
aggregate_ Operation
op]
textChannelProperty (TBand Double
x) = [Text
"band" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x]
textChannelProperty (TBin [BinProperty]
bps) = [[BinProperty] -> LabelledSpec
bin [BinProperty]
bps]
textChannelProperty TextChannel
TBinned = [LabelledSpec
binned_]
textChannelProperty (TDataCondition [(BooleanOp, [TextChannel])]
tests [TextChannel]
elseClause) =
  (TextChannel -> [LabelledSpec])
-> [(BooleanOp, [TextChannel])] -> [TextChannel] -> [LabelledSpec]
forall a.
(a -> [LabelledSpec])
-> [(BooleanOp, [a])] -> [a] -> [LabelledSpec]
dataCond_ TextChannel -> [LabelledSpec]
textChannelProperty [(BooleanOp, [TextChannel])]
tests [TextChannel]
elseClause
textChannelProperty (TSelectionCondition BooleanOp
selName [TextChannel]
ifClause [TextChannel]
elseClause) =
  (TextChannel -> [LabelledSpec])
-> BooleanOp -> [TextChannel] -> [TextChannel] -> [LabelledSpec]
forall a.
(a -> [LabelledSpec]) -> BooleanOp -> [a] -> [a] -> [LabelledSpec]
selCond_ TextChannel -> [LabelledSpec]
textChannelProperty BooleanOp
selName [TextChannel]
ifClause [TextChannel]
elseClause
textChannelProperty (TDatum DataValue
dv) = [Text
"datum" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= DataValue -> VLSpec
dataValueSpec DataValue
dv]
textChannelProperty (TFormat Text
fmt) = [Text
"format" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
fmt]
textChannelProperty TextChannel
TFormatAsNum = [Text
"formatType" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text -> VLSpec
fromT Text
"number"]
textChannelProperty TextChannel
TFormatAsTemporal = [Text
"formatType" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text -> VLSpec
fromT Text
"time"]
textChannelProperty (TFormatAsCustom Text
c) = [Text
"formatType" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
c]
textChannelProperty (TLabelExpr Text
e) = [Text
"labelExpr" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
e]
textChannelProperty (TString Text
s) = [Text
"value" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
s]
textChannelProperty (TStrings [Text]
xs) = [Text
"value" Text -> [Text] -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [Text]
xs]
textChannelProperty (TTimeUnit TimeUnit
tu) = [TimeUnit -> LabelledSpec
timeUnit_ TimeUnit
tu]
textChannelProperty (TTitle Text
s) = [Text
"title" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text -> VLSpec
splitOnNewline Text
s]
textChannelProperty TextChannel
TNoTitle = [Text
"title" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= VLSpec
A.Null]


-- | Properties of an ordering channel used for sorting data fields.

-- maps to OrderFieldDef

data OrderChannel
    = OName FieldName
      -- ^ The name of the field used for encoding with an order channel.
    | ORepeat Arrangement
      -- ^ Reference in an order channel to a field name generated by 'repeatFlow'
      -- or 'repeat'. The parameter identifies whether reference is being made to
      -- fields that are to be arranged in columns, in rows, or a with a flow layout.
    | OAggregate Operation
      -- ^ Compute some aggregate summary statistics for a field to be encoded
      --   with an order channel.
    | OBand Double
      -- ^ For rect-based marks, define the mark size relative to the bandwidth of
      --   band scales, bins, or time units: a value of 1 uses the range and 0.5
      --   half the range. For other marks it defines the relative position in a
      --   band of a stacked, binned, time unit, or band scale: if 0 the marks
      --   will be positioned at the beginning of the band and 0.5 gives the
      --   middle of the band.
      --
      --   The argument must be in the range 0 to 1, inclusive, but there is no
      --   check on this.
      --
      --   @since 0.11.0.0
    | OBin [BinProperty]
      -- ^ Discretize numeric values into bins when encoding with an
      --   order channel.
    | OSort [SortProperty]
      -- ^ Sort order for field when encoding with an order channel.
    | OTimeUnit TimeUnit
      -- ^ Form of time unit aggregation of field values when encoding with
      --   an order channel.
    | OTitle T.Text
      -- ^ The title for the field.
      --
      --   Note that if both the field and axis, header, or legend titles are
      --   defined than the latter (axis, header, or legend) will be used.
      --
      --   @since 0.11.0.0
    | ONoTitle
      -- ^ Remove the title.
      --
      --   @since 0.11.0.0
    | OmType Measurement
      -- ^ The level of measurement when encoding with an order channel.
    | ODataCondition [(BooleanOp, [OrderChannel])] [OrderChannel]
      -- ^ Make an order channel conditional on one or more predicate expressions. The first
      --   parameter is a list of tuples each pairing an expression to evaluate with the encoding
      --   if that expression is @True@. The second is the encoding if none of the expressions
      --   evaluate as @True@.
      --
      --   @since 0.11.0.0
    | OSelectionCondition BooleanOp [OrderChannel] [OrderChannel]
      -- ^ Make an order channel conditional on interactive selection. The first parameter
      --   is a selection condition to evaluate; the second the encoding to apply if that
      --   selection is true; the third parameter is the encoding if the selection is false.
      --
      --   An example:
      --
      --   @'order' ['OSelectionCondition' ('SelectionName' "highlight")
      --           ['ONumber' 1] ['ONumber' 0]]
      --   @
      --
      --   @since 0.11.0.0
    | ONumber Double
      -- ^ Create a value with this number. For use with 'OSelectionCondition'
      --   and 'ODataCondition'.
      --
      --   @since 0.11.0.0

orderChannelProperty :: OrderChannel -> [LabelledSpec]
orderChannelProperty :: OrderChannel -> [LabelledSpec]
orderChannelProperty (OAggregate Operation
op) = [Operation -> LabelledSpec
aggregate_ Operation
op]
orderChannelProperty (OBand Double
x) = [Text
"band" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
x]
orderChannelProperty (OBin [BinProperty]
bps) = [[BinProperty] -> LabelledSpec
bin [BinProperty]
bps]
orderChannelProperty (OName Text
s) = [Text -> LabelledSpec
field_ Text
s]
orderChannelProperty (ORepeat Arrangement
arr) = [Text
"field" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [LabelledSpec] -> VLSpec
object [Arrangement -> LabelledSpec
repeat_ Arrangement
arr]]
orderChannelProperty (OSort [SortProperty]
ops) = [[SortProperty] -> LabelledSpec
sort_ [SortProperty]
ops]
orderChannelProperty (OTimeUnit TimeUnit
tu) = [TimeUnit -> LabelledSpec
timeUnit_ TimeUnit
tu]
orderChannelProperty (OTitle Text
s) = [Text
"title" Text -> Text -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Text
s]
orderChannelProperty OrderChannel
ONoTitle = [Text
"title" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= VLSpec
A.Null]
orderChannelProperty (OmType Measurement
measure) = [Measurement -> LabelledSpec
mtype_ Measurement
measure]
orderChannelProperty (ODataCondition [(BooleanOp, [OrderChannel])]
tests [OrderChannel]
elseClause) =
  (OrderChannel -> [LabelledSpec])
-> [(BooleanOp, [OrderChannel])]
-> [OrderChannel]
-> [LabelledSpec]
forall a.
(a -> [LabelledSpec])
-> [(BooleanOp, [a])] -> [a] -> [LabelledSpec]
dataCond_ OrderChannel -> [LabelledSpec]
orderChannelProperty [(BooleanOp, [OrderChannel])]
tests [OrderChannel]
elseClause
orderChannelProperty (OSelectionCondition BooleanOp
selName [OrderChannel]
ifClause [OrderChannel]
elseClause) =
  (OrderChannel -> [LabelledSpec])
-> BooleanOp -> [OrderChannel] -> [OrderChannel] -> [LabelledSpec]
forall a.
(a -> [LabelledSpec]) -> BooleanOp -> [a] -> [a] -> [LabelledSpec]
selCond_ OrderChannel -> [LabelledSpec]
orderChannelProperty BooleanOp
selName [OrderChannel]
ifClause [OrderChannel]
elseClause
orderChannelProperty (ONumber Double
n) = [Text
"value" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
n]

-- | Level of detail channel properties used for creating a grouped channel
--   encoding.

data DetailChannel
    = DName FieldName
      -- ^ The name of the field.
    | DmType Measurement
      -- ^ The measurement type of the field.
    | DBin [BinProperty]
      -- ^ How to convert discrete numeric values into bins.
    | DTimeUnit TimeUnit
      -- ^ The form of time unit aggregation.
    | DAggregate Operation
      -- ^ How should the detail field be aggregated?


detailChannelProperty :: DetailChannel -> LabelledSpec
detailChannelProperty :: DetailChannel -> LabelledSpec
detailChannelProperty (DName Text
s) = Text -> LabelledSpec
field_ Text
s
detailChannelProperty (DmType Measurement
t) = Measurement -> LabelledSpec
mtype_ Measurement
t
detailChannelProperty (DBin [BinProperty]
bps) = [BinProperty] -> LabelledSpec
bin [BinProperty]
bps
detailChannelProperty (DTimeUnit TimeUnit
tu) = TimeUnit -> LabelledSpec
timeUnit_ TimeUnit
tu
detailChannelProperty (DAggregate Operation
op) = Operation -> LabelledSpec
aggregate_ Operation
op


{-|

Provides details of the mapping between a row or column and its field
definitions in a set of faceted small multiples. For details see the
<https://vega.github.io/vega-lite/docs/facet.html#mapping Vega-Lite documentation>.
-}
data FacetMapping
    = ColumnBy [FacetChannel]
    | RowBy [FacetChannel]


facetMappingProperty :: FacetMapping -> LabelledSpec
facetMappingProperty :: FacetMapping -> LabelledSpec
facetMappingProperty (RowBy [FacetChannel]
fFields) =
  Text
"row" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [LabelledSpec] -> VLSpec
object ((FacetChannel -> LabelledSpec) -> [FacetChannel] -> [LabelledSpec]
forall a b. (a -> b) -> [a] -> [b]
map FacetChannel -> LabelledSpec
facetChannelProperty [FacetChannel]
fFields)
facetMappingProperty (ColumnBy [FacetChannel]
fFields) =
  Text
"column" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [LabelledSpec] -> VLSpec
object ((FacetChannel -> LabelledSpec) -> [FacetChannel] -> [LabelledSpec]
forall a b. (a -> b) -> [a] -> [b]
map FacetChannel -> LabelledSpec
facetChannelProperty [FacetChannel]
fFields)


{-|

Create a single global configuration from a list of configuration specifications.
Configurations are applied to all relevant items in the specification. See the
<https://vega.github.io/vega-lite/docs/config.html Vega-Lite documentation> for
more details.

The following example would make axis lines (domain) 2 pixels wide,
remove the border rectangle and require interactive selection of items
to use a double-click:

@
config =
    'configure'
        . 'Graphics.Vega.VegaLite.configuration' ('Graphics.Vega.VegaLite.Axis' [ 'Graphics.Vega.VegaLite.DomainWidth' 1 ])
        . 'Graphics.Vega.VegaLite.configuration' ('Graphics.Vega.VegaLite.ViewStyle' [ 'Graphics.Vega.VegaLite.ViewStroke' "transparent" ])
        . 'Graphics.Vega.VegaLite.configuration' ('Graphics.Vega.VegaLite.SelectionStyle' [ ( 'Graphics.Vega.VegaLite.Single', [ 'Graphics.Vega.VegaLite.On' \"dblclick\" ] ) ])
@
-}

configure ::
  [ConfigureSpec]
  -- ^ The configuration options, created with 'Graphics.Vega.VegaLite.configuration'.
  --
  --    Prior to version @0.5.0.0@ this was @[LabelledSpec]@.
  -> PropertySpec
configure :: [ConfigureSpec] -> PropertySpec
configure [ConfigureSpec]
configs = (VLProperty
VLConfig, [LabelledSpec] -> VLSpec
object ((ConfigureSpec -> LabelledSpec)
-> [ConfigureSpec] -> [LabelledSpec]
forall a b. (a -> b) -> [a] -> [b]
map ConfigureSpec -> LabelledSpec
unCS [ConfigureSpec]
configs))


-- | Alignment to apply to grid rows and columns generated by a composition
--   operator. This version sets the same alignment for rows and columns.
--
--   See also 'alignRC'.
--
--   @since 0.4.0.0

align :: CompositionAlignment -> PropertySpec
align :: CompositionAlignment -> PropertySpec
align CompositionAlignment
algn = (VLProperty
VLAlign, CompositionAlignment -> VLSpec
compositionAlignmentSpec CompositionAlignment
algn)


-- | Similar to 'align' but with independent alignments for rows and columns.
--
--   See also 'align'.
--
--   @since 0.4.0.0

alignRC ::
  CompositionAlignment     -- ^ Row alignment
  -> CompositionAlignment  -- ^ Column alignment
  -> PropertySpec
alignRC :: CompositionAlignment -> CompositionAlignment -> PropertySpec
alignRC CompositionAlignment
alRow CompositionAlignment
alCol =
  (VLProperty
VLSpacing, [LabelledSpec] -> VLSpec
object [ Text
"row" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= CompositionAlignment -> VLSpec
compositionAlignmentSpec CompositionAlignment
alRow
                     , Text
"col" Text -> VLSpec -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= CompositionAlignment -> VLSpec
compositionAlignmentSpec CompositionAlignment
alCol
                     ])


-- | Spacing between sub-views in a composition operator.
--
--   See also 'spacingRC'.
--
--   @since 0.4.0.0

spacing ::
  Double   -- ^ Spacing in pixels.
  -> PropertySpec
spacing :: Double -> PropertySpec
spacing Double
sp = (VLProperty
VLSpacing, Double -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON Double
sp)


-- | Set the spacing between the rows and columns.
--
--   See also 'spacing'.
--
--   @since 0.4.0.0

spacingRC ::
  Double      -- ^ Spacing between rows (in pixels).
  -> Double   -- ^ Spacing between columns (in pixels).
  -> PropertySpec
spacingRC :: Double -> Double -> PropertySpec
spacingRC Double
spRow Double
spCol = (VLProperty
VLSpacing, [LabelledSpec] -> VLSpec
object [Text
"row" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
spRow, Text
"column" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
spCol])


-- | Are sub-views in a composition operator centred relative to their respective
--   rows and columns?
--
--   See also 'centerRC'.
--
--   @since 0.4.0.0

center :: Bool -> PropertySpec
center :: Bool -> PropertySpec
center Bool
c = (VLProperty
VLCenter, Bool -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON Bool
c)


-- | Are sub-views in a composition operator centred relative to their respective
--   rows and columns?
--
--   See also 'center'.
--
--   @since 0.4.0.0

centerRC ::
  Bool     -- ^ Are rows to be centered?
  -> Bool  -- ^ Are columns to be centered?
  -> PropertySpec
centerRC :: Bool -> Bool -> PropertySpec
centerRC Bool
cRow Bool
cCol = (VLProperty
VLCenter, [LabelledSpec] -> VLSpec
object [Text
"row" Text -> Bool -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
cRow, Text
"col" Text -> Bool -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Bool
cCol])


{-|

Bounds calculation method to use for determining the extent of a sub-plot in
a composed view.

@since 0.4.0.0
-}
bounds :: Bounds -> PropertySpec
bounds :: Bounds -> PropertySpec
bounds Bounds
bnds = (VLProperty
VLBounds, Bounds -> VLSpec
boundsSpec Bounds
bnds)


{-|

The list of specifications to be juxtaposed horizontally in a flow
layout of views.
See also 'hConcat' and 'vConcat'.

The number of columns in the flow layout can be set with 'columns'
and, if not specified, will default to a single row of unlimited columns.

@
let dvals = 'Graphics.Vega.VegaLite.dataSequenceAs' 0 6.28 0.1 \"x\"
    trans = 'transform'
              . 'calculateAs' \"sin(datum.x)\" \"sinX\"
              . 'calculateAs' \"cos(datum.x)\" \"cosX\"
    enc = 'encoding'
            . 'position' 'Graphics.Vega.VegaLite.X' ['PName' \"x\", 'PmType' 'Graphics.Vega.VegaLite.Quantitative']
    encCos = enc . 'position' 'Graphics.Vega.VegaLite.Y' ['PName' \"cosX\", 'PmType' 'Graphics.Vega.VegaLite.Quantitative']
    encSin = enc . 'position' 'Graphics.Vega.VegaLite.Y' ['PName' \"sinX\", 'PmType' 'Graphics.Vega.VegaLite.Quantitative']

in toVegaLite [ dvals
              , trans []
              , 'vlConcat' [ 'Graphics.Vega.VegaLite.asSpec' [encCos [], 'mark' 'Graphics.Vega.VegaLite.Line' []]
                         , 'Graphics.Vega.VegaLite.asSpec' [encSin [], 'mark' 'Graphics.Vega.VegaLite.Line' []]
                         ]
              ]
@

This is named @concat@ in Elm VegaLite but has been renamed here
to avoid conflicting with the Prelude.

@since 0.4.0.0

-}
vlConcat :: [VLSpec] -> PropertySpec
vlConcat :: [VLSpec] -> PropertySpec
vlConcat [VLSpec]
specs = (VLProperty
VLConcat, [VLSpec] -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON [VLSpec]
specs)


{-|

Defines the fields that will be used to facet a view in rows or columns to create
a set of small multiples. This is used where the encoding of the visualization in small
multiples is identical, but data for each is grouped by the given fields. When
creating a faceted view in this way you also need to define a full specification
to apply to each of those facets using 'Graphics.Vega.VegaLite.asSpec'.

See the
<https://vega.github.io/vega-lite/docs/facet.html Vega-Lite documentation>
for further details.

@
'Graphics.Vega.VegaLite.toVegaLite'
    [ facet [ 'RowBy' [ 'FName' \"Month\", 'FmType' 'Graphics.Vega.VegaLite.Ordinal' ]
            , 'ColumnBy' [ 'FName' \"Week\", 'FmType' 'Graphics.Vega.VegaLite.Ordinal' ]
            ]
    , 'Graphics.Vega.VegaLite.specification' spec
    ]
@

See also 'facetFlow'.

-}

facet :: [FacetMapping] -> PropertySpec
facet :: [FacetMapping] -> PropertySpec
facet [FacetMapping]
fMaps = (VLProperty
VLFacet, [LabelledSpec] -> VLSpec
object ((FacetMapping -> LabelledSpec) -> [FacetMapping] -> [LabelledSpec]
forall a b. (a -> b) -> [a] -> [b]
map FacetMapping -> LabelledSpec
facetMappingProperty [FacetMapping]
fMaps))


{-|

Facet a view to create small multiples in a flow layout. Used when the encoding
of the visualization in small multiples is identical, but data for each is grouped
by the given fields. When creating a faceted view in this way you also need to
define a full specification to apply to each of those facets using 'Graphics.Vega.VegaLite.asSpec'.

Small multiples will be laid out from left to right, moving on to new rows only
if the number of plots exceeds an optional column limit (specified via 'columns').

@
'Graphics.Vega.VegaLite.toVegaLite'
    [ facetFlow [ 'FName' \"Origin\", 'FmType' 'Graphics.Vega.VegaLite.Nominal' ]
    , 'Graphics.Vega.VegaLite.specification' spec
    ]
@

See also 'facet'.

@since 0.4.0.0
-}
facetFlow :: [FacetChannel] -> PropertySpec
facetFlow :: [FacetChannel] -> PropertySpec
facetFlow [FacetChannel]
fFields = (VLProperty
VLFacet, [LabelledSpec] -> VLSpec
object ((FacetChannel -> LabelledSpec) -> [FacetChannel] -> [LabelledSpec]
forall a b. (a -> b) -> [a] -> [b]
map FacetChannel -> LabelledSpec
facetChannelProperty [FacetChannel]
fFields))


{-|

Overrides the default height of the visualization. If not specified the height
will be calculated based on the content of the visualization. See
'autosize' for customization of the content sizing relative to this
setting, 'heightOfContainer' for setting the height to that of
the surrounding container,
and 'heightStep' for setting the height of discrete fields.

@
'Graphics.Vega.VegaLite.toVegaLite'
    [ 'height' 300
    , 'Graphics.Vega.VegaLite.dataFromUrl' "data/population.json" []
    , 'mark' 'Graphics.Vega.VegaLite.Bar' []
    , enc []
    ]
@
-}
height :: Double -> PropertySpec
height :: Double -> PropertySpec
height Double
h = (VLProperty
VLHeight, Double -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON Double
h)


{-|
Set the height of the view to that of the surrounding container,
to allow for responsive sizing.

Please see the [Vega Lite responsive sizing](https://vega.github.io/vega-lite/docs/size.html#specifying-responsive-width-and-height)
documentation for caveats and limitations.

@since 0.5.0.0
-}
heightOfContainer :: PropertySpec
heightOfContainer :: PropertySpec
heightOfContainer = (VLProperty
VLHeight, Text -> VLSpec
fromT Text
"container")


{-|

Set the height of the discrete y-field (e.g. individual bars in a
horizontal bar chart).
The total height is then calculated based on the number of discrete fields
(e.g. bars).

@
'Graphics.Vega.VegaLite.toVegaLite'
  [ 'heightStep' 17
  , data []
  , enc []
  , 'mark' 'Graphcs.Vega.VegaLite.Bar' []
  ]
@

This replaces the use of @SRangeStep@ from 'ScaleProperty'.

@since 0.5.0.0
-}

-- Note that unlike ELm, we do not create a separate property here
-- (ie no VLHeightStep)
--
heightStep :: Double -> PropertySpec
heightStep :: Double -> PropertySpec
heightStep Double
s = (VLProperty
VLHeight, [LabelledSpec] -> VLSpec
object [ Text
"step" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
s ])


{-|

Assigns a list of specifications to be juxtaposed horizontally in a visualization.
See also 'vConcat' and 'vlConcat'.

@
'Graphics.Vega.VegaLite.toVegaLite'
    [ 'Graphics.Vega.VegaLite.dataFromUrl' "data/driving.json" []
    , hConcat [ spec1, spec2 ]
    ]
@
-}
hConcat :: [VLSpec] -> PropertySpec
hConcat :: [VLSpec] -> PropertySpec
hConcat [VLSpec]
specs = (VLProperty
VLHConcat, [VLSpec] -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON [VLSpec]
specs)


{-|

Assigns a list of specifications to superposed layers in a visualization.

@
'Graphics.Vega.VegaLite.toVegaLite' ['Graphics.Vega.VegaLite.dataFromUrl' "data/driving.json" [], layer [spec1, spec2]]
@

A complete example showing @layer@ in use:

@
let dvals = 'Graphics.Vega.VegaLite.dataFromColumns' []
              . 'Graphics.Vega.VegaLite.dataColumn' \"x\" ('Numbers' [1, 2, 3, 4, 5])
              . 'Graphics.Vega.VegaLite.dataColumn' \"a\" ('Numbers' [28, 91, 43, 55, 81])
    enc = 'encoding'
             . 'position' 'Graphics.Vega.VegaLite.X' ['PName' \"x\", 'PmType' 'Graphics.Vega.VegaLite.Ordinal']
             . 'position' 'Graphics.Vega.VegaLite.Y' ['PName' \"a\", 'PmType' 'Graphics.Vega.VegaLite.Quantitative']
             . 'text' ['TName' \"a\", 'TmType' 'Graphics.Vega.VegaLite.Nominal']

    in 'Graphics.Vega.VegaLite.toVegaLite' [ dvals []
                  , enc []
                  , 'layer' [ 'Graphics.Vega.VegaLite.asSpec' ['mark' 'Graphics.Vega.VegaLite.Bar' []]
                          , 'Graphics.Vega.VegaLite.asSpec' ['mark' 'Graphics.Vega.VegaLite.Text' ['Graphics.Vega.VegaLite.MdY' (-8)]]
                          ]
                  ]
@

-}
layer :: [VLSpec] -> PropertySpec
layer :: [VLSpec] -> PropertySpec
layer [VLSpec]
specs = (VLProperty
VLLayer, [VLSpec] -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON [VLSpec]
specs)


{-|

Provides an optional name to be associated with the visualization.

@
'Graphics.Vega.VegaLite.toVegaLite'
    [ 'name' \"PopGrowth\"
    , 'Graphics.Vega.VegaLite.dataFromUrl' \"data/population.json\" []
    , 'mark' 'Graphics.Vega.VegaLite.Bar' []
    , enc []
    ]
@
-}
name :: T.Text -> PropertySpec
name :: Text -> PropertySpec
name Text
s = (VLProperty
VLName, Text -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON Text
s)


{-|

Set the padding around the visualization in pixel units. The way padding is
interpreted will depend on the 'autosize' properties. See the
<https://vega.github.io/vega-lite/docs/spec.html#top-level-specifications Vega-Lite documentation>
for details.

@
'Graphics.Vega.VegaLite.toVegaLite'
    [ 'width' 500
    , 'padding' ('Graphics.Vega.VegaLite.PEdges' 20 10 5 15)
    , 'Graphics.Vega.VegaLite.dataFromUrl' "data/population.json" []
    , 'mark' 'Graphics.Vega.VegaLite.Bar' []
    , enc []
    ]
@
-}
padding :: Padding -> PropertySpec
padding :: Padding -> PropertySpec
padding Padding
pad = (VLProperty
VLPadding, Padding -> VLSpec
paddingSpec Padding
pad)


{-|

Define the fields that will be used to compose rows and columns of a
set of small multiples. This is used where the encoding of the
visualization in small multiples is largely identical, but the data
field used in each might vary. When a list of fields is identified
with @repeat@ you also need to define a full specification to apply to
each of those fields using 'Graphics.Vega.VegaLite.asSpec'.

Unlike __faceting__, which creates multiple charts based on different values of a
single field, __repeating__ uses a different field for each chart.

See the
<https://vega.github.io/vega-lite/docs/repeat.html Vega-Lite documentation>
for further details.

@
'Graphics.Vega.VegaLite.toVegaLite'
    [ 'repeat' ['Graphics.Vega.VegaLite.ColumnFields' [\"Cat\", \"Dog\", \"Fish\"]]
    , 'Graphics.Vega.VegaLite.specification' ('Graphics.Vega.VegaLite.asSpec' spec)
    ]
@

See also 'repeatFlow'.

-}

repeat :: [RepeatFields] -> PropertySpec
repeat :: [RepeatFields] -> PropertySpec
repeat [RepeatFields]
fields = (VLProperty
VLRepeat, [LabelledSpec] -> VLSpec
object ((RepeatFields -> LabelledSpec) -> [RepeatFields] -> [LabelledSpec]
forall a b. (a -> b) -> [a] -> [b]
map RepeatFields -> LabelledSpec
repeatFieldsProperty [RepeatFields]
fields))


{-|

Define the fields that will be used to compose a flow layout of a set of
small multiples. Used when the encoding is largely identical, but the data field
used in each might vary. When a list of fields is identified with @repeatFlow@ you also
need to define a full specification to apply to each of those fields using 'Graphics.Vega.VegaLite.asSpec'.

Small multiples will be laid out from left to right, moving on to new rows only
if the number of plots exceeds an optional column limit (specified via 'columns').

@
'Graphics.Vega.VegaLite.toVegaLite'
    [ 'repeatFlow' [ \"Cat\", \"Dog\", \"Fish\" ]
    , 'Graphics.Vega.VegaLite.specification' ('Graphics.Vega.VegaLite.asSpec' spec)
    ]
@

See also 'repeat'.

@since 0.4.0.0

-}
repeatFlow ::
  [FieldName]
  -> PropertySpec
repeatFlow :: [Text] -> PropertySpec
repeatFlow [Text]
fields = (VLProperty
VLRepeat, [Text] -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON [Text]
fields)


{-|

Determine whether scales, axes or legends in composite views should
share channel encodings. This allows, for example, two different color
encodings to be created in a layered view, which otherwise by default
would share color channels between layers. Each resolution rule should
be in a tuple pairing the channel to which it applies and the rule
type.

@
let res = 'resolve'
            . 'resolution' ('Graphics.Vega.VegaLite.RLegend' [('Graphics.Vega.VegaLite.ChColor', 'Graphics.Vega.VegaLite.Independent')])

in 'Graphics.Vega.VegaLite.toVegaLite'
    [ 'Graphics.Vega.VegaLite.dataFromUrl' \"data/movies.json\" []
    , 'vConcat' [heatSpec, barSpec]
    , res []
    ]
@

For more information see the
<https://vega.github.io/vega-lite/docs/resolve.html Vega-Lite documentation>.

@
let dvals = 'Graphics.Vega.VegaLite.dataFromColumns' []
              . 'Graphics.Vega.VegaLite.dataColumn' "x" ('Numbers' [1, 2, 3, 4, 5])
              . 'Graphics.Vega.VegaLite.dataColumn' "a" ('Numbers' [28, 91, 43, 55, 81])
              . 'Graphics.Vega.VegaLite.dataColumn' "b" ('Numbers' [17, 22, 28, 30, 40])
    encBar = 'encoding'
               . 'position' 'Graphics.Vega.VegaLite.X' ['PName' \"x\", 'PmType' 'Graphics.Vega.VegaLite.Quantitative']
               . 'position' 'Graphics.Vega.VegaLite.Y' ['PName' \"a\", 'PmType' 'Graphics.Vega.VegaLite.Quantitative']
    specBar = 'Graphics.Vega.VegaLite.asSpec' ['mark' 'Graphics.Vega.VegaLite.Bar' [], encBar []]
    encLine = 'encoding'
                . 'position' 'Graphics.Vega.VegaLite.X' ['PName' \"x\", 'PmType' 'Graphics.Vega.VegaLite.Quantitative']
                . 'position' 'Graphics.Vega.VegaLite.Y' ['PName' \"b\", 'PmType' 'Graphics.Vega.VegaLite.Quantitative']
    specLine = 'Graphics.Vega.VegaLite.asSpec' ['mark' 'Graphics.Vega.VegaLite.Line' ['Graphics.Vega.VegaLite.MColor' \"firebrick\"], encLine []]
    res = 'resolve'
            . 'resolution' ('Graphics.Vega.VegaLite.RScale' [('Graphics.Vega.VegaLite.ChY', 'Graphics.Vega.VegaLite.Independent')])

in 'Graphics.Vega.VegaLite.toVegaLite' [dvals [], res [], 'layer' [specBar, specLine]]
@

-}
resolve ::
  [ResolveSpec]
  -- ^ The arguments created by 'Graphics.Vega.VegaLite.resolution'.
  --
  --   Prior to @0.5.0.0@ this argument was @['LabelledSpec']@.
  -> PropertySpec
resolve :: [ResolveSpec] -> PropertySpec
resolve [ResolveSpec]
res = (VLProperty
VLResolve, [LabelledSpec] -> VLSpec
object ((ResolveSpec -> LabelledSpec) -> [ResolveSpec] -> [LabelledSpec]
forall a b. (a -> b) -> [a] -> [b]
map ResolveSpec -> LabelledSpec
unRS [ResolveSpec]
res))


{-|

Create a single transform from a list of transformation
specifications. Note that the order of transformations can be
important, especially if labels created with 'calculateAs',
'timeUnitAs', and 'binAs' are used in other transformations.  Using
the functional composition pipeline idiom (as example below) allows
you to provide the transformations in the order intended in a clear
manner.

@
'transform'
    . 'filter' ('FExpr' "datum.year == 2010")
    . 'calculateAs' "datum.sex == 2 ? \'Female\' : \'Male\'" "gender"
@

The supported transformations are:
'aggregate', 'binAs', 'calculateAs', 'density', 'filter', 'flatten',
'flattenAs', 'fold', 'foldAs', 'impute', 'joinAggregate', 'loess',
'lookup', 'lookupAs', 'lookupSelection', 'pivot', 'quantile',
'regression', 'sample', 'stack', 'timeUnitAs', and 'window'.

-}

transform ::
  [TransformSpec]
  -- ^ The transformations to apply. The order does matter.
  --
  --   Prior to @0.5.0.0@ this argument was @['LabelledSpec']@.
  -> PropertySpec
transform :: [TransformSpec] -> PropertySpec
transform [TransformSpec]
transforms =
  let js :: VLSpec
js = if [TransformSpec] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [TransformSpec]
transforms then VLSpec
A.Null else [VLSpec] -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON ((TransformSpec -> VLSpec) -> [TransformSpec] -> [VLSpec]
forall a b. (a -> b) -> [a] -> [b]
map TransformSpec -> VLSpec
unTS [TransformSpec]
transforms)
  in (VLProperty
VLTransform, VLSpec
js)


{-|

Assigns a list of specifications to be juxtaposed vertically in a visualization.
See also 'hConcat' and 'vlConcat'.

@
'Graphics.Vega.VegaLite.toVegaLite'
    [ 'Graphics.Vega.VegaLite.dataFromUrl' "data/driving.json" []
    , 'vConcat' [ spec1, spec2 ]
    ]
@
-}
vConcat :: [VLSpec] -> PropertySpec
vConcat :: [VLSpec] -> PropertySpec
vConcat [VLSpec]
specs = (VLProperty
VLVConcat, [VLSpec] -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON [VLSpec]
specs)


{-|

Override the default width of the visualization. If not specified the width
will be calculated based on the content of the visualization. See
'autosize' for customization of the content sizing relative to this
setting, 'widthOfContainer' for setting the width to that of
the surrounding container,
and 'widthStep' for setting the width of discrete fields.

@
'Graphics.Vega.VegaLite.toVegaLite'
    [ 'width' 500
    , 'Graphics.Vega.VegaLite.dataFromUrl' "data/population.json" []
    , 'mark' 'Graphics.Vega.VegaLite.Bar' []
    , enc []
    ]
@
-}
width :: Double -> PropertySpec
width :: Double -> PropertySpec
width Double
w = (VLProperty
VLWidth, Double -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON Double
w)


{-|
Set the width of the view to that of the surrounding container,
to allow for responsive sizing.

Please see the [Vega Lite responsive sizing](https://vega.github.io/vega-lite/docs/size.html#specifying-responsive-width-and-height)
documentation for caveats and limitations.

@since 0.5.0.0
-}
widthOfContainer :: PropertySpec
widthOfContainer :: PropertySpec
widthOfContainer = (VLProperty
VLWidth, Text -> VLSpec
fromT Text
"container")


{-|

Set the width of the discrete x-field (e.g. individual bars in a bar chart).
The total width is then calculated based on the number of discrete fields
(e.g. bars).

@
'Graphics.Vega.VegaLite.toVegaLite'
  [ 'widthStep' 17
  , data []
  , enc []
  , 'mark' 'Graphcs.Vega.VegaLite.Bar' []
  ]
@

This replaces the use of @SRangeStep@ from 'ScaleProperty'.

@since 0.5.0.0
-}

-- Note that unlike ELm, we do not create a separate property here
-- (ie no VLWidthStep)
--
widthStep :: Double -> PropertySpec
widthStep :: Double -> PropertySpec
widthStep Double
s = (VLProperty
VLWidth, [LabelledSpec] -> VLSpec
object [ Text
"step" Text -> Double -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
s ])


{-|

Defines a set of named aggregation transformations to be used when encoding
channels. This is useful when, for example, you wish to apply the same transformation
to a number of channels but do not want to define it each time. For further details
see the
<https://vega.github.io/vega-lite/docs/aggregate.html#aggregate-op-def Vega-Lite documentation>.

@
'transform'
    . 'aggregate'
        [ 'opAs' 'Graphics.Vega.VegaLite.Min' "people" "lowerBound"
        , 'opAs' 'Graphics.Vega.VegaLite.Max' "people" "upperBound" ]
        [ "age" ]
@

See also 'joinAggregate'.

-}
aggregate ::
  [VLSpec]
  -- ^ The named aggregation operations to apply.
  -> [FieldName]
  -- ^ The \"group by\" fields.
  -> BuildTransformSpecs
aggregate :: [VLSpec] -> [Text] -> BuildTransformSpecs
aggregate [VLSpec]
ops [Text]
groups [TransformSpec]
ols =
  let fields :: [LabelledSpec]
fields = [ Text
"aggregate" Text -> [VLSpec] -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [VLSpec]
ops
               , Text
"groupby" Text -> [Text] -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [Text]
groups ]
  in VLSpec -> TransformSpec
TS ([LabelledSpec] -> VLSpec
object [LabelledSpec]
fields) TransformSpec -> BuildTransformSpecs
forall a. a -> [a] -> [a]
: [TransformSpec]
ols


{-|

Aggregation transformations to be used when encoding channels. Unlike
'aggregate', this transformation joins the results to the input data.
Can be helpful for creating derived values that combine raw data with some aggregate
measure, such as percentages of group totals. The first parameter is a list
of the named aggregation operations to apply. The second is a list of possible
window aggregate field properties, such as a field to group by when aggregating.
The third parameter is a list of transformations to which this is added.

@
'transform'
    . 'joinAggregate'
        [ 'opAs' 'Graphics.Vega.VegaLite.Mean' "rating" "avYearRating" ]
        [ 'Graphics.Vega.VegaLite.WGroupBy' [ "year" ] ]
    . 'filter' ('FExpr' "(datum.rating - datum.avYearRating) > 3"))
@

For details, see the
<https://vega.github.io/vega-lite/docs/joinaggregate.html Vega-Lite join aggregate documentation>.

See also 'aggregate'.

@since 0.4.0.0
-}

joinAggregate ::
  [VLSpec]
  -> [WindowProperty]
  -> BuildTransformSpecs
joinAggregate :: [VLSpec] -> [WindowProperty] -> BuildTransformSpecs
joinAggregate [VLSpec]
ops [WindowProperty]
wProps [TransformSpec]
ols = [VLSpec] -> [WindowProperty] -> TransformSpec
joinAggregateTS [VLSpec]
ops [WindowProperty]
wProps TransformSpec -> BuildTransformSpecs
forall a. a -> [a] -> [a]
: [TransformSpec]
ols


{-|

Window transform for performing calculations over sorted groups of
data objects such as ranking, lead/lag analysis, running sums and averages.

@
'transform'
    . 'window' [ ( [ 'Graphics.Vega.VegaLite.WAggregateOp' 'Graphics.Vega.VegaLite.Sum', 'Graphics.Vega.VegaLite.WField' \"Time\" ], \"TotalTime\" ) ]
             [ 'Graphics.Vega.VegaLite.WFrame' Nothing Nothing ]
@

@since 0.4.0.0

-}
window ::
  [([Window], FieldName)]
  -- ^ The window-transform definition and associated output name.
  -> [WindowProperty]
  -- ^ The window transform.
  -> BuildTransformSpecs
window :: [([Window], Text)] -> [WindowProperty] -> BuildTransformSpecs
window [([Window], Text)]
wss [WindowProperty]
wProps [TransformSpec]
ols = [([Window], Text)] -> [WindowProperty] -> TransformSpec
windowTS [([Window], Text)]
wss [WindowProperty]
wProps TransformSpec -> BuildTransformSpecs
forall a. a -> [a] -> [a]
: [TransformSpec]
ols


{-|

Randomly sample rows from a data source up to a given maximum.

For example, the following randomly samples 50 values from a sine curve:

@
 dvals = 'Graphics.Vega.VegaLite.dataSequenceAs' 0 13 0.001 \"x\"
 trans = 'transform'
           . 'calculateAs' \"sin(datum.x)\" \"y\"
           . 'sample' 50
@

@since 0.4.0.0

-}

sample :: Int -> BuildTransformSpecs
sample :: Int -> BuildTransformSpecs
sample Int
maxSize [TransformSpec]
ols = VLSpec -> TransformSpec
TS ([LabelledSpec] -> VLSpec
object [ Text
"sample" Text -> Int -> LabelledSpec
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Int
maxSize ]) TransformSpec -> BuildTransformSpecs
forall a. a -> [a] -> [a]
: [TransformSpec]
ols


{-|

Configure the kernel density estimation process. Used by 'density'.

@since 0.5.0.0
-}

data DensityProperty
  = DnAs FieldName FieldName
    -- ^ Name the outputs of a density transform. The first argument is the
    --   name of the field containing the samples and the second the name
    --   for the field containing the density estimates.
    --
    --   The defaults are @\"value\"@ and @\"density\"@ respectively.
  | DnBandwidth Double
    -- ^ The bandwidth (standard deviation) of the Gaussian kernel to be
    --   used in the KDE. If not given, or set to 0, then
    --   [Scott's method](https://stats.stackexchange.com/questions/90656/kernel-bandwidth-scotts-vs-silvermans-rules)
    --   is used.
  | DnCounts Bool
    -- ^ If @'True'@ then the KDE generates counts, if @'False'@ it
    --   generates probabilities.
    --
    --   The default is probabilities.
  | DnCumulative Bool
    -- ^ Should the density estimates be cumulative?
    --
    --   The default is @'False'@.
  | DnExtent Double Double
    -- ^ The domain (minimum to maximum) from which to sample a distribution
    --   for the density estimation.
    --
    --   The default is to use the full extent of the input values.
  | DnGroupBy [FieldName]
    -- ^ The data fields to group by.
    --
    --   The default is to use a single group containing all the data objects.
  | DnMaxSteps Natural
    -- ^ The maximum number of samples to take from the extent domain.
    --
    --   The default is 200.
  | DnMinSteps Natural
    -- ^ The minimum number of samples to take from the extent domain.
    --
    --   The default is 25.
  | DnSteps Natural
    -- ^ This overrides the 'DnMinSteps' and 'DnMaxSteps' options and
    --   specified an exact number of steps to take from the extent
    --   domain.
    --
    --   It can be used with 'DnExtent' to ensure a consistent
    --   set of sample points for stacked densities.


data DensityPropertyLabel =
  DPLGroupby | DPLCumulative | DPLCounts | DPLBandwidth | DPLExtent |
  DPLMinsteps | DPLMaxsteps | DPLSteps | DPLAs


densityPropertySpec :: DensityPropertyLabel -> [DensityProperty] -> VLSpec
densityPropertySpec :: DensityPropertyLabel -> [DensityProperty] -> VLSpec
densityPropertySpec DensityPropertyLabel
DPLGroupby [DensityProperty]
ps =
  let wanted :: DensityProperty -> Maybe [Text]
wanted (DnGroupBy [Text]
xs) = [Text] -> Maybe [Text]
forall a. a -> Maybe a
Just [Text]
xs
      wanted DensityProperty
_ = Maybe [Text]
forall a. Maybe a
Nothing

  in case (DensityProperty -> Maybe [Text]) -> [DensityProperty] -> [[Text]]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe DensityProperty -> Maybe [Text]
wanted [DensityProperty]
ps of
    [[Text]
x] -> [Text] -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON [Text]
x
    [[Text]]
_ -> VLSpec
A.Null

densityPropertySpec DensityPropertyLabel
DPLCumulative [DensityProperty]
ps =
  let wanted :: DensityProperty -> Maybe Bool
wanted (DnCumulative Bool
xs) = Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
xs
      wanted DensityProperty
_ = Maybe Bool
forall a. Maybe a
Nothing

  in case (DensityProperty -> Maybe Bool) -> [DensityProperty] -> [Bool]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe DensityProperty -> Maybe Bool
wanted [DensityProperty]
ps of
    [Bool
x] -> Bool -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON Bool
x
    [Bool]
_ -> VLSpec
A.Null

densityPropertySpec DensityPropertyLabel
DPLCounts [DensityProperty]
ps =
  let wanted :: DensityProperty -> Maybe Bool
wanted (DnCounts Bool
xs) = Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
xs
      wanted DensityProperty
_ = Maybe Bool
forall a. Maybe a
Nothing

  in case (DensityProperty -> Maybe Bool) -> [DensityProperty] -> [Bool]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe DensityProperty -> Maybe Bool
wanted [DensityProperty]
ps of
    [Bool
x] -> Bool -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON Bool
x
    [Bool]
_ -> VLSpec
A.Null

densityPropertySpec DensityPropertyLabel
DPLBandwidth [DensityProperty]
ps =
  let wanted :: DensityProperty -> Maybe Double
wanted (DnBandwidth Double
xs) = Double -> Maybe Double
forall a. a -> Maybe a
Just Double
xs
      wanted DensityProperty
_ = Maybe Double
forall a. Maybe a
Nothing

  in case (DensityProperty -> Maybe Double) -> [DensityProperty] -> [Double]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe DensityProperty -> Maybe Double
wanted [DensityProperty]
ps of
    [Double
x] -> Double -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON Double
x
    [Double]
_ -> VLSpec
A.Null

densityPropertySpec DensityPropertyLabel
DPLExtent [DensityProperty]
ps =
  let wanted :: DensityProperty -> Maybe [Double]
wanted (DnExtent Double
xs Double
ys) = [Double] -> Maybe [Double]
forall a. a -> Maybe a
Just [Double
xs, Double
ys]
      wanted DensityProperty
_ = Maybe [Double]
forall a. Maybe a
Nothing

  in case (DensityProperty -> Maybe [Double])
-> [DensityProperty] -> [[Double]]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe DensityProperty -> Maybe [Double]
wanted [DensityProperty]
ps of
    [[Double]
x] -> [Double] -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON [Double]
x
    [[Double]]
_ -> VLSpec
A.Null

densityPropertySpec DensityPropertyLabel
DPLMinsteps [DensityProperty]
ps =
  let wanted :: DensityProperty -> Maybe ZIndex
wanted (DnMinSteps ZIndex
xs) = ZIndex -> Maybe ZIndex
forall a. a -> Maybe a
Just ZIndex
xs
      wanted DensityProperty
_ = Maybe ZIndex
forall a. Maybe a
Nothing

  in case (DensityProperty -> Maybe ZIndex) -> [DensityProperty] -> [ZIndex]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe DensityProperty -> Maybe ZIndex
wanted [DensityProperty]
ps of
    [ZIndex
x] -> ZIndex -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON ZIndex
x
    [ZIndex]
_ -> VLSpec
A.Null

densityPropertySpec DensityPropertyLabel
DPLMaxsteps [DensityProperty]
ps =
  let wanted :: DensityProperty -> Maybe ZIndex
wanted (DnMaxSteps ZIndex
xs) = ZIndex -> Maybe ZIndex
forall a. a -> Maybe a
Just ZIndex
xs
      wanted DensityProperty
_ = Maybe ZIndex
forall a. Maybe a
Nothing

  in case (DensityProperty -> Maybe ZIndex) -> [DensityProperty] -> [ZIndex]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe DensityProperty -> Maybe ZIndex
wanted [DensityProperty]
ps of
    [ZIndex
x] -> ZIndex -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON ZIndex
x
    [ZIndex]
_ -> VLSpec
A.Null

densityPropertySpec DensityPropertyLabel
DPLSteps [DensityProperty]
ps =
  let wanted :: DensityProperty -> Maybe ZIndex
wanted (DnSteps ZIndex
xs) = ZIndex -> Maybe ZIndex
forall a. a -> Maybe a
Just ZIndex
xs
      wanted DensityProperty
_ = Maybe ZIndex
forall a. Maybe a
Nothing

  in case (DensityProperty -> Maybe ZIndex) -> [DensityProperty] -> [ZIndex]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe DensityProperty -> Maybe ZIndex
wanted [DensityProperty]
ps of
    [ZIndex
x] -> ZIndex -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON ZIndex
x
    [ZIndex]
_ -> VLSpec
A.Null

densityPropertySpec DensityPropertyLabel
DPLAs [DensityProperty]
ps =
  let wanted :: DensityProperty -> Maybe [Text]
wanted (DnAs Text
xs Text
ys) = [Text] -> Maybe [Text]
forall a. a -> Maybe a
Just [Text
xs, Text
ys]
      wanted DensityProperty
_ = Maybe [Text]
forall a. Maybe a
Nothing

  in case (DensityProperty -> Maybe [Text]) -> [DensityProperty] -> [[Text]]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe DensityProperty -> Maybe [Text]
wanted [DensityProperty]
ps of
    [[Text]
x] -> [Text] -> VLSpec
forall a. ToJSON a => a -> VLSpec
toJSON [Text]
x
    [[Text]]
_ -> VLSpec
A.Null



{-|

Apply /Kernel Density Estimation/ to a data stream to generate a new stream
of samples of the estimated density. This is useful for representing
probability distributions and generating continuous distributions from
discrete samples.

The following example creates a faceted display of the smoothed
length and width distributions from the iris dataset.

@
dvals = 'Graphics.Vega.VegaLite.dataFromUrl' \"https:\/\/vega.github.io\/vega-lite\/data\/iris.json" []

colNames = [ \"petalWidth\", \"petalLength\", \"sepalWidth\", \"sepalLength\" ]
trans = 'transform'
        . 'foldAs' colNames \"measurement\" \"value\"
        . 'density' \"value\" [ 'DnGroupBy' [ \"measurement\" ] ]

enc = 'encoding'
      . 'position' 'Graphics.Vega.VegaLite.X' [ 'PName' \"value\", 'PmType' 'Graphics.Vega.VegaLite.Quantitative' ]
      . 'position' 'Graphics.Vega.VegaLite.Y' [ 'PName' \"density\", 'PmType' 'Graphics.Vega.VegaLite.Quantitative' ]
      . 'row' [ 'FName' \"measurement\", 'FmType' 'Graphics.Vega.VegaLite.Nominal' ]

layer = 'Graphics.Vega.VegaLite.asSpec' [ trans [], enc [], 'mark' 'Graphics.Vega.VegaLite.Area' [ 'Graphics.Vega.VegaLite.MOpacity' 0.7 ] ]
@

@since 0.5.0.0
-}

density ::
  FieldName
  -- ^ The field used for the KDE.
  -> [DensityProperty]
  -- ^ Configure the calculation.
  -> BuildTransformSpecs
density :: Text -> [DensityProperty] -> BuildTransformSpecs
density Text
field [DensityProperty]
dps [TransformSpec]
ols =
  let addField :: Text -> DensityPropertyLabel -> [a]
addField Text
n DensityPropertyLabel
p = case DensityPropertyLabel -> [DensityProperty] -> VLSpec
densityPropertySpec DensityPropertyLabel
p [DensityProperty]
dps of
                       VLSpec
A.Null -> []
                       VLSpec
x -> [ Text
n